GTK docking interfaces and more

By using this site, you agree to have cookies stored on your device, strictly for functional purposes, such as storing your session and preferences.

Dismiss

 sqlite_orm.h

View raw Download
text/x-c • 923.61 kiB
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