sqlite_orm.h
C source, ASCII text
1
#pragma once
2
3
#if defined(_MSC_VER)
4
__pragma(push_macro("min"))
5
#undef min
6
__pragma(push_macro("max"))
7
#undef max
8
#endif // defined(_MSC_VER)
9
#pragma once
10
11
#include <sqlite3.h>
12
#pragma once
13
14
// #include "cxx_universal.h"
15
16
/*
17
* This header makes central C++ functionality on which sqlite_orm depends universally available:
18
* - alternative operator representations
19
* - ::size_t, ::ptrdiff_t, ::nullptr_t
20
* - C++ core language feature macros
21
* - macros for dealing with compiler quirks
22
*/
23
24
#include <iso646.h> // alternative operator representations
25
#include <cstddef> // sqlite_orm is using size_t, ptrdiff_t, nullptr_t everywhere, pull it in early
26
27
// earlier clang versions didn't make nullptr_t available in the global namespace via stddef.h,
28
// though it should have according to C++ documentation (see https://en.cppreference.com/w/cpp/types/nullptr_t#Notes).
29
// actually it should be available when including stddef.h
30
using std::nullptr_t;
31
32
// #include "cxx_core_features.h"
33
34
/*
35
* This header detects core C++ language features on which sqlite_orm depends.
36
* May be updated/overwritten by cxx_compiler_quirks.h
37
*/
38
39
#ifdef __has_cpp_attribute
40
#define SQLITE_ORM_HAS_CPP_ATTRIBUTE(attr) __has_cpp_attribute(attr)
41
#else
42
#define SQLITE_ORM_HAS_CPP_ATTRIBUTE(attr) 0L
43
#endif
44
45
#ifdef __has_include
46
#define SQLITE_ORM_HAS_INCLUDE(file) __has_include(file)
47
#else
48
#define SQLITE_ORM_HAS_INCLUDE(file) 0L
49
#endif
50
51
#if __cpp_aggregate_nsdmi >= 201304L
52
#define SQLITE_ORM_AGGREGATE_NSDMI_SUPPORTED
53
#endif
54
55
#if __cpp_constexpr >= 201304L
56
#define SQLITE_ORM_RELAXED_CONSTEXPR_SUPPORTED
57
#endif
58
59
#if __cpp_noexcept_function_type >= 201510L
60
#define SQLITE_ORM_NOTHROW_ALIASES_SUPPORTED
61
#endif
62
63
#if __cpp_aggregate_bases >= 201603L
64
#define SQLITE_ORM_AGGREGATE_BASES_SUPPORTED
65
#endif
66
67
#if __cpp_fold_expressions >= 201603L
68
#define SQLITE_ORM_FOLD_EXPRESSIONS_SUPPORTED
69
#endif
70
71
#if __cpp_constexpr >= 201603L
72
#define SQLITE_ORM_CONSTEXPR_LAMBDAS_SUPPORTED
73
#endif
74
75
#if __cpp_range_based_for >= 201603L
76
#define SQLITE_ORM_SENTINEL_BASED_FOR_SUPPORTED
77
#endif
78
79
#if __cpp_if_constexpr >= 201606L
80
#define SQLITE_ORM_IF_CONSTEXPR_SUPPORTED
81
#endif
82
83
#if __cpp_inline_variables >= 201606L
84
#define SQLITE_ORM_INLINE_VARIABLES_SUPPORTED
85
#endif
86
87
#if __cpp_structured_bindings >= 201606L
88
#define SQLITE_ORM_STRUCTURED_BINDINGS_SUPPORTED
89
#endif
90
91
#if __cpp_generic_lambdas >= 201707L
92
#define SQLITE_ORM_EXPLICIT_GENERIC_LAMBDA_SUPPORTED
93
#else
94
#endif
95
96
#if __cpp_init_captures >= 201803L
97
#define SQLITE_ORM_PACK_EXPANSION_IN_INIT_CAPTURE_SUPPORTED
98
#endif
99
100
#if __cpp_consteval >= 201811L
101
#define SQLITE_ORM_CONSTEVAL_SUPPORTED
102
#endif
103
104
#if __cpp_char8_t >= 201811L
105
#define SQLITE_ORM_CHAR8T_SUPPORTED
106
#endif
107
108
#if __cpp_aggregate_paren_init >= 201902L
109
#define SQLITE_ORM_AGGREGATE_PAREN_INIT_SUPPORTED
110
#endif
111
112
#if __cpp_concepts >= 201907L
113
#define SQLITE_ORM_CONCEPTS_SUPPORTED
114
#endif
115
116
#if __cpp_nontype_template_args >= 201911L
117
#define SQLITE_ORM_CLASSTYPE_TEMPLATE_ARGS_SUPPORTED
118
#endif
119
120
#if __cpp_nontype_template_args >= 201911L
121
#define SQLITE_ORM_CLASSTYPE_TEMPLATE_ARGS_SUPPORTED
122
#endif
123
124
#if __cpp_pack_indexing >= 202311L
125
#define SQLITE_ORM_PACK_INDEXING_SUPPORTED
126
#endif
127
128
#if __cplusplus >= 202002L
129
#define SQLITE_ORM_DEFAULT_COMPARISONS_SUPPORTED
130
#endif
131
132
// #include "cxx_compiler_quirks.h"
133
134
/*
135
* This header defines macros for circumventing compiler quirks on which sqlite_orm depends.
136
* May amend cxx_core_features.h
137
*/
138
139
#ifdef __clang__
140
#define SQLITE_ORM_DO_PRAGMA(...) _Pragma(#__VA_ARGS__)
141
#endif
142
143
#ifdef __clang__
144
#define SQLITE_ORM_CLANG_SUPPRESS(warnoption, ...) \
145
SQLITE_ORM_DO_PRAGMA(clang diagnostic push) \
146
SQLITE_ORM_DO_PRAGMA(clang diagnostic ignored warnoption) \
147
__VA_ARGS__ \
148
SQLITE_ORM_DO_PRAGMA(clang diagnostic pop)
149
150
#else
151
#define SQLITE_ORM_CLANG_SUPPRESS(warnoption, ...) __VA_ARGS__
152
#endif
153
154
// clang has the bad habit of diagnosing missing brace-init-lists when constructing aggregates with base classes.
155
// This is a false positive, since the C++ standard is quite clear that braces for nested or base objects may be omitted,
156
// see https://en.cppreference.com/w/cpp/language/aggregate_initialization:
157
// "The braces around the nested initializer lists may be elided (omitted),
158
// in which case as many initializer clauses as necessary are used to initialize every member or element of the corresponding subaggregate,
159
// and the subsequent initializer clauses are used to initialize the following members of the object."
160
// In this sense clang should only warn about missing field initializers.
161
// Because we know what we are doing, we suppress the diagnostic message
162
#define SQLITE_ORM_CLANG_SUPPRESS_MISSING_BRACES(...) SQLITE_ORM_CLANG_SUPPRESS("-Wmissing-braces", __VA_ARGS__)
163
164
#if defined(_MSC_VER) && (_MSC_VER < 1920)
165
#define SQLITE_ORM_BROKEN_VARIADIC_PACK_EXPANSION
166
// Type replacement may fail if an alias template has a non-type template parameter from a dependent expression in it,
167
// `e.g. template<class T> using is_something = std::bool_constant<is_something_v<T>>;`
168
// Remedy, e.g.: use a derived struct: `template<class T> struct is_somthing : std::bool_constant<is_something_v<T>>;`
169
#define SQLITE_ORM_BROKEN_ALIAS_TEMPLATE_DEPENDENT_NTTP_EXPR
170
#endif
171
172
// These compilers are known to have problems with alias templates in SFINAE contexts:
173
// clang 3.5
174
// gcc 8.3
175
// msvc 15.9
176
// Type replacement may fail if an alias template has dependent expression or decltype in it.
177
// In these cases we have to use helper structures to break down the type alias.
178
// Note that the detection of specific compilers is so complicated because some compilers emulate other compilers,
179
// so we simply exclude all compilers that do not support C++20, even though this test is actually inaccurate.
180
#if (defined(_MSC_VER) && (_MSC_VER < 1920)) || (!defined(_MSC_VER) && (__cplusplus < 202002L))
181
#define SQLITE_ORM_BROKEN_ALIAS_TEMPLATE_DEPENDENT_EXPR_SFINAE
182
#endif
183
184
// overwrite SQLITE_ORM_CLASSTYPE_TEMPLATE_ARGS_SUPPORTED
185
#if (__cpp_nontype_template_args < 201911L) && \
186
(defined(__clang__) && (__clang_major__ >= 12) && (__cplusplus >= 202002L))
187
#define SQLITE_ORM_CLASSTYPE_TEMPLATE_ARGS_SUPPORTED
188
#endif
189
190
// clang 10 chokes on concepts that don't depend on template parameters;
191
// when it tries to instantiate an expression in a requires expression, which results in an error,
192
// the compiler reports an error instead of dismissing the templated function.
193
#if defined(SQLITE_ORM_CONCEPTS_SUPPORTED) && (defined(__clang__) && (__clang_major__ == 10))
194
#define SQLITE_ORM_BROKEN_NONTEMPLATE_CONCEPTS
195
#endif
196
197
#if SQLITE_ORM_HAS_INCLUDE(<version>)
198
#include <version>
199
#endif
200
201
#ifdef SQLITE_ORM_CONSTEXPR_LAMBDAS_SUPPORTED
202
#define SQLITE_ORM_CONSTEXPR_LAMBDA_CPP17 constexpr
203
#else
204
#define SQLITE_ORM_CONSTEXPR_LAMBDA_CPP17
205
#endif
206
207
#ifdef SQLITE_ORM_INLINE_VARIABLES_SUPPORTED
208
#define SQLITE_ORM_INLINE_VAR inline
209
#else
210
#define SQLITE_ORM_INLINE_VAR
211
#endif
212
213
#ifdef SQLITE_ORM_IF_CONSTEXPR_SUPPORTED
214
#define SQLITE_ORM_CONSTEXPR_IF constexpr
215
#else
216
#define SQLITE_ORM_CONSTEXPR_IF
217
#endif
218
219
#if __cpp_lib_constexpr_functional >= 201907L
220
#define SQLITE_ORM_CONSTEXPR_CPP20 constexpr
221
#else
222
#define SQLITE_ORM_CONSTEXPR_CPP20
223
#endif
224
225
#if SQLITE_ORM_HAS_CPP_ATTRIBUTE(no_unique_address) >= 201803L
226
#define SQLITE_ORM_NOUNIQUEADDRESS [[no_unique_address]]
227
#else
228
#define SQLITE_ORM_NOUNIQUEADDRESS
229
#endif
230
231
#if SQLITE_ORM_HAS_CPP_ATTRIBUTE(likely) >= 201803L
232
#define SQLITE_ORM_CPP_LIKELY [[likely]]
233
#define SQLITE_ORM_CPP_UNLIKELY [[unlikely]]
234
#else
235
#define SQLITE_ORM_CPP_LIKELY
236
#define SQLITE_ORM_CPP_UNLIKELY
237
#endif
238
239
#ifdef SQLITE_ORM_CONSTEVAL_SUPPORTED
240
#define SQLITE_ORM_CONSTEVAL consteval
241
#else
242
#define SQLITE_ORM_CONSTEVAL constexpr
243
#endif
244
245
#if defined(SQLITE_ORM_CONCEPTS_SUPPORTED) && __cpp_lib_concepts >= 202002L
246
#define SQLITE_ORM_CPP20_CONCEPTS_SUPPORTED
247
#endif
248
249
#if __cpp_lib_ranges >= 201911L
250
#define SQLITE_ORM_CPP20_RANGES_SUPPORTED
251
#endif
252
253
// C++20 or later (unfortunately there's no feature test macro).
254
// Stupidly, clang says C++20, but `std::default_sentinel_t` was only implemented in libc++ 13 and libstd++-v3 10
255
// (the latter is used on Linux).
256
// gcc got it right and reports C++20 only starting with v10.
257
// The check here doesn't care and checks the library versions in use.
258
//
259
// Another way of detection might be the feature-test macro __cpp_lib_concepts
260
#if (__cplusplus >= 202002L) && \
261
((!_LIBCPP_VERSION || _LIBCPP_VERSION >= 13000) && (!_GLIBCXX_RELEASE || _GLIBCXX_RELEASE >= 10))
262
#define SQLITE_ORM_STL_HAS_DEFAULT_SENTINEL
263
#endif
264
265
#if (defined(SQLITE_ORM_CLASSTYPE_TEMPLATE_ARGS_SUPPORTED) && defined(SQLITE_ORM_INLINE_VARIABLES_SUPPORTED) && \
266
defined(SQLITE_ORM_CONSTEVAL_SUPPORTED)) && \
267
(defined(SQLITE_ORM_CPP20_CONCEPTS_SUPPORTED))
268
#define SQLITE_ORM_WITH_CPP20_ALIASES
269
#endif
270
271
#if defined(SQLITE_ORM_FOLD_EXPRESSIONS_SUPPORTED) && defined(SQLITE_ORM_IF_CONSTEXPR_SUPPORTED)
272
#define SQLITE_ORM_WITH_CTE
273
#endif
274
275
// define the inline namespace "literals" so that it is available even if it was not introduced by a feature
276
namespace sqlite_orm {
277
inline namespace literals {}
278
}
279
#pragma once
280
281
#include <sqlite3.h>
282
#include <memory> // std::unique_ptr/shared_ptr, std::make_unique
283
#include <system_error> // std::system_error
284
#include <string> // std::string
285
#include <type_traits> // std::remove_reference, std::remove_cvref, std::decay
286
#include <functional> // std::identity
287
#include <sstream> // std::stringstream
288
#include <iomanip> // std::flush
289
#include <map> // std::map
290
#include <vector> // std::vector
291
#include <tuple> // std::tuple_size, std::tuple, std::make_tuple, std::tie
292
#include <utility> // std::forward, std::pair
293
#include <algorithm> // std::for_each, std::ranges::for_each
294
// #include "functional/cxx_optional.h"
295
296
// #include "cxx_core_features.h"
297
298
#if SQLITE_ORM_HAS_INCLUDE(<optional>)
299
#include <optional>
300
#endif
301
302
#if __cpp_lib_optional >= 201606L
303
#define SQLITE_ORM_OPTIONAL_SUPPORTED
304
#endif
305
306
// #include "functional/cxx_type_traits_polyfill.h"
307
308
#include <type_traits>
309
310
// #include "mpl/conditional.h"
311
312
namespace sqlite_orm {
313
namespace internal {
314
namespace mpl {
315
316
/*
317
* Binary quoted metafunction equivalent to `std::conditional`,
318
* using an improved implementation in respect to memoization.
319
*
320
* Because `conditional` is only typed on a single bool non-type template parameter,
321
* the compiler only ever needs to memoize 2 instances of this class template.
322
* The type selection is a nested cheap alias template.
323
*/
324
template<bool>
325
struct conditional {
326
template<typename A, typename>
327
using fn = A;
328
};
329
330
template<>
331
struct conditional<false> {
332
template<typename, typename B>
333
using fn = B;
334
};
335
336
// directly invoke `conditional`
337
template<bool v, typename A, typename B>
338
using conditional_t = typename conditional<v>::template fn<A, B>;
339
}
340
}
341
342
namespace mpl = internal::mpl;
343
}
344
345
namespace sqlite_orm {
346
namespace internal {
347
namespace polyfill {
348
#if __cpp_lib_void_t >= 201411L
349
using std::void_t;
350
#else
351
/*
352
* Implementation note: Conservative implementation due to CWG issue 1558 (Unused arguments in alias template specializations).
353
*/
354
template<class...>
355
struct always_void {
356
using type = void;
357
};
358
template<class... T>
359
using void_t = typename always_void<T...>::type;
360
#endif
361
362
#if __cpp_lib_bool_constant >= 201505L
363
using std::bool_constant;
364
#else
365
template<bool v>
366
using bool_constant = std::integral_constant<bool, v>;
367
#endif
368
369
#if __cpp_lib_logical_traits >= 201510L && __cpp_lib_type_trait_variable_templates >= 201510L
370
using std::conjunction;
371
using std::conjunction_v;
372
using std::disjunction;
373
using std::disjunction_v;
374
using std::negation;
375
using std::negation_v;
376
#else
377
template<typename...>
378
struct conjunction : std::true_type {};
379
template<typename B1>
380
struct conjunction<B1> : B1 {};
381
template<typename B1, typename... Bn>
382
struct conjunction<B1, Bn...> : mpl::conditional_t<bool(B1::value), conjunction<Bn...>, B1> {};
383
template<typename... Bs>
384
SQLITE_ORM_INLINE_VAR constexpr bool conjunction_v = conjunction<Bs...>::value;
385
386
template<typename...>
387
struct disjunction : std::false_type {};
388
template<typename B1>
389
struct disjunction<B1> : B1 {};
390
template<typename B1, typename... Bn>
391
struct disjunction<B1, Bn...> : mpl::conditional_t<bool(B1::value), B1, disjunction<Bn...>> {};
392
template<typename... Bs>
393
SQLITE_ORM_INLINE_VAR constexpr bool disjunction_v = disjunction<Bs...>::value;
394
395
template<typename B>
396
struct negation : bool_constant<!bool(B::value)> {};
397
template<typename B>
398
SQLITE_ORM_INLINE_VAR constexpr bool negation_v = negation<B>::value;
399
#endif
400
401
#if __cpp_lib_remove_cvref >= 201711L
402
using std::remove_cvref, std::remove_cvref_t;
403
#else
404
template<class T>
405
struct remove_cvref : std::remove_cv<std::remove_reference_t<T>> {};
406
407
template<class T>
408
using remove_cvref_t = typename remove_cvref<T>::type;
409
#endif
410
411
#if __cpp_lib_type_identity >= 201806L
412
using std::type_identity, std::type_identity_t;
413
#else
414
template<class T>
415
struct type_identity {
416
using type = T;
417
};
418
419
template<class T>
420
using type_identity_t = typename type_identity<T>::type;
421
#endif
422
423
#if 0 // __cpp_lib_detect >= 0L // library fundamentals TS v2, [meta.detect]
424
using std::nonesuch;
425
using std::detector;
426
using std::is_detected, std::is_detected_v;
427
using std::detected, std::detected_t;
428
using std::detected_or, std::detected_or_t;
429
#else
430
struct nonesuch {
431
~nonesuch() = delete;
432
nonesuch(const nonesuch&) = delete;
433
void operator=(const nonesuch&) = delete;
434
};
435
436
template<class Default, class AlwaysVoid, template<class...> class Op, class... Args>
437
struct detector {
438
using value_t = std::false_type;
439
using type = Default;
440
};
441
442
template<class Default, template<class...> class Op, class... Args>
443
struct detector<Default, polyfill::void_t<Op<Args...>>, Op, Args...> {
444
using value_t = std::true_type;
445
using type = Op<Args...>;
446
};
447
448
template<template<class...> class Op, class... Args>
449
using is_detected = typename detector<nonesuch, void, Op, Args...>::value_t;
450
451
template<template<class...> class Op, class... Args>
452
using detected = detector<nonesuch, void, Op, Args...>;
453
454
template<template<class...> class Op, class... Args>
455
using detected_t = typename detector<nonesuch, void, Op, Args...>::type;
456
457
template<class Default, template<class...> class Op, class... Args>
458
using detected_or = detector<Default, void, Op, Args...>;
459
460
template<class Default, template<class...> class Op, class... Args>
461
using detected_or_t = typename detected_or<Default, Op, Args...>::type;
462
463
template<template<class...> class Op, class... Args>
464
SQLITE_ORM_INLINE_VAR constexpr bool is_detected_v = is_detected<Op, Args...>::value;
465
#endif
466
467
#if 0 // proposed but not pursued
468
using std::is_specialization_of, std::is_specialization_of_t, std::is_specialization_of_v;
469
#else
470
// is_specialization_of: https://github.com/cplusplus/papers/issues/812
471
472
template<typename Type, template<typename...> class Primary>
473
SQLITE_ORM_INLINE_VAR constexpr bool is_specialization_of_v = false;
474
475
template<template<typename...> class Primary, class... Types>
476
SQLITE_ORM_INLINE_VAR constexpr bool is_specialization_of_v<Primary<Types...>, Primary> = true;
477
478
template<typename Type, template<typename...> class Primary>
479
struct is_specialization_of : bool_constant<is_specialization_of_v<Type, Primary>> {};
480
#endif
481
482
template<typename...>
483
SQLITE_ORM_INLINE_VAR constexpr bool always_false_v = false;
484
485
template<size_t I>
486
using index_constant = std::integral_constant<size_t, I>;
487
}
488
}
489
490
namespace polyfill = internal::polyfill;
491
}
492
493
// #include "functional/cxx_functional_polyfill.h"
494
495
#include <functional>
496
#if __cpp_lib_invoke < 201411L
497
#include <type_traits> // std::enable_if, std::is_member_object_pointer, std::is_member_function_pointer
498
#endif
499
#include <utility> // std::forward
500
501
// #include "cxx_type_traits_polyfill.h"
502
503
// #include "../member_traits/member_traits.h"
504
505
#include <type_traits> // std::enable_if, std::is_function, std::true_type, std::false_type
506
507
// #include "../functional/cxx_type_traits_polyfill.h"
508
509
namespace sqlite_orm {
510
namespace internal {
511
// SFINAE friendly trait to get a member object pointer's field type
512
template<class T>
513
struct object_field_type {};
514
515
template<class T>
516
using object_field_type_t = typename object_field_type<T>::type;
517
518
template<class F, class O>
519
struct object_field_type<F O::*> : std::enable_if<!std::is_function<F>::value, F> {};
520
521
// SFINAE friendly trait to get a member function pointer's field type (i.e. unqualified return type)
522
template<class T>
523
struct getter_field_type {};
524
525
template<class T>
526
using getter_field_type_t = typename getter_field_type<T>::type;
527
528
template<class T, class O>
529
struct getter_field_type<T O::*> : getter_field_type<T> {};
530
531
template<class F>
532
struct getter_field_type<F(void) const> : polyfill::remove_cvref<F> {};
533
534
template<class F>
535
struct getter_field_type<F(void)> : polyfill::remove_cvref<F> {};
536
537
#ifdef SQLITE_ORM_NOTHROW_ALIASES_SUPPORTED
538
template<class F>
539
struct getter_field_type<F(void) const noexcept> : polyfill::remove_cvref<F> {};
540
541
template<class F>
542
struct getter_field_type<F(void) noexcept> : polyfill::remove_cvref<F> {};
543
#endif
544
545
// SFINAE friendly trait to get a member function pointer's field type (i.e. unqualified parameter type)
546
template<class T>
547
struct setter_field_type {};
548
549
template<class T>
550
using setter_field_type_t = typename setter_field_type<T>::type;
551
552
template<class T, class O>
553
struct setter_field_type<T O::*> : setter_field_type<T> {};
554
555
template<class F>
556
struct setter_field_type<void(F)> : polyfill::remove_cvref<F> {};
557
558
#ifdef SQLITE_ORM_NOTHROW_ALIASES_SUPPORTED
559
template<class F>
560
struct setter_field_type<void(F) noexcept> : polyfill::remove_cvref<F> {};
561
#endif
562
563
template<class T, class SFINAE = void>
564
struct is_getter : std::false_type {};
565
template<class T>
566
struct is_getter<T, polyfill::void_t<getter_field_type_t<T>>> : std::true_type {};
567
568
template<class T>
569
SQLITE_ORM_INLINE_VAR constexpr bool is_getter_v = is_getter<T>::value;
570
571
template<class T, class SFINAE = void>
572
struct is_setter : std::false_type {};
573
template<class T>
574
struct is_setter<T, polyfill::void_t<setter_field_type_t<T>>> : std::true_type {};
575
576
template<class T>
577
SQLITE_ORM_INLINE_VAR constexpr bool is_setter_v = is_setter<T>::value;
578
579
template<class T>
580
struct member_field_type : object_field_type<T>, getter_field_type<T>, setter_field_type<T> {};
581
582
template<class T>
583
using member_field_type_t = typename member_field_type<T>::type;
584
585
template<class T>
586
struct member_object_type {};
587
588
template<class F, class O>
589
struct member_object_type<F O::*> : polyfill::type_identity<O> {};
590
591
template<class T>
592
using member_object_type_t = typename member_object_type<T>::type;
593
}
594
}
595
596
namespace sqlite_orm {
597
namespace internal {
598
namespace polyfill {
599
// C++20 or later (unfortunately there's no feature test macro).
600
// Stupidly, clang says C++20, but `std::identity` was only implemented in libc++ 13 and libstd++-v3 10
601
// (the latter is used on Linux).
602
// gcc got it right and reports C++20 only starting with v10.
603
// The check here doesn't care and checks the library versions in use.
604
//
605
// Another way of detection would be the constrained algorithms feature-test macro __cpp_lib_ranges
606
#if (__cplusplus >= 202002L) && \
607
((!_LIBCPP_VERSION || _LIBCPP_VERSION >= 13000) && (!_GLIBCXX_RELEASE || _GLIBCXX_RELEASE >= 10))
608
using std::identity;
609
#else
610
struct identity {
611
template<class T>
612
constexpr T&& operator()(T&& v) const noexcept {
613
return std::forward<T>(v);
614
}
615
616
using is_transparent = int;
617
};
618
#endif
619
620
#if __cpp_lib_invoke >= 201411L
621
using std::invoke;
622
#else
623
// pointer-to-data-member+object
624
template<class Callable,
625
class Object,
626
class... Args,
627
class Unqualified = remove_cvref_t<Callable>,
628
std::enable_if_t<std::is_member_object_pointer<Unqualified>::value, bool> = true>
629
decltype(auto) invoke(Callable&& callable, Object&& object, Args&&... args) {
630
return std::forward<Object>(object).*callable;
631
}
632
633
// pointer-to-member-function+object
634
template<class Callable,
635
class Object,
636
class... Args,
637
class Unqualified = remove_cvref_t<Callable>,
638
std::enable_if_t<std::is_member_function_pointer<Unqualified>::value, bool> = true>
639
decltype(auto) invoke(Callable&& callable, Object&& object, Args&&... args) {
640
return (std::forward<Object>(object).*callable)(std::forward<Args>(args)...);
641
}
642
643
// pointer-to-member+reference-wrapped object (expect `reference_wrapper::*`)
644
template<class Callable,
645
class Object,
646
class... Args,
647
std::enable_if_t<polyfill::negation<polyfill::is_specialization_of<
648
member_object_type_t<std::remove_reference_t<Callable>>,
649
std::reference_wrapper>>::value,
650
bool> = true>
651
decltype(auto) invoke(Callable&& callable, std::reference_wrapper<Object> wrapper, Args&&... args) {
652
return invoke(std::forward<Callable>(callable), wrapper.get(), std::forward<Args>(args)...);
653
}
654
655
// functor
656
template<class Callable, class... Args>
657
decltype(auto) invoke(Callable&& callable, Args&&... args) {
658
return std::forward<Callable>(callable)(std::forward<Args>(args)...);
659
}
660
#endif
661
}
662
}
663
664
namespace polyfill = internal::polyfill;
665
}
666
667
// #include "functional/static_magic.h"
668
669
#ifndef SQLITE_ORM_IF_CONSTEXPR_SUPPORTED
670
#include <type_traits> // std::false_type, std::true_type, std::integral_constant
671
#endif
672
#include <utility> // std::forward
673
674
namespace sqlite_orm {
675
676
// got from here
677
// https://stackoverflow.com/questions/37617677/implementing-a-compile-time-static-if-logic-for-different-string-types-in-a-co
678
namespace internal {
679
680
// note: this is a class template accompanied with a variable template because older compilers (e.g. VC 2017)
681
// cannot handle a static lambda variable inside a template function
682
template<class R>
683
struct empty_callable_t {
684
template<class... Args>
685
R operator()(Args&&...) const {
686
return R();
687
}
688
};
689
template<class R = void>
690
constexpr empty_callable_t<R> empty_callable{};
691
692
#ifdef SQLITE_ORM_IF_CONSTEXPR_SUPPORTED
693
template<bool B, typename T, typename F>
694
decltype(auto) static_if([[maybe_unused]] T&& trueFn, [[maybe_unused]] F&& falseFn) {
695
if constexpr (B) {
696
return std::forward<T>(trueFn);
697
} else {
698
return std::forward<F>(falseFn);
699
}
700
}
701
702
template<bool B, typename T>
703
decltype(auto) static_if([[maybe_unused]] T&& trueFn) {
704
if constexpr (B) {
705
return std::forward<T>(trueFn);
706
} else {
707
return empty_callable<>;
708
}
709
}
710
711
template<bool B, typename L, typename... Args>
712
void call_if_constexpr([[maybe_unused]] L&& lambda, [[maybe_unused]] Args&&... args) {
713
if constexpr (B) {
714
lambda(std::forward<Args>(args)...);
715
}
716
}
717
#else
718
template<typename T, typename F>
719
decltype(auto) static_if(std::true_type, T&& trueFn, const F&) {
720
return std::forward<T>(trueFn);
721
}
722
723
template<typename T, typename F>
724
decltype(auto) static_if(std::false_type, const T&, F&& falseFn) {
725
return std::forward<F>(falseFn);
726
}
727
728
template<bool B, typename T, typename F>
729
decltype(auto) static_if(T&& trueFn, F&& falseFn) {
730
return static_if(std::integral_constant<bool, B>{}, std::forward<T>(trueFn), std::forward<F>(falseFn));
731
}
732
733
template<bool B, typename T>
734
decltype(auto) static_if(T&& trueFn) {
735
return static_if(std::integral_constant<bool, B>{}, std::forward<T>(trueFn), empty_callable<>);
736
}
737
738
template<bool B, typename L, typename... Args>
739
void call_if_constexpr(L&& lambda, Args&&... args) {
740
static_if<B>(std::forward<L>(lambda))(std::forward<Args>(args)...);
741
}
742
#endif
743
}
744
745
}
746
747
// #include "functional/mpl.h"
748
749
/*
750
* Symbols for 'template metaprogramming' (compile-time template programming),
751
* inspired by the MPL of Aleksey Gurtovoy and David Abrahams, and the Mp11 of Peter Dimov and Bjorn Reese.
752
*
753
* Currently, the focus is on facilitating advanced type filtering,
754
* such as filtering columns by constraints having various traits.
755
* Hence it contains only a very small subset of a full MPL.
756
*
757
* Three key concepts are critical to understanding:
758
* 1. A 'trait' is a class template with a nested `type` typename.
759
* The term 'trait' might be too narrow or not entirely accurate, however in the STL those class templates are summarized as "Type transformations".
760
* hence being "transformation type traits".
761
* It was the traditional way of transforming types before the arrival of alias templates.
762
* E.g. `template<class T> struct x { using type = T; };`
763
* They are of course still available today, but are rather used as building blocks.
764
* 2. A 'metafunction' is an alias template for a class template or a nested template expression, whose instantiation yields a type.
765
* E.g. `template<class T> using alias_op_t = typename x<T>::type`
766
* 3. A 'quoted metafunction' (aka 'metafunction class') is a certain form of metafunction representation that enables higher-order metaprogramming.
767
* More precisely, it's a class with a nested metafunction called "fn".
768
* Correspondingly, a quoted metafunction invocation is defined as invocation of its nested "fn" metafunction.
769
*
770
* Conventions:
771
* - "Fn" is the name of a template template parameter for a metafunction.
772
* - "Q" is the name of class template parameter for a quoted metafunction.
773
* - "_fn" is a suffix for a class or alias template that accepts metafunctions and turns them into quoted metafunctions.
774
* - "higher order" denotes a metafunction that operates on another metafunction (i.e. takes it as an argument).
775
*/
776
777
#include <type_traits> // std::true_type, std::false_type, std::is_same, std::negation, std::conjunction, std::disjunction
778
#ifdef SQLITE_ORM_RELAXED_CONSTEXPR_SUPPORTED
779
#include <initializer_list>
780
#else
781
#include <array>
782
#endif
783
784
// #include "cxx_type_traits_polyfill.h"
785
786
// #include "mpl/conditional.h"
787
788
namespace sqlite_orm {
789
namespace internal {
790
namespace mpl {
791
template<template<class...> class Fn>
792
struct indirectly_test_metafunction;
793
794
/*
795
* Determines whether a class template has a nested metafunction `fn`.
796
*
797
* Implementation note: the technique of specialiazing on the inline variable must come first because
798
* of older compilers having problems with the detection of dependent templates [SQLITE_ORM_BROKEN_ALIAS_TEMPLATE_DEPENDENT_EXPR_SFINAE].
799
*/
800
template<class T, class SFINAE = void>
801
SQLITE_ORM_INLINE_VAR constexpr bool is_quoted_metafuntion_v = false;
802
template<class Q>
803
SQLITE_ORM_INLINE_VAR constexpr bool
804
is_quoted_metafuntion_v<Q, polyfill::void_t<indirectly_test_metafunction<Q::template fn>>> = true;
805
806
template<class T>
807
struct is_quoted_metafuntion : polyfill::bool_constant<is_quoted_metafuntion_v<T>> {};
808
809
/*
810
* Type pack.
811
*/
812
template<class...>
813
struct pack {};
814
815
/*
816
* The indirection through `defer_fn` works around the language inability
817
* to expand `Args...` into a fixed parameter list of an alias template.
818
*
819
* Also, legacy compilers need an extra layer of indirection, otherwise type replacement may fail
820
* if alias template `Fn` has a dependent expression in it.
821
*/
822
template<template<class...> class Fn, class... Args>
823
struct defer_fn {
824
using type = Fn<Args...>;
825
};
826
827
/*
828
* The indirection through `defer` works around the language inability
829
* to expand `Args...` into a fixed parameter list of an alias template.
830
*/
831
template<class Q, class... Args>
832
struct defer {
833
using type = typename Q::template fn<Args...>;
834
};
835
836
/*
837
* Invoke metafunction.
838
*/
839
template<template<class...> class Fn, class... Args>
840
using invoke_fn_t = typename defer_fn<Fn, Args...>::type;
841
842
/*
843
* Invoke quoted metafunction by invoking its nested metafunction.
844
*/
845
template<class Q, class... Args>
846
using invoke_t = typename defer<Q, Args...>::type;
847
848
/*
849
* Turn metafunction into a quoted metafunction.
850
*
851
* Invocation of the nested metafunction `fn` is SFINAE-friendly (detection idiom).
852
* This is necessary because `fn` is a proxy to the originally quoted metafunction,
853
* and the instantiation of the metafunction might be an invalid expression.
854
*/
855
template<template<class...> class Fn>
856
struct quote_fn {
857
template<class InvocableTest, template<class...> class, class...>
858
struct invoke_this_fn {
859
// error N: 'type': is not a member of any direct or indirect base class of 'quote_fn<Fn>::invoke_this_fn<void,Fn,T>'
860
// means that the metafunction cannot be called with the passed arguments.
861
};
862
863
template<template<class...> class F, class... Args>
864
struct invoke_this_fn<polyfill::void_t<F<Args...>>, F, Args...> {
865
using type = F<Args...>;
866
};
867
868
template<class... Args>
869
using fn = typename invoke_this_fn<void, Fn, Args...>::type;
870
};
871
872
/*
873
* Indirection wrapper for higher-order metafunctions,
874
* specialized on the argument indexes where metafunctions appear.
875
*/
876
template<size_t...>
877
struct higherorder;
878
879
template<>
880
struct higherorder<0u> {
881
template<template<template<class...> class Fn, class... Args2> class HigherFn, class Q, class... Args>
882
struct defer_higher_fn {
883
using type = HigherFn<Q::template fn, Args...>;
884
};
885
886
/*
887
* Turn higher-order metafunction into a quoted metafunction.
888
*/
889
template<template<template<class...> class Fn, class... Args2> class HigherFn>
890
struct quote_fn {
891
template<class Q, class... Args>
892
using fn = typename defer_higher_fn<HigherFn, Q, Args...>::type;
893
};
894
};
895
896
/*
897
* Quoted metafunction that extracts the nested metafunction of its quoted metafunction argument,
898
* quotes the extracted metafunction and passes it on to the next quoted metafunction
899
* (kind of the inverse of quoting).
900
*/
901
template<class Q>
902
struct pass_extracted_fn_to {
903
template<class... Args>
904
struct invoke_this_fn {
905
using type = typename Q::template fn<Args...>;
906
};
907
908
// extract class template, quote, pass on
909
template<template<class...> class Fn, class... T>
910
struct invoke_this_fn<Fn<T...>> {
911
using type = typename Q::template fn<quote_fn<Fn>>;
912
};
913
914
template<class... Args>
915
using fn = typename invoke_this_fn<Args...>::type;
916
};
917
918
/*
919
* Quoted metafunction that invokes the specified quoted metafunctions,
920
* and passes their results on to the next quoted metafunction.
921
*/
922
template<class Q, class... Qs>
923
struct pass_result_of {
924
// invoke `Fn`, pass on their result
925
template<class... Args>
926
using fn = typename Q::template fn<typename defer<Qs, Args...>::type...>;
927
};
928
929
/*
930
* Quoted metafunction that invokes the specified metafunctions,
931
* and passes their results on to the next quoted metafunction.
932
*/
933
template<class Q, template<class...> class... Fn>
934
using pass_result_of_fn = pass_result_of<Q, quote_fn<Fn>...>;
935
936
/*
937
* Bind arguments at the front of a quoted metafunction.
938
*/
939
template<class Q, class... Bound>
940
struct bind_front {
941
template<class... Args>
942
using fn = typename Q::template fn<Bound..., Args...>;
943
};
944
945
/*
946
* Bind arguments at the back of a quoted metafunction.
947
*/
948
template<class Q, class... Bound>
949
struct bind_back {
950
template<class... Args>
951
using fn = typename Q::template fn<Args..., Bound...>;
952
};
953
954
/*
955
* Quoted metafunction equivalent to `polyfill::always_false`.
956
* It ignores arguments passed to the metafunction, and always returns the specified type.
957
*/
958
template<class T>
959
struct always {
960
template<class... /*Args*/>
961
using fn = T;
962
};
963
964
/*
965
* Unary quoted metafunction equivalent to `std::type_identity_t`.
966
*/
967
using identity = quote_fn<polyfill::type_identity_t>;
968
969
/*
970
* Quoted metafunction equivalent to `std::negation`.
971
*/
972
template<class TraitQ>
973
using not_ = pass_result_of<quote_fn<polyfill::negation>, TraitQ>;
974
975
/*
976
* Quoted metafunction equivalent to `std::conjunction`.
977
*/
978
template<class... TraitQ>
979
struct conjunction {
980
template<class... Args>
981
using fn = std::true_type;
982
};
983
984
template<class FirstQ, class... TraitQ>
985
struct conjunction<FirstQ, TraitQ...> {
986
// match last or `std::false_type`
987
template<class ArgPack, class ResultTrait, class...>
988
struct invoke_this_fn {
989
static_assert(std::is_same<ResultTrait, std::true_type>::value ||
990
std::is_same<ResultTrait, std::false_type>::value,
991
"Resulting trait must be a std::bool_constant");
992
using type = ResultTrait;
993
};
994
995
// match `std::true_type` and one or more remaining
996
template<class... Args, class NextQ, class... RestQ>
997
struct invoke_this_fn<pack<Args...>, std::true_type, NextQ, RestQ...>
998
: invoke_this_fn<pack<Args...>,
999
// access resulting trait::type
1000
typename defer<NextQ, Args...>::type::type,
1001
RestQ...> {};
1002
1003
template<class... Args>
1004
using fn = typename invoke_this_fn<pack<Args...>,
1005
// access resulting trait::type
1006
typename defer<FirstQ, Args...>::type::type,
1007
TraitQ...>::type;
1008
};
1009
1010
/*
1011
* Quoted metafunction equivalent to `std::disjunction`.
1012
*/
1013
template<class... TraitQ>
1014
struct disjunction {
1015
template<class... Args>
1016
using fn = std::false_type;
1017
};
1018
1019
template<class FirstQ, class... TraitQ>
1020
struct disjunction<FirstQ, TraitQ...> {
1021
// match last or `std::true_type`
1022
template<class ArgPack, class ResultTrait, class...>
1023
struct invoke_this_fn {
1024
static_assert(std::is_same<ResultTrait, std::true_type>::value ||
1025
std::is_same<ResultTrait, std::false_type>::value,
1026
"Resulting trait must be a std::bool_constant");
1027
using type = ResultTrait;
1028
};
1029
1030
// match `std::false_type` and one or more remaining
1031
template<class... Args, class NextQ, class... RestQ>
1032
struct invoke_this_fn<pack<Args...>, std::false_type, NextQ, RestQ...>
1033
: invoke_this_fn<pack<Args...>,
1034
// access resulting trait::type
1035
typename defer<NextQ, Args...>::type::type,
1036
RestQ...> {};
1037
1038
template<class... Args>
1039
using fn = typename invoke_this_fn<pack<Args...>,
1040
// access resulting trait::type
1041
typename defer<FirstQ, Args...>::type::type,
1042
TraitQ...>::type;
1043
};
1044
1045
/*
1046
* Metafunction equivalent to `std::conjunction`.
1047
*/
1048
template<template<class...> class... TraitFn>
1049
using conjunction_fn = pass_result_of_fn<quote_fn<polyfill::conjunction>, TraitFn...>;
1050
1051
/*
1052
* Metafunction equivalent to `std::disjunction`.
1053
*/
1054
template<template<class...> class... TraitFn>
1055
using disjunction_fn = pass_result_of_fn<quote_fn<polyfill::disjunction>, TraitFn...>;
1056
1057
/*
1058
* Metafunction equivalent to `std::negation`.
1059
*/
1060
template<template<class...> class Fn>
1061
using not_fn = pass_result_of_fn<quote_fn<polyfill::negation>, Fn>;
1062
1063
/*
1064
* Bind arguments at the front of a metafunction.
1065
*/
1066
template<template<class...> class Fn, class... Bound>
1067
using bind_front_fn = bind_front<quote_fn<Fn>, Bound...>;
1068
1069
/*
1070
* Bind arguments at the back of a metafunction.
1071
*/
1072
template<template<class...> class Fn, class... Bound>
1073
using bind_back_fn = bind_back<quote_fn<Fn>, Bound...>;
1074
1075
/*
1076
* Bind a metafunction and arguments at the front of a higher-order metafunction.
1077
*/
1078
template<template<template<class...> class Fn, class... Args2> class HigherFn,
1079
template<class...> class BoundFn,
1080
class... Bound>
1081
using bind_front_higherorder_fn =
1082
bind_front<higherorder<0>::quote_fn<HigherFn>, quote_fn<BoundFn>, Bound...>;
1083
1084
#ifdef SQLITE_ORM_RELAXED_CONSTEXPR_SUPPORTED
1085
constexpr size_t find_first_true_helper(std::initializer_list<bool> values) {
1086
size_t i = 0;
1087
for (auto first = values.begin(); first != values.end() && !*first; ++first) {
1088
++i;
1089
}
1090
return i;
1091
}
1092
1093
constexpr size_t count_true_helper(std::initializer_list<bool> values) {
1094
size_t n = 0;
1095
for (auto first = values.begin(); first != values.end(); ++first) {
1096
n += *first;
1097
}
1098
return n;
1099
}
1100
#else
1101
template<size_t N>
1102
constexpr size_t find_first_true_helper(const std::array<bool, N>& values, size_t i = 0) {
1103
return i == N || values[i] ? 0 : 1 + find_first_true_helper(values, i + 1);
1104
}
1105
1106
template<size_t N>
1107
constexpr size_t count_true_helper(const std::array<bool, N>& values, size_t i = 0) {
1108
return i == N ? 0 : values[i] + count_true_helper(values, i + 1);
1109
}
1110
#endif
1111
1112
/*
1113
* Quoted metafunction that invokes the specified quoted predicate metafunction on each element of a type list,
1114
* and returns the index constant of the first element for which the predicate returns true.
1115
*/
1116
template<class PredicateQ>
1117
struct finds {
1118
template<class Pack, class ProjectQ>
1119
struct invoke_this_fn {
1120
static_assert(polyfill::always_false_v<Pack>,
1121
"`finds` must be invoked with a type list as first argument.");
1122
};
1123
1124
template<template<class...> class Pack, class... T, class ProjectQ>
1125
struct invoke_this_fn<Pack<T...>, ProjectQ> {
1126
// hoist result into `value` [SQLITE_ORM_BROKEN_ALIAS_TEMPLATE_DEPENDENT_NTTP_EXPR]
1127
static constexpr size_t value = find_first_true_helper
1128
#ifndef SQLITE_ORM_RELAXED_CONSTEXPR_SUPPORTED
1129
<sizeof...(T)>
1130
#endif
1131
({PredicateQ::template fn<typename ProjectQ::template fn<T>>::value...});
1132
using type = polyfill::index_constant<value>;
1133
};
1134
1135
template<class Pack, class ProjectQ = identity>
1136
using fn = typename invoke_this_fn<Pack, ProjectQ>::type;
1137
};
1138
1139
template<template<class...> class PredicateFn>
1140
using finds_fn = finds<quote_fn<PredicateFn>>;
1141
1142
/*
1143
* Quoted metafunction that invokes the specified quoted predicate metafunction on each element of a type list,
1144
* and returns the index constant of the first element for which the predicate returns true.
1145
*/
1146
template<class PredicateQ>
1147
struct counts {
1148
template<class Pack, class ProjectQ>
1149
struct invoke_this_fn {
1150
static_assert(polyfill::always_false_v<Pack>,
1151
"`counts` must be invoked with a type list as first argument.");
1152
};
1153
1154
template<template<class...> class Pack, class... T, class ProjectQ>
1155
struct invoke_this_fn<Pack<T...>, ProjectQ> {
1156
// hoist result into `value` [SQLITE_ORM_BROKEN_ALIAS_TEMPLATE_DEPENDENT_NTTP_EXPR]
1157
static constexpr size_t value = count_true_helper
1158
#ifndef SQLITE_ORM_RELAXED_CONSTEXPR_SUPPORTED
1159
<sizeof...(T)>
1160
#endif
1161
({PredicateQ::template fn<typename ProjectQ::template fn<T>>::value...});
1162
using type = polyfill::index_constant<value>;
1163
};
1164
1165
template<class Pack, class ProjectQ = identity>
1166
using fn = typename invoke_this_fn<Pack, ProjectQ>::type;
1167
};
1168
1169
template<template<class...> class PredicateFn>
1170
using counts_fn = counts<quote_fn<PredicateFn>>;
1171
1172
/*
1173
* Quoted metafunction that invokes the specified quoted predicate metafunction on each element of a type list,
1174
* and returns the index constant of the first element for which the predicate returns true.
1175
*/
1176
template<class TraitQ>
1177
struct contains {
1178
template<class Pack, class ProjectQ>
1179
struct invoke_this_fn {
1180
static_assert(polyfill::always_false_v<Pack>,
1181
"`contains` must be invoked with a type list as first argument.");
1182
};
1183
1184
template<template<class...> class Pack, class... T, class ProjectQ>
1185
struct invoke_this_fn<Pack<T...>, ProjectQ> {
1186
// hoist result into `value` [SQLITE_ORM_BROKEN_ALIAS_TEMPLATE_DEPENDENT_NTTP_EXPR]
1187
static constexpr size_t value =
1188
static_cast<bool>(count_true_helper
1189
#ifndef SQLITE_ORM_RELAXED_CONSTEXPR_SUPPORTED
1190
<sizeof...(T)>
1191
#endif
1192
({TraitQ::template fn<typename ProjectQ::template fn<T>>::value...}));
1193
using type = polyfill::bool_constant<value>;
1194
};
1195
1196
template<class Pack, class ProjectQ = identity>
1197
using fn = typename invoke_this_fn<Pack, ProjectQ>::type;
1198
};
1199
1200
template<template<class...> class TraitFn>
1201
using contains_fn = contains<quote_fn<TraitFn>>;
1202
}
1203
}
1204
1205
namespace mpl = internal::mpl;
1206
1207
// convenience quoted metafunctions
1208
namespace internal {
1209
/*
1210
* Quoted trait metafunction that checks if a type has the specified trait.
1211
*/
1212
template<template<class...> class TraitFn, class... Bound>
1213
using check_if =
1214
mpl::conditional_t<sizeof...(Bound) == 0, mpl::quote_fn<TraitFn>, mpl::bind_front_fn<TraitFn, Bound...>>;
1215
1216
/*
1217
* Quoted trait metafunction that checks if a type doesn't have the specified trait.
1218
*/
1219
template<template<class...> class TraitFn>
1220
using check_if_not = mpl::not_fn<TraitFn>;
1221
1222
/*
1223
* Quoted trait metafunction that checks if a type is the same as the specified type.
1224
* Commonly used named abbreviation for `check_if<std::is_same, Type>`.
1225
*/
1226
template<class Type>
1227
using check_if_is_type = mpl::bind_front_fn<std::is_same, Type>;
1228
1229
/*
1230
* Quoted trait metafunction that checks if a type's template matches the specified template
1231
* (similar to `is_specialization_of`).
1232
*/
1233
template<template<class...> class Template>
1234
using check_if_is_template =
1235
mpl::pass_extracted_fn_to<mpl::bind_front_fn<std::is_same, mpl::quote_fn<Template>>>;
1236
1237
/*
1238
* Quoted metafunction that finds the index of the given type in a tuple.
1239
*/
1240
template<class Type>
1241
using finds_if_has_type = mpl::finds<check_if_is_type<Type>>;
1242
1243
/*
1244
* Quoted metafunction that finds the index of the given class template in a tuple.
1245
*/
1246
template<template<class...> class Template>
1247
using finds_if_has_template = mpl::finds<check_if_is_template<Template>>;
1248
1249
/*
1250
* Quoted trait metafunction that counts tuple elements having a given trait.
1251
*/
1252
template<template<class...> class TraitFn>
1253
using counts_if_has = mpl::counts_fn<TraitFn>;
1254
1255
/*
1256
* Quoted trait metafunction that checks whether a tuple contains a type with given trait.
1257
*/
1258
template<template<class...> class TraitFn>
1259
using check_if_has = mpl::contains_fn<TraitFn>;
1260
1261
/*
1262
* Quoted trait metafunction that checks whether a tuple doesn't contain a type with given trait.
1263
*/
1264
template<template<class...> class TraitFn>
1265
using check_if_has_not = mpl::not_<mpl::contains_fn<TraitFn>>;
1266
1267
/*
1268
* Quoted metafunction that checks whether a tuple contains given type.
1269
*/
1270
template<class T>
1271
using check_if_has_type = mpl::contains<check_if_is_type<T>>;
1272
1273
/*
1274
* Quoted metafunction that checks whether a tuple contains a given template.
1275
*
1276
* Note: we are using 2 small tricks:
1277
* 1. A template template parameter can be treated like a metafunction, so we can just "quote" a 'primary'
1278
* template into the MPL system (e.g. `std::vector`).
1279
* 2. This quoted metafunction does the opposite of the trait metafunction `is_specialization`:
1280
* `is_specialization` tries to instantiate the primary template template parameter using the
1281
* template parameters of a template type, then compares both instantiated types.
1282
* Here instead, `pass_extracted_fn_to` extracts the template template parameter from a template type,
1283
* then compares the resulting template template parameters.
1284
*/
1285
template<template<class...> class Template>
1286
using check_if_has_template = mpl::contains<check_if_is_template<Template>>;
1287
}
1288
}
1289
1290
// #include "tuple_helper/tuple_traits.h"
1291
1292
// #include "../functional/cxx_type_traits_polyfill.h"
1293
1294
// #include "../functional/mpl.h"
1295
1296
namespace sqlite_orm {
1297
// convenience metafunction algorithms
1298
namespace internal {
1299
/*
1300
* Higher-order trait metafunction that checks whether a tuple contains a type with given trait (possibly projected).
1301
*
1302
* `ProjOp` is a metafunction
1303
*/
1304
template<class Pack,
1305
template<class...> class TraitFn,
1306
template<class...> class ProjOp = polyfill::type_identity_t>
1307
using tuple_has = mpl::invoke_t<check_if_has<TraitFn>, Pack, mpl::quote_fn<ProjOp>>;
1308
1309
/*
1310
* Higher-order trait metafunction that checks whether a tuple contains the specified type (possibly projected).
1311
*
1312
* `ProjOp` is a metafunction
1313
*/
1314
template<class Pack, class Type, template<class...> class ProjOp = polyfill::type_identity_t>
1315
using tuple_has_type = mpl::invoke_t<check_if_has_type<Type>, Pack, mpl::quote_fn<ProjOp>>;
1316
1317
/*
1318
* Higher-order trait metafunction that checks whether a tuple contains the specified class template (possibly projected).
1319
*
1320
* `ProjOp` is a metafunction
1321
*/
1322
template<class Pack,
1323
template<class...> class Template,
1324
template<class...> class ProjOp = polyfill::type_identity_t>
1325
using tuple_has_template = mpl::invoke_t<check_if_has_template<Template>, Pack, mpl::quote_fn<ProjOp>>;
1326
1327
/*
1328
* Higher-order metafunction returning the first index constant of the desired type in a tuple (possibly projected).
1329
*/
1330
template<class Pack, class Type, template<class...> class ProjOp = polyfill::type_identity_t>
1331
using find_tuple_type = mpl::invoke_t<finds_if_has_type<Type>, Pack, mpl::quote_fn<ProjOp>>;
1332
1333
/*
1334
* Higher-order metafunction returning the first index constant of the desired class template in a tuple (possibly projected).
1335
*
1336
* `ProjOp` is a metafunction
1337
*/
1338
template<class Pack,
1339
template<class...> class Template,
1340
template<class...> class ProjOp = polyfill::type_identity_t>
1341
using find_tuple_template = mpl::invoke_t<finds_if_has_template<Template>, Pack, mpl::quote_fn<ProjOp>>;
1342
1343
/*
1344
* Higher-order trait metafunction that counts the types having the specified trait in a tuple (possibly projected).
1345
*
1346
* `Pred` is a predicate metafunction with a nested bool member named `value`
1347
* `ProjOp` is a metafunction
1348
*/
1349
template<class Pack, template<class...> class Pred, template<class...> class ProjOp = polyfill::type_identity_t>
1350
using count_tuple = mpl::invoke_t<counts_if_has<Pred>, Pack, mpl::quote_fn<ProjOp>>;
1351
}
1352
}
1353
1354
// #include "tuple_helper/tuple_filter.h"
1355
1356
#include <type_traits> // std::integral_constant, std::index_sequence, std::conditional, std::declval
1357
#include <tuple> // std::tuple, std::tuple_cat, std::tuple_element
1358
1359
// #include "../functional/mpl/conditional.h"
1360
1361
// #include "../functional/index_sequence_util.h"
1362
1363
#include <utility> // std::index_sequence
1364
1365
namespace sqlite_orm {
1366
namespace internal {
1367
#if defined(SQLITE_ORM_PACK_INDEXING_SUPPORTED)
1368
/**
1369
* Get the index value of an `index_sequence` at a specific position.
1370
*/
1371
template<size_t Pos, size_t... Idx>
1372
SQLITE_ORM_CONSTEVAL auto index_sequence_value_at(std::index_sequence<Idx...>) {
1373
return Idx...[Pos];
1374
}
1375
#elif defined(SQLITE_ORM_FOLD_EXPRESSIONS_SUPPORTED)
1376
/**
1377
* Get the index value of an `index_sequence` at a specific position.
1378
*/
1379
template<size_t Pos, size_t... Idx>
1380
SQLITE_ORM_CONSTEVAL size_t index_sequence_value_at(std::index_sequence<Idx...>) {
1381
static_assert(Pos < sizeof...(Idx));
1382
#ifdef SQLITE_ORM_CONSTEVAL_SUPPORTED
1383
size_t result;
1384
#else
1385
size_t result = 0;
1386
#endif
1387
size_t i = 0;
1388
// note: `(void)` cast silences warning 'expression result unused'
1389
(void)((result = Idx, i++ == Pos) || ...);
1390
return result;
1391
}
1392
#else
1393
/**
1394
* Get the index value of an `index_sequence` at a specific position.
1395
* `Pos` must always be `0`.
1396
*/
1397
template<size_t Pos, size_t I, size_t... Idx>
1398
SQLITE_ORM_CONSTEVAL size_t index_sequence_value_at(std::index_sequence<I, Idx...>) {
1399
static_assert(Pos == 0, "");
1400
return I;
1401
}
1402
#endif
1403
1404
template<class... Seq>
1405
struct flatten_idxseq {
1406
using type = std::index_sequence<>;
1407
};
1408
1409
template<size_t... Ix>
1410
struct flatten_idxseq<std::index_sequence<Ix...>> {
1411
using type = std::index_sequence<Ix...>;
1412
};
1413
1414
template<size_t... As, size_t... Bs, class... Seq>
1415
struct flatten_idxseq<std::index_sequence<As...>, std::index_sequence<Bs...>, Seq...>
1416
: flatten_idxseq<std::index_sequence<As..., Bs...>, Seq...> {};
1417
1418
template<class... Seq>
1419
using flatten_idxseq_t = typename flatten_idxseq<Seq...>::type;
1420
}
1421
}
1422
1423
namespace sqlite_orm {
1424
namespace internal {
1425
1426
template<typename... input_t>
1427
using tuple_cat_t = decltype(std::tuple_cat(std::declval<input_t>()...));
1428
1429
template<class... Tpl>
1430
struct conc_tuple {
1431
using type = tuple_cat_t<Tpl...>;
1432
};
1433
1434
template<class Tpl, class Seq>
1435
struct tuple_from_index_sequence;
1436
1437
template<class Tpl, size_t... Idx>
1438
struct tuple_from_index_sequence<Tpl, std::index_sequence<Idx...>> {
1439
using type = std::tuple<std::tuple_element_t<Idx, Tpl>...>;
1440
};
1441
1442
template<class Tpl, class Seq>
1443
using tuple_from_index_sequence_t = typename tuple_from_index_sequence<Tpl, Seq>::type;
1444
1445
template<class Tpl, template<class...> class Pred, template<class...> class Proj, class Seq>
1446
struct filter_tuple_sequence;
1447
1448
#ifndef SQLITE_ORM_BROKEN_VARIADIC_PACK_EXPANSION
1449
template<class Tpl, template<class...> class Pred, template<class...> class Proj, size_t... Idx>
1450
struct filter_tuple_sequence<Tpl, Pred, Proj, std::index_sequence<Idx...>>
1451
: flatten_idxseq<mpl::conditional_t<Pred<mpl::invoke_fn_t<Proj, std::tuple_element_t<Idx, Tpl>>>::value,
1452
std::index_sequence<Idx>,
1453
std::index_sequence<>>...> {};
1454
#else
1455
template<size_t Idx, class T, template<class...> class Pred, class SFINAE = void>
1456
struct tuple_seq_single {
1457
using type = std::index_sequence<>;
1458
};
1459
1460
template<size_t Idx, class T, template<class...> class Pred>
1461
struct tuple_seq_single<Idx, T, Pred, std::enable_if_t<Pred<T>::value>> {
1462
using type = std::index_sequence<Idx>;
1463
};
1464
1465
template<class Tpl, template<class...> class Pred, template<class...> class Proj, size_t... Idx>
1466
struct filter_tuple_sequence<Tpl, Pred, Proj, std::index_sequence<Idx...>>
1467
: flatten_idxseq<typename tuple_seq_single<Idx,
1468
mpl::invoke_fn_t<Proj, std::tuple_element_t<Idx, Tpl>>,
1469
Pred>::type...> {};
1470
#endif
1471
1472
/*
1473
* `Pred` is a metafunction that defines a bool member named `value`
1474
* `FilterProj` is a metafunction
1475
*/
1476
template<class Tpl,
1477
template<class...> class Pred,
1478
template<class...> class FilterProj = polyfill::type_identity_t,
1479
class Seq = std::make_index_sequence<std::tuple_size<Tpl>::value>>
1480
using filter_tuple_sequence_t = typename filter_tuple_sequence<Tpl, Pred, FilterProj, Seq>::type;
1481
1482
/*
1483
* `Pred` is a metafunction that defines a bool member named `value`
1484
* `FilterProj` is a metafunction
1485
*/
1486
template<class Tpl,
1487
template<class...> class Pred,
1488
template<class...> class FilterProj = polyfill::type_identity_t,
1489
class Seq = std::make_index_sequence<std::tuple_size<Tpl>::value>>
1490
using filter_tuple_t = tuple_from_index_sequence_t<Tpl, filter_tuple_sequence_t<Tpl, Pred, FilterProj, Seq>>;
1491
1492
/*
1493
* Count a tuple, picking only those elements specified in the index sequence.
1494
*
1495
* `Pred` is a metafunction that defines a bool member named `value`
1496
* `FilterProj` is a metafunction
1497
*
1498
* Implementation note: must be distinct from a `count_tuple` w/o index sequence parameter because legacy compilers have problems
1499
* with a default Sequence in function template parameters [SQLITE_ORM_BROKEN_VARIADIC_PACK_EXPANSION].
1500
*/
1501
template<class Tpl,
1502
template<class...> class Pred,
1503
class Seq,
1504
template<class...> class FilterProj = polyfill::type_identity_t>
1505
struct count_filtered_tuple
1506
: std::integral_constant<size_t, filter_tuple_sequence_t<Tpl, Pred, FilterProj, Seq>::size()> {};
1507
}
1508
}
1509
1510
// #include "tuple_helper/tuple_transformer.h"
1511
1512
#include <type_traits> // std::remove_reference, std::common_type, std::index_sequence, std::make_index_sequence, std::forward, std::move, std::integral_constant, std::declval
1513
#include <tuple> // std::tuple_size, std::get
1514
1515
// #include "../functional/cxx_type_traits_polyfill.h"
1516
1517
// #include "../functional/cxx_functional_polyfill.h"
1518
1519
// #include "../functional/mpl.h"
1520
1521
namespace sqlite_orm {
1522
namespace internal {
1523
1524
template<class Pack, template<class...> class Op>
1525
struct tuple_transformer;
1526
1527
template<template<class...> class Pack, class... Types, template<class...> class Op>
1528
struct tuple_transformer<Pack<Types...>, Op> {
1529
using type = Pack<mpl::invoke_fn_t<Op, Types>...>;
1530
};
1531
1532
/*
1533
* Transform specified tuple.
1534
*
1535
* `Op` is a metafunction.
1536
*/
1537
template<class Pack, template<class...> class Op>
1538
using transform_tuple_t = typename tuple_transformer<Pack, Op>::type;
1539
1540
// note: applying a combiner like `plus_fold_integrals` needs fold expressions
1541
#if defined(SQLITE_ORM_FOLD_EXPRESSIONS_SUPPORTED)
1542
/*
1543
* Apply a projection to a tuple's elements filtered by the specified indexes, and combine the results.
1544
*
1545
* @note It's a glorified version of `std::apply()` and a variant of `std::accumulate()`.
1546
* It combines filtering the tuple (indexes), transforming the elements (projection) and finally applying the callable (combine).
1547
*
1548
* @note `project` is called using `std::invoke`, which is `constexpr` since C++20.
1549
*/
1550
template<class CombineOp, class Tpl, size_t... Idx, class Projector, class Init>
1551
SQLITE_ORM_CONSTEXPR_CPP20 auto recombine_tuple(CombineOp combine,
1552
const Tpl& tpl,
1553
std::index_sequence<Idx...>,
1554
Projector project,
1555
Init initial) {
1556
return combine(initial, polyfill::invoke(project, std::get<Idx>(tpl))...);
1557
}
1558
1559
/*
1560
* Apply a projection to a tuple's elements, and combine the results.
1561
*
1562
* @note It's a glorified version of `std::apply()` and a variant of `std::accumulate()`.
1563
* It combines filtering the tuple (indexes), transforming the elements (projection) and finally applying the callable (combine).
1564
*
1565
* @note `project` is called using `std::invoke`, which is `constexpr` since C++20.
1566
*/
1567
template<class CombineOp, class Tpl, class Projector, class Init>
1568
SQLITE_ORM_CONSTEXPR_CPP20 auto
1569
recombine_tuple(CombineOp combine, const Tpl& tpl, Projector project, Init initial) {
1570
return recombine_tuple(std::move(combine),
1571
std::forward<decltype(tpl)>(tpl),
1572
std::make_index_sequence<std::tuple_size<Tpl>::value>{},
1573
std::move(project),
1574
std::move(initial));
1575
}
1576
1577
/*
1578
* Function object that takes integral constants and returns the sum of their values as an integral constant.
1579
* Because it's a "transparent" functor, it must be called with at least one argument, otherwise it cannot deduce the integral constant type.
1580
*/
1581
struct plus_fold_integrals {
1582
template<class... Integrals>
1583
constexpr auto operator()(const Integrals&...) const {
1584
using integral_type = std::common_type_t<typename Integrals::value_type...>;
1585
return std::integral_constant<integral_type, (Integrals::value + ...)>{};
1586
}
1587
};
1588
1589
/*
1590
* Function object that takes a type, applies a projection on it, and returns the tuple size of the projected type (as an integral constant).
1591
* The projection is applied on the argument type, not the argument value/object.
1592
*/
1593
template<template<class...> class NestedProject>
1594
struct project_nested_tuple_size {
1595
template<class T>
1596
constexpr auto operator()(const T&) const {
1597
return typename std::tuple_size<NestedProject<T>>::type{};
1598
}
1599
};
1600
1601
template<template<class...> class NestedProject, class Tpl, class IdxSeq>
1602
using nested_tuple_size_for_t = decltype(recombine_tuple(plus_fold_integrals{},
1603
std::declval<Tpl>(),
1604
IdxSeq{},
1605
project_nested_tuple_size<NestedProject>{},
1606
std::integral_constant<size_t, 0u>{}));
1607
#endif
1608
1609
template<class R, class Tpl, size_t... Idx, class Projection = polyfill::identity>
1610
constexpr R create_from_tuple(Tpl&& tpl, std::index_sequence<Idx...>, Projection project = {}) {
1611
return R{polyfill::invoke(project, std::get<Idx>(std::forward<Tpl>(tpl)))...};
1612
}
1613
1614
/*
1615
* Like `std::make_from_tuple`, but using a projection on the tuple elements.
1616
*/
1617
template<class R, class Tpl, class Projection = polyfill::identity>
1618
constexpr R create_from_tuple(Tpl&& tpl, Projection project = {}) {
1619
return create_from_tuple<R>(
1620
std::forward<Tpl>(tpl),
1621
std::make_index_sequence<std::tuple_size<std::remove_reference_t<Tpl>>::value>{},
1622
std::forward<Projection>(project));
1623
}
1624
}
1625
}
1626
1627
// #include "tuple_helper/tuple_iteration.h"
1628
1629
#include <tuple> // std::get, std::tuple_element, std::tuple_size
1630
#include <type_traits> // std::index_sequence, std::make_index_sequence
1631
#include <utility> // std::forward, std::move
1632
1633
namespace sqlite_orm {
1634
namespace internal {
1635
#if defined(SQLITE_ORM_FOLD_EXPRESSIONS_SUPPORTED) && defined(SQLITE_ORM_IF_CONSTEXPR_SUPPORTED)
1636
template<bool reversed = false, class Tpl, size_t... Idx, class L>
1637
constexpr void iterate_tuple(Tpl& tpl, std::index_sequence<Idx...>, L&& lambda) {
1638
if constexpr (reversed) {
1639
// nifty fold expression trick: make use of guaranteed right-to-left evaluation order when folding over operator=
1640
int sink;
1641
// note: `(void)` cast silences warning 'expression result unused'
1642
(void)((lambda(std::get<Idx>(tpl)), sink) = ... = 0);
1643
} else {
1644
(lambda(std::get<Idx>(tpl)), ...);
1645
}
1646
}
1647
#else
1648
template<bool reversed = false, class Tpl, class L>
1649
void iterate_tuple(Tpl& /*tpl*/, std::index_sequence<>, L&& /*lambda*/) {}
1650
1651
template<bool reversed = false, class Tpl, size_t I, size_t... Idx, class L>
1652
void iterate_tuple(Tpl& tpl, std::index_sequence<I, Idx...>, L&& lambda) {
1653
if SQLITE_ORM_CONSTEXPR_IF (reversed) {
1654
iterate_tuple<reversed>(tpl, std::index_sequence<Idx...>{}, std::forward<L>(lambda));
1655
lambda(std::get<I>(tpl));
1656
} else {
1657
lambda(std::get<I>(tpl));
1658
iterate_tuple<reversed>(tpl, std::index_sequence<Idx...>{}, std::forward<L>(lambda));
1659
}
1660
}
1661
#endif
1662
template<bool reversed = false, class Tpl, class L>
1663
constexpr void iterate_tuple(Tpl&& tpl, L&& lambda) {
1664
iterate_tuple<reversed>(tpl,
1665
std::make_index_sequence<std::tuple_size<std::remove_reference_t<Tpl>>::value>{},
1666
std::forward<L>(lambda));
1667
}
1668
1669
#ifdef SQLITE_ORM_FOLD_EXPRESSIONS_SUPPORTED
1670
template<class Tpl, size_t... Idx, class L>
1671
void iterate_tuple(std::index_sequence<Idx...>, L&& lambda) {
1672
(lambda((std::tuple_element_t<Idx, Tpl>*)nullptr), ...);
1673
}
1674
#else
1675
template<class Tpl, size_t... Idx, class L>
1676
void iterate_tuple(std::index_sequence<Idx...>, L&& lambda) {
1677
using Sink = int[sizeof...(Idx)];
1678
(void)Sink{(lambda((std::tuple_element_t<Idx, Tpl>*)nullptr), 0)...};
1679
}
1680
#endif
1681
template<class Tpl, class L>
1682
void iterate_tuple(L&& lambda) {
1683
iterate_tuple<Tpl>(std::make_index_sequence<std::tuple_size<Tpl>::value>{}, std::forward<L>(lambda));
1684
}
1685
1686
template<template<class...> class Base, class L>
1687
struct lambda_as_template_base : L {
1688
#ifndef SQLITE_ORM_AGGREGATE_BASES_SUPPORTED
1689
lambda_as_template_base(L&& lambda) : L{std::move(lambda)} {}
1690
#endif
1691
template<class... T>
1692
decltype(auto) operator()(const Base<T...>& object) {
1693
return L::operator()(object);
1694
}
1695
};
1696
1697
/*
1698
* This method wraps the specified callable in another function object,
1699
* which in turn implicitly casts its single argument to the specified template base class,
1700
* then passes the converted argument to the lambda.
1701
*
1702
* Note: This method is useful for reducing combinatorial instantiation of template lambdas,
1703
* as long as this library supports compilers that do not implement
1704
* explicit template parameters in generic lambdas [SQLITE_ORM_EXPLICIT_GENERIC_LAMBDA_SUPPORTED].
1705
* Unfortunately it doesn't work with user-defined conversion operators in order to extract
1706
* parts of a class. In other words, the destination type must be a direct template base class.
1707
*/
1708
template<template<class...> class Base, class L>
1709
lambda_as_template_base<Base, L> call_as_template_base(L lambda) {
1710
return {std::move(lambda)};
1711
}
1712
}
1713
}
1714
1715
// #include "type_traits.h"
1716
1717
#include <type_traits> // std::enable_if, std::is_same, std::is_empty, std::is_aggregate
1718
#if __cpp_lib_unwrap_ref >= 201811L
1719
#include <utility> // std::reference_wrapper
1720
#else
1721
#include <functional> // std::reference_wrapper
1722
#endif
1723
1724
// #include "functional/cxx_core_features.h"
1725
1726
// #include "functional/cxx_type_traits_polyfill.h"
1727
1728
namespace sqlite_orm {
1729
// C++ generic traits used throughout the library
1730
namespace internal {
1731
template<class T, class... Types>
1732
using is_any_of = polyfill::disjunction<std::is_same<T, Types>...>;
1733
1734
template<class T>
1735
struct value_unref_type : polyfill::remove_cvref<T> {};
1736
1737
template<class T>
1738
struct value_unref_type<std::reference_wrapper<T>> : std::remove_const<T> {};
1739
1740
template<class T>
1741
using value_unref_type_t = typename value_unref_type<T>::type;
1742
1743
template<class T>
1744
using is_eval_order_garanteed =
1745
#if __cpp_lib_is_aggregate >= 201703L
1746
std::is_aggregate<T>;
1747
#else
1748
std::is_pod<T>;
1749
#endif
1750
1751
// enable_if for types
1752
template<template<typename...> class Op, class... Args>
1753
using match_if = std::enable_if_t<Op<Args...>::value>;
1754
1755
// enable_if for types
1756
template<template<typename...> class Op, class... Args>
1757
using match_if_not = std::enable_if_t<polyfill::negation<Op<Args...>>::value>;
1758
1759
// enable_if for types
1760
template<class T, template<typename...> class Primary>
1761
using match_specialization_of = std::enable_if_t<polyfill::is_specialization_of<T, Primary>::value>;
1762
1763
// enable_if for functions
1764
template<template<typename...> class Op, class... Args>
1765
using satisfies = std::enable_if_t<Op<Args...>::value, bool>;
1766
1767
// enable_if for functions
1768
template<template<typename...> class Op, class... Args>
1769
using satisfies_not = std::enable_if_t<polyfill::negation<Op<Args...>>::value, bool>;
1770
1771
// enable_if for functions
1772
template<class T, template<typename...> class Primary>
1773
using satisfies_is_specialization_of =
1774
std::enable_if_t<polyfill::is_specialization_of<T, Primary>::value, bool>;
1775
}
1776
1777
// type name template aliases for syntactic sugar
1778
namespace internal {
1779
template<typename T>
1780
using type_t = typename T::type;
1781
1782
#ifdef SQLITE_ORM_WITH_CPP20_ALIASES
1783
template<auto a>
1784
using auto_type_t = typename decltype(a)::type;
1785
#endif
1786
1787
template<typename T>
1788
using value_type_t = typename T::value_type;
1789
1790
template<typename T>
1791
using field_type_t = typename T::field_type;
1792
1793
template<typename T>
1794
using constraints_type_t = typename T::constraints_type;
1795
1796
template<typename T>
1797
using columns_tuple_t = typename T::columns_tuple;
1798
1799
template<typename T>
1800
using object_type_t = typename T::object_type;
1801
1802
template<typename T>
1803
using elements_type_t = typename T::elements_type;
1804
1805
template<typename T>
1806
using table_type_t = typename T::table_type;
1807
1808
template<typename T>
1809
using target_type_t = typename T::target_type;
1810
1811
template<typename T>
1812
using left_type_t = typename T::left_type;
1813
1814
template<typename T>
1815
using right_type_t = typename T::right_type;
1816
1817
template<typename T>
1818
using on_type_t = typename T::on_type;
1819
1820
template<typename T>
1821
using expression_type_t = typename T::expression_type;
1822
1823
template<class As>
1824
using alias_type_t = typename As::alias_type;
1825
1826
#ifdef SQLITE_ORM_WITH_CPP20_ALIASES
1827
template<class T>
1828
using udf_type_t = typename T::udf_type;
1829
1830
template<auto a>
1831
using auto_udf_type_t = typename decltype(a)::udf_type;
1832
#endif
1833
1834
#if (SQLITE_VERSION_NUMBER >= 3008003) && defined(SQLITE_ORM_WITH_CTE)
1835
template<typename T>
1836
using cte_moniker_type_t = typename T::cte_moniker_type;
1837
1838
template<typename T>
1839
using cte_mapper_type_t = typename T::cte_mapper_type;
1840
1841
// T::alias_type or nonesuch
1842
template<class T>
1843
using alias_holder_type_or_none = polyfill::detected<type_t, T>;
1844
1845
template<class T>
1846
using alias_holder_type_or_none_t = typename alias_holder_type_or_none<T>::type;
1847
#endif
1848
1849
#ifdef SQLITE_ORM_CPP20_CONCEPTS_SUPPORTED
1850
template<typename T>
1851
concept stateless = std::is_empty_v<T>;
1852
#endif
1853
}
1854
1855
#ifdef SQLITE_ORM_CPP20_CONCEPTS_SUPPORTED
1856
template<class T>
1857
concept orm_names_type = requires { typename T::type; };
1858
#endif
1859
}
1860
1861
// #include "alias.h"
1862
1863
#include <type_traits> // std::enable_if, std::is_same
1864
#include <utility> // std::make_index_sequence, std::move
1865
#include <string> // std::string
1866
#include <sstream> // std::stringstream
1867
#if (SQLITE_VERSION_NUMBER >= 3008003) && defined(SQLITE_ORM_WITH_CTE)
1868
#include <array>
1869
#endif
1870
1871
// #include "functional/cxx_type_traits_polyfill.h"
1872
1873
// #include "functional/mpl/conditional.h"
1874
1875
// #include "functional/cstring_literal.h"
1876
1877
#ifdef SQLITE_ORM_WITH_CPP20_ALIASES
1878
#include <utility> // std::index_sequence
1879
#include <algorithm> // std::copy_n
1880
#endif
1881
1882
#ifdef SQLITE_ORM_WITH_CPP20_ALIASES
1883
namespace sqlite_orm::internal {
1884
/*
1885
* Wraps a C string of fixed size.
1886
* Its main purpose is to enable the user-defined string literal operator template.
1887
*/
1888
template<size_t N>
1889
struct cstring_literal {
1890
static constexpr size_t size() {
1891
return N - 1;
1892
}
1893
1894
constexpr cstring_literal(const char (&cstr)[N]) {
1895
std::copy_n(cstr, N, this->cstr);
1896
}
1897
1898
char cstr[N];
1899
};
1900
1901
template<template<char...> class Template, cstring_literal literal, size_t... Idx>
1902
consteval auto explode_into(std::index_sequence<Idx...>) {
1903
return Template<literal.cstr[Idx]...>{};
1904
}
1905
}
1906
#endif
1907
1908
// #include "type_traits.h"
1909
1910
// #include "alias_traits.h"
1911
1912
#include <type_traits> // std::is_base_of, std::is_same
1913
#ifdef SQLITE_ORM_WITH_CPP20_ALIASES
1914
#include <concepts>
1915
#endif
1916
1917
// #include "functional/cxx_type_traits_polyfill.h"
1918
1919
// #include "type_traits.h"
1920
1921
// #include "table_reference.h"
1922
1923
#include <type_traits> // std::remove_const, std::type_identity
1924
1925
// #include "functional/cxx_type_traits_polyfill.h"
1926
1927
namespace sqlite_orm {
1928
namespace internal {
1929
/*
1930
* Identity wrapper around a mapped object, facilitating uniform column pointer expressions.
1931
*/
1932
template<class O>
1933
struct table_reference : polyfill::type_identity<O> {};
1934
1935
template<class RecordSet>
1936
struct decay_table_ref : std::remove_const<RecordSet> {};
1937
template<class O>
1938
struct decay_table_ref<table_reference<O>> : polyfill::type_identity<O> {};
1939
template<class O>
1940
struct decay_table_ref<const table_reference<O>> : polyfill::type_identity<O> {};
1941
1942
template<class RecordSet>
1943
using decay_table_ref_t = typename decay_table_ref<RecordSet>::type;
1944
#ifdef SQLITE_ORM_WITH_CPP20_ALIASES
1945
template<auto recordset>
1946
using auto_decay_table_ref_t = typename decay_table_ref<decltype(recordset)>::type;
1947
#endif
1948
1949
template<class R>
1950
SQLITE_ORM_INLINE_VAR constexpr bool is_table_reference_v =
1951
polyfill::is_specialization_of_v<std::remove_const_t<R>, table_reference>;
1952
1953
template<class R>
1954
struct is_table_reference : polyfill::bool_constant<is_table_reference_v<R>> {};
1955
}
1956
1957
#ifdef SQLITE_ORM_CPP20_CONCEPTS_SUPPORTED
1958
/** @short Specifies that a type is a reference of a concrete table, especially of a derived class.
1959
*
1960
* A concrete table reference has the following traits:
1961
* - specialization of `table_reference`, whose `type` typename references a mapped object.
1962
*/
1963
template<class R>
1964
concept orm_table_reference = polyfill::is_specialization_of_v<std::remove_const_t<R>, internal::table_reference>;
1965
#endif
1966
}
1967
1968
namespace sqlite_orm {
1969
1970
/** @short Base class for a custom table alias, column alias or expression alias.
1971
*/
1972
struct alias_tag {};
1973
1974
namespace internal {
1975
1976
template<class A>
1977
SQLITE_ORM_INLINE_VAR constexpr bool is_alias_v = std::is_base_of<alias_tag, A>::value;
1978
1979
template<class A>
1980
struct is_alias : polyfill::bool_constant<is_alias_v<A>> {};
1981
1982
/** @short Alias of a column in a record set, see `orm_column_alias`.
1983
*/
1984
template<class A>
1985
SQLITE_ORM_INLINE_VAR constexpr bool is_column_alias_v =
1986
polyfill::conjunction<is_alias<A>, polyfill::negation<polyfill::is_detected<type_t, A>>>::value;
1987
1988
template<class A>
1989
struct is_column_alias : is_alias<A> {};
1990
1991
/** @short Alias of any type of record set, see `orm_recordset_alias`.
1992
*/
1993
template<class A>
1994
SQLITE_ORM_INLINE_VAR constexpr bool is_recordset_alias_v =
1995
polyfill::conjunction<is_alias<A>, polyfill::is_detected<type_t, A>>::value;
1996
1997
template<class A>
1998
struct is_recordset_alias : polyfill::bool_constant<is_recordset_alias_v<A>> {};
1999
2000
/** @short Alias of a concrete table, see `orm_table_alias`.
2001
*/
2002
template<class A>
2003
SQLITE_ORM_INLINE_VAR constexpr bool is_table_alias_v = polyfill::conjunction<
2004
is_recordset_alias<A>,
2005
polyfill::negation<std::is_same<polyfill::detected_t<type_t, A>, std::remove_const_t<A>>>>::value;
2006
2007
template<class A>
2008
struct is_table_alias : polyfill::bool_constant<is_table_alias_v<A>> {};
2009
2010
/** @short Moniker of a CTE, see `orm_cte_moniker`.
2011
*/
2012
template<class A>
2013
SQLITE_ORM_INLINE_VAR constexpr bool is_cte_moniker_v =
2014
#if (SQLITE_VERSION_NUMBER >= 3008003) && defined(SQLITE_ORM_WITH_CTE)
2015
polyfill::conjunction_v<is_recordset_alias<A>,
2016
std::is_same<polyfill::detected_t<type_t, A>, std::remove_const_t<A>>>;
2017
#else
2018
false;
2019
#endif
2020
2021
template<class A>
2022
using is_cte_moniker = polyfill::bool_constant<is_cte_moniker_v<A>>;
2023
}
2024
2025
#ifdef SQLITE_ORM_WITH_CPP20_ALIASES
2026
template<class A>
2027
concept orm_alias = std::derived_from<A, alias_tag>;
2028
2029
/** @short Specifies that a type is an alias of a column in a record set.
2030
*
2031
* A column alias has the following traits:
2032
* - is derived from `alias_tag`
2033
* - must not have a nested `type` typename
2034
*/
2035
template<class A>
2036
concept orm_column_alias = (orm_alias<A> && !orm_names_type<A>);
2037
2038
/** @short Specifies that a type is an alias of any type of record set.
2039
*
2040
* A record set alias has the following traits:
2041
* - is derived from `alias_tag`.
2042
* - has a nested `type` typename, which refers to a mapped object.
2043
*/
2044
template<class A>
2045
concept orm_recordset_alias = (orm_alias<A> && orm_names_type<A>);
2046
2047
/** @short Specifies that a type is an alias of a concrete table.
2048
*
2049
* A concrete table alias has the following traits:
2050
* - is derived from `alias_tag`.
2051
* - has a `type` typename, which refers to another mapped object (i.e. doesn't refer to itself).
2052
*/
2053
template<class A>
2054
concept orm_table_alias = (orm_recordset_alias<A> && !std::same_as<typename A::type, std::remove_const_t<A>>);
2055
2056
/** @short Moniker of a CTE.
2057
*
2058
* A CTE moniker has the following traits:
2059
* - is derived from `alias_tag`.
2060
* - has a `type` typename, which refers to itself.
2061
*/
2062
template<class A>
2063
concept orm_cte_moniker = (orm_recordset_alias<A> && std::same_as<typename A::type, std::remove_const_t<A>>);
2064
2065
/** @short Specifies that a type refers to a mapped table (possibly aliased).
2066
*/
2067
template<class T>
2068
concept orm_refers_to_table = (orm_table_reference<T> || orm_table_alias<T>);
2069
2070
/** @short Specifies that a type refers to a recordset.
2071
*/
2072
template<class T>
2073
concept orm_refers_to_recordset = (orm_table_reference<T> || orm_recordset_alias<T>);
2074
2075
/** @short Specifies that a type is a mapped recordset (table reference).
2076
*/
2077
template<class T>
2078
concept orm_mapped_recordset = (orm_table_reference<T> || orm_cte_moniker<T>);
2079
#endif
2080
}
2081
2082
// #include "table_type_of.h"
2083
2084
#include <type_traits> // std::enable_if, std::is_convertible
2085
2086
namespace sqlite_orm {
2087
2088
namespace internal {
2089
2090
template<class T, class F>
2091
struct column_pointer;
2092
2093
template<class C>
2094
struct indexed_column_t;
2095
2096
/**
2097
* Trait class used to define table mapped type by setter/getter/member
2098
* T - member pointer
2099
* `type` is a type which is mapped.
2100
* E.g.
2101
* - `table_type_of<decltype(&User::id)>::type` is `User`
2102
* - `table_type_of<decltype(&User::getName)>::type` is `User`
2103
* - `table_type_of<decltype(&User::setName)>::type` is `User`
2104
* - `table_type_of<decltype(column<User>(&User::id))>::type` is `User`
2105
* - `table_type_of<decltype(derived->*&User::id)>::type` is `User`
2106
*/
2107
template<class T>
2108
struct table_type_of;
2109
2110
template<class O, class F>
2111
struct table_type_of<F O::*> {
2112
using type = O;
2113
};
2114
2115
template<class T, class F>
2116
struct table_type_of<column_pointer<T, F>> {
2117
using type = T;
2118
};
2119
2120
template<class C>
2121
struct table_type_of<indexed_column_t<C>> : table_type_of<C> {};
2122
2123
template<class T>
2124
using table_type_of_t = typename table_type_of<T>::type;
2125
2126
/*
2127
* This trait can be used to check whether the object type of a member pointer or column pointer matches the target type.
2128
*
2129
* One use case is the ability to create column reference to an aliased table column of a derived object field without explicitly using a column pointer.
2130
* E.g.
2131
* regular: `alias_column<alias_d<Derived>>(column<Derived>(&Base::field))`
2132
* short: `alias_column<alias_d<Derived>>(&Base::field)`
2133
*/
2134
template<class F, class T, class SFINAE = void>
2135
SQLITE_ORM_INLINE_VAR constexpr bool is_field_of_v = false;
2136
2137
/*
2138
* `true` if a pointer-to-member of Base is convertible to a pointer-to-member of Derived.
2139
*/
2140
template<class O, class Base, class F>
2141
SQLITE_ORM_INLINE_VAR constexpr bool
2142
is_field_of_v<F Base::*, O, std::enable_if_t<std::is_convertible<F Base::*, F O::*>::value>> = true;
2143
2144
template<class F, class T>
2145
SQLITE_ORM_INLINE_VAR constexpr bool is_field_of_v<column_pointer<T, F>, T, void> = true;
2146
}
2147
}
2148
2149
// #include "tags.h"
2150
2151
// #include "functional/cxx_functional_polyfill.h"
2152
2153
namespace sqlite_orm {
2154
namespace internal {
2155
struct negatable_t {};
2156
2157
/**
2158
* Inherit from this class to support arithmetic types overloading
2159
*/
2160
struct arithmetic_t {};
2161
2162
/**
2163
* Inherit from this class if target class can be chained with other conditions with '&&' and '||' operators
2164
*/
2165
struct condition_t {};
2166
2167
/**
2168
* Specialize if a type participates as an argument to overloaded operators (arithmetic, conditional, negation, chaining)
2169
*/
2170
template<class T, class SFINAE = void>
2171
SQLITE_ORM_INLINE_VAR constexpr bool is_operator_argument_v = false;
2172
2173
template<class T>
2174
using is_operator_argument = polyfill::bool_constant<is_operator_argument_v<T>>;
2175
}
2176
}
2177
2178
// #include "column_pointer.h"
2179
2180
#include <type_traits> // std::enable_if, std::is_convertible
2181
#include <utility> // std::move
2182
2183
// #include "functional/cxx_core_features.h"
2184
2185
// #include "functional/cxx_type_traits_polyfill.h"
2186
2187
// #include "type_traits.h"
2188
2189
// #include "table_reference.h"
2190
2191
// #include "alias_traits.h"
2192
2193
// #include "tags.h"
2194
2195
namespace sqlite_orm {
2196
namespace internal {
2197
/**
2198
* This class is used to store explicit mapped type T and its column descriptor (member pointer/getter/setter).
2199
* Is useful when mapped type is derived from other type and base class has members mapped to a storage.
2200
*/
2201
template<class T, class F>
2202
struct column_pointer {
2203
using type = T;
2204
using field_type = F;
2205
2206
field_type field;
2207
};
2208
2209
template<class T>
2210
SQLITE_ORM_INLINE_VAR constexpr bool is_column_pointer_v =
2211
polyfill::is_specialization_of<T, column_pointer>::value;
2212
2213
template<class T>
2214
struct is_column_pointer : polyfill::bool_constant<is_column_pointer_v<T>> {};
2215
2216
template<class T>
2217
SQLITE_ORM_INLINE_VAR constexpr bool is_operator_argument_v<T, std::enable_if_t<is_column_pointer<T>::value>> =
2218
true;
2219
2220
#if (SQLITE_VERSION_NUMBER >= 3008003) && defined(SQLITE_ORM_WITH_CTE)
2221
template<class A>
2222
struct alias_holder;
2223
#endif
2224
}
2225
2226
/**
2227
* Explicitly refer to a column, used in contexts
2228
* where the automatic object mapping deduction needs to be overridden.
2229
*
2230
* Example:
2231
* struct BaseType : { int64 id; };
2232
* struct MyType : BaseType { ... };
2233
* storage.select(column<MyType>(&BaseType::id));
2234
*/
2235
template<class O, class Base, class F, internal::satisfies_not<internal::is_recordset_alias, O> = true>
2236
constexpr internal::column_pointer<O, F Base::*> column(F Base::* field) {
2237
static_assert(std::is_convertible<F Base::*, F O::*>::value, "Field must be from derived class");
2238
return {field};
2239
}
2240
2241
#ifdef SQLITE_ORM_WITH_CPP20_ALIASES
2242
/**
2243
* Explicitly refer to a column.
2244
*/
2245
template<orm_table_reference auto table, class O, class F>
2246
constexpr auto column(F O::* field) {
2247
return column<internal::auto_type_t<table>>(field);
2248
}
2249
2250
// Intentionally place pointer-to-member operator for table references in the internal namespace
2251
// to facilitate ADL (Argument Dependent Lookup)
2252
namespace internal {
2253
/**
2254
* Explicitly refer to a column.
2255
*/
2256
template<orm_table_reference R, class O, class F>
2257
constexpr auto operator->*(const R& /*table*/, F O::* field) {
2258
return column<typename R::type>(field);
2259
}
2260
}
2261
2262
/**
2263
* Make a table reference.
2264
*/
2265
template<class O>
2266
requires (!orm_recordset_alias<O>)
2267
consteval internal::table_reference<O> column() {
2268
return {};
2269
}
2270
2271
/**
2272
* Make a table reference.
2273
*/
2274
template<class O>
2275
requires (!orm_recordset_alias<O>)
2276
consteval internal::table_reference<O> c() {
2277
return {};
2278
}
2279
#endif
2280
2281
#if (SQLITE_VERSION_NUMBER >= 3008003) && defined(SQLITE_ORM_WITH_CTE)
2282
/**
2283
* Explicitly refer to a column alias mapped into a CTE or subquery.
2284
*
2285
* Example:
2286
* struct Object { ... };
2287
* using cte_1 = decltype(1_ctealias);
2288
* storage.with(cte<cte_1>()(select(&Object::id)), select(column<cte_1>(&Object::id)));
2289
* storage.with(cte<cte_1>()(select(&Object::id)), select(column<cte_1>(1_colalias)));
2290
* storage.with(cte<cte_1>()(select(as<colalias_a>(&Object::id))), select(column<cte_1>(colalias_a{})));
2291
* storage.with(cte<cte_1>(colalias_a{})(select(&Object::id)), select(column<cte_1>(colalias_a{})));
2292
* storage.with(cte<cte_1>()(select(as<colalias_a>(&Object::id))), select(column<cte_1>(get<colalias_a>())));
2293
*/
2294
template<class Moniker, class F, internal::satisfies<internal::is_recordset_alias, Moniker> = true>
2295
constexpr auto column(F field) {
2296
using namespace ::sqlite_orm::internal;
2297
2298
static_assert(is_cte_moniker_v<Moniker>, "`Moniker' must be a CTE moniker");
2299
2300
if constexpr (polyfill::is_specialization_of_v<F, alias_holder>) {
2301
static_assert(is_column_alias_v<type_t<F>>);
2302
return column_pointer<Moniker, F>{{}};
2303
} else if constexpr (is_column_alias_v<F>) {
2304
return column_pointer<Moniker, alias_holder<F>>{{}};
2305
} else {
2306
return column_pointer<Moniker, F>{std::move(field)};
2307
}
2308
(void)field;
2309
}
2310
2311
#ifdef SQLITE_ORM_WITH_CPP20_ALIASES
2312
/**
2313
* Explicitly refer to a column mapped into a CTE or subquery.
2314
*
2315
* Example:
2316
* struct Object { ... };
2317
* storage.with(cte<"z"_cte>()(select(&Object::id)), select(column<"z"_cte>(&Object::id)));
2318
* storage.with(cte<"z"_cte>()(select(&Object::id)), select(column<"z"_cte>(1_colalias)));
2319
*/
2320
template<orm_cte_moniker auto moniker, class F>
2321
constexpr auto column(F field) {
2322
using Moniker = std::remove_const_t<decltype(moniker)>;
2323
return column<Moniker>(std::forward<F>(field));
2324
}
2325
2326
/**
2327
* Explicitly refer to a column mapped into a CTE or subquery.
2328
*
2329
* @note (internal) Intentionally place in the sqlite_orm namespace for ADL (Argument Dependent Lookup)
2330
* because recordset aliases are derived from `sqlite_orm::alias_tag`
2331
*
2332
* Example:
2333
* struct Object { ... };
2334
* using cte_1 = decltype(1_ctealias);
2335
* storage.with(cte<cte_1>()(select(&Object::id)), select(1_ctealias->*&Object::id));
2336
* storage.with(cte<cte_1>()(select(&Object::id)), select(1_ctealias->*1_colalias));
2337
*/
2338
template<orm_cte_moniker Moniker, class F>
2339
constexpr auto operator->*(const Moniker& /*moniker*/, F field) {
2340
return column<Moniker>(std::forward<F>(field));
2341
}
2342
#endif
2343
#endif
2344
}
2345
2346
namespace sqlite_orm {
2347
2348
namespace internal {
2349
#ifdef SQLITE_ORM_WITH_CPP20_ALIASES
2350
template<class T>
2351
inline constexpr bool is_operator_argument_v<T, std::enable_if_t<orm_column_alias<T>>> = true;
2352
#endif
2353
2354
/**
2355
* This is a common built-in class used for character based table aliases.
2356
* For convenience there exist public type aliases `alias_a`, `alias_b`, ...
2357
* The easiest way to create a table alias is using `"z"_alias.for_<Object>()`.
2358
*/
2359
template<class T, char A, char... X>
2360
struct recordset_alias : alias_tag {
2361
using type = T;
2362
2363
static std::string get() {
2364
return {A, X...};
2365
}
2366
};
2367
2368
/**
2369
* Column expression with table alias attached like 'C.ID'. This is not a column alias
2370
*/
2371
template<class T, class C>
2372
struct alias_column_t {
2373
using alias_type = T;
2374
using column_type = C;
2375
2376
column_type column;
2377
};
2378
2379
template<class T>
2380
SQLITE_ORM_INLINE_VAR constexpr bool
2381
is_operator_argument_v<T, std::enable_if_t<polyfill::is_specialization_of<T, alias_column_t>::value>> =
2382
true;
2383
2384
struct basic_table;
2385
2386
/*
2387
* Encapsulates extracting the alias identifier of a non-alias.
2388
*
2389
* `extract()` always returns the empty string.
2390
* `as_alias()` is used in contexts where a table might be aliased, and the empty string is returned.
2391
* `as_qualifier()` is used in contexts where a table might be aliased, and the given table's name is returned.
2392
*/
2393
template<class T, class SFINAE = void>
2394
struct alias_extractor {
2395
static std::string extract() {
2396
return {};
2397
}
2398
2399
static std::string as_alias() {
2400
return {};
2401
}
2402
2403
template<class X = basic_table>
2404
static const std::string& as_qualifier(const X& table) {
2405
return table.name;
2406
}
2407
};
2408
2409
/*
2410
* Encapsulates extracting the alias identifier of an alias.
2411
*
2412
* `extract()` always returns the alias identifier or CTE moniker.
2413
* `as_alias()` is used in contexts where a recordset is aliased, and the alias identifier is returned.
2414
* `as_qualifier()` is used in contexts where a table is aliased, and the alias identifier is returned.
2415
*/
2416
template<class A>
2417
struct alias_extractor<A, match_if<is_alias, A>> {
2418
static std::string extract() {
2419
std::stringstream ss;
2420
ss << A::get();
2421
return ss.str();
2422
}
2423
2424
// for column and regular table aliases -> alias identifier
2425
template<class T = A, satisfies_not<std::is_same, polyfill::detected_t<type_t, T>, A> = true>
2426
static std::string as_alias() {
2427
return alias_extractor::extract();
2428
}
2429
2430
#if (SQLITE_VERSION_NUMBER >= 3008003) && defined(SQLITE_ORM_WITH_CTE)
2431
// for CTE monikers -> empty
2432
template<class T = A, satisfies<std::is_same, polyfill::detected_t<type_t, T>, A> = true>
2433
static std::string as_alias() {
2434
return {};
2435
}
2436
#endif
2437
2438
// for regular table aliases -> alias identifier
2439
template<class T = A, satisfies<is_table_alias, T> = true>
2440
static std::string as_qualifier(const basic_table&) {
2441
return alias_extractor::extract();
2442
}
2443
};
2444
2445
/**
2446
* Used to store alias for expression
2447
*/
2448
template<class T, class E>
2449
struct as_t {
2450
using alias_type = T;
2451
using expression_type = E;
2452
2453
expression_type expression;
2454
};
2455
2456
/**
2457
* Built-in column alias.
2458
* For convenience there exist type aliases `colalias_a`, `colalias_b`, ...
2459
* The easiest way to create a column alias is using `"xyz"_col`.
2460
*/
2461
template<char A, char... X>
2462
struct column_alias : alias_tag {
2463
static std::string get() {
2464
return {A, X...};
2465
}
2466
};
2467
2468
template<class T>
2469
struct alias_holder {
2470
using type = T;
2471
2472
alias_holder() = default;
2473
// CTE feature needs it to implicitly convert a column alias to an alias_holder; see `cte()` factory function
2474
alias_holder(const T&) noexcept {}
2475
};
2476
2477
template<class T>
2478
SQLITE_ORM_INLINE_VAR constexpr bool
2479
is_operator_argument_v<T, std::enable_if_t<polyfill::is_specialization_of<T, alias_holder>::value>> = true;
2480
2481
#ifdef SQLITE_ORM_WITH_CPP20_ALIASES
2482
template<char A, char... X>
2483
struct recordset_alias_builder {
2484
template<class T>
2485
[[nodiscard]] consteval recordset_alias<T, A, X...> for_() const {
2486
return {};
2487
}
2488
2489
template<auto t>
2490
[[nodiscard]] consteval auto for_() const {
2491
using T = std::remove_const_t<decltype(t)>;
2492
return recordset_alias<T, A, X...>{};
2493
}
2494
};
2495
#endif
2496
2497
#if (SQLITE_VERSION_NUMBER >= 3008003) && defined(SQLITE_ORM_WITH_CTE)
2498
template<size_t n, char... C>
2499
SQLITE_ORM_CONSTEVAL auto n_to_colalias() {
2500
constexpr column_alias<'1' + n % 10, C...> colalias{};
2501
if constexpr (n > 10) {
2502
return n_to_colalias<n / 10, '1' + n % 10, C...>();
2503
} else {
2504
return colalias;
2505
}
2506
}
2507
2508
template<class T>
2509
inline constexpr bool is_builtin_numeric_column_alias_v = false;
2510
template<char... C>
2511
inline constexpr bool is_builtin_numeric_column_alias_v<column_alias<C...>> = ((C >= '0' && C <= '9') && ...);
2512
#endif
2513
}
2514
2515
/**
2516
* Using a column pointer, create a column reference to an aliased table column.
2517
*
2518
* Example:
2519
* using als = alias_u<User>;
2520
* select(alias_column<als>(column<User>(&User::id)))
2521
*/
2522
template<class A,
2523
class C,
2524
std::enable_if_t<
2525
polyfill::conjunction<internal::is_table_alias<A>,
2526
polyfill::negation<internal::is_cte_moniker<internal::type_t<A>>>>::value,
2527
bool> = true>
2528
constexpr auto alias_column(C field) {
2529
using namespace ::sqlite_orm::internal;
2530
using aliased_type = type_t<A>;
2531
static_assert(is_field_of_v<C, aliased_type>, "Column must be from aliased table");
2532
2533
return alias_column_t<A, C>{std::move(field)};
2534
}
2535
2536
/**
2537
* Using an object member field, create a column reference to an aliased table column.
2538
*
2539
* @note The object member pointer can be from a derived class without explicitly forming a column pointer.
2540
*
2541
* Example:
2542
* using als = alias_u<User>;
2543
* select(alias_column<als>(&User::id))
2544
*/
2545
template<class A,
2546
class F,
2547
class O,
2548
std::enable_if_t<
2549
polyfill::conjunction<internal::is_table_alias<A>,
2550
polyfill::negation<internal::is_cte_moniker<internal::type_t<A>>>>::value,
2551
bool> = true>
2552
constexpr auto alias_column(F O::* field) {
2553
using namespace ::sqlite_orm::internal;
2554
using aliased_type = type_t<A>;
2555
static_assert(is_field_of_v<F O::*, aliased_type>, "Column must be from aliased table");
2556
2557
using C1 =
2558
mpl::conditional_t<std::is_same<O, aliased_type>::value, F O::*, column_pointer<aliased_type, F O::*>>;
2559
return alias_column_t<A, C1>{C1{field}};
2560
}
2561
2562
#ifdef SQLITE_ORM_WITH_CPP20_ALIASES
2563
/**
2564
* Create a column reference to an aliased table column.
2565
*
2566
* @note An object member pointer can be from a derived class without explicitly forming a column pointer.
2567
*
2568
* Example:
2569
* constexpr orm_table_alias auto als = "u"_alias.for_<User>();
2570
* select(alias_column<als>(&User::id))
2571
*/
2572
template<orm_table_alias auto als, class C>
2573
requires (!orm_cte_moniker<internal::auto_type_t<als>>)
2574
constexpr auto alias_column(C field) {
2575
using namespace ::sqlite_orm::internal;
2576
using A = decltype(als);
2577
using aliased_type = type_t<A>;
2578
static_assert(is_field_of_v<C, aliased_type>, "Column must be from aliased table");
2579
2580
if constexpr (is_column_pointer_v<C>) {
2581
return alias_column_t<A, C>{std::move(field)};
2582
} else if constexpr (std::is_same_v<member_object_type_t<C>, aliased_type>) {
2583
return alias_column_t<A, C>{field};
2584
} else {
2585
// wrap in column_pointer
2586
using C1 = column_pointer<aliased_type, C>;
2587
return alias_column_t<A, C1>{{field}};
2588
}
2589
}
2590
2591
/**
2592
* Create a column reference to an aliased table column.
2593
*
2594
* @note An object member pointer can be from a derived class without explicitly forming a column pointer.
2595
*
2596
* @note (internal) Intentionally place in the sqlite_orm namespace for ADL (Argument Dependent Lookup)
2597
* because recordset aliases are derived from `sqlite_orm::alias_tag`
2598
*
2599
* Example:
2600
* constexpr auto als = "u"_alias.for_<User>();
2601
* select(als->*&User::id)
2602
*/
2603
template<orm_table_alias A, class F>
2604
requires (!orm_cte_moniker<internal::type_t<A>>)
2605
constexpr auto operator->*(const A& /*tableAlias*/, F field) {
2606
return alias_column<A>(std::move(field));
2607
}
2608
#endif
2609
2610
#if (SQLITE_VERSION_NUMBER >= 3008003) && defined(SQLITE_ORM_WITH_CTE)
2611
/**
2612
* Create a column reference to an aliased CTE column.
2613
*/
2614
template<class A,
2615
class C,
2616
std::enable_if_t<
2617
polyfill::conjunction_v<internal::is_table_alias<A>, internal::is_cte_moniker<internal::type_t<A>>>,
2618
bool> = true>
2619
constexpr auto alias_column(C c) {
2620
using namespace ::sqlite_orm::internal;
2621
using cte_moniker_t = type_t<A>;
2622
2623
if constexpr (is_column_pointer_v<C>) {
2624
static_assert(std::is_same<table_type_of_t<C>, cte_moniker_t>::value,
2625
"Column pointer must match aliased CTE");
2626
return alias_column_t<A, C>{c};
2627
} else {
2628
auto cp = column<cte_moniker_t>(c);
2629
return alias_column_t<A, decltype(cp)>{std::move(cp)};
2630
}
2631
}
2632
2633
#ifdef SQLITE_ORM_WITH_CPP20_ALIASES
2634
/**
2635
* Create a column reference to an aliased CTE column.
2636
*
2637
* @note (internal) Intentionally place in the sqlite_orm namespace for ADL (Argument Dependent Lookup)
2638
* because recordset aliases are derived from `sqlite_orm::alias_tag`
2639
*/
2640
template<orm_table_alias A, class C>
2641
requires (orm_cte_moniker<internal::type_t<A>>)
2642
constexpr auto operator->*(const A& /*tableAlias*/, C c) {
2643
return alias_column<A>(std::move(c));
2644
}
2645
2646
/**
2647
* Create a column reference to an aliased CTE column.
2648
*/
2649
template<orm_table_alias auto als, class C>
2650
requires (orm_cte_moniker<internal::auto_type_t<als>>)
2651
constexpr auto alias_column(C c) {
2652
using A = std::remove_const_t<decltype(als)>;
2653
return alias_column<A>(std::move(c));
2654
}
2655
#endif
2656
#endif
2657
2658
/**
2659
* Alias a column expression.
2660
*/
2661
template<class A, class E, internal::satisfies<internal::is_column_alias, A> = true>
2662
internal::as_t<A, E> as(E expression) {
2663
return {std::move(expression)};
2664
}
2665
2666
#ifdef SQLITE_ORM_WITH_CPP20_ALIASES
2667
/**
2668
* Alias a column expression.
2669
*/
2670
template<orm_column_alias auto als, class E>
2671
auto as(E expression) {
2672
return internal::as_t<decltype(als), E>{std::move(expression)};
2673
}
2674
2675
/**
2676
* Alias a column expression.
2677
*/
2678
template<orm_column_alias A, class E>
2679
internal::as_t<A, E> operator>>=(E expression, const A&) {
2680
return {std::move(expression)};
2681
}
2682
#else
2683
/**
2684
* Alias a column expression.
2685
*/
2686
template<class A, class E, internal::satisfies<internal::is_column_alias, A> = true>
2687
internal::as_t<A, E> operator>>=(E expression, const A&) {
2688
return {std::move(expression)};
2689
}
2690
#endif
2691
2692
/**
2693
* Wrap a column alias in an alias holder.
2694
*/
2695
template<class T>
2696
internal::alias_holder<T> get() {
2697
static_assert(internal::is_column_alias_v<T>, "");
2698
return {};
2699
}
2700
2701
#ifdef SQLITE_ORM_WITH_CPP20_ALIASES
2702
template<orm_column_alias auto als>
2703
auto get() {
2704
return internal::alias_holder<decltype(als)>{};
2705
}
2706
#endif
2707
2708
template<class T>
2709
using alias_a = internal::recordset_alias<T, 'a'>;
2710
template<class T>
2711
using alias_b = internal::recordset_alias<T, 'b'>;
2712
template<class T>
2713
using alias_c = internal::recordset_alias<T, 'c'>;
2714
template<class T>
2715
using alias_d = internal::recordset_alias<T, 'd'>;
2716
template<class T>
2717
using alias_e = internal::recordset_alias<T, 'e'>;
2718
template<class T>
2719
using alias_f = internal::recordset_alias<T, 'f'>;
2720
template<class T>
2721
using alias_g = internal::recordset_alias<T, 'g'>;
2722
template<class T>
2723
using alias_h = internal::recordset_alias<T, 'h'>;
2724
template<class T>
2725
using alias_i = internal::recordset_alias<T, 'i'>;
2726
template<class T>
2727
using alias_j = internal::recordset_alias<T, 'j'>;
2728
template<class T>
2729
using alias_k = internal::recordset_alias<T, 'k'>;
2730
template<class T>
2731
using alias_l = internal::recordset_alias<T, 'l'>;
2732
template<class T>
2733
using alias_m = internal::recordset_alias<T, 'm'>;
2734
template<class T>
2735
using alias_n = internal::recordset_alias<T, 'n'>;
2736
template<class T>
2737
using alias_o = internal::recordset_alias<T, 'o'>;
2738
template<class T>
2739
using alias_p = internal::recordset_alias<T, 'p'>;
2740
template<class T>
2741
using alias_q = internal::recordset_alias<T, 'q'>;
2742
template<class T>
2743
using alias_r = internal::recordset_alias<T, 'r'>;
2744
template<class T>
2745
using alias_s = internal::recordset_alias<T, 's'>;
2746
template<class T>
2747
using alias_t = internal::recordset_alias<T, 't'>;
2748
template<class T>
2749
using alias_u = internal::recordset_alias<T, 'u'>;
2750
template<class T>
2751
using alias_v = internal::recordset_alias<T, 'v'>;
2752
template<class T>
2753
using alias_w = internal::recordset_alias<T, 'w'>;
2754
template<class T>
2755
using alias_x = internal::recordset_alias<T, 'x'>;
2756
template<class T>
2757
using alias_y = internal::recordset_alias<T, 'y'>;
2758
template<class T>
2759
using alias_z = internal::recordset_alias<T, 'z'>;
2760
2761
using colalias_a = internal::column_alias<'a'>;
2762
using colalias_b = internal::column_alias<'b'>;
2763
using colalias_c = internal::column_alias<'c'>;
2764
using colalias_d = internal::column_alias<'d'>;
2765
using colalias_e = internal::column_alias<'e'>;
2766
using colalias_f = internal::column_alias<'f'>;
2767
using colalias_g = internal::column_alias<'g'>;
2768
using colalias_h = internal::column_alias<'h'>;
2769
using colalias_i = internal::column_alias<'i'>;
2770
2771
#ifdef SQLITE_ORM_WITH_CPP20_ALIASES
2772
/** @short Create a table alias.
2773
*
2774
* Examples:
2775
* constexpr orm_table_alias auto z_alias = alias<'z'>.for_<User>();
2776
*/
2777
template<char A, char... X>
2778
inline constexpr internal::recordset_alias_builder<A, X...> alias{};
2779
2780
inline namespace literals {
2781
/** @short Create a table alias.
2782
*
2783
* Examples:
2784
* constexpr orm_table_alias auto z_alias = "z"_alias.for_<User>();
2785
*/
2786
template<internal::cstring_literal name>
2787
[[nodiscard]] consteval auto operator"" _alias() {
2788
return internal::explode_into<internal::recordset_alias_builder, name>(
2789
std::make_index_sequence<name.size()>{});
2790
}
2791
2792
/** @short Create a column alias.
2793
* column_alias<'a'[, ...]> from a string literal.
2794
* E.g. "a"_col, "b"_col
2795
*/
2796
template<internal::cstring_literal name>
2797
[[nodiscard]] consteval auto operator"" _col() {
2798
return internal::explode_into<internal::column_alias, name>(std::make_index_sequence<name.size()>{});
2799
}
2800
}
2801
#endif
2802
2803
#if (SQLITE_VERSION_NUMBER >= 3008003) && defined(SQLITE_ORM_WITH_CTE)
2804
inline namespace literals {
2805
/**
2806
* column_alias<'1'[, ...]> from a numeric literal.
2807
* E.g. 1_colalias, 2_colalias
2808
*/
2809
template<char... Chars>
2810
[[nodiscard]] SQLITE_ORM_CONSTEVAL auto operator"" _colalias() {
2811
// numeric identifiers are used for automatically assigning implicit aliases to unaliased column expressions,
2812
// which start at "1".
2813
static_assert(std::array{Chars...}[0] > '0');
2814
return internal::column_alias<Chars...>{};
2815
}
2816
}
2817
#endif
2818
}
2819
2820
// #include "error_code.h"
2821
2822
#include <sqlite3.h>
2823
#include <system_error> // std::error_code, std::system_error
2824
#include <string> // std::string
2825
#include <stdexcept>
2826
#include <sstream> // std::ostringstream
2827
#include <type_traits>
2828
2829
namespace sqlite_orm {
2830
2831
/** @short Enables classifying sqlite error codes.
2832
2833
@note We don't bother listing all possible values;
2834
this also allows for compatibility with
2835
'Construction rules for enum class values (P0138R2)'
2836
*/
2837
enum class sqlite_errc {};
2838
2839
enum class orm_error_code {
2840
not_found = 1,
2841
type_is_not_mapped_to_storage,
2842
trying_to_dereference_null_iterator,
2843
too_many_tables_specified,
2844
incorrect_set_fields_specified,
2845
column_not_found,
2846
table_has_no_primary_key_column,
2847
cannot_start_a_transaction_within_a_transaction,
2848
no_active_transaction,
2849
incorrect_journal_mode_string,
2850
incorrect_locking_mode_string,
2851
invalid_collate_argument_enum,
2852
failed_to_init_a_backup,
2853
unknown_member_value,
2854
incorrect_order,
2855
cannot_use_default_value,
2856
arguments_count_does_not_match,
2857
function_not_found,
2858
index_is_out_of_bounds,
2859
value_is_null,
2860
no_tables_specified,
2861
};
2862
}
2863
2864
namespace std {
2865
template<>
2866
struct is_error_code_enum<::sqlite_orm::sqlite_errc> : true_type {};
2867
2868
template<>
2869
struct is_error_code_enum<::sqlite_orm::orm_error_code> : true_type {};
2870
}
2871
2872
namespace sqlite_orm {
2873
2874
class orm_error_category : public std::error_category {
2875
public:
2876
const char* name() const noexcept override final {
2877
return "ORM error";
2878
}
2879
2880
std::string message(int c) const override final {
2881
switch (static_cast<orm_error_code>(c)) {
2882
case orm_error_code::not_found:
2883
return "Not found";
2884
case orm_error_code::type_is_not_mapped_to_storage:
2885
return "Type is not mapped to storage";
2886
case orm_error_code::trying_to_dereference_null_iterator:
2887
return "Trying to dereference null iterator";
2888
case orm_error_code::too_many_tables_specified:
2889
return "Too many tables specified";
2890
case orm_error_code::incorrect_set_fields_specified:
2891
return "Incorrect set fields specified";
2892
case orm_error_code::column_not_found:
2893
return "Column not found";
2894
case orm_error_code::table_has_no_primary_key_column:
2895
return "Table has no primary key column";
2896
case orm_error_code::cannot_start_a_transaction_within_a_transaction:
2897
return "Cannot start a transaction within a transaction";
2898
case orm_error_code::no_active_transaction:
2899
return "No active transaction";
2900
case orm_error_code::invalid_collate_argument_enum:
2901
return "Invalid collate_argument enum";
2902
case orm_error_code::failed_to_init_a_backup:
2903
return "Failed to init a backup";
2904
case orm_error_code::unknown_member_value:
2905
return "Unknown member value";
2906
case orm_error_code::incorrect_order:
2907
return "Incorrect order";
2908
case orm_error_code::cannot_use_default_value:
2909
return "The statement 'INSERT INTO * DEFAULT VALUES' can be used with only one row";
2910
case orm_error_code::arguments_count_does_not_match:
2911
return "Arguments count does not match";
2912
case orm_error_code::function_not_found:
2913
return "Function not found";
2914
case orm_error_code::index_is_out_of_bounds:
2915
return "Index is out of bounds";
2916
case orm_error_code::value_is_null:
2917
return "Value is null";
2918
case orm_error_code::no_tables_specified:
2919
return "No tables specified";
2920
default:
2921
return "unknown error";
2922
}
2923
}
2924
};
2925
2926
class sqlite_error_category : public std::error_category {
2927
public:
2928
const char* name() const noexcept override final {
2929
return "SQLite error";
2930
}
2931
2932
std::string message(int c) const override final {
2933
return sqlite3_errstr(c);
2934
}
2935
};
2936
2937
inline const orm_error_category& get_orm_error_category() {
2938
static orm_error_category res;
2939
return res;
2940
}
2941
2942
inline const sqlite_error_category& get_sqlite_error_category() {
2943
static sqlite_error_category res;
2944
return res;
2945
}
2946
2947
inline std::error_code make_error_code(sqlite_errc ev) noexcept {
2948
return {static_cast<int>(ev), get_sqlite_error_category()};
2949
}
2950
2951
inline std::error_code make_error_code(orm_error_code ev) noexcept {
2952
return {static_cast<int>(ev), get_orm_error_category()};
2953
}
2954
2955
template<typename... T>
2956
std::string get_error_message(sqlite3* db, T&&... args) {
2957
std::ostringstream stream;
2958
using unpack = int[];
2959
(void)unpack{0, (stream << args, 0)...};
2960
stream << sqlite3_errmsg(db);
2961
return stream.str();
2962
}
2963
2964
template<typename... T>
2965
[[noreturn]] void throw_error(sqlite3* db, T&&... args) {
2966
throw std::system_error{sqlite_errc(sqlite3_errcode(db)), get_error_message(db, std::forward<T>(args)...)};
2967
}
2968
2969
inline std::system_error sqlite_to_system_error(int ev) {
2970
return {sqlite_errc(ev)};
2971
}
2972
2973
inline std::system_error sqlite_to_system_error(sqlite3* db) {
2974
return {sqlite_errc(sqlite3_errcode(db)), sqlite3_errmsg(db)};
2975
}
2976
2977
[[noreturn]] inline void throw_translated_sqlite_error(int ev) {
2978
throw sqlite_to_system_error(ev);
2979
}
2980
2981
[[noreturn]] inline void throw_translated_sqlite_error(sqlite3* db) {
2982
throw sqlite_to_system_error(db);
2983
}
2984
2985
[[noreturn]] inline void throw_translated_sqlite_error(sqlite3_stmt* stmt) {
2986
throw sqlite_to_system_error(sqlite3_db_handle(stmt));
2987
}
2988
}
2989
2990
// #include "type_printer.h"
2991
2992
#include <string> // std::string
2993
#include <memory> // std::shared_ptr, std::unique_ptr
2994
#include <vector> // std::vector
2995
// #include "functional/cxx_optional.h"
2996
2997
// #include "functional/cxx_type_traits_polyfill.h"
2998
2999
// #include "type_traits.h"
3000
3001
// #include "is_std_ptr.h"
3002
3003
#include <type_traits>
3004
#include <memory>
3005
3006
namespace sqlite_orm {
3007
3008
/**
3009
* Specialization for optional type (std::shared_ptr / std::unique_ptr).
3010
*/
3011
template<typename T>
3012
struct is_std_ptr : std::false_type {};
3013
3014
template<typename T>
3015
struct is_std_ptr<std::shared_ptr<T>> : std::true_type {
3016
using element_type = typename std::shared_ptr<T>::element_type;
3017
3018
static std::shared_ptr<T> make(std::remove_cv_t<T>&& v) {
3019
return std::make_shared<T>(std::move(v));
3020
}
3021
};
3022
3023
template<typename T>
3024
struct is_std_ptr<std::unique_ptr<T>> : std::true_type {
3025
using element_type = typename std::unique_ptr<T>::element_type;
3026
3027
static auto make(std::remove_cv_t<T>&& v) {
3028
return std::make_unique<T>(std::move(v));
3029
}
3030
};
3031
}
3032
3033
namespace sqlite_orm {
3034
3035
/**
3036
* This class transforms a C++ type to a sqlite type name (int -> INTEGER, ...)
3037
*/
3038
template<class T, typename Enable = void>
3039
struct type_printer {};
3040
3041
struct integer_printer {
3042
const std::string& print() const {
3043
static const std::string res = "INTEGER";
3044
return res;
3045
}
3046
};
3047
3048
struct text_printer {
3049
const std::string& print() const {
3050
static const std::string res = "TEXT";
3051
return res;
3052
}
3053
};
3054
3055
struct real_printer {
3056
const std::string& print() const {
3057
static const std::string res = "REAL";
3058
return res;
3059
}
3060
};
3061
3062
struct blob_printer {
3063
const std::string& print() const {
3064
static const std::string res = "BLOB";
3065
return res;
3066
}
3067
};
3068
3069
// Note: char, unsigned/signed char are used for storing integer values, not char values.
3070
template<class T>
3071
struct type_printer<T,
3072
std::enable_if_t<polyfill::conjunction<polyfill::negation<internal::is_any_of<T,
3073
wchar_t,
3074
#ifdef SQLITE_ORM_CHAR8T_SUPPORTED
3075
char8_t,
3076
#endif
3077
char16_t,
3078
char32_t>>,
3079
std::is_integral<T>>::value>> : integer_printer {
3080
};
3081
3082
template<class T>
3083
struct type_printer<T, std::enable_if_t<std::is_floating_point<T>::value>> : real_printer {};
3084
3085
template<class T>
3086
struct type_printer<T,
3087
std::enable_if_t<polyfill::disjunction<std::is_same<T, const char*>,
3088
std::is_base_of<std::string, T>,
3089
std::is_base_of<std::wstring, T>>::value>>
3090
: text_printer {};
3091
3092
template<class T>
3093
struct type_printer<T, std::enable_if_t<is_std_ptr<T>::value>> : type_printer<typename T::element_type> {};
3094
3095
#ifdef SQLITE_ORM_OPTIONAL_SUPPORTED
3096
template<class T>
3097
struct type_printer<T, std::enable_if_t<polyfill::is_specialization_of_v<T, std::optional>>>
3098
: type_printer<typename T::value_type> {};
3099
#endif
3100
3101
template<>
3102
struct type_printer<std::vector<char>, void> : blob_printer {};
3103
}
3104
3105
// #include "constraints.h"
3106
3107
#include <type_traits> // std::is_base_of, std::false_type, std::true_type
3108
#include <system_error> // std::system_error
3109
#include <ostream> // std::ostream
3110
#include <string> // std::string
3111
#include <tuple> // std::tuple
3112
3113
// #include "functional/cxx_type_traits_polyfill.h"
3114
3115
// #include "functional/mpl.h"
3116
3117
// #include "tuple_helper/same_or_void.h"
3118
3119
#include <type_traits> // std::common_type
3120
3121
namespace sqlite_orm {
3122
namespace internal {
3123
3124
/**
3125
* Accepts any number of arguments and evaluates a nested `type` typename as `T` if all arguments are the same, otherwise `void`.
3126
*/
3127
template<class... Args>
3128
struct same_or_void {
3129
using type = void;
3130
};
3131
3132
template<class A>
3133
struct same_or_void<A> {
3134
using type = A;
3135
};
3136
3137
template<class A>
3138
struct same_or_void<A, A> {
3139
using type = A;
3140
};
3141
3142
template<class... Args>
3143
using same_or_void_t = typename same_or_void<Args...>::type;
3144
3145
template<class A, class... Args>
3146
struct same_or_void<A, A, Args...> : same_or_void<A, Args...> {};
3147
3148
template<class Pack>
3149
struct common_type_of;
3150
3151
template<template<class...> class Pack, class... Types>
3152
struct common_type_of<Pack<Types...>> : std::common_type<Types...> {};
3153
3154
/**
3155
* Accepts a pack of types and defines a nested `type` typename to a common type if possible, otherwise nonexistent.
3156
*
3157
* @note: SFINAE friendly like `std::common_type`.
3158
*/
3159
template<class Pack>
3160
using common_type_of_t = typename common_type_of<Pack>::type;
3161
}
3162
}
3163
3164
// #include "tuple_helper/tuple_traits.h"
3165
3166
// #include "tuple_helper/tuple_filter.h"
3167
3168
// #include "type_traits.h"
3169
3170
// #include "collate_argument.h"
3171
3172
namespace sqlite_orm {
3173
3174
namespace internal {
3175
3176
enum class collate_argument {
3177
binary,
3178
nocase,
3179
rtrim,
3180
};
3181
}
3182
}
3183
3184
// #include "error_code.h"
3185
3186
// #include "table_type_of.h"
3187
3188
// #include "type_printer.h"
3189
3190
// #include "column_pointer.h"
3191
3192
namespace sqlite_orm {
3193
3194
namespace internal {
3195
3196
enum class conflict_clause_t {
3197
rollback,
3198
abort,
3199
fail,
3200
ignore,
3201
replace,
3202
};
3203
3204
struct primary_key_base {
3205
enum class order_by {
3206
unspecified,
3207
ascending,
3208
descending,
3209
};
3210
struct {
3211
order_by asc_option = order_by::unspecified;
3212
conflict_clause_t conflict_clause = conflict_clause_t::rollback;
3213
bool conflict_clause_is_on = false;
3214
} options;
3215
};
3216
3217
template<class T>
3218
struct primary_key_with_autoincrement : T {
3219
using primary_key_type = T;
3220
3221
const primary_key_type& as_base() const {
3222
return *this;
3223
}
3224
#ifndef SQLITE_ORM_AGGREGATE_BASES_SUPPORTED
3225
primary_key_with_autoincrement(primary_key_type primary_key) : primary_key_type{primary_key} {}
3226
#endif
3227
};
3228
3229
/**
3230
* PRIMARY KEY constraint class.
3231
* Cs is parameter pack which contains columns (member pointers and/or function pointers). Can be empty when
3232
* used within `make_column` function.
3233
*/
3234
template<class... Cs>
3235
struct primary_key_t : primary_key_base {
3236
using self = primary_key_t<Cs...>;
3237
using order_by = primary_key_base::order_by;
3238
using columns_tuple = std::tuple<Cs...>;
3239
3240
columns_tuple columns;
3241
3242
primary_key_t(columns_tuple columns) : columns(std::move(columns)) {}
3243
3244
self asc() const {
3245
auto res = *this;
3246
res.options.asc_option = order_by::ascending;
3247
return res;
3248
}
3249
3250
self desc() const {
3251
auto res = *this;
3252
res.options.asc_option = order_by::descending;
3253
return res;
3254
}
3255
3256
primary_key_with_autoincrement<self> autoincrement() const {
3257
return {*this};
3258
}
3259
3260
self on_conflict_rollback() const {
3261
auto res = *this;
3262
res.options.conflict_clause_is_on = true;
3263
res.options.conflict_clause = conflict_clause_t::rollback;
3264
return res;
3265
}
3266
3267
self on_conflict_abort() const {
3268
auto res = *this;
3269
res.options.conflict_clause_is_on = true;
3270
res.options.conflict_clause = conflict_clause_t::abort;
3271
return res;
3272
}
3273
3274
self on_conflict_fail() const {
3275
auto res = *this;
3276
res.options.conflict_clause_is_on = true;
3277
res.options.conflict_clause = conflict_clause_t::fail;
3278
return res;
3279
}
3280
3281
self on_conflict_ignore() const {
3282
auto res = *this;
3283
res.options.conflict_clause_is_on = true;
3284
res.options.conflict_clause = conflict_clause_t::ignore;
3285
return res;
3286
}
3287
3288
self on_conflict_replace() const {
3289
auto res = *this;
3290
res.options.conflict_clause_is_on = true;
3291
res.options.conflict_clause = conflict_clause_t::replace;
3292
return res;
3293
}
3294
};
3295
3296
struct unique_base {
3297
operator std::string() const {
3298
return "UNIQUE";
3299
}
3300
};
3301
3302
/**
3303
* UNIQUE constraint class.
3304
*/
3305
template<class... Args>
3306
struct unique_t : unique_base {
3307
using columns_tuple = std::tuple<Args...>;
3308
3309
columns_tuple columns;
3310
3311
unique_t(columns_tuple columns_) : columns(std::move(columns_)) {}
3312
};
3313
3314
struct unindexed_t {};
3315
3316
template<class T>
3317
struct prefix_t {
3318
using value_type = T;
3319
3320
value_type value;
3321
};
3322
3323
template<class T>
3324
struct tokenize_t {
3325
using value_type = T;
3326
3327
value_type value;
3328
};
3329
3330
template<class T>
3331
struct content_t {
3332
using value_type = T;
3333
3334
value_type value;
3335
};
3336
3337
template<class T>
3338
struct table_content_t {
3339
using mapped_type = T;
3340
};
3341
3342
/**
3343
* DEFAULT constraint class.
3344
* T is a value type.
3345
*/
3346
template<class T>
3347
struct default_t {
3348
using value_type = T;
3349
3350
value_type value;
3351
3352
operator std::string() const {
3353
return "DEFAULT";
3354
}
3355
};
3356
3357
#if SQLITE_VERSION_NUMBER >= 3006019
3358
/**
3359
* FOREIGN KEY constraint class.
3360
* Cs are columns which has foreign key
3361
* Rs are column which C references to
3362
* Available in SQLite 3.6.19 or higher
3363
*/
3364
3365
template<class A, class B>
3366
struct foreign_key_t;
3367
3368
enum class foreign_key_action {
3369
none, // not specified
3370
no_action,
3371
restrict_,
3372
set_null,
3373
set_default,
3374
cascade,
3375
};
3376
3377
inline std::ostream& operator<<(std::ostream& os, foreign_key_action action) {
3378
switch (action) {
3379
case foreign_key_action::no_action:
3380
os << "NO ACTION";
3381
break;
3382
case foreign_key_action::restrict_:
3383
os << "RESTRICT";
3384
break;
3385
case foreign_key_action::set_null:
3386
os << "SET NULL";
3387
break;
3388
case foreign_key_action::set_default:
3389
os << "SET DEFAULT";
3390
break;
3391
case foreign_key_action::cascade:
3392
os << "CASCADE";
3393
break;
3394
case foreign_key_action::none:
3395
break;
3396
}
3397
return os;
3398
}
3399
3400
struct on_update_delete_base {
3401
const bool update; // true if update and false if delete
3402
3403
operator std::string() const {
3404
if (this->update) {
3405
return "ON UPDATE";
3406
} else {
3407
return "ON DELETE";
3408
}
3409
}
3410
};
3411
3412
/**
3413
* F - foreign key class
3414
*/
3415
template<class F>
3416
struct on_update_delete_t : on_update_delete_base {
3417
using foreign_key_type = F;
3418
3419
const foreign_key_type& fk;
3420
3421
on_update_delete_t(decltype(fk) fk_, decltype(update) update_, foreign_key_action action_) :
3422
on_update_delete_base{update_}, fk(fk_), _action(action_) {}
3423
3424
foreign_key_action _action = foreign_key_action::none;
3425
3426
foreign_key_type no_action() const {
3427
auto res = this->fk;
3428
if (update) {
3429
res.on_update._action = foreign_key_action::no_action;
3430
} else {
3431
res.on_delete._action = foreign_key_action::no_action;
3432
}
3433
return res;
3434
}
3435
3436
foreign_key_type restrict_() const {
3437
auto res = this->fk;
3438
if (update) {
3439
res.on_update._action = foreign_key_action::restrict_;
3440
} else {
3441
res.on_delete._action = foreign_key_action::restrict_;
3442
}
3443
return res;
3444
}
3445
3446
foreign_key_type set_null() const {
3447
auto res = this->fk;
3448
if (update) {
3449
res.on_update._action = foreign_key_action::set_null;
3450
} else {
3451
res.on_delete._action = foreign_key_action::set_null;
3452
}
3453
return res;
3454
}
3455
3456
foreign_key_type set_default() const {
3457
auto res = this->fk;
3458
if (update) {
3459
res.on_update._action = foreign_key_action::set_default;
3460
} else {
3461
res.on_delete._action = foreign_key_action::set_default;
3462
}
3463
return res;
3464
}
3465
3466
foreign_key_type cascade() const {
3467
auto res = this->fk;
3468
if (update) {
3469
res.on_update._action = foreign_key_action::cascade;
3470
} else {
3471
res.on_delete._action = foreign_key_action::cascade;
3472
}
3473
return res;
3474
}
3475
3476
operator bool() const {
3477
return this->_action != foreign_key_action::none;
3478
}
3479
};
3480
3481
template<class F>
3482
bool operator==(const on_update_delete_t<F>& lhs, const on_update_delete_t<F>& rhs) {
3483
return lhs._action == rhs._action;
3484
}
3485
3486
template<class... Cs, class... Rs>
3487
struct foreign_key_t<std::tuple<Cs...>, std::tuple<Rs...>> {
3488
using columns_type = std::tuple<Cs...>;
3489
using references_type = std::tuple<Rs...>;
3490
using self = foreign_key_t<columns_type, references_type>;
3491
3492
/**
3493
* Holds obect type of all referenced columns.
3494
*/
3495
using target_type = same_or_void_t<table_type_of_t<Rs>...>;
3496
3497
/**
3498
* Holds obect type of all source columns.
3499
*/
3500
using source_type = same_or_void_t<table_type_of_t<Cs>...>;
3501
3502
columns_type columns;
3503
references_type references;
3504
3505
on_update_delete_t<self> on_update;
3506
on_update_delete_t<self> on_delete;
3507
3508
static_assert(std::tuple_size<columns_type>::value == std::tuple_size<references_type>::value,
3509
"Columns size must be equal to references tuple");
3510
static_assert(!std::is_same<target_type, void>::value, "All references must have the same type");
3511
3512
foreign_key_t(columns_type columns_, references_type references_) :
3513
columns(std::move(columns_)), references(std::move(references_)),
3514
on_update(*this, true, foreign_key_action::none), on_delete(*this, false, foreign_key_action::none) {}
3515
3516
foreign_key_t(const self& other) :
3517
columns(other.columns), references(other.references), on_update(*this, true, other.on_update._action),
3518
on_delete(*this, false, other.on_delete._action) {}
3519
3520
self& operator=(const self& other) {
3521
this->columns = other.columns;
3522
this->references = other.references;
3523
this->on_update = {*this, true, other.on_update._action};
3524
this->on_delete = {*this, false, other.on_delete._action};
3525
return *this;
3526
}
3527
};
3528
3529
template<class A, class B>
3530
bool operator==(const foreign_key_t<A, B>& lhs, const foreign_key_t<A, B>& rhs) {
3531
return lhs.columns == rhs.columns && lhs.references == rhs.references && lhs.on_update == rhs.on_update &&
3532
lhs.on_delete == rhs.on_delete;
3533
}
3534
3535
/**
3536
* Cs can be a class member pointer, a getter function member pointer or setter
3537
* func member pointer
3538
* Available in SQLite 3.6.19 or higher
3539
*/
3540
template<class... Cs>
3541
struct foreign_key_intermediate_t {
3542
using tuple_type = std::tuple<Cs...>;
3543
3544
tuple_type columns;
3545
3546
template<class... Rs>
3547
foreign_key_t<std::tuple<Cs...>, std::tuple<Rs...>> references(Rs... refs) {
3548
return {std::move(this->columns), {std::forward<Rs>(refs)...}};
3549
}
3550
3551
template<class T, class... Rs>
3552
foreign_key_t<std::tuple<Cs...>, std::tuple<internal::column_pointer<T, Rs>...>> references(Rs... refs) {
3553
return {std::move(this->columns), {sqlite_orm::column<T>(refs)...}};
3554
}
3555
};
3556
#endif
3557
3558
struct collate_constraint_t {
3559
collate_argument argument = collate_argument::binary;
3560
#ifndef SQLITE_ORM_AGGREGATE_NSDMI_SUPPORTED
3561
collate_constraint_t(collate_argument argument) : argument{argument} {}
3562
#endif
3563
3564
operator std::string() const {
3565
return "COLLATE " + this->string_from_collate_argument(this->argument);
3566
}
3567
3568
static std::string string_from_collate_argument(collate_argument argument) {
3569
switch (argument) {
3570
case collate_argument::binary:
3571
return "BINARY";
3572
case collate_argument::nocase:
3573
return "NOCASE";
3574
case collate_argument::rtrim:
3575
return "RTRIM";
3576
}
3577
throw std::system_error{orm_error_code::invalid_collate_argument_enum};
3578
}
3579
};
3580
3581
template<class T>
3582
struct check_t {
3583
using expression_type = T;
3584
3585
expression_type expression;
3586
};
3587
3588
struct basic_generated_always {
3589
enum class storage_type {
3590
not_specified,
3591
virtual_,
3592
stored,
3593
};
3594
3595
#if SQLITE_VERSION_NUMBER >= 3031000
3596
bool full = true;
3597
storage_type storage = storage_type::not_specified;
3598
#endif
3599
3600
#ifndef SQLITE_ORM_AGGREGATE_NSDMI_SUPPORTED
3601
basic_generated_always(bool full, storage_type storage) : full{full}, storage{storage} {}
3602
#endif
3603
};
3604
3605
#if SQLITE_VERSION_NUMBER >= 3031000
3606
template<class T>
3607
struct generated_always_t : basic_generated_always {
3608
using expression_type = T;
3609
3610
expression_type expression;
3611
3612
generated_always_t(expression_type expression_, bool full, storage_type storage) :
3613
basic_generated_always{full, storage}, expression(std::move(expression_)) {}
3614
3615
generated_always_t<T> virtual_() {
3616
return {std::move(this->expression), this->full, storage_type::virtual_};
3617
}
3618
3619
generated_always_t<T> stored() {
3620
return {std::move(this->expression), this->full, storage_type::stored};
3621
}
3622
};
3623
#endif
3624
3625
struct null_t {};
3626
3627
struct not_null_t {};
3628
}
3629
3630
namespace internal {
3631
3632
template<class T>
3633
SQLITE_ORM_INLINE_VAR constexpr bool is_foreign_key_v =
3634
#if SQLITE_VERSION_NUMBER >= 3006019
3635
polyfill::is_specialization_of<T, foreign_key_t>::value;
3636
#else
3637
false;
3638
#endif
3639
3640
template<class T>
3641
struct is_foreign_key : polyfill::bool_constant<is_foreign_key_v<T>> {};
3642
3643
template<class T>
3644
SQLITE_ORM_INLINE_VAR constexpr bool is_primary_key_v = std::is_base_of<primary_key_base, T>::value;
3645
3646
template<class T>
3647
struct is_primary_key : polyfill::bool_constant<is_primary_key_v<T>> {};
3648
3649
template<class T>
3650
SQLITE_ORM_INLINE_VAR constexpr bool is_generated_always_v =
3651
#if SQLITE_VERSION_NUMBER >= 3031000
3652
polyfill::is_specialization_of<T, generated_always_t>::value;
3653
#else
3654
false;
3655
#endif
3656
3657
template<class T>
3658
struct is_generated_always : polyfill::bool_constant<is_generated_always_v<T>> {};
3659
3660
/**
3661
* PRIMARY KEY INSERTABLE traits.
3662
*/
3663
template<typename Column>
3664
struct is_primary_key_insertable
3665
: polyfill::disjunction<
3666
mpl::invoke_t<mpl::disjunction<check_if_has_template<primary_key_with_autoincrement>,
3667
check_if_has_template<default_t>>,
3668
constraints_type_t<Column>>,
3669
std::is_base_of<integer_printer, type_printer<field_type_t<Column>>>> {
3670
3671
static_assert(tuple_has<constraints_type_t<Column>, is_primary_key>::value,
3672
"an unexpected type was passed");
3673
};
3674
3675
template<class T>
3676
using is_column_constraint = mpl::invoke_t<mpl::disjunction<check_if<std::is_base_of, primary_key_t<>>,
3677
check_if_is_type<null_t>,
3678
check_if_is_type<not_null_t>,
3679
check_if_is_type<unique_t<>>,
3680
check_if_is_template<default_t>,
3681
check_if_is_template<check_t>,
3682
check_if_is_type<collate_constraint_t>,
3683
check_if<is_generated_always>,
3684
check_if_is_type<unindexed_t>>,
3685
T>;
3686
}
3687
3688
#if SQLITE_VERSION_NUMBER >= 3031000
3689
template<class T>
3690
internal::generated_always_t<T> generated_always_as(T expression) {
3691
return {std::move(expression), true, internal::basic_generated_always::storage_type::not_specified};
3692
}
3693
3694
template<class T>
3695
internal::generated_always_t<T> as(T expression) {
3696
return {std::move(expression), false, internal::basic_generated_always::storage_type::not_specified};
3697
}
3698
#endif
3699
3700
#if SQLITE_VERSION_NUMBER >= 3006019
3701
/**
3702
* FOREIGN KEY constraint construction function that takes member pointer as argument
3703
* Available in SQLite 3.6.19 or higher
3704
*/
3705
template<class... Cs>
3706
internal::foreign_key_intermediate_t<Cs...> foreign_key(Cs... columns) {
3707
return {{std::forward<Cs>(columns)...}};
3708
}
3709
#endif
3710
3711
/**
3712
* UNIQUE table constraint builder function.
3713
*/
3714
template<class... Args>
3715
internal::unique_t<Args...> unique(Args... args) {
3716
return {{std::forward<Args>(args)...}};
3717
}
3718
3719
/**
3720
* UNIQUE column constraint builder function.
3721
*/
3722
inline internal::unique_t<> unique() {
3723
return {{}};
3724
}
3725
3726
#if SQLITE_VERSION_NUMBER >= 3009000
3727
/**
3728
* UNINDEXED column constraint builder function. Used in FTS virtual tables.
3729
*
3730
* https://www.sqlite.org/fts5.html#the_unindexed_column_option
3731
*/
3732
inline internal::unindexed_t unindexed() {
3733
return {};
3734
}
3735
3736
/**
3737
* prefix=N table constraint builder function. Used in FTS virtual tables.
3738
*
3739
* https://www.sqlite.org/fts5.html#prefix_indexes
3740
*/
3741
template<class T>
3742
internal::prefix_t<T> prefix(T value) {
3743
return {std::move(value)};
3744
}
3745
3746
/**
3747
* tokenize='...'' table constraint builder function. Used in FTS virtual tables.
3748
*
3749
* https://www.sqlite.org/fts5.html#tokenizers
3750
*/
3751
template<class T>
3752
internal::tokenize_t<T> tokenize(T value) {
3753
return {std::move(value)};
3754
}
3755
3756
/**
3757
* content='' table constraint builder function. Used in FTS virtual tables.
3758
*
3759
* https://www.sqlite.org/fts5.html#contentless_tables
3760
*/
3761
template<class T>
3762
internal::content_t<T> content(T value) {
3763
return {std::move(value)};
3764
}
3765
3766
/**
3767
* content='table' table constraint builder function. Used in FTS virtual tables.
3768
*
3769
* https://www.sqlite.org/fts5.html#external_content_tables
3770
*/
3771
template<class T>
3772
internal::table_content_t<T> content() {
3773
return {};
3774
}
3775
#endif
3776
3777
/**
3778
* PRIMARY KEY table constraint builder function.
3779
*/
3780
template<class... Cs>
3781
internal::primary_key_t<Cs...> primary_key(Cs... cs) {
3782
return {{std::forward<Cs>(cs)...}};
3783
}
3784
3785
/**
3786
* PRIMARY KEY column constraint builder function.
3787
*/
3788
inline internal::primary_key_t<> primary_key() {
3789
return {{}};
3790
}
3791
3792
template<class T>
3793
internal::default_t<T> default_value(T t) {
3794
return {std::move(t)};
3795
}
3796
3797
inline internal::collate_constraint_t collate_nocase() {
3798
return {internal::collate_argument::nocase};
3799
}
3800
3801
inline internal::collate_constraint_t collate_binary() {
3802
return {internal::collate_argument::binary};
3803
}
3804
3805
inline internal::collate_constraint_t collate_rtrim() {
3806
return {internal::collate_argument::rtrim};
3807
}
3808
3809
template<class T>
3810
internal::check_t<T> check(T t) {
3811
return {std::move(t)};
3812
}
3813
3814
inline internal::null_t null() {
3815
return {};
3816
}
3817
3818
inline internal::not_null_t not_null() {
3819
return {};
3820
}
3821
}
3822
3823
// #include "field_printer.h"
3824
3825
#include <string> // std::string
3826
#include <sstream> // std::stringstream
3827
#include <vector> // std::vector
3828
#include <memory> // std::shared_ptr, std::unique_ptr
3829
#ifndef SQLITE_ORM_OMITS_CODECVT
3830
#include <locale> // std::wstring_convert
3831
#include <codecvt> // std::codecvt_utf8_utf16
3832
#endif
3833
// #include "functional/cxx_optional.h"
3834
3835
// #include "functional/cxx_type_traits_polyfill.h"
3836
3837
// #include "is_std_ptr.h"
3838
3839
// #include "type_traits.h"
3840
3841
namespace sqlite_orm {
3842
3843
/**
3844
* Is used to print members mapped to objects in storage_t::dump member function.
3845
* Other developers can create own specialization to map custom types
3846
*/
3847
template<class T, typename SFINAE = void>
3848
struct field_printer;
3849
3850
namespace internal {
3851
/*
3852
* Implementation note: the technique of indirect expression testing is because
3853
* of older compilers having problems with the detection of dependent templates [SQLITE_ORM_BROKEN_ALIAS_TEMPLATE_DEPENDENT_EXPR_SFINAE].
3854
* It must also be a type that differs from those for `is_preparable_v`, `is_bindable_v`.
3855
*/
3856
template<class Printer>
3857
struct indirectly_test_printable;
3858
3859
template<class T, class SFINAE = void>
3860
SQLITE_ORM_INLINE_VAR constexpr bool is_printable_v = false;
3861
template<class T>
3862
SQLITE_ORM_INLINE_VAR constexpr bool
3863
is_printable_v<T, polyfill::void_t<indirectly_test_printable<decltype(field_printer<T>{})>>> = true;
3864
3865
template<class T>
3866
struct is_printable : polyfill::bool_constant<is_printable_v<T>> {};
3867
}
3868
3869
template<class T>
3870
struct field_printer<T, internal::match_if<std::is_arithmetic, T>> {
3871
std::string operator()(const T& t) const {
3872
std::stringstream ss;
3873
ss << t;
3874
return ss.str();
3875
}
3876
};
3877
3878
/**
3879
* Upgrade to integer is required when using unsigned char(uint8_t)
3880
*/
3881
template<>
3882
struct field_printer<unsigned char, void> {
3883
std::string operator()(const unsigned char& t) const {
3884
std::stringstream ss;
3885
ss << +t;
3886
return ss.str();
3887
}
3888
};
3889
3890
/**
3891
* Upgrade to integer is required when using signed char(int8_t)
3892
*/
3893
template<>
3894
struct field_printer<signed char, void> {
3895
std::string operator()(const signed char& t) const {
3896
std::stringstream ss;
3897
ss << +t;
3898
return ss.str();
3899
}
3900
};
3901
3902
/**
3903
* char is neither signed char nor unsigned char so it has its own specialization
3904
*/
3905
template<>
3906
struct field_printer<char, void> {
3907
std::string operator()(const char& t) const {
3908
std::stringstream ss;
3909
ss << +t;
3910
return ss.str();
3911
}
3912
};
3913
3914
template<class T>
3915
struct field_printer<T, internal::match_if<std::is_base_of, std::string, T>> {
3916
std::string operator()(std::string string) const {
3917
return string;
3918
}
3919
};
3920
3921
template<>
3922
struct field_printer<std::vector<char>, void> {
3923
std::string operator()(const std::vector<char>& t) const {
3924
std::stringstream ss;
3925
ss << std::hex;
3926
for (auto c: t) {
3927
ss << c;
3928
}
3929
return ss.str();
3930
}
3931
};
3932
#ifndef SQLITE_ORM_OMITS_CODECVT
3933
/**
3934
* Specialization for std::wstring (UTF-16 assumed).
3935
*/
3936
template<class T>
3937
struct field_printer<T, internal::match_if<std::is_base_of, std::wstring, T>> {
3938
std::string operator()(const std::wstring& wideString) const {
3939
std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>> converter;
3940
return converter.to_bytes(wideString);
3941
}
3942
};
3943
#endif // SQLITE_ORM_OMITS_CODECVT
3944
template<>
3945
struct field_printer<nullptr_t, void> {
3946
std::string operator()(const nullptr_t&) const {
3947
return "NULL";
3948
}
3949
};
3950
#ifdef SQLITE_ORM_OPTIONAL_SUPPORTED
3951
template<>
3952
struct field_printer<std::nullopt_t, void> {
3953
std::string operator()(const std::nullopt_t&) const {
3954
return "NULL";
3955
}
3956
};
3957
#endif // SQLITE_ORM_OPTIONAL_SUPPORTED
3958
template<class T>
3959
struct field_printer<T,
3960
std::enable_if_t<polyfill::conjunction<
3961
is_std_ptr<T>,
3962
internal::is_printable<std::remove_cv_t<typename T::element_type>>>::value>> {
3963
using unqualified_type = std::remove_cv_t<typename T::element_type>;
3964
3965
std::string operator()(const T& t) const {
3966
if (t) {
3967
return field_printer<unqualified_type>()(*t);
3968
} else {
3969
return field_printer<nullptr_t>{}(nullptr);
3970
}
3971
}
3972
};
3973
3974
#ifdef SQLITE_ORM_OPTIONAL_SUPPORTED
3975
template<class T>
3976
struct field_printer<
3977
T,
3978
std::enable_if_t<polyfill::conjunction_v<polyfill::is_specialization_of<T, std::optional>,
3979
internal::is_printable<std::remove_cv_t<typename T::value_type>>>>> {
3980
using unqualified_type = std::remove_cv_t<typename T::value_type>;
3981
3982
std::string operator()(const T& t) const {
3983
if (t.has_value()) {
3984
return field_printer<unqualified_type>()(*t);
3985
} else {
3986
return field_printer<std::nullopt_t>{}(std::nullopt);
3987
}
3988
}
3989
};
3990
#endif // SQLITE_ORM_OPTIONAL_SUPPORTED
3991
}
3992
3993
// #include "rowid.h"
3994
3995
#include <string> // std::string
3996
3997
namespace sqlite_orm {
3998
3999
namespace internal {
4000
4001
struct rowid_t {
4002
operator std::string() const {
4003
return "rowid";
4004
}
4005
};
4006
4007
struct oid_t {
4008
operator std::string() const {
4009
return "oid";
4010
}
4011
};
4012
4013
struct _rowid_t {
4014
operator std::string() const {
4015
return "_rowid_";
4016
}
4017
};
4018
4019
template<class T>
4020
struct table_rowid_t : public rowid_t {
4021
using type = T;
4022
};
4023
4024
template<class T>
4025
struct table_oid_t : public oid_t {
4026
using type = T;
4027
};
4028
template<class T>
4029
struct table__rowid_t : public _rowid_t {
4030
using type = T;
4031
};
4032
4033
}
4034
4035
inline internal::rowid_t rowid() {
4036
return {};
4037
}
4038
4039
inline internal::oid_t oid() {
4040
return {};
4041
}
4042
4043
inline internal::_rowid_t _rowid_() {
4044
return {};
4045
}
4046
4047
template<class T>
4048
internal::table_rowid_t<T> rowid() {
4049
return {};
4050
}
4051
4052
template<class T>
4053
internal::table_oid_t<T> oid() {
4054
return {};
4055
}
4056
4057
template<class T>
4058
internal::table__rowid_t<T> _rowid_() {
4059
return {};
4060
}
4061
}
4062
4063
// #include "operators.h"
4064
4065
#include <type_traits> // std::false_type, std::true_type
4066
#include <utility> // std::move
4067
4068
// #include "functional/cxx_type_traits_polyfill.h"
4069
4070
// #include "is_base_of_template.h"
4071
4072
#include <type_traits> // std::true_type, std::false_type, std::declval
4073
4074
namespace sqlite_orm {
4075
4076
namespace internal {
4077
4078
/*
4079
* This is because of bug in MSVC, for more information, please visit
4080
* https://stackoverflow.com/questions/34672441/stdis-base-of-for-template-classes/34672753#34672753
4081
*/
4082
#ifdef SQLITE_ORM_BROKEN_VARIADIC_PACK_EXPANSION
4083
template<template<typename...> class Base>
4084
struct is_base_of_template_impl {
4085
template<typename... Ts>
4086
static constexpr std::true_type test(const Base<Ts...>&);
4087
4088
static constexpr std::false_type test(...);
4089
};
4090
4091
template<typename T, template<typename...> class C>
4092
using is_base_of_template = decltype(is_base_of_template_impl<C>::test(std::declval<T>()));
4093
#else
4094
template<template<typename...> class C, typename... Ts>
4095
std::true_type is_base_of_template_impl(const C<Ts...>&);
4096
4097
template<template<typename...> class C>
4098
std::false_type is_base_of_template_impl(...);
4099
4100
template<typename T, template<typename...> class C>
4101
using is_base_of_template = decltype(is_base_of_template_impl<C>(std::declval<T>()));
4102
#endif
4103
4104
template<typename T, template<typename...> class C>
4105
SQLITE_ORM_INLINE_VAR constexpr bool is_base_of_template_v = is_base_of_template<T, C>::value;
4106
}
4107
}
4108
4109
// #include "tags.h"
4110
4111
// #include "serialize_result_type.h"
4112
4113
// #include "functional/cxx_string_view.h"
4114
4115
// #include "cxx_core_features.h"
4116
4117
#if SQLITE_ORM_HAS_INCLUDE(<string_view>)
4118
#include <string_view>
4119
#endif
4120
4121
#if __cpp_lib_string_view >= 201606L
4122
#define SQLITE_ORM_STRING_VIEW_SUPPORTED
4123
#endif
4124
4125
#ifndef SQLITE_ORM_STRING_VIEW_SUPPORTED
4126
#include <string> // std::string
4127
#endif
4128
4129
namespace sqlite_orm {
4130
namespace internal {
4131
#ifdef SQLITE_ORM_STRING_VIEW_SUPPORTED
4132
using serialize_result_type = std::string_view;
4133
using serialize_arg_type = std::string_view;
4134
#else
4135
using serialize_result_type = std::string;
4136
using serialize_arg_type = const std::string&;
4137
#endif
4138
}
4139
}
4140
4141
namespace sqlite_orm {
4142
4143
namespace internal {
4144
4145
template<class L, class R, class... Ds>
4146
struct binary_operator : Ds... {
4147
using left_type = L;
4148
using right_type = R;
4149
4150
left_type lhs;
4151
right_type rhs;
4152
4153
constexpr binary_operator(left_type lhs_, right_type rhs_) : lhs(std::move(lhs_)), rhs(std::move(rhs_)) {}
4154
};
4155
4156
template<class T>
4157
SQLITE_ORM_INLINE_VAR constexpr bool is_binary_operator_v = is_base_of_template<T, binary_operator>::value;
4158
4159
template<class T>
4160
using is_binary_operator = polyfill::bool_constant<is_binary_operator_v<T>>;
4161
4162
struct conc_string {
4163
serialize_result_type serialize() const {
4164
return "||";
4165
}
4166
};
4167
4168
/**
4169
* Result of concatenation || operator
4170
*/
4171
template<class L, class R>
4172
using conc_t = binary_operator<L, R, conc_string>;
4173
4174
struct unary_minus_string {
4175
serialize_result_type serialize() const {
4176
return "-";
4177
}
4178
};
4179
4180
/**
4181
* Result of unary minus - operator
4182
*/
4183
template<class T>
4184
struct unary_minus_t : unary_minus_string, arithmetic_t, negatable_t {
4185
using argument_type = T;
4186
4187
argument_type argument;
4188
4189
unary_minus_t(argument_type argument_) : argument(std::move(argument_)) {}
4190
};
4191
4192
struct add_string {
4193
serialize_result_type serialize() const {
4194
return "+";
4195
}
4196
};
4197
4198
/**
4199
* Result of addition + operator
4200
*/
4201
template<class L, class R>
4202
using add_t = binary_operator<L, R, add_string, arithmetic_t, negatable_t>;
4203
4204
struct sub_string {
4205
serialize_result_type serialize() const {
4206
return "-";
4207
}
4208
};
4209
4210
/**
4211
* Result of substraction - operator
4212
*/
4213
template<class L, class R>
4214
using sub_t = binary_operator<L, R, sub_string, arithmetic_t, negatable_t>;
4215
4216
struct mul_string {
4217
serialize_result_type serialize() const {
4218
return "*";
4219
}
4220
};
4221
4222
/**
4223
* Result of multiply * operator
4224
*/
4225
template<class L, class R>
4226
using mul_t = binary_operator<L, R, mul_string, arithmetic_t, negatable_t>;
4227
4228
struct div_string {
4229
serialize_result_type serialize() const {
4230
return "/";
4231
}
4232
};
4233
4234
/**
4235
* Result of divide / operator
4236
*/
4237
template<class L, class R>
4238
using div_t = binary_operator<L, R, div_string, arithmetic_t, negatable_t>;
4239
4240
struct mod_operator_string {
4241
serialize_result_type serialize() const {
4242
return "%";
4243
}
4244
};
4245
4246
/**
4247
* Result of mod % operator
4248
*/
4249
template<class L, class R>
4250
using mod_t = binary_operator<L, R, mod_operator_string, arithmetic_t, negatable_t>;
4251
4252
struct bitwise_shift_left_string {
4253
serialize_result_type serialize() const {
4254
return "<<";
4255
}
4256
};
4257
4258
/**
4259
* Result of bitwise shift left << operator
4260
*/
4261
template<class L, class R>
4262
using bitwise_shift_left_t = binary_operator<L, R, bitwise_shift_left_string, arithmetic_t, negatable_t>;
4263
4264
struct bitwise_shift_right_string {
4265
serialize_result_type serialize() const {
4266
return ">>";
4267
}
4268
};
4269
4270
/**
4271
* Result of bitwise shift right >> operator
4272
*/
4273
template<class L, class R>
4274
using bitwise_shift_right_t = binary_operator<L, R, bitwise_shift_right_string, arithmetic_t, negatable_t>;
4275
4276
struct bitwise_and_string {
4277
serialize_result_type serialize() const {
4278
return "&";
4279
}
4280
};
4281
4282
/**
4283
* Result of bitwise and & operator
4284
*/
4285
template<class L, class R>
4286
using bitwise_and_t = binary_operator<L, R, bitwise_and_string, arithmetic_t, negatable_t>;
4287
4288
struct bitwise_or_string {
4289
serialize_result_type serialize() const {
4290
return "|";
4291
}
4292
};
4293
4294
/**
4295
* Result of bitwise or | operator
4296
*/
4297
template<class L, class R>
4298
using bitwise_or_t = binary_operator<L, R, bitwise_or_string, arithmetic_t, negatable_t>;
4299
4300
struct bitwise_not_string {
4301
serialize_result_type serialize() const {
4302
return "~";
4303
}
4304
};
4305
4306
/**
4307
* Result of bitwise not ~ operator
4308
*/
4309
template<class T>
4310
struct bitwise_not_t : bitwise_not_string, arithmetic_t, negatable_t {
4311
using argument_type = T;
4312
4313
argument_type argument;
4314
4315
bitwise_not_t(argument_type argument_) : argument(std::move(argument_)) {}
4316
};
4317
4318
struct assign_string {
4319
serialize_result_type serialize() const {
4320
return "=";
4321
}
4322
};
4323
4324
/**
4325
* Result of assign = operator
4326
*/
4327
template<class L, class R>
4328
using assign_t = binary_operator<L, R, assign_string>;
4329
4330
/**
4331
* Assign operator traits. Common case
4332
*/
4333
template<class T>
4334
struct is_assign_t : public std::false_type {};
4335
4336
/**
4337
* Assign operator traits. Specialized case
4338
*/
4339
template<class L, class R>
4340
struct is_assign_t<assign_t<L, R>> : public std::true_type {};
4341
}
4342
4343
/**
4344
* Public interface for || concatenation operator. Example: `select(conc(&User::name, "@gmail.com"));` => SELECT
4345
* name || '@gmail.com' FROM users
4346
*/
4347
template<class L, class R>
4348
constexpr internal::conc_t<L, R> conc(L l, R r) {
4349
return {std::move(l), std::move(r)};
4350
}
4351
4352
template<class T>
4353
constexpr internal::unary_minus_t<T> minus(T t) {
4354
return {std::move(t)};
4355
}
4356
4357
/**
4358
* Public interface for + operator. Example: `select(add(&User::age, 100));` => SELECT age + 100 FROM users
4359
*/
4360
template<class L, class R>
4361
constexpr internal::add_t<L, R> add(L l, R r) {
4362
return {std::move(l), std::move(r)};
4363
}
4364
4365
/**
4366
* Public interface for - operator. Example: `select(sub(&User::age, 1));` => SELECT age - 1 FROM users
4367
*/
4368
template<class L, class R>
4369
constexpr internal::sub_t<L, R> sub(L l, R r) {
4370
return {std::move(l), std::move(r)};
4371
}
4372
4373
/**
4374
* Public interface for * operator. Example: `select(mul(&User::salary, 2));` => SELECT salary * 2 FROM users
4375
*/
4376
template<class L, class R>
4377
constexpr internal::mul_t<L, R> mul(L l, R r) {
4378
return {std::move(l), std::move(r)};
4379
}
4380
4381
/**
4382
* Public interface for / operator. Example: `select(div(&User::salary, 3));` => SELECT salary / 3 FROM users
4383
* @note Please notice that ::div function already exists in pure C standard library inside <cstdlib> header.
4384
* If you use `using namespace sqlite_orm` directive you an specify which `div` you call explicitly using `::div` or `sqlite_orm::div` statements.
4385
*/
4386
template<class L, class R>
4387
constexpr internal::div_t<L, R> div(L l, R r) {
4388
return {std::move(l), std::move(r)};
4389
}
4390
4391
/**
4392
* Public interface for % operator. Example: `select(mod(&User::age, 5));` => SELECT age % 5 FROM users
4393
*/
4394
template<class L, class R>
4395
constexpr internal::mod_t<L, R> mod(L l, R r) {
4396
return {std::move(l), std::move(r)};
4397
}
4398
4399
template<class L, class R>
4400
constexpr internal::bitwise_shift_left_t<L, R> bitwise_shift_left(L l, R r) {
4401
return {std::move(l), std::move(r)};
4402
}
4403
4404
template<class L, class R>
4405
constexpr internal::bitwise_shift_right_t<L, R> bitwise_shift_right(L l, R r) {
4406
return {std::move(l), std::move(r)};
4407
}
4408
4409
template<class L, class R>
4410
constexpr internal::bitwise_and_t<L, R> bitwise_and(L l, R r) {
4411
return {std::move(l), std::move(r)};
4412
}
4413
4414
template<class L, class R>
4415
constexpr internal::bitwise_or_t<L, R> bitwise_or(L l, R r) {
4416
return {std::move(l), std::move(r)};
4417
}
4418
4419
template<class T>
4420
constexpr internal::bitwise_not_t<T> bitwise_not(T t) {
4421
return {std::move(t)};
4422
}
4423
4424
template<class L, class R>
4425
internal::assign_t<L, R> assign(L l, R r) {
4426
return {std::move(l), std::move(r)};
4427
}
4428
}
4429
4430
// #include "select_constraints.h"
4431
4432
#ifdef SQLITE_ORM_WITH_CPP20_ALIASES
4433
#include <concepts>
4434
#endif
4435
#include <type_traits> // std::enable_if, std::remove_cvref, std::is_convertible, std::is_same, std::is_member_pointer
4436
#include <string> // std::string
4437
#include <utility> // std::move
4438
#include <tuple> // std::tuple, std::get, std::tuple_size
4439
// #include "functional/cxx_optional.h"
4440
4441
// #include "functional/cxx_type_traits_polyfill.h"
4442
4443
// #include "is_base_of_template.h"
4444
4445
// #include "tuple_helper/tuple_traits.h"
4446
4447
// #include "tuple_helper/tuple_transformer.h"
4448
4449
// #include "tuple_helper/tuple_iteration.h"
4450
4451
// #include "optional_container.h"
4452
4453
namespace sqlite_orm {
4454
4455
namespace internal {
4456
4457
/**
4458
* This is a cute class which allows storing something or nothing
4459
* depending on template argument. Useful for optional class members
4460
*/
4461
template<class T>
4462
struct optional_container {
4463
using type = T;
4464
4465
type field;
4466
4467
template<class L>
4468
void apply(const L& l) const {
4469
l(this->field);
4470
}
4471
};
4472
4473
template<>
4474
struct optional_container<void> {
4475
using type = void;
4476
4477
template<class L>
4478
void apply(const L&) const {
4479
//..
4480
}
4481
};
4482
}
4483
}
4484
4485
// #include "ast/where.h"
4486
4487
#include <type_traits> // std::false_type, std::true_type
4488
#include <utility> // std::move
4489
4490
// #include "../functional/cxx_type_traits_polyfill.h"
4491
4492
// #include "../serialize_result_type.h"
4493
4494
namespace sqlite_orm {
4495
namespace internal {
4496
4497
struct where_string {
4498
serialize_result_type serialize() const {
4499
return "WHERE";
4500
}
4501
};
4502
4503
/**
4504
* WHERE argument holder.
4505
* C is expression type. Can be any expression like: is_equal_t, is_null_t, exists_t etc
4506
* Don't construct it manually. Call `where(...)` function instead.
4507
*/
4508
template<class C>
4509
struct where_t : where_string {
4510
using expression_type = C;
4511
4512
expression_type expression;
4513
4514
constexpr where_t(expression_type expression_) : expression(std::move(expression_)) {}
4515
};
4516
4517
template<class T>
4518
SQLITE_ORM_INLINE_VAR constexpr bool is_where_v = polyfill::is_specialization_of<T, where_t>::value;
4519
4520
template<class T>
4521
struct is_where : polyfill::bool_constant<is_where_v<T>> {};
4522
}
4523
4524
/**
4525
* WHERE clause. Use it to add WHERE conditions wherever you like.
4526
* C is expression type. Can be any expression like: is_equal_t, is_null_t, exists_t etc
4527
* @example
4528
* // SELECT name
4529
* // FROM letters
4530
* // WHERE id > 3
4531
* auto rows = storage.select(&Letter::name, where(greater_than(&Letter::id, 3)));
4532
*/
4533
template<class C>
4534
constexpr internal::where_t<C> where(C expression) {
4535
return {std::move(expression)};
4536
}
4537
}
4538
4539
// #include "ast/group_by.h"
4540
4541
#include <tuple> // std::tuple, std::make_tuple
4542
#include <type_traits> // std::true_type, std::false_type
4543
#include <utility> // std::forward, std::move
4544
4545
// #include "../functional/cxx_type_traits_polyfill.h"
4546
4547
namespace sqlite_orm {
4548
namespace internal {
4549
4550
template<class T, class... Args>
4551
struct group_by_with_having {
4552
using args_type = std::tuple<Args...>;
4553
using expression_type = T;
4554
4555
args_type args;
4556
expression_type expression;
4557
};
4558
4559
/**
4560
* GROUP BY pack holder.
4561
*/
4562
template<class... Args>
4563
struct group_by_t {
4564
using args_type = std::tuple<Args...>;
4565
4566
args_type args;
4567
4568
template<class T>
4569
group_by_with_having<T, Args...> having(T expression) {
4570
return {std::move(this->args), std::move(expression)};
4571
}
4572
};
4573
4574
template<class T>
4575
using is_group_by = polyfill::disjunction<polyfill::is_specialization_of<T, group_by_t>,
4576
polyfill::is_specialization_of<T, group_by_with_having>>;
4577
}
4578
4579
/**
4580
* GROUP BY column.
4581
* Example: storage.get_all<Employee>(group_by(&Employee::name))
4582
*/
4583
template<class... Args>
4584
internal::group_by_t<Args...> group_by(Args... args) {
4585
return {{std::forward<Args>(args)...}};
4586
}
4587
}
4588
4589
// #include "core_functions.h"
4590
4591
#include <string> // std::string
4592
#include <tuple> // std::make_tuple, std::tuple_size
4593
#include <type_traits> // std::forward, std::is_base_of, std::enable_if
4594
#include <memory> // std::unique_ptr
4595
#include <vector> // std::vector
4596
4597
// #include "functional/cxx_type_traits_polyfill.h"
4598
4599
// #include "functional/mpl/conditional.h"
4600
4601
// #include "is_base_of_template.h"
4602
4603
// #include "tuple_helper/tuple_traits.h"
4604
4605
// #include "conditions.h"
4606
4607
#include <string> // std::string
4608
#include <type_traits> // std::enable_if, std::is_same, std::remove_const
4609
#include <vector> // std::vector
4610
#include <tuple> // std::tuple
4611
#include <utility> // std::move, std::forward
4612
#include <sstream> // std::stringstream
4613
#include <iomanip> // std::flush
4614
4615
// #include "functional/cxx_type_traits_polyfill.h"
4616
4617
// #include "is_base_of_template.h"
4618
4619
// #include "type_traits.h"
4620
4621
// #include "collate_argument.h"
4622
4623
// #include "constraints.h"
4624
4625
// #include "optional_container.h"
4626
4627
// #include "serializer_context.h"
4628
4629
namespace sqlite_orm {
4630
4631
namespace internal {
4632
4633
struct serializer_context_base {
4634
bool replace_bindable_with_question = false;
4635
bool skip_table_name = true;
4636
bool use_parentheses = true;
4637
bool fts5_columns = false;
4638
};
4639
4640
template<class DBOs>
4641
struct serializer_context : serializer_context_base {
4642
using db_objects_type = DBOs;
4643
4644
const db_objects_type& db_objects;
4645
4646
serializer_context(const db_objects_type& dbObjects) : db_objects{dbObjects} {}
4647
};
4648
4649
template<class S>
4650
struct serializer_context_builder {
4651
using storage_type = S;
4652
using db_objects_type = typename storage_type::db_objects_type;
4653
4654
serializer_context_builder(const storage_type& storage_) : storage{storage_} {}
4655
4656
serializer_context<db_objects_type> operator()() const {
4657
return {obtain_db_objects(this->storage)};
4658
}
4659
4660
const storage_type& storage;
4661
};
4662
}
4663
4664
}
4665
4666
// #include "serialize_result_type.h"
4667
4668
// #include "tags.h"
4669
4670
// #include "table_reference.h"
4671
4672
// #include "alias_traits.h"
4673
4674
// #include "expression.h"
4675
4676
#include <tuple>
4677
#include <type_traits> // std::enable_if
4678
#include <utility> // std::move, std::forward, std::declval
4679
// #include "functional/cxx_optional.h"
4680
4681
// #include "functional/cxx_type_traits_polyfill.h"
4682
4683
// #include "tags.h"
4684
4685
// #include "operators.h"
4686
4687
namespace sqlite_orm {
4688
4689
namespace internal {
4690
4691
template<class L, class... Args>
4692
struct in_t;
4693
4694
template<class L, class R>
4695
struct and_condition_t;
4696
4697
template<class L, class R>
4698
struct or_condition_t;
4699
4700
/**
4701
* Result of c(...) function. Has operator= overloaded which returns assign_t
4702
*/
4703
template<class T>
4704
struct expression_t {
4705
T value;
4706
4707
template<class R>
4708
assign_t<T, R> operator=(R r) const {
4709
return {this->value, std::move(r)};
4710
}
4711
4712
assign_t<T, nullptr_t> operator=(nullptr_t) const {
4713
return {this->value, nullptr};
4714
}
4715
#ifdef SQLITE_ORM_OPTIONAL_SUPPORTED
4716
assign_t<T, std::nullopt_t> operator=(std::nullopt_t) const {
4717
return {this->value, std::nullopt};
4718
}
4719
#endif
4720
template<class... Args>
4721
in_t<T, Args...> in(Args... args) const {
4722
return {this->value, {std::forward<Args>(args)...}, false};
4723
}
4724
4725
template<class... Args>
4726
in_t<T, Args...> not_in(Args... args) const {
4727
return {this->value, {std::forward<Args>(args)...}, true};
4728
}
4729
4730
template<class R>
4731
and_condition_t<T, R> and_(R right) const {
4732
return {this->value, std::move(right)};
4733
}
4734
4735
template<class R>
4736
or_condition_t<T, R> or_(R right) const {
4737
return {this->value, std::move(right)};
4738
}
4739
};
4740
4741
template<class T>
4742
SQLITE_ORM_INLINE_VAR constexpr bool
4743
is_operator_argument_v<T, std::enable_if_t<polyfill::is_specialization_of<T, expression_t>::value>> = true;
4744
4745
template<class T>
4746
constexpr T get_from_expression(T&& value) {
4747
return std::move(value);
4748
}
4749
4750
template<class T>
4751
constexpr const T& get_from_expression(const T& value) {
4752
return value;
4753
}
4754
4755
template<class T>
4756
constexpr T get_from_expression(expression_t<T>&& expression) {
4757
return std::move(expression.value);
4758
}
4759
4760
template<class T>
4761
constexpr const T& get_from_expression(const expression_t<T>& expression) {
4762
return expression.value;
4763
}
4764
4765
template<class T>
4766
using unwrap_expression_t = decltype(get_from_expression(std::declval<T>()));
4767
}
4768
4769
/**
4770
* Public interface for syntax sugar for columns. Example: `where(c(&User::id) == 5)` or
4771
* `storage.update(set(c(&User::name) = "Dua Lipa"));
4772
*/
4773
template<class T>
4774
constexpr internal::expression_t<T> c(T value) {
4775
return {std::move(value)};
4776
}
4777
}
4778
4779
// #include "column_pointer.h"
4780
4781
// #include "tags.h"
4782
4783
// #include "type_printer.h"
4784
4785
// #include "literal.h"
4786
4787
namespace sqlite_orm {
4788
namespace internal {
4789
4790
/*
4791
* Protect an otherwise bindable element so that it is always serialized as a literal value.
4792
*/
4793
template<class T>
4794
struct literal_holder {
4795
using type = T;
4796
4797
type value;
4798
};
4799
4800
}
4801
}
4802
4803
namespace sqlite_orm {
4804
4805
namespace internal {
4806
4807
struct limit_string {
4808
operator std::string() const {
4809
return "LIMIT";
4810
}
4811
};
4812
4813
/**
4814
* Stores LIMIT/OFFSET info
4815
*/
4816
template<class T, bool has_offset, bool offset_is_implicit, class O>
4817
struct limit_t : limit_string {
4818
T lim;
4819
optional_container<O> off;
4820
4821
limit_t() = default;
4822
4823
limit_t(decltype(lim) lim_) : lim(std::move(lim_)) {}
4824
4825
limit_t(decltype(lim) lim_, decltype(off) off_) : lim(std::move(lim_)), off(std::move(off_)) {}
4826
};
4827
4828
template<class T>
4829
struct is_limit : std::false_type {};
4830
4831
template<class T, bool has_offset, bool offset_is_implicit, class O>
4832
struct is_limit<limit_t<T, has_offset, offset_is_implicit, O>> : std::true_type {};
4833
4834
/**
4835
* Stores OFFSET only info
4836
*/
4837
template<class T>
4838
struct offset_t {
4839
T off;
4840
};
4841
4842
template<class T>
4843
using is_offset = polyfill::is_specialization_of<T, offset_t>;
4844
4845
/**
4846
* Collated something
4847
*/
4848
template<class T>
4849
struct collate_t : public condition_t {
4850
T expr;
4851
collate_argument argument;
4852
4853
collate_t(T expr_, collate_argument argument_) : expr(std::move(expr_)), argument(argument_) {}
4854
4855
operator std::string() const {
4856
return collate_constraint_t{this->argument};
4857
}
4858
};
4859
4860
struct named_collate_base {
4861
std::string name;
4862
4863
operator std::string() const {
4864
return "COLLATE " + this->name;
4865
}
4866
};
4867
4868
/**
4869
* Collated something with custom collate function
4870
*/
4871
template<class T>
4872
struct named_collate : named_collate_base {
4873
T expr;
4874
4875
named_collate(T expr_, std::string name_) : named_collate_base{std::move(name_)}, expr(std::move(expr_)) {}
4876
};
4877
4878
struct negated_condition_string {
4879
operator std::string() const {
4880
return "NOT";
4881
}
4882
};
4883
4884
/**
4885
* Result of not operator
4886
*/
4887
template<class C>
4888
struct negated_condition_t : condition_t, negated_condition_string {
4889
using argument_type = C;
4890
4891
argument_type c;
4892
4893
constexpr negated_condition_t(argument_type arg) : c(std::move(arg)) {}
4894
};
4895
4896
/**
4897
* Base class for binary conditions
4898
* L is left argument type
4899
* R is right argument type
4900
* S is 'string' class (a class which has cast to `std::string` operator)
4901
* Res is result type
4902
*/
4903
template<class L, class R, class S, class Res>
4904
struct binary_condition : condition_t, S {
4905
using left_type = L;
4906
using right_type = R;
4907
using result_type = Res;
4908
4909
left_type lhs;
4910
right_type rhs;
4911
4912
constexpr binary_condition() = default;
4913
4914
constexpr binary_condition(left_type l_, right_type r_) : lhs(std::move(l_)), rhs(std::move(r_)) {}
4915
};
4916
4917
template<class T>
4918
SQLITE_ORM_INLINE_VAR constexpr bool is_binary_condition_v = is_base_of_template_v<T, binary_condition>;
4919
4920
template<class T>
4921
struct is_binary_condition : polyfill::bool_constant<is_binary_condition_v<T>> {};
4922
4923
struct and_condition_string {
4924
serialize_result_type serialize() const {
4925
return "AND";
4926
}
4927
};
4928
4929
/**
4930
* Result of and operator
4931
*/
4932
template<class L, class R>
4933
struct and_condition_t : binary_condition<L, R, and_condition_string, bool>, negatable_t {
4934
using super = binary_condition<L, R, and_condition_string, bool>;
4935
4936
using super::super;
4937
};
4938
4939
struct or_condition_string {
4940
serialize_result_type serialize() const {
4941
return "OR";
4942
}
4943
};
4944
4945
/**
4946
* Result of or operator
4947
*/
4948
template<class L, class R>
4949
struct or_condition_t : binary_condition<L, R, or_condition_string, bool>, negatable_t {
4950
using super = binary_condition<L, R, or_condition_string, bool>;
4951
4952
using super::super;
4953
};
4954
4955
struct is_equal_string {
4956
serialize_result_type serialize() const {
4957
return "=";
4958
}
4959
};
4960
4961
/**
4962
* = and == operators object
4963
*/
4964
template<class L, class R>
4965
struct is_equal_t : binary_condition<L, R, is_equal_string, bool>, negatable_t {
4966
using self = is_equal_t<L, R>;
4967
4968
using binary_condition<L, R, is_equal_string, bool>::binary_condition;
4969
4970
collate_t<self> collate_binary() const {
4971
return {*this, collate_argument::binary};
4972
}
4973
4974
collate_t<self> collate_nocase() const {
4975
return {*this, collate_argument::nocase};
4976
}
4977
4978
collate_t<self> collate_rtrim() const {
4979
return {*this, collate_argument::rtrim};
4980
}
4981
4982
named_collate<self> collate(std::string name) const {
4983
return {*this, std::move(name)};
4984
}
4985
4986
template<class C>
4987
named_collate<self> collate() const {
4988
std::stringstream ss;
4989
ss << C::name() << std::flush;
4990
return {*this, ss.str()};
4991
}
4992
};
4993
4994
template<class L, class R>
4995
struct is_equal_with_table_t : negatable_t {
4996
using left_type = L;
4997
using right_type = R;
4998
4999
right_type rhs;
5000
5001
is_equal_with_table_t(right_type rhs) : rhs(std::move(rhs)) {}
5002
};
5003
5004
struct is_not_equal_string {
5005
serialize_result_type serialize() const {
5006
return "!=";
5007
}
5008
};
5009
5010
/**
5011
* != operator object
5012
*/
5013
template<class L, class R>
5014
struct is_not_equal_t : binary_condition<L, R, is_not_equal_string, bool>, negatable_t {
5015
using self = is_not_equal_t<L, R>;
5016
5017
using binary_condition<L, R, is_not_equal_string, bool>::binary_condition;
5018
5019
collate_t<self> collate_binary() const {
5020
return {*this, collate_argument::binary};
5021
}
5022
5023
collate_t<self> collate_nocase() const {
5024
return {*this, collate_argument::nocase};
5025
}
5026
5027
collate_t<self> collate_rtrim() const {
5028
return {*this, collate_argument::rtrim};
5029
}
5030
};
5031
5032
struct greater_than_string {
5033
serialize_result_type serialize() const {
5034
return ">";
5035
}
5036
};
5037
5038
/**
5039
* > operator object.
5040
*/
5041
template<class L, class R>
5042
struct greater_than_t : binary_condition<L, R, greater_than_string, bool>, negatable_t {
5043
using self = greater_than_t<L, R>;
5044
5045
using binary_condition<L, R, greater_than_string, bool>::binary_condition;
5046
5047
collate_t<self> collate_binary() const {
5048
return {*this, collate_argument::binary};
5049
}
5050
5051
collate_t<self> collate_nocase() const {
5052
return {*this, collate_argument::nocase};
5053
}
5054
5055
collate_t<self> collate_rtrim() const {
5056
return {*this, collate_argument::rtrim};
5057
}
5058
};
5059
5060
struct greater_or_equal_string {
5061
serialize_result_type serialize() const {
5062
return ">=";
5063
}
5064
};
5065
5066
/**
5067
* >= operator object.
5068
*/
5069
template<class L, class R>
5070
struct greater_or_equal_t : binary_condition<L, R, greater_or_equal_string, bool>, negatable_t {
5071
using self = greater_or_equal_t<L, R>;
5072
5073
using binary_condition<L, R, greater_or_equal_string, bool>::binary_condition;
5074
5075
collate_t<self> collate_binary() const {
5076
return {*this, collate_argument::binary};
5077
}
5078
5079
collate_t<self> collate_nocase() const {
5080
return {*this, collate_argument::nocase};
5081
}
5082
5083
collate_t<self> collate_rtrim() const {
5084
return {*this, collate_argument::rtrim};
5085
}
5086
};
5087
5088
struct less_than_string {
5089
serialize_result_type serialize() const {
5090
return "<";
5091
}
5092
};
5093
5094
/**
5095
* < operator object.
5096
*/
5097
template<class L, class R>
5098
struct less_than_t : binary_condition<L, R, less_than_string, bool>, negatable_t {
5099
using self = less_than_t<L, R>;
5100
5101
using binary_condition<L, R, less_than_string, bool>::binary_condition;
5102
5103
collate_t<self> collate_binary() const {
5104
return {*this, collate_argument::binary};
5105
}
5106
5107
collate_t<self> collate_nocase() const {
5108
return {*this, collate_argument::nocase};
5109
}
5110
5111
collate_t<self> collate_rtrim() const {
5112
return {*this, collate_argument::rtrim};
5113
}
5114
};
5115
5116
struct less_or_equal_string {
5117
serialize_result_type serialize() const {
5118
return "<=";
5119
}
5120
};
5121
5122
/**
5123
* <= operator object.
5124
*/
5125
template<class L, class R>
5126
struct less_or_equal_t : binary_condition<L, R, less_or_equal_string, bool>, negatable_t {
5127
using self = less_or_equal_t<L, R>;
5128
5129
using binary_condition<L, R, less_or_equal_string, bool>::binary_condition;
5130
5131
collate_t<self> collate_binary() const {
5132
return {*this, collate_argument::binary};
5133
}
5134
5135
collate_t<self> collate_nocase() const {
5136
return {*this, collate_argument::nocase};
5137
}
5138
5139
collate_t<self> collate_rtrim() const {
5140
return {*this, collate_argument::rtrim};
5141
}
5142
};
5143
5144
struct in_base {
5145
bool negative = false; // used in not_in
5146
5147
#ifndef SQLITE_ORM_AGGREGATE_NSDMI_SUPPORTED
5148
in_base(bool negative) : negative{negative} {}
5149
#endif
5150
};
5151
5152
/**
5153
* IN operator object.
5154
*/
5155
template<class L, class A>
5156
struct dynamic_in_t : condition_t, in_base, negatable_t {
5157
using self = dynamic_in_t<L, A>;
5158
5159
L left; // left expression
5160
A argument; // in arg
5161
5162
dynamic_in_t(L left_, A argument_, bool negative_) :
5163
in_base{negative_}, left(std::move(left_)), argument(std::move(argument_)) {}
5164
};
5165
5166
template<class L, class... Args>
5167
struct in_t : condition_t, in_base, negatable_t {
5168
L left;
5169
std::tuple<Args...> argument;
5170
5171
in_t(L left_, decltype(argument) argument_, bool negative_) :
5172
in_base{negative_}, left(std::move(left_)), argument(std::move(argument_)) {}
5173
};
5174
5175
struct is_null_string {
5176
operator std::string() const {
5177
return "IS NULL";
5178
}
5179
};
5180
5181
/**
5182
* IS NULL operator object.
5183
*/
5184
template<class T>
5185
struct is_null_t : is_null_string, negatable_t {
5186
using self = is_null_t<T>;
5187
5188
T t;
5189
5190
is_null_t(T t_) : t(std::move(t_)) {}
5191
};
5192
5193
struct is_not_null_string {
5194
operator std::string() const {
5195
return "IS NOT NULL";
5196
}
5197
};
5198
5199
/**
5200
* IS NOT NULL operator object.
5201
*/
5202
template<class T>
5203
struct is_not_null_t : is_not_null_string, negatable_t {
5204
using self = is_not_null_t<T>;
5205
5206
T t;
5207
5208
is_not_null_t(T t_) : t(std::move(t_)) {}
5209
};
5210
5211
struct order_by_base {
5212
int asc_desc = 0; // 1: asc, -1: desc
5213
std::string _collate_argument;
5214
5215
#ifndef SQLITE_ORM_AGGREGATE_NSDMI_SUPPORTED
5216
order_by_base() = default;
5217
5218
order_by_base(decltype(asc_desc) asc_desc_, decltype(_collate_argument) _collate_argument_) :
5219
asc_desc(asc_desc_), _collate_argument(std::move(_collate_argument_)) {}
5220
#endif
5221
};
5222
5223
struct order_by_string {
5224
operator std::string() const {
5225
return "ORDER BY";
5226
}
5227
};
5228
5229
/**
5230
* ORDER BY argument holder.
5231
*/
5232
template<class O>
5233
struct order_by_t : order_by_base, order_by_string {
5234
using expression_type = O;
5235
using self = order_by_t<expression_type>;
5236
5237
expression_type expression;
5238
5239
order_by_t(expression_type expression_) : order_by_base(), expression(std::move(expression_)) {}
5240
5241
self asc() const {
5242
auto res = *this;
5243
res.asc_desc = 1;
5244
return res;
5245
}
5246
5247
self desc() const {
5248
auto res = *this;
5249
res.asc_desc = -1;
5250
return res;
5251
}
5252
5253
self collate_binary() const {
5254
auto res = *this;
5255
res._collate_argument = collate_constraint_t::string_from_collate_argument(collate_argument::binary);
5256
return res;
5257
}
5258
5259
self collate_nocase() const {
5260
auto res = *this;
5261
res._collate_argument = collate_constraint_t::string_from_collate_argument(collate_argument::nocase);
5262
return res;
5263
}
5264
5265
self collate_rtrim() const {
5266
auto res = *this;
5267
res._collate_argument = collate_constraint_t::string_from_collate_argument(collate_argument::rtrim);
5268
return res;
5269
}
5270
5271
self collate(std::string name) const {
5272
auto res = *this;
5273
res._collate_argument = std::move(name);
5274
return res;
5275
}
5276
5277
template<class C>
5278
self collate() const {
5279
std::stringstream ss;
5280
ss << C::name() << std::flush;
5281
return this->collate(ss.str());
5282
}
5283
};
5284
5285
/**
5286
* ORDER BY pack holder.
5287
*/
5288
template<class... Args>
5289
struct multi_order_by_t : order_by_string {
5290
using args_type = std::tuple<Args...>;
5291
5292
args_type args;
5293
5294
multi_order_by_t(args_type args_) : args{std::move(args_)} {}
5295
};
5296
5297
struct dynamic_order_by_entry_t : order_by_base {
5298
std::string name;
5299
5300
dynamic_order_by_entry_t(decltype(name) name_, int asc_desc_, std::string collate_argument_) :
5301
order_by_base{asc_desc_, std::move(collate_argument_)}, name(std::move(name_)) {}
5302
};
5303
5304
/**
5305
* C - serializer context class
5306
*/
5307
template<class C>
5308
struct dynamic_order_by_t : order_by_string {
5309
using context_t = C;
5310
using entry_t = dynamic_order_by_entry_t;
5311
using const_iterator = typename std::vector<entry_t>::const_iterator;
5312
5313
dynamic_order_by_t(const context_t& context_) : context(context_) {}
5314
5315
template<class O>
5316
void push_back(order_by_t<O> order_by) {
5317
auto newContext = this->context;
5318
newContext.skip_table_name = false;
5319
auto columnName = serialize(order_by.expression, newContext);
5320
this->entries.emplace_back(std::move(columnName),
5321
order_by.asc_desc,
5322
std::move(order_by._collate_argument));
5323
}
5324
5325
const_iterator begin() const {
5326
return this->entries.begin();
5327
}
5328
5329
const_iterator end() const {
5330
return this->entries.end();
5331
}
5332
5333
void clear() {
5334
this->entries.clear();
5335
}
5336
5337
protected:
5338
std::vector<entry_t> entries;
5339
context_t context;
5340
};
5341
5342
template<class T>
5343
SQLITE_ORM_INLINE_VAR constexpr bool is_order_by_v =
5344
polyfill::disjunction<polyfill::is_specialization_of<T, order_by_t>,
5345
polyfill::is_specialization_of<T, multi_order_by_t>,
5346
polyfill::is_specialization_of<T, dynamic_order_by_t>>::value;
5347
5348
template<class T>
5349
struct is_order_by : polyfill::bool_constant<is_order_by_v<T>> {};
5350
5351
struct between_string {
5352
operator std::string() const {
5353
return "BETWEEN";
5354
}
5355
};
5356
5357
/**
5358
* BETWEEN operator object.
5359
*/
5360
template<class A, class T>
5361
struct between_t : condition_t, between_string {
5362
using expression_type = A;
5363
using lower_type = T;
5364
using upper_type = T;
5365
5366
expression_type expr;
5367
lower_type b1;
5368
upper_type b2;
5369
5370
between_t(expression_type expr_, lower_type b1_, upper_type b2_) :
5371
expr(std::move(expr_)), b1(std::move(b1_)), b2(std::move(b2_)) {}
5372
};
5373
5374
struct like_string {
5375
operator std::string() const {
5376
return "LIKE";
5377
}
5378
};
5379
5380
/**
5381
* LIKE operator object.
5382
*/
5383
template<class A, class T, class E>
5384
struct like_t : condition_t, like_string, negatable_t {
5385
using self = like_t<A, T, E>;
5386
using arg_t = A;
5387
using pattern_t = T;
5388
using escape_t = E;
5389
5390
arg_t arg;
5391
pattern_t pattern;
5392
optional_container<escape_t> arg3; // not escape cause escape exists as a function here
5393
5394
like_t(arg_t arg_, pattern_t pattern_, optional_container<escape_t> escape_) :
5395
arg(std::move(arg_)), pattern(std::move(pattern_)), arg3(std::move(escape_)) {}
5396
5397
template<class C>
5398
like_t<A, T, C> escape(C c) const {
5399
optional_container<C> newArg3{std::move(c)};
5400
return {std::move(this->arg), std::move(this->pattern), std::move(newArg3)};
5401
}
5402
};
5403
5404
struct glob_string {
5405
operator std::string() const {
5406
return "GLOB";
5407
}
5408
};
5409
5410
template<class A, class T>
5411
struct glob_t : condition_t, glob_string, negatable_t {
5412
using self = glob_t<A, T>;
5413
using arg_t = A;
5414
using pattern_t = T;
5415
5416
arg_t arg;
5417
pattern_t pattern;
5418
5419
glob_t(arg_t arg_, pattern_t pattern_) : arg(std::move(arg_)), pattern(std::move(pattern_)) {}
5420
};
5421
5422
struct cross_join_string {
5423
operator std::string() const {
5424
return "CROSS JOIN";
5425
}
5426
};
5427
5428
/**
5429
* CROSS JOIN holder.
5430
* T is joined type which represents any mapped table.
5431
*/
5432
template<class T>
5433
struct cross_join_t : cross_join_string {
5434
using type = T;
5435
};
5436
5437
struct natural_join_string {
5438
operator std::string() const {
5439
return "NATURAL JOIN";
5440
}
5441
};
5442
5443
/**
5444
* NATURAL JOIN holder.
5445
* T is joined type which represents any mapped table.
5446
*/
5447
template<class T>
5448
struct natural_join_t : natural_join_string {
5449
using type = T;
5450
};
5451
5452
struct left_join_string {
5453
operator std::string() const {
5454
return "LEFT JOIN";
5455
}
5456
};
5457
5458
/**
5459
* LEFT JOIN holder.
5460
* T is joined type which represents any mapped table.
5461
* O is on(...) argument type.
5462
*/
5463
template<class T, class O>
5464
struct left_join_t : left_join_string {
5465
using type = T;
5466
using on_type = O;
5467
5468
on_type constraint;
5469
5470
left_join_t(on_type constraint_) : constraint(std::move(constraint_)) {}
5471
};
5472
5473
struct join_string {
5474
operator std::string() const {
5475
return "JOIN";
5476
}
5477
};
5478
5479
/**
5480
* Simple JOIN holder.
5481
* T is joined type which represents any mapped table.
5482
* O is on(...) argument type.
5483
*/
5484
template<class T, class O>
5485
struct join_t : join_string {
5486
using type = T;
5487
using on_type = O;
5488
5489
on_type constraint;
5490
5491
join_t(on_type constraint_) : constraint(std::move(constraint_)) {}
5492
};
5493
5494
struct left_outer_join_string {
5495
operator std::string() const {
5496
return "LEFT OUTER JOIN";
5497
}
5498
};
5499
5500
/**
5501
* LEFT OUTER JOIN holder.
5502
* T is joined type which represents any mapped table.
5503
* O is on(...) argument type.
5504
*/
5505
template<class T, class O>
5506
struct left_outer_join_t : left_outer_join_string {
5507
using type = T;
5508
using on_type = O;
5509
5510
on_type constraint;
5511
5512
left_outer_join_t(on_type constraint_) : constraint(std::move(constraint_)) {}
5513
};
5514
5515
struct on_string {
5516
operator std::string() const {
5517
return "ON";
5518
}
5519
};
5520
5521
/**
5522
* on(...) argument holder used for JOIN, LEFT JOIN, LEFT OUTER JOIN and INNER JOIN
5523
* T is on type argument.
5524
*/
5525
template<class T>
5526
struct on_t : on_string {
5527
using arg_type = T;
5528
5529
arg_type arg;
5530
5531
on_t(arg_type arg_) : arg(std::move(arg_)) {}
5532
};
5533
5534
/**
5535
* USING argument holder.
5536
*/
5537
template<class T, class M>
5538
struct using_t {
5539
column_pointer<T, M> column;
5540
5541
operator std::string() const {
5542
return "USING";
5543
}
5544
};
5545
5546
struct inner_join_string {
5547
operator std::string() const {
5548
return "INNER JOIN";
5549
}
5550
};
5551
5552
/**
5553
* INNER JOIN holder.
5554
* T is joined type which represents any mapped table.
5555
* O is on(...) argument type.
5556
*/
5557
template<class T, class O>
5558
struct inner_join_t : inner_join_string {
5559
using type = T;
5560
using on_type = O;
5561
5562
on_type constraint;
5563
5564
inner_join_t(on_type constraint_) : constraint(std::move(constraint_)) {}
5565
};
5566
5567
struct cast_string {
5568
operator std::string() const {
5569
return "CAST";
5570
}
5571
};
5572
5573
/**
5574
* CAST holder.
5575
* T is a type to cast to
5576
* E is an expression type
5577
* Example: cast<std::string>(&User::id)
5578
*/
5579
template<class T, class E>
5580
struct cast_t : cast_string {
5581
using to_type = T;
5582
using expression_type = E;
5583
5584
expression_type expression;
5585
5586
cast_t(expression_type expression_) : expression(std::move(expression_)) {}
5587
};
5588
5589
template<class... Args>
5590
struct from_t {
5591
using tuple_type = std::tuple<Args...>;
5592
};
5593
5594
template<class T>
5595
using is_from = polyfill::is_specialization_of<T, from_t>;
5596
5597
template<class T>
5598
using is_constrained_join = polyfill::is_detected<on_type_t, T>;
5599
}
5600
5601
/**
5602
* Explicit FROM function. Usage:
5603
* `storage.select(&User::id, from<User>());`
5604
*/
5605
template<class... Tables>
5606
internal::from_t<Tables...> from() {
5607
static_assert(sizeof...(Tables) > 0, "");
5608
return {};
5609
}
5610
5611
#ifdef SQLITE_ORM_WITH_CPP20_ALIASES
5612
/**
5613
* Explicit FROM function. Usage:
5614
* `storage.select(&User::id, from<"a"_alias.for_<User>>());`
5615
*/
5616
template<orm_refers_to_recordset auto... recordsets>
5617
auto from() {
5618
return from<internal::auto_decay_table_ref_t<recordsets>...>();
5619
}
5620
#endif
5621
5622
// Intentionally place operators for types classified as arithmetic or general operator arguments in the internal namespace
5623
// to facilitate ADL (Argument Dependent Lookup)
5624
namespace internal {
5625
template<
5626
class T,
5627
std::enable_if_t<polyfill::disjunction<std::is_base_of<negatable_t, T>, is_operator_argument<T>>::value,
5628
bool> = true>
5629
constexpr negated_condition_t<T> operator!(T arg) {
5630
return {std::move(arg)};
5631
}
5632
5633
template<class L,
5634
class R,
5635
std::enable_if_t<polyfill::disjunction<std::is_base_of<arithmetic_t, L>,
5636
std::is_base_of<arithmetic_t, R>,
5637
is_operator_argument<L>,
5638
is_operator_argument<R>>::value,
5639
bool> = true>
5640
constexpr less_than_t<unwrap_expression_t<L>, unwrap_expression_t<R>> operator<(L l, R r) {
5641
return {get_from_expression(std::forward<L>(l)), get_from_expression(std::forward<R>(r))};
5642
}
5643
5644
template<class L,
5645
class R,
5646
std::enable_if_t<polyfill::disjunction<std::is_base_of<arithmetic_t, L>,
5647
std::is_base_of<arithmetic_t, R>,
5648
is_operator_argument<L>,
5649
is_operator_argument<R>>::value,
5650
bool> = true>
5651
constexpr less_or_equal_t<unwrap_expression_t<L>, unwrap_expression_t<R>> operator<=(L l, R r) {
5652
return {get_from_expression(std::forward<L>(l)), get_from_expression(std::forward<R>(r))};
5653
}
5654
5655
template<class L,
5656
class R,
5657
std::enable_if_t<polyfill::disjunction<std::is_base_of<arithmetic_t, L>,
5658
std::is_base_of<arithmetic_t, R>,
5659
is_operator_argument<L>,
5660
is_operator_argument<R>>::value,
5661
bool> = true>
5662
constexpr greater_than_t<unwrap_expression_t<L>, unwrap_expression_t<R>> operator>(L l, R r) {
5663
return {get_from_expression(std::forward<L>(l)), get_from_expression(std::forward<R>(r))};
5664
}
5665
5666
template<class L,
5667
class R,
5668
std::enable_if_t<polyfill::disjunction<std::is_base_of<arithmetic_t, L>,
5669
std::is_base_of<arithmetic_t, R>,
5670
is_operator_argument<L>,
5671
is_operator_argument<R>>::value,
5672
bool> = true>
5673
constexpr greater_or_equal_t<unwrap_expression_t<L>, unwrap_expression_t<R>> operator>=(L l, R r) {
5674
return {get_from_expression(std::forward<L>(l)), get_from_expression(std::forward<R>(r))};
5675
}
5676
5677
template<class L,
5678
class R,
5679
std::enable_if_t<polyfill::disjunction<std::is_base_of<arithmetic_t, L>,
5680
std::is_base_of<arithmetic_t, R>,
5681
std::is_base_of<condition_t, L>,
5682
std::is_base_of<condition_t, R>,
5683
is_operator_argument<L>,
5684
is_operator_argument<R>>::value,
5685
bool> = true>
5686
constexpr is_equal_t<unwrap_expression_t<L>, unwrap_expression_t<R>> operator==(L l, R r) {
5687
return {get_from_expression(std::forward<L>(l)), get_from_expression(std::forward<R>(r))};
5688
}
5689
5690
template<class L,
5691
class R,
5692
std::enable_if_t<polyfill::disjunction<std::is_base_of<arithmetic_t, L>,
5693
std::is_base_of<arithmetic_t, R>,
5694
std::is_base_of<condition_t, L>,
5695
std::is_base_of<condition_t, R>,
5696
is_operator_argument<L>,
5697
is_operator_argument<R>>::value,
5698
bool> = true>
5699
constexpr is_not_equal_t<unwrap_expression_t<L>, unwrap_expression_t<R>> operator!=(L l, R r) {
5700
return {get_from_expression(std::forward<L>(l)), get_from_expression(std::forward<R>(r))};
5701
}
5702
5703
template<class L,
5704
class R,
5705
std::enable_if_t<polyfill::disjunction<std::is_base_of<condition_t, L>,
5706
std::is_base_of<condition_t, R>,
5707
is_operator_argument<L>,
5708
is_operator_argument<R>>::value,
5709
bool> = true>
5710
constexpr and_condition_t<unwrap_expression_t<L>, unwrap_expression_t<R>> operator&&(L l, R r) {
5711
return {get_from_expression(std::forward<L>(l)), get_from_expression(std::forward<R>(r))};
5712
}
5713
5714
template<class L,
5715
class R,
5716
std::enable_if_t<
5717
polyfill::disjunction<std::is_base_of<condition_t, L>, std::is_base_of<condition_t, R>>::value,
5718
bool> = true>
5719
constexpr or_condition_t<unwrap_expression_t<L>, unwrap_expression_t<R>> operator||(L l, R r) {
5720
return {get_from_expression(std::forward<L>(l)), get_from_expression(std::forward<R>(r))};
5721
}
5722
5723
template<
5724
class L,
5725
class R,
5726
std::enable_if_t<polyfill::conjunction<
5727
polyfill::disjunction<std::is_base_of<conc_string, L>,
5728
std::is_base_of<conc_string, R>,
5729
is_operator_argument<L>,
5730
is_operator_argument<R>>,
5731
// exclude conditions
5732
polyfill::negation<polyfill::disjunction<std::is_base_of<condition_t, L>,
5733
std::is_base_of<condition_t, R>>>>::value,
5734
bool> = true>
5735
constexpr conc_t<unwrap_expression_t<L>, unwrap_expression_t<R>> operator||(L l, R r) {
5736
return {get_from_expression(std::forward<L>(l)), get_from_expression(std::forward<R>(r))};
5737
}
5738
}
5739
5740
template<class F, class O>
5741
internal::using_t<O, F O::*> using_(F O::* field) {
5742
return {field};
5743
}
5744
template<class T, class M>
5745
internal::using_t<T, M> using_(internal::column_pointer<T, M> field) {
5746
return {std::move(field)};
5747
}
5748
5749
template<class T>
5750
internal::on_t<T> on(T t) {
5751
return {std::move(t)};
5752
}
5753
5754
template<class T>
5755
internal::cross_join_t<T> cross_join() {
5756
return {};
5757
}
5758
5759
template<class T>
5760
internal::natural_join_t<T> natural_join() {
5761
return {};
5762
}
5763
5764
template<class T, class O>
5765
internal::left_join_t<T, O> left_join(O o) {
5766
return {std::move(o)};
5767
}
5768
5769
#ifdef SQLITE_ORM_WITH_CPP20_ALIASES
5770
template<orm_refers_to_recordset auto alias, class On>
5771
auto left_join(On on) {
5772
return left_join<internal::auto_decay_table_ref_t<alias>, On>(std::move(on));
5773
}
5774
#endif
5775
5776
template<class T, class O>
5777
internal::join_t<T, O> join(O o) {
5778
return {std::move(o)};
5779
}
5780
5781
#ifdef SQLITE_ORM_WITH_CPP20_ALIASES
5782
template<orm_refers_to_recordset auto alias, class On>
5783
auto join(On on) {
5784
return join<internal::auto_decay_table_ref_t<alias>, On>(std::move(on));
5785
}
5786
#endif
5787
5788
template<class T, class O>
5789
internal::left_outer_join_t<T, O> left_outer_join(O o) {
5790
return {std::move(o)};
5791
}
5792
5793
#ifdef SQLITE_ORM_WITH_CPP20_ALIASES
5794
template<orm_refers_to_recordset auto alias, class On>
5795
auto left_outer_join(On on) {
5796
return left_outer_join<internal::auto_decay_table_ref_t<alias>, On>(std::move(on));
5797
}
5798
#endif
5799
5800
template<class T, class O>
5801
internal::inner_join_t<T, O> inner_join(O o) {
5802
return {std::move(o)};
5803
}
5804
5805
#ifdef SQLITE_ORM_WITH_CPP20_ALIASES
5806
template<orm_refers_to_recordset auto alias, class On>
5807
auto inner_join(On on) {
5808
return inner_join<internal::auto_decay_table_ref_t<alias>, On>(std::move(on));
5809
}
5810
#endif
5811
5812
template<class T>
5813
internal::offset_t<T> offset(T off) {
5814
return {std::move(off)};
5815
}
5816
5817
template<class T>
5818
internal::limit_t<T, false, false, void> limit(T lim) {
5819
return {std::move(lim)};
5820
}
5821
5822
template<class T, class O, internal::satisfies_not<internal::is_offset, T> = true>
5823
internal::limit_t<T, true, true, O> limit(O off, T lim) {
5824
return {std::move(lim), {std::move(off)}};
5825
}
5826
5827
template<class T, class O>
5828
internal::limit_t<T, true, false, O> limit(T lim, internal::offset_t<O> offt) {
5829
return {std::move(lim), {std::move(offt.off)}};
5830
}
5831
5832
template<class L, class R>
5833
constexpr auto and_(L l, R r) {
5834
using namespace ::sqlite_orm::internal;
5835
return and_condition_t<unwrap_expression_t<L>, unwrap_expression_t<R>>{get_from_expression(std::forward<L>(l)),
5836
get_from_expression(std::forward<R>(r))};
5837
}
5838
5839
template<class L, class R>
5840
constexpr auto or_(L l, R r) {
5841
using namespace ::sqlite_orm::internal;
5842
return or_condition_t<unwrap_expression_t<L>, unwrap_expression_t<R>>{get_from_expression(std::forward<L>(l)),
5843
get_from_expression(std::forward<R>(r))};
5844
}
5845
5846
template<class T>
5847
internal::is_not_null_t<T> is_not_null(T t) {
5848
return {std::move(t)};
5849
}
5850
5851
template<class T>
5852
internal::is_null_t<T> is_null(T t) {
5853
return {std::move(t)};
5854
}
5855
5856
template<class L, class E>
5857
internal::dynamic_in_t<L, std::vector<E>> in(L l, std::vector<E> values) {
5858
return {std::move(l), std::move(values), false};
5859
}
5860
5861
template<class L, class E>
5862
internal::dynamic_in_t<L, std::vector<E>> in(L l, std::initializer_list<E> values) {
5863
return {std::move(l), std::move(values), false};
5864
}
5865
5866
template<class L, class A>
5867
internal::dynamic_in_t<L, A> in(L l, A arg) {
5868
return {std::move(l), std::move(arg), false};
5869
}
5870
5871
template<class L, class E>
5872
internal::dynamic_in_t<L, std::vector<E>> not_in(L l, std::vector<E> values) {
5873
return {std::move(l), std::move(values), true};
5874
}
5875
5876
template<class L, class E>
5877
internal::dynamic_in_t<L, std::vector<E>> not_in(L l, std::initializer_list<E> values) {
5878
return {std::move(l), std::move(values), true};
5879
}
5880
5881
template<class L, class A>
5882
internal::dynamic_in_t<L, A> not_in(L l, A arg) {
5883
return {std::move(l), std::move(arg), true};
5884
}
5885
5886
template<class L, class R>
5887
constexpr internal::is_equal_t<L, R> is_equal(L l, R r) {
5888
return {std::move(l), std::move(r)};
5889
}
5890
5891
template<class L, class R>
5892
constexpr internal::is_equal_t<L, R> eq(L l, R r) {
5893
return {std::move(l), std::move(r)};
5894
}
5895
5896
template<class L, class R>
5897
constexpr internal::is_equal_with_table_t<L, R> is_equal(R rhs) {
5898
return {std::move(rhs)};
5899
}
5900
5901
template<class L, class R>
5902
constexpr internal::is_not_equal_t<L, R> is_not_equal(L l, R r) {
5903
return {std::move(l), std::move(r)};
5904
}
5905
5906
template<class L, class R>
5907
constexpr internal::is_not_equal_t<L, R> ne(L l, R r) {
5908
return {std::move(l), std::move(r)};
5909
}
5910
5911
template<class L, class R>
5912
constexpr internal::greater_than_t<L, R> greater_than(L l, R r) {
5913
return {std::move(l), std::move(r)};
5914
}
5915
5916
template<class L, class R>
5917
constexpr internal::greater_than_t<L, R> gt(L l, R r) {
5918
return {std::move(l), std::move(r)};
5919
}
5920
5921
template<class L, class R>
5922
constexpr internal::greater_or_equal_t<L, R> greater_or_equal(L l, R r) {
5923
return {std::move(l), std::move(r)};
5924
}
5925
5926
template<class L, class R>
5927
constexpr internal::greater_or_equal_t<L, R> ge(L l, R r) {
5928
return {std::move(l), std::move(r)};
5929
}
5930
5931
template<class L, class R>
5932
constexpr internal::less_than_t<L, R> less_than(L l, R r) {
5933
return {std::move(l), std::move(r)};
5934
}
5935
5936
/**
5937
* [Deprecation notice] This function is deprecated and will be removed in v1.10. Use the accurately named function `less_than(...)` instead.
5938
*/
5939
template<class L, class R>
5940
[[deprecated("Use the accurately named function `less_than(...)` instead")]] internal::less_than_t<L, R>
5941
lesser_than(L l, R r) {
5942
return {std::move(l), std::move(r)};
5943
}
5944
5945
template<class L, class R>
5946
constexpr internal::less_than_t<L, R> lt(L l, R r) {
5947
return {std::move(l), std::move(r)};
5948
}
5949
5950
template<class L, class R>
5951
constexpr internal::less_or_equal_t<L, R> less_or_equal(L l, R r) {
5952
return {std::move(l), std::move(r)};
5953
}
5954
5955
/**
5956
* [Deprecation notice] This function is deprecated and will be removed in v1.10. Use the accurately named function `less_or_equal(...)` instead.
5957
*/
5958
template<class L, class R>
5959
[[deprecated("Use the accurately named function `less_or_equal(...)` instead")]] internal::less_or_equal_t<L, R>
5960
lesser_or_equal(L l, R r) {
5961
return {std::move(l), std::move(r)};
5962
}
5963
5964
template<class L, class R>
5965
constexpr internal::less_or_equal_t<L, R> le(L l, R r) {
5966
return {std::move(l), std::move(r)};
5967
}
5968
5969
/**
5970
* ORDER BY column, column alias or expression
5971
*
5972
* Examples:
5973
* storage.select(&User::name, order_by(&User::id))
5974
* storage.select(as<colalias_a>(&User::name), order_by(get<colalias_a>()))
5975
*/
5976
template<class O, internal::satisfies_not<std::is_base_of, integer_printer, type_printer<O>> = true>
5977
internal::order_by_t<O> order_by(O o) {
5978
return {std::move(o)};
5979
}
5980
5981
/**
5982
* ORDER BY positional ordinal
5983
*
5984
* Examples:
5985
* storage.select(&User::name, order_by(1))
5986
*/
5987
template<class O, internal::satisfies<std::is_base_of, integer_printer, type_printer<O>> = true>
5988
internal::order_by_t<internal::literal_holder<O>> order_by(O o) {
5989
return {{std::move(o)}};
5990
}
5991
5992
/**
5993
* ORDER BY column1, column2
5994
* Example: storage.get_all<Singer>(multi_order_by(order_by(&Singer::name).asc(), order_by(&Singer::gender).desc())
5995
*/
5996
template<class... Args>
5997
internal::multi_order_by_t<Args...> multi_order_by(Args... args) {
5998
return {{std::forward<Args>(args)...}};
5999
}
6000
6001
/**
6002
* ORDER BY column1, column2
6003
* Difference from `multi_order_by` is that `dynamic_order_by` can be changed at runtime using `push_back` member
6004
* function Example:
6005
* auto orderBy = dynamic_order_by(storage);
6006
* if(someCondition) {
6007
* orderBy.push_back(&User::id);
6008
* } else {
6009
* orderBy.push_back(&User::name);
6010
* orderBy.push_back(&User::birthDate);
6011
* }
6012
*/
6013
template<class S>
6014
internal::dynamic_order_by_t<internal::serializer_context<typename S::db_objects_type>>
6015
dynamic_order_by(const S& storage) {
6016
internal::serializer_context_builder<S> builder(storage);
6017
return builder();
6018
}
6019
6020
/**
6021
* X BETWEEN Y AND Z
6022
* Example: storage.select(between(&User::id, 10, 20))
6023
*/
6024
template<class A, class T>
6025
internal::between_t<A, T> between(A expr, T b1, T b2) {
6026
return {std::move(expr), std::move(b1), std::move(b2)};
6027
}
6028
6029
/**
6030
* X LIKE Y
6031
* Example: storage.select(like(&User::name, "T%"))
6032
*/
6033
template<class A, class T>
6034
internal::like_t<A, T, void> like(A a, T t) {
6035
return {std::move(a), std::move(t), {}};
6036
}
6037
6038
/**
6039
* X GLOB Y
6040
* Example: storage.select(glob(&User::name, "*S"))
6041
*/
6042
template<class A, class T>
6043
internal::glob_t<A, T> glob(A a, T t) {
6044
return {std::move(a), std::move(t)};
6045
}
6046
6047
/**
6048
* X LIKE Y ESCAPE Z
6049
* Example: storage.select(like(&User::name, "T%", "%"))
6050
*/
6051
template<class A, class T, class E>
6052
internal::like_t<A, T, E> like(A a, T t, E e) {
6053
return {std::move(a), std::move(t), {std::move(e)}};
6054
}
6055
6056
/**
6057
* CAST(X AS type).
6058
* Example: cast<std::string>(&User::id)
6059
*/
6060
template<class T, class E>
6061
internal::cast_t<T, E> cast(E e) {
6062
return {std::move(e)};
6063
}
6064
}
6065
6066
// #include "serialize_result_type.h"
6067
6068
// #include "operators.h"
6069
6070
// #include "tags.h"
6071
6072
// #include "table_reference.h"
6073
6074
// #include "ast/into.h"
6075
6076
// #include "../functional/cxx_type_traits_polyfill.h"
6077
6078
namespace sqlite_orm {
6079
namespace internal {
6080
6081
template<class T>
6082
struct into_t {
6083
using type = T;
6084
};
6085
6086
template<class T>
6087
using is_into = polyfill::is_specialization_of<T, into_t>;
6088
}
6089
6090
template<class T>
6091
internal::into_t<T> into() {
6092
return {};
6093
}
6094
}
6095
6096
namespace sqlite_orm {
6097
6098
using int64 = sqlite_int64;
6099
using uint64 = sqlite_uint64;
6100
6101
namespace internal {
6102
6103
template<class T>
6104
struct unique_ptr_result_of {};
6105
6106
/**
6107
* Base class for operator overloading
6108
* R - return type
6109
* S - class with operator std::string
6110
* Args - function arguments types
6111
*/
6112
template<class R, class S, class... Args>
6113
struct built_in_function_t : S, arithmetic_t {
6114
using return_type = R;
6115
using string_type = S;
6116
using args_type = std::tuple<Args...>;
6117
6118
static constexpr size_t args_size = std::tuple_size<args_type>::value;
6119
6120
args_type args;
6121
6122
built_in_function_t(args_type&& args_) : args(std::move(args_)) {}
6123
};
6124
6125
template<class T>
6126
SQLITE_ORM_INLINE_VAR constexpr bool is_built_in_function_v =
6127
is_base_of_template<T, built_in_function_t>::value;
6128
6129
template<class T>
6130
struct is_built_in_function : polyfill::bool_constant<is_built_in_function_v<T>> {};
6131
6132
template<class F, class W>
6133
struct filtered_aggregate_function {
6134
using function_type = F;
6135
using where_expression = W;
6136
6137
function_type function;
6138
where_expression where;
6139
};
6140
6141
template<class C>
6142
struct where_t;
6143
6144
template<class R, class S, class... Args>
6145
struct built_in_aggregate_function_t : built_in_function_t<R, S, Args...> {
6146
using super = built_in_function_t<R, S, Args...>;
6147
6148
using super::super;
6149
6150
template<class W>
6151
filtered_aggregate_function<built_in_aggregate_function_t<R, S, Args...>, W> filter(where_t<W> wh) {
6152
return {*this, std::move(wh.expression)};
6153
}
6154
};
6155
6156
struct typeof_string {
6157
serialize_result_type serialize() const {
6158
return "TYPEOF";
6159
}
6160
};
6161
6162
struct unicode_string {
6163
serialize_result_type serialize() const {
6164
return "UNICODE";
6165
}
6166
};
6167
6168
struct length_string {
6169
serialize_result_type serialize() const {
6170
return "LENGTH";
6171
}
6172
};
6173
6174
struct abs_string {
6175
serialize_result_type serialize() const {
6176
return "ABS";
6177
}
6178
};
6179
6180
struct lower_string {
6181
serialize_result_type serialize() const {
6182
return "LOWER";
6183
}
6184
};
6185
6186
struct upper_string {
6187
serialize_result_type serialize() const {
6188
return "UPPER";
6189
}
6190
};
6191
6192
struct last_insert_rowid_string {
6193
serialize_result_type serialize() const {
6194
return "LAST_INSERT_ROWID";
6195
}
6196
};
6197
6198
struct total_changes_string {
6199
serialize_result_type serialize() const {
6200
return "TOTAL_CHANGES";
6201
}
6202
};
6203
6204
struct changes_string {
6205
serialize_result_type serialize() const {
6206
return "CHANGES";
6207
}
6208
};
6209
6210
struct trim_string {
6211
serialize_result_type serialize() const {
6212
return "TRIM";
6213
}
6214
};
6215
6216
struct ltrim_string {
6217
serialize_result_type serialize() const {
6218
return "LTRIM";
6219
}
6220
};
6221
6222
struct rtrim_string {
6223
serialize_result_type serialize() const {
6224
return "RTRIM";
6225
}
6226
};
6227
6228
struct hex_string {
6229
serialize_result_type serialize() const {
6230
return "HEX";
6231
}
6232
};
6233
6234
struct quote_string {
6235
serialize_result_type serialize() const {
6236
return "QUOTE";
6237
}
6238
};
6239
6240
struct randomblob_string {
6241
serialize_result_type serialize() const {
6242
return "RANDOMBLOB";
6243
}
6244
};
6245
6246
struct instr_string {
6247
serialize_result_type serialize() const {
6248
return "INSTR";
6249
}
6250
};
6251
6252
struct replace_string {
6253
serialize_result_type serialize() const {
6254
return "REPLACE";
6255
}
6256
};
6257
6258
struct round_string {
6259
serialize_result_type serialize() const {
6260
return "ROUND";
6261
}
6262
};
6263
6264
#if SQLITE_VERSION_NUMBER >= 3007016
6265
struct char_string {
6266
serialize_result_type serialize() const {
6267
return "CHAR";
6268
}
6269
};
6270
6271
struct random_string {
6272
serialize_result_type serialize() const {
6273
return "RANDOM";
6274
}
6275
};
6276
6277
#endif
6278
6279
struct coalesce_string {
6280
serialize_result_type serialize() const {
6281
return "COALESCE";
6282
}
6283
};
6284
6285
struct ifnull_string {
6286
serialize_result_type serialize() const {
6287
return "IFNULL";
6288
}
6289
};
6290
6291
struct nullif_string {
6292
serialize_result_type serialize() const {
6293
return "NULLIF";
6294
}
6295
};
6296
6297
struct date_string {
6298
serialize_result_type serialize() const {
6299
return "DATE";
6300
}
6301
};
6302
6303
struct time_string {
6304
serialize_result_type serialize() const {
6305
return "TIME";
6306
}
6307
};
6308
6309
struct datetime_string {
6310
serialize_result_type serialize() const {
6311
return "DATETIME";
6312
}
6313
};
6314
6315
struct julianday_string {
6316
serialize_result_type serialize() const {
6317
return "JULIANDAY";
6318
}
6319
};
6320
6321
struct strftime_string {
6322
serialize_result_type serialize() const {
6323
return "STRFTIME";
6324
}
6325
};
6326
6327
struct zeroblob_string {
6328
serialize_result_type serialize() const {
6329
return "ZEROBLOB";
6330
}
6331
};
6332
6333
struct substr_string {
6334
serialize_result_type serialize() const {
6335
return "SUBSTR";
6336
}
6337
};
6338
#ifdef SQLITE_SOUNDEX
6339
struct soundex_string {
6340
serialize_result_type serialize() const {
6341
return "SOUNDEX";
6342
}
6343
};
6344
#endif
6345
struct total_string {
6346
serialize_result_type serialize() const {
6347
return "TOTAL";
6348
}
6349
};
6350
6351
struct sum_string {
6352
serialize_result_type serialize() const {
6353
return "SUM";
6354
}
6355
};
6356
6357
struct count_string {
6358
serialize_result_type serialize() const {
6359
return "COUNT";
6360
}
6361
};
6362
6363
/**
6364
* T is use to specify type explicitly for queries like
6365
* SELECT COUNT(*) FROM table_name;
6366
* T can be omitted with void.
6367
*/
6368
template<class T>
6369
struct count_asterisk_t : count_string {
6370
using type = T;
6371
6372
template<class W>
6373
filtered_aggregate_function<count_asterisk_t<T>, W> filter(where_t<W> wh) {
6374
return {*this, std::move(wh.expression)};
6375
}
6376
};
6377
6378
/**
6379
* The same thing as count<T>() but without T arg.
6380
* Is used in cases like this:
6381
* SELECT cust_code, cust_name, cust_city, grade
6382
* FROM customer
6383
* WHERE grade=2 AND EXISTS
6384
* (SELECT COUNT(*)
6385
* FROM customer
6386
* WHERE grade=2
6387
* GROUP BY grade
6388
* HAVING COUNT(*)>2);
6389
* `c++`
6390
* auto rows =
6391
* storage.select(columns(&Customer::code, &Customer::name, &Customer::city, &Customer::grade),
6392
* where(is_equal(&Customer::grade, 2)
6393
* and exists(select(count<Customer>(),
6394
* where(is_equal(&Customer::grade, 2)),
6395
* group_by(&Customer::grade),
6396
* having(greater_than(count(), 2))))));
6397
*/
6398
struct count_asterisk_without_type : count_string {};
6399
6400
struct avg_string {
6401
serialize_result_type serialize() const {
6402
return "AVG";
6403
}
6404
};
6405
6406
struct max_string {
6407
serialize_result_type serialize() const {
6408
return "MAX";
6409
}
6410
};
6411
6412
struct min_string {
6413
serialize_result_type serialize() const {
6414
return "MIN";
6415
}
6416
};
6417
6418
struct group_concat_string {
6419
serialize_result_type serialize() const {
6420
return "GROUP_CONCAT";
6421
}
6422
};
6423
#ifdef SQLITE_ENABLE_MATH_FUNCTIONS
6424
struct acos_string {
6425
serialize_result_type serialize() const {
6426
return "ACOS";
6427
}
6428
};
6429
6430
struct acosh_string {
6431
serialize_result_type serialize() const {
6432
return "ACOSH";
6433
}
6434
};
6435
6436
struct asin_string {
6437
serialize_result_type serialize() const {
6438
return "ASIN";
6439
}
6440
};
6441
6442
struct asinh_string {
6443
serialize_result_type serialize() const {
6444
return "ASINH";
6445
}
6446
};
6447
6448
struct atan_string {
6449
serialize_result_type serialize() const {
6450
return "ATAN";
6451
}
6452
};
6453
6454
struct atan2_string {
6455
serialize_result_type serialize() const {
6456
return "ATAN2";
6457
}
6458
};
6459
6460
struct atanh_string {
6461
serialize_result_type serialize() const {
6462
return "ATANH";
6463
}
6464
};
6465
6466
struct ceil_string {
6467
serialize_result_type serialize() const {
6468
return "CEIL";
6469
}
6470
};
6471
6472
struct ceiling_string {
6473
serialize_result_type serialize() const {
6474
return "CEILING";
6475
}
6476
};
6477
6478
struct cos_string {
6479
serialize_result_type serialize() const {
6480
return "COS";
6481
}
6482
};
6483
6484
struct cosh_string {
6485
serialize_result_type serialize() const {
6486
return "COSH";
6487
}
6488
};
6489
6490
struct degrees_string {
6491
serialize_result_type serialize() const {
6492
return "DEGREES";
6493
}
6494
};
6495
6496
struct exp_string {
6497
serialize_result_type serialize() const {
6498
return "EXP";
6499
}
6500
};
6501
6502
struct floor_string {
6503
serialize_result_type serialize() const {
6504
return "FLOOR";
6505
}
6506
};
6507
6508
struct ln_string {
6509
serialize_result_type serialize() const {
6510
return "LN";
6511
}
6512
};
6513
6514
struct log_string {
6515
serialize_result_type serialize() const {
6516
return "LOG";
6517
}
6518
};
6519
6520
struct log10_string {
6521
serialize_result_type serialize() const {
6522
return "LOG10";
6523
}
6524
};
6525
6526
struct log2_string {
6527
serialize_result_type serialize() const {
6528
return "LOG2";
6529
}
6530
};
6531
6532
struct mod_string {
6533
serialize_result_type serialize() const {
6534
return "MOD";
6535
}
6536
};
6537
6538
struct pi_string {
6539
serialize_result_type serialize() const {
6540
return "PI";
6541
}
6542
};
6543
6544
struct pow_string {
6545
serialize_result_type serialize() const {
6546
return "POW";
6547
}
6548
};
6549
6550
struct power_string {
6551
serialize_result_type serialize() const {
6552
return "POWER";
6553
}
6554
};
6555
6556
struct radians_string {
6557
serialize_result_type serialize() const {
6558
return "RADIANS";
6559
}
6560
};
6561
6562
struct sin_string {
6563
serialize_result_type serialize() const {
6564
return "SIN";
6565
}
6566
};
6567
6568
struct sinh_string {
6569
serialize_result_type serialize() const {
6570
return "SINH";
6571
}
6572
};
6573
6574
struct sqrt_string {
6575
serialize_result_type serialize() const {
6576
return "SQRT";
6577
}
6578
};
6579
6580
struct tan_string {
6581
serialize_result_type serialize() const {
6582
return "TAN";
6583
}
6584
};
6585
6586
struct tanh_string {
6587
serialize_result_type serialize() const {
6588
return "TANH";
6589
}
6590
};
6591
6592
struct trunc_string {
6593
serialize_result_type serialize() const {
6594
return "TRUNC";
6595
}
6596
};
6597
6598
#endif // SQLITE_ENABLE_MATH_FUNCTIONS
6599
#ifdef SQLITE_ENABLE_JSON1
6600
struct json_string {
6601
serialize_result_type serialize() const {
6602
return "JSON";
6603
}
6604
};
6605
6606
struct json_array_string {
6607
serialize_result_type serialize() const {
6608
return "JSON_ARRAY";
6609
}
6610
};
6611
6612
struct json_array_length_string {
6613
serialize_result_type serialize() const {
6614
return "JSON_ARRAY_LENGTH";
6615
}
6616
};
6617
6618
struct json_extract_string {
6619
serialize_result_type serialize() const {
6620
return "JSON_EXTRACT";
6621
}
6622
};
6623
6624
struct json_insert_string {
6625
serialize_result_type serialize() const {
6626
return "JSON_INSERT";
6627
}
6628
};
6629
6630
struct json_replace_string {
6631
serialize_result_type serialize() const {
6632
return "JSON_REPLACE";
6633
}
6634
};
6635
6636
struct json_set_string {
6637
serialize_result_type serialize() const {
6638
return "JSON_SET";
6639
}
6640
};
6641
6642
struct json_object_string {
6643
serialize_result_type serialize() const {
6644
return "JSON_OBJECT";
6645
}
6646
};
6647
6648
struct json_patch_string {
6649
serialize_result_type serialize() const {
6650
return "JSON_PATCH";
6651
}
6652
};
6653
6654
struct json_remove_string {
6655
serialize_result_type serialize() const {
6656
return "JSON_REMOVE";
6657
}
6658
};
6659
6660
struct json_type_string {
6661
serialize_result_type serialize() const {
6662
return "JSON_TYPE";
6663
}
6664
};
6665
6666
struct json_valid_string {
6667
serialize_result_type serialize() const {
6668
return "JSON_VALID";
6669
}
6670
};
6671
6672
struct json_quote_string {
6673
serialize_result_type serialize() const {
6674
return "JSON_QUOTE";
6675
}
6676
};
6677
6678
struct json_group_array_string {
6679
serialize_result_type serialize() const {
6680
return "JSON_GROUP_ARRAY";
6681
}
6682
};
6683
6684
struct json_group_object_string {
6685
serialize_result_type serialize() const {
6686
return "JSON_GROUP_OBJECT";
6687
}
6688
};
6689
#endif // SQLITE_ENABLE_JSON1
6690
6691
template<class T>
6692
using field_type_or_type_t = polyfill::detected_or_t<T, type_t, member_field_type<T>>;
6693
6694
template<class T, class X, class Y, class Z>
6695
struct highlight_t {
6696
using table_type = T;
6697
using argument0_type = X;
6698
using argument1_type = Y;
6699
using argument2_type = Z;
6700
6701
argument0_type argument0;
6702
argument1_type argument1;
6703
argument2_type argument2;
6704
6705
highlight_t(argument0_type argument0, argument1_type argument1, argument2_type argument2) :
6706
argument0(std::move(argument0)), argument1(std::move(argument1)), argument2(std::move(argument2)) {}
6707
};
6708
}
6709
6710
#ifdef SQLITE_ENABLE_MATH_FUNCTIONS
6711
6712
/**
6713
* ACOS(X) function https://www.sqlite.org/lang_mathfunc.html#acos
6714
*
6715
* Example:
6716
*
6717
* auto rows = storage.select(sqlite_orm::acos(&Triangle::cornerA)); // decltype(rows) is std::vector<double>
6718
*/
6719
template<class X>
6720
internal::built_in_function_t<double, internal::acos_string, X> acos(X x) {
6721
return {std::tuple<X>{std::forward<X>(x)}};
6722
}
6723
6724
/**
6725
* ACOS(X) function https://www.sqlite.org/lang_mathfunc.html#acos
6726
*
6727
* Difference with the previous function is that previous override has `double` as return type but this
6728
* override accepts return type from you as a template argument. You can use any bindable type:
6729
* `float`, `int`, `std::optional<double>` etc. This override is handy when you expect `null` as result.
6730
*
6731
* Example:
6732
*
6733
* auto rows = storage.select(sqlite_orm::acos<std::optional<double>>(&Triangle::cornerA)); // decltype(rows) is std::vector<std::optional<double>>
6734
*/
6735
template<class R, class X>
6736
internal::built_in_function_t<R, internal::acos_string, X> acos(X x) {
6737
return {std::tuple<X>{std::forward<X>(x)}};
6738
}
6739
6740
/**
6741
* ACOSH(X) function https://www.sqlite.org/lang_mathfunc.html#acosh
6742
*
6743
* Example:
6744
*
6745
* auto rows = storage.select(sqlite_orm::acosh(&Triangle::cornerA)); // decltype(rows) is std::vector<double>
6746
*/
6747
template<class X>
6748
internal::built_in_function_t<double, internal::acosh_string, X> acosh(X x) {
6749
return {std::tuple<X>{std::forward<X>(x)}};
6750
}
6751
6752
/**
6753
* ACOSH(X) function https://www.sqlite.org/lang_mathfunc.html#acosh
6754
*
6755
* Difference with the previous function is that previous override has `double` as return type but this
6756
* override accepts return type from you as a template argument. You can use any bindable type:
6757
* `float`, `int`, `std::optional<double>` etc. This override is handy when you expect `null` as result.
6758
*
6759
* Example:
6760
*
6761
* auto rows = storage.select(sqlite_orm::acosh<std::optional<double>>(&Triangle::cornerA)); // decltype(rows) is std::vector<std::optional<double>>
6762
*/
6763
template<class R, class X>
6764
internal::built_in_function_t<R, internal::acosh_string, X> acosh(X x) {
6765
return {std::tuple<X>{std::forward<X>(x)}};
6766
}
6767
6768
/**
6769
* ASIN(X) function https://www.sqlite.org/lang_mathfunc.html#asin
6770
*
6771
* Example:
6772
*
6773
* auto rows = storage.select(sqlite_orm::asin(&Triangle::cornerA)); // decltype(rows) is std::vector<double>
6774
*/
6775
template<class X>
6776
internal::built_in_function_t<double, internal::asin_string, X> asin(X x) {
6777
return {std::tuple<X>{std::forward<X>(x)}};
6778
}
6779
6780
/**
6781
* ASIN(X) function https://www.sqlite.org/lang_mathfunc.html#asin
6782
*
6783
* Difference with the previous function is that previous override has `double` as return type but this
6784
* override accepts return type from you as a template argument. You can use any bindable type:
6785
* `float`, `int`, `std::optional<double>` etc. This override is handy when you expect `null` as result.
6786
*
6787
* Example:
6788
*
6789
* auto rows = storage.select(sqlite_orm::asin<std::optional<double>>(&Triangle::cornerA)); // decltype(rows) is std::vector<std::optional<double>>
6790
*/
6791
template<class R, class X>
6792
internal::built_in_function_t<R, internal::asin_string, X> asin(X x) {
6793
return {std::tuple<X>{std::forward<X>(x)}};
6794
}
6795
6796
/**
6797
* ASINH(X) function https://www.sqlite.org/lang_mathfunc.html#asinh
6798
*
6799
* Example:
6800
*
6801
* auto rows = storage.select(sqlite_orm::asinh(&Triangle::cornerA)); // decltype(rows) is std::vector<double>
6802
*/
6803
template<class X>
6804
internal::built_in_function_t<double, internal::asinh_string, X> asinh(X x) {
6805
return {std::tuple<X>{std::forward<X>(x)}};
6806
}
6807
6808
/**
6809
* ASINH(X) function https://www.sqlite.org/lang_mathfunc.html#asinh
6810
*
6811
* Difference with the previous function is that previous override has `double` as return type but this
6812
* override accepts return type from you as a template argument. You can use any bindable type:
6813
* `float`, `int`, `std::optional<double>` etc. This override is handy when you expect `null` as result.
6814
*
6815
* Example:
6816
*
6817
* auto rows = storage.select(sqlite_orm::asinh<std::optional<double>>(&Triangle::cornerA)); // decltype(rows) is std::vector<std::optional<double>>
6818
*/
6819
template<class R, class X>
6820
internal::built_in_function_t<R, internal::asinh_string, X> asinh(X x) {
6821
return {std::tuple<X>{std::forward<X>(x)}};
6822
}
6823
6824
/**
6825
* ATAN(X) function https://www.sqlite.org/lang_mathfunc.html#atan
6826
*
6827
* Example:
6828
*
6829
* auto rows = storage.select(sqlite_orm::atan(1)); // decltype(rows) is std::vector<double>
6830
*/
6831
template<class X>
6832
internal::built_in_function_t<double, internal::atan_string, X> atan(X x) {
6833
return {std::tuple<X>{std::forward<X>(x)}};
6834
}
6835
6836
/**
6837
* ATAN(X) function https://www.sqlite.org/lang_mathfunc.html#atan
6838
*
6839
* Difference with the previous function is that previous override has `double` as return type but this
6840
* override accepts return type from you as a template argument. You can use any bindable type:
6841
* `float`, `int`, `std::optional<double>` etc. This override is handy when you expect `null` as result.
6842
*
6843
* Example:
6844
*
6845
* auto rows = storage.select(sqlite_orm::atan<std::optional<double>>(1)); // decltype(rows) is std::vector<std::optional<double>>
6846
*/
6847
template<class R, class X>
6848
internal::built_in_function_t<R, internal::atan_string, X> atan(X x) {
6849
return {std::tuple<X>{std::forward<X>(x)}};
6850
}
6851
6852
/**
6853
* ATAN2(X, Y) function https://www.sqlite.org/lang_mathfunc.html#atan2
6854
*
6855
* Example:
6856
*
6857
* auto rows = storage.select(sqlite_orm::atan2(1, 3)); // decltype(rows) is std::vector<double>
6858
*/
6859
template<class X, class Y>
6860
internal::built_in_function_t<double, internal::atan2_string, X, Y> atan2(X x, Y y) {
6861
return {std::tuple<X, Y>{std::forward<X>(x), std::forward<Y>(y)}};
6862
}
6863
6864
/**
6865
* ATAN2(X, Y) function https://www.sqlite.org/lang_mathfunc.html#atan2
6866
*
6867
* Difference with the previous function is that previous override has `double` as return type but this
6868
* override accepts return type from you as a template argument. You can use any bindable type:
6869
* `float`, `int`, `std::optional<double>` etc. This override is handy when you expect `null` as result.
6870
*
6871
* Example:
6872
*
6873
* auto rows = storage.select(sqlite_orm::atan2<std::optional<double>>(1, 3)); // decltype(rows) is std::vector<std::optional<double>>
6874
*/
6875
template<class R, class X, class Y>
6876
internal::built_in_function_t<R, internal::atan2_string, X, Y> atan2(X x, Y y) {
6877
return {std::tuple<X, Y>{std::forward<X>(x), std::forward<Y>(y)}};
6878
}
6879
6880
/**
6881
* ATANH(X) function https://www.sqlite.org/lang_mathfunc.html#atanh
6882
*
6883
* Example:
6884
*
6885
* auto rows = storage.select(sqlite_orm::atanh(1)); // decltype(rows) is std::vector<double>
6886
*/
6887
template<class X>
6888
internal::built_in_function_t<double, internal::atanh_string, X> atanh(X x) {
6889
return {std::tuple<X>{std::forward<X>(x)}};
6890
}
6891
6892
/**
6893
* ATANH(X) function https://www.sqlite.org/lang_mathfunc.html#atanh
6894
*
6895
* Difference with the previous function is that previous override has `double` as return type but this
6896
* override accepts return type from you as a template argument. You can use any bindable type:
6897
* `float`, `int`, `std::optional<double>` etc. This override is handy when you expect `null` as result.
6898
*
6899
* Example:
6900
*
6901
* auto rows = storage.select(sqlite_orm::atanh<std::optional<double>>(1)); // decltype(rows) is std::vector<std::optional<double>>
6902
*/
6903
template<class R, class X>
6904
internal::built_in_function_t<R, internal::atanh_string, X> atanh(X x) {
6905
return {std::tuple<X>{std::forward<X>(x)}};
6906
}
6907
6908
/**
6909
* CEIL(X) function https://www.sqlite.org/lang_mathfunc.html#ceil
6910
*
6911
* Example:
6912
*
6913
* auto rows = storage.select(sqlite_orm::ceil(&User::rating)); // decltype(rows) is std::vector<double>
6914
*/
6915
template<class X>
6916
internal::built_in_function_t<double, internal::ceil_string, X> ceil(X x) {
6917
return {std::tuple<X>{std::forward<X>(x)}};
6918
}
6919
6920
/**
6921
* CEIL(X) function https://www.sqlite.org/lang_mathfunc.html#ceil
6922
*
6923
* Difference with the previous function is that previous override has `double` as return type but this
6924
* override accepts return type from you as a template argument. You can use any bindable type:
6925
* `float`, `int`, `std::optional<double>` etc. This override is handy when you expect `null` as result.
6926
*
6927
* Example:
6928
*
6929
* auto rows = storage.select(sqlite_orm::ceil<std::optional<double>>(&User::rating)); // decltype(rows) is std::vector<std::optional<double>>
6930
*/
6931
template<class R, class X>
6932
internal::built_in_function_t<R, internal::ceil_string, X> ceil(X x) {
6933
return {std::tuple<X>{std::forward<X>(x)}};
6934
}
6935
6936
/**
6937
* CEILING(X) function https://www.sqlite.org/lang_mathfunc.html#ceil
6938
*
6939
* Example:
6940
*
6941
* auto rows = storage.select(sqlite_orm::ceiling(&User::rating)); // decltype(rows) is std::vector<double>
6942
*/
6943
template<class X>
6944
internal::built_in_function_t<double, internal::ceiling_string, X> ceiling(X x) {
6945
return {std::tuple<X>{std::forward<X>(x)}};
6946
}
6947
6948
/**
6949
* CEILING(X) function https://www.sqlite.org/lang_mathfunc.html#ceil
6950
*
6951
* Difference with the previous function is that previous override has `double` as return type but this
6952
* override accepts return type from you as a template argument. You can use any bindable type:
6953
* `float`, `int`, `std::optional<double>` etc. This override is handy when you expect `null` as result.
6954
*
6955
* Example:
6956
*
6957
* auto rows = storage.select(sqlite_orm::ceiling<std::optional<double>>(&User::rating)); // decltype(rows) is std::vector<std::optional<double>>
6958
*/
6959
template<class R, class X>
6960
internal::built_in_function_t<R, internal::ceiling_string, X> ceiling(X x) {
6961
return {std::tuple<X>{std::forward<X>(x)}};
6962
}
6963
6964
/**
6965
* COS(X) function https://www.sqlite.org/lang_mathfunc.html#cos
6966
*
6967
* Example:
6968
*
6969
* auto rows = storage.select(sqlite_orm::cos(&Triangle::cornerB)); // decltype(rows) is std::vector<double>
6970
*/
6971
template<class X>
6972
internal::built_in_function_t<double, internal::cos_string, X> cos(X x) {
6973
return {std::tuple<X>{std::forward<X>(x)}};
6974
}
6975
6976
/**
6977
* COS(X) function https://www.sqlite.org/lang_mathfunc.html#cos
6978
*
6979
* Difference with the previous function is that previous override has `double` as return type but this
6980
* override accepts return type from you as a template argument. You can use any bindable type:
6981
* `float`, `int`, `std::optional<double>` etc. This override is handy when you expect `null` as result.
6982
*
6983
* Example:
6984
*
6985
* auto rows = storage.select(sqlite_orm::cos<std::optional<double>>(&User::rating)); // decltype(rows) is std::vector<std::optional<double>>
6986
*/
6987
template<class R, class X>
6988
internal::built_in_function_t<R, internal::cos_string, X> cos(X x) {
6989
return {std::tuple<X>{std::forward<X>(x)}};
6990
}
6991
6992
/**
6993
* COSH(X) function https://www.sqlite.org/lang_mathfunc.html#cosh
6994
*
6995
* Example:
6996
*
6997
* auto rows = storage.select(sqlite_orm::cosh(&Triangle::cornerB)); // decltype(rows) is std::vector<double>
6998
*/
6999
template<class X>
7000
internal::built_in_function_t<double, internal::cosh_string, X> cosh(X x) {
7001
return {std::tuple<X>{std::forward<X>(x)}};
7002
}
7003
7004
/**
7005
* COSH(X) function https://www.sqlite.org/lang_mathfunc.html#cosh
7006
*
7007
* Difference with the previous function is that previous override has `double` as return type but this
7008
* override accepts return type from you as a template argument. You can use any bindable type:
7009
* `float`, `int`, `std::optional<double>` etc. This override is handy when you expect `null` as result.
7010
*
7011
* Example:
7012
*
7013
* auto rows = storage.select(sqlite_orm::cosh<std::optional<double>>(&User::rating)); // decltype(rows) is std::vector<std::optional<double>>
7014
*/
7015
template<class R, class X>
7016
internal::built_in_function_t<R, internal::cosh_string, X> cosh(X x) {
7017
return {std::tuple<X>{std::forward<X>(x)}};
7018
}
7019
7020
/**
7021
* DEGREES(X) function https://www.sqlite.org/lang_mathfunc.html#degrees
7022
*
7023
* Example:
7024
*
7025
* auto rows = storage.select(sqlite_orm::degrees(&Triangle::cornerB)); // decltype(rows) is std::vector<double>
7026
*/
7027
template<class X>
7028
internal::built_in_function_t<double, internal::degrees_string, X> degrees(X x) {
7029
return {std::tuple<X>{std::forward<X>(x)}};
7030
}
7031
7032
/**
7033
* DEGREES(X) function https://www.sqlite.org/lang_mathfunc.html#degrees
7034
*
7035
* Difference with the previous function is that previous override has `double` as return type but this
7036
* override accepts return type from you as a template argument. You can use any bindable type:
7037
* `float`, `int`, `std::optional<double>` etc. This override is handy when you expect `null` as result.
7038
*
7039
* Example:
7040
*
7041
* auto rows = storage.select(sqlite_orm::degrees<std::optional<double>>(&User::rating)); // decltype(rows) is std::vector<std::optional<double>>
7042
*/
7043
template<class R, class X>
7044
internal::built_in_function_t<R, internal::degrees_string, X> degrees(X x) {
7045
return {std::tuple<X>{std::forward<X>(x)}};
7046
}
7047
7048
/**
7049
* EXP(X) function https://www.sqlite.org/lang_mathfunc.html#exp
7050
*
7051
* Example:
7052
*
7053
* auto rows = storage.select(sqlite_orm::exp(&Triangle::cornerB)); // decltype(rows) is std::vector<double>
7054
*/
7055
template<class X>
7056
internal::built_in_function_t<double, internal::exp_string, X> exp(X x) {
7057
return {std::tuple<X>{std::forward<X>(x)}};
7058
}
7059
7060
/**
7061
* EXP(X) function https://www.sqlite.org/lang_mathfunc.html#exp
7062
*
7063
* Difference with the previous function is that previous override has `double` as return type but this
7064
* override accepts return type from you as a template argument. You can use any bindable type:
7065
* `float`, `int`, `std::optional<double>` etc. This override is handy when you expect `null` as result.
7066
*
7067
* Example:
7068
*
7069
* auto rows = storage.select(sqlite_orm::exp<std::optional<double>>(&User::rating)); // decltype(rows) is std::vector<std::optional<double>>
7070
*/
7071
template<class R, class X>
7072
internal::built_in_function_t<R, internal::exp_string, X> exp(X x) {
7073
return {std::tuple<X>{std::forward<X>(x)}};
7074
}
7075
7076
/**
7077
* FLOOR(X) function https://www.sqlite.org/lang_mathfunc.html#floor
7078
*
7079
* Example:
7080
*
7081
* auto rows = storage.select(sqlite_orm::floor(&User::rating)); // decltype(rows) is std::vector<double>
7082
*/
7083
template<class X>
7084
internal::built_in_function_t<double, internal::floor_string, X> floor(X x) {
7085
return {std::tuple<X>{std::forward<X>(x)}};
7086
}
7087
7088
/**
7089
* FLOOR(X) function https://www.sqlite.org/lang_mathfunc.html#floor
7090
*
7091
* Difference with the previous function is that previous override has `double` as return type but this
7092
* override accepts return type from you as a template argument. You can use any bindable type:
7093
* `float`, `int`, `std::optional<double>` etc. This override is handy when you expect `null` as result.
7094
*
7095
* Example:
7096
*
7097
* auto rows = storage.select(sqlite_orm::floor<std::optional<double>>(&User::rating)); // decltype(rows) is std::vector<std::optional<double>>
7098
*/
7099
template<class R, class X>
7100
internal::built_in_function_t<R, internal::floor_string, X> floor(X x) {
7101
return {std::tuple<X>{std::forward<X>(x)}};
7102
}
7103
7104
/**
7105
* LN(X) function https://www.sqlite.org/lang_mathfunc.html#ln
7106
*
7107
* Example:
7108
*
7109
* auto rows = storage.select(sqlite_orm::ln(200)); // decltype(rows) is std::vector<double>
7110
*/
7111
template<class X>
7112
internal::built_in_function_t<double, internal::ln_string, X> ln(X x) {
7113
return {std::tuple<X>{std::forward<X>(x)}};
7114
}
7115
7116
/**
7117
* LN(X) function https://www.sqlite.org/lang_mathfunc.html#ln
7118
*
7119
* Difference with the previous function is that previous override has `double` as return type but this
7120
* override accepts return type from you as a template argument. You can use any bindable type:
7121
* `float`, `int`, `std::optional<double>` etc. This override is handy when you expect `null` as result.
7122
*
7123
* Example:
7124
*
7125
* auto rows = storage.select(sqlite_orm::ln<std::optional<double>>(200)); // decltype(rows) is std::vector<std::optional<double>>
7126
*/
7127
template<class R, class X>
7128
internal::built_in_function_t<R, internal::ln_string, X> ln(X x) {
7129
return {std::tuple<X>{std::forward<X>(x)}};
7130
}
7131
7132
/**
7133
* LOG(X) function https://www.sqlite.org/lang_mathfunc.html#log
7134
*
7135
* Example:
7136
*
7137
* auto rows = storage.select(sqlite_orm::log(100)); // decltype(rows) is std::vector<double>
7138
*/
7139
template<class X>
7140
internal::built_in_function_t<double, internal::log_string, X> log(X x) {
7141
return {std::tuple<X>{std::forward<X>(x)}};
7142
}
7143
7144
/**
7145
* LOG(X) function https://www.sqlite.org/lang_mathfunc.html#log
7146
*
7147
* Difference with the previous function is that previous override has `double` as return type but this
7148
* override accepts return type from you as a template argument. You can use any bindable type:
7149
* `float`, `int`, `std::optional<double>` etc. This override is handy when you expect `null` as result.
7150
*
7151
* Example:
7152
*
7153
* auto rows = storage.select(sqlite_orm::log<std::optional<double>>(100)); // decltype(rows) is std::vector<std::optional<double>>
7154
*/
7155
template<class R, class X>
7156
internal::built_in_function_t<R, internal::log_string, X> log(X x) {
7157
return {std::tuple<X>{std::forward<X>(x)}};
7158
}
7159
7160
/**
7161
* LOG10(X) function https://www.sqlite.org/lang_mathfunc.html#log
7162
*
7163
* Example:
7164
*
7165
* auto rows = storage.select(sqlite_orm::log10(100)); // decltype(rows) is std::vector<double>
7166
*/
7167
template<class X>
7168
internal::built_in_function_t<double, internal::log10_string, X> log10(X x) {
7169
return {std::tuple<X>{std::forward<X>(x)}};
7170
}
7171
7172
/**
7173
* LOG10(X) function https://www.sqlite.org/lang_mathfunc.html#log
7174
*
7175
* Difference with the previous function is that previous override has `double` as return type but this
7176
* override accepts return type from you as a template argument. You can use any bindable type:
7177
* `float`, `int`, `std::optional<double>` etc. This override is handy when you expect `null` as result.
7178
*
7179
* Example:
7180
*
7181
* auto rows = storage.select(sqlite_orm::log10<std::optional<double>>(100)); // decltype(rows) is std::vector<std::optional<double>>
7182
*/
7183
template<class R, class X>
7184
internal::built_in_function_t<R, internal::log10_string, X> log10(X x) {
7185
return {std::tuple<X>{std::forward<X>(x)}};
7186
}
7187
7188
/**
7189
* LOG(B, X) function https://www.sqlite.org/lang_mathfunc.html#log
7190
*
7191
* Example:
7192
*
7193
* auto rows = storage.select(sqlite_orm::log(10, 100)); // decltype(rows) is std::vector<double>
7194
*/
7195
template<class B, class X>
7196
internal::built_in_function_t<double, internal::log_string, B, X> log(B b, X x) {
7197
return {std::tuple<B, X>{std::forward<B>(b), std::forward<X>(x)}};
7198
}
7199
7200
/**
7201
* LOG(B, X) function https://www.sqlite.org/lang_mathfunc.html#log
7202
*
7203
* Difference with the previous function is that previous override has `double` as return type but this
7204
* override accepts return type from you as a template argument. You can use any bindable type:
7205
* `float`, `int`, `std::optional<double>` etc. This override is handy when you expect `null` as result.
7206
*
7207
* Example:
7208
*
7209
* auto rows = storage.select(sqlite_orm::log<std::optional<double>>(10, 100)); // decltype(rows) is std::vector<std::optional<double>>
7210
*/
7211
template<class R, class B, class X>
7212
internal::built_in_function_t<R, internal::log_string, B, X> log(B b, X x) {
7213
return {std::tuple<B, X>{std::forward<B>(b), std::forward<X>(x)}};
7214
}
7215
7216
/**
7217
* LOG2(X) function https://www.sqlite.org/lang_mathfunc.html#log2
7218
*
7219
* Example:
7220
*
7221
* auto rows = storage.select(sqlite_orm::log2(64)); // decltype(rows) is std::vector<double>
7222
*/
7223
template<class X>
7224
internal::built_in_function_t<double, internal::log2_string, X> log2(X x) {
7225
return {std::tuple<X>{std::forward<X>(x)}};
7226
}
7227
7228
/**
7229
* LOG2(X) function https://www.sqlite.org/lang_mathfunc.html#log2
7230
*
7231
* Difference with the previous function is that previous override has `double` as return type but this
7232
* override accepts return type from you as a template argument. You can use any bindable type:
7233
* `float`, `int`, `std::optional<double>` etc. This override is handy when you expect `null` as result.
7234
*
7235
* Example:
7236
*
7237
* auto rows = storage.select(sqlite_orm::log2<std::optional<double>>(64)); // decltype(rows) is std::vector<std::optional<double>>
7238
*/
7239
template<class R, class X>
7240
internal::built_in_function_t<R, internal::log2_string, X> log2(X x) {
7241
return {std::tuple<X>{std::forward<X>(x)}};
7242
}
7243
7244
/**
7245
* MOD(X, Y) function https://www.sqlite.org/lang_mathfunc.html#mod
7246
*
7247
* Example:
7248
*
7249
* auto rows = storage.select(sqlite_orm::mod_f(6, 5)); // decltype(rows) is std::vector<double>
7250
*/
7251
template<class X, class Y>
7252
internal::built_in_function_t<double, internal::mod_string, X, Y> mod_f(X x, Y y) {
7253
return {std::tuple<X, Y>{std::forward<X>(x), std::forward<Y>(y)}};
7254
}
7255
7256
/**
7257
* MOD(X, Y) function https://www.sqlite.org/lang_mathfunc.html#mod
7258
*
7259
* Difference with the previous function is that previous override has `double` as return type but this
7260
* override accepts return type from you as a template argument. You can use any bindable type:
7261
* `float`, `int`, `std::optional<double>` etc. This override is handy when you expect `null` as result.
7262
*
7263
* Example:
7264
*
7265
* auto rows = storage.select(sqlite_orm::mod_f<std::optional<double>>(6, 5)); // decltype(rows) is std::vector<std::optional<double>>
7266
*/
7267
template<class R, class X, class Y>
7268
internal::built_in_function_t<R, internal::mod_string, X, Y> mod_f(X x, Y y) {
7269
return {std::tuple<X, Y>{std::forward<X>(x), std::forward<Y>(y)}};
7270
}
7271
7272
/**
7273
* PI() function https://www.sqlite.org/lang_mathfunc.html#pi
7274
*
7275
* Example:
7276
*
7277
* auto rows = storage.select(sqlite_orm::pi()); // decltype(rows) is std::vector<double>
7278
*/
7279
inline internal::built_in_function_t<double, internal::pi_string> pi() {
7280
return {{}};
7281
}
7282
7283
/**
7284
* PI() function https://www.sqlite.org/lang_mathfunc.html#pi
7285
*
7286
* Difference with the previous function is that previous override has `double` as return type but this
7287
* override accepts return type from you as a template argument. You can use any bindable type:
7288
* `float`, `int`, etc.
7289
*
7290
* Example:
7291
*
7292
* auto rows = storage.select(sqlite_orm::pi<float>()); // decltype(rows) is std::vector<float>
7293
*/
7294
template<class R>
7295
internal::built_in_function_t<R, internal::pi_string> pi() {
7296
return {{}};
7297
}
7298
7299
/**
7300
* POW(X, Y) function https://www.sqlite.org/lang_mathfunc.html#pow
7301
*
7302
* Example:
7303
*
7304
* auto rows = storage.select(sqlite_orm::pow(2, 5)); // decltype(rows) is std::vector<double>
7305
*/
7306
template<class X, class Y>
7307
internal::built_in_function_t<double, internal::pow_string, X, Y> pow(X x, Y y) {
7308
return {std::tuple<X, Y>{std::forward<X>(x), std::forward<Y>(y)}};
7309
}
7310
7311
/**
7312
* POW(X, Y) function https://www.sqlite.org/lang_mathfunc.html#pow
7313
*
7314
* Difference with the previous function is that previous override has `double` as return type but this
7315
* override accepts return type from you as a template argument. You can use any bindable type:
7316
* `float`, `int`, `std::optional<double>` etc. This override is handy when you expect `null` as result.
7317
*
7318
* Example:
7319
*
7320
* auto rows = storage.select(sqlite_orm::pow<std::optional<double>>(2, 5)); // decltype(rows) is std::vector<std::optional<double>>
7321
*/
7322
template<class R, class X, class Y>
7323
internal::built_in_function_t<R, internal::pow_string, X, Y> pow(X x, Y y) {
7324
return {std::tuple<X, Y>{std::forward<X>(x), std::forward<Y>(y)}};
7325
}
7326
7327
/**
7328
* POWER(X, Y) function https://www.sqlite.org/lang_mathfunc.html#pow
7329
*
7330
* Example:
7331
*
7332
* auto rows = storage.select(sqlite_orm::power(2, 5)); // decltype(rows) is std::vector<double>
7333
*/
7334
template<class X, class Y>
7335
internal::built_in_function_t<double, internal::power_string, X, Y> power(X x, Y y) {
7336
return {std::tuple<X, Y>{std::forward<X>(x), std::forward<Y>(y)}};
7337
}
7338
7339
/**
7340
* POWER(X, Y) function https://www.sqlite.org/lang_mathfunc.html#pow
7341
*
7342
* Difference with the previous function is that previous override has `double` as return type but this
7343
* override accepts return type from you as a template argument. You can use any bindable type:
7344
* `float`, `int`, `std::optional<double>` etc. This override is handy when you expect `null` as result.
7345
*
7346
* Example:
7347
*
7348
* auto rows = storage.select(sqlite_orm::power<std::optional<double>>(2, 5)); // decltype(rows) is std::vector<std::optional<double>>
7349
*/
7350
template<class R, class X, class Y>
7351
internal::built_in_function_t<R, internal::power_string, X, Y> power(X x, Y y) {
7352
return {std::tuple<X, Y>{std::forward<X>(x), std::forward<Y>(y)}};
7353
}
7354
7355
/**
7356
* RADIANS(X) function https://www.sqlite.org/lang_mathfunc.html#radians
7357
*
7358
* Example:
7359
*
7360
* auto rows = storage.select(sqlite_orm::radians(&Triangle::cornerAInDegrees)); // decltype(rows) is std::vector<double>
7361
*/
7362
template<class X>
7363
internal::built_in_function_t<double, internal::radians_string, X> radians(X x) {
7364
return {std::tuple<X>{std::forward<X>(x)}};
7365
}
7366
7367
/**
7368
* RADIANS(X) function https://www.sqlite.org/lang_mathfunc.html#radians
7369
*
7370
* Difference with the previous function is that previous override has `double` as return type but this
7371
* override accepts return type from you as a template argument. You can use any bindable type:
7372
* `float`, `int`, `std::optional<double>` etc. This override is handy when you expect `null` as result.
7373
*
7374
* Example:
7375
*
7376
* auto rows = storage.select(sqlite_orm::radians<std::optional<double>>(&Triangle::cornerAInDegrees)); // decltype(rows) is std::vector<std::optional<double>>
7377
*/
7378
template<class R, class X>
7379
internal::built_in_function_t<R, internal::radians_string, X> radians(X x) {
7380
return {std::tuple<X>{std::forward<X>(x)}};
7381
}
7382
7383
/**
7384
* SIN(X) function https://www.sqlite.org/lang_mathfunc.html#sin
7385
*
7386
* Example:
7387
*
7388
* auto rows = storage.select(sqlite_orm::sin(&Triangle::cornerA)); // decltype(rows) is std::vector<double>
7389
*/
7390
template<class X>
7391
internal::built_in_function_t<double, internal::sin_string, X> sin(X x) {
7392
return {std::tuple<X>{std::forward<X>(x)}};
7393
}
7394
7395
/**
7396
* SIN(X) function https://www.sqlite.org/lang_mathfunc.html#sin
7397
*
7398
* Difference with the previous function is that previous override has `double` as return type but this
7399
* override accepts return type from you as a template argument. You can use any bindable type:
7400
* `float`, `int`, `std::optional<double>` etc. This override is handy when you expect `null` as result.
7401
*
7402
* Example:
7403
*
7404
* auto rows = storage.select(sqlite_orm::sin<std::optional<double>>(&Triangle::cornerA)); // decltype(rows) is std::vector<std::optional<double>>
7405
*/
7406
template<class R, class X>
7407
internal::built_in_function_t<R, internal::sin_string, X> sin(X x) {
7408
return {std::tuple<X>{std::forward<X>(x)}};
7409
}
7410
7411
/**
7412
* SINH(X) function https://www.sqlite.org/lang_mathfunc.html#sinh
7413
*
7414
* Example:
7415
*
7416
* auto rows = storage.select(sqlite_orm::sinh(&Triangle::cornerA)); // decltype(rows) is std::vector<double>
7417
*/
7418
template<class X>
7419
internal::built_in_function_t<double, internal::sinh_string, X> sinh(X x) {
7420
return {std::tuple<X>{std::forward<X>(x)}};
7421
}
7422
7423
/**
7424
* SINH(X) function https://www.sqlite.org/lang_mathfunc.html#sinh
7425
*
7426
* Difference with the previous function is that previous override has `double` as return type but this
7427
* override accepts return type from you as a template argument. You can use any bindable type:
7428
* `float`, `int`, `std::optional<double>` etc. This override is handy when you expect `null` as result.
7429
*
7430
* Example:
7431
*
7432
* auto rows = storage.select(sqlite_orm::sinh<std::optional<double>>(&Triangle::cornerA)); // decltype(rows) is std::vector<std::optional<double>>
7433
*/
7434
template<class R, class X>
7435
internal::built_in_function_t<R, internal::sinh_string, X> sinh(X x) {
7436
return {std::tuple<X>{std::forward<X>(x)}};
7437
}
7438
7439
/**
7440
* SQRT(X) function https://www.sqlite.org/lang_mathfunc.html#sqrt
7441
*
7442
* Example:
7443
*
7444
* auto rows = storage.select(sqlite_orm::sqrt(25)); // decltype(rows) is std::vector<double>
7445
*/
7446
template<class X>
7447
internal::built_in_function_t<double, internal::sqrt_string, X> sqrt(X x) {
7448
return {std::tuple<X>{std::forward<X>(x)}};
7449
}
7450
7451
/**
7452
* SQRT(X) function https://www.sqlite.org/lang_mathfunc.html#sqrt
7453
*
7454
* Difference with the previous function is that previous override has `double` as return type but this
7455
* override accepts return type from you as a template argument. You can use any bindable type:
7456
* `float`, `int`, `std::optional<double>` etc. This override is handy when you expect `null` as result.
7457
*
7458
* Example:
7459
*
7460
* auto rows = storage.select(sqlite_orm::sqrt<int>(25)); // decltype(rows) is std::vector<int>
7461
*/
7462
template<class R, class X>
7463
internal::built_in_function_t<R, internal::sqrt_string, X> sqrt(X x) {
7464
return {std::tuple<X>{std::forward<X>(x)}};
7465
}
7466
7467
/**
7468
* TAN(X) function https://www.sqlite.org/lang_mathfunc.html#tan
7469
*
7470
* Example:
7471
*
7472
* auto rows = storage.select(sqlite_orm::tan(&Triangle::cornerC)); // decltype(rows) is std::vector<double>
7473
*/
7474
template<class X>
7475
internal::built_in_function_t<double, internal::tan_string, X> tan(X x) {
7476
return {std::tuple<X>{std::forward<X>(x)}};
7477
}
7478
7479
/**
7480
* TAN(X) function https://www.sqlite.org/lang_mathfunc.html#tan
7481
*
7482
* Difference with the previous function is that previous override has `double` as return type but this
7483
* override accepts return type from you as a template argument. You can use any bindable type:
7484
* `float`, `int`, `std::optional<double>` etc. This override is handy when you expect `null` as result.
7485
*
7486
* Example:
7487
*
7488
* auto rows = storage.select(sqlite_orm::tan<float>(&Triangle::cornerC)); // decltype(rows) is std::vector<float>
7489
*/
7490
template<class R, class X>
7491
internal::built_in_function_t<R, internal::tan_string, X> tan(X x) {
7492
return {std::tuple<X>{std::forward<X>(x)}};
7493
}
7494
7495
/**
7496
* TANH(X) function https://www.sqlite.org/lang_mathfunc.html#tanh
7497
*
7498
* Example:
7499
*
7500
* auto rows = storage.select(sqlite_orm::tanh(&Triangle::cornerC)); // decltype(rows) is std::vector<double>
7501
*/
7502
template<class X>
7503
internal::built_in_function_t<double, internal::tanh_string, X> tanh(X x) {
7504
return {std::tuple<X>{std::forward<X>(x)}};
7505
}
7506
7507
/**
7508
* TANH(X) function https://www.sqlite.org/lang_mathfunc.html#tanh
7509
*
7510
* Difference with the previous function is that previous override has `double` as return type but this
7511
* override accepts return type from you as a template argument. You can use any bindable type:
7512
* `float`, `int`, `std::optional<double>` etc. This override is handy when you expect `null` as result.
7513
*
7514
* Example:
7515
*
7516
* auto rows = storage.select(sqlite_orm::tanh<float>(&Triangle::cornerC)); // decltype(rows) is std::vector<float>
7517
*/
7518
template<class R, class X>
7519
internal::built_in_function_t<R, internal::tanh_string, X> tanh(X x) {
7520
return {std::tuple<X>{std::forward<X>(x)}};
7521
}
7522
7523
/**
7524
* TRUNC(X) function https://www.sqlite.org/lang_mathfunc.html#trunc
7525
*
7526
* Example:
7527
*
7528
* auto rows = storage.select(sqlite_orm::trunc(5.5)); // decltype(rows) is std::vector<double>
7529
*/
7530
template<class X>
7531
internal::built_in_function_t<double, internal::trunc_string, X> trunc(X x) {
7532
return {std::tuple<X>{std::forward<X>(x)}};
7533
}
7534
7535
/**
7536
* TRUNC(X) function https://www.sqlite.org/lang_mathfunc.html#trunc
7537
*
7538
* Difference with the previous function is that previous override has `double` as return type but this
7539
* override accepts return type from you as a template argument. You can use any bindable type:
7540
* `float`, `int`, `std::optional<double>` etc. This override is handy when you expect `null` as result.
7541
*
7542
* Example:
7543
*
7544
* auto rows = storage.select(sqlite_orm::trunc<float>(5.5)); // decltype(rows) is std::vector<float>
7545
*/
7546
template<class R, class X>
7547
internal::built_in_function_t<R, internal::trunc_string, X> trunc(X x) {
7548
return {std::tuple<X>{std::forward<X>(x)}};
7549
}
7550
#endif // SQLITE_ENABLE_MATH_FUNCTIONS
7551
/**
7552
* TYPEOF(x) function https://sqlite.org/lang_corefunc.html#typeof
7553
*/
7554
template<class T>
7555
internal::built_in_function_t<std::string, internal::typeof_string, T> typeof_(T t) {
7556
return {std::tuple<T>{std::forward<T>(t)}};
7557
}
7558
7559
/**
7560
* UNICODE(x) function https://sqlite.org/lang_corefunc.html#unicode
7561
*/
7562
template<class T>
7563
internal::built_in_function_t<int, internal::unicode_string, T> unicode(T t) {
7564
return {std::tuple<T>{std::forward<T>(t)}};
7565
}
7566
7567
/**
7568
* LENGTH(x) function https://sqlite.org/lang_corefunc.html#length
7569
*/
7570
template<class T>
7571
internal::built_in_function_t<int, internal::length_string, T> length(T t) {
7572
return {std::tuple<T>{std::forward<T>(t)}};
7573
}
7574
7575
/**
7576
* ABS(x) function https://sqlite.org/lang_corefunc.html#abs
7577
*/
7578
template<class T>
7579
internal::built_in_function_t<std::unique_ptr<double>, internal::abs_string, T> abs(T t) {
7580
return {std::tuple<T>{std::forward<T>(t)}};
7581
}
7582
7583
/**
7584
* LOWER(x) function https://sqlite.org/lang_corefunc.html#lower
7585
*/
7586
template<class T>
7587
internal::built_in_function_t<std::string, internal::lower_string, T> lower(T t) {
7588
return {std::tuple<T>{std::forward<T>(t)}};
7589
}
7590
7591
/**
7592
* UPPER(x) function https://sqlite.org/lang_corefunc.html#upper
7593
*/
7594
template<class T>
7595
internal::built_in_function_t<std::string, internal::upper_string, T> upper(T t) {
7596
return {std::tuple<T>{std::forward<T>(t)}};
7597
}
7598
7599
/**
7600
* LAST_INSERT_ROWID(x) function https://www.sqlite.org/lang_corefunc.html#last_insert_rowid
7601
*/
7602
inline internal::built_in_function_t<int64, internal::last_insert_rowid_string> last_insert_rowid() {
7603
return {{}};
7604
}
7605
7606
/**
7607
* TOTAL_CHANGES() function https://sqlite.org/lang_corefunc.html#total_changes
7608
*/
7609
inline internal::built_in_function_t<int, internal::total_changes_string> total_changes() {
7610
return {{}};
7611
}
7612
7613
/**
7614
* CHANGES() function https://sqlite.org/lang_corefunc.html#changes
7615
*/
7616
inline internal::built_in_function_t<int, internal::changes_string> changes() {
7617
return {{}};
7618
}
7619
7620
/**
7621
* TRIM(X) function https://sqlite.org/lang_corefunc.html#trim
7622
*/
7623
template<class T>
7624
internal::built_in_function_t<std::string, internal::trim_string, T> trim(T t) {
7625
return {std::tuple<T>{std::forward<T>(t)}};
7626
}
7627
7628
/**
7629
* TRIM(X,Y) function https://sqlite.org/lang_corefunc.html#trim
7630
*/
7631
template<class X, class Y>
7632
internal::built_in_function_t<std::string, internal::trim_string, X, Y> trim(X x, Y y) {
7633
return {std::tuple<X, Y>{std::forward<X>(x), std::forward<Y>(y)}};
7634
}
7635
7636
/**
7637
* LTRIM(X) function https://sqlite.org/lang_corefunc.html#ltrim
7638
*/
7639
template<class X>
7640
internal::built_in_function_t<std::string, internal::ltrim_string, X> ltrim(X x) {
7641
return {std::tuple<X>{std::forward<X>(x)}};
7642
}
7643
7644
/**
7645
* LTRIM(X,Y) function https://sqlite.org/lang_corefunc.html#ltrim
7646
*/
7647
template<class X, class Y>
7648
internal::built_in_function_t<std::string, internal::ltrim_string, X, Y> ltrim(X x, Y y) {
7649
return {std::tuple<X, Y>{std::forward<X>(x), std::forward<Y>(y)}};
7650
}
7651
7652
/**
7653
* RTRIM(X) function https://sqlite.org/lang_corefunc.html#rtrim
7654
*/
7655
template<class X>
7656
internal::built_in_function_t<std::string, internal::rtrim_string, X> rtrim(X x) {
7657
return {std::tuple<X>{std::forward<X>(x)}};
7658
}
7659
7660
/**
7661
* RTRIM(X,Y) function https://sqlite.org/lang_corefunc.html#rtrim
7662
*/
7663
template<class X, class Y>
7664
internal::built_in_function_t<std::string, internal::rtrim_string, X, Y> rtrim(X x, Y y) {
7665
return {std::tuple<X, Y>{std::forward<X>(x), std::forward<Y>(y)}};
7666
}
7667
7668
/**
7669
* HEX(X) function https://sqlite.org/lang_corefunc.html#hex
7670
*/
7671
template<class X>
7672
internal::built_in_function_t<std::string, internal::hex_string, X> hex(X x) {
7673
return {std::tuple<X>{std::forward<X>(x)}};
7674
}
7675
7676
/**
7677
* QUOTE(X) function https://sqlite.org/lang_corefunc.html#quote
7678
*/
7679
template<class X>
7680
internal::built_in_function_t<std::string, internal::quote_string, X> quote(X x) {
7681
return {std::tuple<X>{std::forward<X>(x)}};
7682
}
7683
7684
/**
7685
* RANDOMBLOB(X) function https://sqlite.org/lang_corefunc.html#randomblob
7686
*/
7687
template<class X>
7688
internal::built_in_function_t<std::vector<char>, internal::randomblob_string, X> randomblob(X x) {
7689
return {std::tuple<X>{std::forward<X>(x)}};
7690
}
7691
7692
/**
7693
* INSTR(X) function https://sqlite.org/lang_corefunc.html#instr
7694
*/
7695
template<class X, class Y>
7696
internal::built_in_function_t<int, internal::instr_string, X, Y> instr(X x, Y y) {
7697
return {std::tuple<X, Y>{std::forward<X>(x), std::forward<Y>(y)}};
7698
}
7699
7700
/**
7701
* REPLACE(X) function https://sqlite.org/lang_corefunc.html#replace
7702
*/
7703
template<class X,
7704
class Y,
7705
class Z,
7706
std::enable_if_t<internal::count_tuple<std::tuple<X, Y, Z>, internal::is_into>::value == 0, bool> = true>
7707
internal::built_in_function_t<std::string, internal::replace_string, X, Y, Z> replace(X x, Y y, Z z) {
7708
return {std::tuple<X, Y, Z>{std::forward<X>(x), std::forward<Y>(y), std::forward<Z>(z)}};
7709
}
7710
7711
/**
7712
* ROUND(X) function https://sqlite.org/lang_corefunc.html#round
7713
*/
7714
template<class X>
7715
internal::built_in_function_t<double, internal::round_string, X> round(X x) {
7716
return {std::tuple<X>{std::forward<X>(x)}};
7717
}
7718
7719
/**
7720
* ROUND(X, Y) function https://sqlite.org/lang_corefunc.html#round
7721
*/
7722
template<class X, class Y>
7723
internal::built_in_function_t<double, internal::round_string, X, Y> round(X x, Y y) {
7724
return {std::tuple<X, Y>{std::forward<X>(x), std::forward<Y>(y)}};
7725
}
7726
7727
#if SQLITE_VERSION_NUMBER >= 3007016
7728
/**
7729
* CHAR(X1,X2,...,XN) function https://sqlite.org/lang_corefunc.html#char
7730
*/
7731
template<class... Args>
7732
internal::built_in_function_t<std::string, internal::char_string, Args...> char_(Args... args) {
7733
return {std::make_tuple(std::forward<Args>(args)...)};
7734
}
7735
7736
/**
7737
* RANDOM() function https://www.sqlite.org/lang_corefunc.html#random
7738
*/
7739
inline internal::built_in_function_t<int, internal::random_string> random() {
7740
return {{}};
7741
}
7742
#endif
7743
7744
/**
7745
* COALESCE(X,Y,...) function https://www.sqlite.org/lang_corefunc.html#coalesce
7746
*/
7747
template<class R = void, class... Args>
7748
auto coalesce(Args... args)
7749
-> internal::built_in_function_t<typename mpl::conditional_t< // choose R or common type
7750
std::is_void<R>::value,
7751
std::common_type<internal::field_type_or_type_t<Args>...>,
7752
polyfill::type_identity<R>>::type,
7753
internal::coalesce_string,
7754
Args...> {
7755
return {std::make_tuple(std::forward<Args>(args)...)};
7756
}
7757
7758
/**
7759
* IFNULL(X,Y) function https://www.sqlite.org/lang_corefunc.html#ifnull
7760
*/
7761
template<class R = void, class X, class Y>
7762
auto ifnull(X x, Y y) -> internal::built_in_function_t<
7763
typename mpl::conditional_t< // choose R or common type
7764
std::is_void<R>::value,
7765
std::common_type<internal::field_type_or_type_t<X>, internal::field_type_or_type_t<Y>>,
7766
polyfill::type_identity<R>>::type,
7767
internal::ifnull_string,
7768
X,
7769
Y> {
7770
return {std::make_tuple(std::move(x), std::move(y))};
7771
}
7772
7773
/**
7774
* NULLIF(X,Y) function https://www.sqlite.org/lang_corefunc.html#nullif
7775
*/
7776
#if defined(SQLITE_ORM_OPTIONAL_SUPPORTED) && defined(SQLITE_ORM_IF_CONSTEXPR_SUPPORTED)
7777
/**
7778
* NULLIF(X,Y) using common return type of X and Y
7779
*/
7780
template<class R = void,
7781
class X,
7782
class Y,
7783
std::enable_if_t<polyfill::disjunction_v<polyfill::negation<std::is_void<R>>,
7784
polyfill::is_detected<std::common_type_t,
7785
internal::field_type_or_type_t<X>,
7786
internal::field_type_or_type_t<Y>>>,
7787
bool> = true>
7788
auto nullif(X x, Y y) {
7789
if constexpr (std::is_void_v<R>) {
7790
using F = internal::built_in_function_t<
7791
std::optional<std::common_type_t<internal::field_type_or_type_t<X>, internal::field_type_or_type_t<Y>>>,
7792
internal::nullif_string,
7793
X,
7794
Y>;
7795
7796
return F{std::make_tuple(std::move(x), std::move(y))};
7797
} else {
7798
using F = internal::built_in_function_t<R, internal::nullif_string, X, Y>;
7799
7800
return F{std::make_tuple(std::move(x), std::move(y))};
7801
}
7802
}
7803
#else
7804
template<class R, class X, class Y>
7805
internal::built_in_function_t<R, internal::nullif_string, X, Y> nullif(X x, Y y) {
7806
return {std::make_tuple(std::move(x), std::move(y))};
7807
}
7808
#endif
7809
7810
/**
7811
* DATE(timestring, modifier, modifier, ...) function https://www.sqlite.org/lang_datefunc.html
7812
*/
7813
template<class... Args>
7814
internal::built_in_function_t<std::string, internal::date_string, Args...> date(Args... args) {
7815
return {std::tuple<Args...>{std::forward<Args>(args)...}};
7816
}
7817
7818
/**
7819
* TIME(timestring, modifier, modifier, ...) function https://www.sqlite.org/lang_datefunc.html
7820
*/
7821
template<class... Args>
7822
internal::built_in_function_t<std::string, internal::time_string, Args...> time(Args... args) {
7823
return {std::tuple<Args...>{std::forward<Args>(args)...}};
7824
}
7825
7826
/**
7827
* DATETIME(timestring, modifier, modifier, ...) function https://www.sqlite.org/lang_datefunc.html
7828
*/
7829
template<class... Args>
7830
internal::built_in_function_t<std::string, internal::datetime_string, Args...> datetime(Args... args) {
7831
return {std::tuple<Args...>{std::forward<Args>(args)...}};
7832
}
7833
7834
/**
7835
* JULIANDAY(timestring, modifier, modifier, ...) function https://www.sqlite.org/lang_datefunc.html
7836
*/
7837
template<class... Args>
7838
internal::built_in_function_t<double, internal::julianday_string, Args...> julianday(Args... args) {
7839
return {std::tuple<Args...>{std::forward<Args>(args)...}};
7840
}
7841
7842
/**
7843
* STRFTIME(timestring, modifier, modifier, ...) function https://www.sqlite.org/lang_datefunc.html
7844
*/
7845
template<class... Args>
7846
internal::built_in_function_t<std::string, internal::strftime_string, Args...> strftime(Args... args) {
7847
return {std::tuple<Args...>{std::forward<Args>(args)...}};
7848
}
7849
7850
/**
7851
* ZEROBLOB(N) function https://www.sqlite.org/lang_corefunc.html#zeroblob
7852
*/
7853
template<class N>
7854
internal::built_in_function_t<std::vector<char>, internal::zeroblob_string, N> zeroblob(N n) {
7855
return {std::tuple<N>{std::forward<N>(n)}};
7856
}
7857
7858
/**
7859
* SUBSTR(X,Y) function https://www.sqlite.org/lang_corefunc.html#substr
7860
*/
7861
template<class X, class Y>
7862
internal::built_in_function_t<std::string, internal::substr_string, X, Y> substr(X x, Y y) {
7863
return {std::tuple<X, Y>{std::forward<X>(x), std::forward<Y>(y)}};
7864
}
7865
7866
/**
7867
* SUBSTR(X,Y,Z) function https://www.sqlite.org/lang_corefunc.html#substr
7868
*/
7869
template<class X, class Y, class Z>
7870
internal::built_in_function_t<std::string, internal::substr_string, X, Y, Z> substr(X x, Y y, Z z) {
7871
return {std::tuple<X, Y, Z>{std::forward<X>(x), std::forward<Y>(y), std::forward<Z>(z)}};
7872
}
7873
7874
#ifdef SQLITE_SOUNDEX
7875
/**
7876
* SOUNDEX(X) function https://www.sqlite.org/lang_corefunc.html#soundex
7877
*/
7878
template<class X>
7879
internal::built_in_function_t<std::string, internal::soundex_string, X> soundex(X x) {
7880
return {std::tuple<X>{std::forward<X>(x)}};
7881
}
7882
#endif
7883
7884
/**
7885
* TOTAL(X) aggregate function.
7886
*/
7887
template<class X>
7888
internal::built_in_aggregate_function_t<double, internal::total_string, X> total(X x) {
7889
return {std::tuple<X>{std::forward<X>(x)}};
7890
}
7891
7892
/**
7893
* SUM(X) aggregate function.
7894
*/
7895
template<class X>
7896
internal::built_in_aggregate_function_t<std::unique_ptr<double>, internal::sum_string, X> sum(X x) {
7897
return {std::tuple<X>{std::forward<X>(x)}};
7898
}
7899
7900
/**
7901
* COUNT(X) aggregate function.
7902
*/
7903
template<class X>
7904
internal::built_in_aggregate_function_t<int, internal::count_string, X> count(X x) {
7905
return {std::tuple<X>{std::forward<X>(x)}};
7906
}
7907
7908
/**
7909
* COUNT(*) without FROM function.
7910
*/
7911
inline internal::count_asterisk_without_type count() {
7912
return {};
7913
}
7914
7915
/**
7916
* COUNT(*) with FROM function. Specified type T will be serialized as
7917
* a from argument.
7918
*/
7919
template<class T>
7920
internal::count_asterisk_t<T> count() {
7921
return {};
7922
}
7923
7924
#ifdef SQLITE_ORM_WITH_CPP20_ALIASES
7925
/**
7926
* COUNT(*) with FROM function. Specified recordset will be serialized as
7927
* a from argument.
7928
*/
7929
template<orm_refers_to_recordset auto mapped>
7930
auto count() {
7931
return count<internal::auto_decay_table_ref_t<mapped>>();
7932
}
7933
#endif
7934
7935
/**
7936
* AVG(X) aggregate function.
7937
*/
7938
template<class X>
7939
internal::built_in_aggregate_function_t<double, internal::avg_string, X> avg(X x) {
7940
return {std::tuple<X>{std::forward<X>(x)}};
7941
}
7942
7943
/**
7944
* MAX(X) aggregate function.
7945
*/
7946
template<class X>
7947
internal::built_in_aggregate_function_t<internal::unique_ptr_result_of<X>, internal::max_string, X> max(X x) {
7948
return {std::tuple<X>{std::forward<X>(x)}};
7949
}
7950
7951
/**
7952
* MIN(X) aggregate function.
7953
*/
7954
template<class X>
7955
internal::built_in_aggregate_function_t<internal::unique_ptr_result_of<X>, internal::min_string, X> min(X x) {
7956
return {std::tuple<X>{std::forward<X>(x)}};
7957
}
7958
7959
/**
7960
* MAX(X, Y, ...) scalar function.
7961
* The return type is the type of the first argument.
7962
*/
7963
template<class X, class Y, class... Rest>
7964
internal::built_in_function_t<internal::unique_ptr_result_of<X>, internal::max_string, X, Y, Rest...>
7965
max(X x, Y y, Rest... rest) {
7966
return {std::tuple<X, Y, Rest...>{std::forward<X>(x), std::forward<Y>(y), std::forward<Rest>(rest)...}};
7967
}
7968
7969
/**
7970
* MIN(X, Y, ...) scalar function.
7971
* The return type is the type of the first argument.
7972
*/
7973
template<class X, class Y, class... Rest>
7974
internal::built_in_function_t<internal::unique_ptr_result_of<X>, internal::min_string, X, Y, Rest...>
7975
min(X x, Y y, Rest... rest) {
7976
return {std::tuple<X, Y, Rest...>{std::forward<X>(x), std::forward<Y>(y), std::forward<Rest>(rest)...}};
7977
}
7978
7979
/**
7980
* GROUP_CONCAT(X) aggregate function.
7981
*/
7982
template<class X>
7983
internal::built_in_aggregate_function_t<std::string, internal::group_concat_string, X> group_concat(X x) {
7984
return {std::tuple<X>{std::forward<X>(x)}};
7985
}
7986
7987
/**
7988
* GROUP_CONCAT(X, Y) aggregate function.
7989
*/
7990
template<class X, class Y>
7991
internal::built_in_aggregate_function_t<std::string, internal::group_concat_string, X, Y> group_concat(X x, Y y) {
7992
return {std::tuple<X, Y>{std::forward<X>(x), std::forward<Y>(y)}};
7993
}
7994
#ifdef SQLITE_ENABLE_JSON1
7995
template<class X>
7996
internal::built_in_function_t<std::string, internal::json_string, X> json(X x) {
7997
return {std::tuple<X>{std::forward<X>(x)}};
7998
}
7999
8000
template<class... Args>
8001
internal::built_in_function_t<std::string, internal::json_array_string, Args...> json_array(Args... args) {
8002
return {std::tuple<Args...>{std::forward<Args>(args)...}};
8003
}
8004
8005
template<class X>
8006
internal::built_in_function_t<int, internal::json_array_length_string, X> json_array_length(X x) {
8007
return {std::tuple<X>{std::forward<X>(x)}};
8008
}
8009
8010
template<class R, class X>
8011
internal::built_in_function_t<R, internal::json_array_length_string, X> json_array_length(X x) {
8012
return {std::tuple<X>{std::forward<X>(x)}};
8013
}
8014
8015
template<class X, class Y>
8016
internal::built_in_function_t<int, internal::json_array_length_string, X, Y> json_array_length(X x, Y y) {
8017
return {std::tuple<X, Y>{std::forward<X>(x), std::forward<Y>(y)}};
8018
}
8019
8020
template<class R, class X, class Y>
8021
internal::built_in_function_t<R, internal::json_array_length_string, X, Y> json_array_length(X x, Y y) {
8022
return {std::tuple<X, Y>{std::forward<X>(x), std::forward<Y>(y)}};
8023
}
8024
8025
template<class R, class X, class... Args>
8026
internal::built_in_function_t<R, internal::json_extract_string, X, Args...> json_extract(X x, Args... args) {
8027
return {std::tuple<X, Args...>{std::forward<X>(x), std::forward<Args>(args)...}};
8028
}
8029
8030
template<class X, class... Args>
8031
internal::built_in_function_t<std::string, internal::json_insert_string, X, Args...> json_insert(X x,
8032
Args... args) {
8033
static_assert(std::tuple_size<std::tuple<Args...>>::value % 2 == 0,
8034
"number of arguments in json_insert must be odd");
8035
return {std::tuple<X, Args...>{std::forward<X>(x), std::forward<Args>(args)...}};
8036
}
8037
8038
template<class X, class... Args>
8039
internal::built_in_function_t<std::string, internal::json_replace_string, X, Args...> json_replace(X x,
8040
Args... args) {
8041
static_assert(std::tuple_size<std::tuple<Args...>>::value % 2 == 0,
8042
"number of arguments in json_replace must be odd");
8043
return {std::tuple<X, Args...>{std::forward<X>(x), std::forward<Args>(args)...}};
8044
}
8045
8046
template<class X, class... Args>
8047
internal::built_in_function_t<std::string, internal::json_set_string, X, Args...> json_set(X x, Args... args) {
8048
static_assert(std::tuple_size<std::tuple<Args...>>::value % 2 == 0,
8049
"number of arguments in json_set must be odd");
8050
return {std::tuple<X, Args...>{std::forward<X>(x), std::forward<Args>(args)...}};
8051
}
8052
8053
template<class... Args>
8054
internal::built_in_function_t<std::string, internal::json_object_string, Args...> json_object(Args... args) {
8055
static_assert(std::tuple_size<std::tuple<Args...>>::value % 2 == 0,
8056
"number of arguments in json_object must be even");
8057
return {std::tuple<Args...>{std::forward<Args>(args)...}};
8058
}
8059
8060
template<class X, class Y>
8061
internal::built_in_function_t<std::string, internal::json_patch_string, X, Y> json_patch(X x, Y y) {
8062
return {std::tuple<X, Y>{std::forward<X>(x), std::forward<Y>(y)}};
8063
}
8064
8065
template<class X, class... Args>
8066
internal::built_in_function_t<std::string, internal::json_remove_string, X, Args...> json_remove(X x,
8067
Args... args) {
8068
return {std::tuple<X, Args...>{std::forward<X>(x), std::forward<Args>(args)...}};
8069
}
8070
8071
template<class R, class X, class... Args>
8072
internal::built_in_function_t<R, internal::json_remove_string, X, Args...> json_remove(X x, Args... args) {
8073
return {std::tuple<X, Args...>{std::forward<X>(x), std::forward<Args>(args)...}};
8074
}
8075
8076
template<class X>
8077
internal::built_in_function_t<std::string, internal::json_type_string, X> json_type(X x) {
8078
return {std::tuple<X>{std::forward<X>(x)}};
8079
}
8080
8081
template<class R, class X>
8082
internal::built_in_function_t<R, internal::json_type_string, X> json_type(X x) {
8083
return {std::tuple<X>{std::forward<X>(x)}};
8084
}
8085
8086
template<class X, class Y>
8087
internal::built_in_function_t<std::string, internal::json_type_string, X, Y> json_type(X x, Y y) {
8088
return {std::tuple<X, Y>{std::forward<X>(x), std::forward<Y>(y)}};
8089
}
8090
8091
template<class R, class X, class Y>
8092
internal::built_in_function_t<R, internal::json_type_string, X, Y> json_type(X x, Y y) {
8093
return {std::tuple<X, Y>{std::forward<X>(x), std::forward<Y>(y)}};
8094
}
8095
8096
template<class X>
8097
internal::built_in_function_t<bool, internal::json_valid_string, X> json_valid(X x) {
8098
return {std::tuple<X>{std::forward<X>(x)}};
8099
}
8100
8101
template<class R, class X>
8102
internal::built_in_function_t<R, internal::json_quote_string, X> json_quote(X x) {
8103
return {std::tuple<X>{std::forward<X>(x)}};
8104
}
8105
8106
template<class X>
8107
internal::built_in_function_t<std::string, internal::json_group_array_string, X> json_group_array(X x) {
8108
return {std::tuple<X>{std::forward<X>(x)}};
8109
}
8110
8111
template<class X, class Y>
8112
internal::built_in_function_t<std::string, internal::json_group_object_string, X, Y> json_group_object(X x, Y y) {
8113
return {std::tuple<X, Y>{std::forward<X>(x), std::forward<Y>(y)}};
8114
}
8115
#endif // SQLITE_ENABLE_JSON1
8116
8117
// Intentionally place operators for types classified as arithmetic or general operator arguments in the internal namespace
8118
// to facilitate ADL (Argument Dependent Lookup)
8119
namespace internal {
8120
template<
8121
class T,
8122
std::enable_if_t<polyfill::disjunction<std::is_base_of<arithmetic_t, T>, is_operator_argument<T>>::value,
8123
bool> = true>
8124
constexpr unary_minus_t<unwrap_expression_t<T>> operator-(T arg) {
8125
return {get_from_expression(std::forward<T>(arg))};
8126
}
8127
8128
template<class L,
8129
class R,
8130
std::enable_if_t<polyfill::disjunction<std::is_base_of<arithmetic_t, L>,
8131
std::is_base_of<arithmetic_t, R>,
8132
is_operator_argument<L>,
8133
is_operator_argument<R>>::value,
8134
bool> = true>
8135
constexpr add_t<unwrap_expression_t<L>, unwrap_expression_t<R>> operator+(L l, R r) {
8136
return {get_from_expression(std::forward<L>(l)), get_from_expression(std::forward<R>(r))};
8137
}
8138
8139
template<class L,
8140
class R,
8141
std::enable_if_t<polyfill::disjunction<std::is_base_of<arithmetic_t, L>,
8142
std::is_base_of<arithmetic_t, R>,
8143
is_operator_argument<L>,
8144
is_operator_argument<R>>::value,
8145
bool> = true>
8146
constexpr sub_t<unwrap_expression_t<L>, unwrap_expression_t<R>> operator-(L l, R r) {
8147
return {get_from_expression(std::forward<L>(l)), get_from_expression(std::forward<R>(r))};
8148
}
8149
8150
template<class L,
8151
class R,
8152
std::enable_if_t<polyfill::disjunction<std::is_base_of<arithmetic_t, L>,
8153
std::is_base_of<arithmetic_t, R>,
8154
is_operator_argument<L>,
8155
is_operator_argument<R>>::value,
8156
bool> = true>
8157
constexpr mul_t<unwrap_expression_t<L>, unwrap_expression_t<R>> operator*(L l, R r) {
8158
return {get_from_expression(std::forward<L>(l)), get_from_expression(std::forward<R>(r))};
8159
}
8160
8161
template<class L,
8162
class R,
8163
std::enable_if_t<polyfill::disjunction<std::is_base_of<arithmetic_t, L>,
8164
std::is_base_of<arithmetic_t, R>,
8165
is_operator_argument<L>,
8166
is_operator_argument<R>>::value,
8167
bool> = true>
8168
constexpr div_t<unwrap_expression_t<L>, unwrap_expression_t<R>> operator/(L l, R r) {
8169
return {get_from_expression(std::forward<L>(l)), get_from_expression(std::forward<R>(r))};
8170
}
8171
8172
template<class L,
8173
class R,
8174
std::enable_if_t<polyfill::disjunction<std::is_base_of<arithmetic_t, L>,
8175
std::is_base_of<arithmetic_t, R>,
8176
is_operator_argument<L>,
8177
is_operator_argument<R>>::value,
8178
bool> = true>
8179
constexpr mod_t<unwrap_expression_t<L>, unwrap_expression_t<R>> operator%(L l, R r) {
8180
return {get_from_expression(std::forward<L>(l)), get_from_expression(std::forward<R>(r))};
8181
}
8182
8183
template<
8184
class T,
8185
std::enable_if_t<polyfill::disjunction<std::is_base_of<arithmetic_t, T>, is_operator_argument<T>>::value,
8186
bool> = true>
8187
constexpr bitwise_not_t<unwrap_expression_t<T>> operator~(T arg) {
8188
return {get_from_expression(std::forward<T>(arg))};
8189
}
8190
8191
template<class L,
8192
class R,
8193
std::enable_if_t<polyfill::disjunction<std::is_base_of<arithmetic_t, L>,
8194
std::is_base_of<arithmetic_t, R>,
8195
is_operator_argument<L>,
8196
is_operator_argument<R>>::value,
8197
bool> = true>
8198
constexpr bitwise_shift_left_t<unwrap_expression_t<L>, unwrap_expression_t<R>> operator<<(L l, R r) {
8199
return {get_from_expression(std::forward<L>(l)), get_from_expression(std::forward<R>(r))};
8200
}
8201
8202
template<class L,
8203
class R,
8204
std::enable_if_t<polyfill::disjunction<std::is_base_of<arithmetic_t, L>,
8205
std::is_base_of<arithmetic_t, R>,
8206
is_operator_argument<L>,
8207
is_operator_argument<R>>::value,
8208
bool> = true>
8209
constexpr bitwise_shift_right_t<unwrap_expression_t<L>, unwrap_expression_t<R>> operator>>(L l, R r) {
8210
return {get_from_expression(std::forward<L>(l)), get_from_expression(std::forward<R>(r))};
8211
}
8212
8213
template<class L,
8214
class R,
8215
std::enable_if_t<polyfill::disjunction<std::is_base_of<arithmetic_t, L>,
8216
std::is_base_of<arithmetic_t, R>,
8217
is_operator_argument<L>,
8218
is_operator_argument<R>>::value,
8219
bool> = true>
8220
constexpr bitwise_and_t<unwrap_expression_t<L>, unwrap_expression_t<R>> operator&(L l, R r) {
8221
return {get_from_expression(std::forward<L>(l)), get_from_expression(std::forward<R>(r))};
8222
}
8223
8224
template<class L,
8225
class R,
8226
std::enable_if_t<polyfill::disjunction<std::is_base_of<arithmetic_t, L>,
8227
std::is_base_of<arithmetic_t, R>,
8228
is_operator_argument<L>,
8229
is_operator_argument<R>>::value,
8230
bool> = true>
8231
constexpr bitwise_or_t<unwrap_expression_t<L>, unwrap_expression_t<R>> operator|(L l, R r) {
8232
return {get_from_expression(std::forward<L>(l)), get_from_expression(std::forward<R>(r))};
8233
}
8234
}
8235
8236
template<class T, class X, class Y, class Z>
8237
internal::highlight_t<T, X, Y, Z> highlight(X x, Y y, Z z) {
8238
return {std::move(x), std::move(y), std::move(z)};
8239
}
8240
}
8241
8242
// #include "alias_traits.h"
8243
8244
// #include "cte_moniker.h"
8245
8246
#if (SQLITE_VERSION_NUMBER >= 3008003) && defined(SQLITE_ORM_WITH_CTE)
8247
#ifdef SQLITE_ORM_WITH_CPP20_ALIASES
8248
#include <concepts>
8249
#include <utility> // std::make_index_sequence
8250
#endif
8251
#include <type_traits> // std::enable_if, std::is_member_pointer, std::is_same, std::is_convertible
8252
#include <tuple> // std::ignore
8253
#include <string>
8254
#endif
8255
8256
// #include "functional/cstring_literal.h"
8257
8258
// #include "alias.h"
8259
8260
#if (SQLITE_VERSION_NUMBER >= 3008003) && defined(SQLITE_ORM_WITH_CTE)
8261
namespace sqlite_orm {
8262
8263
namespace internal {
8264
/**
8265
* A special record set alias that is both, a storage lookup type (mapping type) and an alias.
8266
*/
8267
template<char A, char... X>
8268
struct cte_moniker
8269
: recordset_alias<
8270
cte_moniker<A, X...> /* refer to self, since a moniker is both, an alias and a mapped type */,
8271
A,
8272
X...> {
8273
/**
8274
* Introduce the construction of a common table expression using this moniker.
8275
*
8276
* The list of explicit columns is optional;
8277
* if provided the number of columns must match the number of columns of the subselect.
8278
* The column names will be merged with the subselect:
8279
* 1. column names of subselect
8280
* 2. explicit columns
8281
* 3. fill in empty column names with column index
8282
*
8283
* Example:
8284
* 1_ctealias()(select(&Object::id));
8285
* 1_ctealias(&Object::name)(select("object"));
8286
*
8287
* @return A `cte_builder` instance.
8288
* @note (internal): Defined in select_constraints.h in order to keep this member function in the same place as the named factory function `cte()`,
8289
* and to keep the actual creation of the builder in one place.
8290
*/
8291
#ifdef SQLITE_ORM_WITH_CPP20_ALIASES
8292
template<class... ExplicitCols>
8293
requires ((is_column_alias_v<ExplicitCols> || std::is_member_pointer_v<ExplicitCols> ||
8294
std::same_as<ExplicitCols, std::remove_cvref_t<decltype(std::ignore)>> ||
8295
std::convertible_to<ExplicitCols, std::string>) &&
8296
...)
8297
constexpr auto operator()(ExplicitCols... explicitColumns) const;
8298
#else
8299
template<class... ExplicitCols,
8300
std::enable_if_t<polyfill::conjunction_v<polyfill::disjunction<
8301
is_column_alias<ExplicitCols>,
8302
std::is_member_pointer<ExplicitCols>,
8303
std::is_same<ExplicitCols, polyfill::remove_cvref_t<decltype(std::ignore)>>,
8304
std::is_convertible<ExplicitCols, std::string>>...>,
8305
bool> = true>
8306
constexpr auto operator()(ExplicitCols... explicitColumns) const;
8307
#endif
8308
};
8309
}
8310
8311
inline namespace literals {
8312
/**
8313
* cte_moniker<'n'> from a numeric literal.
8314
* E.g. 1_ctealias, 2_ctealias
8315
*/
8316
template<char... Chars>
8317
[[nodiscard]] SQLITE_ORM_CONSTEVAL auto operator"" _ctealias() {
8318
return internal::cte_moniker<Chars...>{};
8319
}
8320
8321
#ifdef SQLITE_ORM_WITH_CPP20_ALIASES
8322
/**
8323
* cte_moniker<'1'[, ...]> from a string literal.
8324
* E.g. "1"_cte, "2"_cte
8325
*/
8326
template<internal::cstring_literal moniker>
8327
[[nodiscard]] consteval auto operator"" _cte() {
8328
return internal::explode_into<internal::cte_moniker, moniker>(std::make_index_sequence<moniker.size()>{});
8329
}
8330
#endif
8331
}
8332
}
8333
#endif
8334
8335
// #include "schema/column.h"
8336
8337
#include <tuple> // std::tuple
8338
#include <string> // std::string
8339
#include <memory> // std::unique_ptr
8340
#include <type_traits> // std::is_same, std::is_member_object_pointer
8341
#include <utility> // std::move
8342
8343
// #include "../functional/cxx_type_traits_polyfill.h"
8344
8345
// #include "../tuple_helper/tuple_traits.h"
8346
8347
// #include "../tuple_helper/tuple_filter.h"
8348
8349
// #include "../type_traits.h"
8350
8351
// #include "../member_traits/member_traits.h"
8352
8353
// #include "../type_is_nullable.h"
8354
8355
#include <type_traits> // std::false_type, std::true_type, std::enable_if
8356
#include <memory> // std::shared_ptr, std::unique_ptr
8357
// #include "functional/cxx_optional.h"
8358
8359
// #include "functional/cxx_type_traits_polyfill.h"
8360
8361
namespace sqlite_orm {
8362
8363
/**
8364
* This is class that tells `sqlite_orm` that type is nullable. Nullable types
8365
* are mapped to sqlite database as `NULL` and not-nullable are mapped as `NOT NULL`.
8366
* Default nullability status for all types is `NOT NULL`. So if you want to map
8367
* custom type as `NULL` (for example: boost::optional) you have to create a specialization
8368
* of `type_is_nullable` for your type and derive from `std::true_type`.
8369
*/
8370
template<class T, class SFINAE = void>
8371
struct type_is_nullable : std::false_type {
8372
bool operator()(const T&) const {
8373
return true;
8374
}
8375
};
8376
8377
/**
8378
* This is a specialization for std::shared_ptr, std::unique_ptr, std::optional, which are nullable in sqlite_orm.
8379
*/
8380
template<class T>
8381
struct type_is_nullable<T,
8382
std::enable_if_t<polyfill::disjunction<
8383
#ifdef SQLITE_ORM_OPTIONAL_SUPPORTED
8384
polyfill::is_specialization_of<T, std::optional>,
8385
#endif
8386
polyfill::is_specialization_of<T, std::unique_ptr>,
8387
polyfill::is_specialization_of<T, std::shared_ptr>>::value>> : std::true_type {
8388
bool operator()(const T& t) const {
8389
return static_cast<bool>(t);
8390
}
8391
};
8392
}
8393
8394
// #include "../constraints.h"
8395
8396
namespace sqlite_orm {
8397
8398
namespace internal {
8399
8400
struct column_identifier {
8401
8402
/**
8403
* Column name.
8404
*/
8405
std::string name;
8406
};
8407
8408
struct empty_setter {};
8409
8410
/*
8411
* Encapsulates object member pointers that are used as column fields,
8412
* and whose object is mapped to storage.
8413
*
8414
* G is a member object pointer or member function pointer
8415
* S is a member function pointer or `empty_setter`
8416
*/
8417
template<class G, class S>
8418
struct column_field {
8419
using member_pointer_t = G;
8420
using setter_type = S;
8421
using object_type = member_object_type_t<G>;
8422
using field_type = member_field_type_t<G>;
8423
8424
/**
8425
* Member pointer used to read a field value.
8426
* If it is a object member pointer it is also used to write a field value.
8427
*/
8428
const member_pointer_t member_pointer;
8429
8430
/**
8431
* Setter member function to write a field value
8432
*/
8433
SQLITE_ORM_NOUNIQUEADDRESS
8434
const setter_type setter;
8435
8436
/**
8437
* Simplified interface for `NOT NULL` constraint
8438
*/
8439
constexpr bool is_not_null() const {
8440
return !type_is_nullable<field_type>::value;
8441
}
8442
};
8443
8444
/*
8445
* Encapsulates a tuple of column constraints.
8446
*
8447
* Op... is a constraints pack, e.g. primary_key_t, unique_t etc
8448
*/
8449
template<class... Op>
8450
struct column_constraints {
8451
using constraints_type = std::tuple<Op...>;
8452
8453
SQLITE_ORM_NOUNIQUEADDRESS
8454
constraints_type constraints;
8455
8456
/**
8457
* Checks whether contraints contain specified type.
8458
*/
8459
template<template<class...> class Trait>
8460
constexpr static bool is() {
8461
return tuple_has<constraints_type, Trait>::value;
8462
}
8463
8464
/**
8465
* Simplified interface for `DEFAULT` constraint
8466
* @return string representation of default value if it exists otherwise nullptr
8467
*/
8468
std::unique_ptr<std::string> default_value() const;
8469
};
8470
8471
/**
8472
* Column definition.
8473
*
8474
* It is a composition of orthogonal information stored in different base classes.
8475
*/
8476
template<class G, class S, class... Op>
8477
struct column_t : column_identifier, column_field<G, S>, column_constraints<Op...> {
8478
#ifndef SQLITE_ORM_AGGREGATE_BASES_SUPPORTED
8479
column_t(std::string name, G memberPointer, S setter, std::tuple<Op...> op) :
8480
column_identifier{std::move(name)}, column_field<G, S>{memberPointer, setter},
8481
column_constraints<Op...>{std::move(op)} {}
8482
#endif
8483
};
8484
8485
template<class T, class SFINAE = void>
8486
struct column_field_expression {
8487
using type = void;
8488
};
8489
8490
template<class G, class S, class... Op>
8491
struct column_field_expression<column_t<G, S, Op...>, void> {
8492
using type = typename column_t<G, S, Op...>::member_pointer_t;
8493
};
8494
8495
template<typename T>
8496
using column_field_expression_t = typename column_field_expression<T>::type;
8497
8498
template<class T>
8499
SQLITE_ORM_INLINE_VAR constexpr bool is_column_v = polyfill::is_specialization_of<T, column_t>::value;
8500
8501
template<class T>
8502
using is_column = polyfill::bool_constant<is_column_v<T>>;
8503
8504
template<class Elements, class F>
8505
using col_index_sequence_with_field_type =
8506
filter_tuple_sequence_t<Elements,
8507
check_if_is_type<F>::template fn,
8508
field_type_t,
8509
filter_tuple_sequence_t<Elements, is_column>>;
8510
8511
template<class Elements, template<class...> class TraitFn>
8512
using col_index_sequence_with = filter_tuple_sequence_t<Elements,
8513
check_if_has<TraitFn>::template fn,
8514
constraints_type_t,
8515
filter_tuple_sequence_t<Elements, is_column>>;
8516
8517
template<class Elements, template<class...> class TraitFn>
8518
using col_index_sequence_excluding = filter_tuple_sequence_t<Elements,
8519
check_if_has_not<TraitFn>::template fn,
8520
constraints_type_t,
8521
filter_tuple_sequence_t<Elements, is_column>>;
8522
}
8523
8524
/**
8525
* Factory function for a column definition from a member object pointer of the object to be mapped.
8526
*/
8527
template<class M, class... Op, internal::satisfies<std::is_member_object_pointer, M> = true>
8528
internal::column_t<M, internal::empty_setter, Op...>
8529
make_column(std::string name, M memberPointer, Op... constraints) {
8530
static_assert(polyfill::conjunction_v<internal::is_column_constraint<Op>...>, "Incorrect constraints pack");
8531
8532
// attention: do not use `std::make_tuple()` for constructing the tuple member `[[no_unique_address]] column_constraints::constraints`,
8533
// as this will lead to UB with Clang on MinGW!
8534
SQLITE_ORM_CLANG_SUPPRESS_MISSING_BRACES(
8535
return {std::move(name), memberPointer, {}, std::tuple<Op...>{std::move(constraints)...}});
8536
}
8537
8538
/**
8539
* Factory function for a column definition from "setter" and "getter" member function pointers of the object to be mapped.
8540
*/
8541
template<class G,
8542
class S,
8543
class... Op,
8544
internal::satisfies<internal::is_getter, G> = true,
8545
internal::satisfies<internal::is_setter, S> = true>
8546
internal::column_t<G, S, Op...> make_column(std::string name, S setter, G getter, Op... constraints) {
8547
static_assert(std::is_same<internal::setter_field_type_t<S>, internal::getter_field_type_t<G>>::value,
8548
"Getter and setter must get and set same data type");
8549
static_assert(polyfill::conjunction_v<internal::is_column_constraint<Op>...>, "Incorrect constraints pack");
8550
8551
// attention: do not use `std::make_tuple()` for constructing the tuple member `[[no_unique_address]] column_constraints::constraints`,
8552
// as this will lead to UB with Clang on MinGW!
8553
SQLITE_ORM_CLANG_SUPPRESS_MISSING_BRACES(
8554
return {std::move(name), getter, setter, std::tuple<Op...>{std::move(constraints)...}});
8555
}
8556
8557
/**
8558
* Factory function for a column definition from "getter" and "setter" member function pointers of the object to be mapped.
8559
*/
8560
template<class G,
8561
class S,
8562
class... Op,
8563
internal::satisfies<internal::is_getter, G> = true,
8564
internal::satisfies<internal::is_setter, S> = true>
8565
internal::column_t<G, S, Op...> make_column(std::string name, G getter, S setter, Op... constraints) {
8566
static_assert(std::is_same<internal::setter_field_type_t<S>, internal::getter_field_type_t<G>>::value,
8567
"Getter and setter must get and set same data type");
8568
static_assert(polyfill::conjunction_v<internal::is_column_constraint<Op>...>, "Incorrect constraints pack");
8569
8570
// attention: do not use `std::make_tuple()` for constructing the tuple member `[[no_unique_address]] column_constraints::constraints`,
8571
// as this will lead to UB with Clang on MinGW!
8572
SQLITE_ORM_CLANG_SUPPRESS_MISSING_BRACES(
8573
return {std::move(name), getter, setter, std::tuple<Op...>{std::move(constraints)...}});
8574
}
8575
}
8576
8577
namespace sqlite_orm {
8578
8579
namespace internal {
8580
#ifdef SQLITE_ORM_OPTIONAL_SUPPORTED
8581
template<class T>
8582
struct as_optional_t {
8583
using expression_type = T;
8584
8585
expression_type expression;
8586
};
8587
#endif // SQLITE_ORM_OPTIONAL_SUPPORTED
8588
8589
struct distinct_string {
8590
operator std::string() const {
8591
return "DISTINCT";
8592
}
8593
};
8594
8595
/**
8596
* DISCTINCT generic container.
8597
*/
8598
template<class T>
8599
struct distinct_t : distinct_string {
8600
using expression_type = T;
8601
8602
expression_type expression;
8603
8604
distinct_t(expression_type expression) : expression(std::move(expression)) {}
8605
};
8606
8607
struct all_string {
8608
operator std::string() const {
8609
return "ALL";
8610
}
8611
};
8612
8613
/**
8614
* ALL generic container.
8615
*/
8616
template<class T>
8617
struct all_t : all_string {
8618
using expression_type = T;
8619
8620
expression_type expression;
8621
8622
all_t(expression_type expression) : expression(std::move(expression)) {}
8623
};
8624
8625
/**
8626
* Whether a type represents a keyword for a result set modifier (as part of a simple select expression).
8627
*/
8628
template<class T>
8629
SQLITE_ORM_INLINE_VAR constexpr bool is_rowset_deduplicator_v =
8630
polyfill::disjunction<polyfill::is_specialization_of<T, distinct_t>,
8631
polyfill::is_specialization_of<T, all_t>>::value;
8632
8633
template<class T>
8634
struct is_rowset_deduplicator : polyfill::bool_constant<is_rowset_deduplicator_v<T>> {};
8635
8636
template<class... Args>
8637
struct columns_t {
8638
using columns_type = std::tuple<Args...>;
8639
8640
columns_type columns;
8641
8642
static constexpr int count = std::tuple_size<columns_type>::value;
8643
8644
#ifndef SQLITE_ORM_AGGREGATE_NSDMI_SUPPORTED
8645
columns_t(columns_type columns) : columns{std::move(columns)} {}
8646
#endif
8647
};
8648
8649
template<class T>
8650
SQLITE_ORM_INLINE_VAR constexpr bool is_columns_v = polyfill::is_specialization_of<T, columns_t>::value;
8651
8652
template<class T>
8653
using is_columns = polyfill::bool_constant<is_columns_v<T>>;
8654
8655
/*
8656
* Captures the type of an aggregate/structure/object and column expressions, such that
8657
* `T` can be constructed in-place as part of a result row.
8658
* `T` must be constructible using direct-list-initialization.
8659
*/
8660
template<class T, class... Args>
8661
struct struct_t {
8662
using columns_type = std::tuple<Args...>;
8663
8664
columns_type columns;
8665
8666
static constexpr int count = std::tuple_size<columns_type>::value;
8667
8668
#ifndef SQLITE_ORM_AGGREGATE_NSDMI_SUPPORTED
8669
struct_t(columns_type columns) : columns{std::move(columns)} {}
8670
#endif
8671
};
8672
8673
template<class T>
8674
SQLITE_ORM_INLINE_VAR constexpr bool is_struct_v = polyfill::is_specialization_of<T, struct_t>::value;
8675
8676
template<class T>
8677
using is_struct = polyfill::bool_constant<is_struct_v<T>>;
8678
8679
/**
8680
* Subselect object type.
8681
*/
8682
template<class T, class... Args>
8683
struct select_t {
8684
using return_type = T;
8685
using conditions_type = std::tuple<Args...>;
8686
8687
return_type col;
8688
conditions_type conditions;
8689
bool highest_level = false;
8690
8691
#ifndef SQLITE_ORM_AGGREGATE_NSDMI_SUPPORTED
8692
select_t(return_type col, conditions_type conditions) :
8693
col{std::move(col)}, conditions{std::move(conditions)} {}
8694
#endif
8695
};
8696
8697
template<class T>
8698
SQLITE_ORM_INLINE_VAR constexpr bool is_select_v = polyfill::is_specialization_of<T, select_t>::value;
8699
8700
template<class T>
8701
using is_select = polyfill::bool_constant<is_select_v<T>>;
8702
8703
/**
8704
* Base for UNION, UNION ALL, EXCEPT and INTERSECT
8705
*/
8706
template<class... E>
8707
struct compound_operator {
8708
using expressions_tuple = std::tuple<E...>;
8709
8710
expressions_tuple compound;
8711
8712
constexpr compound_operator(expressions_tuple compound) : compound{std::move(compound)} {
8713
iterate_tuple(this->compound, [](auto& expression) {
8714
expression.highest_level = true;
8715
});
8716
}
8717
};
8718
8719
template<class T>
8720
SQLITE_ORM_INLINE_VAR constexpr bool is_compound_operator_v = is_base_of_template<T, compound_operator>::value;
8721
8722
template<class T>
8723
using is_compound_operator = polyfill::bool_constant<is_compound_operator_v<T>>;
8724
8725
struct union_base {
8726
bool all = false;
8727
8728
#ifndef SQLITE_ORM_AGGREGATE_NSDMI_SUPPORTED
8729
union_base(bool all) : all{all} {}
8730
#endif
8731
8732
operator std::string() const {
8733
if (!this->all) {
8734
return "UNION";
8735
} else {
8736
return "UNION ALL";
8737
}
8738
}
8739
};
8740
8741
/**
8742
* UNION object type.
8743
*/
8744
template<class... E>
8745
struct union_t : public compound_operator<E...>, union_base {
8746
using typename compound_operator<E...>::expressions_tuple;
8747
8748
constexpr union_t(expressions_tuple compound, bool all) :
8749
compound_operator<E...>{std::move(compound)}, union_base{all} {}
8750
};
8751
8752
struct except_string {
8753
operator std::string() const {
8754
return "EXCEPT";
8755
}
8756
};
8757
8758
/**
8759
* EXCEPT object type.
8760
*/
8761
template<class... E>
8762
struct except_t : compound_operator<E...>, except_string {
8763
using super = compound_operator<E...>;
8764
8765
using super::super;
8766
};
8767
8768
struct intersect_string {
8769
operator std::string() const {
8770
return "INTERSECT";
8771
}
8772
};
8773
/**
8774
* INTERSECT object type.
8775
*/
8776
template<class... E>
8777
struct intersect_t : compound_operator<E...>, intersect_string {
8778
using super = compound_operator<E...>;
8779
8780
using super::super;
8781
};
8782
8783
#if (SQLITE_VERSION_NUMBER >= 3008003) && defined(SQLITE_ORM_WITH_CTE)
8784
/*
8785
* Turn explicit columns for a CTE into types that the CTE backend understands
8786
*/
8787
template<class T, class SFINAE = void>
8788
struct decay_explicit_column {
8789
using type = T;
8790
};
8791
template<class T>
8792
struct decay_explicit_column<T, match_if<is_column_alias, T>> {
8793
using type = alias_holder<T>;
8794
};
8795
template<class T>
8796
struct decay_explicit_column<T, match_if<std::is_convertible, T, std::string>> {
8797
using type = std::string;
8798
};
8799
template<class T>
8800
using decay_explicit_column_t = typename decay_explicit_column<T>::type;
8801
8802
#ifdef SQLITE_ORM_WITH_CPP20_ALIASES
8803
/*
8804
* Materialization hint to instruct SQLite to materialize the select statement of a CTE into an ephemeral table as an "optimization fence".
8805
*/
8806
struct materialized_t {};
8807
8808
/*
8809
* Materialization hint to instruct SQLite to substitute a CTE's select statement as a subquery subject to optimization.
8810
*/
8811
struct not_materialized_t {};
8812
#endif
8813
8814
/**
8815
* Monikered (aliased) CTE expression.
8816
*/
8817
template<class Moniker, class ExplicitCols, class Hints, class Select>
8818
struct common_table_expression {
8819
using cte_moniker_type = Moniker;
8820
using expression_type = Select;
8821
using explicit_colrefs_tuple = ExplicitCols;
8822
using hints_tuple = Hints;
8823
static constexpr size_t explicit_colref_count = std::tuple_size_v<ExplicitCols>;
8824
8825
SQLITE_ORM_NOUNIQUEADDRESS hints_tuple hints;
8826
explicit_colrefs_tuple explicitColumns;
8827
expression_type subselect;
8828
8829
constexpr common_table_expression(explicit_colrefs_tuple explicitColumns, expression_type subselect) :
8830
explicitColumns{std::move(explicitColumns)}, subselect{std::move(subselect)} {
8831
this->subselect.highest_level = true;
8832
}
8833
};
8834
8835
template<class... CTEs>
8836
using common_table_expressions = std::tuple<CTEs...>;
8837
8838
template<typename Moniker, class ExplicitCols>
8839
struct cte_builder {
8840
ExplicitCols explicitColumns;
8841
8842
#if SQLITE_VERSION_NUMBER >= 3035000 && defined(SQLITE_ORM_WITH_CPP20_ALIASES)
8843
template<auto... hints, class Select, satisfies<is_select, Select> = true>
8844
constexpr common_table_expression<Moniker, ExplicitCols, std::tuple<decltype(hints)...>, Select>
8845
as(Select sel) && {
8846
return {std::move(this->explicitColumns), std::move(sel)};
8847
}
8848
8849
template<auto... hints, class Compound, satisfies<is_compound_operator, Compound> = true>
8850
constexpr common_table_expression<Moniker, ExplicitCols, std::tuple<decltype(hints)...>, select_t<Compound>>
8851
as(Compound sel) && {
8852
return {std::move(this->explicitColumns), {std::move(sel)}};
8853
}
8854
#else
8855
template<class Select, satisfies<is_select, Select> = true>
8856
constexpr common_table_expression<Moniker, ExplicitCols, std::tuple<>, Select> as(Select sel) && {
8857
return {std::move(this->explicitColumns), std::move(sel)};
8858
}
8859
8860
template<class Compound, satisfies<is_compound_operator, Compound> = true>
8861
constexpr common_table_expression<Moniker, ExplicitCols, std::tuple<>, select_t<Compound>>
8862
as(Compound sel) && {
8863
return {std::move(this->explicitColumns), {std::move(sel)}};
8864
}
8865
#endif
8866
};
8867
8868
/**
8869
* WITH object type - expression with prepended CTEs.
8870
*/
8871
template<class E, class... CTEs>
8872
struct with_t {
8873
using cte_type = common_table_expressions<CTEs...>;
8874
using expression_type = E;
8875
8876
bool recursiveIndicated;
8877
cte_type cte;
8878
expression_type expression;
8879
8880
with_t(bool recursiveIndicated, cte_type cte, expression_type expression) :
8881
recursiveIndicated{recursiveIndicated}, cte{std::move(cte)}, expression{std::move(expression)} {
8882
if constexpr (is_select_v<expression_type>) {
8883
this->expression.highest_level = true;
8884
}
8885
}
8886
};
8887
#endif
8888
8889
template<class T>
8890
struct asterisk_t {
8891
using type = T;
8892
8893
bool defined_order = false;
8894
8895
#ifndef SQLITE_ORM_AGGREGATE_NSDMI_SUPPORTED
8896
asterisk_t(bool definedOrder) : defined_order{definedOrder} {}
8897
#endif
8898
};
8899
8900
template<class T>
8901
struct object_t {
8902
using type = T;
8903
8904
bool defined_order = false;
8905
8906
#ifndef SQLITE_ORM_AGGREGATE_NSDMI_SUPPORTED
8907
object_t(bool definedOrder) : defined_order{definedOrder} {}
8908
#endif
8909
};
8910
8911
template<class T>
8912
struct then_t {
8913
using expression_type = T;
8914
8915
expression_type expression;
8916
};
8917
8918
template<class R, class T, class E, class... Args>
8919
struct simple_case_t {
8920
using return_type = R;
8921
using case_expression_type = T;
8922
using args_type = std::tuple<Args...>;
8923
using else_expression_type = E;
8924
8925
optional_container<case_expression_type> case_expression;
8926
args_type args;
8927
optional_container<else_expression_type> else_expression;
8928
};
8929
8930
/**
8931
* T is a case expression type
8932
* E is else type (void is ELSE is omitted)
8933
* Args... is a pack of WHEN expressions
8934
*/
8935
template<class R, class T, class E, class... Args>
8936
struct simple_case_builder {
8937
using return_type = R;
8938
using case_expression_type = T;
8939
using args_type = std::tuple<Args...>;
8940
using else_expression_type = E;
8941
8942
optional_container<case_expression_type> case_expression;
8943
args_type args;
8944
optional_container<else_expression_type> else_expression;
8945
8946
template<class W, class Th>
8947
simple_case_builder<R, T, E, Args..., std::pair<W, Th>> when(W w, then_t<Th> t) {
8948
using result_args_type = std::tuple<Args..., std::pair<W, Th>>;
8949
std::pair<W, Th> newPair{std::move(w), std::move(t.expression)};
8950
result_args_type result_args = std::tuple_cat(std::move(this->args), std::make_tuple(newPair));
8951
std::get<std::tuple_size<result_args_type>::value - 1>(result_args) = std::move(newPair);
8952
return {std::move(this->case_expression), std::move(result_args), std::move(this->else_expression)};
8953
}
8954
8955
simple_case_t<R, T, E, Args...> end() {
8956
return {std::move(this->case_expression), std::move(args), std::move(this->else_expression)};
8957
}
8958
8959
template<class El>
8960
simple_case_builder<R, T, El, Args...> else_(El el) {
8961
return {{std::move(this->case_expression)}, std::move(args), {std::move(el)}};
8962
}
8963
};
8964
8965
template<class T, std::enable_if_t<!is_rowset_deduplicator_v<T>, bool> = true>
8966
const T& access_column_expression(const T& expression) {
8967
return expression;
8968
}
8969
8970
/*
8971
* Access a column expression prefixed by a result set deduplicator (as part of a simple select expression, i.e. distinct, all)
8972
*/
8973
template<class D, std::enable_if_t<is_rowset_deduplicator_v<D>, bool> = true>
8974
const typename D::expression_type& access_column_expression(const D& modifier) {
8975
return modifier.expression;
8976
}
8977
8978
template<class T>
8979
constexpr void validate_conditions() {
8980
static_assert(count_tuple<T, is_where>::value <= 1, "a single query cannot contain > 1 WHERE blocks");
8981
static_assert(count_tuple<T, is_group_by>::value <= 1, "a single query cannot contain > 1 GROUP BY blocks");
8982
static_assert(count_tuple<T, is_order_by>::value <= 1, "a single query cannot contain > 1 ORDER BY blocks");
8983
static_assert(count_tuple<T, is_limit>::value <= 1, "a single query cannot contain > 1 LIMIT blocks");
8984
static_assert(count_tuple<T, is_from>::value <= 1, "a single query cannot contain > 1 FROM blocks");
8985
}
8986
}
8987
8988
#ifdef SQLITE_ORM_OPTIONAL_SUPPORTED
8989
template<class T>
8990
internal::as_optional_t<T> as_optional(T value) {
8991
return {std::move(value)};
8992
}
8993
#endif // SQLITE_ORM_OPTIONAL_SUPPORTED
8994
8995
template<class T>
8996
internal::then_t<T> then(T t) {
8997
return {std::move(t)};
8998
}
8999
9000
template<class R, class T>
9001
internal::simple_case_builder<R, T, void> case_(T t) {
9002
return {{std::move(t)}};
9003
}
9004
9005
template<class R>
9006
internal::simple_case_builder<R, void, void> case_() {
9007
return {};
9008
}
9009
9010
template<class T>
9011
internal::distinct_t<T> distinct(T t) {
9012
return {std::move(t)};
9013
}
9014
9015
template<class T>
9016
internal::all_t<T> all(T t) {
9017
return {std::move(t)};
9018
}
9019
9020
/*
9021
* Combine multiple columns in a tuple.
9022
*/
9023
template<class... Args>
9024
constexpr internal::columns_t<Args...> columns(Args... args) {
9025
return {{std::forward<Args>(args)...}};
9026
}
9027
9028
/*
9029
* Construct an unmapped structure ad-hoc from multiple columns.
9030
* `T` must be constructible from the column results using direct-list-initialization.
9031
*/
9032
template<class T, class... Args>
9033
constexpr internal::struct_t<T, Args...> struct_(Args... args) {
9034
return {{std::forward<Args>(args)...}};
9035
}
9036
9037
/**
9038
* Public function for subselect query. Is useful in UNION queries.
9039
*/
9040
template<class T, class... Args>
9041
constexpr internal::select_t<T, Args...> select(T t, Args... args) {
9042
using args_tuple = std::tuple<Args...>;
9043
internal::validate_conditions<args_tuple>();
9044
return {std::move(t), {std::forward<Args>(args)...}};
9045
}
9046
9047
/**
9048
* Public function for UNION operator.
9049
* Expressions are subselect objects.
9050
* Look through example in examples/union.cpp
9051
*/
9052
template<class... E>
9053
constexpr internal::union_t<E...> union_(E... expressions) {
9054
static_assert(sizeof...(E) >= 2, "Compound operators must have at least 2 select statements");
9055
return {{std::forward<E>(expressions)...}, false};
9056
}
9057
9058
/**
9059
* Public function for UNION ALL operator.
9060
* Expressions are subselect objects.
9061
* Look through example in examples/union.cpp
9062
*/
9063
template<class... E>
9064
constexpr internal::union_t<E...> union_all(E... expressions) {
9065
static_assert(sizeof...(E) >= 2, "Compound operators must have at least 2 select statements");
9066
return {{std::forward<E>(expressions)...}, true};
9067
}
9068
9069
/**
9070
* Public function for EXCEPT operator.
9071
* Expressions are subselect objects.
9072
* Look through example in examples/except.cpp
9073
*/
9074
template<class... E>
9075
constexpr internal::except_t<E...> except(E... expressions) {
9076
static_assert(sizeof...(E) >= 2, "Compound operators must have at least 2 select statements");
9077
return {{std::forward<E>(expressions)...}};
9078
}
9079
9080
template<class... E>
9081
constexpr internal::intersect_t<E...> intersect(E... expressions) {
9082
static_assert(sizeof...(E) >= 2, "Compound operators must have at least 2 select statements");
9083
return {{std::forward<E>(expressions)...}};
9084
}
9085
9086
#if (SQLITE_VERSION_NUMBER >= 3008003) && defined(SQLITE_ORM_WITH_CTE)
9087
#if SQLITE_VERSION_NUMBER >= 3035003
9088
#ifdef SQLITE_ORM_WITH_CPP20_ALIASES
9089
/*
9090
* Materialization hint to instruct SQLite to materialize the select statement of a CTE into an ephemeral table as an "optimization fence".
9091
*
9092
* Example:
9093
* 1_ctealias().as<materialized()>(select(1));
9094
*/
9095
consteval internal::materialized_t materialized() {
9096
return {};
9097
}
9098
9099
/*
9100
* Materialization hint to instruct SQLite to substitute a CTE's select statement as a subquery subject to optimization.
9101
*
9102
* Example:
9103
* 1_ctealias().as<not_materialized()>(select(1));
9104
*/
9105
consteval internal::not_materialized_t not_materialized() {
9106
return {};
9107
}
9108
#endif
9109
#endif
9110
9111
/**
9112
* Introduce the construction of a common table expression using the specified moniker.
9113
*
9114
* The list of explicit columns is optional;
9115
* if provided the number of columns must match the number of columns of the subselect.
9116
* The column names will be merged with the subselect:
9117
* 1. column names of subselect
9118
* 2. explicit columns
9119
* 3. fill in empty column names with column index
9120
*
9121
* Example:
9122
* using cte_1 = decltype(1_ctealias);
9123
* cte<cte_1>()(select(&Object::id));
9124
* cte<cte_1>(&Object::name)(select("object"));
9125
*/
9126
template<class Moniker,
9127
class... ExplicitCols,
9128
std::enable_if_t<polyfill::conjunction_v<polyfill::disjunction<
9129
internal::is_column_alias<ExplicitCols>,
9130
std::is_member_pointer<ExplicitCols>,
9131
internal::is_column<ExplicitCols>,
9132
std::is_same<ExplicitCols, polyfill::remove_cvref_t<decltype(std::ignore)>>,
9133
std::is_convertible<ExplicitCols, std::string>>...>,
9134
bool> = true>
9135
constexpr auto cte(ExplicitCols... explicitColumns) {
9136
using namespace ::sqlite_orm::internal;
9137
static_assert(is_cte_moniker_v<Moniker>, "Moniker must be a CTE moniker");
9138
static_assert((!is_builtin_numeric_column_alias_v<ExplicitCols> && ...),
9139
"Numeric column aliases are reserved for referencing columns locally within a single CTE.");
9140
9141
using builder_type =
9142
cte_builder<Moniker, transform_tuple_t<std::tuple<ExplicitCols...>, decay_explicit_column_t>>;
9143
return builder_type{{std::move(explicitColumns)...}};
9144
}
9145
9146
#ifdef SQLITE_ORM_WITH_CPP20_ALIASES
9147
template<orm_cte_moniker auto moniker, class... ExplicitCols>
9148
requires ((internal::is_column_alias_v<ExplicitCols> || std::is_member_pointer_v<ExplicitCols> ||
9149
internal::is_column_v<ExplicitCols> ||
9150
std::same_as<ExplicitCols, std::remove_cvref_t<decltype(std::ignore)>> ||
9151
std::convertible_to<ExplicitCols, std::string>) &&
9152
...)
9153
constexpr auto cte(ExplicitCols... explicitColumns) {
9154
using namespace ::sqlite_orm::internal;
9155
static_assert((!is_builtin_numeric_column_alias_v<ExplicitCols> && ...),
9156
"Numeric column aliases are reserved for referencing columns locally within a single CTE.");
9157
9158
using builder_type =
9159
cte_builder<decltype(moniker), transform_tuple_t<std::tuple<ExplicitCols...>, decay_explicit_column_t>>;
9160
return builder_type{{std::move(explicitColumns)...}};
9161
}
9162
#endif
9163
9164
namespace internal {
9165
#ifdef SQLITE_ORM_WITH_CPP20_ALIASES
9166
template<char A, char... X>
9167
template<class... ExplicitCols>
9168
requires ((is_column_alias_v<ExplicitCols> || std::is_member_pointer_v<ExplicitCols> ||
9169
std::same_as<ExplicitCols, std::remove_cvref_t<decltype(std::ignore)>> ||
9170
std::convertible_to<ExplicitCols, std::string>) &&
9171
...)
9172
constexpr auto cte_moniker<A, X...>::operator()(ExplicitCols... explicitColumns) const {
9173
return cte<cte_moniker<A, X...>>(std::forward<ExplicitCols>(explicitColumns)...);
9174
}
9175
#else
9176
template<char A, char... X>
9177
template<class... ExplicitCols,
9178
std::enable_if_t<polyfill::conjunction_v<polyfill::disjunction<
9179
is_column_alias<ExplicitCols>,
9180
std::is_member_pointer<ExplicitCols>,
9181
std::is_same<ExplicitCols, polyfill::remove_cvref_t<decltype(std::ignore)>>,
9182
std::is_convertible<ExplicitCols, std::string>>...>,
9183
bool>>
9184
constexpr auto cte_moniker<A, X...>::operator()(ExplicitCols... explicitColumns) const {
9185
return cte<cte_moniker<A, X...>>(std::forward<ExplicitCols>(explicitColumns)...);
9186
}
9187
#endif
9188
}
9189
9190
/**
9191
* With-clause for a tuple of ordinary CTEs.
9192
*
9193
* Despite the missing RECURSIVE keyword, the CTEs can be recursive.
9194
*/
9195
template<class E, class... CTEs, internal::satisfies_not<internal::is_compound_operator, E> = true>
9196
internal::with_t<E, CTEs...> with(internal::common_table_expressions<CTEs...> ctes, E expression) {
9197
return {false, std::move(ctes), std::move(expression)};
9198
}
9199
9200
/**
9201
* With-clause for a tuple of ordinary CTEs.
9202
*
9203
* Despite the missing RECURSIVE keyword, the CTEs can be recursive.
9204
*/
9205
template<class Compound, class... CTEs, internal::satisfies<internal::is_compound_operator, Compound> = true>
9206
internal::with_t<internal::select_t<Compound>, CTEs...> with(internal::common_table_expressions<CTEs...> ctes,
9207
Compound sel) {
9208
return {false, std::move(ctes), sqlite_orm::select(std::move(sel))};
9209
}
9210
9211
/**
9212
* With-clause for a single ordinary CTE.
9213
*
9214
* Despite the missing `RECURSIVE` keyword, the CTE can be recursive.
9215
*
9216
* Example:
9217
* constexpr orm_cte_moniker auto cte_1 = 1_ctealias;
9218
* with(cte_1().as(select(&Object::id)), select(cte_1->*1_colalias));
9219
*/
9220
template<class E,
9221
class CTE,
9222
internal::satisfies_is_specialization_of<CTE, internal::common_table_expression> = true,
9223
internal::satisfies_not<internal::is_compound_operator, E> = true>
9224
internal::with_t<E, CTE> with(CTE cte, E expression) {
9225
return {false, {std::move(cte)}, std::move(expression)};
9226
}
9227
9228
/**
9229
* With-clause for a single ordinary CTE.
9230
*
9231
* Despite the missing `RECURSIVE` keyword, the CTE can be recursive.
9232
*
9233
* Example:
9234
* constexpr orm_cte_moniker auto cte_1 = 1_ctealias;
9235
* with(cte_1().as(select(&Object::id)), select(cte_1->*1_colalias));
9236
*/
9237
template<class Compound,
9238
class CTE,
9239
internal::satisfies_is_specialization_of<CTE, internal::common_table_expression> = true,
9240
internal::satisfies<internal::is_compound_operator, Compound> = true>
9241
internal::with_t<internal::select_t<Compound>, CTE> with(CTE cte, Compound sel) {
9242
return {false, {std::move(cte)}, sqlite_orm::select(std::move(sel))};
9243
}
9244
9245
/**
9246
* With-clause for a tuple of potentially recursive CTEs.
9247
*
9248
* @note The use of RECURSIVE does not force common table expressions to be recursive.
9249
*/
9250
template<class E, class... CTEs, internal::satisfies_not<internal::is_compound_operator, E> = true>
9251
internal::with_t<E, CTEs...> with_recursive(internal::common_table_expressions<CTEs...> ctes, E expression) {
9252
return {true, std::move(ctes), std::move(expression)};
9253
}
9254
9255
/**
9256
* With-clause for a tuple of potentially recursive CTEs.
9257
*
9258
* @note The use of RECURSIVE does not force common table expressions to be recursive.
9259
*/
9260
template<class Compound, class... CTEs, internal::satisfies<internal::is_compound_operator, Compound> = true>
9261
internal::with_t<internal::select_t<Compound>, CTEs...>
9262
with_recursive(internal::common_table_expressions<CTEs...> ctes, Compound sel) {
9263
return {true, std::move(ctes), sqlite_orm::select(std::move(sel))};
9264
}
9265
9266
/**
9267
* With-clause for a single potentially recursive CTE.
9268
*
9269
* @note The use of RECURSIVE does not force common table expressions to be recursive.
9270
*
9271
* Example:
9272
* constexpr orm_cte_moniker auto cte_1 = 1_ctealias;
9273
* with_recursive(cte_1().as(select(&Object::id)), select(cte_1->*1_colalias));
9274
*/
9275
template<class E,
9276
class CTE,
9277
internal::satisfies_is_specialization_of<CTE, internal::common_table_expression> = true,
9278
internal::satisfies_not<internal::is_compound_operator, E> = true>
9279
internal::with_t<E, CTE> with_recursive(CTE cte, E expression) {
9280
return {true, {std::move(cte)}, std::move(expression)};
9281
}
9282
9283
/**
9284
* With-clause for a single potentially recursive CTE.
9285
*
9286
* @note The use of RECURSIVE does not force common table expressions to be recursive.
9287
*
9288
* Example:
9289
* constexpr orm_cte_moniker auto cte_1 = 1_ctealias;
9290
* with_recursive(cte_1().as(select(&Object::id)), select(cte_1->*1_colalias));
9291
*/
9292
template<class Compound,
9293
class CTE,
9294
internal::satisfies_is_specialization_of<CTE, internal::common_table_expression> = true,
9295
internal::satisfies<internal::is_compound_operator, Compound> = true>
9296
internal::with_t<internal::select_t<Compound>, CTE> with_recursive(CTE cte, Compound sel) {
9297
return {true, {std::move(cte)}, sqlite_orm::select(std::move(sel))};
9298
}
9299
#endif
9300
9301
/**
9302
* `SELECT * FROM T` expression that fetches results as tuples.
9303
* T is a type mapped to a storage, or an alias of it.
9304
* The `definedOrder` parameter denotes the expected order of result columns.
9305
* The default is the implicit order as returned by SQLite, which may differ from the defined order
9306
* if the schema of a table has been changed.
9307
* By specifying the defined order, the columns are written out in the resulting select SQL string.
9308
*
9309
* In pseudo code:
9310
* select(asterisk<User>(false)) -> SELECT * from User
9311
* select(asterisk<User>(true)) -> SELECT id, name from User
9312
*
9313
* Example: auto rows = storage.select(asterisk<User>());
9314
* // decltype(rows) is std::vector<std::tuple<...all columns in implicitly stored order...>>
9315
* Example: auto rows = storage.select(asterisk<User>(true));
9316
* // decltype(rows) is std::vector<std::tuple<...all columns in declared make_table order...>>
9317
*
9318
* If you need to fetch results as objects instead of tuples please use `object<T>()`.
9319
*/
9320
template<class T>
9321
constexpr internal::asterisk_t<T> asterisk(bool definedOrder = false) {
9322
return {definedOrder};
9323
}
9324
9325
#ifdef SQLITE_ORM_WITH_CPP20_ALIASES
9326
/**
9327
* Example:
9328
* constexpr orm_table_alias auto m = "m"_alias.for_<Employee>();
9329
* auto reportingTo =
9330
* storage.select(asterisk<m>(), inner_join<m>(on(m->*&Employee::reportsTo == &Employee::employeeId)));
9331
*/
9332
template<orm_refers_to_recordset auto recordset>
9333
constexpr auto asterisk(bool definedOrder = false) {
9334
return asterisk<internal::auto_decay_table_ref_t<recordset>>(definedOrder);
9335
}
9336
#endif
9337
9338
/**
9339
* `SELECT * FROM T` expression that fetches results as objects of type T.
9340
* T is a type mapped to a storage, or an alias of it.
9341
*
9342
* Example: auto rows = storage.select(object<User>());
9343
* // decltype(rows) is std::vector<User>, where the User objects are constructed from columns in implicitly stored order
9344
* Example: auto rows = storage.select(object<User>(true));
9345
* // decltype(rows) is std::vector<User>, where the User objects are constructed from columns in declared make_table order
9346
*
9347
* If you need to fetch results as tuples instead of objects please use `asterisk<T>()`.
9348
*/
9349
template<class T>
9350
constexpr internal::object_t<T> object(bool definedOrder = false) {
9351
return {definedOrder};
9352
}
9353
9354
#ifdef SQLITE_ORM_WITH_CPP20_ALIASES
9355
template<orm_refers_to_table auto als>
9356
constexpr auto object(bool definedOrder = false) {
9357
return object<internal::auto_decay_table_ref_t<als>>(definedOrder);
9358
}
9359
#endif
9360
}
9361
9362
// #include "core_functions.h"
9363
9364
// #include "conditions.h"
9365
9366
// #include "statement_binder.h"
9367
9368
#include <sqlite3.h>
9369
#include <type_traits> // std::enable_if_t, std::is_arithmetic, std::is_same, std::true_type, std::false_type, std::make_index_sequence, std::index_sequence
9370
#include <memory> // std::default_delete
9371
#include <string> // std::string, std::wstring
9372
#include <vector> // std::vector
9373
#include <cstring> // strncpy, strlen
9374
// #include "functional/cxx_string_view.h"
9375
9376
#ifndef SQLITE_ORM_STRING_VIEW_SUPPORTED
9377
#include <cwchar> // wcsncpy, wcslen
9378
#endif
9379
#ifndef SQLITE_ORM_OMITS_CODECVT
9380
#include <locale> // std::wstring_convert
9381
#include <codecvt> // std::codecvt_utf8_utf16
9382
#endif
9383
9384
// #include "functional/cxx_type_traits_polyfill.h"
9385
9386
// #include "functional/cxx_functional_polyfill.h"
9387
9388
// #include "is_std_ptr.h"
9389
9390
// #include "tuple_helper/tuple_filter.h"
9391
9392
// #include "type_traits.h"
9393
9394
// #include "error_code.h"
9395
9396
// #include "arithmetic_tag.h"
9397
9398
#include <type_traits> // std::is_integral
9399
9400
// #include "functional/mpl/conditional.h"
9401
9402
namespace sqlite_orm {
9403
9404
/**
9405
* Helper classes used by statement_binder and row_extractor.
9406
*/
9407
struct int_or_smaller_tag {};
9408
struct bigint_tag {};
9409
struct real_tag {};
9410
9411
template<class V>
9412
using arithmetic_tag_t =
9413
mpl::conditional_t<std::is_integral<V>::value,
9414
// Integer class
9415
mpl::conditional_t<sizeof(V) <= sizeof(int), int_or_smaller_tag, bigint_tag>,
9416
// Floating-point class
9417
real_tag>;
9418
}
9419
9420
// #include "xdestroy_handling.h"
9421
9422
#include <type_traits> // std::integral_constant
9423
#ifdef SQLITE_ORM_CPP20_CONCEPTS_SUPPORTED
9424
#include <concepts>
9425
#endif
9426
9427
// #include "functional/cxx_type_traits_polyfill.h"
9428
9429
namespace sqlite_orm {
9430
9431
using xdestroy_fn_t = void (*)(void*);
9432
using null_xdestroy_t = std::integral_constant<xdestroy_fn_t, nullptr>;
9433
SQLITE_ORM_INLINE_VAR constexpr null_xdestroy_t null_xdestroy_f{};
9434
}
9435
9436
namespace sqlite_orm {
9437
namespace internal {
9438
#ifdef SQLITE_ORM_CONCEPTS_SUPPORTED
9439
/**
9440
* Constrains a deleter to be state-less.
9441
*/
9442
template<typename D>
9443
concept stateless_deleter = std::is_empty_v<D> && std::is_default_constructible_v<D>;
9444
9445
/**
9446
* Constrains a deleter to be an integral function constant.
9447
*/
9448
template<typename D>
9449
concept integral_fp_c = requires {
9450
typename D::value_type;
9451
D::value;
9452
requires std::is_function_v<std::remove_pointer_t<typename D::value_type>>;
9453
};
9454
9455
/**
9456
* Constrains a deleter to be or to yield a function pointer.
9457
*/
9458
template<typename D>
9459
concept yields_fp = requires(D d) {
9460
// yielding function pointer by using the plus trick
9461
{ +d };
9462
requires std::is_function_v<std::remove_pointer_t<decltype(+d)>>;
9463
};
9464
#endif
9465
9466
#ifdef SQLITE_ORM_CPP20_CONCEPTS_SUPPORTED
9467
/**
9468
* Yield a deleter's function pointer.
9469
*/
9470
template<yields_fp D>
9471
struct yield_fp_of {
9472
using type = decltype(+std::declval<D>());
9473
};
9474
#else
9475
9476
template<typename D>
9477
SQLITE_ORM_INLINE_VAR constexpr bool is_stateless_deleter_v =
9478
std::is_empty<D>::value && std::is_default_constructible<D>::value;
9479
9480
template<typename D, typename SFINAE = void>
9481
struct is_integral_fp_c : std::false_type {};
9482
template<typename D>
9483
struct is_integral_fp_c<
9484
D,
9485
polyfill::void_t<typename D::value_type,
9486
decltype(D::value),
9487
std::enable_if_t<std::is_function<std::remove_pointer_t<typename D::value_type>>::value>>>
9488
: std::true_type {};
9489
template<typename D>
9490
SQLITE_ORM_INLINE_VAR constexpr bool is_integral_fp_c_v = is_integral_fp_c<D>::value;
9491
9492
template<typename D, typename SFINAE = void>
9493
struct can_yield_fp : std::false_type {};
9494
template<typename D>
9495
struct can_yield_fp<
9496
D,
9497
polyfill::void_t<
9498
decltype(+std::declval<D>()),
9499
std::enable_if_t<std::is_function<std::remove_pointer_t<decltype(+std::declval<D>())>>::value>>>
9500
: std::true_type {};
9501
template<typename D>
9502
SQLITE_ORM_INLINE_VAR constexpr bool can_yield_fp_v = can_yield_fp<D>::value;
9503
9504
template<typename D, bool = can_yield_fp_v<D>>
9505
struct yield_fp_of {
9506
using type = void;
9507
};
9508
template<typename D>
9509
struct yield_fp_of<D, true> {
9510
using type = decltype(+std::declval<D>());
9511
};
9512
#endif
9513
template<typename D>
9514
using yielded_fn_t = typename yield_fp_of<D>::type;
9515
9516
#ifdef SQLITE_ORM_CPP20_CONCEPTS_SUPPORTED
9517
template<typename D>
9518
concept is_unusable_for_xdestroy =
9519
(!stateless_deleter<D> && (yields_fp<D> && !std::convertible_to<yielded_fn_t<D>, xdestroy_fn_t>));
9520
9521
/**
9522
* This concept tests whether a deleter yields a function pointer, which is convertible to an xdestroy function pointer.
9523
* Note: We are using 'is convertible' rather than 'is same' because of any exception specification.
9524
*/
9525
template<typename D>
9526
concept yields_xdestroy = yields_fp<D> && std::convertible_to<yielded_fn_t<D>, xdestroy_fn_t>;
9527
9528
template<typename D, typename P>
9529
concept needs_xdestroy_proxy =
9530
(stateless_deleter<D> && (!yields_fp<D> || !std::convertible_to<yielded_fn_t<D>, xdestroy_fn_t>));
9531
9532
/**
9533
* xDestroy function that constructs and invokes the stateless deleter.
9534
*
9535
* Requires that the deleter can be called with the q-qualified pointer argument;
9536
* it doesn't check so explicitly, but a compiler error will occur.
9537
*/
9538
template<typename D, typename P>
9539
requires (!integral_fp_c<D>)
9540
void xdestroy_proxy(void* p) noexcept {
9541
// C-casting `void* -> P*` like statement_binder<pointer_binding<P, T, D>>
9542
auto o = (P*)p;
9543
// ignoring return code
9544
(void)D{}(o);
9545
}
9546
9547
/**
9548
* xDestroy function that invokes the integral function pointer constant.
9549
*
9550
* Performs a const-cast of the argument pointer in order to allow for C API functions
9551
* that take a non-const parameter, but user code passes a pointer to a const object.
9552
*/
9553
template<integral_fp_c D, typename P>
9554
void xdestroy_proxy(void* p) noexcept {
9555
// C-casting `void* -> P*` like statement_binder<pointer_binding<P, T, D>>,
9556
auto o = (std::remove_cv_t<P>*)(P*)p;
9557
// ignoring return code
9558
(void)D{}(o);
9559
}
9560
#else
9561
template<typename D>
9562
SQLITE_ORM_INLINE_VAR constexpr bool is_unusable_for_xdestroy_v =
9563
!is_stateless_deleter_v<D> &&
9564
(can_yield_fp_v<D> && !std::is_convertible<yielded_fn_t<D>, xdestroy_fn_t>::value);
9565
9566
template<typename D>
9567
SQLITE_ORM_INLINE_VAR constexpr bool can_yield_xdestroy_v =
9568
can_yield_fp_v<D> && std::is_convertible<yielded_fn_t<D>, xdestroy_fn_t>::value;
9569
9570
template<typename D, typename P>
9571
SQLITE_ORM_INLINE_VAR constexpr bool needs_xdestroy_proxy_v =
9572
is_stateless_deleter_v<D> &&
9573
(!can_yield_fp_v<D> || !std::is_convertible<yielded_fn_t<D>, xdestroy_fn_t>::value);
9574
9575
template<typename D, typename P, std::enable_if_t<!is_integral_fp_c_v<D>, bool> = true>
9576
void xdestroy_proxy(void* p) noexcept {
9577
// C-casting `void* -> P*` like statement_binder<pointer_binding<P, T, D>>
9578
auto o = (P*)p;
9579
// ignoring return code
9580
(void)D{}(o);
9581
}
9582
9583
template<typename D, typename P, std::enable_if_t<is_integral_fp_c_v<D>, bool> = true>
9584
void xdestroy_proxy(void* p) noexcept {
9585
// C-casting `void* -> P*` like statement_binder<pointer_binding<P, T, D>>,
9586
auto o = (std::remove_cv_t<P>*)(P*)p;
9587
// ignoring return code
9588
(void)D{}(o);
9589
}
9590
#endif
9591
}
9592
}
9593
9594
namespace sqlite_orm {
9595
9596
#ifdef SQLITE_ORM_CPP20_CONCEPTS_SUPPORTED
9597
/**
9598
* Prohibits using a yielded function pointer, which is not of type xdestroy_fn_t.
9599
*
9600
* Explicitly declared for better error messages.
9601
*/
9602
template<typename P, typename D>
9603
constexpr xdestroy_fn_t obtain_xdestroy_for(D, P* = nullptr) noexcept
9604
requires (internal::is_unusable_for_xdestroy<D>)
9605
{
9606
static_assert(polyfill::always_false_v<D>,
9607
"A function pointer, which is not of type xdestroy_fn_t, is prohibited.");
9608
return nullptr;
9609
}
9610
9611
/**
9612
* Obtains a proxy 'xDestroy' function pointer [of type void(*)(void*)]
9613
* for a deleter in a type-safe way.
9614
*
9615
* The deleter can be one of:
9616
* - integral function constant
9617
* - state-less (empty) deleter
9618
* - non-capturing lambda
9619
*
9620
* Type-safety is garanteed by checking whether the deleter or yielded function pointer
9621
* is invocable with the non-q-qualified pointer value.
9622
*/
9623
template<typename P, typename D>
9624
constexpr xdestroy_fn_t obtain_xdestroy_for(D, P* = nullptr) noexcept
9625
requires (internal::needs_xdestroy_proxy<D, P>)
9626
{
9627
return internal::xdestroy_proxy<D, P>;
9628
}
9629
9630
/**
9631
* Directly obtains a 'xDestroy' function pointer [of type void(*)(void*)]
9632
* from a deleter in a type-safe way.
9633
*
9634
* The deleter can be one of:
9635
* - function pointer of type xdestroy_fn_t
9636
* - structure holding a function pointer
9637
* - integral function constant
9638
* - non-capturing lambda
9639
* ... and yield a function pointer of type xdestroy_fn_t.
9640
*
9641
* Type-safety is garanteed by checking whether the deleter or yielded function pointer
9642
* is invocable with the non-q-qualified pointer value.
9643
*/
9644
template<typename P, typename D>
9645
constexpr xdestroy_fn_t obtain_xdestroy_for(D d, P* = nullptr) noexcept
9646
requires (internal::yields_xdestroy<D>)
9647
{
9648
return d;
9649
}
9650
#else
9651
template<typename P, typename D, std::enable_if_t<internal::is_unusable_for_xdestroy_v<D>, bool> = true>
9652
constexpr xdestroy_fn_t obtain_xdestroy_for(D, P* = nullptr) {
9653
static_assert(polyfill::always_false_v<D>,
9654
"A function pointer, which is not of type xdestroy_fn_t, is prohibited.");
9655
return nullptr;
9656
}
9657
9658
template<typename P, typename D, std::enable_if_t<internal::needs_xdestroy_proxy_v<D, P>, bool> = true>
9659
constexpr xdestroy_fn_t obtain_xdestroy_for(D, P* = nullptr) noexcept {
9660
return internal::xdestroy_proxy<D, P>;
9661
}
9662
9663
template<typename P, typename D, std::enable_if_t<internal::can_yield_xdestroy_v<D>, bool> = true>
9664
constexpr xdestroy_fn_t obtain_xdestroy_for(D d, P* = nullptr) noexcept {
9665
return d;
9666
}
9667
#endif
9668
}
9669
9670
// #include "pointer_value.h"
9671
9672
#if SQLITE_VERSION_NUMBER >= 3020000
9673
#include <type_traits>
9674
#include <memory>
9675
#include <utility>
9676
#ifdef SQLITE_ORM_WITH_CPP20_ALIASES
9677
#include <concepts>
9678
#endif
9679
#endif
9680
9681
// #include "functional/cstring_literal.h"
9682
9683
// #include "xdestroy_handling.h"
9684
9685
#if SQLITE_VERSION_NUMBER >= 3020000
9686
namespace sqlite_orm {
9687
#ifdef SQLITE_ORM_WITH_CPP20_ALIASES
9688
namespace internal {
9689
template<char... C>
9690
struct pointer_type {
9691
using value_type = const char[sizeof...(C) + 1];
9692
static inline constexpr value_type value = {C..., '\0'};
9693
};
9694
}
9695
9696
inline namespace literals {
9697
template<internal::cstring_literal tag>
9698
[[nodiscard]] consteval auto operator"" _pointer_type() {
9699
return internal::explode_into<internal::pointer_type, tag>(std::make_index_sequence<tag.size()>{});
9700
}
9701
}
9702
9703
/** @short Specifies that a type is an integral constant string usable as a pointer type.
9704
*/
9705
template<class T>
9706
concept orm_pointer_type = requires {
9707
typename T::value_type;
9708
{ T::value } -> std::convertible_to<const char*>;
9709
};
9710
#endif
9711
9712
/**
9713
* Wraps a pointer and tags it with a pointer type,
9714
* used for accepting function parameters,
9715
* facilitating the 'pointer-passing interface'.
9716
*
9717
* Template parameters:
9718
* - P: The value type, possibly const-qualified.
9719
* - T: An integral constant string denoting the pointer type, e.g. `"carray"_pointer_type`.
9720
*
9721
*/
9722
template<typename P, typename T>
9723
struct pointer_arg {
9724
9725
#ifdef SQLITE_ORM_WITH_CPP20_ALIASES
9726
// note (internal): this is currently a static assertion instead of a type constraint because
9727
// of forward declarations in other places (e.g. function.h)
9728
static_assert(orm_pointer_type<T>, "T must be a pointer type (tag)");
9729
#else
9730
static_assert(std::is_convertible<typename T::value_type, const char*>::value,
9731
"The pointer type (tag) must be convertible to `const char*`");
9732
#endif
9733
9734
using tag = T;
9735
using qualified_type = P;
9736
9737
P* p_;
9738
9739
P* ptr() const noexcept {
9740
return p_;
9741
}
9742
9743
operator P*() const noexcept {
9744
return p_;
9745
}
9746
};
9747
9748
/**
9749
* Pointer value with associated deleter function,
9750
* used for returning or binding pointer values
9751
* as part of facilitating the 'pointer-passing interface'.
9752
*
9753
* Template parameters:
9754
* - P: The value type, possibly const-qualified.
9755
* - T: An integral constant string denoting the pointer type, e.g. `carray_pointer_type`.
9756
* - D: The deleter for the pointer value;
9757
* can be one of:
9758
* - function pointer
9759
* - integral function pointer constant
9760
* - state-less (empty) deleter
9761
* - non-capturing lambda
9762
* - structure implicitly yielding a function pointer
9763
*
9764
* @note Use one of the factory functions to create a pointer binding,
9765
* e.g. bindable_carray_pointer or statically_bindable_carray_pointer().
9766
*
9767
* @example
9768
* ```
9769
* int64 rememberedId;
9770
* storage.select(func<remember_fn>(&Object::id, statically_bindable_carray_pointer(&rememberedId)));
9771
* ```
9772
*/
9773
template<typename P, typename T, typename D>
9774
class pointer_binding {
9775
9776
P* p_;
9777
SQLITE_ORM_NOUNIQUEADDRESS
9778
D d_;
9779
9780
protected:
9781
// Constructing pointer bindings must go through bind_pointer()
9782
template<class T2, class P2, class D2>
9783
friend auto bind_pointer(P2*, D2) noexcept -> pointer_binding<P2, T2, D2>;
9784
#ifdef SQLITE_ORM_WITH_CPP20_ALIASES
9785
// Constructing pointer bindings must go through bind_pointer()
9786
template<orm_pointer_type auto tag, class P2, class D2>
9787
friend auto bind_pointer(P2*, D2) noexcept -> pointer_binding<P2, decltype(tag), D2>;
9788
#endif
9789
template<class B>
9790
friend B bind_pointer(typename B::qualified_type*, typename B::deleter_type) noexcept;
9791
9792
// Construct from pointer and deleter.
9793
// Transfers ownership of the passed in object.
9794
pointer_binding(P* p, D d = {}) noexcept : p_{p}, d_{std::move(d)} {}
9795
9796
public:
9797
using qualified_type = P;
9798
using tag = T;
9799
using deleter_type = D;
9800
9801
pointer_binding(const pointer_binding&) = delete;
9802
pointer_binding& operator=(const pointer_binding&) = delete;
9803
pointer_binding& operator=(pointer_binding&&) = delete;
9804
9805
pointer_binding(pointer_binding&& other) noexcept :
9806
p_{std::exchange(other.p_, nullptr)}, d_{std::move(other.d_)} {}
9807
9808
~pointer_binding() {
9809
if (p_) {
9810
if (auto xDestroy = get_xdestroy()) {
9811
// note: C-casting `P* -> void*` like statement_binder<pointer_binding<P, T, D>>
9812
xDestroy((void*)p_);
9813
}
9814
}
9815
}
9816
9817
P* ptr() const noexcept {
9818
return p_;
9819
}
9820
9821
P* take_ptr() noexcept {
9822
return std::exchange(p_, nullptr);
9823
}
9824
9825
xdestroy_fn_t get_xdestroy() const noexcept {
9826
return obtain_xdestroy_for(d_, p_);
9827
}
9828
};
9829
9830
/**
9831
* Alias template for a static pointer value binding.
9832
* 'Static' means that ownership won't be transferred to sqlite,
9833
* sqlite doesn't delete it, and sqlite assumes the object
9834
* pointed to is valid throughout the lifetime of a statement.
9835
*/
9836
template<typename P, typename T>
9837
using static_pointer_binding = pointer_binding<P, T, null_xdestroy_t>;
9838
9839
#ifdef SQLITE_ORM_WITH_CPP20_ALIASES
9840
template<class P, orm_pointer_type auto tag>
9841
using pointer_arg_t = pointer_arg<P, decltype(tag)>;
9842
9843
template<class P, orm_pointer_type auto tag, class D>
9844
using pointer_binding_t = pointer_binding<P, decltype(tag), D>;
9845
9846
/**
9847
* Alias template for a static pointer value binding.
9848
* 'Static' means that ownership won't be transferred to sqlite,
9849
* sqlite doesn't delete it, and sqlite assumes the object
9850
* pointed to is valid throughout the lifetime of a statement.
9851
*/
9852
template<typename P, orm_pointer_type auto tag>
9853
using static_pointer_binding_t = pointer_binding_t<P, tag, null_xdestroy_t>;
9854
#endif
9855
}
9856
9857
namespace sqlite_orm {
9858
/**
9859
* Wrap a pointer, its type and its deleter function for binding it to a statement.
9860
*
9861
* Unless the deleter yields a nullptr 'xDestroy' function the ownership of the pointed-to-object
9862
* is transferred to the pointer binding, which will delete it through
9863
* the deleter when the statement finishes.
9864
*/
9865
template<class T, class P, class D>
9866
auto bind_pointer(P* p, D d) noexcept -> pointer_binding<P, T, D> {
9867
return {p, std::move(d)};
9868
}
9869
9870
template<class T, class P, class D>
9871
auto bind_pointer(std::unique_ptr<P, D> p) noexcept -> pointer_binding<P, T, D> {
9872
return bind_pointer<T>(p.release(), p.get_deleter());
9873
}
9874
9875
template<typename B>
9876
auto bind_pointer(typename B::qualified_type* p, typename B::deleter_type d = {}) noexcept -> B {
9877
return B{p, std::move(d)};
9878
}
9879
9880
template<class T, class P, class D>
9881
[[deprecated("Use the better named function `bind_pointer(...)`")]] pointer_binding<P, T, D>
9882
bindable_pointer(P* p, D d) noexcept {
9883
return bind_pointer<T>(p, std::move(d));
9884
}
9885
9886
template<class T, class P, class D>
9887
[[deprecated("Use the better named function `bind_pointer(...)`")]] pointer_binding<P, T, D>
9888
bindable_pointer(std::unique_ptr<P, D> p) noexcept {
9889
return bind_pointer<T>(p.release(), p.get_deleter());
9890
}
9891
9892
template<typename B>
9893
[[deprecated("Use the better named function `bind_pointer(...)`")]] B
9894
bindable_pointer(typename B::qualified_type* p, typename B::deleter_type d = {}) noexcept {
9895
return bind_pointer<B>(p, std::move(d));
9896
}
9897
9898
#ifdef SQLITE_ORM_WITH_CPP20_ALIASES
9899
/**
9900
* Wrap a pointer, its type (tag) and its deleter function for binding it to a statement.
9901
*
9902
* Unless the deleter yields a nullptr 'xDestroy' function the ownership of the pointed-to-object
9903
* is transferred to the pointer binding, which will delete it through
9904
* the deleter when the statement finishes.
9905
*/
9906
template<orm_pointer_type auto tag, class P, class D>
9907
auto bind_pointer(P* p, D d) noexcept -> pointer_binding<P, decltype(tag), D> {
9908
return {p, std::move(d)};
9909
}
9910
9911
template<orm_pointer_type auto tag, class P, class D>
9912
auto bind_pointer(std::unique_ptr<P, D> p) noexcept -> pointer_binding<P, decltype(tag), D> {
9913
return bind_pointer<tag>(p.release(), p.get_deleter());
9914
}
9915
#endif
9916
9917
/**
9918
* Wrap a pointer and its type for binding it to a statement.
9919
*
9920
* Note: 'Static' means that ownership of the pointed-to-object won't be transferred
9921
* and sqlite assumes the object pointed to is valid throughout the lifetime of a statement.
9922
*/
9923
template<class T, class P>
9924
auto bind_pointer_statically(P* p) noexcept -> static_pointer_binding<P, T> {
9925
return bind_pointer<T>(p, null_xdestroy_f);
9926
}
9927
9928
template<typename B>
9929
B bind_pointer_statically(typename B::qualified_type* p,
9930
typename B::deleter_type* /*exposition*/ = nullptr) noexcept {
9931
return bind_pointer<B>(p);
9932
}
9933
9934
template<class T, class P>
9935
[[deprecated("Use the better named function `bind_pointer_statically(...)`")]] static_pointer_binding<P, T>
9936
statically_bindable_pointer(P* p) noexcept {
9937
return bind_pointer<T>(p, null_xdestroy_f);
9938
}
9939
9940
template<typename B>
9941
[[deprecated("Use the better named function `bind_pointer_statically(...)`")]] B
9942
statically_bindable_pointer(typename B::qualified_type* p,
9943
typename B::deleter_type* /*exposition*/ = nullptr) noexcept {
9944
return bind_pointer<B>(p);
9945
}
9946
9947
#ifdef SQLITE_ORM_WITH_CPP20_ALIASES
9948
/**
9949
* Wrap a pointer and its type (tag) for binding it to a statement.
9950
*
9951
* Note: 'Static' means that ownership of the pointed-to-object won't be transferred
9952
* and sqlite assumes the object pointed to is valid throughout the lifetime of a statement.
9953
*/
9954
template<orm_pointer_type auto tag, class P>
9955
auto bind_pointer_statically(P* p) noexcept -> static_pointer_binding<P, decltype(tag)> {
9956
return bind_pointer<tag>(p, null_xdestroy_f);
9957
}
9958
#endif
9959
9960
/**
9961
* Forward a pointer value from an argument.
9962
*/
9963
template<class P, class T>
9964
auto rebind_statically(const pointer_arg<P, T>& pv) noexcept -> static_pointer_binding<P, T> {
9965
return bind_pointer_statically<T>(pv.ptr());
9966
}
9967
}
9968
#endif
9969
9970
namespace sqlite_orm {
9971
9972
/**
9973
* Helper class used for binding fields to sqlite3 statements.
9974
*/
9975
template<class V, typename Enable = void>
9976
struct statement_binder;
9977
9978
namespace internal {
9979
/*
9980
* Implementation note: the technique of indirect expression testing is because
9981
* of older compilers having problems with the detection of dependent templates [SQLITE_ORM_BROKEN_ALIAS_TEMPLATE_DEPENDENT_EXPR_SFINAE].
9982
* It must also be a type that differs from those for `is_printable_v`, `is_preparable_v`.
9983
*/
9984
template<class Binder>
9985
struct indirectly_test_bindable;
9986
9987
template<class T, class SFINAE = void>
9988
SQLITE_ORM_INLINE_VAR constexpr bool is_bindable_v = false;
9989
template<class T>
9990
SQLITE_ORM_INLINE_VAR constexpr bool
9991
is_bindable_v<T, polyfill::void_t<indirectly_test_bindable<decltype(statement_binder<T>{})>>> = true;
9992
9993
template<class T>
9994
struct is_bindable : polyfill::bool_constant<is_bindable_v<T>> {};
9995
}
9996
9997
#if SQLITE_VERSION_NUMBER >= 3020000
9998
/**
9999
* Specialization for pointer bindings (part of the 'pointer-passing interface').
10000
*/
10001
template<class P, class T, class D>
10002
struct statement_binder<pointer_binding<P, T, D>, void> {
10003
using V = pointer_binding<P, T, D>;
10004
10005
// ownership of pointed-to-object is left untouched and remains at prepared statement's AST expression
10006
int bind(sqlite3_stmt* stmt, int index, const V& value) const {
10007
// note: C-casting `P* -> void*`, internal::xdestroy_proxy() does the inverse
10008
return sqlite3_bind_pointer(stmt, index, (void*)value.ptr(), T::value, null_xdestroy_f);
10009
}
10010
10011
// ownership of pointed-to-object is transferred to sqlite
10012
void result(sqlite3_context* context, V& value) const {
10013
// note: C-casting `P* -> void*`,
10014
// row_extractor<pointer_arg<P, T>>::extract() and internal::xdestroy_proxy() do the inverse
10015
sqlite3_result_pointer(context, (void*)value.take_ptr(), T::value, value.get_xdestroy());
10016
}
10017
};
10018
#endif
10019
10020
/**
10021
* Specialization for arithmetic types.
10022
*/
10023
template<class V>
10024
struct statement_binder<V, internal::match_if<std::is_arithmetic, V>> {
10025
10026
int bind(sqlite3_stmt* stmt, int index, const V& value) const {
10027
return this->bind(stmt, index, value, tag());
10028
}
10029
10030
void result(sqlite3_context* context, const V& value) const {
10031
this->result(context, value, tag());
10032
}
10033
10034
private:
10035
using tag = arithmetic_tag_t<V>;
10036
10037
int bind(sqlite3_stmt* stmt, int index, const V& value, int_or_smaller_tag) const {
10038
return sqlite3_bind_int(stmt, index, static_cast<int>(value));
10039
}
10040
10041
void result(sqlite3_context* context, const V& value, int_or_smaller_tag) const {
10042
sqlite3_result_int(context, static_cast<int>(value));
10043
}
10044
10045
int bind(sqlite3_stmt* stmt, int index, const V& value, bigint_tag) const {
10046
return sqlite3_bind_int64(stmt, index, static_cast<sqlite3_int64>(value));
10047
}
10048
10049
void result(sqlite3_context* context, const V& value, bigint_tag) const {
10050
sqlite3_result_int64(context, static_cast<sqlite3_int64>(value));
10051
}
10052
10053
int bind(sqlite3_stmt* stmt, int index, const V& value, real_tag) const {
10054
return sqlite3_bind_double(stmt, index, static_cast<double>(value));
10055
}
10056
10057
void result(sqlite3_context* context, const V& value, real_tag) const {
10058
sqlite3_result_double(context, static_cast<double>(value));
10059
}
10060
};
10061
10062
/**
10063
* Specialization for std::string and C-string.
10064
*/
10065
template<class V>
10066
struct statement_binder<V,
10067
std::enable_if_t<polyfill::disjunction<std::is_base_of<std::string, V>,
10068
std::is_same<V, const char*>
10069
#ifdef SQLITE_ORM_STRING_VIEW_SUPPORTED
10070
,
10071
std::is_same<V, std::string_view>
10072
#endif
10073
>::value>> {
10074
10075
int bind(sqlite3_stmt* stmt, int index, const V& value) const {
10076
auto stringData = this->string_data(value);
10077
return sqlite3_bind_text(stmt, index, stringData.first, stringData.second, SQLITE_TRANSIENT);
10078
}
10079
10080
void result(sqlite3_context* context, const V& value) const {
10081
auto stringData = this->string_data(value);
10082
auto dataCopy = new char[stringData.second + 1];
10083
constexpr auto deleter = std::default_delete<char[]>{};
10084
strncpy(dataCopy, stringData.first, stringData.second + 1);
10085
sqlite3_result_text(context, dataCopy, stringData.second, obtain_xdestroy_for(deleter, dataCopy));
10086
}
10087
10088
private:
10089
#ifdef SQLITE_ORM_STRING_VIEW_SUPPORTED
10090
std::pair<const char*, int> string_data(const std::string_view& s) const {
10091
return {s.data(), int(s.size())};
10092
}
10093
#else
10094
std::pair<const char*, int> string_data(const std::string& s) const {
10095
return {s.c_str(), int(s.size())};
10096
}
10097
10098
std::pair<const char*, int> string_data(const char* s) const {
10099
return {s, int(strlen(s))};
10100
}
10101
#endif
10102
};
10103
10104
#ifndef SQLITE_ORM_OMITS_CODECVT
10105
template<class V>
10106
struct statement_binder<V,
10107
std::enable_if_t<polyfill::disjunction<std::is_base_of<std::wstring, V>,
10108
std::is_same<V, const wchar_t*>
10109
#ifdef SQLITE_ORM_STRING_VIEW_SUPPORTED
10110
,
10111
std::is_same<V, std::wstring_view>
10112
#endif
10113
>::value>> {
10114
10115
int bind(sqlite3_stmt* stmt, int index, const V& value) const {
10116
auto stringData = this->string_data(value);
10117
std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>> converter;
10118
std::string utf8Str = converter.to_bytes(stringData.first, stringData.first + stringData.second);
10119
return statement_binder<decltype(utf8Str)>().bind(stmt, index, utf8Str);
10120
}
10121
10122
void result(sqlite3_context* context, const V& value) const {
10123
auto stringData = this->string_data(value);
10124
sqlite3_result_text16(context, stringData.first, stringData.second, nullptr);
10125
}
10126
10127
private:
10128
#ifdef SQLITE_ORM_STRING_VIEW_SUPPORTED
10129
std::pair<const wchar_t*, int> string_data(const std::wstring_view& s) const {
10130
return {s.data(), int(s.size())};
10131
}
10132
#else
10133
std::pair<const wchar_t*, int> string_data(const std::wstring& s) const {
10134
return {s.c_str(), int(s.size())};
10135
}
10136
10137
std::pair<const wchar_t*, int> string_data(const wchar_t* s) const {
10138
return {s, int(wcslen(s))};
10139
}
10140
#endif
10141
};
10142
#endif
10143
10144
/**
10145
* Specialization for nullptr_t.
10146
*/
10147
template<>
10148
struct statement_binder<nullptr_t, void> {
10149
int bind(sqlite3_stmt* stmt, int index, const nullptr_t&) const {
10150
return sqlite3_bind_null(stmt, index);
10151
}
10152
10153
void result(sqlite3_context* context, const nullptr_t&) const {
10154
sqlite3_result_null(context);
10155
}
10156
};
10157
10158
#ifdef SQLITE_ORM_OPTIONAL_SUPPORTED
10159
/**
10160
* Specialization for std::nullopt_t.
10161
*/
10162
template<>
10163
struct statement_binder<std::nullopt_t, void> {
10164
int bind(sqlite3_stmt* stmt, int index, const std::nullopt_t&) const {
10165
return sqlite3_bind_null(stmt, index);
10166
}
10167
10168
void result(sqlite3_context* context, const std::nullopt_t&) const {
10169
sqlite3_result_null(context);
10170
}
10171
};
10172
#endif // SQLITE_ORM_OPTIONAL_SUPPORTED
10173
10174
template<class V>
10175
struct statement_binder<
10176
V,
10177
std::enable_if_t<is_std_ptr<V>::value &&
10178
internal::is_bindable<std::remove_cv_t<typename V::element_type>>::value>> {
10179
using unqualified_type = std::remove_cv_t<typename V::element_type>;
10180
10181
int bind(sqlite3_stmt* stmt, int index, const V& value) const {
10182
if (value) {
10183
return statement_binder<unqualified_type>().bind(stmt, index, *value);
10184
} else {
10185
return statement_binder<nullptr_t>().bind(stmt, index, nullptr);
10186
}
10187
}
10188
};
10189
10190
/**
10191
* Specialization for binary data (std::vector<char>).
10192
*/
10193
template<>
10194
struct statement_binder<std::vector<char>, void> {
10195
int bind(sqlite3_stmt* stmt, int index, const std::vector<char>& value) const {
10196
if (!value.empty()) {
10197
return sqlite3_bind_blob(stmt, index, (const void*)&value.front(), int(value.size()), SQLITE_TRANSIENT);
10198
} else {
10199
return sqlite3_bind_blob(stmt, index, "", 0, SQLITE_TRANSIENT);
10200
}
10201
}
10202
10203
void result(sqlite3_context* context, const std::vector<char>& value) const {
10204
if (!value.empty()) {
10205
sqlite3_result_blob(context, (const void*)&value.front(), int(value.size()), nullptr);
10206
} else {
10207
sqlite3_result_blob(context, "", 0, nullptr);
10208
}
10209
}
10210
};
10211
10212
#ifdef SQLITE_ORM_OPTIONAL_SUPPORTED
10213
template<class V>
10214
struct statement_binder<V,
10215
std::enable_if_t<polyfill::is_specialization_of_v<V, std::optional> &&
10216
internal::is_bindable_v<std::remove_cv_t<typename V::value_type>>>> {
10217
using unqualified_type = std::remove_cv_t<typename V::value_type>;
10218
10219
int bind(sqlite3_stmt* stmt, int index, const V& value) const {
10220
if (value) {
10221
return statement_binder<unqualified_type>().bind(stmt, index, *value);
10222
} else {
10223
return statement_binder<std::nullopt_t>().bind(stmt, index, std::nullopt);
10224
}
10225
}
10226
};
10227
#endif // SQLITE_ORM_OPTIONAL_SUPPORTED
10228
10229
namespace internal {
10230
10231
struct conditional_binder {
10232
sqlite3_stmt* stmt = nullptr;
10233
int index = 1;
10234
10235
explicit conditional_binder(sqlite3_stmt* stmt) : stmt{stmt} {}
10236
10237
template<class T, satisfies<is_bindable, T> = true>
10238
void operator()(const T& t) {
10239
int rc = statement_binder<T>{}.bind(this->stmt, this->index++, t);
10240
if (SQLITE_OK != rc) {
10241
throw_translated_sqlite_error(this->stmt);
10242
}
10243
}
10244
10245
template<class T, satisfies_not<is_bindable, T> = true>
10246
void operator()(const T&) const {}
10247
};
10248
10249
struct field_value_binder : conditional_binder {
10250
using conditional_binder::conditional_binder;
10251
using conditional_binder::operator();
10252
10253
template<class T, satisfies_not<is_bindable, T> = true>
10254
void operator()(const T&) const = delete;
10255
10256
template<class T>
10257
void operator()(const T* value) {
10258
if (!value) {
10259
throw std::system_error{orm_error_code::value_is_null};
10260
}
10261
(*this)(*value);
10262
}
10263
};
10264
10265
struct tuple_value_binder {
10266
sqlite3_stmt* stmt = nullptr;
10267
10268
explicit tuple_value_binder(sqlite3_stmt* stmt) : stmt{stmt} {}
10269
10270
template<class Tpl, class Projection>
10271
void operator()(const Tpl& tpl, Projection project) const {
10272
(*this)(tpl,
10273
std::make_index_sequence<std::tuple_size<Tpl>::value>{},
10274
std::forward<Projection>(project));
10275
}
10276
10277
private:
10278
#ifdef SQLITE_ORM_FOLD_EXPRESSIONS_SUPPORTED
10279
template<class Tpl, size_t... Idx, class Projection>
10280
void operator()(const Tpl& tpl, std::index_sequence<Idx...>, Projection project) const {
10281
(this->bind(polyfill::invoke(project, std::get<Idx>(tpl)), Idx), ...);
10282
}
10283
#else
10284
template<class Tpl, size_t... Idx, class Projection>
10285
void operator()(const Tpl& tpl, std::index_sequence<Idx...>, Projection project) const {
10286
using Sink = int[sizeof...(Idx)];
10287
(void)Sink{(this->bind(polyfill::invoke(project, std::get<Idx>(tpl)), Idx), 0)...};
10288
}
10289
#endif
10290
10291
template<class T>
10292
void bind(const T& t, size_t idx) const {
10293
int rc = statement_binder<T>{}.bind(this->stmt, int(idx + 1), t);
10294
if (SQLITE_OK != rc) {
10295
throw_translated_sqlite_error(this->stmt);
10296
}
10297
}
10298
10299
template<class T>
10300
void bind(const T* value, size_t idx) const {
10301
if (!value) {
10302
throw std::system_error{orm_error_code::value_is_null};
10303
}
10304
(*this)(*value, idx);
10305
}
10306
};
10307
10308
template<class Tpl>
10309
using bindable_filter_t = filter_tuple_t<Tpl, is_bindable>;
10310
}
10311
}
10312
10313
// #include "column_result.h"
10314
10315
#include <type_traits> // std::enable_if, std::is_same, std::decay, std::is_arithmetic, std::is_base_of
10316
#include <functional> // std::reference_wrapper
10317
10318
// #include "functional/cxx_type_traits_polyfill.h"
10319
10320
// #include "functional/mpl.h"
10321
10322
// #include "tuple_helper/tuple_traits.h"
10323
10324
// #include "tuple_helper/tuple_fy.h"
10325
10326
#include <tuple>
10327
10328
namespace sqlite_orm {
10329
10330
namespace internal {
10331
10332
template<typename T>
10333
struct tuplify {
10334
using type = std::tuple<T>;
10335
};
10336
template<typename... Ts>
10337
struct tuplify<std::tuple<Ts...>> {
10338
using type = std::tuple<Ts...>;
10339
};
10340
10341
template<typename T>
10342
using tuplify_t = typename tuplify<T>::type;
10343
}
10344
}
10345
10346
// #include "tuple_helper/tuple_filter.h"
10347
10348
// #include "tuple_helper/tuple_transformer.h"
10349
10350
// #include "tuple_helper/same_or_void.h"
10351
10352
// #include "type_traits.h"
10353
10354
// #include "member_traits/member_traits.h"
10355
10356
// #include "mapped_type_proxy.h"
10357
10358
#include <type_traits> // std::remove_const
10359
10360
// #include "type_traits.h"
10361
10362
// #include "table_reference.h"
10363
10364
// #include "alias_traits.h"
10365
10366
namespace sqlite_orm {
10367
10368
namespace internal {
10369
10370
/**
10371
* If T is a table reference or recordset alias then the typename mapped_type_proxy<T>::type is the unqualified aliased type,
10372
* otherwise unqualified T.
10373
*/
10374
template<class T, class SFINAE = void>
10375
struct mapped_type_proxy : std::remove_const<T> {};
10376
10377
#ifdef SQLITE_ORM_WITH_CPP20_ALIASES
10378
template<orm_table_reference R>
10379
struct mapped_type_proxy<R, void> : R {};
10380
#endif
10381
10382
template<class A>
10383
struct mapped_type_proxy<A, match_if<is_recordset_alias, A>> : std::remove_const<type_t<A>> {};
10384
10385
template<class T>
10386
using mapped_type_proxy_t = typename mapped_type_proxy<T>::type;
10387
}
10388
}
10389
10390
// #include "core_functions.h"
10391
10392
// #include "select_constraints.h"
10393
10394
// #include "operators.h"
10395
10396
// #include "rowid.h"
10397
10398
// #include "column_result_proxy.h"
10399
10400
// #include "type_traits.h"
10401
10402
// #include "table_reference.h"
10403
10404
namespace sqlite_orm {
10405
namespace internal {
10406
10407
/*
10408
* Holder for the type of an unmapped aggregate/structure/object to be constructed ad-hoc from column results.
10409
* `T` must be constructible using direct-list-initialization.
10410
*/
10411
template<class T, class ColResults>
10412
struct structure {
10413
using type = T;
10414
};
10415
}
10416
}
10417
10418
namespace sqlite_orm {
10419
namespace internal {
10420
10421
template<class T, class SFINAE = void>
10422
struct column_result_proxy : std::remove_const<T> {};
10423
10424
/*
10425
* Unwrap `table_reference`
10426
*/
10427
template<class P>
10428
struct column_result_proxy<P, match_if<is_table_reference, P>> : decay_table_ref<P> {};
10429
10430
/*
10431
* Pass through `structure`
10432
*/
10433
template<class P>
10434
struct column_result_proxy<P, match_specialization_of<P, structure>> : P {};
10435
10436
template<class T>
10437
using column_result_proxy_t = typename column_result_proxy<T>::type;
10438
}
10439
}
10440
10441
// #include "alias.h"
10442
10443
// #include "cte_types.h"
10444
10445
#if (SQLITE_VERSION_NUMBER >= 3008003) && defined(SQLITE_ORM_WITH_CTE)
10446
#include <type_traits>
10447
#include <tuple>
10448
#endif
10449
10450
// #include "functional/cxx_core_features.h"
10451
10452
// #include "functional/cxx_type_traits_polyfill.h"
10453
10454
// #include "tuple_helper/tuple_fy.h"
10455
10456
#if (SQLITE_VERSION_NUMBER >= 3008003) && defined(SQLITE_ORM_WITH_CTE)
10457
namespace sqlite_orm {
10458
10459
namespace internal {
10460
10461
/**
10462
* Aliased column expression mapped into a CTE, stored as a field in a table column.
10463
*/
10464
template<class A, class F>
10465
struct aliased_field {
10466
~aliased_field() = delete;
10467
aliased_field(const aliased_field&) = delete;
10468
void operator=(const aliased_field&) = delete;
10469
10470
F field;
10471
};
10472
10473
/**
10474
* This class captures various properties and aspects of a subselect's column expression,
10475
* and is used as a proxy in table_t<>.
10476
*/
10477
template<typename Moniker,
10478
typename ExplicitColRefs,
10479
typename Expression,
10480
typename SubselectColRefs,
10481
typename FinalColRefs,
10482
typename... Fs>
10483
class subselect_mapper {
10484
public:
10485
subselect_mapper() = delete;
10486
10487
// this type name is used to detect the mapping from moniker to object
10488
using cte_moniker_type = Moniker;
10489
using fields_type = std::tuple<Fs...>;
10490
// this type captures the expressions forming the columns in a subselect;
10491
// it is currently unused, however proves to be useful in compilation errors,
10492
// as it simplifies recognizing errors in column expressions
10493
using expressions_tuple = tuplify_t<Expression>;
10494
// this type captures column reference expressions specified at CTE construction;
10495
// those are: member pointers, alias holders
10496
using explicit_colrefs_tuple = ExplicitColRefs;
10497
// this type captures column reference expressions from the subselect;
10498
// those are: member pointers, alias holders
10499
using subselect_colrefs_tuple = SubselectColRefs;
10500
// this type captures column reference expressions merged from SubselectColRefs and ExplicitColRefs
10501
using final_colrefs_tuple = FinalColRefs;
10502
};
10503
}
10504
}
10505
#endif
10506
10507
// #include "storage_traits.h"
10508
10509
#include <tuple> // std::tuple
10510
10511
// #include "functional/cxx_type_traits_polyfill.h"
10512
10513
// #include "tuple_helper/tuple_filter.h"
10514
10515
// #include "tuple_helper/tuple_transformer.h"
10516
10517
// #include "type_traits.h"
10518
10519
// #include "storage_lookup.h"
10520
10521
#include <type_traits> // std::true_type, std::false_type, std::remove_const, std::enable_if, std::is_base_of, std::is_void
10522
#include <tuple>
10523
#include <utility> // std::index_sequence, std::make_index_sequence
10524
10525
// #include "functional/cxx_type_traits_polyfill.h"
10526
10527
// #include "type_traits.h"
10528
10529
namespace sqlite_orm {
10530
namespace internal {
10531
10532
template<class... DBO>
10533
struct storage_t;
10534
10535
template<class... DBO>
10536
using db_objects_tuple = std::tuple<DBO...>;
10537
10538
struct basic_table;
10539
struct index_base;
10540
struct base_trigger;
10541
10542
template<class T>
10543
struct is_storage : std::false_type {};
10544
10545
template<class... DBO>
10546
struct is_storage<storage_t<DBO...>> : std::true_type {};
10547
template<class... DBO>
10548
struct is_storage<const storage_t<DBO...>> : std::true_type {};
10549
10550
template<class T>
10551
struct is_db_objects : std::false_type {};
10552
10553
template<class... DBO>
10554
struct is_db_objects<std::tuple<DBO...>> : std::true_type {};
10555
// note: cannot use `db_objects_tuple` alias template because older compilers have problems
10556
// to match `const db_objects_tuple`.
10557
template<class... DBO>
10558
struct is_db_objects<const std::tuple<DBO...>> : std::true_type {};
10559
10560
/**
10561
* `std::true_type` if given object is mapped, `std::false_type` otherwise.
10562
*
10563
* Note: unlike table_t<>, index_t<>::object_type and trigger_t<>::object_type is always void.
10564
*/
10565
template<typename DBO, typename Lookup>
10566
struct object_type_matches : polyfill::conjunction<polyfill::negation<std::is_void<object_type_t<DBO>>>,
10567
std::is_same<Lookup, object_type_t<DBO>>> {};
10568
10569
/**
10570
* `std::true_type` if given lookup type (object or moniker) is mapped, `std::false_type` otherwise.
10571
*/
10572
template<typename DBO, typename Lookup>
10573
using lookup_type_matches = object_type_matches<DBO, Lookup>;
10574
}
10575
10576
// pick/lookup metafunctions
10577
namespace internal {
10578
10579
/**
10580
* Indirect enabler for DBO, accepting an index to disambiguate non-unique DBOs
10581
*/
10582
template<class Lookup, size_t Ix, class DBO>
10583
struct enable_found_table : std::enable_if<lookup_type_matches<DBO, Lookup>::value, DBO> {};
10584
10585
/**
10586
* SFINAE friendly facility to pick a table definition (`table_t`) from a tuple of database objects.
10587
*
10588
* Lookup - mapped data type
10589
* Seq - index sequence matching the number of DBOs
10590
* DBOs - db_objects_tuple type
10591
*/
10592
template<class Lookup, class Seq, class DBOs>
10593
struct storage_pick_table;
10594
10595
template<class Lookup, size_t... Ix, class... DBO>
10596
struct storage_pick_table<Lookup, std::index_sequence<Ix...>, db_objects_tuple<DBO...>>
10597
: enable_found_table<Lookup, Ix, DBO>... {};
10598
10599
/**
10600
* SFINAE friendly facility to pick a table definition (`table_t`) from a tuple of database objects.
10601
*
10602
* Lookup - 'table' type, mapped data type
10603
* DBOs - db_objects_tuple type, possibly const-qualified
10604
*/
10605
template<class Lookup, class DBOs>
10606
using storage_pick_table_t = typename storage_pick_table<Lookup,
10607
std::make_index_sequence<std::tuple_size<DBOs>::value>,
10608
std::remove_const_t<DBOs>>::type;
10609
10610
/**
10611
* Find a table definition (`table_t`) from a tuple of database objects;
10612
* `std::nonesuch` if not found.
10613
*
10614
* DBOs - db_objects_tuple type
10615
* Lookup - mapped data type
10616
*/
10617
template<class Lookup, class DBOs>
10618
struct storage_find_table : polyfill::detected<storage_pick_table_t, Lookup, DBOs> {};
10619
10620
/**
10621
* Find a table definition (`table_t`) from a tuple of database objects;
10622
* `std::nonesuch` if not found.
10623
*
10624
* DBOs - db_objects_tuple type, possibly const-qualified
10625
* Lookup - mapped data type
10626
*/
10627
template<class Lookup, class DBOs>
10628
using storage_find_table_t = typename storage_find_table<Lookup, std::remove_const_t<DBOs>>::type;
10629
10630
#ifndef SQLITE_ORM_BROKEN_VARIADIC_PACK_EXPANSION
10631
template<class DBOs, class Lookup, class SFINAE = void>
10632
struct is_mapped : std::false_type {};
10633
template<class DBOs, class Lookup>
10634
struct is_mapped<DBOs, Lookup, polyfill::void_t<storage_pick_table_t<Lookup, DBOs>>> : std::true_type {};
10635
#else
10636
template<class DBOs, class Lookup, class SFINAE = storage_find_table_t<Lookup, DBOs>>
10637
struct is_mapped : std::true_type {};
10638
template<class DBOs, class Lookup>
10639
struct is_mapped<DBOs, Lookup, polyfill::nonesuch> : std::false_type {};
10640
#endif
10641
10642
template<class DBOs, class Lookup>
10643
SQLITE_ORM_INLINE_VAR constexpr bool is_mapped_v = is_mapped<DBOs, Lookup>::value;
10644
}
10645
}
10646
10647
// runtime lookup functions
10648
namespace sqlite_orm {
10649
namespace internal {
10650
/**
10651
* Pick the table definition for the specified lookup type from the given tuple of schema objects.
10652
*
10653
* Note: This function requires Lookup to be mapped, otherwise it is removed from the overload resolution set.
10654
*/
10655
template<class Lookup, class DBOs, satisfies<is_mapped, DBOs, Lookup> = true>
10656
auto& pick_table(DBOs& dbObjects) {
10657
using table_type = storage_pick_table_t<Lookup, DBOs>;
10658
return std::get<table_type>(dbObjects);
10659
}
10660
10661
/**
10662
* Return passed in DBOs.
10663
*/
10664
template<class DBOs, class E, satisfies<is_db_objects, DBOs> = true>
10665
decltype(auto) db_objects_for_expression(DBOs& dbObjects, const E&) {
10666
return dbObjects;
10667
}
10668
10669
template<class Lookup, class DBOs, satisfies<is_db_objects, DBOs> = true>
10670
decltype(auto) lookup_table_name(const DBOs& dbObjects);
10671
}
10672
}
10673
10674
// #include "schema/column.h"
10675
10676
namespace sqlite_orm {
10677
namespace internal {
10678
10679
namespace storage_traits {
10680
10681
/**
10682
* DBO - db object (table)
10683
*/
10684
template<class DBO>
10685
struct storage_mapped_columns_impl
10686
: tuple_transformer<filter_tuple_t<elements_type_t<DBO>, is_column>, field_type_t> {};
10687
10688
template<>
10689
struct storage_mapped_columns_impl<polyfill::nonesuch> {
10690
using type = std::tuple<>;
10691
};
10692
10693
/**
10694
* DBOs - db_objects_tuple type
10695
* Lookup - mapped or unmapped data type
10696
*/
10697
template<class DBOs, class Lookup>
10698
struct storage_mapped_columns : storage_mapped_columns_impl<storage_find_table_t<Lookup, DBOs>> {};
10699
10700
/**
10701
* DBO - db object (table)
10702
*/
10703
template<class DBO>
10704
struct storage_mapped_column_expressions_impl
10705
: tuple_transformer<filter_tuple_t<elements_type_t<DBO>, is_column>, column_field_expression_t> {};
10706
10707
template<>
10708
struct storage_mapped_column_expressions_impl<polyfill::nonesuch> {
10709
using type = std::tuple<>;
10710
};
10711
10712
/**
10713
* DBOs - db_objects_tuple type
10714
* Lookup - mapped or unmapped data type
10715
*/
10716
template<class DBOs, class Lookup>
10717
struct storage_mapped_column_expressions
10718
: storage_mapped_column_expressions_impl<storage_find_table_t<Lookup, DBOs>> {};
10719
}
10720
}
10721
}
10722
10723
// #include "function.h"
10724
10725
#include <type_traits> // std::enable_if, std::is_member_function_pointer, std::is_function, std::remove_const, std::decay, std::is_convertible, std::is_same, std::false_type, std::true_type
10726
#ifdef SQLITE_ORM_CPP20_CONCEPTS_SUPPORTED
10727
#include <concepts> // std::copy_constructible
10728
#endif
10729
#include <tuple> // std::tuple, std::tuple_size, std::tuple_element
10730
#include <algorithm> // std::min, std::copy_n
10731
#include <utility> // std::move, std::forward
10732
10733
// #include "functional/cxx_type_traits_polyfill.h"
10734
10735
// #include "functional/cstring_literal.h"
10736
10737
// #include "functional/function_traits.h"
10738
10739
// #include "cxx_type_traits_polyfill.h"
10740
10741
// #include "mpl.h"
10742
10743
namespace sqlite_orm {
10744
namespace internal {
10745
/*
10746
* Define nested typenames:
10747
* - return_type
10748
* - arguments_tuple
10749
* - signature_type
10750
*/
10751
template<class F>
10752
struct function_traits;
10753
10754
/*
10755
* A function's return type
10756
*/
10757
template<class F>
10758
using function_return_type_t = typename function_traits<F>::return_type;
10759
10760
/*
10761
* A function's arguments tuple
10762
*/
10763
template<class F,
10764
template<class...> class Tuple,
10765
template<class...> class ProjectOp = polyfill::type_identity_t>
10766
using function_arguments = typename function_traits<F>::template arguments_tuple<Tuple, ProjectOp>;
10767
10768
/*
10769
* A function's signature
10770
*/
10771
template<class F>
10772
using function_signature_type_t = typename function_traits<F>::signature_type;
10773
10774
template<class R, class... Args>
10775
struct function_traits<R(Args...)> {
10776
using return_type = R;
10777
10778
template<template<class...> class Tuple, template<class...> class ProjectOp>
10779
using arguments_tuple = Tuple<mpl::invoke_fn_t<ProjectOp, Args>...>;
10780
10781
using signature_type = R(Args...);
10782
};
10783
10784
// non-exhaustive partial specializations of `function_traits`
10785
10786
template<class R, class... Args>
10787
struct function_traits<R(Args...) const> : function_traits<R(Args...)> {
10788
using signature_type = R(Args...) const;
10789
};
10790
10791
#ifdef SQLITE_ORM_NOTHROW_ALIASES_SUPPORTED
10792
template<class R, class... Args>
10793
struct function_traits<R(Args...) noexcept> : function_traits<R(Args...)> {
10794
using signature_type = R(Args...) noexcept;
10795
};
10796
10797
template<class R, class... Args>
10798
struct function_traits<R(Args...) const noexcept> : function_traits<R(Args...)> {
10799
using signature_type = R(Args...) const noexcept;
10800
};
10801
#endif
10802
10803
/*
10804
* Pick signature of function pointer
10805
*/
10806
template<class F>
10807
struct function_traits<F(*)> : function_traits<F> {};
10808
10809
/*
10810
* Pick signature of function reference
10811
*/
10812
template<class F>
10813
struct function_traits<F(&)> : function_traits<F> {};
10814
10815
/*
10816
* Pick signature of pointer-to-member function
10817
*/
10818
template<class F, class O>
10819
struct function_traits<F O::*> : function_traits<F> {};
10820
}
10821
}
10822
10823
// #include "type_traits.h"
10824
10825
// #include "tags.h"
10826
10827
namespace sqlite_orm {
10828
10829
struct arg_values;
10830
10831
// note (internal): forward declare even if `SQLITE_VERSION_NUMBER < 3020000` in order to simplify coding below
10832
template<class P, class T>
10833
struct pointer_arg;
10834
// note (internal): forward declare even if `SQLITE_VERSION_NUMBER < 3020000` in order to simplify coding below
10835
template<class P, class T, class D>
10836
class pointer_binding;
10837
10838
namespace internal {
10839
template<class F>
10840
using scalar_call_function_t = decltype(&F::operator());
10841
10842
template<class F>
10843
using aggregate_step_function_t = decltype(&F::step);
10844
10845
template<class F>
10846
using aggregate_fin_function_t = decltype(&F::fin);
10847
10848
template<class F, class SFINAE = void>
10849
SQLITE_ORM_INLINE_VAR constexpr bool is_scalar_udf_v = false;
10850
template<class F>
10851
SQLITE_ORM_INLINE_VAR constexpr bool is_scalar_udf_v<F, polyfill::void_t<scalar_call_function_t<F>>> = true;
10852
10853
template<class F>
10854
struct is_scalar_udf : polyfill::bool_constant<is_scalar_udf_v<F>> {};
10855
10856
template<class F, class SFINAE = void>
10857
SQLITE_ORM_INLINE_VAR constexpr bool is_aggregate_udf_v = false;
10858
template<class F>
10859
SQLITE_ORM_INLINE_VAR constexpr bool is_aggregate_udf_v<
10860
F,
10861
polyfill::void_t<aggregate_step_function_t<F>,
10862
aggregate_fin_function_t<F>,
10863
std::enable_if_t<std::is_member_function_pointer<aggregate_step_function_t<F>>::value>,
10864
std::enable_if_t<std::is_member_function_pointer<aggregate_fin_function_t<F>>::value>>> =
10865
true;
10866
10867
template<class F>
10868
struct is_aggregate_udf : polyfill::bool_constant<is_aggregate_udf_v<F>> {};
10869
10870
template<class UDF>
10871
struct function;
10872
}
10873
10874
#ifdef SQLITE_ORM_WITH_CPP20_ALIASES
10875
/** @short Specifies that a type is a function signature (i.e. a function in the C++ type system).
10876
*/
10877
template<class Sig>
10878
concept orm_function_sig = std::is_function_v<Sig>;
10879
10880
/** @short Specifies that a type is a classic function object.
10881
*
10882
* A classic function object meets the following requirements:
10883
* - defines a single call operator `F::operator()`
10884
* - isn't a traditional sqlite_orm scalar function (having a static `F::name()` function
10885
*/
10886
template<class F>
10887
concept orm_classic_function_object =
10888
((!requires { typename F::is_transparent; }) && (requires { &F::operator(); }) &&
10889
/*rule out sqlite_orm scalar function*/
10890
(!requires { F::name(); }));
10891
10892
/** @short Specifies that a type is a user-defined scalar function.
10893
*
10894
* `UDF` must meet the following requirements:
10895
* - `UDF::name()` static function
10896
* - `UDF::operator()()` call operator
10897
*/
10898
template<class UDF>
10899
concept orm_scalar_udf = requires {
10900
UDF::name();
10901
typename internal::scalar_call_function_t<UDF>;
10902
};
10903
10904
/** @short Specifies that a type is a user-defined aggregate function.
10905
*
10906
* `UDF` must meet the following requirements:
10907
* - `UDF::name()` static function
10908
* - `UDF::step()` member function
10909
* - `UDF::fin()` member function
10910
*/
10911
template<class UDF>
10912
concept orm_aggregate_udf = requires {
10913
UDF::name();
10914
typename internal::aggregate_step_function_t<UDF>;
10915
typename internal::aggregate_fin_function_t<UDF>;
10916
requires std::is_member_function_pointer_v<internal::aggregate_step_function_t<UDF>>;
10917
requires std::is_member_function_pointer_v<internal::aggregate_fin_function_t<UDF>>;
10918
};
10919
10920
/** @short Specifies that a type is a framed user-defined scalar function.
10921
*/
10922
template<class F>
10923
concept orm_scalar_function = (polyfill::is_specialization_of_v<std::remove_const_t<F>, internal::function> &&
10924
orm_scalar_udf<typename F::udf_type>);
10925
10926
/** @short Specifies that a type is a framed user-defined aggregate function.
10927
*/
10928
template<class F>
10929
concept orm_aggregate_function = (polyfill::is_specialization_of_v<std::remove_const_t<F>, internal::function> &&
10930
orm_aggregate_udf<typename F::udf_type>);
10931
10932
/** @short Specifies that a type is a framed and quoted user-defined scalar function.
10933
*/
10934
template<class Q>
10935
concept orm_quoted_scalar_function = requires(const Q& quotedF) {
10936
quotedF.name();
10937
quotedF.callable();
10938
};
10939
#endif
10940
10941
namespace internal {
10942
template<class F, class SFINAE = void>
10943
struct callable_arguments_impl;
10944
10945
template<class F>
10946
struct callable_arguments_impl<F, match_if<is_scalar_udf, F>> {
10947
using args_tuple = function_arguments<scalar_call_function_t<F>, std::tuple, std::decay_t>;
10948
using return_type = function_return_type_t<scalar_call_function_t<F>>;
10949
};
10950
10951
template<class F>
10952
struct callable_arguments_impl<F, match_if<is_aggregate_udf, F>> {
10953
using args_tuple = function_arguments<aggregate_step_function_t<F>, std::tuple, std::decay_t>;
10954
using return_type = function_return_type_t<aggregate_fin_function_t<F>>;
10955
};
10956
10957
#ifdef SQLITE_ORM_WITH_CPP20_ALIASES
10958
template<class F>
10959
requires (std::is_function_v<F>)
10960
struct callable_arguments_impl<F, void> {
10961
using args_tuple = function_arguments<F, std::tuple, std::decay_t>;
10962
using return_type = std::decay_t<function_return_type_t<F>>;
10963
};
10964
#endif
10965
10966
template<class F>
10967
struct callable_arguments : callable_arguments_impl<F> {};
10968
10969
#ifdef SQLITE_ORM_WITH_CPP20_ALIASES
10970
/*
10971
* Bundle of type and name of a quoted user-defined function.
10972
*/
10973
template<class UDF>
10974
struct udf_holder : private std::string {
10975
using udf_type = UDF;
10976
10977
using std::string::basic_string;
10978
10979
const std::string& operator()() const {
10980
return *this;
10981
}
10982
};
10983
#endif
10984
10985
#ifdef SQLITE_ORM_WITH_CPP20_ALIASES
10986
/*
10987
* Bundle of type and name of a traditional sqlite_orm user-defined function.
10988
*/
10989
template<class UDF>
10990
requires (requires { UDF::name(); })
10991
struct udf_holder<UDF>
10992
#else
10993
/*
10994
* Bundle of type and name of a traditional sqlite_orm user-defined function.
10995
*/
10996
template<class UDF>
10997
struct udf_holder
10998
#endif
10999
{
11000
using udf_type = UDF;
11001
11002
template<class R = decltype(UDF::name()),
11003
std::enable_if_t<polyfill::negation<std::is_same<R, char>>::value, bool> = true>
11004
decltype(auto) operator()() const {
11005
return UDF::name();
11006
}
11007
11008
template<class R = decltype(UDF::name()), std::enable_if_t<std::is_same<R, char>::value, bool> = true>
11009
std::string operator()() const {
11010
return std::string{UDF::name()};
11011
}
11012
};
11013
11014
/*
11015
* Represents a call of a user-defined function.
11016
*/
11017
template<class UDF, class... CallArgs>
11018
struct function_call {
11019
using udf_type = UDF;
11020
using args_tuple = std::tuple<CallArgs...>;
11021
11022
udf_holder<udf_type> name;
11023
args_tuple callArgs;
11024
};
11025
11026
template<class T>
11027
SQLITE_ORM_INLINE_VAR constexpr bool
11028
is_operator_argument_v<T, std::enable_if_t<polyfill::is_specialization_of<T, function_call>::value>> = true;
11029
11030
template<class T>
11031
struct unpacked_arg {
11032
using type = T;
11033
};
11034
template<class F, class... CallArgs>
11035
struct unpacked_arg<function_call<F, CallArgs...>> {
11036
using type = typename callable_arguments<F>::return_type;
11037
};
11038
template<class T>
11039
using unpacked_arg_t = typename unpacked_arg<T>::type;
11040
11041
template<size_t I, class FnParam, class CallArg>
11042
SQLITE_ORM_CONSTEVAL bool expected_pointer_value() {
11043
static_assert(polyfill::always_false_v<FnParam, CallArg>, "Expected a pointer value for I-th argument");
11044
return false;
11045
}
11046
11047
template<size_t I, class FnParam, class CallArg, class EnableIfTag = void>
11048
constexpr bool is_same_pvt_v = expected_pointer_value<I, FnParam, CallArg>();
11049
11050
// Always allow binding nullptr to a pointer argument
11051
template<size_t I, class PointerArg>
11052
constexpr bool is_same_pvt_v<I, PointerArg, nullptr_t, polyfill::void_t<typename PointerArg::tag>> = true;
11053
// Always allow binding nullptr to a pointer argument
11054
template<size_t I, class P, class T, class D>
11055
constexpr bool is_same_pvt_v<I, pointer_arg<P, T>, pointer_binding<nullptr_t, T, D>, void> = true;
11056
11057
template<size_t I, class PointerArgDataType, class BindingDataType>
11058
SQLITE_ORM_CONSTEVAL bool assert_same_pointer_data_type() {
11059
constexpr bool valid = std::is_convertible<BindingDataType*, PointerArgDataType*>::value;
11060
static_assert(valid, "Pointer data types of I-th argument do not match");
11061
return valid;
11062
}
11063
11064
#if __cplusplus >= 201703L // C++17 or later
11065
template<size_t I, const char* PointerArg, const char* Binding>
11066
SQLITE_ORM_CONSTEVAL bool assert_same_pointer_tag() {
11067
constexpr bool valid = Binding == PointerArg;
11068
static_assert(valid, "Pointer types (tags) of I-th argument do not match");
11069
return valid;
11070
}
11071
template<size_t I, class PointerArg, class Binding>
11072
constexpr bool
11073
is_same_pvt_v<I, PointerArg, Binding, polyfill::void_t<typename PointerArg::tag, typename Binding::tag>> =
11074
assert_same_pointer_tag<I, PointerArg::tag::value, Binding::tag::value>() &&
11075
assert_same_pointer_data_type<I,
11076
typename PointerArg::qualified_type,
11077
typename Binding::qualified_type>();
11078
#else
11079
template<size_t I, class PointerArg, class Binding>
11080
constexpr bool assert_same_pointer_tag() {
11081
constexpr bool valid = Binding::value == PointerArg::value;
11082
static_assert(valid, "Pointer types (tags) of I-th argument do not match");
11083
return valid;
11084
}
11085
11086
template<size_t I, class PointerArg, class Binding>
11087
constexpr bool
11088
is_same_pvt_v<I, PointerArg, Binding, polyfill::void_t<typename PointerArg::tag, typename Binding::tag>> =
11089
assert_same_pointer_tag<I, typename PointerArg::tag, typename Binding::tag>();
11090
#endif
11091
11092
// not a pointer value, currently leave it unchecked
11093
template<size_t I, class FnParam, class CallArg>
11094
SQLITE_ORM_CONSTEVAL bool validate_pointer_value_type(std::false_type) {
11095
return true;
11096
}
11097
11098
// check the type of pointer values
11099
template<size_t I, class FnParam, class CallArg>
11100
SQLITE_ORM_CONSTEVAL bool validate_pointer_value_type(std::true_type) {
11101
return is_same_pvt_v<I, FnParam, CallArg>;
11102
}
11103
11104
template<class FnParams, class CallArgs>
11105
SQLITE_ORM_CONSTEVAL bool validate_pointer_value_types(polyfill::index_constant<size_t(-1)>) {
11106
return true;
11107
}
11108
template<class FnParams, class CallArgs, size_t I>
11109
SQLITE_ORM_CONSTEVAL bool validate_pointer_value_types(polyfill::index_constant<I>) {
11110
using func_param_type = std::tuple_element_t<I, FnParams>;
11111
using call_arg_type = unpacked_arg_t<std::tuple_element_t<I, CallArgs>>;
11112
11113
#ifdef SQLITE_ORM_RELAXED_CONSTEXPR_SUPPORTED
11114
constexpr bool valid = validate_pointer_value_type<I,
11115
std::tuple_element_t<I, FnParams>,
11116
unpacked_arg_t<std::tuple_element_t<I, CallArgs>>>(
11117
polyfill::bool_constant < (polyfill::is_specialization_of_v<func_param_type, pointer_arg>) ||
11118
(polyfill::is_specialization_of_v<call_arg_type, pointer_binding>) > {});
11119
11120
return validate_pointer_value_types<FnParams, CallArgs>(polyfill::index_constant<I - 1>{}) && valid;
11121
#else
11122
return validate_pointer_value_types<FnParams, CallArgs>(polyfill::index_constant<I - 1>{}) &&
11123
validate_pointer_value_type<I,
11124
std::tuple_element_t<I, FnParams>,
11125
unpacked_arg_t<std::tuple_element_t<I, CallArgs>>>(
11126
polyfill::bool_constant < (polyfill::is_specialization_of_v<func_param_type, pointer_arg>) ||
11127
(polyfill::is_specialization_of_v<call_arg_type, pointer_binding>) > {});
11128
#endif
11129
}
11130
11131
/*
11132
* Note: Currently the number of call arguments is checked and whether the types of pointer values match,
11133
* but other call argument types are not checked against the parameter types of the function.
11134
*/
11135
template<typename UDF, typename... CallArgs>
11136
#ifdef SQLITE_ORM_RELAXED_CONSTEXPR_SUPPORTED
11137
SQLITE_ORM_CONSTEVAL void check_function_call() {
11138
#else
11139
void check_function_call() {
11140
#endif
11141
using call_args_tuple = std::tuple<CallArgs...>;
11142
using function_params_tuple = typename callable_arguments<UDF>::args_tuple;
11143
constexpr size_t callArgsCount = std::tuple_size<call_args_tuple>::value;
11144
constexpr size_t functionParamsCount = std::tuple_size<function_params_tuple>::value;
11145
static_assert(std::is_same<function_params_tuple, std::tuple<arg_values>>::value ||
11146
(callArgsCount == functionParamsCount &&
11147
validate_pointer_value_types<function_params_tuple, call_args_tuple>(
11148
polyfill::index_constant<std::min(functionParamsCount, callArgsCount) - 1>{})),
11149
"Check the number and types of the function call arguments");
11150
}
11151
11152
/*
11153
* Generator of a user-defined function call in a sql query expression.
11154
*
11155
* Use the variable template `func<>` to instantiate.
11156
*
11157
* Calling the function captures the parameters in a `function_call` node.
11158
*/
11159
template<class UDF>
11160
struct function {
11161
using udf_type = UDF;
11162
using callable_type = UDF;
11163
11164
/*
11165
* Generates the SQL function call.
11166
*/
11167
template<typename... CallArgs>
11168
function_call<UDF, CallArgs...> operator()(CallArgs... callArgs) const {
11169
check_function_call<UDF, CallArgs...>();
11170
return {this->udf_holder(), {std::forward<CallArgs>(callArgs)...}};
11171
}
11172
11173
constexpr auto udf_holder() const {
11174
return internal::udf_holder<UDF>{};
11175
}
11176
11177
// returns a character range
11178
constexpr auto name() const {
11179
return this->udf_holder()();
11180
}
11181
};
11182
11183
#ifdef SQLITE_ORM_WITH_CPP20_ALIASES
11184
/*
11185
* Generator of a user-defined function call in a sql query expression.
11186
*
11187
* Use the string literal operator template `""_scalar.quote()` to quote
11188
* a freestanding function, stateless lambda or function object.
11189
*
11190
* Calling the function captures the parameters in a `function_call` node.
11191
*
11192
* Internal note:
11193
* 1. Captures and represents a function [pointer or object], especially one without side effects.
11194
* If `F` is a stateless function object, `quoted_scalar_function::callable()` returns the original function object,
11195
* otherwise it is assumed to have possibe side-effects and `quoted_scalar_function::callable()` returns a copy.
11196
* 2. The nested `udf_type` typename is deliberately chosen to be the function signature,
11197
* and will be the abstracted version of the user-defined function.
11198
*/
11199
template<class F, class Sig, size_t N>
11200
struct quoted_scalar_function {
11201
using udf_type = Sig;
11202
using callable_type = F;
11203
11204
/*
11205
* Generates the SQL function call.
11206
*/
11207
template<typename... CallArgs>
11208
function_call<udf_type, CallArgs...> operator()(CallArgs... callArgs) const {
11209
check_function_call<udf_type, CallArgs...>();
11210
return {this->udf_holder(), {std::forward<CallArgs>(callArgs)...}};
11211
}
11212
11213
/*
11214
* Return original `udf` if stateless or a copy of it otherwise
11215
*/
11216
constexpr decltype(auto) callable() const {
11217
if constexpr (stateless<F>) {
11218
return (this->udf);
11219
} else {
11220
// non-const copy
11221
return F(this->udf);
11222
}
11223
}
11224
11225
constexpr auto udf_holder() const {
11226
return internal::udf_holder<udf_type>{this->name()};
11227
}
11228
11229
constexpr auto name() const {
11230
return this->nme;
11231
}
11232
11233
template<class... Args>
11234
consteval quoted_scalar_function(const char (&name)[N], Args&&... constructorArgs) :
11235
udf(std::forward<Args>(constructorArgs)...) {
11236
std::copy_n(name, N, this->nme);
11237
}
11238
11239
F udf;
11240
char nme[N];
11241
};
11242
11243
template<size_t N>
11244
struct quoted_function_builder : cstring_literal<N> {
11245
using cstring_literal<N>::cstring_literal;
11246
11247
/*
11248
* From a freestanding function, possibly overloaded.
11249
*/
11250
template<orm_function_sig F>
11251
[[nodiscard]] consteval auto quote(F* callable) const {
11252
return quoted_scalar_function<F*, F, N>{this->cstr, std::move(callable)};
11253
}
11254
11255
/*
11256
* From a classic function object instance.
11257
*/
11258
template<class F>
11259
requires (orm_classic_function_object<F> && (stateless<F> || std::copy_constructible<F>))
11260
[[nodiscard]] consteval auto quote(F callable) const {
11261
using Sig = function_signature_type_t<decltype(&F::operator())>;
11262
// detect whether overloaded call operator can be picked using `Sig`
11263
using call_operator_type = decltype(static_cast<Sig F::*>(&F::operator()));
11264
return quoted_scalar_function<F, Sig, N>{this->cstr, std::move(callable)};
11265
}
11266
11267
/*
11268
* From a function object instance, picking the overloaded call operator.
11269
*/
11270
template<orm_function_sig Sig, class F>
11271
requires ((stateless<F> || std::copy_constructible<F>))
11272
[[nodiscard]] consteval auto quote(F callable) const {
11273
// detect whether overloaded call operator can be picked using `Sig`
11274
using call_operator_type = decltype(static_cast<Sig F::*>(&F::operator()));
11275
return quoted_scalar_function<F, Sig, N>{this->cstr, std::move(callable)};
11276
}
11277
11278
/*
11279
* From a classic function object type.
11280
*/
11281
template<orm_classic_function_object F, class... Args>
11282
requires (stateless<F> || std::copy_constructible<F>)
11283
[[nodiscard]] consteval auto quote(Args&&... constructorArgs) const {
11284
using Sig = function_signature_type_t<decltype(&F::operator())>;
11285
return quoted_scalar_function<F, Sig, N>{this->cstr, std::forward<Args>(constructorArgs)...};
11286
}
11287
11288
/*
11289
* From a function object type, picking the overloaded call operator.
11290
*/
11291
template<orm_function_sig Sig, class F, class... Args>
11292
requires ((stateless<F> || std::copy_constructible<F>))
11293
[[nodiscard]] consteval auto quote(Args&&... constructorArgs) const {
11294
// detect whether overloaded call operator can be picked using `Sig`
11295
using call_operator_type = decltype(static_cast<Sig F::*>(&F::operator()));
11296
return quoted_scalar_function<F, Sig, N>{this->cstr, std::forward<Args>(constructorArgs)...};
11297
}
11298
};
11299
#endif
11300
}
11301
11302
/** @short Call a user-defined function.
11303
*
11304
* Note: Currently the number of call arguments is checked and whether the types of pointer values match,
11305
* but other call argument types are not checked against the parameter types of the function.
11306
*
11307
* Example:
11308
* struct IdFunc { int oeprator(int arg)() const { return arg; } };
11309
* // inline:
11310
* select(func<IdFunc>(42));
11311
* // As this is a variable template, you can frame the user-defined function and define a variable for syntactic sugar and legibility:
11312
* inline constexpr orm_scalar_function auto idfunc = func<IdFunc>;
11313
* select(idfunc(42));
11314
*
11315
*/
11316
template<class UDF>
11317
#ifdef SQLITE_ORM_WITH_CPP20_ALIASES
11318
requires (orm_scalar_udf<UDF> || orm_aggregate_udf<UDF>)
11319
#endif
11320
SQLITE_ORM_INLINE_VAR constexpr internal::function<UDF> func{};
11321
11322
#ifdef SQLITE_ORM_WITH_CPP20_ALIASES
11323
inline namespace literals {
11324
/* @short Create a scalar function from a freestanding function, stateless lambda or function object,
11325
* and call such a user-defined function.
11326
*
11327
* If you need to pick a function or method from an overload set, or pick a template function you can
11328
* specify an explicit function signature in the call to `from()`.
11329
*
11330
* Examples:
11331
* // freestanding function from a library
11332
* constexpr orm_quoted_scalar_function auto clamp_int_f = "clamp_int"_scalar.quote(std::clamp<int>);
11333
* // stateless lambda
11334
* constexpr orm_quoted_scalar_function auto is_fatal_error_f = "IS_FATAL_ERROR"_scalar.quote([](unsigned long errcode) {
11335
* return errcode != 0;
11336
* });
11337
* // function object instance
11338
* constexpr orm_quoted_scalar_function auto equal_to_int_f = "equal_to"_scalar.quote(std::equal_to<int>{});
11339
* // function object
11340
* constexpr orm_quoted_scalar_function auto equal_to_int_2_f = "equal_to"_scalar.quote<std::equal_to<int>>();
11341
* // pick function object's template call operator
11342
* constexpr orm_quoted_scalar_function auto equal_to_int_3_f = "equal_to"_scalar.quote<bool(const int&, const int&) const>(std::equal_to<void>{});
11343
*
11344
* storage.create_scalar_function<clamp_int_f>();
11345
* storage.create_scalar_function<is_fatal_error_f>();
11346
* storage.create_scalar_function<equal_to_int_f>();
11347
* storage.create_scalar_function<equal_to_int_2_f>();
11348
* storage.create_scalar_function<equal_to_int_3_f>();
11349
*
11350
* auto rows = storage.select(clamp_int_f(0, 1, 1));
11351
* auto rows = storage.select(is_fatal_error_f(1));
11352
* auto rows = storage.select(equal_to_int_f(1, 1));
11353
* auto rows = storage.select(equal_to_int_2_f(1, 1));
11354
* auto rows = storage.select(equal_to_int_3_f(1, 1));
11355
*/
11356
template<internal::quoted_function_builder builder>
11357
[[nodiscard]] consteval auto operator"" _scalar() {
11358
return builder;
11359
}
11360
}
11361
#endif
11362
}
11363
11364
// #include "ast/special_keywords.h"
11365
11366
namespace sqlite_orm {
11367
namespace internal {
11368
struct current_time_t {};
11369
struct current_date_t {};
11370
struct current_timestamp_t {};
11371
}
11372
11373
inline internal::current_time_t current_time() {
11374
return {};
11375
}
11376
11377
inline internal::current_date_t current_date() {
11378
return {};
11379
}
11380
11381
inline internal::current_timestamp_t current_timestamp() {
11382
return {};
11383
}
11384
}
11385
11386
namespace sqlite_orm {
11387
11388
namespace internal {
11389
11390
/**
11391
* Obtains the result type of expressions that form the columns of a select statement.
11392
*
11393
* This is a proxy class used to define what type must have result type depending on select
11394
* arguments (member pointer, aggregate functions, etc). Below you can see specializations
11395
* for different types. E.g. specialization for internal::length_t has `type` int cause
11396
* LENGTH returns INTEGER in sqlite. Every column_result_t must have `type` type that equals
11397
* c++ SELECT return type for T
11398
* DBOs - db_objects_tuple type
11399
* T - C++ type
11400
* SFINAE - sfinae argument
11401
*/
11402
template<class DBOs, class T, class SFINAE = void>
11403
struct column_result_t {
11404
#ifdef __FUNCTION__
11405
// produce an error message that reveals `T` and `DBOs`
11406
static constexpr bool reveal() {
11407
static_assert(polyfill::always_false_v<T>, "T not found in DBOs - " __FUNCTION__);
11408
}
11409
static constexpr bool trigger = reveal();
11410
#endif
11411
};
11412
11413
template<class DBOs, class T>
11414
using column_result_of_t = typename column_result_t<DBOs, T>::type;
11415
11416
template<class DBOs, class Tpl>
11417
using column_result_for_tuple_t =
11418
transform_tuple_t<Tpl, mpl::bind_front_fn<column_result_of_t, DBOs>::template fn>;
11419
11420
#ifdef SQLITE_ORM_OPTIONAL_SUPPORTED
11421
template<class DBOs, class T>
11422
struct column_result_t<DBOs, as_optional_t<T>, void> {
11423
using type = std::optional<column_result_of_t<DBOs, T>>;
11424
};
11425
11426
template<class DBOs, class T>
11427
struct column_result_t<DBOs, std::optional<T>, void> {
11428
using type = std::optional<T>;
11429
};
11430
#endif // SQLITE_ORM_OPTIONAL_SUPPORTED
11431
11432
template<class DBOs, class L, class A>
11433
struct column_result_t<DBOs, dynamic_in_t<L, A>, void> {
11434
using type = bool;
11435
};
11436
11437
template<class DBOs, class L, class... Args>
11438
struct column_result_t<DBOs, in_t<L, Args...>, void> {
11439
using type = bool;
11440
};
11441
11442
template<class DBOs>
11443
struct column_result_t<DBOs, current_time_t, void> {
11444
using type = std::string;
11445
};
11446
11447
template<class DBOs>
11448
struct column_result_t<DBOs, current_date_t, void> {
11449
using type = std::string;
11450
};
11451
11452
template<class DBOs>
11453
struct column_result_t<DBOs, current_timestamp_t, void> {
11454
using type = std::string;
11455
};
11456
11457
template<class DBOs, class T>
11458
struct column_result_t<DBOs, T, match_if<std::is_member_pointer, T>> : member_field_type<T> {};
11459
11460
template<class DBOs, class R, class S, class... Args>
11461
struct column_result_t<DBOs, built_in_function_t<R, S, Args...>, void> {
11462
using type = R;
11463
};
11464
11465
template<class DBOs, class R, class S, class... Args>
11466
struct column_result_t<DBOs, built_in_aggregate_function_t<R, S, Args...>, void> {
11467
using type = R;
11468
};
11469
11470
template<class DBOs, class F, class... Args>
11471
struct column_result_t<DBOs, function_call<F, Args...>, void> {
11472
using type = typename callable_arguments<F>::return_type;
11473
};
11474
11475
template<class DBOs, class X, class... Rest, class S>
11476
struct column_result_t<DBOs, built_in_function_t<unique_ptr_result_of<X>, S, X, Rest...>, void> {
11477
using type = std::unique_ptr<column_result_of_t<DBOs, X>>;
11478
};
11479
11480
template<class DBOs, class X, class S>
11481
struct column_result_t<DBOs, built_in_aggregate_function_t<unique_ptr_result_of<X>, S, X>, void> {
11482
using type = std::unique_ptr<column_result_of_t<DBOs, X>>;
11483
};
11484
11485
template<class DBOs, class T>
11486
struct column_result_t<DBOs, count_asterisk_t<T>, void> {
11487
using type = int;
11488
};
11489
11490
template<class DBOs>
11491
struct column_result_t<DBOs, nullptr_t, void> {
11492
using type = nullptr_t;
11493
};
11494
11495
template<class DBOs>
11496
struct column_result_t<DBOs, count_asterisk_without_type, void> {
11497
using type = int;
11498
};
11499
11500
template<class DBOs, class T>
11501
struct column_result_t<DBOs, distinct_t<T>, void> : column_result_t<DBOs, T> {};
11502
11503
template<class DBOs, class T>
11504
struct column_result_t<DBOs, all_t<T>, void> : column_result_t<DBOs, T> {};
11505
11506
template<class DBOs, class L, class R>
11507
struct column_result_t<DBOs, conc_t<L, R>, void> {
11508
using type = std::string;
11509
};
11510
11511
template<class DBOs, class T>
11512
struct column_result_t<DBOs, unary_minus_t<T>, void> {
11513
using type = double;
11514
};
11515
11516
template<class DBOs, class L, class R>
11517
struct column_result_t<DBOs, add_t<L, R>, void> {
11518
using type = double;
11519
};
11520
11521
template<class DBOs, class L, class R>
11522
struct column_result_t<DBOs, sub_t<L, R>, void> {
11523
using type = double;
11524
};
11525
11526
template<class DBOs, class L, class R>
11527
struct column_result_t<DBOs, mul_t<L, R>, void> {
11528
using type = double;
11529
};
11530
11531
template<class DBOs, class L, class R>
11532
struct column_result_t<DBOs, div_t<L, R>, void> {
11533
using type = double;
11534
};
11535
11536
template<class DBOs, class L, class R>
11537
struct column_result_t<DBOs, mod_t<L, R>, void> {
11538
using type = double;
11539
};
11540
11541
template<class DBOs, class L, class R>
11542
struct column_result_t<DBOs, bitwise_shift_left_t<L, R>, void> {
11543
using type = int;
11544
};
11545
11546
template<class DBOs, class L, class R>
11547
struct column_result_t<DBOs, bitwise_shift_right_t<L, R>, void> {
11548
using type = int;
11549
};
11550
11551
template<class DBOs, class L, class R>
11552
struct column_result_t<DBOs, bitwise_and_t<L, R>, void> {
11553
using type = int;
11554
};
11555
11556
template<class DBOs, class L, class R>
11557
struct column_result_t<DBOs, bitwise_or_t<L, R>, void> {
11558
using type = int;
11559
};
11560
11561
template<class DBOs, class T>
11562
struct column_result_t<DBOs, bitwise_not_t<T>, void> {
11563
using type = int;
11564
};
11565
11566
template<class DBOs>
11567
struct column_result_t<DBOs, rowid_t, void> {
11568
using type = int64;
11569
};
11570
11571
template<class DBOs>
11572
struct column_result_t<DBOs, oid_t, void> {
11573
using type = int64;
11574
};
11575
11576
template<class DBOs>
11577
struct column_result_t<DBOs, _rowid_t, void> {
11578
using type = int64;
11579
};
11580
11581
template<class DBOs, class T>
11582
struct column_result_t<DBOs, table_rowid_t<T>, void> {
11583
using type = int64;
11584
};
11585
11586
template<class DBOs, class T>
11587
struct column_result_t<DBOs, table_oid_t<T>, void> {
11588
using type = int64;
11589
};
11590
11591
template<class DBOs, class T>
11592
struct column_result_t<DBOs, table__rowid_t<T>, void> {
11593
using type = int64;
11594
};
11595
11596
template<class DBOs, class T, class C>
11597
struct column_result_t<DBOs, alias_column_t<T, C>, void> : column_result_t<DBOs, C> {};
11598
11599
template<class DBOs, class T, class F>
11600
struct column_result_t<DBOs, column_pointer<T, F>, void> : column_result_t<DBOs, F> {};
11601
11602
#if (SQLITE_VERSION_NUMBER >= 3008003) && defined(SQLITE_ORM_WITH_CTE)
11603
template<class DBOs, class Moniker, class ColAlias>
11604
struct column_result_t<DBOs, column_pointer<Moniker, alias_holder<ColAlias>>, void> {
11605
using table_type = storage_pick_table_t<Moniker, DBOs>;
11606
using cte_mapper_type = cte_mapper_type_t<table_type>;
11607
11608
// lookup ColAlias in the final column references
11609
using colalias_index =
11610
find_tuple_type<typename cte_mapper_type::final_colrefs_tuple, alias_holder<ColAlias>>;
11611
static_assert(colalias_index::value < std::tuple_size_v<typename cte_mapper_type::final_colrefs_tuple>,
11612
"No such column mapped into the CTE.");
11613
using type = std::tuple_element_t<colalias_index::value, typename cte_mapper_type::fields_type>;
11614
};
11615
#endif
11616
11617
template<class DBOs, class... Args>
11618
struct column_result_t<DBOs, columns_t<Args...>, void>
11619
: conc_tuple<tuplify_t<column_result_of_t<DBOs, std::decay_t<Args>>>...> {};
11620
11621
template<class DBOs, class T, class... Args>
11622
struct column_result_t<DBOs, struct_t<T, Args...>, void> {
11623
using type = structure<T, tuple_cat_t<tuplify_t<column_result_of_t<DBOs, std::decay_t<Args>>>...>>;
11624
};
11625
11626
template<class DBOs, class T, class... Args>
11627
struct column_result_t<DBOs, select_t<T, Args...>> : column_result_t<DBOs, T> {};
11628
11629
template<class DBOs, class T>
11630
struct column_result_t<DBOs, T, match_if<is_compound_operator, T>> {
11631
using type =
11632
polyfill::detected_t<common_type_of_t, column_result_for_tuple_t<DBOs, typename T::expressions_tuple>>;
11633
static_assert(!std::is_same<type, polyfill::nonesuch>::value,
11634
"Compound select statements must return a common type");
11635
};
11636
11637
template<class DBOs, class T>
11638
struct column_result_t<DBOs, T, match_if<is_binary_condition, T>> {
11639
using type = typename T::result_type;
11640
};
11641
11642
template<class DBOs, class T, class X, class Y, class Z>
11643
struct column_result_t<DBOs, highlight_t<T, X, Y, Z>, void> {
11644
using type = std::string;
11645
};
11646
11647
/**
11648
* Result for the most simple queries like `SELECT 1`
11649
*/
11650
template<class DBOs, class T>
11651
struct column_result_t<DBOs, T, match_if<std::is_arithmetic, T>> {
11652
using type = T;
11653
};
11654
11655
/**
11656
* Result for the most simple queries like `SELECT 'ototo'`
11657
*/
11658
template<class DBOs>
11659
struct column_result_t<DBOs, const char*, void> {
11660
using type = std::string;
11661
};
11662
11663
template<class DBOs>
11664
struct column_result_t<DBOs, std::string, void> {
11665
using type = std::string;
11666
};
11667
11668
template<class DBOs, class T, class E>
11669
struct column_result_t<DBOs, as_t<T, E>, void> : column_result_t<DBOs, std::decay_t<E>> {};
11670
11671
template<class DBOs, class T>
11672
struct column_result_t<DBOs, asterisk_t<T>, void>
11673
: storage_traits::storage_mapped_columns<DBOs, mapped_type_proxy_t<T>> {};
11674
11675
template<class DBOs, class T>
11676
struct column_result_t<DBOs, object_t<T>, void> {
11677
using type = table_reference<T>;
11678
};
11679
11680
template<class DBOs, class T, class E>
11681
struct column_result_t<DBOs, cast_t<T, E>, void> {
11682
using type = T;
11683
};
11684
11685
template<class DBOs, class R, class T, class E, class... Args>
11686
struct column_result_t<DBOs, simple_case_t<R, T, E, Args...>, void> {
11687
using type = R;
11688
};
11689
11690
template<class DBOs, class A, class T, class E>
11691
struct column_result_t<DBOs, like_t<A, T, E>, void> {
11692
using type = bool;
11693
};
11694
11695
template<class DBOs, class A, class T>
11696
struct column_result_t<DBOs, glob_t<A, T>, void> {
11697
using type = bool;
11698
};
11699
11700
template<class DBOs, class C>
11701
struct column_result_t<DBOs, negated_condition_t<C>, void> {
11702
using type = bool;
11703
};
11704
11705
template<class DBOs, class T>
11706
struct column_result_t<DBOs, std::reference_wrapper<T>, void> : column_result_t<DBOs, T> {};
11707
}
11708
}
11709
11710
// #include "mapped_type_proxy.h"
11711
11712
// #include "sync_schema_result.h"
11713
11714
#include <ostream>
11715
11716
namespace sqlite_orm {
11717
11718
enum class sync_schema_result {
11719
11720
/**
11721
* created new table, table with the same tablename did not exist
11722
*/
11723
new_table_created,
11724
11725
/**
11726
* table schema is the same as storage, nothing to be done
11727
*/
11728
already_in_sync,
11729
11730
/**
11731
* removed excess columns in table (than storage) without dropping a table
11732
*/
11733
old_columns_removed,
11734
11735
/**
11736
* lacking columns in table (than storage) added without dropping a table
11737
*/
11738
new_columns_added,
11739
11740
/**
11741
* both old_columns_removed and new_columns_added
11742
*/
11743
new_columns_added_and_old_columns_removed,
11744
11745
/**
11746
* old table is dropped and new is recreated. Reasons :
11747
* 1. delete excess columns in the table than storage if preseve = false
11748
* 2. Lacking columns in the table cannot be added due to NULL and DEFAULT constraint
11749
* 3. Reasons 1 and 2 both together
11750
* 4. data_type mismatch between table and storage.
11751
*/
11752
dropped_and_recreated,
11753
};
11754
11755
inline std::ostream& operator<<(std::ostream& os, sync_schema_result value) {
11756
switch (value) {
11757
case sync_schema_result::new_table_created:
11758
return os << "new table created";
11759
case sync_schema_result::already_in_sync:
11760
return os << "table and storage is already in sync.";
11761
case sync_schema_result::old_columns_removed:
11762
return os << "old excess columns removed";
11763
case sync_schema_result::new_columns_added:
11764
return os << "new columns added";
11765
case sync_schema_result::new_columns_added_and_old_columns_removed:
11766
return os << "old excess columns removed and new columns added";
11767
case sync_schema_result::dropped_and_recreated:
11768
return os << "old table dropped and recreated";
11769
}
11770
return os;
11771
}
11772
}
11773
11774
// #include "table_info.h"
11775
11776
#include <string> // std::string
11777
11778
namespace sqlite_orm {
11779
11780
struct table_info {
11781
int cid = 0;
11782
std::string name;
11783
std::string type;
11784
bool notnull = false;
11785
std::string dflt_value;
11786
int pk = 0;
11787
11788
#if !defined(SQLITE_ORM_AGGREGATE_NSDMI_SUPPORTED) || !defined(SQLITE_ORM_AGGREGATE_PAREN_INIT_SUPPORTED)
11789
table_info(decltype(cid) cid_,
11790
decltype(name) name_,
11791
decltype(type) type_,
11792
decltype(notnull) notnull_,
11793
decltype(dflt_value) dflt_value_,
11794
decltype(pk) pk_) :
11795
cid(cid_), name(std::move(name_)), type(std::move(type_)), notnull(notnull_),
11796
dflt_value(std::move(dflt_value_)), pk(pk_) {}
11797
#endif
11798
};
11799
11800
struct table_xinfo {
11801
int cid = 0;
11802
std::string name;
11803
std::string type;
11804
bool notnull = false;
11805
std::string dflt_value;
11806
int pk = 0;
11807
int hidden = 0; // different than 0 => generated_always_as() - TODO verify
11808
11809
#if !defined(SQLITE_ORM_AGGREGATE_NSDMI_SUPPORTED) || !defined(SQLITE_ORM_AGGREGATE_PAREN_INIT_SUPPORTED)
11810
table_xinfo(decltype(cid) cid_,
11811
decltype(name) name_,
11812
decltype(type) type_,
11813
decltype(notnull) notnull_,
11814
decltype(dflt_value) dflt_value_,
11815
decltype(pk) pk_,
11816
decltype(hidden) hidden_) :
11817
cid(cid_), name(std::move(name_)), type(std::move(type_)), notnull(notnull_),
11818
dflt_value(std::move(dflt_value_)), pk(pk_), hidden{hidden_} {}
11819
#endif
11820
};
11821
}
11822
11823
// #include "storage_impl.h"
11824
11825
#include <string> // std::string
11826
11827
// #include "functional/static_magic.h"
11828
11829
// #include "functional/index_sequence_util.h"
11830
11831
// #include "tuple_helper/tuple_traits.h"
11832
11833
// #include "tuple_helper/tuple_filter.h"
11834
11835
// #include "tuple_helper/tuple_iteration.h"
11836
11837
// #include "type_traits.h"
11838
11839
// #include "select_constraints.h"
11840
11841
// #include "cte_types.h"
11842
11843
// #include "schema/column.h"
11844
11845
// #include "schema/table.h"
11846
11847
#include <string> // std::string
11848
#include <type_traits> // std::remove_const, std::is_member_pointer, std::true_type, std::false_type
11849
#include <vector> // std::vector
11850
#include <tuple> // std::tuple_element
11851
#include <utility> // std::forward, std::move
11852
11853
// #include "../functional/cxx_type_traits_polyfill.h"
11854
11855
// #include "../functional/cxx_functional_polyfill.h"
11856
11857
// #include "../functional/static_magic.h"
11858
11859
// #include "../functional/mpl.h"
11860
11861
// #include "../functional/index_sequence_util.h"
11862
11863
// #include "../tuple_helper/tuple_filter.h"
11864
11865
// #include "../tuple_helper/tuple_traits.h"
11866
11867
// #include "../tuple_helper/tuple_iteration.h"
11868
11869
// #include "../tuple_helper/tuple_transformer.h"
11870
11871
// #include "../member_traits/member_traits.h"
11872
11873
// #include "../typed_comparator.h"
11874
11875
namespace sqlite_orm {
11876
11877
namespace internal {
11878
11879
template<class L, class R>
11880
bool compare_any(const L& /*lhs*/, const R& /*rhs*/) {
11881
return false;
11882
}
11883
template<class O>
11884
bool compare_any(const O& lhs, const O& rhs) {
11885
return lhs == rhs;
11886
}
11887
}
11888
}
11889
11890
// #include "../type_traits.h"
11891
11892
// #include "../alias_traits.h"
11893
11894
// #include "../constraints.h"
11895
11896
// #include "../table_info.h"
11897
11898
// #include "index.h"
11899
11900
#include <tuple> // std::tuple, std::make_tuple, std::declval, std::tuple_element_t
11901
#include <string> // std::string
11902
#include <utility> // std::forward
11903
11904
// #include "../tuple_helper/tuple_traits.h"
11905
11906
// #include "../indexed_column.h"
11907
11908
#include <string> // std::string
11909
#include <utility> // std::move
11910
11911
// #include "ast/where.h"
11912
11913
namespace sqlite_orm {
11914
11915
namespace internal {
11916
11917
template<class C>
11918
struct indexed_column_t {
11919
using column_type = C;
11920
11921
#ifndef SQLITE_ORM_AGGREGATE_NSDMI_SUPPORTED
11922
indexed_column_t(column_type _column_or_expression) :
11923
column_or_expression(std::move(_column_or_expression)) {}
11924
#endif
11925
11926
column_type column_or_expression;
11927
std::string _collation_name;
11928
int _order = 0; // -1 = desc, 1 = asc, 0 = not specified
11929
11930
indexed_column_t<column_type> collate(std::string name) {
11931
auto res = std::move(*this);
11932
res._collation_name = std::move(name);
11933
return res;
11934
}
11935
11936
indexed_column_t<column_type> asc() {
11937
auto res = std::move(*this);
11938
res._order = 1;
11939
return res;
11940
}
11941
11942
indexed_column_t<column_type> desc() {
11943
auto res = std::move(*this);
11944
res._order = -1;
11945
return res;
11946
}
11947
};
11948
11949
template<class C>
11950
indexed_column_t<C> make_indexed_column(C col) {
11951
return {std::move(col)};
11952
}
11953
11954
template<class C>
11955
where_t<C> make_indexed_column(where_t<C> wher) {
11956
return std::move(wher);
11957
}
11958
11959
template<class C>
11960
indexed_column_t<C> make_indexed_column(indexed_column_t<C> col) {
11961
return std::move(col);
11962
}
11963
}
11964
11965
/**
11966
* Use this function to specify indexed column inside `make_index` function call.
11967
* Example: make_index("index_name", indexed_column(&User::id).asc())
11968
*/
11969
template<class C>
11970
internal::indexed_column_t<C> indexed_column(C column_or_expression) {
11971
return {std::move(column_or_expression)};
11972
}
11973
}
11974
11975
// #include "../table_type_of.h"
11976
11977
namespace sqlite_orm {
11978
11979
namespace internal {
11980
11981
struct index_base {
11982
std::string name;
11983
bool unique = false;
11984
11985
#ifndef SQLITE_ORM_AGGREGATE_NSDMI_SUPPORTED
11986
index_base(std::string name, bool unique) : name{std::move(name)}, unique{unique} {}
11987
#endif
11988
};
11989
11990
template<class T, class... Els>
11991
struct index_t : index_base {
11992
using elements_type = std::tuple<Els...>;
11993
using object_type = void;
11994
using table_mapped_type = T;
11995
11996
#ifndef SQLITE_ORM_AGGREGATE_BASES_SUPPORTED
11997
index_t(std::string name_, bool unique_, elements_type elements_) :
11998
index_base{std::move(name_), unique_}, elements(std::move(elements_)) {}
11999
#endif
12000
12001
elements_type elements;
12002
};
12003
}
12004
12005
template<class T, class... Cols>
12006
internal::index_t<T, decltype(internal::make_indexed_column(std::declval<Cols>()))...> make_index(std::string name,
12007
Cols... cols) {
12008
using cols_tuple = std::tuple<Cols...>;
12009
static_assert(internal::count_tuple<cols_tuple, internal::is_where>::value <= 1,
12010
"amount of where arguments can be 0 or 1");
12011
SQLITE_ORM_CLANG_SUPPRESS_MISSING_BRACES(
12012
return {std::move(name), false, std::make_tuple(internal::make_indexed_column(std::move(cols))...)});
12013
}
12014
12015
template<class... Cols>
12016
internal::index_t<internal::table_type_of_t<typename std::tuple_element_t<0, std::tuple<Cols...>>>,
12017
decltype(internal::make_indexed_column(std::declval<Cols>()))...>
12018
make_index(std::string name, Cols... cols) {
12019
using cols_tuple = std::tuple<Cols...>;
12020
static_assert(internal::count_tuple<cols_tuple, internal::is_where>::value <= 1,
12021
"amount of where arguments can be 0 or 1");
12022
SQLITE_ORM_CLANG_SUPPRESS_MISSING_BRACES(
12023
return {std::move(name), false, std::make_tuple(internal::make_indexed_column(std::move(cols))...)});
12024
}
12025
12026
template<class... Cols>
12027
internal::index_t<internal::table_type_of_t<typename std::tuple_element_t<0, std::tuple<Cols...>>>,
12028
decltype(internal::make_indexed_column(std::declval<Cols>()))...>
12029
make_unique_index(std::string name, Cols... cols) {
12030
using cols_tuple = std::tuple<Cols...>;
12031
static_assert(internal::count_tuple<cols_tuple, internal::is_where>::value <= 1,
12032
"amount of where arguments can be 0 or 1");
12033
SQLITE_ORM_CLANG_SUPPRESS_MISSING_BRACES(
12034
return {std::move(name), true, std::make_tuple(internal::make_indexed_column(std::move(cols))...)});
12035
}
12036
}
12037
12038
// #include "column.h"
12039
12040
namespace sqlite_orm {
12041
12042
namespace internal {
12043
12044
template<class T>
12045
using is_table_element_or_constraint = mpl::invoke_t<mpl::disjunction<check_if<is_column>,
12046
check_if<is_primary_key>,
12047
check_if<is_foreign_key>,
12048
check_if_is_template<index_t>,
12049
check_if_is_template<unique_t>,
12050
check_if_is_template<check_t>,
12051
check_if_is_template<prefix_t>,
12052
check_if_is_template<tokenize_t>,
12053
check_if_is_template<content_t>,
12054
check_if_is_template<table_content_t>>,
12055
T>;
12056
12057
#if (SQLITE_VERSION_NUMBER >= 3008003) && defined(SQLITE_ORM_WITH_CTE)
12058
/**
12059
* A subselect mapper's CTE moniker, void otherwise.
12060
*/
12061
template<typename O>
12062
using moniker_of_or_void_t = polyfill::detected_or_t<void, cte_moniker_type_t, O>;
12063
12064
/**
12065
* If O is a subselect_mapper then returns its nested type name O::cte_moniker_type,
12066
* otherwise O itself is a regular object type to be mapped.
12067
*/
12068
template<typename O>
12069
using mapped_object_type_for_t = polyfill::detected_or_t<O, cte_moniker_type_t, O>;
12070
#endif
12071
12072
struct basic_table {
12073
12074
/**
12075
* Table name.
12076
*/
12077
std::string name;
12078
};
12079
12080
/**
12081
* Table definition.
12082
*/
12083
template<class O, bool WithoutRowId, class... Cs>
12084
struct table_t : basic_table {
12085
#if (SQLITE_VERSION_NUMBER >= 3008003) && defined(SQLITE_ORM_WITH_CTE)
12086
// this typename is used in contexts where it is known that the 'table' holds a subselect_mapper
12087
// instead of a regular object type
12088
using cte_mapper_type = O;
12089
using cte_moniker_type = moniker_of_or_void_t<O>;
12090
using object_type = mapped_object_type_for_t<O>;
12091
#else
12092
using object_type = O;
12093
#endif
12094
using elements_type = std::tuple<Cs...>;
12095
12096
static constexpr bool is_without_rowid_v = WithoutRowId;
12097
12098
using is_without_rowid = polyfill::bool_constant<is_without_rowid_v>;
12099
12100
elements_type elements;
12101
12102
#ifndef SQLITE_ORM_AGGREGATE_BASES_SUPPORTED
12103
table_t(std::string name_, elements_type elements_) :
12104
basic_table{std::move(name_)}, elements{std::move(elements_)} {}
12105
#endif
12106
12107
table_t<O, true, Cs...> without_rowid() const {
12108
return {this->name, this->elements};
12109
}
12110
12111
/*
12112
* Returns the number of elements of the specified type.
12113
*/
12114
template<template<class...> class Trait>
12115
static constexpr int count_of() {
12116
using sequence_of = filter_tuple_sequence_t<elements_type, Trait>;
12117
return int(sequence_of::size());
12118
}
12119
12120
/*
12121
* Returns the number of columns having the specified constraint trait.
12122
*/
12123
template<template<class...> class Trait>
12124
static constexpr int count_of_columns_with() {
12125
using filtered_index_sequence = col_index_sequence_with<elements_type, Trait>;
12126
return int(filtered_index_sequence::size());
12127
}
12128
12129
/*
12130
* Returns the number of columns having the specified constraint trait.
12131
*/
12132
template<template<class...> class Trait>
12133
static constexpr int count_of_columns_excluding() {
12134
using excluded_col_index_sequence = col_index_sequence_excluding<elements_type, Trait>;
12135
return int(excluded_col_index_sequence::size());
12136
}
12137
12138
/**
12139
* Function used to get field value from object by mapped member pointer/setter/getter.
12140
*
12141
* For a setter the corresponding getter has to be searched,
12142
* so the method returns a pointer to the field as returned by the found getter.
12143
* Otherwise the method invokes the member pointer and returns its result.
12144
*/
12145
template<class M, satisfies_not<is_setter, M> = true>
12146
decltype(auto) object_field_value(const object_type& object, M memberPointer) const {
12147
return polyfill::invoke(memberPointer, object);
12148
}
12149
12150
template<class M, satisfies<is_setter, M> = true>
12151
const member_field_type_t<M>* object_field_value(const object_type& object, M memberPointer) const {
12152
using field_type = member_field_type_t<M>;
12153
const field_type* res = nullptr;
12154
iterate_tuple(this->elements,
12155
col_index_sequence_with_field_type<elements_type, field_type>{},
12156
call_as_template_base<column_field>([&res, &memberPointer, &object](const auto& column) {
12157
if (compare_any(column.setter, memberPointer)) {
12158
res = &polyfill::invoke(column.member_pointer, object);
12159
}
12160
}));
12161
return res;
12162
}
12163
12164
const basic_generated_always::storage_type*
12165
find_column_generated_storage_type(const std::string& name) const {
12166
const basic_generated_always::storage_type* result = nullptr;
12167
#if SQLITE_VERSION_NUMBER >= 3031000
12168
iterate_tuple(this->elements,
12169
col_index_sequence_with<elements_type, is_generated_always>{},
12170
[&result, &name](auto& column) {
12171
if (column.name != name) {
12172
return;
12173
}
12174
using generated_op_index_sequence =
12175
filter_tuple_sequence_t<std::remove_const_t<decltype(column.constraints)>,
12176
is_generated_always>;
12177
constexpr size_t opIndex = index_sequence_value_at<0>(generated_op_index_sequence{});
12178
result = &std::get<opIndex>(column.constraints).storage;
12179
});
12180
#else
12181
(void)name;
12182
#endif
12183
return result;
12184
}
12185
12186
/**
12187
* Call passed lambda with all defined primary keys.
12188
*/
12189
template<class L>
12190
void for_each_primary_key(L&& lambda) const {
12191
using pk_index_sequence = filter_tuple_sequence_t<elements_type, is_primary_key>;
12192
iterate_tuple(this->elements, pk_index_sequence{}, lambda);
12193
}
12194
12195
std::vector<std::string> composite_key_columns_names() const {
12196
std::vector<std::string> res;
12197
this->for_each_primary_key([this, &res](auto& primaryKey) {
12198
res = this->composite_key_columns_names(primaryKey);
12199
});
12200
return res;
12201
}
12202
12203
std::vector<std::string> primary_key_column_names() const {
12204
using pkcol_index_sequence = col_index_sequence_with<elements_type, is_primary_key>;
12205
12206
if (pkcol_index_sequence::size() > 0) {
12207
return create_from_tuple<std::vector<std::string>>(this->elements,
12208
pkcol_index_sequence{},
12209
&column_identifier::name);
12210
} else {
12211
return this->composite_key_columns_names();
12212
}
12213
}
12214
12215
template<class L>
12216
void for_each_primary_key_column(L&& lambda) const {
12217
iterate_tuple(this->elements,
12218
col_index_sequence_with<elements_type, is_primary_key>{},
12219
call_as_template_base<column_field>([&lambda](const auto& column) {
12220
lambda(column.member_pointer);
12221
}));
12222
this->for_each_primary_key([&lambda](auto& primaryKey) {
12223
iterate_tuple(primaryKey.columns, lambda);
12224
});
12225
}
12226
12227
template<class... Args>
12228
std::vector<std::string> composite_key_columns_names(const primary_key_t<Args...>& primaryKey) const {
12229
return create_from_tuple<std::vector<std::string>>(primaryKey.columns,
12230
[this, empty = std::string{}](auto& memberPointer) {
12231
if (const std::string* columnName =
12232
this->find_column_name(memberPointer)) {
12233
return *columnName;
12234
} else {
12235
return empty;
12236
}
12237
});
12238
}
12239
12240
/**
12241
* Searches column name by class member pointer passed as the first argument.
12242
* @return column name or empty string if nothing found.
12243
*/
12244
template<class M, satisfies<std::is_member_pointer, M> = true>
12245
const std::string* find_column_name(M m) const {
12246
const std::string* res = nullptr;
12247
using field_type = member_field_type_t<M>;
12248
iterate_tuple(this->elements,
12249
col_index_sequence_with_field_type<elements_type, field_type>{},
12250
[&res, m](auto& c) {
12251
if (compare_any(c.member_pointer, m) || compare_any(c.setter, m)) {
12252
res = &c.name;
12253
}
12254
});
12255
return res;
12256
}
12257
12258
/**
12259
* Call passed lambda with all defined foreign keys.
12260
* @param lambda Lambda called for each column. Function signature: `void(auto& column)`
12261
*/
12262
template<class L>
12263
void for_each_foreign_key(L&& lambda) const {
12264
using fk_index_sequence = filter_tuple_sequence_t<elements_type, is_foreign_key>;
12265
iterate_tuple(this->elements, fk_index_sequence{}, lambda);
12266
}
12267
12268
template<class Target, class L>
12269
void for_each_foreign_key_to(L&& lambda) const {
12270
using fk_index_sequence = filter_tuple_sequence_t<elements_type, is_foreign_key>;
12271
using filtered_index_sequence = filter_tuple_sequence_t<elements_type,
12272
check_if_is_type<Target>::template fn,
12273
target_type_t,
12274
fk_index_sequence>;
12275
iterate_tuple(this->elements, filtered_index_sequence{}, lambda);
12276
}
12277
12278
/**
12279
* Call passed lambda with all defined columns.
12280
* @param lambda Lambda called for each column. Function signature: `void(auto& column)`
12281
*/
12282
template<class L>
12283
void for_each_column(L&& lambda) const {
12284
using col_index_sequence = filter_tuple_sequence_t<elements_type, is_column>;
12285
iterate_tuple(this->elements, col_index_sequence{}, lambda);
12286
}
12287
12288
/**
12289
* Call passed lambda with columns not having the specified constraint trait `OpTrait`.
12290
* @param lambda Lambda called for each column.
12291
*/
12292
template<template<class...> class OpTraitFn, class L>
12293
void for_each_column_excluding(L&& lambda) const {
12294
iterate_tuple(this->elements, col_index_sequence_excluding<elements_type, OpTraitFn>{}, lambda);
12295
}
12296
12297
/**
12298
* Call passed lambda with columns not having the specified constraint trait `OpTrait`.
12299
* @param lambda Lambda called for each column.
12300
*/
12301
template<class OpTraitQ, class L, satisfies<mpl::is_quoted_metafuntion, OpTraitQ> = true>
12302
void for_each_column_excluding(L&& lambda) const {
12303
this->template for_each_column_excluding<OpTraitQ::template fn>(lambda);
12304
}
12305
12306
std::vector<table_xinfo> get_table_info() const;
12307
};
12308
12309
template<class T>
12310
struct is_table : std::false_type {};
12311
12312
template<class O, bool W, class... Cs>
12313
struct is_table<table_t<O, W, Cs...>> : std::true_type {};
12314
12315
template<class M>
12316
struct virtual_table_t : basic_table {
12317
using module_details_type = M;
12318
using object_type = typename module_details_type::object_type;
12319
using elements_type = typename module_details_type::columns_type;
12320
12321
static constexpr bool is_without_rowid_v = false;
12322
using is_without_rowid = polyfill::bool_constant<is_without_rowid_v>;
12323
12324
module_details_type module_details;
12325
12326
#ifndef SQLITE_ORM_AGGREGATE_BASES_SUPPORTED
12327
virtual_table_t(std::string name, module_details_type module_details) :
12328
basic_table{std::move(name)}, module_details{std::move(module_details)} {}
12329
#endif
12330
12331
/**
12332
* Call passed lambda with columns not having the specified constraint trait `OpTrait`.
12333
* @param lambda Lambda called for each column.
12334
*/
12335
template<template<class...> class OpTraitFn, class L>
12336
void for_each_column_excluding(L&& lambda) const {
12337
this->module_details.template for_each_column_excluding<OpTraitFn>(lambda);
12338
}
12339
12340
/**
12341
* Call passed lambda with columns not having the specified constraint trait `OpTrait`.
12342
* @param lambda Lambda called for each column.
12343
*/
12344
template<class OpTraitQ, class L, satisfies<mpl::is_quoted_metafuntion, OpTraitQ> = true>
12345
void for_each_column_excluding(L&& lambda) const {
12346
this->module_details.template for_each_column_excluding<OpTraitQ>(lambda);
12347
}
12348
12349
/**
12350
* Call passed lambda with all defined columns.
12351
* @param lambda Lambda called for each column. Function signature: `void(auto& column)`
12352
*/
12353
template<class L>
12354
void for_each_column(L&& lambda) const {
12355
this->module_details.for_each_column(lambda);
12356
}
12357
};
12358
12359
template<class T>
12360
struct is_virtual_table : std::false_type {};
12361
12362
template<class M>
12363
struct is_virtual_table<virtual_table_t<M>> : std::true_type {};
12364
12365
#if SQLITE_VERSION_NUMBER >= 3009000
12366
template<class T, class... Cs>
12367
struct using_fts5_t {
12368
using object_type = T;
12369
using columns_type = std::tuple<Cs...>;
12370
12371
columns_type columns;
12372
12373
using_fts5_t(columns_type columns) : columns(std::move(columns)) {}
12374
12375
/**
12376
* Call passed lambda with columns not having the specified constraint trait `OpTrait`.
12377
* @param lambda Lambda called for each column.
12378
*/
12379
template<template<class...> class OpTraitFn, class L>
12380
void for_each_column_excluding(L&& lambda) const {
12381
iterate_tuple(this->columns, col_index_sequence_excluding<columns_type, OpTraitFn>{}, lambda);
12382
}
12383
12384
/**
12385
* Call passed lambda with columns not having the specified constraint trait `OpTrait`.
12386
* @param lambda Lambda called for each column.
12387
*/
12388
template<class OpTraitQ, class L, satisfies<mpl::is_quoted_metafuntion, OpTraitQ> = true>
12389
void for_each_column_excluding(L&& lambda) const {
12390
this->template for_each_column_excluding<OpTraitQ::template fn>(lambda);
12391
}
12392
12393
/**
12394
* Call passed lambda with all defined columns.
12395
* @param lambda Lambda called for each column. Function signature: `void(auto& column)`
12396
*/
12397
template<class L>
12398
void for_each_column(L&& lambda) const {
12399
using col_index_sequence = filter_tuple_sequence_t<columns_type, is_column>;
12400
iterate_tuple(this->columns, col_index_sequence{}, lambda);
12401
}
12402
};
12403
#endif
12404
12405
template<class O, bool WithoutRowId, class... Cs, class G, class S>
12406
bool exists_in_composite_primary_key(const table_t<O, WithoutRowId, Cs...>& table,
12407
const column_field<G, S>& column) {
12408
bool res = false;
12409
table.for_each_primary_key([&column, &res](auto& primaryKey) {
12410
using colrefs_tuple = decltype(primaryKey.columns);
12411
using same_type_index_sequence =
12412
filter_tuple_sequence_t<colrefs_tuple,
12413
check_if_is_type<member_field_type_t<G>>::template fn,
12414
member_field_type_t>;
12415
iterate_tuple(primaryKey.columns, same_type_index_sequence{}, [&res, &column](auto& memberPointer) {
12416
if (compare_any(memberPointer, column.member_pointer) ||
12417
compare_any(memberPointer, column.setter)) {
12418
res = true;
12419
}
12420
});
12421
});
12422
return res;
12423
}
12424
12425
template<class M, class G, class S>
12426
bool exists_in_composite_primary_key(const virtual_table_t<M>& /*virtualTable*/,
12427
const column_field<G, S>& /*column*/) {
12428
return false;
12429
}
12430
}
12431
12432
#if SQLITE_VERSION_NUMBER >= 3009000
12433
template<class... Cs, class T = typename std::tuple_element_t<0, std::tuple<Cs...>>::object_type>
12434
internal::using_fts5_t<T, Cs...> using_fts5(Cs... columns) {
12435
static_assert(polyfill::conjunction_v<internal::is_table_element_or_constraint<Cs>...>,
12436
"Incorrect table elements or constraints");
12437
12438
SQLITE_ORM_CLANG_SUPPRESS_MISSING_BRACES(return {std::make_tuple(std::forward<Cs>(columns)...)});
12439
}
12440
12441
template<class T, class... Cs>
12442
internal::using_fts5_t<T, Cs...> using_fts5(Cs... columns) {
12443
static_assert(polyfill::conjunction_v<internal::is_table_element_or_constraint<Cs>...>,
12444
"Incorrect table elements or constraints");
12445
12446
SQLITE_ORM_CLANG_SUPPRESS_MISSING_BRACES(return {std::make_tuple(std::forward<Cs>(columns)...)});
12447
}
12448
#endif
12449
12450
/**
12451
* Factory function for a table definition.
12452
*
12453
* The mapped object type is determined implicitly from the first column definition.
12454
*/
12455
template<class... Cs, class T = typename std::tuple_element_t<0, std::tuple<Cs...>>::object_type>
12456
internal::table_t<T, false, Cs...> make_table(std::string name, Cs... args) {
12457
static_assert(polyfill::conjunction_v<internal::is_table_element_or_constraint<Cs>...>,
12458
"Incorrect table elements or constraints");
12459
12460
SQLITE_ORM_CLANG_SUPPRESS_MISSING_BRACES(
12461
return {std::move(name), std::make_tuple<Cs...>(std::forward<Cs>(args)...)});
12462
}
12463
12464
/**
12465
* Factory function for a table definition.
12466
*
12467
* The mapped object type is explicitly specified.
12468
*/
12469
template<class T, class... Cs>
12470
internal::table_t<T, false, Cs...> make_table(std::string name, Cs... args) {
12471
static_assert(polyfill::conjunction_v<internal::is_table_element_or_constraint<Cs>...>,
12472
"Incorrect table elements or constraints");
12473
12474
SQLITE_ORM_CLANG_SUPPRESS_MISSING_BRACES(
12475
return {std::move(name), std::make_tuple<Cs...>(std::forward<Cs>(args)...)});
12476
}
12477
12478
#ifdef SQLITE_ORM_WITH_CPP20_ALIASES
12479
/**
12480
* Factory function for a table definition.
12481
*
12482
* The mapped object type is explicitly specified.
12483
*/
12484
template<orm_table_reference auto table, class... Cs>
12485
auto make_table(std::string name, Cs... args) {
12486
return make_table<internal::auto_decay_table_ref_t<table>>(std::move(name), std::forward<Cs>(args)...);
12487
}
12488
#endif
12489
12490
template<class M>
12491
internal::virtual_table_t<M> make_virtual_table(std::string name, M module_details) {
12492
SQLITE_ORM_CLANG_SUPPRESS_MISSING_BRACES(return {std::move(name), std::move(module_details)});
12493
}
12494
}
12495
12496
// #include "storage_lookup.h"
12497
12498
// interface functions
12499
namespace sqlite_orm {
12500
namespace internal {
12501
12502
template<class DBOs>
12503
using tables_index_sequence = filter_tuple_sequence_t<DBOs, is_table>;
12504
12505
template<class DBOs, satisfies<is_db_objects, DBOs> = true>
12506
int foreign_keys_count(const DBOs& dbObjects) {
12507
int res = 0;
12508
iterate_tuple<true>(dbObjects, tables_index_sequence<DBOs>{}, [&res](const auto& table) {
12509
res += table.template count_of<is_foreign_key>();
12510
});
12511
return res;
12512
}
12513
12514
template<class Lookup, class DBOs, satisfies<is_db_objects, DBOs>>
12515
decltype(auto) lookup_table_name(const DBOs& dbObjects) {
12516
return static_if<is_mapped<DBOs, Lookup>::value>(
12517
[](const auto& dbObjects) -> const std::string& {
12518
return pick_table<Lookup>(dbObjects).name;
12519
},
12520
empty_callable<std::string>)(dbObjects);
12521
}
12522
12523
/**
12524
* Find column name by its type and member pointer.
12525
*/
12526
template<class O, class F, class DBOs, satisfies<is_db_objects, DBOs> = true>
12527
const std::string* find_column_name(const DBOs& dbObjects, F O::* field) {
12528
return pick_table<O>(dbObjects).find_column_name(field);
12529
}
12530
12531
/**
12532
* Materialize column pointer:
12533
* 1. by explicit object type and member pointer.
12534
* 2. by moniker and member pointer.
12535
*/
12536
template<class O, class F, class DBOs, satisfies<is_db_objects, DBOs> = true>
12537
constexpr decltype(auto) materialize_column_pointer(const DBOs&, const column_pointer<O, F>& cp) {
12538
return cp.field;
12539
}
12540
12541
#if (SQLITE_VERSION_NUMBER >= 3008003) && defined(SQLITE_ORM_WITH_CTE)
12542
/**
12543
* Materialize column pointer:
12544
* 3. by moniker and alias_holder<>.
12545
*
12546
* internal note: there's an overload for `find_column_name()` that avoids going through `table_t<>::find_column_name()`
12547
*/
12548
template<class Moniker, class ColAlias, class DBOs, satisfies<is_db_objects, DBOs> = true>
12549
constexpr decltype(auto) materialize_column_pointer(const DBOs&,
12550
const column_pointer<Moniker, alias_holder<ColAlias>>&) {
12551
using table_type = storage_pick_table_t<Moniker, DBOs>;
12552
using cte_mapper_type = cte_mapper_type_t<table_type>;
12553
12554
// lookup ColAlias in the final column references
12555
using colalias_index =
12556
find_tuple_type<typename cte_mapper_type::final_colrefs_tuple, alias_holder<ColAlias>>;
12557
static_assert(colalias_index::value < std::tuple_size_v<typename cte_mapper_type::final_colrefs_tuple>,
12558
"No such column mapped into the CTE.");
12559
12560
return &aliased_field<
12561
ColAlias,
12562
std::tuple_element_t<colalias_index::value, typename cte_mapper_type::fields_type>>::field;
12563
}
12564
#endif
12565
12566
/**
12567
* Find column name by:
12568
* 1. by explicit object type and member pointer.
12569
* 2. by moniker and member pointer.
12570
*/
12571
template<class O, class F, class DBOs, satisfies<is_db_objects, DBOs> = true>
12572
const std::string* find_column_name(const DBOs& dbObjects, const column_pointer<O, F>& cp) {
12573
auto field = materialize_column_pointer(dbObjects, cp);
12574
return pick_table<O>(dbObjects).find_column_name(field);
12575
}
12576
12577
#if (SQLITE_VERSION_NUMBER >= 3008003) && defined(SQLITE_ORM_WITH_CTE)
12578
/**
12579
* Find column name by:
12580
* 3. by moniker and alias_holder<>.
12581
*/
12582
template<class Moniker, class ColAlias, class DBOs, satisfies<is_db_objects, DBOs> = true>
12583
constexpr decltype(auto) find_column_name(const DBOs& dboObjects,
12584
const column_pointer<Moniker, alias_holder<ColAlias>>&) {
12585
using table_type = storage_pick_table_t<Moniker, DBOs>;
12586
using cte_mapper_type = cte_mapper_type_t<table_type>;
12587
using column_index_sequence = filter_tuple_sequence_t<elements_type_t<table_type>, is_column>;
12588
12589
// note: even though the columns contain the [`aliased_field<>::*`] we perform the lookup using the column references.
12590
// lookup ColAlias in the final column references
12591
using colalias_index =
12592
find_tuple_type<typename cte_mapper_type::final_colrefs_tuple, alias_holder<ColAlias>>;
12593
static_assert(colalias_index::value < std::tuple_size_v<typename cte_mapper_type::final_colrefs_tuple>,
12594
"No such column mapped into the CTE.");
12595
12596
// note: we could "materialize" the alias to an `aliased_field<>::*` and use the regular `table_t<>::find_column_name()` mechanism;
12597
// however we have the column index already.
12598
// lookup column in table_t<>'s elements
12599
constexpr size_t ColIdx = index_sequence_value_at<colalias_index::value>(column_index_sequence{});
12600
auto& table = pick_table<Moniker>(dboObjects);
12601
return &std::get<ColIdx>(table.elements).name;
12602
}
12603
#endif
12604
}
12605
}
12606
12607
// #include "journal_mode.h"
12608
12609
#include <array> // std::array
12610
#include <string> // std::string
12611
#include <utility> // std::pair
12612
#include <algorithm> // std::ranges::transform
12613
#include <cctype> // std::toupper
12614
12615
// #include "serialize_result_type.h"
12616
12617
#if defined(_WINNT_)
12618
// DELETE is a macro defined in the Windows SDK (winnt.h)
12619
#pragma push_macro("DELETE")
12620
#undef DELETE
12621
#endif
12622
12623
namespace sqlite_orm {
12624
12625
/**
12626
* Caps case because of:
12627
* 1) delete keyword;
12628
* 2) https://www.sqlite.org/pragma.html#pragma_journal_mode original spelling
12629
*/
12630
enum class journal_mode : signed char {
12631
DELETE = 0,
12632
// An alternate enumeration value when using the Windows SDK that defines DELETE as a macro.
12633
DELETE_ = DELETE,
12634
TRUNCATE = 1,
12635
PERSIST = 2,
12636
MEMORY = 3,
12637
WAL = 4,
12638
OFF = 5,
12639
};
12640
12641
namespace internal {
12642
12643
inline const serialize_result_type& journal_mode_to_string(journal_mode value) {
12644
#ifdef SQLITE_ORM_STRING_VIEW_SUPPORTED
12645
static constexpr std::array<serialize_result_type, 6> idx2str = {
12646
#else
12647
static const std::array<serialize_result_type, 6> idx2str = {
12648
#endif
12649
"DELETE",
12650
"TRUNCATE",
12651
"PERSIST",
12652
"MEMORY",
12653
"WAL",
12654
"OFF",
12655
};
12656
return idx2str.at(static_cast<int>(value));
12657
}
12658
12659
inline std::pair<bool, journal_mode> journal_mode_from_string(std::string string) {
12660
static constexpr std::array<journal_mode, 6> journalModes = {{
12661
journal_mode::DELETE,
12662
journal_mode::TRUNCATE,
12663
journal_mode::PERSIST,
12664
journal_mode::MEMORY,
12665
journal_mode::WAL,
12666
journal_mode::OFF,
12667
}};
12668
#if __cpp_lib_ranges >= 201911L
12669
std::ranges::transform(string, string.begin(), [](unsigned char c) noexcept {
12670
return std::toupper(c);
12671
});
12672
if (auto found = std::ranges::find(journalModes, string, journal_mode_to_string);
12673
found != journalModes.end()) SQLITE_ORM_CPP_LIKELY {
12674
return {true, *found};
12675
}
12676
#else
12677
std::transform(string.begin(), string.end(), string.begin(), [](unsigned char c) noexcept {
12678
return std::toupper(c);
12679
});
12680
for (auto journalMode: journalModes) {
12681
if (journal_mode_to_string(journalMode) == string) {
12682
return {true, journalMode};
12683
}
12684
}
12685
#endif
12686
return {false, journal_mode::OFF};
12687
}
12688
}
12689
}
12690
12691
#if defined(_WINNT_)
12692
#pragma pop_macro("DELETE")
12693
#endif
12694
12695
// #include "mapped_view.h"
12696
12697
#include <sqlite3.h>
12698
#include <utility> // std::forward, std::move
12699
12700
// #include "row_extractor.h"
12701
12702
#include <sqlite3.h>
12703
#include <type_traits> // std::enable_if_t, std::is_arithmetic, std::is_same, std::enable_if
12704
#include <cstdlib> // atof, atoi, atoll
12705
#include <cstring> // strlen
12706
#include <system_error> // std::system_error
12707
#include <string> // std::string, std::wstring
12708
#ifndef SQLITE_ORM_OMITS_CODECVT
12709
#include <locale> // std::wstring_convert
12710
#include <codecvt> // std::codecvt_utf8_utf16
12711
#endif
12712
#include <vector> // std::vector
12713
#include <algorithm> // std::copy
12714
#include <iterator> // std::back_inserter
12715
#include <tuple> // std::tuple, std::tuple_size, std::tuple_element
12716
#ifdef SQLITE_ORM_CPP20_CONCEPTS_SUPPORTED
12717
#include <concepts>
12718
#endif
12719
12720
// #include "functional/cxx_functional_polyfill.h"
12721
12722
// #include "functional/static_magic.h"
12723
12724
// #include "tuple_helper/tuple_transformer.h"
12725
12726
// #include "column_result_proxy.h"
12727
12728
// #include "arithmetic_tag.h"
12729
12730
// #include "pointer_value.h"
12731
12732
// #include "journal_mode.h"
12733
12734
// #include "locking_mode.h"
12735
12736
#include <array> // std::array
12737
#include <string> // std::string
12738
#include <utility> // std::pair
12739
#include <algorithm> // std::ranges::transform
12740
#include <cctype> // std::toupper
12741
12742
// #include "serialize_result_type.h"
12743
12744
namespace sqlite_orm {
12745
enum class locking_mode : signed char {
12746
NORMAL = 0,
12747
EXCLUSIVE = 1,
12748
};
12749
12750
namespace internal {
12751
inline const serialize_result_type& locking_mode_to_string(locking_mode value) {
12752
#ifdef SQLITE_ORM_STRING_VIEW_SUPPORTED
12753
static constexpr std::array<serialize_result_type, 2> idx2str = {
12754
#else
12755
static const std::array<serialize_result_type, 2> idx2str = {
12756
#endif
12757
"NORMAL",
12758
"EXCLUSIVE",
12759
};
12760
return idx2str.at(static_cast<int>(value));
12761
}
12762
12763
inline std::pair<bool, locking_mode> locking_mode_from_string(std::string string) {
12764
static constexpr std::array<locking_mode, 2> lockingModes = {{
12765
locking_mode::NORMAL,
12766
locking_mode::EXCLUSIVE,
12767
}};
12768
12769
#if __cpp_lib_ranges >= 201911L
12770
std::ranges::transform(string, string.begin(), [](unsigned char c) noexcept {
12771
return std::toupper(c);
12772
});
12773
if (auto found = std::ranges::find(lockingModes, string, locking_mode_to_string);
12774
found != lockingModes.end()) SQLITE_ORM_CPP_LIKELY {
12775
return {true, *found};
12776
}
12777
#else
12778
std::transform(string.begin(), string.end(), string.begin(), [](unsigned char c) noexcept {
12779
return std::toupper(c);
12780
});
12781
for (auto lockingMode: lockingModes) {
12782
if (locking_mode_to_string(lockingMode) == string) {
12783
return {true, lockingMode};
12784
}
12785
}
12786
#endif
12787
return {false, locking_mode::NORMAL};
12788
}
12789
}
12790
}
12791
// #include "error_code.h"
12792
12793
// #include "is_std_ptr.h"
12794
12795
// #include "type_traits.h"
12796
12797
namespace sqlite_orm {
12798
12799
/**
12800
* Helper for casting values originating from SQL to C++ typed values, usually from rows of a result set.
12801
*
12802
* sqlite_orm provides specializations for known C++ types, users may define their custom specialization
12803
* of this helper.
12804
*
12805
* @note (internal): Since row extractors are used in certain contexts with only one purpose at a time
12806
* (e.g., converting a row result set but not function values or column text),
12807
* there are factory functions that perform conceptual checking that should be used
12808
* instead of directly creating row extractors.
12809
*
12810
*
12811
*/
12812
template<class V, typename Enable = void>
12813
struct row_extractor {
12814
/*
12815
* Called during one-step query execution (one result row) for each column of a result row.
12816
*/
12817
V extract(const char* columnText) const = delete;
12818
12819
/*
12820
* Called during multi-step query execution (result set) for each column of a result row.
12821
*/
12822
V extract(sqlite3_stmt* stmt, int columnIndex) const = delete;
12823
12824
/*
12825
* Called before invocation of user-defined scalar or aggregate functions,
12826
* in order to unbox dynamically typed SQL function values into a tuple of C++ function arguments.
12827
*/
12828
V extract(sqlite3_value* value) const = delete;
12829
};
12830
12831
#ifdef SQLITE_ORM_CPP20_CONCEPTS_SUPPORTED
12832
template<typename T>
12833
concept orm_column_text_extractable = requires(const row_extractor<T>& extractor, const char* columnText) {
12834
{ extractor.extract(columnText) } -> std::same_as<T>;
12835
};
12836
12837
template<typename T>
12838
concept orm_row_value_extractable =
12839
requires(const row_extractor<T>& extractor, sqlite3_stmt* stmt, int columnIndex) {
12840
{ extractor.extract(stmt, columnIndex) } -> std::same_as<T>;
12841
};
12842
12843
template<typename T>
12844
concept orm_boxed_value_extractable = requires(const row_extractor<T>& extractor, sqlite3_value* value) {
12845
{ extractor.extract(value) } -> std::same_as<T>;
12846
};
12847
#endif
12848
12849
namespace internal {
12850
/*
12851
* Make a row extractor to be used for casting SQL column text to a C++ typed value.
12852
*/
12853
template<class R>
12854
#ifdef SQLITE_ORM_CPP20_CONCEPTS_SUPPORTED
12855
requires (orm_column_text_extractable<R>)
12856
#endif
12857
row_extractor<R> column_text_extractor() {
12858
return {};
12859
}
12860
12861
/*
12862
* Make a row extractor to be used for converting a value from a SQL result row set to a C++ typed value.
12863
*/
12864
template<class R>
12865
#ifdef SQLITE_ORM_CPP20_CONCEPTS_SUPPORTED
12866
requires (orm_row_value_extractable<R>)
12867
#endif
12868
row_extractor<R> row_value_extractor() {
12869
return {};
12870
}
12871
12872
/*
12873
* Make a row extractor to be used for unboxing a dynamically typed SQL value to a C++ typed value.
12874
*/
12875
template<class R>
12876
#ifdef SQLITE_ORM_CPP20_CONCEPTS_SUPPORTED
12877
requires (orm_boxed_value_extractable<R>)
12878
#endif
12879
row_extractor<R> boxed_value_extractor() {
12880
return {};
12881
}
12882
}
12883
12884
template<class R>
12885
int extract_single_value(void* data, int argc, char** argv, char**) {
12886
auto& res = *(R*)data;
12887
if (argc) {
12888
const auto rowExtractor = internal::column_text_extractor<R>();
12889
res = rowExtractor.extract(argv[0]);
12890
}
12891
return 0;
12892
}
12893
12894
#if SQLITE_VERSION_NUMBER >= 3020000
12895
/**
12896
* Specialization for the 'pointer-passing interface'.
12897
*
12898
* @note The 'pointer-passing' interface doesn't support (and in fact prohibits)
12899
* extracting pointers from columns.
12900
*/
12901
template<class P, class T>
12902
struct row_extractor<pointer_arg<P, T>, void> {
12903
using V = pointer_arg<P, T>;
12904
12905
V extract(const char* columnText) const = delete;
12906
12907
V extract(sqlite3_stmt* stmt, int columnIndex) const = delete;
12908
12909
V extract(sqlite3_value* value) const {
12910
return {(P*)sqlite3_value_pointer(value, T::value)};
12911
}
12912
};
12913
12914
/**
12915
* Undefine using pointer_binding<> for querying values
12916
*/
12917
template<class P, class T, class D>
12918
struct row_extractor<pointer_binding<P, T, D>, void>;
12919
#endif
12920
12921
/**
12922
* Specialization for arithmetic types.
12923
*/
12924
template<class V>
12925
struct row_extractor<V, std::enable_if_t<std::is_arithmetic<V>::value>> {
12926
V extract(const char* columnText) const {
12927
return this->extract(columnText, tag());
12928
}
12929
12930
V extract(sqlite3_stmt* stmt, int columnIndex) const {
12931
return this->extract(stmt, columnIndex, tag());
12932
}
12933
12934
V extract(sqlite3_value* value) const {
12935
return this->extract(value, tag());
12936
}
12937
12938
private:
12939
using tag = arithmetic_tag_t<V>;
12940
12941
V extract(const char* columnText, const int_or_smaller_tag&) const {
12942
return static_cast<V>(atoi(columnText));
12943
}
12944
12945
V extract(sqlite3_stmt* stmt, int columnIndex, const int_or_smaller_tag&) const {
12946
return static_cast<V>(sqlite3_column_int(stmt, columnIndex));
12947
}
12948
12949
V extract(sqlite3_value* value, const int_or_smaller_tag&) const {
12950
return static_cast<V>(sqlite3_value_int(value));
12951
}
12952
12953
V extract(const char* columnText, const bigint_tag&) const {
12954
return static_cast<V>(atoll(columnText));
12955
}
12956
12957
V extract(sqlite3_stmt* stmt, int columnIndex, const bigint_tag&) const {
12958
return static_cast<V>(sqlite3_column_int64(stmt, columnIndex));
12959
}
12960
12961
V extract(sqlite3_value* value, const bigint_tag&) const {
12962
return static_cast<V>(sqlite3_value_int64(value));
12963
}
12964
12965
V extract(const char* columnText, const real_tag&) const {
12966
return static_cast<V>(atof(columnText));
12967
}
12968
12969
V extract(sqlite3_stmt* stmt, int columnIndex, const real_tag&) const {
12970
return static_cast<V>(sqlite3_column_double(stmt, columnIndex));
12971
}
12972
12973
V extract(sqlite3_value* value, const real_tag&) const {
12974
return static_cast<V>(sqlite3_value_double(value));
12975
}
12976
};
12977
12978
/**
12979
* Specialization for std::string.
12980
*/
12981
template<class T>
12982
struct row_extractor<T, std::enable_if_t<std::is_base_of<std::string, T>::value>> {
12983
T extract(const char* columnText) const {
12984
if (columnText) {
12985
return columnText;
12986
} else {
12987
return {};
12988
}
12989
}
12990
12991
T extract(sqlite3_stmt* stmt, int columnIndex) const {
12992
if (auto cStr = (const char*)sqlite3_column_text(stmt, columnIndex)) {
12993
return cStr;
12994
} else {
12995
return {};
12996
}
12997
}
12998
12999
T extract(sqlite3_value* value) const {
13000
if (auto cStr = (const char*)sqlite3_value_text(value)) {
13001
return cStr;
13002
} else {
13003
return {};
13004
}
13005
}
13006
};
13007
#ifndef SQLITE_ORM_OMITS_CODECVT
13008
/**
13009
* Specialization for std::wstring.
13010
*/
13011
template<>
13012
struct row_extractor<std::wstring, void> {
13013
std::wstring extract(const char* columnText) const {
13014
if (columnText) {
13015
std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>> converter;
13016
return converter.from_bytes(columnText);
13017
} else {
13018
return {};
13019
}
13020
}
13021
13022
std::wstring extract(sqlite3_stmt* stmt, int columnIndex) const {
13023
auto cStr = (const char*)sqlite3_column_text(stmt, columnIndex);
13024
if (cStr) {
13025
std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>> converter;
13026
return converter.from_bytes(cStr);
13027
} else {
13028
return {};
13029
}
13030
}
13031
13032
std::wstring extract(sqlite3_value* value) const {
13033
if (auto cStr = (const wchar_t*)sqlite3_value_text16(value)) {
13034
return cStr;
13035
} else {
13036
return {};
13037
}
13038
}
13039
};
13040
#endif // SQLITE_ORM_OMITS_CODECVT
13041
13042
template<class V>
13043
struct row_extractor<V, std::enable_if_t<is_std_ptr<V>::value>> {
13044
using unqualified_type = std::remove_cv_t<typename V::element_type>;
13045
13046
V extract(const char* columnText) const
13047
#ifdef SQLITE_ORM_CPP20_CONCEPTS_SUPPORTED
13048
requires (orm_column_text_extractable<unqualified_type>)
13049
#endif
13050
{
13051
if (columnText) {
13052
const row_extractor<unqualified_type> rowExtractor{};
13053
return is_std_ptr<V>::make(rowExtractor.extract(columnText));
13054
} else {
13055
return {};
13056
}
13057
}
13058
13059
V extract(sqlite3_stmt* stmt, int columnIndex) const
13060
#ifdef SQLITE_ORM_CPP20_CONCEPTS_SUPPORTED
13061
requires (orm_row_value_extractable<unqualified_type>)
13062
#endif
13063
{
13064
auto type = sqlite3_column_type(stmt, columnIndex);
13065
if (type != SQLITE_NULL) {
13066
const row_extractor<unqualified_type> rowExtractor{};
13067
return is_std_ptr<V>::make(rowExtractor.extract(stmt, columnIndex));
13068
} else {
13069
return {};
13070
}
13071
}
13072
13073
V extract(sqlite3_value* value) const
13074
#ifdef SQLITE_ORM_CPP20_CONCEPTS_SUPPORTED
13075
requires (orm_boxed_value_extractable<unqualified_type>)
13076
#endif
13077
{
13078
auto type = sqlite3_value_type(value);
13079
if (type != SQLITE_NULL) {
13080
const row_extractor<unqualified_type> rowExtractor{};
13081
return is_std_ptr<V>::make(rowExtractor.extract(value));
13082
} else {
13083
return {};
13084
}
13085
}
13086
};
13087
13088
#ifdef SQLITE_ORM_OPTIONAL_SUPPORTED
13089
template<class V>
13090
struct row_extractor<V, std::enable_if_t<polyfill::is_specialization_of_v<V, std::optional>>> {
13091
using unqualified_type = std::remove_cv_t<typename V::value_type>;
13092
13093
V extract(const char* columnText) const
13094
#ifdef SQLITE_ORM_CPP20_CONCEPTS_SUPPORTED
13095
requires (orm_column_text_extractable<unqualified_type>)
13096
#endif
13097
{
13098
if (columnText) {
13099
const row_extractor<unqualified_type> rowExtractor{};
13100
return std::make_optional(rowExtractor.extract(columnText));
13101
} else {
13102
return std::nullopt;
13103
}
13104
}
13105
13106
V extract(sqlite3_stmt* stmt, int columnIndex) const
13107
#ifdef SQLITE_ORM_CPP20_CONCEPTS_SUPPORTED
13108
requires (orm_row_value_extractable<unqualified_type>)
13109
#endif
13110
{
13111
auto type = sqlite3_column_type(stmt, columnIndex);
13112
if (type != SQLITE_NULL) {
13113
const row_extractor<unqualified_type> rowExtractor{};
13114
return std::make_optional(rowExtractor.extract(stmt, columnIndex));
13115
} else {
13116
return std::nullopt;
13117
}
13118
}
13119
13120
V extract(sqlite3_value* value) const
13121
#ifdef SQLITE_ORM_CPP20_CONCEPTS_SUPPORTED
13122
requires (orm_boxed_value_extractable<unqualified_type>)
13123
#endif
13124
{
13125
auto type = sqlite3_value_type(value);
13126
if (type != SQLITE_NULL) {
13127
const row_extractor<unqualified_type> rowExtractor{};
13128
return std::make_optional(rowExtractor.extract(value));
13129
} else {
13130
return std::nullopt;
13131
}
13132
}
13133
};
13134
#endif // SQLITE_ORM_OPTIONAL_SUPPORTED
13135
13136
template<>
13137
struct row_extractor<nullptr_t, void> {
13138
nullptr_t extract(const char* /*columnText*/) const {
13139
return nullptr;
13140
}
13141
13142
nullptr_t extract(sqlite3_stmt*, int /*columnIndex*/) const {
13143
return nullptr;
13144
}
13145
13146
nullptr_t extract(sqlite3_value*) const {
13147
return nullptr;
13148
}
13149
};
13150
/**
13151
* Specialization for std::vector<char>.
13152
*/
13153
template<>
13154
struct row_extractor<std::vector<char>, void> {
13155
std::vector<char> extract(const char* columnText) const {
13156
return {columnText, columnText + (columnText ? strlen(columnText) : 0)};
13157
}
13158
13159
std::vector<char> extract(sqlite3_stmt* stmt, int columnIndex) const {
13160
auto bytes = static_cast<const char*>(sqlite3_column_blob(stmt, columnIndex));
13161
auto len = static_cast<size_t>(sqlite3_column_bytes(stmt, columnIndex));
13162
return {bytes, bytes + len};
13163
}
13164
13165
std::vector<char> extract(sqlite3_value* value) const {
13166
auto bytes = static_cast<const char*>(sqlite3_value_blob(value));
13167
auto len = static_cast<size_t>(sqlite3_value_bytes(value));
13168
return {bytes, bytes + len};
13169
}
13170
};
13171
13172
/**
13173
* Specialization for locking_mode.
13174
*/
13175
template<>
13176
struct row_extractor<locking_mode, void> {
13177
locking_mode extract(const char* columnText) const {
13178
if (columnText) {
13179
auto resultPair = internal::locking_mode_from_string(columnText);
13180
if (resultPair.first) {
13181
return resultPair.second;
13182
} else {
13183
throw std::system_error{orm_error_code::incorrect_locking_mode_string};
13184
}
13185
} else {
13186
throw std::system_error{orm_error_code::incorrect_locking_mode_string};
13187
}
13188
}
13189
13190
locking_mode extract(sqlite3_stmt* stmt, int columnIndex) const {
13191
auto cStr = (const char*)sqlite3_column_text(stmt, columnIndex);
13192
return this->extract(cStr);
13193
}
13194
13195
locking_mode extract(sqlite3_value* value) const = delete;
13196
};
13197
13198
/**
13199
* Specialization for journal_mode.
13200
*/
13201
template<>
13202
struct row_extractor<journal_mode, void> {
13203
journal_mode extract(const char* columnText) const {
13204
if (columnText) {
13205
auto resultPair = internal::journal_mode_from_string(columnText);
13206
if (resultPair.first) {
13207
return resultPair.second;
13208
} else {
13209
throw std::system_error{orm_error_code::incorrect_journal_mode_string};
13210
}
13211
} else {
13212
throw std::system_error{orm_error_code::incorrect_journal_mode_string};
13213
}
13214
}
13215
13216
journal_mode extract(sqlite3_stmt* stmt, int columnIndex) const {
13217
auto cStr = (const char*)sqlite3_column_text(stmt, columnIndex);
13218
return this->extract(cStr);
13219
}
13220
13221
journal_mode extract(sqlite3_value* value) const = delete;
13222
};
13223
13224
namespace internal {
13225
13226
/*
13227
* Helper to extract a structure from a rowset.
13228
*/
13229
template<class R, class DBOs>
13230
struct struct_extractor;
13231
13232
#ifdef SQLITE_ORM_IF_CONSTEXPR_SUPPORTED
13233
/*
13234
* Returns a value-based row extractor for an unmapped type,
13235
* returns a structure extractor for a table reference, tuple or named struct.
13236
*/
13237
template<class R, class DBOs>
13238
auto make_row_extractor([[maybe_unused]] const DBOs& dbObjects) {
13239
if constexpr (polyfill::is_specialization_of_v<R, std::tuple> ||
13240
polyfill::is_specialization_of_v<R, structure> || is_table_reference_v<R>) {
13241
return struct_extractor<R, DBOs>{dbObjects};
13242
} else {
13243
return row_value_extractor<R>();
13244
}
13245
}
13246
#else
13247
/*
13248
* Overload for an unmapped type returns a common row extractor.
13249
*/
13250
template<
13251
class R,
13252
class DBOs,
13253
std::enable_if_t<polyfill::negation<polyfill::disjunction<polyfill::is_specialization_of<R, std::tuple>,
13254
polyfill::is_specialization_of<R, structure>,
13255
is_table_reference<R>>>::value,
13256
bool> = true>
13257
auto make_row_extractor(const DBOs& /*dbObjects*/) {
13258
return row_value_extractor<R>();
13259
}
13260
13261
/*
13262
* Overload for a table reference, tuple or aggregate of column results returns a structure extractor.
13263
*/
13264
template<class R,
13265
class DBOs,
13266
std::enable_if_t<polyfill::disjunction<polyfill::is_specialization_of<R, std::tuple>,
13267
polyfill::is_specialization_of<R, structure>,
13268
is_table_reference<R>>::value,
13269
bool> = true>
13270
struct_extractor<R, DBOs> make_row_extractor(const DBOs& dbObjects) {
13271
return {dbObjects};
13272
}
13273
#endif
13274
13275
/**
13276
* Specialization for a tuple of top-level column results.
13277
*/
13278
template<class DBOs, class... Args>
13279
struct struct_extractor<std::tuple<Args...>, DBOs> {
13280
const DBOs& db_objects;
13281
13282
std::tuple<Args...> extract(const char* columnText) const = delete;
13283
13284
// note: expects to be called only from the top level, and therefore discards the index
13285
std::tuple<column_result_proxy_t<Args>...> extract(sqlite3_stmt* stmt,
13286
int&& /*nextColumnIndex*/ = 0) const {
13287
int columnIndex = -1;
13288
return {make_row_extractor<Args>(this->db_objects).extract(stmt, ++columnIndex)...};
13289
}
13290
13291
// unused to date
13292
std::tuple<column_result_proxy_t<Args>...> extract(sqlite3_stmt* stmt, int& columnIndex) const = delete;
13293
13294
std::tuple<Args...> extract(sqlite3_value* value) const = delete;
13295
};
13296
13297
/**
13298
* Specialization for an unmapped structure to be constructed ad-hoc from column results.
13299
*
13300
* This plays together with `column_result_of_t`, which returns `struct_t<O>` as `structure<O>`
13301
*/
13302
template<class O, class... Args, class DBOs>
13303
struct struct_extractor<structure<O, std::tuple<Args...>>, DBOs> {
13304
const DBOs& db_objects;
13305
13306
O extract(const char* columnText) const = delete;
13307
13308
// note: expects to be called only from the top level, and therefore discards the index;
13309
// note: brace-init-list initialization guarantees order of evaluation, but only for aggregates and variadic constructors it seems.
13310
// see unit test tests/prepared_statement_tests/select.cpp/TEST_CASE("Prepared select")/SECTION("non-aggregate struct")
13311
template<class Ox = O, satisfies<is_eval_order_garanteed, Ox> = true>
13312
O extract(sqlite3_stmt* stmt, int&& /*nextColumnIndex*/ = 0) const {
13313
int columnIndex = -1;
13314
return O{make_row_extractor<Args>(this->db_objects).extract(stmt, ++columnIndex)...};
13315
}
13316
13317
template<class Ox = O, satisfies_not<is_eval_order_garanteed, Ox> = true>
13318
O extract(sqlite3_stmt* stmt, int&& /*nextColumnIndex*/ = 0) const {
13319
int columnIndex = -1;
13320
// note: brace-init-list initialization guarantees order of evaluation, but only for aggregates and variadic constructors it seems.
13321
std::tuple<Args...> t{make_row_extractor<Args>(this->db_objects).extract(stmt, ++columnIndex)...};
13322
return create_from_tuple<O>(std::move(t), std::index_sequence_for<Args...>{});
13323
}
13324
13325
// note: brace-init-list initialization guarantees order of evaluation, but only for aggregates and variadic constructors it seems.
13326
// see unit test tests/prepared_statement_tests/select.cpp/TEST_CASE("Prepared select")/SECTION("non-aggregate struct")
13327
template<class Ox = O, satisfies<is_eval_order_garanteed, Ox> = true>
13328
O extract(sqlite3_stmt* stmt, int& columnIndex) const {
13329
--columnIndex;
13330
return O{make_row_extractor<Args>(this->db_objects).extract(stmt, ++columnIndex)...};
13331
}
13332
13333
template<class Ox = O, satisfies_not<is_eval_order_garanteed, Ox> = true>
13334
O extract(sqlite3_stmt* stmt, int& columnIndex) const {
13335
--columnIndex;
13336
// note: brace-init-list initialization guarantees order of evaluation, but only for aggregates and variadic constructors it seems.
13337
std::tuple<Args...> t{make_row_extractor<Args>(this->db_objects).extract(stmt, ++columnIndex)...};
13338
return create_from_tuple<O>(std::move(t), std::index_sequence_for<Args...>{});
13339
}
13340
13341
O extract(sqlite3_value* value) const = delete;
13342
};
13343
}
13344
}
13345
13346
// #include "mapped_iterator.h"
13347
13348
#include <sqlite3.h>
13349
#include <memory> // std::shared_ptr, std::make_shared
13350
#include <utility> // std::move
13351
#include <iterator> // std::input_iterator_tag
13352
#include <system_error> // std::system_error
13353
#include <functional> // std::bind
13354
13355
// #include "statement_finalizer.h"
13356
13357
#include <sqlite3.h>
13358
#include <memory> // std::unique_ptr
13359
#include <type_traits> // std::integral_constant
13360
13361
namespace sqlite_orm {
13362
13363
/**
13364
* Guard class which finalizes `sqlite3_stmt` in dtor
13365
*/
13366
using statement_finalizer =
13367
std::unique_ptr<sqlite3_stmt, std::integral_constant<decltype(&sqlite3_finalize), sqlite3_finalize>>;
13368
}
13369
13370
// #include "error_code.h"
13371
13372
// #include "object_from_column_builder.h"
13373
13374
#include <sqlite3.h>
13375
#include <type_traits> // std::is_member_object_pointer
13376
#include <utility> // std::move
13377
13378
// #include "functional/static_magic.h"
13379
13380
// #include "member_traits/member_traits.h"
13381
13382
// #include "table_reference.h"
13383
13384
// #include "row_extractor.h"
13385
13386
// #include "schema/column.h"
13387
13388
// #include "storage_lookup.h"
13389
13390
namespace sqlite_orm {
13391
13392
namespace internal {
13393
13394
struct object_from_column_builder_base {
13395
sqlite3_stmt* stmt = nullptr;
13396
int columnIndex = -1;
13397
13398
#ifndef SQLITE_ORM_AGGREGATE_NSDMI_SUPPORTED
13399
object_from_column_builder_base(sqlite3_stmt* stmt, int columnIndex = -1) :
13400
stmt{stmt}, columnIndex{columnIndex} {}
13401
#endif
13402
};
13403
13404
/**
13405
* Function object for building an object from a result row.
13406
*/
13407
template<class O>
13408
struct object_from_column_builder : object_from_column_builder_base {
13409
using object_type = O;
13410
13411
object_type& object;
13412
13413
object_from_column_builder(object_type& object_, sqlite3_stmt* stmt_, int nextColumnIndex = 0) :
13414
object_from_column_builder_base{stmt_, nextColumnIndex - 1}, object(object_) {}
13415
13416
template<class G, class S>
13417
void operator()(const column_field<G, S>& column) {
13418
const auto rowExtractor = row_value_extractor<member_field_type_t<G>>();
13419
auto value = rowExtractor.extract(this->stmt, ++this->columnIndex);
13420
static_if<std::is_member_object_pointer<G>::value>(
13421
[&value, &object = this->object](const auto& column) {
13422
object.*column.member_pointer = std::move(value);
13423
},
13424
[&value, &object = this->object](const auto& column) {
13425
(object.*column.setter)(std::move(value));
13426
})(column);
13427
}
13428
};
13429
13430
/**
13431
* Specialization for a table reference.
13432
*
13433
* This plays together with `column_result_of_t`, which returns `object_t<O>` as `table_referenece<O>`
13434
*/
13435
template<class O, class DBOs>
13436
struct struct_extractor<table_reference<O>, DBOs> {
13437
const DBOs& db_objects;
13438
13439
O extract(const char* columnText) const = delete;
13440
13441
// note: expects to be called only from the top level, and therefore discards the index
13442
O extract(sqlite3_stmt* stmt, int&& /*nextColumnIndex*/ = 0) const {
13443
int columnIndex = 0;
13444
return this->extract(stmt, columnIndex);
13445
}
13446
13447
O extract(sqlite3_stmt* stmt, int& columnIndex) const {
13448
O obj;
13449
object_from_column_builder<O> builder{obj, stmt, columnIndex};
13450
auto& table = pick_table<O>(this->db_objects);
13451
table.for_each_column(builder);
13452
columnIndex = builder.columnIndex;
13453
return obj;
13454
}
13455
13456
O extract(sqlite3_value* value) const = delete;
13457
};
13458
}
13459
}
13460
13461
// #include "storage_lookup.h"
13462
13463
// #include "util.h"
13464
13465
#include <sqlite3.h>
13466
#include <string> // std::string
13467
#include <utility> // std::move
13468
13469
// #include "error_code.h"
13470
13471
namespace sqlite_orm {
13472
13473
/**
13474
* Escape the provided character in the given string by doubling it.
13475
* @param str A copy of the original string
13476
* @param char2Escape The character to escape
13477
*/
13478
inline std::string sql_escape(std::string str, char char2Escape) {
13479
for (size_t pos = 0; (pos = str.find(char2Escape, pos)) != str.npos; pos += 2) {
13480
str.replace(pos, 1, 2, char2Escape);
13481
}
13482
13483
return str;
13484
}
13485
13486
/**
13487
* Quote the given string value using single quotes,
13488
* escape containing single quotes by doubling them.
13489
*/
13490
inline std::string quote_string_literal(std::string v) {
13491
constexpr char quoteChar = '\'';
13492
return quoteChar + sql_escape(std::move(v), quoteChar) + quoteChar;
13493
}
13494
13495
/**
13496
* Quote the given string value using single quotes,
13497
* escape containing single quotes by doubling them.
13498
*/
13499
inline std::string quote_blob_literal(std::string v) {
13500
constexpr char quoteChar = '\'';
13501
return std::string{char('x'), quoteChar} + std::move(v) + quoteChar;
13502
}
13503
13504
/**
13505
* Quote the given identifier using double quotes,
13506
* escape containing double quotes by doubling them.
13507
*/
13508
inline std::string quote_identifier(std::string identifier) {
13509
constexpr char quoteChar = '"';
13510
return quoteChar + sql_escape(std::move(identifier), quoteChar) + quoteChar;
13511
}
13512
13513
namespace internal {
13514
// Wrapper to reduce boiler-plate code
13515
inline sqlite3_stmt* reset_stmt(sqlite3_stmt* stmt) {
13516
sqlite3_reset(stmt);
13517
return stmt;
13518
}
13519
13520
// note: query is deliberately taken by value, such that it is thrown away early
13521
inline sqlite3_stmt* prepare_stmt(sqlite3* db, std::string query) {
13522
sqlite3_stmt* stmt;
13523
if (sqlite3_prepare_v2(db, query.c_str(), -1, &stmt, nullptr) != SQLITE_OK) {
13524
throw_translated_sqlite_error(db);
13525
}
13526
return stmt;
13527
}
13528
13529
inline void perform_void_exec(sqlite3* db, const std::string& query) {
13530
int rc = sqlite3_exec(db, query.c_str(), nullptr, nullptr, nullptr);
13531
if (rc != SQLITE_OK) {
13532
throw_translated_sqlite_error(db);
13533
}
13534
}
13535
13536
inline void perform_exec(sqlite3* db,
13537
const char* query,
13538
int (*callback)(void* data, int argc, char** argv, char**),
13539
void* user_data) {
13540
int rc = sqlite3_exec(db, query, callback, user_data, nullptr);
13541
if (rc != SQLITE_OK) {
13542
throw_translated_sqlite_error(db);
13543
}
13544
}
13545
13546
inline void perform_exec(sqlite3* db,
13547
const std::string& query,
13548
int (*callback)(void* data, int argc, char** argv, char**),
13549
void* user_data) {
13550
return perform_exec(db, query.c_str(), callback, user_data);
13551
}
13552
13553
template<int expected = SQLITE_DONE>
13554
void perform_step(sqlite3_stmt* stmt) {
13555
int rc = sqlite3_step(stmt);
13556
if (rc != expected) {
13557
throw_translated_sqlite_error(stmt);
13558
}
13559
}
13560
13561
template<class L>
13562
void perform_step(sqlite3_stmt* stmt, L&& lambda) {
13563
switch (int rc = sqlite3_step(stmt)) {
13564
case SQLITE_ROW: {
13565
lambda(stmt);
13566
} break;
13567
case SQLITE_DONE:
13568
break;
13569
default: {
13570
throw_translated_sqlite_error(stmt);
13571
}
13572
}
13573
}
13574
13575
template<class L>
13576
void perform_steps(sqlite3_stmt* stmt, L&& lambda) {
13577
int rc;
13578
do {
13579
switch (rc = sqlite3_step(stmt)) {
13580
case SQLITE_ROW: {
13581
lambda(stmt);
13582
} break;
13583
case SQLITE_DONE:
13584
break;
13585
default: {
13586
throw_translated_sqlite_error(stmt);
13587
}
13588
}
13589
} while (rc != SQLITE_DONE);
13590
}
13591
}
13592
}
13593
13594
namespace sqlite_orm {
13595
namespace internal {
13596
13597
/*
13598
* (Legacy) Input iterator over a result set for a mapped object.
13599
*/
13600
template<class O, class DBOs>
13601
class mapped_iterator {
13602
public:
13603
using db_objects_type = DBOs;
13604
13605
using iterator_category = std::input_iterator_tag;
13606
using difference_type = ptrdiff_t;
13607
using value_type = O;
13608
using reference = O&;
13609
using pointer = O*;
13610
13611
private:
13612
/**
13613
pointer to the db objects.
13614
only null for the default constructed iterator.
13615
*/
13616
const db_objects_type* db_objects = nullptr;
13617
13618
/**
13619
* shared_ptr is used over unique_ptr here
13620
* so that the iterator can be copyable.
13621
*/
13622
std::shared_ptr<sqlite3_stmt> stmt;
13623
13624
/**
13625
* shared_ptr is used over unique_ptr here
13626
* so that the iterator can be copyable.
13627
*/
13628
std::shared_ptr<value_type> current;
13629
13630
void extract_object() {
13631
this->current = std::make_shared<value_type>();
13632
object_from_column_builder<value_type> builder{*this->current, this->stmt.get()};
13633
auto& table = pick_table<value_type>(*this->db_objects);
13634
table.for_each_column(builder);
13635
}
13636
13637
void step() {
13638
perform_step(this->stmt.get(), std::bind(&mapped_iterator::extract_object, this));
13639
if (!this->current) {
13640
this->stmt.reset();
13641
}
13642
}
13643
13644
void next() {
13645
this->current.reset();
13646
this->step();
13647
}
13648
13649
public:
13650
mapped_iterator() = default;
13651
13652
mapped_iterator(const db_objects_type& dbObjects, statement_finalizer stmt) :
13653
db_objects{&dbObjects}, stmt{std::move(stmt)} {
13654
this->step();
13655
}
13656
13657
mapped_iterator(const mapped_iterator&) = default;
13658
mapped_iterator& operator=(const mapped_iterator&) = default;
13659
mapped_iterator(mapped_iterator&&) = default;
13660
mapped_iterator& operator=(mapped_iterator&&) = default;
13661
13662
value_type& operator*() const {
13663
if (!this->stmt) SQLITE_ORM_CPP_UNLIKELY {
13664
throw std::system_error{orm_error_code::trying_to_dereference_null_iterator};
13665
}
13666
return *this->current;
13667
}
13668
13669
// note: should actually be only present for contiguous iterators
13670
value_type* operator->() const {
13671
return &(this->operator*());
13672
}
13673
13674
mapped_iterator& operator++() {
13675
next();
13676
return *this;
13677
}
13678
13679
mapped_iterator operator++(int) {
13680
auto tmp = *this;
13681
++*this;
13682
return tmp;
13683
}
13684
13685
friend bool operator==(const mapped_iterator& lhs, const mapped_iterator& rhs) {
13686
return lhs.current == rhs.current;
13687
}
13688
13689
#ifndef SQLITE_ORM_DEFAULT_COMPARISONS_SUPPORTED
13690
friend bool operator!=(const mapped_iterator& lhs, const mapped_iterator& rhs) {
13691
return !(lhs == rhs);
13692
}
13693
#endif
13694
};
13695
}
13696
}
13697
13698
// #include "ast_iterator.h"
13699
13700
#include <vector> // std::vector
13701
#include <functional> // std::reference_wrapper
13702
13703
// #include "tuple_helper/tuple_iteration.h"
13704
13705
// #include "type_traits.h"
13706
13707
// #include "conditions.h"
13708
13709
// #include "alias.h"
13710
13711
// #include "select_constraints.h"
13712
13713
// #include "operators.h"
13714
13715
// #include "core_functions.h"
13716
13717
// #include "prepared_statement.h"
13718
13719
#include <sqlite3.h>
13720
#include <memory> // std::unique_ptr
13721
#include <iterator> // std::iterator_traits
13722
#include <string> // std::string
13723
#include <type_traits> // std::integral_constant, std::declval
13724
#include <utility> // std::move, std::forward, std::pair
13725
#include <tuple> // std::tuple
13726
13727
// #include "functional/cxx_type_traits_polyfill.h"
13728
13729
// #include "functional/cxx_functional_polyfill.h"
13730
13731
// #include "tuple_helper/tuple_traits.h"
13732
13733
// #include "connection_holder.h"
13734
13735
#include <sqlite3.h>
13736
#include <atomic>
13737
#include <string> // std::string
13738
13739
// #include "error_code.h"
13740
13741
namespace sqlite_orm {
13742
13743
namespace internal {
13744
13745
struct connection_holder {
13746
13747
connection_holder(std::string filename_) : filename(std::move(filename_)) {}
13748
13749
void retain() {
13750
if (1 == ++this->_retain_count) {
13751
auto rc = sqlite3_open(this->filename.c_str(), &this->db);
13752
if (rc != SQLITE_OK) {
13753
throw_translated_sqlite_error(db);
13754
}
13755
}
13756
}
13757
13758
void release() {
13759
if (0 == --this->_retain_count) {
13760
auto rc = sqlite3_close(this->db);
13761
if (rc != SQLITE_OK) {
13762
throw_translated_sqlite_error(db);
13763
}
13764
}
13765
}
13766
13767
sqlite3* get() const {
13768
return this->db;
13769
}
13770
13771
int retain_count() const {
13772
return this->_retain_count;
13773
}
13774
13775
const std::string filename;
13776
13777
protected:
13778
sqlite3* db = nullptr;
13779
std::atomic_int _retain_count{};
13780
};
13781
13782
struct connection_ref {
13783
connection_ref(connection_holder& holder) : holder(&holder) {
13784
this->holder->retain();
13785
}
13786
13787
connection_ref(const connection_ref& other) : holder(other.holder) {
13788
this->holder->retain();
13789
}
13790
13791
// rebind connection reference
13792
connection_ref& operator=(const connection_ref& other) {
13793
if (other.holder != this->holder) {
13794
this->holder->release();
13795
this->holder = other.holder;
13796
this->holder->retain();
13797
}
13798
13799
return *this;
13800
}
13801
13802
~connection_ref() {
13803
this->holder->release();
13804
}
13805
13806
sqlite3* get() const {
13807
return this->holder->get();
13808
}
13809
13810
private:
13811
connection_holder* holder = nullptr;
13812
};
13813
}
13814
}
13815
13816
// #include "select_constraints.h"
13817
13818
// #include "values.h"
13819
13820
#include <vector> // std::vector
13821
#include <tuple> // std::tuple
13822
#include <utility> // std::forward, std::move
13823
13824
// #include "functional/cxx_type_traits_polyfill.h"
13825
13826
namespace sqlite_orm {
13827
13828
namespace internal {
13829
13830
template<class... Args>
13831
struct values_t {
13832
using args_tuple = std::tuple<Args...>;
13833
13834
args_tuple tuple;
13835
};
13836
13837
template<class T>
13838
SQLITE_ORM_INLINE_VAR constexpr bool is_values_v = polyfill::is_specialization_of<T, values_t>::value;
13839
13840
template<class T>
13841
using is_values = polyfill::bool_constant<is_values_v<T>>;
13842
13843
template<class T>
13844
struct dynamic_values_t {
13845
std::vector<T> vector;
13846
};
13847
13848
}
13849
13850
template<class... Args>
13851
internal::values_t<Args...> values(Args... args) {
13852
return {{std::forward<Args>(args)...}};
13853
}
13854
13855
template<class T>
13856
internal::dynamic_values_t<T> values(std::vector<T> vector) {
13857
return {{std::move(vector)}};
13858
}
13859
}
13860
13861
// #include "table_reference.h"
13862
13863
// #include "mapped_type_proxy.h"
13864
13865
// #include "ast/upsert_clause.h"
13866
13867
#if SQLITE_VERSION_NUMBER >= 3024000
13868
#include <tuple> // std::tuple
13869
#include <utility> // std::forward, std::move
13870
#endif
13871
13872
// #include "../functional/cxx_type_traits_polyfill.h"
13873
13874
namespace sqlite_orm {
13875
namespace internal {
13876
#if SQLITE_VERSION_NUMBER >= 3024000
13877
template<class T, class A>
13878
struct upsert_clause;
13879
13880
template<class... Args>
13881
struct conflict_target {
13882
using args_tuple = std::tuple<Args...>;
13883
13884
args_tuple args;
13885
13886
upsert_clause<args_tuple, std::tuple<>> do_nothing() {
13887
return {std::move(this->args), {}};
13888
}
13889
13890
template<class... ActionsArgs>
13891
upsert_clause<args_tuple, std::tuple<ActionsArgs...>> do_update(ActionsArgs... actions) {
13892
return {std::move(this->args), {std::forward<ActionsArgs>(actions)...}};
13893
}
13894
};
13895
13896
template<class... TargetArgs, class... ActionsArgs>
13897
struct upsert_clause<std::tuple<TargetArgs...>, std::tuple<ActionsArgs...>> {
13898
using target_args_tuple = std::tuple<TargetArgs...>;
13899
using actions_tuple = std::tuple<ActionsArgs...>;
13900
13901
target_args_tuple target_args;
13902
13903
actions_tuple actions;
13904
};
13905
#endif
13906
13907
template<class T>
13908
SQLITE_ORM_INLINE_VAR constexpr bool is_upsert_clause_v =
13909
#if SQLITE_VERSION_NUMBER >= 3024000
13910
polyfill::is_specialization_of<T, upsert_clause>::value;
13911
#else
13912
false;
13913
#endif
13914
13915
template<class T>
13916
using is_upsert_clause = polyfill::bool_constant<is_upsert_clause_v<T>>;
13917
}
13918
13919
#if SQLITE_VERSION_NUMBER >= 3024000
13920
/**
13921
* ON CONFLICT upsert clause builder function.
13922
* @example
13923
* storage.insert(into<Employee>(),
13924
* columns(&Employee::id, &Employee::name, &Employee::age, &Employee::address, &Employee::salary),
13925
* values(std::make_tuple(3, "Sofia", 26, "Madrid", 15000.0),
13926
* std::make_tuple(4, "Doja", 26, "LA", 25000.0)),
13927
* on_conflict(&Employee::id).do_update(set(c(&Employee::name) = excluded(&Employee::name),
13928
* c(&Employee::age) = excluded(&Employee::age),
13929
* c(&Employee::address) = excluded(&Employee::address),
13930
* c(&Employee::salary) = excluded(&Employee::salary))));
13931
*/
13932
template<class... Args>
13933
internal::conflict_target<Args...> on_conflict(Args... args) {
13934
return {{std::forward<Args>(args)...}};
13935
}
13936
#endif
13937
}
13938
13939
// #include "ast/set.h"
13940
13941
#include <tuple> // std::tuple, std::tuple_size
13942
#include <string> // std::string
13943
#include <vector> // std::vector
13944
#include <sstream> // std::stringstream
13945
#include <type_traits> // std::false_type, std::true_type
13946
13947
// #include "../tuple_helper/tuple_traits.h"
13948
13949
// #include "../table_name_collector.h"
13950
13951
#include <set> // std::set
13952
#include <string> // std::string
13953
#include <utility> // std::pair, std::move
13954
13955
// #include "functional/cxx_type_traits_polyfill.h"
13956
13957
// #include "type_traits.h"
13958
13959
// #include "mapped_type_proxy.h"
13960
13961
// #include "select_constraints.h"
13962
13963
// #include "alias.h"
13964
13965
// #include "core_functions.h"
13966
13967
// #include "storage_lookup.h"
13968
13969
namespace sqlite_orm {
13970
13971
namespace internal {
13972
13973
struct table_name_collector_base {
13974
using table_name_set = std::set<std::pair<std::string, std::string>>;
13975
13976
table_name_set table_names;
13977
};
13978
13979
template<class DBOs>
13980
struct table_name_collector : table_name_collector_base {
13981
using db_objects_type = DBOs;
13982
13983
const db_objects_type& db_objects;
13984
13985
table_name_collector() = default;
13986
13987
table_name_collector(const db_objects_type& dbObjects) : db_objects{dbObjects} {}
13988
13989
template<class T>
13990
void operator()(const T&) const {}
13991
13992
template<class F, class O>
13993
void operator()(F O::*) {
13994
this->table_names.emplace(lookup_table_name<O>(this->db_objects), "");
13995
}
13996
13997
template<class T, class F>
13998
void operator()(const column_pointer<T, F>&) {
13999
auto tableName = lookup_table_name<mapped_type_proxy_t<T>>(this->db_objects);
14000
this->table_names.emplace(std::move(tableName), alias_extractor<T>::as_alias());
14001
}
14002
14003
template<class A, class C>
14004
void operator()(const alias_column_t<A, C>&) {
14005
// note: instead of accessing the column, we are interested in the type the column is aliased into
14006
auto tableName = lookup_table_name<mapped_type_proxy_t<A>>(this->db_objects);
14007
this->table_names.emplace(std::move(tableName), alias_extractor<A>::as_alias());
14008
}
14009
14010
template<class T>
14011
void operator()(const count_asterisk_t<T>&) {
14012
auto tableName = lookup_table_name<T>(this->db_objects);
14013
if (!tableName.empty()) {
14014
this->table_names.emplace(std::move(tableName), "");
14015
}
14016
}
14017
14018
template<class T>
14019
void operator()(const asterisk_t<T>&) {
14020
auto tableName = lookup_table_name<mapped_type_proxy_t<T>>(this->db_objects);
14021
table_names.emplace(std::move(tableName), alias_extractor<T>::as_alias());
14022
}
14023
14024
template<class T>
14025
void operator()(const object_t<T>&) {
14026
this->table_names.emplace(lookup_table_name<T>(this->db_objects), "");
14027
}
14028
14029
template<class T>
14030
void operator()(const table_rowid_t<T>&) {
14031
this->table_names.emplace(lookup_table_name<T>(this->db_objects), "");
14032
}
14033
14034
template<class T>
14035
void operator()(const table_oid_t<T>&) {
14036
this->table_names.emplace(lookup_table_name<T>(this->db_objects), "");
14037
}
14038
14039
template<class T>
14040
void operator()(const table__rowid_t<T>&) {
14041
this->table_names.emplace(lookup_table_name<T>(this->db_objects), "");
14042
}
14043
14044
template<class T, class X, class Y, class Z>
14045
void operator()(const highlight_t<T, X, Y, Z>&) {
14046
this->table_names.emplace(lookup_table_name<T>(this->db_objects), "");
14047
}
14048
};
14049
14050
template<class DBOs, satisfies<is_db_objects, DBOs> = true>
14051
table_name_collector<DBOs> make_table_name_collector(const DBOs& dbObjects) {
14052
return {dbObjects};
14053
}
14054
14055
}
14056
14057
}
14058
14059
namespace sqlite_orm {
14060
14061
namespace internal {
14062
14063
template<class T, class L>
14064
void iterate_ast(const T& t, L&& lambda);
14065
14066
template<class... Args>
14067
struct set_t {
14068
using assigns_type = std::tuple<Args...>;
14069
14070
assigns_type assigns;
14071
};
14072
14073
template<class T>
14074
struct is_set : std::false_type {};
14075
14076
template<class... Args>
14077
struct is_set<set_t<Args...>> : std::true_type {};
14078
14079
struct dynamic_set_entry {
14080
std::string serialized_value;
14081
};
14082
14083
template<class C>
14084
struct dynamic_set_t {
14085
using context_t = C;
14086
using entry_t = dynamic_set_entry;
14087
using const_iterator = typename std::vector<entry_t>::const_iterator;
14088
14089
dynamic_set_t(const context_t& context_) : context(context_), collector(this->context.db_objects) {}
14090
14091
dynamic_set_t(const dynamic_set_t& other) = default;
14092
dynamic_set_t(dynamic_set_t&& other) = default;
14093
dynamic_set_t& operator=(const dynamic_set_t& other) = default;
14094
dynamic_set_t& operator=(dynamic_set_t&& other) = default;
14095
14096
template<class L, class R>
14097
void push_back(assign_t<L, R> assign) {
14098
auto newContext = this->context;
14099
newContext.skip_table_name = true;
14100
// note: we are only interested in the table name on the left-hand side of the assignment operator expression
14101
iterate_ast(assign.lhs, this->collector);
14102
std::stringstream ss;
14103
ss << serialize(assign.lhs, newContext) << ' ' << assign.serialize() << ' '
14104
<< serialize(assign.rhs, context);
14105
this->entries.push_back({ss.str()});
14106
}
14107
14108
const_iterator begin() const {
14109
return this->entries.begin();
14110
}
14111
14112
const_iterator end() const {
14113
return this->entries.end();
14114
}
14115
14116
void clear() {
14117
this->entries.clear();
14118
this->collector.table_names.clear();
14119
}
14120
14121
std::vector<entry_t> entries;
14122
context_t context;
14123
table_name_collector<typename context_t::db_objects_type> collector;
14124
};
14125
14126
template<class C>
14127
struct is_set<dynamic_set_t<C>> : std::true_type {};
14128
14129
template<class C>
14130
struct is_dynamic_set : std::false_type {};
14131
14132
template<class C>
14133
struct is_dynamic_set<dynamic_set_t<C>> : std::true_type {};
14134
}
14135
14136
/**
14137
* SET keyword used in UPDATE ... SET queries.
14138
* Args must have `assign_t` type. E.g. set(assign(&User::id, 5)) or set(c(&User::id) = 5)
14139
*/
14140
template<class... Args>
14141
internal::set_t<Args...> set(Args... args) {
14142
using arg_tuple = std::tuple<Args...>;
14143
static_assert(std::tuple_size<arg_tuple>::value ==
14144
internal::count_tuple<arg_tuple, internal::is_assign_t>::value,
14145
"set function accepts assign operators only");
14146
return {std::make_tuple(std::forward<Args>(args)...)};
14147
}
14148
14149
/**
14150
* SET keyword used in UPDATE ... SET queries. It is dynamic version. It means use can add amount of arguments now known at compilation time but known at runtime.
14151
*/
14152
template<class S>
14153
internal::dynamic_set_t<internal::serializer_context<typename S::db_objects_type>> dynamic_set(const S& storage) {
14154
internal::serializer_context_builder<S> builder(storage);
14155
return builder();
14156
}
14157
}
14158
14159
namespace sqlite_orm {
14160
14161
namespace internal {
14162
14163
struct prepared_statement_base {
14164
sqlite3_stmt* stmt = nullptr;
14165
connection_ref con;
14166
14167
#ifndef SQLITE_ORM_AGGREGATE_NSDMI_SUPPORTED
14168
prepared_statement_base(sqlite3_stmt* stmt, connection_ref con) : stmt{stmt}, con{std::move(con)} {}
14169
#endif
14170
14171
~prepared_statement_base() {
14172
sqlite3_finalize(this->stmt);
14173
}
14174
14175
std::string sql() const {
14176
// note: sqlite3 internally checks for null before calling
14177
// sqlite3_normalized_sql() or sqlite3_expanded_sql(), so check here, too, even if superfluous
14178
if (const char* sql = sqlite3_sql(this->stmt)) {
14179
return sql;
14180
} else {
14181
return {};
14182
}
14183
}
14184
14185
#if SQLITE_VERSION_NUMBER >= 3014000
14186
std::string expanded_sql() const {
14187
// note: must check return value due to SQLITE_OMIT_TRACE
14188
using char_ptr = std::unique_ptr<char, std::integral_constant<decltype(&sqlite3_free), sqlite3_free>>;
14189
if (char_ptr sql{sqlite3_expanded_sql(this->stmt)}) {
14190
return sql.get();
14191
} else {
14192
return {};
14193
}
14194
}
14195
#endif
14196
#if SQLITE_VERSION_NUMBER >= 3026000 and defined(SQLITE_ENABLE_NORMALIZE)
14197
std::string normalized_sql() const {
14198
if (const char* sql = sqlite3_normalized_sql(this->stmt)) {
14199
return sql;
14200
} else {
14201
return {};
14202
}
14203
}
14204
#endif
14205
14206
#ifdef SQLITE_ORM_STRING_VIEW_SUPPORTED
14207
std::string_view column_name(int index) const {
14208
return sqlite3_column_name(stmt, index);
14209
}
14210
#endif
14211
};
14212
14213
template<class T>
14214
struct prepared_statement_t : prepared_statement_base {
14215
using expression_type = T;
14216
14217
expression_type expression;
14218
14219
prepared_statement_t(T expression_, sqlite3_stmt* stmt_, connection_ref con_) :
14220
prepared_statement_base{stmt_, std::move(con_)}, expression(std::move(expression_)) {}
14221
14222
prepared_statement_t(prepared_statement_t&& prepared_stmt) :
14223
prepared_statement_base{prepared_stmt.stmt, std::move(prepared_stmt.con)},
14224
expression(std::move(prepared_stmt.expression)) {
14225
prepared_stmt.stmt = nullptr;
14226
}
14227
};
14228
14229
template<class T>
14230
SQLITE_ORM_INLINE_VAR constexpr bool is_prepared_statement_v =
14231
polyfill::is_specialization_of<T, prepared_statement_t>::value;
14232
14233
template<class T>
14234
struct is_prepared_statement : polyfill::bool_constant<is_prepared_statement_v<T>> {};
14235
14236
/**
14237
* T - type of object to obtain from a database
14238
*/
14239
template<class T, class R, class... Args>
14240
struct get_all_t {
14241
using type = T;
14242
using return_type = R;
14243
14244
using conditions_type = std::tuple<Args...>;
14245
14246
conditions_type conditions;
14247
};
14248
14249
template<class T, class R, class... Args>
14250
struct get_all_pointer_t {
14251
using type = T;
14252
using return_type = R;
14253
14254
using conditions_type = std::tuple<Args...>;
14255
14256
conditions_type conditions;
14257
};
14258
14259
#ifdef SQLITE_ORM_OPTIONAL_SUPPORTED
14260
template<class T, class R, class... Args>
14261
struct get_all_optional_t {
14262
using type = T;
14263
using return_type = R;
14264
14265
using conditions_type = std::tuple<Args...>;
14266
14267
conditions_type conditions;
14268
};
14269
#endif // SQLITE_ORM_OPTIONAL_SUPPORTED
14270
14271
template<class S, class... Wargs>
14272
struct update_all_t {
14273
using set_type = S;
14274
using conditions_type = std::tuple<Wargs...>;
14275
14276
static_assert(is_set<S>::value, "update_all_t must have set or dynamic set as the first argument");
14277
14278
set_type set;
14279
conditions_type conditions;
14280
};
14281
14282
template<class T>
14283
SQLITE_ORM_INLINE_VAR constexpr bool is_update_all_v = polyfill::is_specialization_of<T, update_all_t>::value;
14284
14285
template<class T>
14286
using is_update_all = polyfill::bool_constant<is_update_all_v<T>>;
14287
14288
template<class T, class... Args>
14289
struct remove_all_t {
14290
using type = T;
14291
using conditions_type = std::tuple<Args...>;
14292
14293
conditions_type conditions;
14294
};
14295
14296
template<class T>
14297
SQLITE_ORM_INLINE_VAR constexpr bool is_remove_all_v = polyfill::is_specialization_of<T, remove_all_t>::value;
14298
14299
template<class T>
14300
using is_remove_all = polyfill::bool_constant<is_remove_all_v<T>>;
14301
14302
template<class T, class... Ids>
14303
struct get_t {
14304
using type = T;
14305
using ids_type = std::tuple<Ids...>;
14306
14307
ids_type ids;
14308
};
14309
14310
template<class T, class... Ids>
14311
struct get_pointer_t {
14312
using type = T;
14313
using ids_type = std::tuple<Ids...>;
14314
14315
ids_type ids;
14316
};
14317
14318
#ifdef SQLITE_ORM_OPTIONAL_SUPPORTED
14319
template<class T, class... Ids>
14320
struct get_optional_t {
14321
using type = T;
14322
using ids_type = std::tuple<Ids...>;
14323
14324
ids_type ids;
14325
};
14326
#endif // SQLITE_ORM_OPTIONAL_SUPPORTED
14327
14328
template<class T>
14329
struct update_t {
14330
using type = T;
14331
14332
type object;
14333
};
14334
14335
template<class T, class... Ids>
14336
struct remove_t {
14337
using type = T;
14338
using ids_type = std::tuple<Ids...>;
14339
14340
ids_type ids;
14341
};
14342
14343
template<class T>
14344
struct insert_t {
14345
using type = T;
14346
14347
type object;
14348
};
14349
14350
template<class T>
14351
SQLITE_ORM_INLINE_VAR constexpr bool is_insert_v = polyfill::is_specialization_of<T, insert_t>::value;
14352
14353
template<class T>
14354
struct is_insert : polyfill::bool_constant<is_insert_v<T>> {};
14355
14356
template<class T, class... Cols>
14357
struct insert_explicit {
14358
using type = T;
14359
using columns_type = columns_t<Cols...>;
14360
14361
type obj;
14362
columns_type columns;
14363
};
14364
14365
template<class T>
14366
struct replace_t {
14367
using type = T;
14368
14369
type object;
14370
};
14371
14372
template<class T>
14373
SQLITE_ORM_INLINE_VAR constexpr bool is_replace_v = polyfill::is_specialization_of<T, replace_t>::value;
14374
14375
template<class T>
14376
struct is_replace : polyfill::bool_constant<is_replace_v<T>> {};
14377
14378
template<class It, class Projection, class O>
14379
struct insert_range_t {
14380
using iterator_type = It;
14381
using transformer_type = Projection;
14382
using object_type = O;
14383
14384
std::pair<iterator_type, iterator_type> range;
14385
transformer_type transformer;
14386
};
14387
14388
template<class T>
14389
SQLITE_ORM_INLINE_VAR constexpr bool is_insert_range_v =
14390
polyfill::is_specialization_of<T, insert_range_t>::value;
14391
14392
template<class T>
14393
struct is_insert_range : polyfill::bool_constant<is_insert_range_v<T>> {};
14394
14395
template<class It, class Projection, class O>
14396
struct replace_range_t {
14397
using iterator_type = It;
14398
using transformer_type = Projection;
14399
using object_type = O;
14400
14401
std::pair<iterator_type, iterator_type> range;
14402
transformer_type transformer;
14403
};
14404
14405
template<class T>
14406
SQLITE_ORM_INLINE_VAR constexpr bool is_replace_range_v =
14407
polyfill::is_specialization_of<T, replace_range_t>::value;
14408
14409
template<class T>
14410
struct is_replace_range : polyfill::bool_constant<is_replace_range_v<T>> {};
14411
14412
template<class... Args>
14413
struct insert_raw_t {
14414
using args_tuple = std::tuple<Args...>;
14415
14416
args_tuple args;
14417
};
14418
14419
template<class T>
14420
SQLITE_ORM_INLINE_VAR constexpr bool is_insert_raw_v = polyfill::is_specialization_of<T, insert_raw_t>::value;
14421
14422
template<class T>
14423
struct is_insert_raw : polyfill::bool_constant<is_insert_raw_v<T>> {};
14424
14425
template<class... Args>
14426
struct replace_raw_t {
14427
using args_tuple = std::tuple<Args...>;
14428
14429
args_tuple args;
14430
};
14431
14432
template<class T>
14433
SQLITE_ORM_INLINE_VAR constexpr bool is_replace_raw_v = polyfill::is_specialization_of<T, replace_raw_t>::value;
14434
14435
template<class T>
14436
struct is_replace_raw : polyfill::bool_constant<is_replace_raw_v<T>> {};
14437
14438
struct default_values_t {};
14439
14440
template<class T>
14441
using is_default_values = std::is_same<T, default_values_t>;
14442
14443
enum class conflict_action {
14444
abort,
14445
fail,
14446
ignore,
14447
replace,
14448
rollback,
14449
};
14450
14451
struct insert_constraint {
14452
conflict_action action = conflict_action::abort;
14453
14454
#ifndef SQLITE_ORM_AGGREGATE_NSDMI_SUPPORTED
14455
insert_constraint(conflict_action action) : action{action} {}
14456
#endif
14457
};
14458
14459
template<class T>
14460
using is_insert_constraint = std::is_same<T, insert_constraint>;
14461
}
14462
14463
inline internal::insert_constraint or_rollback() {
14464
return {internal::conflict_action::rollback};
14465
}
14466
14467
inline internal::insert_constraint or_replace() {
14468
return {internal::conflict_action::replace};
14469
}
14470
14471
inline internal::insert_constraint or_ignore() {
14472
return {internal::conflict_action::ignore};
14473
}
14474
14475
inline internal::insert_constraint or_fail() {
14476
return {internal::conflict_action::fail};
14477
}
14478
14479
inline internal::insert_constraint or_abort() {
14480
return {internal::conflict_action::abort};
14481
}
14482
14483
/**
14484
* Use this function to add `DEFAULT VALUES` modifier to raw `INSERT`.
14485
*
14486
* @example
14487
* ```
14488
* storage.insert(into<Singer>(), default_values());
14489
* ```
14490
*/
14491
inline internal::default_values_t default_values() {
14492
return {};
14493
}
14494
14495
/**
14496
* Raw insert statement creation routine. Use this if `insert` with object does not fit you. This insert is designed to be able
14497
* to call any type of `INSERT` query with no limitations.
14498
* @example
14499
* ```sql
14500
* INSERT INTO users (id, name) VALUES(5, 'Little Mix')
14501
* ```
14502
* will be
14503
* ```c++
14504
* auto statement = storage.prepare(insert(into<User>, columns(&User::id, &User::name), values(std::make_tuple(5, "Little Mix"))));
14505
* storage.execute(statement));
14506
* ```
14507
* One more example:
14508
* ```sql
14509
* INSERT INTO singers (name) VALUES ('Sofia Reyes')('Kungs')
14510
* ```
14511
* will be
14512
* ```c++
14513
* auto statement = storage.prepare(insert(into<Singer>(), columns(&Singer::name), values(std::make_tuple("Sofia Reyes"), std::make_tuple("Kungs"))));
14514
* storage.execute(statement));
14515
* ```
14516
* One can use `default_values` to add `DEFAULT VALUES` modifier:
14517
* ```sql
14518
* INSERT INTO users DEFAULT VALUES
14519
* ```
14520
* will be
14521
* ```c++
14522
* auto statement = storage.prepare(insert(into<Singer>(), default_values()));
14523
* storage.execute(statement));
14524
* ```
14525
* Also one can use `INSERT OR ABORT`/`INSERT OR FAIL`/`INSERT OR IGNORE`/`INSERT OR REPLACE`/`INSERT ROLLBACK`:
14526
* ```c++
14527
* auto statement = storage.prepare(insert(or_ignore(), into<Singer>(), columns(&Singer::name), values(std::make_tuple("Sofia Reyes"), std::make_tuple("Kungs"))));
14528
* auto statement2 = storage.prepare(insert(or_rollback(), into<Singer>(), default_values()));
14529
* auto statement3 = storage.prepare(insert(or_abort(), into<User>, columns(&User::id, &User::name), values(std::make_tuple(5, "Little Mix"))));
14530
* ```
14531
*/
14532
template<class... Args>
14533
internal::insert_raw_t<Args...> insert(Args... args) {
14534
using args_tuple = std::tuple<Args...>;
14535
using internal::count_tuple;
14536
using internal::is_columns;
14537
using internal::is_insert_constraint;
14538
using internal::is_into;
14539
using internal::is_select;
14540
using internal::is_upsert_clause;
14541
using internal::is_values;
14542
14543
constexpr int orArgsCount = count_tuple<args_tuple, is_insert_constraint>::value;
14544
static_assert(orArgsCount < 2, "Raw insert must have only one OR... argument");
14545
14546
constexpr int intoArgsCount = count_tuple<args_tuple, is_into>::value;
14547
static_assert(intoArgsCount != 0, "Raw insert must have into<T> argument");
14548
static_assert(intoArgsCount < 2, "Raw insert must have only one into<T> argument");
14549
14550
constexpr int columnsArgsCount = count_tuple<args_tuple, is_columns>::value;
14551
static_assert(columnsArgsCount < 2, "Raw insert must have only one columns(...) argument");
14552
14553
constexpr int valuesArgsCount = count_tuple<args_tuple, is_values>::value;
14554
static_assert(valuesArgsCount < 2, "Raw insert must have only one values(...) argument");
14555
14556
constexpr int defaultValuesCount = count_tuple<args_tuple, internal::is_default_values>::value;
14557
static_assert(defaultValuesCount < 2, "Raw insert must have only one default_values() argument");
14558
14559
constexpr int selectsArgsCount = count_tuple<args_tuple, is_select>::value;
14560
static_assert(selectsArgsCount < 2, "Raw insert must have only one select(...) argument");
14561
14562
constexpr int upsertClausesCount = count_tuple<args_tuple, is_upsert_clause>::value;
14563
static_assert(upsertClausesCount <= 2, "Raw insert can contain 2 instances of upsert clause maximum");
14564
14565
constexpr int argsCount = int(std::tuple_size<args_tuple>::value);
14566
static_assert(argsCount == intoArgsCount + columnsArgsCount + valuesArgsCount + defaultValuesCount +
14567
selectsArgsCount + orArgsCount + upsertClausesCount,
14568
"Raw insert has invalid arguments");
14569
14570
return {{std::forward<Args>(args)...}};
14571
}
14572
14573
/**
14574
* Raw replace statement creation routine. Use this if `replace` with object does not fit you. This replace is designed to be able
14575
* to call any type of `REPLACE` query with no limitations. Actually this is the same query as raw insert except `OR...` option existance.
14576
* @example
14577
* ```sql
14578
* REPLACE INTO users (id, name) VALUES(5, 'Little Mix')
14579
* ```
14580
* will be
14581
* ```c++
14582
* auto statement = storage.prepare(replace(into<User>, columns(&User::id, &User::name), values(std::make_tuple(5, "Little Mix"))));
14583
* storage.execute(statement));
14584
* ```
14585
* One more example:
14586
* ```sql
14587
* REPLACE INTO singers (name) VALUES ('Sofia Reyes')('Kungs')
14588
* ```
14589
* will be
14590
* ```c++
14591
* auto statement = storage.prepare(replace(into<Singer>(), columns(&Singer::name), values(std::make_tuple("Sofia Reyes"), std::make_tuple("Kungs"))));
14592
* storage.execute(statement));
14593
* ```
14594
* One can use `default_values` to add `DEFAULT VALUES` modifier:
14595
* ```sql
14596
* REPLACE INTO users DEFAULT VALUES
14597
* ```
14598
* will be
14599
* ```c++
14600
* auto statement = storage.prepare(replace(into<Singer>(), default_values()));
14601
* storage.execute(statement));
14602
* ```
14603
*/
14604
template<class... Args>
14605
internal::replace_raw_t<Args...> replace(Args... args) {
14606
using args_tuple = std::tuple<Args...>;
14607
using internal::count_tuple;
14608
using internal::is_columns;
14609
using internal::is_into;
14610
using internal::is_values;
14611
14612
constexpr int intoArgsCount = count_tuple<args_tuple, is_into>::value;
14613
static_assert(intoArgsCount != 0, "Raw replace must have into<T> argument");
14614
static_assert(intoArgsCount < 2, "Raw replace must have only one into<T> argument");
14615
14616
constexpr int columnsArgsCount = count_tuple<args_tuple, is_columns>::value;
14617
static_assert(columnsArgsCount < 2, "Raw replace must have only one columns(...) argument");
14618
14619
constexpr int valuesArgsCount = count_tuple<args_tuple, is_values>::value;
14620
static_assert(valuesArgsCount < 2, "Raw replace must have only one values(...) argument");
14621
14622
constexpr int defaultValuesCount = count_tuple<args_tuple, internal::is_default_values>::value;
14623
static_assert(defaultValuesCount < 2, "Raw replace must have only one default_values() argument");
14624
14625
constexpr int selectsArgsCount = count_tuple<args_tuple, internal::is_select>::value;
14626
static_assert(selectsArgsCount < 2, "Raw replace must have only one select(...) argument");
14627
14628
constexpr int argsCount = int(std::tuple_size<args_tuple>::value);
14629
static_assert(argsCount ==
14630
intoArgsCount + columnsArgsCount + valuesArgsCount + defaultValuesCount + selectsArgsCount,
14631
"Raw replace has invalid arguments");
14632
14633
return {{std::forward<Args>(args)...}};
14634
}
14635
14636
/**
14637
* Create a replace range statement.
14638
* The objects in the range are transformed using the specified projection, which defaults to identity projection.
14639
*
14640
* @example
14641
* ```
14642
* std::vector<User> users;
14643
* users.push_back(User{1, "Leony"});
14644
* auto statement = storage.prepare(replace_range(users.begin(), users.end()));
14645
* storage.execute(statement);
14646
* ```
14647
* @example
14648
* ```
14649
* std::vector<std::unique_ptr<User>> userPointers;
14650
* userPointers.push_back(std::make_unique<User>(1, "Eneli"));
14651
* auto statement = storage.prepare(replace_range(userPointers.begin(), userPointers.end(), &std::unique_ptr<User>::operator*));
14652
* storage.execute(statement);
14653
* ```
14654
*/
14655
template<class It, class Projection = polyfill::identity>
14656
auto replace_range(It from, It to, Projection project = {}) {
14657
using O = std::decay_t<decltype(polyfill::invoke(std::declval<Projection>(), *std::declval<It>()))>;
14658
return internal::replace_range_t<It, Projection, O>{{std::move(from), std::move(to)}, std::move(project)};
14659
}
14660
14661
/*
14662
* Create a replace range statement.
14663
* Overload of `replace_range(It, It, Projection)` with explicit object type template parameter.
14664
*/
14665
template<class O, class It, class Projection = polyfill::identity>
14666
internal::replace_range_t<It, Projection, O> replace_range(It from, It to, Projection project = {}) {
14667
return {{std::move(from), std::move(to)}, std::move(project)};
14668
}
14669
14670
/**
14671
* Create an insert range statement.
14672
* The objects in the range are transformed using the specified projection, which defaults to identity projection.
14673
*
14674
* @example
14675
* ```
14676
* std::vector<User> users;
14677
* users.push_back(User{1, "Leony"});
14678
* auto statement = storage.prepare(insert_range(users.begin(), users.end()));
14679
* storage.execute(statement);
14680
* ```
14681
* @example
14682
* ```
14683
* std::vector<std::unique_ptr<User>> userPointers;
14684
* userPointers.push_back(std::make_unique<User>(1, "Eneli"));
14685
* auto statement = storage.prepare(insert_range(userPointers.begin(), userPointers.end(), &std::unique_ptr<User>::operator*));
14686
* storage.execute(statement);
14687
* ```
14688
*/
14689
template<class It, class Projection = polyfill::identity>
14690
auto insert_range(It from, It to, Projection project = {}) {
14691
using O = std::decay_t<decltype(polyfill::invoke(std::declval<Projection>(), *std::declval<It>()))>;
14692
return internal::insert_range_t<It, Projection, O>{{std::move(from), std::move(to)}, std::move(project)};
14693
}
14694
14695
/*
14696
* Create an insert range statement.
14697
* Overload of `insert_range(It, It, Projection)` with explicit object type template parameter.
14698
*/
14699
template<class O, class It, class Projection = polyfill::identity>
14700
internal::insert_range_t<It, Projection, O> insert_range(It from, It to, Projection project = {}) {
14701
return {{std::move(from), std::move(to)}, std::move(project)};
14702
}
14703
14704
/**
14705
* Create a replace statement.
14706
* T is an object type mapped to a storage.
14707
* Usage: storage.replace(myUserInstance);
14708
* Parameter obj is accepted by value. If you want to accept it by ref
14709
* please use std::ref function: storage.replace(std::ref(myUserInstance));
14710
*/
14711
template<class T>
14712
internal::replace_t<T> replace(T obj) {
14713
return {std::move(obj)};
14714
}
14715
14716
/**
14717
* Create an insert statement.
14718
* T is an object type mapped to a storage.
14719
* Usage: storage.insert(myUserInstance);
14720
* Parameter obj is accepted by value. If you want to accept it by ref
14721
* please use std::ref function: storage.insert(std::ref(myUserInstance));
14722
*/
14723
template<class T>
14724
internal::insert_t<T> insert(T obj) {
14725
return {std::move(obj)};
14726
}
14727
14728
/**
14729
* Create an explicit insert statement.
14730
* T is an object type mapped to a storage.
14731
* Cols is columns types aparameter pack. Must contain member pointers
14732
* Usage: storage.insert(myUserInstance, columns(&User::id, &User::name));
14733
* Parameter obj is accepted by value. If you want to accept it by ref
14734
* please use std::ref function: storage.insert(std::ref(myUserInstance), columns(&User::id, &User::name));
14735
*/
14736
template<class T, class... Cols>
14737
internal::insert_explicit<T, Cols...> insert(T obj, internal::columns_t<Cols...> cols) {
14738
return {std::move(obj), std::move(cols)};
14739
}
14740
14741
/**
14742
* Create a remove statement
14743
* T is an object type mapped to a storage.
14744
* Usage: remove<User>(5);
14745
*/
14746
template<class T, class... Ids>
14747
internal::remove_t<T, Ids...> remove(Ids... ids) {
14748
return {{std::forward<Ids>(ids)...}};
14749
}
14750
14751
#ifdef SQLITE_ORM_WITH_CPP20_ALIASES
14752
/**
14753
* Create a remove statement
14754
* `table` is an explicitly specified table reference of a mapped object to be extracted.
14755
* Usage: remove<user_table>(5);
14756
*/
14757
template<orm_table_reference auto table, class... Ids>
14758
auto remove(Ids... ids) {
14759
return remove<internal::auto_decay_table_ref_t<table>>(std::forward<Ids>(ids)...);
14760
}
14761
#endif
14762
14763
/**
14764
* Create an update statement.
14765
* T is an object type mapped to a storage.
14766
* Usage: storage.update(myUserInstance);
14767
* Parameter obj is accepted by value. If you want to accept it by ref
14768
* please use std::ref function: storage.update(std::ref(myUserInstance));
14769
*/
14770
template<class T>
14771
internal::update_t<T> update(T obj) {
14772
return {std::move(obj)};
14773
}
14774
14775
/**
14776
* Create a get statement.
14777
* T is an object type mapped to a storage.
14778
* Usage: get<User>(5);
14779
*/
14780
template<class T, class... Ids>
14781
internal::get_t<T, Ids...> get(Ids... ids) {
14782
return {{std::forward<Ids>(ids)...}};
14783
}
14784
14785
#ifdef SQLITE_ORM_WITH_CPP20_ALIASES
14786
/**
14787
* Create a get statement.
14788
* `table` is an explicitly specified table reference of a mapped object to be extracted.
14789
* Usage: get<user_table>(5);
14790
*/
14791
template<orm_table_reference auto table, class... Ids>
14792
auto get(Ids... ids) {
14793
return get<internal::auto_decay_table_ref_t<table>>(std::forward<Ids>(ids)...);
14794
}
14795
#endif
14796
14797
/**
14798
* Create a get pointer statement.
14799
* T is an object type mapped to a storage.
14800
* Usage: get_pointer<User>(5);
14801
*/
14802
template<class T, class... Ids>
14803
internal::get_pointer_t<T, Ids...> get_pointer(Ids... ids) {
14804
return {{std::forward<Ids>(ids)...}};
14805
}
14806
14807
#ifdef SQLITE_ORM_WITH_CPP20_ALIASES
14808
/**
14809
* Create a get pointer statement.
14810
* `table` is an explicitly specified table reference of a mapped object to be extracted.
14811
* Usage: get_pointer<user_table>(5);
14812
*/
14813
template<orm_table_reference auto table, class... Ids>
14814
auto get_pointer(Ids... ids) {
14815
return get_pointer<internal::auto_decay_table_ref_t<table>>(std::forward<Ids>(ids)...);
14816
}
14817
#endif
14818
14819
#ifdef SQLITE_ORM_OPTIONAL_SUPPORTED
14820
/**
14821
* Create a get optional statement.
14822
* T is an object type mapped to a storage.
14823
* Usage: get_optional<User>(5);
14824
*/
14825
template<class T, class... Ids>
14826
internal::get_optional_t<T, Ids...> get_optional(Ids... ids) {
14827
return {{std::forward<Ids>(ids)...}};
14828
}
14829
#endif // SQLITE_ORM_OPTIONAL_SUPPORTED
14830
14831
#ifdef SQLITE_ORM_WITH_CPP20_ALIASES
14832
/**
14833
* Create a get optional statement.
14834
* `table` is an explicitly specified table reference of a mapped object to be extracted.
14835
* Usage: get_optional<user_table>(5);
14836
*/
14837
template<orm_table_reference auto table, class... Ids>
14838
auto get_optional(Ids... ids) {
14839
return get_optional<internal::auto_decay_table_ref_t<table>>(std::forward<Ids>(ids)...);
14840
}
14841
#endif
14842
14843
/**
14844
* Create a remove all statement.
14845
* T is an object type mapped to a storage.
14846
* Usage: storage.remove_all<User>(...);
14847
*/
14848
template<class T, class... Args>
14849
internal::remove_all_t<T, Args...> remove_all(Args... args) {
14850
using args_tuple = std::tuple<Args...>;
14851
internal::validate_conditions<args_tuple>();
14852
return {{std::forward<Args>(args)...}};
14853
}
14854
14855
#ifdef SQLITE_ORM_WITH_CPP20_ALIASES
14856
/**
14857
* Create a remove all statement.
14858
* `table` is an explicitly specified table reference of a mapped object to be extracted.
14859
* Usage: storage.remove_all<user_table>(...);
14860
*/
14861
template<orm_table_reference auto table, class... Args>
14862
auto remove_all(Args... args) {
14863
return remove_all<internal::auto_decay_table_ref_t<table>>(std::forward<Args>(args)...);
14864
}
14865
#endif
14866
14867
/**
14868
* Create a get all statement.
14869
* T is an explicitly specified object mapped to a storage or a table alias.
14870
* R is a container type. std::vector<T> is default
14871
* Usage: storage.prepare(get_all<User>(...));
14872
*/
14873
template<class T, class R = std::vector<internal::mapped_type_proxy_t<T>>, class... Args>
14874
internal::get_all_t<T, R, Args...> get_all(Args... conditions) {
14875
using conditions_tuple = std::tuple<Args...>;
14876
internal::validate_conditions<conditions_tuple>();
14877
return {{std::forward<Args>(conditions)...}};
14878
}
14879
14880
#ifdef SQLITE_ORM_WITH_CPP20_ALIASES
14881
/**
14882
* Create a get all statement.
14883
* `mapped` is an explicitly specified table reference or table alias to be extracted.
14884
* `R` is the container return type, which must have a `R::push_back(T&&)` method, and defaults to `std::vector<T>`
14885
* Usage: storage.get_all<sqlite_schema>(...);
14886
*/
14887
template<orm_refers_to_table auto mapped,
14888
class R = std::vector<internal::mapped_type_proxy_t<decltype(mapped)>>,
14889
class... Args>
14890
auto get_all(Args&&... conditions) {
14891
return get_all<internal::auto_decay_table_ref_t<mapped>, R>(std::forward<Args>(conditions)...);
14892
}
14893
#endif
14894
14895
/**
14896
* Create an update all statement.
14897
* Usage: storage.update_all(set(...), ...);
14898
*/
14899
template<class S, class... Wargs>
14900
internal::update_all_t<S, Wargs...> update_all(S set, Wargs... wh) {
14901
static_assert(internal::is_set<S>::value, "first argument in update_all can be either set or dynamic_set");
14902
using args_tuple = std::tuple<Wargs...>;
14903
internal::validate_conditions<args_tuple>();
14904
return {std::move(set), {std::forward<Wargs>(wh)...}};
14905
}
14906
14907
/**
14908
* Create a get all pointer statement.
14909
* T is an object type mapped to a storage.
14910
* R is a container return type. std::vector<std::unique_ptr<T>> is default
14911
* Usage: storage.prepare(get_all_pointer<User>(...));
14912
*/
14913
template<class T, class R = std::vector<std::unique_ptr<T>>, class... Args>
14914
internal::get_all_pointer_t<T, R, Args...> get_all_pointer(Args... conditions) {
14915
using conditions_tuple = std::tuple<Args...>;
14916
internal::validate_conditions<conditions_tuple>();
14917
return {{std::forward<Args>(conditions)...}};
14918
}
14919
14920
#ifdef SQLITE_ORM_WITH_CPP20_ALIASES
14921
/**
14922
* Create a get all pointer statement.
14923
* `table` is an explicitly specified table reference of a mapped object to be extracted.
14924
* R is a container return type. std::vector<std::unique_ptr<T>> is default
14925
* Usage: storage.prepare(get_all_pointer<user_table>(...));
14926
*/
14927
template<orm_table_reference auto table,
14928
class R = std::vector<internal::auto_decay_table_ref_t<table>>,
14929
class... Args>
14930
auto get_all_pointer(Args... conditions) {
14931
return get_all_pointer<internal::auto_decay_table_ref_t<table>, R>(std::forward<Args>(conditions)...);
14932
}
14933
#endif
14934
14935
#ifdef SQLITE_ORM_OPTIONAL_SUPPORTED
14936
/**
14937
* Create a get all optional statement.
14938
* T is an object type mapped to a storage.
14939
* R is a container return type. std::vector<std::optional<T>> is default
14940
* Usage: storage.get_all_optional<User>(...);
14941
*/
14942
template<class T, class R = std::vector<std::optional<T>>, class... Args>
14943
internal::get_all_optional_t<T, R, Args...> get_all_optional(Args... conditions) {
14944
using conditions_tuple = std::tuple<Args...>;
14945
internal::validate_conditions<conditions_tuple>();
14946
return {{std::forward<Args>(conditions)...}};
14947
}
14948
#endif // SQLITE_ORM_OPTIONAL_SUPPORTED
14949
14950
#ifdef SQLITE_ORM_WITH_CPP20_ALIASES
14951
/**
14952
* Create a get all optional statement.
14953
* `table` is an explicitly specified table reference of a mapped object to be extracted.
14954
* R is a container return type. std::vector<std::optional<T>> is default
14955
* Usage: storage.get_all_optional<user_table>(...);
14956
*/
14957
template<orm_table_reference auto table,
14958
class R = std::vector<internal::auto_decay_table_ref_t<table>>,
14959
class... Args>
14960
auto get_all_optional(Args&&... conditions) {
14961
return get_all_optional<internal::auto_decay_table_ref_t<table>, R>(std::forward<Args>(conditions)...);
14962
}
14963
#endif
14964
}
14965
14966
// #include "values.h"
14967
14968
// #include "function.h"
14969
14970
// #include "ast/excluded.h"
14971
14972
#include <utility> // std::move
14973
14974
namespace sqlite_orm {
14975
namespace internal {
14976
14977
template<class T>
14978
struct excluded_t {
14979
using expression_type = T;
14980
14981
expression_type expression;
14982
};
14983
}
14984
14985
template<class T>
14986
internal::excluded_t<T> excluded(T expression) {
14987
return {std::move(expression)};
14988
}
14989
}
14990
14991
// #include "ast/upsert_clause.h"
14992
14993
// #include "ast/where.h"
14994
14995
// #include "ast/into.h"
14996
14997
// #include "ast/group_by.h"
14998
14999
// #include "ast/exists.h"
15000
15001
#include <utility> // std::move
15002
15003
// #include "../tags.h"
15004
15005
namespace sqlite_orm {
15006
namespace internal {
15007
15008
template<class T>
15009
struct exists_t : condition_t, negatable_t {
15010
using expression_type = T;
15011
using self = exists_t<expression_type>;
15012
15013
expression_type expression;
15014
15015
exists_t(expression_type expression_) : expression(std::move(expression_)) {}
15016
};
15017
}
15018
15019
/**
15020
* EXISTS(condition).
15021
* Example: storage.select(columns(&Agent::code, &Agent::name, &Agent::workingArea, &Agent::comission),
15022
where(exists(select(asterisk<Customer>(),
15023
where(is_equal(&Customer::grade, 3) and
15024
is_equal(&Agent::code, &Customer::agentCode))))),
15025
order_by(&Agent::comission));
15026
*/
15027
template<class T>
15028
internal::exists_t<T> exists(T expression) {
15029
return {std::move(expression)};
15030
}
15031
}
15032
15033
// #include "ast/set.h"
15034
15035
// #include "ast/match.h"
15036
15037
#include <utility> // std::move
15038
15039
namespace sqlite_orm {
15040
namespace internal {
15041
15042
template<class T, class X>
15043
struct match_t {
15044
using mapped_type = T;
15045
using argument_type = X;
15046
15047
argument_type argument;
15048
15049
match_t(argument_type argument) : argument(std::move(argument)) {}
15050
};
15051
}
15052
15053
template<class T, class X>
15054
internal::match_t<T, X> match(X argument) {
15055
return {std::move(argument)};
15056
}
15057
}
15058
15059
namespace sqlite_orm {
15060
15061
namespace internal {
15062
15063
/**
15064
* ast_iterator accepts any expression and a callable object
15065
* which will be called for any node of provided expression.
15066
* E.g. if we pass `where(is_equal(5, max(&User::id, 10))` then
15067
* callable object will be called with 5, &User::id and 10.
15068
* ast_iterator is used in finding literals to be bound to
15069
* a statement, and to collect table names.
15070
*
15071
* Note that not all leaves of the expression tree are always visited:
15072
* Column expressions can be more complex, but are passed as a whole to the callable.
15073
* Examples are `column_pointer<>` and `alias_column_t<>`.
15074
*
15075
* To use `ast_iterator` call `iterate_ast(object, callable);`
15076
*
15077
* `T` is an ast element, e.g. where_t
15078
*/
15079
template<class T, class SFINAE = void>
15080
struct ast_iterator {
15081
using node_type = T;
15082
15083
/**
15084
* L is a callable type. Mostly is a templated lambda
15085
*/
15086
template<class L>
15087
void operator()(const T& t, L& lambda) const {
15088
lambda(t);
15089
}
15090
};
15091
15092
/**
15093
* Simplified API
15094
*/
15095
template<class T, class L>
15096
void iterate_ast(const T& t, L&& lambda) {
15097
ast_iterator<T> iterator;
15098
iterator(t, lambda);
15099
}
15100
15101
#ifdef SQLITE_ORM_OPTIONAL_SUPPORTED
15102
template<class T>
15103
struct ast_iterator<as_optional_t<T>, void> {
15104
using node_type = as_optional_t<T>;
15105
15106
template<class L>
15107
void operator()(const node_type& node, L& lambda) const {
15108
iterate_ast(node.expression, lambda);
15109
}
15110
};
15111
#endif // SQLITE_ORM_OPTIONAL_SUPPORTED
15112
15113
template<class T>
15114
struct ast_iterator<std::reference_wrapper<T>, void> {
15115
using node_type = std::reference_wrapper<T>;
15116
15117
template<class L>
15118
void operator()(const node_type& expression, L& lambda) const {
15119
iterate_ast(expression.get(), lambda);
15120
}
15121
};
15122
15123
template<class T, class X>
15124
struct ast_iterator<match_t<T, X>, void> {
15125
using node_type = match_t<T, X>;
15126
15127
template<class L>
15128
void operator()(const node_type& node, L& lambda) const {
15129
iterate_ast(node.argument, lambda);
15130
}
15131
};
15132
15133
template<class... Args>
15134
struct ast_iterator<group_by_t<Args...>, void> {
15135
using node_type = group_by_t<Args...>;
15136
15137
template<class L>
15138
void operator()(const node_type& expression, L& lambda) const {
15139
iterate_ast(expression.args, lambda);
15140
}
15141
};
15142
15143
template<class T, class X, class Y, class Z>
15144
struct ast_iterator<highlight_t<T, X, Y, Z>, void> {
15145
using node_type = highlight_t<T, X, Y, Z>;
15146
15147
template<class L>
15148
void operator()(const node_type& expression, L& lambda) const {
15149
lambda(expression);
15150
iterate_ast(expression.argument0, lambda);
15151
iterate_ast(expression.argument1, lambda);
15152
iterate_ast(expression.argument2, lambda);
15153
}
15154
};
15155
15156
template<class T>
15157
struct ast_iterator<excluded_t<T>, void> {
15158
using node_type = excluded_t<T>;
15159
15160
template<class L>
15161
void operator()(const node_type& expression, L& lambda) const {
15162
iterate_ast(expression.expression, lambda);
15163
}
15164
};
15165
15166
template<class T>
15167
struct ast_iterator<T, match_if<is_upsert_clause, T>> {
15168
using node_type = T;
15169
15170
template<class L>
15171
void operator()(const node_type& expression, L& lambda) const {
15172
iterate_ast(expression.actions, lambda);
15173
}
15174
};
15175
15176
template<class C>
15177
struct ast_iterator<where_t<C>, void> {
15178
using node_type = where_t<C>;
15179
15180
template<class L>
15181
void operator()(const node_type& expression, L& lambda) const {
15182
iterate_ast(expression.expression, lambda);
15183
}
15184
};
15185
15186
template<class T>
15187
struct ast_iterator<
15188
T,
15189
std::enable_if_t<polyfill::disjunction<is_binary_condition<T>, is_binary_operator<T>>::value>> {
15190
using node_type = T;
15191
15192
template<class L>
15193
void operator()(const node_type& node, L& lambda) const {
15194
iterate_ast(node.lhs, lambda);
15195
iterate_ast(node.rhs, lambda);
15196
}
15197
};
15198
15199
template<class L, class R>
15200
struct ast_iterator<is_equal_with_table_t<L, R>, void> {
15201
using node_type = is_equal_with_table_t<L, R>;
15202
15203
template<class C>
15204
void operator()(const node_type& node, C& lambda) const {
15205
iterate_ast(node.rhs, lambda);
15206
}
15207
};
15208
15209
template<class C>
15210
struct ast_iterator<C, std::enable_if_t<polyfill::disjunction<is_columns<C>, is_struct<C>>::value>> {
15211
using node_type = C;
15212
15213
template<class L>
15214
void operator()(const node_type& cols, L& lambda) const {
15215
iterate_ast(cols.columns, lambda);
15216
}
15217
};
15218
15219
template<class L, class A>
15220
struct ast_iterator<dynamic_in_t<L, A>, void> {
15221
using node_type = dynamic_in_t<L, A>;
15222
15223
template<class C>
15224
void operator()(const node_type& in, C& lambda) const {
15225
iterate_ast(in.left, lambda);
15226
iterate_ast(in.argument, lambda);
15227
}
15228
};
15229
15230
template<class L, class... Args>
15231
struct ast_iterator<in_t<L, Args...>, void> {
15232
using node_type = in_t<L, Args...>;
15233
15234
template<class C>
15235
void operator()(const node_type& in, C& lambda) const {
15236
iterate_ast(in.left, lambda);
15237
iterate_ast(in.argument, lambda);
15238
}
15239
};
15240
15241
template<class T>
15242
struct ast_iterator<std::vector<T>, void> {
15243
using node_type = std::vector<T>;
15244
15245
template<class L>
15246
void operator()(const node_type& vec, L& lambda) const {
15247
for (auto& i: vec) {
15248
iterate_ast(i, lambda);
15249
}
15250
}
15251
};
15252
15253
template<>
15254
struct ast_iterator<std::vector<char>, void> {
15255
using node_type = std::vector<char>;
15256
15257
template<class L>
15258
void operator()(const node_type& vec, L& lambda) const {
15259
lambda(vec);
15260
}
15261
};
15262
15263
#if (SQLITE_VERSION_NUMBER >= 3008003) && defined(SQLITE_ORM_WITH_CTE)
15264
template<class CTE>
15265
struct ast_iterator<CTE, match_specialization_of<CTE, common_table_expression>> {
15266
using node_type = CTE;
15267
15268
template<class L>
15269
void operator()(const node_type& c, L& lambda) const {
15270
iterate_ast(c.subselect, lambda);
15271
}
15272
};
15273
15274
template<class With>
15275
struct ast_iterator<With, match_specialization_of<With, with_t>> {
15276
using node_type = With;
15277
15278
template<class L>
15279
void operator()(const node_type& c, L& lambda) const {
15280
iterate_ast(c.cte, lambda);
15281
iterate_ast(c.expression, lambda);
15282
}
15283
};
15284
#endif
15285
15286
template<class T>
15287
struct ast_iterator<T, match_if<is_compound_operator, T>> {
15288
using node_type = T;
15289
15290
template<class L>
15291
void operator()(const node_type& c, L& lambda) const {
15292
iterate_ast(c.compound, lambda);
15293
}
15294
};
15295
15296
template<class T>
15297
struct ast_iterator<into_t<T>, void> {
15298
using node_type = into_t<T>;
15299
15300
template<class L>
15301
void operator()(const node_type& /*node*/, L& /*lambda*/) const {
15302
//..
15303
}
15304
};
15305
15306
template<class... Args>
15307
struct ast_iterator<insert_raw_t<Args...>, void> {
15308
using node_type = insert_raw_t<Args...>;
15309
15310
template<class L>
15311
void operator()(const node_type& node, L& lambda) const {
15312
iterate_ast(node.args, lambda);
15313
}
15314
};
15315
15316
template<class... Args>
15317
struct ast_iterator<replace_raw_t<Args...>, void> {
15318
using node_type = replace_raw_t<Args...>;
15319
15320
template<class L>
15321
void operator()(const node_type& node, L& lambda) const {
15322
iterate_ast(node.args, lambda);
15323
}
15324
};
15325
15326
template<class T, class... Args>
15327
struct ast_iterator<select_t<T, Args...>, void> {
15328
using node_type = select_t<T, Args...>;
15329
15330
template<class L>
15331
void operator()(const node_type& sel, L& lambda) const {
15332
iterate_ast(sel.col, lambda);
15333
iterate_ast(sel.conditions, lambda);
15334
}
15335
};
15336
15337
template<class T, class R, class... Args>
15338
struct ast_iterator<get_all_t<T, R, Args...>, void> {
15339
using node_type = get_all_t<T, R, Args...>;
15340
15341
template<class L>
15342
void operator()(const node_type& get, L& lambda) const {
15343
iterate_ast(get.conditions, lambda);
15344
}
15345
};
15346
15347
template<class T, class... Args>
15348
struct ast_iterator<get_all_pointer_t<T, Args...>, void> {
15349
using node_type = get_all_pointer_t<T, Args...>;
15350
15351
template<class L>
15352
void operator()(const node_type& get, L& lambda) const {
15353
iterate_ast(get.conditions, lambda);
15354
}
15355
};
15356
15357
#ifdef SQLITE_ORM_OPTIONAL_SUPPORTED
15358
template<class T, class... Args>
15359
struct ast_iterator<get_all_optional_t<T, Args...>, void> {
15360
using node_type = get_all_optional_t<T, Args...>;
15361
15362
template<class L>
15363
void operator()(const node_type& get, L& lambda) const {
15364
iterate_ast(get.conditions, lambda);
15365
}
15366
};
15367
#endif // SQLITE_ORM_OPTIONAL_SUPPORTED
15368
15369
template<class S, class... Wargs>
15370
struct ast_iterator<update_all_t<S, Wargs...>, void> {
15371
using node_type = update_all_t<S, Wargs...>;
15372
15373
template<class L>
15374
void operator()(const node_type& u, L& lambda) const {
15375
iterate_ast(u.set, lambda);
15376
iterate_ast(u.conditions, lambda);
15377
}
15378
};
15379
15380
template<class T, class... Args>
15381
struct ast_iterator<remove_all_t<T, Args...>, void> {
15382
using node_type = remove_all_t<T, Args...>;
15383
15384
template<class L>
15385
void operator()(const node_type& r, L& lambda) const {
15386
iterate_ast(r.conditions, lambda);
15387
}
15388
};
15389
15390
template<class... Args>
15391
struct ast_iterator<set_t<Args...>, void> {
15392
using node_type = set_t<Args...>;
15393
15394
template<class L>
15395
void operator()(const node_type& node, L& lambda) const {
15396
iterate_ast(node.assigns, lambda);
15397
}
15398
};
15399
15400
template<class S>
15401
struct ast_iterator<dynamic_set_t<S>, void> {
15402
using node_type = dynamic_set_t<S>;
15403
15404
template<class L>
15405
void operator()(const node_type& node, L& lambda) const {
15406
iterate_ast(node.entries, lambda);
15407
}
15408
};
15409
15410
template<class... Args>
15411
struct ast_iterator<std::tuple<Args...>, void> {
15412
using node_type = std::tuple<Args...>;
15413
15414
template<class L>
15415
void operator()(const node_type& node, L& lambda) const {
15416
iterate_tuple(node, [&lambda](auto& v) {
15417
iterate_ast(v, lambda);
15418
});
15419
}
15420
};
15421
15422
template<class T, class... Args>
15423
struct ast_iterator<group_by_with_having<T, Args...>, void> {
15424
using node_type = group_by_with_having<T, Args...>;
15425
15426
template<class L>
15427
void operator()(const node_type& node, L& lambda) const {
15428
iterate_ast(node.args, lambda);
15429
iterate_ast(node.expression, lambda);
15430
}
15431
};
15432
15433
template<class T, class E>
15434
struct ast_iterator<cast_t<T, E>, void> {
15435
using node_type = cast_t<T, E>;
15436
15437
template<class L>
15438
void operator()(const node_type& c, L& lambda) const {
15439
iterate_ast(c.expression, lambda);
15440
}
15441
};
15442
15443
template<class T>
15444
struct ast_iterator<exists_t<T>, void> {
15445
using node_type = exists_t<T>;
15446
15447
template<class L>
15448
void operator()(const node_type& node, L& lambda) const {
15449
iterate_ast(node.expression, lambda);
15450
}
15451
};
15452
15453
template<class A, class T, class E>
15454
struct ast_iterator<like_t<A, T, E>, void> {
15455
using node_type = like_t<A, T, E>;
15456
15457
template<class L>
15458
void operator()(const node_type& lk, L& lambda) const {
15459
iterate_ast(lk.arg, lambda);
15460
iterate_ast(lk.pattern, lambda);
15461
lk.arg3.apply([&lambda](auto& value) {
15462
iterate_ast(value, lambda);
15463
});
15464
}
15465
};
15466
15467
template<class A, class T>
15468
struct ast_iterator<glob_t<A, T>, void> {
15469
using node_type = glob_t<A, T>;
15470
15471
template<class L>
15472
void operator()(const node_type& lk, L& lambda) const {
15473
iterate_ast(lk.arg, lambda);
15474
iterate_ast(lk.pattern, lambda);
15475
}
15476
};
15477
15478
template<class A, class T>
15479
struct ast_iterator<between_t<A, T>, void> {
15480
using node_type = between_t<A, T>;
15481
15482
template<class L>
15483
void operator()(const node_type& b, L& lambda) const {
15484
iterate_ast(b.expr, lambda);
15485
iterate_ast(b.b1, lambda);
15486
iterate_ast(b.b2, lambda);
15487
}
15488
};
15489
15490
template<class T>
15491
struct ast_iterator<named_collate<T>, void> {
15492
using node_type = named_collate<T>;
15493
15494
template<class L>
15495
void operator()(const node_type& col, L& lambda) const {
15496
iterate_ast(col.expr, lambda);
15497
}
15498
};
15499
15500
template<class C>
15501
struct ast_iterator<negated_condition_t<C>, void> {
15502
using node_type = negated_condition_t<C>;
15503
15504
template<class L>
15505
void operator()(const node_type& neg, L& lambda) const {
15506
iterate_ast(neg.c, lambda);
15507
}
15508
};
15509
15510
template<class T>
15511
struct ast_iterator<is_null_t<T>, void> {
15512
using node_type = is_null_t<T>;
15513
15514
template<class L>
15515
void operator()(const node_type& i, L& lambda) const {
15516
iterate_ast(i.t, lambda);
15517
}
15518
};
15519
15520
template<class T>
15521
struct ast_iterator<is_not_null_t<T>, void> {
15522
using node_type = is_not_null_t<T>;
15523
15524
template<class L>
15525
void operator()(const node_type& i, L& lambda) const {
15526
iterate_ast(i.t, lambda);
15527
}
15528
};
15529
15530
template<class F, class... CallArgs>
15531
struct ast_iterator<function_call<F, CallArgs...>, void> {
15532
using node_type = function_call<F, CallArgs...>;
15533
15534
template<class L>
15535
void operator()(const node_type& f, L& lambda) const {
15536
iterate_ast(f.callArgs, lambda);
15537
}
15538
};
15539
15540
template<class R, class S, class... Args>
15541
struct ast_iterator<built_in_function_t<R, S, Args...>, void> {
15542
using node_type = built_in_function_t<R, S, Args...>;
15543
15544
template<class L>
15545
void operator()(const node_type& node, L& lambda) const {
15546
iterate_ast(node.args, lambda);
15547
}
15548
};
15549
15550
template<class R, class S, class... Args>
15551
struct ast_iterator<built_in_aggregate_function_t<R, S, Args...>, void> {
15552
using node_type = built_in_aggregate_function_t<R, S, Args...>;
15553
15554
template<class L>
15555
void operator()(const node_type& node, L& lambda) const {
15556
iterate_ast(node.args, lambda);
15557
}
15558
};
15559
15560
template<class F, class W>
15561
struct ast_iterator<filtered_aggregate_function<F, W>, void> {
15562
using node_type = filtered_aggregate_function<F, W>;
15563
15564
template<class L>
15565
void operator()(const node_type& node, L& lambda) const {
15566
iterate_ast(node.function, lambda);
15567
iterate_ast(node.where, lambda);
15568
}
15569
};
15570
15571
template<class Join>
15572
struct ast_iterator<Join, match_if<is_constrained_join, Join>> {
15573
using node_type = Join;
15574
15575
template<class L>
15576
void operator()(const node_type& join, L& lambda) const {
15577
iterate_ast(join.constraint, lambda);
15578
}
15579
};
15580
15581
template<class T>
15582
struct ast_iterator<on_t<T>, void> {
15583
using node_type = on_t<T>;
15584
15585
template<class L>
15586
void operator()(const node_type& on, L& lambda) const {
15587
iterate_ast(on.arg, lambda);
15588
}
15589
};
15590
15591
// note: not strictly necessary as there's no binding support for USING;
15592
// we provide it nevertheless, in line with on_t.
15593
template<class T>
15594
struct ast_iterator<T, std::enable_if_t<polyfill::is_specialization_of<T, using_t>::value>> {
15595
using node_type = T;
15596
15597
template<class L>
15598
void operator()(const node_type& o, L& lambda) const {
15599
iterate_ast(o.column, lambda);
15600
}
15601
};
15602
15603
template<class R, class T, class E, class... Args>
15604
struct ast_iterator<simple_case_t<R, T, E, Args...>, void> {
15605
using node_type = simple_case_t<R, T, E, Args...>;
15606
15607
template<class L>
15608
void operator()(const node_type& c, L& lambda) const {
15609
c.case_expression.apply([&lambda](auto& c_) {
15610
iterate_ast(c_, lambda);
15611
});
15612
iterate_tuple(c.args, [&lambda](auto& pair) {
15613
iterate_ast(pair.first, lambda);
15614
iterate_ast(pair.second, lambda);
15615
});
15616
c.else_expression.apply([&lambda](auto& el) {
15617
iterate_ast(el, lambda);
15618
});
15619
}
15620
};
15621
15622
template<class T, class E>
15623
struct ast_iterator<as_t<T, E>, void> {
15624
using node_type = as_t<T, E>;
15625
15626
template<class L>
15627
void operator()(const node_type& a, L& lambda) const {
15628
iterate_ast(a.expression, lambda);
15629
}
15630
};
15631
15632
template<class T, bool OI>
15633
struct ast_iterator<limit_t<T, false, OI, void>, void> {
15634
using node_type = limit_t<T, false, OI, void>;
15635
15636
template<class L>
15637
void operator()(const node_type& a, L& lambda) const {
15638
iterate_ast(a.lim, lambda);
15639
}
15640
};
15641
15642
template<class T, class O>
15643
struct ast_iterator<limit_t<T, true, false, O>, void> {
15644
using node_type = limit_t<T, true, false, O>;
15645
15646
template<class L>
15647
void operator()(const node_type& a, L& lambda) const {
15648
iterate_ast(a.lim, lambda);
15649
a.off.apply([&lambda](auto& value) {
15650
iterate_ast(value, lambda);
15651
});
15652
}
15653
};
15654
15655
template<class T, class O>
15656
struct ast_iterator<limit_t<T, true, true, O>, void> {
15657
using node_type = limit_t<T, true, true, O>;
15658
15659
template<class L>
15660
void operator()(const node_type& a, L& lambda) const {
15661
a.off.apply([&lambda](auto& value) {
15662
iterate_ast(value, lambda);
15663
});
15664
iterate_ast(a.lim, lambda);
15665
}
15666
};
15667
15668
template<class T>
15669
struct ast_iterator<distinct_t<T>, void> {
15670
using node_type = distinct_t<T>;
15671
15672
template<class L>
15673
void operator()(const node_type& a, L& lambda) const {
15674
iterate_ast(a.expression, lambda);
15675
}
15676
};
15677
15678
template<class T>
15679
struct ast_iterator<all_t<T>, void> {
15680
using node_type = all_t<T>;
15681
15682
template<class L>
15683
void operator()(const node_type& a, L& lambda) const {
15684
iterate_ast(a.expression, lambda);
15685
}
15686
};
15687
15688
template<class T>
15689
struct ast_iterator<bitwise_not_t<T>, void> {
15690
using node_type = bitwise_not_t<T>;
15691
15692
template<class L>
15693
void operator()(const node_type& a, L& lambda) const {
15694
iterate_ast(a.argument, lambda);
15695
}
15696
};
15697
15698
template<class... Args>
15699
struct ast_iterator<values_t<Args...>, void> {
15700
using node_type = values_t<Args...>;
15701
15702
template<class L>
15703
void operator()(const node_type& node, L& lambda) const {
15704
iterate_ast(node.tuple, lambda);
15705
}
15706
};
15707
15708
template<class T>
15709
struct ast_iterator<dynamic_values_t<T>, void> {
15710
using node_type = dynamic_values_t<T>;
15711
15712
template<class L>
15713
void operator()(const node_type& node, L& lambda) const {
15714
iterate_ast(node.vector, lambda);
15715
}
15716
};
15717
15718
/**
15719
* Column alias or literal: skipped
15720
*/
15721
template<class T>
15722
struct ast_iterator<T,
15723
std::enable_if_t<polyfill::disjunction<polyfill::is_specialization_of<T, alias_holder>,
15724
polyfill::is_specialization_of<T, literal_holder>,
15725
is_column_alias<T>>::value>> {
15726
using node_type = T;
15727
15728
template<class L>
15729
void operator()(const node_type& /*node*/, L& /*lambda*/) const {}
15730
};
15731
15732
template<class E>
15733
struct ast_iterator<order_by_t<E>, void> {
15734
using node_type = order_by_t<E>;
15735
15736
template<class L>
15737
void operator()(const node_type& node, L& lambda) const {
15738
iterate_ast(node.expression, lambda);
15739
}
15740
};
15741
15742
template<class T>
15743
struct ast_iterator<collate_t<T>, void> {
15744
using node_type = collate_t<T>;
15745
15746
template<class L>
15747
void operator()(const node_type& node, L& lambda) const {
15748
iterate_ast(node.expr, lambda);
15749
}
15750
};
15751
15752
}
15753
}
15754
15755
// #include "prepared_statement.h"
15756
15757
// #include "connection_holder.h"
15758
15759
// #include "util.h"
15760
15761
namespace sqlite_orm {
15762
15763
namespace internal {
15764
15765
/**
15766
* A C++ view-like class which is returned
15767
* by `storage_t::iterate()` function. This class contains STL functions:
15768
* - size_t size()
15769
* - bool empty()
15770
* - iterator end()
15771
* - iterator begin()
15772
* All these functions are not right const cause all of them may open SQLite connections.
15773
*
15774
* `mapped_view` is also a 'borrowed range',
15775
* meaning that iterators obtained from it are not tied to the lifetime of the view instance.
15776
*/
15777
template<class T, class S, class... Args>
15778
struct mapped_view {
15779
using mapped_type = T;
15780
using storage_type = S;
15781
using db_objects_type = typename S::db_objects_type;
15782
15783
storage_type& storage;
15784
connection_ref connection;
15785
get_all_t<T, void, Args...> expression;
15786
15787
mapped_view(storage_type& storage, connection_ref conn, Args&&... args) :
15788
storage(storage), connection(std::move(conn)), expression{{std::forward<Args>(args)...}} {}
15789
15790
size_t size() const {
15791
return this->storage.template count<T>();
15792
}
15793
15794
bool empty() const {
15795
return !this->size();
15796
}
15797
15798
mapped_iterator<T, db_objects_type> begin() {
15799
using context_t = serializer_context<db_objects_type>;
15800
auto& dbObjects = obtain_db_objects(this->storage);
15801
context_t context{dbObjects};
15802
context.skip_table_name = false;
15803
context.replace_bindable_with_question = true;
15804
15805
statement_finalizer stmt{prepare_stmt(this->connection.get(), serialize(this->expression, context))};
15806
iterate_ast(this->expression.conditions, conditional_binder{stmt.get()});
15807
return {dbObjects, std::move(stmt)};
15808
}
15809
15810
mapped_iterator<T, db_objects_type> end() {
15811
return {};
15812
}
15813
};
15814
}
15815
}
15816
15817
#ifdef SQLITE_ORM_CPP20_RANGES_SUPPORTED
15818
template<class T, class S, class... Args>
15819
inline constexpr bool std::ranges::enable_borrowed_range<sqlite_orm::internal::mapped_view<T, S, Args...>> = true;
15820
#endif
15821
15822
// #include "result_set_view.h"
15823
15824
#include <sqlite3.h>
15825
#include <utility> // std::move, std::remove_cvref
15826
#include <functional> // std::reference_wrapper
15827
#if defined(SQLITE_ORM_SENTINEL_BASED_FOR_SUPPORTED) && defined(SQLITE_ORM_DEFAULT_COMPARISONS_SUPPORTED) && \
15828
defined(SQLITE_ORM_CPP20_RANGES_SUPPORTED)
15829
#include <ranges> // std::ranges::view_interface
15830
#endif
15831
15832
// #include "functional/cxx_type_traits_polyfill.h"
15833
15834
// #include "row_extractor.h"
15835
15836
// #include "result_set_iterator.h"
15837
15838
#include <sqlite3.h>
15839
#include <utility> // std::move
15840
#include <iterator> // std::input_iterator_tag, std::default_sentinel_t
15841
#include <functional> // std::reference_wrapper
15842
15843
// #include "statement_finalizer.h"
15844
15845
// #include "row_extractor.h"
15846
15847
// #include "column_result_proxy.h"
15848
15849
// #include "util.h"
15850
15851
#if defined(SQLITE_ORM_SENTINEL_BASED_FOR_SUPPORTED) && defined(SQLITE_ORM_DEFAULT_COMPARISONS_SUPPORTED)
15852
namespace sqlite_orm::internal {
15853
15854
template<class ColResult, class DBOs>
15855
class result_set_iterator;
15856
15857
#ifdef SQLITE_ORM_STL_HAS_DEFAULT_SENTINEL
15858
using result_set_sentinel_t = std::default_sentinel_t;
15859
#else
15860
// sentinel
15861
template<>
15862
class result_set_iterator<void, void> {};
15863
15864
using result_set_sentinel_t = result_set_iterator<void, void>;
15865
#endif
15866
15867
/*
15868
* Input iterator over a result set for a select statement.
15869
*/
15870
template<class ColResult, class DBOs>
15871
class result_set_iterator {
15872
public:
15873
using db_objects_type = DBOs;
15874
15875
#ifdef SQLITE_ORM_CPP20_CONCEPTS_SUPPORTED
15876
using iterator_concept = std::input_iterator_tag;
15877
#else
15878
using iterator_category = std::input_iterator_tag;
15879
#endif
15880
using difference_type = ptrdiff_t;
15881
using value_type = column_result_proxy_t<ColResult>;
15882
15883
public:
15884
result_set_iterator(const db_objects_type& dbObjects, statement_finalizer stmt) :
15885
db_objects{dbObjects}, stmt{std::move(stmt)} {
15886
this->step();
15887
}
15888
result_set_iterator(result_set_iterator&&) = default;
15889
result_set_iterator& operator=(result_set_iterator&&) = default;
15890
result_set_iterator(const result_set_iterator&) = delete;
15891
result_set_iterator& operator=(const result_set_iterator&) = delete;
15892
15893
/** @pre `*this != std::default_sentinel` */
15894
value_type operator*() const {
15895
return this->extract();
15896
}
15897
15898
result_set_iterator& operator++() {
15899
this->step();
15900
return *this;
15901
}
15902
15903
void operator++(int) {
15904
++*this;
15905
}
15906
15907
friend bool operator==(const result_set_iterator& it, const result_set_sentinel_t&) noexcept {
15908
return sqlite3_data_count(it.stmt.get()) == 0;
15909
}
15910
15911
private:
15912
void step() {
15913
perform_step(this->stmt.get(), [](sqlite3_stmt*) {});
15914
}
15915
15916
value_type extract() const {
15917
const auto rowExtractor = make_row_extractor<ColResult>(this->db_objects.get());
15918
return rowExtractor.extract(this->stmt.get(), 0);
15919
}
15920
15921
private:
15922
std::reference_wrapper<const db_objects_type> db_objects;
15923
statement_finalizer stmt;
15924
};
15925
}
15926
#endif
15927
15928
// #include "ast_iterator.h"
15929
15930
// #include "connection_holder.h"
15931
15932
// #include "util.h"
15933
15934
// #include "type_traits.h"
15935
15936
// #include "storage_lookup.h"
15937
15938
#if defined(SQLITE_ORM_SENTINEL_BASED_FOR_SUPPORTED) && defined(SQLITE_ORM_DEFAULT_COMPARISONS_SUPPORTED)
15939
namespace sqlite_orm::internal {
15940
/*
15941
* A C++ view over a result set of a select statement, returned by `storage_t::iterate()`.
15942
*
15943
* `result_set_view` is also a 'borrowed range',
15944
* meaning that iterators obtained from it are not tied to the lifetime of the view instance.
15945
*/
15946
template<class Select, class DBOs>
15947
struct result_set_view
15948
#ifdef SQLITE_ORM_CPP20_RANGES_SUPPORTED
15949
: std::ranges::view_interface<result_set_view<Select, DBOs>>
15950
#endif
15951
{
15952
using db_objects_type = DBOs;
15953
using expression_type = Select;
15954
15955
result_set_view(const db_objects_type& dbObjects, connection_ref conn, Select expression) :
15956
db_objects{dbObjects}, connection{std::move(conn)}, expression{std::move(expression)} {}
15957
15958
result_set_view(result_set_view&&) = default;
15959
result_set_view& operator=(result_set_view&&) = default;
15960
result_set_view(const result_set_view&) = default;
15961
result_set_view& operator=(const result_set_view&) = default;
15962
15963
auto begin() {
15964
const auto& exprDBOs = db_objects_for_expression(this->db_objects.get(), this->expression);
15965
using ExprDBOs = std::remove_cvref_t<decltype(exprDBOs)>;
15966
// note: Select can be `select_t` or `with_t`
15967
using select_type = polyfill::detected_or_t<expression_type, expression_type_t, expression_type>;
15968
using column_result_type = column_result_of_t<ExprDBOs, select_type>;
15969
using context_t = serializer_context<ExprDBOs>;
15970
context_t context{exprDBOs};
15971
context.skip_table_name = false;
15972
context.replace_bindable_with_question = true;
15973
15974
statement_finalizer stmt{prepare_stmt(this->connection.get(), serialize(this->expression, context))};
15975
iterate_ast(this->expression, conditional_binder{stmt.get()});
15976
15977
// note: it is enough to only use the 'expression DBOs' at compile-time to determine the column results;
15978
// because we cannot select objects/structs from a CTE, passing the permanently defined DBOs are enough.
15979
using iterator_type = result_set_iterator<column_result_type, db_objects_type>;
15980
return iterator_type{this->db_objects, std::move(stmt)};
15981
}
15982
15983
result_set_sentinel_t end() {
15984
return {};
15985
}
15986
15987
private:
15988
std::reference_wrapper<const db_objects_type> db_objects;
15989
connection_ref connection;
15990
expression_type expression;
15991
};
15992
}
15993
15994
#ifdef SQLITE_ORM_CPP20_RANGES_SUPPORTED
15995
template<class Select, class DBOs>
15996
inline constexpr bool std::ranges::enable_borrowed_range<sqlite_orm::internal::result_set_view<Select, DBOs>> = true;
15997
#endif
15998
#endif
15999
16000
// #include "ast_iterator.h"
16001
16002
// #include "storage_base.h"
16003
16004
#include <sqlite3.h>
16005
#include <cstdlib> // atoi
16006
#include <memory> // std::allocator
16007
#include <functional> // std::function, std::bind, std::bind_front
16008
#include <string> // std::string
16009
#include <sstream> // std::stringstream
16010
#include <iomanip> // std::flush
16011
#include <utility> // std::move
16012
#include <system_error> // std::system_error
16013
#include <vector> // std::vector
16014
#include <list> // std::list
16015
#include <memory> // std::make_unique, std::unique_ptr
16016
#include <map> // std::map
16017
#include <type_traits> // std::is_same
16018
#include <algorithm> // std::find_if, std::ranges::find
16019
16020
// #include "functional/cxx_tuple_polyfill.h"
16021
16022
#include <tuple> // std::apply; std::tuple_size
16023
#if __cpp_lib_apply < 201603L
16024
#include <utility> // std::forward, std::index_sequence, std::make_index_sequence
16025
#endif
16026
16027
// #include "../functional/cxx_functional_polyfill.h"
16028
// std::invoke
16029
16030
namespace sqlite_orm {
16031
namespace internal {
16032
namespace polyfill {
16033
#if __cpp_lib_apply >= 201603L
16034
using std::apply;
16035
#else
16036
template<class Callable, class Tpl, size_t... Idx>
16037
decltype(auto) apply(Callable&& callable, Tpl&& tpl, std::index_sequence<Idx...>) {
16038
return polyfill::invoke(std::forward<Callable>(callable), std::get<Idx>(std::forward<Tpl>(tpl))...);
16039
}
16040
16041
template<class Callable, class Tpl>
16042
decltype(auto) apply(Callable&& callable, Tpl&& tpl) {
16043
constexpr size_t size = std::tuple_size<std::remove_reference_t<Tpl>>::value;
16044
return apply(std::forward<Callable>(callable),
16045
std::forward<Tpl>(tpl),
16046
std::make_index_sequence<size>{});
16047
}
16048
#endif
16049
}
16050
}
16051
16052
namespace polyfill = internal::polyfill;
16053
}
16054
// std::apply
16055
// #include "tuple_helper/tuple_iteration.h"
16056
16057
// #include "pragma.h"
16058
16059
#include <sqlite3.h>
16060
#include <cstdlib> // atoi
16061
#include <string> // std::string
16062
#include <functional> // std::function
16063
#include <memory> // std::shared_ptr
16064
#include <vector> // std::vector
16065
#include <sstream>
16066
#include <iomanip> // std::flush
16067
16068
// #include "error_code.h"
16069
16070
// #include "row_extractor.h"
16071
16072
// #include "journal_mode.h"
16073
16074
// #include "locking_mode.h"
16075
16076
// #include "connection_holder.h"
16077
16078
// #include "util.h"
16079
16080
// #include "serializing_util.h"
16081
16082
#include <type_traits> // std::index_sequence, std::remove_cvref
16083
#include <tuple>
16084
#include <array>
16085
#include <string>
16086
#include <ostream>
16087
#include <utility> // std::exchange, std::tuple_size, std::make_index_sequence
16088
16089
// #include "functional/cxx_type_traits_polyfill.h"
16090
// std::remove_cvref, polyfill::is_detected
16091
// #include "functional/cxx_functional_polyfill.h"
16092
16093
// #include "tuple_helper/tuple_iteration.h"
16094
16095
// #include "type_traits.h"
16096
16097
// #include "error_code.h"
16098
16099
// #include "serializer_context.h"
16100
16101
// #include "serialize_result_type.h"
16102
16103
// #include "util.h"
16104
16105
// #include "schema/column.h"
16106
16107
namespace sqlite_orm {
16108
namespace internal {
16109
template<class O>
16110
struct order_by_t;
16111
16112
template<class T, class Ctx>
16113
auto serialize(const T& t, const Ctx& context);
16114
16115
template<class T, class Ctx>
16116
std::string serialize_order_by(const T&, const Ctx&);
16117
16118
inline void stream_sql_escaped(std::ostream& os, serialize_arg_type str, char char2Escape) {
16119
for (size_t offset = 0, next; true; offset = next + 1) {
16120
next = str.find(char2Escape, offset);
16121
16122
if (next == str.npos) SQLITE_ORM_CPP_LIKELY {
16123
os.write(str.data() + offset, str.size() - offset);
16124
break;
16125
}
16126
16127
os.write(str.data() + offset, next - offset + 1);
16128
os.write(&char2Escape, 1);
16129
}
16130
}
16131
16132
inline void stream_identifier(std::ostream& ss,
16133
serialize_arg_type qualifier,
16134
serialize_arg_type identifier,
16135
serialize_arg_type alias) {
16136
constexpr char quoteChar = '"';
16137
constexpr char qualified[] = {quoteChar, '.', '\0'};
16138
constexpr char aliased[] = {' ', quoteChar, '\0'};
16139
16140
// note: In practice, escaping double quotes in identifiers is arguably overkill,
16141
// but since the SQLite grammar allows it, it's better to be safe than sorry.
16142
16143
if (!qualifier.empty()) {
16144
ss << quoteChar;
16145
stream_sql_escaped(ss, qualifier, quoteChar);
16146
ss << qualified;
16147
}
16148
{
16149
ss << quoteChar;
16150
stream_sql_escaped(ss, identifier, quoteChar);
16151
ss << quoteChar;
16152
}
16153
if (!alias.empty()) {
16154
ss << aliased;
16155
stream_sql_escaped(ss, alias, quoteChar);
16156
ss << quoteChar;
16157
}
16158
}
16159
16160
inline void stream_identifier(std::ostream& ss, const std::string& identifier, const std::string& alias) {
16161
return stream_identifier(ss, "", identifier, alias);
16162
}
16163
16164
inline void stream_identifier(std::ostream& ss, const std::string& identifier) {
16165
return stream_identifier(ss, "", identifier, "");
16166
}
16167
16168
template<typename Tpl, size_t... Is>
16169
void stream_identifier(std::ostream& ss, const Tpl& tpl, std::index_sequence<Is...>) {
16170
static_assert(sizeof...(Is) > 0 && sizeof...(Is) <= 3, "");
16171
return stream_identifier(ss, std::get<Is>(tpl)...);
16172
}
16173
16174
template<typename Tpl,
16175
std::enable_if_t<polyfill::is_detected<type_t, std::tuple_size<Tpl>>::value, bool> = true>
16176
void stream_identifier(std::ostream& ss, const Tpl& tpl) {
16177
return stream_identifier(ss, tpl, std::make_index_sequence<std::tuple_size<Tpl>::value>{});
16178
}
16179
16180
enum class stream_as {
16181
conditions_tuple,
16182
actions_tuple,
16183
expressions_tuple,
16184
dynamic_expressions,
16185
compound_expressions,
16186
serialized,
16187
identifier,
16188
identifiers,
16189
values_placeholders,
16190
table_columns,
16191
non_generated_columns,
16192
field_values_excluding,
16193
mapped_columns_expressions,
16194
column_constraints,
16195
constraints_tuple,
16196
};
16197
16198
template<stream_as mode>
16199
struct streaming {
16200
template<class... Ts>
16201
auto operator()(const Ts&... ts) const {
16202
return std::forward_as_tuple(*this, ts...);
16203
}
16204
16205
template<size_t... Idx>
16206
constexpr std::index_sequence<1u + Idx...> offset_index(std::index_sequence<Idx...>) const {
16207
return {};
16208
}
16209
};
16210
constexpr streaming<stream_as::conditions_tuple> streaming_conditions_tuple{};
16211
constexpr streaming<stream_as::actions_tuple> streaming_actions_tuple{};
16212
constexpr streaming<stream_as::expressions_tuple> streaming_expressions_tuple{};
16213
constexpr streaming<stream_as::dynamic_expressions> streaming_dynamic_expressions{};
16214
constexpr streaming<stream_as::compound_expressions> streaming_compound_expressions{};
16215
constexpr streaming<stream_as::serialized> streaming_serialized{};
16216
constexpr streaming<stream_as::identifier> streaming_identifier{};
16217
constexpr streaming<stream_as::identifiers> streaming_identifiers{};
16218
constexpr streaming<stream_as::values_placeholders> streaming_values_placeholders{};
16219
constexpr streaming<stream_as::table_columns> streaming_table_column_names{};
16220
constexpr streaming<stream_as::non_generated_columns> streaming_non_generated_column_names{};
16221
constexpr streaming<stream_as::field_values_excluding> streaming_field_values_excluding{};
16222
constexpr streaming<stream_as::mapped_columns_expressions> streaming_mapped_columns_expressions{};
16223
constexpr streaming<stream_as::constraints_tuple> streaming_constraints_tuple{};
16224
constexpr streaming<stream_as::column_constraints> streaming_column_constraints{};
16225
16226
// serialize and stream a tuple of condition expressions;
16227
// space + space-separated
16228
template<class T, class Ctx>
16229
std::ostream& operator<<(std::ostream& ss,
16230
std::tuple<const streaming<stream_as::conditions_tuple>&, T, Ctx> tpl) {
16231
const auto& conditions = std::get<1>(tpl);
16232
auto& context = std::get<2>(tpl);
16233
16234
iterate_tuple(conditions, [&ss, &context](auto& c) {
16235
ss << " " << serialize(c, context);
16236
});
16237
return ss;
16238
}
16239
16240
// serialize and stream a tuple of action expressions;
16241
// space-separated
16242
template<class T, class Ctx>
16243
std::ostream& operator<<(std::ostream& ss, std::tuple<const streaming<stream_as::actions_tuple>&, T, Ctx> tpl) {
16244
const auto& actions = std::get<1>(tpl);
16245
auto& context = std::get<2>(tpl);
16246
16247
iterate_tuple(actions, [&ss, &context, first = true](auto& action) mutable {
16248
static constexpr std::array<const char*, 2> sep = {" ", ""};
16249
ss << sep[std::exchange(first, false)] << serialize(action, context);
16250
});
16251
return ss;
16252
}
16253
16254
// serialize and stream a tuple of expressions;
16255
// comma-separated
16256
template<class T, class Ctx>
16257
std::ostream& operator<<(std::ostream& ss,
16258
std::tuple<const streaming<stream_as::expressions_tuple>&, T, Ctx> tpl) {
16259
const auto& args = std::get<1>(tpl);
16260
auto& context = std::get<2>(tpl);
16261
16262
iterate_tuple(args, [&ss, &context, first = true](auto& arg) mutable {
16263
static constexpr std::array<const char*, 2> sep = {", ", ""};
16264
ss << sep[std::exchange(first, false)] << serialize(arg, context);
16265
});
16266
return ss;
16267
}
16268
16269
// serialize and stream expressions of a compound statement;
16270
// separated by compound operator
16271
template<class T, class Ctx>
16272
std::ostream&
16273
operator<<(std::ostream& ss,
16274
std::tuple<const streaming<stream_as::compound_expressions>&, T, const std::string&, Ctx> tpl) {
16275
const auto& args = std::get<1>(tpl);
16276
const std::string& opString = std::get<2>(tpl);
16277
auto& context = std::get<3>(tpl);
16278
16279
iterate_tuple(args, [&ss, &opString, &context, first = true](auto& arg) mutable {
16280
if (!std::exchange(first, false)) {
16281
ss << ' ' << opString << ' ';
16282
}
16283
ss << serialize(arg, context);
16284
});
16285
return ss;
16286
}
16287
16288
// serialize and stream multi_order_by arguments;
16289
// comma-separated
16290
template<class... Os, class Ctx>
16291
std::ostream& operator<<(
16292
std::ostream& ss,
16293
std::tuple<const streaming<stream_as::expressions_tuple>&, const std::tuple<order_by_t<Os>...>&, Ctx> tpl) {
16294
const auto& args = std::get<1>(tpl);
16295
auto& context = std::get<2>(tpl);
16296
16297
iterate_tuple(args, [&ss, &context, first = true](auto& arg) mutable {
16298
static constexpr std::array<const char*, 2> sep = {", ", ""};
16299
ss << sep[std::exchange(first, false)] << serialize_order_by(arg, context);
16300
});
16301
return ss;
16302
}
16303
16304
// serialize and stream a vector or any other STL container of expressions;
16305
// comma-separated
16306
template<class C, class Ctx>
16307
std::ostream& operator<<(std::ostream& ss,
16308
std::tuple<const streaming<stream_as::dynamic_expressions>&, C, Ctx> tpl) {
16309
const auto& args = std::get<1>(tpl);
16310
auto& context = std::get<2>(tpl);
16311
16312
static constexpr std::array<const char*, 2> sep = {", ", ""};
16313
bool first = true;
16314
for (auto& argument: args) {
16315
ss << sep[std::exchange(first, false)] << serialize(argument, context);
16316
}
16317
return ss;
16318
}
16319
16320
// stream a vector of already serialized strings;
16321
// comma-separated
16322
template<class C>
16323
std::ostream& operator<<(std::ostream& ss, std::tuple<const streaming<stream_as::serialized>&, C> tpl) {
16324
const auto& strings = std::get<1>(tpl);
16325
16326
static constexpr std::array<const char*, 2> sep = {", ", ""};
16327
for (size_t i = 0, first = true; i < strings.size(); ++i) {
16328
ss << sep[std::exchange(first, false)] << strings[i];
16329
}
16330
return ss;
16331
}
16332
16333
// stream an identifier described by a variadic string pack, which is one of:
16334
// 1. identifier
16335
// 2. identifier, alias
16336
// 3. qualifier, identifier, alias
16337
template<class... Strings>
16338
std::ostream& operator<<(std::ostream& ss,
16339
std::tuple<const streaming<stream_as::identifier>&, Strings...> tpl) {
16340
stream_identifier(ss, tpl, streaming_identifier.offset_index(std::index_sequence_for<Strings...>{}));
16341
return ss;
16342
}
16343
16344
// stream a container of identifiers described by a string or a tuple, which is one of:
16345
// 1. identifier
16346
// 1. tuple(identifier)
16347
// 2. tuple(identifier, alias), pair(identifier, alias)
16348
// 3. tuple(qualifier, identifier, alias)
16349
//
16350
// comma-separated
16351
template<class C>
16352
std::ostream& operator<<(std::ostream& ss, std::tuple<const streaming<stream_as::identifiers>&, C> tpl) {
16353
const auto& identifiers = std::get<1>(tpl);
16354
16355
static constexpr std::array<const char*, 2> sep = {", ", ""};
16356
bool first = true;
16357
for (auto& identifier: identifiers) {
16358
ss << sep[std::exchange(first, false)];
16359
stream_identifier(ss, identifier);
16360
}
16361
return ss;
16362
}
16363
16364
// stream placeholders as part of a values clause
16365
template<class... Ts>
16366
std::ostream& operator<<(std::ostream& ss,
16367
std::tuple<const streaming<stream_as::values_placeholders>&, Ts...> tpl) {
16368
const size_t& columnsCount = std::get<1>(tpl);
16369
const ptrdiff_t& valuesCount = std::get<2>(tpl);
16370
16371
if (!valuesCount || !columnsCount) {
16372
return ss;
16373
}
16374
16375
std::string result;
16376
result.reserve((1 + (columnsCount * 1) + (columnsCount * 2 - 2) + 1) * valuesCount + (valuesCount * 2 - 2));
16377
16378
static constexpr std::array<const char*, 2> sep = {", ", ""};
16379
for (ptrdiff_t i = 0, first = true; i < valuesCount; ++i) {
16380
result += sep[std::exchange(first, false)];
16381
result += "(";
16382
for (size_t i = 0, first = true; i < columnsCount; ++i) {
16383
result += sep[std::exchange(first, false)];
16384
result += "?";
16385
}
16386
result += ")";
16387
}
16388
ss << result;
16389
return ss;
16390
}
16391
16392
// stream a table's column identifiers, possibly qualified;
16393
// comma-separated
16394
template<class Table>
16395
std::ostream&
16396
operator<<(std::ostream& ss,
16397
std::tuple<const streaming<stream_as::table_columns>&, Table, const std::string&> tpl) {
16398
const auto& table = std::get<1>(tpl);
16399
const std::string& qualifier = std::get<2>(tpl);
16400
16401
table.for_each_column([&ss, &qualifier, first = true](const column_identifier& column) mutable {
16402
static constexpr std::array<const char*, 2> sep = {", ", ""};
16403
ss << sep[std::exchange(first, false)];
16404
stream_identifier(ss, qualifier, column.name, std::string{});
16405
});
16406
return ss;
16407
}
16408
16409
// stream a table's non-generated column identifiers, unqualified;
16410
// comma-separated
16411
template<class Table>
16412
std::ostream& operator<<(std::ostream& ss,
16413
std::tuple<const streaming<stream_as::non_generated_columns>&, Table> tpl) {
16414
const auto& table = std::get<1>(tpl);
16415
16416
table.template for_each_column_excluding<is_generated_always>(
16417
[&ss, first = true](const column_identifier& column) mutable {
16418
static constexpr std::array<const char*, 2> sep = {", ", ""};
16419
ss << sep[std::exchange(first, false)];
16420
stream_identifier(ss, column.name);
16421
});
16422
return ss;
16423
}
16424
16425
// stream a table's non-generated column identifiers, unqualified;
16426
// comma-separated
16427
template<class PredFnCls, class L, class Ctx, class Obj>
16428
std::ostream&
16429
operator<<(std::ostream& ss,
16430
std::tuple<const streaming<stream_as::field_values_excluding>&, PredFnCls, L, Ctx, Obj> tpl) {
16431
using check_if_excluded = polyfill::remove_cvref_t<std::tuple_element_t<1, decltype(tpl)>>;
16432
auto& excluded = std::get<2>(tpl);
16433
auto& context = std::get<3>(tpl);
16434
auto& object = std::get<4>(tpl);
16435
using object_type = polyfill::remove_cvref_t<decltype(object)>;
16436
auto& table = pick_table<object_type>(context.db_objects);
16437
16438
table.template for_each_column_excluding<check_if_excluded>(call_as_template_base<column_field>(
16439
[&ss, &excluded, &context, &object, first = true](auto& column) mutable {
16440
if (excluded(column)) {
16441
return;
16442
}
16443
16444
static constexpr std::array<const char*, 2> sep = {", ", ""};
16445
ss << sep[std::exchange(first, false)]
16446
<< serialize(polyfill::invoke(column.member_pointer, object), context);
16447
}));
16448
return ss;
16449
}
16450
16451
// stream a tuple of mapped columns (which are member pointers or column pointers);
16452
// comma-separated
16453
template<class T, class Ctx>
16454
std::ostream& operator<<(std::ostream& ss,
16455
std::tuple<const streaming<stream_as::mapped_columns_expressions>&, T, Ctx> tpl) {
16456
const auto& columns = std::get<1>(tpl);
16457
auto& context = std::get<2>(tpl);
16458
16459
iterate_tuple(columns, [&ss, &context, first = true](auto& colRef) mutable {
16460
const std::string* columnName = find_column_name(context.db_objects, colRef);
16461
if (!columnName) {
16462
throw std::system_error{orm_error_code::column_not_found};
16463
}
16464
16465
static constexpr std::array<const char*, 2> sep = {", ", ""};
16466
ss << sep[std::exchange(first, false)];
16467
stream_identifier(ss, *columnName);
16468
});
16469
return ss;
16470
}
16471
16472
// serialize and stream a tuple of conditions or hints;
16473
// space + space-separated
16474
template<class T, class Ctx>
16475
std::ostream& operator<<(std::ostream& ss,
16476
std::tuple<const streaming<stream_as::constraints_tuple>&, T, Ctx> tpl) {
16477
const auto& constraints = get<1>(tpl);
16478
auto& context = get<2>(tpl);
16479
16480
iterate_tuple(constraints, [&ss, &context](auto& constraint) mutable {
16481
ss << ' ' << serialize(constraint, context);
16482
});
16483
return ss;
16484
}
16485
16486
// serialize and stream a tuple of column constraints;
16487
// space + space-separated
16488
template<class... Op, class Ctx>
16489
std::ostream& operator<<(std::ostream& ss,
16490
std::tuple<const streaming<stream_as::column_constraints>&,
16491
const column_constraints<Op...>&,
16492
const bool&,
16493
Ctx> tpl) {
16494
const auto& column = std::get<1>(tpl);
16495
const bool& isNotNull = std::get<2>(tpl);
16496
auto& context = std::get<3>(tpl);
16497
16498
using constraints_tuple = decltype(column.constraints);
16499
iterate_tuple(column.constraints, [&ss, &context](auto& constraint) {
16500
ss << ' ' << serialize(constraint, context);
16501
});
16502
// add implicit null constraint
16503
if (!context.fts5_columns) {
16504
constexpr bool hasExplicitNullableConstraint =
16505
mpl::invoke_t<mpl::disjunction<check_if_has_type<null_t>, check_if_has_type<not_null_t>>,
16506
constraints_tuple>::value;
16507
if SQLITE_ORM_CONSTEXPR_IF (!hasExplicitNullableConstraint) {
16508
if (isNotNull) {
16509
ss << " NOT NULL";
16510
} else {
16511
ss << " NULL";
16512
}
16513
}
16514
}
16515
16516
return ss;
16517
}
16518
}
16519
}
16520
16521
namespace sqlite_orm {
16522
16523
namespace internal {
16524
struct storage_base;
16525
16526
template<class T>
16527
int getPragmaCallback(void* data, int argc, char** argv, char** x) {
16528
return extract_single_value<T>(data, argc, argv, x);
16529
}
16530
16531
template<>
16532
inline int getPragmaCallback<std::vector<std::string>>(void* data, int argc, char** argv, char**) {
16533
auto& res = *(std::vector<std::string>*)data;
16534
res.reserve(argc);
16535
const auto rowExtractor = column_text_extractor<std::string>();
16536
for (int i = 0; i < argc; ++i) {
16537
auto rowString = rowExtractor.extract(argv[i]);
16538
res.push_back(std::move(rowString));
16539
}
16540
return 0;
16541
}
16542
16543
struct pragma_t {
16544
using get_connection_t = std::function<internal::connection_ref()>;
16545
16546
pragma_t(get_connection_t get_connection_) : get_connection(std::move(get_connection_)) {}
16547
16548
std::vector<std::string> module_list() {
16549
return this->get_pragma<std::vector<std::string>>("module_list");
16550
}
16551
16552
bool recursive_triggers() {
16553
return bool(this->get_pragma<int>("recursive_triggers"));
16554
}
16555
16556
void recursive_triggers(bool value) {
16557
this->set_pragma("recursive_triggers", int(value));
16558
}
16559
16560
void busy_timeout(int value) {
16561
this->set_pragma("busy_timeout", value);
16562
}
16563
16564
int busy_timeout() {
16565
return this->get_pragma<int>("busy_timeout");
16566
}
16567
16568
sqlite_orm::locking_mode locking_mode() {
16569
return this->get_pragma<sqlite_orm::locking_mode>("locking_mode");
16570
}
16571
16572
void locking_mode(sqlite_orm::locking_mode value) {
16573
this->set_pragma("locking_mode", value);
16574
}
16575
16576
sqlite_orm::journal_mode journal_mode() {
16577
return this->get_pragma<sqlite_orm::journal_mode>("journal_mode");
16578
}
16579
16580
void journal_mode(sqlite_orm::journal_mode value) {
16581
this->journal_mode_ = -1;
16582
this->set_pragma("journal_mode", value);
16583
this->journal_mode_ = static_cast<decltype(this->journal_mode_)>(value);
16584
}
16585
16586
/**
16587
* https://www.sqlite.org/pragma.html#pragma_application_id
16588
*/
16589
int application_id() {
16590
return this->get_pragma<int>("application_id");
16591
}
16592
16593
/**
16594
* https://www.sqlite.org/pragma.html#pragma_application_id
16595
*/
16596
void application_id(int value) {
16597
this->set_pragma("application_id", value);
16598
}
16599
16600
int synchronous() {
16601
return this->get_pragma<int>("synchronous");
16602
}
16603
16604
void synchronous(int value) {
16605
this->synchronous_ = -1;
16606
this->set_pragma("synchronous", value);
16607
this->synchronous_ = value;
16608
}
16609
16610
int user_version() {
16611
return this->get_pragma<int>("user_version");
16612
}
16613
16614
void user_version(int value) {
16615
this->set_pragma("user_version", value);
16616
}
16617
16618
int auto_vacuum() {
16619
return this->get_pragma<int>("auto_vacuum");
16620
}
16621
16622
void auto_vacuum(int value) {
16623
this->set_pragma("auto_vacuum", value);
16624
}
16625
16626
int max_page_count() {
16627
return this->get_pragma<int>("max_page_count");
16628
}
16629
16630
void max_page_count(int value) {
16631
this->set_pragma("max_page_count", value);
16632
}
16633
16634
std::vector<std::string> integrity_check() {
16635
return this->get_pragma<std::vector<std::string>>("integrity_check");
16636
}
16637
16638
template<class T>
16639
std::vector<std::string> integrity_check(T table_name) {
16640
std::ostringstream ss;
16641
ss << "integrity_check(" << table_name << ")" << std::flush;
16642
return this->get_pragma<std::vector<std::string>>(ss.str());
16643
}
16644
16645
std::vector<std::string> integrity_check(int n) {
16646
std::ostringstream ss;
16647
ss << "integrity_check(" << n << ")" << std::flush;
16648
return this->get_pragma<std::vector<std::string>>(ss.str());
16649
}
16650
16651
std::vector<std::string> quick_check() {
16652
return this->get_pragma<std::vector<std::string>>("quick_check");
16653
}
16654
16655
// will include generated columns in response as opposed to table_info
16656
std::vector<sqlite_orm::table_xinfo> table_xinfo(const std::string& tableName) const {
16657
auto connection = this->get_connection();
16658
16659
std::vector<sqlite_orm::table_xinfo> result;
16660
std::ostringstream ss;
16661
ss << "PRAGMA "
16662
"table_xinfo("
16663
<< streaming_identifier(tableName) << ")" << std::flush;
16664
perform_exec(
16665
connection.get(),
16666
ss.str(),
16667
[](void* data, int argc, char** argv, char**) -> int {
16668
auto& res = *(std::vector<sqlite_orm::table_xinfo>*)data;
16669
if (argc) {
16670
auto index = 0;
16671
auto cid = atoi(argv[index++]);
16672
std::string name = argv[index++];
16673
std::string type = argv[index++];
16674
bool notnull = !!atoi(argv[index++]);
16675
std::string dflt_value = argv[index] ? argv[index] : "";
16676
++index;
16677
auto pk = atoi(argv[index++]);
16678
auto hidden = atoi(argv[index++]);
16679
res.emplace_back(cid,
16680
std::move(name),
16681
std::move(type),
16682
notnull,
16683
std::move(dflt_value),
16684
pk,
16685
hidden);
16686
}
16687
return 0;
16688
},
16689
&result);
16690
return result;
16691
}
16692
16693
std::vector<sqlite_orm::table_info> table_info(const std::string& tableName) const {
16694
auto connection = this->get_connection();
16695
16696
std::ostringstream ss;
16697
ss << "PRAGMA "
16698
"table_info("
16699
<< streaming_identifier(tableName) << ")" << std::flush;
16700
std::vector<sqlite_orm::table_info> result;
16701
perform_exec(
16702
connection.get(),
16703
ss.str(),
16704
[](void* data, int argc, char** argv, char**) -> int {
16705
auto& res = *(std::vector<sqlite_orm::table_info>*)data;
16706
if (argc) {
16707
auto index = 0;
16708
auto cid = atoi(argv[index++]);
16709
std::string name = argv[index++];
16710
std::string type = argv[index++];
16711
bool notnull = !!atoi(argv[index++]);
16712
std::string dflt_value = argv[index] ? argv[index] : "";
16713
++index;
16714
auto pk = atoi(argv[index++]);
16715
res.emplace_back(cid, std::move(name), std::move(type), notnull, std::move(dflt_value), pk);
16716
}
16717
return 0;
16718
},
16719
&result);
16720
return result;
16721
}
16722
16723
private:
16724
friend struct storage_base;
16725
16726
int synchronous_ = -1;
16727
signed char journal_mode_ = -1; // if != -1 stores static_cast<sqlite_orm::journal_mode>(journal_mode)
16728
get_connection_t get_connection;
16729
16730
template<class T>
16731
T get_pragma(const std::string& name) {
16732
auto connection = this->get_connection();
16733
T result;
16734
perform_exec(connection.get(), "PRAGMA " + name, getPragmaCallback<T>, &result);
16735
return result;
16736
}
16737
16738
/**
16739
* Yevgeniy Zakharov: I wanted to refactor this function with statements and value bindings
16740
* but it turns out that bindings in pragma statements are not supported.
16741
*/
16742
template<class T>
16743
void set_pragma(const std::string& name, const T& value, sqlite3* db = nullptr) {
16744
std::stringstream ss;
16745
ss << "PRAGMA " << name << " = " << value;
16746
this->set_pragma_impl(ss.str(), db);
16747
}
16748
16749
void set_pragma(const std::string& name, sqlite_orm::journal_mode value, sqlite3* db = nullptr) {
16750
std::stringstream ss;
16751
ss << "PRAGMA " << name << " = " << journal_mode_to_string(value);
16752
this->set_pragma_impl(ss.str(), db);
16753
}
16754
16755
void set_pragma(const std::string& name, sqlite_orm::locking_mode value, sqlite3* db = nullptr) {
16756
std::stringstream ss;
16757
ss << "PRAGMA " << name << " = " << locking_mode_to_string(value);
16758
this->set_pragma_impl(ss.str(), db);
16759
}
16760
16761
void set_pragma_impl(const std::string& query, sqlite3* db = nullptr) {
16762
auto con = this->get_connection();
16763
if (db == nullptr) {
16764
db = con.get();
16765
}
16766
perform_void_exec(db, query);
16767
}
16768
};
16769
}
16770
}
16771
16772
// #include "limit_accessor.h"
16773
16774
#include <sqlite3.h>
16775
#include <map> // std::map
16776
#include <functional> // std::function
16777
#include <memory> // std::shared_ptr
16778
16779
// #include "connection_holder.h"
16780
16781
namespace sqlite_orm {
16782
16783
namespace internal {
16784
16785
struct limit_accessor {
16786
using get_connection_t = std::function<connection_ref()>;
16787
16788
limit_accessor(get_connection_t get_connection_) : get_connection(std::move(get_connection_)) {}
16789
16790
int length() {
16791
return this->get(SQLITE_LIMIT_LENGTH);
16792
}
16793
16794
void length(int newValue) {
16795
this->set(SQLITE_LIMIT_LENGTH, newValue);
16796
}
16797
16798
int sql_length() {
16799
return this->get(SQLITE_LIMIT_SQL_LENGTH);
16800
}
16801
16802
void sql_length(int newValue) {
16803
this->set(SQLITE_LIMIT_SQL_LENGTH, newValue);
16804
}
16805
16806
int column() {
16807
return this->get(SQLITE_LIMIT_COLUMN);
16808
}
16809
16810
void column(int newValue) {
16811
this->set(SQLITE_LIMIT_COLUMN, newValue);
16812
}
16813
16814
int expr_depth() {
16815
return this->get(SQLITE_LIMIT_EXPR_DEPTH);
16816
}
16817
16818
void expr_depth(int newValue) {
16819
this->set(SQLITE_LIMIT_EXPR_DEPTH, newValue);
16820
}
16821
16822
int compound_select() {
16823
return this->get(SQLITE_LIMIT_COMPOUND_SELECT);
16824
}
16825
16826
void compound_select(int newValue) {
16827
this->set(SQLITE_LIMIT_COMPOUND_SELECT, newValue);
16828
}
16829
16830
int vdbe_op() {
16831
return this->get(SQLITE_LIMIT_VDBE_OP);
16832
}
16833
16834
void vdbe_op(int newValue) {
16835
this->set(SQLITE_LIMIT_VDBE_OP, newValue);
16836
}
16837
16838
int function_arg() {
16839
return this->get(SQLITE_LIMIT_FUNCTION_ARG);
16840
}
16841
16842
void function_arg(int newValue) {
16843
this->set(SQLITE_LIMIT_FUNCTION_ARG, newValue);
16844
}
16845
16846
int attached() {
16847
return this->get(SQLITE_LIMIT_ATTACHED);
16848
}
16849
16850
void attached(int newValue) {
16851
this->set(SQLITE_LIMIT_ATTACHED, newValue);
16852
}
16853
16854
int like_pattern_length() {
16855
return this->get(SQLITE_LIMIT_LIKE_PATTERN_LENGTH);
16856
}
16857
16858
void like_pattern_length(int newValue) {
16859
this->set(SQLITE_LIMIT_LIKE_PATTERN_LENGTH, newValue);
16860
}
16861
16862
int variable_number() {
16863
return this->get(SQLITE_LIMIT_VARIABLE_NUMBER);
16864
}
16865
16866
void variable_number(int newValue) {
16867
this->set(SQLITE_LIMIT_VARIABLE_NUMBER, newValue);
16868
}
16869
16870
int trigger_depth() {
16871
return this->get(SQLITE_LIMIT_TRIGGER_DEPTH);
16872
}
16873
16874
void trigger_depth(int newValue) {
16875
this->set(SQLITE_LIMIT_TRIGGER_DEPTH, newValue);
16876
}
16877
16878
#if SQLITE_VERSION_NUMBER >= 3008007
16879
int worker_threads() {
16880
return this->get(SQLITE_LIMIT_WORKER_THREADS);
16881
}
16882
16883
void worker_threads(int newValue) {
16884
this->set(SQLITE_LIMIT_WORKER_THREADS, newValue);
16885
}
16886
#endif
16887
16888
protected:
16889
get_connection_t get_connection;
16890
16891
friend struct storage_base;
16892
16893
/**
16894
* Stores limit set between connections.
16895
*/
16896
std::map<int, int> limits;
16897
16898
int get(int id) {
16899
auto connection = this->get_connection();
16900
return sqlite3_limit(connection.get(), id, -1);
16901
}
16902
16903
void set(int id, int newValue) {
16904
this->limits[id] = newValue;
16905
auto connection = this->get_connection();
16906
sqlite3_limit(connection.get(), id, newValue);
16907
}
16908
};
16909
}
16910
}
16911
16912
// #include "transaction_guard.h"
16913
16914
#include <functional> // std::function
16915
#include <utility> // std::move
16916
16917
// #include "connection_holder.h"
16918
16919
namespace sqlite_orm {
16920
16921
namespace internal {
16922
16923
/**
16924
* Class used as a guard for a transaction. Calls `ROLLBACK` in destructor.
16925
* Has explicit `commit()` and `rollback()` functions. After explicit function is fired
16926
* guard won't do anything in d-tor. Also you can set `commit_on_destroy` to true to
16927
* make it call `COMMIT` on destroy.
16928
*
16929
* Note: The guard's destructor is explicitly marked as potentially throwing,
16930
* so exceptions that occur during commit or rollback are propagated to the caller.
16931
*/
16932
struct transaction_guard_t {
16933
/**
16934
* This is a public lever to tell a guard what it must do in its destructor
16935
* if `gotta_fire` is true
16936
*/
16937
bool commit_on_destroy = false;
16938
16939
transaction_guard_t(connection_ref connection_,
16940
std::function<void()> commit_func_,
16941
std::function<void()> rollback_func_) :
16942
connection(std::move(connection_)), commit_func(std::move(commit_func_)),
16943
rollback_func(std::move(rollback_func_)) {}
16944
16945
transaction_guard_t(transaction_guard_t&& other) :
16946
commit_on_destroy(other.commit_on_destroy), connection(std::move(other.connection)),
16947
commit_func(std::move(other.commit_func)), rollback_func(std::move(other.rollback_func)),
16948
gotta_fire(other.gotta_fire) {
16949
other.gotta_fire = false;
16950
}
16951
16952
~transaction_guard_t() noexcept(false) {
16953
if (this->gotta_fire) {
16954
if (this->commit_on_destroy) {
16955
this->commit_func();
16956
} else {
16957
this->rollback_func();
16958
}
16959
}
16960
}
16961
16962
transaction_guard_t& operator=(transaction_guard_t&&) = delete;
16963
16964
/**
16965
* Call `COMMIT` explicitly. After this call
16966
* guard will not call `COMMIT` or `ROLLBACK`
16967
* in its destructor.
16968
*/
16969
void commit() {
16970
this->gotta_fire = false;
16971
this->commit_func();
16972
}
16973
16974
/**
16975
* Call `ROLLBACK` explicitly. After this call
16976
* guard will not call `COMMIT` or `ROLLBACK`
16977
* in its destructor.
16978
*/
16979
void rollback() {
16980
this->gotta_fire = false;
16981
this->rollback_func();
16982
}
16983
16984
protected:
16985
connection_ref connection;
16986
std::function<void()> commit_func;
16987
std::function<void()> rollback_func;
16988
bool gotta_fire = true;
16989
};
16990
}
16991
}
16992
16993
// #include "row_extractor.h"
16994
16995
// #include "connection_holder.h"
16996
16997
// #include "backup.h"
16998
16999
#include <sqlite3.h>
17000
#include <system_error> // std::system_error
17001
#include <string> // std::string
17002
#include <memory>
17003
#include <utility> // std::move, std::exchange
17004
17005
// #include "error_code.h"
17006
17007
// #include "connection_holder.h"
17008
17009
namespace sqlite_orm {
17010
17011
namespace internal {
17012
17013
/**
17014
* A backup class. Don't construct it as is, call storage.make_backup_from or storage.make_backup_to instead.
17015
* An instance of this class represents a wrapper around sqlite3_backup pointer. Use this class
17016
* to have maximum control on a backup operation. In case you need a single backup in one line you
17017
* can skip creating a backup_t instance and just call storage.backup_from or storage.backup_to function.
17018
*/
17019
struct backup_t {
17020
backup_t(connection_ref to_,
17021
const std::string& zDestName,
17022
connection_ref from_,
17023
const std::string& zSourceName,
17024
std::unique_ptr<connection_holder> holder_) :
17025
handle(sqlite3_backup_init(to_.get(), zDestName.c_str(), from_.get(), zSourceName.c_str())),
17026
holder(std::move(holder_)), to(to_), from(from_) {
17027
if (!this->handle) {
17028
throw std::system_error{orm_error_code::failed_to_init_a_backup};
17029
}
17030
}
17031
17032
backup_t(backup_t&& other) :
17033
handle(std::exchange(other.handle, nullptr)), holder(std::move(other.holder)), to(other.to),
17034
from(other.from) {}
17035
17036
~backup_t() {
17037
if (this->handle) {
17038
(void)sqlite3_backup_finish(this->handle);
17039
}
17040
}
17041
17042
/**
17043
* Calls sqlite3_backup_step with pages argument
17044
*/
17045
int step(int pages) {
17046
return sqlite3_backup_step(this->handle, pages);
17047
}
17048
17049
/**
17050
* Returns sqlite3_backup_remaining result
17051
*/
17052
int remaining() const {
17053
return sqlite3_backup_remaining(this->handle);
17054
}
17055
17056
/**
17057
* Returns sqlite3_backup_pagecount result
17058
*/
17059
int pagecount() const {
17060
return sqlite3_backup_pagecount(this->handle);
17061
}
17062
17063
protected:
17064
sqlite3_backup* handle = nullptr;
17065
std::unique_ptr<connection_holder> holder;
17066
connection_ref to;
17067
connection_ref from;
17068
};
17069
}
17070
}
17071
17072
// #include "function.h"
17073
17074
// #include "values_to_tuple.h"
17075
17076
#include <sqlite3.h>
17077
#include <type_traits> // std::enable_if, std::is_same, std::index_sequence, std::make_index_sequence
17078
#include <tuple> // std::tuple, std::tuple_size, std::tuple_element
17079
17080
// #include "functional/cxx_functional_polyfill.h"
17081
17082
// #include "type_traits.h"
17083
17084
// #include "row_extractor.h"
17085
17086
// #include "arg_values.h"
17087
17088
#include <sqlite3.h>
17089
17090
// #include "row_extractor.h"
17091
17092
namespace sqlite_orm {
17093
17094
/** @short Wrapper around a dynamically typed value object.
17095
*/
17096
struct arg_value {
17097
17098
arg_value() : arg_value(nullptr) {}
17099
17100
arg_value(sqlite3_value* value_) : value(value_) {}
17101
17102
template<class T>
17103
T get() const {
17104
const auto rowExtractor = internal::boxed_value_extractor<T>();
17105
return rowExtractor.extract(this->value);
17106
}
17107
17108
bool is_null() const {
17109
auto type = sqlite3_value_type(this->value);
17110
return type == SQLITE_NULL;
17111
}
17112
17113
bool is_text() const {
17114
auto type = sqlite3_value_type(this->value);
17115
return type == SQLITE_TEXT;
17116
}
17117
17118
bool is_integer() const {
17119
auto type = sqlite3_value_type(this->value);
17120
return type == SQLITE_INTEGER;
17121
}
17122
17123
bool is_float() const {
17124
auto type = sqlite3_value_type(this->value);
17125
return type == SQLITE_FLOAT;
17126
}
17127
17128
bool is_blob() const {
17129
auto type = sqlite3_value_type(this->value);
17130
return type == SQLITE_BLOB;
17131
}
17132
17133
bool empty() const {
17134
return this->value == nullptr;
17135
}
17136
17137
private:
17138
sqlite3_value* value = nullptr;
17139
};
17140
17141
struct arg_values {
17142
17143
struct iterator {
17144
17145
iterator(const arg_values& container_, int index_) :
17146
container(container_), index(index_),
17147
currentValue(index_ < int(container_.size()) ? container_[index_] : arg_value()) {}
17148
17149
iterator& operator++() {
17150
++this->index;
17151
if (this->index < int(this->container.size())) {
17152
this->currentValue = this->container[this->index];
17153
} else {
17154
this->currentValue = {};
17155
}
17156
return *this;
17157
}
17158
17159
iterator operator++(int) {
17160
auto res = *this;
17161
++this->index;
17162
if (this->index < int(this->container.size())) {
17163
this->currentValue = this->container[this->index];
17164
} else {
17165
this->currentValue = {};
17166
}
17167
return res;
17168
}
17169
17170
arg_value operator*() const {
17171
if (this->index < int(this->container.size()) && this->index >= 0) {
17172
return this->currentValue;
17173
} else {
17174
throw std::system_error{orm_error_code::index_is_out_of_bounds};
17175
}
17176
}
17177
17178
arg_value* operator->() const {
17179
return &this->currentValue;
17180
}
17181
17182
bool operator==(const iterator& other) const {
17183
return &other.container == &this->container && other.index == this->index;
17184
}
17185
17186
bool operator!=(const iterator& other) const {
17187
return !(*this == other);
17188
}
17189
17190
private:
17191
const arg_values& container;
17192
int index = 0;
17193
mutable arg_value currentValue;
17194
};
17195
17196
arg_values() : arg_values(0, nullptr) {}
17197
17198
arg_values(int argsCount_, sqlite3_value** values_) : argsCount(argsCount_), values(values_) {}
17199
17200
size_t size() const {
17201
return this->argsCount;
17202
}
17203
17204
bool empty() const {
17205
return 0 == this->argsCount;
17206
}
17207
17208
arg_value operator[](int index) const {
17209
if (index < this->argsCount && index >= 0) {
17210
sqlite3_value* value = this->values[index];
17211
return {value};
17212
} else {
17213
throw std::system_error{orm_error_code::index_is_out_of_bounds};
17214
}
17215
}
17216
17217
arg_value at(int index) const {
17218
return this->operator[](index);
17219
}
17220
17221
iterator begin() const {
17222
return {*this, 0};
17223
}
17224
17225
iterator end() const {
17226
return {*this, this->argsCount};
17227
}
17228
17229
private:
17230
int argsCount = 0;
17231
sqlite3_value** values = nullptr;
17232
};
17233
}
17234
17235
namespace sqlite_orm {
17236
17237
namespace internal {
17238
17239
template<class Tpl>
17240
struct tuple_from_values {
17241
template<class R = Tpl, satisfies_not<std::is_same, R, std::tuple<arg_values>> = true>
17242
R operator()(sqlite3_value** values, int /*argsCount*/) const {
17243
return this->create_from(values, std::make_index_sequence<std::tuple_size<Tpl>::value>{});
17244
}
17245
17246
template<class R = Tpl, satisfies<std::is_same, R, std::tuple<arg_values>> = true>
17247
R operator()(sqlite3_value** values, int argsCount) const {
17248
return {arg_values(argsCount, values)};
17249
}
17250
17251
private:
17252
template<size_t... Idx>
17253
Tpl create_from(sqlite3_value** values, std::index_sequence<Idx...>) const {
17254
return {this->extract<std::tuple_element_t<Idx, Tpl>>(values[Idx])...};
17255
}
17256
17257
template<class T>
17258
T extract(sqlite3_value* value) const {
17259
const auto rowExtractor = boxed_value_extractor<T>();
17260
return rowExtractor.extract(value);
17261
}
17262
};
17263
}
17264
}
17265
17266
// #include "arg_values.h"
17267
17268
// #include "util.h"
17269
17270
// #include "xdestroy_handling.h"
17271
17272
// #include "udf_proxy.h"
17273
17274
#include <sqlite3.h>
17275
#include <cassert> // assert macro
17276
#include <type_traits> // std::true_type, std::false_type
17277
#include <new> // std::bad_alloc
17278
#include <memory> // std::allocator, std::allocator_traits, std::unique_ptr
17279
#include <string> // std::string
17280
#include <functional> // std::function
17281
#include <utility> // std::move, std::pair
17282
17283
// #include "error_code.h"
17284
17285
namespace sqlite_orm {
17286
namespace internal {
17287
/*
17288
* Returns properly allocated memory space for the specified application-defined function object
17289
* paired with an accompanying deallocation function.
17290
*/
17291
template<class UDF>
17292
std::pair<void*, xdestroy_fn_t> preallocate_udf_memory() {
17293
std::allocator<UDF> allocator;
17294
using traits = std::allocator_traits<decltype(allocator)>;
17295
17296
SQLITE_ORM_CONSTEXPR_LAMBDA_CPP17 auto deallocate = [](void* location) noexcept {
17297
std::allocator<UDF> allocator;
17298
using traits = std::allocator_traits<decltype(allocator)>;
17299
traits::deallocate(allocator, (UDF*)location, 1);
17300
};
17301
17302
return {traits::allocate(allocator, 1), deallocate};
17303
}
17304
17305
/*
17306
* Returns a pair of functions to allocate/deallocate properly aligned memory space for the specified application-defined function object.
17307
*/
17308
template<class UDF>
17309
std::pair<void* (*)(), xdestroy_fn_t> obtain_udf_allocator() {
17310
SQLITE_ORM_CONSTEXPR_LAMBDA_CPP17 auto allocate = []() {
17311
std::allocator<UDF> allocator;
17312
using traits = std::allocator_traits<decltype(allocator)>;
17313
return (void*)traits::allocate(allocator, 1);
17314
};
17315
17316
SQLITE_ORM_CONSTEXPR_LAMBDA_CPP17 auto deallocate = [](void* location) noexcept {
17317
std::allocator<UDF> allocator;
17318
using traits = std::allocator_traits<decltype(allocator)>;
17319
traits::deallocate(allocator, (UDF*)location, 1);
17320
};
17321
17322
return {allocate, deallocate};
17323
}
17324
17325
/*
17326
* A deleter that only destroys the application-defined function object.
17327
*/
17328
struct udf_destruct_only_deleter {
17329
template<class UDF>
17330
void operator()(UDF* f) const noexcept {
17331
std::allocator<UDF> allocator;
17332
using traits = std::allocator_traits<decltype(allocator)>;
17333
traits::destroy(allocator, f);
17334
}
17335
};
17336
17337
/*
17338
* Stores type-erased information in relation to an application-defined scalar or aggregate function object:
17339
* - name and argument count
17340
* - function dispatch (step, final)
17341
* - either preallocated memory with a possibly a priori constructed function object [scalar],
17342
* - or memory allocation/deallocation functions [aggregate]
17343
*/
17344
struct udf_proxy {
17345
using sqlite_func_t = void (*)(sqlite3_context* context, int argsCount, sqlite3_value** values);
17346
using final_call_fn_t = void (*)(void* udfHandle, sqlite3_context* context);
17347
using memory_alloc = std::pair<void* (*)() /*allocate*/, xdestroy_fn_t /*deallocate*/>;
17348
using memory_space = std::pair<void* /*udfHandle*/, xdestroy_fn_t /*deallocate*/>;
17349
17350
std::string name;
17351
int argumentsCount;
17352
std::function<void(void* location)> constructAt;
17353
xdestroy_fn_t destroy;
17354
sqlite_func_t func;
17355
final_call_fn_t finalAggregateCall;
17356
17357
// allocator/deallocator function pair for aggregate UDF
17358
const memory_alloc udfAllocator;
17359
// pointer to preallocated memory space for scalar UDF, already constructed by caller if stateless
17360
const memory_space udfMemorySpace;
17361
17362
udf_proxy(std::string name,
17363
int argumentsCount,
17364
std::function<void(void* location)> constructAt,
17365
xdestroy_fn_t destroy,
17366
sqlite_func_t func,
17367
memory_space udfMemorySpace) :
17368
name{std::move(name)}, argumentsCount{argumentsCount}, constructAt{std::move(constructAt)},
17369
destroy{destroy}, func{func}, finalAggregateCall{nullptr}, udfAllocator{},
17370
udfMemorySpace{udfMemorySpace} {}
17371
17372
udf_proxy(std::string name,
17373
int argumentsCount,
17374
std::function<void(void* location)> constructAt,
17375
xdestroy_fn_t destroy,
17376
sqlite_func_t func,
17377
final_call_fn_t finalAggregateCall,
17378
memory_alloc udfAllocator) :
17379
name{std::move(name)}, argumentsCount{argumentsCount}, constructAt{std::move(constructAt)},
17380
destroy{destroy}, func{func}, finalAggregateCall{finalAggregateCall}, udfAllocator{udfAllocator},
17381
udfMemorySpace{} {}
17382
17383
~udf_proxy() {
17384
// destruct
17385
if (/*bool aprioriConstructed = */ !constructAt && destroy) {
17386
destroy(udfMemorySpace.first);
17387
}
17388
// deallocate
17389
if (udfMemorySpace.second) {
17390
udfMemorySpace.second(udfMemorySpace.first);
17391
}
17392
}
17393
17394
udf_proxy(const udf_proxy&) = delete;
17395
udf_proxy& operator=(const udf_proxy&) = delete;
17396
17397
// convenience accessors for better legibility;
17398
// [`friend` is intentional - it ensures that these are core accessors (only found via ADL), yet still be an out-of-class interface]
17399
17400
friend void* preallocated_udf_handle(udf_proxy* proxy) {
17401
return proxy->udfMemorySpace.first;
17402
}
17403
17404
friend void* allocate_udf(udf_proxy* proxy) {
17405
return proxy->udfAllocator.first();
17406
}
17407
17408
friend void deallocate_udf(udf_proxy* proxy, void* udfHandle) {
17409
proxy->udfAllocator.second(udfHandle);
17410
}
17411
};
17412
17413
// safety net of doing a triple check at runtime
17414
inline void assert_args_count(const udf_proxy* proxy, int argsCount) {
17415
assert((proxy->argumentsCount == -1) || (proxy->argumentsCount == argsCount ||
17416
/*check fin call*/ argsCount == -1));
17417
(void)proxy;
17418
(void)argsCount;
17419
}
17420
17421
// safety net of doing a triple check at runtime
17422
inline void proxy_assert_args_count(sqlite3_context* context, int argsCount) {
17423
udf_proxy* proxy;
17424
assert((proxy = static_cast<udf_proxy*>(sqlite3_user_data(context))) != nullptr);
17425
assert_args_count(proxy, argsCount);
17426
(void)context;
17427
}
17428
17429
// note: may throw `std::bad_alloc` in case memory space for the aggregate function object cannot be allocated
17430
inline void* ensure_aggregate_udf(sqlite3_context* context, udf_proxy* proxy, int argsCount) {
17431
// reserve memory for storing a void pointer (which is the `udfHandle`, i.e. address of the aggregate function object)
17432
void* ctxMemory = sqlite3_aggregate_context(context, sizeof(void*));
17433
if (!ctxMemory) SQLITE_ORM_CPP_UNLIKELY {
17434
throw std::bad_alloc();
17435
}
17436
void*& udfHandle = *static_cast<void**>(ctxMemory);
17437
17438
if (udfHandle) SQLITE_ORM_CPP_LIKELY {
17439
return udfHandle;
17440
} else {
17441
assert_args_count(proxy, argsCount);
17442
udfHandle = allocate_udf(proxy);
17443
// Note on the use of the `udfHandle` pointer after the object construction:
17444
// since we only ever cast between void* and UDF* pointer types and
17445
// only use the memory space for one type during the entire lifetime of a proxy,
17446
// we can use `udfHandle` interconvertibly without laundering its provenance.
17447
proxy->constructAt(udfHandle);
17448
return udfHandle;
17449
}
17450
}
17451
17452
inline void delete_aggregate_udf(udf_proxy* proxy, void* udfHandle) {
17453
proxy->destroy(udfHandle);
17454
deallocate_udf(proxy, udfHandle);
17455
}
17456
17457
// Return C pointer to preallocated and a priori constructed UDF
17458
template<class UDF>
17459
inline UDF*
17460
proxy_get_scalar_udf(std::true_type /*is_stateless*/, sqlite3_context* context, int argsCount) noexcept {
17461
proxy_assert_args_count(context, argsCount);
17462
udf_proxy* proxy = static_cast<udf_proxy*>(sqlite3_user_data(context));
17463
return static_cast<UDF*>(preallocated_udf_handle(proxy));
17464
}
17465
17466
// Return unique pointer to newly constructed UDF at preallocated memory space
17467
template<class UDF>
17468
inline auto proxy_get_scalar_udf(std::false_type /*is_stateless*/, sqlite3_context* context, int argsCount) {
17469
proxy_assert_args_count(context, argsCount);
17470
udf_proxy* proxy = static_cast<udf_proxy*>(sqlite3_user_data(context));
17471
// Note on the use of the `udfHandle` pointer after the object construction:
17472
// since we only ever cast between void* and UDF* pointer types and
17473
// only use the memory space for one type during the entire lifetime of a proxy,
17474
// we can use `udfHandle` interconvertibly without laundering its provenance.
17475
proxy->constructAt(preallocated_udf_handle(proxy));
17476
return std::unique_ptr<UDF, xdestroy_fn_t>{static_cast<UDF*>(preallocated_udf_handle(proxy)),
17477
proxy->destroy};
17478
}
17479
17480
// note: may throw `std::bad_alloc` in case memory space for the aggregate function object cannot be allocated
17481
template<class UDF>
17482
inline UDF* proxy_get_aggregate_step_udf(sqlite3_context* context, int argsCount) {
17483
udf_proxy* proxy = static_cast<udf_proxy*>(sqlite3_user_data(context));
17484
void* udfHandle = ensure_aggregate_udf(context, proxy, argsCount);
17485
return static_cast<UDF*>(udfHandle);
17486
}
17487
17488
inline void aggregate_function_final_callback(sqlite3_context* context) {
17489
udf_proxy* proxy = static_cast<udf_proxy*>(sqlite3_user_data(context));
17490
void* udfHandle;
17491
try {
17492
// note: it is possible that the 'step' function was never called
17493
udfHandle = ensure_aggregate_udf(context, proxy, -1);
17494
} catch (const std::bad_alloc&) {
17495
sqlite3_result_error_nomem(context);
17496
return;
17497
}
17498
proxy->finalAggregateCall(udfHandle, context);
17499
delete_aggregate_udf(proxy, udfHandle);
17500
}
17501
}
17502
}
17503
17504
// #include "serializing_util.h"
17505
17506
// #include "table_info.h"
17507
17508
namespace sqlite_orm {
17509
17510
namespace internal {
17511
17512
struct storage_base {
17513
using collating_function = std::function<int(int, const void*, int, const void*)>;
17514
17515
std::function<void(sqlite3*)> on_open;
17516
pragma_t pragma;
17517
limit_accessor limit;
17518
17519
transaction_guard_t transaction_guard() {
17520
this->begin_transaction();
17521
return {this->get_connection(),
17522
std::bind(&storage_base::commit, this),
17523
std::bind(&storage_base::rollback, this)};
17524
}
17525
17526
transaction_guard_t deferred_transaction_guard() {
17527
this->begin_deferred_transaction();
17528
return {this->get_connection(),
17529
std::bind(&storage_base::commit, this),
17530
std::bind(&storage_base::rollback, this)};
17531
}
17532
17533
transaction_guard_t immediate_transaction_guard() {
17534
this->begin_immediate_transaction();
17535
return {this->get_connection(),
17536
std::bind(&storage_base::commit, this),
17537
std::bind(&storage_base::rollback, this)};
17538
}
17539
17540
transaction_guard_t exclusive_transaction_guard() {
17541
this->begin_exclusive_transaction();
17542
return {this->get_connection(),
17543
std::bind(&storage_base::commit, this),
17544
std::bind(&storage_base::rollback, this)};
17545
}
17546
17547
/**
17548
* Drops index with given name.
17549
* Calls `DROP INDEX indexName`.
17550
* More info: https://www.sqlite.org/lang_dropindex.html
17551
*/
17552
void drop_index(const std::string& indexName) {
17553
this->drop_index_internal(indexName, false);
17554
}
17555
17556
/**
17557
* Drops trigger with given name if trigger exists.
17558
* Calls `DROP INDEX IF EXISTS indexName`.
17559
* More info: https://www.sqlite.org/lang_dropindex.html
17560
*/
17561
void drop_index_if_exists(const std::string& indexName) {
17562
this->drop_index_internal(indexName, true);
17563
}
17564
17565
/**
17566
* Drops trigger with given name.
17567
* Calls `DROP TRIGGER triggerName`.
17568
* More info: https://www.sqlite.org/lang_droptrigger.html
17569
*/
17570
void drop_trigger(const std::string& triggerName) {
17571
this->drop_trigger_internal(triggerName, false);
17572
}
17573
17574
/**
17575
* Drops trigger with given name if trigger exists.
17576
* Calls `DROP TRIGGER IF EXISTS triggerName`.
17577
* More info: https://www.sqlite.org/lang_droptrigger.html
17578
*/
17579
void drop_trigger_if_exists(const std::string& triggerName) {
17580
this->drop_trigger_internal(triggerName, true);
17581
}
17582
17583
/**
17584
* `VACUUM` query.
17585
* More info: https://www.sqlite.org/lang_vacuum.html
17586
*/
17587
void vacuum() {
17588
perform_void_exec(this->get_connection().get(), "VACUUM");
17589
}
17590
17591
/**
17592
* Drops table with given name.
17593
* Calls `DROP TABLE tableName`.
17594
* More info: https://www.sqlite.org/lang_droptable.html
17595
*/
17596
void drop_table(const std::string& tableName) {
17597
this->drop_table_internal(this->get_connection().get(), tableName, false);
17598
}
17599
17600
/**
17601
* Drops table with given name if table exists.
17602
* Calls `DROP TABLE IF EXISTS tableName`.
17603
* More info: https://www.sqlite.org/lang_droptable.html
17604
*/
17605
void drop_table_if_exists(const std::string& tableName) {
17606
this->drop_table_internal(this->get_connection().get(), tableName, true);
17607
}
17608
17609
/**
17610
* Rename table named `from` to `to`.
17611
*/
17612
void rename_table(const std::string& from, const std::string& to) {
17613
this->rename_table(this->get_connection().get(), from, to);
17614
}
17615
17616
protected:
17617
void rename_table(sqlite3* db, const std::string& oldName, const std::string& newName) const {
17618
std::stringstream ss;
17619
ss << "ALTER TABLE " << streaming_identifier(oldName) << " RENAME TO " << streaming_identifier(newName)
17620
<< std::flush;
17621
perform_void_exec(db, ss.str());
17622
}
17623
17624
/**
17625
* Checks whether table exists in db. Doesn't check storage itself - works only with actual database.
17626
* Note: table can be not mapped to a storage
17627
* @return true if table with a given name exists in db, false otherwise.
17628
*/
17629
bool table_exists(const std::string& tableName) {
17630
auto con = this->get_connection();
17631
return this->table_exists(con.get(), tableName);
17632
}
17633
17634
bool table_exists(sqlite3* db, const std::string& tableName) const {
17635
bool result = false;
17636
std::stringstream ss;
17637
ss << "SELECT COUNT(*) FROM sqlite_master WHERE type = " << quote_string_literal("table")
17638
<< " AND name = " << quote_string_literal(tableName) << std::flush;
17639
perform_exec(
17640
db,
17641
ss.str(),
17642
[](void* data, int argc, char** argv, char** /*azColName*/) -> int {
17643
auto& res = *(bool*)data;
17644
if (argc) {
17645
res = !!atoi(argv[0]);
17646
}
17647
return 0;
17648
},
17649
&result);
17650
return result;
17651
}
17652
17653
void add_generated_cols(std::vector<const table_xinfo*>& columnsToAdd,
17654
const std::vector<table_xinfo>& storageTableInfo) {
17655
// iterate through storage columns
17656
for (const table_xinfo& storageColumnInfo: storageTableInfo) {
17657
if (storageColumnInfo.hidden) {
17658
columnsToAdd.push_back(&storageColumnInfo);
17659
}
17660
}
17661
}
17662
17663
public:
17664
/**
17665
* sqlite3_changes function.
17666
*/
17667
int changes() {
17668
auto con = this->get_connection();
17669
return sqlite3_changes(con.get());
17670
}
17671
17672
/**
17673
* sqlite3_total_changes function.
17674
*/
17675
int total_changes() {
17676
auto con = this->get_connection();
17677
return sqlite3_total_changes(con.get());
17678
}
17679
17680
int64 last_insert_rowid() {
17681
auto con = this->get_connection();
17682
return sqlite3_last_insert_rowid(con.get());
17683
}
17684
17685
int busy_timeout(int ms) {
17686
auto con = this->get_connection();
17687
return sqlite3_busy_timeout(con.get(), ms);
17688
}
17689
17690
/**
17691
* Returns libsqlite3 version, not sqlite_orm
17692
*/
17693
std::string libversion() {
17694
return sqlite3_libversion();
17695
}
17696
17697
bool transaction(const std::function<bool()>& f) {
17698
auto guard = this->transaction_guard();
17699
return guard.commit_on_destroy = f();
17700
}
17701
17702
std::string current_time() {
17703
auto con = this->get_connection();
17704
return this->current_time(con.get());
17705
}
17706
17707
std::string current_date() {
17708
auto con = this->get_connection();
17709
return this->current_date(con.get());
17710
}
17711
17712
std::string current_timestamp() {
17713
auto con = this->get_connection();
17714
return this->current_timestamp(con.get());
17715
}
17716
17717
#if SQLITE_VERSION_NUMBER >= 3007010
17718
/**
17719
* \fn db_release_memory
17720
* \brief Releases freeable memory of database. It is function can/should be called periodically by
17721
* application, if application has less memory usage constraint. \note sqlite3_db_release_memory added
17722
* in 3.7.10 https://sqlite.org/changes.html
17723
*/
17724
int db_release_memory() {
17725
auto con = this->get_connection();
17726
return sqlite3_db_release_memory(con.get());
17727
}
17728
#endif
17729
17730
/**
17731
* Returns existing permanent table names in database. Doesn't check storage itself - works only with
17732
* actual database.
17733
* @return Returns list of tables in database.
17734
*/
17735
std::vector<std::string> table_names() {
17736
auto con = this->get_connection();
17737
std::vector<std::string> tableNames;
17738
using data_t = std::vector<std::string>;
17739
perform_exec(
17740
con.get(),
17741
"SELECT name FROM sqlite_master WHERE type='table'",
17742
[](void* data, int argc, char** argv, char** /*columnName*/) -> int {
17743
auto& tableNames_ = *(data_t*)data;
17744
for (int i = 0; i < argc; ++i) {
17745
if (argv[i]) {
17746
tableNames_.emplace_back(argv[i]);
17747
}
17748
}
17749
return 0;
17750
},
17751
&tableNames);
17752
tableNames.shrink_to_fit();
17753
return tableNames;
17754
}
17755
17756
/**
17757
* Call it once during storage lifetime to make it keeping its connection opened till dtor call.
17758
* By default if storage is not in-memory it calls `sqlite3_open` only when the connection is really
17759
* needed and closes when it is not needed. This function breaks this rule. In memory storage always
17760
* keeps connection opened so calling this for in-memory storage changes nothing.
17761
* Note about multithreading: in multithreading context avoiding using this function for not in-memory
17762
* storage may lead to data races. If you have data races in such a configuration try to call `open_forever`
17763
* before accessing your storage - it may fix data races.
17764
*/
17765
void open_forever() {
17766
this->isOpenedForever = true;
17767
this->connection->retain();
17768
if (1 == this->connection->retain_count()) {
17769
this->on_open_internal(this->connection->get());
17770
}
17771
}
17772
17773
/**
17774
* Create an application-defined scalar SQL function.
17775
* Can be called at any time no matter whether the database connection is opened or not.
17776
*
17777
* Note: `create_scalar_function()` merely creates a closure to generate an instance of the scalar function object,
17778
* together with a copy of the passed initialization arguments.
17779
* If `F` is a stateless function object, an instance of the function object is created once, otherwise
17780
* an instance of the function object is repeatedly recreated for each result row,
17781
* ensuring that the calculations always start with freshly initialized values.
17782
*
17783
* T - function class. T must have operator() overload and static name function like this:
17784
* ```
17785
* struct SqrtFunction {
17786
*
17787
* double operator()(double arg) const {
17788
* return std::sqrt(arg);
17789
* }
17790
*
17791
* static const char *name() {
17792
* return "SQRT";
17793
* }
17794
* };
17795
* ```
17796
*/
17797
template<class F, class... Args>
17798
void create_scalar_function(Args&&... constructorArgs) {
17799
static_assert(is_scalar_udf_v<F>, "F must be a scalar function");
17800
17801
this->create_scalar_function_impl(
17802
udf_holder<F>{},
17803
#ifdef SQLITE_ORM_PACK_EXPANSION_IN_INIT_CAPTURE_SUPPORTED
17804
/* constructAt */ [... constructorArgs = std::move(constructorArgs)](void* location) {
17805
#else
17806
/* constructAt */
17807
[constructorArgs...](void* location) {
17808
#endif
17809
std::allocator<F> allocator;
17810
using traits = std::allocator_traits<decltype(allocator)>;
17811
traits::construct(allocator, (F*)location, constructorArgs...);
17812
});
17813
}
17814
17815
#ifdef SQLITE_ORM_WITH_CPP20_ALIASES
17816
/**
17817
* Create an application-defined scalar function.
17818
* Can be called at any time no matter whether the database connection is opened or not.
17819
*
17820
* Note: `create_scalar_function()` merely creates a closure to generate an instance of the scalar function object,
17821
* together with a copy of the passed initialization arguments.
17822
* If `F` is a stateless function object, an instance of the function object is created once, otherwise
17823
* an instance of the function object is repeatedly recreated for each result row,
17824
* ensuring that the calculations always start with freshly initialized values.
17825
*/
17826
template<orm_scalar_function auto f, std::copy_constructible... Args>
17827
void create_scalar_function(Args&&... constructorArgs) {
17828
return this->create_scalar_function<auto_udf_type_t<f>>(std::forward<Args>(constructorArgs)...);
17829
}
17830
17831
/**
17832
* Create an application-defined scalar function.
17833
* Can be called at any time no matter whether the database connection is opened or not.
17834
*
17835
* If `quotedF` contains a freestanding function, stateless lambda or stateless function object,
17836
* `quoted_scalar_function::callable()` uses the original function object, assuming it is free of side effects;
17837
* otherwise, it repeatedly uses a copy of the contained function object, assuming possible side effects.
17838
*/
17839
template<orm_quoted_scalar_function auto quotedF>
17840
void create_scalar_function() {
17841
using Sig = auto_udf_type_t<quotedF>;
17842
using args_tuple = typename callable_arguments<Sig>::args_tuple;
17843
using return_type = typename callable_arguments<Sig>::return_type;
17844
constexpr auto argsCount = std::is_same<args_tuple, std::tuple<arg_values>>::value
17845
? -1
17846
: int(std::tuple_size<args_tuple>::value);
17847
this->scalarFunctions.emplace_back(
17848
std::string{quotedF.name()},
17849
argsCount,
17850
/* constructAt = */
17851
nullptr,
17852
/* destroy = */
17853
nullptr,
17854
/* call = */
17855
[](sqlite3_context* context, int argsCount, sqlite3_value** values) {
17856
proxy_assert_args_count(context, argsCount);
17857
args_tuple argsTuple = tuple_from_values<args_tuple>{}(values, argsCount);
17858
auto result = polyfill::apply(quotedF.callable(), std::move(argsTuple));
17859
statement_binder<return_type>().result(context, result);
17860
},
17861
/* finalCall = */
17862
nullptr,
17863
std::pair{nullptr, null_xdestroy_f});
17864
17865
if (this->connection->retain_count() > 0) {
17866
sqlite3* db = this->connection->get();
17867
try_to_create_scalar_function(db, this->scalarFunctions.back());
17868
}
17869
}
17870
#endif
17871
17872
/**
17873
* Create an application-defined aggregate SQL function.
17874
* Can be called at any time no matter whether the database connection is opened or not.
17875
*
17876
* Note: `create_aggregate_function()` merely creates a closure to generate an instance of the aggregate function object,
17877
* together with a copy of the passed initialization arguments.
17878
* An instance of the function object is repeatedly recreated for each result row,
17879
* ensuring that the calculations always start with freshly initialized values.
17880
*
17881
* T - function class. T must have step member function, fin member function and static name function like this:
17882
* ```
17883
* struct MeanFunction {
17884
* double total = 0;
17885
* int count = 0;
17886
*
17887
* void step(double value) {
17888
* total += value;
17889
* ++count;
17890
* }
17891
*
17892
* int fin() const {
17893
* return total / count;
17894
* }
17895
*
17896
* static std::string name() {
17897
* return "MEAN";
17898
* }
17899
* };
17900
* ```
17901
*/
17902
template<class F, class... Args>
17903
void create_aggregate_function(Args&&... constructorArgs) {
17904
static_assert(is_aggregate_udf_v<F>, "F must be an aggregate function");
17905
17906
this->create_aggregate_function_impl(
17907
udf_holder<F>{}, /* constructAt = */
17908
#ifdef SQLITE_ORM_PACK_EXPANSION_IN_INIT_CAPTURE_SUPPORTED
17909
/* constructAt */ [... constructorArgs = std::move(constructorArgs)](void* location) {
17910
#else
17911
/* constructAt */
17912
[constructorArgs...](void* location) {
17913
#endif
17914
std::allocator<F> allocator;
17915
using traits = std::allocator_traits<decltype(allocator)>;
17916
traits::construct(allocator, (F*)location, constructorArgs...);
17917
});
17918
}
17919
17920
#ifdef SQLITE_ORM_WITH_CPP20_ALIASES
17921
/**
17922
* Create an application-defined aggregate function.
17923
* Can be called at any time no matter whether the database connection is opened or not.
17924
*
17925
* Note: `create_aggregate_function()` merely creates a closure to generate an instance of the aggregate function object,
17926
* together with a copy of the passed initialization arguments.
17927
* An instance of the function object is repeatedly recreated for each result row,
17928
* ensuring that the calculations always start with freshly initialized values.
17929
*/
17930
template<orm_aggregate_function auto f, std::copy_constructible... Args>
17931
void create_aggregate_function(Args&&... constructorArgs) {
17932
return this->create_aggregate_function<auto_udf_type_t<f>>(std::forward<Args>(constructorArgs)...);
17933
}
17934
#endif
17935
17936
/**
17937
* Delete a scalar function you created before.
17938
* Can be called at any time no matter whether the database connection is open or not.
17939
*/
17940
template<class F>
17941
void delete_scalar_function() {
17942
static_assert(is_scalar_udf_v<F>, "F must be a scalar function");
17943
udf_holder<F> udfName;
17944
this->delete_function_impl(udfName(), this->scalarFunctions);
17945
}
17946
17947
#ifdef SQLITE_ORM_WITH_CPP20_ALIASES
17948
/**
17949
* Delete a scalar function you created before.
17950
* Can be called at any time no matter whether the database connection is open or not.
17951
*/
17952
template<orm_scalar_function auto f>
17953
void delete_scalar_function() {
17954
this->delete_function_impl(f.name(), this->scalarFunctions);
17955
}
17956
17957
/**
17958
* Delete a quoted scalar function you created before.
17959
* Can be called at any time no matter whether the database connection is open or not.
17960
*/
17961
template<orm_quoted_scalar_function auto quotedF>
17962
void delete_scalar_function() {
17963
this->delete_function_impl(quotedF.name(), this->scalarFunctions);
17964
}
17965
#endif
17966
17967
/**
17968
* Delete aggregate function you created before.
17969
* Can be called at any time no matter whether the database connection is open or not.
17970
*/
17971
template<class F>
17972
void delete_aggregate_function() {
17973
static_assert(is_aggregate_udf_v<F>, "F must be an aggregate function");
17974
udf_holder<F> udfName;
17975
this->delete_function_impl(udfName(), this->aggregateFunctions);
17976
}
17977
17978
#ifdef SQLITE_ORM_WITH_CPP20_ALIASES
17979
template<orm_aggregate_function auto f>
17980
void delete_aggregate_function() {
17981
this->delete_function_impl(f.name(), this->aggregateFunctions);
17982
}
17983
#endif
17984
17985
template<class C>
17986
void create_collation() {
17987
collating_function func = [](int leftLength, const void* lhs, int rightLength, const void* rhs) {
17988
C collatingObject;
17989
return collatingObject(leftLength, lhs, rightLength, rhs);
17990
};
17991
std::stringstream ss;
17992
ss << C::name() << std::flush;
17993
this->create_collation(ss.str(), std::move(func));
17994
}
17995
17996
void create_collation(const std::string& name, collating_function f) {
17997
const auto functionExists = bool(f);
17998
collating_function* function = nullptr;
17999
if (functionExists) {
18000
function = &(collatingFunctions[name] = std::move(f));
18001
}
18002
18003
// create collations if db is open
18004
if (this->connection->retain_count() > 0) {
18005
sqlite3* db = this->connection->get();
18006
int rc = sqlite3_create_collation(db,
18007
name.c_str(),
18008
SQLITE_UTF8,
18009
function,
18010
functionExists ? collate_callback : nullptr);
18011
if (rc != SQLITE_OK) {
18012
throw_translated_sqlite_error(db);
18013
}
18014
}
18015
18016
if (!functionExists) {
18017
collatingFunctions.erase(name);
18018
}
18019
}
18020
18021
template<class C>
18022
void delete_collation() {
18023
std::stringstream ss;
18024
ss << C::name() << std::flush;
18025
this->create_collation(ss.str(), {});
18026
}
18027
18028
void begin_transaction() {
18029
this->begin_transaction_internal("BEGIN TRANSACTION");
18030
}
18031
18032
void begin_deferred_transaction() {
18033
this->begin_transaction_internal("BEGIN DEFERRED TRANSACTION");
18034
}
18035
18036
void begin_immediate_transaction() {
18037
this->begin_transaction_internal("BEGIN IMMEDIATE TRANSACTION");
18038
}
18039
18040
void begin_exclusive_transaction() {
18041
this->begin_transaction_internal("BEGIN EXCLUSIVE TRANSACTION");
18042
}
18043
18044
void commit() {
18045
sqlite3* db = this->connection->get();
18046
perform_void_exec(db, "COMMIT");
18047
this->connection->release();
18048
if (this->connection->retain_count() < 0) {
18049
throw std::system_error{orm_error_code::no_active_transaction};
18050
}
18051
}
18052
18053
void rollback() {
18054
sqlite3* db = this->connection->get();
18055
perform_void_exec(db, "ROLLBACK");
18056
this->connection->release();
18057
if (this->connection->retain_count() < 0) {
18058
throw std::system_error{orm_error_code::no_active_transaction};
18059
}
18060
}
18061
18062
void backup_to(const std::string& filename) {
18063
auto backup = this->make_backup_to(filename);
18064
backup.step(-1);
18065
}
18066
18067
void backup_to(storage_base& other) {
18068
auto backup = this->make_backup_to(other);
18069
backup.step(-1);
18070
}
18071
18072
void backup_from(const std::string& filename) {
18073
auto backup = this->make_backup_from(filename);
18074
backup.step(-1);
18075
}
18076
18077
void backup_from(storage_base& other) {
18078
auto backup = this->make_backup_from(other);
18079
backup.step(-1);
18080
}
18081
18082
backup_t make_backup_to(const std::string& filename) {
18083
auto holder = std::make_unique<connection_holder>(filename);
18084
connection_ref conRef{*holder};
18085
return {conRef, "main", this->get_connection(), "main", std::move(holder)};
18086
}
18087
18088
backup_t make_backup_to(storage_base& other) {
18089
return {other.get_connection(), "main", this->get_connection(), "main", {}};
18090
}
18091
18092
backup_t make_backup_from(const std::string& filename) {
18093
auto holder = std::make_unique<connection_holder>(filename);
18094
connection_ref conRef{*holder};
18095
return {this->get_connection(), "main", conRef, "main", std::move(holder)};
18096
}
18097
18098
backup_t make_backup_from(storage_base& other) {
18099
return {this->get_connection(), "main", other.get_connection(), "main", {}};
18100
}
18101
18102
const std::string& filename() const {
18103
return this->connection->filename;
18104
}
18105
18106
/**
18107
* Checks whether connection to database is opened right now.
18108
* Returns always `true` for in memory databases.
18109
*/
18110
bool is_opened() const {
18111
return this->connection->retain_count() > 0;
18112
}
18113
18114
/*
18115
* returning false when there is a transaction in place
18116
* otherwise true; function is not const because it has to call get_connection()
18117
*/
18118
bool get_autocommit() {
18119
auto con = this->get_connection();
18120
return sqlite3_get_autocommit(con.get());
18121
}
18122
18123
int busy_handler(std::function<int(int)> handler) {
18124
_busy_handler = std::move(handler);
18125
if (this->is_opened()) {
18126
if (_busy_handler) {
18127
return sqlite3_busy_handler(this->connection->get(), busy_handler_callback, this);
18128
} else {
18129
return sqlite3_busy_handler(this->connection->get(), nullptr, nullptr);
18130
}
18131
} else {
18132
return SQLITE_OK;
18133
}
18134
}
18135
18136
protected:
18137
storage_base(std::string filename, int foreignKeysCount) :
18138
pragma(std::bind(&storage_base::get_connection, this)),
18139
limit(std::bind(&storage_base::get_connection, this)),
18140
inMemory(filename.empty() || filename == ":memory:"),
18141
connection(std::make_unique<connection_holder>(std::move(filename))),
18142
cachedForeignKeysCount(foreignKeysCount) {
18143
if (this->inMemory) {
18144
this->connection->retain();
18145
this->on_open_internal(this->connection->get());
18146
}
18147
}
18148
18149
storage_base(const storage_base& other) :
18150
on_open(other.on_open), pragma(std::bind(&storage_base::get_connection, this)),
18151
limit(std::bind(&storage_base::get_connection, this)), inMemory(other.inMemory),
18152
connection(std::make_unique<connection_holder>(other.connection->filename)),
18153
cachedForeignKeysCount(other.cachedForeignKeysCount) {
18154
if (this->inMemory) {
18155
this->connection->retain();
18156
this->on_open_internal(this->connection->get());
18157
}
18158
}
18159
18160
~storage_base() {
18161
if (this->isOpenedForever) {
18162
this->connection->release();
18163
}
18164
if (this->inMemory) {
18165
this->connection->release();
18166
}
18167
}
18168
18169
void begin_transaction_internal(const std::string& query) {
18170
this->connection->retain();
18171
if (1 == this->connection->retain_count()) {
18172
this->on_open_internal(this->connection->get());
18173
}
18174
sqlite3* db = this->connection->get();
18175
perform_void_exec(db, query);
18176
}
18177
18178
connection_ref get_connection() {
18179
connection_ref res{*this->connection};
18180
if (1 == this->connection->retain_count()) {
18181
this->on_open_internal(this->connection->get());
18182
}
18183
return res;
18184
}
18185
18186
#if SQLITE_VERSION_NUMBER >= 3006019
18187
void foreign_keys(sqlite3* db, bool value) {
18188
std::stringstream ss;
18189
ss << "PRAGMA foreign_keys = " << value << std::flush;
18190
perform_void_exec(db, ss.str());
18191
}
18192
18193
bool foreign_keys(sqlite3* db) {
18194
bool result = false;
18195
perform_exec(db, "PRAGMA foreign_keys", extract_single_value<bool>, &result);
18196
return result;
18197
}
18198
18199
#endif
18200
void on_open_internal(sqlite3* db) {
18201
18202
#if SQLITE_VERSION_NUMBER >= 3006019
18203
if (this->cachedForeignKeysCount) {
18204
this->foreign_keys(db, true);
18205
}
18206
#endif
18207
if (this->pragma.synchronous_ != -1) {
18208
this->pragma.synchronous(this->pragma.synchronous_);
18209
}
18210
18211
if (this->pragma.journal_mode_ != -1) {
18212
this->pragma.set_pragma("journal_mode", static_cast<journal_mode>(this->pragma.journal_mode_), db);
18213
}
18214
18215
for (auto& p: this->collatingFunctions) {
18216
int rc = sqlite3_create_collation(db, p.first.c_str(), SQLITE_UTF8, &p.second, collate_callback);
18217
if (rc != SQLITE_OK) {
18218
throw_translated_sqlite_error(db);
18219
}
18220
}
18221
18222
for (auto& p: this->limit.limits) {
18223
sqlite3_limit(db, p.first, p.second);
18224
}
18225
18226
if (_busy_handler) {
18227
sqlite3_busy_handler(this->connection->get(), busy_handler_callback, this);
18228
}
18229
18230
for (auto& udfProxy: this->scalarFunctions) {
18231
try_to_create_scalar_function(db, udfProxy);
18232
}
18233
18234
for (auto& udfProxy: this->aggregateFunctions) {
18235
try_to_create_aggregate_function(db, udfProxy);
18236
}
18237
18238
if (this->on_open) {
18239
this->on_open(db);
18240
}
18241
}
18242
18243
template<class F>
18244
void create_scalar_function_impl(udf_holder<F> udfName, std::function<void(void* location)> constructAt) {
18245
using args_tuple = typename callable_arguments<F>::args_tuple;
18246
using return_type = typename callable_arguments<F>::return_type;
18247
constexpr auto argsCount = std::is_same<args_tuple, std::tuple<arg_values>>::value
18248
? -1
18249
: int(std::tuple_size<args_tuple>::value);
18250
using is_stateless = std::is_empty<F>;
18251
auto udfMemorySpace = preallocate_udf_memory<F>();
18252
if SQLITE_ORM_CONSTEXPR_IF (is_stateless::value) {
18253
constructAt(udfMemorySpace.first);
18254
}
18255
this->scalarFunctions.emplace_back(
18256
udfName(),
18257
argsCount,
18258
is_stateless::value ? nullptr : std::move(constructAt),
18259
/* destroy = */
18260
obtain_xdestroy_for<F>(udf_destruct_only_deleter{}),
18261
/* call = */
18262
[](sqlite3_context* context, int argsCount, sqlite3_value** values) {
18263
auto udfPointer = proxy_get_scalar_udf<F>(is_stateless{}, context, argsCount);
18264
args_tuple argsTuple = tuple_from_values<args_tuple>{}(values, argsCount);
18265
auto result = polyfill::apply(*udfPointer, std::move(argsTuple));
18266
statement_binder<return_type>().result(context, result);
18267
},
18268
udfMemorySpace);
18269
18270
if (this->connection->retain_count() > 0) {
18271
sqlite3* db = this->connection->get();
18272
try_to_create_scalar_function(db, this->scalarFunctions.back());
18273
}
18274
}
18275
18276
template<class F>
18277
void create_aggregate_function_impl(udf_holder<F> udfName,
18278
std::function<void(void* location)> constructAt) {
18279
using args_tuple = typename callable_arguments<F>::args_tuple;
18280
using return_type = typename callable_arguments<F>::return_type;
18281
constexpr auto argsCount = std::is_same<args_tuple, std::tuple<arg_values>>::value
18282
? -1
18283
: int(std::tuple_size<args_tuple>::value);
18284
this->aggregateFunctions.emplace_back(
18285
udfName(),
18286
argsCount,
18287
std::move(constructAt),
18288
/* destroy = */
18289
obtain_xdestroy_for<F>(udf_destruct_only_deleter{}),
18290
/* step = */
18291
[](sqlite3_context* context, int argsCount, sqlite3_value** values) {
18292
F* udfPointer;
18293
try {
18294
udfPointer = proxy_get_aggregate_step_udf<F>(context, argsCount);
18295
} catch (const std::bad_alloc&) {
18296
sqlite3_result_error_nomem(context);
18297
return;
18298
}
18299
args_tuple argsTuple = tuple_from_values<args_tuple>{}(values, argsCount);
18300
#if __cpp_lib_bind_front >= 201907L
18301
std::apply(std::bind_front(&F::step, udfPointer), std::move(argsTuple));
18302
#else
18303
polyfill::apply(
18304
[udfPointer](auto&&... args) {
18305
udfPointer->step(std::forward<decltype(args)>(args)...);
18306
},
18307
std::move(argsTuple));
18308
#endif
18309
},
18310
/* finalCall = */
18311
[](void* udfHandle, sqlite3_context* context) {
18312
F& udf = *static_cast<F*>(udfHandle);
18313
auto result = udf.fin();
18314
statement_binder<return_type>().result(context, result);
18315
},
18316
obtain_udf_allocator<F>());
18317
18318
if (this->connection->retain_count() > 0) {
18319
sqlite3* db = this->connection->get();
18320
try_to_create_aggregate_function(db, this->aggregateFunctions.back());
18321
}
18322
}
18323
18324
void delete_function_impl(const std::string& name, std::list<udf_proxy>& functions) const {
18325
#if __cpp_lib_ranges >= 201911L
18326
auto it = std::ranges::find(functions, name, &udf_proxy::name);
18327
#else
18328
auto it = std::find_if(functions.begin(), functions.end(), [&name](auto& udfProxy) {
18329
return udfProxy.name == name;
18330
});
18331
#endif
18332
if (it != functions.end()) {
18333
if (this->connection->retain_count() > 0) {
18334
sqlite3* db = this->connection->get();
18335
int rc = sqlite3_create_function_v2(db,
18336
name.c_str(),
18337
it->argumentsCount,
18338
SQLITE_UTF8,
18339
nullptr,
18340
nullptr,
18341
nullptr,
18342
nullptr,
18343
nullptr);
18344
if (rc != SQLITE_OK) {
18345
throw_translated_sqlite_error(db);
18346
}
18347
}
18348
it = functions.erase(it);
18349
} else {
18350
throw std::system_error{orm_error_code::function_not_found};
18351
}
18352
}
18353
18354
static void try_to_create_scalar_function(sqlite3* db, udf_proxy& udfProxy) {
18355
int rc = sqlite3_create_function_v2(db,
18356
udfProxy.name.c_str(),
18357
udfProxy.argumentsCount,
18358
SQLITE_UTF8,
18359
&udfProxy,
18360
udfProxy.func,
18361
nullptr,
18362
nullptr,
18363
nullptr);
18364
if (rc != SQLITE_OK) {
18365
throw_translated_sqlite_error(db);
18366
}
18367
}
18368
18369
static void try_to_create_aggregate_function(sqlite3* db, udf_proxy& udfProxy) {
18370
int rc = sqlite3_create_function(db,
18371
udfProxy.name.c_str(),
18372
udfProxy.argumentsCount,
18373
SQLITE_UTF8,
18374
&udfProxy,
18375
nullptr,
18376
udfProxy.func,
18377
aggregate_function_final_callback);
18378
if (rc != SQLITE_OK) {
18379
throw_translated_sqlite_error(rc);
18380
}
18381
}
18382
18383
std::string current_time(sqlite3* db) {
18384
std::string result;
18385
perform_exec(db, "SELECT CURRENT_TIME", extract_single_value<std::string>, &result);
18386
return result;
18387
}
18388
18389
std::string current_date(sqlite3* db) {
18390
std::string result;
18391
perform_exec(db, "SELECT CURRENT_DATE", extract_single_value<std::string>, &result);
18392
return result;
18393
}
18394
18395
std::string current_timestamp(sqlite3* db) {
18396
std::string result;
18397
perform_exec(db, "SELECT CURRENT_TIMESTAMP", extract_single_value<std::string>, &result);
18398
return result;
18399
}
18400
18401
void drop_table_internal(sqlite3* db, const std::string& tableName, bool ifExists) {
18402
std::stringstream ss;
18403
ss << "DROP TABLE";
18404
if (ifExists) {
18405
ss << " IF EXISTS";
18406
}
18407
ss << ' ' << streaming_identifier(tableName) << std::flush;
18408
perform_void_exec(db, ss.str());
18409
}
18410
18411
void drop_index_internal(const std::string& indexName, bool ifExists) {
18412
std::stringstream ss;
18413
ss << "DROP INDEX";
18414
if (ifExists) {
18415
ss << " IF EXISTS";
18416
}
18417
ss << ' ' << quote_identifier(indexName) << std::flush;
18418
perform_void_exec(this->get_connection().get(), ss.str());
18419
}
18420
18421
void drop_trigger_internal(const std::string& triggerName, bool ifExists) {
18422
std::stringstream ss;
18423
ss << "DROP TRIGGER";
18424
if (ifExists) {
18425
ss << " IF EXISTS";
18426
}
18427
ss << ' ' << quote_identifier(triggerName) << std::flush;
18428
perform_void_exec(this->get_connection().get(), ss.str());
18429
}
18430
18431
static int
18432
collate_callback(void* argument, int leftLength, const void* lhs, int rightLength, const void* rhs) {
18433
auto& function = *(collating_function*)argument;
18434
return function(leftLength, lhs, rightLength, rhs);
18435
}
18436
18437
static int busy_handler_callback(void* selfPointer, int triesCount) {
18438
auto& storage = *static_cast<storage_base*>(selfPointer);
18439
if (storage._busy_handler) {
18440
return storage._busy_handler(triesCount);
18441
} else {
18442
return 0;
18443
}
18444
}
18445
18446
bool calculate_remove_add_columns(std::vector<const table_xinfo*>& columnsToAdd,
18447
std::vector<table_xinfo>& storageTableInfo,
18448
std::vector<table_xinfo>& dbTableInfo) const {
18449
bool notEqual = false;
18450
18451
// iterate through storage columns
18452
for (size_t storageColumnInfoIndex = 0; storageColumnInfoIndex < storageTableInfo.size();
18453
++storageColumnInfoIndex) {
18454
18455
// get storage's column info
18456
table_xinfo& storageColumnInfo = storageTableInfo[storageColumnInfoIndex];
18457
const std::string& columnName = storageColumnInfo.name;
18458
18459
// search for a column in db with the same name
18460
#if __cpp_lib_ranges >= 201911L
18461
auto dbColumnInfoIt = std::ranges::find(dbTableInfo, columnName, &table_xinfo::name);
18462
#else
18463
auto dbColumnInfoIt = std::find_if(dbTableInfo.begin(), dbTableInfo.end(), [&columnName](auto& ti) {
18464
return ti.name == columnName;
18465
});
18466
#endif
18467
if (dbColumnInfoIt != dbTableInfo.end()) {
18468
auto& dbColumnInfo = *dbColumnInfoIt;
18469
auto columnsAreEqual =
18470
dbColumnInfo.name == storageColumnInfo.name &&
18471
dbColumnInfo.notnull == storageColumnInfo.notnull &&
18472
(!dbColumnInfo.dflt_value.empty()) == (!storageColumnInfo.dflt_value.empty()) &&
18473
dbColumnInfo.pk == storageColumnInfo.pk &&
18474
(dbColumnInfo.hidden == 0) == (storageColumnInfo.hidden == 0);
18475
if (!columnsAreEqual) {
18476
notEqual = true;
18477
break;
18478
}
18479
dbTableInfo.erase(dbColumnInfoIt);
18480
storageTableInfo.erase(storageTableInfo.begin() +
18481
static_cast<ptrdiff_t>(storageColumnInfoIndex));
18482
--storageColumnInfoIndex;
18483
} else {
18484
columnsToAdd.push_back(&storageColumnInfo);
18485
}
18486
}
18487
return notEqual;
18488
}
18489
18490
const bool inMemory;
18491
bool isOpenedForever = false;
18492
std::unique_ptr<connection_holder> connection;
18493
std::map<std::string, collating_function> collatingFunctions;
18494
const int cachedForeignKeysCount;
18495
std::function<int(int)> _busy_handler;
18496
std::list<udf_proxy> scalarFunctions;
18497
std::list<udf_proxy> aggregateFunctions;
18498
};
18499
}
18500
}
18501
18502
// #include "prepared_statement.h"
18503
18504
// #include "expression_object_type.h"
18505
18506
#include <type_traits> // std::decay, std::remove_reference
18507
#include <functional> // std::reference_wrapper
18508
18509
// #include "type_traits.h"
18510
18511
// #include "prepared_statement.h"
18512
18513
namespace sqlite_orm {
18514
18515
namespace internal {
18516
18517
template<class T, class SFINAE = void>
18518
struct expression_object_type;
18519
18520
template<class T>
18521
using expression_object_type_t = typename expression_object_type<T>::type;
18522
18523
template<typename S>
18524
using statement_object_type_t = expression_object_type_t<expression_type_t<std::remove_reference_t<S>>>;
18525
18526
template<class T>
18527
struct expression_object_type<update_t<T>, void> : value_unref_type<T> {};
18528
18529
template<class T>
18530
struct expression_object_type<replace_t<T>, void> : value_unref_type<T> {};
18531
18532
template<class T>
18533
struct expression_object_type<T, match_if<is_replace_range, T>> {
18534
using type = object_type_t<T>;
18535
};
18536
18537
template<class T, class... Ids>
18538
struct expression_object_type<remove_t<T, Ids...>, void> : value_unref_type<T> {};
18539
18540
template<class T>
18541
struct expression_object_type<insert_t<T>, void> : value_unref_type<T> {};
18542
18543
template<class T>
18544
struct expression_object_type<T, match_if<is_insert_range, T>> {
18545
using type = object_type_t<T>;
18546
};
18547
18548
template<class T, class... Cols>
18549
struct expression_object_type<insert_explicit<T, Cols...>, void> : value_unref_type<T> {};
18550
18551
template<class T>
18552
struct get_ref_t {
18553
18554
template<class O>
18555
auto& operator()(O& t) const {
18556
return t;
18557
}
18558
};
18559
18560
template<class T>
18561
struct get_ref_t<std::reference_wrapper<T>> {
18562
18563
template<class O>
18564
auto& operator()(O& t) const {
18565
return t.get();
18566
}
18567
};
18568
18569
template<class T>
18570
auto& get_ref(T& t) {
18571
using arg_type = std::decay_t<T>;
18572
get_ref_t<arg_type> g;
18573
return g(t);
18574
}
18575
18576
template<class T>
18577
struct get_object_t;
18578
18579
template<class T>
18580
struct get_object_t<const T> : get_object_t<T> {};
18581
18582
template<class T>
18583
auto& get_object(T& t) {
18584
using expression_type = std::decay_t<T>;
18585
get_object_t<expression_type> obj;
18586
return obj(t);
18587
}
18588
18589
template<class T>
18590
struct get_object_t<replace_t<T>> {
18591
using expression_type = replace_t<T>;
18592
18593
template<class O>
18594
auto& operator()(O& e) const {
18595
return get_ref(e.object);
18596
}
18597
};
18598
18599
template<class T>
18600
struct get_object_t<insert_t<T>> {
18601
using expression_type = insert_t<T>;
18602
18603
template<class O>
18604
auto& operator()(O& e) const {
18605
return get_ref(e.object);
18606
}
18607
};
18608
18609
template<class T>
18610
struct get_object_t<update_t<T>> {
18611
using expression_type = update_t<T>;
18612
18613
template<class O>
18614
auto& operator()(O& e) const {
18615
return get_ref(e.object);
18616
}
18617
};
18618
}
18619
}
18620
18621
// #include "statement_serializer.h"
18622
18623
#include <type_traits> // std::enable_if, std::remove_pointer, std::remove_reference, std::remove_cvref, std::disjunction
18624
#include <sstream> // std::stringstream
18625
#include <string> // std::string
18626
#include <vector> // std::vector
18627
#ifndef SQLITE_ORM_OMITS_CODECVT
18628
#include <locale> // std::wstring_convert
18629
#include <codecvt> // std::codecvt_utf8_utf16
18630
#endif
18631
#include <memory>
18632
#include <array>
18633
#include <list> // std::list
18634
// #include "functional/cxx_string_view.h"
18635
18636
// #include "functional/cxx_optional.h"
18637
18638
// #include "functional/cxx_type_traits_polyfill.h"
18639
// std::remove_cvref, std::disjunction
18640
// #include "functional/cxx_functional_polyfill.h"
18641
// std::identity, std::invoke
18642
// #include "functional/mpl.h"
18643
18644
// #include "tuple_helper/tuple_filter.h"
18645
18646
// #include "ast/upsert_clause.h"
18647
18648
// #include "ast/excluded.h"
18649
18650
// #include "ast/group_by.h"
18651
18652
// #include "ast/into.h"
18653
18654
// #include "ast/match.h"
18655
18656
// #include "ast/rank.h"
18657
18658
namespace sqlite_orm {
18659
namespace internal {
18660
struct rank_t {};
18661
}
18662
18663
inline internal::rank_t rank() {
18664
return {};
18665
}
18666
}
18667
18668
// #include "ast/special_keywords.h"
18669
18670
// #include "core_functions.h"
18671
18672
// #include "constraints.h"
18673
18674
// #include "conditions.h"
18675
18676
// #include "indexed_column.h"
18677
18678
// #include "function.h"
18679
18680
// #include "prepared_statement.h"
18681
18682
// #include "rowid.h"
18683
18684
// #include "pointer_value.h"
18685
18686
// #include "type_printer.h"
18687
18688
// #include "field_printer.h"
18689
18690
// #include "literal.h"
18691
18692
// #include "expression.h"
18693
18694
// #include "table_name_collector.h"
18695
18696
// #include "column_names_getter.h"
18697
18698
#include <type_traits> // std::is_base_of
18699
#include <string> // std::string
18700
#include <vector> // std::vector
18701
#include <functional> // std::reference_wrapper
18702
#include <system_error>
18703
#include <utility> // std::move
18704
18705
// #include "tuple_helper/tuple_traits.h"
18706
18707
// #include "tuple_helper/tuple_iteration.h"
18708
18709
// #include "error_code.h"
18710
18711
// #include "mapped_type_proxy.h"
18712
18713
// #include "alias_traits.h"
18714
18715
// #include "select_constraints.h"
18716
18717
// #include "storage_lookup.h"
18718
// pick_table
18719
// #include "serializer_context.h"
18720
18721
// #include "util.h"
18722
18723
namespace sqlite_orm {
18724
18725
namespace internal {
18726
18727
template<class T, class Ctx>
18728
auto serialize(const T& t, const Ctx& context);
18729
18730
template<class T, class Ctx>
18731
std::vector<std::string>& collect_table_column_names(std::vector<std::string>& collectedExpressions,
18732
bool definedOrder,
18733
const Ctx& context) {
18734
if (definedOrder) {
18735
auto& table = pick_table<mapped_type_proxy_t<T>>(context.db_objects);
18736
collectedExpressions.reserve(collectedExpressions.size() + table.template count_of<is_column>());
18737
table.for_each_column([qualified = !context.skip_table_name,
18738
&tableName = table.name,
18739
&collectedExpressions](const column_identifier& column) {
18740
if (is_alias<T>::value) {
18741
collectedExpressions.push_back(quote_identifier(alias_extractor<T>::extract()) + "." +
18742
quote_identifier(column.name));
18743
} else if (qualified) {
18744
collectedExpressions.push_back(quote_identifier(tableName) + "." +
18745
quote_identifier(column.name));
18746
} else {
18747
collectedExpressions.push_back(quote_identifier(column.name));
18748
}
18749
});
18750
} else {
18751
collectedExpressions.reserve(collectedExpressions.size() + 1);
18752
if (is_alias<T>::value) {
18753
collectedExpressions.push_back(quote_identifier(alias_extractor<T>::extract()) + ".*");
18754
} else if (!context.skip_table_name) {
18755
const basic_table& table = pick_table<mapped_type_proxy_t<T>>(context.db_objects);
18756
collectedExpressions.push_back(quote_identifier(table.name) + ".*");
18757
} else {
18758
collectedExpressions.emplace_back("*");
18759
}
18760
}
18761
18762
return collectedExpressions;
18763
}
18764
18765
/** @short Column expression collector.
18766
*/
18767
struct column_names_getter {
18768
/**
18769
* The default implementation simply serializes the passed argument.
18770
*/
18771
template<class E, class Ctx>
18772
std::vector<std::string>& operator()(const E& t, const Ctx& context) {
18773
auto columnExpression = serialize(t, context);
18774
if (columnExpression.empty()) {
18775
throw std::system_error{orm_error_code::column_not_found};
18776
}
18777
this->collectedExpressions.reserve(this->collectedExpressions.size() + 1);
18778
this->collectedExpressions.push_back(std::move(columnExpression));
18779
return this->collectedExpressions;
18780
}
18781
18782
template<class T, class Ctx>
18783
std::vector<std::string>& operator()(const std::reference_wrapper<T>& expression, const Ctx& context) {
18784
return (*this)(expression.get(), context);
18785
}
18786
18787
template<class T, class Ctx>
18788
std::vector<std::string>& operator()(const asterisk_t<T>& expression, const Ctx& context) {
18789
return collect_table_column_names<T>(this->collectedExpressions, expression.defined_order, context);
18790
}
18791
18792
template<class T, class Ctx>
18793
std::vector<std::string>& operator()(const object_t<T>& expression, const Ctx& context) {
18794
return collect_table_column_names<T>(this->collectedExpressions, expression.defined_order, context);
18795
}
18796
18797
template<class... Args, class Ctx>
18798
std::vector<std::string>& operator()(const columns_t<Args...>& cols, const Ctx& context) {
18799
this->collectedExpressions.reserve(this->collectedExpressions.size() + cols.count);
18800
iterate_tuple(cols.columns, [this, &context](auto& colExpr) {
18801
(*this)(colExpr, context);
18802
});
18803
// note: `capacity() > size()` can occur in case `asterisk_t<>` does spell out the columns in defined order
18804
if (tuple_has_template<typename columns_t<Args...>::columns_type, asterisk_t>::value &&
18805
this->collectedExpressions.capacity() > this->collectedExpressions.size()) {
18806
this->collectedExpressions.shrink_to_fit();
18807
}
18808
return this->collectedExpressions;
18809
}
18810
18811
template<class T, class... Args, class Ctx>
18812
std::vector<std::string>& operator()(const struct_t<T, Args...>& cols, const Ctx& context) {
18813
this->collectedExpressions.reserve(this->collectedExpressions.size() + cols.count);
18814
iterate_tuple(cols.columns, [this, &context](auto& colExpr) {
18815
(*this)(colExpr, context);
18816
});
18817
// note: `capacity() > size()` can occur in case `asterisk_t<>` does spell out the columns in defined order
18818
if (tuple_has_template<typename struct_t<T, Args...>::columns_type, asterisk_t>::value &&
18819
this->collectedExpressions.capacity() > this->collectedExpressions.size()) {
18820
this->collectedExpressions.shrink_to_fit();
18821
}
18822
return this->collectedExpressions;
18823
}
18824
18825
std::vector<std::string> collectedExpressions;
18826
};
18827
18828
template<class T, class Ctx>
18829
std::vector<std::string> get_column_names(const T& expression, const Ctx& context) {
18830
column_names_getter serializer;
18831
return serializer(access_column_expression(expression), context);
18832
}
18833
}
18834
}
18835
18836
// #include "cte_column_names_collector.h"
18837
18838
#if (SQLITE_VERSION_NUMBER >= 3008003) && defined(SQLITE_ORM_WITH_CTE)
18839
#include <string>
18840
#include <vector>
18841
#include <functional> // std::reference_wrapper
18842
#include <system_error>
18843
#endif
18844
18845
// #include "functional/cxx_type_traits_polyfill.h"
18846
18847
// #include "type_traits.h"
18848
18849
// #include "member_traits/member_traits.h"
18850
18851
// #include "error_code.h"
18852
18853
// #include "alias.h"
18854
18855
// #include "select_constraints.h"
18856
18857
// #include "serializer_context.h"
18858
18859
#if (SQLITE_VERSION_NUMBER >= 3008003) && defined(SQLITE_ORM_WITH_CTE)
18860
namespace sqlite_orm {
18861
namespace internal {
18862
// collecting column names utilizes the statement serializer
18863
template<class T, class Ctx>
18864
auto serialize(const T& t, const Ctx& context);
18865
18866
inline void unquote_identifier(std::string& identifier) {
18867
if (!identifier.empty()) {
18868
constexpr char quoteChar = '"';
18869
constexpr char sqlEscaped[] = {quoteChar, quoteChar};
18870
identifier.erase(identifier.end() - 1);
18871
identifier.erase(identifier.begin());
18872
for (size_t pos = 0; (pos = identifier.find(sqlEscaped, pos, 2)) != identifier.npos; ++pos) {
18873
identifier.erase(pos, 1);
18874
}
18875
}
18876
}
18877
18878
inline void unquote_or_erase(std::string& name) {
18879
constexpr char quoteChar = '"';
18880
if (name.front() == quoteChar) {
18881
unquote_identifier(name);
18882
} else {
18883
// unaliased expression - see 3. below
18884
name.clear();
18885
}
18886
}
18887
18888
template<class T, class SFINAE = void>
18889
struct cte_column_names_collector {
18890
using expression_type = T;
18891
18892
// Compound statements are never passed in by db_objects_for_expression()
18893
static_assert(!is_compound_operator_v<T>);
18894
18895
template<class Ctx>
18896
std::vector<std::string> operator()(const expression_type& t, const Ctx& context) const {
18897
auto newContext = context;
18898
newContext.skip_table_name = true;
18899
std::string columnName = serialize(t, newContext);
18900
if (columnName.empty()) {
18901
throw std::system_error{orm_error_code::column_not_found};
18902
}
18903
unquote_or_erase(columnName);
18904
return {std::move(columnName)};
18905
}
18906
};
18907
18908
template<class T, class Ctx>
18909
std::vector<std::string> get_cte_column_names(const T& t, const Ctx& context) {
18910
cte_column_names_collector<T> collector;
18911
return collector(access_column_expression(t), context);
18912
}
18913
18914
template<class As>
18915
struct cte_column_names_collector<As, match_specialization_of<As, as_t>> {
18916
using expression_type = As;
18917
18918
template<class Ctx>
18919
std::vector<std::string> operator()(const expression_type& /*expression*/, const Ctx& /*context*/) const {
18920
return {alias_extractor<alias_type_t<As>>::extract()};
18921
}
18922
};
18923
18924
template<class Wrapper>
18925
struct cte_column_names_collector<Wrapper, match_specialization_of<Wrapper, std::reference_wrapper>> {
18926
using expression_type = Wrapper;
18927
18928
template<class Ctx>
18929
std::vector<std::string> operator()(const expression_type& expression, const Ctx& context) const {
18930
return get_cte_column_names(expression.get(), context);
18931
}
18932
};
18933
18934
template<class Asterisk>
18935
struct cte_column_names_collector<Asterisk, match_specialization_of<Asterisk, asterisk_t>> {
18936
using expression_type = Asterisk;
18937
using T = typename Asterisk::type;
18938
18939
template<class Ctx>
18940
std::vector<std::string> operator()(const expression_type&, const Ctx& context) const {
18941
auto& table = pick_table<T>(context.db_objects);
18942
18943
std::vector<std::string> columnNames;
18944
columnNames.reserve(size_t(table.template count_of<is_column>()));
18945
18946
table.for_each_column([&columnNames](const column_identifier& column) {
18947
columnNames.push_back(column.name);
18948
});
18949
return columnNames;
18950
}
18951
};
18952
18953
// No CTE for object expressions.
18954
template<class Object>
18955
struct cte_column_names_collector<Object, match_specialization_of<Object, object_t>> {
18956
static_assert(polyfill::always_false_v<Object>, "Selecting an object in a subselect is not allowed.");
18957
};
18958
18959
// No CTE for object expressions.
18960
template<class Object>
18961
struct cte_column_names_collector<Object, match_if<is_struct, Object>> {
18962
static_assert(polyfill::always_false_v<Object>, "Repacking columns in a subselect is not allowed.");
18963
};
18964
18965
template<class Columns>
18966
struct cte_column_names_collector<Columns, match_specialization_of<Columns, columns_t>> {
18967
using expression_type = Columns;
18968
18969
template<class Ctx>
18970
std::vector<std::string> operator()(const expression_type& cols, const Ctx& context) const {
18971
std::vector<std::string> columnNames;
18972
columnNames.reserve(size_t(cols.count));
18973
auto newContext = context;
18974
newContext.skip_table_name = true;
18975
iterate_tuple(cols.columns, [&columnNames, &newContext](auto& m) {
18976
using value_type = polyfill::remove_cvref_t<decltype(m)>;
18977
18978
if constexpr (polyfill::is_specialization_of_v<value_type, as_t>) {
18979
columnNames.push_back(alias_extractor<alias_type_t<value_type>>::extract());
18980
} else {
18981
std::string columnName = serialize(m, newContext);
18982
if (!columnName.empty()) {
18983
columnNames.push_back(std::move(columnName));
18984
} else {
18985
throw std::system_error{orm_error_code::column_not_found};
18986
}
18987
unquote_or_erase(columnNames.back());
18988
}
18989
});
18990
return columnNames;
18991
}
18992
};
18993
18994
template<typename Ctx, typename E, typename ExplicitColRefs, satisfies_is_specialization_of<E, select_t> = true>
18995
std::vector<std::string>
18996
collect_cte_column_names(const E& sel, const ExplicitColRefs& explicitColRefs, const Ctx& context) {
18997
// 1. determine column names from subselect
18998
std::vector<std::string> columnNames = get_cte_column_names(sel.col, context);
18999
19000
// 2. override column names from cte expression
19001
if (size_t n = std::tuple_size_v<ExplicitColRefs>) {
19002
if (n != columnNames.size()) {
19003
throw std::system_error{orm_error_code::column_not_found};
19004
}
19005
19006
size_t idx = 0;
19007
iterate_tuple(explicitColRefs, [&idx, &columnNames, &context](auto& colRef) {
19008
using ColRef = polyfill::remove_cvref_t<decltype(colRef)>;
19009
19010
if constexpr (polyfill::is_specialization_of_v<ColRef, alias_holder>) {
19011
columnNames[idx] = alias_extractor<type_t<ColRef>>::extract();
19012
} else if constexpr (std::is_member_pointer<ColRef>::value) {
19013
using O = table_type_of_t<ColRef>;
19014
if (auto* columnName = find_column_name<O>(context.db_objects, colRef)) {
19015
columnNames[idx] = *columnName;
19016
} else {
19017
// relaxed: allow any member pointer as column reference
19018
columnNames[idx] = typeid(ColRef).name();
19019
}
19020
} else if constexpr (polyfill::is_specialization_of_v<ColRef, column_t>) {
19021
columnNames[idx] = colRef.name;
19022
} else if constexpr (std::is_same_v<ColRef, std::string>) {
19023
if (!colRef.empty()) {
19024
columnNames[idx] = colRef;
19025
}
19026
} else if constexpr (std::is_same_v<ColRef, polyfill::remove_cvref_t<decltype(std::ignore)>>) {
19027
if (columnNames[idx].empty()) {
19028
columnNames[idx] = std::to_string(idx + 1);
19029
}
19030
} else {
19031
static_assert(polyfill::always_false_v<ColRef>, "Invalid explicit column reference specified");
19032
}
19033
++idx;
19034
});
19035
}
19036
19037
// 3. fill in blanks with numerical column identifiers
19038
{
19039
for (size_t i = 0, n = columnNames.size(); i < n; ++i) {
19040
if (columnNames[i].empty()) {
19041
columnNames[i] = std::to_string(i + 1);
19042
}
19043
}
19044
}
19045
19046
return columnNames;
19047
}
19048
}
19049
}
19050
#endif
19051
19052
// #include "order_by_serializer.h"
19053
19054
#include <string> // std::string
19055
#include <sstream> // std::stringstream
19056
19057
namespace sqlite_orm {
19058
19059
namespace internal {
19060
19061
template<class T, class SFINAE = void>
19062
struct order_by_serializer;
19063
19064
template<class T, class Ctx>
19065
std::string serialize_order_by(const T& t, const Ctx& context) {
19066
order_by_serializer<T> serializer;
19067
return serializer(t, context);
19068
}
19069
19070
template<class O>
19071
struct order_by_serializer<order_by_t<O>, void> {
19072
using statement_type = order_by_t<O>;
19073
19074
template<class Ctx>
19075
std::string operator()(const statement_type& orderBy, const Ctx& context) const {
19076
std::stringstream ss;
19077
auto newContext = context;
19078
newContext.skip_table_name = false;
19079
19080
ss << serialize(orderBy.expression, newContext);
19081
if (!orderBy._collate_argument.empty()) {
19082
ss << " COLLATE " << orderBy._collate_argument;
19083
}
19084
switch (orderBy.asc_desc) {
19085
case 1:
19086
ss << " ASC";
19087
break;
19088
case -1:
19089
ss << " DESC";
19090
break;
19091
}
19092
return ss.str();
19093
}
19094
};
19095
19096
template<class C>
19097
struct order_by_serializer<dynamic_order_by_t<C>, void> {
19098
using statement_type = dynamic_order_by_t<C>;
19099
19100
template<class Ctx>
19101
std::string operator()(const statement_type& orderBy, const Ctx&) const {
19102
std::stringstream ss;
19103
ss << static_cast<std::string>(orderBy) << " ";
19104
int index = 0;
19105
for (const dynamic_order_by_entry_t& entry: orderBy) {
19106
if (index > 0) {
19107
ss << ", ";
19108
}
19109
19110
ss << entry.name;
19111
if (!entry._collate_argument.empty()) {
19112
ss << " COLLATE " << entry._collate_argument;
19113
}
19114
switch (entry.asc_desc) {
19115
case 1:
19116
ss << " ASC";
19117
break;
19118
case -1:
19119
ss << " DESC";
19120
break;
19121
}
19122
++index;
19123
};
19124
return ss.str();
19125
}
19126
};
19127
19128
}
19129
}
19130
19131
// #include "serializing_util.h"
19132
19133
// #include "serialize_result_type.h"
19134
19135
// #include "statement_binder.h"
19136
19137
// #include "values.h"
19138
19139
// #include "table_type_of.h"
19140
19141
// #include "util.h"
19142
19143
// #include "error_code.h"
19144
19145
// #include "schema/triggers.h"
19146
19147
#include <memory>
19148
#include <sstream>
19149
#include <string>
19150
#include <tuple>
19151
19152
// #include "../optional_container.h"
19153
19154
// NOTE Idea : Maybe also implement a custom trigger system to call a c++ callback when a trigger triggers ?
19155
// (Could be implemented with a normal trigger that insert or update an internal table and then retreive
19156
// the event in the C++ code, to call the C++ user callback, with update hooks: https://www.sqlite.org/c3ref/update_hook.html)
19157
// It could be an interesting feature to bring to sqlite_orm that other libraries don't have ?
19158
19159
namespace sqlite_orm {
19160
namespace internal {
19161
enum class trigger_timing { trigger_before, trigger_after, trigger_instead_of };
19162
enum class trigger_type { trigger_delete, trigger_insert, trigger_update };
19163
19164
/**
19165
* This class is an intermediate SQLite trigger, to be used with
19166
* `make_trigger` to create a full trigger.
19167
* T is the base of the trigger (contains its type, timing and associated table)
19168
* S is the list of trigger statements
19169
*/
19170
template<class T, class... S>
19171
struct partial_trigger_t {
19172
using statements_type = std::tuple<S...>;
19173
19174
/**
19175
* Base of the trigger (contains its type, timing and associated table)
19176
*/
19177
T base;
19178
/**
19179
* Statements of the triggers (to be executed when the trigger fires)
19180
*/
19181
statements_type statements;
19182
19183
partial_trigger_t(T trigger_base, S... statements) :
19184
base{std::move(trigger_base)}, statements{std::make_tuple<S...>(std::forward<S>(statements)...)} {}
19185
19186
partial_trigger_t& end() {
19187
return *this;
19188
}
19189
};
19190
19191
struct base_trigger {
19192
/**
19193
* Name of the trigger
19194
*/
19195
std::string name;
19196
};
19197
19198
/**
19199
* This class represent a SQLite trigger
19200
* T is the base of the trigger (contains its type, timing and associated table)
19201
* S is the list of trigger statments
19202
*/
19203
template<class T, class... S>
19204
struct trigger_t : base_trigger {
19205
using object_type = void;
19206
using elements_type = typename partial_trigger_t<T, S...>::statements_type;
19207
19208
/**
19209
* Base of the trigger (contains its type, timing and associated table)
19210
*/
19211
T base;
19212
19213
/**
19214
* Statements of the triggers (to be executed when the trigger fires)
19215
*/
19216
elements_type elements;
19217
19218
#ifndef SQLITE_ORM_AGGREGATE_BASES_SUPPORTED
19219
trigger_t(std::string name, T trigger_base, elements_type statements) :
19220
base_trigger{std::move(name)}, base(std::move(trigger_base)), elements(std::move(statements)) {}
19221
#endif
19222
};
19223
19224
/**
19225
* Base of a trigger. Contains the trigger type/timming and the table type
19226
* T is the table type
19227
* W is `when` expression type
19228
* Type is the trigger base type (type+timing)
19229
*/
19230
template<class T, class W, class Type>
19231
struct trigger_base_t {
19232
using table_type = T;
19233
using when_type = W;
19234
using trigger_type_base = Type;
19235
19236
/**
19237
* Contains the trigger type and timing
19238
*/
19239
trigger_type_base type_base;
19240
/**
19241
* Value used to determine if we execute the trigger on each row or on each statement
19242
* (SQLite doesn't support the FOR EACH STATEMENT syntax yet: https://sqlite.org/lang_createtrigger.html#description
19243
* so this value is more of a placeholder for a later update)
19244
*/
19245
bool do_for_each_row = false;
19246
/**
19247
* When expression (if any)
19248
* If a WHEN expression is specified, the trigger will only execute
19249
* if the expression evaluates to true when the trigger is fired
19250
*/
19251
optional_container<when_type> container_when;
19252
19253
trigger_base_t(trigger_type_base type_base_) : type_base(std::move(type_base_)) {}
19254
19255
trigger_base_t& for_each_row() {
19256
this->do_for_each_row = true;
19257
return *this;
19258
}
19259
19260
template<class WW>
19261
trigger_base_t<T, WW, Type> when(WW expression) {
19262
trigger_base_t<T, WW, Type> res(this->type_base);
19263
res.container_when.field = std::move(expression);
19264
return res;
19265
}
19266
19267
template<class... S>
19268
partial_trigger_t<trigger_base_t<T, W, Type>, S...> begin(S... statements) {
19269
return {*this, std::forward<S>(statements)...};
19270
}
19271
};
19272
19273
/**
19274
* Contains the trigger type and timing
19275
*/
19276
struct trigger_type_base_t {
19277
/**
19278
* Value indicating if the trigger is run BEFORE, AFTER or INSTEAD OF
19279
* the statement that fired it.
19280
*/
19281
trigger_timing timing;
19282
/**
19283
* The type of the statement that would cause the trigger to fire.
19284
* Can be DELETE, INSERT, or UPDATE.
19285
*/
19286
trigger_type type;
19287
19288
trigger_type_base_t(trigger_timing timing, trigger_type type) : timing(timing), type(type) {}
19289
19290
template<class T>
19291
trigger_base_t<T, void, trigger_type_base_t> on() {
19292
return {*this};
19293
}
19294
};
19295
19296
/**
19297
* Special case for UPDATE OF (columns)
19298
* Contains the trigger type and timing
19299
*/
19300
template<class... Cs>
19301
struct trigger_update_type_t : trigger_type_base_t {
19302
using columns_type = std::tuple<Cs...>;
19303
19304
/**
19305
* Contains the columns the trigger is watching. Will only
19306
* trigger if one of theses columns is updated.
19307
*/
19308
columns_type columns;
19309
19310
trigger_update_type_t(trigger_timing timing, trigger_type type, Cs... columns) :
19311
trigger_type_base_t(timing, type), columns(std::make_tuple<Cs...>(std::forward<Cs>(columns)...)) {}
19312
19313
template<class T>
19314
trigger_base_t<T, void, trigger_update_type_t<Cs...>> on() {
19315
return {*this};
19316
}
19317
};
19318
19319
struct trigger_timing_t {
19320
trigger_timing timing;
19321
19322
trigger_type_base_t delete_() {
19323
return {timing, trigger_type::trigger_delete};
19324
}
19325
19326
trigger_type_base_t insert() {
19327
return {timing, trigger_type::trigger_insert};
19328
}
19329
19330
trigger_type_base_t update() {
19331
return {timing, trigger_type::trigger_update};
19332
}
19333
19334
template<class... Cs>
19335
trigger_update_type_t<Cs...> update_of(Cs... columns) {
19336
return {timing, trigger_type::trigger_update, std::forward<Cs>(columns)...};
19337
}
19338
};
19339
19340
struct raise_t {
19341
enum class type_t {
19342
ignore,
19343
rollback,
19344
abort,
19345
fail,
19346
};
19347
19348
type_t type = type_t::ignore;
19349
std::string message;
19350
19351
#ifndef SQLITE_ORM_AGGREGATE_NSDMI_SUPPORTED
19352
raise_t(type_t type, std::string message) : type{type}, message{std::move(message)} {}
19353
#endif
19354
};
19355
19356
template<class T>
19357
struct new_t {
19358
using expression_type = T;
19359
19360
expression_type expression;
19361
};
19362
19363
template<class T>
19364
struct old_t {
19365
using expression_type = T;
19366
19367
expression_type expression;
19368
};
19369
} // NAMESPACE internal
19370
19371
/**
19372
* NEW.expression function used within TRIGGER expressions
19373
*/
19374
template<class T>
19375
internal::new_t<T> new_(T expression) {
19376
return {std::move(expression)};
19377
}
19378
19379
/**
19380
* OLD.expression function used within TRIGGER expressions
19381
*/
19382
template<class T>
19383
internal::old_t<T> old(T expression) {
19384
return {std::move(expression)};
19385
}
19386
19387
/**
19388
* RAISE(IGNORE) expression used within TRIGGER expressions
19389
*/
19390
inline internal::raise_t raise_ignore() {
19391
return {internal::raise_t::type_t::ignore, {}};
19392
}
19393
19394
/**
19395
* RAISE(ROLLBACK, %message%) expression used within TRIGGER expressions
19396
*/
19397
inline internal::raise_t raise_rollback(std::string message) {
19398
return {internal::raise_t::type_t::rollback, std::move(message)};
19399
}
19400
19401
/**
19402
* RAISE(ABORT, %message%) expression used within TRIGGER expressions
19403
*/
19404
inline internal::raise_t raise_abort(std::string message) {
19405
return {internal::raise_t::type_t::abort, std::move(message)};
19406
}
19407
19408
/**
19409
* RAISE(FAIL, %message%) expression used within TRIGGER expressions
19410
*/
19411
inline internal::raise_t raise_fail(std::string message) {
19412
return {internal::raise_t::type_t::fail, std::move(message)};
19413
}
19414
19415
template<class T, class... S>
19416
internal::trigger_t<T, S...> make_trigger(std::string name, const internal::partial_trigger_t<T, S...>& part) {
19417
SQLITE_ORM_CLANG_SUPPRESS_MISSING_BRACES(
19418
return {std::move(name), std::move(part.base), std::move(part.statements)});
19419
}
19420
19421
inline internal::trigger_timing_t before() {
19422
return {internal::trigger_timing::trigger_before};
19423
}
19424
19425
inline internal::trigger_timing_t after() {
19426
return {internal::trigger_timing::trigger_after};
19427
}
19428
19429
inline internal::trigger_timing_t instead_of() {
19430
return {internal::trigger_timing::trigger_instead_of};
19431
}
19432
}
19433
19434
// #include "schema/column.h"
19435
19436
// #include "schema/index.h"
19437
19438
// #include "schema/table.h"
19439
19440
namespace sqlite_orm {
19441
19442
namespace internal {
19443
19444
template<class T, class SFINAE = void>
19445
struct statement_serializer;
19446
19447
template<class T, class Ctx>
19448
auto serialize(const T& t, const Ctx& context) {
19449
statement_serializer<T> serializer;
19450
return serializer(t, context);
19451
}
19452
19453
/**
19454
* Serializer for bindable types.
19455
*/
19456
template<class T>
19457
struct statement_serializer<T, match_if<is_bindable, T>> {
19458
using statement_type = T;
19459
19460
template<class Ctx>
19461
std::string operator()(const T& statement, const Ctx& context) const {
19462
if (context.replace_bindable_with_question) {
19463
return "?";
19464
} else {
19465
return this->do_serialize(statement);
19466
}
19467
}
19468
19469
private:
19470
template<class X,
19471
std::enable_if_t<is_printable<X>::value && !std::is_base_of<std::string, X>::value
19472
#ifndef SQLITE_ORM_OMITS_CODECVT
19473
&& !std::is_base_of<std::wstring, X>::value
19474
#endif
19475
,
19476
bool> = true>
19477
std::string do_serialize(const X& c) const {
19478
static_assert(std::is_same<X, T>::value, "");
19479
19480
// implementation detail: utilizing field_printer
19481
return field_printer<X>{}(c);
19482
}
19483
19484
std::string do_serialize(const std::string& c) const {
19485
// implementation detail: utilizing field_printer
19486
return quote_string_literal(field_printer<std::string>{}(c));
19487
}
19488
19489
std::string do_serialize(const char* c) const {
19490
return quote_string_literal(c);
19491
}
19492
#ifndef SQLITE_ORM_OMITS_CODECVT
19493
std::string do_serialize(const std::wstring& c) const {
19494
// implementation detail: utilizing field_printer
19495
return quote_string_literal(field_printer<std::wstring>{}(c));
19496
}
19497
19498
std::string do_serialize(const wchar_t* c) const {
19499
std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>> converter;
19500
return quote_string_literal(converter.to_bytes(c));
19501
}
19502
#endif
19503
#ifdef SQLITE_ORM_STRING_VIEW_SUPPORTED
19504
std::string do_serialize(const std::string_view& c) const {
19505
return quote_string_literal(std::string(c));
19506
}
19507
#ifndef SQLITE_ORM_OMITS_CODECVT
19508
std::string do_serialize(const std::wstring_view& c) const {
19509
std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>> converter;
19510
return quote_string_literal(converter.to_bytes(c.data(), c.data() + c.size()));
19511
}
19512
#endif
19513
#endif
19514
/**
19515
* Specialization for binary data (std::vector<char>).
19516
*/
19517
std::string do_serialize(const std::vector<char>& t) const {
19518
return quote_blob_literal(field_printer<std::vector<char>>{}(t));
19519
}
19520
19521
#if SQLITE_VERSION_NUMBER >= 3020000
19522
template<class P, class PT, class D>
19523
std::string do_serialize(const pointer_binding<P, PT, D>&) const {
19524
// always serialize null (security reasons)
19525
return field_printer<nullptr_t>{}(nullptr);
19526
}
19527
#endif
19528
};
19529
19530
template<class O, bool WithoutRowId, class... Cs>
19531
struct statement_serializer<table_t<O, WithoutRowId, Cs...>, void> {
19532
using statement_type = table_t<O, WithoutRowId, Cs...>;
19533
19534
template<class Ctx>
19535
std::string operator()(const statement_type& statement, const Ctx& context) {
19536
return this->serialize(statement, context, statement.name);
19537
}
19538
19539
template<class Ctx>
19540
auto serialize(const statement_type& statement, const Ctx& context, const std::string& tableName) {
19541
std::stringstream ss;
19542
ss << "CREATE TABLE " << streaming_identifier(tableName) << " ("
19543
<< streaming_expressions_tuple(statement.elements, context) << ")";
19544
if (statement_type::is_without_rowid_v) {
19545
ss << " WITHOUT ROWID";
19546
}
19547
return ss.str();
19548
}
19549
};
19550
19551
template<>
19552
struct statement_serializer<current_time_t, void> {
19553
using statement_type = current_time_t;
19554
19555
template<class Ctx>
19556
std::string operator()(const statement_type& /*statement*/, const Ctx& /*context*/) {
19557
return "CURRENT_TIME";
19558
}
19559
};
19560
19561
template<>
19562
struct statement_serializer<current_date_t, void> {
19563
using statement_type = current_date_t;
19564
19565
template<class Ctx>
19566
std::string operator()(const statement_type& /*statement*/, const Ctx& /*context*/) {
19567
return "CURRENT_DATE";
19568
}
19569
};
19570
19571
template<>
19572
struct statement_serializer<current_timestamp_t, void> {
19573
using statement_type = current_timestamp_t;
19574
19575
template<class Ctx>
19576
std::string operator()(const statement_type& /*statement*/, const Ctx& /*context*/) {
19577
return "CURRENT_TIMESTAMP";
19578
}
19579
};
19580
19581
template<class T, class X, class Y, class Z>
19582
struct statement_serializer<highlight_t<T, X, Y, Z>, void> {
19583
using statement_type = highlight_t<T, X, Y, Z>;
19584
19585
template<class Ctx>
19586
std::string operator()(const statement_type& statement, const Ctx& context) {
19587
std::stringstream ss;
19588
auto& tableName = lookup_table_name<T>(context.db_objects);
19589
ss << "HIGHLIGHT (" << streaming_identifier(tableName);
19590
ss << ", " << serialize(statement.argument0, context);
19591
ss << ", " << serialize(statement.argument1, context);
19592
ss << ", " << serialize(statement.argument2, context) << ")";
19593
return ss.str();
19594
}
19595
};
19596
19597
/**
19598
* Serializer for literal values.
19599
*/
19600
template<class T>
19601
struct statement_serializer<T, match_specialization_of<T, literal_holder>> {
19602
using statement_type = T;
19603
19604
template<class Ctx>
19605
std::string operator()(const statement_type& literal, const Ctx& context) const {
19606
static_assert(is_bindable_v<type_t<statement_type>>, "A literal value must be also bindable");
19607
19608
Ctx literalCtx = context;
19609
literalCtx.replace_bindable_with_question = false;
19610
statement_serializer<type_t<statement_type>> serializer{};
19611
return serializer(literal.value, literalCtx);
19612
}
19613
};
19614
19615
template<class F, class W>
19616
struct statement_serializer<filtered_aggregate_function<F, W>, void> {
19617
using statement_type = filtered_aggregate_function<F, W>;
19618
19619
template<class Ctx>
19620
std::string operator()(const statement_type& statement, const Ctx& context) {
19621
std::stringstream ss;
19622
ss << serialize(statement.function, context);
19623
ss << " FILTER (WHERE " << serialize(statement.where, context) << ")";
19624
return ss.str();
19625
}
19626
};
19627
19628
template<class T>
19629
struct statement_serializer<excluded_t<T>, void> {
19630
using statement_type = excluded_t<T>;
19631
19632
template<class Ctx>
19633
std::string operator()(const statement_type& statement, const Ctx& context) const {
19634
std::stringstream ss;
19635
ss << "excluded.";
19636
if (auto* columnName = find_column_name(context.db_objects, statement.expression)) {
19637
ss << streaming_identifier(*columnName);
19638
} else {
19639
throw std::system_error{orm_error_code::column_not_found};
19640
}
19641
return ss.str();
19642
}
19643
};
19644
#ifdef SQLITE_ORM_OPTIONAL_SUPPORTED
19645
template<class T>
19646
struct statement_serializer<as_optional_t<T>, void> {
19647
using statement_type = as_optional_t<T>;
19648
19649
template<class Ctx>
19650
std::string operator()(const statement_type& statement, const Ctx& context) const {
19651
return serialize(statement.expression, context);
19652
}
19653
};
19654
#endif // SQLITE_ORM_OPTIONAL_SUPPORTED
19655
template<class T>
19656
struct statement_serializer<std::reference_wrapper<T>, void> {
19657
using statement_type = std::reference_wrapper<T>;
19658
19659
template<class Ctx>
19660
std::string operator()(const statement_type& s, const Ctx& context) const {
19661
return serialize(s.get(), context);
19662
}
19663
};
19664
19665
template<class T>
19666
struct statement_serializer<alias_holder<T>, void> {
19667
using statement_type = alias_holder<T>;
19668
19669
template<class Ctx>
19670
std::string operator()(const statement_type&, const Ctx&) {
19671
std::stringstream ss;
19672
ss << streaming_identifier(T::get());
19673
return ss.str();
19674
}
19675
};
19676
19677
template<class T, class X>
19678
struct statement_serializer<match_t<T, X>, void> {
19679
using statement_type = match_t<T, X>;
19680
19681
template<class Ctx>
19682
std::string operator()(const statement_type& statement, const Ctx& context) const {
19683
auto& table = pick_table<T>(context.db_objects);
19684
std::stringstream ss;
19685
ss << streaming_identifier(table.name) << " MATCH " << serialize(statement.argument, context);
19686
return ss.str();
19687
}
19688
};
19689
19690
template<char... C>
19691
struct statement_serializer<column_alias<C...>, void> {
19692
using statement_type = column_alias<C...>;
19693
19694
template<class Ctx>
19695
std::string operator()(const statement_type&, const Ctx&) {
19696
std::stringstream ss;
19697
ss << streaming_identifier(statement_type::get());
19698
return ss.str();
19699
}
19700
};
19701
19702
template<class T>
19703
struct statement_serializer<T, match_if<is_upsert_clause, T>> {
19704
using statement_type = T;
19705
19706
template<class Ctx>
19707
std::string operator()(const statement_type& statement, const Ctx& context) const {
19708
std::stringstream ss;
19709
ss << "ON CONFLICT";
19710
iterate_tuple(statement.target_args, [&ss, &context](auto& value) {
19711
using value_type = polyfill::remove_cvref_t<decltype(value)>;
19712
auto needParenthesis = std::is_member_pointer<value_type>::value;
19713
ss << ' ';
19714
if (needParenthesis) {
19715
ss << '(';
19716
}
19717
ss << serialize(value, context);
19718
if (needParenthesis) {
19719
ss << ')';
19720
}
19721
});
19722
ss << ' ' << "DO";
19723
if (std::tuple_size<typename statement_type::actions_tuple>::value == 0) {
19724
ss << " NOTHING";
19725
} else {
19726
auto updateContext = context;
19727
updateContext.use_parentheses = false;
19728
ss << " UPDATE " << streaming_actions_tuple(statement.actions, updateContext);
19729
}
19730
return ss.str();
19731
}
19732
};
19733
19734
template<class R, class S, class... Args>
19735
struct statement_serializer<built_in_function_t<R, S, Args...>, void> {
19736
using statement_type = built_in_function_t<R, S, Args...>;
19737
19738
template<class Ctx>
19739
std::string operator()(const statement_type& statement, const Ctx& context) const {
19740
std::stringstream ss;
19741
ss << statement.serialize() << "(" << streaming_expressions_tuple(statement.args, context) << ")";
19742
return ss.str();
19743
}
19744
};
19745
19746
template<class R, class S, class... Args>
19747
struct statement_serializer<built_in_aggregate_function_t<R, S, Args...>, void>
19748
: statement_serializer<built_in_function_t<R, S, Args...>, void> {};
19749
19750
template<class F, class... CallArgs>
19751
struct statement_serializer<function_call<F, CallArgs...>, void> {
19752
using statement_type = function_call<F, CallArgs...>;
19753
19754
template<class Ctx>
19755
std::string operator()(const statement_type& statement, const Ctx& context) const {
19756
std::stringstream ss;
19757
stream_identifier(ss, "", statement.name(), "");
19758
ss << "(" << streaming_expressions_tuple(statement.callArgs, context) << ")";
19759
return ss.str();
19760
}
19761
};
19762
19763
template<class T, class E>
19764
struct statement_serializer<as_t<T, E>, void> {
19765
using statement_type = as_t<T, E>;
19766
19767
template<class Ctx>
19768
std::string operator()(const statement_type& c, const Ctx& context) const {
19769
std::stringstream ss;
19770
ss << serialize(c.expression, context) + " AS " << streaming_identifier(alias_extractor<T>::extract());
19771
return ss.str();
19772
}
19773
};
19774
19775
template<class T, class P>
19776
struct statement_serializer<alias_column_t<T, P>, void> {
19777
using statement_type = alias_column_t<T, P>;
19778
19779
template<class Ctx>
19780
std::string operator()(const statement_type& c, const Ctx& context) const {
19781
std::stringstream ss;
19782
if (!context.skip_table_name) {
19783
ss << streaming_identifier(alias_extractor<T>::extract()) << ".";
19784
}
19785
auto newContext = context;
19786
newContext.skip_table_name = true;
19787
ss << serialize(c.column, newContext);
19788
return ss.str();
19789
}
19790
};
19791
19792
template<class E>
19793
struct statement_serializer<
19794
E,
19795
std::enable_if_t<polyfill::disjunction<std::is_member_pointer<E>, is_column_pointer<E>>::value>> {
19796
using statement_type = E;
19797
19798
template<class Ctx>
19799
std::string operator()(const statement_type& e, const Ctx& context) const {
19800
std::stringstream ss;
19801
if (auto* columnName = find_column_name(context.db_objects, e)) {
19802
ss << streaming_identifier(
19803
!context.skip_table_name ? lookup_table_name<table_type_of_t<E>>(context.db_objects) : "",
19804
*columnName,
19805
"");
19806
} else {
19807
throw std::system_error{orm_error_code::column_not_found};
19808
}
19809
return ss.str();
19810
}
19811
};
19812
19813
template<>
19814
struct statement_serializer<rank_t, void> {
19815
using statement_type = rank_t;
19816
19817
template<class Ctx>
19818
serialize_result_type operator()(const statement_type& /*statement*/, const Ctx&) const {
19819
return "rank";
19820
}
19821
};
19822
19823
template<>
19824
struct statement_serializer<rowid_t, void> {
19825
using statement_type = rowid_t;
19826
19827
template<class Ctx>
19828
std::string operator()(const statement_type& statement, const Ctx&) const {
19829
return static_cast<std::string>(statement);
19830
}
19831
};
19832
19833
template<>
19834
struct statement_serializer<oid_t, void> {
19835
using statement_type = oid_t;
19836
19837
template<class Ctx>
19838
std::string operator()(const statement_type& statement, const Ctx&) const {
19839
return static_cast<std::string>(statement);
19840
}
19841
};
19842
19843
template<>
19844
struct statement_serializer<_rowid_t, void> {
19845
using statement_type = _rowid_t;
19846
19847
template<class Ctx>
19848
std::string operator()(const statement_type& statement, const Ctx&) const {
19849
return static_cast<std::string>(statement);
19850
}
19851
};
19852
19853
template<class O>
19854
struct statement_serializer<table_rowid_t<O>, void> {
19855
using statement_type = table_rowid_t<O>;
19856
19857
template<class Ctx>
19858
std::string operator()(const statement_type& statement, const Ctx& context) const {
19859
std::stringstream ss;
19860
if (!context.skip_table_name) {
19861
ss << streaming_identifier(lookup_table_name<O>(context.db_objects)) << ".";
19862
}
19863
ss << static_cast<std::string>(statement);
19864
return ss.str();
19865
}
19866
};
19867
19868
template<class O>
19869
struct statement_serializer<table_oid_t<O>, void> {
19870
using statement_type = table_oid_t<O>;
19871
19872
template<class Ctx>
19873
std::string operator()(const statement_type& statement, const Ctx& context) const {
19874
std::stringstream ss;
19875
if (!context.skip_table_name) {
19876
ss << streaming_identifier(lookup_table_name<O>(context.db_objects)) << ".";
19877
}
19878
ss << static_cast<std::string>(statement);
19879
return ss.str();
19880
}
19881
};
19882
19883
template<class O>
19884
struct statement_serializer<table__rowid_t<O>, void> {
19885
using statement_type = table__rowid_t<O>;
19886
19887
template<class Ctx>
19888
std::string operator()(const statement_type& statement, const Ctx& context) const {
19889
std::stringstream ss;
19890
if (!context.skip_table_name) {
19891
ss << streaming_identifier(lookup_table_name<O>(context.db_objects)) << ".";
19892
}
19893
ss << static_cast<std::string>(statement);
19894
return ss.str();
19895
}
19896
};
19897
19898
template<class L, class R>
19899
struct statement_serializer<is_equal_with_table_t<L, R>, void> {
19900
using statement_type = is_equal_with_table_t<L, R>;
19901
19902
template<class Ctx>
19903
std::string operator()(const statement_type& statement, const Ctx& context) const {
19904
std::stringstream ss;
19905
const auto tableName = lookup_table_name<L>(context.db_objects);
19906
ss << streaming_identifier(tableName);
19907
ss << " = ";
19908
ss << serialize(statement.rhs, context);
19909
return ss.str();
19910
}
19911
};
19912
19913
template<class T>
19914
struct statement_serializer<count_asterisk_t<T>, void> {
19915
using statement_type = count_asterisk_t<T>;
19916
19917
template<class Ctx>
19918
std::string operator()(const statement_type&, const Ctx& context) const {
19919
return serialize(count_asterisk_without_type{}, context);
19920
}
19921
};
19922
19923
template<>
19924
struct statement_serializer<count_asterisk_without_type, void> {
19925
using statement_type = count_asterisk_without_type;
19926
19927
template<class Ctx>
19928
std::string operator()(const statement_type& c, const Ctx&) const {
19929
std::stringstream ss;
19930
auto functionName = c.serialize();
19931
ss << functionName << "(*)";
19932
return ss.str();
19933
}
19934
};
19935
19936
// note (internal): this is a serializer for the deduplicator in an aggregate function;
19937
// the result set deduplicators in a simple-select are treated by the select serializer.
19938
template<class T>
19939
struct statement_serializer<distinct_t<T>, void> {
19940
using statement_type = distinct_t<T>;
19941
19942
template<class Ctx>
19943
std::string operator()(const statement_type& c, const Ctx& context) const {
19944
// DISTINCT introduces no parentheses
19945
auto subCtx = context;
19946
subCtx.use_parentheses = false;
19947
19948
std::stringstream ss;
19949
auto expr = serialize(c.expression, subCtx);
19950
ss << static_cast<std::string>(c) << " " << expr;
19951
return ss.str();
19952
}
19953
};
19954
19955
template<class T, class E>
19956
struct statement_serializer<cast_t<T, E>, void> {
19957
using statement_type = cast_t<T, E>;
19958
19959
template<class Ctx>
19960
std::string operator()(const statement_type& c, const Ctx& context) const {
19961
std::stringstream ss;
19962
ss << static_cast<std::string>(c) << " (";
19963
ss << serialize(c.expression, context) << " AS " << type_printer<T>().print() << ")";
19964
return ss.str();
19965
}
19966
};
19967
19968
#if (SQLITE_VERSION_NUMBER >= 3008003) && defined(SQLITE_ORM_WITH_CTE)
19969
#if SQLITE_VERSION_NUMBER >= 3035003
19970
#ifdef SQLITE_ORM_WITH_CPP20_ALIASES
19971
template<>
19972
struct statement_serializer<materialized_t, void> {
19973
using statement_type = materialized_t;
19974
19975
template<class Ctx>
19976
std::string_view operator()(const statement_type& /*statement*/, const Ctx& /*context*/) const {
19977
return "MATERIALIZED";
19978
}
19979
};
19980
19981
template<>
19982
struct statement_serializer<not_materialized_t, void> {
19983
using statement_type = not_materialized_t;
19984
19985
template<class Ctx>
19986
std::string_view operator()(const statement_type& /*statement*/, const Ctx& /*context*/) const {
19987
return "NOT MATERIALIZED";
19988
}
19989
};
19990
#endif
19991
#endif
19992
19993
template<class CTE>
19994
struct statement_serializer<CTE, match_specialization_of<CTE, common_table_expression>> {
19995
using statement_type = CTE;
19996
19997
template<class Ctx>
19998
std::string operator()(const statement_type& cte, const Ctx& context) const {
19999
// A CTE always starts a new 'highest level' context
20000
Ctx cteContext = context;
20001
cteContext.use_parentheses = false;
20002
20003
std::stringstream ss;
20004
ss << streaming_identifier(alias_extractor<cte_moniker_type_t<CTE>>::extract());
20005
{
20006
std::vector<std::string> columnNames =
20007
collect_cte_column_names(get_cte_driving_subselect(cte.subselect),
20008
cte.explicitColumns,
20009
context);
20010
ss << '(' << streaming_identifiers(columnNames) << ')';
20011
}
20012
ss << " AS" << streaming_constraints_tuple(cte.hints, context) << " ("
20013
<< serialize(cte.subselect, cteContext) << ')';
20014
return ss.str();
20015
}
20016
};
20017
20018
template<class With>
20019
struct statement_serializer<With, match_specialization_of<With, with_t>> {
20020
using statement_type = With;
20021
20022
template<class Ctx>
20023
std::string operator()(const statement_type& c, const Ctx& context) const {
20024
Ctx tupleContext = context;
20025
tupleContext.use_parentheses = false;
20026
20027
std::stringstream ss;
20028
ss << "WITH";
20029
if (c.recursiveIndicated) {
20030
ss << " RECURSIVE";
20031
}
20032
ss << " " << serialize(c.cte, tupleContext);
20033
ss << " " << serialize(c.expression, context);
20034
return ss.str();
20035
}
20036
};
20037
#endif
20038
20039
template<class T>
20040
struct statement_serializer<T, match_if<is_compound_operator, T>> {
20041
using statement_type = T;
20042
20043
template<class Ctx>
20044
std::string operator()(const statement_type& c, const Ctx& context) const {
20045
std::stringstream ss;
20046
ss << streaming_compound_expressions(c.compound, static_cast<std::string>(c), context);
20047
return ss.str();
20048
}
20049
};
20050
20051
template<class R, class T, class E, class... Args>
20052
struct statement_serializer<simple_case_t<R, T, E, Args...>, void> {
20053
using statement_type = simple_case_t<R, T, E, Args...>;
20054
20055
template<class Ctx>
20056
std::string operator()(const statement_type& c, const Ctx& context) const {
20057
std::stringstream ss;
20058
ss << "CASE ";
20059
c.case_expression.apply([&ss, context](auto& c_) {
20060
ss << serialize(c_, context) << " ";
20061
});
20062
iterate_tuple(c.args, [&ss, context](auto& pair) {
20063
ss << "WHEN " << serialize(pair.first, context) << " ";
20064
ss << "THEN " << serialize(pair.second, context) << " ";
20065
});
20066
c.else_expression.apply([&ss, context](auto& el) {
20067
ss << "ELSE " << serialize(el, context) << " ";
20068
});
20069
ss << "END";
20070
return ss.str();
20071
}
20072
};
20073
20074
template<class T>
20075
struct statement_serializer<is_null_t<T>, void> {
20076
using statement_type = is_null_t<T>;
20077
20078
template<class Ctx>
20079
std::string operator()(const statement_type& c, const Ctx& context) const {
20080
std::stringstream ss;
20081
ss << serialize(c.t, context) << " " << static_cast<std::string>(c);
20082
return ss.str();
20083
}
20084
};
20085
20086
template<class T>
20087
struct statement_serializer<is_not_null_t<T>, void> {
20088
using statement_type = is_not_null_t<T>;
20089
20090
template<class Ctx>
20091
std::string operator()(const statement_type& c, const Ctx& context) const {
20092
std::stringstream ss;
20093
ss << serialize(c.t, context) << " " << static_cast<std::string>(c);
20094
return ss.str();
20095
}
20096
};
20097
20098
template<class T>
20099
struct statement_serializer<
20100
T,
20101
std::enable_if_t<polyfill::disjunction<polyfill::is_specialization_of<T, unary_minus_t>,
20102
polyfill::is_specialization_of<T, bitwise_not_t>>::value>> {
20103
using statement_type = T;
20104
20105
template<class Ctx>
20106
std::string operator()(const statement_type& expression, const Ctx& context) const {
20107
// subqueries should always use parentheses in binary expressions
20108
auto subCtx = context;
20109
subCtx.use_parentheses = true;
20110
// parentheses for sub-trees to ensure the order of precedence
20111
constexpr bool parenthesize = is_binary_condition<typename statement_type::argument_type>::value ||
20112
is_binary_operator<typename statement_type::argument_type>::value;
20113
20114
std::stringstream ss;
20115
ss << expression.serialize();
20116
if SQLITE_ORM_CONSTEXPR_IF (parenthesize) {
20117
ss << "(";
20118
}
20119
ss << serialize(get_from_expression(expression.argument), subCtx);
20120
if SQLITE_ORM_CONSTEXPR_IF (parenthesize) {
20121
ss << ")";
20122
}
20123
return ss.str();
20124
}
20125
};
20126
20127
template<class T>
20128
struct statement_serializer<negated_condition_t<T>, void> {
20129
using statement_type = negated_condition_t<T>;
20130
20131
template<class Ctx>
20132
std::string operator()(const statement_type& expression, const Ctx& context) const {
20133
// subqueries should always use parentheses in binary expressions
20134
auto subCtx = context;
20135
subCtx.use_parentheses = true;
20136
// parentheses for sub-trees to ensure the order of precedence
20137
constexpr bool parenthesize = is_binary_condition<typename statement_type::argument_type>::value ||
20138
is_binary_operator<typename statement_type::argument_type>::value;
20139
20140
std::stringstream ss;
20141
ss << static_cast<std::string>(expression) << " ";
20142
if SQLITE_ORM_CONSTEXPR_IF (parenthesize) {
20143
ss << "(";
20144
}
20145
ss << serialize(get_from_expression(expression.c), subCtx);
20146
if SQLITE_ORM_CONSTEXPR_IF (parenthesize) {
20147
ss << ")";
20148
}
20149
return ss.str();
20150
}
20151
};
20152
20153
template<class T>
20154
struct statement_serializer<
20155
T,
20156
std::enable_if_t<polyfill::disjunction<is_binary_condition<T>, is_binary_operator<T>>::value>> {
20157
using statement_type = T;
20158
20159
template<class Ctx>
20160
std::string operator()(const statement_type& statement, const Ctx& context) const {
20161
// subqueries should always use parentheses in binary expressions
20162
auto subCtx = context;
20163
subCtx.use_parentheses = true;
20164
// parentheses for sub-trees to ensure the order of precedence
20165
constexpr bool parenthesizeLeft = is_binary_condition<left_type_t<statement_type>>::value ||
20166
is_binary_operator<left_type_t<statement_type>>::value;
20167
constexpr bool parenthesizeRight = is_binary_condition<right_type_t<statement_type>>::value ||
20168
is_binary_operator<right_type_t<statement_type>>::value;
20169
20170
std::stringstream ss;
20171
if SQLITE_ORM_CONSTEXPR_IF (parenthesizeLeft) {
20172
ss << "(";
20173
}
20174
ss << serialize(statement.lhs, subCtx);
20175
if SQLITE_ORM_CONSTEXPR_IF (parenthesizeLeft) {
20176
ss << ")";
20177
}
20178
ss << " " << statement.serialize() << " ";
20179
if SQLITE_ORM_CONSTEXPR_IF (parenthesizeRight) {
20180
ss << "(";
20181
}
20182
ss << serialize(statement.rhs, subCtx);
20183
if SQLITE_ORM_CONSTEXPR_IF (parenthesizeRight) {
20184
ss << ")";
20185
}
20186
return ss.str();
20187
}
20188
};
20189
20190
template<class T>
20191
struct statement_serializer<named_collate<T>, void> {
20192
using statement_type = named_collate<T>;
20193
20194
template<class Ctx>
20195
std::string operator()(const statement_type& c, const Ctx& context) const {
20196
auto newContext = context;
20197
newContext.use_parentheses = false;
20198
auto res = serialize(c.expr, newContext);
20199
return res + " " + static_cast<std::string>(c);
20200
}
20201
};
20202
20203
template<class T>
20204
struct statement_serializer<collate_t<T>, void> {
20205
using statement_type = collate_t<T>;
20206
20207
template<class Ctx>
20208
std::string operator()(const statement_type& c, const Ctx& context) const {
20209
auto newContext = context;
20210
newContext.use_parentheses = false;
20211
auto res = serialize(c.expr, newContext);
20212
return res + " " + static_cast<std::string>(c);
20213
}
20214
};
20215
20216
template<class L, class C>
20217
struct statement_serializer<
20218
dynamic_in_t<L, C>,
20219
std::enable_if_t<!polyfill::disjunction<polyfill::is_specialization_of<C, std::vector>,
20220
polyfill::is_specialization_of<C, std::list>>::value>> {
20221
using statement_type = dynamic_in_t<L, C>;
20222
20223
template<class Ctx>
20224
std::string operator()(const statement_type& statement, const Ctx& context) const {
20225
std::stringstream ss;
20226
auto leftString = serialize(statement.left, context);
20227
ss << leftString << " ";
20228
if (!statement.negative) {
20229
ss << "IN";
20230
} else {
20231
ss << "NOT IN";
20232
}
20233
ss << " ";
20234
if (is_compound_operator<C>::value) {
20235
ss << '(';
20236
}
20237
auto newContext = context;
20238
newContext.use_parentheses = true;
20239
ss << serialize(statement.argument, newContext);
20240
if (is_compound_operator<C>::value) {
20241
ss << ')';
20242
}
20243
return ss.str();
20244
}
20245
};
20246
20247
template<class L, class C>
20248
struct statement_serializer<
20249
dynamic_in_t<L, C>,
20250
std::enable_if_t<polyfill::disjunction<polyfill::is_specialization_of<C, std::vector>,
20251
polyfill::is_specialization_of<C, std::list>>::value>> {
20252
using statement_type = dynamic_in_t<L, C>;
20253
20254
template<class Ctx>
20255
std::string operator()(const statement_type& statement, const Ctx& context) const {
20256
std::stringstream ss;
20257
auto leftString = serialize(statement.left, context);
20258
ss << leftString << " ";
20259
if (!statement.negative) {
20260
ss << "IN";
20261
} else {
20262
ss << "NOT IN";
20263
}
20264
ss << " (" << streaming_dynamic_expressions(statement.argument, context) << ")";
20265
return ss.str();
20266
}
20267
};
20268
20269
template<class L, class... Args>
20270
struct statement_serializer<in_t<L, Args...>, void> {
20271
using statement_type = in_t<L, Args...>;
20272
20273
template<class Ctx>
20274
std::string operator()(const statement_type& statement, const Ctx& context) const {
20275
std::stringstream ss;
20276
auto leftString = serialize(statement.left, context);
20277
ss << leftString << " ";
20278
if (!statement.negative) {
20279
ss << "IN";
20280
} else {
20281
ss << "NOT IN";
20282
}
20283
ss << " ";
20284
using args_type = std::tuple<Args...>;
20285
constexpr bool theOnlySelect =
20286
std::tuple_size<args_type>::value == 1 && is_select<std::tuple_element_t<0, args_type>>::value;
20287
if (!theOnlySelect) {
20288
ss << "(";
20289
}
20290
ss << streaming_expressions_tuple(statement.argument, context);
20291
if (!theOnlySelect) {
20292
ss << ")";
20293
}
20294
return ss.str();
20295
}
20296
};
20297
20298
template<class A, class T, class E>
20299
struct statement_serializer<like_t<A, T, E>, void> {
20300
using statement_type = like_t<A, T, E>;
20301
20302
template<class Ctx>
20303
std::string operator()(const statement_type& c, const Ctx& context) const {
20304
std::stringstream ss;
20305
ss << serialize(c.arg, context) << " ";
20306
ss << static_cast<std::string>(c) << " ";
20307
ss << serialize(c.pattern, context);
20308
c.arg3.apply([&ss, &context](auto& value) {
20309
ss << " ESCAPE " << serialize(value, context);
20310
});
20311
return ss.str();
20312
}
20313
};
20314
20315
template<class A, class T>
20316
struct statement_serializer<glob_t<A, T>, void> {
20317
using statement_type = glob_t<A, T>;
20318
20319
template<class Ctx>
20320
std::string operator()(const statement_type& c, const Ctx& context) const {
20321
std::stringstream ss;
20322
ss << serialize(c.arg, context) << " ";
20323
ss << static_cast<std::string>(c) << " ";
20324
ss << serialize(c.pattern, context);
20325
return ss.str();
20326
}
20327
};
20328
20329
template<class A, class T>
20330
struct statement_serializer<between_t<A, T>, void> {
20331
using statement_type = between_t<A, T>;
20332
20333
template<class Ctx>
20334
std::string operator()(const statement_type& c, const Ctx& context) const {
20335
std::stringstream ss;
20336
auto expr = serialize(c.expr, context);
20337
ss << expr << " " << static_cast<std::string>(c) << " ";
20338
ss << serialize(c.b1, context);
20339
ss << " AND ";
20340
ss << serialize(c.b2, context);
20341
return ss.str();
20342
}
20343
};
20344
20345
template<class T>
20346
struct statement_serializer<exists_t<T>, void> {
20347
using statement_type = exists_t<T>;
20348
20349
template<class Ctx>
20350
std::string operator()(const statement_type& statement, const Ctx& context) const {
20351
std::stringstream ss;
20352
auto newContext = context;
20353
newContext.use_parentheses = true;
20354
ss << "EXISTS " << serialize(statement.expression, newContext);
20355
return ss.str();
20356
}
20357
};
20358
20359
template<>
20360
struct statement_serializer<conflict_clause_t, void> {
20361
using statement_type = conflict_clause_t;
20362
20363
template<class Ctx>
20364
serialize_result_type operator()(const statement_type& statement, const Ctx&) const {
20365
switch (statement) {
20366
case conflict_clause_t::rollback:
20367
return "ROLLBACK";
20368
case conflict_clause_t::abort:
20369
return "ABORT";
20370
case conflict_clause_t::fail:
20371
return "FAIL";
20372
case conflict_clause_t::ignore:
20373
return "IGNORE";
20374
case conflict_clause_t::replace:
20375
return "REPLACE";
20376
}
20377
return {};
20378
}
20379
};
20380
20381
template<class PK>
20382
struct statement_serializer<primary_key_with_autoincrement<PK>, void> {
20383
using statement_type = primary_key_with_autoincrement<PK>;
20384
20385
template<class Ctx>
20386
std::string operator()(const statement_type& statement, const Ctx& context) const {
20387
return serialize(statement.as_base(), context) + " AUTOINCREMENT";
20388
}
20389
};
20390
20391
template<>
20392
struct statement_serializer<null_t, void> {
20393
using statement_type = null_t;
20394
20395
template<class Ctx>
20396
serialize_result_type operator()(const statement_type& /*statement*/, const Ctx& /*context*/) const {
20397
return "NULL";
20398
}
20399
};
20400
20401
template<>
20402
struct statement_serializer<not_null_t, void> {
20403
using statement_type = not_null_t;
20404
20405
template<class Ctx>
20406
serialize_result_type operator()(const statement_type& /*statement*/, const Ctx& /*context*/) const {
20407
return "NOT NULL";
20408
}
20409
};
20410
20411
template<class... Cs>
20412
struct statement_serializer<primary_key_t<Cs...>, void> {
20413
using statement_type = primary_key_t<Cs...>;
20414
20415
template<class Ctx>
20416
std::string operator()(const statement_type& statement, const Ctx& context) const {
20417
std::stringstream ss;
20418
ss << "PRIMARY KEY";
20419
switch (statement.options.asc_option) {
20420
case statement_type::order_by::ascending:
20421
ss << " ASC";
20422
break;
20423
case statement_type::order_by::descending:
20424
ss << " DESC";
20425
break;
20426
default:
20427
break;
20428
}
20429
if (statement.options.conflict_clause_is_on) {
20430
ss << " ON CONFLICT " << serialize(statement.options.conflict_clause, context);
20431
}
20432
using columns_tuple = typename statement_type::columns_tuple;
20433
const size_t columnsCount = std::tuple_size<columns_tuple>::value;
20434
if (columnsCount) {
20435
ss << "(" << streaming_mapped_columns_expressions(statement.columns, context) << ")";
20436
}
20437
return ss.str();
20438
}
20439
};
20440
20441
template<class... Args>
20442
struct statement_serializer<unique_t<Args...>, void> {
20443
using statement_type = unique_t<Args...>;
20444
20445
template<class Ctx>
20446
std::string operator()(const statement_type& c, const Ctx& context) const {
20447
std::stringstream ss;
20448
ss << static_cast<std::string>(c);
20449
using columns_tuple = typename statement_type::columns_tuple;
20450
const size_t columnsCount = std::tuple_size<columns_tuple>::value;
20451
if (columnsCount) {
20452
ss << "(" << streaming_mapped_columns_expressions(c.columns, context) << ")";
20453
}
20454
return ss.str();
20455
}
20456
};
20457
20458
#if SQLITE_VERSION_NUMBER >= 3009000
20459
template<>
20460
struct statement_serializer<unindexed_t, void> {
20461
using statement_type = unindexed_t;
20462
20463
template<class Ctx>
20464
serialize_result_type operator()(const statement_type& /*statement*/, const Ctx& /*context*/) const {
20465
return "UNINDEXED";
20466
}
20467
};
20468
20469
template<class T>
20470
struct statement_serializer<prefix_t<T>, void> {
20471
using statement_type = prefix_t<T>;
20472
20473
template<class Ctx>
20474
std::string operator()(const statement_type& statement, const Ctx& context) const {
20475
std::stringstream ss;
20476
ss << "prefix=" << serialize(statement.value, context);
20477
return ss.str();
20478
}
20479
};
20480
20481
template<class T>
20482
struct statement_serializer<tokenize_t<T>, void> {
20483
using statement_type = tokenize_t<T>;
20484
20485
template<class Ctx>
20486
std::string operator()(const statement_type& statement, const Ctx& context) const {
20487
std::stringstream ss;
20488
ss << "tokenize = " << serialize(statement.value, context);
20489
return ss.str();
20490
}
20491
};
20492
20493
template<class T>
20494
struct statement_serializer<content_t<T>, void> {
20495
using statement_type = content_t<T>;
20496
20497
template<class Ctx>
20498
std::string operator()(const statement_type& statement, const Ctx& context) const {
20499
std::stringstream ss;
20500
ss << "content=" << serialize(statement.value, context);
20501
return ss.str();
20502
}
20503
};
20504
20505
template<class T>
20506
struct statement_serializer<table_content_t<T>, void> {
20507
using statement_type = table_content_t<T>;
20508
20509
template<class Ctx>
20510
std::string operator()(const statement_type& /*statement*/, const Ctx& context) const {
20511
using mapped_type = typename statement_type::mapped_type;
20512
20513
auto& table = pick_table<mapped_type>(context.db_objects);
20514
20515
std::stringstream ss;
20516
ss << "content=" << streaming_identifier(table.name);
20517
return ss.str();
20518
}
20519
};
20520
#endif
20521
20522
template<>
20523
struct statement_serializer<collate_constraint_t, void> {
20524
using statement_type = collate_constraint_t;
20525
20526
template<class Ctx>
20527
std::string operator()(const statement_type& statement, const Ctx&) const {
20528
return static_cast<std::string>(statement);
20529
}
20530
};
20531
20532
template<class T>
20533
struct statement_serializer<default_t<T>, void> {
20534
using statement_type = default_t<T>;
20535
20536
template<class Ctx>
20537
std::string operator()(const statement_type& statement, const Ctx& context) const {
20538
return static_cast<std::string>(statement) + " (" + serialize(statement.value, context) + ")";
20539
}
20540
};
20541
20542
#if SQLITE_VERSION_NUMBER >= 3006019
20543
template<class... Cs, class... Rs>
20544
struct statement_serializer<foreign_key_t<std::tuple<Cs...>, std::tuple<Rs...>>, void> {
20545
using statement_type = foreign_key_t<std::tuple<Cs...>, std::tuple<Rs...>>;
20546
20547
template<class Ctx>
20548
std::string operator()(const statement_type& fk, const Ctx& context) const {
20549
std::stringstream ss;
20550
ss << "FOREIGN KEY(" << streaming_mapped_columns_expressions(fk.columns, context) << ") REFERENCES ";
20551
{
20552
using references_type_t = typename statement_type::references_type;
20553
using first_reference_t = std::tuple_element_t<0, references_type_t>;
20554
using first_reference_mapped_type = table_type_of_t<first_reference_t>;
20555
auto refTableName = lookup_table_name<first_reference_mapped_type>(context.db_objects);
20556
ss << streaming_identifier(refTableName);
20557
}
20558
ss << "(" << streaming_mapped_columns_expressions(fk.references, context) << ")";
20559
if (fk.on_update) {
20560
ss << ' ' << static_cast<std::string>(fk.on_update) << " " << fk.on_update._action;
20561
}
20562
if (fk.on_delete) {
20563
ss << ' ' << static_cast<std::string>(fk.on_delete) << " " << fk.on_delete._action;
20564
}
20565
return ss.str();
20566
}
20567
};
20568
#endif
20569
20570
template<class T>
20571
struct statement_serializer<check_t<T>, void> {
20572
using statement_type = check_t<T>;
20573
20574
template<class Ctx>
20575
std::string operator()(const statement_type& statement, const Ctx& context) const {
20576
std::stringstream ss;
20577
ss << "CHECK (" << serialize(statement.expression, context) << ")";
20578
return ss.str();
20579
}
20580
};
20581
#if SQLITE_VERSION_NUMBER >= 3031000
20582
template<class T>
20583
struct statement_serializer<generated_always_t<T>, void> {
20584
using statement_type = generated_always_t<T>;
20585
20586
template<class Ctx>
20587
std::string operator()(const statement_type& statement, const Ctx& context) const {
20588
std::stringstream ss;
20589
if (statement.full) {
20590
ss << "GENERATED ALWAYS ";
20591
}
20592
ss << "AS (";
20593
ss << serialize(statement.expression, context) << ")";
20594
switch (statement.storage) {
20595
case basic_generated_always::storage_type::not_specified:
20596
//..
20597
break;
20598
case basic_generated_always::storage_type::virtual_:
20599
ss << " VIRTUAL";
20600
break;
20601
case basic_generated_always::storage_type::stored:
20602
ss << " STORED";
20603
break;
20604
}
20605
return ss.str();
20606
}
20607
};
20608
#endif
20609
template<class G, class S, class... Op>
20610
struct statement_serializer<column_t<G, S, Op...>, void> {
20611
using statement_type = column_t<G, S, Op...>;
20612
20613
template<class Ctx>
20614
std::string operator()(const statement_type& column, const Ctx& context) const {
20615
std::stringstream ss;
20616
ss << streaming_identifier(column.name);
20617
if (!context.fts5_columns) {
20618
ss << " " << type_printer<field_type_t<column_field<G, S>>>().print();
20619
}
20620
ss << streaming_column_constraints(
20621
call_as_template_base<column_constraints>(polyfill::identity{})(column),
20622
column.is_not_null(),
20623
context);
20624
return ss.str();
20625
}
20626
};
20627
20628
template<class T, class... Args>
20629
struct statement_serializer<remove_all_t<T, Args...>, void> {
20630
using statement_type = remove_all_t<T, Args...>;
20631
20632
template<class Ctx>
20633
std::string operator()(const statement_type& rem, const Ctx& context) const {
20634
auto& table = pick_table<T>(context.db_objects);
20635
20636
std::stringstream ss;
20637
ss << "DELETE FROM " << streaming_identifier(table.name)
20638
<< streaming_conditions_tuple(rem.conditions, context);
20639
return ss.str();
20640
}
20641
};
20642
20643
template<class T>
20644
struct statement_serializer<replace_t<T>, void> {
20645
using statement_type = replace_t<T>;
20646
20647
template<class Ctx>
20648
std::string operator()(const statement_type& statement, const Ctx& context) const {
20649
using object_type = expression_object_type_t<statement_type>;
20650
auto& table = pick_table<object_type>(context.db_objects);
20651
std::stringstream ss;
20652
ss << "REPLACE INTO " << streaming_identifier(table.name) << " ("
20653
<< streaming_non_generated_column_names(table) << ")"
20654
<< " VALUES ("
20655
<< streaming_field_values_excluding(check_if<is_generated_always>{},
20656
empty_callable<std::false_type>, // don't exclude
20657
context,
20658
get_ref(statement.object))
20659
<< ")";
20660
return ss.str();
20661
}
20662
};
20663
20664
template<class T, class... Cols>
20665
struct statement_serializer<insert_explicit<T, Cols...>, void> {
20666
using statement_type = insert_explicit<T, Cols...>;
20667
20668
template<class Ctx>
20669
std::string operator()(const statement_type& ins, const Ctx& context) const {
20670
constexpr size_t colsCount = std::tuple_size<std::tuple<Cols...>>::value;
20671
static_assert(colsCount > 0, "Use insert or replace with 1 argument instead");
20672
using object_type = expression_object_type_t<statement_type>;
20673
auto& table = pick_table<object_type>(context.db_objects);
20674
std::stringstream ss;
20675
ss << "INSERT INTO " << streaming_identifier(table.name) << " ";
20676
ss << "(" << streaming_mapped_columns_expressions(ins.columns.columns, context) << ") "
20677
<< "VALUES (";
20678
iterate_tuple(ins.columns.columns,
20679
[&ss, &context, &object = get_ref(ins.obj), first = true](auto& memberPointer) mutable {
20680
using member_pointer_type = std::remove_reference_t<decltype(memberPointer)>;
20681
static_assert(!is_setter_v<member_pointer_type>,
20682
"Unable to use setter within insert explicit");
20683
20684
static constexpr std::array<const char*, 2> sep = {", ", ""};
20685
ss << sep[std::exchange(first, false)]
20686
<< serialize(polyfill::invoke(memberPointer, object), context);
20687
});
20688
ss << ")";
20689
return ss.str();
20690
}
20691
};
20692
20693
template<class T>
20694
struct statement_serializer<update_t<T>, void> {
20695
using statement_type = update_t<T>;
20696
20697
template<class Ctx>
20698
std::string operator()(const statement_type& statement, const Ctx& context) const {
20699
using object_type = expression_object_type_t<statement_type>;
20700
auto& table = pick_table<object_type>(context.db_objects);
20701
20702
std::stringstream ss;
20703
ss << "UPDATE " << streaming_identifier(table.name) << " SET ";
20704
table.template for_each_column_excluding<mpl::disjunction_fn<is_primary_key, is_generated_always>>(
20705
[&table, &ss, &context, &object = get_ref(statement.object), first = true](auto& column) mutable {
20706
if (exists_in_composite_primary_key(table, column)) {
20707
return;
20708
}
20709
20710
static constexpr std::array<const char*, 2> sep = {", ", ""};
20711
ss << sep[std::exchange(first, false)] << streaming_identifier(column.name) << " = "
20712
<< serialize(polyfill::invoke(column.member_pointer, object), context);
20713
});
20714
ss << " WHERE ";
20715
table.for_each_column(
20716
[&table, &context, &ss, &object = get_ref(statement.object), first = true](auto& column) mutable {
20717
if (!column.template is<is_primary_key>() && !exists_in_composite_primary_key(table, column)) {
20718
return;
20719
}
20720
20721
static constexpr std::array<const char*, 2> sep = {" AND ", ""};
20722
ss << sep[std::exchange(first, false)] << streaming_identifier(column.name) << " = "
20723
<< serialize(polyfill::invoke(column.member_pointer, object), context);
20724
});
20725
return ss.str();
20726
}
20727
};
20728
20729
template<class C>
20730
struct statement_serializer<dynamic_set_t<C>, void> {
20731
using statement_type = dynamic_set_t<C>;
20732
20733
template<class Ctx>
20734
std::string operator()(const statement_type& statement, const Ctx&) const {
20735
std::stringstream ss;
20736
ss << "SET ";
20737
int index = 0;
20738
for (const dynamic_set_entry& entry: statement) {
20739
if (index > 0) {
20740
ss << ", ";
20741
}
20742
ss << entry.serialized_value;
20743
++index;
20744
}
20745
return ss.str();
20746
}
20747
};
20748
20749
template<class... Args>
20750
struct statement_serializer<set_t<Args...>, void> {
20751
using statement_type = set_t<Args...>;
20752
20753
template<class Ctx>
20754
std::string operator()(const statement_type& statement, const Ctx& context) const {
20755
std::stringstream ss;
20756
ss << "SET ";
20757
auto leftContext = context;
20758
leftContext.skip_table_name = true;
20759
iterate_tuple(statement.assigns, [&ss, &context, &leftContext, first = true](auto& value) mutable {
20760
static constexpr std::array<const char*, 2> sep = {", ", ""};
20761
ss << sep[std::exchange(first, false)] << serialize(value.lhs, leftContext) << ' '
20762
<< value.serialize() << ' ' << serialize(value.rhs, context);
20763
});
20764
return ss.str();
20765
}
20766
};
20767
20768
template<class Ctx, class... Args>
20769
std::set<std::pair<std::string, std::string>> collect_table_names(const set_t<Args...>& set, const Ctx& ctx) {
20770
auto collector = make_table_name_collector(ctx.db_objects);
20771
// note: we are only interested in the table name on the left-hand side of the assignment operator expression
20772
iterate_tuple(set.assigns, [&collector](const auto& assignmentOperator) {
20773
iterate_ast(assignmentOperator.lhs, collector);
20774
});
20775
return std::move(collector.table_names);
20776
}
20777
20778
template<class Ctx, class C>
20779
const std::set<std::pair<std::string, std::string>>& collect_table_names(const dynamic_set_t<C>& set,
20780
const Ctx&) {
20781
return set.collector.table_names;
20782
}
20783
20784
template<class Ctx, class T, satisfies<is_select, T> = true>
20785
std::set<std::pair<std::string, std::string>> collect_table_names(const T& sel, const Ctx& ctx) {
20786
auto collector = make_table_name_collector(ctx.db_objects);
20787
iterate_ast(sel, collector);
20788
return std::move(collector.table_names);
20789
}
20790
20791
template<class S, class... Wargs>
20792
struct statement_serializer<update_all_t<S, Wargs...>, void> {
20793
using statement_type = update_all_t<S, Wargs...>;
20794
20795
template<class Ctx>
20796
std::string operator()(const statement_type& statement, const Ctx& context) const {
20797
const auto& tableNames = collect_table_names(statement.set, context);
20798
if (tableNames.empty()) {
20799
throw std::system_error{orm_error_code::no_tables_specified};
20800
}
20801
const std::string& tableName = tableNames.begin()->first;
20802
20803
std::stringstream ss;
20804
ss << "UPDATE " << streaming_identifier(tableName) << ' ' << serialize(statement.set, context)
20805
<< streaming_conditions_tuple(statement.conditions, context);
20806
return ss.str();
20807
}
20808
};
20809
20810
template<class T>
20811
struct statement_serializer<insert_t<T>, void> {
20812
using statement_type = insert_t<T>;
20813
20814
template<class Ctx>
20815
std::string operator()(const statement_type& statement, const Ctx& context) const {
20816
using object_type = expression_object_type_t<statement_type>;
20817
auto& table = pick_table<object_type>(context.db_objects);
20818
using is_without_rowid = typename std::remove_reference_t<decltype(table)>::is_without_rowid;
20819
20820
std::vector<std::reference_wrapper<const std::string>> columnNames;
20821
table.template for_each_column_excluding<
20822
mpl::conjunction<mpl::not_<mpl::always<is_without_rowid>>,
20823
mpl::disjunction_fn<is_primary_key, is_generated_always>>>(
20824
[&table, &columnNames](auto& column) {
20825
if (exists_in_composite_primary_key(table, column)) {
20826
return;
20827
}
20828
20829
columnNames.push_back(cref(column.name));
20830
});
20831
const size_t columnNamesCount = columnNames.size();
20832
20833
std::stringstream ss;
20834
ss << "INSERT INTO " << streaming_identifier(table.name) << " ";
20835
if (columnNamesCount) {
20836
ss << "(" << streaming_identifiers(columnNames) << ")";
20837
} else {
20838
ss << "DEFAULT";
20839
}
20840
ss << " VALUES";
20841
if (columnNamesCount) {
20842
ss << " ("
20843
<< streaming_field_values_excluding(
20844
mpl::conjunction<mpl::not_<mpl::always<is_without_rowid>>,
20845
mpl::disjunction_fn<is_primary_key, is_generated_always>>{},
20846
[&table](auto& column) {
20847
return exists_in_composite_primary_key(table, column);
20848
},
20849
context,
20850
get_ref(statement.object))
20851
<< ")";
20852
}
20853
20854
return ss.str();
20855
}
20856
};
20857
20858
template<class T>
20859
struct statement_serializer<into_t<T>, void> {
20860
using statement_type = into_t<T>;
20861
20862
template<class Ctx>
20863
std::string operator()(const statement_type&, const Ctx& context) const {
20864
auto& table = pick_table<T>(context.db_objects);
20865
20866
std::stringstream ss;
20867
ss << "INTO " << streaming_identifier(table.name);
20868
return ss.str();
20869
}
20870
};
20871
20872
template<class C>
20873
struct statement_serializer<C, std::enable_if_t<polyfill::disjunction<is_columns<C>, is_struct<C>>::value>> {
20874
using statement_type = C;
20875
20876
template<class Ctx>
20877
std::string operator()(const statement_type& statement, const Ctx& context) const {
20878
// subqueries should always use parentheses in column names
20879
auto subCtx = context;
20880
subCtx.use_parentheses = true;
20881
20882
std::stringstream ss;
20883
if (context.use_parentheses) {
20884
ss << '(';
20885
}
20886
ss << streaming_serialized(get_column_names(statement, subCtx));
20887
if (context.use_parentheses) {
20888
ss << ')';
20889
}
20890
return ss.str();
20891
}
20892
};
20893
20894
template<class T>
20895
struct statement_serializer<
20896
T,
20897
std::enable_if_t<polyfill::disjunction<is_insert_raw<T>, is_replace_raw<T>>::value>> {
20898
using statement_type = T;
20899
20900
template<class Ctx>
20901
std::string operator()(const statement_type& statement, const Ctx& context) const {
20902
std::stringstream ss;
20903
if (is_insert_raw<T>::value) {
20904
ss << "INSERT";
20905
} else {
20906
ss << "REPLACE";
20907
}
20908
iterate_tuple(statement.args, [&context, &ss](auto& value) {
20909
using value_type = polyfill::remove_cvref_t<decltype(value)>;
20910
ss << ' ';
20911
if (is_columns<value_type>::value) {
20912
auto newContext = context;
20913
newContext.skip_table_name = true;
20914
newContext.use_parentheses = true;
20915
ss << serialize(value, newContext);
20916
} else if (is_values<value_type>::value || is_select<value_type>::value) {
20917
auto newContext = context;
20918
newContext.use_parentheses = false;
20919
ss << serialize(value, newContext);
20920
} else {
20921
ss << serialize(value, context);
20922
}
20923
});
20924
return ss.str();
20925
}
20926
};
20927
20928
template<class T, class... Ids>
20929
struct statement_serializer<remove_t<T, Ids...>, void> {
20930
using statement_type = remove_t<T, Ids...>;
20931
20932
template<class Ctx>
20933
std::string operator()(const statement_type& statement, const Ctx& context) const {
20934
auto& table = pick_table<T>(context.db_objects);
20935
std::stringstream ss;
20936
ss << "DELETE FROM " << streaming_identifier(table.name) << " "
20937
<< "WHERE ";
20938
std::vector<std::string> idsStrings;
20939
idsStrings.reserve(std::tuple_size<typename statement_type::ids_type>::value);
20940
iterate_tuple(statement.ids, [&idsStrings, &context](auto& idValue) {
20941
idsStrings.push_back(serialize(idValue, context));
20942
});
20943
table.for_each_primary_key_column([&table, &ss, &idsStrings, index = 0](auto& memberPointer) mutable {
20944
auto* columnName = table.find_column_name(memberPointer);
20945
if (!columnName) {
20946
throw std::system_error{orm_error_code::column_not_found};
20947
}
20948
20949
static constexpr std::array<const char*, 2> sep = {" AND ", ""};
20950
ss << sep[index == 0] << streaming_identifier(*columnName) << " = " << idsStrings[index];
20951
++index;
20952
});
20953
return ss.str();
20954
}
20955
};
20956
20957
template<class It, class L, class O>
20958
struct statement_serializer<replace_range_t<It, L, O>, void> {
20959
using statement_type = replace_range_t<It, L, O>;
20960
20961
template<class Ctx>
20962
std::string operator()(const statement_type& rep, const Ctx& context) const {
20963
using object_type = expression_object_type_t<statement_type>;
20964
auto& table = pick_table<object_type>(context.db_objects);
20965
20966
std::stringstream ss;
20967
ss << "REPLACE INTO " << streaming_identifier(table.name) << " ("
20968
<< streaming_non_generated_column_names(table) << ")";
20969
const auto valuesCount = std::distance(rep.range.first, rep.range.second);
20970
const auto columnsCount = table.template count_of_columns_excluding<is_generated_always>();
20971
ss << " VALUES " << streaming_values_placeholders(columnsCount, valuesCount);
20972
return ss.str();
20973
}
20974
};
20975
20976
template<class It, class L, class O>
20977
struct statement_serializer<insert_range_t<It, L, O>, void> {
20978
using statement_type = insert_range_t<It, L, O>;
20979
20980
template<class Ctx>
20981
std::string operator()(const statement_type& statement, const Ctx& context) const {
20982
using object_type = expression_object_type_t<statement_type>;
20983
auto& table = pick_table<object_type>(context.db_objects);
20984
using is_without_rowid = typename std::remove_reference_t<decltype(table)>::is_without_rowid;
20985
20986
std::vector<std::reference_wrapper<const std::string>> columnNames;
20987
table.template for_each_column_excluding<
20988
mpl::conjunction<mpl::not_<mpl::always<is_without_rowid>>,
20989
mpl::disjunction_fn<is_primary_key, is_generated_always>>>(
20990
[&table, &columnNames](auto& column) {
20991
if (exists_in_composite_primary_key(table, column)) {
20992
return;
20993
}
20994
20995
columnNames.push_back(cref(column.name));
20996
});
20997
const size_t valuesCount = std::distance(statement.range.first, statement.range.second);
20998
const size_t columnNamesCount = columnNames.size();
20999
21000
std::stringstream ss;
21001
ss << "INSERT INTO " << streaming_identifier(table.name) << " ";
21002
if (columnNamesCount) {
21003
ss << "(" << streaming_identifiers(columnNames) << ")";
21004
} else {
21005
ss << "DEFAULT";
21006
}
21007
ss << " VALUES ";
21008
if (columnNamesCount) {
21009
ss << streaming_values_placeholders(columnNamesCount, valuesCount);
21010
} else if (valuesCount != 1) {
21011
throw std::system_error{orm_error_code::cannot_use_default_value};
21012
}
21013
return ss.str();
21014
}
21015
};
21016
21017
template<class T, class Ctx>
21018
std::string serialize_get_all_impl(const T& getAll, const Ctx& context) {
21019
using table_type = type_t<T>;
21020
using mapped_type = mapped_type_proxy_t<table_type>;
21021
21022
auto& table = pick_table<mapped_type>(context.db_objects);
21023
21024
std::stringstream ss;
21025
ss << "SELECT " << streaming_table_column_names(table, alias_extractor<table_type>::as_qualifier(table))
21026
<< " FROM " << streaming_identifier(table.name, alias_extractor<table_type>::as_alias())
21027
<< streaming_conditions_tuple(getAll.conditions, context);
21028
return ss.str();
21029
}
21030
21031
#ifdef SQLITE_ORM_OPTIONAL_SUPPORTED
21032
template<class T, class R, class... Args>
21033
struct statement_serializer<get_all_optional_t<T, R, Args...>, void> {
21034
using statement_type = get_all_optional_t<T, R, Args...>;
21035
21036
template<class Ctx>
21037
std::string operator()(const statement_type& get, const Ctx& context) const {
21038
return serialize_get_all_impl(get, context);
21039
}
21040
};
21041
#endif // SQLITE_ORM_OPTIONAL_SUPPORTED
21042
21043
template<class T, class R, class... Args>
21044
struct statement_serializer<get_all_pointer_t<T, R, Args...>, void> {
21045
using statement_type = get_all_pointer_t<T, R, Args...>;
21046
21047
template<class Ctx>
21048
std::string operator()(const statement_type& get, const Ctx& context) const {
21049
return serialize_get_all_impl(get, context);
21050
}
21051
};
21052
21053
template<class T, class R, class... Args>
21054
struct statement_serializer<get_all_t<T, R, Args...>, void> {
21055
using statement_type = get_all_t<T, R, Args...>;
21056
21057
template<class Ctx>
21058
std::string operator()(const statement_type& get, const Ctx& context) const {
21059
return serialize_get_all_impl(get, context);
21060
}
21061
};
21062
21063
template<class T, class Ctx>
21064
std::string serialize_get_impl(const T&, const Ctx& context) {
21065
using primary_type = type_t<T>;
21066
auto& table = pick_table<primary_type>(context.db_objects);
21067
std::stringstream ss;
21068
ss << "SELECT " << streaming_table_column_names(table, std::string{}) << " FROM "
21069
<< streaming_identifier(table.name) << " WHERE ";
21070
21071
auto primaryKeyColumnNames = table.primary_key_column_names();
21072
if (primaryKeyColumnNames.empty()) {
21073
throw std::system_error{orm_error_code::table_has_no_primary_key_column};
21074
}
21075
21076
for (size_t i = 0; i < primaryKeyColumnNames.size(); ++i) {
21077
if (i > 0) {
21078
ss << " AND ";
21079
}
21080
ss << streaming_identifier(primaryKeyColumnNames[i]) << " = ?";
21081
}
21082
return ss.str();
21083
}
21084
21085
template<class T, class... Ids>
21086
struct statement_serializer<get_t<T, Ids...>, void> {
21087
using statement_type = get_t<T, Ids...>;
21088
21089
template<class Ctx>
21090
std::string operator()(const statement_type& get, const Ctx& context) const {
21091
return serialize_get_impl(get, context);
21092
}
21093
};
21094
21095
template<class T, class... Ids>
21096
struct statement_serializer<get_pointer_t<T, Ids...>, void> {
21097
using statement_type = get_pointer_t<T, Ids...>;
21098
21099
template<class Ctx>
21100
std::string operator()(const statement_type& statement, const Ctx& context) const {
21101
return serialize_get_impl(statement, context);
21102
}
21103
};
21104
21105
template<>
21106
struct statement_serializer<conflict_action, void> {
21107
using statement_type = conflict_action;
21108
21109
template<class Ctx>
21110
serialize_result_type operator()(const statement_type& statement, const Ctx&) const {
21111
switch (statement) {
21112
case conflict_action::replace:
21113
return "REPLACE";
21114
case conflict_action::abort:
21115
return "ABORT";
21116
case conflict_action::fail:
21117
return "FAIL";
21118
case conflict_action::ignore:
21119
return "IGNORE";
21120
case conflict_action::rollback:
21121
return "ROLLBACK";
21122
}
21123
return {};
21124
}
21125
};
21126
21127
template<>
21128
struct statement_serializer<insert_constraint, void> {
21129
using statement_type = insert_constraint;
21130
21131
template<class Ctx>
21132
std::string operator()(const statement_type& statement, const Ctx& context) const {
21133
std::stringstream ss;
21134
21135
ss << "OR " << serialize(statement.action, context);
21136
return ss.str();
21137
}
21138
};
21139
21140
#ifdef SQLITE_ORM_OPTIONAL_SUPPORTED
21141
template<class T, class... Ids>
21142
struct statement_serializer<get_optional_t<T, Ids...>, void> {
21143
using statement_type = get_optional_t<T, Ids...>;
21144
21145
template<class Ctx>
21146
std::string operator()(const statement_type& get, const Ctx& context) const {
21147
return serialize_get_impl(get, context);
21148
}
21149
};
21150
#endif // SQLITE_ORM_OPTIONAL_SUPPORTED
21151
21152
template<class T, class... Args>
21153
struct statement_serializer<select_t<T, Args...>, void> {
21154
using statement_type = select_t<T, Args...>;
21155
using return_type = typename statement_type::return_type;
21156
21157
template<class Ctx>
21158
std::string operator()(const statement_type& sel, Ctx context) const {
21159
context.skip_table_name = false;
21160
// subqueries should always use parentheses in column names
21161
auto subCtx = context;
21162
subCtx.use_parentheses = true;
21163
21164
std::stringstream ss;
21165
if (!is_compound_operator<T>::value) {
21166
if (!sel.highest_level && context.use_parentheses) {
21167
ss << "(";
21168
}
21169
ss << "SELECT ";
21170
call_if_constexpr<is_rowset_deduplicator_v<return_type>>(
21171
// note: make use of implicit to-string conversion
21172
[&ss](std::string keyword) {
21173
ss << keyword << ' ';
21174
},
21175
sel.col);
21176
}
21177
21178
ss << streaming_serialized(get_column_names(sel.col, subCtx));
21179
using conditions_tuple = typename statement_type::conditions_type;
21180
constexpr bool hasExplicitFrom = tuple_has<conditions_tuple, is_from>::value;
21181
if (!hasExplicitFrom) {
21182
auto tableNames = collect_table_names(sel, context);
21183
using joins_index_sequence = filter_tuple_sequence_t<conditions_tuple, is_constrained_join>;
21184
// deduplicate table names of constrained join statements
21185
iterate_tuple(sel.conditions, joins_index_sequence{}, [&tableNames, &context](auto& join) {
21186
using original_join_type = typename std::remove_reference_t<decltype(join)>::type;
21187
using cross_join_type = mapped_type_proxy_t<original_join_type>;
21188
std::pair<const std::string&, std::string> tableNameWithAlias{
21189
lookup_table_name<cross_join_type>(context.db_objects),
21190
alias_extractor<original_join_type>::as_alias()};
21191
tableNames.erase(tableNameWithAlias);
21192
});
21193
if (!tableNames.empty() && !is_compound_operator<T>::value) {
21194
ss << " FROM " << streaming_identifiers(tableNames);
21195
}
21196
}
21197
ss << streaming_conditions_tuple(sel.conditions, context);
21198
if (!is_compound_operator<T>::value) {
21199
if (!sel.highest_level && context.use_parentheses) {
21200
ss << ")";
21201
}
21202
}
21203
return ss.str();
21204
}
21205
};
21206
21207
template<class T>
21208
struct statement_serializer<indexed_column_t<T>, void> {
21209
using statement_type = indexed_column_t<T>;
21210
21211
template<class Ctx>
21212
std::string operator()(const statement_type& statement, const Ctx& context) const {
21213
std::stringstream ss;
21214
ss << serialize(statement.column_or_expression, context);
21215
if (!statement._collation_name.empty()) {
21216
ss << " COLLATE " << statement._collation_name;
21217
}
21218
if (statement._order) {
21219
switch (statement._order) {
21220
case 1:
21221
ss << " ASC";
21222
break;
21223
case -1:
21224
ss << " DESC";
21225
break;
21226
}
21227
}
21228
return ss.str();
21229
}
21230
};
21231
21232
#if SQLITE_VERSION_NUMBER >= 3009000
21233
template<class... Cs>
21234
struct statement_serializer<using_fts5_t<Cs...>, void> {
21235
using statement_type = using_fts5_t<Cs...>;
21236
21237
template<class Ctx>
21238
std::string operator()(const statement_type& statement, const Ctx& context) const {
21239
std::stringstream ss;
21240
ss << "USING FTS5(";
21241
auto subContext = context;
21242
subContext.fts5_columns = true;
21243
ss << streaming_expressions_tuple(statement.columns, subContext) << ")";
21244
return ss.str();
21245
}
21246
};
21247
#endif
21248
21249
template<class M>
21250
struct statement_serializer<virtual_table_t<M>, void> {
21251
using statement_type = virtual_table_t<M>;
21252
21253
template<class Ctx>
21254
std::string operator()(const statement_type& statement, const Ctx& context) const {
21255
std::stringstream ss;
21256
ss << "CREATE VIRTUAL TABLE IF NOT EXISTS ";
21257
ss << streaming_identifier(statement.name) << ' ';
21258
ss << serialize(statement.module_details, context);
21259
return ss.str();
21260
}
21261
};
21262
21263
template<class T, class... Cols>
21264
struct statement_serializer<index_t<T, Cols...>, void> {
21265
using statement_type = index_t<T, Cols...>;
21266
21267
template<class Ctx>
21268
std::string operator()(const statement_type& statement, const Ctx& context) const {
21269
std::stringstream ss;
21270
ss << "CREATE ";
21271
if (statement.unique) {
21272
ss << "UNIQUE ";
21273
}
21274
using indexed_type = typename statement_type::table_mapped_type;
21275
ss << "INDEX IF NOT EXISTS " << streaming_identifier(statement.name) << " ON "
21276
<< streaming_identifier(lookup_table_name<indexed_type>(context.db_objects));
21277
std::vector<std::string> columnNames;
21278
std::string whereString;
21279
iterate_tuple(statement.elements, [&columnNames, &context, &whereString](auto& value) {
21280
using value_type = polyfill::remove_cvref_t<decltype(value)>;
21281
if (!is_where<value_type>::value) {
21282
auto newContext = context;
21283
newContext.use_parentheses = false;
21284
auto whereString = serialize(value, newContext);
21285
columnNames.push_back(std::move(whereString));
21286
} else {
21287
auto columnName = serialize(value, context);
21288
whereString = std::move(columnName);
21289
}
21290
});
21291
ss << " (" << streaming_serialized(columnNames) << ")";
21292
if (!whereString.empty()) {
21293
ss << ' ' << whereString;
21294
}
21295
return ss.str();
21296
}
21297
};
21298
21299
template<class From>
21300
struct statement_serializer<From, match_if<is_from, From>> {
21301
using statement_type = From;
21302
21303
template<class Ctx>
21304
std::string operator()(const statement_type&, const Ctx& context) const {
21305
std::stringstream ss;
21306
ss << "FROM ";
21307
iterate_tuple<typename From::tuple_type>([&context, &ss, first = true](auto* dummyItem) mutable {
21308
using table_type = std::remove_pointer_t<decltype(dummyItem)>;
21309
21310
static constexpr std::array<const char*, 2> sep = {", ", ""};
21311
ss << sep[std::exchange(first, false)]
21312
<< streaming_identifier(lookup_table_name<mapped_type_proxy_t<table_type>>(context.db_objects),
21313
alias_extractor<table_type>::as_alias());
21314
});
21315
return ss.str();
21316
}
21317
};
21318
21319
template<class T>
21320
struct statement_serializer<old_t<T>, void> {
21321
using statement_type = old_t<T>;
21322
21323
template<class Ctx>
21324
std::string operator()(const statement_type& statement, const Ctx& context) const {
21325
std::stringstream ss;
21326
ss << "OLD.";
21327
auto newContext = context;
21328
newContext.skip_table_name = true;
21329
ss << serialize(statement.expression, newContext);
21330
return ss.str();
21331
}
21332
};
21333
21334
template<class T>
21335
struct statement_serializer<new_t<T>, void> {
21336
using statement_type = new_t<T>;
21337
21338
template<class Ctx>
21339
std::string operator()(const statement_type& statement, const Ctx& context) const {
21340
std::stringstream ss;
21341
ss << "NEW.";
21342
auto newContext = context;
21343
newContext.skip_table_name = true;
21344
ss << serialize(statement.expression, newContext);
21345
return ss.str();
21346
}
21347
};
21348
21349
template<>
21350
struct statement_serializer<raise_t, void> {
21351
using statement_type = raise_t;
21352
21353
template<class Ctx>
21354
std::string operator()(const statement_type& statement, const Ctx& context) const {
21355
switch (statement.type) {
21356
case raise_t::type_t::ignore:
21357
return "RAISE(IGNORE)";
21358
21359
case raise_t::type_t::rollback:
21360
return "RAISE(ROLLBACK, " + serialize(statement.message, context) + ")";
21361
21362
case raise_t::type_t::abort:
21363
return "RAISE(ABORT, " + serialize(statement.message, context) + ")";
21364
21365
case raise_t::type_t::fail:
21366
return "RAISE(FAIL, " + serialize(statement.message, context) + ")";
21367
}
21368
return {};
21369
}
21370
};
21371
21372
template<>
21373
struct statement_serializer<trigger_timing, void> {
21374
using statement_type = trigger_timing;
21375
21376
template<class Ctx>
21377
serialize_result_type operator()(const statement_type& statement, const Ctx&) const {
21378
switch (statement) {
21379
case trigger_timing::trigger_before:
21380
return "BEFORE";
21381
case trigger_timing::trigger_after:
21382
return "AFTER";
21383
case trigger_timing::trigger_instead_of:
21384
return "INSTEAD OF";
21385
}
21386
return {};
21387
}
21388
};
21389
21390
template<>
21391
struct statement_serializer<trigger_type, void> {
21392
using statement_type = trigger_type;
21393
21394
template<class Ctx>
21395
serialize_result_type operator()(const statement_type& statement, const Ctx&) const {
21396
switch (statement) {
21397
case trigger_type::trigger_delete:
21398
return "DELETE";
21399
case trigger_type::trigger_insert:
21400
return "INSERT";
21401
case trigger_type::trigger_update:
21402
return "UPDATE";
21403
}
21404
return {};
21405
}
21406
};
21407
21408
template<>
21409
struct statement_serializer<trigger_type_base_t, void> {
21410
using statement_type = trigger_type_base_t;
21411
21412
template<class Ctx>
21413
std::string operator()(const statement_type& statement, const Ctx& context) const {
21414
std::stringstream ss;
21415
21416
ss << serialize(statement.timing, context) << " " << serialize(statement.type, context);
21417
return ss.str();
21418
}
21419
};
21420
21421
template<class... Cs>
21422
struct statement_serializer<trigger_update_type_t<Cs...>, void> {
21423
using statement_type = trigger_update_type_t<Cs...>;
21424
21425
template<class Ctx>
21426
std::string operator()(const statement_type& statement, const Ctx& context) const {
21427
std::stringstream ss;
21428
21429
ss << serialize(statement.timing, context) << " UPDATE OF "
21430
<< streaming_mapped_columns_expressions(statement.columns, context);
21431
return ss.str();
21432
}
21433
};
21434
21435
template<class T, class W, class Trigger>
21436
struct statement_serializer<trigger_base_t<T, W, Trigger>, void> {
21437
using statement_type = trigger_base_t<T, W, Trigger>;
21438
21439
template<class Ctx>
21440
std::string operator()(const statement_type& statement, const Ctx& context) const {
21441
std::stringstream ss;
21442
21443
ss << serialize(statement.type_base, context);
21444
ss << " ON " << streaming_identifier(lookup_table_name<T>(context.db_objects));
21445
if (statement.do_for_each_row) {
21446
ss << " FOR EACH ROW";
21447
}
21448
statement.container_when.apply([&ss, &context](auto& value) {
21449
ss << " WHEN " << serialize(value, context);
21450
});
21451
return ss.str();
21452
}
21453
};
21454
21455
template<class... S>
21456
struct statement_serializer<trigger_t<S...>, void> {
21457
using statement_type = trigger_t<S...>;
21458
21459
template<class Ctx>
21460
std::string operator()(const statement_type& statement, const Ctx& context) const {
21461
std::stringstream ss;
21462
ss << "CREATE ";
21463
21464
ss << "TRIGGER IF NOT EXISTS " << streaming_identifier(statement.name) << " "
21465
<< serialize(statement.base, context);
21466
ss << " BEGIN ";
21467
iterate_tuple(statement.elements, [&ss, &context](auto& element) {
21468
using element_type = polyfill::remove_cvref_t<decltype(element)>;
21469
if (is_select<element_type>::value) {
21470
auto newContext = context;
21471
newContext.use_parentheses = false;
21472
ss << serialize(element, newContext);
21473
} else {
21474
ss << serialize(element, context);
21475
}
21476
ss << ";";
21477
});
21478
ss << " END";
21479
21480
return ss.str();
21481
}
21482
};
21483
21484
template<class T>
21485
struct statement_serializer<where_t<T>, void> {
21486
using statement_type = where_t<T>;
21487
21488
template<class Ctx>
21489
std::string operator()(const statement_type& statement, const Ctx& context) const {
21490
std::stringstream ss;
21491
ss << statement.serialize() << " ";
21492
auto whereString = serialize(statement.expression, context);
21493
ss << '(' << whereString << ')';
21494
return ss.str();
21495
}
21496
};
21497
21498
template<class O>
21499
struct statement_serializer<order_by_t<O>, void> {
21500
using statement_type = order_by_t<O>;
21501
21502
template<class Ctx>
21503
std::string operator()(const statement_type& orderBy, const Ctx& context) const {
21504
std::stringstream ss;
21505
ss << static_cast<std::string>(orderBy) << " ";
21506
ss << serialize_order_by(orderBy, context);
21507
return ss.str();
21508
}
21509
};
21510
21511
template<class C>
21512
struct statement_serializer<dynamic_order_by_t<C>, void> {
21513
using statement_type = dynamic_order_by_t<C>;
21514
21515
template<class Ctx>
21516
std::string operator()(const statement_type& orderBy, const Ctx& context) const {
21517
return serialize_order_by(orderBy, context);
21518
}
21519
};
21520
21521
template<class... Args>
21522
struct statement_serializer<multi_order_by_t<Args...>, void> {
21523
using statement_type = multi_order_by_t<Args...>;
21524
21525
template<class Ctx>
21526
std::string operator()(const statement_type& orderBy, const Ctx& context) const {
21527
std::stringstream ss;
21528
ss << static_cast<std::string>(orderBy) << " " << streaming_expressions_tuple(orderBy.args, context);
21529
return ss.str();
21530
}
21531
};
21532
21533
template<class Join>
21534
struct statement_serializer<
21535
Join,
21536
std::enable_if_t<polyfill::disjunction<polyfill::is_specialization_of<Join, cross_join_t>,
21537
polyfill::is_specialization_of<Join, natural_join_t>>::value>> {
21538
using statement_type = Join;
21539
21540
template<class Ctx>
21541
std::string operator()(const statement_type& join, const Ctx& context) const {
21542
std::stringstream ss;
21543
ss << static_cast<std::string>(join) << " "
21544
<< streaming_identifier(lookup_table_name<type_t<Join>>(context.db_objects));
21545
return ss.str();
21546
}
21547
};
21548
21549
template<class Join>
21550
struct statement_serializer<Join, match_if<is_constrained_join, Join>> {
21551
using statement_type = Join;
21552
21553
template<class Ctx>
21554
std::string operator()(const statement_type& join, const Ctx& context) const {
21555
std::stringstream ss;
21556
ss << static_cast<std::string>(join) << " "
21557
<< streaming_identifier(lookup_table_name<mapped_type_proxy_t<type_t<Join>>>(context.db_objects),
21558
alias_extractor<type_t<Join>>::as_alias())
21559
<< " " << serialize(join.constraint, context);
21560
return ss.str();
21561
}
21562
};
21563
21564
template<class T>
21565
struct statement_serializer<on_t<T>, void> {
21566
using statement_type = on_t<T>;
21567
21568
template<class Ctx>
21569
std::string operator()(const statement_type& on, const Ctx& context) const {
21570
std::stringstream ss;
21571
auto newContext = context;
21572
newContext.skip_table_name = false;
21573
ss << static_cast<std::string>(on) << " " << serialize(on.arg, newContext) << " ";
21574
return ss.str();
21575
}
21576
};
21577
21578
template<class T, class... Args>
21579
struct statement_serializer<group_by_with_having<T, Args...>, void> {
21580
using statement_type = group_by_with_having<T, Args...>;
21581
21582
template<class Ctx>
21583
std::string operator()(const statement_type& statement, const Ctx& context) const {
21584
std::stringstream ss;
21585
auto newContext = context;
21586
newContext.skip_table_name = false;
21587
ss << "GROUP BY " << streaming_expressions_tuple(statement.args, newContext) << " HAVING "
21588
<< serialize(statement.expression, context);
21589
return ss.str();
21590
}
21591
};
21592
21593
template<class... Args>
21594
struct statement_serializer<group_by_t<Args...>, void> {
21595
using statement_type = group_by_t<Args...>;
21596
21597
template<class Ctx>
21598
std::string operator()(const statement_type& statement, const Ctx& context) const {
21599
std::stringstream ss;
21600
auto newContext = context;
21601
newContext.skip_table_name = false;
21602
ss << "GROUP BY " << streaming_expressions_tuple(statement.args, newContext);
21603
return ss.str();
21604
}
21605
};
21606
21607
/**
21608
* HO - has offset
21609
* OI - offset is implicit
21610
*/
21611
template<class T, bool HO, bool OI, class O>
21612
struct statement_serializer<limit_t<T, HO, OI, O>, void> {
21613
using statement_type = limit_t<T, HO, OI, O>;
21614
21615
template<class Ctx>
21616
std::string operator()(const statement_type& limt, const Ctx& context) const {
21617
auto newContext = context;
21618
newContext.skip_table_name = false;
21619
std::stringstream ss;
21620
ss << static_cast<std::string>(limt) << " ";
21621
if (HO) {
21622
if (OI) {
21623
limt.off.apply([&newContext, &ss](auto& value) {
21624
ss << serialize(value, newContext);
21625
});
21626
ss << ", ";
21627
ss << serialize(limt.lim, newContext);
21628
} else {
21629
ss << serialize(limt.lim, newContext) << " OFFSET ";
21630
limt.off.apply([&newContext, &ss](auto& value) {
21631
ss << serialize(value, newContext);
21632
});
21633
}
21634
} else {
21635
ss << serialize(limt.lim, newContext);
21636
}
21637
return ss.str();
21638
}
21639
};
21640
21641
template<>
21642
struct statement_serializer<default_values_t, void> {
21643
using statement_type = default_values_t;
21644
21645
template<class Ctx>
21646
serialize_result_type operator()(const statement_type&, const Ctx&) const {
21647
return "DEFAULT VALUES";
21648
}
21649
};
21650
21651
template<class T, class M>
21652
struct statement_serializer<using_t<T, M>, void> {
21653
using statement_type = using_t<T, M>;
21654
21655
template<class Ctx>
21656
std::string operator()(const statement_type& statement, const Ctx& context) const {
21657
auto newContext = context;
21658
newContext.skip_table_name = true;
21659
return static_cast<std::string>(statement) + " (" + serialize(statement.column, newContext) + ")";
21660
}
21661
};
21662
21663
template<class... Args>
21664
struct statement_serializer<std::tuple<Args...>, void> {
21665
using statement_type = std::tuple<Args...>;
21666
21667
template<class Ctx>
21668
std::string operator()(const statement_type& statement, const Ctx& context) const {
21669
std::stringstream ss;
21670
if (context.use_parentheses) {
21671
ss << '(';
21672
}
21673
ss << streaming_expressions_tuple(statement, context);
21674
if (context.use_parentheses) {
21675
ss << ')';
21676
}
21677
return ss.str();
21678
}
21679
};
21680
21681
template<class... Args>
21682
struct statement_serializer<values_t<Args...>, void> {
21683
using statement_type = values_t<Args...>;
21684
21685
template<class Ctx>
21686
std::string operator()(const statement_type& statement, const Ctx& context) const {
21687
std::stringstream ss;
21688
if (context.use_parentheses) {
21689
ss << '(';
21690
}
21691
ss << "VALUES ";
21692
{
21693
Ctx tupleContext = context;
21694
tupleContext.use_parentheses = true;
21695
ss << streaming_expressions_tuple(statement.tuple, tupleContext);
21696
}
21697
if (context.use_parentheses) {
21698
ss << ')';
21699
}
21700
return ss.str();
21701
}
21702
};
21703
21704
template<class T>
21705
struct statement_serializer<dynamic_values_t<T>, void> {
21706
using statement_type = dynamic_values_t<T>;
21707
21708
template<class Ctx>
21709
std::string operator()(const statement_type& statement, const Ctx& context) const {
21710
std::stringstream ss;
21711
if (context.use_parentheses) {
21712
ss << '(';
21713
}
21714
ss << "VALUES " << streaming_dynamic_expressions(statement.vector, context);
21715
if (context.use_parentheses) {
21716
ss << ')';
21717
}
21718
return ss.str();
21719
}
21720
};
21721
}
21722
}
21723
21724
// #include "serializer_context.h"
21725
21726
// #include "schema/triggers.h"
21727
21728
// #include "object_from_column_builder.h"
21729
21730
// #include "row_extractor.h"
21731
21732
// #include "schema/table.h"
21733
21734
// #include "schema/column.h"
21735
21736
// #include "schema/index.h"
21737
21738
// #include "cte_storage.h"
21739
21740
#if (SQLITE_VERSION_NUMBER >= 3008003) && defined(SQLITE_ORM_WITH_CTE)
21741
#include <type_traits>
21742
#include <tuple>
21743
#include <string>
21744
#include <vector>
21745
#endif
21746
21747
// #include "tuple_helper/tuple_fy.h"
21748
21749
// #include "table_type_of.h"
21750
21751
// #include "column_result.h"
21752
21753
// #include "select_constraints.h"
21754
21755
// #include "schema/table.h"
21756
21757
// #include "alias.h"
21758
21759
// #include "cte_types.h"
21760
21761
// #include "cte_column_names_collector.h"
21762
21763
// #include "column_expression.h"
21764
21765
#include <type_traits> // std::enable_if, std::is_same, std::decay, std::is_arithmetic
21766
#include <tuple> // std::tuple
21767
#include <functional> // std::reference_wrapper
21768
21769
// #include "functional/cxx_type_traits_polyfill.h"
21770
21771
// #include "tuple_helper/tuple_transformer.h"
21772
21773
// #include "type_traits.h"
21774
21775
// #include "select_constraints.h"
21776
21777
// #include "alias.h"
21778
21779
// #include "storage_traits.h"
21780
21781
namespace sqlite_orm {
21782
21783
namespace internal {
21784
21785
template<class DBOs, class E, class SFINAE = void>
21786
struct column_expression_type;
21787
21788
/**
21789
* Obains the expressions that form the columns of a subselect statement.
21790
*/
21791
template<class DBOs, class E>
21792
using column_expression_of_t = typename column_expression_type<DBOs, E>::type;
21793
21794
/**
21795
* Identity.
21796
*/
21797
template<class DBOs, class E, class SFINAE>
21798
struct column_expression_type {
21799
using type = E;
21800
};
21801
21802
/**
21803
* Resolve column alias.
21804
* as_t<Alias, E> -> as_t<Alias, ColExpr>
21805
*/
21806
template<class DBOs, class As>
21807
struct column_expression_type<DBOs, As, match_specialization_of<As, as_t>> {
21808
using type = as_t<alias_type_t<As>, column_expression_of_t<DBOs, expression_type_t<As>>>;
21809
};
21810
21811
/**
21812
* Resolve reference wrapper.
21813
* reference_wrapper<T> -> T&
21814
*/
21815
template<class DBOs, class E>
21816
struct column_expression_type<DBOs, std::reference_wrapper<E>, void>
21817
: std::add_lvalue_reference<column_expression_of_t<DBOs, E>> {};
21818
21819
// No CTE for object expression.
21820
template<class DBOs, class E>
21821
struct column_expression_type<DBOs, object_t<E>, void> {
21822
static_assert(polyfill::always_false_v<E>, "Selecting an object in a subselect is not allowed.");
21823
};
21824
21825
/**
21826
* Resolve all columns of a mapped object or CTE.
21827
* asterisk_t<O> -> tuple<ColExpr...>
21828
*/
21829
template<class DBOs, class E>
21830
struct column_expression_type<DBOs,
21831
asterisk_t<E>,
21832
std::enable_if_t<polyfill::disjunction<polyfill::negation<is_recordset_alias<E>>,
21833
is_cte_moniker<E>>::value>>
21834
: storage_traits::storage_mapped_column_expressions<DBOs, E> {};
21835
21836
template<class A>
21837
struct add_column_alias {
21838
template<typename ColExpr>
21839
using apply_t = alias_column_t<A, ColExpr>;
21840
};
21841
/**
21842
* Resolve all columns of an aliased object.
21843
* asterisk_t<Alias> -> tuple<alias_column_t<Alias, ColExpr>...>
21844
*/
21845
template<class DBOs, class A>
21846
struct column_expression_type<DBOs, asterisk_t<A>, match_if<is_table_alias, A>>
21847
: tuple_transformer<typename storage_traits::storage_mapped_column_expressions<DBOs, type_t<A>>::type,
21848
add_column_alias<A>::template apply_t> {};
21849
21850
/**
21851
* Resolve multiple columns.
21852
* columns_t<C...> -> tuple<ColExpr...>
21853
*/
21854
template<class DBOs, class... Args>
21855
struct column_expression_type<DBOs, columns_t<Args...>, void> {
21856
using type = std::tuple<column_expression_of_t<DBOs, std::decay_t<Args>>...>;
21857
};
21858
21859
/**
21860
* Resolve multiple columns.
21861
* struct_t<T, C...> -> tuple<ColExpr...>
21862
*/
21863
template<class DBOs, class T, class... Args>
21864
struct column_expression_type<DBOs, struct_t<T, Args...>, void> {
21865
using type = std::tuple<column_expression_of_t<DBOs, std::decay_t<Args>>...>;
21866
};
21867
21868
/**
21869
* Resolve column(s) of subselect.
21870
* select_t<E, Args...> -> ColExpr, tuple<ColExpr....>
21871
*/
21872
template<class DBOs, class E, class... Args>
21873
struct column_expression_type<DBOs, select_t<E, Args...>> : column_expression_type<DBOs, E> {};
21874
}
21875
}
21876
21877
// #include "storage_lookup.h"
21878
21879
namespace sqlite_orm {
21880
namespace internal {
21881
21882
#if (SQLITE_VERSION_NUMBER >= 3008003) && defined(SQLITE_ORM_WITH_CTE)
21883
// F = field_type
21884
template<typename Moniker,
21885
typename ExplicitColRefs,
21886
typename Expression,
21887
typename SubselectColRefs,
21888
typename FinalColRefs,
21889
typename F>
21890
struct create_cte_mapper {
21891
using type = subselect_mapper<Moniker, ExplicitColRefs, Expression, SubselectColRefs, FinalColRefs, F>;
21892
};
21893
21894
// std::tuple<Fs...>
21895
template<typename Moniker,
21896
typename ExplicitColRefs,
21897
typename Expression,
21898
typename SubselectColRefs,
21899
typename FinalColRefs,
21900
typename... Fs>
21901
struct create_cte_mapper<Moniker,
21902
ExplicitColRefs,
21903
Expression,
21904
SubselectColRefs,
21905
FinalColRefs,
21906
std::tuple<Fs...>> {
21907
using type = subselect_mapper<Moniker, ExplicitColRefs, Expression, SubselectColRefs, FinalColRefs, Fs...>;
21908
};
21909
21910
template<typename Moniker,
21911
typename ExplicitColRefs,
21912
typename Expression,
21913
typename SubselectColRefs,
21914
typename FinalColRefs,
21915
typename Result>
21916
using create_cte_mapper_t =
21917
typename create_cte_mapper<Moniker, ExplicitColRefs, Expression, SubselectColRefs, FinalColRefs, Result>::
21918
type;
21919
21920
// aliased column expressions, explicit or implicitly numbered
21921
template<typename F, typename ColRef, satisfies_is_specialization_of<ColRef, alias_holder> = true>
21922
static auto make_cte_column(std::string name, const ColRef& /*finalColRef*/) {
21923
using object_type = aliased_field<type_t<ColRef>, F>;
21924
21925
return sqlite_orm::make_column<>(std::move(name), &object_type::field);
21926
}
21927
21928
// F O::*
21929
template<typename F, typename ColRef, satisfies<std::is_member_pointer, ColRef> = true>
21930
static auto make_cte_column(std::string name, const ColRef& finalColRef) {
21931
using object_type = table_type_of_t<ColRef>;
21932
using column_type = column_t<ColRef, empty_setter>;
21933
21934
return column_type{std::move(name), finalColRef, empty_setter{}};
21935
}
21936
21937
/**
21938
* Concatenate newly created tables with given DBOs, forming a new set of DBOs.
21939
*/
21940
template<typename DBOs, size_t... Idx, typename... CTETables>
21941
auto db_objects_cat(const DBOs& dbObjects, std::index_sequence<Idx...>, CTETables&&... cteTables) {
21942
return std::tuple{std::forward<CTETables>(cteTables)..., get<Idx>(dbObjects)...};
21943
}
21944
21945
/**
21946
* Concatenate newly created tables with given DBOs, forming a new set of DBOs.
21947
*/
21948
template<typename DBOs, typename... CTETables>
21949
auto db_objects_cat(const DBOs& dbObjects, CTETables&&... cteTables) {
21950
return db_objects_cat(dbObjects,
21951
std::make_index_sequence<std::tuple_size_v<DBOs>>{},
21952
std::forward<CTETables>(cteTables)...);
21953
}
21954
21955
/**
21956
* This function returns the expression contained in a subselect that is relevant for
21957
* creating the definition of a CTE table.
21958
* Because CTEs can recursively refer to themselves in a compound statement, parsing
21959
* the whole compound statement would lead to compiler errors if a column_pointer<>
21960
* can't be resolved. Therefore, at the time of building a CTE table, we are only
21961
* interested in the column results of the left-most select expression.
21962
*/
21963
template<class Select>
21964
decltype(auto) get_cte_driving_subselect(const Select& subSelect);
21965
21966
/**
21967
* Return given select expression.
21968
*/
21969
template<class Select>
21970
decltype(auto) get_cte_driving_subselect(const Select& subSelect) {
21971
return subSelect;
21972
}
21973
21974
/**
21975
* Return left-most select expression of compound statement.
21976
*/
21977
template<class Compound, class... Args, std::enable_if_t<is_compound_operator_v<Compound>, bool> = true>
21978
decltype(auto) get_cte_driving_subselect(const select_t<Compound, Args...>& subSelect) {
21979
return std::get<0>(subSelect.col.compound);
21980
}
21981
21982
/**
21983
* Return a tuple of member pointers of all columns
21984
*/
21985
template<class C, size_t... Idx>
21986
auto get_table_columns_fields(const C& coldef, std::index_sequence<Idx...>) {
21987
return std::make_tuple(get<Idx>(coldef).member_pointer...);
21988
}
21989
21990
// any expression -> numeric column alias
21991
template<class DBOs,
21992
class E,
21993
size_t Idx = 0,
21994
std::enable_if_t<polyfill::negation_v<polyfill::is_specialization_of<E, std::tuple>>, bool> = true>
21995
auto extract_colref_expressions(const DBOs& /*dbObjects*/, const E& /*col*/, std::index_sequence<Idx> = {})
21996
-> std::tuple<alias_holder<decltype(n_to_colalias<Idx>())>> {
21997
return {};
21998
}
21999
22000
// expression_t<>
22001
template<class DBOs, class E, size_t Idx = 0>
22002
auto
22003
extract_colref_expressions(const DBOs& dbObjects, const expression_t<E>& col, std::index_sequence<Idx> s = {}) {
22004
return extract_colref_expressions(dbObjects, col.value, s);
22005
}
22006
22007
// F O::* (field/getter) -> field/getter
22008
template<class DBOs, class F, class O, size_t Idx = 0>
22009
auto extract_colref_expressions(const DBOs& /*dbObjects*/, F O::* col, std::index_sequence<Idx> = {}) {
22010
return std::make_tuple(col);
22011
}
22012
22013
// as_t<> (aliased expression) -> alias_holder
22014
template<class DBOs, class A, class E, size_t Idx = 0>
22015
std::tuple<alias_holder<A>> extract_colref_expressions(const DBOs& /*dbObjects*/,
22016
const as_t<A, E>& /*col*/,
22017
std::index_sequence<Idx> = {}) {
22018
return {};
22019
}
22020
22021
// alias_holder<> (colref) -> alias_holder
22022
template<class DBOs, class A, size_t Idx = 0>
22023
std::tuple<alias_holder<A>> extract_colref_expressions(const DBOs& /*dbObjects*/,
22024
const alias_holder<A>& /*col*/,
22025
std::index_sequence<Idx> = {}) {
22026
return {};
22027
}
22028
22029
// column_pointer<>
22030
template<class DBOs, class Moniker, class F, size_t Idx = 0>
22031
auto extract_colref_expressions(const DBOs& dbObjects,
22032
const column_pointer<Moniker, F>& col,
22033
std::index_sequence<Idx> s = {}) {
22034
return extract_colref_expressions(dbObjects, col.field, s);
22035
}
22036
22037
// column expression tuple
22038
template<class DBOs, class... Args, size_t... Idx>
22039
auto extract_colref_expressions(const DBOs& dbObjects,
22040
const std::tuple<Args...>& cols,
22041
std::index_sequence<Idx...>) {
22042
return std::tuple_cat(extract_colref_expressions(dbObjects, get<Idx>(cols), std::index_sequence<Idx>{})...);
22043
}
22044
22045
// columns_t<>
22046
template<class DBOs, class... Args>
22047
auto extract_colref_expressions(const DBOs& dbObjects, const columns_t<Args...>& cols) {
22048
return extract_colref_expressions(dbObjects, cols.columns, std::index_sequence_for<Args...>{});
22049
}
22050
22051
// asterisk_t<> -> fields
22052
template<class DBOs, class O>
22053
auto extract_colref_expressions(const DBOs& dbObjects, const asterisk_t<O>& /*col*/) {
22054
using table_type = storage_pick_table_t<O, DBOs>;
22055
using elements_t = typename table_type::elements_type;
22056
using column_idxs = filter_tuple_sequence_t<elements_t, is_column>;
22057
22058
auto& table = pick_table<O>(dbObjects);
22059
return get_table_columns_fields(table.elements, column_idxs{});
22060
}
22061
22062
template<class DBOs, class E, class... Args>
22063
void extract_colref_expressions(const DBOs& /*dbObjects*/, const select_t<E, Args...>& /*subSelect*/) = delete;
22064
22065
template<class DBOs, class Compound, std::enable_if_t<is_compound_operator_v<Compound>, bool> = true>
22066
void extract_colref_expressions(const DBOs& /*dbObjects*/, const Compound& /*subSelect*/) = delete;
22067
22068
/*
22069
* Depending on ExplicitColRef's type returns either the explicit column reference
22070
* or the expression's column reference otherwise.
22071
*/
22072
template<typename DBOs, typename SubselectColRef, typename ExplicitColRef>
22073
auto determine_cte_colref(const DBOs& /*dbObjects*/,
22074
const SubselectColRef& subselectColRef,
22075
const ExplicitColRef& explicitColRef) {
22076
if constexpr (polyfill::is_specialization_of_v<ExplicitColRef, alias_holder>) {
22077
return explicitColRef;
22078
} else if constexpr (std::is_member_pointer<ExplicitColRef>::value) {
22079
return explicitColRef;
22080
} else if constexpr (std::is_base_of_v<column_identifier, ExplicitColRef>) {
22081
return explicitColRef.member_pointer;
22082
} else if constexpr (std::is_same_v<ExplicitColRef, std::string>) {
22083
return subselectColRef;
22084
} else if constexpr (std::is_same_v<ExplicitColRef, polyfill::remove_cvref_t<decltype(std::ignore)>>) {
22085
return subselectColRef;
22086
} else {
22087
static_assert(polyfill::always_false_v<ExplicitColRef>, "Invalid explicit column reference specified");
22088
}
22089
}
22090
22091
template<typename DBOs, typename SubselectColRefs, typename ExplicitColRefs, size_t... Idx>
22092
auto determine_cte_colrefs([[maybe_unused]] const DBOs& dbObjects,
22093
const SubselectColRefs& subselectColRefs,
22094
[[maybe_unused]] const ExplicitColRefs& explicitColRefs,
22095
std::index_sequence<Idx...>) {
22096
if constexpr (std::tuple_size_v<ExplicitColRefs> != 0) {
22097
static_assert(
22098
(!is_builtin_numeric_column_alias_v<
22099
alias_holder_type_or_none_t<std::tuple_element_t<Idx, ExplicitColRefs>>> &&
22100
...),
22101
"Numeric column aliases are reserved for referencing columns locally within a single CTE.");
22102
22103
return std::tuple{
22104
determine_cte_colref(dbObjects, get<Idx>(subselectColRefs), get<Idx>(explicitColRefs))...};
22105
} else {
22106
return subselectColRefs;
22107
}
22108
}
22109
22110
template<typename Mapper, typename DBOs, typename ColRefs, size_t... CIs>
22111
auto make_cte_table_using_column_indices(const DBOs& /*dbObjects*/,
22112
std::string tableName,
22113
std::vector<std::string> columnNames,
22114
const ColRefs& finalColRefs,
22115
std::index_sequence<CIs...>) {
22116
return make_table<Mapper>(
22117
std::move(tableName),
22118
make_cte_column<std::tuple_element_t<CIs, typename Mapper::fields_type>>(std::move(columnNames.at(CIs)),
22119
get<CIs>(finalColRefs))...);
22120
}
22121
22122
template<typename DBOs, typename CTE>
22123
auto make_cte_table(const DBOs& dbObjects, const CTE& cte) {
22124
using cte_type = CTE;
22125
22126
auto subSelect = get_cte_driving_subselect(cte.subselect);
22127
22128
using subselect_type = decltype(subSelect);
22129
using column_results = column_result_of_t<DBOs, subselect_type>;
22130
using index_sequence = std::make_index_sequence<std::tuple_size_v<tuplify_t<column_results>>>;
22131
static_assert(cte_type::explicit_colref_count == 0 ||
22132
cte_type::explicit_colref_count == index_sequence::size(),
22133
"Number of explicit columns of common table expression doesn't match the number of columns "
22134
"in the subselect.");
22135
22136
std::string tableName = alias_extractor<cte_moniker_type_t<cte_type>>::extract();
22137
auto subselectColRefs = extract_colref_expressions(dbObjects, subSelect.col);
22138
const auto& finalColRefs =
22139
determine_cte_colrefs(dbObjects, subselectColRefs, cte.explicitColumns, index_sequence{});
22140
22141
serializer_context context{dbObjects};
22142
std::vector<std::string> columnNames = collect_cte_column_names(subSelect, cte.explicitColumns, context);
22143
22144
using mapper_type = create_cte_mapper_t<cte_moniker_type_t<cte_type>,
22145
typename cte_type::explicit_colrefs_tuple,
22146
column_expression_of_t<DBOs, subselect_type>,
22147
decltype(subselectColRefs),
22148
polyfill::remove_cvref_t<decltype(finalColRefs)>,
22149
column_results>;
22150
return make_cte_table_using_column_indices<mapper_type>(dbObjects,
22151
std::move(tableName),
22152
std::move(columnNames),
22153
finalColRefs,
22154
index_sequence{});
22155
}
22156
22157
template<typename DBOs, typename... CTEs, size_t Ii, size_t... In>
22158
decltype(auto) make_recursive_cte_db_objects(const DBOs& dbObjects,
22159
const common_table_expressions<CTEs...>& cte,
22160
std::index_sequence<Ii, In...>) {
22161
auto tbl = make_cte_table(dbObjects, get<Ii>(cte));
22162
22163
if constexpr (sizeof...(In) > 0) {
22164
return make_recursive_cte_db_objects(
22165
// Because CTEs can depend on their predecessor we recursively pass in a new set of DBOs
22166
db_objects_cat(dbObjects, std::move(tbl)),
22167
cte,
22168
std::index_sequence<In...>{});
22169
} else {
22170
return db_objects_cat(dbObjects, std::move(tbl));
22171
}
22172
}
22173
22174
/**
22175
* Return new DBOs for CTE expressions.
22176
*/
22177
template<class DBOs, class E, class... CTEs, satisfies<is_db_objects, DBOs> = true>
22178
decltype(auto) db_objects_for_expression(DBOs& dbObjects, const with_t<E, CTEs...>& e) {
22179
return make_recursive_cte_db_objects(dbObjects, e.cte, std::index_sequence_for<CTEs...>{});
22180
}
22181
#endif
22182
}
22183
}
22184
22185
// #include "util.h"
22186
22187
// #include "serializing_util.h"
22188
22189
namespace sqlite_orm {
22190
22191
namespace internal {
22192
/*
22193
* Implementation note: the technique of indirect expression testing is because
22194
* of older compilers having problems with the detection of dependent templates [SQLITE_ORM_BROKEN_ALIAS_TEMPLATE_DEPENDENT_EXPR_SFINAE].
22195
* It must also be a type that differs from those for `is_printable_v`, `is_bindable_v`.
22196
*/
22197
template<class Binder>
22198
struct indirectly_test_preparable;
22199
22200
template<class S, class E, class SFINAE = void>
22201
SQLITE_ORM_INLINE_VAR constexpr bool is_preparable_v = false;
22202
template<class S, class E>
22203
SQLITE_ORM_INLINE_VAR constexpr bool is_preparable_v<
22204
S,
22205
E,
22206
polyfill::void_t<indirectly_test_preparable<decltype(std::declval<S>().prepare(std::declval<E>()))>>> =
22207
true;
22208
22209
/**
22210
* Storage class itself. Create an instanse to use it as an interfacto to sqlite db by calling `make_storage`
22211
* function.
22212
*/
22213
template<class... DBO>
22214
struct storage_t : storage_base {
22215
using self = storage_t<DBO...>;
22216
using db_objects_type = db_objects_tuple<DBO...>;
22217
22218
/**
22219
* @param filename database filename.
22220
* @param dbObjects db_objects_tuple
22221
*/
22222
storage_t(std::string filename, db_objects_type dbObjects) :
22223
storage_base{std::move(filename), foreign_keys_count(dbObjects)}, db_objects{std::move(dbObjects)} {}
22224
22225
storage_t(const storage_t&) = default;
22226
22227
private:
22228
db_objects_type db_objects;
22229
22230
/**
22231
* Obtain a storage_t's const db_objects_tuple.
22232
*
22233
* @note Historically, `serializer_context_builder` was declared friend, along with
22234
* a few other library stock objects, in order to limit access to the db_objects_tuple.
22235
* However, one could gain access to a storage_t's db_objects_tuple through
22236
* `serializer_context_builder`, hence leading the whole friend declaration mambo-jumbo
22237
* ad absurdum.
22238
* Providing a free function is way better and cleaner.
22239
*
22240
* Hence, friend was replaced by `obtain_db_objects()` and `pick_const_impl()`.
22241
*/
22242
friend const db_objects_type& obtain_db_objects(const self& storage) noexcept {
22243
return storage.db_objects;
22244
}
22245
22246
template<class Table>
22247
void create_table(sqlite3* db, const std::string& tableName, const Table& table) {
22248
using context_t = serializer_context<db_objects_type>;
22249
22250
context_t context{this->db_objects};
22251
statement_serializer<Table, void> serializer;
22252
std::string sql = serializer.serialize(table, context, tableName);
22253
perform_void_exec(db, std::move(sql));
22254
}
22255
22256
/**
22257
* Copies sourceTableName to another table with name: destinationTableName
22258
* Performs INSERT INTO %destinationTableName% () SELECT %table.column_names% FROM %sourceTableName%
22259
*/
22260
template<class Table>
22261
void copy_table(sqlite3* db,
22262
const std::string& sourceTableName,
22263
const std::string& destinationTableName,
22264
const Table& table,
22265
const std::vector<const table_xinfo*>& columnsToIgnore) const;
22266
22267
#if SQLITE_VERSION_NUMBER >= 3035000 // DROP COLUMN feature exists (v3.35.0)
22268
void drop_column(sqlite3* db, const std::string& tableName, const std::string& columnName) {
22269
std::stringstream ss;
22270
ss << "ALTER TABLE " << streaming_identifier(tableName) << " DROP COLUMN "
22271
<< streaming_identifier(columnName) << std::flush;
22272
perform_void_exec(db, ss.str());
22273
}
22274
#endif
22275
22276
template<class Table>
22277
void drop_create_with_loss(sqlite3* db, const Table& table) {
22278
// eliminated all transaction handling
22279
this->drop_table_internal(db, table.name, false);
22280
this->create_table(db, table.name, table);
22281
}
22282
22283
template<class Table>
22284
void backup_table(sqlite3* db, const Table& table, const std::vector<const table_xinfo*>& columnsToIgnore) {
22285
22286
// here we copy source table to another with a name with '_backup' suffix, but in case table with such
22287
// a name already exists we append suffix 1, then 2, etc until we find a free name..
22288
auto backupTableName = table.name + "_backup";
22289
if (this->table_exists(db, backupTableName)) {
22290
int suffix = 1;
22291
do {
22292
std::stringstream ss;
22293
ss << suffix << std::flush;
22294
auto anotherBackupTableName = backupTableName + ss.str();
22295
if (!this->table_exists(db, anotherBackupTableName)) {
22296
backupTableName = std::move(anotherBackupTableName);
22297
break;
22298
}
22299
++suffix;
22300
} while (true);
22301
}
22302
this->create_table(db, backupTableName, table);
22303
22304
this->copy_table(db, table.name, backupTableName, table, columnsToIgnore);
22305
22306
this->drop_table_internal(db, table.name, false);
22307
22308
this->rename_table(db, backupTableName, table.name);
22309
}
22310
22311
template<class O>
22312
void assert_mapped_type() const {
22313
static_assert(tuple_has_type<db_objects_type, O, object_type_t>::value,
22314
"type is not mapped to storage");
22315
}
22316
22317
template<class O>
22318
void assert_updatable_type() const {
22319
#if defined(SQLITE_ORM_FOLD_EXPRESSIONS_SUPPORTED)
22320
using Table = storage_pick_table_t<O, db_objects_type>;
22321
using elements_type = elements_type_t<Table>;
22322
using col_index_sequence = filter_tuple_sequence_t<elements_type, is_column>;
22323
using pk_index_sequence = filter_tuple_sequence_t<elements_type, is_primary_key>;
22324
using pkcol_index_sequence = col_index_sequence_with<elements_type, is_primary_key>;
22325
constexpr size_t dedicatedPrimaryKeyColumnsCount =
22326
nested_tuple_size_for_t<columns_tuple_t, elements_type, pk_index_sequence>::value;
22327
22328
constexpr size_t primaryKeyColumnsCount =
22329
dedicatedPrimaryKeyColumnsCount + pkcol_index_sequence::size();
22330
constexpr ptrdiff_t nonPrimaryKeysColumnsCount = col_index_sequence::size() - primaryKeyColumnsCount;
22331
static_assert(primaryKeyColumnsCount > 0, "A table without primary keys cannot be updated");
22332
static_assert(
22333
nonPrimaryKeysColumnsCount > 0,
22334
"A table with only primary keys cannot be updated. You need at least 1 non-primary key column");
22335
#endif
22336
}
22337
22338
template<class O,
22339
class Table = storage_pick_table_t<O, db_objects_type>,
22340
std::enable_if_t<Table::is_without_rowid::value, bool> = true>
22341
void assert_insertable_type() const {}
22342
22343
template<class O,
22344
class Table = storage_pick_table_t<O, db_objects_type>,
22345
std::enable_if_t<!Table::is_without_rowid::value, bool> = true>
22346
void assert_insertable_type() const {
22347
using elements_type = elements_type_t<Table>;
22348
using pkcol_index_sequence = col_index_sequence_with<elements_type, is_primary_key>;
22349
static_assert(
22350
count_filtered_tuple<elements_type, is_primary_key_insertable, pkcol_index_sequence>::value <= 1,
22351
"Attempting to execute 'insert' request into an noninsertable table was detected. "
22352
"Insertable table cannot contain > 1 primary keys. Please use 'replace' instead of "
22353
"'insert', or you can use 'insert' with explicit column listing.");
22354
static_assert(count_filtered_tuple<elements_type,
22355
check_if_not<is_primary_key_insertable>::template fn,
22356
pkcol_index_sequence>::value == 0,
22357
"Attempting to execute 'insert' request into an noninsertable table was detected. "
22358
"Insertable table cannot contain non-standard primary keys. Please use 'replace' instead "
22359
"of 'insert', or you can use 'insert' with explicit column listing.");
22360
}
22361
22362
template<class O>
22363
auto& get_table() const {
22364
return pick_table<O>(this->db_objects);
22365
}
22366
22367
template<class O>
22368
auto& get_table() {
22369
return pick_table<O>(this->db_objects);
22370
}
22371
22372
public:
22373
template<class T, class O = mapped_type_proxy_t<T>, class... Args>
22374
mapped_view<O, self, Args...> iterate(Args&&... args) {
22375
this->assert_mapped_type<O>();
22376
22377
auto con = this->get_connection();
22378
return {*this, std::move(con), std::forward<Args>(args)...};
22379
}
22380
22381
#ifdef SQLITE_ORM_WITH_CPP20_ALIASES
22382
template<orm_refers_to_table auto mapped, class... Args>
22383
auto iterate(Args&&... args) {
22384
return this->iterate<decltype(mapped)>(std::forward<Args>(args)...);
22385
}
22386
#endif
22387
22388
#if defined(SQLITE_ORM_SENTINEL_BASED_FOR_SUPPORTED) && defined(SQLITE_ORM_DEFAULT_COMPARISONS_SUPPORTED)
22389
template<class Select>
22390
#ifdef SQLITE_ORM_CONCEPTS_SUPPORTED
22391
requires (is_select_v<Select>)
22392
#endif
22393
result_set_view<Select, db_objects_type> iterate(Select expression) {
22394
expression.highest_level = true;
22395
auto con = this->get_connection();
22396
return {this->db_objects, std::move(con), std::move(expression)};
22397
}
22398
22399
#if (SQLITE_VERSION_NUMBER >= 3008003) && defined(SQLITE_ORM_WITH_CTE)
22400
template<class... CTEs, class E>
22401
#ifdef SQLITE_ORM_CONCEPTS_SUPPORTED
22402
requires (is_select_v<E>)
22403
#endif
22404
result_set_view<with_t<E, CTEs...>, db_objects_type> iterate(with_t<E, CTEs...> expression) {
22405
auto con = this->get_connection();
22406
return {this->db_objects, std::move(con), std::move(expression)};
22407
}
22408
#endif
22409
#endif
22410
22411
/**
22412
* Delete from routine.
22413
* O is an object's type. Must be specified explicitly.
22414
* @param args optional conditions: `where`, `join` etc
22415
* @example: storage.remove_all<User>(); - DELETE FROM users
22416
* @example: storage.remove_all<User>(where(in(&User::id, {5, 6, 7}))); - DELETE FROM users WHERE id IN (5, 6, 7)
22417
*/
22418
template<class O, class... Args>
22419
void remove_all(Args&&... args) {
22420
this->assert_mapped_type<O>();
22421
auto statement = this->prepare(sqlite_orm::remove_all<O>(std::forward<Args>(args)...));
22422
this->execute(statement);
22423
}
22424
22425
#ifdef SQLITE_ORM_WITH_CPP20_ALIASES
22426
template<orm_table_reference auto table, class... Args>
22427
void remove_all(Args&&... args) {
22428
return this->remove_all<auto_decay_table_ref_t<table>>(std::forward<Args>(args)...);
22429
}
22430
#endif
22431
22432
/**
22433
* Delete routine.
22434
* O is an object's type. Must be specified explicitly.
22435
* @param ids ids of object to be removed.
22436
*/
22437
template<class O, class... Ids>
22438
void remove(Ids... ids) {
22439
this->assert_mapped_type<O>();
22440
auto statement = this->prepare(sqlite_orm::remove<O>(std::forward<Ids>(ids)...));
22441
this->execute(statement);
22442
}
22443
22444
#ifdef SQLITE_ORM_WITH_CPP20_ALIASES
22445
template<orm_table_reference auto table, class... Ids>
22446
void remove(Ids... ids) {
22447
return this->remove<auto_decay_table_ref_t<table>>(std::forward<Ids>(ids)...);
22448
}
22449
#endif
22450
22451
/**
22452
* Update routine. Sets all non primary key fields where primary key is equal.
22453
* O is an object type. May be not specified explicitly cause it can be deduced by
22454
* compiler from first parameter.
22455
* @param o object to be updated.
22456
*/
22457
template<class O>
22458
void update(const O& o) {
22459
this->assert_mapped_type<O>();
22460
auto statement = this->prepare(sqlite_orm::update(std::ref(o)));
22461
this->execute(statement);
22462
}
22463
22464
template<class S, class... Wargs>
22465
void update_all(S set, Wargs... wh) {
22466
static_assert(internal::is_set<S>::value,
22467
"first argument in update_all can be either set or dynamic_set");
22468
auto statement = this->prepare(sqlite_orm::update_all(std::move(set), std::forward<Wargs>(wh)...));
22469
this->execute(statement);
22470
}
22471
22472
protected:
22473
template<class F, class O, class... Args>
22474
std::string group_concat_internal(F O::* m, std::unique_ptr<std::string> y, Args&&... args) {
22475
this->assert_mapped_type<O>();
22476
std::vector<std::string> rows;
22477
if (y) {
22478
rows = this->select(sqlite_orm::group_concat(m, std::move(*y)), std::forward<Args>(args)...);
22479
} else {
22480
rows = this->select(sqlite_orm::group_concat(m), std::forward<Args>(args)...);
22481
}
22482
if (!rows.empty()) {
22483
return std::move(rows.front());
22484
} else {
22485
return {};
22486
}
22487
}
22488
22489
public:
22490
/**
22491
* SELECT * routine.
22492
* T is an explicitly specified object mapped to a storage or a table alias.
22493
* R is an explicit return type. This type must have `push_back(O &&)` function. Defaults to `std::vector<O>`
22494
* @return All objects of type O stored in database at the moment in `R`.
22495
* @example: storage.get_all<User, std::list<User>>(); - SELECT * FROM users
22496
* @example: storage.get_all<User, std::list<User>>(where(like(&User::name, "N%")), order_by(&User::id)); - SELECT * FROM users WHERE name LIKE 'N%' ORDER BY id
22497
*/
22498
template<class T, class R = std::vector<mapped_type_proxy_t<T>>, class... Args>
22499
R get_all(Args&&... args) {
22500
this->assert_mapped_type<mapped_type_proxy_t<T>>();
22501
auto statement = this->prepare(sqlite_orm::get_all<T, R>(std::forward<Args>(args)...));
22502
return this->execute(statement);
22503
}
22504
22505
#ifdef SQLITE_ORM_WITH_CPP20_ALIASES
22506
/**
22507
* SELECT * routine.
22508
* `mapped` is an explicitly specified table reference or table alias of an object to be extracted.
22509
* `R` is the container return type, which must have a `R::push_back(O&&)` method, and defaults to `std::vector<O>`
22510
* @return All objects stored in database.
22511
* @example: storage.get_all<sqlite_schema, std::list<sqlite_master>>(); - SELECT sqlite_schema.* FROM sqlite_master AS sqlite_schema
22512
*/
22513
template<orm_refers_to_table auto mapped,
22514
class R = std::vector<mapped_type_proxy_t<decltype(mapped)>>,
22515
class... Args>
22516
R get_all(Args&&... args) {
22517
this->assert_mapped_type<mapped_type_proxy_t<decltype(mapped)>>();
22518
auto statement = this->prepare(sqlite_orm::get_all<mapped, R>(std::forward<Args>(args)...));
22519
return this->execute(statement);
22520
}
22521
#endif
22522
22523
/**
22524
* SELECT * routine.
22525
* O is an object type to be extracted. Must be specified explicitly.
22526
* R is a container type. std::vector<std::unique_ptr<O>> is default
22527
* @return All objects of type O as std::unique_ptr<O> stored in database at the moment.
22528
* @example: storage.get_all_pointer<User, std::list<std::unique_ptr<User>>>(); - SELECT * FROM users
22529
* @example: storage.get_all_pointer<User, std::list<std::unique_ptr<User>>>(where(length(&User::name) > 6)); - SELECT * FROM users WHERE LENGTH(name) > 6
22530
*/
22531
template<class O, class R = std::vector<std::unique_ptr<O>>, class... Args>
22532
auto get_all_pointer(Args&&... args) {
22533
this->assert_mapped_type<O>();
22534
auto statement = this->prepare(sqlite_orm::get_all_pointer<O, R>(std::forward<Args>(args)...));
22535
return this->execute(statement);
22536
}
22537
22538
#ifdef SQLITE_ORM_WITH_CPP20_ALIASES
22539
template<orm_table_reference auto table,
22540
class R = std::vector<std::unique_ptr<auto_decay_table_ref_t<table>>>,
22541
class... Args>
22542
auto get_all_pointer(Args&&... args) {
22543
return this->get_all_pointer<auto_decay_table_ref_t<table>>(std::forward<Args>(args)...);
22544
}
22545
#endif
22546
22547
#ifdef SQLITE_ORM_OPTIONAL_SUPPORTED
22548
/**
22549
* SELECT * routine.
22550
* O is an object type to be extracted. Must be specified explicitly.
22551
* R is a container type. std::vector<std::optional<O>> is default
22552
* @return All objects of type O as std::optional<O> stored in database at the moment.
22553
* @example: storage.get_all_optional<User, std::list<std::optional<O>>>(); - SELECT * FROM users
22554
* @example: storage.get_all_optional<User, std::list<std::optional<O>>>(where(length(&User::name) > 6)); - SELECT * FROM users WHERE LENGTH(name) > 6
22555
*/
22556
template<class O, class R = std::vector<std::optional<O>>, class... Args>
22557
auto get_all_optional(Args&&... conditions) {
22558
this->assert_mapped_type<O>();
22559
auto statement = this->prepare(sqlite_orm::get_all_optional<O, R>(std::forward<Args>(conditions)...));
22560
return this->execute(statement);
22561
}
22562
#endif
22563
22564
#ifdef SQLITE_ORM_WITH_CPP20_ALIASES
22565
template<orm_table_reference auto table,
22566
class R = std::vector<std::optional<auto_decay_table_ref_t<table>>>,
22567
class... Args>
22568
auto get_all_optional(Args&&... conditions) {
22569
return this->get_all_optional<auto_decay_table_ref_t<table>>(std::forward<Args>(conditions)...);
22570
}
22571
#endif
22572
22573
/**
22574
* Select * by id routine.
22575
* throws std::system_error{orm_error_code::not_found} if object not found with given
22576
* id. throws std::system_error with orm_error_category in case of db error. O is an object type to be
22577
* extracted. Must be specified explicitly.
22578
* @return Object of type O where id is equal parameter passed or throws
22579
* `std::system_error{orm_error_code::not_found}` if there is no object with such id.
22580
*/
22581
template<class O, class... Ids>
22582
O get(Ids... ids) {
22583
this->assert_mapped_type<O>();
22584
auto statement = this->prepare(sqlite_orm::get<O>(std::forward<Ids>(ids)...));
22585
return this->execute(statement);
22586
}
22587
22588
#ifdef SQLITE_ORM_WITH_CPP20_ALIASES
22589
template<orm_table_reference auto table, class... Ids>
22590
auto get(Ids... ids) {
22591
return this->get<auto_decay_table_ref_t<table>>(std::forward<Ids>(ids)...);
22592
}
22593
#endif
22594
22595
/**
22596
* The same as `get` function but doesn't throw an exception if noting found but returns std::unique_ptr
22597
* with null value. throws std::system_error in case of db error.
22598
*/
22599
template<class O, class... Ids>
22600
std::unique_ptr<O> get_pointer(Ids... ids) {
22601
this->assert_mapped_type<O>();
22602
auto statement = this->prepare(sqlite_orm::get_pointer<O>(std::forward<Ids>(ids)...));
22603
return this->execute(statement);
22604
}
22605
22606
#ifdef SQLITE_ORM_WITH_CPP20_ALIASES
22607
template<orm_table_reference auto table, class... Ids>
22608
auto get_pointer(Ids... ids) {
22609
return this->get_pointer<auto_decay_table_ref_t<table>>(std::forward<Ids>(ids)...);
22610
}
22611
#endif
22612
22613
/**
22614
* A previous version of get_pointer() that returns a shared_ptr
22615
* instead of a unique_ptr. New code should prefer get_pointer()
22616
* unless the data needs to be shared.
22617
*
22618
* @note
22619
* Most scenarios don't need shared ownership of data, so we should prefer
22620
* unique_ptr when possible. It's more efficient, doesn't require atomic
22621
* ops for a reference count (which can cause major slowdowns on
22622
* weakly-ordered platforms like ARM), and can be easily promoted to a
22623
* shared_ptr, exactly like we're doing here.
22624
* (Conversely, you _can't_ go from shared back to unique.)
22625
*/
22626
template<class O, class... Ids>
22627
std::shared_ptr<O> get_no_throw(Ids... ids) {
22628
return std::shared_ptr<O>(this->get_pointer<O>(std::forward<Ids>(ids)...));
22629
}
22630
22631
#ifdef SQLITE_ORM_OPTIONAL_SUPPORTED
22632
/**
22633
* The same as `get` function but doesn't throw an exception if noting found but
22634
* returns an empty std::optional. throws std::system_error in case of db error.
22635
*/
22636
template<class O, class... Ids>
22637
std::optional<O> get_optional(Ids... ids) {
22638
this->assert_mapped_type<O>();
22639
auto statement = this->prepare(sqlite_orm::get_optional<O>(std::forward<Ids>(ids)...));
22640
return this->execute(statement);
22641
}
22642
#endif // SQLITE_ORM_OPTIONAL_SUPPORTED
22643
22644
#ifdef SQLITE_ORM_WITH_CPP20_ALIASES
22645
template<orm_table_reference auto table, class... Ids>
22646
auto get_optional(Ids... ids) {
22647
return this->get_optional<auto_decay_table_ref_t<table>>(std::forward<Ids>(ids)...);
22648
}
22649
#endif
22650
22651
/**
22652
* SELECT COUNT(*) https://www.sqlite.org/lang_aggfunc.html#count
22653
* @return Number of O object in table.
22654
*/
22655
template<class O, class... Args>
22656
int count(Args&&... args) {
22657
using R = mapped_type_proxy_t<O>;
22658
this->assert_mapped_type<R>();
22659
auto rows = this->select(sqlite_orm::count<R>(), std::forward<Args>(args)...);
22660
if (!rows.empty()) {
22661
return rows.front();
22662
} else {
22663
return 0;
22664
}
22665
}
22666
22667
#ifdef SQLITE_ORM_WITH_CPP20_ALIASES
22668
template<orm_refers_to_table auto mapped, class... Args>
22669
int count(Args&&... args) {
22670
return this->count<auto_decay_table_ref_t<mapped>>(std::forward<Args>(args)...);
22671
}
22672
#endif
22673
22674
/**
22675
* SELECT COUNT(X) https://www.sqlite.org/lang_aggfunc.html#count
22676
* @param m member pointer to class mapped to the storage.
22677
* @return count of `m` values from database.
22678
*/
22679
template<class F,
22680
class... Args,
22681
std::enable_if_t<polyfill::disjunction<std::is_member_pointer<F>, is_column_pointer<F>>::value,
22682
bool> = true>
22683
int count(F field, Args&&... args) {
22684
this->assert_mapped_type<table_type_of_t<F>>();
22685
auto rows = this->select(sqlite_orm::count(std::move(field)), std::forward<Args>(args)...);
22686
if (!rows.empty()) {
22687
return rows.front();
22688
} else {
22689
return 0;
22690
}
22691
}
22692
22693
/**
22694
* AVG(X) query. https://www.sqlite.org/lang_aggfunc.html#avg
22695
* @param m is a class member pointer (the same you passed into make_column).
22696
* @return average value from database.
22697
*/
22698
template<class F,
22699
class... Args,
22700
std::enable_if_t<polyfill::disjunction<std::is_member_pointer<F>, is_column_pointer<F>>::value,
22701
bool> = true>
22702
double avg(F field, Args&&... args) {
22703
this->assert_mapped_type<table_type_of_t<F>>();
22704
auto rows = this->select(sqlite_orm::avg(std::move(field)), std::forward<Args>(args)...);
22705
if (!rows.empty()) {
22706
return rows.front();
22707
} else {
22708
return 0;
22709
}
22710
}
22711
22712
template<class F,
22713
std::enable_if_t<polyfill::disjunction<std::is_member_pointer<F>, is_column_pointer<F>>::value,
22714
bool> = true>
22715
std::string group_concat(F field) {
22716
return this->group_concat_internal(std::move(field), {});
22717
}
22718
22719
/**
22720
* GROUP_CONCAT(X) query. https://www.sqlite.org/lang_aggfunc.html#groupconcat
22721
* @param m is a class member pointer (the same you passed into make_column).
22722
* @return group_concat query result.
22723
*/
22724
template<class F,
22725
class... Args,
22726
class Tuple = std::tuple<Args...>,
22727
std::enable_if_t<std::tuple_size<Tuple>::value >= 1, bool> = true,
22728
std::enable_if_t<polyfill::disjunction<std::is_member_pointer<F>, is_column_pointer<F>>::value,
22729
bool> = true>
22730
std::string group_concat(F field, Args&&... args) {
22731
return this->group_concat_internal(std::move(field), {}, std::forward<Args>(args)...);
22732
}
22733
22734
/**
22735
* GROUP_CONCAT(X, Y) query. https://www.sqlite.org/lang_aggfunc.html#groupconcat
22736
* @param m is a class member pointer (the same you passed into make_column).
22737
* @return group_concat query result.
22738
*/
22739
template<class F,
22740
class... Args,
22741
std::enable_if_t<polyfill::disjunction<std::is_member_pointer<F>, is_column_pointer<F>>::value,
22742
bool> = true>
22743
std::string group_concat(F field, std::string y, Args&&... args) {
22744
return this->group_concat_internal(std::move(field),
22745
std::make_unique<std::string>(std::move(y)),
22746
std::forward<Args>(args)...);
22747
}
22748
22749
template<class F,
22750
class... Args,
22751
std::enable_if_t<polyfill::disjunction<std::is_member_pointer<F>, is_column_pointer<F>>::value,
22752
bool> = true>
22753
std::string group_concat(F field, const char* y, Args&&... args) {
22754
std::unique_ptr<std::string> str;
22755
if (y) {
22756
str = std::make_unique<std::string>(y);
22757
} else {
22758
str = std::make_unique<std::string>();
22759
}
22760
return this->group_concat_internal(std::move(field), std::move(str), std::forward<Args>(args)...);
22761
}
22762
22763
/**
22764
* MAX(x) query.
22765
* @param m is a class member pointer (the same you passed into make_column).
22766
* @return std::unique_ptr with max value or null if sqlite engine returned null.
22767
*/
22768
template<class F,
22769
class... Args,
22770
class R = column_result_of_t<db_objects_type, F>,
22771
std::enable_if_t<polyfill::disjunction<std::is_member_pointer<F>, is_column_pointer<F>>::value,
22772
bool> = true>
22773
std::unique_ptr<R> max(F field, Args&&... args) {
22774
this->assert_mapped_type<table_type_of_t<F>>();
22775
auto rows = this->select(sqlite_orm::max(std::move(field)), std::forward<Args>(args)...);
22776
if (!rows.empty()) {
22777
return std::move(rows.front());
22778
} else {
22779
return {};
22780
}
22781
}
22782
22783
/**
22784
* MIN(x) query.
22785
* @param m is a class member pointer (the same you passed into make_column).
22786
* @return std::unique_ptr with min value or null if sqlite engine returned null.
22787
*/
22788
template<class F,
22789
class... Args,
22790
class R = column_result_of_t<db_objects_type, F>,
22791
std::enable_if_t<polyfill::disjunction<std::is_member_pointer<F>, is_column_pointer<F>>::value,
22792
bool> = true>
22793
std::unique_ptr<R> min(F field, Args&&... args) {
22794
this->assert_mapped_type<table_type_of_t<F>>();
22795
auto rows = this->select(sqlite_orm::min(std::move(field)), std::forward<Args>(args)...);
22796
if (!rows.empty()) {
22797
return std::move(rows.front());
22798
} else {
22799
return {};
22800
}
22801
}
22802
22803
/**
22804
* SUM(x) query.
22805
* @param m is a class member pointer (the same you passed into make_column).
22806
* @return std::unique_ptr with sum value or null if sqlite engine returned null.
22807
*/
22808
template<class F,
22809
class... Args,
22810
class R = column_result_of_t<db_objects_type, F>,
22811
std::enable_if_t<polyfill::disjunction<std::is_member_pointer<F>, is_column_pointer<F>>::value,
22812
bool> = true>
22813
std::unique_ptr<R> sum(F field, Args&&... args) {
22814
this->assert_mapped_type<table_type_of_t<F>>();
22815
std::vector<std::unique_ptr<double>> rows =
22816
this->select(sqlite_orm::sum(std::move(field)), std::forward<Args>(args)...);
22817
if (!rows.empty()) {
22818
if (rows.front()) {
22819
return std::make_unique<R>(std::move(*rows.front()));
22820
} else {
22821
return {};
22822
}
22823
} else {
22824
return {};
22825
}
22826
}
22827
22828
/**
22829
* TOTAL(x) query.
22830
* @param m is a class member pointer (the same you passed into make_column).
22831
* @return total value (the same as SUM but not nullable. More details here
22832
* https://www.sqlite.org/lang_aggfunc.html)
22833
*/
22834
template<class F,
22835
class... Args,
22836
std::enable_if_t<polyfill::disjunction<std::is_member_pointer<F>, is_column_pointer<F>>::value,
22837
bool> = true>
22838
double total(F field, Args&&... args) {
22839
this->assert_mapped_type<table_type_of_t<F>>();
22840
auto rows = this->select(sqlite_orm::total(std::move(field)), std::forward<Args>(args)...);
22841
if (!rows.empty()) {
22842
return std::move(rows.front());
22843
} else {
22844
return {};
22845
}
22846
}
22847
22848
/**
22849
* Select a single column into std::vector<T> or multiple columns into std::vector<std::tuple<...>>.
22850
* For a single column use `auto rows = storage.select(&User::id, where(...));
22851
* For multicolumns use `auto rows = storage.select(columns(&User::id, &User::name), where(...));
22852
*/
22853
template<class T, class... Args>
22854
auto select(T m, Args... args) {
22855
static_assert(!is_compound_operator_v<T> || sizeof...(Args) == 0,
22856
"Cannot use args with a compound operator");
22857
auto statement = this->prepare(sqlite_orm::select(std::move(m), std::forward<Args>(args)...));
22858
return this->execute(statement);
22859
}
22860
22861
#if (SQLITE_VERSION_NUMBER >= 3008003) && defined(SQLITE_ORM_WITH_CTE)
22862
/**
22863
* Using a CTE, select a single column into std::vector<T> or multiple columns into std::vector<std::tuple<...>>.
22864
*/
22865
template<class CTE, class E>
22866
auto with(CTE cte, E expression) {
22867
auto statement = this->prepare(sqlite_orm::with(std::move(cte), std::move(expression)));
22868
return this->execute(statement);
22869
}
22870
22871
/**
22872
* Using a CTE, select a single column into std::vector<T> or multiple columns into std::vector<std::tuple<...>>.
22873
*/
22874
template<class... CTEs, class E>
22875
auto with(common_table_expressions<CTEs...> cte, E expression) {
22876
auto statement = this->prepare(sqlite_orm::with(std::move(cte), std::move(expression)));
22877
return this->execute(statement);
22878
}
22879
22880
/**
22881
* Using a CTE, select a single column into std::vector<T> or multiple columns into std::vector<std::tuple<...>>.
22882
*/
22883
template<class CTE, class E>
22884
auto with_recursive(CTE cte, E expression) {
22885
auto statement = this->prepare(sqlite_orm::with_recursive(std::move(cte), std::move(expression)));
22886
return this->execute(statement);
22887
}
22888
22889
/**
22890
* Using a CTE, select a single column into std::vector<T> or multiple columns into std::vector<std::tuple<...>>.
22891
*/
22892
template<class... CTEs, class E>
22893
auto with_recursive(common_table_expressions<CTEs...> cte, E expression) {
22894
auto statement = this->prepare(sqlite_orm::with_recursive(std::move(cte), std::move(expression)));
22895
return this->execute(statement);
22896
}
22897
#endif
22898
22899
template<class T, satisfies<is_prepared_statement, T> = true>
22900
std::string dump(const T& preparedStatement, bool parametrized = true) const {
22901
return this->dump_highest_level(preparedStatement.expression, parametrized);
22902
}
22903
22904
template<class E,
22905
class Ex = polyfill::remove_cvref_t<E>,
22906
std::enable_if_t<!is_prepared_statement<Ex>::value && !is_mapped<db_objects_type, Ex>::value,
22907
bool> = true>
22908
std::string dump(E&& expression, bool parametrized = false) const {
22909
static_assert(is_preparable_v<self, Ex>, "Expression must be a high-level statement");
22910
22911
decltype(auto) e2 = static_if<is_select<Ex>::value>(
22912
[](auto expression) -> auto {
22913
expression.highest_level = true;
22914
return expression;
22915
},
22916
[](const auto& expression) -> decltype(auto) {
22917
return (expression);
22918
})(std::forward<E>(expression));
22919
return this->dump_highest_level(e2, parametrized);
22920
}
22921
22922
/**
22923
* Returns a string representation of object of a class mapped to the storage.
22924
* Type of string has json-like style.
22925
*/
22926
template<class O, satisfies<is_mapped, db_objects_type, O> = true>
22927
std::string dump(const O& object) const {
22928
auto& table = this->get_table<O>();
22929
std::stringstream ss;
22930
ss << "{ ";
22931
table.for_each_column([&ss, &object, first = true](auto& column) mutable {
22932
using field_type = field_type_t<std::remove_reference_t<decltype(column)>>;
22933
static constexpr std::array<const char*, 2> sep = {", ", ""};
22934
22935
ss << sep[std::exchange(first, false)] << column.name << " : '"
22936
<< field_printer<field_type>{}(polyfill::invoke(column.member_pointer, object)) << "'";
22937
});
22938
ss << " }";
22939
return ss.str();
22940
}
22941
22942
/**
22943
* This is REPLACE (INSERT OR REPLACE) function.
22944
* Also if you need to insert value with knows id you should
22945
* also you this function instead of insert cause inserts ignores
22946
* id and creates own one.
22947
*/
22948
template<class O>
22949
void replace(const O& o) {
22950
this->assert_mapped_type<O>();
22951
auto statement = this->prepare(sqlite_orm::replace(std::ref(o)));
22952
this->execute(statement);
22953
}
22954
22955
template<class It, class Projection = polyfill::identity>
22956
void replace_range(It from, It to, Projection project = {}) {
22957
using O = std::decay_t<decltype(polyfill::invoke(project, *from))>;
22958
this->assert_mapped_type<O>();
22959
if (from == to) {
22960
return;
22961
}
22962
22963
auto statement =
22964
this->prepare(sqlite_orm::replace_range(std::move(from), std::move(to), std::move(project)));
22965
this->execute(statement);
22966
}
22967
22968
template<class O, class It, class Projection = polyfill::identity>
22969
void replace_range(It from, It to, Projection project = {}) {
22970
this->assert_mapped_type<O>();
22971
if (from == to) {
22972
return;
22973
}
22974
22975
auto statement =
22976
this->prepare(sqlite_orm::replace_range<O>(std::move(from), std::move(to), std::move(project)));
22977
this->execute(statement);
22978
}
22979
22980
template<class O, class... Cols>
22981
int insert(const O& o, columns_t<Cols...> cols) {
22982
static_assert(cols.count > 0, "Use insert or replace with 1 argument instead");
22983
this->assert_mapped_type<O>();
22984
auto statement = this->prepare(sqlite_orm::insert(std::ref(o), std::move(cols)));
22985
return int(this->execute(statement));
22986
}
22987
22988
/**
22989
* Insert routine. Inserts object with all non primary key fields in passed object. Id of passed
22990
* object doesn't matter.
22991
* @return id of just created object.
22992
*/
22993
template<class O>
22994
int insert(const O& o) {
22995
this->assert_mapped_type<O>();
22996
this->assert_insertable_type<O>();
22997
auto statement = this->prepare(sqlite_orm::insert(std::ref(o)));
22998
return int(this->execute(statement));
22999
}
23000
23001
/**
23002
* Raw insert routine. Use this if `insert` with object does not fit you. This insert is designed to be able
23003
* to call any type of `INSERT` query with no limitations.
23004
* @example
23005
* ```sql
23006
* INSERT INTO users (id, name) VALUES(5, 'Little Mix')
23007
* ```
23008
* will be
23009
* ```c++
23010
* storage.insert(into<User>, columns(&User::id, &User::name), values(std::make_tuple(5, "Little Mix")));
23011
* ```
23012
* One more example:
23013
* ```sql
23014
* INSERT INTO singers (name) VALUES ('Sofia Reyes')('Kungs')
23015
* ```
23016
* will be
23017
* ```c++
23018
* storage.insert(into<Singer>(), columns(&Singer::name), values(std::make_tuple("Sofia Reyes"), std::make_tuple("Kungs")));
23019
* ```
23020
* One can use `default_values` to add `DEFAULT VALUES` modifier:
23021
* ```sql
23022
* INSERT INTO users DEFAULT VALUES
23023
* ```
23024
* will be
23025
* ```c++
23026
* storage.insert(into<Singer>(), default_values());
23027
* ```
23028
* Also one can use `INSERT OR ABORT`/`INSERT OR FAIL`/`INSERT OR IGNORE`/`INSERT OR REPLACE`/`INSERT ROLLBACK`:
23029
* ```c++
23030
* storage.insert(or_ignore(), into<Singer>(), columns(&Singer::name), values(std::make_tuple("Sofia Reyes"), std::make_tuple("Kungs")));
23031
* storage.insert(or_rollback(), into<Singer>(), default_values());
23032
* storage.insert(or_abort(), into<User>, columns(&User::id, &User::name), values(std::make_tuple(5, "Little Mix")));
23033
* ```
23034
*/
23035
template<class... Args>
23036
void insert(Args... args) {
23037
auto statement = this->prepare(sqlite_orm::insert(std::forward<Args>(args)...));
23038
this->execute(statement);
23039
}
23040
23041
/**
23042
* Raw replace statement creation routine. Use this if `replace` with object does not fit you. This replace is designed to be able
23043
* to call any type of `REPLACE` query with no limitations. Actually this is the same query as raw insert except `OR...` option existance.
23044
* @example
23045
* ```sql
23046
* REPLACE INTO users (id, name) VALUES(5, 'Little Mix')
23047
* ```
23048
* will be
23049
* ```c++
23050
* storage.prepare(replace(into<User>, columns(&User::id, &User::name), values(std::make_tuple(5, "Little Mix"))));
23051
* ```
23052
* One more example:
23053
* ```sql
23054
* REPLACE INTO singers (name) VALUES ('Sofia Reyes')('Kungs')
23055
* ```
23056
* will be
23057
* ```c++
23058
* storage.prepare(replace(into<Singer>(), columns(&Singer::name), values(std::make_tuple("Sofia Reyes"), std::make_tuple("Kungs"))));
23059
* ```
23060
* One can use `default_values` to add `DEFAULT VALUES` modifier:
23061
* ```sql
23062
* REPLACE INTO users DEFAULT VALUES
23063
* ```
23064
* will be
23065
* ```c++
23066
* storage.prepare(replace(into<Singer>(), default_values()));
23067
* ```
23068
*/
23069
template<class... Args>
23070
void replace(Args... args) {
23071
auto statement = this->prepare(sqlite_orm::replace(std::forward<Args>(args)...));
23072
this->execute(statement);
23073
}
23074
23075
template<class It, class Projection = polyfill::identity>
23076
void insert_range(It from, It to, Projection project = {}) {
23077
using O = std::decay_t<decltype(polyfill::invoke(std::declval<Projection>(), *std::declval<It>()))>;
23078
this->assert_mapped_type<O>();
23079
this->assert_insertable_type<O>();
23080
if (from == to) {
23081
return;
23082
}
23083
auto statement =
23084
this->prepare(sqlite_orm::insert_range(std::move(from), std::move(to), std::move(project)));
23085
this->execute(statement);
23086
}
23087
23088
template<class O, class It, class Projection = polyfill::identity>
23089
void insert_range(It from, It to, Projection project = {}) {
23090
this->assert_mapped_type<O>();
23091
this->assert_insertable_type<O>();
23092
if (from == to) {
23093
return;
23094
}
23095
auto statement =
23096
this->prepare(sqlite_orm::insert_range<O>(std::move(from), std::move(to), std::move(project)));
23097
this->execute(statement);
23098
}
23099
23100
/**
23101
* Change table name inside storage's schema info. This function does not
23102
* affect database
23103
*/
23104
template<class O>
23105
void rename_table(std::string name) {
23106
this->assert_mapped_type<O>();
23107
auto& table = this->get_table<O>();
23108
table.name = std::move(name);
23109
}
23110
23111
using storage_base::rename_table;
23112
23113
/**
23114
* Get table's name stored in storage's schema info. This function does not call
23115
* any SQLite queries
23116
*/
23117
template<class O>
23118
const std::string& tablename() const {
23119
this->assert_mapped_type<O>();
23120
auto& table = this->get_table<O>();
23121
return table.name;
23122
}
23123
23124
template<class F, class O>
23125
[[deprecated("Use the more accurately named function `find_column_name()`")]] const std::string*
23126
column_name(F O::* memberPointer) const {
23127
return internal::find_column_name(this->db_objects, memberPointer);
23128
}
23129
23130
template<class F, class O>
23131
const std::string* find_column_name(F O::* memberPointer) const {
23132
return internal::find_column_name(this->db_objects, memberPointer);
23133
}
23134
23135
protected:
23136
template<class M>
23137
sync_schema_result schema_status(const virtual_table_t<M>&, sqlite3*, bool, bool*) {
23138
return sync_schema_result::already_in_sync;
23139
}
23140
23141
template<class T, class... S>
23142
sync_schema_result schema_status(const trigger_t<T, S...>&, sqlite3*, bool, bool*) {
23143
return sync_schema_result::already_in_sync;
23144
}
23145
23146
template<class... Cols>
23147
sync_schema_result schema_status(const index_t<Cols...>&, sqlite3*, bool, bool*) {
23148
return sync_schema_result::already_in_sync;
23149
}
23150
23151
template<class T, bool WithoutRowId, class... Cs>
23152
sync_schema_result schema_status(const table_t<T, WithoutRowId, Cs...>& table,
23153
sqlite3* db,
23154
bool preserve,
23155
bool* attempt_to_preserve) {
23156
if (attempt_to_preserve) {
23157
*attempt_to_preserve = true;
23158
}
23159
23160
auto dbTableInfo = this->pragma.table_xinfo(table.name);
23161
auto res = sync_schema_result::already_in_sync;
23162
23163
// first let's see if table with such name exists..
23164
auto gottaCreateTable = !this->table_exists(db, table.name);
23165
if (!gottaCreateTable) {
23166
23167
// get table info provided in `make_table` call..
23168
auto storageTableInfo = table.get_table_info();
23169
23170
// this vector will contain pointers to columns that gotta be added..
23171
std::vector<const table_xinfo*> columnsToAdd;
23172
23173
if (calculate_remove_add_columns(columnsToAdd, storageTableInfo, dbTableInfo)) {
23174
gottaCreateTable = true;
23175
}
23176
23177
if (!gottaCreateTable) { // if all storage columns are equal to actual db columns but there are
23178
// excess columns at the db..
23179
if (!dbTableInfo.empty()) {
23180
// extra table columns than storage columns
23181
if (!preserve) {
23182
#if SQLITE_VERSION_NUMBER >= 3035000 // DROP COLUMN feature exists (v3.35.0)
23183
res = sync_schema_result::old_columns_removed;
23184
#else
23185
gottaCreateTable = true;
23186
#endif
23187
} else {
23188
res = sync_schema_result::old_columns_removed;
23189
}
23190
}
23191
}
23192
if (gottaCreateTable) {
23193
res = sync_schema_result::dropped_and_recreated;
23194
} else {
23195
if (!columnsToAdd.empty()) {
23196
// extra storage columns than table columns
23197
for (const table_xinfo* colInfo: columnsToAdd) {
23198
const basic_generated_always::storage_type* generatedStorageType =
23199
table.find_column_generated_storage_type(colInfo->name);
23200
if (generatedStorageType) {
23201
if (*generatedStorageType == basic_generated_always::storage_type::stored) {
23202
gottaCreateTable = true;
23203
break;
23204
}
23205
// fallback cause VIRTUAL can be added
23206
} else {
23207
if (colInfo->notnull && colInfo->dflt_value.empty()) {
23208
gottaCreateTable = true;
23209
// no matter if preserve is true or false, there is no way to preserve data, so we wont try!
23210
if (attempt_to_preserve) {
23211
*attempt_to_preserve = false;
23212
};
23213
break;
23214
}
23215
}
23216
}
23217
if (!gottaCreateTable) {
23218
if (res == sync_schema_result::old_columns_removed) {
23219
res = sync_schema_result::new_columns_added_and_old_columns_removed;
23220
} else {
23221
res = sync_schema_result::new_columns_added;
23222
}
23223
} else {
23224
res = sync_schema_result::dropped_and_recreated;
23225
}
23226
} else {
23227
if (res != sync_schema_result::old_columns_removed) {
23228
res = sync_schema_result::already_in_sync;
23229
}
23230
}
23231
}
23232
} else {
23233
res = sync_schema_result::new_table_created;
23234
}
23235
return res;
23236
}
23237
23238
template<class M>
23239
sync_schema_result sync_table(const virtual_table_t<M>& virtualTable, sqlite3* db, bool) {
23240
auto res = sync_schema_result::already_in_sync;
23241
using context_t = serializer_context<db_objects_type>;
23242
context_t context{this->db_objects};
23243
auto query = serialize(virtualTable, context);
23244
perform_void_exec(db, query);
23245
return res;
23246
}
23247
23248
template<class... Cols>
23249
sync_schema_result sync_table(const index_t<Cols...>& index, sqlite3* db, bool) {
23250
auto res = sync_schema_result::already_in_sync;
23251
using context_t = serializer_context<db_objects_type>;
23252
context_t context{this->db_objects};
23253
auto query = serialize(index, context);
23254
perform_void_exec(db, query);
23255
return res;
23256
}
23257
23258
template<class... Cols>
23259
sync_schema_result sync_table(const trigger_t<Cols...>& trigger, sqlite3* db, bool) {
23260
auto res = sync_schema_result::already_in_sync; // TODO Change accordingly
23261
using context_t = serializer_context<db_objects_type>;
23262
context_t context{this->db_objects};
23263
auto query = serialize(trigger, context);
23264
perform_void_exec(db, query);
23265
return res;
23266
}
23267
23268
template<class Table, satisfies<is_table, Table> = true>
23269
sync_schema_result sync_table(const Table& table, sqlite3* db, bool preserve);
23270
23271
template<class C>
23272
void add_column(sqlite3* db, const std::string& tableName, const C& column) const {
23273
using context_t = serializer_context<db_objects_type>;
23274
23275
context_t context{this->db_objects};
23276
std::stringstream ss;
23277
ss << "ALTER TABLE " << streaming_identifier(tableName) << " ADD COLUMN " << serialize(column, context)
23278
<< std::flush;
23279
perform_void_exec(db, ss.str());
23280
}
23281
23282
template<class ColResult, class S>
23283
auto execute_select(const S& statement) {
23284
sqlite3_stmt* stmt = reset_stmt(statement.stmt);
23285
23286
iterate_ast(statement.expression, conditional_binder{stmt});
23287
23288
using R = decltype(make_row_extractor<ColResult>(this->db_objects).extract(nullptr, 0));
23289
std::vector<R> res;
23290
perform_steps(
23291
stmt,
23292
[rowExtractor = make_row_extractor<ColResult>(this->db_objects), &res](sqlite3_stmt* stmt) {
23293
res.push_back(rowExtractor.extract(stmt, 0));
23294
});
23295
res.shrink_to_fit();
23296
return res;
23297
}
23298
23299
template<class E>
23300
std::string dump_highest_level(E&& expression, bool parametrized) const {
23301
const auto& exprDBOs = db_objects_for_expression(this->db_objects, expression);
23302
using context_t = serializer_context<polyfill::remove_cvref_t<decltype(exprDBOs)>>;
23303
context_t context{exprDBOs};
23304
context.replace_bindable_with_question = parametrized;
23305
// just like prepare_impl()
23306
context.skip_table_name = false;
23307
return serialize(expression, context);
23308
}
23309
23310
template<typename S>
23311
prepared_statement_t<S> prepare_impl(S statement) {
23312
const auto& exprDBOs = db_objects_for_expression(this->db_objects, statement);
23313
using context_t = serializer_context<polyfill::remove_cvref_t<decltype(exprDBOs)>>;
23314
context_t context{exprDBOs};
23315
context.skip_table_name = false;
23316
context.replace_bindable_with_question = true;
23317
23318
auto con = this->get_connection();
23319
std::string sql = serialize(statement, context);
23320
sqlite3_stmt* stmt = prepare_stmt(con.get(), std::move(sql));
23321
return prepared_statement_t<S>{std::forward<S>(statement), stmt, con};
23322
}
23323
23324
public:
23325
/**
23326
* This is a cute function used to replace migration up/down functionality.
23327
* It performs check storage schema with actual db schema and:
23328
* * if there are excess tables exist in db they are ignored (not dropped)
23329
* * every table from storage is compared with it's db analog and
23330
* * if table doesn't exist it is being created
23331
* * if table exists its colums are being compared with table_info from db and
23332
* * if there are columns in db that do not exist in storage (excess) table will be dropped and
23333
* recreated
23334
* * if there are columns in storage that do not exist in db they will be added using `ALTER TABLE
23335
* ... ADD COLUMN ...' command
23336
* * if there is any column existing in both db and storage but differs by any of
23337
* properties/constraints (pk, notnull, dflt_value) table will be dropped and recreated. Be aware that
23338
* `sync_schema` doesn't guarantee that data will not be dropped. It guarantees only that it will make db
23339
* schema the same as you specified in `make_storage` function call. A good point is that if you have no db
23340
* file at all it will be created and all tables also will be created with exact tables and columns you
23341
* specified in `make_storage`, `make_table` and `make_column` calls. The best practice is to call this
23342
* function right after storage creation.
23343
* @param preserve affects function's behaviour in case it is needed to remove a column. If it is `false`
23344
* so table will be dropped if there is column to remove if SQLite version is < 3.35.0 and remove column if SQLite version >= 3.35.0,
23345
* if `true` - table is being copied into another table, dropped and copied table is renamed with source table name.
23346
* Warning: sync_schema doesn't check foreign keys cause it is unable to do so in sqlite3. If you know how to get foreign key info please
23347
* submit an issue https://github.com/fnc12/sqlite_orm/issues
23348
* @return std::map with std::string key equal table name and `sync_schema_result` as value.
23349
* `sync_schema_result` is a enum value that stores table state after syncing a schema. `sync_schema_result`
23350
* can be printed out on std::ostream with `operator<<`.
23351
*/
23352
std::map<std::string, sync_schema_result> sync_schema(bool preserve = false) {
23353
auto con = this->get_connection();
23354
std::map<std::string, sync_schema_result> result;
23355
iterate_tuple<true>(this->db_objects, [this, db = con.get(), preserve, &result](auto& schemaObject) {
23356
sync_schema_result status = this->sync_table(schemaObject, db, preserve);
23357
result.emplace(schemaObject.name, status);
23358
});
23359
return result;
23360
}
23361
23362
/**
23363
* This function returns the same map that `sync_schema` returns but it
23364
* doesn't perform `sync_schema` actually - just simulates it in case you want to know
23365
* what will happen if you sync your schema.
23366
*/
23367
std::map<std::string, sync_schema_result> sync_schema_simulate(bool preserve = false) {
23368
auto con = this->get_connection();
23369
std::map<std::string, sync_schema_result> result;
23370
iterate_tuple<true>(this->db_objects, [this, db = con.get(), preserve, &result](auto& schemaObject) {
23371
sync_schema_result status = this->schema_status(schemaObject, db, preserve, nullptr);
23372
result.emplace(schemaObject.name, status);
23373
});
23374
return result;
23375
}
23376
23377
using storage_base::table_exists; // now that it is in storage_base make it into overload set
23378
23379
#if (SQLITE_VERSION_NUMBER >= 3008003) && defined(SQLITE_ORM_WITH_CTE)
23380
template<class... CTEs,
23381
class E,
23382
std::enable_if_t<polyfill::disjunction_v<is_select<E>,
23383
is_insert_raw<E>,
23384
is_replace_raw<E>,
23385
is_update_all<E>,
23386
is_remove_all<E>>,
23387
bool> = true>
23388
prepared_statement_t<with_t<E, CTEs...>> prepare(with_t<E, CTEs...> sel) {
23389
return this->prepare_impl<with_t<E, CTEs...>>(std::move(sel));
23390
}
23391
#endif
23392
23393
template<class T, class... Args>
23394
prepared_statement_t<select_t<T, Args...>> prepare(select_t<T, Args...> statement) {
23395
statement.highest_level = true;
23396
return this->prepare_impl(std::move(statement));
23397
}
23398
23399
template<class T, class... Args>
23400
prepared_statement_t<get_all_t<T, Args...>> prepare(get_all_t<T, Args...> statement) {
23401
return this->prepare_impl(std::move(statement));
23402
}
23403
23404
template<class T, class... Args>
23405
prepared_statement_t<get_all_pointer_t<T, Args...>> prepare(get_all_pointer_t<T, Args...> statement) {
23406
return this->prepare_impl(std::move(statement));
23407
}
23408
23409
template<class... Args>
23410
prepared_statement_t<replace_raw_t<Args...>> prepare(replace_raw_t<Args...> statement) {
23411
return this->prepare_impl(std::move(statement));
23412
}
23413
23414
template<class... Args>
23415
prepared_statement_t<insert_raw_t<Args...>> prepare(insert_raw_t<Args...> statement) {
23416
return this->prepare_impl(std::move(statement));
23417
}
23418
23419
#ifdef SQLITE_ORM_OPTIONAL_SUPPORTED
23420
template<class T, class R, class... Args>
23421
prepared_statement_t<get_all_optional_t<T, R, Args...>>
23422
prepare(get_all_optional_t<T, R, Args...> statement) {
23423
return this->prepare_impl(std::move(statement));
23424
}
23425
#endif // SQLITE_ORM_OPTIONAL_SUPPORTED
23426
23427
template<class S, class... Wargs>
23428
prepared_statement_t<update_all_t<S, Wargs...>> prepare(update_all_t<S, Wargs...> statement) {
23429
return this->prepare_impl(std::move(statement));
23430
}
23431
23432
template<class T, class... Args>
23433
prepared_statement_t<remove_all_t<T, Args...>> prepare(remove_all_t<T, Args...> statement) {
23434
return this->prepare_impl(std::move(statement));
23435
}
23436
23437
template<class T, class... Ids>
23438
prepared_statement_t<get_t<T, Ids...>> prepare(get_t<T, Ids...> statement) {
23439
return this->prepare_impl(std::move(statement));
23440
}
23441
23442
template<class T, class... Ids>
23443
prepared_statement_t<get_pointer_t<T, Ids...>> prepare(get_pointer_t<T, Ids...> statement) {
23444
return this->prepare_impl(std::move(statement));
23445
}
23446
23447
#ifdef SQLITE_ORM_OPTIONAL_SUPPORTED
23448
template<class T, class... Ids>
23449
prepared_statement_t<get_optional_t<T, Ids...>> prepare(get_optional_t<T, Ids...> statement) {
23450
return this->prepare_impl(std::move(statement));
23451
}
23452
#endif // SQLITE_ORM_OPTIONAL_SUPPORTED
23453
23454
template<class T>
23455
prepared_statement_t<update_t<T>> prepare(update_t<T> statement) {
23456
using object_type = expression_object_type_t<decltype(statement)>;
23457
this->assert_mapped_type<object_type>();
23458
this->assert_updatable_type<object_type>();
23459
return this->prepare_impl(std::move(statement));
23460
}
23461
23462
template<class T, class... Ids>
23463
prepared_statement_t<remove_t<T, Ids...>> prepare(remove_t<T, Ids...> statement) {
23464
using object_type = expression_object_type_t<decltype(statement)>;
23465
this->assert_mapped_type<object_type>();
23466
return this->prepare_impl(std::move(statement));
23467
}
23468
23469
template<class T>
23470
prepared_statement_t<insert_t<T>> prepare(insert_t<T> statement) {
23471
using object_type = expression_object_type_t<decltype(statement)>;
23472
this->assert_mapped_type<object_type>();
23473
this->assert_insertable_type<object_type>();
23474
return this->prepare_impl(std::move(statement));
23475
}
23476
23477
template<class T>
23478
prepared_statement_t<replace_t<T>> prepare(replace_t<T> statement) {
23479
using object_type = expression_object_type_t<decltype(statement)>;
23480
this->assert_mapped_type<object_type>();
23481
return this->prepare_impl(std::move(statement));
23482
}
23483
23484
template<class E, satisfies<is_insert_range, E> = true>
23485
prepared_statement_t<E> prepare(E statement) {
23486
using object_type = expression_object_type_t<decltype(statement)>;
23487
this->assert_mapped_type<object_type>();
23488
this->assert_insertable_type<object_type>();
23489
return this->prepare_impl(std::move(statement));
23490
}
23491
23492
template<class E, satisfies<is_replace_range, E> = true>
23493
prepared_statement_t<E> prepare(E statement) {
23494
using object_type = expression_object_type_t<decltype(statement)>;
23495
this->assert_mapped_type<object_type>();
23496
return this->prepare_impl(std::move(statement));
23497
}
23498
23499
template<class T, class... Cols>
23500
prepared_statement_t<insert_explicit<T, Cols...>> prepare(insert_explicit<T, Cols...> statement) {
23501
using object_type = expression_object_type_t<decltype(statement)>;
23502
this->assert_mapped_type<object_type>();
23503
return this->prepare_impl(std::move(statement));
23504
}
23505
23506
template<class... Args>
23507
void execute(const prepared_statement_t<replace_raw_t<Args...>>& statement) {
23508
sqlite3_stmt* stmt = reset_stmt(statement.stmt);
23509
iterate_ast(statement.expression, conditional_binder{stmt});
23510
perform_step(stmt);
23511
}
23512
23513
#if (SQLITE_VERSION_NUMBER >= 3008003) && defined(SQLITE_ORM_WITH_CTE)
23514
template<
23515
class... CTEs,
23516
class E,
23517
std::enable_if_t<
23518
polyfill::disjunction_v<is_insert_raw<E>, is_replace_raw<E>, is_update_all<E>, is_remove_all<E>>,
23519
bool> = true>
23520
void execute(const prepared_statement_t<with_t<E, CTEs...>>& statement) {
23521
sqlite3_stmt* stmt = reset_stmt(statement.stmt);
23522
iterate_ast(statement.expression, conditional_binder{stmt});
23523
perform_step(stmt);
23524
}
23525
#endif
23526
23527
template<class... Args>
23528
void execute(const prepared_statement_t<insert_raw_t<Args...>>& statement) {
23529
sqlite3_stmt* stmt = reset_stmt(statement.stmt);
23530
iterate_ast(statement.expression, conditional_binder{stmt});
23531
perform_step(stmt);
23532
}
23533
23534
template<class T, class... Cols>
23535
int64 execute(const prepared_statement_t<insert_explicit<T, Cols...>>& statement) {
23536
using object_type = statement_object_type_t<decltype(statement)>;
23537
23538
sqlite3_stmt* stmt = reset_stmt(statement.stmt);
23539
23540
tuple_value_binder{stmt}(
23541
statement.expression.columns.columns,
23542
[&table = this->get_table<object_type>(), &object = statement.expression.obj](auto& memberPointer) {
23543
return table.object_field_value(object, memberPointer);
23544
});
23545
perform_step(stmt);
23546
return sqlite3_last_insert_rowid(sqlite3_db_handle(stmt));
23547
}
23548
23549
template<class T,
23550
std::enable_if_t<polyfill::disjunction<is_replace<T>, is_replace_range<T>>::value, bool> = true>
23551
void execute(const prepared_statement_t<T>& statement) {
23552
using object_type = statement_object_type_t<decltype(statement)>;
23553
23554
sqlite3_stmt* stmt = reset_stmt(statement.stmt);
23555
23556
auto processObject = [&table = this->get_table<object_type>(),
23557
bindValue = field_value_binder{stmt}](auto& object) mutable {
23558
table.template for_each_column_excluding<is_generated_always>(
23559
call_as_template_base<column_field>([&bindValue, &object](auto& column) {
23560
bindValue(polyfill::invoke(column.member_pointer, object));
23561
}));
23562
};
23563
23564
static_if<is_replace_range<T>::value>(
23565
[&processObject](auto& expression) {
23566
#if __cpp_lib_ranges >= 201911L
23567
std::ranges::for_each(expression.range.first,
23568
expression.range.second,
23569
std::ref(processObject),
23570
std::ref(expression.transformer));
23571
#else
23572
auto& transformer = expression.transformer;
23573
std::for_each(expression.range.first,
23574
expression.range.second,
23575
[&processObject, &transformer](auto& item) {
23576
const object_type& object = polyfill::invoke(transformer, item);
23577
processObject(object);
23578
});
23579
#endif
23580
},
23581
[&processObject](auto& expression) {
23582
const object_type& o = get_object(expression);
23583
processObject(o);
23584
})(statement.expression);
23585
23586
perform_step(stmt);
23587
}
23588
23589
template<class T,
23590
std::enable_if_t<polyfill::disjunction<is_insert<T>, is_insert_range<T>>::value, bool> = true>
23591
int64 execute(const prepared_statement_t<T>& statement) {
23592
using object_type = statement_object_type_t<decltype(statement)>;
23593
23594
sqlite3_stmt* stmt = reset_stmt(statement.stmt);
23595
23596
auto processObject = [&table = this->get_table<object_type>(),
23597
bindValue = field_value_binder{stmt}](auto& object) mutable {
23598
using is_without_rowid = typename std::remove_reference_t<decltype(table)>::is_without_rowid;
23599
table.template for_each_column_excluding<
23600
mpl::conjunction<mpl::not_<mpl::always<is_without_rowid>>,
23601
mpl::disjunction_fn<is_primary_key, is_generated_always>>>(
23602
call_as_template_base<column_field>([&table, &bindValue, &object](auto& column) {
23603
if (!exists_in_composite_primary_key(table, column)) {
23604
bindValue(polyfill::invoke(column.member_pointer, object));
23605
}
23606
}));
23607
};
23608
23609
static_if<is_insert_range<T>::value>(
23610
[&processObject](auto& expression) {
23611
#if __cpp_lib_ranges >= 201911L
23612
std::ranges::for_each(expression.range.first,
23613
expression.range.second,
23614
std::ref(processObject),
23615
std::ref(expression.transformer));
23616
#else
23617
auto& transformer = expression.transformer;
23618
std::for_each(expression.range.first,
23619
expression.range.second,
23620
[&processObject, &transformer](auto& item) {
23621
const object_type& object = polyfill::invoke(transformer, item);
23622
processObject(object);
23623
});
23624
#endif
23625
},
23626
[&processObject](auto& expression) {
23627
const object_type& o = get_object(expression);
23628
processObject(o);
23629
})(statement.expression);
23630
23631
perform_step(stmt);
23632
return sqlite3_last_insert_rowid(sqlite3_db_handle(stmt));
23633
}
23634
23635
template<class T, class... Ids>
23636
void execute(const prepared_statement_t<remove_t<T, Ids...>>& statement) {
23637
sqlite3_stmt* stmt = reset_stmt(statement.stmt);
23638
iterate_ast(statement.expression.ids, conditional_binder{stmt});
23639
perform_step(stmt);
23640
}
23641
23642
template<class T>
23643
void execute(const prepared_statement_t<update_t<T>>& statement) {
23644
using object_type = statement_object_type_t<decltype(statement)>;
23645
23646
sqlite3_stmt* stmt = reset_stmt(statement.stmt);
23647
auto& table = this->get_table<object_type>();
23648
23649
field_value_binder bindValue{stmt};
23650
auto& object = get_object(statement.expression);
23651
table.template for_each_column_excluding<mpl::disjunction_fn<is_primary_key, is_generated_always>>(
23652
call_as_template_base<column_field>([&table, &bindValue, &object](auto& column) {
23653
if (!exists_in_composite_primary_key(table, column)) {
23654
bindValue(polyfill::invoke(column.member_pointer, object));
23655
}
23656
}));
23657
table.for_each_column([&table, &bindValue, &object](auto& column) {
23658
if (column.template is<is_primary_key>() || exists_in_composite_primary_key(table, column)) {
23659
bindValue(polyfill::invoke(column.member_pointer, object));
23660
}
23661
});
23662
perform_step(stmt);
23663
}
23664
23665
template<class T, class... Ids>
23666
std::unique_ptr<T> execute(const prepared_statement_t<get_pointer_t<T, Ids...>>& statement) {
23667
sqlite3_stmt* stmt = reset_stmt(statement.stmt);
23668
23669
iterate_ast(statement.expression.ids, conditional_binder{stmt});
23670
23671
std::unique_ptr<T> res;
23672
perform_step(stmt, [&table = this->get_table<T>(), &res](sqlite3_stmt* stmt) {
23673
res = std::make_unique<T>();
23674
object_from_column_builder<T> builder{*res, stmt};
23675
table.for_each_column(builder);
23676
});
23677
return res;
23678
}
23679
23680
#ifdef SQLITE_ORM_OPTIONAL_SUPPORTED
23681
template<class T, class... Ids>
23682
std::optional<T> execute(const prepared_statement_t<get_optional_t<T, Ids...>>& statement) {
23683
sqlite3_stmt* stmt = reset_stmt(statement.stmt);
23684
23685
iterate_ast(statement.expression.ids, conditional_binder{stmt});
23686
23687
std::optional<T> res;
23688
perform_step(stmt, [&table = this->get_table<T>(), &res](sqlite3_stmt* stmt) {
23689
object_from_column_builder<T> builder{res.emplace(), stmt};
23690
table.for_each_column(builder);
23691
});
23692
return res;
23693
}
23694
#endif // SQLITE_ORM_OPTIONAL_SUPPORTED
23695
23696
template<class T, class... Ids>
23697
T execute(const prepared_statement_t<get_t<T, Ids...>>& statement) {
23698
sqlite3_stmt* stmt = reset_stmt(statement.stmt);
23699
23700
iterate_ast(statement.expression.ids, conditional_binder{stmt});
23701
23702
#ifdef SQLITE_ORM_OPTIONAL_SUPPORTED
23703
std::optional<T> res;
23704
perform_step(stmt, [&table = this->get_table<T>(), &res](sqlite3_stmt* stmt) {
23705
object_from_column_builder<T> builder{res.emplace(), stmt};
23706
table.for_each_column(builder);
23707
});
23708
if (!res.has_value()) {
23709
throw std::system_error{orm_error_code::not_found};
23710
}
23711
return std::move(res).value();
23712
#else
23713
auto& table = this->get_table<T>();
23714
auto stepRes = sqlite3_step(stmt);
23715
switch (stepRes) {
23716
case SQLITE_ROW: {
23717
T res;
23718
object_from_column_builder<T> builder{res, stmt};
23719
table.for_each_column(builder);
23720
return res;
23721
} break;
23722
case SQLITE_DONE: {
23723
throw std::system_error{orm_error_code::not_found};
23724
} break;
23725
default: {
23726
throw_translated_sqlite_error(stmt);
23727
}
23728
}
23729
#endif
23730
}
23731
23732
template<class T, class... Args>
23733
void execute(const prepared_statement_t<remove_all_t<T, Args...>>& statement) {
23734
sqlite3_stmt* stmt = reset_stmt(statement.stmt);
23735
iterate_ast(statement.expression.conditions, conditional_binder{stmt});
23736
perform_step(stmt);
23737
}
23738
23739
template<class S, class... Wargs>
23740
void execute(const prepared_statement_t<update_all_t<S, Wargs...>>& statement) {
23741
sqlite3_stmt* stmt = reset_stmt(statement.stmt);
23742
conditional_binder bindNode{stmt};
23743
iterate_ast(statement.expression.set, bindNode);
23744
iterate_ast(statement.expression.conditions, bindNode);
23745
perform_step(stmt);
23746
}
23747
23748
#if (SQLITE_VERSION_NUMBER >= 3008003) && defined(SQLITE_ORM_WITH_CTE)
23749
template<class... CTEs, class T, class... Args>
23750
auto execute(const prepared_statement_t<with_t<select_t<T, Args...>, CTEs...>>& statement) {
23751
using ExprDBOs = decltype(db_objects_for_expression(this->db_objects, statement.expression));
23752
// note: it is enough to only use the 'expression DBOs' at compile-time to determine the column results;
23753
// because we cannot select objects/structs from a CTE, passing the permanently defined DBOs are enough.
23754
using ColResult = column_result_of_t<ExprDBOs, T>;
23755
return this->execute_select<ColResult>(statement);
23756
}
23757
#endif
23758
23759
template<class T, class... Args>
23760
auto execute(const prepared_statement_t<select_t<T, Args...>>& statement) {
23761
using ColResult = column_result_of_t<db_objects_type, T>;
23762
return this->execute_select<ColResult>(statement);
23763
}
23764
23765
template<class T, class R, class... Args, class O = mapped_type_proxy_t<T>>
23766
R execute(const prepared_statement_t<get_all_t<T, R, Args...>>& statement) {
23767
sqlite3_stmt* stmt = reset_stmt(statement.stmt);
23768
23769
iterate_ast(statement.expression, conditional_binder{stmt});
23770
23771
R res;
23772
perform_steps(stmt, [&table = this->get_table<O>(), &res](sqlite3_stmt* stmt) {
23773
O obj;
23774
object_from_column_builder<O> builder{obj, stmt};
23775
table.for_each_column(builder);
23776
res.push_back(std::move(obj));
23777
});
23778
#ifdef SQLITE_ORM_IF_CONSTEXPR_SUPPORTED
23779
if constexpr (polyfill::is_specialization_of_v<R, std::vector>) {
23780
res.shrink_to_fit();
23781
}
23782
#endif
23783
return res;
23784
}
23785
23786
template<class T, class R, class... Args>
23787
R execute(const prepared_statement_t<get_all_pointer_t<T, R, Args...>>& statement) {
23788
sqlite3_stmt* stmt = reset_stmt(statement.stmt);
23789
23790
iterate_ast(statement.expression, conditional_binder{stmt});
23791
23792
R res;
23793
perform_steps(stmt, [&table = this->get_table<T>(), &res](sqlite3_stmt* stmt) {
23794
auto obj = std::make_unique<T>();
23795
object_from_column_builder<T> builder{*obj, stmt};
23796
table.for_each_column(builder);
23797
res.push_back(std::move(obj));
23798
});
23799
#ifdef SQLITE_ORM_IF_CONSTEXPR_SUPPORTED
23800
if constexpr (polyfill::is_specialization_of_v<R, std::vector>) {
23801
res.shrink_to_fit();
23802
}
23803
#endif
23804
return res;
23805
}
23806
23807
#ifdef SQLITE_ORM_OPTIONAL_SUPPORTED
23808
template<class T, class R, class... Args>
23809
R execute(const prepared_statement_t<get_all_optional_t<T, R, Args...>>& statement) {
23810
sqlite3_stmt* stmt = reset_stmt(statement.stmt);
23811
23812
iterate_ast(statement.expression, conditional_binder{stmt});
23813
23814
R res;
23815
perform_steps(stmt, [&table = this->get_table<T>(), &res](sqlite3_stmt* stmt) {
23816
auto obj = std::make_optional<T>();
23817
object_from_column_builder<T> builder{*obj, stmt};
23818
table.for_each_column(builder);
23819
res.push_back(std::move(obj));
23820
});
23821
#ifdef SQLITE_ORM_IF_CONSTEXPR_SUPPORTED
23822
if constexpr (polyfill::is_specialization_of_v<R, std::vector>) {
23823
res.shrink_to_fit();
23824
}
23825
#endif
23826
return res;
23827
}
23828
#endif // SQLITE_ORM_OPTIONAL_SUPPORTED
23829
}; // struct storage_t
23830
}
23831
23832
/*
23833
* Factory function for a storage, from a database file and a bunch of database object definitions.
23834
*/
23835
template<class... DBO>
23836
internal::storage_t<DBO...> make_storage(std::string filename, DBO... dbObjects) {
23837
return {std::move(filename), internal::db_objects_tuple<DBO...>{std::forward<DBO>(dbObjects)...}};
23838
}
23839
23840
/**
23841
* sqlite3_threadsafe() interface.
23842
*/
23843
inline int threadsafe() {
23844
return sqlite3_threadsafe();
23845
}
23846
}
23847
/** @file Mainly existing to disentangle implementation details from circular and cross dependencies
23848
* (e.g. column_t -> default_value_extractor -> serializer_context -> db_objects_tuple -> table_t -> column_t)
23849
* this file is also used to provide definitions of interface methods 'hitting the database'.
23850
*/
23851
#pragma once
23852
23853
// #include "implementations/column_definitions.h"
23854
/** @file Mainly existing to disentangle implementation details from circular and cross dependencies
23855
* (e.g. column_t -> default_value_extractor -> serializer_context -> db_objects_tuple -> table_t -> column_t)
23856
* this file is also used to provide definitions of interface methods 'hitting the database'.
23857
*/
23858
23859
#include <memory> // std::make_unique
23860
23861
// #include "../functional/static_magic.h"
23862
23863
// #include "../tuple_helper/tuple_traits.h"
23864
23865
// #include "../default_value_extractor.h"
23866
23867
#include <string> // std::string
23868
23869
// #include "constraints.h"
23870
23871
// #include "serializer_context.h"
23872
23873
// #include "storage_lookup.h"
23874
23875
namespace sqlite_orm {
23876
23877
namespace internal {
23878
23879
template<class T, class Ctx>
23880
auto serialize(const T& t, const Ctx& context);
23881
23882
/**
23883
* Serialize a column's default value.
23884
*/
23885
template<class T>
23886
std::string serialize_default_value(const default_t<T>& dft) {
23887
db_objects_tuple<> dbObjects;
23888
serializer_context<db_objects_tuple<>> context{dbObjects};
23889
return serialize(dft.value, context);
23890
}
23891
23892
}
23893
23894
}
23895
23896
// #include "../schema/column.h"
23897
23898
namespace sqlite_orm {
23899
namespace internal {
23900
23901
template<class... Op>
23902
std::unique_ptr<std::string> column_constraints<Op...>::default_value() const {
23903
static constexpr size_t default_op_index = find_tuple_template<constraints_type, default_t>::value;
23904
23905
std::unique_ptr<std::string> value;
23906
call_if_constexpr<default_op_index != std::tuple_size<constraints_type>::value>(
23907
[&value](auto& constraints) {
23908
value =
23909
std::make_unique<std::string>(serialize_default_value(std::get<default_op_index>(constraints)));
23910
},
23911
this->constraints);
23912
return value;
23913
}
23914
23915
}
23916
}
23917
23918
// #include "implementations/table_definitions.h"
23919
/** @file Mainly existing to disentangle implementation details from circular and cross dependencies
23920
* (e.g. column_t -> default_value_extractor -> serializer_context -> db_objects_tuple -> table_t -> column_t)
23921
* this file is also used to provide definitions of interface methods 'hitting the database'.
23922
*/
23923
23924
#include <type_traits> // std::remove_reference
23925
#include <utility> // std::move
23926
#include <algorithm> // std::find_if, std::ranges::find
23927
23928
// #include "../tuple_helper/tuple_filter.h"
23929
23930
// #include "../type_traits.h"
23931
23932
// #include "../type_printer.h"
23933
23934
// #include "../schema/column.h"
23935
23936
// #include "../schema/table.h"
23937
23938
namespace sqlite_orm {
23939
namespace internal {
23940
23941
template<class T, bool WithoutRowId, class... Cs>
23942
std::vector<table_xinfo> table_t<T, WithoutRowId, Cs...>::get_table_info() const {
23943
std::vector<table_xinfo> res;
23944
res.reserve(filter_tuple_sequence_t<elements_type, is_column>::size());
23945
this->for_each_column([&res](auto& column) {
23946
using field_type = field_type_t<std::remove_reference_t<decltype(column)>>;
23947
std::string dft;
23948
if (auto d = column.default_value()) {
23949
dft = std::move(*d);
23950
}
23951
using constraints_tuple = decltype(column.constraints);
23952
constexpr bool hasExplicitNull =
23953
mpl::invoke_t<mpl::disjunction<check_if_has_type<null_t>>, constraints_tuple>::value;
23954
constexpr bool hasExplicitNotNull =
23955
mpl::invoke_t<mpl::disjunction<check_if_has_type<not_null_t>>, constraints_tuple>::value;
23956
res.emplace_back(-1,
23957
column.name,
23958
type_printer<field_type>().print(),
23959
!hasExplicitNull && !hasExplicitNotNull
23960
? column.is_not_null()
23961
: (hasExplicitNull ? !hasExplicitNull : hasExplicitNotNull),
23962
std::move(dft),
23963
column.template is<is_primary_key>(),
23964
column.template is<is_generated_always>());
23965
});
23966
auto compositeKeyColumnNames = this->composite_key_columns_names();
23967
for (size_t i = 0; i < compositeKeyColumnNames.size(); ++i) {
23968
const std::string& columnName = compositeKeyColumnNames[i];
23969
#if __cpp_lib_ranges >= 201911L
23970
auto it = std::ranges::find(res, columnName, &table_xinfo::name);
23971
#else
23972
auto it = std::find_if(res.begin(), res.end(), [&columnName](const table_xinfo& ti) {
23973
return ti.name == columnName;
23974
});
23975
#endif
23976
if (it != res.end()) {
23977
it->pk = static_cast<int>(i + 1);
23978
}
23979
}
23980
return res;
23981
}
23982
23983
}
23984
}
23985
23986
// #include "implementations/storage_definitions.h"
23987
/** @file Mainly existing to disentangle implementation details from circular and cross dependencies
23988
* this file is also used to separate implementation details from the main header file,
23989
* e.g. usage of the dbstat table.
23990
*/
23991
23992
#include <type_traits> // std::is_same
23993
#include <sstream> // std::stringstream
23994
#include <iomanip> // std::flush
23995
#include <functional> // std::reference_wrapper, std::cref
23996
#include <algorithm> // std::find_if, std::ranges::find
23997
23998
// #include "../type_traits.h"
23999
24000
// #include "../sqlite_schema_table.h"
24001
24002
#include <string> // std::string
24003
24004
// #include "schema/column.h"
24005
24006
// #include "schema/table.h"
24007
24008
// #include "column_pointer.h"
24009
24010
// #include "alias.h"
24011
24012
namespace sqlite_orm {
24013
/**
24014
* SQLite's "schema table" that stores the schema for a database.
24015
*
24016
* @note Despite the fact that the schema table was renamed from "sqlite_master" to "sqlite_schema" in SQLite 3.33.0
24017
* the renaming process was more like keeping the previous name "sqlite_master" and attaching an internal alias "sqlite_schema".
24018
* One can infer this fact from the following SQL statement:
24019
* It qualifies the set of columns, but bails out with error "no such table: sqlite_schema": `SELECT sqlite_schema.* from sqlite_schema`.
24020
* Hence we keep its previous table name `sqlite_master`, and provide `sqlite_schema` as a table alias in sqlite_orm.
24021
*/
24022
struct sqlite_master {
24023
std::string type;
24024
std::string name;
24025
std::string tbl_name;
24026
int rootpage = 0;
24027
std::string sql;
24028
24029
#ifdef SQLITE_ORM_DEFAULT_COMPARISONS_SUPPORTED
24030
friend bool operator==(const sqlite_master&, const sqlite_master&) = default;
24031
#endif
24032
};
24033
24034
inline auto make_sqlite_schema_table() {
24035
return make_table("sqlite_master",
24036
make_column("type", &sqlite_master::type),
24037
make_column("name", &sqlite_master::name),
24038
make_column("tbl_name", &sqlite_master::tbl_name),
24039
make_column("rootpage", &sqlite_master::rootpage),
24040
make_column("sql", &sqlite_master::sql));
24041
}
24042
24043
#ifdef SQLITE_ORM_WITH_CPP20_ALIASES
24044
inline constexpr orm_table_reference auto sqlite_master_table = c<sqlite_master>();
24045
inline constexpr orm_table_alias auto sqlite_schema = "sqlite_schema"_alias.for_<sqlite_master>();
24046
#endif
24047
}
24048
24049
// #include "../eponymous_vtabs/dbstat.h"
24050
24051
#ifdef SQLITE_ENABLE_DBSTAT_VTAB
24052
#include <string> // std::string
24053
#endif
24054
24055
// #include "../schema/column.h"
24056
24057
// #include "../schema/table.h"
24058
24059
// #include "../column_pointer.h"
24060
24061
namespace sqlite_orm {
24062
#ifdef SQLITE_ENABLE_DBSTAT_VTAB
24063
struct dbstat {
24064
std::string name;
24065
std::string path;
24066
int pageno = 0;
24067
std::string pagetype;
24068
int ncell = 0;
24069
int payload = 0;
24070
int unused = 0;
24071
int mx_payload = 0;
24072
int pgoffset = 0;
24073
int pgsize = 0;
24074
};
24075
24076
inline auto make_dbstat_table() {
24077
return make_table("dbstat",
24078
make_column("name", &dbstat::name),
24079
make_column("path", &dbstat::path),
24080
make_column("pageno", &dbstat::pageno),
24081
make_column("pagetype", &dbstat::pagetype),
24082
make_column("ncell", &dbstat::ncell),
24083
make_column("payload", &dbstat::payload),
24084
make_column("unused", &dbstat::unused),
24085
make_column("mx_payload", &dbstat::mx_payload),
24086
make_column("pgoffset", &dbstat::pgoffset),
24087
make_column("pgsize", &dbstat::pgsize));
24088
}
24089
24090
#ifdef SQLITE_ORM_WITH_CPP20_ALIASES
24091
inline constexpr orm_table_reference auto dbstat_table = c<dbstat>();
24092
#endif
24093
#endif // SQLITE_ENABLE_DBSTAT_VTAB
24094
}
24095
24096
// #include "../type_traits.h"
24097
24098
// #include "../util.h"
24099
24100
// #include "../serializing_util.h"
24101
24102
// #include "../storage.h"
24103
24104
namespace sqlite_orm {
24105
namespace internal {
24106
24107
template<class... DBO>
24108
template<class Table, satisfies<is_table, Table>>
24109
sync_schema_result storage_t<DBO...>::sync_table(const Table& table, sqlite3* db, bool preserve) {
24110
if (std::is_same<object_type_t<Table>, sqlite_master>::value) {
24111
return sync_schema_result::already_in_sync;
24112
}
24113
#ifdef SQLITE_ENABLE_DBSTAT_VTAB
24114
if (std::is_same<object_type_t<Table>, dbstat>::value) {
24115
return sync_schema_result::already_in_sync;
24116
}
24117
#endif // SQLITE_ENABLE_DBSTAT_VTAB
24118
auto res = sync_schema_result::already_in_sync;
24119
bool attempt_to_preserve = true;
24120
24121
auto schema_stat = this->schema_status(table, db, preserve, &attempt_to_preserve);
24122
if (schema_stat != sync_schema_result::already_in_sync) {
24123
if (schema_stat == sync_schema_result::new_table_created) {
24124
this->create_table(db, table.name, table);
24125
res = sync_schema_result::new_table_created;
24126
} else {
24127
if (schema_stat == sync_schema_result::old_columns_removed ||
24128
schema_stat == sync_schema_result::new_columns_added ||
24129
schema_stat == sync_schema_result::new_columns_added_and_old_columns_removed) {
24130
24131
// get table info provided in `make_table` call..
24132
auto storageTableInfo = table.get_table_info();
24133
24134
// now get current table info from db using `PRAGMA table_xinfo` query..
24135
auto dbTableInfo = this->pragma.table_xinfo(table.name); // should include generated columns
24136
24137
// this vector will contain pointers to columns that gotta be added..
24138
std::vector<const table_xinfo*> columnsToAdd;
24139
24140
this->calculate_remove_add_columns(columnsToAdd, storageTableInfo, dbTableInfo);
24141
24142
if (schema_stat == sync_schema_result::old_columns_removed) {
24143
#if SQLITE_VERSION_NUMBER >= 3035000 // DROP COLUMN feature exists (v3.35.0)
24144
for (auto& tableInfo: dbTableInfo) {
24145
this->drop_column(db, table.name, tableInfo.name);
24146
}
24147
res = sync_schema_result::old_columns_removed;
24148
#else
24149
// extra table columns than storage columns
24150
this->backup_table(db, table, {});
24151
res = sync_schema_result::old_columns_removed;
24152
#endif
24153
}
24154
24155
if (schema_stat == sync_schema_result::new_columns_added) {
24156
for (const table_xinfo* colInfo: columnsToAdd) {
24157
table.for_each_column([this, colInfo, &tableName = table.name, db](auto& column) {
24158
if (column.name != colInfo->name) {
24159
return;
24160
}
24161
this->add_column(db, tableName, column);
24162
});
24163
}
24164
res = sync_schema_result::new_columns_added;
24165
}
24166
24167
if (schema_stat == sync_schema_result::new_columns_added_and_old_columns_removed) {
24168
24169
auto storageTableInfo = table.get_table_info();
24170
this->add_generated_cols(columnsToAdd, storageTableInfo);
24171
24172
// remove extra columns and generated columns
24173
this->backup_table(db, table, columnsToAdd);
24174
res = sync_schema_result::new_columns_added_and_old_columns_removed;
24175
}
24176
} else if (schema_stat == sync_schema_result::dropped_and_recreated) {
24177
// now get current table info from db using `PRAGMA table_xinfo` query..
24178
auto dbTableInfo = this->pragma.table_xinfo(table.name); // should include generated columns
24179
auto storageTableInfo = table.get_table_info();
24180
24181
// this vector will contain pointers to columns that gotta be added..
24182
std::vector<const table_xinfo*> columnsToAdd;
24183
24184
this->calculate_remove_add_columns(columnsToAdd, storageTableInfo, dbTableInfo);
24185
24186
this->add_generated_cols(columnsToAdd, storageTableInfo);
24187
24188
if (preserve && attempt_to_preserve) {
24189
this->backup_table(db, table, columnsToAdd);
24190
} else {
24191
this->drop_create_with_loss(db, table);
24192
}
24193
res = schema_stat;
24194
}
24195
}
24196
}
24197
return res;
24198
}
24199
24200
template<class... DBO>
24201
template<class Table>
24202
void storage_t<DBO...>::copy_table(
24203
sqlite3* db,
24204
const std::string& sourceTableName,
24205
const std::string& destinationTableName,
24206
const Table& table,
24207
const std::vector<const table_xinfo*>& columnsToIgnore) const { // must ignore generated columns
24208
std::vector<std::reference_wrapper<const std::string>> columnNames;
24209
columnNames.reserve(table.template count_of<is_column>());
24210
table.for_each_column([&columnNames, &columnsToIgnore](const column_identifier& column) {
24211
auto& columnName = column.name;
24212
#if __cpp_lib_ranges >= 201911L
24213
auto columnToIgnoreIt = std::ranges::find(columnsToIgnore, columnName, &table_xinfo::name);
24214
#else
24215
auto columnToIgnoreIt = std::find_if(columnsToIgnore.begin(),
24216
columnsToIgnore.end(),
24217
[&columnName](const table_xinfo* tableInfo) {
24218
return columnName == tableInfo->name;
24219
});
24220
#endif
24221
if (columnToIgnoreIt == columnsToIgnore.end()) {
24222
columnNames.push_back(cref(columnName));
24223
}
24224
});
24225
24226
std::stringstream ss;
24227
ss << "INSERT INTO " << streaming_identifier(destinationTableName) << " ("
24228
<< streaming_identifiers(columnNames) << ") "
24229
<< "SELECT " << streaming_identifiers(columnNames) << " FROM " << streaming_identifier(sourceTableName)
24230
<< std::flush;
24231
perform_void_exec(db, ss.str());
24232
}
24233
}
24234
}
24235
24236
#pragma once
24237
24238
#include <type_traits> // std::is_same, std::remove_reference, std::remove_cvref
24239
#include <tuple> // std::get
24240
24241
// #include "functional/cxx_type_traits_polyfill.h"
24242
24243
// #include "functional/static_magic.h"
24244
24245
// #include "type_traits.h"
24246
24247
// #include "prepared_statement.h"
24248
24249
// #include "ast_iterator.h"
24250
24251
// #include "node_tuple.h"
24252
24253
#include <type_traits> // std::enable_if
24254
#include <tuple> // std::tuple
24255
#include <utility> // std::pair
24256
#include <functional> // std::reference_wrapper
24257
// #include "functional/cxx_optional.h"
24258
24259
// #include "functional/cxx_type_traits_polyfill.h"
24260
24261
// #include "tuple_helper/tuple_filter.h"
24262
24263
// #include "type_traits.h"
24264
24265
// #include "conditions.h"
24266
24267
// #include "operators.h"
24268
24269
// #include "select_constraints.h"
24270
24271
// #include "prepared_statement.h"
24272
24273
// #include "optional_container.h"
24274
24275
// #include "core_functions.h"
24276
24277
// #include "function.h"
24278
24279
// #include "ast/excluded.h"
24280
24281
// #include "ast/upsert_clause.h"
24282
24283
// #include "ast/where.h"
24284
24285
// #include "ast/into.h"
24286
24287
// #include "ast/group_by.h"
24288
24289
// #include "ast/match.h"
24290
24291
namespace sqlite_orm {
24292
namespace internal {
24293
24294
template<class T, class SFINAE = void>
24295
struct node_tuple {
24296
using type = std::tuple<T>;
24297
};
24298
24299
template<class T>
24300
using node_tuple_t = typename node_tuple<T>::type;
24301
24302
/*
24303
* Node tuple for several types.
24304
*/
24305
template<class... T>
24306
using node_tuple_for = conc_tuple<typename node_tuple<T>::type...>;
24307
24308
template<>
24309
struct node_tuple<void, void> {
24310
using type = std::tuple<>;
24311
};
24312
24313
template<class T>
24314
struct node_tuple<std::reference_wrapper<T>, void> : node_tuple<T> {};
24315
24316
template<class... Args>
24317
struct node_tuple<std::tuple<Args...>, void> : node_tuple_for<Args...> {};
24318
24319
#ifdef SQLITE_ORM_OPTIONAL_SUPPORTED
24320
template<class T>
24321
struct node_tuple<as_optional_t<T>, void> : node_tuple<T> {};
24322
#endif // SQLITE_ORM_OPTIONAL_SUPPORTED
24323
24324
template<class... Args>
24325
struct node_tuple<group_by_t<Args...>, void> : node_tuple_for<Args...> {};
24326
24327
template<class T, class... Args>
24328
struct node_tuple<group_by_with_having<T, Args...>, void> : node_tuple_for<Args..., T> {};
24329
24330
#if SQLITE_VERSION_NUMBER >= 3024000
24331
template<class Targets, class Actions>
24332
struct node_tuple<upsert_clause<Targets, Actions>, void> : node_tuple<Actions> {};
24333
#endif
24334
24335
template<class... Args>
24336
struct node_tuple<set_t<Args...>, void> : node_tuple_for<Args...> {};
24337
24338
template<class T, class X, class Y, class Z>
24339
struct node_tuple<highlight_t<T, X, Y, Z>, void> : node_tuple_for<X, Y, Z> {};
24340
24341
template<class T>
24342
struct node_tuple<excluded_t<T>, void> : node_tuple<T> {};
24343
24344
template<class C>
24345
struct node_tuple<where_t<C>, void> : node_tuple<C> {};
24346
24347
template<class T, class X>
24348
struct node_tuple<match_t<T, X>, void> : node_tuple<X> {};
24349
24350
/**
24351
* Column alias
24352
*/
24353
template<class A>
24354
struct node_tuple<alias_holder<A>, void> : node_tuple<void> {};
24355
24356
/**
24357
* Column alias
24358
*/
24359
template<char... C>
24360
struct node_tuple<column_alias<C...>, void> : node_tuple<void> {};
24361
24362
/**
24363
* Literal
24364
*/
24365
template<class T>
24366
struct node_tuple<literal_holder<T>, void> : node_tuple<void> {};
24367
24368
template<class E>
24369
struct node_tuple<order_by_t<E>, void> : node_tuple<E> {};
24370
24371
template<class L, class R>
24372
struct node_tuple<is_equal_with_table_t<L, R>, void> : node_tuple<R> {};
24373
24374
template<class T>
24375
struct node_tuple<T, match_if<is_binary_condition, T>> : node_tuple_for<left_type_t<T>, right_type_t<T>> {};
24376
24377
template<class T>
24378
struct node_tuple<T, match_if<is_binary_operator, T>> : node_tuple_for<left_type_t<T>, right_type_t<T>> {};
24379
24380
template<class... Args>
24381
struct node_tuple<columns_t<Args...>, void> : node_tuple_for<Args...> {};
24382
24383
template<class T, class... Args>
24384
struct node_tuple<struct_t<T, Args...>, void> : node_tuple_for<Args...> {};
24385
24386
template<class L, class A>
24387
struct node_tuple<dynamic_in_t<L, A>, void> : node_tuple_for<L, A> {};
24388
24389
template<class L, class... Args>
24390
struct node_tuple<in_t<L, Args...>, void> : node_tuple_for<L, Args...> {};
24391
24392
template<class T>
24393
struct node_tuple<T, match_if<is_compound_operator, T>> : node_tuple<typename T::expressions_tuple> {};
24394
24395
#if (SQLITE_VERSION_NUMBER >= 3008003) && defined(SQLITE_ORM_WITH_CTE)
24396
template<class CTE>
24397
struct node_tuple<CTE, match_specialization_of<CTE, common_table_expression>>
24398
: node_tuple<typename CTE::expression_type> {};
24399
24400
template<class With>
24401
struct node_tuple<With, match_specialization_of<With, with_t>>
24402
: node_tuple_for<typename With::cte_type, typename With::expression_type> {};
24403
#endif
24404
24405
template<class T, class... Args>
24406
struct node_tuple<select_t<T, Args...>, void> : node_tuple_for<T, Args...> {};
24407
24408
template<class... Args>
24409
struct node_tuple<insert_raw_t<Args...>, void> : node_tuple_for<Args...> {};
24410
24411
template<class... Args>
24412
struct node_tuple<replace_raw_t<Args...>, void> : node_tuple_for<Args...> {};
24413
24414
template<class T>
24415
struct node_tuple<into_t<T>, void> : node_tuple<void> {};
24416
24417
template<class... Args>
24418
struct node_tuple<values_t<Args...>, void> : node_tuple_for<Args...> {};
24419
24420
template<class T, class R, class... Args>
24421
struct node_tuple<get_all_t<T, R, Args...>, void> : node_tuple_for<Args...> {};
24422
24423
template<class T, class... Args>
24424
struct node_tuple<get_all_pointer_t<T, Args...>, void> : node_tuple_for<Args...> {};
24425
24426
#ifdef SQLITE_ORM_OPTIONAL_SUPPORTED
24427
template<class T, class... Args>
24428
struct node_tuple<get_all_optional_t<T, Args...>, void> : node_tuple_for<Args...> {};
24429
#endif // SQLITE_ORM_OPTIONAL_SUPPORTED
24430
24431
template<class... Args, class... Wargs>
24432
struct node_tuple<update_all_t<set_t<Args...>, Wargs...>, void> : node_tuple_for<Args..., Wargs...> {};
24433
24434
template<class T, class... Args>
24435
struct node_tuple<remove_all_t<T, Args...>, void> : node_tuple_for<Args...> {};
24436
24437
template<class T, class E>
24438
struct node_tuple<cast_t<T, E>, void> : node_tuple<E> {};
24439
24440
template<class T>
24441
struct node_tuple<exists_t<T>, void> : node_tuple<T> {};
24442
24443
template<class T>
24444
struct node_tuple<optional_container<T>, void> : node_tuple<T> {};
24445
24446
template<class A, class T, class E>
24447
struct node_tuple<like_t<A, T, E>, void> : node_tuple_for<A, T, E> {};
24448
24449
template<class A, class T>
24450
struct node_tuple<glob_t<A, T>, void> : node_tuple_for<A, T> {};
24451
24452
template<class A, class T>
24453
struct node_tuple<between_t<A, T>, void> : node_tuple_for<A, T, T> {};
24454
24455
template<class T>
24456
struct node_tuple<named_collate<T>, void> : node_tuple<T> {};
24457
24458
template<class T>
24459
struct node_tuple<is_null_t<T>, void> : node_tuple<T> {};
24460
24461
template<class T>
24462
struct node_tuple<is_not_null_t<T>, void> : node_tuple<T> {};
24463
24464
template<class C>
24465
struct node_tuple<negated_condition_t<C>, void> : node_tuple<C> {};
24466
24467
template<class T>
24468
struct node_tuple<unary_minus_t<T>, void> : node_tuple<T> {};
24469
24470
template<class T>
24471
struct node_tuple<bitwise_not_t<T>, void> : node_tuple<T> {};
24472
24473
template<class R, class S, class... Args>
24474
struct node_tuple<built_in_function_t<R, S, Args...>, void> : node_tuple_for<Args...> {};
24475
24476
template<class R, class S, class... Args>
24477
struct node_tuple<built_in_aggregate_function_t<R, S, Args...>, void> : node_tuple_for<Args...> {};
24478
24479
template<class F, class W>
24480
struct node_tuple<filtered_aggregate_function<F, W>, void> : node_tuple_for<F, W> {};
24481
24482
template<class F, class... Args>
24483
struct node_tuple<function_call<F, Args...>, void> : node_tuple_for<Args...> {};
24484
24485
template<class T, class O>
24486
struct node_tuple<left_join_t<T, O>, void> : node_tuple<O> {};
24487
24488
template<class T>
24489
struct node_tuple<on_t<T>, void> : node_tuple<T> {};
24490
24491
// note: not strictly necessary as there's no binding support for USING;
24492
// we provide it nevertheless, in line with on_t.
24493
template<class T, class M>
24494
struct node_tuple<using_t<T, M>, void> : node_tuple<column_pointer<T, M>> {};
24495
24496
template<class T, class O>
24497
struct node_tuple<join_t<T, O>, void> : node_tuple<O> {};
24498
24499
template<class T, class O>
24500
struct node_tuple<left_outer_join_t<T, O>, void> : node_tuple<O> {};
24501
24502
template<class T, class O>
24503
struct node_tuple<inner_join_t<T, O>, void> : node_tuple<O> {};
24504
24505
template<class R, class T, class E, class... Args>
24506
struct node_tuple<simple_case_t<R, T, E, Args...>, void> : node_tuple_for<T, Args..., E> {};
24507
24508
template<class L, class R>
24509
struct node_tuple<std::pair<L, R>, void> : node_tuple_for<L, R> {};
24510
24511
template<class T, class E>
24512
struct node_tuple<as_t<T, E>, void> : node_tuple<E> {};
24513
24514
template<class T>
24515
struct node_tuple<limit_t<T, false, false, void>, void> : node_tuple<T> {};
24516
24517
template<class T, class O>
24518
struct node_tuple<limit_t<T, true, false, O>, void> : node_tuple_for<T, O> {};
24519
24520
template<class T, class O>
24521
struct node_tuple<limit_t<T, true, true, O>, void> : node_tuple_for<O, T> {};
24522
}
24523
}
24524
24525
// #include "expression_object_type.h"
24526
24527
namespace sqlite_orm {
24528
24529
template<int N, class It, class L, class O>
24530
auto& get(internal::prepared_statement_t<internal::insert_range_t<It, L, O>>& statement) {
24531
return std::get<N>(statement.expression.range);
24532
}
24533
24534
template<int N, class It, class L, class O>
24535
const auto& get(const internal::prepared_statement_t<internal::insert_range_t<It, L, O>>& statement) {
24536
return std::get<N>(statement.expression.range);
24537
}
24538
24539
template<int N, class It, class L, class O>
24540
auto& get(internal::prepared_statement_t<internal::replace_range_t<It, L, O>>& statement) {
24541
return std::get<N>(statement.expression.range);
24542
}
24543
24544
template<int N, class It, class L, class O>
24545
const auto& get(const internal::prepared_statement_t<internal::replace_range_t<It, L, O>>& statement) {
24546
return std::get<N>(statement.expression.range);
24547
}
24548
24549
template<int N, class T, class... Ids>
24550
auto& get(internal::prepared_statement_t<internal::get_t<T, Ids...>>& statement) {
24551
return internal::get_ref(std::get<N>(statement.expression.ids));
24552
}
24553
24554
template<int N, class T, class... Ids>
24555
const auto& get(const internal::prepared_statement_t<internal::get_t<T, Ids...>>& statement) {
24556
return internal::get_ref(std::get<N>(statement.expression.ids));
24557
}
24558
24559
template<int N, class T, class... Ids>
24560
auto& get(internal::prepared_statement_t<internal::get_pointer_t<T, Ids...>>& statement) {
24561
return internal::get_ref(std::get<N>(statement.expression.ids));
24562
}
24563
24564
template<int N, class T, class... Ids>
24565
const auto& get(const internal::prepared_statement_t<internal::get_pointer_t<T, Ids...>>& statement) {
24566
return internal::get_ref(std::get<N>(statement.expression.ids));
24567
}
24568
24569
#ifdef SQLITE_ORM_OPTIONAL_SUPPORTED
24570
template<int N, class T, class... Ids>
24571
auto& get(internal::prepared_statement_t<internal::get_optional_t<T, Ids...>>& statement) {
24572
return internal::get_ref(std::get<N>(statement.expression.ids));
24573
}
24574
24575
template<int N, class T, class... Ids>
24576
const auto& get(const internal::prepared_statement_t<internal::get_optional_t<T, Ids...>>& statement) {
24577
return internal::get_ref(std::get<N>(statement.expression.ids));
24578
}
24579
#endif // SQLITE_ORM_OPTIONAL_SUPPORTED
24580
24581
template<int N, class T, class... Ids>
24582
auto& get(internal::prepared_statement_t<internal::remove_t<T, Ids...>>& statement) {
24583
return internal::get_ref(std::get<N>(statement.expression.ids));
24584
}
24585
24586
template<int N, class T, class... Ids>
24587
const auto& get(const internal::prepared_statement_t<internal::remove_t<T, Ids...>>& statement) {
24588
return internal::get_ref(std::get<N>(statement.expression.ids));
24589
}
24590
24591
template<int N, class T>
24592
auto& get(internal::prepared_statement_t<internal::update_t<T>>& statement) {
24593
static_assert(N == 0, "get<> works only with 0 argument for update statement");
24594
return internal::get_ref(statement.expression.object);
24595
}
24596
24597
template<int N, class T>
24598
const auto& get(const internal::prepared_statement_t<internal::update_t<T>>& statement) {
24599
static_assert(N == 0, "get<> works only with 0 argument for update statement");
24600
return internal::get_ref(statement.expression.object);
24601
}
24602
24603
template<int N, class T, class... Cols>
24604
auto& get(internal::prepared_statement_t<internal::insert_explicit<T, Cols...>>& statement) {
24605
static_assert(N == 0, "get<> works only with 0 argument for insert statement");
24606
return internal::get_ref(statement.expression.obj);
24607
}
24608
24609
template<int N, class T, class... Cols>
24610
const auto& get(const internal::prepared_statement_t<internal::insert_explicit<T, Cols...>>& statement) {
24611
static_assert(N == 0, "get<> works only with 0 argument for insert statement");
24612
return internal::get_ref(statement.expression.obj);
24613
}
24614
24615
template<int N, class T>
24616
auto& get(internal::prepared_statement_t<internal::replace_t<T>>& statement) {
24617
static_assert(N == 0, "get<> works only with 0 argument for replace statement");
24618
return internal::get_ref(statement.expression.object);
24619
}
24620
24621
template<int N, class T>
24622
const auto& get(const internal::prepared_statement_t<internal::replace_t<T>>& statement) {
24623
static_assert(N == 0, "get<> works only with 0 argument for replace statement");
24624
return internal::get_ref(statement.expression.object);
24625
}
24626
24627
template<int N, class T>
24628
auto& get(internal::prepared_statement_t<internal::insert_t<T>>& statement) {
24629
static_assert(N == 0, "get<> works only with 0 argument for insert statement");
24630
return internal::get_ref(statement.expression.object);
24631
}
24632
24633
template<int N, class T>
24634
const auto& get(const internal::prepared_statement_t<internal::insert_t<T>>& statement) {
24635
static_assert(N == 0, "get<> works only with 0 argument for insert statement");
24636
return internal::get_ref(statement.expression.object);
24637
}
24638
24639
template<int N, class T>
24640
const auto& get(const internal::prepared_statement_t<T>& statement) {
24641
using statement_type = polyfill::remove_cvref_t<decltype(statement)>;
24642
using expression_type = internal::expression_type_t<statement_type>;
24643
using node_tuple = internal::node_tuple_t<expression_type>;
24644
using bind_tuple = internal::bindable_filter_t<node_tuple>;
24645
using result_type = std::tuple_element_t<static_cast<size_t>(N), bind_tuple>;
24646
const result_type* result = nullptr;
24647
internal::iterate_ast(statement.expression, [&result, index = -1](auto& node) mutable {
24648
using node_type = polyfill::remove_cvref_t<decltype(node)>;
24649
if (internal::is_bindable<node_type>::value) {
24650
++index;
24651
}
24652
if (index == N) {
24653
internal::call_if_constexpr<std::is_same<result_type, node_type>::value>(
24654
[](auto& r, auto& n) {
24655
r = &n;
24656
},
24657
result,
24658
node);
24659
}
24660
});
24661
return internal::get_ref(*result);
24662
}
24663
24664
template<int N, class T>
24665
auto& get(internal::prepared_statement_t<T>& statement) {
24666
using statement_type = std::remove_reference_t<decltype(statement)>;
24667
using expression_type = internal::expression_type_t<statement_type>;
24668
using node_tuple = internal::node_tuple_t<expression_type>;
24669
using bind_tuple = internal::bindable_filter_t<node_tuple>;
24670
using result_type = std::tuple_element_t<static_cast<size_t>(N), bind_tuple>;
24671
result_type* result = nullptr;
24672
24673
internal::iterate_ast(statement.expression, [&result, index = -1](auto& node) mutable {
24674
using node_type = polyfill::remove_cvref_t<decltype(node)>;
24675
if (internal::is_bindable<node_type>::value) {
24676
++index;
24677
}
24678
if (index == N) {
24679
internal::call_if_constexpr<std::is_same<result_type, node_type>::value>(
24680
[](auto& r, auto& n) {
24681
r = const_cast<std::remove_reference_t<decltype(r)>>(&n);
24682
},
24683
result,
24684
node);
24685
}
24686
});
24687
return internal::get_ref(*result);
24688
}
24689
}
24690
#pragma once
24691
24692
/*
24693
* Note: This feature needs constexpr variables with external linkage.
24694
* which can be achieved before C++17's inline variables, but differs from compiler to compiler.
24695
* Hence we make it only available for compilers supporting inline variables.
24696
*/
24697
24698
#if SQLITE_VERSION_NUMBER >= 3020000
24699
#ifdef SQLITE_ORM_INLINE_VARIABLES_SUPPORTED
24700
#include <utility> // std::move
24701
#ifndef SQLITE_ORM_WITH_CPP20_ALIASES
24702
#include <type_traits> // std::integral_constant
24703
#endif
24704
#endif
24705
#endif
24706
24707
// #include "pointer_value.h"
24708
24709
#if SQLITE_VERSION_NUMBER >= 3020000
24710
#ifdef SQLITE_ORM_INLINE_VARIABLES_SUPPORTED
24711
namespace sqlite_orm {
24712
24713
#ifdef SQLITE_ORM_WITH_CPP20_ALIASES
24714
inline constexpr orm_pointer_type auto carray_pointer_tag = "carray"_pointer_type;
24715
// [Deprecation notice] This type is deprecated and will be removed in v1.10. Use the inline variable `carray_pointer_tag` instead.
24716
using carray_pvt [[deprecated]] = decltype("carray"_pointer_type);
24717
24718
template<typename P>
24719
using carray_pointer_arg = pointer_arg_t<P, carray_pointer_tag>;
24720
template<typename P, typename D>
24721
using carray_pointer_binding = pointer_binding_t<P, carray_pointer_tag, D>;
24722
template<typename P>
24723
using static_carray_pointer_binding = static_pointer_binding_t<P, carray_pointer_tag>;
24724
24725
/**
24726
* Wrap a pointer of type 'carray' and its deleter function for binding it to a statement.
24727
*
24728
* Unless the deleter yields a nullptr 'xDestroy' function the ownership of the pointed-to-object
24729
* is transferred to the pointer binding, which will delete it through
24730
* the deleter when the statement finishes.
24731
*/
24732
template<class P, class D>
24733
carray_pointer_binding<P, D> bind_carray_pointer(P* p, D d) noexcept {
24734
return bind_pointer<carray_pointer_tag>(p, std::move(d));
24735
}
24736
24737
template<class P>
24738
static_carray_pointer_binding<P> bind_carray_pointer_statically(P* p) noexcept {
24739
return bind_pointer_statically<carray_pointer_tag>(p);
24740
}
24741
24742
/**
24743
* Wrap a pointer of type 'carray' for binding it to a statement.
24744
*
24745
* Note: 'Static' means that ownership of the pointed-to-object won't be transferred
24746
* and sqlite assumes the object pointed to is valid throughout the lifetime of a statement.
24747
*/
24748
template<class P, class D>
24749
[[deprecated("Use the better named function `bind_carray_pointer(...)`")]] carray_pointer_binding<P, D>
24750
bindable_carray_pointer(P* p, D d) noexcept {
24751
return bind_pointer<carray_pointer_tag>(p, std::move(d));
24752
}
24753
24754
template<class P>
24755
[[deprecated(
24756
"Use the better named function `bind_carray_pointer_statically(...)` ")]] static_carray_pointer_binding<P>
24757
statically_bindable_carray_pointer(P* p) noexcept {
24758
return bind_pointer_statically<carray_pointer_tag>(p);
24759
}
24760
#else
24761
inline constexpr const char carray_pointer_name[] = "carray";
24762
using carray_pointer_type = std::integral_constant<const char*, carray_pointer_name>;
24763
// [Deprecation notice] This type is deprecated and will be removed in v1.10. Use the alias type `carray_pointer_type` instead.
24764
using carray_pvt [[deprecated]] = carray_pointer_type;
24765
24766
template<typename P>
24767
using carray_pointer_arg = pointer_arg<P, carray_pointer_type>;
24768
template<typename P, typename D>
24769
using carray_pointer_binding = pointer_binding<P, carray_pointer_type, D>;
24770
template<typename P>
24771
using static_carray_pointer_binding = static_pointer_binding<P, carray_pointer_type>;
24772
24773
/**
24774
* Wrap a pointer of type 'carray' and its deleter function for binding it to a statement.
24775
*
24776
* Unless the deleter yields a nullptr 'xDestroy' function the ownership of the pointed-to-object
24777
* is transferred to the pointer binding, which will delete it through
24778
* the deleter when the statement finishes.
24779
*/
24780
template<class P, class D>
24781
carray_pointer_binding<P, D> bind_carray_pointer(P* p, D d) noexcept {
24782
return bind_pointer<carray_pointer_type>(p, std::move(d));
24783
}
24784
24785
/**
24786
* Wrap a pointer of type 'carray' for binding it to a statement.
24787
*
24788
* Note: 'Static' means that ownership of the pointed-to-object won't be transferred
24789
* and sqlite assumes the object pointed to is valid throughout the lifetime of a statement.
24790
*/
24791
template<class P>
24792
static_carray_pointer_binding<P> bind_carray_pointer_statically(P* p) noexcept {
24793
return bind_pointer_statically<carray_pointer_type>(p);
24794
}
24795
24796
template<class P, class D>
24797
[[deprecated("Use the better named function `bind_carray_pointer(...)`")]] carray_pointer_binding<P, D>
24798
bindable_carray_pointer(P* p, D d) noexcept {
24799
return bind_carray_pointer(p, std::move(d));
24800
}
24801
24802
template<class P>
24803
[[deprecated(
24804
"Use the better named function `bind_carray_pointer_statically(...)` ")]] static_carray_pointer_binding<P>
24805
statically_bindable_carray_pointer(P* p) noexcept {
24806
return bind_carray_pointer_statically(p);
24807
}
24808
#endif
24809
24810
/**
24811
* Base for a generalized form of the 'remember' SQL function that is a pass-through for values
24812
* (it returns its argument unchanged using move semantics) but also saves the
24813
* value that is passed through into a bound variable.
24814
*/
24815
template<typename P>
24816
struct note_value_fn {
24817
P operator()(P&& value, carray_pointer_arg<P> pv) const {
24818
if (P* observer = pv) {
24819
*observer = value;
24820
}
24821
return std::move(value);
24822
}
24823
};
24824
24825
/**
24826
* remember(V, $PTR) extension function https://sqlite.org/src/file/ext/misc/remember.c
24827
*/
24828
struct remember_fn : note_value_fn<int64> {
24829
static constexpr const char* name() {
24830
return "remember";
24831
}
24832
};
24833
}
24834
#endif
24835
#endif
24836
#pragma once
24837
24838
#if defined(_MSC_VER)
24839
__pragma(pop_macro("max"))
24840
__pragma(pop_macro("min"))
24841
#endif // defined(_MSC_VER)
24842