sqlite_orm.h
C source, ASCII text
1#pragma once 2 3#if defined(_MSC_VER) 4__pragma(push_macro("min")) 5#undef min 6__pragma(push_macro("max")) 7#undef max 8#endif // defined(_MSC_VER) 9#pragma once 10 11#include <sqlite3.h> 12#pragma once 13 14// #include "cxx_universal.h" 15 16/* 17* This header makes central C++ functionality on which sqlite_orm depends universally available: 18* - alternative operator representations 19* - ::size_t, ::ptrdiff_t, ::nullptr_t 20* - C++ core language feature macros 21* - macros for dealing with compiler quirks 22*/ 23 24#include <iso646.h> // alternative operator representations 25#include <cstddef> // sqlite_orm is using size_t, ptrdiff_t, nullptr_t everywhere, pull it in early 26 27// earlier clang versions didn't make nullptr_t available in the global namespace via stddef.h, 28// though it should have according to C++ documentation (see https://en.cppreference.com/w/cpp/types/nullptr_t#Notes). 29// actually it should be available when including stddef.h 30using 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, ...) \ 145SQLITE_ORM_DO_PRAGMA(clang diagnostic push) \ 146SQLITE_ORM_DO_PRAGMA(clang diagnostic ignored warnoption) \ 147__VA_ARGS__ \ 148SQLITE_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) && \ 266defined(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 276namespace sqlite_orm { 277inline 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 312namespace sqlite_orm { 313namespace internal { 314namespace 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*/ 324template<bool> 325struct conditional { 326template<typename A, typename> 327using fn = A; 328}; 329 330template<> 331struct conditional<false> { 332template<typename, typename B> 333using fn = B; 334}; 335 336// directly invoke `conditional` 337template<bool v, typename A, typename B> 338using conditional_t = typename conditional<v>::template fn<A, B>; 339} 340} 341 342namespace mpl = internal::mpl; 343} 344 345namespace sqlite_orm { 346namespace internal { 347namespace polyfill { 348#if __cpp_lib_void_t >= 201411L 349using std::void_t; 350#else 351/* 352* Implementation note: Conservative implementation due to CWG issue 1558 (Unused arguments in alias template specializations). 353*/ 354template<class...> 355struct always_void { 356using type = void; 357}; 358template<class... T> 359using void_t = typename always_void<T...>::type; 360#endif 361 362#if __cpp_lib_bool_constant >= 201505L 363using std::bool_constant; 364#else 365template<bool v> 366using bool_constant = std::integral_constant<bool, v>; 367#endif 368 369#if __cpp_lib_logical_traits >= 201510L && __cpp_lib_type_trait_variable_templates >= 201510L 370using std::conjunction; 371using std::conjunction_v; 372using std::disjunction; 373using std::disjunction_v; 374using std::negation; 375using std::negation_v; 376#else 377template<typename...> 378struct conjunction : std::true_type {}; 379template<typename B1> 380struct conjunction<B1> : B1 {}; 381template<typename B1, typename... Bn> 382struct conjunction<B1, Bn...> : mpl::conditional_t<bool(B1::value), conjunction<Bn...>, B1> {}; 383template<typename... Bs> 384SQLITE_ORM_INLINE_VAR constexpr bool conjunction_v = conjunction<Bs...>::value; 385 386template<typename...> 387struct disjunction : std::false_type {}; 388template<typename B1> 389struct disjunction<B1> : B1 {}; 390template<typename B1, typename... Bn> 391struct disjunction<B1, Bn...> : mpl::conditional_t<bool(B1::value), B1, disjunction<Bn...>> {}; 392template<typename... Bs> 393SQLITE_ORM_INLINE_VAR constexpr bool disjunction_v = disjunction<Bs...>::value; 394 395template<typename B> 396struct negation : bool_constant<!bool(B::value)> {}; 397template<typename B> 398SQLITE_ORM_INLINE_VAR constexpr bool negation_v = negation<B>::value; 399#endif 400 401#if __cpp_lib_remove_cvref >= 201711L 402using std::remove_cvref, std::remove_cvref_t; 403#else 404template<class T> 405struct remove_cvref : std::remove_cv<std::remove_reference_t<T>> {}; 406 407template<class T> 408using remove_cvref_t = typename remove_cvref<T>::type; 409#endif 410 411#if __cpp_lib_type_identity >= 201806L 412using std::type_identity, std::type_identity_t; 413#else 414template<class T> 415struct type_identity { 416using type = T; 417}; 418 419template<class T> 420using type_identity_t = typename type_identity<T>::type; 421#endif 422 423#if 0 // __cpp_lib_detect >= 0L // library fundamentals TS v2, [meta.detect] 424using std::nonesuch; 425using std::detector; 426using std::is_detected, std::is_detected_v; 427using std::detected, std::detected_t; 428using std::detected_or, std::detected_or_t; 429#else 430struct nonesuch { 431~nonesuch() = delete; 432nonesuch(const nonesuch&) = delete; 433void operator=(const nonesuch&) = delete; 434}; 435 436template<class Default, class AlwaysVoid, template<class...> class Op, class... Args> 437struct detector { 438using value_t = std::false_type; 439using type = Default; 440}; 441 442template<class Default, template<class...> class Op, class... Args> 443struct detector<Default, polyfill::void_t<Op<Args...>>, Op, Args...> { 444using value_t = std::true_type; 445using type = Op<Args...>; 446}; 447 448template<template<class...> class Op, class... Args> 449using is_detected = typename detector<nonesuch, void, Op, Args...>::value_t; 450 451template<template<class...> class Op, class... Args> 452using detected = detector<nonesuch, void, Op, Args...>; 453 454template<template<class...> class Op, class... Args> 455using detected_t = typename detector<nonesuch, void, Op, Args...>::type; 456 457template<class Default, template<class...> class Op, class... Args> 458using detected_or = detector<Default, void, Op, Args...>; 459 460template<class Default, template<class...> class Op, class... Args> 461using detected_or_t = typename detected_or<Default, Op, Args...>::type; 462 463template<template<class...> class Op, class... Args> 464SQLITE_ORM_INLINE_VAR constexpr bool is_detected_v = is_detected<Op, Args...>::value; 465#endif 466 467#if 0 // proposed but not pursued 468using 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 472template<typename Type, template<typename...> class Primary> 473SQLITE_ORM_INLINE_VAR constexpr bool is_specialization_of_v = false; 474 475template<template<typename...> class Primary, class... Types> 476SQLITE_ORM_INLINE_VAR constexpr bool is_specialization_of_v<Primary<Types...>, Primary> = true; 477 478template<typename Type, template<typename...> class Primary> 479struct is_specialization_of : bool_constant<is_specialization_of_v<Type, Primary>> {}; 480#endif 481 482template<typename...> 483SQLITE_ORM_INLINE_VAR constexpr bool always_false_v = false; 484 485template<size_t I> 486using index_constant = std::integral_constant<size_t, I>; 487} 488} 489 490namespace 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 509namespace sqlite_orm { 510namespace internal { 511// SFINAE friendly trait to get a member object pointer's field type 512template<class T> 513struct object_field_type {}; 514 515template<class T> 516using object_field_type_t = typename object_field_type<T>::type; 517 518template<class F, class O> 519struct 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) 522template<class T> 523struct getter_field_type {}; 524 525template<class T> 526using getter_field_type_t = typename getter_field_type<T>::type; 527 528template<class T, class O> 529struct getter_field_type<T O::*> : getter_field_type<T> {}; 530 531template<class F> 532struct getter_field_type<F(void) const> : polyfill::remove_cvref<F> {}; 533 534template<class F> 535struct getter_field_type<F(void)> : polyfill::remove_cvref<F> {}; 536 537#ifdef SQLITE_ORM_NOTHROW_ALIASES_SUPPORTED 538template<class F> 539struct getter_field_type<F(void) const noexcept> : polyfill::remove_cvref<F> {}; 540 541template<class F> 542struct 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) 546template<class T> 547struct setter_field_type {}; 548 549template<class T> 550using setter_field_type_t = typename setter_field_type<T>::type; 551 552template<class T, class O> 553struct setter_field_type<T O::*> : setter_field_type<T> {}; 554 555template<class F> 556struct setter_field_type<void(F)> : polyfill::remove_cvref<F> {}; 557 558#ifdef SQLITE_ORM_NOTHROW_ALIASES_SUPPORTED 559template<class F> 560struct setter_field_type<void(F) noexcept> : polyfill::remove_cvref<F> {}; 561#endif 562 563template<class T, class SFINAE = void> 564struct is_getter : std::false_type {}; 565template<class T> 566struct is_getter<T, polyfill::void_t<getter_field_type_t<T>>> : std::true_type {}; 567 568template<class T> 569SQLITE_ORM_INLINE_VAR constexpr bool is_getter_v = is_getter<T>::value; 570 571template<class T, class SFINAE = void> 572struct is_setter : std::false_type {}; 573template<class T> 574struct is_setter<T, polyfill::void_t<setter_field_type_t<T>>> : std::true_type {}; 575 576template<class T> 577SQLITE_ORM_INLINE_VAR constexpr bool is_setter_v = is_setter<T>::value; 578 579template<class T> 580struct member_field_type : object_field_type<T>, getter_field_type<T>, setter_field_type<T> {}; 581 582template<class T> 583using member_field_type_t = typename member_field_type<T>::type; 584 585template<class T> 586struct member_object_type {}; 587 588template<class F, class O> 589struct member_object_type<F O::*> : polyfill::type_identity<O> {}; 590 591template<class T> 592using member_object_type_t = typename member_object_type<T>::type; 593} 594} 595 596namespace sqlite_orm { 597namespace internal { 598namespace 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)) 608using std::identity; 609#else 610struct identity { 611template<class T> 612constexpr T&& operator()(T&& v) const noexcept { 613return std::forward<T>(v); 614} 615 616using is_transparent = int; 617}; 618#endif 619 620#if __cpp_lib_invoke >= 201411L 621using std::invoke; 622#else 623// pointer-to-data-member+object 624template<class Callable, 625class Object, 626class... Args, 627class Unqualified = remove_cvref_t<Callable>, 628std::enable_if_t<std::is_member_object_pointer<Unqualified>::value, bool> = true> 629decltype(auto) invoke(Callable&& callable, Object&& object, Args&&... args) { 630return std::forward<Object>(object).*callable; 631} 632 633// pointer-to-member-function+object 634template<class Callable, 635class Object, 636class... Args, 637class Unqualified = remove_cvref_t<Callable>, 638std::enable_if_t<std::is_member_function_pointer<Unqualified>::value, bool> = true> 639decltype(auto) invoke(Callable&& callable, Object&& object, Args&&... args) { 640return (std::forward<Object>(object).*callable)(std::forward<Args>(args)...); 641} 642 643// pointer-to-member+reference-wrapped object (expect `reference_wrapper::*`) 644template<class Callable, 645class Object, 646class... Args, 647std::enable_if_t<polyfill::negation<polyfill::is_specialization_of< 648member_object_type_t<std::remove_reference_t<Callable>>, 649std::reference_wrapper>>::value, 650bool> = true> 651decltype(auto) invoke(Callable&& callable, std::reference_wrapper<Object> wrapper, Args&&... args) { 652return invoke(std::forward<Callable>(callable), wrapper.get(), std::forward<Args>(args)...); 653} 654 655// functor 656template<class Callable, class... Args> 657decltype(auto) invoke(Callable&& callable, Args&&... args) { 658return std::forward<Callable>(callable)(std::forward<Args>(args)...); 659} 660#endif 661} 662} 663 664namespace 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 674namespace 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 678namespace 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 682template<class R> 683struct empty_callable_t { 684template<class... Args> 685R operator()(Args&&...) const { 686return R(); 687} 688}; 689template<class R = void> 690constexpr empty_callable_t<R> empty_callable{}; 691 692#ifdef SQLITE_ORM_IF_CONSTEXPR_SUPPORTED 693template<bool B, typename T, typename F> 694decltype(auto) static_if([[maybe_unused]] T&& trueFn, [[maybe_unused]] F&& falseFn) { 695if constexpr (B) { 696return std::forward<T>(trueFn); 697} else { 698return std::forward<F>(falseFn); 699} 700} 701 702template<bool B, typename T> 703decltype(auto) static_if([[maybe_unused]] T&& trueFn) { 704if constexpr (B) { 705return std::forward<T>(trueFn); 706} else { 707return empty_callable<>; 708} 709} 710 711template<bool B, typename L, typename... Args> 712void call_if_constexpr([[maybe_unused]] L&& lambda, [[maybe_unused]] Args&&... args) { 713if constexpr (B) { 714lambda(std::forward<Args>(args)...); 715} 716} 717#else 718template<typename T, typename F> 719decltype(auto) static_if(std::true_type, T&& trueFn, const F&) { 720return std::forward<T>(trueFn); 721} 722 723template<typename T, typename F> 724decltype(auto) static_if(std::false_type, const T&, F&& falseFn) { 725return std::forward<F>(falseFn); 726} 727 728template<bool B, typename T, typename F> 729decltype(auto) static_if(T&& trueFn, F&& falseFn) { 730return static_if(std::integral_constant<bool, B>{}, std::forward<T>(trueFn), std::forward<F>(falseFn)); 731} 732 733template<bool B, typename T> 734decltype(auto) static_if(T&& trueFn) { 735return static_if(std::integral_constant<bool, B>{}, std::forward<T>(trueFn), empty_callable<>); 736} 737 738template<bool B, typename L, typename... Args> 739void call_if_constexpr(L&& lambda, Args&&... args) { 740static_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 788namespace sqlite_orm { 789namespace internal { 790namespace mpl { 791template<template<class...> class Fn> 792struct 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*/ 800template<class T, class SFINAE = void> 801SQLITE_ORM_INLINE_VAR constexpr bool is_quoted_metafuntion_v = false; 802template<class Q> 803SQLITE_ORM_INLINE_VAR constexpr bool 804is_quoted_metafuntion_v<Q, polyfill::void_t<indirectly_test_metafunction<Q::template fn>>> = true; 805 806template<class T> 807struct is_quoted_metafuntion : polyfill::bool_constant<is_quoted_metafuntion_v<T>> {}; 808 809/* 810* Type pack. 811*/ 812template<class...> 813struct 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*/ 822template<template<class...> class Fn, class... Args> 823struct defer_fn { 824using 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*/ 831template<class Q, class... Args> 832struct defer { 833using type = typename Q::template fn<Args...>; 834}; 835 836/* 837* Invoke metafunction. 838*/ 839template<template<class...> class Fn, class... Args> 840using invoke_fn_t = typename defer_fn<Fn, Args...>::type; 841 842/* 843* Invoke quoted metafunction by invoking its nested metafunction. 844*/ 845template<class Q, class... Args> 846using 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*/ 855template<template<class...> class Fn> 856struct quote_fn { 857template<class InvocableTest, template<class...> class, class...> 858struct 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 863template<template<class...> class F, class... Args> 864struct invoke_this_fn<polyfill::void_t<F<Args...>>, F, Args...> { 865using type = F<Args...>; 866}; 867 868template<class... Args> 869using 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*/ 876template<size_t...> 877struct higherorder; 878 879template<> 880struct higherorder<0u> { 881template<template<template<class...> class Fn, class... Args2> class HigherFn, class Q, class... Args> 882struct defer_higher_fn { 883using type = HigherFn<Q::template fn, Args...>; 884}; 885 886/* 887* Turn higher-order metafunction into a quoted metafunction. 888*/ 889template<template<template<class...> class Fn, class... Args2> class HigherFn> 890struct quote_fn { 891template<class Q, class... Args> 892using 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*/ 901template<class Q> 902struct pass_extracted_fn_to { 903template<class... Args> 904struct invoke_this_fn { 905using type = typename Q::template fn<Args...>; 906}; 907 908// extract class template, quote, pass on 909template<template<class...> class Fn, class... T> 910struct invoke_this_fn<Fn<T...>> { 911using type = typename Q::template fn<quote_fn<Fn>>; 912}; 913 914template<class... Args> 915using 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*/ 922template<class Q, class... Qs> 923struct pass_result_of { 924// invoke `Fn`, pass on their result 925template<class... Args> 926using 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*/ 933template<class Q, template<class...> class... Fn> 934using pass_result_of_fn = pass_result_of<Q, quote_fn<Fn>...>; 935 936/* 937* Bind arguments at the front of a quoted metafunction. 938*/ 939template<class Q, class... Bound> 940struct bind_front { 941template<class... Args> 942using fn = typename Q::template fn<Bound..., Args...>; 943}; 944 945/* 946* Bind arguments at the back of a quoted metafunction. 947*/ 948template<class Q, class... Bound> 949struct bind_back { 950template<class... Args> 951using 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*/ 958template<class T> 959struct always { 960template<class... /*Args*/> 961using fn = T; 962}; 963 964/* 965* Unary quoted metafunction equivalent to `std::type_identity_t`. 966*/ 967using identity = quote_fn<polyfill::type_identity_t>; 968 969/* 970* Quoted metafunction equivalent to `std::negation`. 971*/ 972template<class TraitQ> 973using not_ = pass_result_of<quote_fn<polyfill::negation>, TraitQ>; 974 975/* 976* Quoted metafunction equivalent to `std::conjunction`. 977*/ 978template<class... TraitQ> 979struct conjunction { 980template<class... Args> 981using fn = std::true_type; 982}; 983 984template<class FirstQ, class... TraitQ> 985struct conjunction<FirstQ, TraitQ...> { 986// match last or `std::false_type` 987template<class ArgPack, class ResultTrait, class...> 988struct invoke_this_fn { 989static_assert(std::is_same<ResultTrait, std::true_type>::value || 990std::is_same<ResultTrait, std::false_type>::value, 991"Resulting trait must be a std::bool_constant"); 992using type = ResultTrait; 993}; 994 995// match `std::true_type` and one or more remaining 996template<class... Args, class NextQ, class... RestQ> 997struct invoke_this_fn<pack<Args...>, std::true_type, NextQ, RestQ...> 998: invoke_this_fn<pack<Args...>, 999// access resulting trait::type 1000typename defer<NextQ, Args...>::type::type, 1001RestQ...> {}; 1002 1003template<class... Args> 1004using fn = typename invoke_this_fn<pack<Args...>, 1005// access resulting trait::type 1006typename defer<FirstQ, Args...>::type::type, 1007TraitQ...>::type; 1008}; 1009 1010/* 1011* Quoted metafunction equivalent to `std::disjunction`. 1012*/ 1013template<class... TraitQ> 1014struct disjunction { 1015template<class... Args> 1016using fn = std::false_type; 1017}; 1018 1019template<class FirstQ, class... TraitQ> 1020struct disjunction<FirstQ, TraitQ...> { 1021// match last or `std::true_type` 1022template<class ArgPack, class ResultTrait, class...> 1023struct invoke_this_fn { 1024static_assert(std::is_same<ResultTrait, std::true_type>::value || 1025std::is_same<ResultTrait, std::false_type>::value, 1026"Resulting trait must be a std::bool_constant"); 1027using type = ResultTrait; 1028}; 1029 1030// match `std::false_type` and one or more remaining 1031template<class... Args, class NextQ, class... RestQ> 1032struct invoke_this_fn<pack<Args...>, std::false_type, NextQ, RestQ...> 1033: invoke_this_fn<pack<Args...>, 1034// access resulting trait::type 1035typename defer<NextQ, Args...>::type::type, 1036RestQ...> {}; 1037 1038template<class... Args> 1039using fn = typename invoke_this_fn<pack<Args...>, 1040// access resulting trait::type 1041typename defer<FirstQ, Args...>::type::type, 1042TraitQ...>::type; 1043}; 1044 1045/* 1046* Metafunction equivalent to `std::conjunction`. 1047*/ 1048template<template<class...> class... TraitFn> 1049using conjunction_fn = pass_result_of_fn<quote_fn<polyfill::conjunction>, TraitFn...>; 1050 1051/* 1052* Metafunction equivalent to `std::disjunction`. 1053*/ 1054template<template<class...> class... TraitFn> 1055using disjunction_fn = pass_result_of_fn<quote_fn<polyfill::disjunction>, TraitFn...>; 1056 1057/* 1058* Metafunction equivalent to `std::negation`. 1059*/ 1060template<template<class...> class Fn> 1061using not_fn = pass_result_of_fn<quote_fn<polyfill::negation>, Fn>; 1062 1063/* 1064* Bind arguments at the front of a metafunction. 1065*/ 1066template<template<class...> class Fn, class... Bound> 1067using bind_front_fn = bind_front<quote_fn<Fn>, Bound...>; 1068 1069/* 1070* Bind arguments at the back of a metafunction. 1071*/ 1072template<template<class...> class Fn, class... Bound> 1073using 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*/ 1078template<template<template<class...> class Fn, class... Args2> class HigherFn, 1079template<class...> class BoundFn, 1080class... Bound> 1081using bind_front_higherorder_fn = 1082bind_front<higherorder<0>::quote_fn<HigherFn>, quote_fn<BoundFn>, Bound...>; 1083 1084#ifdef SQLITE_ORM_RELAXED_CONSTEXPR_SUPPORTED 1085constexpr size_t find_first_true_helper(std::initializer_list<bool> values) { 1086size_t i = 0; 1087for (auto first = values.begin(); first != values.end() && !*first; ++first) { 1088++i; 1089} 1090return i; 1091} 1092 1093constexpr size_t count_true_helper(std::initializer_list<bool> values) { 1094size_t n = 0; 1095for (auto first = values.begin(); first != values.end(); ++first) { 1096n += *first; 1097} 1098return n; 1099} 1100#else 1101template<size_t N> 1102constexpr size_t find_first_true_helper(const std::array<bool, N>& values, size_t i = 0) { 1103return i == N || values[i] ? 0 : 1 + find_first_true_helper(values, i + 1); 1104} 1105 1106template<size_t N> 1107constexpr size_t count_true_helper(const std::array<bool, N>& values, size_t i = 0) { 1108return 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*/ 1116template<class PredicateQ> 1117struct finds { 1118template<class Pack, class ProjectQ> 1119struct invoke_this_fn { 1120static_assert(polyfill::always_false_v<Pack>, 1121"`finds` must be invoked with a type list as first argument."); 1122}; 1123 1124template<template<class...> class Pack, class... T, class ProjectQ> 1125struct invoke_this_fn<Pack<T...>, ProjectQ> { 1126// hoist result into `value` [SQLITE_ORM_BROKEN_ALIAS_TEMPLATE_DEPENDENT_NTTP_EXPR] 1127static 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...}); 1132using type = polyfill::index_constant<value>; 1133}; 1134 1135template<class Pack, class ProjectQ = identity> 1136using fn = typename invoke_this_fn<Pack, ProjectQ>::type; 1137}; 1138 1139template<template<class...> class PredicateFn> 1140using 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*/ 1146template<class PredicateQ> 1147struct counts { 1148template<class Pack, class ProjectQ> 1149struct invoke_this_fn { 1150static_assert(polyfill::always_false_v<Pack>, 1151"`counts` must be invoked with a type list as first argument."); 1152}; 1153 1154template<template<class...> class Pack, class... T, class ProjectQ> 1155struct invoke_this_fn<Pack<T...>, ProjectQ> { 1156// hoist result into `value` [SQLITE_ORM_BROKEN_ALIAS_TEMPLATE_DEPENDENT_NTTP_EXPR] 1157static 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...}); 1162using type = polyfill::index_constant<value>; 1163}; 1164 1165template<class Pack, class ProjectQ = identity> 1166using fn = typename invoke_this_fn<Pack, ProjectQ>::type; 1167}; 1168 1169template<template<class...> class PredicateFn> 1170using 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*/ 1176template<class TraitQ> 1177struct contains { 1178template<class Pack, class ProjectQ> 1179struct invoke_this_fn { 1180static_assert(polyfill::always_false_v<Pack>, 1181"`contains` must be invoked with a type list as first argument."); 1182}; 1183 1184template<template<class...> class Pack, class... T, class ProjectQ> 1185struct invoke_this_fn<Pack<T...>, ProjectQ> { 1186// hoist result into `value` [SQLITE_ORM_BROKEN_ALIAS_TEMPLATE_DEPENDENT_NTTP_EXPR] 1187static constexpr size_t value = 1188static_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...})); 1193using type = polyfill::bool_constant<value>; 1194}; 1195 1196template<class Pack, class ProjectQ = identity> 1197using fn = typename invoke_this_fn<Pack, ProjectQ>::type; 1198}; 1199 1200template<template<class...> class TraitFn> 1201using contains_fn = contains<quote_fn<TraitFn>>; 1202} 1203} 1204 1205namespace mpl = internal::mpl; 1206 1207// convenience quoted metafunctions 1208namespace internal { 1209/* 1210* Quoted trait metafunction that checks if a type has the specified trait. 1211*/ 1212template<template<class...> class TraitFn, class... Bound> 1213using check_if = 1214mpl::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*/ 1219template<template<class...> class TraitFn> 1220using 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*/ 1226template<class Type> 1227using 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*/ 1233template<template<class...> class Template> 1234using check_if_is_template = 1235mpl::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*/ 1240template<class Type> 1241using 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*/ 1246template<template<class...> class Template> 1247using 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*/ 1252template<template<class...> class TraitFn> 1253using 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*/ 1258template<template<class...> class TraitFn> 1259using 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*/ 1264template<template<class...> class TraitFn> 1265using check_if_has_not = mpl::not_<mpl::contains_fn<TraitFn>>; 1266 1267/* 1268* Quoted metafunction that checks whether a tuple contains given type. 1269*/ 1270template<class T> 1271using 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*/ 1285template<template<class...> class Template> 1286using 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 1296namespace sqlite_orm { 1297// convenience metafunction algorithms 1298namespace 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*/ 1304template<class Pack, 1305template<class...> class TraitFn, 1306template<class...> class ProjOp = polyfill::type_identity_t> 1307using 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*/ 1314template<class Pack, class Type, template<class...> class ProjOp = polyfill::type_identity_t> 1315using 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*/ 1322template<class Pack, 1323template<class...> class Template, 1324template<class...> class ProjOp = polyfill::type_identity_t> 1325using 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*/ 1330template<class Pack, class Type, template<class...> class ProjOp = polyfill::type_identity_t> 1331using 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*/ 1338template<class Pack, 1339template<class...> class Template, 1340template<class...> class ProjOp = polyfill::type_identity_t> 1341using 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*/ 1349template<class Pack, template<class...> class Pred, template<class...> class ProjOp = polyfill::type_identity_t> 1350using 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 1365namespace sqlite_orm { 1366namespace internal { 1367#if defined(SQLITE_ORM_PACK_INDEXING_SUPPORTED) 1368/** 1369* Get the index value of an `index_sequence` at a specific position. 1370*/ 1371template<size_t Pos, size_t... Idx> 1372SQLITE_ORM_CONSTEVAL auto index_sequence_value_at(std::index_sequence<Idx...>) { 1373return 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*/ 1379template<size_t Pos, size_t... Idx> 1380SQLITE_ORM_CONSTEVAL size_t index_sequence_value_at(std::index_sequence<Idx...>) { 1381static_assert(Pos < sizeof...(Idx)); 1382#ifdef SQLITE_ORM_CONSTEVAL_SUPPORTED 1383size_t result; 1384#else 1385size_t result = 0; 1386#endif 1387size_t i = 0; 1388// note: `(void)` cast silences warning 'expression result unused' 1389(void)((result = Idx, i++ == Pos) || ...); 1390return 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*/ 1397template<size_t Pos, size_t I, size_t... Idx> 1398SQLITE_ORM_CONSTEVAL size_t index_sequence_value_at(std::index_sequence<I, Idx...>) { 1399static_assert(Pos == 0, ""); 1400return I; 1401} 1402#endif 1403 1404template<class... Seq> 1405struct flatten_idxseq { 1406using type = std::index_sequence<>; 1407}; 1408 1409template<size_t... Ix> 1410struct flatten_idxseq<std::index_sequence<Ix...>> { 1411using type = std::index_sequence<Ix...>; 1412}; 1413 1414template<size_t... As, size_t... Bs, class... Seq> 1415struct flatten_idxseq<std::index_sequence<As...>, std::index_sequence<Bs...>, Seq...> 1416: flatten_idxseq<std::index_sequence<As..., Bs...>, Seq...> {}; 1417 1418template<class... Seq> 1419using flatten_idxseq_t = typename flatten_idxseq<Seq...>::type; 1420} 1421} 1422 1423namespace sqlite_orm { 1424namespace internal { 1425 1426template<typename... input_t> 1427using tuple_cat_t = decltype(std::tuple_cat(std::declval<input_t>()...)); 1428 1429template<class... Tpl> 1430struct conc_tuple { 1431using type = tuple_cat_t<Tpl...>; 1432}; 1433 1434template<class Tpl, class Seq> 1435struct tuple_from_index_sequence; 1436 1437template<class Tpl, size_t... Idx> 1438struct tuple_from_index_sequence<Tpl, std::index_sequence<Idx...>> { 1439using type = std::tuple<std::tuple_element_t<Idx, Tpl>...>; 1440}; 1441 1442template<class Tpl, class Seq> 1443using tuple_from_index_sequence_t = typename tuple_from_index_sequence<Tpl, Seq>::type; 1444 1445template<class Tpl, template<class...> class Pred, template<class...> class Proj, class Seq> 1446struct filter_tuple_sequence; 1447 1448#ifndef SQLITE_ORM_BROKEN_VARIADIC_PACK_EXPANSION 1449template<class Tpl, template<class...> class Pred, template<class...> class Proj, size_t... Idx> 1450struct 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, 1452std::index_sequence<Idx>, 1453std::index_sequence<>>...> {}; 1454#else 1455template<size_t Idx, class T, template<class...> class Pred, class SFINAE = void> 1456struct tuple_seq_single { 1457using type = std::index_sequence<>; 1458}; 1459 1460template<size_t Idx, class T, template<class...> class Pred> 1461struct tuple_seq_single<Idx, T, Pred, std::enable_if_t<Pred<T>::value>> { 1462using type = std::index_sequence<Idx>; 1463}; 1464 1465template<class Tpl, template<class...> class Pred, template<class...> class Proj, size_t... Idx> 1466struct filter_tuple_sequence<Tpl, Pred, Proj, std::index_sequence<Idx...>> 1467: flatten_idxseq<typename tuple_seq_single<Idx, 1468mpl::invoke_fn_t<Proj, std::tuple_element_t<Idx, Tpl>>, 1469Pred>::type...> {}; 1470#endif 1471 1472/* 1473* `Pred` is a metafunction that defines a bool member named `value` 1474* `FilterProj` is a metafunction 1475*/ 1476template<class Tpl, 1477template<class...> class Pred, 1478template<class...> class FilterProj = polyfill::type_identity_t, 1479class Seq = std::make_index_sequence<std::tuple_size<Tpl>::value>> 1480using 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*/ 1486template<class Tpl, 1487template<class...> class Pred, 1488template<class...> class FilterProj = polyfill::type_identity_t, 1489class Seq = std::make_index_sequence<std::tuple_size<Tpl>::value>> 1490using 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*/ 1501template<class Tpl, 1502template<class...> class Pred, 1503class Seq, 1504template<class...> class FilterProj = polyfill::type_identity_t> 1505struct 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 1521namespace sqlite_orm { 1522namespace internal { 1523 1524template<class Pack, template<class...> class Op> 1525struct tuple_transformer; 1526 1527template<template<class...> class Pack, class... Types, template<class...> class Op> 1528struct tuple_transformer<Pack<Types...>, Op> { 1529using type = Pack<mpl::invoke_fn_t<Op, Types>...>; 1530}; 1531 1532/* 1533* Transform specified tuple. 1534* 1535* `Op` is a metafunction. 1536*/ 1537template<class Pack, template<class...> class Op> 1538using 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*/ 1550template<class CombineOp, class Tpl, size_t... Idx, class Projector, class Init> 1551SQLITE_ORM_CONSTEXPR_CPP20 auto recombine_tuple(CombineOp combine, 1552const Tpl& tpl, 1553std::index_sequence<Idx...>, 1554Projector project, 1555Init initial) { 1556return 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*/ 1567template<class CombineOp, class Tpl, class Projector, class Init> 1568SQLITE_ORM_CONSTEXPR_CPP20 auto 1569recombine_tuple(CombineOp combine, const Tpl& tpl, Projector project, Init initial) { 1570return recombine_tuple(std::move(combine), 1571std::forward<decltype(tpl)>(tpl), 1572std::make_index_sequence<std::tuple_size<Tpl>::value>{}, 1573std::move(project), 1574std::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*/ 1581struct plus_fold_integrals { 1582template<class... Integrals> 1583constexpr auto operator()(const Integrals&...) const { 1584using integral_type = std::common_type_t<typename Integrals::value_type...>; 1585return 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*/ 1593template<template<class...> class NestedProject> 1594struct project_nested_tuple_size { 1595template<class T> 1596constexpr auto operator()(const T&) const { 1597return typename std::tuple_size<NestedProject<T>>::type{}; 1598} 1599}; 1600 1601template<template<class...> class NestedProject, class Tpl, class IdxSeq> 1602using nested_tuple_size_for_t = decltype(recombine_tuple(plus_fold_integrals{}, 1603std::declval<Tpl>(), 1604IdxSeq{}, 1605project_nested_tuple_size<NestedProject>{}, 1606std::integral_constant<size_t, 0u>{})); 1607#endif 1608 1609template<class R, class Tpl, size_t... Idx, class Projection = polyfill::identity> 1610constexpr R create_from_tuple(Tpl&& tpl, std::index_sequence<Idx...>, Projection project = {}) { 1611return 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*/ 1617template<class R, class Tpl, class Projection = polyfill::identity> 1618constexpr R create_from_tuple(Tpl&& tpl, Projection project = {}) { 1619return create_from_tuple<R>( 1620std::forward<Tpl>(tpl), 1621std::make_index_sequence<std::tuple_size<std::remove_reference_t<Tpl>>::value>{}, 1622std::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 1633namespace sqlite_orm { 1634namespace internal { 1635#if defined(SQLITE_ORM_FOLD_EXPRESSIONS_SUPPORTED) && defined(SQLITE_ORM_IF_CONSTEXPR_SUPPORTED) 1636template<bool reversed = false, class Tpl, size_t... Idx, class L> 1637constexpr void iterate_tuple(Tpl& tpl, std::index_sequence<Idx...>, L&& lambda) { 1638if constexpr (reversed) { 1639// nifty fold expression trick: make use of guaranteed right-to-left evaluation order when folding over operator= 1640int 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 1648template<bool reversed = false, class Tpl, class L> 1649void iterate_tuple(Tpl& /*tpl*/, std::index_sequence<>, L&& /*lambda*/) {} 1650 1651template<bool reversed = false, class Tpl, size_t I, size_t... Idx, class L> 1652void iterate_tuple(Tpl& tpl, std::index_sequence<I, Idx...>, L&& lambda) { 1653if SQLITE_ORM_CONSTEXPR_IF (reversed) { 1654iterate_tuple<reversed>(tpl, std::index_sequence<Idx...>{}, std::forward<L>(lambda)); 1655lambda(std::get<I>(tpl)); 1656} else { 1657lambda(std::get<I>(tpl)); 1658iterate_tuple<reversed>(tpl, std::index_sequence<Idx...>{}, std::forward<L>(lambda)); 1659} 1660} 1661#endif 1662template<bool reversed = false, class Tpl, class L> 1663constexpr void iterate_tuple(Tpl&& tpl, L&& lambda) { 1664iterate_tuple<reversed>(tpl, 1665std::make_index_sequence<std::tuple_size<std::remove_reference_t<Tpl>>::value>{}, 1666std::forward<L>(lambda)); 1667} 1668 1669#ifdef SQLITE_ORM_FOLD_EXPRESSIONS_SUPPORTED 1670template<class Tpl, size_t... Idx, class L> 1671void iterate_tuple(std::index_sequence<Idx...>, L&& lambda) { 1672(lambda((std::tuple_element_t<Idx, Tpl>*)nullptr), ...); 1673} 1674#else 1675template<class Tpl, size_t... Idx, class L> 1676void iterate_tuple(std::index_sequence<Idx...>, L&& lambda) { 1677using Sink = int[sizeof...(Idx)]; 1678(void)Sink{(lambda((std::tuple_element_t<Idx, Tpl>*)nullptr), 0)...}; 1679} 1680#endif 1681template<class Tpl, class L> 1682void iterate_tuple(L&& lambda) { 1683iterate_tuple<Tpl>(std::make_index_sequence<std::tuple_size<Tpl>::value>{}, std::forward<L>(lambda)); 1684} 1685 1686template<template<class...> class Base, class L> 1687struct lambda_as_template_base : L { 1688#ifndef SQLITE_ORM_AGGREGATE_BASES_SUPPORTED 1689lambda_as_template_base(L&& lambda) : L{std::move(lambda)} {} 1690#endif 1691template<class... T> 1692decltype(auto) operator()(const Base<T...>& object) { 1693return 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*/ 1708template<template<class...> class Base, class L> 1709lambda_as_template_base<Base, L> call_as_template_base(L lambda) { 1710return {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 1728namespace sqlite_orm { 1729// C++ generic traits used throughout the library 1730namespace internal { 1731template<class T, class... Types> 1732using is_any_of = polyfill::disjunction<std::is_same<T, Types>...>; 1733 1734template<class T> 1735struct value_unref_type : polyfill::remove_cvref<T> {}; 1736 1737template<class T> 1738struct value_unref_type<std::reference_wrapper<T>> : std::remove_const<T> {}; 1739 1740template<class T> 1741using value_unref_type_t = typename value_unref_type<T>::type; 1742 1743template<class T> 1744using is_eval_order_garanteed = 1745#if __cpp_lib_is_aggregate >= 201703L 1746std::is_aggregate<T>; 1747#else 1748std::is_pod<T>; 1749#endif 1750 1751// enable_if for types 1752template<template<typename...> class Op, class... Args> 1753using match_if = std::enable_if_t<Op<Args...>::value>; 1754 1755// enable_if for types 1756template<template<typename...> class Op, class... Args> 1757using match_if_not = std::enable_if_t<polyfill::negation<Op<Args...>>::value>; 1758 1759// enable_if for types 1760template<class T, template<typename...> class Primary> 1761using match_specialization_of = std::enable_if_t<polyfill::is_specialization_of<T, Primary>::value>; 1762 1763// enable_if for functions 1764template<template<typename...> class Op, class... Args> 1765using satisfies = std::enable_if_t<Op<Args...>::value, bool>; 1766 1767// enable_if for functions 1768template<template<typename...> class Op, class... Args> 1769using satisfies_not = std::enable_if_t<polyfill::negation<Op<Args...>>::value, bool>; 1770 1771// enable_if for functions 1772template<class T, template<typename...> class Primary> 1773using satisfies_is_specialization_of = 1774std::enable_if_t<polyfill::is_specialization_of<T, Primary>::value, bool>; 1775} 1776 1777// type name template aliases for syntactic sugar 1778namespace internal { 1779template<typename T> 1780using type_t = typename T::type; 1781 1782#ifdef SQLITE_ORM_WITH_CPP20_ALIASES 1783template<auto a> 1784using auto_type_t = typename decltype(a)::type; 1785#endif 1786 1787template<typename T> 1788using value_type_t = typename T::value_type; 1789 1790template<typename T> 1791using field_type_t = typename T::field_type; 1792 1793template<typename T> 1794using constraints_type_t = typename T::constraints_type; 1795 1796template<typename T> 1797using columns_tuple_t = typename T::columns_tuple; 1798 1799template<typename T> 1800using object_type_t = typename T::object_type; 1801 1802template<typename T> 1803using elements_type_t = typename T::elements_type; 1804 1805template<typename T> 1806using table_type_t = typename T::table_type; 1807 1808template<typename T> 1809using target_type_t = typename T::target_type; 1810 1811template<typename T> 1812using left_type_t = typename T::left_type; 1813 1814template<typename T> 1815using right_type_t = typename T::right_type; 1816 1817template<typename T> 1818using on_type_t = typename T::on_type; 1819 1820template<typename T> 1821using expression_type_t = typename T::expression_type; 1822 1823template<class As> 1824using alias_type_t = typename As::alias_type; 1825 1826#ifdef SQLITE_ORM_WITH_CPP20_ALIASES 1827template<class T> 1828using udf_type_t = typename T::udf_type; 1829 1830template<auto a> 1831using auto_udf_type_t = typename decltype(a)::udf_type; 1832#endif 1833 1834#if (SQLITE_VERSION_NUMBER >= 3008003) && defined(SQLITE_ORM_WITH_CTE) 1835template<typename T> 1836using cte_moniker_type_t = typename T::cte_moniker_type; 1837 1838template<typename T> 1839using cte_mapper_type_t = typename T::cte_mapper_type; 1840 1841// T::alias_type or nonesuch 1842template<class T> 1843using alias_holder_type_or_none = polyfill::detected<type_t, T>; 1844 1845template<class T> 1846using alias_holder_type_or_none_t = typename alias_holder_type_or_none<T>::type; 1847#endif 1848 1849#ifdef SQLITE_ORM_CPP20_CONCEPTS_SUPPORTED 1850template<typename T> 1851concept stateless = std::is_empty_v<T>; 1852#endif 1853} 1854 1855#ifdef SQLITE_ORM_CPP20_CONCEPTS_SUPPORTED 1856template<class T> 1857concept 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 1883namespace 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*/ 1888template<size_t N> 1889struct cstring_literal { 1890static constexpr size_t size() { 1891return N - 1; 1892} 1893 1894constexpr cstring_literal(const char (&cstr)[N]) { 1895std::copy_n(cstr, N, this->cstr); 1896} 1897 1898char cstr[N]; 1899}; 1900 1901template<template<char...> class Template, cstring_literal literal, size_t... Idx> 1902consteval auto explode_into(std::index_sequence<Idx...>) { 1903return 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 1927namespace sqlite_orm { 1928namespace internal { 1929/* 1930* Identity wrapper around a mapped object, facilitating uniform column pointer expressions. 1931*/ 1932template<class O> 1933struct table_reference : polyfill::type_identity<O> {}; 1934 1935template<class RecordSet> 1936struct decay_table_ref : std::remove_const<RecordSet> {}; 1937template<class O> 1938struct decay_table_ref<table_reference<O>> : polyfill::type_identity<O> {}; 1939template<class O> 1940struct decay_table_ref<const table_reference<O>> : polyfill::type_identity<O> {}; 1941 1942template<class RecordSet> 1943using decay_table_ref_t = typename decay_table_ref<RecordSet>::type; 1944#ifdef SQLITE_ORM_WITH_CPP20_ALIASES 1945template<auto recordset> 1946using auto_decay_table_ref_t = typename decay_table_ref<decltype(recordset)>::type; 1947#endif 1948 1949template<class R> 1950SQLITE_ORM_INLINE_VAR constexpr bool is_table_reference_v = 1951polyfill::is_specialization_of_v<std::remove_const_t<R>, table_reference>; 1952 1953template<class R> 1954struct 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*/ 1963template<class R> 1964concept orm_table_reference = polyfill::is_specialization_of_v<std::remove_const_t<R>, internal::table_reference>; 1965#endif 1966} 1967 1968namespace sqlite_orm { 1969 1970/** @short Base class for a custom table alias, column alias or expression alias. 1971*/ 1972struct alias_tag {}; 1973 1974namespace internal { 1975 1976template<class A> 1977SQLITE_ORM_INLINE_VAR constexpr bool is_alias_v = std::is_base_of<alias_tag, A>::value; 1978 1979template<class A> 1980struct 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*/ 1984template<class A> 1985SQLITE_ORM_INLINE_VAR constexpr bool is_column_alias_v = 1986polyfill::conjunction<is_alias<A>, polyfill::negation<polyfill::is_detected<type_t, A>>>::value; 1987 1988template<class A> 1989struct is_column_alias : is_alias<A> {}; 1990 1991/** @short Alias of any type of record set, see `orm_recordset_alias`. 1992*/ 1993template<class A> 1994SQLITE_ORM_INLINE_VAR constexpr bool is_recordset_alias_v = 1995polyfill::conjunction<is_alias<A>, polyfill::is_detected<type_t, A>>::value; 1996 1997template<class A> 1998struct is_recordset_alias : polyfill::bool_constant<is_recordset_alias_v<A>> {}; 1999 2000/** @short Alias of a concrete table, see `orm_table_alias`. 2001*/ 2002template<class A> 2003SQLITE_ORM_INLINE_VAR constexpr bool is_table_alias_v = polyfill::conjunction< 2004is_recordset_alias<A>, 2005polyfill::negation<std::is_same<polyfill::detected_t<type_t, A>, std::remove_const_t<A>>>>::value; 2006 2007template<class A> 2008struct is_table_alias : polyfill::bool_constant<is_table_alias_v<A>> {}; 2009 2010/** @short Moniker of a CTE, see `orm_cte_moniker`. 2011*/ 2012template<class A> 2013SQLITE_ORM_INLINE_VAR constexpr bool is_cte_moniker_v = 2014#if (SQLITE_VERSION_NUMBER >= 3008003) && defined(SQLITE_ORM_WITH_CTE) 2015polyfill::conjunction_v<is_recordset_alias<A>, 2016std::is_same<polyfill::detected_t<type_t, A>, std::remove_const_t<A>>>; 2017#else 2018false; 2019#endif 2020 2021template<class A> 2022using is_cte_moniker = polyfill::bool_constant<is_cte_moniker_v<A>>; 2023} 2024 2025#ifdef SQLITE_ORM_WITH_CPP20_ALIASES 2026template<class A> 2027concept 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*/ 2035template<class A> 2036concept 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*/ 2044template<class A> 2045concept 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*/ 2053template<class A> 2054concept 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*/ 2062template<class A> 2063concept 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*/ 2067template<class T> 2068concept orm_refers_to_table = (orm_table_reference<T> || orm_table_alias<T>); 2069 2070/** @short Specifies that a type refers to a recordset. 2071*/ 2072template<class T> 2073concept 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*/ 2077template<class T> 2078concept 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 2086namespace sqlite_orm { 2087 2088namespace internal { 2089 2090template<class T, class F> 2091struct column_pointer; 2092 2093template<class C> 2094struct 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*/ 2107template<class T> 2108struct table_type_of; 2109 2110template<class O, class F> 2111struct table_type_of<F O::*> { 2112using type = O; 2113}; 2114 2115template<class T, class F> 2116struct table_type_of<column_pointer<T, F>> { 2117using type = T; 2118}; 2119 2120template<class C> 2121struct table_type_of<indexed_column_t<C>> : table_type_of<C> {}; 2122 2123template<class T> 2124using 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*/ 2134template<class F, class T, class SFINAE = void> 2135SQLITE_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*/ 2140template<class O, class Base, class F> 2141SQLITE_ORM_INLINE_VAR constexpr bool 2142is_field_of_v<F Base::*, O, std::enable_if_t<std::is_convertible<F Base::*, F O::*>::value>> = true; 2143 2144template<class F, class T> 2145SQLITE_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 2153namespace sqlite_orm { 2154namespace internal { 2155struct negatable_t {}; 2156 2157/** 2158* Inherit from this class to support arithmetic types overloading 2159*/ 2160struct arithmetic_t {}; 2161 2162/** 2163* Inherit from this class if target class can be chained with other conditions with '&&' and '||' operators 2164*/ 2165struct condition_t {}; 2166 2167/** 2168* Specialize if a type participates as an argument to overloaded operators (arithmetic, conditional, negation, chaining) 2169*/ 2170template<class T, class SFINAE = void> 2171SQLITE_ORM_INLINE_VAR constexpr bool is_operator_argument_v = false; 2172 2173template<class T> 2174using 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 2195namespace sqlite_orm { 2196namespace 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*/ 2201template<class T, class F> 2202struct column_pointer { 2203using type = T; 2204using field_type = F; 2205 2206field_type field; 2207}; 2208 2209template<class T> 2210SQLITE_ORM_INLINE_VAR constexpr bool is_column_pointer_v = 2211polyfill::is_specialization_of<T, column_pointer>::value; 2212 2213template<class T> 2214struct is_column_pointer : polyfill::bool_constant<is_column_pointer_v<T>> {}; 2215 2216template<class T> 2217SQLITE_ORM_INLINE_VAR constexpr bool is_operator_argument_v<T, std::enable_if_t<is_column_pointer<T>::value>> = 2218true; 2219 2220#if (SQLITE_VERSION_NUMBER >= 3008003) && defined(SQLITE_ORM_WITH_CTE) 2221template<class A> 2222struct 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*/ 2235template<class O, class Base, class F, internal::satisfies_not<internal::is_recordset_alias, O> = true> 2236constexpr internal::column_pointer<O, F Base::*> column(F Base::* field) { 2237static_assert(std::is_convertible<F Base::*, F O::*>::value, "Field must be from derived class"); 2238return {field}; 2239} 2240 2241#ifdef SQLITE_ORM_WITH_CPP20_ALIASES 2242/** 2243* Explicitly refer to a column. 2244*/ 2245template<orm_table_reference auto table, class O, class F> 2246constexpr auto column(F O::* field) { 2247return 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) 2252namespace internal { 2253/** 2254* Explicitly refer to a column. 2255*/ 2256template<orm_table_reference R, class O, class F> 2257constexpr auto operator->*(const R& /*table*/, F O::* field) { 2258return column<typename R::type>(field); 2259} 2260} 2261 2262/** 2263* Make a table reference. 2264*/ 2265template<class O> 2266requires (!orm_recordset_alias<O>) 2267consteval internal::table_reference<O> column() { 2268return {}; 2269} 2270 2271/** 2272* Make a table reference. 2273*/ 2274template<class O> 2275requires (!orm_recordset_alias<O>) 2276consteval internal::table_reference<O> c() { 2277return {}; 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*/ 2294template<class Moniker, class F, internal::satisfies<internal::is_recordset_alias, Moniker> = true> 2295constexpr auto column(F field) { 2296using namespace ::sqlite_orm::internal; 2297 2298static_assert(is_cte_moniker_v<Moniker>, "`Moniker' must be a CTE moniker"); 2299 2300if constexpr (polyfill::is_specialization_of_v<F, alias_holder>) { 2301static_assert(is_column_alias_v<type_t<F>>); 2302return column_pointer<Moniker, F>{{}}; 2303} else if constexpr (is_column_alias_v<F>) { 2304return column_pointer<Moniker, alias_holder<F>>{{}}; 2305} else { 2306return 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*/ 2320template<orm_cte_moniker auto moniker, class F> 2321constexpr auto column(F field) { 2322using Moniker = std::remove_const_t<decltype(moniker)>; 2323return 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*/ 2338template<orm_cte_moniker Moniker, class F> 2339constexpr auto operator->*(const Moniker& /*moniker*/, F field) { 2340return column<Moniker>(std::forward<F>(field)); 2341} 2342#endif 2343#endif 2344} 2345 2346namespace sqlite_orm { 2347 2348namespace internal { 2349#ifdef SQLITE_ORM_WITH_CPP20_ALIASES 2350template<class T> 2351inline 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*/ 2359template<class T, char A, char... X> 2360struct recordset_alias : alias_tag { 2361using type = T; 2362 2363static std::string get() { 2364return {A, X...}; 2365} 2366}; 2367 2368/** 2369* Column expression with table alias attached like 'C.ID'. This is not a column alias 2370*/ 2371template<class T, class C> 2372struct alias_column_t { 2373using alias_type = T; 2374using column_type = C; 2375 2376column_type column; 2377}; 2378 2379template<class T> 2380SQLITE_ORM_INLINE_VAR constexpr bool 2381is_operator_argument_v<T, std::enable_if_t<polyfill::is_specialization_of<T, alias_column_t>::value>> = 2382true; 2383 2384struct 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*/ 2393template<class T, class SFINAE = void> 2394struct alias_extractor { 2395static std::string extract() { 2396return {}; 2397} 2398 2399static std::string as_alias() { 2400return {}; 2401} 2402 2403template<class X = basic_table> 2404static const std::string& as_qualifier(const X& table) { 2405return 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*/ 2416template<class A> 2417struct alias_extractor<A, match_if<is_alias, A>> { 2418static std::string extract() { 2419std::stringstream ss; 2420ss << A::get(); 2421return ss.str(); 2422} 2423 2424// for column and regular table aliases -> alias identifier 2425template<class T = A, satisfies_not<std::is_same, polyfill::detected_t<type_t, T>, A> = true> 2426static std::string as_alias() { 2427return alias_extractor::extract(); 2428} 2429 2430#if (SQLITE_VERSION_NUMBER >= 3008003) && defined(SQLITE_ORM_WITH_CTE) 2431// for CTE monikers -> empty 2432template<class T = A, satisfies<std::is_same, polyfill::detected_t<type_t, T>, A> = true> 2433static std::string as_alias() { 2434return {}; 2435} 2436#endif 2437 2438// for regular table aliases -> alias identifier 2439template<class T = A, satisfies<is_table_alias, T> = true> 2440static std::string as_qualifier(const basic_table&) { 2441return alias_extractor::extract(); 2442} 2443}; 2444 2445/** 2446* Used to store alias for expression 2447*/ 2448template<class T, class E> 2449struct as_t { 2450using alias_type = T; 2451using expression_type = E; 2452 2453expression_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*/ 2461template<char A, char... X> 2462struct column_alias : alias_tag { 2463static std::string get() { 2464return {A, X...}; 2465} 2466}; 2467 2468template<class T> 2469struct alias_holder { 2470using type = T; 2471 2472alias_holder() = default; 2473// CTE feature needs it to implicitly convert a column alias to an alias_holder; see `cte()` factory function 2474alias_holder(const T&) noexcept {} 2475}; 2476 2477template<class T> 2478SQLITE_ORM_INLINE_VAR constexpr bool 2479is_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 2482template<char A, char... X> 2483struct recordset_alias_builder { 2484template<class T> 2485[[nodiscard]] consteval recordset_alias<T, A, X...> for_() const { 2486return {}; 2487} 2488 2489template<auto t> 2490[[nodiscard]] consteval auto for_() const { 2491using T = std::remove_const_t<decltype(t)>; 2492return recordset_alias<T, A, X...>{}; 2493} 2494}; 2495#endif 2496 2497#if (SQLITE_VERSION_NUMBER >= 3008003) && defined(SQLITE_ORM_WITH_CTE) 2498template<size_t n, char... C> 2499SQLITE_ORM_CONSTEVAL auto n_to_colalias() { 2500constexpr column_alias<'1' + n % 10, C...> colalias{}; 2501if constexpr (n > 10) { 2502return n_to_colalias<n / 10, '1' + n % 10, C...>(); 2503} else { 2504return colalias; 2505} 2506} 2507 2508template<class T> 2509inline constexpr bool is_builtin_numeric_column_alias_v = false; 2510template<char... C> 2511inline 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*/ 2522template<class A, 2523class C, 2524std::enable_if_t< 2525polyfill::conjunction<internal::is_table_alias<A>, 2526polyfill::negation<internal::is_cte_moniker<internal::type_t<A>>>>::value, 2527bool> = true> 2528constexpr auto alias_column(C field) { 2529using namespace ::sqlite_orm::internal; 2530using aliased_type = type_t<A>; 2531static_assert(is_field_of_v<C, aliased_type>, "Column must be from aliased table"); 2532 2533return 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*/ 2545template<class A, 2546class F, 2547class O, 2548std::enable_if_t< 2549polyfill::conjunction<internal::is_table_alias<A>, 2550polyfill::negation<internal::is_cte_moniker<internal::type_t<A>>>>::value, 2551bool> = true> 2552constexpr auto alias_column(F O::* field) { 2553using namespace ::sqlite_orm::internal; 2554using aliased_type = type_t<A>; 2555static_assert(is_field_of_v<F O::*, aliased_type>, "Column must be from aliased table"); 2556 2557using C1 = 2558mpl::conditional_t<std::is_same<O, aliased_type>::value, F O::*, column_pointer<aliased_type, F O::*>>; 2559return 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*/ 2572template<orm_table_alias auto als, class C> 2573requires (!orm_cte_moniker<internal::auto_type_t<als>>) 2574constexpr auto alias_column(C field) { 2575using namespace ::sqlite_orm::internal; 2576using A = decltype(als); 2577using aliased_type = type_t<A>; 2578static_assert(is_field_of_v<C, aliased_type>, "Column must be from aliased table"); 2579 2580if constexpr (is_column_pointer_v<C>) { 2581return alias_column_t<A, C>{std::move(field)}; 2582} else if constexpr (std::is_same_v<member_object_type_t<C>, aliased_type>) { 2583return alias_column_t<A, C>{field}; 2584} else { 2585// wrap in column_pointer 2586using C1 = column_pointer<aliased_type, C>; 2587return 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*/ 2603template<orm_table_alias A, class F> 2604requires (!orm_cte_moniker<internal::type_t<A>>) 2605constexpr auto operator->*(const A& /*tableAlias*/, F field) { 2606return 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*/ 2614template<class A, 2615class C, 2616std::enable_if_t< 2617polyfill::conjunction_v<internal::is_table_alias<A>, internal::is_cte_moniker<internal::type_t<A>>>, 2618bool> = true> 2619constexpr auto alias_column(C c) { 2620using namespace ::sqlite_orm::internal; 2621using cte_moniker_t = type_t<A>; 2622 2623if constexpr (is_column_pointer_v<C>) { 2624static_assert(std::is_same<table_type_of_t<C>, cte_moniker_t>::value, 2625"Column pointer must match aliased CTE"); 2626return alias_column_t<A, C>{c}; 2627} else { 2628auto cp = column<cte_moniker_t>(c); 2629return 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*/ 2640template<orm_table_alias A, class C> 2641requires (orm_cte_moniker<internal::type_t<A>>) 2642constexpr auto operator->*(const A& /*tableAlias*/, C c) { 2643return alias_column<A>(std::move(c)); 2644} 2645 2646/** 2647* Create a column reference to an aliased CTE column. 2648*/ 2649template<orm_table_alias auto als, class C> 2650requires (orm_cte_moniker<internal::auto_type_t<als>>) 2651constexpr auto alias_column(C c) { 2652using A = std::remove_const_t<decltype(als)>; 2653return alias_column<A>(std::move(c)); 2654} 2655#endif 2656#endif 2657 2658/** 2659* Alias a column expression. 2660*/ 2661template<class A, class E, internal::satisfies<internal::is_column_alias, A> = true> 2662internal::as_t<A, E> as(E expression) { 2663return {std::move(expression)}; 2664} 2665 2666#ifdef SQLITE_ORM_WITH_CPP20_ALIASES 2667/** 2668* Alias a column expression. 2669*/ 2670template<orm_column_alias auto als, class E> 2671auto as(E expression) { 2672return internal::as_t<decltype(als), E>{std::move(expression)}; 2673} 2674 2675/** 2676* Alias a column expression. 2677*/ 2678template<orm_column_alias A, class E> 2679internal::as_t<A, E> operator>>=(E expression, const A&) { 2680return {std::move(expression)}; 2681} 2682#else 2683/** 2684* Alias a column expression. 2685*/ 2686template<class A, class E, internal::satisfies<internal::is_column_alias, A> = true> 2687internal::as_t<A, E> operator>>=(E expression, const A&) { 2688return {std::move(expression)}; 2689} 2690#endif 2691 2692/** 2693* Wrap a column alias in an alias holder. 2694*/ 2695template<class T> 2696internal::alias_holder<T> get() { 2697static_assert(internal::is_column_alias_v<T>, ""); 2698return {}; 2699} 2700 2701#ifdef SQLITE_ORM_WITH_CPP20_ALIASES 2702template<orm_column_alias auto als> 2703auto get() { 2704return internal::alias_holder<decltype(als)>{}; 2705} 2706#endif 2707 2708template<class T> 2709using alias_a = internal::recordset_alias<T, 'a'>; 2710template<class T> 2711using alias_b = internal::recordset_alias<T, 'b'>; 2712template<class T> 2713using alias_c = internal::recordset_alias<T, 'c'>; 2714template<class T> 2715using alias_d = internal::recordset_alias<T, 'd'>; 2716template<class T> 2717using alias_e = internal::recordset_alias<T, 'e'>; 2718template<class T> 2719using alias_f = internal::recordset_alias<T, 'f'>; 2720template<class T> 2721using alias_g = internal::recordset_alias<T, 'g'>; 2722template<class T> 2723using alias_h = internal::recordset_alias<T, 'h'>; 2724template<class T> 2725using alias_i = internal::recordset_alias<T, 'i'>; 2726template<class T> 2727using alias_j = internal::recordset_alias<T, 'j'>; 2728template<class T> 2729using alias_k = internal::recordset_alias<T, 'k'>; 2730template<class T> 2731using alias_l = internal::recordset_alias<T, 'l'>; 2732template<class T> 2733using alias_m = internal::recordset_alias<T, 'm'>; 2734template<class T> 2735using alias_n = internal::recordset_alias<T, 'n'>; 2736template<class T> 2737using alias_o = internal::recordset_alias<T, 'o'>; 2738template<class T> 2739using alias_p = internal::recordset_alias<T, 'p'>; 2740template<class T> 2741using alias_q = internal::recordset_alias<T, 'q'>; 2742template<class T> 2743using alias_r = internal::recordset_alias<T, 'r'>; 2744template<class T> 2745using alias_s = internal::recordset_alias<T, 's'>; 2746template<class T> 2747using alias_t = internal::recordset_alias<T, 't'>; 2748template<class T> 2749using alias_u = internal::recordset_alias<T, 'u'>; 2750template<class T> 2751using alias_v = internal::recordset_alias<T, 'v'>; 2752template<class T> 2753using alias_w = internal::recordset_alias<T, 'w'>; 2754template<class T> 2755using alias_x = internal::recordset_alias<T, 'x'>; 2756template<class T> 2757using alias_y = internal::recordset_alias<T, 'y'>; 2758template<class T> 2759using alias_z = internal::recordset_alias<T, 'z'>; 2760 2761using colalias_a = internal::column_alias<'a'>; 2762using colalias_b = internal::column_alias<'b'>; 2763using colalias_c = internal::column_alias<'c'>; 2764using colalias_d = internal::column_alias<'d'>; 2765using colalias_e = internal::column_alias<'e'>; 2766using colalias_f = internal::column_alias<'f'>; 2767using colalias_g = internal::column_alias<'g'>; 2768using colalias_h = internal::column_alias<'h'>; 2769using 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*/ 2777template<char A, char... X> 2778inline constexpr internal::recordset_alias_builder<A, X...> alias{}; 2779 2780inline namespace literals { 2781/** @short Create a table alias. 2782* 2783* Examples: 2784* constexpr orm_table_alias auto z_alias = "z"_alias.for_<User>(); 2785*/ 2786template<internal::cstring_literal name> 2787[[nodiscard]] consteval auto operator"" _alias() { 2788return internal::explode_into<internal::recordset_alias_builder, name>( 2789std::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*/ 2796template<internal::cstring_literal name> 2797[[nodiscard]] consteval auto operator"" _col() { 2798return 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) 2804inline namespace literals { 2805/** 2806* column_alias<'1'[, ...]> from a numeric literal. 2807* E.g. 1_colalias, 2_colalias 2808*/ 2809template<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". 2813static_assert(std::array{Chars...}[0] > '0'); 2814return 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 2829namespace sqlite_orm { 2830 2831/** @short Enables classifying sqlite error codes. 2832 2833@note We don't bother listing all possible values; 2834this also allows for compatibility with 2835'Construction rules for enum class values (P0138R2)' 2836*/ 2837enum class sqlite_errc {}; 2838 2839enum class orm_error_code { 2840not_found = 1, 2841type_is_not_mapped_to_storage, 2842trying_to_dereference_null_iterator, 2843too_many_tables_specified, 2844incorrect_set_fields_specified, 2845column_not_found, 2846table_has_no_primary_key_column, 2847cannot_start_a_transaction_within_a_transaction, 2848no_active_transaction, 2849incorrect_journal_mode_string, 2850incorrect_locking_mode_string, 2851invalid_collate_argument_enum, 2852failed_to_init_a_backup, 2853unknown_member_value, 2854incorrect_order, 2855cannot_use_default_value, 2856arguments_count_does_not_match, 2857function_not_found, 2858index_is_out_of_bounds, 2859value_is_null, 2860no_tables_specified, 2861}; 2862} 2863 2864namespace std { 2865template<> 2866struct is_error_code_enum<::sqlite_orm::sqlite_errc> : true_type {}; 2867 2868template<> 2869struct is_error_code_enum<::sqlite_orm::orm_error_code> : true_type {}; 2870} 2871 2872namespace sqlite_orm { 2873 2874class orm_error_category : public std::error_category { 2875public: 2876const char* name() const noexcept override final { 2877return "ORM error"; 2878} 2879 2880std::string message(int c) const override final { 2881switch (static_cast<orm_error_code>(c)) { 2882case orm_error_code::not_found: 2883return "Not found"; 2884case orm_error_code::type_is_not_mapped_to_storage: 2885return "Type is not mapped to storage"; 2886case orm_error_code::trying_to_dereference_null_iterator: 2887return "Trying to dereference null iterator"; 2888case orm_error_code::too_many_tables_specified: 2889return "Too many tables specified"; 2890case orm_error_code::incorrect_set_fields_specified: 2891return "Incorrect set fields specified"; 2892case orm_error_code::column_not_found: 2893return "Column not found"; 2894case orm_error_code::table_has_no_primary_key_column: 2895return "Table has no primary key column"; 2896case orm_error_code::cannot_start_a_transaction_within_a_transaction: 2897return "Cannot start a transaction within a transaction"; 2898case orm_error_code::no_active_transaction: 2899return "No active transaction"; 2900case orm_error_code::invalid_collate_argument_enum: 2901return "Invalid collate_argument enum"; 2902case orm_error_code::failed_to_init_a_backup: 2903return "Failed to init a backup"; 2904case orm_error_code::unknown_member_value: 2905return "Unknown member value"; 2906case orm_error_code::incorrect_order: 2907return "Incorrect order"; 2908case orm_error_code::cannot_use_default_value: 2909return "The statement 'INSERT INTO * DEFAULT VALUES' can be used with only one row"; 2910case orm_error_code::arguments_count_does_not_match: 2911return "Arguments count does not match"; 2912case orm_error_code::function_not_found: 2913return "Function not found"; 2914case orm_error_code::index_is_out_of_bounds: 2915return "Index is out of bounds"; 2916case orm_error_code::value_is_null: 2917return "Value is null"; 2918case orm_error_code::no_tables_specified: 2919return "No tables specified"; 2920default: 2921return "unknown error"; 2922} 2923} 2924}; 2925 2926class sqlite_error_category : public std::error_category { 2927public: 2928const char* name() const noexcept override final { 2929return "SQLite error"; 2930} 2931 2932std::string message(int c) const override final { 2933return sqlite3_errstr(c); 2934} 2935}; 2936 2937inline const orm_error_category& get_orm_error_category() { 2938static orm_error_category res; 2939return res; 2940} 2941 2942inline const sqlite_error_category& get_sqlite_error_category() { 2943static sqlite_error_category res; 2944return res; 2945} 2946 2947inline std::error_code make_error_code(sqlite_errc ev) noexcept { 2948return {static_cast<int>(ev), get_sqlite_error_category()}; 2949} 2950 2951inline std::error_code make_error_code(orm_error_code ev) noexcept { 2952return {static_cast<int>(ev), get_orm_error_category()}; 2953} 2954 2955template<typename... T> 2956std::string get_error_message(sqlite3* db, T&&... args) { 2957std::ostringstream stream; 2958using unpack = int[]; 2959(void)unpack{0, (stream << args, 0)...}; 2960stream << sqlite3_errmsg(db); 2961return stream.str(); 2962} 2963 2964template<typename... T> 2965[[noreturn]] void throw_error(sqlite3* db, T&&... args) { 2966throw std::system_error{sqlite_errc(sqlite3_errcode(db)), get_error_message(db, std::forward<T>(args)...)}; 2967} 2968 2969inline std::system_error sqlite_to_system_error(int ev) { 2970return {sqlite_errc(ev)}; 2971} 2972 2973inline std::system_error sqlite_to_system_error(sqlite3* db) { 2974return {sqlite_errc(sqlite3_errcode(db)), sqlite3_errmsg(db)}; 2975} 2976 2977[[noreturn]] inline void throw_translated_sqlite_error(int ev) { 2978throw sqlite_to_system_error(ev); 2979} 2980 2981[[noreturn]] inline void throw_translated_sqlite_error(sqlite3* db) { 2982throw sqlite_to_system_error(db); 2983} 2984 2985[[noreturn]] inline void throw_translated_sqlite_error(sqlite3_stmt* stmt) { 2986throw 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 3006namespace sqlite_orm { 3007 3008/** 3009* Specialization for optional type (std::shared_ptr / std::unique_ptr). 3010*/ 3011template<typename T> 3012struct is_std_ptr : std::false_type {}; 3013 3014template<typename T> 3015struct is_std_ptr<std::shared_ptr<T>> : std::true_type { 3016using element_type = typename std::shared_ptr<T>::element_type; 3017 3018static std::shared_ptr<T> make(std::remove_cv_t<T>&& v) { 3019return std::make_shared<T>(std::move(v)); 3020} 3021}; 3022 3023template<typename T> 3024struct is_std_ptr<std::unique_ptr<T>> : std::true_type { 3025using element_type = typename std::unique_ptr<T>::element_type; 3026 3027static auto make(std::remove_cv_t<T>&& v) { 3028return std::make_unique<T>(std::move(v)); 3029} 3030}; 3031} 3032 3033namespace sqlite_orm { 3034 3035/** 3036* This class transforms a C++ type to a sqlite type name (int -> INTEGER, ...) 3037*/ 3038template<class T, typename Enable = void> 3039struct type_printer {}; 3040 3041struct integer_printer { 3042const std::string& print() const { 3043static const std::string res = "INTEGER"; 3044return res; 3045} 3046}; 3047 3048struct text_printer { 3049const std::string& print() const { 3050static const std::string res = "TEXT"; 3051return res; 3052} 3053}; 3054 3055struct real_printer { 3056const std::string& print() const { 3057static const std::string res = "REAL"; 3058return res; 3059} 3060}; 3061 3062struct blob_printer { 3063const std::string& print() const { 3064static const std::string res = "BLOB"; 3065return res; 3066} 3067}; 3068 3069// Note: char, unsigned/signed char are used for storing integer values, not char values. 3070template<class T> 3071struct type_printer<T, 3072std::enable_if_t<polyfill::conjunction<polyfill::negation<internal::is_any_of<T, 3073wchar_t, 3074#ifdef SQLITE_ORM_CHAR8T_SUPPORTED 3075char8_t, 3076#endif 3077char16_t, 3078char32_t>>, 3079std::is_integral<T>>::value>> : integer_printer { 3080}; 3081 3082template<class T> 3083struct type_printer<T, std::enable_if_t<std::is_floating_point<T>::value>> : real_printer {}; 3084 3085template<class T> 3086struct type_printer<T, 3087std::enable_if_t<polyfill::disjunction<std::is_same<T, const char*>, 3088std::is_base_of<std::string, T>, 3089std::is_base_of<std::wstring, T>>::value>> 3090: text_printer {}; 3091 3092template<class T> 3093struct 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 3096template<class T> 3097struct 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 3101template<> 3102struct 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 3121namespace sqlite_orm { 3122namespace 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*/ 3127template<class... Args> 3128struct same_or_void { 3129using type = void; 3130}; 3131 3132template<class A> 3133struct same_or_void<A> { 3134using type = A; 3135}; 3136 3137template<class A> 3138struct same_or_void<A, A> { 3139using type = A; 3140}; 3141 3142template<class... Args> 3143using same_or_void_t = typename same_or_void<Args...>::type; 3144 3145template<class A, class... Args> 3146struct same_or_void<A, A, Args...> : same_or_void<A, Args...> {}; 3147 3148template<class Pack> 3149struct common_type_of; 3150 3151template<template<class...> class Pack, class... Types> 3152struct 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*/ 3159template<class Pack> 3160using 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 3172namespace sqlite_orm { 3173 3174namespace internal { 3175 3176enum class collate_argument { 3177binary, 3178nocase, 3179rtrim, 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 3192namespace sqlite_orm { 3193 3194namespace internal { 3195 3196enum class conflict_clause_t { 3197rollback, 3198abort, 3199fail, 3200ignore, 3201replace, 3202}; 3203 3204struct primary_key_base { 3205enum class order_by { 3206unspecified, 3207ascending, 3208descending, 3209}; 3210struct { 3211order_by asc_option = order_by::unspecified; 3212conflict_clause_t conflict_clause = conflict_clause_t::rollback; 3213bool conflict_clause_is_on = false; 3214} options; 3215}; 3216 3217template<class T> 3218struct primary_key_with_autoincrement : T { 3219using primary_key_type = T; 3220 3221const primary_key_type& as_base() const { 3222return *this; 3223} 3224#ifndef SQLITE_ORM_AGGREGATE_BASES_SUPPORTED 3225primary_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*/ 3234template<class... Cs> 3235struct primary_key_t : primary_key_base { 3236using self = primary_key_t<Cs...>; 3237using order_by = primary_key_base::order_by; 3238using columns_tuple = std::tuple<Cs...>; 3239 3240columns_tuple columns; 3241 3242primary_key_t(columns_tuple columns) : columns(std::move(columns)) {} 3243 3244self asc() const { 3245auto res = *this; 3246res.options.asc_option = order_by::ascending; 3247return res; 3248} 3249 3250self desc() const { 3251auto res = *this; 3252res.options.asc_option = order_by::descending; 3253return res; 3254} 3255 3256primary_key_with_autoincrement<self> autoincrement() const { 3257return {*this}; 3258} 3259 3260self on_conflict_rollback() const { 3261auto res = *this; 3262res.options.conflict_clause_is_on = true; 3263res.options.conflict_clause = conflict_clause_t::rollback; 3264return res; 3265} 3266 3267self on_conflict_abort() const { 3268auto res = *this; 3269res.options.conflict_clause_is_on = true; 3270res.options.conflict_clause = conflict_clause_t::abort; 3271return res; 3272} 3273 3274self on_conflict_fail() const { 3275auto res = *this; 3276res.options.conflict_clause_is_on = true; 3277res.options.conflict_clause = conflict_clause_t::fail; 3278return res; 3279} 3280 3281self on_conflict_ignore() const { 3282auto res = *this; 3283res.options.conflict_clause_is_on = true; 3284res.options.conflict_clause = conflict_clause_t::ignore; 3285return res; 3286} 3287 3288self on_conflict_replace() const { 3289auto res = *this; 3290res.options.conflict_clause_is_on = true; 3291res.options.conflict_clause = conflict_clause_t::replace; 3292return res; 3293} 3294}; 3295 3296struct unique_base { 3297operator std::string() const { 3298return "UNIQUE"; 3299} 3300}; 3301 3302/** 3303* UNIQUE constraint class. 3304*/ 3305template<class... Args> 3306struct unique_t : unique_base { 3307using columns_tuple = std::tuple<Args...>; 3308 3309columns_tuple columns; 3310 3311unique_t(columns_tuple columns_) : columns(std::move(columns_)) {} 3312}; 3313 3314struct unindexed_t {}; 3315 3316template<class T> 3317struct prefix_t { 3318using value_type = T; 3319 3320value_type value; 3321}; 3322 3323template<class T> 3324struct tokenize_t { 3325using value_type = T; 3326 3327value_type value; 3328}; 3329 3330template<class T> 3331struct content_t { 3332using value_type = T; 3333 3334value_type value; 3335}; 3336 3337template<class T> 3338struct table_content_t { 3339using mapped_type = T; 3340}; 3341 3342/** 3343* DEFAULT constraint class. 3344* T is a value type. 3345*/ 3346template<class T> 3347struct default_t { 3348using value_type = T; 3349 3350value_type value; 3351 3352operator std::string() const { 3353return "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 3365template<class A, class B> 3366struct foreign_key_t; 3367 3368enum class foreign_key_action { 3369none, // not specified 3370no_action, 3371restrict_, 3372set_null, 3373set_default, 3374cascade, 3375}; 3376 3377inline std::ostream& operator<<(std::ostream& os, foreign_key_action action) { 3378switch (action) { 3379case foreign_key_action::no_action: 3380os << "NO ACTION"; 3381break; 3382case foreign_key_action::restrict_: 3383os << "RESTRICT"; 3384break; 3385case foreign_key_action::set_null: 3386os << "SET NULL"; 3387break; 3388case foreign_key_action::set_default: 3389os << "SET DEFAULT"; 3390break; 3391case foreign_key_action::cascade: 3392os << "CASCADE"; 3393break; 3394case foreign_key_action::none: 3395break; 3396} 3397return os; 3398} 3399 3400struct on_update_delete_base { 3401const bool update; // true if update and false if delete 3402 3403operator std::string() const { 3404if (this->update) { 3405return "ON UPDATE"; 3406} else { 3407return "ON DELETE"; 3408} 3409} 3410}; 3411 3412/** 3413* F - foreign key class 3414*/ 3415template<class F> 3416struct on_update_delete_t : on_update_delete_base { 3417using foreign_key_type = F; 3418 3419const foreign_key_type& fk; 3420 3421on_update_delete_t(decltype(fk) fk_, decltype(update) update_, foreign_key_action action_) : 3422on_update_delete_base{update_}, fk(fk_), _action(action_) {} 3423 3424foreign_key_action _action = foreign_key_action::none; 3425 3426foreign_key_type no_action() const { 3427auto res = this->fk; 3428if (update) { 3429res.on_update._action = foreign_key_action::no_action; 3430} else { 3431res.on_delete._action = foreign_key_action::no_action; 3432} 3433return res; 3434} 3435 3436foreign_key_type restrict_() const { 3437auto res = this->fk; 3438if (update) { 3439res.on_update._action = foreign_key_action::restrict_; 3440} else { 3441res.on_delete._action = foreign_key_action::restrict_; 3442} 3443return res; 3444} 3445 3446foreign_key_type set_null() const { 3447auto res = this->fk; 3448if (update) { 3449res.on_update._action = foreign_key_action::set_null; 3450} else { 3451res.on_delete._action = foreign_key_action::set_null; 3452} 3453return res; 3454} 3455 3456foreign_key_type set_default() const { 3457auto res = this->fk; 3458if (update) { 3459res.on_update._action = foreign_key_action::set_default; 3460} else { 3461res.on_delete._action = foreign_key_action::set_default; 3462} 3463return res; 3464} 3465 3466foreign_key_type cascade() const { 3467auto res = this->fk; 3468if (update) { 3469res.on_update._action = foreign_key_action::cascade; 3470} else { 3471res.on_delete._action = foreign_key_action::cascade; 3472} 3473return res; 3474} 3475 3476operator bool() const { 3477return this->_action != foreign_key_action::none; 3478} 3479}; 3480 3481template<class F> 3482bool operator==(const on_update_delete_t<F>& lhs, const on_update_delete_t<F>& rhs) { 3483return lhs._action == rhs._action; 3484} 3485 3486template<class... Cs, class... Rs> 3487struct foreign_key_t<std::tuple<Cs...>, std::tuple<Rs...>> { 3488using columns_type = std::tuple<Cs...>; 3489using references_type = std::tuple<Rs...>; 3490using self = foreign_key_t<columns_type, references_type>; 3491 3492/** 3493* Holds obect type of all referenced columns. 3494*/ 3495using target_type = same_or_void_t<table_type_of_t<Rs>...>; 3496 3497/** 3498* Holds obect type of all source columns. 3499*/ 3500using source_type = same_or_void_t<table_type_of_t<Cs>...>; 3501 3502columns_type columns; 3503references_type references; 3504 3505on_update_delete_t<self> on_update; 3506on_update_delete_t<self> on_delete; 3507 3508static_assert(std::tuple_size<columns_type>::value == std::tuple_size<references_type>::value, 3509"Columns size must be equal to references tuple"); 3510static_assert(!std::is_same<target_type, void>::value, "All references must have the same type"); 3511 3512foreign_key_t(columns_type columns_, references_type references_) : 3513columns(std::move(columns_)), references(std::move(references_)), 3514on_update(*this, true, foreign_key_action::none), on_delete(*this, false, foreign_key_action::none) {} 3515 3516foreign_key_t(const self& other) : 3517columns(other.columns), references(other.references), on_update(*this, true, other.on_update._action), 3518on_delete(*this, false, other.on_delete._action) {} 3519 3520self& operator=(const self& other) { 3521this->columns = other.columns; 3522this->references = other.references; 3523this->on_update = {*this, true, other.on_update._action}; 3524this->on_delete = {*this, false, other.on_delete._action}; 3525return *this; 3526} 3527}; 3528 3529template<class A, class B> 3530bool operator==(const foreign_key_t<A, B>& lhs, const foreign_key_t<A, B>& rhs) { 3531return lhs.columns == rhs.columns && lhs.references == rhs.references && lhs.on_update == rhs.on_update && 3532lhs.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*/ 3540template<class... Cs> 3541struct foreign_key_intermediate_t { 3542using tuple_type = std::tuple<Cs...>; 3543 3544tuple_type columns; 3545 3546template<class... Rs> 3547foreign_key_t<std::tuple<Cs...>, std::tuple<Rs...>> references(Rs... refs) { 3548return {std::move(this->columns), {std::forward<Rs>(refs)...}}; 3549} 3550 3551template<class T, class... Rs> 3552foreign_key_t<std::tuple<Cs...>, std::tuple<internal::column_pointer<T, Rs>...>> references(Rs... refs) { 3553return {std::move(this->columns), {sqlite_orm::column<T>(refs)...}}; 3554} 3555}; 3556#endif 3557 3558struct collate_constraint_t { 3559collate_argument argument = collate_argument::binary; 3560#ifndef SQLITE_ORM_AGGREGATE_NSDMI_SUPPORTED 3561collate_constraint_t(collate_argument argument) : argument{argument} {} 3562#endif 3563 3564operator std::string() const { 3565return "COLLATE " + this->string_from_collate_argument(this->argument); 3566} 3567 3568static std::string string_from_collate_argument(collate_argument argument) { 3569switch (argument) { 3570case collate_argument::binary: 3571return "BINARY"; 3572case collate_argument::nocase: 3573return "NOCASE"; 3574case collate_argument::rtrim: 3575return "RTRIM"; 3576} 3577throw std::system_error{orm_error_code::invalid_collate_argument_enum}; 3578} 3579}; 3580 3581template<class T> 3582struct check_t { 3583using expression_type = T; 3584 3585expression_type expression; 3586}; 3587 3588struct basic_generated_always { 3589enum class storage_type { 3590not_specified, 3591virtual_, 3592stored, 3593}; 3594 3595#if SQLITE_VERSION_NUMBER >= 3031000 3596bool full = true; 3597storage_type storage = storage_type::not_specified; 3598#endif 3599 3600#ifndef SQLITE_ORM_AGGREGATE_NSDMI_SUPPORTED 3601basic_generated_always(bool full, storage_type storage) : full{full}, storage{storage} {} 3602#endif 3603}; 3604 3605#if SQLITE_VERSION_NUMBER >= 3031000 3606template<class T> 3607struct generated_always_t : basic_generated_always { 3608using expression_type = T; 3609 3610expression_type expression; 3611 3612generated_always_t(expression_type expression_, bool full, storage_type storage) : 3613basic_generated_always{full, storage}, expression(std::move(expression_)) {} 3614 3615generated_always_t<T> virtual_() { 3616return {std::move(this->expression), this->full, storage_type::virtual_}; 3617} 3618 3619generated_always_t<T> stored() { 3620return {std::move(this->expression), this->full, storage_type::stored}; 3621} 3622}; 3623#endif 3624 3625struct null_t {}; 3626 3627struct not_null_t {}; 3628} 3629 3630namespace internal { 3631 3632template<class T> 3633SQLITE_ORM_INLINE_VAR constexpr bool is_foreign_key_v = 3634#if SQLITE_VERSION_NUMBER >= 3006019 3635polyfill::is_specialization_of<T, foreign_key_t>::value; 3636#else 3637false; 3638#endif 3639 3640template<class T> 3641struct is_foreign_key : polyfill::bool_constant<is_foreign_key_v<T>> {}; 3642 3643template<class T> 3644SQLITE_ORM_INLINE_VAR constexpr bool is_primary_key_v = std::is_base_of<primary_key_base, T>::value; 3645 3646template<class T> 3647struct is_primary_key : polyfill::bool_constant<is_primary_key_v<T>> {}; 3648 3649template<class T> 3650SQLITE_ORM_INLINE_VAR constexpr bool is_generated_always_v = 3651#if SQLITE_VERSION_NUMBER >= 3031000 3652polyfill::is_specialization_of<T, generated_always_t>::value; 3653#else 3654false; 3655#endif 3656 3657template<class T> 3658struct is_generated_always : polyfill::bool_constant<is_generated_always_v<T>> {}; 3659 3660/** 3661* PRIMARY KEY INSERTABLE traits. 3662*/ 3663template<typename Column> 3664struct is_primary_key_insertable 3665: polyfill::disjunction< 3666mpl::invoke_t<mpl::disjunction<check_if_has_template<primary_key_with_autoincrement>, 3667check_if_has_template<default_t>>, 3668constraints_type_t<Column>>, 3669std::is_base_of<integer_printer, type_printer<field_type_t<Column>>>> { 3670 3671static_assert(tuple_has<constraints_type_t<Column>, is_primary_key>::value, 3672"an unexpected type was passed"); 3673}; 3674 3675template<class T> 3676using is_column_constraint = mpl::invoke_t<mpl::disjunction<check_if<std::is_base_of, primary_key_t<>>, 3677check_if_is_type<null_t>, 3678check_if_is_type<not_null_t>, 3679check_if_is_type<unique_t<>>, 3680check_if_is_template<default_t>, 3681check_if_is_template<check_t>, 3682check_if_is_type<collate_constraint_t>, 3683check_if<is_generated_always>, 3684check_if_is_type<unindexed_t>>, 3685T>; 3686} 3687 3688#if SQLITE_VERSION_NUMBER >= 3031000 3689template<class T> 3690internal::generated_always_t<T> generated_always_as(T expression) { 3691return {std::move(expression), true, internal::basic_generated_always::storage_type::not_specified}; 3692} 3693 3694template<class T> 3695internal::generated_always_t<T> as(T expression) { 3696return {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*/ 3705template<class... Cs> 3706internal::foreign_key_intermediate_t<Cs...> foreign_key(Cs... columns) { 3707return {{std::forward<Cs>(columns)...}}; 3708} 3709#endif 3710 3711/** 3712* UNIQUE table constraint builder function. 3713*/ 3714template<class... Args> 3715internal::unique_t<Args...> unique(Args... args) { 3716return {{std::forward<Args>(args)...}}; 3717} 3718 3719/** 3720* UNIQUE column constraint builder function. 3721*/ 3722inline internal::unique_t<> unique() { 3723return {{}}; 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*/ 3732inline internal::unindexed_t unindexed() { 3733return {}; 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*/ 3741template<class T> 3742internal::prefix_t<T> prefix(T value) { 3743return {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*/ 3751template<class T> 3752internal::tokenize_t<T> tokenize(T value) { 3753return {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*/ 3761template<class T> 3762internal::content_t<T> content(T value) { 3763return {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*/ 3771template<class T> 3772internal::table_content_t<T> content() { 3773return {}; 3774} 3775#endif 3776 3777/** 3778* PRIMARY KEY table constraint builder function. 3779*/ 3780template<class... Cs> 3781internal::primary_key_t<Cs...> primary_key(Cs... cs) { 3782return {{std::forward<Cs>(cs)...}}; 3783} 3784 3785/** 3786* PRIMARY KEY column constraint builder function. 3787*/ 3788inline internal::primary_key_t<> primary_key() { 3789return {{}}; 3790} 3791 3792template<class T> 3793internal::default_t<T> default_value(T t) { 3794return {std::move(t)}; 3795} 3796 3797inline internal::collate_constraint_t collate_nocase() { 3798return {internal::collate_argument::nocase}; 3799} 3800 3801inline internal::collate_constraint_t collate_binary() { 3802return {internal::collate_argument::binary}; 3803} 3804 3805inline internal::collate_constraint_t collate_rtrim() { 3806return {internal::collate_argument::rtrim}; 3807} 3808 3809template<class T> 3810internal::check_t<T> check(T t) { 3811return {std::move(t)}; 3812} 3813 3814inline internal::null_t null() { 3815return {}; 3816} 3817 3818inline internal::not_null_t not_null() { 3819return {}; 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 3841namespace 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*/ 3847template<class T, typename SFINAE = void> 3848struct field_printer; 3849 3850namespace 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*/ 3856template<class Printer> 3857struct indirectly_test_printable; 3858 3859template<class T, class SFINAE = void> 3860SQLITE_ORM_INLINE_VAR constexpr bool is_printable_v = false; 3861template<class T> 3862SQLITE_ORM_INLINE_VAR constexpr bool 3863is_printable_v<T, polyfill::void_t<indirectly_test_printable<decltype(field_printer<T>{})>>> = true; 3864 3865template<class T> 3866struct is_printable : polyfill::bool_constant<is_printable_v<T>> {}; 3867} 3868 3869template<class T> 3870struct field_printer<T, internal::match_if<std::is_arithmetic, T>> { 3871std::string operator()(const T& t) const { 3872std::stringstream ss; 3873ss << t; 3874return ss.str(); 3875} 3876}; 3877 3878/** 3879* Upgrade to integer is required when using unsigned char(uint8_t) 3880*/ 3881template<> 3882struct field_printer<unsigned char, void> { 3883std::string operator()(const unsigned char& t) const { 3884std::stringstream ss; 3885ss << +t; 3886return ss.str(); 3887} 3888}; 3889 3890/** 3891* Upgrade to integer is required when using signed char(int8_t) 3892*/ 3893template<> 3894struct field_printer<signed char, void> { 3895std::string operator()(const signed char& t) const { 3896std::stringstream ss; 3897ss << +t; 3898return ss.str(); 3899} 3900}; 3901 3902/** 3903* char is neither signed char nor unsigned char so it has its own specialization 3904*/ 3905template<> 3906struct field_printer<char, void> { 3907std::string operator()(const char& t) const { 3908std::stringstream ss; 3909ss << +t; 3910return ss.str(); 3911} 3912}; 3913 3914template<class T> 3915struct field_printer<T, internal::match_if<std::is_base_of, std::string, T>> { 3916std::string operator()(std::string string) const { 3917return string; 3918} 3919}; 3920 3921template<> 3922struct field_printer<std::vector<char>, void> { 3923std::string operator()(const std::vector<char>& t) const { 3924std::stringstream ss; 3925ss << std::hex; 3926for (auto c: t) { 3927ss << c; 3928} 3929return ss.str(); 3930} 3931}; 3932#ifndef SQLITE_ORM_OMITS_CODECVT 3933/** 3934* Specialization for std::wstring (UTF-16 assumed). 3935*/ 3936template<class T> 3937struct field_printer<T, internal::match_if<std::is_base_of, std::wstring, T>> { 3938std::string operator()(const std::wstring& wideString) const { 3939std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>> converter; 3940return converter.to_bytes(wideString); 3941} 3942}; 3943#endif // SQLITE_ORM_OMITS_CODECVT 3944template<> 3945struct field_printer<nullptr_t, void> { 3946std::string operator()(const nullptr_t&) const { 3947return "NULL"; 3948} 3949}; 3950#ifdef SQLITE_ORM_OPTIONAL_SUPPORTED 3951template<> 3952struct field_printer<std::nullopt_t, void> { 3953std::string operator()(const std::nullopt_t&) const { 3954return "NULL"; 3955} 3956}; 3957#endif // SQLITE_ORM_OPTIONAL_SUPPORTED 3958template<class T> 3959struct field_printer<T, 3960std::enable_if_t<polyfill::conjunction< 3961is_std_ptr<T>, 3962internal::is_printable<std::remove_cv_t<typename T::element_type>>>::value>> { 3963using unqualified_type = std::remove_cv_t<typename T::element_type>; 3964 3965std::string operator()(const T& t) const { 3966if (t) { 3967return field_printer<unqualified_type>()(*t); 3968} else { 3969return field_printer<nullptr_t>{}(nullptr); 3970} 3971} 3972}; 3973 3974#ifdef SQLITE_ORM_OPTIONAL_SUPPORTED 3975template<class T> 3976struct field_printer< 3977T, 3978std::enable_if_t<polyfill::conjunction_v<polyfill::is_specialization_of<T, std::optional>, 3979internal::is_printable<std::remove_cv_t<typename T::value_type>>>>> { 3980using unqualified_type = std::remove_cv_t<typename T::value_type>; 3981 3982std::string operator()(const T& t) const { 3983if (t.has_value()) { 3984return field_printer<unqualified_type>()(*t); 3985} else { 3986return 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 3997namespace sqlite_orm { 3998 3999namespace internal { 4000 4001struct rowid_t { 4002operator std::string() const { 4003return "rowid"; 4004} 4005}; 4006 4007struct oid_t { 4008operator std::string() const { 4009return "oid"; 4010} 4011}; 4012 4013struct _rowid_t { 4014operator std::string() const { 4015return "_rowid_"; 4016} 4017}; 4018 4019template<class T> 4020struct table_rowid_t : public rowid_t { 4021using type = T; 4022}; 4023 4024template<class T> 4025struct table_oid_t : public oid_t { 4026using type = T; 4027}; 4028template<class T> 4029struct table__rowid_t : public _rowid_t { 4030using type = T; 4031}; 4032 4033} 4034 4035inline internal::rowid_t rowid() { 4036return {}; 4037} 4038 4039inline internal::oid_t oid() { 4040return {}; 4041} 4042 4043inline internal::_rowid_t _rowid_() { 4044return {}; 4045} 4046 4047template<class T> 4048internal::table_rowid_t<T> rowid() { 4049return {}; 4050} 4051 4052template<class T> 4053internal::table_oid_t<T> oid() { 4054return {}; 4055} 4056 4057template<class T> 4058internal::table__rowid_t<T> _rowid_() { 4059return {}; 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 4074namespace sqlite_orm { 4075 4076namespace 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 4083template<template<typename...> class Base> 4084struct is_base_of_template_impl { 4085template<typename... Ts> 4086static constexpr std::true_type test(const Base<Ts...>&); 4087 4088static constexpr std::false_type test(...); 4089}; 4090 4091template<typename T, template<typename...> class C> 4092using is_base_of_template = decltype(is_base_of_template_impl<C>::test(std::declval<T>())); 4093#else 4094template<template<typename...> class C, typename... Ts> 4095std::true_type is_base_of_template_impl(const C<Ts...>&); 4096 4097template<template<typename...> class C> 4098std::false_type is_base_of_template_impl(...); 4099 4100template<typename T, template<typename...> class C> 4101using is_base_of_template = decltype(is_base_of_template_impl<C>(std::declval<T>())); 4102#endif 4103 4104template<typename T, template<typename...> class C> 4105SQLITE_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 4129namespace sqlite_orm { 4130namespace internal { 4131#ifdef SQLITE_ORM_STRING_VIEW_SUPPORTED 4132using serialize_result_type = std::string_view; 4133using serialize_arg_type = std::string_view; 4134#else 4135using serialize_result_type = std::string; 4136using serialize_arg_type = const std::string&; 4137#endif 4138} 4139} 4140 4141namespace sqlite_orm { 4142 4143namespace internal { 4144 4145template<class L, class R, class... Ds> 4146struct binary_operator : Ds... { 4147using left_type = L; 4148using right_type = R; 4149 4150left_type lhs; 4151right_type rhs; 4152 4153constexpr binary_operator(left_type lhs_, right_type rhs_) : lhs(std::move(lhs_)), rhs(std::move(rhs_)) {} 4154}; 4155 4156template<class T> 4157SQLITE_ORM_INLINE_VAR constexpr bool is_binary_operator_v = is_base_of_template<T, binary_operator>::value; 4158 4159template<class T> 4160using is_binary_operator = polyfill::bool_constant<is_binary_operator_v<T>>; 4161 4162struct conc_string { 4163serialize_result_type serialize() const { 4164return "||"; 4165} 4166}; 4167 4168/** 4169* Result of concatenation || operator 4170*/ 4171template<class L, class R> 4172using conc_t = binary_operator<L, R, conc_string>; 4173 4174struct unary_minus_string { 4175serialize_result_type serialize() const { 4176return "-"; 4177} 4178}; 4179 4180/** 4181* Result of unary minus - operator 4182*/ 4183template<class T> 4184struct unary_minus_t : unary_minus_string, arithmetic_t, negatable_t { 4185using argument_type = T; 4186 4187argument_type argument; 4188 4189unary_minus_t(argument_type argument_) : argument(std::move(argument_)) {} 4190}; 4191 4192struct add_string { 4193serialize_result_type serialize() const { 4194return "+"; 4195} 4196}; 4197 4198/** 4199* Result of addition + operator 4200*/ 4201template<class L, class R> 4202using add_t = binary_operator<L, R, add_string, arithmetic_t, negatable_t>; 4203 4204struct sub_string { 4205serialize_result_type serialize() const { 4206return "-"; 4207} 4208}; 4209 4210/** 4211* Result of substraction - operator 4212*/ 4213template<class L, class R> 4214using sub_t = binary_operator<L, R, sub_string, arithmetic_t, negatable_t>; 4215 4216struct mul_string { 4217serialize_result_type serialize() const { 4218return "*"; 4219} 4220}; 4221 4222/** 4223* Result of multiply * operator 4224*/ 4225template<class L, class R> 4226using mul_t = binary_operator<L, R, mul_string, arithmetic_t, negatable_t>; 4227 4228struct div_string { 4229serialize_result_type serialize() const { 4230return "/"; 4231} 4232}; 4233 4234/** 4235* Result of divide / operator 4236*/ 4237template<class L, class R> 4238using div_t = binary_operator<L, R, div_string, arithmetic_t, negatable_t>; 4239 4240struct mod_operator_string { 4241serialize_result_type serialize() const { 4242return "%"; 4243} 4244}; 4245 4246/** 4247* Result of mod % operator 4248*/ 4249template<class L, class R> 4250using mod_t = binary_operator<L, R, mod_operator_string, arithmetic_t, negatable_t>; 4251 4252struct bitwise_shift_left_string { 4253serialize_result_type serialize() const { 4254return "<<"; 4255} 4256}; 4257 4258/** 4259* Result of bitwise shift left << operator 4260*/ 4261template<class L, class R> 4262using bitwise_shift_left_t = binary_operator<L, R, bitwise_shift_left_string, arithmetic_t, negatable_t>; 4263 4264struct bitwise_shift_right_string { 4265serialize_result_type serialize() const { 4266return ">>"; 4267} 4268}; 4269 4270/** 4271* Result of bitwise shift right >> operator 4272*/ 4273template<class L, class R> 4274using bitwise_shift_right_t = binary_operator<L, R, bitwise_shift_right_string, arithmetic_t, negatable_t>; 4275 4276struct bitwise_and_string { 4277serialize_result_type serialize() const { 4278return "&"; 4279} 4280}; 4281 4282/** 4283* Result of bitwise and & operator 4284*/ 4285template<class L, class R> 4286using bitwise_and_t = binary_operator<L, R, bitwise_and_string, arithmetic_t, negatable_t>; 4287 4288struct bitwise_or_string { 4289serialize_result_type serialize() const { 4290return "|"; 4291} 4292}; 4293 4294/** 4295* Result of bitwise or | operator 4296*/ 4297template<class L, class R> 4298using bitwise_or_t = binary_operator<L, R, bitwise_or_string, arithmetic_t, negatable_t>; 4299 4300struct bitwise_not_string { 4301serialize_result_type serialize() const { 4302return "~"; 4303} 4304}; 4305 4306/** 4307* Result of bitwise not ~ operator 4308*/ 4309template<class T> 4310struct bitwise_not_t : bitwise_not_string, arithmetic_t, negatable_t { 4311using argument_type = T; 4312 4313argument_type argument; 4314 4315bitwise_not_t(argument_type argument_) : argument(std::move(argument_)) {} 4316}; 4317 4318struct assign_string { 4319serialize_result_type serialize() const { 4320return "="; 4321} 4322}; 4323 4324/** 4325* Result of assign = operator 4326*/ 4327template<class L, class R> 4328using assign_t = binary_operator<L, R, assign_string>; 4329 4330/** 4331* Assign operator traits. Common case 4332*/ 4333template<class T> 4334struct is_assign_t : public std::false_type {}; 4335 4336/** 4337* Assign operator traits. Specialized case 4338*/ 4339template<class L, class R> 4340struct 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*/ 4347template<class L, class R> 4348constexpr internal::conc_t<L, R> conc(L l, R r) { 4349return {std::move(l), std::move(r)}; 4350} 4351 4352template<class T> 4353constexpr internal::unary_minus_t<T> minus(T t) { 4354return {std::move(t)}; 4355} 4356 4357/** 4358* Public interface for + operator. Example: `select(add(&User::age, 100));` => SELECT age + 100 FROM users 4359*/ 4360template<class L, class R> 4361constexpr internal::add_t<L, R> add(L l, R r) { 4362return {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*/ 4368template<class L, class R> 4369constexpr internal::sub_t<L, R> sub(L l, R r) { 4370return {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*/ 4376template<class L, class R> 4377constexpr internal::mul_t<L, R> mul(L l, R r) { 4378return {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*/ 4386template<class L, class R> 4387constexpr internal::div_t<L, R> div(L l, R r) { 4388return {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*/ 4394template<class L, class R> 4395constexpr internal::mod_t<L, R> mod(L l, R r) { 4396return {std::move(l), std::move(r)}; 4397} 4398 4399template<class L, class R> 4400constexpr internal::bitwise_shift_left_t<L, R> bitwise_shift_left(L l, R r) { 4401return {std::move(l), std::move(r)}; 4402} 4403 4404template<class L, class R> 4405constexpr internal::bitwise_shift_right_t<L, R> bitwise_shift_right(L l, R r) { 4406return {std::move(l), std::move(r)}; 4407} 4408 4409template<class L, class R> 4410constexpr internal::bitwise_and_t<L, R> bitwise_and(L l, R r) { 4411return {std::move(l), std::move(r)}; 4412} 4413 4414template<class L, class R> 4415constexpr internal::bitwise_or_t<L, R> bitwise_or(L l, R r) { 4416return {std::move(l), std::move(r)}; 4417} 4418 4419template<class T> 4420constexpr internal::bitwise_not_t<T> bitwise_not(T t) { 4421return {std::move(t)}; 4422} 4423 4424template<class L, class R> 4425internal::assign_t<L, R> assign(L l, R r) { 4426return {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 4453namespace sqlite_orm { 4454 4455namespace 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*/ 4461template<class T> 4462struct optional_container { 4463using type = T; 4464 4465type field; 4466 4467template<class L> 4468void apply(const L& l) const { 4469l(this->field); 4470} 4471}; 4472 4473template<> 4474struct optional_container<void> { 4475using type = void; 4476 4477template<class L> 4478void 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 4494namespace sqlite_orm { 4495namespace internal { 4496 4497struct where_string { 4498serialize_result_type serialize() const { 4499return "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*/ 4508template<class C> 4509struct where_t : where_string { 4510using expression_type = C; 4511 4512expression_type expression; 4513 4514constexpr where_t(expression_type expression_) : expression(std::move(expression_)) {} 4515}; 4516 4517template<class T> 4518SQLITE_ORM_INLINE_VAR constexpr bool is_where_v = polyfill::is_specialization_of<T, where_t>::value; 4519 4520template<class T> 4521struct 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*/ 4533template<class C> 4534constexpr internal::where_t<C> where(C expression) { 4535return {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 4547namespace sqlite_orm { 4548namespace internal { 4549 4550template<class T, class... Args> 4551struct group_by_with_having { 4552using args_type = std::tuple<Args...>; 4553using expression_type = T; 4554 4555args_type args; 4556expression_type expression; 4557}; 4558 4559/** 4560* GROUP BY pack holder. 4561*/ 4562template<class... Args> 4563struct group_by_t { 4564using args_type = std::tuple<Args...>; 4565 4566args_type args; 4567 4568template<class T> 4569group_by_with_having<T, Args...> having(T expression) { 4570return {std::move(this->args), std::move(expression)}; 4571} 4572}; 4573 4574template<class T> 4575using is_group_by = polyfill::disjunction<polyfill::is_specialization_of<T, group_by_t>, 4576polyfill::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*/ 4583template<class... Args> 4584internal::group_by_t<Args...> group_by(Args... args) { 4585return {{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 4629namespace sqlite_orm { 4630 4631namespace internal { 4632 4633struct serializer_context_base { 4634bool replace_bindable_with_question = false; 4635bool skip_table_name = true; 4636bool use_parentheses = true; 4637bool fts5_columns = false; 4638}; 4639 4640template<class DBOs> 4641struct serializer_context : serializer_context_base { 4642using db_objects_type = DBOs; 4643 4644const db_objects_type& db_objects; 4645 4646serializer_context(const db_objects_type& dbObjects) : db_objects{dbObjects} {} 4647}; 4648 4649template<class S> 4650struct serializer_context_builder { 4651using storage_type = S; 4652using db_objects_type = typename storage_type::db_objects_type; 4653 4654serializer_context_builder(const storage_type& storage_) : storage{storage_} {} 4655 4656serializer_context<db_objects_type> operator()() const { 4657return {obtain_db_objects(this->storage)}; 4658} 4659 4660const 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 4687namespace sqlite_orm { 4688 4689namespace internal { 4690 4691template<class L, class... Args> 4692struct in_t; 4693 4694template<class L, class R> 4695struct and_condition_t; 4696 4697template<class L, class R> 4698struct or_condition_t; 4699 4700/** 4701* Result of c(...) function. Has operator= overloaded which returns assign_t 4702*/ 4703template<class T> 4704struct expression_t { 4705T value; 4706 4707template<class R> 4708assign_t<T, R> operator=(R r) const { 4709return {this->value, std::move(r)}; 4710} 4711 4712assign_t<T, nullptr_t> operator=(nullptr_t) const { 4713return {this->value, nullptr}; 4714} 4715#ifdef SQLITE_ORM_OPTIONAL_SUPPORTED 4716assign_t<T, std::nullopt_t> operator=(std::nullopt_t) const { 4717return {this->value, std::nullopt}; 4718} 4719#endif 4720template<class... Args> 4721in_t<T, Args...> in(Args... args) const { 4722return {this->value, {std::forward<Args>(args)...}, false}; 4723} 4724 4725template<class... Args> 4726in_t<T, Args...> not_in(Args... args) const { 4727return {this->value, {std::forward<Args>(args)...}, true}; 4728} 4729 4730template<class R> 4731and_condition_t<T, R> and_(R right) const { 4732return {this->value, std::move(right)}; 4733} 4734 4735template<class R> 4736or_condition_t<T, R> or_(R right) const { 4737return {this->value, std::move(right)}; 4738} 4739}; 4740 4741template<class T> 4742SQLITE_ORM_INLINE_VAR constexpr bool 4743is_operator_argument_v<T, std::enable_if_t<polyfill::is_specialization_of<T, expression_t>::value>> = true; 4744 4745template<class T> 4746constexpr T get_from_expression(T&& value) { 4747return std::move(value); 4748} 4749 4750template<class T> 4751constexpr const T& get_from_expression(const T& value) { 4752return value; 4753} 4754 4755template<class T> 4756constexpr T get_from_expression(expression_t<T>&& expression) { 4757return std::move(expression.value); 4758} 4759 4760template<class T> 4761constexpr const T& get_from_expression(const expression_t<T>& expression) { 4762return expression.value; 4763} 4764 4765template<class T> 4766using 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*/ 4773template<class T> 4774constexpr internal::expression_t<T> c(T value) { 4775return {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 4787namespace sqlite_orm { 4788namespace internal { 4789 4790/* 4791* Protect an otherwise bindable element so that it is always serialized as a literal value. 4792*/ 4793template<class T> 4794struct literal_holder { 4795using type = T; 4796 4797type value; 4798}; 4799 4800} 4801} 4802 4803namespace sqlite_orm { 4804 4805namespace internal { 4806 4807struct limit_string { 4808operator std::string() const { 4809return "LIMIT"; 4810} 4811}; 4812 4813/** 4814* Stores LIMIT/OFFSET info 4815*/ 4816template<class T, bool has_offset, bool offset_is_implicit, class O> 4817struct limit_t : limit_string { 4818T lim; 4819optional_container<O> off; 4820 4821limit_t() = default; 4822 4823limit_t(decltype(lim) lim_) : lim(std::move(lim_)) {} 4824 4825limit_t(decltype(lim) lim_, decltype(off) off_) : lim(std::move(lim_)), off(std::move(off_)) {} 4826}; 4827 4828template<class T> 4829struct is_limit : std::false_type {}; 4830 4831template<class T, bool has_offset, bool offset_is_implicit, class O> 4832struct is_limit<limit_t<T, has_offset, offset_is_implicit, O>> : std::true_type {}; 4833 4834/** 4835* Stores OFFSET only info 4836*/ 4837template<class T> 4838struct offset_t { 4839T off; 4840}; 4841 4842template<class T> 4843using is_offset = polyfill::is_specialization_of<T, offset_t>; 4844 4845/** 4846* Collated something 4847*/ 4848template<class T> 4849struct collate_t : public condition_t { 4850T expr; 4851collate_argument argument; 4852 4853collate_t(T expr_, collate_argument argument_) : expr(std::move(expr_)), argument(argument_) {} 4854 4855operator std::string() const { 4856return collate_constraint_t{this->argument}; 4857} 4858}; 4859 4860struct named_collate_base { 4861std::string name; 4862 4863operator std::string() const { 4864return "COLLATE " + this->name; 4865} 4866}; 4867 4868/** 4869* Collated something with custom collate function 4870*/ 4871template<class T> 4872struct named_collate : named_collate_base { 4873T expr; 4874 4875named_collate(T expr_, std::string name_) : named_collate_base{std::move(name_)}, expr(std::move(expr_)) {} 4876}; 4877 4878struct negated_condition_string { 4879operator std::string() const { 4880return "NOT"; 4881} 4882}; 4883 4884/** 4885* Result of not operator 4886*/ 4887template<class C> 4888struct negated_condition_t : condition_t, negated_condition_string { 4889using argument_type = C; 4890 4891argument_type c; 4892 4893constexpr 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*/ 4903template<class L, class R, class S, class Res> 4904struct binary_condition : condition_t, S { 4905using left_type = L; 4906using right_type = R; 4907using result_type = Res; 4908 4909left_type lhs; 4910right_type rhs; 4911 4912constexpr binary_condition() = default; 4913 4914constexpr binary_condition(left_type l_, right_type r_) : lhs(std::move(l_)), rhs(std::move(r_)) {} 4915}; 4916 4917template<class T> 4918SQLITE_ORM_INLINE_VAR constexpr bool is_binary_condition_v = is_base_of_template_v<T, binary_condition>; 4919 4920template<class T> 4921struct is_binary_condition : polyfill::bool_constant<is_binary_condition_v<T>> {}; 4922 4923struct and_condition_string { 4924serialize_result_type serialize() const { 4925return "AND"; 4926} 4927}; 4928 4929/** 4930* Result of and operator 4931*/ 4932template<class L, class R> 4933struct and_condition_t : binary_condition<L, R, and_condition_string, bool>, negatable_t { 4934using super = binary_condition<L, R, and_condition_string, bool>; 4935 4936using super::super; 4937}; 4938 4939struct or_condition_string { 4940serialize_result_type serialize() const { 4941return "OR"; 4942} 4943}; 4944 4945/** 4946* Result of or operator 4947*/ 4948template<class L, class R> 4949struct or_condition_t : binary_condition<L, R, or_condition_string, bool>, negatable_t { 4950using super = binary_condition<L, R, or_condition_string, bool>; 4951 4952using super::super; 4953}; 4954 4955struct is_equal_string { 4956serialize_result_type serialize() const { 4957return "="; 4958} 4959}; 4960 4961/** 4962* = and == operators object 4963*/ 4964template<class L, class R> 4965struct is_equal_t : binary_condition<L, R, is_equal_string, bool>, negatable_t { 4966using self = is_equal_t<L, R>; 4967 4968using binary_condition<L, R, is_equal_string, bool>::binary_condition; 4969 4970collate_t<self> collate_binary() const { 4971return {*this, collate_argument::binary}; 4972} 4973 4974collate_t<self> collate_nocase() const { 4975return {*this, collate_argument::nocase}; 4976} 4977 4978collate_t<self> collate_rtrim() const { 4979return {*this, collate_argument::rtrim}; 4980} 4981 4982named_collate<self> collate(std::string name) const { 4983return {*this, std::move(name)}; 4984} 4985 4986template<class C> 4987named_collate<self> collate() const { 4988std::stringstream ss; 4989ss << C::name() << std::flush; 4990return {*this, ss.str()}; 4991} 4992}; 4993 4994template<class L, class R> 4995struct is_equal_with_table_t : negatable_t { 4996using left_type = L; 4997using right_type = R; 4998 4999right_type rhs; 5000 5001is_equal_with_table_t(right_type rhs) : rhs(std::move(rhs)) {} 5002}; 5003 5004struct is_not_equal_string { 5005serialize_result_type serialize() const { 5006return "!="; 5007} 5008}; 5009 5010/** 5011* != operator object 5012*/ 5013template<class L, class R> 5014struct is_not_equal_t : binary_condition<L, R, is_not_equal_string, bool>, negatable_t { 5015using self = is_not_equal_t<L, R>; 5016 5017using binary_condition<L, R, is_not_equal_string, bool>::binary_condition; 5018 5019collate_t<self> collate_binary() const { 5020return {*this, collate_argument::binary}; 5021} 5022 5023collate_t<self> collate_nocase() const { 5024return {*this, collate_argument::nocase}; 5025} 5026 5027collate_t<self> collate_rtrim() const { 5028return {*this, collate_argument::rtrim}; 5029} 5030}; 5031 5032struct greater_than_string { 5033serialize_result_type serialize() const { 5034return ">"; 5035} 5036}; 5037 5038/** 5039* > operator object. 5040*/ 5041template<class L, class R> 5042struct greater_than_t : binary_condition<L, R, greater_than_string, bool>, negatable_t { 5043using self = greater_than_t<L, R>; 5044 5045using binary_condition<L, R, greater_than_string, bool>::binary_condition; 5046 5047collate_t<self> collate_binary() const { 5048return {*this, collate_argument::binary}; 5049} 5050 5051collate_t<self> collate_nocase() const { 5052return {*this, collate_argument::nocase}; 5053} 5054 5055collate_t<self> collate_rtrim() const { 5056return {*this, collate_argument::rtrim}; 5057} 5058}; 5059 5060struct greater_or_equal_string { 5061serialize_result_type serialize() const { 5062return ">="; 5063} 5064}; 5065 5066/** 5067* >= operator object. 5068*/ 5069template<class L, class R> 5070struct greater_or_equal_t : binary_condition<L, R, greater_or_equal_string, bool>, negatable_t { 5071using self = greater_or_equal_t<L, R>; 5072 5073using binary_condition<L, R, greater_or_equal_string, bool>::binary_condition; 5074 5075collate_t<self> collate_binary() const { 5076return {*this, collate_argument::binary}; 5077} 5078 5079collate_t<self> collate_nocase() const { 5080return {*this, collate_argument::nocase}; 5081} 5082 5083collate_t<self> collate_rtrim() const { 5084return {*this, collate_argument::rtrim}; 5085} 5086}; 5087 5088struct less_than_string { 5089serialize_result_type serialize() const { 5090return "<"; 5091} 5092}; 5093 5094/** 5095* < operator object. 5096*/ 5097template<class L, class R> 5098struct less_than_t : binary_condition<L, R, less_than_string, bool>, negatable_t { 5099using self = less_than_t<L, R>; 5100 5101using binary_condition<L, R, less_than_string, bool>::binary_condition; 5102 5103collate_t<self> collate_binary() const { 5104return {*this, collate_argument::binary}; 5105} 5106 5107collate_t<self> collate_nocase() const { 5108return {*this, collate_argument::nocase}; 5109} 5110 5111collate_t<self> collate_rtrim() const { 5112return {*this, collate_argument::rtrim}; 5113} 5114}; 5115 5116struct less_or_equal_string { 5117serialize_result_type serialize() const { 5118return "<="; 5119} 5120}; 5121 5122/** 5123* <= operator object. 5124*/ 5125template<class L, class R> 5126struct less_or_equal_t : binary_condition<L, R, less_or_equal_string, bool>, negatable_t { 5127using self = less_or_equal_t<L, R>; 5128 5129using binary_condition<L, R, less_or_equal_string, bool>::binary_condition; 5130 5131collate_t<self> collate_binary() const { 5132return {*this, collate_argument::binary}; 5133} 5134 5135collate_t<self> collate_nocase() const { 5136return {*this, collate_argument::nocase}; 5137} 5138 5139collate_t<self> collate_rtrim() const { 5140return {*this, collate_argument::rtrim}; 5141} 5142}; 5143 5144struct in_base { 5145bool negative = false; // used in not_in 5146 5147#ifndef SQLITE_ORM_AGGREGATE_NSDMI_SUPPORTED 5148in_base(bool negative) : negative{negative} {} 5149#endif 5150}; 5151 5152/** 5153* IN operator object. 5154*/ 5155template<class L, class A> 5156struct dynamic_in_t : condition_t, in_base, negatable_t { 5157using self = dynamic_in_t<L, A>; 5158 5159L left; // left expression 5160A argument; // in arg 5161 5162dynamic_in_t(L left_, A argument_, bool negative_) : 5163in_base{negative_}, left(std::move(left_)), argument(std::move(argument_)) {} 5164}; 5165 5166template<class L, class... Args> 5167struct in_t : condition_t, in_base, negatable_t { 5168L left; 5169std::tuple<Args...> argument; 5170 5171in_t(L left_, decltype(argument) argument_, bool negative_) : 5172in_base{negative_}, left(std::move(left_)), argument(std::move(argument_)) {} 5173}; 5174 5175struct is_null_string { 5176operator std::string() const { 5177return "IS NULL"; 5178} 5179}; 5180 5181/** 5182* IS NULL operator object. 5183*/ 5184template<class T> 5185struct is_null_t : is_null_string, negatable_t { 5186using self = is_null_t<T>; 5187 5188T t; 5189 5190is_null_t(T t_) : t(std::move(t_)) {} 5191}; 5192 5193struct is_not_null_string { 5194operator std::string() const { 5195return "IS NOT NULL"; 5196} 5197}; 5198 5199/** 5200* IS NOT NULL operator object. 5201*/ 5202template<class T> 5203struct is_not_null_t : is_not_null_string, negatable_t { 5204using self = is_not_null_t<T>; 5205 5206T t; 5207 5208is_not_null_t(T t_) : t(std::move(t_)) {} 5209}; 5210 5211struct order_by_base { 5212int asc_desc = 0; // 1: asc, -1: desc 5213std::string _collate_argument; 5214 5215#ifndef SQLITE_ORM_AGGREGATE_NSDMI_SUPPORTED 5216order_by_base() = default; 5217 5218order_by_base(decltype(asc_desc) asc_desc_, decltype(_collate_argument) _collate_argument_) : 5219asc_desc(asc_desc_), _collate_argument(std::move(_collate_argument_)) {} 5220#endif 5221}; 5222 5223struct order_by_string { 5224operator std::string() const { 5225return "ORDER BY"; 5226} 5227}; 5228 5229/** 5230* ORDER BY argument holder. 5231*/ 5232template<class O> 5233struct order_by_t : order_by_base, order_by_string { 5234using expression_type = O; 5235using self = order_by_t<expression_type>; 5236 5237expression_type expression; 5238 5239order_by_t(expression_type expression_) : order_by_base(), expression(std::move(expression_)) {} 5240 5241self asc() const { 5242auto res = *this; 5243res.asc_desc = 1; 5244return res; 5245} 5246 5247self desc() const { 5248auto res = *this; 5249res.asc_desc = -1; 5250return res; 5251} 5252 5253self collate_binary() const { 5254auto res = *this; 5255res._collate_argument = collate_constraint_t::string_from_collate_argument(collate_argument::binary); 5256return res; 5257} 5258 5259self collate_nocase() const { 5260auto res = *this; 5261res._collate_argument = collate_constraint_t::string_from_collate_argument(collate_argument::nocase); 5262return res; 5263} 5264 5265self collate_rtrim() const { 5266auto res = *this; 5267res._collate_argument = collate_constraint_t::string_from_collate_argument(collate_argument::rtrim); 5268return res; 5269} 5270 5271self collate(std::string name) const { 5272auto res = *this; 5273res._collate_argument = std::move(name); 5274return res; 5275} 5276 5277template<class C> 5278self collate() const { 5279std::stringstream ss; 5280ss << C::name() << std::flush; 5281return this->collate(ss.str()); 5282} 5283}; 5284 5285/** 5286* ORDER BY pack holder. 5287*/ 5288template<class... Args> 5289struct multi_order_by_t : order_by_string { 5290using args_type = std::tuple<Args...>; 5291 5292args_type args; 5293 5294multi_order_by_t(args_type args_) : args{std::move(args_)} {} 5295}; 5296 5297struct dynamic_order_by_entry_t : order_by_base { 5298std::string name; 5299 5300dynamic_order_by_entry_t(decltype(name) name_, int asc_desc_, std::string collate_argument_) : 5301order_by_base{asc_desc_, std::move(collate_argument_)}, name(std::move(name_)) {} 5302}; 5303 5304/** 5305* C - serializer context class 5306*/ 5307template<class C> 5308struct dynamic_order_by_t : order_by_string { 5309using context_t = C; 5310using entry_t = dynamic_order_by_entry_t; 5311using const_iterator = typename std::vector<entry_t>::const_iterator; 5312 5313dynamic_order_by_t(const context_t& context_) : context(context_) {} 5314 5315template<class O> 5316void push_back(order_by_t<O> order_by) { 5317auto newContext = this->context; 5318newContext.skip_table_name = false; 5319auto columnName = serialize(order_by.expression, newContext); 5320this->entries.emplace_back(std::move(columnName), 5321order_by.asc_desc, 5322std::move(order_by._collate_argument)); 5323} 5324 5325const_iterator begin() const { 5326return this->entries.begin(); 5327} 5328 5329const_iterator end() const { 5330return this->entries.end(); 5331} 5332 5333void clear() { 5334this->entries.clear(); 5335} 5336 5337protected: 5338std::vector<entry_t> entries; 5339context_t context; 5340}; 5341 5342template<class T> 5343SQLITE_ORM_INLINE_VAR constexpr bool is_order_by_v = 5344polyfill::disjunction<polyfill::is_specialization_of<T, order_by_t>, 5345polyfill::is_specialization_of<T, multi_order_by_t>, 5346polyfill::is_specialization_of<T, dynamic_order_by_t>>::value; 5347 5348template<class T> 5349struct is_order_by : polyfill::bool_constant<is_order_by_v<T>> {}; 5350 5351struct between_string { 5352operator std::string() const { 5353return "BETWEEN"; 5354} 5355}; 5356 5357/** 5358* BETWEEN operator object. 5359*/ 5360template<class A, class T> 5361struct between_t : condition_t, between_string { 5362using expression_type = A; 5363using lower_type = T; 5364using upper_type = T; 5365 5366expression_type expr; 5367lower_type b1; 5368upper_type b2; 5369 5370between_t(expression_type expr_, lower_type b1_, upper_type b2_) : 5371expr(std::move(expr_)), b1(std::move(b1_)), b2(std::move(b2_)) {} 5372}; 5373 5374struct like_string { 5375operator std::string() const { 5376return "LIKE"; 5377} 5378}; 5379 5380/** 5381* LIKE operator object. 5382*/ 5383template<class A, class T, class E> 5384struct like_t : condition_t, like_string, negatable_t { 5385using self = like_t<A, T, E>; 5386using arg_t = A; 5387using pattern_t = T; 5388using escape_t = E; 5389 5390arg_t arg; 5391pattern_t pattern; 5392optional_container<escape_t> arg3; // not escape cause escape exists as a function here 5393 5394like_t(arg_t arg_, pattern_t pattern_, optional_container<escape_t> escape_) : 5395arg(std::move(arg_)), pattern(std::move(pattern_)), arg3(std::move(escape_)) {} 5396 5397template<class C> 5398like_t<A, T, C> escape(C c) const { 5399optional_container<C> newArg3{std::move(c)}; 5400return {std::move(this->arg), std::move(this->pattern), std::move(newArg3)}; 5401} 5402}; 5403 5404struct glob_string { 5405operator std::string() const { 5406return "GLOB"; 5407} 5408}; 5409 5410template<class A, class T> 5411struct glob_t : condition_t, glob_string, negatable_t { 5412using self = glob_t<A, T>; 5413using arg_t = A; 5414using pattern_t = T; 5415 5416arg_t arg; 5417pattern_t pattern; 5418 5419glob_t(arg_t arg_, pattern_t pattern_) : arg(std::move(arg_)), pattern(std::move(pattern_)) {} 5420}; 5421 5422struct cross_join_string { 5423operator std::string() const { 5424return "CROSS JOIN"; 5425} 5426}; 5427 5428/** 5429* CROSS JOIN holder. 5430* T is joined type which represents any mapped table. 5431*/ 5432template<class T> 5433struct cross_join_t : cross_join_string { 5434using type = T; 5435}; 5436 5437struct natural_join_string { 5438operator std::string() const { 5439return "NATURAL JOIN"; 5440} 5441}; 5442 5443/** 5444* NATURAL JOIN holder. 5445* T is joined type which represents any mapped table. 5446*/ 5447template<class T> 5448struct natural_join_t : natural_join_string { 5449using type = T; 5450}; 5451 5452struct left_join_string { 5453operator std::string() const { 5454return "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*/ 5463template<class T, class O> 5464struct left_join_t : left_join_string { 5465using type = T; 5466using on_type = O; 5467 5468on_type constraint; 5469 5470left_join_t(on_type constraint_) : constraint(std::move(constraint_)) {} 5471}; 5472 5473struct join_string { 5474operator std::string() const { 5475return "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*/ 5484template<class T, class O> 5485struct join_t : join_string { 5486using type = T; 5487using on_type = O; 5488 5489on_type constraint; 5490 5491join_t(on_type constraint_) : constraint(std::move(constraint_)) {} 5492}; 5493 5494struct left_outer_join_string { 5495operator std::string() const { 5496return "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*/ 5505template<class T, class O> 5506struct left_outer_join_t : left_outer_join_string { 5507using type = T; 5508using on_type = O; 5509 5510on_type constraint; 5511 5512left_outer_join_t(on_type constraint_) : constraint(std::move(constraint_)) {} 5513}; 5514 5515struct on_string { 5516operator std::string() const { 5517return "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*/ 5525template<class T> 5526struct on_t : on_string { 5527using arg_type = T; 5528 5529arg_type arg; 5530 5531on_t(arg_type arg_) : arg(std::move(arg_)) {} 5532}; 5533 5534/** 5535* USING argument holder. 5536*/ 5537template<class T, class M> 5538struct using_t { 5539column_pointer<T, M> column; 5540 5541operator std::string() const { 5542return "USING"; 5543} 5544}; 5545 5546struct inner_join_string { 5547operator std::string() const { 5548return "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*/ 5557template<class T, class O> 5558struct inner_join_t : inner_join_string { 5559using type = T; 5560using on_type = O; 5561 5562on_type constraint; 5563 5564inner_join_t(on_type constraint_) : constraint(std::move(constraint_)) {} 5565}; 5566 5567struct cast_string { 5568operator std::string() const { 5569return "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*/ 5579template<class T, class E> 5580struct cast_t : cast_string { 5581using to_type = T; 5582using expression_type = E; 5583 5584expression_type expression; 5585 5586cast_t(expression_type expression_) : expression(std::move(expression_)) {} 5587}; 5588 5589template<class... Args> 5590struct from_t { 5591using tuple_type = std::tuple<Args...>; 5592}; 5593 5594template<class T> 5595using is_from = polyfill::is_specialization_of<T, from_t>; 5596 5597template<class T> 5598using 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*/ 5605template<class... Tables> 5606internal::from_t<Tables...> from() { 5607static_assert(sizeof...(Tables) > 0, ""); 5608return {}; 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*/ 5616template<orm_refers_to_recordset auto... recordsets> 5617auto from() { 5618return 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) 5624namespace internal { 5625template< 5626class T, 5627std::enable_if_t<polyfill::disjunction<std::is_base_of<negatable_t, T>, is_operator_argument<T>>::value, 5628bool> = true> 5629constexpr negated_condition_t<T> operator!(T arg) { 5630return {std::move(arg)}; 5631} 5632 5633template<class L, 5634class R, 5635std::enable_if_t<polyfill::disjunction<std::is_base_of<arithmetic_t, L>, 5636std::is_base_of<arithmetic_t, R>, 5637is_operator_argument<L>, 5638is_operator_argument<R>>::value, 5639bool> = true> 5640constexpr less_than_t<unwrap_expression_t<L>, unwrap_expression_t<R>> operator<(L l, R r) { 5641return {get_from_expression(std::forward<L>(l)), get_from_expression(std::forward<R>(r))}; 5642} 5643 5644template<class L, 5645class R, 5646std::enable_if_t<polyfill::disjunction<std::is_base_of<arithmetic_t, L>, 5647std::is_base_of<arithmetic_t, R>, 5648is_operator_argument<L>, 5649is_operator_argument<R>>::value, 5650bool> = true> 5651constexpr less_or_equal_t<unwrap_expression_t<L>, unwrap_expression_t<R>> operator<=(L l, R r) { 5652return {get_from_expression(std::forward<L>(l)), get_from_expression(std::forward<R>(r))}; 5653} 5654 5655template<class L, 5656class R, 5657std::enable_if_t<polyfill::disjunction<std::is_base_of<arithmetic_t, L>, 5658std::is_base_of<arithmetic_t, R>, 5659is_operator_argument<L>, 5660is_operator_argument<R>>::value, 5661bool> = true> 5662constexpr greater_than_t<unwrap_expression_t<L>, unwrap_expression_t<R>> operator>(L l, R r) { 5663return {get_from_expression(std::forward<L>(l)), get_from_expression(std::forward<R>(r))}; 5664} 5665 5666template<class L, 5667class R, 5668std::enable_if_t<polyfill::disjunction<std::is_base_of<arithmetic_t, L>, 5669std::is_base_of<arithmetic_t, R>, 5670is_operator_argument<L>, 5671is_operator_argument<R>>::value, 5672bool> = true> 5673constexpr greater_or_equal_t<unwrap_expression_t<L>, unwrap_expression_t<R>> operator>=(L l, R r) { 5674return {get_from_expression(std::forward<L>(l)), get_from_expression(std::forward<R>(r))}; 5675} 5676 5677template<class L, 5678class R, 5679std::enable_if_t<polyfill::disjunction<std::is_base_of<arithmetic_t, L>, 5680std::is_base_of<arithmetic_t, R>, 5681std::is_base_of<condition_t, L>, 5682std::is_base_of<condition_t, R>, 5683is_operator_argument<L>, 5684is_operator_argument<R>>::value, 5685bool> = true> 5686constexpr is_equal_t<unwrap_expression_t<L>, unwrap_expression_t<R>> operator==(L l, R r) { 5687return {get_from_expression(std::forward<L>(l)), get_from_expression(std::forward<R>(r))}; 5688} 5689 5690template<class L, 5691class R, 5692std::enable_if_t<polyfill::disjunction<std::is_base_of<arithmetic_t, L>, 5693std::is_base_of<arithmetic_t, R>, 5694std::is_base_of<condition_t, L>, 5695std::is_base_of<condition_t, R>, 5696is_operator_argument<L>, 5697is_operator_argument<R>>::value, 5698bool> = true> 5699constexpr is_not_equal_t<unwrap_expression_t<L>, unwrap_expression_t<R>> operator!=(L l, R r) { 5700return {get_from_expression(std::forward<L>(l)), get_from_expression(std::forward<R>(r))}; 5701} 5702 5703template<class L, 5704class R, 5705std::enable_if_t<polyfill::disjunction<std::is_base_of<condition_t, L>, 5706std::is_base_of<condition_t, R>, 5707is_operator_argument<L>, 5708is_operator_argument<R>>::value, 5709bool> = true> 5710constexpr and_condition_t<unwrap_expression_t<L>, unwrap_expression_t<R>> operator&&(L l, R r) { 5711return {get_from_expression(std::forward<L>(l)), get_from_expression(std::forward<R>(r))}; 5712} 5713 5714template<class L, 5715class R, 5716std::enable_if_t< 5717polyfill::disjunction<std::is_base_of<condition_t, L>, std::is_base_of<condition_t, R>>::value, 5718bool> = true> 5719constexpr or_condition_t<unwrap_expression_t<L>, unwrap_expression_t<R>> operator||(L l, R r) { 5720return {get_from_expression(std::forward<L>(l)), get_from_expression(std::forward<R>(r))}; 5721} 5722 5723template< 5724class L, 5725class R, 5726std::enable_if_t<polyfill::conjunction< 5727polyfill::disjunction<std::is_base_of<conc_string, L>, 5728std::is_base_of<conc_string, R>, 5729is_operator_argument<L>, 5730is_operator_argument<R>>, 5731// exclude conditions 5732polyfill::negation<polyfill::disjunction<std::is_base_of<condition_t, L>, 5733std::is_base_of<condition_t, R>>>>::value, 5734bool> = true> 5735constexpr conc_t<unwrap_expression_t<L>, unwrap_expression_t<R>> operator||(L l, R r) { 5736return {get_from_expression(std::forward<L>(l)), get_from_expression(std::forward<R>(r))}; 5737} 5738} 5739 5740template<class F, class O> 5741internal::using_t<O, F O::*> using_(F O::* field) { 5742return {field}; 5743} 5744template<class T, class M> 5745internal::using_t<T, M> using_(internal::column_pointer<T, M> field) { 5746return {std::move(field)}; 5747} 5748 5749template<class T> 5750internal::on_t<T> on(T t) { 5751return {std::move(t)}; 5752} 5753 5754template<class T> 5755internal::cross_join_t<T> cross_join() { 5756return {}; 5757} 5758 5759template<class T> 5760internal::natural_join_t<T> natural_join() { 5761return {}; 5762} 5763 5764template<class T, class O> 5765internal::left_join_t<T, O> left_join(O o) { 5766return {std::move(o)}; 5767} 5768 5769#ifdef SQLITE_ORM_WITH_CPP20_ALIASES 5770template<orm_refers_to_recordset auto alias, class On> 5771auto left_join(On on) { 5772return left_join<internal::auto_decay_table_ref_t<alias>, On>(std::move(on)); 5773} 5774#endif 5775 5776template<class T, class O> 5777internal::join_t<T, O> join(O o) { 5778return {std::move(o)}; 5779} 5780 5781#ifdef SQLITE_ORM_WITH_CPP20_ALIASES 5782template<orm_refers_to_recordset auto alias, class On> 5783auto join(On on) { 5784return join<internal::auto_decay_table_ref_t<alias>, On>(std::move(on)); 5785} 5786#endif 5787 5788template<class T, class O> 5789internal::left_outer_join_t<T, O> left_outer_join(O o) { 5790return {std::move(o)}; 5791} 5792 5793#ifdef SQLITE_ORM_WITH_CPP20_ALIASES 5794template<orm_refers_to_recordset auto alias, class On> 5795auto left_outer_join(On on) { 5796return left_outer_join<internal::auto_decay_table_ref_t<alias>, On>(std::move(on)); 5797} 5798#endif 5799 5800template<class T, class O> 5801internal::inner_join_t<T, O> inner_join(O o) { 5802return {std::move(o)}; 5803} 5804 5805#ifdef SQLITE_ORM_WITH_CPP20_ALIASES 5806template<orm_refers_to_recordset auto alias, class On> 5807auto inner_join(On on) { 5808return inner_join<internal::auto_decay_table_ref_t<alias>, On>(std::move(on)); 5809} 5810#endif 5811 5812template<class T> 5813internal::offset_t<T> offset(T off) { 5814return {std::move(off)}; 5815} 5816 5817template<class T> 5818internal::limit_t<T, false, false, void> limit(T lim) { 5819return {std::move(lim)}; 5820} 5821 5822template<class T, class O, internal::satisfies_not<internal::is_offset, T> = true> 5823internal::limit_t<T, true, true, O> limit(O off, T lim) { 5824return {std::move(lim), {std::move(off)}}; 5825} 5826 5827template<class T, class O> 5828internal::limit_t<T, true, false, O> limit(T lim, internal::offset_t<O> offt) { 5829return {std::move(lim), {std::move(offt.off)}}; 5830} 5831 5832template<class L, class R> 5833constexpr auto and_(L l, R r) { 5834using namespace ::sqlite_orm::internal; 5835return and_condition_t<unwrap_expression_t<L>, unwrap_expression_t<R>>{get_from_expression(std::forward<L>(l)), 5836get_from_expression(std::forward<R>(r))}; 5837} 5838 5839template<class L, class R> 5840constexpr auto or_(L l, R r) { 5841using namespace ::sqlite_orm::internal; 5842return or_condition_t<unwrap_expression_t<L>, unwrap_expression_t<R>>{get_from_expression(std::forward<L>(l)), 5843get_from_expression(std::forward<R>(r))}; 5844} 5845 5846template<class T> 5847internal::is_not_null_t<T> is_not_null(T t) { 5848return {std::move(t)}; 5849} 5850 5851template<class T> 5852internal::is_null_t<T> is_null(T t) { 5853return {std::move(t)}; 5854} 5855 5856template<class L, class E> 5857internal::dynamic_in_t<L, std::vector<E>> in(L l, std::vector<E> values) { 5858return {std::move(l), std::move(values), false}; 5859} 5860 5861template<class L, class E> 5862internal::dynamic_in_t<L, std::vector<E>> in(L l, std::initializer_list<E> values) { 5863return {std::move(l), std::move(values), false}; 5864} 5865 5866template<class L, class A> 5867internal::dynamic_in_t<L, A> in(L l, A arg) { 5868return {std::move(l), std::move(arg), false}; 5869} 5870 5871template<class L, class E> 5872internal::dynamic_in_t<L, std::vector<E>> not_in(L l, std::vector<E> values) { 5873return {std::move(l), std::move(values), true}; 5874} 5875 5876template<class L, class E> 5877internal::dynamic_in_t<L, std::vector<E>> not_in(L l, std::initializer_list<E> values) { 5878return {std::move(l), std::move(values), true}; 5879} 5880 5881template<class L, class A> 5882internal::dynamic_in_t<L, A> not_in(L l, A arg) { 5883return {std::move(l), std::move(arg), true}; 5884} 5885 5886template<class L, class R> 5887constexpr internal::is_equal_t<L, R> is_equal(L l, R r) { 5888return {std::move(l), std::move(r)}; 5889} 5890 5891template<class L, class R> 5892constexpr internal::is_equal_t<L, R> eq(L l, R r) { 5893return {std::move(l), std::move(r)}; 5894} 5895 5896template<class L, class R> 5897constexpr internal::is_equal_with_table_t<L, R> is_equal(R rhs) { 5898return {std::move(rhs)}; 5899} 5900 5901template<class L, class R> 5902constexpr internal::is_not_equal_t<L, R> is_not_equal(L l, R r) { 5903return {std::move(l), std::move(r)}; 5904} 5905 5906template<class L, class R> 5907constexpr internal::is_not_equal_t<L, R> ne(L l, R r) { 5908return {std::move(l), std::move(r)}; 5909} 5910 5911template<class L, class R> 5912constexpr internal::greater_than_t<L, R> greater_than(L l, R r) { 5913return {std::move(l), std::move(r)}; 5914} 5915 5916template<class L, class R> 5917constexpr internal::greater_than_t<L, R> gt(L l, R r) { 5918return {std::move(l), std::move(r)}; 5919} 5920 5921template<class L, class R> 5922constexpr internal::greater_or_equal_t<L, R> greater_or_equal(L l, R r) { 5923return {std::move(l), std::move(r)}; 5924} 5925 5926template<class L, class R> 5927constexpr internal::greater_or_equal_t<L, R> ge(L l, R r) { 5928return {std::move(l), std::move(r)}; 5929} 5930 5931template<class L, class R> 5932constexpr internal::less_than_t<L, R> less_than(L l, R r) { 5933return {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*/ 5939template<class L, class R> 5940[[deprecated("Use the accurately named function `less_than(...)` instead")]] internal::less_than_t<L, R> 5941lesser_than(L l, R r) { 5942return {std::move(l), std::move(r)}; 5943} 5944 5945template<class L, class R> 5946constexpr internal::less_than_t<L, R> lt(L l, R r) { 5947return {std::move(l), std::move(r)}; 5948} 5949 5950template<class L, class R> 5951constexpr internal::less_or_equal_t<L, R> less_or_equal(L l, R r) { 5952return {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*/ 5958template<class L, class R> 5959[[deprecated("Use the accurately named function `less_or_equal(...)` instead")]] internal::less_or_equal_t<L, R> 5960lesser_or_equal(L l, R r) { 5961return {std::move(l), std::move(r)}; 5962} 5963 5964template<class L, class R> 5965constexpr internal::less_or_equal_t<L, R> le(L l, R r) { 5966return {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*/ 5976template<class O, internal::satisfies_not<std::is_base_of, integer_printer, type_printer<O>> = true> 5977internal::order_by_t<O> order_by(O o) { 5978return {std::move(o)}; 5979} 5980 5981/** 5982* ORDER BY positional ordinal 5983* 5984* Examples: 5985* storage.select(&User::name, order_by(1)) 5986*/ 5987template<class O, internal::satisfies<std::is_base_of, integer_printer, type_printer<O>> = true> 5988internal::order_by_t<internal::literal_holder<O>> order_by(O o) { 5989return {{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*/ 5996template<class... Args> 5997internal::multi_order_by_t<Args...> multi_order_by(Args... args) { 5998return {{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*/ 6013template<class S> 6014internal::dynamic_order_by_t<internal::serializer_context<typename S::db_objects_type>> 6015dynamic_order_by(const S& storage) { 6016internal::serializer_context_builder<S> builder(storage); 6017return builder(); 6018} 6019 6020/** 6021* X BETWEEN Y AND Z 6022* Example: storage.select(between(&User::id, 10, 20)) 6023*/ 6024template<class A, class T> 6025internal::between_t<A, T> between(A expr, T b1, T b2) { 6026return {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*/ 6033template<class A, class T> 6034internal::like_t<A, T, void> like(A a, T t) { 6035return {std::move(a), std::move(t), {}}; 6036} 6037 6038/** 6039* X GLOB Y 6040* Example: storage.select(glob(&User::name, "*S")) 6041*/ 6042template<class A, class T> 6043internal::glob_t<A, T> glob(A a, T t) { 6044return {std::move(a), std::move(t)}; 6045} 6046 6047/** 6048* X LIKE Y ESCAPE Z 6049* Example: storage.select(like(&User::name, "T%", "%")) 6050*/ 6051template<class A, class T, class E> 6052internal::like_t<A, T, E> like(A a, T t, E e) { 6053return {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*/ 6060template<class T, class E> 6061internal::cast_t<T, E> cast(E e) { 6062return {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 6078namespace sqlite_orm { 6079namespace internal { 6080 6081template<class T> 6082struct into_t { 6083using type = T; 6084}; 6085 6086template<class T> 6087using is_into = polyfill::is_specialization_of<T, into_t>; 6088} 6089 6090template<class T> 6091internal::into_t<T> into() { 6092return {}; 6093} 6094} 6095 6096namespace sqlite_orm { 6097 6098using int64 = sqlite_int64; 6099using uint64 = sqlite_uint64; 6100 6101namespace internal { 6102 6103template<class T> 6104struct 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*/ 6112template<class R, class S, class... Args> 6113struct built_in_function_t : S, arithmetic_t { 6114using return_type = R; 6115using string_type = S; 6116using args_type = std::tuple<Args...>; 6117 6118static constexpr size_t args_size = std::tuple_size<args_type>::value; 6119 6120args_type args; 6121 6122built_in_function_t(args_type&& args_) : args(std::move(args_)) {} 6123}; 6124 6125template<class T> 6126SQLITE_ORM_INLINE_VAR constexpr bool is_built_in_function_v = 6127is_base_of_template<T, built_in_function_t>::value; 6128 6129template<class T> 6130struct is_built_in_function : polyfill::bool_constant<is_built_in_function_v<T>> {}; 6131 6132template<class F, class W> 6133struct filtered_aggregate_function { 6134using function_type = F; 6135using where_expression = W; 6136 6137function_type function; 6138where_expression where; 6139}; 6140 6141template<class C> 6142struct where_t; 6143 6144template<class R, class S, class... Args> 6145struct built_in_aggregate_function_t : built_in_function_t<R, S, Args...> { 6146using super = built_in_function_t<R, S, Args...>; 6147 6148using super::super; 6149 6150template<class W> 6151filtered_aggregate_function<built_in_aggregate_function_t<R, S, Args...>, W> filter(where_t<W> wh) { 6152return {*this, std::move(wh.expression)}; 6153} 6154}; 6155 6156struct typeof_string { 6157serialize_result_type serialize() const { 6158return "TYPEOF"; 6159} 6160}; 6161 6162struct unicode_string { 6163serialize_result_type serialize() const { 6164return "UNICODE"; 6165} 6166}; 6167 6168struct length_string { 6169serialize_result_type serialize() const { 6170return "LENGTH"; 6171} 6172}; 6173 6174struct abs_string { 6175serialize_result_type serialize() const { 6176return "ABS"; 6177} 6178}; 6179 6180struct lower_string { 6181serialize_result_type serialize() const { 6182return "LOWER"; 6183} 6184}; 6185 6186struct upper_string { 6187serialize_result_type serialize() const { 6188return "UPPER"; 6189} 6190}; 6191 6192struct last_insert_rowid_string { 6193serialize_result_type serialize() const { 6194return "LAST_INSERT_ROWID"; 6195} 6196}; 6197 6198struct total_changes_string { 6199serialize_result_type serialize() const { 6200return "TOTAL_CHANGES"; 6201} 6202}; 6203 6204struct changes_string { 6205serialize_result_type serialize() const { 6206return "CHANGES"; 6207} 6208}; 6209 6210struct trim_string { 6211serialize_result_type serialize() const { 6212return "TRIM"; 6213} 6214}; 6215 6216struct ltrim_string { 6217serialize_result_type serialize() const { 6218return "LTRIM"; 6219} 6220}; 6221 6222struct rtrim_string { 6223serialize_result_type serialize() const { 6224return "RTRIM"; 6225} 6226}; 6227 6228struct hex_string { 6229serialize_result_type serialize() const { 6230return "HEX"; 6231} 6232}; 6233 6234struct quote_string { 6235serialize_result_type serialize() const { 6236return "QUOTE"; 6237} 6238}; 6239 6240struct randomblob_string { 6241serialize_result_type serialize() const { 6242return "RANDOMBLOB"; 6243} 6244}; 6245 6246struct instr_string { 6247serialize_result_type serialize() const { 6248return "INSTR"; 6249} 6250}; 6251 6252struct replace_string { 6253serialize_result_type serialize() const { 6254return "REPLACE"; 6255} 6256}; 6257 6258struct round_string { 6259serialize_result_type serialize() const { 6260return "ROUND"; 6261} 6262}; 6263 6264#if SQLITE_VERSION_NUMBER >= 3007016 6265struct char_string { 6266serialize_result_type serialize() const { 6267return "CHAR"; 6268} 6269}; 6270 6271struct random_string { 6272serialize_result_type serialize() const { 6273return "RANDOM"; 6274} 6275}; 6276 6277#endif 6278 6279struct coalesce_string { 6280serialize_result_type serialize() const { 6281return "COALESCE"; 6282} 6283}; 6284 6285struct ifnull_string { 6286serialize_result_type serialize() const { 6287return "IFNULL"; 6288} 6289}; 6290 6291struct nullif_string { 6292serialize_result_type serialize() const { 6293return "NULLIF"; 6294} 6295}; 6296 6297struct date_string { 6298serialize_result_type serialize() const { 6299return "DATE"; 6300} 6301}; 6302 6303struct time_string { 6304serialize_result_type serialize() const { 6305return "TIME"; 6306} 6307}; 6308 6309struct datetime_string { 6310serialize_result_type serialize() const { 6311return "DATETIME"; 6312} 6313}; 6314 6315struct julianday_string { 6316serialize_result_type serialize() const { 6317return "JULIANDAY"; 6318} 6319}; 6320 6321struct strftime_string { 6322serialize_result_type serialize() const { 6323return "STRFTIME"; 6324} 6325}; 6326 6327struct zeroblob_string { 6328serialize_result_type serialize() const { 6329return "ZEROBLOB"; 6330} 6331}; 6332 6333struct substr_string { 6334serialize_result_type serialize() const { 6335return "SUBSTR"; 6336} 6337}; 6338#ifdef SQLITE_SOUNDEX 6339struct soundex_string { 6340serialize_result_type serialize() const { 6341return "SOUNDEX"; 6342} 6343}; 6344#endif 6345struct total_string { 6346serialize_result_type serialize() const { 6347return "TOTAL"; 6348} 6349}; 6350 6351struct sum_string { 6352serialize_result_type serialize() const { 6353return "SUM"; 6354} 6355}; 6356 6357struct count_string { 6358serialize_result_type serialize() const { 6359return "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*/ 6368template<class T> 6369struct count_asterisk_t : count_string { 6370using type = T; 6371 6372template<class W> 6373filtered_aggregate_function<count_asterisk_t<T>, W> filter(where_t<W> wh) { 6374return {*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*/ 6398struct count_asterisk_without_type : count_string {}; 6399 6400struct avg_string { 6401serialize_result_type serialize() const { 6402return "AVG"; 6403} 6404}; 6405 6406struct max_string { 6407serialize_result_type serialize() const { 6408return "MAX"; 6409} 6410}; 6411 6412struct min_string { 6413serialize_result_type serialize() const { 6414return "MIN"; 6415} 6416}; 6417 6418struct group_concat_string { 6419serialize_result_type serialize() const { 6420return "GROUP_CONCAT"; 6421} 6422}; 6423#ifdef SQLITE_ENABLE_MATH_FUNCTIONS 6424struct acos_string { 6425serialize_result_type serialize() const { 6426return "ACOS"; 6427} 6428}; 6429 6430struct acosh_string { 6431serialize_result_type serialize() const { 6432return "ACOSH"; 6433} 6434}; 6435 6436struct asin_string { 6437serialize_result_type serialize() const { 6438return "ASIN"; 6439} 6440}; 6441 6442struct asinh_string { 6443serialize_result_type serialize() const { 6444return "ASINH"; 6445} 6446}; 6447 6448struct atan_string { 6449serialize_result_type serialize() const { 6450return "ATAN"; 6451} 6452}; 6453 6454struct atan2_string { 6455serialize_result_type serialize() const { 6456return "ATAN2"; 6457} 6458}; 6459 6460struct atanh_string { 6461serialize_result_type serialize() const { 6462return "ATANH"; 6463} 6464}; 6465 6466struct ceil_string { 6467serialize_result_type serialize() const { 6468return "CEIL"; 6469} 6470}; 6471 6472struct ceiling_string { 6473serialize_result_type serialize() const { 6474return "CEILING"; 6475} 6476}; 6477 6478struct cos_string { 6479serialize_result_type serialize() const { 6480return "COS"; 6481} 6482}; 6483 6484struct cosh_string { 6485serialize_result_type serialize() const { 6486return "COSH"; 6487} 6488}; 6489 6490struct degrees_string { 6491serialize_result_type serialize() const { 6492return "DEGREES"; 6493} 6494}; 6495 6496struct exp_string { 6497serialize_result_type serialize() const { 6498return "EXP"; 6499} 6500}; 6501 6502struct floor_string { 6503serialize_result_type serialize() const { 6504return "FLOOR"; 6505} 6506}; 6507 6508struct ln_string { 6509serialize_result_type serialize() const { 6510return "LN"; 6511} 6512}; 6513 6514struct log_string { 6515serialize_result_type serialize() const { 6516return "LOG"; 6517} 6518}; 6519 6520struct log10_string { 6521serialize_result_type serialize() const { 6522return "LOG10"; 6523} 6524}; 6525 6526struct log2_string { 6527serialize_result_type serialize() const { 6528return "LOG2"; 6529} 6530}; 6531 6532struct mod_string { 6533serialize_result_type serialize() const { 6534return "MOD"; 6535} 6536}; 6537 6538struct pi_string { 6539serialize_result_type serialize() const { 6540return "PI"; 6541} 6542}; 6543 6544struct pow_string { 6545serialize_result_type serialize() const { 6546return "POW"; 6547} 6548}; 6549 6550struct power_string { 6551serialize_result_type serialize() const { 6552return "POWER"; 6553} 6554}; 6555 6556struct radians_string { 6557serialize_result_type serialize() const { 6558return "RADIANS"; 6559} 6560}; 6561 6562struct sin_string { 6563serialize_result_type serialize() const { 6564return "SIN"; 6565} 6566}; 6567 6568struct sinh_string { 6569serialize_result_type serialize() const { 6570return "SINH"; 6571} 6572}; 6573 6574struct sqrt_string { 6575serialize_result_type serialize() const { 6576return "SQRT"; 6577} 6578}; 6579 6580struct tan_string { 6581serialize_result_type serialize() const { 6582return "TAN"; 6583} 6584}; 6585 6586struct tanh_string { 6587serialize_result_type serialize() const { 6588return "TANH"; 6589} 6590}; 6591 6592struct trunc_string { 6593serialize_result_type serialize() const { 6594return "TRUNC"; 6595} 6596}; 6597 6598#endif // SQLITE_ENABLE_MATH_FUNCTIONS 6599#ifdef SQLITE_ENABLE_JSON1 6600struct json_string { 6601serialize_result_type serialize() const { 6602return "JSON"; 6603} 6604}; 6605 6606struct json_array_string { 6607serialize_result_type serialize() const { 6608return "JSON_ARRAY"; 6609} 6610}; 6611 6612struct json_array_length_string { 6613serialize_result_type serialize() const { 6614return "JSON_ARRAY_LENGTH"; 6615} 6616}; 6617 6618struct json_extract_string { 6619serialize_result_type serialize() const { 6620return "JSON_EXTRACT"; 6621} 6622}; 6623 6624struct json_insert_string { 6625serialize_result_type serialize() const { 6626return "JSON_INSERT"; 6627} 6628}; 6629 6630struct json_replace_string { 6631serialize_result_type serialize() const { 6632return "JSON_REPLACE"; 6633} 6634}; 6635 6636struct json_set_string { 6637serialize_result_type serialize() const { 6638return "JSON_SET"; 6639} 6640}; 6641 6642struct json_object_string { 6643serialize_result_type serialize() const { 6644return "JSON_OBJECT"; 6645} 6646}; 6647 6648struct json_patch_string { 6649serialize_result_type serialize() const { 6650return "JSON_PATCH"; 6651} 6652}; 6653 6654struct json_remove_string { 6655serialize_result_type serialize() const { 6656return "JSON_REMOVE"; 6657} 6658}; 6659 6660struct json_type_string { 6661serialize_result_type serialize() const { 6662return "JSON_TYPE"; 6663} 6664}; 6665 6666struct json_valid_string { 6667serialize_result_type serialize() const { 6668return "JSON_VALID"; 6669} 6670}; 6671 6672struct json_quote_string { 6673serialize_result_type serialize() const { 6674return "JSON_QUOTE"; 6675} 6676}; 6677 6678struct json_group_array_string { 6679serialize_result_type serialize() const { 6680return "JSON_GROUP_ARRAY"; 6681} 6682}; 6683 6684struct json_group_object_string { 6685serialize_result_type serialize() const { 6686return "JSON_GROUP_OBJECT"; 6687} 6688}; 6689#endif // SQLITE_ENABLE_JSON1 6690 6691template<class T> 6692using field_type_or_type_t = polyfill::detected_or_t<T, type_t, member_field_type<T>>; 6693 6694template<class T, class X, class Y, class Z> 6695struct highlight_t { 6696using table_type = T; 6697using argument0_type = X; 6698using argument1_type = Y; 6699using argument2_type = Z; 6700 6701argument0_type argument0; 6702argument1_type argument1; 6703argument2_type argument2; 6704 6705highlight_t(argument0_type argument0, argument1_type argument1, argument2_type argument2) : 6706argument0(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*/ 6719template<class X> 6720internal::built_in_function_t<double, internal::acos_string, X> acos(X x) { 6721return {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*/ 6735template<class R, class X> 6736internal::built_in_function_t<R, internal::acos_string, X> acos(X x) { 6737return {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*/ 6747template<class X> 6748internal::built_in_function_t<double, internal::acosh_string, X> acosh(X x) { 6749return {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*/ 6763template<class R, class X> 6764internal::built_in_function_t<R, internal::acosh_string, X> acosh(X x) { 6765return {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*/ 6775template<class X> 6776internal::built_in_function_t<double, internal::asin_string, X> asin(X x) { 6777return {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*/ 6791template<class R, class X> 6792internal::built_in_function_t<R, internal::asin_string, X> asin(X x) { 6793return {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*/ 6803template<class X> 6804internal::built_in_function_t<double, internal::asinh_string, X> asinh(X x) { 6805return {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*/ 6819template<class R, class X> 6820internal::built_in_function_t<R, internal::asinh_string, X> asinh(X x) { 6821return {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*/ 6831template<class X> 6832internal::built_in_function_t<double, internal::atan_string, X> atan(X x) { 6833return {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*/ 6847template<class R, class X> 6848internal::built_in_function_t<R, internal::atan_string, X> atan(X x) { 6849return {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*/ 6859template<class X, class Y> 6860internal::built_in_function_t<double, internal::atan2_string, X, Y> atan2(X x, Y y) { 6861return {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*/ 6875template<class R, class X, class Y> 6876internal::built_in_function_t<R, internal::atan2_string, X, Y> atan2(X x, Y y) { 6877return {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*/ 6887template<class X> 6888internal::built_in_function_t<double, internal::atanh_string, X> atanh(X x) { 6889return {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*/ 6903template<class R, class X> 6904internal::built_in_function_t<R, internal::atanh_string, X> atanh(X x) { 6905return {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*/ 6915template<class X> 6916internal::built_in_function_t<double, internal::ceil_string, X> ceil(X x) { 6917return {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*/ 6931template<class R, class X> 6932internal::built_in_function_t<R, internal::ceil_string, X> ceil(X x) { 6933return {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*/ 6943template<class X> 6944internal::built_in_function_t<double, internal::ceiling_string, X> ceiling(X x) { 6945return {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*/ 6959template<class R, class X> 6960internal::built_in_function_t<R, internal::ceiling_string, X> ceiling(X x) { 6961return {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*/ 6971template<class X> 6972internal::built_in_function_t<double, internal::cos_string, X> cos(X x) { 6973return {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*/ 6987template<class R, class X> 6988internal::built_in_function_t<R, internal::cos_string, X> cos(X x) { 6989return {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*/ 6999template<class X> 7000internal::built_in_function_t<double, internal::cosh_string, X> cosh(X x) { 7001return {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*/ 7015template<class R, class X> 7016internal::built_in_function_t<R, internal::cosh_string, X> cosh(X x) { 7017return {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*/ 7027template<class X> 7028internal::built_in_function_t<double, internal::degrees_string, X> degrees(X x) { 7029return {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*/ 7043template<class R, class X> 7044internal::built_in_function_t<R, internal::degrees_string, X> degrees(X x) { 7045return {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*/ 7055template<class X> 7056internal::built_in_function_t<double, internal::exp_string, X> exp(X x) { 7057return {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*/ 7071template<class R, class X> 7072internal::built_in_function_t<R, internal::exp_string, X> exp(X x) { 7073return {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*/ 7083template<class X> 7084internal::built_in_function_t<double, internal::floor_string, X> floor(X x) { 7085return {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*/ 7099template<class R, class X> 7100internal::built_in_function_t<R, internal::floor_string, X> floor(X x) { 7101return {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*/ 7111template<class X> 7112internal::built_in_function_t<double, internal::ln_string, X> ln(X x) { 7113return {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*/ 7127template<class R, class X> 7128internal::built_in_function_t<R, internal::ln_string, X> ln(X x) { 7129return {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*/ 7139template<class X> 7140internal::built_in_function_t<double, internal::log_string, X> log(X x) { 7141return {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*/ 7155template<class R, class X> 7156internal::built_in_function_t<R, internal::log_string, X> log(X x) { 7157return {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*/ 7167template<class X> 7168internal::built_in_function_t<double, internal::log10_string, X> log10(X x) { 7169return {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*/ 7183template<class R, class X> 7184internal::built_in_function_t<R, internal::log10_string, X> log10(X x) { 7185return {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*/ 7195template<class B, class X> 7196internal::built_in_function_t<double, internal::log_string, B, X> log(B b, X x) { 7197return {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*/ 7211template<class R, class B, class X> 7212internal::built_in_function_t<R, internal::log_string, B, X> log(B b, X x) { 7213return {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*/ 7223template<class X> 7224internal::built_in_function_t<double, internal::log2_string, X> log2(X x) { 7225return {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*/ 7239template<class R, class X> 7240internal::built_in_function_t<R, internal::log2_string, X> log2(X x) { 7241return {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*/ 7251template<class X, class Y> 7252internal::built_in_function_t<double, internal::mod_string, X, Y> mod_f(X x, Y y) { 7253return {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*/ 7267template<class R, class X, class Y> 7268internal::built_in_function_t<R, internal::mod_string, X, Y> mod_f(X x, Y y) { 7269return {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*/ 7279inline internal::built_in_function_t<double, internal::pi_string> pi() { 7280return {{}}; 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*/ 7294template<class R> 7295internal::built_in_function_t<R, internal::pi_string> pi() { 7296return {{}}; 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*/ 7306template<class X, class Y> 7307internal::built_in_function_t<double, internal::pow_string, X, Y> pow(X x, Y y) { 7308return {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*/ 7322template<class R, class X, class Y> 7323internal::built_in_function_t<R, internal::pow_string, X, Y> pow(X x, Y y) { 7324return {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*/ 7334template<class X, class Y> 7335internal::built_in_function_t<double, internal::power_string, X, Y> power(X x, Y y) { 7336return {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*/ 7350template<class R, class X, class Y> 7351internal::built_in_function_t<R, internal::power_string, X, Y> power(X x, Y y) { 7352return {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*/ 7362template<class X> 7363internal::built_in_function_t<double, internal::radians_string, X> radians(X x) { 7364return {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*/ 7378template<class R, class X> 7379internal::built_in_function_t<R, internal::radians_string, X> radians(X x) { 7380return {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*/ 7390template<class X> 7391internal::built_in_function_t<double, internal::sin_string, X> sin(X x) { 7392return {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*/ 7406template<class R, class X> 7407internal::built_in_function_t<R, internal::sin_string, X> sin(X x) { 7408return {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*/ 7418template<class X> 7419internal::built_in_function_t<double, internal::sinh_string, X> sinh(X x) { 7420return {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*/ 7434template<class R, class X> 7435internal::built_in_function_t<R, internal::sinh_string, X> sinh(X x) { 7436return {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*/ 7446template<class X> 7447internal::built_in_function_t<double, internal::sqrt_string, X> sqrt(X x) { 7448return {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*/ 7462template<class R, class X> 7463internal::built_in_function_t<R, internal::sqrt_string, X> sqrt(X x) { 7464return {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*/ 7474template<class X> 7475internal::built_in_function_t<double, internal::tan_string, X> tan(X x) { 7476return {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*/ 7490template<class R, class X> 7491internal::built_in_function_t<R, internal::tan_string, X> tan(X x) { 7492return {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*/ 7502template<class X> 7503internal::built_in_function_t<double, internal::tanh_string, X> tanh(X x) { 7504return {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*/ 7518template<class R, class X> 7519internal::built_in_function_t<R, internal::tanh_string, X> tanh(X x) { 7520return {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*/ 7530template<class X> 7531internal::built_in_function_t<double, internal::trunc_string, X> trunc(X x) { 7532return {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*/ 7546template<class R, class X> 7547internal::built_in_function_t<R, internal::trunc_string, X> trunc(X x) { 7548return {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*/ 7554template<class T> 7555internal::built_in_function_t<std::string, internal::typeof_string, T> typeof_(T t) { 7556return {std::tuple<T>{std::forward<T>(t)}}; 7557} 7558 7559/** 7560* UNICODE(x) function https://sqlite.org/lang_corefunc.html#unicode 7561*/ 7562template<class T> 7563internal::built_in_function_t<int, internal::unicode_string, T> unicode(T t) { 7564return {std::tuple<T>{std::forward<T>(t)}}; 7565} 7566 7567/** 7568* LENGTH(x) function https://sqlite.org/lang_corefunc.html#length 7569*/ 7570template<class T> 7571internal::built_in_function_t<int, internal::length_string, T> length(T t) { 7572return {std::tuple<T>{std::forward<T>(t)}}; 7573} 7574 7575/** 7576* ABS(x) function https://sqlite.org/lang_corefunc.html#abs 7577*/ 7578template<class T> 7579internal::built_in_function_t<std::unique_ptr<double>, internal::abs_string, T> abs(T t) { 7580return {std::tuple<T>{std::forward<T>(t)}}; 7581} 7582 7583/** 7584* LOWER(x) function https://sqlite.org/lang_corefunc.html#lower 7585*/ 7586template<class T> 7587internal::built_in_function_t<std::string, internal::lower_string, T> lower(T t) { 7588return {std::tuple<T>{std::forward<T>(t)}}; 7589} 7590 7591/** 7592* UPPER(x) function https://sqlite.org/lang_corefunc.html#upper 7593*/ 7594template<class T> 7595internal::built_in_function_t<std::string, internal::upper_string, T> upper(T t) { 7596return {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*/ 7602inline internal::built_in_function_t<int64, internal::last_insert_rowid_string> last_insert_rowid() { 7603return {{}}; 7604} 7605 7606/** 7607* TOTAL_CHANGES() function https://sqlite.org/lang_corefunc.html#total_changes 7608*/ 7609inline internal::built_in_function_t<int, internal::total_changes_string> total_changes() { 7610return {{}}; 7611} 7612 7613/** 7614* CHANGES() function https://sqlite.org/lang_corefunc.html#changes 7615*/ 7616inline internal::built_in_function_t<int, internal::changes_string> changes() { 7617return {{}}; 7618} 7619 7620/** 7621* TRIM(X) function https://sqlite.org/lang_corefunc.html#trim 7622*/ 7623template<class T> 7624internal::built_in_function_t<std::string, internal::trim_string, T> trim(T t) { 7625return {std::tuple<T>{std::forward<T>(t)}}; 7626} 7627 7628/** 7629* TRIM(X,Y) function https://sqlite.org/lang_corefunc.html#trim 7630*/ 7631template<class X, class Y> 7632internal::built_in_function_t<std::string, internal::trim_string, X, Y> trim(X x, Y y) { 7633return {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*/ 7639template<class X> 7640internal::built_in_function_t<std::string, internal::ltrim_string, X> ltrim(X x) { 7641return {std::tuple<X>{std::forward<X>(x)}}; 7642} 7643 7644/** 7645* LTRIM(X,Y) function https://sqlite.org/lang_corefunc.html#ltrim 7646*/ 7647template<class X, class Y> 7648internal::built_in_function_t<std::string, internal::ltrim_string, X, Y> ltrim(X x, Y y) { 7649return {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*/ 7655template<class X> 7656internal::built_in_function_t<std::string, internal::rtrim_string, X> rtrim(X x) { 7657return {std::tuple<X>{std::forward<X>(x)}}; 7658} 7659 7660/** 7661* RTRIM(X,Y) function https://sqlite.org/lang_corefunc.html#rtrim 7662*/ 7663template<class X, class Y> 7664internal::built_in_function_t<std::string, internal::rtrim_string, X, Y> rtrim(X x, Y y) { 7665return {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*/ 7671template<class X> 7672internal::built_in_function_t<std::string, internal::hex_string, X> hex(X x) { 7673return {std::tuple<X>{std::forward<X>(x)}}; 7674} 7675 7676/** 7677* QUOTE(X) function https://sqlite.org/lang_corefunc.html#quote 7678*/ 7679template<class X> 7680internal::built_in_function_t<std::string, internal::quote_string, X> quote(X x) { 7681return {std::tuple<X>{std::forward<X>(x)}}; 7682} 7683 7684/** 7685* RANDOMBLOB(X) function https://sqlite.org/lang_corefunc.html#randomblob 7686*/ 7687template<class X> 7688internal::built_in_function_t<std::vector<char>, internal::randomblob_string, X> randomblob(X x) { 7689return {std::tuple<X>{std::forward<X>(x)}}; 7690} 7691 7692/** 7693* INSTR(X) function https://sqlite.org/lang_corefunc.html#instr 7694*/ 7695template<class X, class Y> 7696internal::built_in_function_t<int, internal::instr_string, X, Y> instr(X x, Y y) { 7697return {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*/ 7703template<class X, 7704class Y, 7705class Z, 7706std::enable_if_t<internal::count_tuple<std::tuple<X, Y, Z>, internal::is_into>::value == 0, bool> = true> 7707internal::built_in_function_t<std::string, internal::replace_string, X, Y, Z> replace(X x, Y y, Z z) { 7708return {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*/ 7714template<class X> 7715internal::built_in_function_t<double, internal::round_string, X> round(X x) { 7716return {std::tuple<X>{std::forward<X>(x)}}; 7717} 7718 7719/** 7720* ROUND(X, Y) function https://sqlite.org/lang_corefunc.html#round 7721*/ 7722template<class X, class Y> 7723internal::built_in_function_t<double, internal::round_string, X, Y> round(X x, Y y) { 7724return {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*/ 7731template<class... Args> 7732internal::built_in_function_t<std::string, internal::char_string, Args...> char_(Args... args) { 7733return {std::make_tuple(std::forward<Args>(args)...)}; 7734} 7735 7736/** 7737* RANDOM() function https://www.sqlite.org/lang_corefunc.html#random 7738*/ 7739inline internal::built_in_function_t<int, internal::random_string> random() { 7740return {{}}; 7741} 7742#endif 7743 7744/** 7745* COALESCE(X,Y,...) function https://www.sqlite.org/lang_corefunc.html#coalesce 7746*/ 7747template<class R = void, class... Args> 7748auto coalesce(Args... args) 7749-> internal::built_in_function_t<typename mpl::conditional_t< // choose R or common type 7750std::is_void<R>::value, 7751std::common_type<internal::field_type_or_type_t<Args>...>, 7752polyfill::type_identity<R>>::type, 7753internal::coalesce_string, 7754Args...> { 7755return {std::make_tuple(std::forward<Args>(args)...)}; 7756} 7757 7758/** 7759* IFNULL(X,Y) function https://www.sqlite.org/lang_corefunc.html#ifnull 7760*/ 7761template<class R = void, class X, class Y> 7762auto ifnull(X x, Y y) -> internal::built_in_function_t< 7763typename mpl::conditional_t< // choose R or common type 7764std::is_void<R>::value, 7765std::common_type<internal::field_type_or_type_t<X>, internal::field_type_or_type_t<Y>>, 7766polyfill::type_identity<R>>::type, 7767internal::ifnull_string, 7768X, 7769Y> { 7770return {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*/ 7780template<class R = void, 7781class X, 7782class Y, 7783std::enable_if_t<polyfill::disjunction_v<polyfill::negation<std::is_void<R>>, 7784polyfill::is_detected<std::common_type_t, 7785internal::field_type_or_type_t<X>, 7786internal::field_type_or_type_t<Y>>>, 7787bool> = true> 7788auto nullif(X x, Y y) { 7789if constexpr (std::is_void_v<R>) { 7790using F = internal::built_in_function_t< 7791std::optional<std::common_type_t<internal::field_type_or_type_t<X>, internal::field_type_or_type_t<Y>>>, 7792internal::nullif_string, 7793X, 7794Y>; 7795 7796return F{std::make_tuple(std::move(x), std::move(y))}; 7797} else { 7798using F = internal::built_in_function_t<R, internal::nullif_string, X, Y>; 7799 7800return F{std::make_tuple(std::move(x), std::move(y))}; 7801} 7802} 7803#else 7804template<class R, class X, class Y> 7805internal::built_in_function_t<R, internal::nullif_string, X, Y> nullif(X x, Y y) { 7806return {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*/ 7813template<class... Args> 7814internal::built_in_function_t<std::string, internal::date_string, Args...> date(Args... args) { 7815return {std::tuple<Args...>{std::forward<Args>(args)...}}; 7816} 7817 7818/** 7819* TIME(timestring, modifier, modifier, ...) function https://www.sqlite.org/lang_datefunc.html 7820*/ 7821template<class... Args> 7822internal::built_in_function_t<std::string, internal::time_string, Args...> time(Args... args) { 7823return {std::tuple<Args...>{std::forward<Args>(args)...}}; 7824} 7825 7826/** 7827* DATETIME(timestring, modifier, modifier, ...) function https://www.sqlite.org/lang_datefunc.html 7828*/ 7829template<class... Args> 7830internal::built_in_function_t<std::string, internal::datetime_string, Args...> datetime(Args... args) { 7831return {std::tuple<Args...>{std::forward<Args>(args)...}}; 7832} 7833 7834/** 7835* JULIANDAY(timestring, modifier, modifier, ...) function https://www.sqlite.org/lang_datefunc.html 7836*/ 7837template<class... Args> 7838internal::built_in_function_t<double, internal::julianday_string, Args...> julianday(Args... args) { 7839return {std::tuple<Args...>{std::forward<Args>(args)...}}; 7840} 7841 7842/** 7843* STRFTIME(timestring, modifier, modifier, ...) function https://www.sqlite.org/lang_datefunc.html 7844*/ 7845template<class... Args> 7846internal::built_in_function_t<std::string, internal::strftime_string, Args...> strftime(Args... args) { 7847return {std::tuple<Args...>{std::forward<Args>(args)...}}; 7848} 7849 7850/** 7851* ZEROBLOB(N) function https://www.sqlite.org/lang_corefunc.html#zeroblob 7852*/ 7853template<class N> 7854internal::built_in_function_t<std::vector<char>, internal::zeroblob_string, N> zeroblob(N n) { 7855return {std::tuple<N>{std::forward<N>(n)}}; 7856} 7857 7858/** 7859* SUBSTR(X,Y) function https://www.sqlite.org/lang_corefunc.html#substr 7860*/ 7861template<class X, class Y> 7862internal::built_in_function_t<std::string, internal::substr_string, X, Y> substr(X x, Y y) { 7863return {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*/ 7869template<class X, class Y, class Z> 7870internal::built_in_function_t<std::string, internal::substr_string, X, Y, Z> substr(X x, Y y, Z z) { 7871return {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*/ 7878template<class X> 7879internal::built_in_function_t<std::string, internal::soundex_string, X> soundex(X x) { 7880return {std::tuple<X>{std::forward<X>(x)}}; 7881} 7882#endif 7883 7884/** 7885* TOTAL(X) aggregate function. 7886*/ 7887template<class X> 7888internal::built_in_aggregate_function_t<double, internal::total_string, X> total(X x) { 7889return {std::tuple<X>{std::forward<X>(x)}}; 7890} 7891 7892/** 7893* SUM(X) aggregate function. 7894*/ 7895template<class X> 7896internal::built_in_aggregate_function_t<std::unique_ptr<double>, internal::sum_string, X> sum(X x) { 7897return {std::tuple<X>{std::forward<X>(x)}}; 7898} 7899 7900/** 7901* COUNT(X) aggregate function. 7902*/ 7903template<class X> 7904internal::built_in_aggregate_function_t<int, internal::count_string, X> count(X x) { 7905return {std::tuple<X>{std::forward<X>(x)}}; 7906} 7907 7908/** 7909* COUNT(*) without FROM function. 7910*/ 7911inline internal::count_asterisk_without_type count() { 7912return {}; 7913} 7914 7915/** 7916* COUNT(*) with FROM function. Specified type T will be serialized as 7917* a from argument. 7918*/ 7919template<class T> 7920internal::count_asterisk_t<T> count() { 7921return {}; 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*/ 7929template<orm_refers_to_recordset auto mapped> 7930auto count() { 7931return count<internal::auto_decay_table_ref_t<mapped>>(); 7932} 7933#endif 7934 7935/** 7936* AVG(X) aggregate function. 7937*/ 7938template<class X> 7939internal::built_in_aggregate_function_t<double, internal::avg_string, X> avg(X x) { 7940return {std::tuple<X>{std::forward<X>(x)}}; 7941} 7942 7943/** 7944* MAX(X) aggregate function. 7945*/ 7946template<class X> 7947internal::built_in_aggregate_function_t<internal::unique_ptr_result_of<X>, internal::max_string, X> max(X x) { 7948return {std::tuple<X>{std::forward<X>(x)}}; 7949} 7950 7951/** 7952* MIN(X) aggregate function. 7953*/ 7954template<class X> 7955internal::built_in_aggregate_function_t<internal::unique_ptr_result_of<X>, internal::min_string, X> min(X x) { 7956return {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*/ 7963template<class X, class Y, class... Rest> 7964internal::built_in_function_t<internal::unique_ptr_result_of<X>, internal::max_string, X, Y, Rest...> 7965max(X x, Y y, Rest... rest) { 7966return {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*/ 7973template<class X, class Y, class... Rest> 7974internal::built_in_function_t<internal::unique_ptr_result_of<X>, internal::min_string, X, Y, Rest...> 7975min(X x, Y y, Rest... rest) { 7976return {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*/ 7982template<class X> 7983internal::built_in_aggregate_function_t<std::string, internal::group_concat_string, X> group_concat(X x) { 7984return {std::tuple<X>{std::forward<X>(x)}}; 7985} 7986 7987/** 7988* GROUP_CONCAT(X, Y) aggregate function. 7989*/ 7990template<class X, class Y> 7991internal::built_in_aggregate_function_t<std::string, internal::group_concat_string, X, Y> group_concat(X x, Y y) { 7992return {std::tuple<X, Y>{std::forward<X>(x), std::forward<Y>(y)}}; 7993} 7994#ifdef SQLITE_ENABLE_JSON1 7995template<class X> 7996internal::built_in_function_t<std::string, internal::json_string, X> json(X x) { 7997return {std::tuple<X>{std::forward<X>(x)}}; 7998} 7999 8000template<class... Args> 8001internal::built_in_function_t<std::string, internal::json_array_string, Args...> json_array(Args... args) { 8002return {std::tuple<Args...>{std::forward<Args>(args)...}}; 8003} 8004 8005template<class X> 8006internal::built_in_function_t<int, internal::json_array_length_string, X> json_array_length(X x) { 8007return {std::tuple<X>{std::forward<X>(x)}}; 8008} 8009 8010template<class R, class X> 8011internal::built_in_function_t<R, internal::json_array_length_string, X> json_array_length(X x) { 8012return {std::tuple<X>{std::forward<X>(x)}}; 8013} 8014 8015template<class X, class Y> 8016internal::built_in_function_t<int, internal::json_array_length_string, X, Y> json_array_length(X x, Y y) { 8017return {std::tuple<X, Y>{std::forward<X>(x), std::forward<Y>(y)}}; 8018} 8019 8020template<class R, class X, class Y> 8021internal::built_in_function_t<R, internal::json_array_length_string, X, Y> json_array_length(X x, Y y) { 8022return {std::tuple<X, Y>{std::forward<X>(x), std::forward<Y>(y)}}; 8023} 8024 8025template<class R, class X, class... Args> 8026internal::built_in_function_t<R, internal::json_extract_string, X, Args...> json_extract(X x, Args... args) { 8027return {std::tuple<X, Args...>{std::forward<X>(x), std::forward<Args>(args)...}}; 8028} 8029 8030template<class X, class... Args> 8031internal::built_in_function_t<std::string, internal::json_insert_string, X, Args...> json_insert(X x, 8032Args... args) { 8033static_assert(std::tuple_size<std::tuple<Args...>>::value % 2 == 0, 8034"number of arguments in json_insert must be odd"); 8035return {std::tuple<X, Args...>{std::forward<X>(x), std::forward<Args>(args)...}}; 8036} 8037 8038template<class X, class... Args> 8039internal::built_in_function_t<std::string, internal::json_replace_string, X, Args...> json_replace(X x, 8040Args... args) { 8041static_assert(std::tuple_size<std::tuple<Args...>>::value % 2 == 0, 8042"number of arguments in json_replace must be odd"); 8043return {std::tuple<X, Args...>{std::forward<X>(x), std::forward<Args>(args)...}}; 8044} 8045 8046template<class X, class... Args> 8047internal::built_in_function_t<std::string, internal::json_set_string, X, Args...> json_set(X x, Args... args) { 8048static_assert(std::tuple_size<std::tuple<Args...>>::value % 2 == 0, 8049"number of arguments in json_set must be odd"); 8050return {std::tuple<X, Args...>{std::forward<X>(x), std::forward<Args>(args)...}}; 8051} 8052 8053template<class... Args> 8054internal::built_in_function_t<std::string, internal::json_object_string, Args...> json_object(Args... args) { 8055static_assert(std::tuple_size<std::tuple<Args...>>::value % 2 == 0, 8056"number of arguments in json_object must be even"); 8057return {std::tuple<Args...>{std::forward<Args>(args)...}}; 8058} 8059 8060template<class X, class Y> 8061internal::built_in_function_t<std::string, internal::json_patch_string, X, Y> json_patch(X x, Y y) { 8062return {std::tuple<X, Y>{std::forward<X>(x), std::forward<Y>(y)}}; 8063} 8064 8065template<class X, class... Args> 8066internal::built_in_function_t<std::string, internal::json_remove_string, X, Args...> json_remove(X x, 8067Args... args) { 8068return {std::tuple<X, Args...>{std::forward<X>(x), std::forward<Args>(args)...}}; 8069} 8070 8071template<class R, class X, class... Args> 8072internal::built_in_function_t<R, internal::json_remove_string, X, Args...> json_remove(X x, Args... args) { 8073return {std::tuple<X, Args...>{std::forward<X>(x), std::forward<Args>(args)...}}; 8074} 8075 8076template<class X> 8077internal::built_in_function_t<std::string, internal::json_type_string, X> json_type(X x) { 8078return {std::tuple<X>{std::forward<X>(x)}}; 8079} 8080 8081template<class R, class X> 8082internal::built_in_function_t<R, internal::json_type_string, X> json_type(X x) { 8083return {std::tuple<X>{std::forward<X>(x)}}; 8084} 8085 8086template<class X, class Y> 8087internal::built_in_function_t<std::string, internal::json_type_string, X, Y> json_type(X x, Y y) { 8088return {std::tuple<X, Y>{std::forward<X>(x), std::forward<Y>(y)}}; 8089} 8090 8091template<class R, class X, class Y> 8092internal::built_in_function_t<R, internal::json_type_string, X, Y> json_type(X x, Y y) { 8093return {std::tuple<X, Y>{std::forward<X>(x), std::forward<Y>(y)}}; 8094} 8095 8096template<class X> 8097internal::built_in_function_t<bool, internal::json_valid_string, X> json_valid(X x) { 8098return {std::tuple<X>{std::forward<X>(x)}}; 8099} 8100 8101template<class R, class X> 8102internal::built_in_function_t<R, internal::json_quote_string, X> json_quote(X x) { 8103return {std::tuple<X>{std::forward<X>(x)}}; 8104} 8105 8106template<class X> 8107internal::built_in_function_t<std::string, internal::json_group_array_string, X> json_group_array(X x) { 8108return {std::tuple<X>{std::forward<X>(x)}}; 8109} 8110 8111template<class X, class Y> 8112internal::built_in_function_t<std::string, internal::json_group_object_string, X, Y> json_group_object(X x, Y y) { 8113return {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) 8119namespace internal { 8120template< 8121class T, 8122std::enable_if_t<polyfill::disjunction<std::is_base_of<arithmetic_t, T>, is_operator_argument<T>>::value, 8123bool> = true> 8124constexpr unary_minus_t<unwrap_expression_t<T>> operator-(T arg) { 8125return {get_from_expression(std::forward<T>(arg))}; 8126} 8127 8128template<class L, 8129class R, 8130std::enable_if_t<polyfill::disjunction<std::is_base_of<arithmetic_t, L>, 8131std::is_base_of<arithmetic_t, R>, 8132is_operator_argument<L>, 8133is_operator_argument<R>>::value, 8134bool> = true> 8135constexpr add_t<unwrap_expression_t<L>, unwrap_expression_t<R>> operator+(L l, R r) { 8136return {get_from_expression(std::forward<L>(l)), get_from_expression(std::forward<R>(r))}; 8137} 8138 8139template<class L, 8140class R, 8141std::enable_if_t<polyfill::disjunction<std::is_base_of<arithmetic_t, L>, 8142std::is_base_of<arithmetic_t, R>, 8143is_operator_argument<L>, 8144is_operator_argument<R>>::value, 8145bool> = true> 8146constexpr sub_t<unwrap_expression_t<L>, unwrap_expression_t<R>> operator-(L l, R r) { 8147return {get_from_expression(std::forward<L>(l)), get_from_expression(std::forward<R>(r))}; 8148} 8149 8150template<class L, 8151class R, 8152std::enable_if_t<polyfill::disjunction<std::is_base_of<arithmetic_t, L>, 8153std::is_base_of<arithmetic_t, R>, 8154is_operator_argument<L>, 8155is_operator_argument<R>>::value, 8156bool> = true> 8157constexpr mul_t<unwrap_expression_t<L>, unwrap_expression_t<R>> operator*(L l, R r) { 8158return {get_from_expression(std::forward<L>(l)), get_from_expression(std::forward<R>(r))}; 8159} 8160 8161template<class L, 8162class R, 8163std::enable_if_t<polyfill::disjunction<std::is_base_of<arithmetic_t, L>, 8164std::is_base_of<arithmetic_t, R>, 8165is_operator_argument<L>, 8166is_operator_argument<R>>::value, 8167bool> = true> 8168constexpr div_t<unwrap_expression_t<L>, unwrap_expression_t<R>> operator/(L l, R r) { 8169return {get_from_expression(std::forward<L>(l)), get_from_expression(std::forward<R>(r))}; 8170} 8171 8172template<class L, 8173class R, 8174std::enable_if_t<polyfill::disjunction<std::is_base_of<arithmetic_t, L>, 8175std::is_base_of<arithmetic_t, R>, 8176is_operator_argument<L>, 8177is_operator_argument<R>>::value, 8178bool> = true> 8179constexpr mod_t<unwrap_expression_t<L>, unwrap_expression_t<R>> operator%(L l, R r) { 8180return {get_from_expression(std::forward<L>(l)), get_from_expression(std::forward<R>(r))}; 8181} 8182 8183template< 8184class T, 8185std::enable_if_t<polyfill::disjunction<std::is_base_of<arithmetic_t, T>, is_operator_argument<T>>::value, 8186bool> = true> 8187constexpr bitwise_not_t<unwrap_expression_t<T>> operator~(T arg) { 8188return {get_from_expression(std::forward<T>(arg))}; 8189} 8190 8191template<class L, 8192class R, 8193std::enable_if_t<polyfill::disjunction<std::is_base_of<arithmetic_t, L>, 8194std::is_base_of<arithmetic_t, R>, 8195is_operator_argument<L>, 8196is_operator_argument<R>>::value, 8197bool> = true> 8198constexpr bitwise_shift_left_t<unwrap_expression_t<L>, unwrap_expression_t<R>> operator<<(L l, R r) { 8199return {get_from_expression(std::forward<L>(l)), get_from_expression(std::forward<R>(r))}; 8200} 8201 8202template<class L, 8203class R, 8204std::enable_if_t<polyfill::disjunction<std::is_base_of<arithmetic_t, L>, 8205std::is_base_of<arithmetic_t, R>, 8206is_operator_argument<L>, 8207is_operator_argument<R>>::value, 8208bool> = true> 8209constexpr bitwise_shift_right_t<unwrap_expression_t<L>, unwrap_expression_t<R>> operator>>(L l, R r) { 8210return {get_from_expression(std::forward<L>(l)), get_from_expression(std::forward<R>(r))}; 8211} 8212 8213template<class L, 8214class R, 8215std::enable_if_t<polyfill::disjunction<std::is_base_of<arithmetic_t, L>, 8216std::is_base_of<arithmetic_t, R>, 8217is_operator_argument<L>, 8218is_operator_argument<R>>::value, 8219bool> = true> 8220constexpr bitwise_and_t<unwrap_expression_t<L>, unwrap_expression_t<R>> operator&(L l, R r) { 8221return {get_from_expression(std::forward<L>(l)), get_from_expression(std::forward<R>(r))}; 8222} 8223 8224template<class L, 8225class R, 8226std::enable_if_t<polyfill::disjunction<std::is_base_of<arithmetic_t, L>, 8227std::is_base_of<arithmetic_t, R>, 8228is_operator_argument<L>, 8229is_operator_argument<R>>::value, 8230bool> = true> 8231constexpr bitwise_or_t<unwrap_expression_t<L>, unwrap_expression_t<R>> operator|(L l, R r) { 8232return {get_from_expression(std::forward<L>(l)), get_from_expression(std::forward<R>(r))}; 8233} 8234} 8235 8236template<class T, class X, class Y, class Z> 8237internal::highlight_t<T, X, Y, Z> highlight(X x, Y y, Z z) { 8238return {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) 8261namespace sqlite_orm { 8262 8263namespace internal { 8264/** 8265* A special record set alias that is both, a storage lookup type (mapping type) and an alias. 8266*/ 8267template<char A, char... X> 8268struct cte_moniker 8269: recordset_alias< 8270cte_moniker<A, X...> /* refer to self, since a moniker is both, an alias and a mapped type */, 8271A, 8272X...> { 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 8292template<class... ExplicitCols> 8293requires ((is_column_alias_v<ExplicitCols> || std::is_member_pointer_v<ExplicitCols> || 8294std::same_as<ExplicitCols, std::remove_cvref_t<decltype(std::ignore)>> || 8295std::convertible_to<ExplicitCols, std::string>) && 8296...) 8297constexpr auto operator()(ExplicitCols... explicitColumns) const; 8298#else 8299template<class... ExplicitCols, 8300std::enable_if_t<polyfill::conjunction_v<polyfill::disjunction< 8301is_column_alias<ExplicitCols>, 8302std::is_member_pointer<ExplicitCols>, 8303std::is_same<ExplicitCols, polyfill::remove_cvref_t<decltype(std::ignore)>>, 8304std::is_convertible<ExplicitCols, std::string>>...>, 8305bool> = true> 8306constexpr auto operator()(ExplicitCols... explicitColumns) const; 8307#endif 8308}; 8309} 8310 8311inline namespace literals { 8312/** 8313* cte_moniker<'n'> from a numeric literal. 8314* E.g. 1_ctealias, 2_ctealias 8315*/ 8316template<char... Chars> 8317[[nodiscard]] SQLITE_ORM_CONSTEVAL auto operator"" _ctealias() { 8318return 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*/ 8326template<internal::cstring_literal moniker> 8327[[nodiscard]] consteval auto operator"" _cte() { 8328return 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 8361namespace 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*/ 8370template<class T, class SFINAE = void> 8371struct type_is_nullable : std::false_type { 8372bool operator()(const T&) const { 8373return 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*/ 8380template<class T> 8381struct type_is_nullable<T, 8382std::enable_if_t<polyfill::disjunction< 8383#ifdef SQLITE_ORM_OPTIONAL_SUPPORTED 8384polyfill::is_specialization_of<T, std::optional>, 8385#endif 8386polyfill::is_specialization_of<T, std::unique_ptr>, 8387polyfill::is_specialization_of<T, std::shared_ptr>>::value>> : std::true_type { 8388bool operator()(const T& t) const { 8389return static_cast<bool>(t); 8390} 8391}; 8392} 8393 8394// #include "../constraints.h" 8395 8396namespace sqlite_orm { 8397 8398namespace internal { 8399 8400struct column_identifier { 8401 8402/** 8403* Column name. 8404*/ 8405std::string name; 8406}; 8407 8408struct 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*/ 8417template<class G, class S> 8418struct column_field { 8419using member_pointer_t = G; 8420using setter_type = S; 8421using object_type = member_object_type_t<G>; 8422using 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*/ 8428const member_pointer_t member_pointer; 8429 8430/** 8431* Setter member function to write a field value 8432*/ 8433SQLITE_ORM_NOUNIQUEADDRESS 8434const setter_type setter; 8435 8436/** 8437* Simplified interface for `NOT NULL` constraint 8438*/ 8439constexpr bool is_not_null() const { 8440return !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*/ 8449template<class... Op> 8450struct column_constraints { 8451using constraints_type = std::tuple<Op...>; 8452 8453SQLITE_ORM_NOUNIQUEADDRESS 8454constraints_type constraints; 8455 8456/** 8457* Checks whether contraints contain specified type. 8458*/ 8459template<template<class...> class Trait> 8460constexpr static bool is() { 8461return 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*/ 8468std::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*/ 8476template<class G, class S, class... Op> 8477struct column_t : column_identifier, column_field<G, S>, column_constraints<Op...> { 8478#ifndef SQLITE_ORM_AGGREGATE_BASES_SUPPORTED 8479column_t(std::string name, G memberPointer, S setter, std::tuple<Op...> op) : 8480column_identifier{std::move(name)}, column_field<G, S>{memberPointer, setter}, 8481column_constraints<Op...>{std::move(op)} {} 8482#endif 8483}; 8484 8485template<class T, class SFINAE = void> 8486struct column_field_expression { 8487using type = void; 8488}; 8489 8490template<class G, class S, class... Op> 8491struct column_field_expression<column_t<G, S, Op...>, void> { 8492using type = typename column_t<G, S, Op...>::member_pointer_t; 8493}; 8494 8495template<typename T> 8496using column_field_expression_t = typename column_field_expression<T>::type; 8497 8498template<class T> 8499SQLITE_ORM_INLINE_VAR constexpr bool is_column_v = polyfill::is_specialization_of<T, column_t>::value; 8500 8501template<class T> 8502using is_column = polyfill::bool_constant<is_column_v<T>>; 8503 8504template<class Elements, class F> 8505using col_index_sequence_with_field_type = 8506filter_tuple_sequence_t<Elements, 8507check_if_is_type<F>::template fn, 8508field_type_t, 8509filter_tuple_sequence_t<Elements, is_column>>; 8510 8511template<class Elements, template<class...> class TraitFn> 8512using col_index_sequence_with = filter_tuple_sequence_t<Elements, 8513check_if_has<TraitFn>::template fn, 8514constraints_type_t, 8515filter_tuple_sequence_t<Elements, is_column>>; 8516 8517template<class Elements, template<class...> class TraitFn> 8518using col_index_sequence_excluding = filter_tuple_sequence_t<Elements, 8519check_if_has_not<TraitFn>::template fn, 8520constraints_type_t, 8521filter_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*/ 8527template<class M, class... Op, internal::satisfies<std::is_member_object_pointer, M> = true> 8528internal::column_t<M, internal::empty_setter, Op...> 8529make_column(std::string name, M memberPointer, Op... constraints) { 8530static_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! 8534SQLITE_ORM_CLANG_SUPPRESS_MISSING_BRACES( 8535return {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*/ 8541template<class G, 8542class S, 8543class... Op, 8544internal::satisfies<internal::is_getter, G> = true, 8545internal::satisfies<internal::is_setter, S> = true> 8546internal::column_t<G, S, Op...> make_column(std::string name, S setter, G getter, Op... constraints) { 8547static_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"); 8549static_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! 8553SQLITE_ORM_CLANG_SUPPRESS_MISSING_BRACES( 8554return {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*/ 8560template<class G, 8561class S, 8562class... Op, 8563internal::satisfies<internal::is_getter, G> = true, 8564internal::satisfies<internal::is_setter, S> = true> 8565internal::column_t<G, S, Op...> make_column(std::string name, G getter, S setter, Op... constraints) { 8566static_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"); 8568static_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! 8572SQLITE_ORM_CLANG_SUPPRESS_MISSING_BRACES( 8573return {std::move(name), getter, setter, std::tuple<Op...>{std::move(constraints)...}}); 8574} 8575} 8576 8577namespace sqlite_orm { 8578 8579namespace internal { 8580#ifdef SQLITE_ORM_OPTIONAL_SUPPORTED 8581template<class T> 8582struct as_optional_t { 8583using expression_type = T; 8584 8585expression_type expression; 8586}; 8587#endif // SQLITE_ORM_OPTIONAL_SUPPORTED 8588 8589struct distinct_string { 8590operator std::string() const { 8591return "DISTINCT"; 8592} 8593}; 8594 8595/** 8596* DISCTINCT generic container. 8597*/ 8598template<class T> 8599struct distinct_t : distinct_string { 8600using expression_type = T; 8601 8602expression_type expression; 8603 8604distinct_t(expression_type expression) : expression(std::move(expression)) {} 8605}; 8606 8607struct all_string { 8608operator std::string() const { 8609return "ALL"; 8610} 8611}; 8612 8613/** 8614* ALL generic container. 8615*/ 8616template<class T> 8617struct all_t : all_string { 8618using expression_type = T; 8619 8620expression_type expression; 8621 8622all_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*/ 8628template<class T> 8629SQLITE_ORM_INLINE_VAR constexpr bool is_rowset_deduplicator_v = 8630polyfill::disjunction<polyfill::is_specialization_of<T, distinct_t>, 8631polyfill::is_specialization_of<T, all_t>>::value; 8632 8633template<class T> 8634struct is_rowset_deduplicator : polyfill::bool_constant<is_rowset_deduplicator_v<T>> {}; 8635 8636template<class... Args> 8637struct columns_t { 8638using columns_type = std::tuple<Args...>; 8639 8640columns_type columns; 8641 8642static constexpr int count = std::tuple_size<columns_type>::value; 8643 8644#ifndef SQLITE_ORM_AGGREGATE_NSDMI_SUPPORTED 8645columns_t(columns_type columns) : columns{std::move(columns)} {} 8646#endif 8647}; 8648 8649template<class T> 8650SQLITE_ORM_INLINE_VAR constexpr bool is_columns_v = polyfill::is_specialization_of<T, columns_t>::value; 8651 8652template<class T> 8653using 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*/ 8660template<class T, class... Args> 8661struct struct_t { 8662using columns_type = std::tuple<Args...>; 8663 8664columns_type columns; 8665 8666static constexpr int count = std::tuple_size<columns_type>::value; 8667 8668#ifndef SQLITE_ORM_AGGREGATE_NSDMI_SUPPORTED 8669struct_t(columns_type columns) : columns{std::move(columns)} {} 8670#endif 8671}; 8672 8673template<class T> 8674SQLITE_ORM_INLINE_VAR constexpr bool is_struct_v = polyfill::is_specialization_of<T, struct_t>::value; 8675 8676template<class T> 8677using is_struct = polyfill::bool_constant<is_struct_v<T>>; 8678 8679/** 8680* Subselect object type. 8681*/ 8682template<class T, class... Args> 8683struct select_t { 8684using return_type = T; 8685using conditions_type = std::tuple<Args...>; 8686 8687return_type col; 8688conditions_type conditions; 8689bool highest_level = false; 8690 8691#ifndef SQLITE_ORM_AGGREGATE_NSDMI_SUPPORTED 8692select_t(return_type col, conditions_type conditions) : 8693col{std::move(col)}, conditions{std::move(conditions)} {} 8694#endif 8695}; 8696 8697template<class T> 8698SQLITE_ORM_INLINE_VAR constexpr bool is_select_v = polyfill::is_specialization_of<T, select_t>::value; 8699 8700template<class T> 8701using is_select = polyfill::bool_constant<is_select_v<T>>; 8702 8703/** 8704* Base for UNION, UNION ALL, EXCEPT and INTERSECT 8705*/ 8706template<class... E> 8707struct compound_operator { 8708using expressions_tuple = std::tuple<E...>; 8709 8710expressions_tuple compound; 8711 8712constexpr compound_operator(expressions_tuple compound) : compound{std::move(compound)} { 8713iterate_tuple(this->compound, [](auto& expression) { 8714expression.highest_level = true; 8715}); 8716} 8717}; 8718 8719template<class T> 8720SQLITE_ORM_INLINE_VAR constexpr bool is_compound_operator_v = is_base_of_template<T, compound_operator>::value; 8721 8722template<class T> 8723using is_compound_operator = polyfill::bool_constant<is_compound_operator_v<T>>; 8724 8725struct union_base { 8726bool all = false; 8727 8728#ifndef SQLITE_ORM_AGGREGATE_NSDMI_SUPPORTED 8729union_base(bool all) : all{all} {} 8730#endif 8731 8732operator std::string() const { 8733if (!this->all) { 8734return "UNION"; 8735} else { 8736return "UNION ALL"; 8737} 8738} 8739}; 8740 8741/** 8742* UNION object type. 8743*/ 8744template<class... E> 8745struct union_t : public compound_operator<E...>, union_base { 8746using typename compound_operator<E...>::expressions_tuple; 8747 8748constexpr union_t(expressions_tuple compound, bool all) : 8749compound_operator<E...>{std::move(compound)}, union_base{all} {} 8750}; 8751 8752struct except_string { 8753operator std::string() const { 8754return "EXCEPT"; 8755} 8756}; 8757 8758/** 8759* EXCEPT object type. 8760*/ 8761template<class... E> 8762struct except_t : compound_operator<E...>, except_string { 8763using super = compound_operator<E...>; 8764 8765using super::super; 8766}; 8767 8768struct intersect_string { 8769operator std::string() const { 8770return "INTERSECT"; 8771} 8772}; 8773/** 8774* INTERSECT object type. 8775*/ 8776template<class... E> 8777struct intersect_t : compound_operator<E...>, intersect_string { 8778using super = compound_operator<E...>; 8779 8780using 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*/ 8787template<class T, class SFINAE = void> 8788struct decay_explicit_column { 8789using type = T; 8790}; 8791template<class T> 8792struct decay_explicit_column<T, match_if<is_column_alias, T>> { 8793using type = alias_holder<T>; 8794}; 8795template<class T> 8796struct decay_explicit_column<T, match_if<std::is_convertible, T, std::string>> { 8797using type = std::string; 8798}; 8799template<class T> 8800using 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*/ 8806struct materialized_t {}; 8807 8808/* 8809* Materialization hint to instruct SQLite to substitute a CTE's select statement as a subquery subject to optimization. 8810*/ 8811struct not_materialized_t {}; 8812#endif 8813 8814/** 8815* Monikered (aliased) CTE expression. 8816*/ 8817template<class Moniker, class ExplicitCols, class Hints, class Select> 8818struct common_table_expression { 8819using cte_moniker_type = Moniker; 8820using expression_type = Select; 8821using explicit_colrefs_tuple = ExplicitCols; 8822using hints_tuple = Hints; 8823static constexpr size_t explicit_colref_count = std::tuple_size_v<ExplicitCols>; 8824 8825SQLITE_ORM_NOUNIQUEADDRESS hints_tuple hints; 8826explicit_colrefs_tuple explicitColumns; 8827expression_type subselect; 8828 8829constexpr common_table_expression(explicit_colrefs_tuple explicitColumns, expression_type subselect) : 8830explicitColumns{std::move(explicitColumns)}, subselect{std::move(subselect)} { 8831this->subselect.highest_level = true; 8832} 8833}; 8834 8835template<class... CTEs> 8836using common_table_expressions = std::tuple<CTEs...>; 8837 8838template<typename Moniker, class ExplicitCols> 8839struct cte_builder { 8840ExplicitCols explicitColumns; 8841 8842#if SQLITE_VERSION_NUMBER >= 3035000 && defined(SQLITE_ORM_WITH_CPP20_ALIASES) 8843template<auto... hints, class Select, satisfies<is_select, Select> = true> 8844constexpr common_table_expression<Moniker, ExplicitCols, std::tuple<decltype(hints)...>, Select> 8845as(Select sel) && { 8846return {std::move(this->explicitColumns), std::move(sel)}; 8847} 8848 8849template<auto... hints, class Compound, satisfies<is_compound_operator, Compound> = true> 8850constexpr common_table_expression<Moniker, ExplicitCols, std::tuple<decltype(hints)...>, select_t<Compound>> 8851as(Compound sel) && { 8852return {std::move(this->explicitColumns), {std::move(sel)}}; 8853} 8854#else 8855template<class Select, satisfies<is_select, Select> = true> 8856constexpr common_table_expression<Moniker, ExplicitCols, std::tuple<>, Select> as(Select sel) && { 8857return {std::move(this->explicitColumns), std::move(sel)}; 8858} 8859 8860template<class Compound, satisfies<is_compound_operator, Compound> = true> 8861constexpr common_table_expression<Moniker, ExplicitCols, std::tuple<>, select_t<Compound>> 8862as(Compound sel) && { 8863return {std::move(this->explicitColumns), {std::move(sel)}}; 8864} 8865#endif 8866}; 8867 8868/** 8869* WITH object type - expression with prepended CTEs. 8870*/ 8871template<class E, class... CTEs> 8872struct with_t { 8873using cte_type = common_table_expressions<CTEs...>; 8874using expression_type = E; 8875 8876bool recursiveIndicated; 8877cte_type cte; 8878expression_type expression; 8879 8880with_t(bool recursiveIndicated, cte_type cte, expression_type expression) : 8881recursiveIndicated{recursiveIndicated}, cte{std::move(cte)}, expression{std::move(expression)} { 8882if constexpr (is_select_v<expression_type>) { 8883this->expression.highest_level = true; 8884} 8885} 8886}; 8887#endif 8888 8889template<class T> 8890struct asterisk_t { 8891using type = T; 8892 8893bool defined_order = false; 8894 8895#ifndef SQLITE_ORM_AGGREGATE_NSDMI_SUPPORTED 8896asterisk_t(bool definedOrder) : defined_order{definedOrder} {} 8897#endif 8898}; 8899 8900template<class T> 8901struct object_t { 8902using type = T; 8903 8904bool defined_order = false; 8905 8906#ifndef SQLITE_ORM_AGGREGATE_NSDMI_SUPPORTED 8907object_t(bool definedOrder) : defined_order{definedOrder} {} 8908#endif 8909}; 8910 8911template<class T> 8912struct then_t { 8913using expression_type = T; 8914 8915expression_type expression; 8916}; 8917 8918template<class R, class T, class E, class... Args> 8919struct simple_case_t { 8920using return_type = R; 8921using case_expression_type = T; 8922using args_type = std::tuple<Args...>; 8923using else_expression_type = E; 8924 8925optional_container<case_expression_type> case_expression; 8926args_type args; 8927optional_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*/ 8935template<class R, class T, class E, class... Args> 8936struct simple_case_builder { 8937using return_type = R; 8938using case_expression_type = T; 8939using args_type = std::tuple<Args...>; 8940using else_expression_type = E; 8941 8942optional_container<case_expression_type> case_expression; 8943args_type args; 8944optional_container<else_expression_type> else_expression; 8945 8946template<class W, class Th> 8947simple_case_builder<R, T, E, Args..., std::pair<W, Th>> when(W w, then_t<Th> t) { 8948using result_args_type = std::tuple<Args..., std::pair<W, Th>>; 8949std::pair<W, Th> newPair{std::move(w), std::move(t.expression)}; 8950result_args_type result_args = std::tuple_cat(std::move(this->args), std::make_tuple(newPair)); 8951std::get<std::tuple_size<result_args_type>::value - 1>(result_args) = std::move(newPair); 8952return {std::move(this->case_expression), std::move(result_args), std::move(this->else_expression)}; 8953} 8954 8955simple_case_t<R, T, E, Args...> end() { 8956return {std::move(this->case_expression), std::move(args), std::move(this->else_expression)}; 8957} 8958 8959template<class El> 8960simple_case_builder<R, T, El, Args...> else_(El el) { 8961return {{std::move(this->case_expression)}, std::move(args), {std::move(el)}}; 8962} 8963}; 8964 8965template<class T, std::enable_if_t<!is_rowset_deduplicator_v<T>, bool> = true> 8966const T& access_column_expression(const T& expression) { 8967return 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*/ 8973template<class D, std::enable_if_t<is_rowset_deduplicator_v<D>, bool> = true> 8974const typename D::expression_type& access_column_expression(const D& modifier) { 8975return modifier.expression; 8976} 8977 8978template<class T> 8979constexpr void validate_conditions() { 8980static_assert(count_tuple<T, is_where>::value <= 1, "a single query cannot contain > 1 WHERE blocks"); 8981static_assert(count_tuple<T, is_group_by>::value <= 1, "a single query cannot contain > 1 GROUP BY blocks"); 8982static_assert(count_tuple<T, is_order_by>::value <= 1, "a single query cannot contain > 1 ORDER BY blocks"); 8983static_assert(count_tuple<T, is_limit>::value <= 1, "a single query cannot contain > 1 LIMIT blocks"); 8984static_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 8989template<class T> 8990internal::as_optional_t<T> as_optional(T value) { 8991return {std::move(value)}; 8992} 8993#endif // SQLITE_ORM_OPTIONAL_SUPPORTED 8994 8995template<class T> 8996internal::then_t<T> then(T t) { 8997return {std::move(t)}; 8998} 8999 9000template<class R, class T> 9001internal::simple_case_builder<R, T, void> case_(T t) { 9002return {{std::move(t)}}; 9003} 9004 9005template<class R> 9006internal::simple_case_builder<R, void, void> case_() { 9007return {}; 9008} 9009 9010template<class T> 9011internal::distinct_t<T> distinct(T t) { 9012return {std::move(t)}; 9013} 9014 9015template<class T> 9016internal::all_t<T> all(T t) { 9017return {std::move(t)}; 9018} 9019 9020/* 9021* Combine multiple columns in a tuple. 9022*/ 9023template<class... Args> 9024constexpr internal::columns_t<Args...> columns(Args... args) { 9025return {{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*/ 9032template<class T, class... Args> 9033constexpr internal::struct_t<T, Args...> struct_(Args... args) { 9034return {{std::forward<Args>(args)...}}; 9035} 9036 9037/** 9038* Public function for subselect query. Is useful in UNION queries. 9039*/ 9040template<class T, class... Args> 9041constexpr internal::select_t<T, Args...> select(T t, Args... args) { 9042using args_tuple = std::tuple<Args...>; 9043internal::validate_conditions<args_tuple>(); 9044return {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*/ 9052template<class... E> 9053constexpr internal::union_t<E...> union_(E... expressions) { 9054static_assert(sizeof...(E) >= 2, "Compound operators must have at least 2 select statements"); 9055return {{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*/ 9063template<class... E> 9064constexpr internal::union_t<E...> union_all(E... expressions) { 9065static_assert(sizeof...(E) >= 2, "Compound operators must have at least 2 select statements"); 9066return {{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*/ 9074template<class... E> 9075constexpr internal::except_t<E...> except(E... expressions) { 9076static_assert(sizeof...(E) >= 2, "Compound operators must have at least 2 select statements"); 9077return {{std::forward<E>(expressions)...}}; 9078} 9079 9080template<class... E> 9081constexpr internal::intersect_t<E...> intersect(E... expressions) { 9082static_assert(sizeof...(E) >= 2, "Compound operators must have at least 2 select statements"); 9083return {{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*/ 9095consteval internal::materialized_t materialized() { 9096return {}; 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*/ 9105consteval internal::not_materialized_t not_materialized() { 9106return {}; 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*/ 9126template<class Moniker, 9127class... ExplicitCols, 9128std::enable_if_t<polyfill::conjunction_v<polyfill::disjunction< 9129internal::is_column_alias<ExplicitCols>, 9130std::is_member_pointer<ExplicitCols>, 9131internal::is_column<ExplicitCols>, 9132std::is_same<ExplicitCols, polyfill::remove_cvref_t<decltype(std::ignore)>>, 9133std::is_convertible<ExplicitCols, std::string>>...>, 9134bool> = true> 9135constexpr auto cte(ExplicitCols... explicitColumns) { 9136using namespace ::sqlite_orm::internal; 9137static_assert(is_cte_moniker_v<Moniker>, "Moniker must be a CTE moniker"); 9138static_assert((!is_builtin_numeric_column_alias_v<ExplicitCols> && ...), 9139"Numeric column aliases are reserved for referencing columns locally within a single CTE."); 9140 9141using builder_type = 9142cte_builder<Moniker, transform_tuple_t<std::tuple<ExplicitCols...>, decay_explicit_column_t>>; 9143return builder_type{{std::move(explicitColumns)...}}; 9144} 9145 9146#ifdef SQLITE_ORM_WITH_CPP20_ALIASES 9147template<orm_cte_moniker auto moniker, class... ExplicitCols> 9148requires ((internal::is_column_alias_v<ExplicitCols> || std::is_member_pointer_v<ExplicitCols> || 9149internal::is_column_v<ExplicitCols> || 9150std::same_as<ExplicitCols, std::remove_cvref_t<decltype(std::ignore)>> || 9151std::convertible_to<ExplicitCols, std::string>) && 9152...) 9153constexpr auto cte(ExplicitCols... explicitColumns) { 9154using namespace ::sqlite_orm::internal; 9155static_assert((!is_builtin_numeric_column_alias_v<ExplicitCols> && ...), 9156"Numeric column aliases are reserved for referencing columns locally within a single CTE."); 9157 9158using builder_type = 9159cte_builder<decltype(moniker), transform_tuple_t<std::tuple<ExplicitCols...>, decay_explicit_column_t>>; 9160return builder_type{{std::move(explicitColumns)...}}; 9161} 9162#endif 9163 9164namespace internal { 9165#ifdef SQLITE_ORM_WITH_CPP20_ALIASES 9166template<char A, char... X> 9167template<class... ExplicitCols> 9168requires ((is_column_alias_v<ExplicitCols> || std::is_member_pointer_v<ExplicitCols> || 9169std::same_as<ExplicitCols, std::remove_cvref_t<decltype(std::ignore)>> || 9170std::convertible_to<ExplicitCols, std::string>) && 9171...) 9172constexpr auto cte_moniker<A, X...>::operator()(ExplicitCols... explicitColumns) const { 9173return cte<cte_moniker<A, X...>>(std::forward<ExplicitCols>(explicitColumns)...); 9174} 9175#else 9176template<char A, char... X> 9177template<class... ExplicitCols, 9178std::enable_if_t<polyfill::conjunction_v<polyfill::disjunction< 9179is_column_alias<ExplicitCols>, 9180std::is_member_pointer<ExplicitCols>, 9181std::is_same<ExplicitCols, polyfill::remove_cvref_t<decltype(std::ignore)>>, 9182std::is_convertible<ExplicitCols, std::string>>...>, 9183bool>> 9184constexpr auto cte_moniker<A, X...>::operator()(ExplicitCols... explicitColumns) const { 9185return 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*/ 9195template<class E, class... CTEs, internal::satisfies_not<internal::is_compound_operator, E> = true> 9196internal::with_t<E, CTEs...> with(internal::common_table_expressions<CTEs...> ctes, E expression) { 9197return {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*/ 9205template<class Compound, class... CTEs, internal::satisfies<internal::is_compound_operator, Compound> = true> 9206internal::with_t<internal::select_t<Compound>, CTEs...> with(internal::common_table_expressions<CTEs...> ctes, 9207Compound sel) { 9208return {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*/ 9220template<class E, 9221class CTE, 9222internal::satisfies_is_specialization_of<CTE, internal::common_table_expression> = true, 9223internal::satisfies_not<internal::is_compound_operator, E> = true> 9224internal::with_t<E, CTE> with(CTE cte, E expression) { 9225return {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*/ 9237template<class Compound, 9238class CTE, 9239internal::satisfies_is_specialization_of<CTE, internal::common_table_expression> = true, 9240internal::satisfies<internal::is_compound_operator, Compound> = true> 9241internal::with_t<internal::select_t<Compound>, CTE> with(CTE cte, Compound sel) { 9242return {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*/ 9250template<class E, class... CTEs, internal::satisfies_not<internal::is_compound_operator, E> = true> 9251internal::with_t<E, CTEs...> with_recursive(internal::common_table_expressions<CTEs...> ctes, E expression) { 9252return {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*/ 9260template<class Compound, class... CTEs, internal::satisfies<internal::is_compound_operator, Compound> = true> 9261internal::with_t<internal::select_t<Compound>, CTEs...> 9262with_recursive(internal::common_table_expressions<CTEs...> ctes, Compound sel) { 9263return {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*/ 9275template<class E, 9276class CTE, 9277internal::satisfies_is_specialization_of<CTE, internal::common_table_expression> = true, 9278internal::satisfies_not<internal::is_compound_operator, E> = true> 9279internal::with_t<E, CTE> with_recursive(CTE cte, E expression) { 9280return {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*/ 9292template<class Compound, 9293class CTE, 9294internal::satisfies_is_specialization_of<CTE, internal::common_table_expression> = true, 9295internal::satisfies<internal::is_compound_operator, Compound> = true> 9296internal::with_t<internal::select_t<Compound>, CTE> with_recursive(CTE cte, Compound sel) { 9297return {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*/ 9320template<class T> 9321constexpr internal::asterisk_t<T> asterisk(bool definedOrder = false) { 9322return {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*/ 9332template<orm_refers_to_recordset auto recordset> 9333constexpr auto asterisk(bool definedOrder = false) { 9334return 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*/ 9349template<class T> 9350constexpr internal::object_t<T> object(bool definedOrder = false) { 9351return {definedOrder}; 9352} 9353 9354#ifdef SQLITE_ORM_WITH_CPP20_ALIASES 9355template<orm_refers_to_table auto als> 9356constexpr auto object(bool definedOrder = false) { 9357return 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 9402namespace sqlite_orm { 9403 9404/** 9405* Helper classes used by statement_binder and row_extractor. 9406*/ 9407struct int_or_smaller_tag {}; 9408struct bigint_tag {}; 9409struct real_tag {}; 9410 9411template<class V> 9412using arithmetic_tag_t = 9413mpl::conditional_t<std::is_integral<V>::value, 9414// Integer class 9415mpl::conditional_t<sizeof(V) <= sizeof(int), int_or_smaller_tag, bigint_tag>, 9416// Floating-point class 9417real_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 9429namespace sqlite_orm { 9430 9431using xdestroy_fn_t = void (*)(void*); 9432using null_xdestroy_t = std::integral_constant<xdestroy_fn_t, nullptr>; 9433SQLITE_ORM_INLINE_VAR constexpr null_xdestroy_t null_xdestroy_f{}; 9434} 9435 9436namespace sqlite_orm { 9437namespace internal { 9438#ifdef SQLITE_ORM_CONCEPTS_SUPPORTED 9439/** 9440* Constrains a deleter to be state-less. 9441*/ 9442template<typename D> 9443concept 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*/ 9448template<typename D> 9449concept integral_fp_c = requires { 9450typename D::value_type; 9451D::value; 9452requires 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*/ 9458template<typename D> 9459concept yields_fp = requires(D d) { 9460// yielding function pointer by using the plus trick 9461{ +d }; 9462requires 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*/ 9470template<yields_fp D> 9471struct yield_fp_of { 9472using type = decltype(+std::declval<D>()); 9473}; 9474#else 9475 9476template<typename D> 9477SQLITE_ORM_INLINE_VAR constexpr bool is_stateless_deleter_v = 9478std::is_empty<D>::value && std::is_default_constructible<D>::value; 9479 9480template<typename D, typename SFINAE = void> 9481struct is_integral_fp_c : std::false_type {}; 9482template<typename D> 9483struct is_integral_fp_c< 9484D, 9485polyfill::void_t<typename D::value_type, 9486decltype(D::value), 9487std::enable_if_t<std::is_function<std::remove_pointer_t<typename D::value_type>>::value>>> 9488: std::true_type {}; 9489template<typename D> 9490SQLITE_ORM_INLINE_VAR constexpr bool is_integral_fp_c_v = is_integral_fp_c<D>::value; 9491 9492template<typename D, typename SFINAE = void> 9493struct can_yield_fp : std::false_type {}; 9494template<typename D> 9495struct can_yield_fp< 9496D, 9497polyfill::void_t< 9498decltype(+std::declval<D>()), 9499std::enable_if_t<std::is_function<std::remove_pointer_t<decltype(+std::declval<D>())>>::value>>> 9500: std::true_type {}; 9501template<typename D> 9502SQLITE_ORM_INLINE_VAR constexpr bool can_yield_fp_v = can_yield_fp<D>::value; 9503 9504template<typename D, bool = can_yield_fp_v<D>> 9505struct yield_fp_of { 9506using type = void; 9507}; 9508template<typename D> 9509struct yield_fp_of<D, true> { 9510using type = decltype(+std::declval<D>()); 9511}; 9512#endif 9513template<typename D> 9514using yielded_fn_t = typename yield_fp_of<D>::type; 9515 9516#ifdef SQLITE_ORM_CPP20_CONCEPTS_SUPPORTED 9517template<typename D> 9518concept 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*/ 9525template<typename D> 9526concept yields_xdestroy = yields_fp<D> && std::convertible_to<yielded_fn_t<D>, xdestroy_fn_t>; 9527 9528template<typename D, typename P> 9529concept 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*/ 9538template<typename D, typename P> 9539requires (!integral_fp_c<D>) 9540void xdestroy_proxy(void* p) noexcept { 9541// C-casting `void* -> P*` like statement_binder<pointer_binding<P, T, D>> 9542auto 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*/ 9553template<integral_fp_c D, typename P> 9554void xdestroy_proxy(void* p) noexcept { 9555// C-casting `void* -> P*` like statement_binder<pointer_binding<P, T, D>>, 9556auto o = (std::remove_cv_t<P>*)(P*)p; 9557// ignoring return code 9558(void)D{}(o); 9559} 9560#else 9561template<typename D> 9562SQLITE_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 9566template<typename D> 9567SQLITE_ORM_INLINE_VAR constexpr bool can_yield_xdestroy_v = 9568can_yield_fp_v<D> && std::is_convertible<yielded_fn_t<D>, xdestroy_fn_t>::value; 9569 9570template<typename D, typename P> 9571SQLITE_ORM_INLINE_VAR constexpr bool needs_xdestroy_proxy_v = 9572is_stateless_deleter_v<D> && 9573(!can_yield_fp_v<D> || !std::is_convertible<yielded_fn_t<D>, xdestroy_fn_t>::value); 9574 9575template<typename D, typename P, std::enable_if_t<!is_integral_fp_c_v<D>, bool> = true> 9576void xdestroy_proxy(void* p) noexcept { 9577// C-casting `void* -> P*` like statement_binder<pointer_binding<P, T, D>> 9578auto o = (P*)p; 9579// ignoring return code 9580(void)D{}(o); 9581} 9582 9583template<typename D, typename P, std::enable_if_t<is_integral_fp_c_v<D>, bool> = true> 9584void xdestroy_proxy(void* p) noexcept { 9585// C-casting `void* -> P*` like statement_binder<pointer_binding<P, T, D>>, 9586auto o = (std::remove_cv_t<P>*)(P*)p; 9587// ignoring return code 9588(void)D{}(o); 9589} 9590#endif 9591} 9592} 9593 9594namespace 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*/ 9602template<typename P, typename D> 9603constexpr xdestroy_fn_t obtain_xdestroy_for(D, P* = nullptr) noexcept 9604requires (internal::is_unusable_for_xdestroy<D>) 9605{ 9606static_assert(polyfill::always_false_v<D>, 9607"A function pointer, which is not of type xdestroy_fn_t, is prohibited."); 9608return 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*/ 9623template<typename P, typename D> 9624constexpr xdestroy_fn_t obtain_xdestroy_for(D, P* = nullptr) noexcept 9625requires (internal::needs_xdestroy_proxy<D, P>) 9626{ 9627return 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*/ 9644template<typename P, typename D> 9645constexpr xdestroy_fn_t obtain_xdestroy_for(D d, P* = nullptr) noexcept 9646requires (internal::yields_xdestroy<D>) 9647{ 9648return d; 9649} 9650#else 9651template<typename P, typename D, std::enable_if_t<internal::is_unusable_for_xdestroy_v<D>, bool> = true> 9652constexpr xdestroy_fn_t obtain_xdestroy_for(D, P* = nullptr) { 9653static_assert(polyfill::always_false_v<D>, 9654"A function pointer, which is not of type xdestroy_fn_t, is prohibited."); 9655return nullptr; 9656} 9657 9658template<typename P, typename D, std::enable_if_t<internal::needs_xdestroy_proxy_v<D, P>, bool> = true> 9659constexpr xdestroy_fn_t obtain_xdestroy_for(D, P* = nullptr) noexcept { 9660return internal::xdestroy_proxy<D, P>; 9661} 9662 9663template<typename P, typename D, std::enable_if_t<internal::can_yield_xdestroy_v<D>, bool> = true> 9664constexpr xdestroy_fn_t obtain_xdestroy_for(D d, P* = nullptr) noexcept { 9665return 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 9686namespace sqlite_orm { 9687#ifdef SQLITE_ORM_WITH_CPP20_ALIASES 9688namespace internal { 9689template<char... C> 9690struct pointer_type { 9691using value_type = const char[sizeof...(C) + 1]; 9692static inline constexpr value_type value = {C..., '\0'}; 9693}; 9694} 9695 9696inline namespace literals { 9697template<internal::cstring_literal tag> 9698[[nodiscard]] consteval auto operator"" _pointer_type() { 9699return 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*/ 9705template<class T> 9706concept orm_pointer_type = requires { 9707typename 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*/ 9722template<typename P, typename T> 9723struct 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) 9728static_assert(orm_pointer_type<T>, "T must be a pointer type (tag)"); 9729#else 9730static_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 9734using tag = T; 9735using qualified_type = P; 9736 9737P* p_; 9738 9739P* ptr() const noexcept { 9740return p_; 9741} 9742 9743operator P*() const noexcept { 9744return 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*/ 9773template<typename P, typename T, typename D> 9774class pointer_binding { 9775 9776P* p_; 9777SQLITE_ORM_NOUNIQUEADDRESS 9778D d_; 9779 9780protected: 9781// Constructing pointer bindings must go through bind_pointer() 9782template<class T2, class P2, class D2> 9783friend 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() 9786template<orm_pointer_type auto tag, class P2, class D2> 9787friend auto bind_pointer(P2*, D2) noexcept -> pointer_binding<P2, decltype(tag), D2>; 9788#endif 9789template<class B> 9790friend 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. 9794pointer_binding(P* p, D d = {}) noexcept : p_{p}, d_{std::move(d)} {} 9795 9796public: 9797using qualified_type = P; 9798using tag = T; 9799using deleter_type = D; 9800 9801pointer_binding(const pointer_binding&) = delete; 9802pointer_binding& operator=(const pointer_binding&) = delete; 9803pointer_binding& operator=(pointer_binding&&) = delete; 9804 9805pointer_binding(pointer_binding&& other) noexcept : 9806p_{std::exchange(other.p_, nullptr)}, d_{std::move(other.d_)} {} 9807 9808~pointer_binding() { 9809if (p_) { 9810if (auto xDestroy = get_xdestroy()) { 9811// note: C-casting `P* -> void*` like statement_binder<pointer_binding<P, T, D>> 9812xDestroy((void*)p_); 9813} 9814} 9815} 9816 9817P* ptr() const noexcept { 9818return p_; 9819} 9820 9821P* take_ptr() noexcept { 9822return std::exchange(p_, nullptr); 9823} 9824 9825xdestroy_fn_t get_xdestroy() const noexcept { 9826return 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*/ 9836template<typename P, typename T> 9837using static_pointer_binding = pointer_binding<P, T, null_xdestroy_t>; 9838 9839#ifdef SQLITE_ORM_WITH_CPP20_ALIASES 9840template<class P, orm_pointer_type auto tag> 9841using pointer_arg_t = pointer_arg<P, decltype(tag)>; 9842 9843template<class P, orm_pointer_type auto tag, class D> 9844using 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*/ 9852template<typename P, orm_pointer_type auto tag> 9853using static_pointer_binding_t = pointer_binding_t<P, tag, null_xdestroy_t>; 9854#endif 9855} 9856 9857namespace 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*/ 9865template<class T, class P, class D> 9866auto bind_pointer(P* p, D d) noexcept -> pointer_binding<P, T, D> { 9867return {p, std::move(d)}; 9868} 9869 9870template<class T, class P, class D> 9871auto bind_pointer(std::unique_ptr<P, D> p) noexcept -> pointer_binding<P, T, D> { 9872return bind_pointer<T>(p.release(), p.get_deleter()); 9873} 9874 9875template<typename B> 9876auto bind_pointer(typename B::qualified_type* p, typename B::deleter_type d = {}) noexcept -> B { 9877return B{p, std::move(d)}; 9878} 9879 9880template<class T, class P, class D> 9881[[deprecated("Use the better named function `bind_pointer(...)`")]] pointer_binding<P, T, D> 9882bindable_pointer(P* p, D d) noexcept { 9883return bind_pointer<T>(p, std::move(d)); 9884} 9885 9886template<class T, class P, class D> 9887[[deprecated("Use the better named function `bind_pointer(...)`")]] pointer_binding<P, T, D> 9888bindable_pointer(std::unique_ptr<P, D> p) noexcept { 9889return bind_pointer<T>(p.release(), p.get_deleter()); 9890} 9891 9892template<typename B> 9893[[deprecated("Use the better named function `bind_pointer(...)`")]] B 9894bindable_pointer(typename B::qualified_type* p, typename B::deleter_type d = {}) noexcept { 9895return 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*/ 9906template<orm_pointer_type auto tag, class P, class D> 9907auto bind_pointer(P* p, D d) noexcept -> pointer_binding<P, decltype(tag), D> { 9908return {p, std::move(d)}; 9909} 9910 9911template<orm_pointer_type auto tag, class P, class D> 9912auto bind_pointer(std::unique_ptr<P, D> p) noexcept -> pointer_binding<P, decltype(tag), D> { 9913return 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*/ 9923template<class T, class P> 9924auto bind_pointer_statically(P* p) noexcept -> static_pointer_binding<P, T> { 9925return bind_pointer<T>(p, null_xdestroy_f); 9926} 9927 9928template<typename B> 9929B bind_pointer_statically(typename B::qualified_type* p, 9930typename B::deleter_type* /*exposition*/ = nullptr) noexcept { 9931return bind_pointer<B>(p); 9932} 9933 9934template<class T, class P> 9935[[deprecated("Use the better named function `bind_pointer_statically(...)`")]] static_pointer_binding<P, T> 9936statically_bindable_pointer(P* p) noexcept { 9937return bind_pointer<T>(p, null_xdestroy_f); 9938} 9939 9940template<typename B> 9941[[deprecated("Use the better named function `bind_pointer_statically(...)`")]] B 9942statically_bindable_pointer(typename B::qualified_type* p, 9943typename B::deleter_type* /*exposition*/ = nullptr) noexcept { 9944return 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*/ 9954template<orm_pointer_type auto tag, class P> 9955auto bind_pointer_statically(P* p) noexcept -> static_pointer_binding<P, decltype(tag)> { 9956return bind_pointer<tag>(p, null_xdestroy_f); 9957} 9958#endif 9959 9960/** 9961* Forward a pointer value from an argument. 9962*/ 9963template<class P, class T> 9964auto rebind_statically(const pointer_arg<P, T>& pv) noexcept -> static_pointer_binding<P, T> { 9965return bind_pointer_statically<T>(pv.ptr()); 9966} 9967} 9968#endif 9969 9970namespace sqlite_orm { 9971 9972/** 9973* Helper class used for binding fields to sqlite3 statements. 9974*/ 9975template<class V, typename Enable = void> 9976struct statement_binder; 9977 9978namespace 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*/ 9984template<class Binder> 9985struct indirectly_test_bindable; 9986 9987template<class T, class SFINAE = void> 9988SQLITE_ORM_INLINE_VAR constexpr bool is_bindable_v = false; 9989template<class T> 9990SQLITE_ORM_INLINE_VAR constexpr bool 9991is_bindable_v<T, polyfill::void_t<indirectly_test_bindable<decltype(statement_binder<T>{})>>> = true; 9992 9993template<class T> 9994struct 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*/ 10001template<class P, class T, class D> 10002struct statement_binder<pointer_binding<P, T, D>, void> { 10003using V = pointer_binding<P, T, D>; 10004 10005// ownership of pointed-to-object is left untouched and remains at prepared statement's AST expression 10006int bind(sqlite3_stmt* stmt, int index, const V& value) const { 10007// note: C-casting `P* -> void*`, internal::xdestroy_proxy() does the inverse 10008return 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 10012void 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 10015sqlite3_result_pointer(context, (void*)value.take_ptr(), T::value, value.get_xdestroy()); 10016} 10017}; 10018#endif 10019 10020/** 10021* Specialization for arithmetic types. 10022*/ 10023template<class V> 10024struct statement_binder<V, internal::match_if<std::is_arithmetic, V>> { 10025 10026int bind(sqlite3_stmt* stmt, int index, const V& value) const { 10027return this->bind(stmt, index, value, tag()); 10028} 10029 10030void result(sqlite3_context* context, const V& value) const { 10031this->result(context, value, tag()); 10032} 10033 10034private: 10035using tag = arithmetic_tag_t<V>; 10036 10037int bind(sqlite3_stmt* stmt, int index, const V& value, int_or_smaller_tag) const { 10038return sqlite3_bind_int(stmt, index, static_cast<int>(value)); 10039} 10040 10041void result(sqlite3_context* context, const V& value, int_or_smaller_tag) const { 10042sqlite3_result_int(context, static_cast<int>(value)); 10043} 10044 10045int bind(sqlite3_stmt* stmt, int index, const V& value, bigint_tag) const { 10046return sqlite3_bind_int64(stmt, index, static_cast<sqlite3_int64>(value)); 10047} 10048 10049void result(sqlite3_context* context, const V& value, bigint_tag) const { 10050sqlite3_result_int64(context, static_cast<sqlite3_int64>(value)); 10051} 10052 10053int bind(sqlite3_stmt* stmt, int index, const V& value, real_tag) const { 10054return sqlite3_bind_double(stmt, index, static_cast<double>(value)); 10055} 10056 10057void result(sqlite3_context* context, const V& value, real_tag) const { 10058sqlite3_result_double(context, static_cast<double>(value)); 10059} 10060}; 10061 10062/** 10063* Specialization for std::string and C-string. 10064*/ 10065template<class V> 10066struct statement_binder<V, 10067std::enable_if_t<polyfill::disjunction<std::is_base_of<std::string, V>, 10068std::is_same<V, const char*> 10069#ifdef SQLITE_ORM_STRING_VIEW_SUPPORTED 10070, 10071std::is_same<V, std::string_view> 10072#endif 10073>::value>> { 10074 10075int bind(sqlite3_stmt* stmt, int index, const V& value) const { 10076auto stringData = this->string_data(value); 10077return sqlite3_bind_text(stmt, index, stringData.first, stringData.second, SQLITE_TRANSIENT); 10078} 10079 10080void result(sqlite3_context* context, const V& value) const { 10081auto stringData = this->string_data(value); 10082auto dataCopy = new char[stringData.second + 1]; 10083constexpr auto deleter = std::default_delete<char[]>{}; 10084strncpy(dataCopy, stringData.first, stringData.second + 1); 10085sqlite3_result_text(context, dataCopy, stringData.second, obtain_xdestroy_for(deleter, dataCopy)); 10086} 10087 10088private: 10089#ifdef SQLITE_ORM_STRING_VIEW_SUPPORTED 10090std::pair<const char*, int> string_data(const std::string_view& s) const { 10091return {s.data(), int(s.size())}; 10092} 10093#else 10094std::pair<const char*, int> string_data(const std::string& s) const { 10095return {s.c_str(), int(s.size())}; 10096} 10097 10098std::pair<const char*, int> string_data(const char* s) const { 10099return {s, int(strlen(s))}; 10100} 10101#endif 10102}; 10103 10104#ifndef SQLITE_ORM_OMITS_CODECVT 10105template<class V> 10106struct statement_binder<V, 10107std::enable_if_t<polyfill::disjunction<std::is_base_of<std::wstring, V>, 10108std::is_same<V, const wchar_t*> 10109#ifdef SQLITE_ORM_STRING_VIEW_SUPPORTED 10110, 10111std::is_same<V, std::wstring_view> 10112#endif 10113>::value>> { 10114 10115int bind(sqlite3_stmt* stmt, int index, const V& value) const { 10116auto stringData = this->string_data(value); 10117std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>> converter; 10118std::string utf8Str = converter.to_bytes(stringData.first, stringData.first + stringData.second); 10119return statement_binder<decltype(utf8Str)>().bind(stmt, index, utf8Str); 10120} 10121 10122void result(sqlite3_context* context, const V& value) const { 10123auto stringData = this->string_data(value); 10124sqlite3_result_text16(context, stringData.first, stringData.second, nullptr); 10125} 10126 10127private: 10128#ifdef SQLITE_ORM_STRING_VIEW_SUPPORTED 10129std::pair<const wchar_t*, int> string_data(const std::wstring_view& s) const { 10130return {s.data(), int(s.size())}; 10131} 10132#else 10133std::pair<const wchar_t*, int> string_data(const std::wstring& s) const { 10134return {s.c_str(), int(s.size())}; 10135} 10136 10137std::pair<const wchar_t*, int> string_data(const wchar_t* s) const { 10138return {s, int(wcslen(s))}; 10139} 10140#endif 10141}; 10142#endif 10143 10144/** 10145* Specialization for nullptr_t. 10146*/ 10147template<> 10148struct statement_binder<nullptr_t, void> { 10149int bind(sqlite3_stmt* stmt, int index, const nullptr_t&) const { 10150return sqlite3_bind_null(stmt, index); 10151} 10152 10153void result(sqlite3_context* context, const nullptr_t&) const { 10154sqlite3_result_null(context); 10155} 10156}; 10157 10158#ifdef SQLITE_ORM_OPTIONAL_SUPPORTED 10159/** 10160* Specialization for std::nullopt_t. 10161*/ 10162template<> 10163struct statement_binder<std::nullopt_t, void> { 10164int bind(sqlite3_stmt* stmt, int index, const std::nullopt_t&) const { 10165return sqlite3_bind_null(stmt, index); 10166} 10167 10168void result(sqlite3_context* context, const std::nullopt_t&) const { 10169sqlite3_result_null(context); 10170} 10171}; 10172#endif // SQLITE_ORM_OPTIONAL_SUPPORTED 10173 10174template<class V> 10175struct statement_binder< 10176V, 10177std::enable_if_t<is_std_ptr<V>::value && 10178internal::is_bindable<std::remove_cv_t<typename V::element_type>>::value>> { 10179using unqualified_type = std::remove_cv_t<typename V::element_type>; 10180 10181int bind(sqlite3_stmt* stmt, int index, const V& value) const { 10182if (value) { 10183return statement_binder<unqualified_type>().bind(stmt, index, *value); 10184} else { 10185return statement_binder<nullptr_t>().bind(stmt, index, nullptr); 10186} 10187} 10188}; 10189 10190/** 10191* Specialization for binary data (std::vector<char>). 10192*/ 10193template<> 10194struct statement_binder<std::vector<char>, void> { 10195int bind(sqlite3_stmt* stmt, int index, const std::vector<char>& value) const { 10196if (!value.empty()) { 10197return sqlite3_bind_blob(stmt, index, (const void*)&value.front(), int(value.size()), SQLITE_TRANSIENT); 10198} else { 10199return sqlite3_bind_blob(stmt, index, "", 0, SQLITE_TRANSIENT); 10200} 10201} 10202 10203void result(sqlite3_context* context, const std::vector<char>& value) const { 10204if (!value.empty()) { 10205sqlite3_result_blob(context, (const void*)&value.front(), int(value.size()), nullptr); 10206} else { 10207sqlite3_result_blob(context, "", 0, nullptr); 10208} 10209} 10210}; 10211 10212#ifdef SQLITE_ORM_OPTIONAL_SUPPORTED 10213template<class V> 10214struct statement_binder<V, 10215std::enable_if_t<polyfill::is_specialization_of_v<V, std::optional> && 10216internal::is_bindable_v<std::remove_cv_t<typename V::value_type>>>> { 10217using unqualified_type = std::remove_cv_t<typename V::value_type>; 10218 10219int bind(sqlite3_stmt* stmt, int index, const V& value) const { 10220if (value) { 10221return statement_binder<unqualified_type>().bind(stmt, index, *value); 10222} else { 10223return statement_binder<std::nullopt_t>().bind(stmt, index, std::nullopt); 10224} 10225} 10226}; 10227#endif // SQLITE_ORM_OPTIONAL_SUPPORTED 10228 10229namespace internal { 10230 10231struct conditional_binder { 10232sqlite3_stmt* stmt = nullptr; 10233int index = 1; 10234 10235explicit conditional_binder(sqlite3_stmt* stmt) : stmt{stmt} {} 10236 10237template<class T, satisfies<is_bindable, T> = true> 10238void operator()(const T& t) { 10239int rc = statement_binder<T>{}.bind(this->stmt, this->index++, t); 10240if (SQLITE_OK != rc) { 10241throw_translated_sqlite_error(this->stmt); 10242} 10243} 10244 10245template<class T, satisfies_not<is_bindable, T> = true> 10246void operator()(const T&) const {} 10247}; 10248 10249struct field_value_binder : conditional_binder { 10250using conditional_binder::conditional_binder; 10251using conditional_binder::operator(); 10252 10253template<class T, satisfies_not<is_bindable, T> = true> 10254void operator()(const T&) const = delete; 10255 10256template<class T> 10257void operator()(const T* value) { 10258if (!value) { 10259throw std::system_error{orm_error_code::value_is_null}; 10260} 10261(*this)(*value); 10262} 10263}; 10264 10265struct tuple_value_binder { 10266sqlite3_stmt* stmt = nullptr; 10267 10268explicit tuple_value_binder(sqlite3_stmt* stmt) : stmt{stmt} {} 10269 10270template<class Tpl, class Projection> 10271void operator()(const Tpl& tpl, Projection project) const { 10272(*this)(tpl, 10273std::make_index_sequence<std::tuple_size<Tpl>::value>{}, 10274std::forward<Projection>(project)); 10275} 10276 10277private: 10278#ifdef SQLITE_ORM_FOLD_EXPRESSIONS_SUPPORTED 10279template<class Tpl, size_t... Idx, class Projection> 10280void 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 10284template<class Tpl, size_t... Idx, class Projection> 10285void operator()(const Tpl& tpl, std::index_sequence<Idx...>, Projection project) const { 10286using Sink = int[sizeof...(Idx)]; 10287(void)Sink{(this->bind(polyfill::invoke(project, std::get<Idx>(tpl)), Idx), 0)...}; 10288} 10289#endif 10290 10291template<class T> 10292void bind(const T& t, size_t idx) const { 10293int rc = statement_binder<T>{}.bind(this->stmt, int(idx + 1), t); 10294if (SQLITE_OK != rc) { 10295throw_translated_sqlite_error(this->stmt); 10296} 10297} 10298 10299template<class T> 10300void bind(const T* value, size_t idx) const { 10301if (!value) { 10302throw std::system_error{orm_error_code::value_is_null}; 10303} 10304(*this)(*value, idx); 10305} 10306}; 10307 10308template<class Tpl> 10309using 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 10328namespace sqlite_orm { 10329 10330namespace internal { 10331 10332template<typename T> 10333struct tuplify { 10334using type = std::tuple<T>; 10335}; 10336template<typename... Ts> 10337struct tuplify<std::tuple<Ts...>> { 10338using type = std::tuple<Ts...>; 10339}; 10340 10341template<typename T> 10342using 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 10366namespace sqlite_orm { 10367 10368namespace 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*/ 10374template<class T, class SFINAE = void> 10375struct mapped_type_proxy : std::remove_const<T> {}; 10376 10377#ifdef SQLITE_ORM_WITH_CPP20_ALIASES 10378template<orm_table_reference R> 10379struct mapped_type_proxy<R, void> : R {}; 10380#endif 10381 10382template<class A> 10383struct mapped_type_proxy<A, match_if<is_recordset_alias, A>> : std::remove_const<type_t<A>> {}; 10384 10385template<class T> 10386using 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 10404namespace sqlite_orm { 10405namespace 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*/ 10411template<class T, class ColResults> 10412struct structure { 10413using type = T; 10414}; 10415} 10416} 10417 10418namespace sqlite_orm { 10419namespace internal { 10420 10421template<class T, class SFINAE = void> 10422struct column_result_proxy : std::remove_const<T> {}; 10423 10424/* 10425* Unwrap `table_reference` 10426*/ 10427template<class P> 10428struct column_result_proxy<P, match_if<is_table_reference, P>> : decay_table_ref<P> {}; 10429 10430/* 10431* Pass through `structure` 10432*/ 10433template<class P> 10434struct column_result_proxy<P, match_specialization_of<P, structure>> : P {}; 10435 10436template<class T> 10437using 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) 10457namespace sqlite_orm { 10458 10459namespace internal { 10460 10461/** 10462* Aliased column expression mapped into a CTE, stored as a field in a table column. 10463*/ 10464template<class A, class F> 10465struct aliased_field { 10466~aliased_field() = delete; 10467aliased_field(const aliased_field&) = delete; 10468void operator=(const aliased_field&) = delete; 10469 10470F 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*/ 10477template<typename Moniker, 10478typename ExplicitColRefs, 10479typename Expression, 10480typename SubselectColRefs, 10481typename FinalColRefs, 10482typename... Fs> 10483class subselect_mapper { 10484public: 10485subselect_mapper() = delete; 10486 10487// this type name is used to detect the mapping from moniker to object 10488using cte_moniker_type = Moniker; 10489using 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 10493using expressions_tuple = tuplify_t<Expression>; 10494// this type captures column reference expressions specified at CTE construction; 10495// those are: member pointers, alias holders 10496using explicit_colrefs_tuple = ExplicitColRefs; 10497// this type captures column reference expressions from the subselect; 10498// those are: member pointers, alias holders 10499using subselect_colrefs_tuple = SubselectColRefs; 10500// this type captures column reference expressions merged from SubselectColRefs and ExplicitColRefs 10501using 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 10529namespace sqlite_orm { 10530namespace internal { 10531 10532template<class... DBO> 10533struct storage_t; 10534 10535template<class... DBO> 10536using db_objects_tuple = std::tuple<DBO...>; 10537 10538struct basic_table; 10539struct index_base; 10540struct base_trigger; 10541 10542template<class T> 10543struct is_storage : std::false_type {}; 10544 10545template<class... DBO> 10546struct is_storage<storage_t<DBO...>> : std::true_type {}; 10547template<class... DBO> 10548struct is_storage<const storage_t<DBO...>> : std::true_type {}; 10549 10550template<class T> 10551struct is_db_objects : std::false_type {}; 10552 10553template<class... DBO> 10554struct 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`. 10557template<class... DBO> 10558struct 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*/ 10565template<typename DBO, typename Lookup> 10566struct object_type_matches : polyfill::conjunction<polyfill::negation<std::is_void<object_type_t<DBO>>>, 10567std::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*/ 10572template<typename DBO, typename Lookup> 10573using lookup_type_matches = object_type_matches<DBO, Lookup>; 10574} 10575 10576// pick/lookup metafunctions 10577namespace internal { 10578 10579/** 10580* Indirect enabler for DBO, accepting an index to disambiguate non-unique DBOs 10581*/ 10582template<class Lookup, size_t Ix, class DBO> 10583struct 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*/ 10592template<class Lookup, class Seq, class DBOs> 10593struct storage_pick_table; 10594 10595template<class Lookup, size_t... Ix, class... DBO> 10596struct 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*/ 10605template<class Lookup, class DBOs> 10606using storage_pick_table_t = typename storage_pick_table<Lookup, 10607std::make_index_sequence<std::tuple_size<DBOs>::value>, 10608std::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*/ 10617template<class Lookup, class DBOs> 10618struct 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*/ 10627template<class Lookup, class DBOs> 10628using storage_find_table_t = typename storage_find_table<Lookup, std::remove_const_t<DBOs>>::type; 10629 10630#ifndef SQLITE_ORM_BROKEN_VARIADIC_PACK_EXPANSION 10631template<class DBOs, class Lookup, class SFINAE = void> 10632struct is_mapped : std::false_type {}; 10633template<class DBOs, class Lookup> 10634struct is_mapped<DBOs, Lookup, polyfill::void_t<storage_pick_table_t<Lookup, DBOs>>> : std::true_type {}; 10635#else 10636template<class DBOs, class Lookup, class SFINAE = storage_find_table_t<Lookup, DBOs>> 10637struct is_mapped : std::true_type {}; 10638template<class DBOs, class Lookup> 10639struct is_mapped<DBOs, Lookup, polyfill::nonesuch> : std::false_type {}; 10640#endif 10641 10642template<class DBOs, class Lookup> 10643SQLITE_ORM_INLINE_VAR constexpr bool is_mapped_v = is_mapped<DBOs, Lookup>::value; 10644} 10645} 10646 10647// runtime lookup functions 10648namespace sqlite_orm { 10649namespace 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*/ 10655template<class Lookup, class DBOs, satisfies<is_mapped, DBOs, Lookup> = true> 10656auto& pick_table(DBOs& dbObjects) { 10657using table_type = storage_pick_table_t<Lookup, DBOs>; 10658return std::get<table_type>(dbObjects); 10659} 10660 10661/** 10662* Return passed in DBOs. 10663*/ 10664template<class DBOs, class E, satisfies<is_db_objects, DBOs> = true> 10665decltype(auto) db_objects_for_expression(DBOs& dbObjects, const E&) { 10666return dbObjects; 10667} 10668 10669template<class Lookup, class DBOs, satisfies<is_db_objects, DBOs> = true> 10670decltype(auto) lookup_table_name(const DBOs& dbObjects); 10671} 10672} 10673 10674// #include "schema/column.h" 10675 10676namespace sqlite_orm { 10677namespace internal { 10678 10679namespace storage_traits { 10680 10681/** 10682* DBO - db object (table) 10683*/ 10684template<class DBO> 10685struct storage_mapped_columns_impl 10686: tuple_transformer<filter_tuple_t<elements_type_t<DBO>, is_column>, field_type_t> {}; 10687 10688template<> 10689struct storage_mapped_columns_impl<polyfill::nonesuch> { 10690using type = std::tuple<>; 10691}; 10692 10693/** 10694* DBOs - db_objects_tuple type 10695* Lookup - mapped or unmapped data type 10696*/ 10697template<class DBOs, class Lookup> 10698struct storage_mapped_columns : storage_mapped_columns_impl<storage_find_table_t<Lookup, DBOs>> {}; 10699 10700/** 10701* DBO - db object (table) 10702*/ 10703template<class DBO> 10704struct storage_mapped_column_expressions_impl 10705: tuple_transformer<filter_tuple_t<elements_type_t<DBO>, is_column>, column_field_expression_t> {}; 10706 10707template<> 10708struct storage_mapped_column_expressions_impl<polyfill::nonesuch> { 10709using type = std::tuple<>; 10710}; 10711 10712/** 10713* DBOs - db_objects_tuple type 10714* Lookup - mapped or unmapped data type 10715*/ 10716template<class DBOs, class Lookup> 10717struct 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 10743namespace sqlite_orm { 10744namespace internal { 10745/* 10746* Define nested typenames: 10747* - return_type 10748* - arguments_tuple 10749* - signature_type 10750*/ 10751template<class F> 10752struct function_traits; 10753 10754/* 10755* A function's return type 10756*/ 10757template<class F> 10758using function_return_type_t = typename function_traits<F>::return_type; 10759 10760/* 10761* A function's arguments tuple 10762*/ 10763template<class F, 10764template<class...> class Tuple, 10765template<class...> class ProjectOp = polyfill::type_identity_t> 10766using function_arguments = typename function_traits<F>::template arguments_tuple<Tuple, ProjectOp>; 10767 10768/* 10769* A function's signature 10770*/ 10771template<class F> 10772using function_signature_type_t = typename function_traits<F>::signature_type; 10773 10774template<class R, class... Args> 10775struct function_traits<R(Args...)> { 10776using return_type = R; 10777 10778template<template<class...> class Tuple, template<class...> class ProjectOp> 10779using arguments_tuple = Tuple<mpl::invoke_fn_t<ProjectOp, Args>...>; 10780 10781using signature_type = R(Args...); 10782}; 10783 10784// non-exhaustive partial specializations of `function_traits` 10785 10786template<class R, class... Args> 10787struct function_traits<R(Args...) const> : function_traits<R(Args...)> { 10788using signature_type = R(Args...) const; 10789}; 10790 10791#ifdef SQLITE_ORM_NOTHROW_ALIASES_SUPPORTED 10792template<class R, class... Args> 10793struct function_traits<R(Args...) noexcept> : function_traits<R(Args...)> { 10794using signature_type = R(Args...) noexcept; 10795}; 10796 10797template<class R, class... Args> 10798struct function_traits<R(Args...) const noexcept> : function_traits<R(Args...)> { 10799using signature_type = R(Args...) const noexcept; 10800}; 10801#endif 10802 10803/* 10804* Pick signature of function pointer 10805*/ 10806template<class F> 10807struct function_traits<F(*)> : function_traits<F> {}; 10808 10809/* 10810* Pick signature of function reference 10811*/ 10812template<class F> 10813struct function_traits<F(&)> : function_traits<F> {}; 10814 10815/* 10816* Pick signature of pointer-to-member function 10817*/ 10818template<class F, class O> 10819struct function_traits<F O::*> : function_traits<F> {}; 10820} 10821} 10822 10823// #include "type_traits.h" 10824 10825// #include "tags.h" 10826 10827namespace sqlite_orm { 10828 10829struct arg_values; 10830 10831// note (internal): forward declare even if `SQLITE_VERSION_NUMBER < 3020000` in order to simplify coding below 10832template<class P, class T> 10833struct pointer_arg; 10834// note (internal): forward declare even if `SQLITE_VERSION_NUMBER < 3020000` in order to simplify coding below 10835template<class P, class T, class D> 10836class pointer_binding; 10837 10838namespace internal { 10839template<class F> 10840using scalar_call_function_t = decltype(&F::operator()); 10841 10842template<class F> 10843using aggregate_step_function_t = decltype(&F::step); 10844 10845template<class F> 10846using aggregate_fin_function_t = decltype(&F::fin); 10847 10848template<class F, class SFINAE = void> 10849SQLITE_ORM_INLINE_VAR constexpr bool is_scalar_udf_v = false; 10850template<class F> 10851SQLITE_ORM_INLINE_VAR constexpr bool is_scalar_udf_v<F, polyfill::void_t<scalar_call_function_t<F>>> = true; 10852 10853template<class F> 10854struct is_scalar_udf : polyfill::bool_constant<is_scalar_udf_v<F>> {}; 10855 10856template<class F, class SFINAE = void> 10857SQLITE_ORM_INLINE_VAR constexpr bool is_aggregate_udf_v = false; 10858template<class F> 10859SQLITE_ORM_INLINE_VAR constexpr bool is_aggregate_udf_v< 10860F, 10861polyfill::void_t<aggregate_step_function_t<F>, 10862aggregate_fin_function_t<F>, 10863std::enable_if_t<std::is_member_function_pointer<aggregate_step_function_t<F>>::value>, 10864std::enable_if_t<std::is_member_function_pointer<aggregate_fin_function_t<F>>::value>>> = 10865true; 10866 10867template<class F> 10868struct is_aggregate_udf : polyfill::bool_constant<is_aggregate_udf_v<F>> {}; 10869 10870template<class UDF> 10871struct 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*/ 10877template<class Sig> 10878concept 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*/ 10886template<class F> 10887concept 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*/ 10898template<class UDF> 10899concept orm_scalar_udf = requires { 10900UDF::name(); 10901typename 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*/ 10911template<class UDF> 10912concept orm_aggregate_udf = requires { 10913UDF::name(); 10914typename internal::aggregate_step_function_t<UDF>; 10915typename internal::aggregate_fin_function_t<UDF>; 10916requires std::is_member_function_pointer_v<internal::aggregate_step_function_t<UDF>>; 10917requires 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*/ 10922template<class F> 10923concept orm_scalar_function = (polyfill::is_specialization_of_v<std::remove_const_t<F>, internal::function> && 10924orm_scalar_udf<typename F::udf_type>); 10925 10926/** @short Specifies that a type is a framed user-defined aggregate function. 10927*/ 10928template<class F> 10929concept orm_aggregate_function = (polyfill::is_specialization_of_v<std::remove_const_t<F>, internal::function> && 10930orm_aggregate_udf<typename F::udf_type>); 10931 10932/** @short Specifies that a type is a framed and quoted user-defined scalar function. 10933*/ 10934template<class Q> 10935concept orm_quoted_scalar_function = requires(const Q& quotedF) { 10936quotedF.name(); 10937quotedF.callable(); 10938}; 10939#endif 10940 10941namespace internal { 10942template<class F, class SFINAE = void> 10943struct callable_arguments_impl; 10944 10945template<class F> 10946struct callable_arguments_impl<F, match_if<is_scalar_udf, F>> { 10947using args_tuple = function_arguments<scalar_call_function_t<F>, std::tuple, std::decay_t>; 10948using return_type = function_return_type_t<scalar_call_function_t<F>>; 10949}; 10950 10951template<class F> 10952struct callable_arguments_impl<F, match_if<is_aggregate_udf, F>> { 10953using args_tuple = function_arguments<aggregate_step_function_t<F>, std::tuple, std::decay_t>; 10954using return_type = function_return_type_t<aggregate_fin_function_t<F>>; 10955}; 10956 10957#ifdef SQLITE_ORM_WITH_CPP20_ALIASES 10958template<class F> 10959requires (std::is_function_v<F>) 10960struct callable_arguments_impl<F, void> { 10961using args_tuple = function_arguments<F, std::tuple, std::decay_t>; 10962using return_type = std::decay_t<function_return_type_t<F>>; 10963}; 10964#endif 10965 10966template<class F> 10967struct 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*/ 10973template<class UDF> 10974struct udf_holder : private std::string { 10975using udf_type = UDF; 10976 10977using std::string::basic_string; 10978 10979const std::string& operator()() const { 10980return *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*/ 10989template<class UDF> 10990requires (requires { UDF::name(); }) 10991struct udf_holder<UDF> 10992#else 10993/* 10994* Bundle of type and name of a traditional sqlite_orm user-defined function. 10995*/ 10996template<class UDF> 10997struct udf_holder 10998#endif 10999{ 11000using udf_type = UDF; 11001 11002template<class R = decltype(UDF::name()), 11003std::enable_if_t<polyfill::negation<std::is_same<R, char>>::value, bool> = true> 11004decltype(auto) operator()() const { 11005return UDF::name(); 11006} 11007 11008template<class R = decltype(UDF::name()), std::enable_if_t<std::is_same<R, char>::value, bool> = true> 11009std::string operator()() const { 11010return std::string{UDF::name()}; 11011} 11012}; 11013 11014/* 11015* Represents a call of a user-defined function. 11016*/ 11017template<class UDF, class... CallArgs> 11018struct function_call { 11019using udf_type = UDF; 11020using args_tuple = std::tuple<CallArgs...>; 11021 11022udf_holder<udf_type> name; 11023args_tuple callArgs; 11024}; 11025 11026template<class T> 11027SQLITE_ORM_INLINE_VAR constexpr bool 11028is_operator_argument_v<T, std::enable_if_t<polyfill::is_specialization_of<T, function_call>::value>> = true; 11029 11030template<class T> 11031struct unpacked_arg { 11032using type = T; 11033}; 11034template<class F, class... CallArgs> 11035struct unpacked_arg<function_call<F, CallArgs...>> { 11036using type = typename callable_arguments<F>::return_type; 11037}; 11038template<class T> 11039using unpacked_arg_t = typename unpacked_arg<T>::type; 11040 11041template<size_t I, class FnParam, class CallArg> 11042SQLITE_ORM_CONSTEVAL bool expected_pointer_value() { 11043static_assert(polyfill::always_false_v<FnParam, CallArg>, "Expected a pointer value for I-th argument"); 11044return false; 11045} 11046 11047template<size_t I, class FnParam, class CallArg, class EnableIfTag = void> 11048constexpr bool is_same_pvt_v = expected_pointer_value<I, FnParam, CallArg>(); 11049 11050// Always allow binding nullptr to a pointer argument 11051template<size_t I, class PointerArg> 11052constexpr 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 11054template<size_t I, class P, class T, class D> 11055constexpr bool is_same_pvt_v<I, pointer_arg<P, T>, pointer_binding<nullptr_t, T, D>, void> = true; 11056 11057template<size_t I, class PointerArgDataType, class BindingDataType> 11058SQLITE_ORM_CONSTEVAL bool assert_same_pointer_data_type() { 11059constexpr bool valid = std::is_convertible<BindingDataType*, PointerArgDataType*>::value; 11060static_assert(valid, "Pointer data types of I-th argument do not match"); 11061return valid; 11062} 11063 11064#if __cplusplus >= 201703L // C++17 or later 11065template<size_t I, const char* PointerArg, const char* Binding> 11066SQLITE_ORM_CONSTEVAL bool assert_same_pointer_tag() { 11067constexpr bool valid = Binding == PointerArg; 11068static_assert(valid, "Pointer types (tags) of I-th argument do not match"); 11069return valid; 11070} 11071template<size_t I, class PointerArg, class Binding> 11072constexpr bool 11073is_same_pvt_v<I, PointerArg, Binding, polyfill::void_t<typename PointerArg::tag, typename Binding::tag>> = 11074assert_same_pointer_tag<I, PointerArg::tag::value, Binding::tag::value>() && 11075assert_same_pointer_data_type<I, 11076typename PointerArg::qualified_type, 11077typename Binding::qualified_type>(); 11078#else 11079template<size_t I, class PointerArg, class Binding> 11080constexpr bool assert_same_pointer_tag() { 11081constexpr bool valid = Binding::value == PointerArg::value; 11082static_assert(valid, "Pointer types (tags) of I-th argument do not match"); 11083return valid; 11084} 11085 11086template<size_t I, class PointerArg, class Binding> 11087constexpr bool 11088is_same_pvt_v<I, PointerArg, Binding, polyfill::void_t<typename PointerArg::tag, typename Binding::tag>> = 11089assert_same_pointer_tag<I, typename PointerArg::tag, typename Binding::tag>(); 11090#endif 11091 11092// not a pointer value, currently leave it unchecked 11093template<size_t I, class FnParam, class CallArg> 11094SQLITE_ORM_CONSTEVAL bool validate_pointer_value_type(std::false_type) { 11095return true; 11096} 11097 11098// check the type of pointer values 11099template<size_t I, class FnParam, class CallArg> 11100SQLITE_ORM_CONSTEVAL bool validate_pointer_value_type(std::true_type) { 11101return is_same_pvt_v<I, FnParam, CallArg>; 11102} 11103 11104template<class FnParams, class CallArgs> 11105SQLITE_ORM_CONSTEVAL bool validate_pointer_value_types(polyfill::index_constant<size_t(-1)>) { 11106return true; 11107} 11108template<class FnParams, class CallArgs, size_t I> 11109SQLITE_ORM_CONSTEVAL bool validate_pointer_value_types(polyfill::index_constant<I>) { 11110using func_param_type = std::tuple_element_t<I, FnParams>; 11111using call_arg_type = unpacked_arg_t<std::tuple_element_t<I, CallArgs>>; 11112 11113#ifdef SQLITE_ORM_RELAXED_CONSTEXPR_SUPPORTED 11114constexpr bool valid = validate_pointer_value_type<I, 11115std::tuple_element_t<I, FnParams>, 11116unpacked_arg_t<std::tuple_element_t<I, CallArgs>>>( 11117polyfill::bool_constant < (polyfill::is_specialization_of_v<func_param_type, pointer_arg>) || 11118(polyfill::is_specialization_of_v<call_arg_type, pointer_binding>) > {}); 11119 11120return validate_pointer_value_types<FnParams, CallArgs>(polyfill::index_constant<I - 1>{}) && valid; 11121#else 11122return validate_pointer_value_types<FnParams, CallArgs>(polyfill::index_constant<I - 1>{}) && 11123validate_pointer_value_type<I, 11124std::tuple_element_t<I, FnParams>, 11125unpacked_arg_t<std::tuple_element_t<I, CallArgs>>>( 11126polyfill::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*/ 11135template<typename UDF, typename... CallArgs> 11136#ifdef SQLITE_ORM_RELAXED_CONSTEXPR_SUPPORTED 11137SQLITE_ORM_CONSTEVAL void check_function_call() { 11138#else 11139void check_function_call() { 11140#endif 11141using call_args_tuple = std::tuple<CallArgs...>; 11142using function_params_tuple = typename callable_arguments<UDF>::args_tuple; 11143constexpr size_t callArgsCount = std::tuple_size<call_args_tuple>::value; 11144constexpr size_t functionParamsCount = std::tuple_size<function_params_tuple>::value; 11145static_assert(std::is_same<function_params_tuple, std::tuple<arg_values>>::value || 11146(callArgsCount == functionParamsCount && 11147validate_pointer_value_types<function_params_tuple, call_args_tuple>( 11148polyfill::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*/ 11159template<class UDF> 11160struct function { 11161using udf_type = UDF; 11162using callable_type = UDF; 11163 11164/* 11165* Generates the SQL function call. 11166*/ 11167template<typename... CallArgs> 11168function_call<UDF, CallArgs...> operator()(CallArgs... callArgs) const { 11169check_function_call<UDF, CallArgs...>(); 11170return {this->udf_holder(), {std::forward<CallArgs>(callArgs)...}}; 11171} 11172 11173constexpr auto udf_holder() const { 11174return internal::udf_holder<UDF>{}; 11175} 11176 11177// returns a character range 11178constexpr auto name() const { 11179return 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*/ 11199template<class F, class Sig, size_t N> 11200struct quoted_scalar_function { 11201using udf_type = Sig; 11202using callable_type = F; 11203 11204/* 11205* Generates the SQL function call. 11206*/ 11207template<typename... CallArgs> 11208function_call<udf_type, CallArgs...> operator()(CallArgs... callArgs) const { 11209check_function_call<udf_type, CallArgs...>(); 11210return {this->udf_holder(), {std::forward<CallArgs>(callArgs)...}}; 11211} 11212 11213/* 11214* Return original `udf` if stateless or a copy of it otherwise 11215*/ 11216constexpr decltype(auto) callable() const { 11217if constexpr (stateless<F>) { 11218return (this->udf); 11219} else { 11220// non-const copy 11221return F(this->udf); 11222} 11223} 11224 11225constexpr auto udf_holder() const { 11226return internal::udf_holder<udf_type>{this->name()}; 11227} 11228 11229constexpr auto name() const { 11230return this->nme; 11231} 11232 11233template<class... Args> 11234consteval quoted_scalar_function(const char (&name)[N], Args&&... constructorArgs) : 11235udf(std::forward<Args>(constructorArgs)...) { 11236std::copy_n(name, N, this->nme); 11237} 11238 11239F udf; 11240char nme[N]; 11241}; 11242 11243template<size_t N> 11244struct quoted_function_builder : cstring_literal<N> { 11245using cstring_literal<N>::cstring_literal; 11246 11247/* 11248* From a freestanding function, possibly overloaded. 11249*/ 11250template<orm_function_sig F> 11251[[nodiscard]] consteval auto quote(F* callable) const { 11252return quoted_scalar_function<F*, F, N>{this->cstr, std::move(callable)}; 11253} 11254 11255/* 11256* From a classic function object instance. 11257*/ 11258template<class F> 11259requires (orm_classic_function_object<F> && (stateless<F> || std::copy_constructible<F>)) 11260[[nodiscard]] consteval auto quote(F callable) const { 11261using Sig = function_signature_type_t<decltype(&F::operator())>; 11262// detect whether overloaded call operator can be picked using `Sig` 11263using call_operator_type = decltype(static_cast<Sig F::*>(&F::operator())); 11264return 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*/ 11270template<orm_function_sig Sig, class F> 11271requires ((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` 11274using call_operator_type = decltype(static_cast<Sig F::*>(&F::operator())); 11275return quoted_scalar_function<F, Sig, N>{this->cstr, std::move(callable)}; 11276} 11277 11278/* 11279* From a classic function object type. 11280*/ 11281template<orm_classic_function_object F, class... Args> 11282requires (stateless<F> || std::copy_constructible<F>) 11283[[nodiscard]] consteval auto quote(Args&&... constructorArgs) const { 11284using Sig = function_signature_type_t<decltype(&F::operator())>; 11285return 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*/ 11291template<orm_function_sig Sig, class F, class... Args> 11292requires ((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` 11295using call_operator_type = decltype(static_cast<Sig F::*>(&F::operator())); 11296return 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*/ 11316template<class UDF> 11317#ifdef SQLITE_ORM_WITH_CPP20_ALIASES 11318requires (orm_scalar_udf<UDF> || orm_aggregate_udf<UDF>) 11319#endif 11320SQLITE_ORM_INLINE_VAR constexpr internal::function<UDF> func{}; 11321 11322#ifdef SQLITE_ORM_WITH_CPP20_ALIASES 11323inline 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*/ 11356template<internal::quoted_function_builder builder> 11357[[nodiscard]] consteval auto operator"" _scalar() { 11358return builder; 11359} 11360} 11361#endif 11362} 11363 11364// #include "ast/special_keywords.h" 11365 11366namespace sqlite_orm { 11367namespace internal { 11368struct current_time_t {}; 11369struct current_date_t {}; 11370struct current_timestamp_t {}; 11371} 11372 11373inline internal::current_time_t current_time() { 11374return {}; 11375} 11376 11377inline internal::current_date_t current_date() { 11378return {}; 11379} 11380 11381inline internal::current_timestamp_t current_timestamp() { 11382return {}; 11383} 11384} 11385 11386namespace sqlite_orm { 11387 11388namespace 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*/ 11402template<class DBOs, class T, class SFINAE = void> 11403struct column_result_t { 11404#ifdef __FUNCTION__ 11405// produce an error message that reveals `T` and `DBOs` 11406static constexpr bool reveal() { 11407static_assert(polyfill::always_false_v<T>, "T not found in DBOs - " __FUNCTION__); 11408} 11409static constexpr bool trigger = reveal(); 11410#endif 11411}; 11412 11413template<class DBOs, class T> 11414using column_result_of_t = typename column_result_t<DBOs, T>::type; 11415 11416template<class DBOs, class Tpl> 11417using column_result_for_tuple_t = 11418transform_tuple_t<Tpl, mpl::bind_front_fn<column_result_of_t, DBOs>::template fn>; 11419 11420#ifdef SQLITE_ORM_OPTIONAL_SUPPORTED 11421template<class DBOs, class T> 11422struct column_result_t<DBOs, as_optional_t<T>, void> { 11423using type = std::optional<column_result_of_t<DBOs, T>>; 11424}; 11425 11426template<class DBOs, class T> 11427struct column_result_t<DBOs, std::optional<T>, void> { 11428using type = std::optional<T>; 11429}; 11430#endif // SQLITE_ORM_OPTIONAL_SUPPORTED 11431 11432template<class DBOs, class L, class A> 11433struct column_result_t<DBOs, dynamic_in_t<L, A>, void> { 11434using type = bool; 11435}; 11436 11437template<class DBOs, class L, class... Args> 11438struct column_result_t<DBOs, in_t<L, Args...>, void> { 11439using type = bool; 11440}; 11441 11442template<class DBOs> 11443struct column_result_t<DBOs, current_time_t, void> { 11444using type = std::string; 11445}; 11446 11447template<class DBOs> 11448struct column_result_t<DBOs, current_date_t, void> { 11449using type = std::string; 11450}; 11451 11452template<class DBOs> 11453struct column_result_t<DBOs, current_timestamp_t, void> { 11454using type = std::string; 11455}; 11456 11457template<class DBOs, class T> 11458struct column_result_t<DBOs, T, match_if<std::is_member_pointer, T>> : member_field_type<T> {}; 11459 11460template<class DBOs, class R, class S, class... Args> 11461struct column_result_t<DBOs, built_in_function_t<R, S, Args...>, void> { 11462using type = R; 11463}; 11464 11465template<class DBOs, class R, class S, class... Args> 11466struct column_result_t<DBOs, built_in_aggregate_function_t<R, S, Args...>, void> { 11467using type = R; 11468}; 11469 11470template<class DBOs, class F, class... Args> 11471struct column_result_t<DBOs, function_call<F, Args...>, void> { 11472using type = typename callable_arguments<F>::return_type; 11473}; 11474 11475template<class DBOs, class X, class... Rest, class S> 11476struct column_result_t<DBOs, built_in_function_t<unique_ptr_result_of<X>, S, X, Rest...>, void> { 11477using type = std::unique_ptr<column_result_of_t<DBOs, X>>; 11478}; 11479 11480template<class DBOs, class X, class S> 11481struct column_result_t<DBOs, built_in_aggregate_function_t<unique_ptr_result_of<X>, S, X>, void> { 11482using type = std::unique_ptr<column_result_of_t<DBOs, X>>; 11483}; 11484 11485template<class DBOs, class T> 11486struct column_result_t<DBOs, count_asterisk_t<T>, void> { 11487using type = int; 11488}; 11489 11490template<class DBOs> 11491struct column_result_t<DBOs, nullptr_t, void> { 11492using type = nullptr_t; 11493}; 11494 11495template<class DBOs> 11496struct column_result_t<DBOs, count_asterisk_without_type, void> { 11497using type = int; 11498}; 11499 11500template<class DBOs, class T> 11501struct column_result_t<DBOs, distinct_t<T>, void> : column_result_t<DBOs, T> {}; 11502 11503template<class DBOs, class T> 11504struct column_result_t<DBOs, all_t<T>, void> : column_result_t<DBOs, T> {}; 11505 11506template<class DBOs, class L, class R> 11507struct column_result_t<DBOs, conc_t<L, R>, void> { 11508using type = std::string; 11509}; 11510 11511template<class DBOs, class T> 11512struct column_result_t<DBOs, unary_minus_t<T>, void> { 11513using type = double; 11514}; 11515 11516template<class DBOs, class L, class R> 11517struct column_result_t<DBOs, add_t<L, R>, void> { 11518using type = double; 11519}; 11520 11521template<class DBOs, class L, class R> 11522struct column_result_t<DBOs, sub_t<L, R>, void> { 11523using type = double; 11524}; 11525 11526template<class DBOs, class L, class R> 11527struct column_result_t<DBOs, mul_t<L, R>, void> { 11528using type = double; 11529}; 11530 11531template<class DBOs, class L, class R> 11532struct column_result_t<DBOs, div_t<L, R>, void> { 11533using type = double; 11534}; 11535 11536template<class DBOs, class L, class R> 11537struct column_result_t<DBOs, mod_t<L, R>, void> { 11538using type = double; 11539}; 11540 11541template<class DBOs, class L, class R> 11542struct column_result_t<DBOs, bitwise_shift_left_t<L, R>, void> { 11543using type = int; 11544}; 11545 11546template<class DBOs, class L, class R> 11547struct column_result_t<DBOs, bitwise_shift_right_t<L, R>, void> { 11548using type = int; 11549}; 11550 11551template<class DBOs, class L, class R> 11552struct column_result_t<DBOs, bitwise_and_t<L, R>, void> { 11553using type = int; 11554}; 11555 11556template<class DBOs, class L, class R> 11557struct column_result_t<DBOs, bitwise_or_t<L, R>, void> { 11558using type = int; 11559}; 11560 11561template<class DBOs, class T> 11562struct column_result_t<DBOs, bitwise_not_t<T>, void> { 11563using type = int; 11564}; 11565 11566template<class DBOs> 11567struct column_result_t<DBOs, rowid_t, void> { 11568using type = int64; 11569}; 11570 11571template<class DBOs> 11572struct column_result_t<DBOs, oid_t, void> { 11573using type = int64; 11574}; 11575 11576template<class DBOs> 11577struct column_result_t<DBOs, _rowid_t, void> { 11578using type = int64; 11579}; 11580 11581template<class DBOs, class T> 11582struct column_result_t<DBOs, table_rowid_t<T>, void> { 11583using type = int64; 11584}; 11585 11586template<class DBOs, class T> 11587struct column_result_t<DBOs, table_oid_t<T>, void> { 11588using type = int64; 11589}; 11590 11591template<class DBOs, class T> 11592struct column_result_t<DBOs, table__rowid_t<T>, void> { 11593using type = int64; 11594}; 11595 11596template<class DBOs, class T, class C> 11597struct column_result_t<DBOs, alias_column_t<T, C>, void> : column_result_t<DBOs, C> {}; 11598 11599template<class DBOs, class T, class F> 11600struct 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) 11603template<class DBOs, class Moniker, class ColAlias> 11604struct column_result_t<DBOs, column_pointer<Moniker, alias_holder<ColAlias>>, void> { 11605using table_type = storage_pick_table_t<Moniker, DBOs>; 11606using cte_mapper_type = cte_mapper_type_t<table_type>; 11607 11608// lookup ColAlias in the final column references 11609using colalias_index = 11610find_tuple_type<typename cte_mapper_type::final_colrefs_tuple, alias_holder<ColAlias>>; 11611static_assert(colalias_index::value < std::tuple_size_v<typename cte_mapper_type::final_colrefs_tuple>, 11612"No such column mapped into the CTE."); 11613using type = std::tuple_element_t<colalias_index::value, typename cte_mapper_type::fields_type>; 11614}; 11615#endif 11616 11617template<class DBOs, class... Args> 11618struct column_result_t<DBOs, columns_t<Args...>, void> 11619: conc_tuple<tuplify_t<column_result_of_t<DBOs, std::decay_t<Args>>>...> {}; 11620 11621template<class DBOs, class T, class... Args> 11622struct column_result_t<DBOs, struct_t<T, Args...>, void> { 11623using type = structure<T, tuple_cat_t<tuplify_t<column_result_of_t<DBOs, std::decay_t<Args>>>...>>; 11624}; 11625 11626template<class DBOs, class T, class... Args> 11627struct column_result_t<DBOs, select_t<T, Args...>> : column_result_t<DBOs, T> {}; 11628 11629template<class DBOs, class T> 11630struct column_result_t<DBOs, T, match_if<is_compound_operator, T>> { 11631using type = 11632polyfill::detected_t<common_type_of_t, column_result_for_tuple_t<DBOs, typename T::expressions_tuple>>; 11633static_assert(!std::is_same<type, polyfill::nonesuch>::value, 11634"Compound select statements must return a common type"); 11635}; 11636 11637template<class DBOs, class T> 11638struct column_result_t<DBOs, T, match_if<is_binary_condition, T>> { 11639using type = typename T::result_type; 11640}; 11641 11642template<class DBOs, class T, class X, class Y, class Z> 11643struct column_result_t<DBOs, highlight_t<T, X, Y, Z>, void> { 11644using type = std::string; 11645}; 11646 11647/** 11648* Result for the most simple queries like `SELECT 1` 11649*/ 11650template<class DBOs, class T> 11651struct column_result_t<DBOs, T, match_if<std::is_arithmetic, T>> { 11652using type = T; 11653}; 11654 11655/** 11656* Result for the most simple queries like `SELECT 'ototo'` 11657*/ 11658template<class DBOs> 11659struct column_result_t<DBOs, const char*, void> { 11660using type = std::string; 11661}; 11662 11663template<class DBOs> 11664struct column_result_t<DBOs, std::string, void> { 11665using type = std::string; 11666}; 11667 11668template<class DBOs, class T, class E> 11669struct column_result_t<DBOs, as_t<T, E>, void> : column_result_t<DBOs, std::decay_t<E>> {}; 11670 11671template<class DBOs, class T> 11672struct column_result_t<DBOs, asterisk_t<T>, void> 11673: storage_traits::storage_mapped_columns<DBOs, mapped_type_proxy_t<T>> {}; 11674 11675template<class DBOs, class T> 11676struct column_result_t<DBOs, object_t<T>, void> { 11677using type = table_reference<T>; 11678}; 11679 11680template<class DBOs, class T, class E> 11681struct column_result_t<DBOs, cast_t<T, E>, void> { 11682using type = T; 11683}; 11684 11685template<class DBOs, class R, class T, class E, class... Args> 11686struct column_result_t<DBOs, simple_case_t<R, T, E, Args...>, void> { 11687using type = R; 11688}; 11689 11690template<class DBOs, class A, class T, class E> 11691struct column_result_t<DBOs, like_t<A, T, E>, void> { 11692using type = bool; 11693}; 11694 11695template<class DBOs, class A, class T> 11696struct column_result_t<DBOs, glob_t<A, T>, void> { 11697using type = bool; 11698}; 11699 11700template<class DBOs, class C> 11701struct column_result_t<DBOs, negated_condition_t<C>, void> { 11702using type = bool; 11703}; 11704 11705template<class DBOs, class T> 11706struct 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 11716namespace sqlite_orm { 11717 11718enum class sync_schema_result { 11719 11720/** 11721* created new table, table with the same tablename did not exist 11722*/ 11723new_table_created, 11724 11725/** 11726* table schema is the same as storage, nothing to be done 11727*/ 11728already_in_sync, 11729 11730/** 11731* removed excess columns in table (than storage) without dropping a table 11732*/ 11733old_columns_removed, 11734 11735/** 11736* lacking columns in table (than storage) added without dropping a table 11737*/ 11738new_columns_added, 11739 11740/** 11741* both old_columns_removed and new_columns_added 11742*/ 11743new_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*/ 11752dropped_and_recreated, 11753}; 11754 11755inline std::ostream& operator<<(std::ostream& os, sync_schema_result value) { 11756switch (value) { 11757case sync_schema_result::new_table_created: 11758return os << "new table created"; 11759case sync_schema_result::already_in_sync: 11760return os << "table and storage is already in sync."; 11761case sync_schema_result::old_columns_removed: 11762return os << "old excess columns removed"; 11763case sync_schema_result::new_columns_added: 11764return os << "new columns added"; 11765case sync_schema_result::new_columns_added_and_old_columns_removed: 11766return os << "old excess columns removed and new columns added"; 11767case sync_schema_result::dropped_and_recreated: 11768return os << "old table dropped and recreated"; 11769} 11770return os; 11771} 11772} 11773 11774// #include "table_info.h" 11775 11776#include <string> // std::string 11777 11778namespace sqlite_orm { 11779 11780struct table_info { 11781int cid = 0; 11782std::string name; 11783std::string type; 11784bool notnull = false; 11785std::string dflt_value; 11786int pk = 0; 11787 11788#if !defined(SQLITE_ORM_AGGREGATE_NSDMI_SUPPORTED) || !defined(SQLITE_ORM_AGGREGATE_PAREN_INIT_SUPPORTED) 11789table_info(decltype(cid) cid_, 11790decltype(name) name_, 11791decltype(type) type_, 11792decltype(notnull) notnull_, 11793decltype(dflt_value) dflt_value_, 11794decltype(pk) pk_) : 11795cid(cid_), name(std::move(name_)), type(std::move(type_)), notnull(notnull_), 11796dflt_value(std::move(dflt_value_)), pk(pk_) {} 11797#endif 11798}; 11799 11800struct table_xinfo { 11801int cid = 0; 11802std::string name; 11803std::string type; 11804bool notnull = false; 11805std::string dflt_value; 11806int pk = 0; 11807int 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) 11810table_xinfo(decltype(cid) cid_, 11811decltype(name) name_, 11812decltype(type) type_, 11813decltype(notnull) notnull_, 11814decltype(dflt_value) dflt_value_, 11815decltype(pk) pk_, 11816decltype(hidden) hidden_) : 11817cid(cid_), name(std::move(name_)), type(std::move(type_)), notnull(notnull_), 11818dflt_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 11875namespace sqlite_orm { 11876 11877namespace internal { 11878 11879template<class L, class R> 11880bool compare_any(const L& /*lhs*/, const R& /*rhs*/) { 11881return false; 11882} 11883template<class O> 11884bool compare_any(const O& lhs, const O& rhs) { 11885return 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 11913namespace sqlite_orm { 11914 11915namespace internal { 11916 11917template<class C> 11918struct indexed_column_t { 11919using column_type = C; 11920 11921#ifndef SQLITE_ORM_AGGREGATE_NSDMI_SUPPORTED 11922indexed_column_t(column_type _column_or_expression) : 11923column_or_expression(std::move(_column_or_expression)) {} 11924#endif 11925 11926column_type column_or_expression; 11927std::string _collation_name; 11928int _order = 0; // -1 = desc, 1 = asc, 0 = not specified 11929 11930indexed_column_t<column_type> collate(std::string name) { 11931auto res = std::move(*this); 11932res._collation_name = std::move(name); 11933return res; 11934} 11935 11936indexed_column_t<column_type> asc() { 11937auto res = std::move(*this); 11938res._order = 1; 11939return res; 11940} 11941 11942indexed_column_t<column_type> desc() { 11943auto res = std::move(*this); 11944res._order = -1; 11945return res; 11946} 11947}; 11948 11949template<class C> 11950indexed_column_t<C> make_indexed_column(C col) { 11951return {std::move(col)}; 11952} 11953 11954template<class C> 11955where_t<C> make_indexed_column(where_t<C> wher) { 11956return std::move(wher); 11957} 11958 11959template<class C> 11960indexed_column_t<C> make_indexed_column(indexed_column_t<C> col) { 11961return 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*/ 11969template<class C> 11970internal::indexed_column_t<C> indexed_column(C column_or_expression) { 11971return {std::move(column_or_expression)}; 11972} 11973} 11974 11975// #include "../table_type_of.h" 11976 11977namespace sqlite_orm { 11978 11979namespace internal { 11980 11981struct index_base { 11982std::string name; 11983bool unique = false; 11984 11985#ifndef SQLITE_ORM_AGGREGATE_NSDMI_SUPPORTED 11986index_base(std::string name, bool unique) : name{std::move(name)}, unique{unique} {} 11987#endif 11988}; 11989 11990template<class T, class... Els> 11991struct index_t : index_base { 11992using elements_type = std::tuple<Els...>; 11993using object_type = void; 11994using table_mapped_type = T; 11995 11996#ifndef SQLITE_ORM_AGGREGATE_BASES_SUPPORTED 11997index_t(std::string name_, bool unique_, elements_type elements_) : 11998index_base{std::move(name_), unique_}, elements(std::move(elements_)) {} 11999#endif 12000 12001elements_type elements; 12002}; 12003} 12004 12005template<class T, class... Cols> 12006internal::index_t<T, decltype(internal::make_indexed_column(std::declval<Cols>()))...> make_index(std::string name, 12007Cols... cols) { 12008using cols_tuple = std::tuple<Cols...>; 12009static_assert(internal::count_tuple<cols_tuple, internal::is_where>::value <= 1, 12010"amount of where arguments can be 0 or 1"); 12011SQLITE_ORM_CLANG_SUPPRESS_MISSING_BRACES( 12012return {std::move(name), false, std::make_tuple(internal::make_indexed_column(std::move(cols))...)}); 12013} 12014 12015template<class... Cols> 12016internal::index_t<internal::table_type_of_t<typename std::tuple_element_t<0, std::tuple<Cols...>>>, 12017decltype(internal::make_indexed_column(std::declval<Cols>()))...> 12018make_index(std::string name, Cols... cols) { 12019using cols_tuple = std::tuple<Cols...>; 12020static_assert(internal::count_tuple<cols_tuple, internal::is_where>::value <= 1, 12021"amount of where arguments can be 0 or 1"); 12022SQLITE_ORM_CLANG_SUPPRESS_MISSING_BRACES( 12023return {std::move(name), false, std::make_tuple(internal::make_indexed_column(std::move(cols))...)}); 12024} 12025 12026template<class... Cols> 12027internal::index_t<internal::table_type_of_t<typename std::tuple_element_t<0, std::tuple<Cols...>>>, 12028decltype(internal::make_indexed_column(std::declval<Cols>()))...> 12029make_unique_index(std::string name, Cols... cols) { 12030using cols_tuple = std::tuple<Cols...>; 12031static_assert(internal::count_tuple<cols_tuple, internal::is_where>::value <= 1, 12032"amount of where arguments can be 0 or 1"); 12033SQLITE_ORM_CLANG_SUPPRESS_MISSING_BRACES( 12034return {std::move(name), true, std::make_tuple(internal::make_indexed_column(std::move(cols))...)}); 12035} 12036} 12037 12038// #include "column.h" 12039 12040namespace sqlite_orm { 12041 12042namespace internal { 12043 12044template<class T> 12045using is_table_element_or_constraint = mpl::invoke_t<mpl::disjunction<check_if<is_column>, 12046check_if<is_primary_key>, 12047check_if<is_foreign_key>, 12048check_if_is_template<index_t>, 12049check_if_is_template<unique_t>, 12050check_if_is_template<check_t>, 12051check_if_is_template<prefix_t>, 12052check_if_is_template<tokenize_t>, 12053check_if_is_template<content_t>, 12054check_if_is_template<table_content_t>>, 12055T>; 12056 12057#if (SQLITE_VERSION_NUMBER >= 3008003) && defined(SQLITE_ORM_WITH_CTE) 12058/** 12059* A subselect mapper's CTE moniker, void otherwise. 12060*/ 12061template<typename O> 12062using 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*/ 12068template<typename O> 12069using mapped_object_type_for_t = polyfill::detected_or_t<O, cte_moniker_type_t, O>; 12070#endif 12071 12072struct basic_table { 12073 12074/** 12075* Table name. 12076*/ 12077std::string name; 12078}; 12079 12080/** 12081* Table definition. 12082*/ 12083template<class O, bool WithoutRowId, class... Cs> 12084struct 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 12088using cte_mapper_type = O; 12089using cte_moniker_type = moniker_of_or_void_t<O>; 12090using object_type = mapped_object_type_for_t<O>; 12091#else 12092using object_type = O; 12093#endif 12094using elements_type = std::tuple<Cs...>; 12095 12096static constexpr bool is_without_rowid_v = WithoutRowId; 12097 12098using is_without_rowid = polyfill::bool_constant<is_without_rowid_v>; 12099 12100elements_type elements; 12101 12102#ifndef SQLITE_ORM_AGGREGATE_BASES_SUPPORTED 12103table_t(std::string name_, elements_type elements_) : 12104basic_table{std::move(name_)}, elements{std::move(elements_)} {} 12105#endif 12106 12107table_t<O, true, Cs...> without_rowid() const { 12108return {this->name, this->elements}; 12109} 12110 12111/* 12112* Returns the number of elements of the specified type. 12113*/ 12114template<template<class...> class Trait> 12115static constexpr int count_of() { 12116using sequence_of = filter_tuple_sequence_t<elements_type, Trait>; 12117return int(sequence_of::size()); 12118} 12119 12120/* 12121* Returns the number of columns having the specified constraint trait. 12122*/ 12123template<template<class...> class Trait> 12124static constexpr int count_of_columns_with() { 12125using filtered_index_sequence = col_index_sequence_with<elements_type, Trait>; 12126return int(filtered_index_sequence::size()); 12127} 12128 12129/* 12130* Returns the number of columns having the specified constraint trait. 12131*/ 12132template<template<class...> class Trait> 12133static constexpr int count_of_columns_excluding() { 12134using excluded_col_index_sequence = col_index_sequence_excluding<elements_type, Trait>; 12135return 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*/ 12145template<class M, satisfies_not<is_setter, M> = true> 12146decltype(auto) object_field_value(const object_type& object, M memberPointer) const { 12147return polyfill::invoke(memberPointer, object); 12148} 12149 12150template<class M, satisfies<is_setter, M> = true> 12151const member_field_type_t<M>* object_field_value(const object_type& object, M memberPointer) const { 12152using field_type = member_field_type_t<M>; 12153const field_type* res = nullptr; 12154iterate_tuple(this->elements, 12155col_index_sequence_with_field_type<elements_type, field_type>{}, 12156call_as_template_base<column_field>([&res, &memberPointer, &object](const auto& column) { 12157if (compare_any(column.setter, memberPointer)) { 12158res = &polyfill::invoke(column.member_pointer, object); 12159} 12160})); 12161return res; 12162} 12163 12164const basic_generated_always::storage_type* 12165find_column_generated_storage_type(const std::string& name) const { 12166const basic_generated_always::storage_type* result = nullptr; 12167#if SQLITE_VERSION_NUMBER >= 3031000 12168iterate_tuple(this->elements, 12169col_index_sequence_with<elements_type, is_generated_always>{}, 12170[&result, &name](auto& column) { 12171if (column.name != name) { 12172return; 12173} 12174using generated_op_index_sequence = 12175filter_tuple_sequence_t<std::remove_const_t<decltype(column.constraints)>, 12176is_generated_always>; 12177constexpr size_t opIndex = index_sequence_value_at<0>(generated_op_index_sequence{}); 12178result = &std::get<opIndex>(column.constraints).storage; 12179}); 12180#else 12181(void)name; 12182#endif 12183return result; 12184} 12185 12186/** 12187* Call passed lambda with all defined primary keys. 12188*/ 12189template<class L> 12190void for_each_primary_key(L&& lambda) const { 12191using pk_index_sequence = filter_tuple_sequence_t<elements_type, is_primary_key>; 12192iterate_tuple(this->elements, pk_index_sequence{}, lambda); 12193} 12194 12195std::vector<std::string> composite_key_columns_names() const { 12196std::vector<std::string> res; 12197this->for_each_primary_key([this, &res](auto& primaryKey) { 12198res = this->composite_key_columns_names(primaryKey); 12199}); 12200return res; 12201} 12202 12203std::vector<std::string> primary_key_column_names() const { 12204using pkcol_index_sequence = col_index_sequence_with<elements_type, is_primary_key>; 12205 12206if (pkcol_index_sequence::size() > 0) { 12207return create_from_tuple<std::vector<std::string>>(this->elements, 12208pkcol_index_sequence{}, 12209&column_identifier::name); 12210} else { 12211return this->composite_key_columns_names(); 12212} 12213} 12214 12215template<class L> 12216void for_each_primary_key_column(L&& lambda) const { 12217iterate_tuple(this->elements, 12218col_index_sequence_with<elements_type, is_primary_key>{}, 12219call_as_template_base<column_field>([&lambda](const auto& column) { 12220lambda(column.member_pointer); 12221})); 12222this->for_each_primary_key([&lambda](auto& primaryKey) { 12223iterate_tuple(primaryKey.columns, lambda); 12224}); 12225} 12226 12227template<class... Args> 12228std::vector<std::string> composite_key_columns_names(const primary_key_t<Args...>& primaryKey) const { 12229return create_from_tuple<std::vector<std::string>>(primaryKey.columns, 12230[this, empty = std::string{}](auto& memberPointer) { 12231if (const std::string* columnName = 12232this->find_column_name(memberPointer)) { 12233return *columnName; 12234} else { 12235return 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*/ 12244template<class M, satisfies<std::is_member_pointer, M> = true> 12245const std::string* find_column_name(M m) const { 12246const std::string* res = nullptr; 12247using field_type = member_field_type_t<M>; 12248iterate_tuple(this->elements, 12249col_index_sequence_with_field_type<elements_type, field_type>{}, 12250[&res, m](auto& c) { 12251if (compare_any(c.member_pointer, m) || compare_any(c.setter, m)) { 12252res = &c.name; 12253} 12254}); 12255return 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*/ 12262template<class L> 12263void for_each_foreign_key(L&& lambda) const { 12264using fk_index_sequence = filter_tuple_sequence_t<elements_type, is_foreign_key>; 12265iterate_tuple(this->elements, fk_index_sequence{}, lambda); 12266} 12267 12268template<class Target, class L> 12269void for_each_foreign_key_to(L&& lambda) const { 12270using fk_index_sequence = filter_tuple_sequence_t<elements_type, is_foreign_key>; 12271using filtered_index_sequence = filter_tuple_sequence_t<elements_type, 12272check_if_is_type<Target>::template fn, 12273target_type_t, 12274fk_index_sequence>; 12275iterate_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*/ 12282template<class L> 12283void for_each_column(L&& lambda) const { 12284using col_index_sequence = filter_tuple_sequence_t<elements_type, is_column>; 12285iterate_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*/ 12292template<template<class...> class OpTraitFn, class L> 12293void for_each_column_excluding(L&& lambda) const { 12294iterate_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*/ 12301template<class OpTraitQ, class L, satisfies<mpl::is_quoted_metafuntion, OpTraitQ> = true> 12302void for_each_column_excluding(L&& lambda) const { 12303this->template for_each_column_excluding<OpTraitQ::template fn>(lambda); 12304} 12305 12306std::vector<table_xinfo> get_table_info() const; 12307}; 12308 12309template<class T> 12310struct is_table : std::false_type {}; 12311 12312template<class O, bool W, class... Cs> 12313struct is_table<table_t<O, W, Cs...>> : std::true_type {}; 12314 12315template<class M> 12316struct virtual_table_t : basic_table { 12317using module_details_type = M; 12318using object_type = typename module_details_type::object_type; 12319using elements_type = typename module_details_type::columns_type; 12320 12321static constexpr bool is_without_rowid_v = false; 12322using is_without_rowid = polyfill::bool_constant<is_without_rowid_v>; 12323 12324module_details_type module_details; 12325 12326#ifndef SQLITE_ORM_AGGREGATE_BASES_SUPPORTED 12327virtual_table_t(std::string name, module_details_type module_details) : 12328basic_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*/ 12335template<template<class...> class OpTraitFn, class L> 12336void for_each_column_excluding(L&& lambda) const { 12337this->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*/ 12344template<class OpTraitQ, class L, satisfies<mpl::is_quoted_metafuntion, OpTraitQ> = true> 12345void for_each_column_excluding(L&& lambda) const { 12346this->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*/ 12353template<class L> 12354void for_each_column(L&& lambda) const { 12355this->module_details.for_each_column(lambda); 12356} 12357}; 12358 12359template<class T> 12360struct is_virtual_table : std::false_type {}; 12361 12362template<class M> 12363struct is_virtual_table<virtual_table_t<M>> : std::true_type {}; 12364 12365#if SQLITE_VERSION_NUMBER >= 3009000 12366template<class T, class... Cs> 12367struct using_fts5_t { 12368using object_type = T; 12369using columns_type = std::tuple<Cs...>; 12370 12371columns_type columns; 12372 12373using_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*/ 12379template<template<class...> class OpTraitFn, class L> 12380void for_each_column_excluding(L&& lambda) const { 12381iterate_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*/ 12388template<class OpTraitQ, class L, satisfies<mpl::is_quoted_metafuntion, OpTraitQ> = true> 12389void for_each_column_excluding(L&& lambda) const { 12390this->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*/ 12397template<class L> 12398void for_each_column(L&& lambda) const { 12399using col_index_sequence = filter_tuple_sequence_t<columns_type, is_column>; 12400iterate_tuple(this->columns, col_index_sequence{}, lambda); 12401} 12402}; 12403#endif 12404 12405template<class O, bool WithoutRowId, class... Cs, class G, class S> 12406bool exists_in_composite_primary_key(const table_t<O, WithoutRowId, Cs...>& table, 12407const column_field<G, S>& column) { 12408bool res = false; 12409table.for_each_primary_key([&column, &res](auto& primaryKey) { 12410using colrefs_tuple = decltype(primaryKey.columns); 12411using same_type_index_sequence = 12412filter_tuple_sequence_t<colrefs_tuple, 12413check_if_is_type<member_field_type_t<G>>::template fn, 12414member_field_type_t>; 12415iterate_tuple(primaryKey.columns, same_type_index_sequence{}, [&res, &column](auto& memberPointer) { 12416if (compare_any(memberPointer, column.member_pointer) || 12417compare_any(memberPointer, column.setter)) { 12418res = true; 12419} 12420}); 12421}); 12422return res; 12423} 12424 12425template<class M, class G, class S> 12426bool exists_in_composite_primary_key(const virtual_table_t<M>& /*virtualTable*/, 12427const column_field<G, S>& /*column*/) { 12428return false; 12429} 12430} 12431 12432#if SQLITE_VERSION_NUMBER >= 3009000 12433template<class... Cs, class T = typename std::tuple_element_t<0, std::tuple<Cs...>>::object_type> 12434internal::using_fts5_t<T, Cs...> using_fts5(Cs... columns) { 12435static_assert(polyfill::conjunction_v<internal::is_table_element_or_constraint<Cs>...>, 12436"Incorrect table elements or constraints"); 12437 12438SQLITE_ORM_CLANG_SUPPRESS_MISSING_BRACES(return {std::make_tuple(std::forward<Cs>(columns)...)}); 12439} 12440 12441template<class T, class... Cs> 12442internal::using_fts5_t<T, Cs...> using_fts5(Cs... columns) { 12443static_assert(polyfill::conjunction_v<internal::is_table_element_or_constraint<Cs>...>, 12444"Incorrect table elements or constraints"); 12445 12446SQLITE_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*/ 12455template<class... Cs, class T = typename std::tuple_element_t<0, std::tuple<Cs...>>::object_type> 12456internal::table_t<T, false, Cs...> make_table(std::string name, Cs... args) { 12457static_assert(polyfill::conjunction_v<internal::is_table_element_or_constraint<Cs>...>, 12458"Incorrect table elements or constraints"); 12459 12460SQLITE_ORM_CLANG_SUPPRESS_MISSING_BRACES( 12461return {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*/ 12469template<class T, class... Cs> 12470internal::table_t<T, false, Cs...> make_table(std::string name, Cs... args) { 12471static_assert(polyfill::conjunction_v<internal::is_table_element_or_constraint<Cs>...>, 12472"Incorrect table elements or constraints"); 12473 12474SQLITE_ORM_CLANG_SUPPRESS_MISSING_BRACES( 12475return {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*/ 12484template<orm_table_reference auto table, class... Cs> 12485auto make_table(std::string name, Cs... args) { 12486return make_table<internal::auto_decay_table_ref_t<table>>(std::move(name), std::forward<Cs>(args)...); 12487} 12488#endif 12489 12490template<class M> 12491internal::virtual_table_t<M> make_virtual_table(std::string name, M module_details) { 12492SQLITE_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 12499namespace sqlite_orm { 12500namespace internal { 12501 12502template<class DBOs> 12503using tables_index_sequence = filter_tuple_sequence_t<DBOs, is_table>; 12504 12505template<class DBOs, satisfies<is_db_objects, DBOs> = true> 12506int foreign_keys_count(const DBOs& dbObjects) { 12507int res = 0; 12508iterate_tuple<true>(dbObjects, tables_index_sequence<DBOs>{}, [&res](const auto& table) { 12509res += table.template count_of<is_foreign_key>(); 12510}); 12511return res; 12512} 12513 12514template<class Lookup, class DBOs, satisfies<is_db_objects, DBOs>> 12515decltype(auto) lookup_table_name(const DBOs& dbObjects) { 12516return static_if<is_mapped<DBOs, Lookup>::value>( 12517[](const auto& dbObjects) -> const std::string& { 12518return pick_table<Lookup>(dbObjects).name; 12519}, 12520empty_callable<std::string>)(dbObjects); 12521} 12522 12523/** 12524* Find column name by its type and member pointer. 12525*/ 12526template<class O, class F, class DBOs, satisfies<is_db_objects, DBOs> = true> 12527const std::string* find_column_name(const DBOs& dbObjects, F O::* field) { 12528return 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*/ 12536template<class O, class F, class DBOs, satisfies<is_db_objects, DBOs> = true> 12537constexpr decltype(auto) materialize_column_pointer(const DBOs&, const column_pointer<O, F>& cp) { 12538return 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*/ 12548template<class Moniker, class ColAlias, class DBOs, satisfies<is_db_objects, DBOs> = true> 12549constexpr decltype(auto) materialize_column_pointer(const DBOs&, 12550const column_pointer<Moniker, alias_holder<ColAlias>>&) { 12551using table_type = storage_pick_table_t<Moniker, DBOs>; 12552using cte_mapper_type = cte_mapper_type_t<table_type>; 12553 12554// lookup ColAlias in the final column references 12555using colalias_index = 12556find_tuple_type<typename cte_mapper_type::final_colrefs_tuple, alias_holder<ColAlias>>; 12557static_assert(colalias_index::value < std::tuple_size_v<typename cte_mapper_type::final_colrefs_tuple>, 12558"No such column mapped into the CTE."); 12559 12560return &aliased_field< 12561ColAlias, 12562std::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*/ 12571template<class O, class F, class DBOs, satisfies<is_db_objects, DBOs> = true> 12572const std::string* find_column_name(const DBOs& dbObjects, const column_pointer<O, F>& cp) { 12573auto field = materialize_column_pointer(dbObjects, cp); 12574return 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*/ 12582template<class Moniker, class ColAlias, class DBOs, satisfies<is_db_objects, DBOs> = true> 12583constexpr decltype(auto) find_column_name(const DBOs& dboObjects, 12584const column_pointer<Moniker, alias_holder<ColAlias>>&) { 12585using table_type = storage_pick_table_t<Moniker, DBOs>; 12586using cte_mapper_type = cte_mapper_type_t<table_type>; 12587using 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 12591using colalias_index = 12592find_tuple_type<typename cte_mapper_type::final_colrefs_tuple, alias_holder<ColAlias>>; 12593static_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 12599constexpr size_t ColIdx = index_sequence_value_at<colalias_index::value>(column_index_sequence{}); 12600auto& table = pick_table<Moniker>(dboObjects); 12601return &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 12623namespace 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*/ 12630enum class journal_mode : signed char { 12631DELETE = 0, 12632// An alternate enumeration value when using the Windows SDK that defines DELETE as a macro. 12633DELETE_ = DELETE, 12634TRUNCATE = 1, 12635PERSIST = 2, 12636MEMORY = 3, 12637WAL = 4, 12638OFF = 5, 12639}; 12640 12641namespace internal { 12642 12643inline const serialize_result_type& journal_mode_to_string(journal_mode value) { 12644#ifdef SQLITE_ORM_STRING_VIEW_SUPPORTED 12645static constexpr std::array<serialize_result_type, 6> idx2str = { 12646#else 12647static const std::array<serialize_result_type, 6> idx2str = { 12648#endif 12649"DELETE", 12650"TRUNCATE", 12651"PERSIST", 12652"MEMORY", 12653"WAL", 12654"OFF", 12655}; 12656return idx2str.at(static_cast<int>(value)); 12657} 12658 12659inline std::pair<bool, journal_mode> journal_mode_from_string(std::string string) { 12660static constexpr std::array<journal_mode, 6> journalModes = {{ 12661journal_mode::DELETE, 12662journal_mode::TRUNCATE, 12663journal_mode::PERSIST, 12664journal_mode::MEMORY, 12665journal_mode::WAL, 12666journal_mode::OFF, 12667}}; 12668#if __cpp_lib_ranges >= 201911L 12669std::ranges::transform(string, string.begin(), [](unsigned char c) noexcept { 12670return std::toupper(c); 12671}); 12672if (auto found = std::ranges::find(journalModes, string, journal_mode_to_string); 12673found != journalModes.end()) SQLITE_ORM_CPP_LIKELY { 12674return {true, *found}; 12675} 12676#else 12677std::transform(string.begin(), string.end(), string.begin(), [](unsigned char c) noexcept { 12678return std::toupper(c); 12679}); 12680for (auto journalMode: journalModes) { 12681if (journal_mode_to_string(journalMode) == string) { 12682return {true, journalMode}; 12683} 12684} 12685#endif 12686return {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 12744namespace sqlite_orm { 12745enum class locking_mode : signed char { 12746NORMAL = 0, 12747EXCLUSIVE = 1, 12748}; 12749 12750namespace internal { 12751inline const serialize_result_type& locking_mode_to_string(locking_mode value) { 12752#ifdef SQLITE_ORM_STRING_VIEW_SUPPORTED 12753static constexpr std::array<serialize_result_type, 2> idx2str = { 12754#else 12755static const std::array<serialize_result_type, 2> idx2str = { 12756#endif 12757"NORMAL", 12758"EXCLUSIVE", 12759}; 12760return idx2str.at(static_cast<int>(value)); 12761} 12762 12763inline std::pair<bool, locking_mode> locking_mode_from_string(std::string string) { 12764static constexpr std::array<locking_mode, 2> lockingModes = {{ 12765locking_mode::NORMAL, 12766locking_mode::EXCLUSIVE, 12767}}; 12768 12769#if __cpp_lib_ranges >= 201911L 12770std::ranges::transform(string, string.begin(), [](unsigned char c) noexcept { 12771return std::toupper(c); 12772}); 12773if (auto found = std::ranges::find(lockingModes, string, locking_mode_to_string); 12774found != lockingModes.end()) SQLITE_ORM_CPP_LIKELY { 12775return {true, *found}; 12776} 12777#else 12778std::transform(string.begin(), string.end(), string.begin(), [](unsigned char c) noexcept { 12779return std::toupper(c); 12780}); 12781for (auto lockingMode: lockingModes) { 12782if (locking_mode_to_string(lockingMode) == string) { 12783return {true, lockingMode}; 12784} 12785} 12786#endif 12787return {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 12797namespace 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*/ 12812template<class V, typename Enable = void> 12813struct row_extractor { 12814/* 12815* Called during one-step query execution (one result row) for each column of a result row. 12816*/ 12817V 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*/ 12822V 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*/ 12828V extract(sqlite3_value* value) const = delete; 12829}; 12830 12831#ifdef SQLITE_ORM_CPP20_CONCEPTS_SUPPORTED 12832template<typename T> 12833concept orm_column_text_extractable = requires(const row_extractor<T>& extractor, const char* columnText) { 12834{ extractor.extract(columnText) } -> std::same_as<T>; 12835}; 12836 12837template<typename T> 12838concept orm_row_value_extractable = 12839requires(const row_extractor<T>& extractor, sqlite3_stmt* stmt, int columnIndex) { 12840{ extractor.extract(stmt, columnIndex) } -> std::same_as<T>; 12841}; 12842 12843template<typename T> 12844concept 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 12849namespace internal { 12850/* 12851* Make a row extractor to be used for casting SQL column text to a C++ typed value. 12852*/ 12853template<class R> 12854#ifdef SQLITE_ORM_CPP20_CONCEPTS_SUPPORTED 12855requires (orm_column_text_extractable<R>) 12856#endif 12857row_extractor<R> column_text_extractor() { 12858return {}; 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*/ 12864template<class R> 12865#ifdef SQLITE_ORM_CPP20_CONCEPTS_SUPPORTED 12866requires (orm_row_value_extractable<R>) 12867#endif 12868row_extractor<R> row_value_extractor() { 12869return {}; 12870} 12871 12872/* 12873* Make a row extractor to be used for unboxing a dynamically typed SQL value to a C++ typed value. 12874*/ 12875template<class R> 12876#ifdef SQLITE_ORM_CPP20_CONCEPTS_SUPPORTED 12877requires (orm_boxed_value_extractable<R>) 12878#endif 12879row_extractor<R> boxed_value_extractor() { 12880return {}; 12881} 12882} 12883 12884template<class R> 12885int extract_single_value(void* data, int argc, char** argv, char**) { 12886auto& res = *(R*)data; 12887if (argc) { 12888const auto rowExtractor = internal::column_text_extractor<R>(); 12889res = rowExtractor.extract(argv[0]); 12890} 12891return 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*/ 12901template<class P, class T> 12902struct row_extractor<pointer_arg<P, T>, void> { 12903using V = pointer_arg<P, T>; 12904 12905V extract(const char* columnText) const = delete; 12906 12907V extract(sqlite3_stmt* stmt, int columnIndex) const = delete; 12908 12909V extract(sqlite3_value* value) const { 12910return {(P*)sqlite3_value_pointer(value, T::value)}; 12911} 12912}; 12913 12914/** 12915* Undefine using pointer_binding<> for querying values 12916*/ 12917template<class P, class T, class D> 12918struct row_extractor<pointer_binding<P, T, D>, void>; 12919#endif 12920 12921/** 12922* Specialization for arithmetic types. 12923*/ 12924template<class V> 12925struct row_extractor<V, std::enable_if_t<std::is_arithmetic<V>::value>> { 12926V extract(const char* columnText) const { 12927return this->extract(columnText, tag()); 12928} 12929 12930V extract(sqlite3_stmt* stmt, int columnIndex) const { 12931return this->extract(stmt, columnIndex, tag()); 12932} 12933 12934V extract(sqlite3_value* value) const { 12935return this->extract(value, tag()); 12936} 12937 12938private: 12939using tag = arithmetic_tag_t<V>; 12940 12941V extract(const char* columnText, const int_or_smaller_tag&) const { 12942return static_cast<V>(atoi(columnText)); 12943} 12944 12945V extract(sqlite3_stmt* stmt, int columnIndex, const int_or_smaller_tag&) const { 12946return static_cast<V>(sqlite3_column_int(stmt, columnIndex)); 12947} 12948 12949V extract(sqlite3_value* value, const int_or_smaller_tag&) const { 12950return static_cast<V>(sqlite3_value_int(value)); 12951} 12952 12953V extract(const char* columnText, const bigint_tag&) const { 12954return static_cast<V>(atoll(columnText)); 12955} 12956 12957V extract(sqlite3_stmt* stmt, int columnIndex, const bigint_tag&) const { 12958return static_cast<V>(sqlite3_column_int64(stmt, columnIndex)); 12959} 12960 12961V extract(sqlite3_value* value, const bigint_tag&) const { 12962return static_cast<V>(sqlite3_value_int64(value)); 12963} 12964 12965V extract(const char* columnText, const real_tag&) const { 12966return static_cast<V>(atof(columnText)); 12967} 12968 12969V extract(sqlite3_stmt* stmt, int columnIndex, const real_tag&) const { 12970return static_cast<V>(sqlite3_column_double(stmt, columnIndex)); 12971} 12972 12973V extract(sqlite3_value* value, const real_tag&) const { 12974return static_cast<V>(sqlite3_value_double(value)); 12975} 12976}; 12977 12978/** 12979* Specialization for std::string. 12980*/ 12981template<class T> 12982struct row_extractor<T, std::enable_if_t<std::is_base_of<std::string, T>::value>> { 12983T extract(const char* columnText) const { 12984if (columnText) { 12985return columnText; 12986} else { 12987return {}; 12988} 12989} 12990 12991T extract(sqlite3_stmt* stmt, int columnIndex) const { 12992if (auto cStr = (const char*)sqlite3_column_text(stmt, columnIndex)) { 12993return cStr; 12994} else { 12995return {}; 12996} 12997} 12998 12999T extract(sqlite3_value* value) const { 13000if (auto cStr = (const char*)sqlite3_value_text(value)) { 13001return cStr; 13002} else { 13003return {}; 13004} 13005} 13006}; 13007#ifndef SQLITE_ORM_OMITS_CODECVT 13008/** 13009* Specialization for std::wstring. 13010*/ 13011template<> 13012struct row_extractor<std::wstring, void> { 13013std::wstring extract(const char* columnText) const { 13014if (columnText) { 13015std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>> converter; 13016return converter.from_bytes(columnText); 13017} else { 13018return {}; 13019} 13020} 13021 13022std::wstring extract(sqlite3_stmt* stmt, int columnIndex) const { 13023auto cStr = (const char*)sqlite3_column_text(stmt, columnIndex); 13024if (cStr) { 13025std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>> converter; 13026return converter.from_bytes(cStr); 13027} else { 13028return {}; 13029} 13030} 13031 13032std::wstring extract(sqlite3_value* value) const { 13033if (auto cStr = (const wchar_t*)sqlite3_value_text16(value)) { 13034return cStr; 13035} else { 13036return {}; 13037} 13038} 13039}; 13040#endif // SQLITE_ORM_OMITS_CODECVT 13041 13042template<class V> 13043struct row_extractor<V, std::enable_if_t<is_std_ptr<V>::value>> { 13044using unqualified_type = std::remove_cv_t<typename V::element_type>; 13045 13046V extract(const char* columnText) const 13047#ifdef SQLITE_ORM_CPP20_CONCEPTS_SUPPORTED 13048requires (orm_column_text_extractable<unqualified_type>) 13049#endif 13050{ 13051if (columnText) { 13052const row_extractor<unqualified_type> rowExtractor{}; 13053return is_std_ptr<V>::make(rowExtractor.extract(columnText)); 13054} else { 13055return {}; 13056} 13057} 13058 13059V extract(sqlite3_stmt* stmt, int columnIndex) const 13060#ifdef SQLITE_ORM_CPP20_CONCEPTS_SUPPORTED 13061requires (orm_row_value_extractable<unqualified_type>) 13062#endif 13063{ 13064auto type = sqlite3_column_type(stmt, columnIndex); 13065if (type != SQLITE_NULL) { 13066const row_extractor<unqualified_type> rowExtractor{}; 13067return is_std_ptr<V>::make(rowExtractor.extract(stmt, columnIndex)); 13068} else { 13069return {}; 13070} 13071} 13072 13073V extract(sqlite3_value* value) const 13074#ifdef SQLITE_ORM_CPP20_CONCEPTS_SUPPORTED 13075requires (orm_boxed_value_extractable<unqualified_type>) 13076#endif 13077{ 13078auto type = sqlite3_value_type(value); 13079if (type != SQLITE_NULL) { 13080const row_extractor<unqualified_type> rowExtractor{}; 13081return is_std_ptr<V>::make(rowExtractor.extract(value)); 13082} else { 13083return {}; 13084} 13085} 13086}; 13087 13088#ifdef SQLITE_ORM_OPTIONAL_SUPPORTED 13089template<class V> 13090struct row_extractor<V, std::enable_if_t<polyfill::is_specialization_of_v<V, std::optional>>> { 13091using unqualified_type = std::remove_cv_t<typename V::value_type>; 13092 13093V extract(const char* columnText) const 13094#ifdef SQLITE_ORM_CPP20_CONCEPTS_SUPPORTED 13095requires (orm_column_text_extractable<unqualified_type>) 13096#endif 13097{ 13098if (columnText) { 13099const row_extractor<unqualified_type> rowExtractor{}; 13100return std::make_optional(rowExtractor.extract(columnText)); 13101} else { 13102return std::nullopt; 13103} 13104} 13105 13106V extract(sqlite3_stmt* stmt, int columnIndex) const 13107#ifdef SQLITE_ORM_CPP20_CONCEPTS_SUPPORTED 13108requires (orm_row_value_extractable<unqualified_type>) 13109#endif 13110{ 13111auto type = sqlite3_column_type(stmt, columnIndex); 13112if (type != SQLITE_NULL) { 13113const row_extractor<unqualified_type> rowExtractor{}; 13114return std::make_optional(rowExtractor.extract(stmt, columnIndex)); 13115} else { 13116return std::nullopt; 13117} 13118} 13119 13120V extract(sqlite3_value* value) const 13121#ifdef SQLITE_ORM_CPP20_CONCEPTS_SUPPORTED 13122requires (orm_boxed_value_extractable<unqualified_type>) 13123#endif 13124{ 13125auto type = sqlite3_value_type(value); 13126if (type != SQLITE_NULL) { 13127const row_extractor<unqualified_type> rowExtractor{}; 13128return std::make_optional(rowExtractor.extract(value)); 13129} else { 13130return std::nullopt; 13131} 13132} 13133}; 13134#endif // SQLITE_ORM_OPTIONAL_SUPPORTED 13135 13136template<> 13137struct row_extractor<nullptr_t, void> { 13138nullptr_t extract(const char* /*columnText*/) const { 13139return nullptr; 13140} 13141 13142nullptr_t extract(sqlite3_stmt*, int /*columnIndex*/) const { 13143return nullptr; 13144} 13145 13146nullptr_t extract(sqlite3_value*) const { 13147return nullptr; 13148} 13149}; 13150/** 13151* Specialization for std::vector<char>. 13152*/ 13153template<> 13154struct row_extractor<std::vector<char>, void> { 13155std::vector<char> extract(const char* columnText) const { 13156return {columnText, columnText + (columnText ? strlen(columnText) : 0)}; 13157} 13158 13159std::vector<char> extract(sqlite3_stmt* stmt, int columnIndex) const { 13160auto bytes = static_cast<const char*>(sqlite3_column_blob(stmt, columnIndex)); 13161auto len = static_cast<size_t>(sqlite3_column_bytes(stmt, columnIndex)); 13162return {bytes, bytes + len}; 13163} 13164 13165std::vector<char> extract(sqlite3_value* value) const { 13166auto bytes = static_cast<const char*>(sqlite3_value_blob(value)); 13167auto len = static_cast<size_t>(sqlite3_value_bytes(value)); 13168return {bytes, bytes + len}; 13169} 13170}; 13171 13172/** 13173* Specialization for locking_mode. 13174*/ 13175template<> 13176struct row_extractor<locking_mode, void> { 13177locking_mode extract(const char* columnText) const { 13178if (columnText) { 13179auto resultPair = internal::locking_mode_from_string(columnText); 13180if (resultPair.first) { 13181return resultPair.second; 13182} else { 13183throw std::system_error{orm_error_code::incorrect_locking_mode_string}; 13184} 13185} else { 13186throw std::system_error{orm_error_code::incorrect_locking_mode_string}; 13187} 13188} 13189 13190locking_mode extract(sqlite3_stmt* stmt, int columnIndex) const { 13191auto cStr = (const char*)sqlite3_column_text(stmt, columnIndex); 13192return this->extract(cStr); 13193} 13194 13195locking_mode extract(sqlite3_value* value) const = delete; 13196}; 13197 13198/** 13199* Specialization for journal_mode. 13200*/ 13201template<> 13202struct row_extractor<journal_mode, void> { 13203journal_mode extract(const char* columnText) const { 13204if (columnText) { 13205auto resultPair = internal::journal_mode_from_string(columnText); 13206if (resultPair.first) { 13207return resultPair.second; 13208} else { 13209throw std::system_error{orm_error_code::incorrect_journal_mode_string}; 13210} 13211} else { 13212throw std::system_error{orm_error_code::incorrect_journal_mode_string}; 13213} 13214} 13215 13216journal_mode extract(sqlite3_stmt* stmt, int columnIndex) const { 13217auto cStr = (const char*)sqlite3_column_text(stmt, columnIndex); 13218return this->extract(cStr); 13219} 13220 13221journal_mode extract(sqlite3_value* value) const = delete; 13222}; 13223 13224namespace internal { 13225 13226/* 13227* Helper to extract a structure from a rowset. 13228*/ 13229template<class R, class DBOs> 13230struct 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*/ 13237template<class R, class DBOs> 13238auto make_row_extractor([[maybe_unused]] const DBOs& dbObjects) { 13239if constexpr (polyfill::is_specialization_of_v<R, std::tuple> || 13240polyfill::is_specialization_of_v<R, structure> || is_table_reference_v<R>) { 13241return struct_extractor<R, DBOs>{dbObjects}; 13242} else { 13243return row_value_extractor<R>(); 13244} 13245} 13246#else 13247/* 13248* Overload for an unmapped type returns a common row extractor. 13249*/ 13250template< 13251class R, 13252class DBOs, 13253std::enable_if_t<polyfill::negation<polyfill::disjunction<polyfill::is_specialization_of<R, std::tuple>, 13254polyfill::is_specialization_of<R, structure>, 13255is_table_reference<R>>>::value, 13256bool> = true> 13257auto make_row_extractor(const DBOs& /*dbObjects*/) { 13258return row_value_extractor<R>(); 13259} 13260 13261/* 13262* Overload for a table reference, tuple or aggregate of column results returns a structure extractor. 13263*/ 13264template<class R, 13265class DBOs, 13266std::enable_if_t<polyfill::disjunction<polyfill::is_specialization_of<R, std::tuple>, 13267polyfill::is_specialization_of<R, structure>, 13268is_table_reference<R>>::value, 13269bool> = true> 13270struct_extractor<R, DBOs> make_row_extractor(const DBOs& dbObjects) { 13271return {dbObjects}; 13272} 13273#endif 13274 13275/** 13276* Specialization for a tuple of top-level column results. 13277*/ 13278template<class DBOs, class... Args> 13279struct struct_extractor<std::tuple<Args...>, DBOs> { 13280const DBOs& db_objects; 13281 13282std::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 13285std::tuple<column_result_proxy_t<Args>...> extract(sqlite3_stmt* stmt, 13286int&& /*nextColumnIndex*/ = 0) const { 13287int columnIndex = -1; 13288return {make_row_extractor<Args>(this->db_objects).extract(stmt, ++columnIndex)...}; 13289} 13290 13291// unused to date 13292std::tuple<column_result_proxy_t<Args>...> extract(sqlite3_stmt* stmt, int& columnIndex) const = delete; 13293 13294std::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*/ 13302template<class O, class... Args, class DBOs> 13303struct struct_extractor<structure<O, std::tuple<Args...>>, DBOs> { 13304const DBOs& db_objects; 13305 13306O 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") 13311template<class Ox = O, satisfies<is_eval_order_garanteed, Ox> = true> 13312O extract(sqlite3_stmt* stmt, int&& /*nextColumnIndex*/ = 0) const { 13313int columnIndex = -1; 13314return O{make_row_extractor<Args>(this->db_objects).extract(stmt, ++columnIndex)...}; 13315} 13316 13317template<class Ox = O, satisfies_not<is_eval_order_garanteed, Ox> = true> 13318O extract(sqlite3_stmt* stmt, int&& /*nextColumnIndex*/ = 0) const { 13319int columnIndex = -1; 13320// note: brace-init-list initialization guarantees order of evaluation, but only for aggregates and variadic constructors it seems. 13321std::tuple<Args...> t{make_row_extractor<Args>(this->db_objects).extract(stmt, ++columnIndex)...}; 13322return 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") 13327template<class Ox = O, satisfies<is_eval_order_garanteed, Ox> = true> 13328O extract(sqlite3_stmt* stmt, int& columnIndex) const { 13329--columnIndex; 13330return O{make_row_extractor<Args>(this->db_objects).extract(stmt, ++columnIndex)...}; 13331} 13332 13333template<class Ox = O, satisfies_not<is_eval_order_garanteed, Ox> = true> 13334O 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. 13337std::tuple<Args...> t{make_row_extractor<Args>(this->db_objects).extract(stmt, ++columnIndex)...}; 13338return create_from_tuple<O>(std::move(t), std::index_sequence_for<Args...>{}); 13339} 13340 13341O 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 13361namespace sqlite_orm { 13362 13363/** 13364* Guard class which finalizes `sqlite3_stmt` in dtor 13365*/ 13366using statement_finalizer = 13367std::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 13390namespace sqlite_orm { 13391 13392namespace internal { 13393 13394struct object_from_column_builder_base { 13395sqlite3_stmt* stmt = nullptr; 13396int columnIndex = -1; 13397 13398#ifndef SQLITE_ORM_AGGREGATE_NSDMI_SUPPORTED 13399object_from_column_builder_base(sqlite3_stmt* stmt, int columnIndex = -1) : 13400stmt{stmt}, columnIndex{columnIndex} {} 13401#endif 13402}; 13403 13404/** 13405* Function object for building an object from a result row. 13406*/ 13407template<class O> 13408struct object_from_column_builder : object_from_column_builder_base { 13409using object_type = O; 13410 13411object_type& object; 13412 13413object_from_column_builder(object_type& object_, sqlite3_stmt* stmt_, int nextColumnIndex = 0) : 13414object_from_column_builder_base{stmt_, nextColumnIndex - 1}, object(object_) {} 13415 13416template<class G, class S> 13417void operator()(const column_field<G, S>& column) { 13418const auto rowExtractor = row_value_extractor<member_field_type_t<G>>(); 13419auto value = rowExtractor.extract(this->stmt, ++this->columnIndex); 13420static_if<std::is_member_object_pointer<G>::value>( 13421[&value, &object = this->object](const auto& column) { 13422object.*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*/ 13435template<class O, class DBOs> 13436struct struct_extractor<table_reference<O>, DBOs> { 13437const DBOs& db_objects; 13438 13439O extract(const char* columnText) const = delete; 13440 13441// note: expects to be called only from the top level, and therefore discards the index 13442O extract(sqlite3_stmt* stmt, int&& /*nextColumnIndex*/ = 0) const { 13443int columnIndex = 0; 13444return this->extract(stmt, columnIndex); 13445} 13446 13447O extract(sqlite3_stmt* stmt, int& columnIndex) const { 13448O obj; 13449object_from_column_builder<O> builder{obj, stmt, columnIndex}; 13450auto& table = pick_table<O>(this->db_objects); 13451table.for_each_column(builder); 13452columnIndex = builder.columnIndex; 13453return obj; 13454} 13455 13456O 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 13471namespace 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*/ 13478inline std::string sql_escape(std::string str, char char2Escape) { 13479for (size_t pos = 0; (pos = str.find(char2Escape, pos)) != str.npos; pos += 2) { 13480str.replace(pos, 1, 2, char2Escape); 13481} 13482 13483return str; 13484} 13485 13486/** 13487* Quote the given string value using single quotes, 13488* escape containing single quotes by doubling them. 13489*/ 13490inline std::string quote_string_literal(std::string v) { 13491constexpr char quoteChar = '\''; 13492return 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*/ 13499inline std::string quote_blob_literal(std::string v) { 13500constexpr char quoteChar = '\''; 13501return 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*/ 13508inline std::string quote_identifier(std::string identifier) { 13509constexpr char quoteChar = '"'; 13510return quoteChar + sql_escape(std::move(identifier), quoteChar) + quoteChar; 13511} 13512 13513namespace internal { 13514// Wrapper to reduce boiler-plate code 13515inline sqlite3_stmt* reset_stmt(sqlite3_stmt* stmt) { 13516sqlite3_reset(stmt); 13517return stmt; 13518} 13519 13520// note: query is deliberately taken by value, such that it is thrown away early 13521inline sqlite3_stmt* prepare_stmt(sqlite3* db, std::string query) { 13522sqlite3_stmt* stmt; 13523if (sqlite3_prepare_v2(db, query.c_str(), -1, &stmt, nullptr) != SQLITE_OK) { 13524throw_translated_sqlite_error(db); 13525} 13526return stmt; 13527} 13528 13529inline void perform_void_exec(sqlite3* db, const std::string& query) { 13530int rc = sqlite3_exec(db, query.c_str(), nullptr, nullptr, nullptr); 13531if (rc != SQLITE_OK) { 13532throw_translated_sqlite_error(db); 13533} 13534} 13535 13536inline void perform_exec(sqlite3* db, 13537const char* query, 13538int (*callback)(void* data, int argc, char** argv, char**), 13539void* user_data) { 13540int rc = sqlite3_exec(db, query, callback, user_data, nullptr); 13541if (rc != SQLITE_OK) { 13542throw_translated_sqlite_error(db); 13543} 13544} 13545 13546inline void perform_exec(sqlite3* db, 13547const std::string& query, 13548int (*callback)(void* data, int argc, char** argv, char**), 13549void* user_data) { 13550return perform_exec(db, query.c_str(), callback, user_data); 13551} 13552 13553template<int expected = SQLITE_DONE> 13554void perform_step(sqlite3_stmt* stmt) { 13555int rc = sqlite3_step(stmt); 13556if (rc != expected) { 13557throw_translated_sqlite_error(stmt); 13558} 13559} 13560 13561template<class L> 13562void perform_step(sqlite3_stmt* stmt, L&& lambda) { 13563switch (int rc = sqlite3_step(stmt)) { 13564case SQLITE_ROW: { 13565lambda(stmt); 13566} break; 13567case SQLITE_DONE: 13568break; 13569default: { 13570throw_translated_sqlite_error(stmt); 13571} 13572} 13573} 13574 13575template<class L> 13576void perform_steps(sqlite3_stmt* stmt, L&& lambda) { 13577int rc; 13578do { 13579switch (rc = sqlite3_step(stmt)) { 13580case SQLITE_ROW: { 13581lambda(stmt); 13582} break; 13583case SQLITE_DONE: 13584break; 13585default: { 13586throw_translated_sqlite_error(stmt); 13587} 13588} 13589} while (rc != SQLITE_DONE); 13590} 13591} 13592} 13593 13594namespace sqlite_orm { 13595namespace internal { 13596 13597/* 13598* (Legacy) Input iterator over a result set for a mapped object. 13599*/ 13600template<class O, class DBOs> 13601class mapped_iterator { 13602public: 13603using db_objects_type = DBOs; 13604 13605using iterator_category = std::input_iterator_tag; 13606using difference_type = ptrdiff_t; 13607using value_type = O; 13608using reference = O&; 13609using pointer = O*; 13610 13611private: 13612/** 13613pointer to the db objects. 13614only null for the default constructed iterator. 13615*/ 13616const 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*/ 13622std::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*/ 13628std::shared_ptr<value_type> current; 13629 13630void extract_object() { 13631this->current = std::make_shared<value_type>(); 13632object_from_column_builder<value_type> builder{*this->current, this->stmt.get()}; 13633auto& table = pick_table<value_type>(*this->db_objects); 13634table.for_each_column(builder); 13635} 13636 13637void step() { 13638perform_step(this->stmt.get(), std::bind(&mapped_iterator::extract_object, this)); 13639if (!this->current) { 13640this->stmt.reset(); 13641} 13642} 13643 13644void next() { 13645this->current.reset(); 13646this->step(); 13647} 13648 13649public: 13650mapped_iterator() = default; 13651 13652mapped_iterator(const db_objects_type& dbObjects, statement_finalizer stmt) : 13653db_objects{&dbObjects}, stmt{std::move(stmt)} { 13654this->step(); 13655} 13656 13657mapped_iterator(const mapped_iterator&) = default; 13658mapped_iterator& operator=(const mapped_iterator&) = default; 13659mapped_iterator(mapped_iterator&&) = default; 13660mapped_iterator& operator=(mapped_iterator&&) = default; 13661 13662value_type& operator*() const { 13663if (!this->stmt) SQLITE_ORM_CPP_UNLIKELY { 13664throw std::system_error{orm_error_code::trying_to_dereference_null_iterator}; 13665} 13666return *this->current; 13667} 13668 13669// note: should actually be only present for contiguous iterators 13670value_type* operator->() const { 13671return &(this->operator*()); 13672} 13673 13674mapped_iterator& operator++() { 13675next(); 13676return *this; 13677} 13678 13679mapped_iterator operator++(int) { 13680auto tmp = *this; 13681++*this; 13682return tmp; 13683} 13684 13685friend bool operator==(const mapped_iterator& lhs, const mapped_iterator& rhs) { 13686return lhs.current == rhs.current; 13687} 13688 13689#ifndef SQLITE_ORM_DEFAULT_COMPARISONS_SUPPORTED 13690friend bool operator!=(const mapped_iterator& lhs, const mapped_iterator& rhs) { 13691return !(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 13741namespace sqlite_orm { 13742 13743namespace internal { 13744 13745struct connection_holder { 13746 13747connection_holder(std::string filename_) : filename(std::move(filename_)) {} 13748 13749void retain() { 13750if (1 == ++this->_retain_count) { 13751auto rc = sqlite3_open(this->filename.c_str(), &this->db); 13752if (rc != SQLITE_OK) { 13753throw_translated_sqlite_error(db); 13754} 13755} 13756} 13757 13758void release() { 13759if (0 == --this->_retain_count) { 13760auto rc = sqlite3_close(this->db); 13761if (rc != SQLITE_OK) { 13762throw_translated_sqlite_error(db); 13763} 13764} 13765} 13766 13767sqlite3* get() const { 13768return this->db; 13769} 13770 13771int retain_count() const { 13772return this->_retain_count; 13773} 13774 13775const std::string filename; 13776 13777protected: 13778sqlite3* db = nullptr; 13779std::atomic_int _retain_count{}; 13780}; 13781 13782struct connection_ref { 13783connection_ref(connection_holder& holder) : holder(&holder) { 13784this->holder->retain(); 13785} 13786 13787connection_ref(const connection_ref& other) : holder(other.holder) { 13788this->holder->retain(); 13789} 13790 13791// rebind connection reference 13792connection_ref& operator=(const connection_ref& other) { 13793if (other.holder != this->holder) { 13794this->holder->release(); 13795this->holder = other.holder; 13796this->holder->retain(); 13797} 13798 13799return *this; 13800} 13801 13802~connection_ref() { 13803this->holder->release(); 13804} 13805 13806sqlite3* get() const { 13807return this->holder->get(); 13808} 13809 13810private: 13811connection_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 13826namespace sqlite_orm { 13827 13828namespace internal { 13829 13830template<class... Args> 13831struct values_t { 13832using args_tuple = std::tuple<Args...>; 13833 13834args_tuple tuple; 13835}; 13836 13837template<class T> 13838SQLITE_ORM_INLINE_VAR constexpr bool is_values_v = polyfill::is_specialization_of<T, values_t>::value; 13839 13840template<class T> 13841using is_values = polyfill::bool_constant<is_values_v<T>>; 13842 13843template<class T> 13844struct dynamic_values_t { 13845std::vector<T> vector; 13846}; 13847 13848} 13849 13850template<class... Args> 13851internal::values_t<Args...> values(Args... args) { 13852return {{std::forward<Args>(args)...}}; 13853} 13854 13855template<class T> 13856internal::dynamic_values_t<T> values(std::vector<T> vector) { 13857return {{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 13874namespace sqlite_orm { 13875namespace internal { 13876#if SQLITE_VERSION_NUMBER >= 3024000 13877template<class T, class A> 13878struct upsert_clause; 13879 13880template<class... Args> 13881struct conflict_target { 13882using args_tuple = std::tuple<Args...>; 13883 13884args_tuple args; 13885 13886upsert_clause<args_tuple, std::tuple<>> do_nothing() { 13887return {std::move(this->args), {}}; 13888} 13889 13890template<class... ActionsArgs> 13891upsert_clause<args_tuple, std::tuple<ActionsArgs...>> do_update(ActionsArgs... actions) { 13892return {std::move(this->args), {std::forward<ActionsArgs>(actions)...}}; 13893} 13894}; 13895 13896template<class... TargetArgs, class... ActionsArgs> 13897struct upsert_clause<std::tuple<TargetArgs...>, std::tuple<ActionsArgs...>> { 13898using target_args_tuple = std::tuple<TargetArgs...>; 13899using actions_tuple = std::tuple<ActionsArgs...>; 13900 13901target_args_tuple target_args; 13902 13903actions_tuple actions; 13904}; 13905#endif 13906 13907template<class T> 13908SQLITE_ORM_INLINE_VAR constexpr bool is_upsert_clause_v = 13909#if SQLITE_VERSION_NUMBER >= 3024000 13910polyfill::is_specialization_of<T, upsert_clause>::value; 13911#else 13912false; 13913#endif 13914 13915template<class T> 13916using 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*/ 13932template<class... Args> 13933internal::conflict_target<Args...> on_conflict(Args... args) { 13934return {{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 13969namespace sqlite_orm { 13970 13971namespace internal { 13972 13973struct table_name_collector_base { 13974using table_name_set = std::set<std::pair<std::string, std::string>>; 13975 13976table_name_set table_names; 13977}; 13978 13979template<class DBOs> 13980struct table_name_collector : table_name_collector_base { 13981using db_objects_type = DBOs; 13982 13983const db_objects_type& db_objects; 13984 13985table_name_collector() = default; 13986 13987table_name_collector(const db_objects_type& dbObjects) : db_objects{dbObjects} {} 13988 13989template<class T> 13990void operator()(const T&) const {} 13991 13992template<class F, class O> 13993void operator()(F O::*) { 13994this->table_names.emplace(lookup_table_name<O>(this->db_objects), ""); 13995} 13996 13997template<class T, class F> 13998void operator()(const column_pointer<T, F>&) { 13999auto tableName = lookup_table_name<mapped_type_proxy_t<T>>(this->db_objects); 14000this->table_names.emplace(std::move(tableName), alias_extractor<T>::as_alias()); 14001} 14002 14003template<class A, class C> 14004void 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 14006auto tableName = lookup_table_name<mapped_type_proxy_t<A>>(this->db_objects); 14007this->table_names.emplace(std::move(tableName), alias_extractor<A>::as_alias()); 14008} 14009 14010template<class T> 14011void operator()(const count_asterisk_t<T>&) { 14012auto tableName = lookup_table_name<T>(this->db_objects); 14013if (!tableName.empty()) { 14014this->table_names.emplace(std::move(tableName), ""); 14015} 14016} 14017 14018template<class T> 14019void operator()(const asterisk_t<T>&) { 14020auto tableName = lookup_table_name<mapped_type_proxy_t<T>>(this->db_objects); 14021table_names.emplace(std::move(tableName), alias_extractor<T>::as_alias()); 14022} 14023 14024template<class T> 14025void operator()(const object_t<T>&) { 14026this->table_names.emplace(lookup_table_name<T>(this->db_objects), ""); 14027} 14028 14029template<class T> 14030void operator()(const table_rowid_t<T>&) { 14031this->table_names.emplace(lookup_table_name<T>(this->db_objects), ""); 14032} 14033 14034template<class T> 14035void operator()(const table_oid_t<T>&) { 14036this->table_names.emplace(lookup_table_name<T>(this->db_objects), ""); 14037} 14038 14039template<class T> 14040void operator()(const table__rowid_t<T>&) { 14041this->table_names.emplace(lookup_table_name<T>(this->db_objects), ""); 14042} 14043 14044template<class T, class X, class Y, class Z> 14045void operator()(const highlight_t<T, X, Y, Z>&) { 14046this->table_names.emplace(lookup_table_name<T>(this->db_objects), ""); 14047} 14048}; 14049 14050template<class DBOs, satisfies<is_db_objects, DBOs> = true> 14051table_name_collector<DBOs> make_table_name_collector(const DBOs& dbObjects) { 14052return {dbObjects}; 14053} 14054 14055} 14056 14057} 14058 14059namespace sqlite_orm { 14060 14061namespace internal { 14062 14063template<class T, class L> 14064void iterate_ast(const T& t, L&& lambda); 14065 14066template<class... Args> 14067struct set_t { 14068using assigns_type = std::tuple<Args...>; 14069 14070assigns_type assigns; 14071}; 14072 14073template<class T> 14074struct is_set : std::false_type {}; 14075 14076template<class... Args> 14077struct is_set<set_t<Args...>> : std::true_type {}; 14078 14079struct dynamic_set_entry { 14080std::string serialized_value; 14081}; 14082 14083template<class C> 14084struct dynamic_set_t { 14085using context_t = C; 14086using entry_t = dynamic_set_entry; 14087using const_iterator = typename std::vector<entry_t>::const_iterator; 14088 14089dynamic_set_t(const context_t& context_) : context(context_), collector(this->context.db_objects) {} 14090 14091dynamic_set_t(const dynamic_set_t& other) = default; 14092dynamic_set_t(dynamic_set_t&& other) = default; 14093dynamic_set_t& operator=(const dynamic_set_t& other) = default; 14094dynamic_set_t& operator=(dynamic_set_t&& other) = default; 14095 14096template<class L, class R> 14097void push_back(assign_t<L, R> assign) { 14098auto newContext = this->context; 14099newContext.skip_table_name = true; 14100// note: we are only interested in the table name on the left-hand side of the assignment operator expression 14101iterate_ast(assign.lhs, this->collector); 14102std::stringstream ss; 14103ss << serialize(assign.lhs, newContext) << ' ' << assign.serialize() << ' ' 14104<< serialize(assign.rhs, context); 14105this->entries.push_back({ss.str()}); 14106} 14107 14108const_iterator begin() const { 14109return this->entries.begin(); 14110} 14111 14112const_iterator end() const { 14113return this->entries.end(); 14114} 14115 14116void clear() { 14117this->entries.clear(); 14118this->collector.table_names.clear(); 14119} 14120 14121std::vector<entry_t> entries; 14122context_t context; 14123table_name_collector<typename context_t::db_objects_type> collector; 14124}; 14125 14126template<class C> 14127struct is_set<dynamic_set_t<C>> : std::true_type {}; 14128 14129template<class C> 14130struct is_dynamic_set : std::false_type {}; 14131 14132template<class C> 14133struct 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*/ 14140template<class... Args> 14141internal::set_t<Args...> set(Args... args) { 14142using arg_tuple = std::tuple<Args...>; 14143static_assert(std::tuple_size<arg_tuple>::value == 14144internal::count_tuple<arg_tuple, internal::is_assign_t>::value, 14145"set function accepts assign operators only"); 14146return {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*/ 14152template<class S> 14153internal::dynamic_set_t<internal::serializer_context<typename S::db_objects_type>> dynamic_set(const S& storage) { 14154internal::serializer_context_builder<S> builder(storage); 14155return builder(); 14156} 14157} 14158 14159namespace sqlite_orm { 14160 14161namespace internal { 14162 14163struct prepared_statement_base { 14164sqlite3_stmt* stmt = nullptr; 14165connection_ref con; 14166 14167#ifndef SQLITE_ORM_AGGREGATE_NSDMI_SUPPORTED 14168prepared_statement_base(sqlite3_stmt* stmt, connection_ref con) : stmt{stmt}, con{std::move(con)} {} 14169#endif 14170 14171~prepared_statement_base() { 14172sqlite3_finalize(this->stmt); 14173} 14174 14175std::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 14178if (const char* sql = sqlite3_sql(this->stmt)) { 14179return sql; 14180} else { 14181return {}; 14182} 14183} 14184 14185#if SQLITE_VERSION_NUMBER >= 3014000 14186std::string expanded_sql() const { 14187// note: must check return value due to SQLITE_OMIT_TRACE 14188using char_ptr = std::unique_ptr<char, std::integral_constant<decltype(&sqlite3_free), sqlite3_free>>; 14189if (char_ptr sql{sqlite3_expanded_sql(this->stmt)}) { 14190return sql.get(); 14191} else { 14192return {}; 14193} 14194} 14195#endif 14196#if SQLITE_VERSION_NUMBER >= 3026000 and defined(SQLITE_ENABLE_NORMALIZE) 14197std::string normalized_sql() const { 14198if (const char* sql = sqlite3_normalized_sql(this->stmt)) { 14199return sql; 14200} else { 14201return {}; 14202} 14203} 14204#endif 14205 14206#ifdef SQLITE_ORM_STRING_VIEW_SUPPORTED 14207std::string_view column_name(int index) const { 14208return sqlite3_column_name(stmt, index); 14209} 14210#endif 14211}; 14212 14213template<class T> 14214struct prepared_statement_t : prepared_statement_base { 14215using expression_type = T; 14216 14217expression_type expression; 14218 14219prepared_statement_t(T expression_, sqlite3_stmt* stmt_, connection_ref con_) : 14220prepared_statement_base{stmt_, std::move(con_)}, expression(std::move(expression_)) {} 14221 14222prepared_statement_t(prepared_statement_t&& prepared_stmt) : 14223prepared_statement_base{prepared_stmt.stmt, std::move(prepared_stmt.con)}, 14224expression(std::move(prepared_stmt.expression)) { 14225prepared_stmt.stmt = nullptr; 14226} 14227}; 14228 14229template<class T> 14230SQLITE_ORM_INLINE_VAR constexpr bool is_prepared_statement_v = 14231polyfill::is_specialization_of<T, prepared_statement_t>::value; 14232 14233template<class T> 14234struct is_prepared_statement : polyfill::bool_constant<is_prepared_statement_v<T>> {}; 14235 14236/** 14237* T - type of object to obtain from a database 14238*/ 14239template<class T, class R, class... Args> 14240struct get_all_t { 14241using type = T; 14242using return_type = R; 14243 14244using conditions_type = std::tuple<Args...>; 14245 14246conditions_type conditions; 14247}; 14248 14249template<class T, class R, class... Args> 14250struct get_all_pointer_t { 14251using type = T; 14252using return_type = R; 14253 14254using conditions_type = std::tuple<Args...>; 14255 14256conditions_type conditions; 14257}; 14258 14259#ifdef SQLITE_ORM_OPTIONAL_SUPPORTED 14260template<class T, class R, class... Args> 14261struct get_all_optional_t { 14262using type = T; 14263using return_type = R; 14264 14265using conditions_type = std::tuple<Args...>; 14266 14267conditions_type conditions; 14268}; 14269#endif // SQLITE_ORM_OPTIONAL_SUPPORTED 14270 14271template<class S, class... Wargs> 14272struct update_all_t { 14273using set_type = S; 14274using conditions_type = std::tuple<Wargs...>; 14275 14276static_assert(is_set<S>::value, "update_all_t must have set or dynamic set as the first argument"); 14277 14278set_type set; 14279conditions_type conditions; 14280}; 14281 14282template<class T> 14283SQLITE_ORM_INLINE_VAR constexpr bool is_update_all_v = polyfill::is_specialization_of<T, update_all_t>::value; 14284 14285template<class T> 14286using is_update_all = polyfill::bool_constant<is_update_all_v<T>>; 14287 14288template<class T, class... Args> 14289struct remove_all_t { 14290using type = T; 14291using conditions_type = std::tuple<Args...>; 14292 14293conditions_type conditions; 14294}; 14295 14296template<class T> 14297SQLITE_ORM_INLINE_VAR constexpr bool is_remove_all_v = polyfill::is_specialization_of<T, remove_all_t>::value; 14298 14299template<class T> 14300using is_remove_all = polyfill::bool_constant<is_remove_all_v<T>>; 14301 14302template<class T, class... Ids> 14303struct get_t { 14304using type = T; 14305using ids_type = std::tuple<Ids...>; 14306 14307ids_type ids; 14308}; 14309 14310template<class T, class... Ids> 14311struct get_pointer_t { 14312using type = T; 14313using ids_type = std::tuple<Ids...>; 14314 14315ids_type ids; 14316}; 14317 14318#ifdef SQLITE_ORM_OPTIONAL_SUPPORTED 14319template<class T, class... Ids> 14320struct get_optional_t { 14321using type = T; 14322using ids_type = std::tuple<Ids...>; 14323 14324ids_type ids; 14325}; 14326#endif // SQLITE_ORM_OPTIONAL_SUPPORTED 14327 14328template<class T> 14329struct update_t { 14330using type = T; 14331 14332type object; 14333}; 14334 14335template<class T, class... Ids> 14336struct remove_t { 14337using type = T; 14338using ids_type = std::tuple<Ids...>; 14339 14340ids_type ids; 14341}; 14342 14343template<class T> 14344struct insert_t { 14345using type = T; 14346 14347type object; 14348}; 14349 14350template<class T> 14351SQLITE_ORM_INLINE_VAR constexpr bool is_insert_v = polyfill::is_specialization_of<T, insert_t>::value; 14352 14353template<class T> 14354struct is_insert : polyfill::bool_constant<is_insert_v<T>> {}; 14355 14356template<class T, class... Cols> 14357struct insert_explicit { 14358using type = T; 14359using columns_type = columns_t<Cols...>; 14360 14361type obj; 14362columns_type columns; 14363}; 14364 14365template<class T> 14366struct replace_t { 14367using type = T; 14368 14369type object; 14370}; 14371 14372template<class T> 14373SQLITE_ORM_INLINE_VAR constexpr bool is_replace_v = polyfill::is_specialization_of<T, replace_t>::value; 14374 14375template<class T> 14376struct is_replace : polyfill::bool_constant<is_replace_v<T>> {}; 14377 14378template<class It, class Projection, class O> 14379struct insert_range_t { 14380using iterator_type = It; 14381using transformer_type = Projection; 14382using object_type = O; 14383 14384std::pair<iterator_type, iterator_type> range; 14385transformer_type transformer; 14386}; 14387 14388template<class T> 14389SQLITE_ORM_INLINE_VAR constexpr bool is_insert_range_v = 14390polyfill::is_specialization_of<T, insert_range_t>::value; 14391 14392template<class T> 14393struct is_insert_range : polyfill::bool_constant<is_insert_range_v<T>> {}; 14394 14395template<class It, class Projection, class O> 14396struct replace_range_t { 14397using iterator_type = It; 14398using transformer_type = Projection; 14399using object_type = O; 14400 14401std::pair<iterator_type, iterator_type> range; 14402transformer_type transformer; 14403}; 14404 14405template<class T> 14406SQLITE_ORM_INLINE_VAR constexpr bool is_replace_range_v = 14407polyfill::is_specialization_of<T, replace_range_t>::value; 14408 14409template<class T> 14410struct is_replace_range : polyfill::bool_constant<is_replace_range_v<T>> {}; 14411 14412template<class... Args> 14413struct insert_raw_t { 14414using args_tuple = std::tuple<Args...>; 14415 14416args_tuple args; 14417}; 14418 14419template<class T> 14420SQLITE_ORM_INLINE_VAR constexpr bool is_insert_raw_v = polyfill::is_specialization_of<T, insert_raw_t>::value; 14421 14422template<class T> 14423struct is_insert_raw : polyfill::bool_constant<is_insert_raw_v<T>> {}; 14424 14425template<class... Args> 14426struct replace_raw_t { 14427using args_tuple = std::tuple<Args...>; 14428 14429args_tuple args; 14430}; 14431 14432template<class T> 14433SQLITE_ORM_INLINE_VAR constexpr bool is_replace_raw_v = polyfill::is_specialization_of<T, replace_raw_t>::value; 14434 14435template<class T> 14436struct is_replace_raw : polyfill::bool_constant<is_replace_raw_v<T>> {}; 14437 14438struct default_values_t {}; 14439 14440template<class T> 14441using is_default_values = std::is_same<T, default_values_t>; 14442 14443enum class conflict_action { 14444abort, 14445fail, 14446ignore, 14447replace, 14448rollback, 14449}; 14450 14451struct insert_constraint { 14452conflict_action action = conflict_action::abort; 14453 14454#ifndef SQLITE_ORM_AGGREGATE_NSDMI_SUPPORTED 14455insert_constraint(conflict_action action) : action{action} {} 14456#endif 14457}; 14458 14459template<class T> 14460using is_insert_constraint = std::is_same<T, insert_constraint>; 14461} 14462 14463inline internal::insert_constraint or_rollback() { 14464return {internal::conflict_action::rollback}; 14465} 14466 14467inline internal::insert_constraint or_replace() { 14468return {internal::conflict_action::replace}; 14469} 14470 14471inline internal::insert_constraint or_ignore() { 14472return {internal::conflict_action::ignore}; 14473} 14474 14475inline internal::insert_constraint or_fail() { 14476return {internal::conflict_action::fail}; 14477} 14478 14479inline internal::insert_constraint or_abort() { 14480return {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*/ 14491inline internal::default_values_t default_values() { 14492return {}; 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*/ 14532template<class... Args> 14533internal::insert_raw_t<Args...> insert(Args... args) { 14534using args_tuple = std::tuple<Args...>; 14535using internal::count_tuple; 14536using internal::is_columns; 14537using internal::is_insert_constraint; 14538using internal::is_into; 14539using internal::is_select; 14540using internal::is_upsert_clause; 14541using internal::is_values; 14542 14543constexpr int orArgsCount = count_tuple<args_tuple, is_insert_constraint>::value; 14544static_assert(orArgsCount < 2, "Raw insert must have only one OR... argument"); 14545 14546constexpr int intoArgsCount = count_tuple<args_tuple, is_into>::value; 14547static_assert(intoArgsCount != 0, "Raw insert must have into<T> argument"); 14548static_assert(intoArgsCount < 2, "Raw insert must have only one into<T> argument"); 14549 14550constexpr int columnsArgsCount = count_tuple<args_tuple, is_columns>::value; 14551static_assert(columnsArgsCount < 2, "Raw insert must have only one columns(...) argument"); 14552 14553constexpr int valuesArgsCount = count_tuple<args_tuple, is_values>::value; 14554static_assert(valuesArgsCount < 2, "Raw insert must have only one values(...) argument"); 14555 14556constexpr int defaultValuesCount = count_tuple<args_tuple, internal::is_default_values>::value; 14557static_assert(defaultValuesCount < 2, "Raw insert must have only one default_values() argument"); 14558 14559constexpr int selectsArgsCount = count_tuple<args_tuple, is_select>::value; 14560static_assert(selectsArgsCount < 2, "Raw insert must have only one select(...) argument"); 14561 14562constexpr int upsertClausesCount = count_tuple<args_tuple, is_upsert_clause>::value; 14563static_assert(upsertClausesCount <= 2, "Raw insert can contain 2 instances of upsert clause maximum"); 14564 14565constexpr int argsCount = int(std::tuple_size<args_tuple>::value); 14566static_assert(argsCount == intoArgsCount + columnsArgsCount + valuesArgsCount + defaultValuesCount + 14567selectsArgsCount + orArgsCount + upsertClausesCount, 14568"Raw insert has invalid arguments"); 14569 14570return {{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*/ 14604template<class... Args> 14605internal::replace_raw_t<Args...> replace(Args... args) { 14606using args_tuple = std::tuple<Args...>; 14607using internal::count_tuple; 14608using internal::is_columns; 14609using internal::is_into; 14610using internal::is_values; 14611 14612constexpr int intoArgsCount = count_tuple<args_tuple, is_into>::value; 14613static_assert(intoArgsCount != 0, "Raw replace must have into<T> argument"); 14614static_assert(intoArgsCount < 2, "Raw replace must have only one into<T> argument"); 14615 14616constexpr int columnsArgsCount = count_tuple<args_tuple, is_columns>::value; 14617static_assert(columnsArgsCount < 2, "Raw replace must have only one columns(...) argument"); 14618 14619constexpr int valuesArgsCount = count_tuple<args_tuple, is_values>::value; 14620static_assert(valuesArgsCount < 2, "Raw replace must have only one values(...) argument"); 14621 14622constexpr int defaultValuesCount = count_tuple<args_tuple, internal::is_default_values>::value; 14623static_assert(defaultValuesCount < 2, "Raw replace must have only one default_values() argument"); 14624 14625constexpr int selectsArgsCount = count_tuple<args_tuple, internal::is_select>::value; 14626static_assert(selectsArgsCount < 2, "Raw replace must have only one select(...) argument"); 14627 14628constexpr int argsCount = int(std::tuple_size<args_tuple>::value); 14629static_assert(argsCount == 14630intoArgsCount + columnsArgsCount + valuesArgsCount + defaultValuesCount + selectsArgsCount, 14631"Raw replace has invalid arguments"); 14632 14633return {{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*/ 14655template<class It, class Projection = polyfill::identity> 14656auto replace_range(It from, It to, Projection project = {}) { 14657using O = std::decay_t<decltype(polyfill::invoke(std::declval<Projection>(), *std::declval<It>()))>; 14658return 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*/ 14665template<class O, class It, class Projection = polyfill::identity> 14666internal::replace_range_t<It, Projection, O> replace_range(It from, It to, Projection project = {}) { 14667return {{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*/ 14689template<class It, class Projection = polyfill::identity> 14690auto insert_range(It from, It to, Projection project = {}) { 14691using O = std::decay_t<decltype(polyfill::invoke(std::declval<Projection>(), *std::declval<It>()))>; 14692return 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*/ 14699template<class O, class It, class Projection = polyfill::identity> 14700internal::insert_range_t<It, Projection, O> insert_range(It from, It to, Projection project = {}) { 14701return {{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*/ 14711template<class T> 14712internal::replace_t<T> replace(T obj) { 14713return {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*/ 14723template<class T> 14724internal::insert_t<T> insert(T obj) { 14725return {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*/ 14736template<class T, class... Cols> 14737internal::insert_explicit<T, Cols...> insert(T obj, internal::columns_t<Cols...> cols) { 14738return {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*/ 14746template<class T, class... Ids> 14747internal::remove_t<T, Ids...> remove(Ids... ids) { 14748return {{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*/ 14757template<orm_table_reference auto table, class... Ids> 14758auto remove(Ids... ids) { 14759return 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*/ 14770template<class T> 14771internal::update_t<T> update(T obj) { 14772return {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*/ 14780template<class T, class... Ids> 14781internal::get_t<T, Ids...> get(Ids... ids) { 14782return {{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*/ 14791template<orm_table_reference auto table, class... Ids> 14792auto get(Ids... ids) { 14793return 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*/ 14802template<class T, class... Ids> 14803internal::get_pointer_t<T, Ids...> get_pointer(Ids... ids) { 14804return {{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*/ 14813template<orm_table_reference auto table, class... Ids> 14814auto get_pointer(Ids... ids) { 14815return 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*/ 14825template<class T, class... Ids> 14826internal::get_optional_t<T, Ids...> get_optional(Ids... ids) { 14827return {{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*/ 14837template<orm_table_reference auto table, class... Ids> 14838auto get_optional(Ids... ids) { 14839return 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*/ 14848template<class T, class... Args> 14849internal::remove_all_t<T, Args...> remove_all(Args... args) { 14850using args_tuple = std::tuple<Args...>; 14851internal::validate_conditions<args_tuple>(); 14852return {{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*/ 14861template<orm_table_reference auto table, class... Args> 14862auto remove_all(Args... args) { 14863return 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*/ 14873template<class T, class R = std::vector<internal::mapped_type_proxy_t<T>>, class... Args> 14874internal::get_all_t<T, R, Args...> get_all(Args... conditions) { 14875using conditions_tuple = std::tuple<Args...>; 14876internal::validate_conditions<conditions_tuple>(); 14877return {{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*/ 14887template<orm_refers_to_table auto mapped, 14888class R = std::vector<internal::mapped_type_proxy_t<decltype(mapped)>>, 14889class... Args> 14890auto get_all(Args&&... conditions) { 14891return 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*/ 14899template<class S, class... Wargs> 14900internal::update_all_t<S, Wargs...> update_all(S set, Wargs... wh) { 14901static_assert(internal::is_set<S>::value, "first argument in update_all can be either set or dynamic_set"); 14902using args_tuple = std::tuple<Wargs...>; 14903internal::validate_conditions<args_tuple>(); 14904return {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*/ 14913template<class T, class R = std::vector<std::unique_ptr<T>>, class... Args> 14914internal::get_all_pointer_t<T, R, Args...> get_all_pointer(Args... conditions) { 14915using conditions_tuple = std::tuple<Args...>; 14916internal::validate_conditions<conditions_tuple>(); 14917return {{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*/ 14927template<orm_table_reference auto table, 14928class R = std::vector<internal::auto_decay_table_ref_t<table>>, 14929class... Args> 14930auto get_all_pointer(Args... conditions) { 14931return 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*/ 14942template<class T, class R = std::vector<std::optional<T>>, class... Args> 14943internal::get_all_optional_t<T, R, Args...> get_all_optional(Args... conditions) { 14944using conditions_tuple = std::tuple<Args...>; 14945internal::validate_conditions<conditions_tuple>(); 14946return {{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*/ 14957template<orm_table_reference auto table, 14958class R = std::vector<internal::auto_decay_table_ref_t<table>>, 14959class... Args> 14960auto get_all_optional(Args&&... conditions) { 14961return 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 14974namespace sqlite_orm { 14975namespace internal { 14976 14977template<class T> 14978struct excluded_t { 14979using expression_type = T; 14980 14981expression_type expression; 14982}; 14983} 14984 14985template<class T> 14986internal::excluded_t<T> excluded(T expression) { 14987return {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 15005namespace sqlite_orm { 15006namespace internal { 15007 15008template<class T> 15009struct exists_t : condition_t, negatable_t { 15010using expression_type = T; 15011using self = exists_t<expression_type>; 15012 15013expression_type expression; 15014 15015exists_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), 15022where(exists(select(asterisk<Customer>(), 15023where(is_equal(&Customer::grade, 3) and 15024is_equal(&Agent::code, &Customer::agentCode))))), 15025order_by(&Agent::comission)); 15026*/ 15027template<class T> 15028internal::exists_t<T> exists(T expression) { 15029return {std::move(expression)}; 15030} 15031} 15032 15033// #include "ast/set.h" 15034 15035// #include "ast/match.h" 15036 15037#include <utility> // std::move 15038 15039namespace sqlite_orm { 15040namespace internal { 15041 15042template<class T, class X> 15043struct match_t { 15044using mapped_type = T; 15045using argument_type = X; 15046 15047argument_type argument; 15048 15049match_t(argument_type argument) : argument(std::move(argument)) {} 15050}; 15051} 15052 15053template<class T, class X> 15054internal::match_t<T, X> match(X argument) { 15055return {std::move(argument)}; 15056} 15057} 15058 15059namespace sqlite_orm { 15060 15061namespace 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*/ 15079template<class T, class SFINAE = void> 15080struct ast_iterator { 15081using node_type = T; 15082 15083/** 15084* L is a callable type. Mostly is a templated lambda 15085*/ 15086template<class L> 15087void operator()(const T& t, L& lambda) const { 15088lambda(t); 15089} 15090}; 15091 15092/** 15093* Simplified API 15094*/ 15095template<class T, class L> 15096void iterate_ast(const T& t, L&& lambda) { 15097ast_iterator<T> iterator; 15098iterator(t, lambda); 15099} 15100 15101#ifdef SQLITE_ORM_OPTIONAL_SUPPORTED 15102template<class T> 15103struct ast_iterator<as_optional_t<T>, void> { 15104using node_type = as_optional_t<T>; 15105 15106template<class L> 15107void operator()(const node_type& node, L& lambda) const { 15108iterate_ast(node.expression, lambda); 15109} 15110}; 15111#endif // SQLITE_ORM_OPTIONAL_SUPPORTED 15112 15113template<class T> 15114struct ast_iterator<std::reference_wrapper<T>, void> { 15115using node_type = std::reference_wrapper<T>; 15116 15117template<class L> 15118void operator()(const node_type& expression, L& lambda) const { 15119iterate_ast(expression.get(), lambda); 15120} 15121}; 15122 15123template<class T, class X> 15124struct ast_iterator<match_t<T, X>, void> { 15125using node_type = match_t<T, X>; 15126 15127template<class L> 15128void operator()(const node_type& node, L& lambda) const { 15129iterate_ast(node.argument, lambda); 15130} 15131}; 15132 15133template<class... Args> 15134struct ast_iterator<group_by_t<Args...>, void> { 15135using node_type = group_by_t<Args...>; 15136 15137template<class L> 15138void operator()(const node_type& expression, L& lambda) const { 15139iterate_ast(expression.args, lambda); 15140} 15141}; 15142 15143template<class T, class X, class Y, class Z> 15144struct ast_iterator<highlight_t<T, X, Y, Z>, void> { 15145using node_type = highlight_t<T, X, Y, Z>; 15146 15147template<class L> 15148void operator()(const node_type& expression, L& lambda) const { 15149lambda(expression); 15150iterate_ast(expression.argument0, lambda); 15151iterate_ast(expression.argument1, lambda); 15152iterate_ast(expression.argument2, lambda); 15153} 15154}; 15155 15156template<class T> 15157struct ast_iterator<excluded_t<T>, void> { 15158using node_type = excluded_t<T>; 15159 15160template<class L> 15161void operator()(const node_type& expression, L& lambda) const { 15162iterate_ast(expression.expression, lambda); 15163} 15164}; 15165 15166template<class T> 15167struct ast_iterator<T, match_if<is_upsert_clause, T>> { 15168using node_type = T; 15169 15170template<class L> 15171void operator()(const node_type& expression, L& lambda) const { 15172iterate_ast(expression.actions, lambda); 15173} 15174}; 15175 15176template<class C> 15177struct ast_iterator<where_t<C>, void> { 15178using node_type = where_t<C>; 15179 15180template<class L> 15181void operator()(const node_type& expression, L& lambda) const { 15182iterate_ast(expression.expression, lambda); 15183} 15184}; 15185 15186template<class T> 15187struct ast_iterator< 15188T, 15189std::enable_if_t<polyfill::disjunction<is_binary_condition<T>, is_binary_operator<T>>::value>> { 15190using node_type = T; 15191 15192template<class L> 15193void operator()(const node_type& node, L& lambda) const { 15194iterate_ast(node.lhs, lambda); 15195iterate_ast(node.rhs, lambda); 15196} 15197}; 15198 15199template<class L, class R> 15200struct ast_iterator<is_equal_with_table_t<L, R>, void> { 15201using node_type = is_equal_with_table_t<L, R>; 15202 15203template<class C> 15204void operator()(const node_type& node, C& lambda) const { 15205iterate_ast(node.rhs, lambda); 15206} 15207}; 15208 15209template<class C> 15210struct ast_iterator<C, std::enable_if_t<polyfill::disjunction<is_columns<C>, is_struct<C>>::value>> { 15211using node_type = C; 15212 15213template<class L> 15214void operator()(const node_type& cols, L& lambda) const { 15215iterate_ast(cols.columns, lambda); 15216} 15217}; 15218 15219template<class L, class A> 15220struct ast_iterator<dynamic_in_t<L, A>, void> { 15221using node_type = dynamic_in_t<L, A>; 15222 15223template<class C> 15224void operator()(const node_type& in, C& lambda) const { 15225iterate_ast(in.left, lambda); 15226iterate_ast(in.argument, lambda); 15227} 15228}; 15229 15230template<class L, class... Args> 15231struct ast_iterator<in_t<L, Args...>, void> { 15232using node_type = in_t<L, Args...>; 15233 15234template<class C> 15235void operator()(const node_type& in, C& lambda) const { 15236iterate_ast(in.left, lambda); 15237iterate_ast(in.argument, lambda); 15238} 15239}; 15240 15241template<class T> 15242struct ast_iterator<std::vector<T>, void> { 15243using node_type = std::vector<T>; 15244 15245template<class L> 15246void operator()(const node_type& vec, L& lambda) const { 15247for (auto& i: vec) { 15248iterate_ast(i, lambda); 15249} 15250} 15251}; 15252 15253template<> 15254struct ast_iterator<std::vector<char>, void> { 15255using node_type = std::vector<char>; 15256 15257template<class L> 15258void operator()(const node_type& vec, L& lambda) const { 15259lambda(vec); 15260} 15261}; 15262 15263#if (SQLITE_VERSION_NUMBER >= 3008003) && defined(SQLITE_ORM_WITH_CTE) 15264template<class CTE> 15265struct ast_iterator<CTE, match_specialization_of<CTE, common_table_expression>> { 15266using node_type = CTE; 15267 15268template<class L> 15269void operator()(const node_type& c, L& lambda) const { 15270iterate_ast(c.subselect, lambda); 15271} 15272}; 15273 15274template<class With> 15275struct ast_iterator<With, match_specialization_of<With, with_t>> { 15276using node_type = With; 15277 15278template<class L> 15279void operator()(const node_type& c, L& lambda) const { 15280iterate_ast(c.cte, lambda); 15281iterate_ast(c.expression, lambda); 15282} 15283}; 15284#endif 15285 15286template<class T> 15287struct ast_iterator<T, match_if<is_compound_operator, T>> { 15288using node_type = T; 15289 15290template<class L> 15291void operator()(const node_type& c, L& lambda) const { 15292iterate_ast(c.compound, lambda); 15293} 15294}; 15295 15296template<class T> 15297struct ast_iterator<into_t<T>, void> { 15298using node_type = into_t<T>; 15299 15300template<class L> 15301void operator()(const node_type& /*node*/, L& /*lambda*/) const { 15302//.. 15303} 15304}; 15305 15306template<class... Args> 15307struct ast_iterator<insert_raw_t<Args...>, void> { 15308using node_type = insert_raw_t<Args...>; 15309 15310template<class L> 15311void operator()(const node_type& node, L& lambda) const { 15312iterate_ast(node.args, lambda); 15313} 15314}; 15315 15316template<class... Args> 15317struct ast_iterator<replace_raw_t<Args...>, void> { 15318using node_type = replace_raw_t<Args...>; 15319 15320template<class L> 15321void operator()(const node_type& node, L& lambda) const { 15322iterate_ast(node.args, lambda); 15323} 15324}; 15325 15326template<class T, class... Args> 15327struct ast_iterator<select_t<T, Args...>, void> { 15328using node_type = select_t<T, Args...>; 15329 15330template<class L> 15331void operator()(const node_type& sel, L& lambda) const { 15332iterate_ast(sel.col, lambda); 15333iterate_ast(sel.conditions, lambda); 15334} 15335}; 15336 15337template<class T, class R, class... Args> 15338struct ast_iterator<get_all_t<T, R, Args...>, void> { 15339using node_type = get_all_t<T, R, Args...>; 15340 15341template<class L> 15342void operator()(const node_type& get, L& lambda) const { 15343iterate_ast(get.conditions, lambda); 15344} 15345}; 15346 15347template<class T, class... Args> 15348struct ast_iterator<get_all_pointer_t<T, Args...>, void> { 15349using node_type = get_all_pointer_t<T, Args...>; 15350 15351template<class L> 15352void operator()(const node_type& get, L& lambda) const { 15353iterate_ast(get.conditions, lambda); 15354} 15355}; 15356 15357#ifdef SQLITE_ORM_OPTIONAL_SUPPORTED 15358template<class T, class... Args> 15359struct ast_iterator<get_all_optional_t<T, Args...>, void> { 15360using node_type = get_all_optional_t<T, Args...>; 15361 15362template<class L> 15363void operator()(const node_type& get, L& lambda) const { 15364iterate_ast(get.conditions, lambda); 15365} 15366}; 15367#endif // SQLITE_ORM_OPTIONAL_SUPPORTED 15368 15369template<class S, class... Wargs> 15370struct ast_iterator<update_all_t<S, Wargs...>, void> { 15371using node_type = update_all_t<S, Wargs...>; 15372 15373template<class L> 15374void operator()(const node_type& u, L& lambda) const { 15375iterate_ast(u.set, lambda); 15376iterate_ast(u.conditions, lambda); 15377} 15378}; 15379 15380template<class T, class... Args> 15381struct ast_iterator<remove_all_t<T, Args...>, void> { 15382using node_type = remove_all_t<T, Args...>; 15383 15384template<class L> 15385void operator()(const node_type& r, L& lambda) const { 15386iterate_ast(r.conditions, lambda); 15387} 15388}; 15389 15390template<class... Args> 15391struct ast_iterator<set_t<Args...>, void> { 15392using node_type = set_t<Args...>; 15393 15394template<class L> 15395void operator()(const node_type& node, L& lambda) const { 15396iterate_ast(node.assigns, lambda); 15397} 15398}; 15399 15400template<class S> 15401struct ast_iterator<dynamic_set_t<S>, void> { 15402using node_type = dynamic_set_t<S>; 15403 15404template<class L> 15405void operator()(const node_type& node, L& lambda) const { 15406iterate_ast(node.entries, lambda); 15407} 15408}; 15409 15410template<class... Args> 15411struct ast_iterator<std::tuple<Args...>, void> { 15412using node_type = std::tuple<Args...>; 15413 15414template<class L> 15415void operator()(const node_type& node, L& lambda) const { 15416iterate_tuple(node, [&lambda](auto& v) { 15417iterate_ast(v, lambda); 15418}); 15419} 15420}; 15421 15422template<class T, class... Args> 15423struct ast_iterator<group_by_with_having<T, Args...>, void> { 15424using node_type = group_by_with_having<T, Args...>; 15425 15426template<class L> 15427void operator()(const node_type& node, L& lambda) const { 15428iterate_ast(node.args, lambda); 15429iterate_ast(node.expression, lambda); 15430} 15431}; 15432 15433template<class T, class E> 15434struct ast_iterator<cast_t<T, E>, void> { 15435using node_type = cast_t<T, E>; 15436 15437template<class L> 15438void operator()(const node_type& c, L& lambda) const { 15439iterate_ast(c.expression, lambda); 15440} 15441}; 15442 15443template<class T> 15444struct ast_iterator<exists_t<T>, void> { 15445using node_type = exists_t<T>; 15446 15447template<class L> 15448void operator()(const node_type& node, L& lambda) const { 15449iterate_ast(node.expression, lambda); 15450} 15451}; 15452 15453template<class A, class T, class E> 15454struct ast_iterator<like_t<A, T, E>, void> { 15455using node_type = like_t<A, T, E>; 15456 15457template<class L> 15458void operator()(const node_type& lk, L& lambda) const { 15459iterate_ast(lk.arg, lambda); 15460iterate_ast(lk.pattern, lambda); 15461lk.arg3.apply([&lambda](auto& value) { 15462iterate_ast(value, lambda); 15463}); 15464} 15465}; 15466 15467template<class A, class T> 15468struct ast_iterator<glob_t<A, T>, void> { 15469using node_type = glob_t<A, T>; 15470 15471template<class L> 15472void operator()(const node_type& lk, L& lambda) const { 15473iterate_ast(lk.arg, lambda); 15474iterate_ast(lk.pattern, lambda); 15475} 15476}; 15477 15478template<class A, class T> 15479struct ast_iterator<between_t<A, T>, void> { 15480using node_type = between_t<A, T>; 15481 15482template<class L> 15483void operator()(const node_type& b, L& lambda) const { 15484iterate_ast(b.expr, lambda); 15485iterate_ast(b.b1, lambda); 15486iterate_ast(b.b2, lambda); 15487} 15488}; 15489 15490template<class T> 15491struct ast_iterator<named_collate<T>, void> { 15492using node_type = named_collate<T>; 15493 15494template<class L> 15495void operator()(const node_type& col, L& lambda) const { 15496iterate_ast(col.expr, lambda); 15497} 15498}; 15499 15500template<class C> 15501struct ast_iterator<negated_condition_t<C>, void> { 15502using node_type = negated_condition_t<C>; 15503 15504template<class L> 15505void operator()(const node_type& neg, L& lambda) const { 15506iterate_ast(neg.c, lambda); 15507} 15508}; 15509 15510template<class T> 15511struct ast_iterator<is_null_t<T>, void> { 15512using node_type = is_null_t<T>; 15513 15514template<class L> 15515void operator()(const node_type& i, L& lambda) const { 15516iterate_ast(i.t, lambda); 15517} 15518}; 15519 15520template<class T> 15521struct ast_iterator<is_not_null_t<T>, void> { 15522using node_type = is_not_null_t<T>; 15523 15524template<class L> 15525void operator()(const node_type& i, L& lambda) const { 15526iterate_ast(i.t, lambda); 15527} 15528}; 15529 15530template<class F, class... CallArgs> 15531struct ast_iterator<function_call<F, CallArgs...>, void> { 15532using node_type = function_call<F, CallArgs...>; 15533 15534template<class L> 15535void operator()(const node_type& f, L& lambda) const { 15536iterate_ast(f.callArgs, lambda); 15537} 15538}; 15539 15540template<class R, class S, class... Args> 15541struct ast_iterator<built_in_function_t<R, S, Args...>, void> { 15542using node_type = built_in_function_t<R, S, Args...>; 15543 15544template<class L> 15545void operator()(const node_type& node, L& lambda) const { 15546iterate_ast(node.args, lambda); 15547} 15548}; 15549 15550template<class R, class S, class... Args> 15551struct ast_iterator<built_in_aggregate_function_t<R, S, Args...>, void> { 15552using node_type = built_in_aggregate_function_t<R, S, Args...>; 15553 15554template<class L> 15555void operator()(const node_type& node, L& lambda) const { 15556iterate_ast(node.args, lambda); 15557} 15558}; 15559 15560template<class F, class W> 15561struct ast_iterator<filtered_aggregate_function<F, W>, void> { 15562using node_type = filtered_aggregate_function<F, W>; 15563 15564template<class L> 15565void operator()(const node_type& node, L& lambda) const { 15566iterate_ast(node.function, lambda); 15567iterate_ast(node.where, lambda); 15568} 15569}; 15570 15571template<class Join> 15572struct ast_iterator<Join, match_if<is_constrained_join, Join>> { 15573using node_type = Join; 15574 15575template<class L> 15576void operator()(const node_type& join, L& lambda) const { 15577iterate_ast(join.constraint, lambda); 15578} 15579}; 15580 15581template<class T> 15582struct ast_iterator<on_t<T>, void> { 15583using node_type = on_t<T>; 15584 15585template<class L> 15586void operator()(const node_type& on, L& lambda) const { 15587iterate_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. 15593template<class T> 15594struct ast_iterator<T, std::enable_if_t<polyfill::is_specialization_of<T, using_t>::value>> { 15595using node_type = T; 15596 15597template<class L> 15598void operator()(const node_type& o, L& lambda) const { 15599iterate_ast(o.column, lambda); 15600} 15601}; 15602 15603template<class R, class T, class E, class... Args> 15604struct ast_iterator<simple_case_t<R, T, E, Args...>, void> { 15605using node_type = simple_case_t<R, T, E, Args...>; 15606 15607template<class L> 15608void operator()(const node_type& c, L& lambda) const { 15609c.case_expression.apply([&lambda](auto& c_) { 15610iterate_ast(c_, lambda); 15611}); 15612iterate_tuple(c.args, [&lambda](auto& pair) { 15613iterate_ast(pair.first, lambda); 15614iterate_ast(pair.second, lambda); 15615}); 15616c.else_expression.apply([&lambda](auto& el) { 15617iterate_ast(el, lambda); 15618}); 15619} 15620}; 15621 15622template<class T, class E> 15623struct ast_iterator<as_t<T, E>, void> { 15624using node_type = as_t<T, E>; 15625 15626template<class L> 15627void operator()(const node_type& a, L& lambda) const { 15628iterate_ast(a.expression, lambda); 15629} 15630}; 15631 15632template<class T, bool OI> 15633struct ast_iterator<limit_t<T, false, OI, void>, void> { 15634using node_type = limit_t<T, false, OI, void>; 15635 15636template<class L> 15637void operator()(const node_type& a, L& lambda) const { 15638iterate_ast(a.lim, lambda); 15639} 15640}; 15641 15642template<class T, class O> 15643struct ast_iterator<limit_t<T, true, false, O>, void> { 15644using node_type = limit_t<T, true, false, O>; 15645 15646template<class L> 15647void operator()(const node_type& a, L& lambda) const { 15648iterate_ast(a.lim, lambda); 15649a.off.apply([&lambda](auto& value) { 15650iterate_ast(value, lambda); 15651}); 15652} 15653}; 15654 15655template<class T, class O> 15656struct ast_iterator<limit_t<T, true, true, O>, void> { 15657using node_type = limit_t<T, true, true, O>; 15658 15659template<class L> 15660void operator()(const node_type& a, L& lambda) const { 15661a.off.apply([&lambda](auto& value) { 15662iterate_ast(value, lambda); 15663}); 15664iterate_ast(a.lim, lambda); 15665} 15666}; 15667 15668template<class T> 15669struct ast_iterator<distinct_t<T>, void> { 15670using node_type = distinct_t<T>; 15671 15672template<class L> 15673void operator()(const node_type& a, L& lambda) const { 15674iterate_ast(a.expression, lambda); 15675} 15676}; 15677 15678template<class T> 15679struct ast_iterator<all_t<T>, void> { 15680using node_type = all_t<T>; 15681 15682template<class L> 15683void operator()(const node_type& a, L& lambda) const { 15684iterate_ast(a.expression, lambda); 15685} 15686}; 15687 15688template<class T> 15689struct ast_iterator<bitwise_not_t<T>, void> { 15690using node_type = bitwise_not_t<T>; 15691 15692template<class L> 15693void operator()(const node_type& a, L& lambda) const { 15694iterate_ast(a.argument, lambda); 15695} 15696}; 15697 15698template<class... Args> 15699struct ast_iterator<values_t<Args...>, void> { 15700using node_type = values_t<Args...>; 15701 15702template<class L> 15703void operator()(const node_type& node, L& lambda) const { 15704iterate_ast(node.tuple, lambda); 15705} 15706}; 15707 15708template<class T> 15709struct ast_iterator<dynamic_values_t<T>, void> { 15710using node_type = dynamic_values_t<T>; 15711 15712template<class L> 15713void operator()(const node_type& node, L& lambda) const { 15714iterate_ast(node.vector, lambda); 15715} 15716}; 15717 15718/** 15719* Column alias or literal: skipped 15720*/ 15721template<class T> 15722struct ast_iterator<T, 15723std::enable_if_t<polyfill::disjunction<polyfill::is_specialization_of<T, alias_holder>, 15724polyfill::is_specialization_of<T, literal_holder>, 15725is_column_alias<T>>::value>> { 15726using node_type = T; 15727 15728template<class L> 15729void operator()(const node_type& /*node*/, L& /*lambda*/) const {} 15730}; 15731 15732template<class E> 15733struct ast_iterator<order_by_t<E>, void> { 15734using node_type = order_by_t<E>; 15735 15736template<class L> 15737void operator()(const node_type& node, L& lambda) const { 15738iterate_ast(node.expression, lambda); 15739} 15740}; 15741 15742template<class T> 15743struct ast_iterator<collate_t<T>, void> { 15744using node_type = collate_t<T>; 15745 15746template<class L> 15747void operator()(const node_type& node, L& lambda) const { 15748iterate_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 15761namespace sqlite_orm { 15762 15763namespace 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*/ 15777template<class T, class S, class... Args> 15778struct mapped_view { 15779using mapped_type = T; 15780using storage_type = S; 15781using db_objects_type = typename S::db_objects_type; 15782 15783storage_type& storage; 15784connection_ref connection; 15785get_all_t<T, void, Args...> expression; 15786 15787mapped_view(storage_type& storage, connection_ref conn, Args&&... args) : 15788storage(storage), connection(std::move(conn)), expression{{std::forward<Args>(args)...}} {} 15789 15790size_t size() const { 15791return this->storage.template count<T>(); 15792} 15793 15794bool empty() const { 15795return !this->size(); 15796} 15797 15798mapped_iterator<T, db_objects_type> begin() { 15799using context_t = serializer_context<db_objects_type>; 15800auto& dbObjects = obtain_db_objects(this->storage); 15801context_t context{dbObjects}; 15802context.skip_table_name = false; 15803context.replace_bindable_with_question = true; 15804 15805statement_finalizer stmt{prepare_stmt(this->connection.get(), serialize(this->expression, context))}; 15806iterate_ast(this->expression.conditions, conditional_binder{stmt.get()}); 15807return {dbObjects, std::move(stmt)}; 15808} 15809 15810mapped_iterator<T, db_objects_type> end() { 15811return {}; 15812} 15813}; 15814} 15815} 15816 15817#ifdef SQLITE_ORM_CPP20_RANGES_SUPPORTED 15818template<class T, class S, class... Args> 15819inline 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) && \ 15828defined(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) 15852namespace sqlite_orm::internal { 15853 15854template<class ColResult, class DBOs> 15855class result_set_iterator; 15856 15857#ifdef SQLITE_ORM_STL_HAS_DEFAULT_SENTINEL 15858using result_set_sentinel_t = std::default_sentinel_t; 15859#else 15860// sentinel 15861template<> 15862class result_set_iterator<void, void> {}; 15863 15864using 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*/ 15870template<class ColResult, class DBOs> 15871class result_set_iterator { 15872public: 15873using db_objects_type = DBOs; 15874 15875#ifdef SQLITE_ORM_CPP20_CONCEPTS_SUPPORTED 15876using iterator_concept = std::input_iterator_tag; 15877#else 15878using iterator_category = std::input_iterator_tag; 15879#endif 15880using difference_type = ptrdiff_t; 15881using value_type = column_result_proxy_t<ColResult>; 15882 15883public: 15884result_set_iterator(const db_objects_type& dbObjects, statement_finalizer stmt) : 15885db_objects{dbObjects}, stmt{std::move(stmt)} { 15886this->step(); 15887} 15888result_set_iterator(result_set_iterator&&) = default; 15889result_set_iterator& operator=(result_set_iterator&&) = default; 15890result_set_iterator(const result_set_iterator&) = delete; 15891result_set_iterator& operator=(const result_set_iterator&) = delete; 15892 15893/** @pre `*this != std::default_sentinel` */ 15894value_type operator*() const { 15895return this->extract(); 15896} 15897 15898result_set_iterator& operator++() { 15899this->step(); 15900return *this; 15901} 15902 15903void operator++(int) { 15904++*this; 15905} 15906 15907friend bool operator==(const result_set_iterator& it, const result_set_sentinel_t&) noexcept { 15908return sqlite3_data_count(it.stmt.get()) == 0; 15909} 15910 15911private: 15912void step() { 15913perform_step(this->stmt.get(), [](sqlite3_stmt*) {}); 15914} 15915 15916value_type extract() const { 15917const auto rowExtractor = make_row_extractor<ColResult>(this->db_objects.get()); 15918return rowExtractor.extract(this->stmt.get(), 0); 15919} 15920 15921private: 15922std::reference_wrapper<const db_objects_type> db_objects; 15923statement_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) 15939namespace 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*/ 15946template<class Select, class DBOs> 15947struct result_set_view 15948#ifdef SQLITE_ORM_CPP20_RANGES_SUPPORTED 15949: std::ranges::view_interface<result_set_view<Select, DBOs>> 15950#endif 15951{ 15952using db_objects_type = DBOs; 15953using expression_type = Select; 15954 15955result_set_view(const db_objects_type& dbObjects, connection_ref conn, Select expression) : 15956db_objects{dbObjects}, connection{std::move(conn)}, expression{std::move(expression)} {} 15957 15958result_set_view(result_set_view&&) = default; 15959result_set_view& operator=(result_set_view&&) = default; 15960result_set_view(const result_set_view&) = default; 15961result_set_view& operator=(const result_set_view&) = default; 15962 15963auto begin() { 15964const auto& exprDBOs = db_objects_for_expression(this->db_objects.get(), this->expression); 15965using ExprDBOs = std::remove_cvref_t<decltype(exprDBOs)>; 15966// note: Select can be `select_t` or `with_t` 15967using select_type = polyfill::detected_or_t<expression_type, expression_type_t, expression_type>; 15968using column_result_type = column_result_of_t<ExprDBOs, select_type>; 15969using context_t = serializer_context<ExprDBOs>; 15970context_t context{exprDBOs}; 15971context.skip_table_name = false; 15972context.replace_bindable_with_question = true; 15973 15974statement_finalizer stmt{prepare_stmt(this->connection.get(), serialize(this->expression, context))}; 15975iterate_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. 15979using iterator_type = result_set_iterator<column_result_type, db_objects_type>; 15980return iterator_type{this->db_objects, std::move(stmt)}; 15981} 15982 15983result_set_sentinel_t end() { 15984return {}; 15985} 15986 15987private: 15988std::reference_wrapper<const db_objects_type> db_objects; 15989connection_ref connection; 15990expression_type expression; 15991}; 15992} 15993 15994#ifdef SQLITE_ORM_CPP20_RANGES_SUPPORTED 15995template<class Select, class DBOs> 15996inline 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 16030namespace sqlite_orm { 16031namespace internal { 16032namespace polyfill { 16033#if __cpp_lib_apply >= 201603L 16034using std::apply; 16035#else 16036template<class Callable, class Tpl, size_t... Idx> 16037decltype(auto) apply(Callable&& callable, Tpl&& tpl, std::index_sequence<Idx...>) { 16038return polyfill::invoke(std::forward<Callable>(callable), std::get<Idx>(std::forward<Tpl>(tpl))...); 16039} 16040 16041template<class Callable, class Tpl> 16042decltype(auto) apply(Callable&& callable, Tpl&& tpl) { 16043constexpr size_t size = std::tuple_size<std::remove_reference_t<Tpl>>::value; 16044return apply(std::forward<Callable>(callable), 16045std::forward<Tpl>(tpl), 16046std::make_index_sequence<size>{}); 16047} 16048#endif 16049} 16050} 16051 16052namespace 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 16107namespace sqlite_orm { 16108namespace internal { 16109template<class O> 16110struct order_by_t; 16111 16112template<class T, class Ctx> 16113auto serialize(const T& t, const Ctx& context); 16114 16115template<class T, class Ctx> 16116std::string serialize_order_by(const T&, const Ctx&); 16117 16118inline void stream_sql_escaped(std::ostream& os, serialize_arg_type str, char char2Escape) { 16119for (size_t offset = 0, next; true; offset = next + 1) { 16120next = str.find(char2Escape, offset); 16121 16122if (next == str.npos) SQLITE_ORM_CPP_LIKELY { 16123os.write(str.data() + offset, str.size() - offset); 16124break; 16125} 16126 16127os.write(str.data() + offset, next - offset + 1); 16128os.write(&char2Escape, 1); 16129} 16130} 16131 16132inline void stream_identifier(std::ostream& ss, 16133serialize_arg_type qualifier, 16134serialize_arg_type identifier, 16135serialize_arg_type alias) { 16136constexpr char quoteChar = '"'; 16137constexpr char qualified[] = {quoteChar, '.', '\0'}; 16138constexpr 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 16143if (!qualifier.empty()) { 16144ss << quoteChar; 16145stream_sql_escaped(ss, qualifier, quoteChar); 16146ss << qualified; 16147} 16148{ 16149ss << quoteChar; 16150stream_sql_escaped(ss, identifier, quoteChar); 16151ss << quoteChar; 16152} 16153if (!alias.empty()) { 16154ss << aliased; 16155stream_sql_escaped(ss, alias, quoteChar); 16156ss << quoteChar; 16157} 16158} 16159 16160inline void stream_identifier(std::ostream& ss, const std::string& identifier, const std::string& alias) { 16161return stream_identifier(ss, "", identifier, alias); 16162} 16163 16164inline void stream_identifier(std::ostream& ss, const std::string& identifier) { 16165return stream_identifier(ss, "", identifier, ""); 16166} 16167 16168template<typename Tpl, size_t... Is> 16169void stream_identifier(std::ostream& ss, const Tpl& tpl, std::index_sequence<Is...>) { 16170static_assert(sizeof...(Is) > 0 && sizeof...(Is) <= 3, ""); 16171return stream_identifier(ss, std::get<Is>(tpl)...); 16172} 16173 16174template<typename Tpl, 16175std::enable_if_t<polyfill::is_detected<type_t, std::tuple_size<Tpl>>::value, bool> = true> 16176void stream_identifier(std::ostream& ss, const Tpl& tpl) { 16177return stream_identifier(ss, tpl, std::make_index_sequence<std::tuple_size<Tpl>::value>{}); 16178} 16179 16180enum class stream_as { 16181conditions_tuple, 16182actions_tuple, 16183expressions_tuple, 16184dynamic_expressions, 16185compound_expressions, 16186serialized, 16187identifier, 16188identifiers, 16189values_placeholders, 16190table_columns, 16191non_generated_columns, 16192field_values_excluding, 16193mapped_columns_expressions, 16194column_constraints, 16195constraints_tuple, 16196}; 16197 16198template<stream_as mode> 16199struct streaming { 16200template<class... Ts> 16201auto operator()(const Ts&... ts) const { 16202return std::forward_as_tuple(*this, ts...); 16203} 16204 16205template<size_t... Idx> 16206constexpr std::index_sequence<1u + Idx...> offset_index(std::index_sequence<Idx...>) const { 16207return {}; 16208} 16209}; 16210constexpr streaming<stream_as::conditions_tuple> streaming_conditions_tuple{}; 16211constexpr streaming<stream_as::actions_tuple> streaming_actions_tuple{}; 16212constexpr streaming<stream_as::expressions_tuple> streaming_expressions_tuple{}; 16213constexpr streaming<stream_as::dynamic_expressions> streaming_dynamic_expressions{}; 16214constexpr streaming<stream_as::compound_expressions> streaming_compound_expressions{}; 16215constexpr streaming<stream_as::serialized> streaming_serialized{}; 16216constexpr streaming<stream_as::identifier> streaming_identifier{}; 16217constexpr streaming<stream_as::identifiers> streaming_identifiers{}; 16218constexpr streaming<stream_as::values_placeholders> streaming_values_placeholders{}; 16219constexpr streaming<stream_as::table_columns> streaming_table_column_names{}; 16220constexpr streaming<stream_as::non_generated_columns> streaming_non_generated_column_names{}; 16221constexpr streaming<stream_as::field_values_excluding> streaming_field_values_excluding{}; 16222constexpr streaming<stream_as::mapped_columns_expressions> streaming_mapped_columns_expressions{}; 16223constexpr streaming<stream_as::constraints_tuple> streaming_constraints_tuple{}; 16224constexpr streaming<stream_as::column_constraints> streaming_column_constraints{}; 16225 16226// serialize and stream a tuple of condition expressions; 16227// space + space-separated 16228template<class T, class Ctx> 16229std::ostream& operator<<(std::ostream& ss, 16230std::tuple<const streaming<stream_as::conditions_tuple>&, T, Ctx> tpl) { 16231const auto& conditions = std::get<1>(tpl); 16232auto& context = std::get<2>(tpl); 16233 16234iterate_tuple(conditions, [&ss, &context](auto& c) { 16235ss << " " << serialize(c, context); 16236}); 16237return ss; 16238} 16239 16240// serialize and stream a tuple of action expressions; 16241// space-separated 16242template<class T, class Ctx> 16243std::ostream& operator<<(std::ostream& ss, std::tuple<const streaming<stream_as::actions_tuple>&, T, Ctx> tpl) { 16244const auto& actions = std::get<1>(tpl); 16245auto& context = std::get<2>(tpl); 16246 16247iterate_tuple(actions, [&ss, &context, first = true](auto& action) mutable { 16248static constexpr std::array<const char*, 2> sep = {" ", ""}; 16249ss << sep[std::exchange(first, false)] << serialize(action, context); 16250}); 16251return ss; 16252} 16253 16254// serialize and stream a tuple of expressions; 16255// comma-separated 16256template<class T, class Ctx> 16257std::ostream& operator<<(std::ostream& ss, 16258std::tuple<const streaming<stream_as::expressions_tuple>&, T, Ctx> tpl) { 16259const auto& args = std::get<1>(tpl); 16260auto& context = std::get<2>(tpl); 16261 16262iterate_tuple(args, [&ss, &context, first = true](auto& arg) mutable { 16263static constexpr std::array<const char*, 2> sep = {", ", ""}; 16264ss << sep[std::exchange(first, false)] << serialize(arg, context); 16265}); 16266return ss; 16267} 16268 16269// serialize and stream expressions of a compound statement; 16270// separated by compound operator 16271template<class T, class Ctx> 16272std::ostream& 16273operator<<(std::ostream& ss, 16274std::tuple<const streaming<stream_as::compound_expressions>&, T, const std::string&, Ctx> tpl) { 16275const auto& args = std::get<1>(tpl); 16276const std::string& opString = std::get<2>(tpl); 16277auto& context = std::get<3>(tpl); 16278 16279iterate_tuple(args, [&ss, &opString, &context, first = true](auto& arg) mutable { 16280if (!std::exchange(first, false)) { 16281ss << ' ' << opString << ' '; 16282} 16283ss << serialize(arg, context); 16284}); 16285return ss; 16286} 16287 16288// serialize and stream multi_order_by arguments; 16289// comma-separated 16290template<class... Os, class Ctx> 16291std::ostream& operator<<( 16292std::ostream& ss, 16293std::tuple<const streaming<stream_as::expressions_tuple>&, const std::tuple<order_by_t<Os>...>&, Ctx> tpl) { 16294const auto& args = std::get<1>(tpl); 16295auto& context = std::get<2>(tpl); 16296 16297iterate_tuple(args, [&ss, &context, first = true](auto& arg) mutable { 16298static constexpr std::array<const char*, 2> sep = {", ", ""}; 16299ss << sep[std::exchange(first, false)] << serialize_order_by(arg, context); 16300}); 16301return ss; 16302} 16303 16304// serialize and stream a vector or any other STL container of expressions; 16305// comma-separated 16306template<class C, class Ctx> 16307std::ostream& operator<<(std::ostream& ss, 16308std::tuple<const streaming<stream_as::dynamic_expressions>&, C, Ctx> tpl) { 16309const auto& args = std::get<1>(tpl); 16310auto& context = std::get<2>(tpl); 16311 16312static constexpr std::array<const char*, 2> sep = {", ", ""}; 16313bool first = true; 16314for (auto& argument: args) { 16315ss << sep[std::exchange(first, false)] << serialize(argument, context); 16316} 16317return ss; 16318} 16319 16320// stream a vector of already serialized strings; 16321// comma-separated 16322template<class C> 16323std::ostream& operator<<(std::ostream& ss, std::tuple<const streaming<stream_as::serialized>&, C> tpl) { 16324const auto& strings = std::get<1>(tpl); 16325 16326static constexpr std::array<const char*, 2> sep = {", ", ""}; 16327for (size_t i = 0, first = true; i < strings.size(); ++i) { 16328ss << sep[std::exchange(first, false)] << strings[i]; 16329} 16330return 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 16337template<class... Strings> 16338std::ostream& operator<<(std::ostream& ss, 16339std::tuple<const streaming<stream_as::identifier>&, Strings...> tpl) { 16340stream_identifier(ss, tpl, streaming_identifier.offset_index(std::index_sequence_for<Strings...>{})); 16341return 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 16351template<class C> 16352std::ostream& operator<<(std::ostream& ss, std::tuple<const streaming<stream_as::identifiers>&, C> tpl) { 16353const auto& identifiers = std::get<1>(tpl); 16354 16355static constexpr std::array<const char*, 2> sep = {", ", ""}; 16356bool first = true; 16357for (auto& identifier: identifiers) { 16358ss << sep[std::exchange(first, false)]; 16359stream_identifier(ss, identifier); 16360} 16361return ss; 16362} 16363 16364// stream placeholders as part of a values clause 16365template<class... Ts> 16366std::ostream& operator<<(std::ostream& ss, 16367std::tuple<const streaming<stream_as::values_placeholders>&, Ts...> tpl) { 16368const size_t& columnsCount = std::get<1>(tpl); 16369const ptrdiff_t& valuesCount = std::get<2>(tpl); 16370 16371if (!valuesCount || !columnsCount) { 16372return ss; 16373} 16374 16375std::string result; 16376result.reserve((1 + (columnsCount * 1) + (columnsCount * 2 - 2) + 1) * valuesCount + (valuesCount * 2 - 2)); 16377 16378static constexpr std::array<const char*, 2> sep = {", ", ""}; 16379for (ptrdiff_t i = 0, first = true; i < valuesCount; ++i) { 16380result += sep[std::exchange(first, false)]; 16381result += "("; 16382for (size_t i = 0, first = true; i < columnsCount; ++i) { 16383result += sep[std::exchange(first, false)]; 16384result += "?"; 16385} 16386result += ")"; 16387} 16388ss << result; 16389return ss; 16390} 16391 16392// stream a table's column identifiers, possibly qualified; 16393// comma-separated 16394template<class Table> 16395std::ostream& 16396operator<<(std::ostream& ss, 16397std::tuple<const streaming<stream_as::table_columns>&, Table, const std::string&> tpl) { 16398const auto& table = std::get<1>(tpl); 16399const std::string& qualifier = std::get<2>(tpl); 16400 16401table.for_each_column([&ss, &qualifier, first = true](const column_identifier& column) mutable { 16402static constexpr std::array<const char*, 2> sep = {", ", ""}; 16403ss << sep[std::exchange(first, false)]; 16404stream_identifier(ss, qualifier, column.name, std::string{}); 16405}); 16406return ss; 16407} 16408 16409// stream a table's non-generated column identifiers, unqualified; 16410// comma-separated 16411template<class Table> 16412std::ostream& operator<<(std::ostream& ss, 16413std::tuple<const streaming<stream_as::non_generated_columns>&, Table> tpl) { 16414const auto& table = std::get<1>(tpl); 16415 16416table.template for_each_column_excluding<is_generated_always>( 16417[&ss, first = true](const column_identifier& column) mutable { 16418static constexpr std::array<const char*, 2> sep = {", ", ""}; 16419ss << sep[std::exchange(first, false)]; 16420stream_identifier(ss, column.name); 16421}); 16422return ss; 16423} 16424 16425// stream a table's non-generated column identifiers, unqualified; 16426// comma-separated 16427template<class PredFnCls, class L, class Ctx, class Obj> 16428std::ostream& 16429operator<<(std::ostream& ss, 16430std::tuple<const streaming<stream_as::field_values_excluding>&, PredFnCls, L, Ctx, Obj> tpl) { 16431using check_if_excluded = polyfill::remove_cvref_t<std::tuple_element_t<1, decltype(tpl)>>; 16432auto& excluded = std::get<2>(tpl); 16433auto& context = std::get<3>(tpl); 16434auto& object = std::get<4>(tpl); 16435using object_type = polyfill::remove_cvref_t<decltype(object)>; 16436auto& table = pick_table<object_type>(context.db_objects); 16437 16438table.template for_each_column_excluding<check_if_excluded>(call_as_template_base<column_field>( 16439[&ss, &excluded, &context, &object, first = true](auto& column) mutable { 16440if (excluded(column)) { 16441return; 16442} 16443 16444static constexpr std::array<const char*, 2> sep = {", ", ""}; 16445ss << sep[std::exchange(first, false)] 16446<< serialize(polyfill::invoke(column.member_pointer, object), context); 16447})); 16448return ss; 16449} 16450 16451// stream a tuple of mapped columns (which are member pointers or column pointers); 16452// comma-separated 16453template<class T, class Ctx> 16454std::ostream& operator<<(std::ostream& ss, 16455std::tuple<const streaming<stream_as::mapped_columns_expressions>&, T, Ctx> tpl) { 16456const auto& columns = std::get<1>(tpl); 16457auto& context = std::get<2>(tpl); 16458 16459iterate_tuple(columns, [&ss, &context, first = true](auto& colRef) mutable { 16460const std::string* columnName = find_column_name(context.db_objects, colRef); 16461if (!columnName) { 16462throw std::system_error{orm_error_code::column_not_found}; 16463} 16464 16465static constexpr std::array<const char*, 2> sep = {", ", ""}; 16466ss << sep[std::exchange(first, false)]; 16467stream_identifier(ss, *columnName); 16468}); 16469return ss; 16470} 16471 16472// serialize and stream a tuple of conditions or hints; 16473// space + space-separated 16474template<class T, class Ctx> 16475std::ostream& operator<<(std::ostream& ss, 16476std::tuple<const streaming<stream_as::constraints_tuple>&, T, Ctx> tpl) { 16477const auto& constraints = get<1>(tpl); 16478auto& context = get<2>(tpl); 16479 16480iterate_tuple(constraints, [&ss, &context](auto& constraint) mutable { 16481ss << ' ' << serialize(constraint, context); 16482}); 16483return ss; 16484} 16485 16486// serialize and stream a tuple of column constraints; 16487// space + space-separated 16488template<class... Op, class Ctx> 16489std::ostream& operator<<(std::ostream& ss, 16490std::tuple<const streaming<stream_as::column_constraints>&, 16491const column_constraints<Op...>&, 16492const bool&, 16493Ctx> tpl) { 16494const auto& column = std::get<1>(tpl); 16495const bool& isNotNull = std::get<2>(tpl); 16496auto& context = std::get<3>(tpl); 16497 16498using constraints_tuple = decltype(column.constraints); 16499iterate_tuple(column.constraints, [&ss, &context](auto& constraint) { 16500ss << ' ' << serialize(constraint, context); 16501}); 16502// add implicit null constraint 16503if (!context.fts5_columns) { 16504constexpr bool hasExplicitNullableConstraint = 16505mpl::invoke_t<mpl::disjunction<check_if_has_type<null_t>, check_if_has_type<not_null_t>>, 16506constraints_tuple>::value; 16507if SQLITE_ORM_CONSTEXPR_IF (!hasExplicitNullableConstraint) { 16508if (isNotNull) { 16509ss << " NOT NULL"; 16510} else { 16511ss << " NULL"; 16512} 16513} 16514} 16515 16516return ss; 16517} 16518} 16519} 16520 16521namespace sqlite_orm { 16522 16523namespace internal { 16524struct storage_base; 16525 16526template<class T> 16527int getPragmaCallback(void* data, int argc, char** argv, char** x) { 16528return extract_single_value<T>(data, argc, argv, x); 16529} 16530 16531template<> 16532inline int getPragmaCallback<std::vector<std::string>>(void* data, int argc, char** argv, char**) { 16533auto& res = *(std::vector<std::string>*)data; 16534res.reserve(argc); 16535const auto rowExtractor = column_text_extractor<std::string>(); 16536for (int i = 0; i < argc; ++i) { 16537auto rowString = rowExtractor.extract(argv[i]); 16538res.push_back(std::move(rowString)); 16539} 16540return 0; 16541} 16542 16543struct pragma_t { 16544using get_connection_t = std::function<internal::connection_ref()>; 16545 16546pragma_t(get_connection_t get_connection_) : get_connection(std::move(get_connection_)) {} 16547 16548std::vector<std::string> module_list() { 16549return this->get_pragma<std::vector<std::string>>("module_list"); 16550} 16551 16552bool recursive_triggers() { 16553return bool(this->get_pragma<int>("recursive_triggers")); 16554} 16555 16556void recursive_triggers(bool value) { 16557this->set_pragma("recursive_triggers", int(value)); 16558} 16559 16560void busy_timeout(int value) { 16561this->set_pragma("busy_timeout", value); 16562} 16563 16564int busy_timeout() { 16565return this->get_pragma<int>("busy_timeout"); 16566} 16567 16568sqlite_orm::locking_mode locking_mode() { 16569return this->get_pragma<sqlite_orm::locking_mode>("locking_mode"); 16570} 16571 16572void locking_mode(sqlite_orm::locking_mode value) { 16573this->set_pragma("locking_mode", value); 16574} 16575 16576sqlite_orm::journal_mode journal_mode() { 16577return this->get_pragma<sqlite_orm::journal_mode>("journal_mode"); 16578} 16579 16580void journal_mode(sqlite_orm::journal_mode value) { 16581this->journal_mode_ = -1; 16582this->set_pragma("journal_mode", value); 16583this->journal_mode_ = static_cast<decltype(this->journal_mode_)>(value); 16584} 16585 16586/** 16587* https://www.sqlite.org/pragma.html#pragma_application_id 16588*/ 16589int application_id() { 16590return this->get_pragma<int>("application_id"); 16591} 16592 16593/** 16594* https://www.sqlite.org/pragma.html#pragma_application_id 16595*/ 16596void application_id(int value) { 16597this->set_pragma("application_id", value); 16598} 16599 16600int synchronous() { 16601return this->get_pragma<int>("synchronous"); 16602} 16603 16604void synchronous(int value) { 16605this->synchronous_ = -1; 16606this->set_pragma("synchronous", value); 16607this->synchronous_ = value; 16608} 16609 16610int user_version() { 16611return this->get_pragma<int>("user_version"); 16612} 16613 16614void user_version(int value) { 16615this->set_pragma("user_version", value); 16616} 16617 16618int auto_vacuum() { 16619return this->get_pragma<int>("auto_vacuum"); 16620} 16621 16622void auto_vacuum(int value) { 16623this->set_pragma("auto_vacuum", value); 16624} 16625 16626int max_page_count() { 16627return this->get_pragma<int>("max_page_count"); 16628} 16629 16630void max_page_count(int value) { 16631this->set_pragma("max_page_count", value); 16632} 16633 16634std::vector<std::string> integrity_check() { 16635return this->get_pragma<std::vector<std::string>>("integrity_check"); 16636} 16637 16638template<class T> 16639std::vector<std::string> integrity_check(T table_name) { 16640std::ostringstream ss; 16641ss << "integrity_check(" << table_name << ")" << std::flush; 16642return this->get_pragma<std::vector<std::string>>(ss.str()); 16643} 16644 16645std::vector<std::string> integrity_check(int n) { 16646std::ostringstream ss; 16647ss << "integrity_check(" << n << ")" << std::flush; 16648return this->get_pragma<std::vector<std::string>>(ss.str()); 16649} 16650 16651std::vector<std::string> quick_check() { 16652return this->get_pragma<std::vector<std::string>>("quick_check"); 16653} 16654 16655// will include generated columns in response as opposed to table_info 16656std::vector<sqlite_orm::table_xinfo> table_xinfo(const std::string& tableName) const { 16657auto connection = this->get_connection(); 16658 16659std::vector<sqlite_orm::table_xinfo> result; 16660std::ostringstream ss; 16661ss << "PRAGMA " 16662"table_xinfo(" 16663<< streaming_identifier(tableName) << ")" << std::flush; 16664perform_exec( 16665connection.get(), 16666ss.str(), 16667[](void* data, int argc, char** argv, char**) -> int { 16668auto& res = *(std::vector<sqlite_orm::table_xinfo>*)data; 16669if (argc) { 16670auto index = 0; 16671auto cid = atoi(argv[index++]); 16672std::string name = argv[index++]; 16673std::string type = argv[index++]; 16674bool notnull = !!atoi(argv[index++]); 16675std::string dflt_value = argv[index] ? argv[index] : ""; 16676++index; 16677auto pk = atoi(argv[index++]); 16678auto hidden = atoi(argv[index++]); 16679res.emplace_back(cid, 16680std::move(name), 16681std::move(type), 16682notnull, 16683std::move(dflt_value), 16684pk, 16685hidden); 16686} 16687return 0; 16688}, 16689&result); 16690return result; 16691} 16692 16693std::vector<sqlite_orm::table_info> table_info(const std::string& tableName) const { 16694auto connection = this->get_connection(); 16695 16696std::ostringstream ss; 16697ss << "PRAGMA " 16698"table_info(" 16699<< streaming_identifier(tableName) << ")" << std::flush; 16700std::vector<sqlite_orm::table_info> result; 16701perform_exec( 16702connection.get(), 16703ss.str(), 16704[](void* data, int argc, char** argv, char**) -> int { 16705auto& res = *(std::vector<sqlite_orm::table_info>*)data; 16706if (argc) { 16707auto index = 0; 16708auto cid = atoi(argv[index++]); 16709std::string name = argv[index++]; 16710std::string type = argv[index++]; 16711bool notnull = !!atoi(argv[index++]); 16712std::string dflt_value = argv[index] ? argv[index] : ""; 16713++index; 16714auto pk = atoi(argv[index++]); 16715res.emplace_back(cid, std::move(name), std::move(type), notnull, std::move(dflt_value), pk); 16716} 16717return 0; 16718}, 16719&result); 16720return result; 16721} 16722 16723private: 16724friend struct storage_base; 16725 16726int synchronous_ = -1; 16727signed char journal_mode_ = -1; // if != -1 stores static_cast<sqlite_orm::journal_mode>(journal_mode) 16728get_connection_t get_connection; 16729 16730template<class T> 16731T get_pragma(const std::string& name) { 16732auto connection = this->get_connection(); 16733T result; 16734perform_exec(connection.get(), "PRAGMA " + name, getPragmaCallback<T>, &result); 16735return 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*/ 16742template<class T> 16743void set_pragma(const std::string& name, const T& value, sqlite3* db = nullptr) { 16744std::stringstream ss; 16745ss << "PRAGMA " << name << " = " << value; 16746this->set_pragma_impl(ss.str(), db); 16747} 16748 16749void set_pragma(const std::string& name, sqlite_orm::journal_mode value, sqlite3* db = nullptr) { 16750std::stringstream ss; 16751ss << "PRAGMA " << name << " = " << journal_mode_to_string(value); 16752this->set_pragma_impl(ss.str(), db); 16753} 16754 16755void set_pragma(const std::string& name, sqlite_orm::locking_mode value, sqlite3* db = nullptr) { 16756std::stringstream ss; 16757ss << "PRAGMA " << name << " = " << locking_mode_to_string(value); 16758this->set_pragma_impl(ss.str(), db); 16759} 16760 16761void set_pragma_impl(const std::string& query, sqlite3* db = nullptr) { 16762auto con = this->get_connection(); 16763if (db == nullptr) { 16764db = con.get(); 16765} 16766perform_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 16781namespace sqlite_orm { 16782 16783namespace internal { 16784 16785struct limit_accessor { 16786using get_connection_t = std::function<connection_ref()>; 16787 16788limit_accessor(get_connection_t get_connection_) : get_connection(std::move(get_connection_)) {} 16789 16790int length() { 16791return this->get(SQLITE_LIMIT_LENGTH); 16792} 16793 16794void length(int newValue) { 16795this->set(SQLITE_LIMIT_LENGTH, newValue); 16796} 16797 16798int sql_length() { 16799return this->get(SQLITE_LIMIT_SQL_LENGTH); 16800} 16801 16802void sql_length(int newValue) { 16803this->set(SQLITE_LIMIT_SQL_LENGTH, newValue); 16804} 16805 16806int column() { 16807return this->get(SQLITE_LIMIT_COLUMN); 16808} 16809 16810void column(int newValue) { 16811this->set(SQLITE_LIMIT_COLUMN, newValue); 16812} 16813 16814int expr_depth() { 16815return this->get(SQLITE_LIMIT_EXPR_DEPTH); 16816} 16817 16818void expr_depth(int newValue) { 16819this->set(SQLITE_LIMIT_EXPR_DEPTH, newValue); 16820} 16821 16822int compound_select() { 16823return this->get(SQLITE_LIMIT_COMPOUND_SELECT); 16824} 16825 16826void compound_select(int newValue) { 16827this->set(SQLITE_LIMIT_COMPOUND_SELECT, newValue); 16828} 16829 16830int vdbe_op() { 16831return this->get(SQLITE_LIMIT_VDBE_OP); 16832} 16833 16834void vdbe_op(int newValue) { 16835this->set(SQLITE_LIMIT_VDBE_OP, newValue); 16836} 16837 16838int function_arg() { 16839return this->get(SQLITE_LIMIT_FUNCTION_ARG); 16840} 16841 16842void function_arg(int newValue) { 16843this->set(SQLITE_LIMIT_FUNCTION_ARG, newValue); 16844} 16845 16846int attached() { 16847return this->get(SQLITE_LIMIT_ATTACHED); 16848} 16849 16850void attached(int newValue) { 16851this->set(SQLITE_LIMIT_ATTACHED, newValue); 16852} 16853 16854int like_pattern_length() { 16855return this->get(SQLITE_LIMIT_LIKE_PATTERN_LENGTH); 16856} 16857 16858void like_pattern_length(int newValue) { 16859this->set(SQLITE_LIMIT_LIKE_PATTERN_LENGTH, newValue); 16860} 16861 16862int variable_number() { 16863return this->get(SQLITE_LIMIT_VARIABLE_NUMBER); 16864} 16865 16866void variable_number(int newValue) { 16867this->set(SQLITE_LIMIT_VARIABLE_NUMBER, newValue); 16868} 16869 16870int trigger_depth() { 16871return this->get(SQLITE_LIMIT_TRIGGER_DEPTH); 16872} 16873 16874void trigger_depth(int newValue) { 16875this->set(SQLITE_LIMIT_TRIGGER_DEPTH, newValue); 16876} 16877 16878#if SQLITE_VERSION_NUMBER >= 3008007 16879int worker_threads() { 16880return this->get(SQLITE_LIMIT_WORKER_THREADS); 16881} 16882 16883void worker_threads(int newValue) { 16884this->set(SQLITE_LIMIT_WORKER_THREADS, newValue); 16885} 16886#endif 16887 16888protected: 16889get_connection_t get_connection; 16890 16891friend struct storage_base; 16892 16893/** 16894* Stores limit set between connections. 16895*/ 16896std::map<int, int> limits; 16897 16898int get(int id) { 16899auto connection = this->get_connection(); 16900return sqlite3_limit(connection.get(), id, -1); 16901} 16902 16903void set(int id, int newValue) { 16904this->limits[id] = newValue; 16905auto connection = this->get_connection(); 16906sqlite3_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 16919namespace sqlite_orm { 16920 16921namespace 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*/ 16932struct 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*/ 16937bool commit_on_destroy = false; 16938 16939transaction_guard_t(connection_ref connection_, 16940std::function<void()> commit_func_, 16941std::function<void()> rollback_func_) : 16942connection(std::move(connection_)), commit_func(std::move(commit_func_)), 16943rollback_func(std::move(rollback_func_)) {} 16944 16945transaction_guard_t(transaction_guard_t&& other) : 16946commit_on_destroy(other.commit_on_destroy), connection(std::move(other.connection)), 16947commit_func(std::move(other.commit_func)), rollback_func(std::move(other.rollback_func)), 16948gotta_fire(other.gotta_fire) { 16949other.gotta_fire = false; 16950} 16951 16952~transaction_guard_t() noexcept(false) { 16953if (this->gotta_fire) { 16954if (this->commit_on_destroy) { 16955this->commit_func(); 16956} else { 16957this->rollback_func(); 16958} 16959} 16960} 16961 16962transaction_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*/ 16969void commit() { 16970this->gotta_fire = false; 16971this->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*/ 16979void rollback() { 16980this->gotta_fire = false; 16981this->rollback_func(); 16982} 16983 16984protected: 16985connection_ref connection; 16986std::function<void()> commit_func; 16987std::function<void()> rollback_func; 16988bool 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 17009namespace sqlite_orm { 17010 17011namespace 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*/ 17019struct backup_t { 17020backup_t(connection_ref to_, 17021const std::string& zDestName, 17022connection_ref from_, 17023const std::string& zSourceName, 17024std::unique_ptr<connection_holder> holder_) : 17025handle(sqlite3_backup_init(to_.get(), zDestName.c_str(), from_.get(), zSourceName.c_str())), 17026holder(std::move(holder_)), to(to_), from(from_) { 17027if (!this->handle) { 17028throw std::system_error{orm_error_code::failed_to_init_a_backup}; 17029} 17030} 17031 17032backup_t(backup_t&& other) : 17033handle(std::exchange(other.handle, nullptr)), holder(std::move(other.holder)), to(other.to), 17034from(other.from) {} 17035 17036~backup_t() { 17037if (this->handle) { 17038(void)sqlite3_backup_finish(this->handle); 17039} 17040} 17041 17042/** 17043* Calls sqlite3_backup_step with pages argument 17044*/ 17045int step(int pages) { 17046return sqlite3_backup_step(this->handle, pages); 17047} 17048 17049/** 17050* Returns sqlite3_backup_remaining result 17051*/ 17052int remaining() const { 17053return sqlite3_backup_remaining(this->handle); 17054} 17055 17056/** 17057* Returns sqlite3_backup_pagecount result 17058*/ 17059int pagecount() const { 17060return sqlite3_backup_pagecount(this->handle); 17061} 17062 17063protected: 17064sqlite3_backup* handle = nullptr; 17065std::unique_ptr<connection_holder> holder; 17066connection_ref to; 17067connection_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 17092namespace sqlite_orm { 17093 17094/** @short Wrapper around a dynamically typed value object. 17095*/ 17096struct arg_value { 17097 17098arg_value() : arg_value(nullptr) {} 17099 17100arg_value(sqlite3_value* value_) : value(value_) {} 17101 17102template<class T> 17103T get() const { 17104const auto rowExtractor = internal::boxed_value_extractor<T>(); 17105return rowExtractor.extract(this->value); 17106} 17107 17108bool is_null() const { 17109auto type = sqlite3_value_type(this->value); 17110return type == SQLITE_NULL; 17111} 17112 17113bool is_text() const { 17114auto type = sqlite3_value_type(this->value); 17115return type == SQLITE_TEXT; 17116} 17117 17118bool is_integer() const { 17119auto type = sqlite3_value_type(this->value); 17120return type == SQLITE_INTEGER; 17121} 17122 17123bool is_float() const { 17124auto type = sqlite3_value_type(this->value); 17125return type == SQLITE_FLOAT; 17126} 17127 17128bool is_blob() const { 17129auto type = sqlite3_value_type(this->value); 17130return type == SQLITE_BLOB; 17131} 17132 17133bool empty() const { 17134return this->value == nullptr; 17135} 17136 17137private: 17138sqlite3_value* value = nullptr; 17139}; 17140 17141struct arg_values { 17142 17143struct iterator { 17144 17145iterator(const arg_values& container_, int index_) : 17146container(container_), index(index_), 17147currentValue(index_ < int(container_.size()) ? container_[index_] : arg_value()) {} 17148 17149iterator& operator++() { 17150++this->index; 17151if (this->index < int(this->container.size())) { 17152this->currentValue = this->container[this->index]; 17153} else { 17154this->currentValue = {}; 17155} 17156return *this; 17157} 17158 17159iterator operator++(int) { 17160auto res = *this; 17161++this->index; 17162if (this->index < int(this->container.size())) { 17163this->currentValue = this->container[this->index]; 17164} else { 17165this->currentValue = {}; 17166} 17167return res; 17168} 17169 17170arg_value operator*() const { 17171if (this->index < int(this->container.size()) && this->index >= 0) { 17172return this->currentValue; 17173} else { 17174throw std::system_error{orm_error_code::index_is_out_of_bounds}; 17175} 17176} 17177 17178arg_value* operator->() const { 17179return &this->currentValue; 17180} 17181 17182bool operator==(const iterator& other) const { 17183return &other.container == &this->container && other.index == this->index; 17184} 17185 17186bool operator!=(const iterator& other) const { 17187return !(*this == other); 17188} 17189 17190private: 17191const arg_values& container; 17192int index = 0; 17193mutable arg_value currentValue; 17194}; 17195 17196arg_values() : arg_values(0, nullptr) {} 17197 17198arg_values(int argsCount_, sqlite3_value** values_) : argsCount(argsCount_), values(values_) {} 17199 17200size_t size() const { 17201return this->argsCount; 17202} 17203 17204bool empty() const { 17205return 0 == this->argsCount; 17206} 17207 17208arg_value operator[](int index) const { 17209if (index < this->argsCount && index >= 0) { 17210sqlite3_value* value = this->values[index]; 17211return {value}; 17212} else { 17213throw std::system_error{orm_error_code::index_is_out_of_bounds}; 17214} 17215} 17216 17217arg_value at(int index) const { 17218return this->operator[](index); 17219} 17220 17221iterator begin() const { 17222return {*this, 0}; 17223} 17224 17225iterator end() const { 17226return {*this, this->argsCount}; 17227} 17228 17229private: 17230int argsCount = 0; 17231sqlite3_value** values = nullptr; 17232}; 17233} 17234 17235namespace sqlite_orm { 17236 17237namespace internal { 17238 17239template<class Tpl> 17240struct tuple_from_values { 17241template<class R = Tpl, satisfies_not<std::is_same, R, std::tuple<arg_values>> = true> 17242R operator()(sqlite3_value** values, int /*argsCount*/) const { 17243return this->create_from(values, std::make_index_sequence<std::tuple_size<Tpl>::value>{}); 17244} 17245 17246template<class R = Tpl, satisfies<std::is_same, R, std::tuple<arg_values>> = true> 17247R operator()(sqlite3_value** values, int argsCount) const { 17248return {arg_values(argsCount, values)}; 17249} 17250 17251private: 17252template<size_t... Idx> 17253Tpl create_from(sqlite3_value** values, std::index_sequence<Idx...>) const { 17254return {this->extract<std::tuple_element_t<Idx, Tpl>>(values[Idx])...}; 17255} 17256 17257template<class T> 17258T extract(sqlite3_value* value) const { 17259const auto rowExtractor = boxed_value_extractor<T>(); 17260return 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 17285namespace sqlite_orm { 17286namespace internal { 17287/* 17288* Returns properly allocated memory space for the specified application-defined function object 17289* paired with an accompanying deallocation function. 17290*/ 17291template<class UDF> 17292std::pair<void*, xdestroy_fn_t> preallocate_udf_memory() { 17293std::allocator<UDF> allocator; 17294using traits = std::allocator_traits<decltype(allocator)>; 17295 17296SQLITE_ORM_CONSTEXPR_LAMBDA_CPP17 auto deallocate = [](void* location) noexcept { 17297std::allocator<UDF> allocator; 17298using traits = std::allocator_traits<decltype(allocator)>; 17299traits::deallocate(allocator, (UDF*)location, 1); 17300}; 17301 17302return {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*/ 17308template<class UDF> 17309std::pair<void* (*)(), xdestroy_fn_t> obtain_udf_allocator() { 17310SQLITE_ORM_CONSTEXPR_LAMBDA_CPP17 auto allocate = []() { 17311std::allocator<UDF> allocator; 17312using traits = std::allocator_traits<decltype(allocator)>; 17313return (void*)traits::allocate(allocator, 1); 17314}; 17315 17316SQLITE_ORM_CONSTEXPR_LAMBDA_CPP17 auto deallocate = [](void* location) noexcept { 17317std::allocator<UDF> allocator; 17318using traits = std::allocator_traits<decltype(allocator)>; 17319traits::deallocate(allocator, (UDF*)location, 1); 17320}; 17321 17322return {allocate, deallocate}; 17323} 17324 17325/* 17326* A deleter that only destroys the application-defined function object. 17327*/ 17328struct udf_destruct_only_deleter { 17329template<class UDF> 17330void operator()(UDF* f) const noexcept { 17331std::allocator<UDF> allocator; 17332using traits = std::allocator_traits<decltype(allocator)>; 17333traits::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*/ 17344struct udf_proxy { 17345using sqlite_func_t = void (*)(sqlite3_context* context, int argsCount, sqlite3_value** values); 17346using final_call_fn_t = void (*)(void* udfHandle, sqlite3_context* context); 17347using memory_alloc = std::pair<void* (*)() /*allocate*/, xdestroy_fn_t /*deallocate*/>; 17348using memory_space = std::pair<void* /*udfHandle*/, xdestroy_fn_t /*deallocate*/>; 17349 17350std::string name; 17351int argumentsCount; 17352std::function<void(void* location)> constructAt; 17353xdestroy_fn_t destroy; 17354sqlite_func_t func; 17355final_call_fn_t finalAggregateCall; 17356 17357// allocator/deallocator function pair for aggregate UDF 17358const memory_alloc udfAllocator; 17359// pointer to preallocated memory space for scalar UDF, already constructed by caller if stateless 17360const memory_space udfMemorySpace; 17361 17362udf_proxy(std::string name, 17363int argumentsCount, 17364std::function<void(void* location)> constructAt, 17365xdestroy_fn_t destroy, 17366sqlite_func_t func, 17367memory_space udfMemorySpace) : 17368name{std::move(name)}, argumentsCount{argumentsCount}, constructAt{std::move(constructAt)}, 17369destroy{destroy}, func{func}, finalAggregateCall{nullptr}, udfAllocator{}, 17370udfMemorySpace{udfMemorySpace} {} 17371 17372udf_proxy(std::string name, 17373int argumentsCount, 17374std::function<void(void* location)> constructAt, 17375xdestroy_fn_t destroy, 17376sqlite_func_t func, 17377final_call_fn_t finalAggregateCall, 17378memory_alloc udfAllocator) : 17379name{std::move(name)}, argumentsCount{argumentsCount}, constructAt{std::move(constructAt)}, 17380destroy{destroy}, func{func}, finalAggregateCall{finalAggregateCall}, udfAllocator{udfAllocator}, 17381udfMemorySpace{} {} 17382 17383~udf_proxy() { 17384// destruct 17385if (/*bool aprioriConstructed = */ !constructAt && destroy) { 17386destroy(udfMemorySpace.first); 17387} 17388// deallocate 17389if (udfMemorySpace.second) { 17390udfMemorySpace.second(udfMemorySpace.first); 17391} 17392} 17393 17394udf_proxy(const udf_proxy&) = delete; 17395udf_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 17400friend void* preallocated_udf_handle(udf_proxy* proxy) { 17401return proxy->udfMemorySpace.first; 17402} 17403 17404friend void* allocate_udf(udf_proxy* proxy) { 17405return proxy->udfAllocator.first(); 17406} 17407 17408friend void deallocate_udf(udf_proxy* proxy, void* udfHandle) { 17409proxy->udfAllocator.second(udfHandle); 17410} 17411}; 17412 17413// safety net of doing a triple check at runtime 17414inline void assert_args_count(const udf_proxy* proxy, int argsCount) { 17415assert((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 17422inline void proxy_assert_args_count(sqlite3_context* context, int argsCount) { 17423udf_proxy* proxy; 17424assert((proxy = static_cast<udf_proxy*>(sqlite3_user_data(context))) != nullptr); 17425assert_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 17430inline 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) 17432void* ctxMemory = sqlite3_aggregate_context(context, sizeof(void*)); 17433if (!ctxMemory) SQLITE_ORM_CPP_UNLIKELY { 17434throw std::bad_alloc(); 17435} 17436void*& udfHandle = *static_cast<void**>(ctxMemory); 17437 17438if (udfHandle) SQLITE_ORM_CPP_LIKELY { 17439return udfHandle; 17440} else { 17441assert_args_count(proxy, argsCount); 17442udfHandle = 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. 17447proxy->constructAt(udfHandle); 17448return udfHandle; 17449} 17450} 17451 17452inline void delete_aggregate_udf(udf_proxy* proxy, void* udfHandle) { 17453proxy->destroy(udfHandle); 17454deallocate_udf(proxy, udfHandle); 17455} 17456 17457// Return C pointer to preallocated and a priori constructed UDF 17458template<class UDF> 17459inline UDF* 17460proxy_get_scalar_udf(std::true_type /*is_stateless*/, sqlite3_context* context, int argsCount) noexcept { 17461proxy_assert_args_count(context, argsCount); 17462udf_proxy* proxy = static_cast<udf_proxy*>(sqlite3_user_data(context)); 17463return static_cast<UDF*>(preallocated_udf_handle(proxy)); 17464} 17465 17466// Return unique pointer to newly constructed UDF at preallocated memory space 17467template<class UDF> 17468inline auto proxy_get_scalar_udf(std::false_type /*is_stateless*/, sqlite3_context* context, int argsCount) { 17469proxy_assert_args_count(context, argsCount); 17470udf_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. 17475proxy->constructAt(preallocated_udf_handle(proxy)); 17476return std::unique_ptr<UDF, xdestroy_fn_t>{static_cast<UDF*>(preallocated_udf_handle(proxy)), 17477proxy->destroy}; 17478} 17479 17480// note: may throw `std::bad_alloc` in case memory space for the aggregate function object cannot be allocated 17481template<class UDF> 17482inline UDF* proxy_get_aggregate_step_udf(sqlite3_context* context, int argsCount) { 17483udf_proxy* proxy = static_cast<udf_proxy*>(sqlite3_user_data(context)); 17484void* udfHandle = ensure_aggregate_udf(context, proxy, argsCount); 17485return static_cast<UDF*>(udfHandle); 17486} 17487 17488inline void aggregate_function_final_callback(sqlite3_context* context) { 17489udf_proxy* proxy = static_cast<udf_proxy*>(sqlite3_user_data(context)); 17490void* udfHandle; 17491try { 17492// note: it is possible that the 'step' function was never called 17493udfHandle = ensure_aggregate_udf(context, proxy, -1); 17494} catch (const std::bad_alloc&) { 17495sqlite3_result_error_nomem(context); 17496return; 17497} 17498proxy->finalAggregateCall(udfHandle, context); 17499delete_aggregate_udf(proxy, udfHandle); 17500} 17501} 17502} 17503 17504// #include "serializing_util.h" 17505 17506// #include "table_info.h" 17507 17508namespace sqlite_orm { 17509 17510namespace internal { 17511 17512struct storage_base { 17513using collating_function = std::function<int(int, const void*, int, const void*)>; 17514 17515std::function<void(sqlite3*)> on_open; 17516pragma_t pragma; 17517limit_accessor limit; 17518 17519transaction_guard_t transaction_guard() { 17520this->begin_transaction(); 17521return {this->get_connection(), 17522std::bind(&storage_base::commit, this), 17523std::bind(&storage_base::rollback, this)}; 17524} 17525 17526transaction_guard_t deferred_transaction_guard() { 17527this->begin_deferred_transaction(); 17528return {this->get_connection(), 17529std::bind(&storage_base::commit, this), 17530std::bind(&storage_base::rollback, this)}; 17531} 17532 17533transaction_guard_t immediate_transaction_guard() { 17534this->begin_immediate_transaction(); 17535return {this->get_connection(), 17536std::bind(&storage_base::commit, this), 17537std::bind(&storage_base::rollback, this)}; 17538} 17539 17540transaction_guard_t exclusive_transaction_guard() { 17541this->begin_exclusive_transaction(); 17542return {this->get_connection(), 17543std::bind(&storage_base::commit, this), 17544std::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*/ 17552void drop_index(const std::string& indexName) { 17553this->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*/ 17561void drop_index_if_exists(const std::string& indexName) { 17562this->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*/ 17570void drop_trigger(const std::string& triggerName) { 17571this->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*/ 17579void drop_trigger_if_exists(const std::string& triggerName) { 17580this->drop_trigger_internal(triggerName, true); 17581} 17582 17583/** 17584* `VACUUM` query. 17585* More info: https://www.sqlite.org/lang_vacuum.html 17586*/ 17587void vacuum() { 17588perform_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*/ 17596void drop_table(const std::string& tableName) { 17597this->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*/ 17605void drop_table_if_exists(const std::string& tableName) { 17606this->drop_table_internal(this->get_connection().get(), tableName, true); 17607} 17608 17609/** 17610* Rename table named `from` to `to`. 17611*/ 17612void rename_table(const std::string& from, const std::string& to) { 17613this->rename_table(this->get_connection().get(), from, to); 17614} 17615 17616protected: 17617void rename_table(sqlite3* db, const std::string& oldName, const std::string& newName) const { 17618std::stringstream ss; 17619ss << "ALTER TABLE " << streaming_identifier(oldName) << " RENAME TO " << streaming_identifier(newName) 17620<< std::flush; 17621perform_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*/ 17629bool table_exists(const std::string& tableName) { 17630auto con = this->get_connection(); 17631return this->table_exists(con.get(), tableName); 17632} 17633 17634bool table_exists(sqlite3* db, const std::string& tableName) const { 17635bool result = false; 17636std::stringstream ss; 17637ss << "SELECT COUNT(*) FROM sqlite_master WHERE type = " << quote_string_literal("table") 17638<< " AND name = " << quote_string_literal(tableName) << std::flush; 17639perform_exec( 17640db, 17641ss.str(), 17642[](void* data, int argc, char** argv, char** /*azColName*/) -> int { 17643auto& res = *(bool*)data; 17644if (argc) { 17645res = !!atoi(argv[0]); 17646} 17647return 0; 17648}, 17649&result); 17650return result; 17651} 17652 17653void add_generated_cols(std::vector<const table_xinfo*>& columnsToAdd, 17654const std::vector<table_xinfo>& storageTableInfo) { 17655// iterate through storage columns 17656for (const table_xinfo& storageColumnInfo: storageTableInfo) { 17657if (storageColumnInfo.hidden) { 17658columnsToAdd.push_back(&storageColumnInfo); 17659} 17660} 17661} 17662 17663public: 17664/** 17665* sqlite3_changes function. 17666*/ 17667int changes() { 17668auto con = this->get_connection(); 17669return sqlite3_changes(con.get()); 17670} 17671 17672/** 17673* sqlite3_total_changes function. 17674*/ 17675int total_changes() { 17676auto con = this->get_connection(); 17677return sqlite3_total_changes(con.get()); 17678} 17679 17680int64 last_insert_rowid() { 17681auto con = this->get_connection(); 17682return sqlite3_last_insert_rowid(con.get()); 17683} 17684 17685int busy_timeout(int ms) { 17686auto con = this->get_connection(); 17687return sqlite3_busy_timeout(con.get(), ms); 17688} 17689 17690/** 17691* Returns libsqlite3 version, not sqlite_orm 17692*/ 17693std::string libversion() { 17694return sqlite3_libversion(); 17695} 17696 17697bool transaction(const std::function<bool()>& f) { 17698auto guard = this->transaction_guard(); 17699return guard.commit_on_destroy = f(); 17700} 17701 17702std::string current_time() { 17703auto con = this->get_connection(); 17704return this->current_time(con.get()); 17705} 17706 17707std::string current_date() { 17708auto con = this->get_connection(); 17709return this->current_date(con.get()); 17710} 17711 17712std::string current_timestamp() { 17713auto con = this->get_connection(); 17714return 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*/ 17724int db_release_memory() { 17725auto con = this->get_connection(); 17726return 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*/ 17735std::vector<std::string> table_names() { 17736auto con = this->get_connection(); 17737std::vector<std::string> tableNames; 17738using data_t = std::vector<std::string>; 17739perform_exec( 17740con.get(), 17741"SELECT name FROM sqlite_master WHERE type='table'", 17742[](void* data, int argc, char** argv, char** /*columnName*/) -> int { 17743auto& tableNames_ = *(data_t*)data; 17744for (int i = 0; i < argc; ++i) { 17745if (argv[i]) { 17746tableNames_.emplace_back(argv[i]); 17747} 17748} 17749return 0; 17750}, 17751&tableNames); 17752tableNames.shrink_to_fit(); 17753return 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*/ 17765void open_forever() { 17766this->isOpenedForever = true; 17767this->connection->retain(); 17768if (1 == this->connection->retain_count()) { 17769this->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*/ 17797template<class F, class... Args> 17798void create_scalar_function(Args&&... constructorArgs) { 17799static_assert(is_scalar_udf_v<F>, "F must be a scalar function"); 17800 17801this->create_scalar_function_impl( 17802udf_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 17809std::allocator<F> allocator; 17810using traits = std::allocator_traits<decltype(allocator)>; 17811traits::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*/ 17826template<orm_scalar_function auto f, std::copy_constructible... Args> 17827void create_scalar_function(Args&&... constructorArgs) { 17828return 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*/ 17839template<orm_quoted_scalar_function auto quotedF> 17840void create_scalar_function() { 17841using Sig = auto_udf_type_t<quotedF>; 17842using args_tuple = typename callable_arguments<Sig>::args_tuple; 17843using return_type = typename callable_arguments<Sig>::return_type; 17844constexpr auto argsCount = std::is_same<args_tuple, std::tuple<arg_values>>::value 17845? -1 17846: int(std::tuple_size<args_tuple>::value); 17847this->scalarFunctions.emplace_back( 17848std::string{quotedF.name()}, 17849argsCount, 17850/* constructAt = */ 17851nullptr, 17852/* destroy = */ 17853nullptr, 17854/* call = */ 17855[](sqlite3_context* context, int argsCount, sqlite3_value** values) { 17856proxy_assert_args_count(context, argsCount); 17857args_tuple argsTuple = tuple_from_values<args_tuple>{}(values, argsCount); 17858auto result = polyfill::apply(quotedF.callable(), std::move(argsTuple)); 17859statement_binder<return_type>().result(context, result); 17860}, 17861/* finalCall = */ 17862nullptr, 17863std::pair{nullptr, null_xdestroy_f}); 17864 17865if (this->connection->retain_count() > 0) { 17866sqlite3* db = this->connection->get(); 17867try_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*/ 17902template<class F, class... Args> 17903void create_aggregate_function(Args&&... constructorArgs) { 17904static_assert(is_aggregate_udf_v<F>, "F must be an aggregate function"); 17905 17906this->create_aggregate_function_impl( 17907udf_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 17914std::allocator<F> allocator; 17915using traits = std::allocator_traits<decltype(allocator)>; 17916traits::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*/ 17930template<orm_aggregate_function auto f, std::copy_constructible... Args> 17931void create_aggregate_function(Args&&... constructorArgs) { 17932return 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*/ 17940template<class F> 17941void delete_scalar_function() { 17942static_assert(is_scalar_udf_v<F>, "F must be a scalar function"); 17943udf_holder<F> udfName; 17944this->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*/ 17952template<orm_scalar_function auto f> 17953void delete_scalar_function() { 17954this->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*/ 17961template<orm_quoted_scalar_function auto quotedF> 17962void delete_scalar_function() { 17963this->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*/ 17971template<class F> 17972void delete_aggregate_function() { 17973static_assert(is_aggregate_udf_v<F>, "F must be an aggregate function"); 17974udf_holder<F> udfName; 17975this->delete_function_impl(udfName(), this->aggregateFunctions); 17976} 17977 17978#ifdef SQLITE_ORM_WITH_CPP20_ALIASES 17979template<orm_aggregate_function auto f> 17980void delete_aggregate_function() { 17981this->delete_function_impl(f.name(), this->aggregateFunctions); 17982} 17983#endif 17984 17985template<class C> 17986void create_collation() { 17987collating_function func = [](int leftLength, const void* lhs, int rightLength, const void* rhs) { 17988C collatingObject; 17989return collatingObject(leftLength, lhs, rightLength, rhs); 17990}; 17991std::stringstream ss; 17992ss << C::name() << std::flush; 17993this->create_collation(ss.str(), std::move(func)); 17994} 17995 17996void create_collation(const std::string& name, collating_function f) { 17997const auto functionExists = bool(f); 17998collating_function* function = nullptr; 17999if (functionExists) { 18000function = &(collatingFunctions[name] = std::move(f)); 18001} 18002 18003// create collations if db is open 18004if (this->connection->retain_count() > 0) { 18005sqlite3* db = this->connection->get(); 18006int rc = sqlite3_create_collation(db, 18007name.c_str(), 18008SQLITE_UTF8, 18009function, 18010functionExists ? collate_callback : nullptr); 18011if (rc != SQLITE_OK) { 18012throw_translated_sqlite_error(db); 18013} 18014} 18015 18016if (!functionExists) { 18017collatingFunctions.erase(name); 18018} 18019} 18020 18021template<class C> 18022void delete_collation() { 18023std::stringstream ss; 18024ss << C::name() << std::flush; 18025this->create_collation(ss.str(), {}); 18026} 18027 18028void begin_transaction() { 18029this->begin_transaction_internal("BEGIN TRANSACTION"); 18030} 18031 18032void begin_deferred_transaction() { 18033this->begin_transaction_internal("BEGIN DEFERRED TRANSACTION"); 18034} 18035 18036void begin_immediate_transaction() { 18037this->begin_transaction_internal("BEGIN IMMEDIATE TRANSACTION"); 18038} 18039 18040void begin_exclusive_transaction() { 18041this->begin_transaction_internal("BEGIN EXCLUSIVE TRANSACTION"); 18042} 18043 18044void commit() { 18045sqlite3* db = this->connection->get(); 18046perform_void_exec(db, "COMMIT"); 18047this->connection->release(); 18048if (this->connection->retain_count() < 0) { 18049throw std::system_error{orm_error_code::no_active_transaction}; 18050} 18051} 18052 18053void rollback() { 18054sqlite3* db = this->connection->get(); 18055perform_void_exec(db, "ROLLBACK"); 18056this->connection->release(); 18057if (this->connection->retain_count() < 0) { 18058throw std::system_error{orm_error_code::no_active_transaction}; 18059} 18060} 18061 18062void backup_to(const std::string& filename) { 18063auto backup = this->make_backup_to(filename); 18064backup.step(-1); 18065} 18066 18067void backup_to(storage_base& other) { 18068auto backup = this->make_backup_to(other); 18069backup.step(-1); 18070} 18071 18072void backup_from(const std::string& filename) { 18073auto backup = this->make_backup_from(filename); 18074backup.step(-1); 18075} 18076 18077void backup_from(storage_base& other) { 18078auto backup = this->make_backup_from(other); 18079backup.step(-1); 18080} 18081 18082backup_t make_backup_to(const std::string& filename) { 18083auto holder = std::make_unique<connection_holder>(filename); 18084connection_ref conRef{*holder}; 18085return {conRef, "main", this->get_connection(), "main", std::move(holder)}; 18086} 18087 18088backup_t make_backup_to(storage_base& other) { 18089return {other.get_connection(), "main", this->get_connection(), "main", {}}; 18090} 18091 18092backup_t make_backup_from(const std::string& filename) { 18093auto holder = std::make_unique<connection_holder>(filename); 18094connection_ref conRef{*holder}; 18095return {this->get_connection(), "main", conRef, "main", std::move(holder)}; 18096} 18097 18098backup_t make_backup_from(storage_base& other) { 18099return {this->get_connection(), "main", other.get_connection(), "main", {}}; 18100} 18101 18102const std::string& filename() const { 18103return 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*/ 18110bool is_opened() const { 18111return 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*/ 18118bool get_autocommit() { 18119auto con = this->get_connection(); 18120return sqlite3_get_autocommit(con.get()); 18121} 18122 18123int busy_handler(std::function<int(int)> handler) { 18124_busy_handler = std::move(handler); 18125if (this->is_opened()) { 18126if (_busy_handler) { 18127return sqlite3_busy_handler(this->connection->get(), busy_handler_callback, this); 18128} else { 18129return sqlite3_busy_handler(this->connection->get(), nullptr, nullptr); 18130} 18131} else { 18132return SQLITE_OK; 18133} 18134} 18135 18136protected: 18137storage_base(std::string filename, int foreignKeysCount) : 18138pragma(std::bind(&storage_base::get_connection, this)), 18139limit(std::bind(&storage_base::get_connection, this)), 18140inMemory(filename.empty() || filename == ":memory:"), 18141connection(std::make_unique<connection_holder>(std::move(filename))), 18142cachedForeignKeysCount(foreignKeysCount) { 18143if (this->inMemory) { 18144this->connection->retain(); 18145this->on_open_internal(this->connection->get()); 18146} 18147} 18148 18149storage_base(const storage_base& other) : 18150on_open(other.on_open), pragma(std::bind(&storage_base::get_connection, this)), 18151limit(std::bind(&storage_base::get_connection, this)), inMemory(other.inMemory), 18152connection(std::make_unique<connection_holder>(other.connection->filename)), 18153cachedForeignKeysCount(other.cachedForeignKeysCount) { 18154if (this->inMemory) { 18155this->connection->retain(); 18156this->on_open_internal(this->connection->get()); 18157} 18158} 18159 18160~storage_base() { 18161if (this->isOpenedForever) { 18162this->connection->release(); 18163} 18164if (this->inMemory) { 18165this->connection->release(); 18166} 18167} 18168 18169void begin_transaction_internal(const std::string& query) { 18170this->connection->retain(); 18171if (1 == this->connection->retain_count()) { 18172this->on_open_internal(this->connection->get()); 18173} 18174sqlite3* db = this->connection->get(); 18175perform_void_exec(db, query); 18176} 18177 18178connection_ref get_connection() { 18179connection_ref res{*this->connection}; 18180if (1 == this->connection->retain_count()) { 18181this->on_open_internal(this->connection->get()); 18182} 18183return res; 18184} 18185 18186#if SQLITE_VERSION_NUMBER >= 3006019 18187void foreign_keys(sqlite3* db, bool value) { 18188std::stringstream ss; 18189ss << "PRAGMA foreign_keys = " << value << std::flush; 18190perform_void_exec(db, ss.str()); 18191} 18192 18193bool foreign_keys(sqlite3* db) { 18194bool result = false; 18195perform_exec(db, "PRAGMA foreign_keys", extract_single_value<bool>, &result); 18196return result; 18197} 18198 18199#endif 18200void on_open_internal(sqlite3* db) { 18201 18202#if SQLITE_VERSION_NUMBER >= 3006019 18203if (this->cachedForeignKeysCount) { 18204this->foreign_keys(db, true); 18205} 18206#endif 18207if (this->pragma.synchronous_ != -1) { 18208this->pragma.synchronous(this->pragma.synchronous_); 18209} 18210 18211if (this->pragma.journal_mode_ != -1) { 18212this->pragma.set_pragma("journal_mode", static_cast<journal_mode>(this->pragma.journal_mode_), db); 18213} 18214 18215for (auto& p: this->collatingFunctions) { 18216int rc = sqlite3_create_collation(db, p.first.c_str(), SQLITE_UTF8, &p.second, collate_callback); 18217if (rc != SQLITE_OK) { 18218throw_translated_sqlite_error(db); 18219} 18220} 18221 18222for (auto& p: this->limit.limits) { 18223sqlite3_limit(db, p.first, p.second); 18224} 18225 18226if (_busy_handler) { 18227sqlite3_busy_handler(this->connection->get(), busy_handler_callback, this); 18228} 18229 18230for (auto& udfProxy: this->scalarFunctions) { 18231try_to_create_scalar_function(db, udfProxy); 18232} 18233 18234for (auto& udfProxy: this->aggregateFunctions) { 18235try_to_create_aggregate_function(db, udfProxy); 18236} 18237 18238if (this->on_open) { 18239this->on_open(db); 18240} 18241} 18242 18243template<class F> 18244void create_scalar_function_impl(udf_holder<F> udfName, std::function<void(void* location)> constructAt) { 18245using args_tuple = typename callable_arguments<F>::args_tuple; 18246using return_type = typename callable_arguments<F>::return_type; 18247constexpr auto argsCount = std::is_same<args_tuple, std::tuple<arg_values>>::value 18248? -1 18249: int(std::tuple_size<args_tuple>::value); 18250using is_stateless = std::is_empty<F>; 18251auto udfMemorySpace = preallocate_udf_memory<F>(); 18252if SQLITE_ORM_CONSTEXPR_IF (is_stateless::value) { 18253constructAt(udfMemorySpace.first); 18254} 18255this->scalarFunctions.emplace_back( 18256udfName(), 18257argsCount, 18258is_stateless::value ? nullptr : std::move(constructAt), 18259/* destroy = */ 18260obtain_xdestroy_for<F>(udf_destruct_only_deleter{}), 18261/* call = */ 18262[](sqlite3_context* context, int argsCount, sqlite3_value** values) { 18263auto udfPointer = proxy_get_scalar_udf<F>(is_stateless{}, context, argsCount); 18264args_tuple argsTuple = tuple_from_values<args_tuple>{}(values, argsCount); 18265auto result = polyfill::apply(*udfPointer, std::move(argsTuple)); 18266statement_binder<return_type>().result(context, result); 18267}, 18268udfMemorySpace); 18269 18270if (this->connection->retain_count() > 0) { 18271sqlite3* db = this->connection->get(); 18272try_to_create_scalar_function(db, this->scalarFunctions.back()); 18273} 18274} 18275 18276template<class F> 18277void create_aggregate_function_impl(udf_holder<F> udfName, 18278std::function<void(void* location)> constructAt) { 18279using args_tuple = typename callable_arguments<F>::args_tuple; 18280using return_type = typename callable_arguments<F>::return_type; 18281constexpr auto argsCount = std::is_same<args_tuple, std::tuple<arg_values>>::value 18282? -1 18283: int(std::tuple_size<args_tuple>::value); 18284this->aggregateFunctions.emplace_back( 18285udfName(), 18286argsCount, 18287std::move(constructAt), 18288/* destroy = */ 18289obtain_xdestroy_for<F>(udf_destruct_only_deleter{}), 18290/* step = */ 18291[](sqlite3_context* context, int argsCount, sqlite3_value** values) { 18292F* udfPointer; 18293try { 18294udfPointer = proxy_get_aggregate_step_udf<F>(context, argsCount); 18295} catch (const std::bad_alloc&) { 18296sqlite3_result_error_nomem(context); 18297return; 18298} 18299args_tuple argsTuple = tuple_from_values<args_tuple>{}(values, argsCount); 18300#if __cpp_lib_bind_front >= 201907L 18301std::apply(std::bind_front(&F::step, udfPointer), std::move(argsTuple)); 18302#else 18303polyfill::apply( 18304[udfPointer](auto&&... args) { 18305udfPointer->step(std::forward<decltype(args)>(args)...); 18306}, 18307std::move(argsTuple)); 18308#endif 18309}, 18310/* finalCall = */ 18311[](void* udfHandle, sqlite3_context* context) { 18312F& udf = *static_cast<F*>(udfHandle); 18313auto result = udf.fin(); 18314statement_binder<return_type>().result(context, result); 18315}, 18316obtain_udf_allocator<F>()); 18317 18318if (this->connection->retain_count() > 0) { 18319sqlite3* db = this->connection->get(); 18320try_to_create_aggregate_function(db, this->aggregateFunctions.back()); 18321} 18322} 18323 18324void delete_function_impl(const std::string& name, std::list<udf_proxy>& functions) const { 18325#if __cpp_lib_ranges >= 201911L 18326auto it = std::ranges::find(functions, name, &udf_proxy::name); 18327#else 18328auto it = std::find_if(functions.begin(), functions.end(), [&name](auto& udfProxy) { 18329return udfProxy.name == name; 18330}); 18331#endif 18332if (it != functions.end()) { 18333if (this->connection->retain_count() > 0) { 18334sqlite3* db = this->connection->get(); 18335int rc = sqlite3_create_function_v2(db, 18336name.c_str(), 18337it->argumentsCount, 18338SQLITE_UTF8, 18339nullptr, 18340nullptr, 18341nullptr, 18342nullptr, 18343nullptr); 18344if (rc != SQLITE_OK) { 18345throw_translated_sqlite_error(db); 18346} 18347} 18348it = functions.erase(it); 18349} else { 18350throw std::system_error{orm_error_code::function_not_found}; 18351} 18352} 18353 18354static void try_to_create_scalar_function(sqlite3* db, udf_proxy& udfProxy) { 18355int rc = sqlite3_create_function_v2(db, 18356udfProxy.name.c_str(), 18357udfProxy.argumentsCount, 18358SQLITE_UTF8, 18359&udfProxy, 18360udfProxy.func, 18361nullptr, 18362nullptr, 18363nullptr); 18364if (rc != SQLITE_OK) { 18365throw_translated_sqlite_error(db); 18366} 18367} 18368 18369static void try_to_create_aggregate_function(sqlite3* db, udf_proxy& udfProxy) { 18370int rc = sqlite3_create_function(db, 18371udfProxy.name.c_str(), 18372udfProxy.argumentsCount, 18373SQLITE_UTF8, 18374&udfProxy, 18375nullptr, 18376udfProxy.func, 18377aggregate_function_final_callback); 18378if (rc != SQLITE_OK) { 18379throw_translated_sqlite_error(rc); 18380} 18381} 18382 18383std::string current_time(sqlite3* db) { 18384std::string result; 18385perform_exec(db, "SELECT CURRENT_TIME", extract_single_value<std::string>, &result); 18386return result; 18387} 18388 18389std::string current_date(sqlite3* db) { 18390std::string result; 18391perform_exec(db, "SELECT CURRENT_DATE", extract_single_value<std::string>, &result); 18392return result; 18393} 18394 18395std::string current_timestamp(sqlite3* db) { 18396std::string result; 18397perform_exec(db, "SELECT CURRENT_TIMESTAMP", extract_single_value<std::string>, &result); 18398return result; 18399} 18400 18401void drop_table_internal(sqlite3* db, const std::string& tableName, bool ifExists) { 18402std::stringstream ss; 18403ss << "DROP TABLE"; 18404if (ifExists) { 18405ss << " IF EXISTS"; 18406} 18407ss << ' ' << streaming_identifier(tableName) << std::flush; 18408perform_void_exec(db, ss.str()); 18409} 18410 18411void drop_index_internal(const std::string& indexName, bool ifExists) { 18412std::stringstream ss; 18413ss << "DROP INDEX"; 18414if (ifExists) { 18415ss << " IF EXISTS"; 18416} 18417ss << ' ' << quote_identifier(indexName) << std::flush; 18418perform_void_exec(this->get_connection().get(), ss.str()); 18419} 18420 18421void drop_trigger_internal(const std::string& triggerName, bool ifExists) { 18422std::stringstream ss; 18423ss << "DROP TRIGGER"; 18424if (ifExists) { 18425ss << " IF EXISTS"; 18426} 18427ss << ' ' << quote_identifier(triggerName) << std::flush; 18428perform_void_exec(this->get_connection().get(), ss.str()); 18429} 18430 18431static int 18432collate_callback(void* argument, int leftLength, const void* lhs, int rightLength, const void* rhs) { 18433auto& function = *(collating_function*)argument; 18434return function(leftLength, lhs, rightLength, rhs); 18435} 18436 18437static int busy_handler_callback(void* selfPointer, int triesCount) { 18438auto& storage = *static_cast<storage_base*>(selfPointer); 18439if (storage._busy_handler) { 18440return storage._busy_handler(triesCount); 18441} else { 18442return 0; 18443} 18444} 18445 18446bool calculate_remove_add_columns(std::vector<const table_xinfo*>& columnsToAdd, 18447std::vector<table_xinfo>& storageTableInfo, 18448std::vector<table_xinfo>& dbTableInfo) const { 18449bool notEqual = false; 18450 18451// iterate through storage columns 18452for (size_t storageColumnInfoIndex = 0; storageColumnInfoIndex < storageTableInfo.size(); 18453++storageColumnInfoIndex) { 18454 18455// get storage's column info 18456table_xinfo& storageColumnInfo = storageTableInfo[storageColumnInfoIndex]; 18457const std::string& columnName = storageColumnInfo.name; 18458 18459// search for a column in db with the same name 18460#if __cpp_lib_ranges >= 201911L 18461auto dbColumnInfoIt = std::ranges::find(dbTableInfo, columnName, &table_xinfo::name); 18462#else 18463auto dbColumnInfoIt = std::find_if(dbTableInfo.begin(), dbTableInfo.end(), [&columnName](auto& ti) { 18464return ti.name == columnName; 18465}); 18466#endif 18467if (dbColumnInfoIt != dbTableInfo.end()) { 18468auto& dbColumnInfo = *dbColumnInfoIt; 18469auto columnsAreEqual = 18470dbColumnInfo.name == storageColumnInfo.name && 18471dbColumnInfo.notnull == storageColumnInfo.notnull && 18472(!dbColumnInfo.dflt_value.empty()) == (!storageColumnInfo.dflt_value.empty()) && 18473dbColumnInfo.pk == storageColumnInfo.pk && 18474(dbColumnInfo.hidden == 0) == (storageColumnInfo.hidden == 0); 18475if (!columnsAreEqual) { 18476notEqual = true; 18477break; 18478} 18479dbTableInfo.erase(dbColumnInfoIt); 18480storageTableInfo.erase(storageTableInfo.begin() + 18481static_cast<ptrdiff_t>(storageColumnInfoIndex)); 18482--storageColumnInfoIndex; 18483} else { 18484columnsToAdd.push_back(&storageColumnInfo); 18485} 18486} 18487return notEqual; 18488} 18489 18490const bool inMemory; 18491bool isOpenedForever = false; 18492std::unique_ptr<connection_holder> connection; 18493std::map<std::string, collating_function> collatingFunctions; 18494const int cachedForeignKeysCount; 18495std::function<int(int)> _busy_handler; 18496std::list<udf_proxy> scalarFunctions; 18497std::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 18513namespace sqlite_orm { 18514 18515namespace internal { 18516 18517template<class T, class SFINAE = void> 18518struct expression_object_type; 18519 18520template<class T> 18521using expression_object_type_t = typename expression_object_type<T>::type; 18522 18523template<typename S> 18524using statement_object_type_t = expression_object_type_t<expression_type_t<std::remove_reference_t<S>>>; 18525 18526template<class T> 18527struct expression_object_type<update_t<T>, void> : value_unref_type<T> {}; 18528 18529template<class T> 18530struct expression_object_type<replace_t<T>, void> : value_unref_type<T> {}; 18531 18532template<class T> 18533struct expression_object_type<T, match_if<is_replace_range, T>> { 18534using type = object_type_t<T>; 18535}; 18536 18537template<class T, class... Ids> 18538struct expression_object_type<remove_t<T, Ids...>, void> : value_unref_type<T> {}; 18539 18540template<class T> 18541struct expression_object_type<insert_t<T>, void> : value_unref_type<T> {}; 18542 18543template<class T> 18544struct expression_object_type<T, match_if<is_insert_range, T>> { 18545using type = object_type_t<T>; 18546}; 18547 18548template<class T, class... Cols> 18549struct expression_object_type<insert_explicit<T, Cols...>, void> : value_unref_type<T> {}; 18550 18551template<class T> 18552struct get_ref_t { 18553 18554template<class O> 18555auto& operator()(O& t) const { 18556return t; 18557} 18558}; 18559 18560template<class T> 18561struct get_ref_t<std::reference_wrapper<T>> { 18562 18563template<class O> 18564auto& operator()(O& t) const { 18565return t.get(); 18566} 18567}; 18568 18569template<class T> 18570auto& get_ref(T& t) { 18571using arg_type = std::decay_t<T>; 18572get_ref_t<arg_type> g; 18573return g(t); 18574} 18575 18576template<class T> 18577struct get_object_t; 18578 18579template<class T> 18580struct get_object_t<const T> : get_object_t<T> {}; 18581 18582template<class T> 18583auto& get_object(T& t) { 18584using expression_type = std::decay_t<T>; 18585get_object_t<expression_type> obj; 18586return obj(t); 18587} 18588 18589template<class T> 18590struct get_object_t<replace_t<T>> { 18591using expression_type = replace_t<T>; 18592 18593template<class O> 18594auto& operator()(O& e) const { 18595return get_ref(e.object); 18596} 18597}; 18598 18599template<class T> 18600struct get_object_t<insert_t<T>> { 18601using expression_type = insert_t<T>; 18602 18603template<class O> 18604auto& operator()(O& e) const { 18605return get_ref(e.object); 18606} 18607}; 18608 18609template<class T> 18610struct get_object_t<update_t<T>> { 18611using expression_type = update_t<T>; 18612 18613template<class O> 18614auto& operator()(O& e) const { 18615return 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 18658namespace sqlite_orm { 18659namespace internal { 18660struct rank_t {}; 18661} 18662 18663inline internal::rank_t rank() { 18664return {}; 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 18723namespace sqlite_orm { 18724 18725namespace internal { 18726 18727template<class T, class Ctx> 18728auto serialize(const T& t, const Ctx& context); 18729 18730template<class T, class Ctx> 18731std::vector<std::string>& collect_table_column_names(std::vector<std::string>& collectedExpressions, 18732bool definedOrder, 18733const Ctx& context) { 18734if (definedOrder) { 18735auto& table = pick_table<mapped_type_proxy_t<T>>(context.db_objects); 18736collectedExpressions.reserve(collectedExpressions.size() + table.template count_of<is_column>()); 18737table.for_each_column([qualified = !context.skip_table_name, 18738&tableName = table.name, 18739&collectedExpressions](const column_identifier& column) { 18740if (is_alias<T>::value) { 18741collectedExpressions.push_back(quote_identifier(alias_extractor<T>::extract()) + "." + 18742quote_identifier(column.name)); 18743} else if (qualified) { 18744collectedExpressions.push_back(quote_identifier(tableName) + "." + 18745quote_identifier(column.name)); 18746} else { 18747collectedExpressions.push_back(quote_identifier(column.name)); 18748} 18749}); 18750} else { 18751collectedExpressions.reserve(collectedExpressions.size() + 1); 18752if (is_alias<T>::value) { 18753collectedExpressions.push_back(quote_identifier(alias_extractor<T>::extract()) + ".*"); 18754} else if (!context.skip_table_name) { 18755const basic_table& table = pick_table<mapped_type_proxy_t<T>>(context.db_objects); 18756collectedExpressions.push_back(quote_identifier(table.name) + ".*"); 18757} else { 18758collectedExpressions.emplace_back("*"); 18759} 18760} 18761 18762return collectedExpressions; 18763} 18764 18765/** @short Column expression collector. 18766*/ 18767struct column_names_getter { 18768/** 18769* The default implementation simply serializes the passed argument. 18770*/ 18771template<class E, class Ctx> 18772std::vector<std::string>& operator()(const E& t, const Ctx& context) { 18773auto columnExpression = serialize(t, context); 18774if (columnExpression.empty()) { 18775throw std::system_error{orm_error_code::column_not_found}; 18776} 18777this->collectedExpressions.reserve(this->collectedExpressions.size() + 1); 18778this->collectedExpressions.push_back(std::move(columnExpression)); 18779return this->collectedExpressions; 18780} 18781 18782template<class T, class Ctx> 18783std::vector<std::string>& operator()(const std::reference_wrapper<T>& expression, const Ctx& context) { 18784return (*this)(expression.get(), context); 18785} 18786 18787template<class T, class Ctx> 18788std::vector<std::string>& operator()(const asterisk_t<T>& expression, const Ctx& context) { 18789return collect_table_column_names<T>(this->collectedExpressions, expression.defined_order, context); 18790} 18791 18792template<class T, class Ctx> 18793std::vector<std::string>& operator()(const object_t<T>& expression, const Ctx& context) { 18794return collect_table_column_names<T>(this->collectedExpressions, expression.defined_order, context); 18795} 18796 18797template<class... Args, class Ctx> 18798std::vector<std::string>& operator()(const columns_t<Args...>& cols, const Ctx& context) { 18799this->collectedExpressions.reserve(this->collectedExpressions.size() + cols.count); 18800iterate_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 18804if (tuple_has_template<typename columns_t<Args...>::columns_type, asterisk_t>::value && 18805this->collectedExpressions.capacity() > this->collectedExpressions.size()) { 18806this->collectedExpressions.shrink_to_fit(); 18807} 18808return this->collectedExpressions; 18809} 18810 18811template<class T, class... Args, class Ctx> 18812std::vector<std::string>& operator()(const struct_t<T, Args...>& cols, const Ctx& context) { 18813this->collectedExpressions.reserve(this->collectedExpressions.size() + cols.count); 18814iterate_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 18818if (tuple_has_template<typename struct_t<T, Args...>::columns_type, asterisk_t>::value && 18819this->collectedExpressions.capacity() > this->collectedExpressions.size()) { 18820this->collectedExpressions.shrink_to_fit(); 18821} 18822return this->collectedExpressions; 18823} 18824 18825std::vector<std::string> collectedExpressions; 18826}; 18827 18828template<class T, class Ctx> 18829std::vector<std::string> get_column_names(const T& expression, const Ctx& context) { 18830column_names_getter serializer; 18831return 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) 18860namespace sqlite_orm { 18861namespace internal { 18862// collecting column names utilizes the statement serializer 18863template<class T, class Ctx> 18864auto serialize(const T& t, const Ctx& context); 18865 18866inline void unquote_identifier(std::string& identifier) { 18867if (!identifier.empty()) { 18868constexpr char quoteChar = '"'; 18869constexpr char sqlEscaped[] = {quoteChar, quoteChar}; 18870identifier.erase(identifier.end() - 1); 18871identifier.erase(identifier.begin()); 18872for (size_t pos = 0; (pos = identifier.find(sqlEscaped, pos, 2)) != identifier.npos; ++pos) { 18873identifier.erase(pos, 1); 18874} 18875} 18876} 18877 18878inline void unquote_or_erase(std::string& name) { 18879constexpr char quoteChar = '"'; 18880if (name.front() == quoteChar) { 18881unquote_identifier(name); 18882} else { 18883// unaliased expression - see 3. below 18884name.clear(); 18885} 18886} 18887 18888template<class T, class SFINAE = void> 18889struct cte_column_names_collector { 18890using expression_type = T; 18891 18892// Compound statements are never passed in by db_objects_for_expression() 18893static_assert(!is_compound_operator_v<T>); 18894 18895template<class Ctx> 18896std::vector<std::string> operator()(const expression_type& t, const Ctx& context) const { 18897auto newContext = context; 18898newContext.skip_table_name = true; 18899std::string columnName = serialize(t, newContext); 18900if (columnName.empty()) { 18901throw std::system_error{orm_error_code::column_not_found}; 18902} 18903unquote_or_erase(columnName); 18904return {std::move(columnName)}; 18905} 18906}; 18907 18908template<class T, class Ctx> 18909std::vector<std::string> get_cte_column_names(const T& t, const Ctx& context) { 18910cte_column_names_collector<T> collector; 18911return collector(access_column_expression(t), context); 18912} 18913 18914template<class As> 18915struct cte_column_names_collector<As, match_specialization_of<As, as_t>> { 18916using expression_type = As; 18917 18918template<class Ctx> 18919std::vector<std::string> operator()(const expression_type& /*expression*/, const Ctx& /*context*/) const { 18920return {alias_extractor<alias_type_t<As>>::extract()}; 18921} 18922}; 18923 18924template<class Wrapper> 18925struct cte_column_names_collector<Wrapper, match_specialization_of<Wrapper, std::reference_wrapper>> { 18926using expression_type = Wrapper; 18927 18928template<class Ctx> 18929std::vector<std::string> operator()(const expression_type& expression, const Ctx& context) const { 18930return get_cte_column_names(expression.get(), context); 18931} 18932}; 18933 18934template<class Asterisk> 18935struct cte_column_names_collector<Asterisk, match_specialization_of<Asterisk, asterisk_t>> { 18936using expression_type = Asterisk; 18937using T = typename Asterisk::type; 18938 18939template<class Ctx> 18940std::vector<std::string> operator()(const expression_type&, const Ctx& context) const { 18941auto& table = pick_table<T>(context.db_objects); 18942 18943std::vector<std::string> columnNames; 18944columnNames.reserve(size_t(table.template count_of<is_column>())); 18945 18946table.for_each_column([&columnNames](const column_identifier& column) { 18947columnNames.push_back(column.name); 18948}); 18949return columnNames; 18950} 18951}; 18952 18953// No CTE for object expressions. 18954template<class Object> 18955struct cte_column_names_collector<Object, match_specialization_of<Object, object_t>> { 18956static_assert(polyfill::always_false_v<Object>, "Selecting an object in a subselect is not allowed."); 18957}; 18958 18959// No CTE for object expressions. 18960template<class Object> 18961struct cte_column_names_collector<Object, match_if<is_struct, Object>> { 18962static_assert(polyfill::always_false_v<Object>, "Repacking columns in a subselect is not allowed."); 18963}; 18964 18965template<class Columns> 18966struct cte_column_names_collector<Columns, match_specialization_of<Columns, columns_t>> { 18967using expression_type = Columns; 18968 18969template<class Ctx> 18970std::vector<std::string> operator()(const expression_type& cols, const Ctx& context) const { 18971std::vector<std::string> columnNames; 18972columnNames.reserve(size_t(cols.count)); 18973auto newContext = context; 18974newContext.skip_table_name = true; 18975iterate_tuple(cols.columns, [&columnNames, &newContext](auto& m) { 18976using value_type = polyfill::remove_cvref_t<decltype(m)>; 18977 18978if constexpr (polyfill::is_specialization_of_v<value_type, as_t>) { 18979columnNames.push_back(alias_extractor<alias_type_t<value_type>>::extract()); 18980} else { 18981std::string columnName = serialize(m, newContext); 18982if (!columnName.empty()) { 18983columnNames.push_back(std::move(columnName)); 18984} else { 18985throw std::system_error{orm_error_code::column_not_found}; 18986} 18987unquote_or_erase(columnNames.back()); 18988} 18989}); 18990return columnNames; 18991} 18992}; 18993 18994template<typename Ctx, typename E, typename ExplicitColRefs, satisfies_is_specialization_of<E, select_t> = true> 18995std::vector<std::string> 18996collect_cte_column_names(const E& sel, const ExplicitColRefs& explicitColRefs, const Ctx& context) { 18997// 1. determine column names from subselect 18998std::vector<std::string> columnNames = get_cte_column_names(sel.col, context); 18999 19000// 2. override column names from cte expression 19001if (size_t n = std::tuple_size_v<ExplicitColRefs>) { 19002if (n != columnNames.size()) { 19003throw std::system_error{orm_error_code::column_not_found}; 19004} 19005 19006size_t idx = 0; 19007iterate_tuple(explicitColRefs, [&idx, &columnNames, &context](auto& colRef) { 19008using ColRef = polyfill::remove_cvref_t<decltype(colRef)>; 19009 19010if constexpr (polyfill::is_specialization_of_v<ColRef, alias_holder>) { 19011columnNames[idx] = alias_extractor<type_t<ColRef>>::extract(); 19012} else if constexpr (std::is_member_pointer<ColRef>::value) { 19013using O = table_type_of_t<ColRef>; 19014if (auto* columnName = find_column_name<O>(context.db_objects, colRef)) { 19015columnNames[idx] = *columnName; 19016} else { 19017// relaxed: allow any member pointer as column reference 19018columnNames[idx] = typeid(ColRef).name(); 19019} 19020} else if constexpr (polyfill::is_specialization_of_v<ColRef, column_t>) { 19021columnNames[idx] = colRef.name; 19022} else if constexpr (std::is_same_v<ColRef, std::string>) { 19023if (!colRef.empty()) { 19024columnNames[idx] = colRef; 19025} 19026} else if constexpr (std::is_same_v<ColRef, polyfill::remove_cvref_t<decltype(std::ignore)>>) { 19027if (columnNames[idx].empty()) { 19028columnNames[idx] = std::to_string(idx + 1); 19029} 19030} else { 19031static_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{ 19039for (size_t i = 0, n = columnNames.size(); i < n; ++i) { 19040if (columnNames[i].empty()) { 19041columnNames[i] = std::to_string(i + 1); 19042} 19043} 19044} 19045 19046return 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 19057namespace sqlite_orm { 19058 19059namespace internal { 19060 19061template<class T, class SFINAE = void> 19062struct order_by_serializer; 19063 19064template<class T, class Ctx> 19065std::string serialize_order_by(const T& t, const Ctx& context) { 19066order_by_serializer<T> serializer; 19067return serializer(t, context); 19068} 19069 19070template<class O> 19071struct order_by_serializer<order_by_t<O>, void> { 19072using statement_type = order_by_t<O>; 19073 19074template<class Ctx> 19075std::string operator()(const statement_type& orderBy, const Ctx& context) const { 19076std::stringstream ss; 19077auto newContext = context; 19078newContext.skip_table_name = false; 19079 19080ss << serialize(orderBy.expression, newContext); 19081if (!orderBy._collate_argument.empty()) { 19082ss << " COLLATE " << orderBy._collate_argument; 19083} 19084switch (orderBy.asc_desc) { 19085case 1: 19086ss << " ASC"; 19087break; 19088case -1: 19089ss << " DESC"; 19090break; 19091} 19092return ss.str(); 19093} 19094}; 19095 19096template<class C> 19097struct order_by_serializer<dynamic_order_by_t<C>, void> { 19098using statement_type = dynamic_order_by_t<C>; 19099 19100template<class Ctx> 19101std::string operator()(const statement_type& orderBy, const Ctx&) const { 19102std::stringstream ss; 19103ss << static_cast<std::string>(orderBy) << " "; 19104int index = 0; 19105for (const dynamic_order_by_entry_t& entry: orderBy) { 19106if (index > 0) { 19107ss << ", "; 19108} 19109 19110ss << entry.name; 19111if (!entry._collate_argument.empty()) { 19112ss << " COLLATE " << entry._collate_argument; 19113} 19114switch (entry.asc_desc) { 19115case 1: 19116ss << " ASC"; 19117break; 19118case -1: 19119ss << " DESC"; 19120break; 19121} 19122++index; 19123}; 19124return 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 19159namespace sqlite_orm { 19160namespace internal { 19161enum class trigger_timing { trigger_before, trigger_after, trigger_instead_of }; 19162enum 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*/ 19170template<class T, class... S> 19171struct partial_trigger_t { 19172using statements_type = std::tuple<S...>; 19173 19174/** 19175* Base of the trigger (contains its type, timing and associated table) 19176*/ 19177T base; 19178/** 19179* Statements of the triggers (to be executed when the trigger fires) 19180*/ 19181statements_type statements; 19182 19183partial_trigger_t(T trigger_base, S... statements) : 19184base{std::move(trigger_base)}, statements{std::make_tuple<S...>(std::forward<S>(statements)...)} {} 19185 19186partial_trigger_t& end() { 19187return *this; 19188} 19189}; 19190 19191struct base_trigger { 19192/** 19193* Name of the trigger 19194*/ 19195std::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*/ 19203template<class T, class... S> 19204struct trigger_t : base_trigger { 19205using object_type = void; 19206using 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*/ 19211T base; 19212 19213/** 19214* Statements of the triggers (to be executed when the trigger fires) 19215*/ 19216elements_type elements; 19217 19218#ifndef SQLITE_ORM_AGGREGATE_BASES_SUPPORTED 19219trigger_t(std::string name, T trigger_base, elements_type statements) : 19220base_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*/ 19230template<class T, class W, class Type> 19231struct trigger_base_t { 19232using table_type = T; 19233using when_type = W; 19234using trigger_type_base = Type; 19235 19236/** 19237* Contains the trigger type and timing 19238*/ 19239trigger_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*/ 19245bool 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*/ 19251optional_container<when_type> container_when; 19252 19253trigger_base_t(trigger_type_base type_base_) : type_base(std::move(type_base_)) {} 19254 19255trigger_base_t& for_each_row() { 19256this->do_for_each_row = true; 19257return *this; 19258} 19259 19260template<class WW> 19261trigger_base_t<T, WW, Type> when(WW expression) { 19262trigger_base_t<T, WW, Type> res(this->type_base); 19263res.container_when.field = std::move(expression); 19264return res; 19265} 19266 19267template<class... S> 19268partial_trigger_t<trigger_base_t<T, W, Type>, S...> begin(S... statements) { 19269return {*this, std::forward<S>(statements)...}; 19270} 19271}; 19272 19273/** 19274* Contains the trigger type and timing 19275*/ 19276struct 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*/ 19281trigger_timing timing; 19282/** 19283* The type of the statement that would cause the trigger to fire. 19284* Can be DELETE, INSERT, or UPDATE. 19285*/ 19286trigger_type type; 19287 19288trigger_type_base_t(trigger_timing timing, trigger_type type) : timing(timing), type(type) {} 19289 19290template<class T> 19291trigger_base_t<T, void, trigger_type_base_t> on() { 19292return {*this}; 19293} 19294}; 19295 19296/** 19297* Special case for UPDATE OF (columns) 19298* Contains the trigger type and timing 19299*/ 19300template<class... Cs> 19301struct trigger_update_type_t : trigger_type_base_t { 19302using 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*/ 19308columns_type columns; 19309 19310trigger_update_type_t(trigger_timing timing, trigger_type type, Cs... columns) : 19311trigger_type_base_t(timing, type), columns(std::make_tuple<Cs...>(std::forward<Cs>(columns)...)) {} 19312 19313template<class T> 19314trigger_base_t<T, void, trigger_update_type_t<Cs...>> on() { 19315return {*this}; 19316} 19317}; 19318 19319struct trigger_timing_t { 19320trigger_timing timing; 19321 19322trigger_type_base_t delete_() { 19323return {timing, trigger_type::trigger_delete}; 19324} 19325 19326trigger_type_base_t insert() { 19327return {timing, trigger_type::trigger_insert}; 19328} 19329 19330trigger_type_base_t update() { 19331return {timing, trigger_type::trigger_update}; 19332} 19333 19334template<class... Cs> 19335trigger_update_type_t<Cs...> update_of(Cs... columns) { 19336return {timing, trigger_type::trigger_update, std::forward<Cs>(columns)...}; 19337} 19338}; 19339 19340struct raise_t { 19341enum class type_t { 19342ignore, 19343rollback, 19344abort, 19345fail, 19346}; 19347 19348type_t type = type_t::ignore; 19349std::string message; 19350 19351#ifndef SQLITE_ORM_AGGREGATE_NSDMI_SUPPORTED 19352raise_t(type_t type, std::string message) : type{type}, message{std::move(message)} {} 19353#endif 19354}; 19355 19356template<class T> 19357struct new_t { 19358using expression_type = T; 19359 19360expression_type expression; 19361}; 19362 19363template<class T> 19364struct old_t { 19365using expression_type = T; 19366 19367expression_type expression; 19368}; 19369} // NAMESPACE internal 19370 19371/** 19372* NEW.expression function used within TRIGGER expressions 19373*/ 19374template<class T> 19375internal::new_t<T> new_(T expression) { 19376return {std::move(expression)}; 19377} 19378 19379/** 19380* OLD.expression function used within TRIGGER expressions 19381*/ 19382template<class T> 19383internal::old_t<T> old(T expression) { 19384return {std::move(expression)}; 19385} 19386 19387/** 19388* RAISE(IGNORE) expression used within TRIGGER expressions 19389*/ 19390inline internal::raise_t raise_ignore() { 19391return {internal::raise_t::type_t::ignore, {}}; 19392} 19393 19394/** 19395* RAISE(ROLLBACK, %message%) expression used within TRIGGER expressions 19396*/ 19397inline internal::raise_t raise_rollback(std::string message) { 19398return {internal::raise_t::type_t::rollback, std::move(message)}; 19399} 19400 19401/** 19402* RAISE(ABORT, %message%) expression used within TRIGGER expressions 19403*/ 19404inline internal::raise_t raise_abort(std::string message) { 19405return {internal::raise_t::type_t::abort, std::move(message)}; 19406} 19407 19408/** 19409* RAISE(FAIL, %message%) expression used within TRIGGER expressions 19410*/ 19411inline internal::raise_t raise_fail(std::string message) { 19412return {internal::raise_t::type_t::fail, std::move(message)}; 19413} 19414 19415template<class T, class... S> 19416internal::trigger_t<T, S...> make_trigger(std::string name, const internal::partial_trigger_t<T, S...>& part) { 19417SQLITE_ORM_CLANG_SUPPRESS_MISSING_BRACES( 19418return {std::move(name), std::move(part.base), std::move(part.statements)}); 19419} 19420 19421inline internal::trigger_timing_t before() { 19422return {internal::trigger_timing::trigger_before}; 19423} 19424 19425inline internal::trigger_timing_t after() { 19426return {internal::trigger_timing::trigger_after}; 19427} 19428 19429inline internal::trigger_timing_t instead_of() { 19430return {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 19440namespace sqlite_orm { 19441 19442namespace internal { 19443 19444template<class T, class SFINAE = void> 19445struct statement_serializer; 19446 19447template<class T, class Ctx> 19448auto serialize(const T& t, const Ctx& context) { 19449statement_serializer<T> serializer; 19450return serializer(t, context); 19451} 19452 19453/** 19454* Serializer for bindable types. 19455*/ 19456template<class T> 19457struct statement_serializer<T, match_if<is_bindable, T>> { 19458using statement_type = T; 19459 19460template<class Ctx> 19461std::string operator()(const T& statement, const Ctx& context) const { 19462if (context.replace_bindable_with_question) { 19463return "?"; 19464} else { 19465return this->do_serialize(statement); 19466} 19467} 19468 19469private: 19470template<class X, 19471std::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, 19476bool> = true> 19477std::string do_serialize(const X& c) const { 19478static_assert(std::is_same<X, T>::value, ""); 19479 19480// implementation detail: utilizing field_printer 19481return field_printer<X>{}(c); 19482} 19483 19484std::string do_serialize(const std::string& c) const { 19485// implementation detail: utilizing field_printer 19486return quote_string_literal(field_printer<std::string>{}(c)); 19487} 19488 19489std::string do_serialize(const char* c) const { 19490return quote_string_literal(c); 19491} 19492#ifndef SQLITE_ORM_OMITS_CODECVT 19493std::string do_serialize(const std::wstring& c) const { 19494// implementation detail: utilizing field_printer 19495return quote_string_literal(field_printer<std::wstring>{}(c)); 19496} 19497 19498std::string do_serialize(const wchar_t* c) const { 19499std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>> converter; 19500return quote_string_literal(converter.to_bytes(c)); 19501} 19502#endif 19503#ifdef SQLITE_ORM_STRING_VIEW_SUPPORTED 19504std::string do_serialize(const std::string_view& c) const { 19505return quote_string_literal(std::string(c)); 19506} 19507#ifndef SQLITE_ORM_OMITS_CODECVT 19508std::string do_serialize(const std::wstring_view& c) const { 19509std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>> converter; 19510return 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*/ 19517std::string do_serialize(const std::vector<char>& t) const { 19518return quote_blob_literal(field_printer<std::vector<char>>{}(t)); 19519} 19520 19521#if SQLITE_VERSION_NUMBER >= 3020000 19522template<class P, class PT, class D> 19523std::string do_serialize(const pointer_binding<P, PT, D>&) const { 19524// always serialize null (security reasons) 19525return field_printer<nullptr_t>{}(nullptr); 19526} 19527#endif 19528}; 19529 19530template<class O, bool WithoutRowId, class... Cs> 19531struct statement_serializer<table_t<O, WithoutRowId, Cs...>, void> { 19532using statement_type = table_t<O, WithoutRowId, Cs...>; 19533 19534template<class Ctx> 19535std::string operator()(const statement_type& statement, const Ctx& context) { 19536return this->serialize(statement, context, statement.name); 19537} 19538 19539template<class Ctx> 19540auto serialize(const statement_type& statement, const Ctx& context, const std::string& tableName) { 19541std::stringstream ss; 19542ss << "CREATE TABLE " << streaming_identifier(tableName) << " (" 19543<< streaming_expressions_tuple(statement.elements, context) << ")"; 19544if (statement_type::is_without_rowid_v) { 19545ss << " WITHOUT ROWID"; 19546} 19547return ss.str(); 19548} 19549}; 19550 19551template<> 19552struct statement_serializer<current_time_t, void> { 19553using statement_type = current_time_t; 19554 19555template<class Ctx> 19556std::string operator()(const statement_type& /*statement*/, const Ctx& /*context*/) { 19557return "CURRENT_TIME"; 19558} 19559}; 19560 19561template<> 19562struct statement_serializer<current_date_t, void> { 19563using statement_type = current_date_t; 19564 19565template<class Ctx> 19566std::string operator()(const statement_type& /*statement*/, const Ctx& /*context*/) { 19567return "CURRENT_DATE"; 19568} 19569}; 19570 19571template<> 19572struct statement_serializer<current_timestamp_t, void> { 19573using statement_type = current_timestamp_t; 19574 19575template<class Ctx> 19576std::string operator()(const statement_type& /*statement*/, const Ctx& /*context*/) { 19577return "CURRENT_TIMESTAMP"; 19578} 19579}; 19580 19581template<class T, class X, class Y, class Z> 19582struct statement_serializer<highlight_t<T, X, Y, Z>, void> { 19583using statement_type = highlight_t<T, X, Y, Z>; 19584 19585template<class Ctx> 19586std::string operator()(const statement_type& statement, const Ctx& context) { 19587std::stringstream ss; 19588auto& tableName = lookup_table_name<T>(context.db_objects); 19589ss << "HIGHLIGHT (" << streaming_identifier(tableName); 19590ss << ", " << serialize(statement.argument0, context); 19591ss << ", " << serialize(statement.argument1, context); 19592ss << ", " << serialize(statement.argument2, context) << ")"; 19593return ss.str(); 19594} 19595}; 19596 19597/** 19598* Serializer for literal values. 19599*/ 19600template<class T> 19601struct statement_serializer<T, match_specialization_of<T, literal_holder>> { 19602using statement_type = T; 19603 19604template<class Ctx> 19605std::string operator()(const statement_type& literal, const Ctx& context) const { 19606static_assert(is_bindable_v<type_t<statement_type>>, "A literal value must be also bindable"); 19607 19608Ctx literalCtx = context; 19609literalCtx.replace_bindable_with_question = false; 19610statement_serializer<type_t<statement_type>> serializer{}; 19611return serializer(literal.value, literalCtx); 19612} 19613}; 19614 19615template<class F, class W> 19616struct statement_serializer<filtered_aggregate_function<F, W>, void> { 19617using statement_type = filtered_aggregate_function<F, W>; 19618 19619template<class Ctx> 19620std::string operator()(const statement_type& statement, const Ctx& context) { 19621std::stringstream ss; 19622ss << serialize(statement.function, context); 19623ss << " FILTER (WHERE " << serialize(statement.where, context) << ")"; 19624return ss.str(); 19625} 19626}; 19627 19628template<class T> 19629struct statement_serializer<excluded_t<T>, void> { 19630using statement_type = excluded_t<T>; 19631 19632template<class Ctx> 19633std::string operator()(const statement_type& statement, const Ctx& context) const { 19634std::stringstream ss; 19635ss << "excluded."; 19636if (auto* columnName = find_column_name(context.db_objects, statement.expression)) { 19637ss << streaming_identifier(*columnName); 19638} else { 19639throw std::system_error{orm_error_code::column_not_found}; 19640} 19641return ss.str(); 19642} 19643}; 19644#ifdef SQLITE_ORM_OPTIONAL_SUPPORTED 19645template<class T> 19646struct statement_serializer<as_optional_t<T>, void> { 19647using statement_type = as_optional_t<T>; 19648 19649template<class Ctx> 19650std::string operator()(const statement_type& statement, const Ctx& context) const { 19651return serialize(statement.expression, context); 19652} 19653}; 19654#endif // SQLITE_ORM_OPTIONAL_SUPPORTED 19655template<class T> 19656struct statement_serializer<std::reference_wrapper<T>, void> { 19657using statement_type = std::reference_wrapper<T>; 19658 19659template<class Ctx> 19660std::string operator()(const statement_type& s, const Ctx& context) const { 19661return serialize(s.get(), context); 19662} 19663}; 19664 19665template<class T> 19666struct statement_serializer<alias_holder<T>, void> { 19667using statement_type = alias_holder<T>; 19668 19669template<class Ctx> 19670std::string operator()(const statement_type&, const Ctx&) { 19671std::stringstream ss; 19672ss << streaming_identifier(T::get()); 19673return ss.str(); 19674} 19675}; 19676 19677template<class T, class X> 19678struct statement_serializer<match_t<T, X>, void> { 19679using statement_type = match_t<T, X>; 19680 19681template<class Ctx> 19682std::string operator()(const statement_type& statement, const Ctx& context) const { 19683auto& table = pick_table<T>(context.db_objects); 19684std::stringstream ss; 19685ss << streaming_identifier(table.name) << " MATCH " << serialize(statement.argument, context); 19686return ss.str(); 19687} 19688}; 19689 19690template<char... C> 19691struct statement_serializer<column_alias<C...>, void> { 19692using statement_type = column_alias<C...>; 19693 19694template<class Ctx> 19695std::string operator()(const statement_type&, const Ctx&) { 19696std::stringstream ss; 19697ss << streaming_identifier(statement_type::get()); 19698return ss.str(); 19699} 19700}; 19701 19702template<class T> 19703struct statement_serializer<T, match_if<is_upsert_clause, T>> { 19704using statement_type = T; 19705 19706template<class Ctx> 19707std::string operator()(const statement_type& statement, const Ctx& context) const { 19708std::stringstream ss; 19709ss << "ON CONFLICT"; 19710iterate_tuple(statement.target_args, [&ss, &context](auto& value) { 19711using value_type = polyfill::remove_cvref_t<decltype(value)>; 19712auto needParenthesis = std::is_member_pointer<value_type>::value; 19713ss << ' '; 19714if (needParenthesis) { 19715ss << '('; 19716} 19717ss << serialize(value, context); 19718if (needParenthesis) { 19719ss << ')'; 19720} 19721}); 19722ss << ' ' << "DO"; 19723if (std::tuple_size<typename statement_type::actions_tuple>::value == 0) { 19724ss << " NOTHING"; 19725} else { 19726auto updateContext = context; 19727updateContext.use_parentheses = false; 19728ss << " UPDATE " << streaming_actions_tuple(statement.actions, updateContext); 19729} 19730return ss.str(); 19731} 19732}; 19733 19734template<class R, class S, class... Args> 19735struct statement_serializer<built_in_function_t<R, S, Args...>, void> { 19736using statement_type = built_in_function_t<R, S, Args...>; 19737 19738template<class Ctx> 19739std::string operator()(const statement_type& statement, const Ctx& context) const { 19740std::stringstream ss; 19741ss << statement.serialize() << "(" << streaming_expressions_tuple(statement.args, context) << ")"; 19742return ss.str(); 19743} 19744}; 19745 19746template<class R, class S, class... Args> 19747struct statement_serializer<built_in_aggregate_function_t<R, S, Args...>, void> 19748: statement_serializer<built_in_function_t<R, S, Args...>, void> {}; 19749 19750template<class F, class... CallArgs> 19751struct statement_serializer<function_call<F, CallArgs...>, void> { 19752using statement_type = function_call<F, CallArgs...>; 19753 19754template<class Ctx> 19755std::string operator()(const statement_type& statement, const Ctx& context) const { 19756std::stringstream ss; 19757stream_identifier(ss, "", statement.name(), ""); 19758ss << "(" << streaming_expressions_tuple(statement.callArgs, context) << ")"; 19759return ss.str(); 19760} 19761}; 19762 19763template<class T, class E> 19764struct statement_serializer<as_t<T, E>, void> { 19765using statement_type = as_t<T, E>; 19766 19767template<class Ctx> 19768std::string operator()(const statement_type& c, const Ctx& context) const { 19769std::stringstream ss; 19770ss << serialize(c.expression, context) + " AS " << streaming_identifier(alias_extractor<T>::extract()); 19771return ss.str(); 19772} 19773}; 19774 19775template<class T, class P> 19776struct statement_serializer<alias_column_t<T, P>, void> { 19777using statement_type = alias_column_t<T, P>; 19778 19779template<class Ctx> 19780std::string operator()(const statement_type& c, const Ctx& context) const { 19781std::stringstream ss; 19782if (!context.skip_table_name) { 19783ss << streaming_identifier(alias_extractor<T>::extract()) << "."; 19784} 19785auto newContext = context; 19786newContext.skip_table_name = true; 19787ss << serialize(c.column, newContext); 19788return ss.str(); 19789} 19790}; 19791 19792template<class E> 19793struct statement_serializer< 19794E, 19795std::enable_if_t<polyfill::disjunction<std::is_member_pointer<E>, is_column_pointer<E>>::value>> { 19796using statement_type = E; 19797 19798template<class Ctx> 19799std::string operator()(const statement_type& e, const Ctx& context) const { 19800std::stringstream ss; 19801if (auto* columnName = find_column_name(context.db_objects, e)) { 19802ss << streaming_identifier( 19803!context.skip_table_name ? lookup_table_name<table_type_of_t<E>>(context.db_objects) : "", 19804*columnName, 19805""); 19806} else { 19807throw std::system_error{orm_error_code::column_not_found}; 19808} 19809return ss.str(); 19810} 19811}; 19812 19813template<> 19814struct statement_serializer<rank_t, void> { 19815using statement_type = rank_t; 19816 19817template<class Ctx> 19818serialize_result_type operator()(const statement_type& /*statement*/, const Ctx&) const { 19819return "rank"; 19820} 19821}; 19822 19823template<> 19824struct statement_serializer<rowid_t, void> { 19825using statement_type = rowid_t; 19826 19827template<class Ctx> 19828std::string operator()(const statement_type& statement, const Ctx&) const { 19829return static_cast<std::string>(statement); 19830} 19831}; 19832 19833template<> 19834struct statement_serializer<oid_t, void> { 19835using statement_type = oid_t; 19836 19837template<class Ctx> 19838std::string operator()(const statement_type& statement, const Ctx&) const { 19839return static_cast<std::string>(statement); 19840} 19841}; 19842 19843template<> 19844struct statement_serializer<_rowid_t, void> { 19845using statement_type = _rowid_t; 19846 19847template<class Ctx> 19848std::string operator()(const statement_type& statement, const Ctx&) const { 19849return static_cast<std::string>(statement); 19850} 19851}; 19852 19853template<class O> 19854struct statement_serializer<table_rowid_t<O>, void> { 19855using statement_type = table_rowid_t<O>; 19856 19857template<class Ctx> 19858std::string operator()(const statement_type& statement, const Ctx& context) const { 19859std::stringstream ss; 19860if (!context.skip_table_name) { 19861ss << streaming_identifier(lookup_table_name<O>(context.db_objects)) << "."; 19862} 19863ss << static_cast<std::string>(statement); 19864return ss.str(); 19865} 19866}; 19867 19868template<class O> 19869struct statement_serializer<table_oid_t<O>, void> { 19870using statement_type = table_oid_t<O>; 19871 19872template<class Ctx> 19873std::string operator()(const statement_type& statement, const Ctx& context) const { 19874std::stringstream ss; 19875if (!context.skip_table_name) { 19876ss << streaming_identifier(lookup_table_name<O>(context.db_objects)) << "."; 19877} 19878ss << static_cast<std::string>(statement); 19879return ss.str(); 19880} 19881}; 19882 19883template<class O> 19884struct statement_serializer<table__rowid_t<O>, void> { 19885using statement_type = table__rowid_t<O>; 19886 19887template<class Ctx> 19888std::string operator()(const statement_type& statement, const Ctx& context) const { 19889std::stringstream ss; 19890if (!context.skip_table_name) { 19891ss << streaming_identifier(lookup_table_name<O>(context.db_objects)) << "."; 19892} 19893ss << static_cast<std::string>(statement); 19894return ss.str(); 19895} 19896}; 19897 19898template<class L, class R> 19899struct statement_serializer<is_equal_with_table_t<L, R>, void> { 19900using statement_type = is_equal_with_table_t<L, R>; 19901 19902template<class Ctx> 19903std::string operator()(const statement_type& statement, const Ctx& context) const { 19904std::stringstream ss; 19905const auto tableName = lookup_table_name<L>(context.db_objects); 19906ss << streaming_identifier(tableName); 19907ss << " = "; 19908ss << serialize(statement.rhs, context); 19909return ss.str(); 19910} 19911}; 19912 19913template<class T> 19914struct statement_serializer<count_asterisk_t<T>, void> { 19915using statement_type = count_asterisk_t<T>; 19916 19917template<class Ctx> 19918std::string operator()(const statement_type&, const Ctx& context) const { 19919return serialize(count_asterisk_without_type{}, context); 19920} 19921}; 19922 19923template<> 19924struct statement_serializer<count_asterisk_without_type, void> { 19925using statement_type = count_asterisk_without_type; 19926 19927template<class Ctx> 19928std::string operator()(const statement_type& c, const Ctx&) const { 19929std::stringstream ss; 19930auto functionName = c.serialize(); 19931ss << functionName << "(*)"; 19932return 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. 19938template<class T> 19939struct statement_serializer<distinct_t<T>, void> { 19940using statement_type = distinct_t<T>; 19941 19942template<class Ctx> 19943std::string operator()(const statement_type& c, const Ctx& context) const { 19944// DISTINCT introduces no parentheses 19945auto subCtx = context; 19946subCtx.use_parentheses = false; 19947 19948std::stringstream ss; 19949auto expr = serialize(c.expression, subCtx); 19950ss << static_cast<std::string>(c) << " " << expr; 19951return ss.str(); 19952} 19953}; 19954 19955template<class T, class E> 19956struct statement_serializer<cast_t<T, E>, void> { 19957using statement_type = cast_t<T, E>; 19958 19959template<class Ctx> 19960std::string operator()(const statement_type& c, const Ctx& context) const { 19961std::stringstream ss; 19962ss << static_cast<std::string>(c) << " ("; 19963ss << serialize(c.expression, context) << " AS " << type_printer<T>().print() << ")"; 19964return 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 19971template<> 19972struct statement_serializer<materialized_t, void> { 19973using statement_type = materialized_t; 19974 19975template<class Ctx> 19976std::string_view operator()(const statement_type& /*statement*/, const Ctx& /*context*/) const { 19977return "MATERIALIZED"; 19978} 19979}; 19980 19981template<> 19982struct statement_serializer<not_materialized_t, void> { 19983using statement_type = not_materialized_t; 19984 19985template<class Ctx> 19986std::string_view operator()(const statement_type& /*statement*/, const Ctx& /*context*/) const { 19987return "NOT MATERIALIZED"; 19988} 19989}; 19990#endif 19991#endif 19992 19993template<class CTE> 19994struct statement_serializer<CTE, match_specialization_of<CTE, common_table_expression>> { 19995using statement_type = CTE; 19996 19997template<class Ctx> 19998std::string operator()(const statement_type& cte, const Ctx& context) const { 19999// A CTE always starts a new 'highest level' context 20000Ctx cteContext = context; 20001cteContext.use_parentheses = false; 20002 20003std::stringstream ss; 20004ss << streaming_identifier(alias_extractor<cte_moniker_type_t<CTE>>::extract()); 20005{ 20006std::vector<std::string> columnNames = 20007collect_cte_column_names(get_cte_driving_subselect(cte.subselect), 20008cte.explicitColumns, 20009context); 20010ss << '(' << streaming_identifiers(columnNames) << ')'; 20011} 20012ss << " AS" << streaming_constraints_tuple(cte.hints, context) << " (" 20013<< serialize(cte.subselect, cteContext) << ')'; 20014return ss.str(); 20015} 20016}; 20017 20018template<class With> 20019struct statement_serializer<With, match_specialization_of<With, with_t>> { 20020using statement_type = With; 20021 20022template<class Ctx> 20023std::string operator()(const statement_type& c, const Ctx& context) const { 20024Ctx tupleContext = context; 20025tupleContext.use_parentheses = false; 20026 20027std::stringstream ss; 20028ss << "WITH"; 20029if (c.recursiveIndicated) { 20030ss << " RECURSIVE"; 20031} 20032ss << " " << serialize(c.cte, tupleContext); 20033ss << " " << serialize(c.expression, context); 20034return ss.str(); 20035} 20036}; 20037#endif 20038 20039template<class T> 20040struct statement_serializer<T, match_if<is_compound_operator, T>> { 20041using statement_type = T; 20042 20043template<class Ctx> 20044std::string operator()(const statement_type& c, const Ctx& context) const { 20045std::stringstream ss; 20046ss << streaming_compound_expressions(c.compound, static_cast<std::string>(c), context); 20047return ss.str(); 20048} 20049}; 20050 20051template<class R, class T, class E, class... Args> 20052struct statement_serializer<simple_case_t<R, T, E, Args...>, void> { 20053using statement_type = simple_case_t<R, T, E, Args...>; 20054 20055template<class Ctx> 20056std::string operator()(const statement_type& c, const Ctx& context) const { 20057std::stringstream ss; 20058ss << "CASE "; 20059c.case_expression.apply([&ss, context](auto& c_) { 20060ss << serialize(c_, context) << " "; 20061}); 20062iterate_tuple(c.args, [&ss, context](auto& pair) { 20063ss << "WHEN " << serialize(pair.first, context) << " "; 20064ss << "THEN " << serialize(pair.second, context) << " "; 20065}); 20066c.else_expression.apply([&ss, context](auto& el) { 20067ss << "ELSE " << serialize(el, context) << " "; 20068}); 20069ss << "END"; 20070return ss.str(); 20071} 20072}; 20073 20074template<class T> 20075struct statement_serializer<is_null_t<T>, void> { 20076using statement_type = is_null_t<T>; 20077 20078template<class Ctx> 20079std::string operator()(const statement_type& c, const Ctx& context) const { 20080std::stringstream ss; 20081ss << serialize(c.t, context) << " " << static_cast<std::string>(c); 20082return ss.str(); 20083} 20084}; 20085 20086template<class T> 20087struct statement_serializer<is_not_null_t<T>, void> { 20088using statement_type = is_not_null_t<T>; 20089 20090template<class Ctx> 20091std::string operator()(const statement_type& c, const Ctx& context) const { 20092std::stringstream ss; 20093ss << serialize(c.t, context) << " " << static_cast<std::string>(c); 20094return ss.str(); 20095} 20096}; 20097 20098template<class T> 20099struct statement_serializer< 20100T, 20101std::enable_if_t<polyfill::disjunction<polyfill::is_specialization_of<T, unary_minus_t>, 20102polyfill::is_specialization_of<T, bitwise_not_t>>::value>> { 20103using statement_type = T; 20104 20105template<class Ctx> 20106std::string operator()(const statement_type& expression, const Ctx& context) const { 20107// subqueries should always use parentheses in binary expressions 20108auto subCtx = context; 20109subCtx.use_parentheses = true; 20110// parentheses for sub-trees to ensure the order of precedence 20111constexpr bool parenthesize = is_binary_condition<typename statement_type::argument_type>::value || 20112is_binary_operator<typename statement_type::argument_type>::value; 20113 20114std::stringstream ss; 20115ss << expression.serialize(); 20116if SQLITE_ORM_CONSTEXPR_IF (parenthesize) { 20117ss << "("; 20118} 20119ss << serialize(get_from_expression(expression.argument), subCtx); 20120if SQLITE_ORM_CONSTEXPR_IF (parenthesize) { 20121ss << ")"; 20122} 20123return ss.str(); 20124} 20125}; 20126 20127template<class T> 20128struct statement_serializer<negated_condition_t<T>, void> { 20129using statement_type = negated_condition_t<T>; 20130 20131template<class Ctx> 20132std::string operator()(const statement_type& expression, const Ctx& context) const { 20133// subqueries should always use parentheses in binary expressions 20134auto subCtx = context; 20135subCtx.use_parentheses = true; 20136// parentheses for sub-trees to ensure the order of precedence 20137constexpr bool parenthesize = is_binary_condition<typename statement_type::argument_type>::value || 20138is_binary_operator<typename statement_type::argument_type>::value; 20139 20140std::stringstream ss; 20141ss << static_cast<std::string>(expression) << " "; 20142if SQLITE_ORM_CONSTEXPR_IF (parenthesize) { 20143ss << "("; 20144} 20145ss << serialize(get_from_expression(expression.c), subCtx); 20146if SQLITE_ORM_CONSTEXPR_IF (parenthesize) { 20147ss << ")"; 20148} 20149return ss.str(); 20150} 20151}; 20152 20153template<class T> 20154struct statement_serializer< 20155T, 20156std::enable_if_t<polyfill::disjunction<is_binary_condition<T>, is_binary_operator<T>>::value>> { 20157using statement_type = T; 20158 20159template<class Ctx> 20160std::string operator()(const statement_type& statement, const Ctx& context) const { 20161// subqueries should always use parentheses in binary expressions 20162auto subCtx = context; 20163subCtx.use_parentheses = true; 20164// parentheses for sub-trees to ensure the order of precedence 20165constexpr bool parenthesizeLeft = is_binary_condition<left_type_t<statement_type>>::value || 20166is_binary_operator<left_type_t<statement_type>>::value; 20167constexpr bool parenthesizeRight = is_binary_condition<right_type_t<statement_type>>::value || 20168is_binary_operator<right_type_t<statement_type>>::value; 20169 20170std::stringstream ss; 20171if SQLITE_ORM_CONSTEXPR_IF (parenthesizeLeft) { 20172ss << "("; 20173} 20174ss << serialize(statement.lhs, subCtx); 20175if SQLITE_ORM_CONSTEXPR_IF (parenthesizeLeft) { 20176ss << ")"; 20177} 20178ss << " " << statement.serialize() << " "; 20179if SQLITE_ORM_CONSTEXPR_IF (parenthesizeRight) { 20180ss << "("; 20181} 20182ss << serialize(statement.rhs, subCtx); 20183if SQLITE_ORM_CONSTEXPR_IF (parenthesizeRight) { 20184ss << ")"; 20185} 20186return ss.str(); 20187} 20188}; 20189 20190template<class T> 20191struct statement_serializer<named_collate<T>, void> { 20192using statement_type = named_collate<T>; 20193 20194template<class Ctx> 20195std::string operator()(const statement_type& c, const Ctx& context) const { 20196auto newContext = context; 20197newContext.use_parentheses = false; 20198auto res = serialize(c.expr, newContext); 20199return res + " " + static_cast<std::string>(c); 20200} 20201}; 20202 20203template<class T> 20204struct statement_serializer<collate_t<T>, void> { 20205using statement_type = collate_t<T>; 20206 20207template<class Ctx> 20208std::string operator()(const statement_type& c, const Ctx& context) const { 20209auto newContext = context; 20210newContext.use_parentheses = false; 20211auto res = serialize(c.expr, newContext); 20212return res + " " + static_cast<std::string>(c); 20213} 20214}; 20215 20216template<class L, class C> 20217struct statement_serializer< 20218dynamic_in_t<L, C>, 20219std::enable_if_t<!polyfill::disjunction<polyfill::is_specialization_of<C, std::vector>, 20220polyfill::is_specialization_of<C, std::list>>::value>> { 20221using statement_type = dynamic_in_t<L, C>; 20222 20223template<class Ctx> 20224std::string operator()(const statement_type& statement, const Ctx& context) const { 20225std::stringstream ss; 20226auto leftString = serialize(statement.left, context); 20227ss << leftString << " "; 20228if (!statement.negative) { 20229ss << "IN"; 20230} else { 20231ss << "NOT IN"; 20232} 20233ss << " "; 20234if (is_compound_operator<C>::value) { 20235ss << '('; 20236} 20237auto newContext = context; 20238newContext.use_parentheses = true; 20239ss << serialize(statement.argument, newContext); 20240if (is_compound_operator<C>::value) { 20241ss << ')'; 20242} 20243return ss.str(); 20244} 20245}; 20246 20247template<class L, class C> 20248struct statement_serializer< 20249dynamic_in_t<L, C>, 20250std::enable_if_t<polyfill::disjunction<polyfill::is_specialization_of<C, std::vector>, 20251polyfill::is_specialization_of<C, std::list>>::value>> { 20252using statement_type = dynamic_in_t<L, C>; 20253 20254template<class Ctx> 20255std::string operator()(const statement_type& statement, const Ctx& context) const { 20256std::stringstream ss; 20257auto leftString = serialize(statement.left, context); 20258ss << leftString << " "; 20259if (!statement.negative) { 20260ss << "IN"; 20261} else { 20262ss << "NOT IN"; 20263} 20264ss << " (" << streaming_dynamic_expressions(statement.argument, context) << ")"; 20265return ss.str(); 20266} 20267}; 20268 20269template<class L, class... Args> 20270struct statement_serializer<in_t<L, Args...>, void> { 20271using statement_type = in_t<L, Args...>; 20272 20273template<class Ctx> 20274std::string operator()(const statement_type& statement, const Ctx& context) const { 20275std::stringstream ss; 20276auto leftString = serialize(statement.left, context); 20277ss << leftString << " "; 20278if (!statement.negative) { 20279ss << "IN"; 20280} else { 20281ss << "NOT IN"; 20282} 20283ss << " "; 20284using args_type = std::tuple<Args...>; 20285constexpr bool theOnlySelect = 20286std::tuple_size<args_type>::value == 1 && is_select<std::tuple_element_t<0, args_type>>::value; 20287if (!theOnlySelect) { 20288ss << "("; 20289} 20290ss << streaming_expressions_tuple(statement.argument, context); 20291if (!theOnlySelect) { 20292ss << ")"; 20293} 20294return ss.str(); 20295} 20296}; 20297 20298template<class A, class T, class E> 20299struct statement_serializer<like_t<A, T, E>, void> { 20300using statement_type = like_t<A, T, E>; 20301 20302template<class Ctx> 20303std::string operator()(const statement_type& c, const Ctx& context) const { 20304std::stringstream ss; 20305ss << serialize(c.arg, context) << " "; 20306ss << static_cast<std::string>(c) << " "; 20307ss << serialize(c.pattern, context); 20308c.arg3.apply([&ss, &context](auto& value) { 20309ss << " ESCAPE " << serialize(value, context); 20310}); 20311return ss.str(); 20312} 20313}; 20314 20315template<class A, class T> 20316struct statement_serializer<glob_t<A, T>, void> { 20317using statement_type = glob_t<A, T>; 20318 20319template<class Ctx> 20320std::string operator()(const statement_type& c, const Ctx& context) const { 20321std::stringstream ss; 20322ss << serialize(c.arg, context) << " "; 20323ss << static_cast<std::string>(c) << " "; 20324ss << serialize(c.pattern, context); 20325return ss.str(); 20326} 20327}; 20328 20329template<class A, class T> 20330struct statement_serializer<between_t<A, T>, void> { 20331using statement_type = between_t<A, T>; 20332 20333template<class Ctx> 20334std::string operator()(const statement_type& c, const Ctx& context) const { 20335std::stringstream ss; 20336auto expr = serialize(c.expr, context); 20337ss << expr << " " << static_cast<std::string>(c) << " "; 20338ss << serialize(c.b1, context); 20339ss << " AND "; 20340ss << serialize(c.b2, context); 20341return ss.str(); 20342} 20343}; 20344 20345template<class T> 20346struct statement_serializer<exists_t<T>, void> { 20347using statement_type = exists_t<T>; 20348 20349template<class Ctx> 20350std::string operator()(const statement_type& statement, const Ctx& context) const { 20351std::stringstream ss; 20352auto newContext = context; 20353newContext.use_parentheses = true; 20354ss << "EXISTS " << serialize(statement.expression, newContext); 20355return ss.str(); 20356} 20357}; 20358 20359template<> 20360struct statement_serializer<conflict_clause_t, void> { 20361using statement_type = conflict_clause_t; 20362 20363template<class Ctx> 20364serialize_result_type operator()(const statement_type& statement, const Ctx&) const { 20365switch (statement) { 20366case conflict_clause_t::rollback: 20367return "ROLLBACK"; 20368case conflict_clause_t::abort: 20369return "ABORT"; 20370case conflict_clause_t::fail: 20371return "FAIL"; 20372case conflict_clause_t::ignore: 20373return "IGNORE"; 20374case conflict_clause_t::replace: 20375return "REPLACE"; 20376} 20377return {}; 20378} 20379}; 20380 20381template<class PK> 20382struct statement_serializer<primary_key_with_autoincrement<PK>, void> { 20383using statement_type = primary_key_with_autoincrement<PK>; 20384 20385template<class Ctx> 20386std::string operator()(const statement_type& statement, const Ctx& context) const { 20387return serialize(statement.as_base(), context) + " AUTOINCREMENT"; 20388} 20389}; 20390 20391template<> 20392struct statement_serializer<null_t, void> { 20393using statement_type = null_t; 20394 20395template<class Ctx> 20396serialize_result_type operator()(const statement_type& /*statement*/, const Ctx& /*context*/) const { 20397return "NULL"; 20398} 20399}; 20400 20401template<> 20402struct statement_serializer<not_null_t, void> { 20403using statement_type = not_null_t; 20404 20405template<class Ctx> 20406serialize_result_type operator()(const statement_type& /*statement*/, const Ctx& /*context*/) const { 20407return "NOT NULL"; 20408} 20409}; 20410 20411template<class... Cs> 20412struct statement_serializer<primary_key_t<Cs...>, void> { 20413using statement_type = primary_key_t<Cs...>; 20414 20415template<class Ctx> 20416std::string operator()(const statement_type& statement, const Ctx& context) const { 20417std::stringstream ss; 20418ss << "PRIMARY KEY"; 20419switch (statement.options.asc_option) { 20420case statement_type::order_by::ascending: 20421ss << " ASC"; 20422break; 20423case statement_type::order_by::descending: 20424ss << " DESC"; 20425break; 20426default: 20427break; 20428} 20429if (statement.options.conflict_clause_is_on) { 20430ss << " ON CONFLICT " << serialize(statement.options.conflict_clause, context); 20431} 20432using columns_tuple = typename statement_type::columns_tuple; 20433const size_t columnsCount = std::tuple_size<columns_tuple>::value; 20434if (columnsCount) { 20435ss << "(" << streaming_mapped_columns_expressions(statement.columns, context) << ")"; 20436} 20437return ss.str(); 20438} 20439}; 20440 20441template<class... Args> 20442struct statement_serializer<unique_t<Args...>, void> { 20443using statement_type = unique_t<Args...>; 20444 20445template<class Ctx> 20446std::string operator()(const statement_type& c, const Ctx& context) const { 20447std::stringstream ss; 20448ss << static_cast<std::string>(c); 20449using columns_tuple = typename statement_type::columns_tuple; 20450const size_t columnsCount = std::tuple_size<columns_tuple>::value; 20451if (columnsCount) { 20452ss << "(" << streaming_mapped_columns_expressions(c.columns, context) << ")"; 20453} 20454return ss.str(); 20455} 20456}; 20457 20458#if SQLITE_VERSION_NUMBER >= 3009000 20459template<> 20460struct statement_serializer<unindexed_t, void> { 20461using statement_type = unindexed_t; 20462 20463template<class Ctx> 20464serialize_result_type operator()(const statement_type& /*statement*/, const Ctx& /*context*/) const { 20465return "UNINDEXED"; 20466} 20467}; 20468 20469template<class T> 20470struct statement_serializer<prefix_t<T>, void> { 20471using statement_type = prefix_t<T>; 20472 20473template<class Ctx> 20474std::string operator()(const statement_type& statement, const Ctx& context) const { 20475std::stringstream ss; 20476ss << "prefix=" << serialize(statement.value, context); 20477return ss.str(); 20478} 20479}; 20480 20481template<class T> 20482struct statement_serializer<tokenize_t<T>, void> { 20483using statement_type = tokenize_t<T>; 20484 20485template<class Ctx> 20486std::string operator()(const statement_type& statement, const Ctx& context) const { 20487std::stringstream ss; 20488ss << "tokenize = " << serialize(statement.value, context); 20489return ss.str(); 20490} 20491}; 20492 20493template<class T> 20494struct statement_serializer<content_t<T>, void> { 20495using statement_type = content_t<T>; 20496 20497template<class Ctx> 20498std::string operator()(const statement_type& statement, const Ctx& context) const { 20499std::stringstream ss; 20500ss << "content=" << serialize(statement.value, context); 20501return ss.str(); 20502} 20503}; 20504 20505template<class T> 20506struct statement_serializer<table_content_t<T>, void> { 20507using statement_type = table_content_t<T>; 20508 20509template<class Ctx> 20510std::string operator()(const statement_type& /*statement*/, const Ctx& context) const { 20511using mapped_type = typename statement_type::mapped_type; 20512 20513auto& table = pick_table<mapped_type>(context.db_objects); 20514 20515std::stringstream ss; 20516ss << "content=" << streaming_identifier(table.name); 20517return ss.str(); 20518} 20519}; 20520#endif 20521 20522template<> 20523struct statement_serializer<collate_constraint_t, void> { 20524using statement_type = collate_constraint_t; 20525 20526template<class Ctx> 20527std::string operator()(const statement_type& statement, const Ctx&) const { 20528return static_cast<std::string>(statement); 20529} 20530}; 20531 20532template<class T> 20533struct statement_serializer<default_t<T>, void> { 20534using statement_type = default_t<T>; 20535 20536template<class Ctx> 20537std::string operator()(const statement_type& statement, const Ctx& context) const { 20538return static_cast<std::string>(statement) + " (" + serialize(statement.value, context) + ")"; 20539} 20540}; 20541 20542#if SQLITE_VERSION_NUMBER >= 3006019 20543template<class... Cs, class... Rs> 20544struct statement_serializer<foreign_key_t<std::tuple<Cs...>, std::tuple<Rs...>>, void> { 20545using statement_type = foreign_key_t<std::tuple<Cs...>, std::tuple<Rs...>>; 20546 20547template<class Ctx> 20548std::string operator()(const statement_type& fk, const Ctx& context) const { 20549std::stringstream ss; 20550ss << "FOREIGN KEY(" << streaming_mapped_columns_expressions(fk.columns, context) << ") REFERENCES "; 20551{ 20552using references_type_t = typename statement_type::references_type; 20553using first_reference_t = std::tuple_element_t<0, references_type_t>; 20554using first_reference_mapped_type = table_type_of_t<first_reference_t>; 20555auto refTableName = lookup_table_name<first_reference_mapped_type>(context.db_objects); 20556ss << streaming_identifier(refTableName); 20557} 20558ss << "(" << streaming_mapped_columns_expressions(fk.references, context) << ")"; 20559if (fk.on_update) { 20560ss << ' ' << static_cast<std::string>(fk.on_update) << " " << fk.on_update._action; 20561} 20562if (fk.on_delete) { 20563ss << ' ' << static_cast<std::string>(fk.on_delete) << " " << fk.on_delete._action; 20564} 20565return ss.str(); 20566} 20567}; 20568#endif 20569 20570template<class T> 20571struct statement_serializer<check_t<T>, void> { 20572using statement_type = check_t<T>; 20573 20574template<class Ctx> 20575std::string operator()(const statement_type& statement, const Ctx& context) const { 20576std::stringstream ss; 20577ss << "CHECK (" << serialize(statement.expression, context) << ")"; 20578return ss.str(); 20579} 20580}; 20581#if SQLITE_VERSION_NUMBER >= 3031000 20582template<class T> 20583struct statement_serializer<generated_always_t<T>, void> { 20584using statement_type = generated_always_t<T>; 20585 20586template<class Ctx> 20587std::string operator()(const statement_type& statement, const Ctx& context) const { 20588std::stringstream ss; 20589if (statement.full) { 20590ss << "GENERATED ALWAYS "; 20591} 20592ss << "AS ("; 20593ss << serialize(statement.expression, context) << ")"; 20594switch (statement.storage) { 20595case basic_generated_always::storage_type::not_specified: 20596//.. 20597break; 20598case basic_generated_always::storage_type::virtual_: 20599ss << " VIRTUAL"; 20600break; 20601case basic_generated_always::storage_type::stored: 20602ss << " STORED"; 20603break; 20604} 20605return ss.str(); 20606} 20607}; 20608#endif 20609template<class G, class S, class... Op> 20610struct statement_serializer<column_t<G, S, Op...>, void> { 20611using statement_type = column_t<G, S, Op...>; 20612 20613template<class Ctx> 20614std::string operator()(const statement_type& column, const Ctx& context) const { 20615std::stringstream ss; 20616ss << streaming_identifier(column.name); 20617if (!context.fts5_columns) { 20618ss << " " << type_printer<field_type_t<column_field<G, S>>>().print(); 20619} 20620ss << streaming_column_constraints( 20621call_as_template_base<column_constraints>(polyfill::identity{})(column), 20622column.is_not_null(), 20623context); 20624return ss.str(); 20625} 20626}; 20627 20628template<class T, class... Args> 20629struct statement_serializer<remove_all_t<T, Args...>, void> { 20630using statement_type = remove_all_t<T, Args...>; 20631 20632template<class Ctx> 20633std::string operator()(const statement_type& rem, const Ctx& context) const { 20634auto& table = pick_table<T>(context.db_objects); 20635 20636std::stringstream ss; 20637ss << "DELETE FROM " << streaming_identifier(table.name) 20638<< streaming_conditions_tuple(rem.conditions, context); 20639return ss.str(); 20640} 20641}; 20642 20643template<class T> 20644struct statement_serializer<replace_t<T>, void> { 20645using statement_type = replace_t<T>; 20646 20647template<class Ctx> 20648std::string operator()(const statement_type& statement, const Ctx& context) const { 20649using object_type = expression_object_type_t<statement_type>; 20650auto& table = pick_table<object_type>(context.db_objects); 20651std::stringstream ss; 20652ss << "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>{}, 20656empty_callable<std::false_type>, // don't exclude 20657context, 20658get_ref(statement.object)) 20659<< ")"; 20660return ss.str(); 20661} 20662}; 20663 20664template<class T, class... Cols> 20665struct statement_serializer<insert_explicit<T, Cols...>, void> { 20666using statement_type = insert_explicit<T, Cols...>; 20667 20668template<class Ctx> 20669std::string operator()(const statement_type& ins, const Ctx& context) const { 20670constexpr size_t colsCount = std::tuple_size<std::tuple<Cols...>>::value; 20671static_assert(colsCount > 0, "Use insert or replace with 1 argument instead"); 20672using object_type = expression_object_type_t<statement_type>; 20673auto& table = pick_table<object_type>(context.db_objects); 20674std::stringstream ss; 20675ss << "INSERT INTO " << streaming_identifier(table.name) << " "; 20676ss << "(" << streaming_mapped_columns_expressions(ins.columns.columns, context) << ") " 20677<< "VALUES ("; 20678iterate_tuple(ins.columns.columns, 20679[&ss, &context, &object = get_ref(ins.obj), first = true](auto& memberPointer) mutable { 20680using member_pointer_type = std::remove_reference_t<decltype(memberPointer)>; 20681static_assert(!is_setter_v<member_pointer_type>, 20682"Unable to use setter within insert explicit"); 20683 20684static constexpr std::array<const char*, 2> sep = {", ", ""}; 20685ss << sep[std::exchange(first, false)] 20686<< serialize(polyfill::invoke(memberPointer, object), context); 20687}); 20688ss << ")"; 20689return ss.str(); 20690} 20691}; 20692 20693template<class T> 20694struct statement_serializer<update_t<T>, void> { 20695using statement_type = update_t<T>; 20696 20697template<class Ctx> 20698std::string operator()(const statement_type& statement, const Ctx& context) const { 20699using object_type = expression_object_type_t<statement_type>; 20700auto& table = pick_table<object_type>(context.db_objects); 20701 20702std::stringstream ss; 20703ss << "UPDATE " << streaming_identifier(table.name) << " SET "; 20704table.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 { 20706if (exists_in_composite_primary_key(table, column)) { 20707return; 20708} 20709 20710static constexpr std::array<const char*, 2> sep = {", ", ""}; 20711ss << sep[std::exchange(first, false)] << streaming_identifier(column.name) << " = " 20712<< serialize(polyfill::invoke(column.member_pointer, object), context); 20713}); 20714ss << " WHERE "; 20715table.for_each_column( 20716[&table, &context, &ss, &object = get_ref(statement.object), first = true](auto& column) mutable { 20717if (!column.template is<is_primary_key>() && !exists_in_composite_primary_key(table, column)) { 20718return; 20719} 20720 20721static constexpr std::array<const char*, 2> sep = {" AND ", ""}; 20722ss << sep[std::exchange(first, false)] << streaming_identifier(column.name) << " = " 20723<< serialize(polyfill::invoke(column.member_pointer, object), context); 20724}); 20725return ss.str(); 20726} 20727}; 20728 20729template<class C> 20730struct statement_serializer<dynamic_set_t<C>, void> { 20731using statement_type = dynamic_set_t<C>; 20732 20733template<class Ctx> 20734std::string operator()(const statement_type& statement, const Ctx&) const { 20735std::stringstream ss; 20736ss << "SET "; 20737int index = 0; 20738for (const dynamic_set_entry& entry: statement) { 20739if (index > 0) { 20740ss << ", "; 20741} 20742ss << entry.serialized_value; 20743++index; 20744} 20745return ss.str(); 20746} 20747}; 20748 20749template<class... Args> 20750struct statement_serializer<set_t<Args...>, void> { 20751using statement_type = set_t<Args...>; 20752 20753template<class Ctx> 20754std::string operator()(const statement_type& statement, const Ctx& context) const { 20755std::stringstream ss; 20756ss << "SET "; 20757auto leftContext = context; 20758leftContext.skip_table_name = true; 20759iterate_tuple(statement.assigns, [&ss, &context, &leftContext, first = true](auto& value) mutable { 20760static constexpr std::array<const char*, 2> sep = {", ", ""}; 20761ss << sep[std::exchange(first, false)] << serialize(value.lhs, leftContext) << ' ' 20762<< value.serialize() << ' ' << serialize(value.rhs, context); 20763}); 20764return ss.str(); 20765} 20766}; 20767 20768template<class Ctx, class... Args> 20769std::set<std::pair<std::string, std::string>> collect_table_names(const set_t<Args...>& set, const Ctx& ctx) { 20770auto 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 20772iterate_tuple(set.assigns, [&collector](const auto& assignmentOperator) { 20773iterate_ast(assignmentOperator.lhs, collector); 20774}); 20775return std::move(collector.table_names); 20776} 20777 20778template<class Ctx, class C> 20779const std::set<std::pair<std::string, std::string>>& collect_table_names(const dynamic_set_t<C>& set, 20780const Ctx&) { 20781return set.collector.table_names; 20782} 20783 20784template<class Ctx, class T, satisfies<is_select, T> = true> 20785std::set<std::pair<std::string, std::string>> collect_table_names(const T& sel, const Ctx& ctx) { 20786auto collector = make_table_name_collector(ctx.db_objects); 20787iterate_ast(sel, collector); 20788return std::move(collector.table_names); 20789} 20790 20791template<class S, class... Wargs> 20792struct statement_serializer<update_all_t<S, Wargs...>, void> { 20793using statement_type = update_all_t<S, Wargs...>; 20794 20795template<class Ctx> 20796std::string operator()(const statement_type& statement, const Ctx& context) const { 20797const auto& tableNames = collect_table_names(statement.set, context); 20798if (tableNames.empty()) { 20799throw std::system_error{orm_error_code::no_tables_specified}; 20800} 20801const std::string& tableName = tableNames.begin()->first; 20802 20803std::stringstream ss; 20804ss << "UPDATE " << streaming_identifier(tableName) << ' ' << serialize(statement.set, context) 20805<< streaming_conditions_tuple(statement.conditions, context); 20806return ss.str(); 20807} 20808}; 20809 20810template<class T> 20811struct statement_serializer<insert_t<T>, void> { 20812using statement_type = insert_t<T>; 20813 20814template<class Ctx> 20815std::string operator()(const statement_type& statement, const Ctx& context) const { 20816using object_type = expression_object_type_t<statement_type>; 20817auto& table = pick_table<object_type>(context.db_objects); 20818using is_without_rowid = typename std::remove_reference_t<decltype(table)>::is_without_rowid; 20819 20820std::vector<std::reference_wrapper<const std::string>> columnNames; 20821table.template for_each_column_excluding< 20822mpl::conjunction<mpl::not_<mpl::always<is_without_rowid>>, 20823mpl::disjunction_fn<is_primary_key, is_generated_always>>>( 20824[&table, &columnNames](auto& column) { 20825if (exists_in_composite_primary_key(table, column)) { 20826return; 20827} 20828 20829columnNames.push_back(cref(column.name)); 20830}); 20831const size_t columnNamesCount = columnNames.size(); 20832 20833std::stringstream ss; 20834ss << "INSERT INTO " << streaming_identifier(table.name) << " "; 20835if (columnNamesCount) { 20836ss << "(" << streaming_identifiers(columnNames) << ")"; 20837} else { 20838ss << "DEFAULT"; 20839} 20840ss << " VALUES"; 20841if (columnNamesCount) { 20842ss << " (" 20843<< streaming_field_values_excluding( 20844mpl::conjunction<mpl::not_<mpl::always<is_without_rowid>>, 20845mpl::disjunction_fn<is_primary_key, is_generated_always>>{}, 20846[&table](auto& column) { 20847return exists_in_composite_primary_key(table, column); 20848}, 20849context, 20850get_ref(statement.object)) 20851<< ")"; 20852} 20853 20854return ss.str(); 20855} 20856}; 20857 20858template<class T> 20859struct statement_serializer<into_t<T>, void> { 20860using statement_type = into_t<T>; 20861 20862template<class Ctx> 20863std::string operator()(const statement_type&, const Ctx& context) const { 20864auto& table = pick_table<T>(context.db_objects); 20865 20866std::stringstream ss; 20867ss << "INTO " << streaming_identifier(table.name); 20868return ss.str(); 20869} 20870}; 20871 20872template<class C> 20873struct statement_serializer<C, std::enable_if_t<polyfill::disjunction<is_columns<C>, is_struct<C>>::value>> { 20874using statement_type = C; 20875 20876template<class Ctx> 20877std::string operator()(const statement_type& statement, const Ctx& context) const { 20878// subqueries should always use parentheses in column names 20879auto subCtx = context; 20880subCtx.use_parentheses = true; 20881 20882std::stringstream ss; 20883if (context.use_parentheses) { 20884ss << '('; 20885} 20886ss << streaming_serialized(get_column_names(statement, subCtx)); 20887if (context.use_parentheses) { 20888ss << ')'; 20889} 20890return ss.str(); 20891} 20892}; 20893 20894template<class T> 20895struct statement_serializer< 20896T, 20897std::enable_if_t<polyfill::disjunction<is_insert_raw<T>, is_replace_raw<T>>::value>> { 20898using statement_type = T; 20899 20900template<class Ctx> 20901std::string operator()(const statement_type& statement, const Ctx& context) const { 20902std::stringstream ss; 20903if (is_insert_raw<T>::value) { 20904ss << "INSERT"; 20905} else { 20906ss << "REPLACE"; 20907} 20908iterate_tuple(statement.args, [&context, &ss](auto& value) { 20909using value_type = polyfill::remove_cvref_t<decltype(value)>; 20910ss << ' '; 20911if (is_columns<value_type>::value) { 20912auto newContext = context; 20913newContext.skip_table_name = true; 20914newContext.use_parentheses = true; 20915ss << serialize(value, newContext); 20916} else if (is_values<value_type>::value || is_select<value_type>::value) { 20917auto newContext = context; 20918newContext.use_parentheses = false; 20919ss << serialize(value, newContext); 20920} else { 20921ss << serialize(value, context); 20922} 20923}); 20924return ss.str(); 20925} 20926}; 20927 20928template<class T, class... Ids> 20929struct statement_serializer<remove_t<T, Ids...>, void> { 20930using statement_type = remove_t<T, Ids...>; 20931 20932template<class Ctx> 20933std::string operator()(const statement_type& statement, const Ctx& context) const { 20934auto& table = pick_table<T>(context.db_objects); 20935std::stringstream ss; 20936ss << "DELETE FROM " << streaming_identifier(table.name) << " " 20937<< "WHERE "; 20938std::vector<std::string> idsStrings; 20939idsStrings.reserve(std::tuple_size<typename statement_type::ids_type>::value); 20940iterate_tuple(statement.ids, [&idsStrings, &context](auto& idValue) { 20941idsStrings.push_back(serialize(idValue, context)); 20942}); 20943table.for_each_primary_key_column([&table, &ss, &idsStrings, index = 0](auto& memberPointer) mutable { 20944auto* columnName = table.find_column_name(memberPointer); 20945if (!columnName) { 20946throw std::system_error{orm_error_code::column_not_found}; 20947} 20948 20949static constexpr std::array<const char*, 2> sep = {" AND ", ""}; 20950ss << sep[index == 0] << streaming_identifier(*columnName) << " = " << idsStrings[index]; 20951++index; 20952}); 20953return ss.str(); 20954} 20955}; 20956 20957template<class It, class L, class O> 20958struct statement_serializer<replace_range_t<It, L, O>, void> { 20959using statement_type = replace_range_t<It, L, O>; 20960 20961template<class Ctx> 20962std::string operator()(const statement_type& rep, const Ctx& context) const { 20963using object_type = expression_object_type_t<statement_type>; 20964auto& table = pick_table<object_type>(context.db_objects); 20965 20966std::stringstream ss; 20967ss << "REPLACE INTO " << streaming_identifier(table.name) << " (" 20968<< streaming_non_generated_column_names(table) << ")"; 20969const auto valuesCount = std::distance(rep.range.first, rep.range.second); 20970const auto columnsCount = table.template count_of_columns_excluding<is_generated_always>(); 20971ss << " VALUES " << streaming_values_placeholders(columnsCount, valuesCount); 20972return ss.str(); 20973} 20974}; 20975 20976template<class It, class L, class O> 20977struct statement_serializer<insert_range_t<It, L, O>, void> { 20978using statement_type = insert_range_t<It, L, O>; 20979 20980template<class Ctx> 20981std::string operator()(const statement_type& statement, const Ctx& context) const { 20982using object_type = expression_object_type_t<statement_type>; 20983auto& table = pick_table<object_type>(context.db_objects); 20984using is_without_rowid = typename std::remove_reference_t<decltype(table)>::is_without_rowid; 20985 20986std::vector<std::reference_wrapper<const std::string>> columnNames; 20987table.template for_each_column_excluding< 20988mpl::conjunction<mpl::not_<mpl::always<is_without_rowid>>, 20989mpl::disjunction_fn<is_primary_key, is_generated_always>>>( 20990[&table, &columnNames](auto& column) { 20991if (exists_in_composite_primary_key(table, column)) { 20992return; 20993} 20994 20995columnNames.push_back(cref(column.name)); 20996}); 20997const size_t valuesCount = std::distance(statement.range.first, statement.range.second); 20998const size_t columnNamesCount = columnNames.size(); 20999 21000std::stringstream ss; 21001ss << "INSERT INTO " << streaming_identifier(table.name) << " "; 21002if (columnNamesCount) { 21003ss << "(" << streaming_identifiers(columnNames) << ")"; 21004} else { 21005ss << "DEFAULT"; 21006} 21007ss << " VALUES "; 21008if (columnNamesCount) { 21009ss << streaming_values_placeholders(columnNamesCount, valuesCount); 21010} else if (valuesCount != 1) { 21011throw std::system_error{orm_error_code::cannot_use_default_value}; 21012} 21013return ss.str(); 21014} 21015}; 21016 21017template<class T, class Ctx> 21018std::string serialize_get_all_impl(const T& getAll, const Ctx& context) { 21019using table_type = type_t<T>; 21020using mapped_type = mapped_type_proxy_t<table_type>; 21021 21022auto& table = pick_table<mapped_type>(context.db_objects); 21023 21024std::stringstream ss; 21025ss << "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); 21028return ss.str(); 21029} 21030 21031#ifdef SQLITE_ORM_OPTIONAL_SUPPORTED 21032template<class T, class R, class... Args> 21033struct statement_serializer<get_all_optional_t<T, R, Args...>, void> { 21034using statement_type = get_all_optional_t<T, R, Args...>; 21035 21036template<class Ctx> 21037std::string operator()(const statement_type& get, const Ctx& context) const { 21038return serialize_get_all_impl(get, context); 21039} 21040}; 21041#endif // SQLITE_ORM_OPTIONAL_SUPPORTED 21042 21043template<class T, class R, class... Args> 21044struct statement_serializer<get_all_pointer_t<T, R, Args...>, void> { 21045using statement_type = get_all_pointer_t<T, R, Args...>; 21046 21047template<class Ctx> 21048std::string operator()(const statement_type& get, const Ctx& context) const { 21049return serialize_get_all_impl(get, context); 21050} 21051}; 21052 21053template<class T, class R, class... Args> 21054struct statement_serializer<get_all_t<T, R, Args...>, void> { 21055using statement_type = get_all_t<T, R, Args...>; 21056 21057template<class Ctx> 21058std::string operator()(const statement_type& get, const Ctx& context) const { 21059return serialize_get_all_impl(get, context); 21060} 21061}; 21062 21063template<class T, class Ctx> 21064std::string serialize_get_impl(const T&, const Ctx& context) { 21065using primary_type = type_t<T>; 21066auto& table = pick_table<primary_type>(context.db_objects); 21067std::stringstream ss; 21068ss << "SELECT " << streaming_table_column_names(table, std::string{}) << " FROM " 21069<< streaming_identifier(table.name) << " WHERE "; 21070 21071auto primaryKeyColumnNames = table.primary_key_column_names(); 21072if (primaryKeyColumnNames.empty()) { 21073throw std::system_error{orm_error_code::table_has_no_primary_key_column}; 21074} 21075 21076for (size_t i = 0; i < primaryKeyColumnNames.size(); ++i) { 21077if (i > 0) { 21078ss << " AND "; 21079} 21080ss << streaming_identifier(primaryKeyColumnNames[i]) << " = ?"; 21081} 21082return ss.str(); 21083} 21084 21085template<class T, class... Ids> 21086struct statement_serializer<get_t<T, Ids...>, void> { 21087using statement_type = get_t<T, Ids...>; 21088 21089template<class Ctx> 21090std::string operator()(const statement_type& get, const Ctx& context) const { 21091return serialize_get_impl(get, context); 21092} 21093}; 21094 21095template<class T, class... Ids> 21096struct statement_serializer<get_pointer_t<T, Ids...>, void> { 21097using statement_type = get_pointer_t<T, Ids...>; 21098 21099template<class Ctx> 21100std::string operator()(const statement_type& statement, const Ctx& context) const { 21101return serialize_get_impl(statement, context); 21102} 21103}; 21104 21105template<> 21106struct statement_serializer<conflict_action, void> { 21107using statement_type = conflict_action; 21108 21109template<class Ctx> 21110serialize_result_type operator()(const statement_type& statement, const Ctx&) const { 21111switch (statement) { 21112case conflict_action::replace: 21113return "REPLACE"; 21114case conflict_action::abort: 21115return "ABORT"; 21116case conflict_action::fail: 21117return "FAIL"; 21118case conflict_action::ignore: 21119return "IGNORE"; 21120case conflict_action::rollback: 21121return "ROLLBACK"; 21122} 21123return {}; 21124} 21125}; 21126 21127template<> 21128struct statement_serializer<insert_constraint, void> { 21129using statement_type = insert_constraint; 21130 21131template<class Ctx> 21132std::string operator()(const statement_type& statement, const Ctx& context) const { 21133std::stringstream ss; 21134 21135ss << "OR " << serialize(statement.action, context); 21136return ss.str(); 21137} 21138}; 21139 21140#ifdef SQLITE_ORM_OPTIONAL_SUPPORTED 21141template<class T, class... Ids> 21142struct statement_serializer<get_optional_t<T, Ids...>, void> { 21143using statement_type = get_optional_t<T, Ids...>; 21144 21145template<class Ctx> 21146std::string operator()(const statement_type& get, const Ctx& context) const { 21147return serialize_get_impl(get, context); 21148} 21149}; 21150#endif // SQLITE_ORM_OPTIONAL_SUPPORTED 21151 21152template<class T, class... Args> 21153struct statement_serializer<select_t<T, Args...>, void> { 21154using statement_type = select_t<T, Args...>; 21155using return_type = typename statement_type::return_type; 21156 21157template<class Ctx> 21158std::string operator()(const statement_type& sel, Ctx context) const { 21159context.skip_table_name = false; 21160// subqueries should always use parentheses in column names 21161auto subCtx = context; 21162subCtx.use_parentheses = true; 21163 21164std::stringstream ss; 21165if (!is_compound_operator<T>::value) { 21166if (!sel.highest_level && context.use_parentheses) { 21167ss << "("; 21168} 21169ss << "SELECT "; 21170call_if_constexpr<is_rowset_deduplicator_v<return_type>>( 21171// note: make use of implicit to-string conversion 21172[&ss](std::string keyword) { 21173ss << keyword << ' '; 21174}, 21175sel.col); 21176} 21177 21178ss << streaming_serialized(get_column_names(sel.col, subCtx)); 21179using conditions_tuple = typename statement_type::conditions_type; 21180constexpr bool hasExplicitFrom = tuple_has<conditions_tuple, is_from>::value; 21181if (!hasExplicitFrom) { 21182auto tableNames = collect_table_names(sel, context); 21183using joins_index_sequence = filter_tuple_sequence_t<conditions_tuple, is_constrained_join>; 21184// deduplicate table names of constrained join statements 21185iterate_tuple(sel.conditions, joins_index_sequence{}, [&tableNames, &context](auto& join) { 21186using original_join_type = typename std::remove_reference_t<decltype(join)>::type; 21187using cross_join_type = mapped_type_proxy_t<original_join_type>; 21188std::pair<const std::string&, std::string> tableNameWithAlias{ 21189lookup_table_name<cross_join_type>(context.db_objects), 21190alias_extractor<original_join_type>::as_alias()}; 21191tableNames.erase(tableNameWithAlias); 21192}); 21193if (!tableNames.empty() && !is_compound_operator<T>::value) { 21194ss << " FROM " << streaming_identifiers(tableNames); 21195} 21196} 21197ss << streaming_conditions_tuple(sel.conditions, context); 21198if (!is_compound_operator<T>::value) { 21199if (!sel.highest_level && context.use_parentheses) { 21200ss << ")"; 21201} 21202} 21203return ss.str(); 21204} 21205}; 21206 21207template<class T> 21208struct statement_serializer<indexed_column_t<T>, void> { 21209using statement_type = indexed_column_t<T>; 21210 21211template<class Ctx> 21212std::string operator()(const statement_type& statement, const Ctx& context) const { 21213std::stringstream ss; 21214ss << serialize(statement.column_or_expression, context); 21215if (!statement._collation_name.empty()) { 21216ss << " COLLATE " << statement._collation_name; 21217} 21218if (statement._order) { 21219switch (statement._order) { 21220case 1: 21221ss << " ASC"; 21222break; 21223case -1: 21224ss << " DESC"; 21225break; 21226} 21227} 21228return ss.str(); 21229} 21230}; 21231 21232#if SQLITE_VERSION_NUMBER >= 3009000 21233template<class... Cs> 21234struct statement_serializer<using_fts5_t<Cs...>, void> { 21235using statement_type = using_fts5_t<Cs...>; 21236 21237template<class Ctx> 21238std::string operator()(const statement_type& statement, const Ctx& context) const { 21239std::stringstream ss; 21240ss << "USING FTS5("; 21241auto subContext = context; 21242subContext.fts5_columns = true; 21243ss << streaming_expressions_tuple(statement.columns, subContext) << ")"; 21244return ss.str(); 21245} 21246}; 21247#endif 21248 21249template<class M> 21250struct statement_serializer<virtual_table_t<M>, void> { 21251using statement_type = virtual_table_t<M>; 21252 21253template<class Ctx> 21254std::string operator()(const statement_type& statement, const Ctx& context) const { 21255std::stringstream ss; 21256ss << "CREATE VIRTUAL TABLE IF NOT EXISTS "; 21257ss << streaming_identifier(statement.name) << ' '; 21258ss << serialize(statement.module_details, context); 21259return ss.str(); 21260} 21261}; 21262 21263template<class T, class... Cols> 21264struct statement_serializer<index_t<T, Cols...>, void> { 21265using statement_type = index_t<T, Cols...>; 21266 21267template<class Ctx> 21268std::string operator()(const statement_type& statement, const Ctx& context) const { 21269std::stringstream ss; 21270ss << "CREATE "; 21271if (statement.unique) { 21272ss << "UNIQUE "; 21273} 21274using indexed_type = typename statement_type::table_mapped_type; 21275ss << "INDEX IF NOT EXISTS " << streaming_identifier(statement.name) << " ON " 21276<< streaming_identifier(lookup_table_name<indexed_type>(context.db_objects)); 21277std::vector<std::string> columnNames; 21278std::string whereString; 21279iterate_tuple(statement.elements, [&columnNames, &context, &whereString](auto& value) { 21280using value_type = polyfill::remove_cvref_t<decltype(value)>; 21281if (!is_where<value_type>::value) { 21282auto newContext = context; 21283newContext.use_parentheses = false; 21284auto whereString = serialize(value, newContext); 21285columnNames.push_back(std::move(whereString)); 21286} else { 21287auto columnName = serialize(value, context); 21288whereString = std::move(columnName); 21289} 21290}); 21291ss << " (" << streaming_serialized(columnNames) << ")"; 21292if (!whereString.empty()) { 21293ss << ' ' << whereString; 21294} 21295return ss.str(); 21296} 21297}; 21298 21299template<class From> 21300struct statement_serializer<From, match_if<is_from, From>> { 21301using statement_type = From; 21302 21303template<class Ctx> 21304std::string operator()(const statement_type&, const Ctx& context) const { 21305std::stringstream ss; 21306ss << "FROM "; 21307iterate_tuple<typename From::tuple_type>([&context, &ss, first = true](auto* dummyItem) mutable { 21308using table_type = std::remove_pointer_t<decltype(dummyItem)>; 21309 21310static constexpr std::array<const char*, 2> sep = {", ", ""}; 21311ss << sep[std::exchange(first, false)] 21312<< streaming_identifier(lookup_table_name<mapped_type_proxy_t<table_type>>(context.db_objects), 21313alias_extractor<table_type>::as_alias()); 21314}); 21315return ss.str(); 21316} 21317}; 21318 21319template<class T> 21320struct statement_serializer<old_t<T>, void> { 21321using statement_type = old_t<T>; 21322 21323template<class Ctx> 21324std::string operator()(const statement_type& statement, const Ctx& context) const { 21325std::stringstream ss; 21326ss << "OLD."; 21327auto newContext = context; 21328newContext.skip_table_name = true; 21329ss << serialize(statement.expression, newContext); 21330return ss.str(); 21331} 21332}; 21333 21334template<class T> 21335struct statement_serializer<new_t<T>, void> { 21336using statement_type = new_t<T>; 21337 21338template<class Ctx> 21339std::string operator()(const statement_type& statement, const Ctx& context) const { 21340std::stringstream ss; 21341ss << "NEW."; 21342auto newContext = context; 21343newContext.skip_table_name = true; 21344ss << serialize(statement.expression, newContext); 21345return ss.str(); 21346} 21347}; 21348 21349template<> 21350struct statement_serializer<raise_t, void> { 21351using statement_type = raise_t; 21352 21353template<class Ctx> 21354std::string operator()(const statement_type& statement, const Ctx& context) const { 21355switch (statement.type) { 21356case raise_t::type_t::ignore: 21357return "RAISE(IGNORE)"; 21358 21359case raise_t::type_t::rollback: 21360return "RAISE(ROLLBACK, " + serialize(statement.message, context) + ")"; 21361 21362case raise_t::type_t::abort: 21363return "RAISE(ABORT, " + serialize(statement.message, context) + ")"; 21364 21365case raise_t::type_t::fail: 21366return "RAISE(FAIL, " + serialize(statement.message, context) + ")"; 21367} 21368return {}; 21369} 21370}; 21371 21372template<> 21373struct statement_serializer<trigger_timing, void> { 21374using statement_type = trigger_timing; 21375 21376template<class Ctx> 21377serialize_result_type operator()(const statement_type& statement, const Ctx&) const { 21378switch (statement) { 21379case trigger_timing::trigger_before: 21380return "BEFORE"; 21381case trigger_timing::trigger_after: 21382return "AFTER"; 21383case trigger_timing::trigger_instead_of: 21384return "INSTEAD OF"; 21385} 21386return {}; 21387} 21388}; 21389 21390template<> 21391struct statement_serializer<trigger_type, void> { 21392using statement_type = trigger_type; 21393 21394template<class Ctx> 21395serialize_result_type operator()(const statement_type& statement, const Ctx&) const { 21396switch (statement) { 21397case trigger_type::trigger_delete: 21398return "DELETE"; 21399case trigger_type::trigger_insert: 21400return "INSERT"; 21401case trigger_type::trigger_update: 21402return "UPDATE"; 21403} 21404return {}; 21405} 21406}; 21407 21408template<> 21409struct statement_serializer<trigger_type_base_t, void> { 21410using statement_type = trigger_type_base_t; 21411 21412template<class Ctx> 21413std::string operator()(const statement_type& statement, const Ctx& context) const { 21414std::stringstream ss; 21415 21416ss << serialize(statement.timing, context) << " " << serialize(statement.type, context); 21417return ss.str(); 21418} 21419}; 21420 21421template<class... Cs> 21422struct statement_serializer<trigger_update_type_t<Cs...>, void> { 21423using statement_type = trigger_update_type_t<Cs...>; 21424 21425template<class Ctx> 21426std::string operator()(const statement_type& statement, const Ctx& context) const { 21427std::stringstream ss; 21428 21429ss << serialize(statement.timing, context) << " UPDATE OF " 21430<< streaming_mapped_columns_expressions(statement.columns, context); 21431return ss.str(); 21432} 21433}; 21434 21435template<class T, class W, class Trigger> 21436struct statement_serializer<trigger_base_t<T, W, Trigger>, void> { 21437using statement_type = trigger_base_t<T, W, Trigger>; 21438 21439template<class Ctx> 21440std::string operator()(const statement_type& statement, const Ctx& context) const { 21441std::stringstream ss; 21442 21443ss << serialize(statement.type_base, context); 21444ss << " ON " << streaming_identifier(lookup_table_name<T>(context.db_objects)); 21445if (statement.do_for_each_row) { 21446ss << " FOR EACH ROW"; 21447} 21448statement.container_when.apply([&ss, &context](auto& value) { 21449ss << " WHEN " << serialize(value, context); 21450}); 21451return ss.str(); 21452} 21453}; 21454 21455template<class... S> 21456struct statement_serializer<trigger_t<S...>, void> { 21457using statement_type = trigger_t<S...>; 21458 21459template<class Ctx> 21460std::string operator()(const statement_type& statement, const Ctx& context) const { 21461std::stringstream ss; 21462ss << "CREATE "; 21463 21464ss << "TRIGGER IF NOT EXISTS " << streaming_identifier(statement.name) << " " 21465<< serialize(statement.base, context); 21466ss << " BEGIN "; 21467iterate_tuple(statement.elements, [&ss, &context](auto& element) { 21468using element_type = polyfill::remove_cvref_t<decltype(element)>; 21469if (is_select<element_type>::value) { 21470auto newContext = context; 21471newContext.use_parentheses = false; 21472ss << serialize(element, newContext); 21473} else { 21474ss << serialize(element, context); 21475} 21476ss << ";"; 21477}); 21478ss << " END"; 21479 21480return ss.str(); 21481} 21482}; 21483 21484template<class T> 21485struct statement_serializer<where_t<T>, void> { 21486using statement_type = where_t<T>; 21487 21488template<class Ctx> 21489std::string operator()(const statement_type& statement, const Ctx& context) const { 21490std::stringstream ss; 21491ss << statement.serialize() << " "; 21492auto whereString = serialize(statement.expression, context); 21493ss << '(' << whereString << ')'; 21494return ss.str(); 21495} 21496}; 21497 21498template<class O> 21499struct statement_serializer<order_by_t<O>, void> { 21500using statement_type = order_by_t<O>; 21501 21502template<class Ctx> 21503std::string operator()(const statement_type& orderBy, const Ctx& context) const { 21504std::stringstream ss; 21505ss << static_cast<std::string>(orderBy) << " "; 21506ss << serialize_order_by(orderBy, context); 21507return ss.str(); 21508} 21509}; 21510 21511template<class C> 21512struct statement_serializer<dynamic_order_by_t<C>, void> { 21513using statement_type = dynamic_order_by_t<C>; 21514 21515template<class Ctx> 21516std::string operator()(const statement_type& orderBy, const Ctx& context) const { 21517return serialize_order_by(orderBy, context); 21518} 21519}; 21520 21521template<class... Args> 21522struct statement_serializer<multi_order_by_t<Args...>, void> { 21523using statement_type = multi_order_by_t<Args...>; 21524 21525template<class Ctx> 21526std::string operator()(const statement_type& orderBy, const Ctx& context) const { 21527std::stringstream ss; 21528ss << static_cast<std::string>(orderBy) << " " << streaming_expressions_tuple(orderBy.args, context); 21529return ss.str(); 21530} 21531}; 21532 21533template<class Join> 21534struct statement_serializer< 21535Join, 21536std::enable_if_t<polyfill::disjunction<polyfill::is_specialization_of<Join, cross_join_t>, 21537polyfill::is_specialization_of<Join, natural_join_t>>::value>> { 21538using statement_type = Join; 21539 21540template<class Ctx> 21541std::string operator()(const statement_type& join, const Ctx& context) const { 21542std::stringstream ss; 21543ss << static_cast<std::string>(join) << " " 21544<< streaming_identifier(lookup_table_name<type_t<Join>>(context.db_objects)); 21545return ss.str(); 21546} 21547}; 21548 21549template<class Join> 21550struct statement_serializer<Join, match_if<is_constrained_join, Join>> { 21551using statement_type = Join; 21552 21553template<class Ctx> 21554std::string operator()(const statement_type& join, const Ctx& context) const { 21555std::stringstream ss; 21556ss << static_cast<std::string>(join) << " " 21557<< streaming_identifier(lookup_table_name<mapped_type_proxy_t<type_t<Join>>>(context.db_objects), 21558alias_extractor<type_t<Join>>::as_alias()) 21559<< " " << serialize(join.constraint, context); 21560return ss.str(); 21561} 21562}; 21563 21564template<class T> 21565struct statement_serializer<on_t<T>, void> { 21566using statement_type = on_t<T>; 21567 21568template<class Ctx> 21569std::string operator()(const statement_type& on, const Ctx& context) const { 21570std::stringstream ss; 21571auto newContext = context; 21572newContext.skip_table_name = false; 21573ss << static_cast<std::string>(on) << " " << serialize(on.arg, newContext) << " "; 21574return ss.str(); 21575} 21576}; 21577 21578template<class T, class... Args> 21579struct statement_serializer<group_by_with_having<T, Args...>, void> { 21580using statement_type = group_by_with_having<T, Args...>; 21581 21582template<class Ctx> 21583std::string operator()(const statement_type& statement, const Ctx& context) const { 21584std::stringstream ss; 21585auto newContext = context; 21586newContext.skip_table_name = false; 21587ss << "GROUP BY " << streaming_expressions_tuple(statement.args, newContext) << " HAVING " 21588<< serialize(statement.expression, context); 21589return ss.str(); 21590} 21591}; 21592 21593template<class... Args> 21594struct statement_serializer<group_by_t<Args...>, void> { 21595using statement_type = group_by_t<Args...>; 21596 21597template<class Ctx> 21598std::string operator()(const statement_type& statement, const Ctx& context) const { 21599std::stringstream ss; 21600auto newContext = context; 21601newContext.skip_table_name = false; 21602ss << "GROUP BY " << streaming_expressions_tuple(statement.args, newContext); 21603return ss.str(); 21604} 21605}; 21606 21607/** 21608* HO - has offset 21609* OI - offset is implicit 21610*/ 21611template<class T, bool HO, bool OI, class O> 21612struct statement_serializer<limit_t<T, HO, OI, O>, void> { 21613using statement_type = limit_t<T, HO, OI, O>; 21614 21615template<class Ctx> 21616std::string operator()(const statement_type& limt, const Ctx& context) const { 21617auto newContext = context; 21618newContext.skip_table_name = false; 21619std::stringstream ss; 21620ss << static_cast<std::string>(limt) << " "; 21621if (HO) { 21622if (OI) { 21623limt.off.apply([&newContext, &ss](auto& value) { 21624ss << serialize(value, newContext); 21625}); 21626ss << ", "; 21627ss << serialize(limt.lim, newContext); 21628} else { 21629ss << serialize(limt.lim, newContext) << " OFFSET "; 21630limt.off.apply([&newContext, &ss](auto& value) { 21631ss << serialize(value, newContext); 21632}); 21633} 21634} else { 21635ss << serialize(limt.lim, newContext); 21636} 21637return ss.str(); 21638} 21639}; 21640 21641template<> 21642struct statement_serializer<default_values_t, void> { 21643using statement_type = default_values_t; 21644 21645template<class Ctx> 21646serialize_result_type operator()(const statement_type&, const Ctx&) const { 21647return "DEFAULT VALUES"; 21648} 21649}; 21650 21651template<class T, class M> 21652struct statement_serializer<using_t<T, M>, void> { 21653using statement_type = using_t<T, M>; 21654 21655template<class Ctx> 21656std::string operator()(const statement_type& statement, const Ctx& context) const { 21657auto newContext = context; 21658newContext.skip_table_name = true; 21659return static_cast<std::string>(statement) + " (" + serialize(statement.column, newContext) + ")"; 21660} 21661}; 21662 21663template<class... Args> 21664struct statement_serializer<std::tuple<Args...>, void> { 21665using statement_type = std::tuple<Args...>; 21666 21667template<class Ctx> 21668std::string operator()(const statement_type& statement, const Ctx& context) const { 21669std::stringstream ss; 21670if (context.use_parentheses) { 21671ss << '('; 21672} 21673ss << streaming_expressions_tuple(statement, context); 21674if (context.use_parentheses) { 21675ss << ')'; 21676} 21677return ss.str(); 21678} 21679}; 21680 21681template<class... Args> 21682struct statement_serializer<values_t<Args...>, void> { 21683using statement_type = values_t<Args...>; 21684 21685template<class Ctx> 21686std::string operator()(const statement_type& statement, const Ctx& context) const { 21687std::stringstream ss; 21688if (context.use_parentheses) { 21689ss << '('; 21690} 21691ss << "VALUES "; 21692{ 21693Ctx tupleContext = context; 21694tupleContext.use_parentheses = true; 21695ss << streaming_expressions_tuple(statement.tuple, tupleContext); 21696} 21697if (context.use_parentheses) { 21698ss << ')'; 21699} 21700return ss.str(); 21701} 21702}; 21703 21704template<class T> 21705struct statement_serializer<dynamic_values_t<T>, void> { 21706using statement_type = dynamic_values_t<T>; 21707 21708template<class Ctx> 21709std::string operator()(const statement_type& statement, const Ctx& context) const { 21710std::stringstream ss; 21711if (context.use_parentheses) { 21712ss << '('; 21713} 21714ss << "VALUES " << streaming_dynamic_expressions(statement.vector, context); 21715if (context.use_parentheses) { 21716ss << ')'; 21717} 21718return 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 21781namespace sqlite_orm { 21782 21783namespace internal { 21784 21785template<class DBOs, class E, class SFINAE = void> 21786struct column_expression_type; 21787 21788/** 21789* Obains the expressions that form the columns of a subselect statement. 21790*/ 21791template<class DBOs, class E> 21792using column_expression_of_t = typename column_expression_type<DBOs, E>::type; 21793 21794/** 21795* Identity. 21796*/ 21797template<class DBOs, class E, class SFINAE> 21798struct column_expression_type { 21799using type = E; 21800}; 21801 21802/** 21803* Resolve column alias. 21804* as_t<Alias, E> -> as_t<Alias, ColExpr> 21805*/ 21806template<class DBOs, class As> 21807struct column_expression_type<DBOs, As, match_specialization_of<As, as_t>> { 21808using 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*/ 21815template<class DBOs, class E> 21816struct 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. 21820template<class DBOs, class E> 21821struct column_expression_type<DBOs, object_t<E>, void> { 21822static_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*/ 21829template<class DBOs, class E> 21830struct column_expression_type<DBOs, 21831asterisk_t<E>, 21832std::enable_if_t<polyfill::disjunction<polyfill::negation<is_recordset_alias<E>>, 21833is_cte_moniker<E>>::value>> 21834: storage_traits::storage_mapped_column_expressions<DBOs, E> {}; 21835 21836template<class A> 21837struct add_column_alias { 21838template<typename ColExpr> 21839using 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*/ 21845template<class DBOs, class A> 21846struct 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, 21848add_column_alias<A>::template apply_t> {}; 21849 21850/** 21851* Resolve multiple columns. 21852* columns_t<C...> -> tuple<ColExpr...> 21853*/ 21854template<class DBOs, class... Args> 21855struct column_expression_type<DBOs, columns_t<Args...>, void> { 21856using 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*/ 21863template<class DBOs, class T, class... Args> 21864struct column_expression_type<DBOs, struct_t<T, Args...>, void> { 21865using 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*/ 21872template<class DBOs, class E, class... Args> 21873struct column_expression_type<DBOs, select_t<E, Args...>> : column_expression_type<DBOs, E> {}; 21874} 21875} 21876 21877// #include "storage_lookup.h" 21878 21879namespace sqlite_orm { 21880namespace internal { 21881 21882#if (SQLITE_VERSION_NUMBER >= 3008003) && defined(SQLITE_ORM_WITH_CTE) 21883// F = field_type 21884template<typename Moniker, 21885typename ExplicitColRefs, 21886typename Expression, 21887typename SubselectColRefs, 21888typename FinalColRefs, 21889typename F> 21890struct create_cte_mapper { 21891using type = subselect_mapper<Moniker, ExplicitColRefs, Expression, SubselectColRefs, FinalColRefs, F>; 21892}; 21893 21894// std::tuple<Fs...> 21895template<typename Moniker, 21896typename ExplicitColRefs, 21897typename Expression, 21898typename SubselectColRefs, 21899typename FinalColRefs, 21900typename... Fs> 21901struct create_cte_mapper<Moniker, 21902ExplicitColRefs, 21903Expression, 21904SubselectColRefs, 21905FinalColRefs, 21906std::tuple<Fs...>> { 21907using type = subselect_mapper<Moniker, ExplicitColRefs, Expression, SubselectColRefs, FinalColRefs, Fs...>; 21908}; 21909 21910template<typename Moniker, 21911typename ExplicitColRefs, 21912typename Expression, 21913typename SubselectColRefs, 21914typename FinalColRefs, 21915typename Result> 21916using create_cte_mapper_t = 21917typename create_cte_mapper<Moniker, ExplicitColRefs, Expression, SubselectColRefs, FinalColRefs, Result>:: 21918type; 21919 21920// aliased column expressions, explicit or implicitly numbered 21921template<typename F, typename ColRef, satisfies_is_specialization_of<ColRef, alias_holder> = true> 21922static auto make_cte_column(std::string name, const ColRef& /*finalColRef*/) { 21923using object_type = aliased_field<type_t<ColRef>, F>; 21924 21925return sqlite_orm::make_column<>(std::move(name), &object_type::field); 21926} 21927 21928// F O::* 21929template<typename F, typename ColRef, satisfies<std::is_member_pointer, ColRef> = true> 21930static auto make_cte_column(std::string name, const ColRef& finalColRef) { 21931using object_type = table_type_of_t<ColRef>; 21932using column_type = column_t<ColRef, empty_setter>; 21933 21934return 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*/ 21940template<typename DBOs, size_t... Idx, typename... CTETables> 21941auto db_objects_cat(const DBOs& dbObjects, std::index_sequence<Idx...>, CTETables&&... cteTables) { 21942return 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*/ 21948template<typename DBOs, typename... CTETables> 21949auto db_objects_cat(const DBOs& dbObjects, CTETables&&... cteTables) { 21950return db_objects_cat(dbObjects, 21951std::make_index_sequence<std::tuple_size_v<DBOs>>{}, 21952std::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*/ 21963template<class Select> 21964decltype(auto) get_cte_driving_subselect(const Select& subSelect); 21965 21966/** 21967* Return given select expression. 21968*/ 21969template<class Select> 21970decltype(auto) get_cte_driving_subselect(const Select& subSelect) { 21971return subSelect; 21972} 21973 21974/** 21975* Return left-most select expression of compound statement. 21976*/ 21977template<class Compound, class... Args, std::enable_if_t<is_compound_operator_v<Compound>, bool> = true> 21978decltype(auto) get_cte_driving_subselect(const select_t<Compound, Args...>& subSelect) { 21979return std::get<0>(subSelect.col.compound); 21980} 21981 21982/** 21983* Return a tuple of member pointers of all columns 21984*/ 21985template<class C, size_t... Idx> 21986auto get_table_columns_fields(const C& coldef, std::index_sequence<Idx...>) { 21987return std::make_tuple(get<Idx>(coldef).member_pointer...); 21988} 21989 21990// any expression -> numeric column alias 21991template<class DBOs, 21992class E, 21993size_t Idx = 0, 21994std::enable_if_t<polyfill::negation_v<polyfill::is_specialization_of<E, std::tuple>>, bool> = true> 21995auto extract_colref_expressions(const DBOs& /*dbObjects*/, const E& /*col*/, std::index_sequence<Idx> = {}) 21996-> std::tuple<alias_holder<decltype(n_to_colalias<Idx>())>> { 21997return {}; 21998} 21999 22000// expression_t<> 22001template<class DBOs, class E, size_t Idx = 0> 22002auto 22003extract_colref_expressions(const DBOs& dbObjects, const expression_t<E>& col, std::index_sequence<Idx> s = {}) { 22004return extract_colref_expressions(dbObjects, col.value, s); 22005} 22006 22007// F O::* (field/getter) -> field/getter 22008template<class DBOs, class F, class O, size_t Idx = 0> 22009auto extract_colref_expressions(const DBOs& /*dbObjects*/, F O::* col, std::index_sequence<Idx> = {}) { 22010return std::make_tuple(col); 22011} 22012 22013// as_t<> (aliased expression) -> alias_holder 22014template<class DBOs, class A, class E, size_t Idx = 0> 22015std::tuple<alias_holder<A>> extract_colref_expressions(const DBOs& /*dbObjects*/, 22016const as_t<A, E>& /*col*/, 22017std::index_sequence<Idx> = {}) { 22018return {}; 22019} 22020 22021// alias_holder<> (colref) -> alias_holder 22022template<class DBOs, class A, size_t Idx = 0> 22023std::tuple<alias_holder<A>> extract_colref_expressions(const DBOs& /*dbObjects*/, 22024const alias_holder<A>& /*col*/, 22025std::index_sequence<Idx> = {}) { 22026return {}; 22027} 22028 22029// column_pointer<> 22030template<class DBOs, class Moniker, class F, size_t Idx = 0> 22031auto extract_colref_expressions(const DBOs& dbObjects, 22032const column_pointer<Moniker, F>& col, 22033std::index_sequence<Idx> s = {}) { 22034return extract_colref_expressions(dbObjects, col.field, s); 22035} 22036 22037// column expression tuple 22038template<class DBOs, class... Args, size_t... Idx> 22039auto extract_colref_expressions(const DBOs& dbObjects, 22040const std::tuple<Args...>& cols, 22041std::index_sequence<Idx...>) { 22042return std::tuple_cat(extract_colref_expressions(dbObjects, get<Idx>(cols), std::index_sequence<Idx>{})...); 22043} 22044 22045// columns_t<> 22046template<class DBOs, class... Args> 22047auto extract_colref_expressions(const DBOs& dbObjects, const columns_t<Args...>& cols) { 22048return extract_colref_expressions(dbObjects, cols.columns, std::index_sequence_for<Args...>{}); 22049} 22050 22051// asterisk_t<> -> fields 22052template<class DBOs, class O> 22053auto extract_colref_expressions(const DBOs& dbObjects, const asterisk_t<O>& /*col*/) { 22054using table_type = storage_pick_table_t<O, DBOs>; 22055using elements_t = typename table_type::elements_type; 22056using column_idxs = filter_tuple_sequence_t<elements_t, is_column>; 22057 22058auto& table = pick_table<O>(dbObjects); 22059return get_table_columns_fields(table.elements, column_idxs{}); 22060} 22061 22062template<class DBOs, class E, class... Args> 22063void extract_colref_expressions(const DBOs& /*dbObjects*/, const select_t<E, Args...>& /*subSelect*/) = delete; 22064 22065template<class DBOs, class Compound, std::enable_if_t<is_compound_operator_v<Compound>, bool> = true> 22066void 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*/ 22072template<typename DBOs, typename SubselectColRef, typename ExplicitColRef> 22073auto determine_cte_colref(const DBOs& /*dbObjects*/, 22074const SubselectColRef& subselectColRef, 22075const ExplicitColRef& explicitColRef) { 22076if constexpr (polyfill::is_specialization_of_v<ExplicitColRef, alias_holder>) { 22077return explicitColRef; 22078} else if constexpr (std::is_member_pointer<ExplicitColRef>::value) { 22079return explicitColRef; 22080} else if constexpr (std::is_base_of_v<column_identifier, ExplicitColRef>) { 22081return explicitColRef.member_pointer; 22082} else if constexpr (std::is_same_v<ExplicitColRef, std::string>) { 22083return subselectColRef; 22084} else if constexpr (std::is_same_v<ExplicitColRef, polyfill::remove_cvref_t<decltype(std::ignore)>>) { 22085return subselectColRef; 22086} else { 22087static_assert(polyfill::always_false_v<ExplicitColRef>, "Invalid explicit column reference specified"); 22088} 22089} 22090 22091template<typename DBOs, typename SubselectColRefs, typename ExplicitColRefs, size_t... Idx> 22092auto determine_cte_colrefs([[maybe_unused]] const DBOs& dbObjects, 22093const SubselectColRefs& subselectColRefs, 22094[[maybe_unused]] const ExplicitColRefs& explicitColRefs, 22095std::index_sequence<Idx...>) { 22096if constexpr (std::tuple_size_v<ExplicitColRefs> != 0) { 22097static_assert( 22098(!is_builtin_numeric_column_alias_v< 22099alias_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 22103return std::tuple{ 22104determine_cte_colref(dbObjects, get<Idx>(subselectColRefs), get<Idx>(explicitColRefs))...}; 22105} else { 22106return subselectColRefs; 22107} 22108} 22109 22110template<typename Mapper, typename DBOs, typename ColRefs, size_t... CIs> 22111auto make_cte_table_using_column_indices(const DBOs& /*dbObjects*/, 22112std::string tableName, 22113std::vector<std::string> columnNames, 22114const ColRefs& finalColRefs, 22115std::index_sequence<CIs...>) { 22116return make_table<Mapper>( 22117std::move(tableName), 22118make_cte_column<std::tuple_element_t<CIs, typename Mapper::fields_type>>(std::move(columnNames.at(CIs)), 22119get<CIs>(finalColRefs))...); 22120} 22121 22122template<typename DBOs, typename CTE> 22123auto make_cte_table(const DBOs& dbObjects, const CTE& cte) { 22124using cte_type = CTE; 22125 22126auto subSelect = get_cte_driving_subselect(cte.subselect); 22127 22128using subselect_type = decltype(subSelect); 22129using column_results = column_result_of_t<DBOs, subselect_type>; 22130using index_sequence = std::make_index_sequence<std::tuple_size_v<tuplify_t<column_results>>>; 22131static_assert(cte_type::explicit_colref_count == 0 || 22132cte_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 22136std::string tableName = alias_extractor<cte_moniker_type_t<cte_type>>::extract(); 22137auto subselectColRefs = extract_colref_expressions(dbObjects, subSelect.col); 22138const auto& finalColRefs = 22139determine_cte_colrefs(dbObjects, subselectColRefs, cte.explicitColumns, index_sequence{}); 22140 22141serializer_context context{dbObjects}; 22142std::vector<std::string> columnNames = collect_cte_column_names(subSelect, cte.explicitColumns, context); 22143 22144using mapper_type = create_cte_mapper_t<cte_moniker_type_t<cte_type>, 22145typename cte_type::explicit_colrefs_tuple, 22146column_expression_of_t<DBOs, subselect_type>, 22147decltype(subselectColRefs), 22148polyfill::remove_cvref_t<decltype(finalColRefs)>, 22149column_results>; 22150return make_cte_table_using_column_indices<mapper_type>(dbObjects, 22151std::move(tableName), 22152std::move(columnNames), 22153finalColRefs, 22154index_sequence{}); 22155} 22156 22157template<typename DBOs, typename... CTEs, size_t Ii, size_t... In> 22158decltype(auto) make_recursive_cte_db_objects(const DBOs& dbObjects, 22159const common_table_expressions<CTEs...>& cte, 22160std::index_sequence<Ii, In...>) { 22161auto tbl = make_cte_table(dbObjects, get<Ii>(cte)); 22162 22163if constexpr (sizeof...(In) > 0) { 22164return make_recursive_cte_db_objects( 22165// Because CTEs can depend on their predecessor we recursively pass in a new set of DBOs 22166db_objects_cat(dbObjects, std::move(tbl)), 22167cte, 22168std::index_sequence<In...>{}); 22169} else { 22170return db_objects_cat(dbObjects, std::move(tbl)); 22171} 22172} 22173 22174/** 22175* Return new DBOs for CTE expressions. 22176*/ 22177template<class DBOs, class E, class... CTEs, satisfies<is_db_objects, DBOs> = true> 22178decltype(auto) db_objects_for_expression(DBOs& dbObjects, const with_t<E, CTEs...>& e) { 22179return 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 22189namespace sqlite_orm { 22190 22191namespace 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*/ 22197template<class Binder> 22198struct indirectly_test_preparable; 22199 22200template<class S, class E, class SFINAE = void> 22201SQLITE_ORM_INLINE_VAR constexpr bool is_preparable_v = false; 22202template<class S, class E> 22203SQLITE_ORM_INLINE_VAR constexpr bool is_preparable_v< 22204S, 22205E, 22206polyfill::void_t<indirectly_test_preparable<decltype(std::declval<S>().prepare(std::declval<E>()))>>> = 22207true; 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*/ 22213template<class... DBO> 22214struct storage_t : storage_base { 22215using self = storage_t<DBO...>; 22216using db_objects_type = db_objects_tuple<DBO...>; 22217 22218/** 22219* @param filename database filename. 22220* @param dbObjects db_objects_tuple 22221*/ 22222storage_t(std::string filename, db_objects_type dbObjects) : 22223storage_base{std::move(filename), foreign_keys_count(dbObjects)}, db_objects{std::move(dbObjects)} {} 22224 22225storage_t(const storage_t&) = default; 22226 22227private: 22228db_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*/ 22242friend const db_objects_type& obtain_db_objects(const self& storage) noexcept { 22243return storage.db_objects; 22244} 22245 22246template<class Table> 22247void create_table(sqlite3* db, const std::string& tableName, const Table& table) { 22248using context_t = serializer_context<db_objects_type>; 22249 22250context_t context{this->db_objects}; 22251statement_serializer<Table, void> serializer; 22252std::string sql = serializer.serialize(table, context, tableName); 22253perform_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*/ 22260template<class Table> 22261void copy_table(sqlite3* db, 22262const std::string& sourceTableName, 22263const std::string& destinationTableName, 22264const Table& table, 22265const std::vector<const table_xinfo*>& columnsToIgnore) const; 22266 22267#if SQLITE_VERSION_NUMBER >= 3035000 // DROP COLUMN feature exists (v3.35.0) 22268void drop_column(sqlite3* db, const std::string& tableName, const std::string& columnName) { 22269std::stringstream ss; 22270ss << "ALTER TABLE " << streaming_identifier(tableName) << " DROP COLUMN " 22271<< streaming_identifier(columnName) << std::flush; 22272perform_void_exec(db, ss.str()); 22273} 22274#endif 22275 22276template<class Table> 22277void drop_create_with_loss(sqlite3* db, const Table& table) { 22278// eliminated all transaction handling 22279this->drop_table_internal(db, table.name, false); 22280this->create_table(db, table.name, table); 22281} 22282 22283template<class Table> 22284void 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.. 22288auto backupTableName = table.name + "_backup"; 22289if (this->table_exists(db, backupTableName)) { 22290int suffix = 1; 22291do { 22292std::stringstream ss; 22293ss << suffix << std::flush; 22294auto anotherBackupTableName = backupTableName + ss.str(); 22295if (!this->table_exists(db, anotherBackupTableName)) { 22296backupTableName = std::move(anotherBackupTableName); 22297break; 22298} 22299++suffix; 22300} while (true); 22301} 22302this->create_table(db, backupTableName, table); 22303 22304this->copy_table(db, table.name, backupTableName, table, columnsToIgnore); 22305 22306this->drop_table_internal(db, table.name, false); 22307 22308this->rename_table(db, backupTableName, table.name); 22309} 22310 22311template<class O> 22312void assert_mapped_type() const { 22313static_assert(tuple_has_type<db_objects_type, O, object_type_t>::value, 22314"type is not mapped to storage"); 22315} 22316 22317template<class O> 22318void assert_updatable_type() const { 22319#if defined(SQLITE_ORM_FOLD_EXPRESSIONS_SUPPORTED) 22320using Table = storage_pick_table_t<O, db_objects_type>; 22321using elements_type = elements_type_t<Table>; 22322using col_index_sequence = filter_tuple_sequence_t<elements_type, is_column>; 22323using pk_index_sequence = filter_tuple_sequence_t<elements_type, is_primary_key>; 22324using pkcol_index_sequence = col_index_sequence_with<elements_type, is_primary_key>; 22325constexpr size_t dedicatedPrimaryKeyColumnsCount = 22326nested_tuple_size_for_t<columns_tuple_t, elements_type, pk_index_sequence>::value; 22327 22328constexpr size_t primaryKeyColumnsCount = 22329dedicatedPrimaryKeyColumnsCount + pkcol_index_sequence::size(); 22330constexpr ptrdiff_t nonPrimaryKeysColumnsCount = col_index_sequence::size() - primaryKeyColumnsCount; 22331static_assert(primaryKeyColumnsCount > 0, "A table without primary keys cannot be updated"); 22332static_assert( 22333nonPrimaryKeysColumnsCount > 0, 22334"A table with only primary keys cannot be updated. You need at least 1 non-primary key column"); 22335#endif 22336} 22337 22338template<class O, 22339class Table = storage_pick_table_t<O, db_objects_type>, 22340std::enable_if_t<Table::is_without_rowid::value, bool> = true> 22341void assert_insertable_type() const {} 22342 22343template<class O, 22344class Table = storage_pick_table_t<O, db_objects_type>, 22345std::enable_if_t<!Table::is_without_rowid::value, bool> = true> 22346void assert_insertable_type() const { 22347using elements_type = elements_type_t<Table>; 22348using pkcol_index_sequence = col_index_sequence_with<elements_type, is_primary_key>; 22349static_assert( 22350count_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."); 22354static_assert(count_filtered_tuple<elements_type, 22355check_if_not<is_primary_key_insertable>::template fn, 22356pkcol_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 22362template<class O> 22363auto& get_table() const { 22364return pick_table<O>(this->db_objects); 22365} 22366 22367template<class O> 22368auto& get_table() { 22369return pick_table<O>(this->db_objects); 22370} 22371 22372public: 22373template<class T, class O = mapped_type_proxy_t<T>, class... Args> 22374mapped_view<O, self, Args...> iterate(Args&&... args) { 22375this->assert_mapped_type<O>(); 22376 22377auto con = this->get_connection(); 22378return {*this, std::move(con), std::forward<Args>(args)...}; 22379} 22380 22381#ifdef SQLITE_ORM_WITH_CPP20_ALIASES 22382template<orm_refers_to_table auto mapped, class... Args> 22383auto iterate(Args&&... args) { 22384return 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) 22389template<class Select> 22390#ifdef SQLITE_ORM_CONCEPTS_SUPPORTED 22391requires (is_select_v<Select>) 22392#endif 22393result_set_view<Select, db_objects_type> iterate(Select expression) { 22394expression.highest_level = true; 22395auto con = this->get_connection(); 22396return {this->db_objects, std::move(con), std::move(expression)}; 22397} 22398 22399#if (SQLITE_VERSION_NUMBER >= 3008003) && defined(SQLITE_ORM_WITH_CTE) 22400template<class... CTEs, class E> 22401#ifdef SQLITE_ORM_CONCEPTS_SUPPORTED 22402requires (is_select_v<E>) 22403#endif 22404result_set_view<with_t<E, CTEs...>, db_objects_type> iterate(with_t<E, CTEs...> expression) { 22405auto con = this->get_connection(); 22406return {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*/ 22418template<class O, class... Args> 22419void remove_all(Args&&... args) { 22420this->assert_mapped_type<O>(); 22421auto statement = this->prepare(sqlite_orm::remove_all<O>(std::forward<Args>(args)...)); 22422this->execute(statement); 22423} 22424 22425#ifdef SQLITE_ORM_WITH_CPP20_ALIASES 22426template<orm_table_reference auto table, class... Args> 22427void remove_all(Args&&... args) { 22428return 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*/ 22437template<class O, class... Ids> 22438void remove(Ids... ids) { 22439this->assert_mapped_type<O>(); 22440auto statement = this->prepare(sqlite_orm::remove<O>(std::forward<Ids>(ids)...)); 22441this->execute(statement); 22442} 22443 22444#ifdef SQLITE_ORM_WITH_CPP20_ALIASES 22445template<orm_table_reference auto table, class... Ids> 22446void remove(Ids... ids) { 22447return 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*/ 22457template<class O> 22458void update(const O& o) { 22459this->assert_mapped_type<O>(); 22460auto statement = this->prepare(sqlite_orm::update(std::ref(o))); 22461this->execute(statement); 22462} 22463 22464template<class S, class... Wargs> 22465void update_all(S set, Wargs... wh) { 22466static_assert(internal::is_set<S>::value, 22467"first argument in update_all can be either set or dynamic_set"); 22468auto statement = this->prepare(sqlite_orm::update_all(std::move(set), std::forward<Wargs>(wh)...)); 22469this->execute(statement); 22470} 22471 22472protected: 22473template<class F, class O, class... Args> 22474std::string group_concat_internal(F O::* m, std::unique_ptr<std::string> y, Args&&... args) { 22475this->assert_mapped_type<O>(); 22476std::vector<std::string> rows; 22477if (y) { 22478rows = this->select(sqlite_orm::group_concat(m, std::move(*y)), std::forward<Args>(args)...); 22479} else { 22480rows = this->select(sqlite_orm::group_concat(m), std::forward<Args>(args)...); 22481} 22482if (!rows.empty()) { 22483return std::move(rows.front()); 22484} else { 22485return {}; 22486} 22487} 22488 22489public: 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*/ 22498template<class T, class R = std::vector<mapped_type_proxy_t<T>>, class... Args> 22499R get_all(Args&&... args) { 22500this->assert_mapped_type<mapped_type_proxy_t<T>>(); 22501auto statement = this->prepare(sqlite_orm::get_all<T, R>(std::forward<Args>(args)...)); 22502return 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*/ 22513template<orm_refers_to_table auto mapped, 22514class R = std::vector<mapped_type_proxy_t<decltype(mapped)>>, 22515class... Args> 22516R get_all(Args&&... args) { 22517this->assert_mapped_type<mapped_type_proxy_t<decltype(mapped)>>(); 22518auto statement = this->prepare(sqlite_orm::get_all<mapped, R>(std::forward<Args>(args)...)); 22519return 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*/ 22531template<class O, class R = std::vector<std::unique_ptr<O>>, class... Args> 22532auto get_all_pointer(Args&&... args) { 22533this->assert_mapped_type<O>(); 22534auto statement = this->prepare(sqlite_orm::get_all_pointer<O, R>(std::forward<Args>(args)...)); 22535return this->execute(statement); 22536} 22537 22538#ifdef SQLITE_ORM_WITH_CPP20_ALIASES 22539template<orm_table_reference auto table, 22540class R = std::vector<std::unique_ptr<auto_decay_table_ref_t<table>>>, 22541class... Args> 22542auto get_all_pointer(Args&&... args) { 22543return 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*/ 22556template<class O, class R = std::vector<std::optional<O>>, class... Args> 22557auto get_all_optional(Args&&... conditions) { 22558this->assert_mapped_type<O>(); 22559auto statement = this->prepare(sqlite_orm::get_all_optional<O, R>(std::forward<Args>(conditions)...)); 22560return this->execute(statement); 22561} 22562#endif 22563 22564#ifdef SQLITE_ORM_WITH_CPP20_ALIASES 22565template<orm_table_reference auto table, 22566class R = std::vector<std::optional<auto_decay_table_ref_t<table>>>, 22567class... Args> 22568auto get_all_optional(Args&&... conditions) { 22569return 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*/ 22581template<class O, class... Ids> 22582O get(Ids... ids) { 22583this->assert_mapped_type<O>(); 22584auto statement = this->prepare(sqlite_orm::get<O>(std::forward<Ids>(ids)...)); 22585return this->execute(statement); 22586} 22587 22588#ifdef SQLITE_ORM_WITH_CPP20_ALIASES 22589template<orm_table_reference auto table, class... Ids> 22590auto get(Ids... ids) { 22591return 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*/ 22599template<class O, class... Ids> 22600std::unique_ptr<O> get_pointer(Ids... ids) { 22601this->assert_mapped_type<O>(); 22602auto statement = this->prepare(sqlite_orm::get_pointer<O>(std::forward<Ids>(ids)...)); 22603return this->execute(statement); 22604} 22605 22606#ifdef SQLITE_ORM_WITH_CPP20_ALIASES 22607template<orm_table_reference auto table, class... Ids> 22608auto get_pointer(Ids... ids) { 22609return 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*/ 22626template<class O, class... Ids> 22627std::shared_ptr<O> get_no_throw(Ids... ids) { 22628return 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*/ 22636template<class O, class... Ids> 22637std::optional<O> get_optional(Ids... ids) { 22638this->assert_mapped_type<O>(); 22639auto statement = this->prepare(sqlite_orm::get_optional<O>(std::forward<Ids>(ids)...)); 22640return this->execute(statement); 22641} 22642#endif // SQLITE_ORM_OPTIONAL_SUPPORTED 22643 22644#ifdef SQLITE_ORM_WITH_CPP20_ALIASES 22645template<orm_table_reference auto table, class... Ids> 22646auto get_optional(Ids... ids) { 22647return 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*/ 22655template<class O, class... Args> 22656int count(Args&&... args) { 22657using R = mapped_type_proxy_t<O>; 22658this->assert_mapped_type<R>(); 22659auto rows = this->select(sqlite_orm::count<R>(), std::forward<Args>(args)...); 22660if (!rows.empty()) { 22661return rows.front(); 22662} else { 22663return 0; 22664} 22665} 22666 22667#ifdef SQLITE_ORM_WITH_CPP20_ALIASES 22668template<orm_refers_to_table auto mapped, class... Args> 22669int count(Args&&... args) { 22670return 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*/ 22679template<class F, 22680class... Args, 22681std::enable_if_t<polyfill::disjunction<std::is_member_pointer<F>, is_column_pointer<F>>::value, 22682bool> = true> 22683int count(F field, Args&&... args) { 22684this->assert_mapped_type<table_type_of_t<F>>(); 22685auto rows = this->select(sqlite_orm::count(std::move(field)), std::forward<Args>(args)...); 22686if (!rows.empty()) { 22687return rows.front(); 22688} else { 22689return 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*/ 22698template<class F, 22699class... Args, 22700std::enable_if_t<polyfill::disjunction<std::is_member_pointer<F>, is_column_pointer<F>>::value, 22701bool> = true> 22702double avg(F field, Args&&... args) { 22703this->assert_mapped_type<table_type_of_t<F>>(); 22704auto rows = this->select(sqlite_orm::avg(std::move(field)), std::forward<Args>(args)...); 22705if (!rows.empty()) { 22706return rows.front(); 22707} else { 22708return 0; 22709} 22710} 22711 22712template<class F, 22713std::enable_if_t<polyfill::disjunction<std::is_member_pointer<F>, is_column_pointer<F>>::value, 22714bool> = true> 22715std::string group_concat(F field) { 22716return 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*/ 22724template<class F, 22725class... Args, 22726class Tuple = std::tuple<Args...>, 22727std::enable_if_t<std::tuple_size<Tuple>::value >= 1, bool> = true, 22728std::enable_if_t<polyfill::disjunction<std::is_member_pointer<F>, is_column_pointer<F>>::value, 22729bool> = true> 22730std::string group_concat(F field, Args&&... args) { 22731return 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*/ 22739template<class F, 22740class... Args, 22741std::enable_if_t<polyfill::disjunction<std::is_member_pointer<F>, is_column_pointer<F>>::value, 22742bool> = true> 22743std::string group_concat(F field, std::string y, Args&&... args) { 22744return this->group_concat_internal(std::move(field), 22745std::make_unique<std::string>(std::move(y)), 22746std::forward<Args>(args)...); 22747} 22748 22749template<class F, 22750class... Args, 22751std::enable_if_t<polyfill::disjunction<std::is_member_pointer<F>, is_column_pointer<F>>::value, 22752bool> = true> 22753std::string group_concat(F field, const char* y, Args&&... args) { 22754std::unique_ptr<std::string> str; 22755if (y) { 22756str = std::make_unique<std::string>(y); 22757} else { 22758str = std::make_unique<std::string>(); 22759} 22760return 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*/ 22768template<class F, 22769class... Args, 22770class R = column_result_of_t<db_objects_type, F>, 22771std::enable_if_t<polyfill::disjunction<std::is_member_pointer<F>, is_column_pointer<F>>::value, 22772bool> = true> 22773std::unique_ptr<R> max(F field, Args&&... args) { 22774this->assert_mapped_type<table_type_of_t<F>>(); 22775auto rows = this->select(sqlite_orm::max(std::move(field)), std::forward<Args>(args)...); 22776if (!rows.empty()) { 22777return std::move(rows.front()); 22778} else { 22779return {}; 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*/ 22788template<class F, 22789class... Args, 22790class R = column_result_of_t<db_objects_type, F>, 22791std::enable_if_t<polyfill::disjunction<std::is_member_pointer<F>, is_column_pointer<F>>::value, 22792bool> = true> 22793std::unique_ptr<R> min(F field, Args&&... args) { 22794this->assert_mapped_type<table_type_of_t<F>>(); 22795auto rows = this->select(sqlite_orm::min(std::move(field)), std::forward<Args>(args)...); 22796if (!rows.empty()) { 22797return std::move(rows.front()); 22798} else { 22799return {}; 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*/ 22808template<class F, 22809class... Args, 22810class R = column_result_of_t<db_objects_type, F>, 22811std::enable_if_t<polyfill::disjunction<std::is_member_pointer<F>, is_column_pointer<F>>::value, 22812bool> = true> 22813std::unique_ptr<R> sum(F field, Args&&... args) { 22814this->assert_mapped_type<table_type_of_t<F>>(); 22815std::vector<std::unique_ptr<double>> rows = 22816this->select(sqlite_orm::sum(std::move(field)), std::forward<Args>(args)...); 22817if (!rows.empty()) { 22818if (rows.front()) { 22819return std::make_unique<R>(std::move(*rows.front())); 22820} else { 22821return {}; 22822} 22823} else { 22824return {}; 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*/ 22834template<class F, 22835class... Args, 22836std::enable_if_t<polyfill::disjunction<std::is_member_pointer<F>, is_column_pointer<F>>::value, 22837bool> = true> 22838double total(F field, Args&&... args) { 22839this->assert_mapped_type<table_type_of_t<F>>(); 22840auto rows = this->select(sqlite_orm::total(std::move(field)), std::forward<Args>(args)...); 22841if (!rows.empty()) { 22842return std::move(rows.front()); 22843} else { 22844return {}; 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*/ 22853template<class T, class... Args> 22854auto select(T m, Args... args) { 22855static_assert(!is_compound_operator_v<T> || sizeof...(Args) == 0, 22856"Cannot use args with a compound operator"); 22857auto statement = this->prepare(sqlite_orm::select(std::move(m), std::forward<Args>(args)...)); 22858return 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*/ 22865template<class CTE, class E> 22866auto with(CTE cte, E expression) { 22867auto statement = this->prepare(sqlite_orm::with(std::move(cte), std::move(expression))); 22868return 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*/ 22874template<class... CTEs, class E> 22875auto with(common_table_expressions<CTEs...> cte, E expression) { 22876auto statement = this->prepare(sqlite_orm::with(std::move(cte), std::move(expression))); 22877return 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*/ 22883template<class CTE, class E> 22884auto with_recursive(CTE cte, E expression) { 22885auto statement = this->prepare(sqlite_orm::with_recursive(std::move(cte), std::move(expression))); 22886return 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*/ 22892template<class... CTEs, class E> 22893auto with_recursive(common_table_expressions<CTEs...> cte, E expression) { 22894auto statement = this->prepare(sqlite_orm::with_recursive(std::move(cte), std::move(expression))); 22895return this->execute(statement); 22896} 22897#endif 22898 22899template<class T, satisfies<is_prepared_statement, T> = true> 22900std::string dump(const T& preparedStatement, bool parametrized = true) const { 22901return this->dump_highest_level(preparedStatement.expression, parametrized); 22902} 22903 22904template<class E, 22905class Ex = polyfill::remove_cvref_t<E>, 22906std::enable_if_t<!is_prepared_statement<Ex>::value && !is_mapped<db_objects_type, Ex>::value, 22907bool> = true> 22908std::string dump(E&& expression, bool parametrized = false) const { 22909static_assert(is_preparable_v<self, Ex>, "Expression must be a high-level statement"); 22910 22911decltype(auto) e2 = static_if<is_select<Ex>::value>( 22912[](auto expression) -> auto { 22913expression.highest_level = true; 22914return expression; 22915}, 22916[](const auto& expression) -> decltype(auto) { 22917return (expression); 22918})(std::forward<E>(expression)); 22919return 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*/ 22926template<class O, satisfies<is_mapped, db_objects_type, O> = true> 22927std::string dump(const O& object) const { 22928auto& table = this->get_table<O>(); 22929std::stringstream ss; 22930ss << "{ "; 22931table.for_each_column([&ss, &object, first = true](auto& column) mutable { 22932using field_type = field_type_t<std::remove_reference_t<decltype(column)>>; 22933static constexpr std::array<const char*, 2> sep = {", ", ""}; 22934 22935ss << sep[std::exchange(first, false)] << column.name << " : '" 22936<< field_printer<field_type>{}(polyfill::invoke(column.member_pointer, object)) << "'"; 22937}); 22938ss << " }"; 22939return 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*/ 22948template<class O> 22949void replace(const O& o) { 22950this->assert_mapped_type<O>(); 22951auto statement = this->prepare(sqlite_orm::replace(std::ref(o))); 22952this->execute(statement); 22953} 22954 22955template<class It, class Projection = polyfill::identity> 22956void replace_range(It from, It to, Projection project = {}) { 22957using O = std::decay_t<decltype(polyfill::invoke(project, *from))>; 22958this->assert_mapped_type<O>(); 22959if (from == to) { 22960return; 22961} 22962 22963auto statement = 22964this->prepare(sqlite_orm::replace_range(std::move(from), std::move(to), std::move(project))); 22965this->execute(statement); 22966} 22967 22968template<class O, class It, class Projection = polyfill::identity> 22969void replace_range(It from, It to, Projection project = {}) { 22970this->assert_mapped_type<O>(); 22971if (from == to) { 22972return; 22973} 22974 22975auto statement = 22976this->prepare(sqlite_orm::replace_range<O>(std::move(from), std::move(to), std::move(project))); 22977this->execute(statement); 22978} 22979 22980template<class O, class... Cols> 22981int insert(const O& o, columns_t<Cols...> cols) { 22982static_assert(cols.count > 0, "Use insert or replace with 1 argument instead"); 22983this->assert_mapped_type<O>(); 22984auto statement = this->prepare(sqlite_orm::insert(std::ref(o), std::move(cols))); 22985return 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*/ 22993template<class O> 22994int insert(const O& o) { 22995this->assert_mapped_type<O>(); 22996this->assert_insertable_type<O>(); 22997auto statement = this->prepare(sqlite_orm::insert(std::ref(o))); 22998return 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*/ 23035template<class... Args> 23036void insert(Args... args) { 23037auto statement = this->prepare(sqlite_orm::insert(std::forward<Args>(args)...)); 23038this->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*/ 23069template<class... Args> 23070void replace(Args... args) { 23071auto statement = this->prepare(sqlite_orm::replace(std::forward<Args>(args)...)); 23072this->execute(statement); 23073} 23074 23075template<class It, class Projection = polyfill::identity> 23076void insert_range(It from, It to, Projection project = {}) { 23077using O = std::decay_t<decltype(polyfill::invoke(std::declval<Projection>(), *std::declval<It>()))>; 23078this->assert_mapped_type<O>(); 23079this->assert_insertable_type<O>(); 23080if (from == to) { 23081return; 23082} 23083auto statement = 23084this->prepare(sqlite_orm::insert_range(std::move(from), std::move(to), std::move(project))); 23085this->execute(statement); 23086} 23087 23088template<class O, class It, class Projection = polyfill::identity> 23089void insert_range(It from, It to, Projection project = {}) { 23090this->assert_mapped_type<O>(); 23091this->assert_insertable_type<O>(); 23092if (from == to) { 23093return; 23094} 23095auto statement = 23096this->prepare(sqlite_orm::insert_range<O>(std::move(from), std::move(to), std::move(project))); 23097this->execute(statement); 23098} 23099 23100/** 23101* Change table name inside storage's schema info. This function does not 23102* affect database 23103*/ 23104template<class O> 23105void rename_table(std::string name) { 23106this->assert_mapped_type<O>(); 23107auto& table = this->get_table<O>(); 23108table.name = std::move(name); 23109} 23110 23111using 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*/ 23117template<class O> 23118const std::string& tablename() const { 23119this->assert_mapped_type<O>(); 23120auto& table = this->get_table<O>(); 23121return table.name; 23122} 23123 23124template<class F, class O> 23125[[deprecated("Use the more accurately named function `find_column_name()`")]] const std::string* 23126column_name(F O::* memberPointer) const { 23127return internal::find_column_name(this->db_objects, memberPointer); 23128} 23129 23130template<class F, class O> 23131const std::string* find_column_name(F O::* memberPointer) const { 23132return internal::find_column_name(this->db_objects, memberPointer); 23133} 23134 23135protected: 23136template<class M> 23137sync_schema_result schema_status(const virtual_table_t<M>&, sqlite3*, bool, bool*) { 23138return sync_schema_result::already_in_sync; 23139} 23140 23141template<class T, class... S> 23142sync_schema_result schema_status(const trigger_t<T, S...>&, sqlite3*, bool, bool*) { 23143return sync_schema_result::already_in_sync; 23144} 23145 23146template<class... Cols> 23147sync_schema_result schema_status(const index_t<Cols...>&, sqlite3*, bool, bool*) { 23148return sync_schema_result::already_in_sync; 23149} 23150 23151template<class T, bool WithoutRowId, class... Cs> 23152sync_schema_result schema_status(const table_t<T, WithoutRowId, Cs...>& table, 23153sqlite3* db, 23154bool preserve, 23155bool* attempt_to_preserve) { 23156if (attempt_to_preserve) { 23157*attempt_to_preserve = true; 23158} 23159 23160auto dbTableInfo = this->pragma.table_xinfo(table.name); 23161auto res = sync_schema_result::already_in_sync; 23162 23163// first let's see if table with such name exists.. 23164auto gottaCreateTable = !this->table_exists(db, table.name); 23165if (!gottaCreateTable) { 23166 23167// get table info provided in `make_table` call.. 23168auto storageTableInfo = table.get_table_info(); 23169 23170// this vector will contain pointers to columns that gotta be added.. 23171std::vector<const table_xinfo*> columnsToAdd; 23172 23173if (calculate_remove_add_columns(columnsToAdd, storageTableInfo, dbTableInfo)) { 23174gottaCreateTable = true; 23175} 23176 23177if (!gottaCreateTable) { // if all storage columns are equal to actual db columns but there are 23178// excess columns at the db.. 23179if (!dbTableInfo.empty()) { 23180// extra table columns than storage columns 23181if (!preserve) { 23182#if SQLITE_VERSION_NUMBER >= 3035000 // DROP COLUMN feature exists (v3.35.0) 23183res = sync_schema_result::old_columns_removed; 23184#else 23185gottaCreateTable = true; 23186#endif 23187} else { 23188res = sync_schema_result::old_columns_removed; 23189} 23190} 23191} 23192if (gottaCreateTable) { 23193res = sync_schema_result::dropped_and_recreated; 23194} else { 23195if (!columnsToAdd.empty()) { 23196// extra storage columns than table columns 23197for (const table_xinfo* colInfo: columnsToAdd) { 23198const basic_generated_always::storage_type* generatedStorageType = 23199table.find_column_generated_storage_type(colInfo->name); 23200if (generatedStorageType) { 23201if (*generatedStorageType == basic_generated_always::storage_type::stored) { 23202gottaCreateTable = true; 23203break; 23204} 23205// fallback cause VIRTUAL can be added 23206} else { 23207if (colInfo->notnull && colInfo->dflt_value.empty()) { 23208gottaCreateTable = true; 23209// no matter if preserve is true or false, there is no way to preserve data, so we wont try! 23210if (attempt_to_preserve) { 23211*attempt_to_preserve = false; 23212}; 23213break; 23214} 23215} 23216} 23217if (!gottaCreateTable) { 23218if (res == sync_schema_result::old_columns_removed) { 23219res = sync_schema_result::new_columns_added_and_old_columns_removed; 23220} else { 23221res = sync_schema_result::new_columns_added; 23222} 23223} else { 23224res = sync_schema_result::dropped_and_recreated; 23225} 23226} else { 23227if (res != sync_schema_result::old_columns_removed) { 23228res = sync_schema_result::already_in_sync; 23229} 23230} 23231} 23232} else { 23233res = sync_schema_result::new_table_created; 23234} 23235return res; 23236} 23237 23238template<class M> 23239sync_schema_result sync_table(const virtual_table_t<M>& virtualTable, sqlite3* db, bool) { 23240auto res = sync_schema_result::already_in_sync; 23241using context_t = serializer_context<db_objects_type>; 23242context_t context{this->db_objects}; 23243auto query = serialize(virtualTable, context); 23244perform_void_exec(db, query); 23245return res; 23246} 23247 23248template<class... Cols> 23249sync_schema_result sync_table(const index_t<Cols...>& index, sqlite3* db, bool) { 23250auto res = sync_schema_result::already_in_sync; 23251using context_t = serializer_context<db_objects_type>; 23252context_t context{this->db_objects}; 23253auto query = serialize(index, context); 23254perform_void_exec(db, query); 23255return res; 23256} 23257 23258template<class... Cols> 23259sync_schema_result sync_table(const trigger_t<Cols...>& trigger, sqlite3* db, bool) { 23260auto res = sync_schema_result::already_in_sync; // TODO Change accordingly 23261using context_t = serializer_context<db_objects_type>; 23262context_t context{this->db_objects}; 23263auto query = serialize(trigger, context); 23264perform_void_exec(db, query); 23265return res; 23266} 23267 23268template<class Table, satisfies<is_table, Table> = true> 23269sync_schema_result sync_table(const Table& table, sqlite3* db, bool preserve); 23270 23271template<class C> 23272void add_column(sqlite3* db, const std::string& tableName, const C& column) const { 23273using context_t = serializer_context<db_objects_type>; 23274 23275context_t context{this->db_objects}; 23276std::stringstream ss; 23277ss << "ALTER TABLE " << streaming_identifier(tableName) << " ADD COLUMN " << serialize(column, context) 23278<< std::flush; 23279perform_void_exec(db, ss.str()); 23280} 23281 23282template<class ColResult, class S> 23283auto execute_select(const S& statement) { 23284sqlite3_stmt* stmt = reset_stmt(statement.stmt); 23285 23286iterate_ast(statement.expression, conditional_binder{stmt}); 23287 23288using R = decltype(make_row_extractor<ColResult>(this->db_objects).extract(nullptr, 0)); 23289std::vector<R> res; 23290perform_steps( 23291stmt, 23292[rowExtractor = make_row_extractor<ColResult>(this->db_objects), &res](sqlite3_stmt* stmt) { 23293res.push_back(rowExtractor.extract(stmt, 0)); 23294}); 23295res.shrink_to_fit(); 23296return res; 23297} 23298 23299template<class E> 23300std::string dump_highest_level(E&& expression, bool parametrized) const { 23301const auto& exprDBOs = db_objects_for_expression(this->db_objects, expression); 23302using context_t = serializer_context<polyfill::remove_cvref_t<decltype(exprDBOs)>>; 23303context_t context{exprDBOs}; 23304context.replace_bindable_with_question = parametrized; 23305// just like prepare_impl() 23306context.skip_table_name = false; 23307return serialize(expression, context); 23308} 23309 23310template<typename S> 23311prepared_statement_t<S> prepare_impl(S statement) { 23312const auto& exprDBOs = db_objects_for_expression(this->db_objects, statement); 23313using context_t = serializer_context<polyfill::remove_cvref_t<decltype(exprDBOs)>>; 23314context_t context{exprDBOs}; 23315context.skip_table_name = false; 23316context.replace_bindable_with_question = true; 23317 23318auto con = this->get_connection(); 23319std::string sql = serialize(statement, context); 23320sqlite3_stmt* stmt = prepare_stmt(con.get(), std::move(sql)); 23321return prepared_statement_t<S>{std::forward<S>(statement), stmt, con}; 23322} 23323 23324public: 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*/ 23352std::map<std::string, sync_schema_result> sync_schema(bool preserve = false) { 23353auto con = this->get_connection(); 23354std::map<std::string, sync_schema_result> result; 23355iterate_tuple<true>(this->db_objects, [this, db = con.get(), preserve, &result](auto& schemaObject) { 23356sync_schema_result status = this->sync_table(schemaObject, db, preserve); 23357result.emplace(schemaObject.name, status); 23358}); 23359return 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*/ 23367std::map<std::string, sync_schema_result> sync_schema_simulate(bool preserve = false) { 23368auto con = this->get_connection(); 23369std::map<std::string, sync_schema_result> result; 23370iterate_tuple<true>(this->db_objects, [this, db = con.get(), preserve, &result](auto& schemaObject) { 23371sync_schema_result status = this->schema_status(schemaObject, db, preserve, nullptr); 23372result.emplace(schemaObject.name, status); 23373}); 23374return result; 23375} 23376 23377using 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) 23380template<class... CTEs, 23381class E, 23382std::enable_if_t<polyfill::disjunction_v<is_select<E>, 23383is_insert_raw<E>, 23384is_replace_raw<E>, 23385is_update_all<E>, 23386is_remove_all<E>>, 23387bool> = true> 23388prepared_statement_t<with_t<E, CTEs...>> prepare(with_t<E, CTEs...> sel) { 23389return this->prepare_impl<with_t<E, CTEs...>>(std::move(sel)); 23390} 23391#endif 23392 23393template<class T, class... Args> 23394prepared_statement_t<select_t<T, Args...>> prepare(select_t<T, Args...> statement) { 23395statement.highest_level = true; 23396return this->prepare_impl(std::move(statement)); 23397} 23398 23399template<class T, class... Args> 23400prepared_statement_t<get_all_t<T, Args...>> prepare(get_all_t<T, Args...> statement) { 23401return this->prepare_impl(std::move(statement)); 23402} 23403 23404template<class T, class... Args> 23405prepared_statement_t<get_all_pointer_t<T, Args...>> prepare(get_all_pointer_t<T, Args...> statement) { 23406return this->prepare_impl(std::move(statement)); 23407} 23408 23409template<class... Args> 23410prepared_statement_t<replace_raw_t<Args...>> prepare(replace_raw_t<Args...> statement) { 23411return this->prepare_impl(std::move(statement)); 23412} 23413 23414template<class... Args> 23415prepared_statement_t<insert_raw_t<Args...>> prepare(insert_raw_t<Args...> statement) { 23416return this->prepare_impl(std::move(statement)); 23417} 23418 23419#ifdef SQLITE_ORM_OPTIONAL_SUPPORTED 23420template<class T, class R, class... Args> 23421prepared_statement_t<get_all_optional_t<T, R, Args...>> 23422prepare(get_all_optional_t<T, R, Args...> statement) { 23423return this->prepare_impl(std::move(statement)); 23424} 23425#endif // SQLITE_ORM_OPTIONAL_SUPPORTED 23426 23427template<class S, class... Wargs> 23428prepared_statement_t<update_all_t<S, Wargs...>> prepare(update_all_t<S, Wargs...> statement) { 23429return this->prepare_impl(std::move(statement)); 23430} 23431 23432template<class T, class... Args> 23433prepared_statement_t<remove_all_t<T, Args...>> prepare(remove_all_t<T, Args...> statement) { 23434return this->prepare_impl(std::move(statement)); 23435} 23436 23437template<class T, class... Ids> 23438prepared_statement_t<get_t<T, Ids...>> prepare(get_t<T, Ids...> statement) { 23439return this->prepare_impl(std::move(statement)); 23440} 23441 23442template<class T, class... Ids> 23443prepared_statement_t<get_pointer_t<T, Ids...>> prepare(get_pointer_t<T, Ids...> statement) { 23444return this->prepare_impl(std::move(statement)); 23445} 23446 23447#ifdef SQLITE_ORM_OPTIONAL_SUPPORTED 23448template<class T, class... Ids> 23449prepared_statement_t<get_optional_t<T, Ids...>> prepare(get_optional_t<T, Ids...> statement) { 23450return this->prepare_impl(std::move(statement)); 23451} 23452#endif // SQLITE_ORM_OPTIONAL_SUPPORTED 23453 23454template<class T> 23455prepared_statement_t<update_t<T>> prepare(update_t<T> statement) { 23456using object_type = expression_object_type_t<decltype(statement)>; 23457this->assert_mapped_type<object_type>(); 23458this->assert_updatable_type<object_type>(); 23459return this->prepare_impl(std::move(statement)); 23460} 23461 23462template<class T, class... Ids> 23463prepared_statement_t<remove_t<T, Ids...>> prepare(remove_t<T, Ids...> statement) { 23464using object_type = expression_object_type_t<decltype(statement)>; 23465this->assert_mapped_type<object_type>(); 23466return this->prepare_impl(std::move(statement)); 23467} 23468 23469template<class T> 23470prepared_statement_t<insert_t<T>> prepare(insert_t<T> statement) { 23471using object_type = expression_object_type_t<decltype(statement)>; 23472this->assert_mapped_type<object_type>(); 23473this->assert_insertable_type<object_type>(); 23474return this->prepare_impl(std::move(statement)); 23475} 23476 23477template<class T> 23478prepared_statement_t<replace_t<T>> prepare(replace_t<T> statement) { 23479using object_type = expression_object_type_t<decltype(statement)>; 23480this->assert_mapped_type<object_type>(); 23481return this->prepare_impl(std::move(statement)); 23482} 23483 23484template<class E, satisfies<is_insert_range, E> = true> 23485prepared_statement_t<E> prepare(E statement) { 23486using object_type = expression_object_type_t<decltype(statement)>; 23487this->assert_mapped_type<object_type>(); 23488this->assert_insertable_type<object_type>(); 23489return this->prepare_impl(std::move(statement)); 23490} 23491 23492template<class E, satisfies<is_replace_range, E> = true> 23493prepared_statement_t<E> prepare(E statement) { 23494using object_type = expression_object_type_t<decltype(statement)>; 23495this->assert_mapped_type<object_type>(); 23496return this->prepare_impl(std::move(statement)); 23497} 23498 23499template<class T, class... Cols> 23500prepared_statement_t<insert_explicit<T, Cols...>> prepare(insert_explicit<T, Cols...> statement) { 23501using object_type = expression_object_type_t<decltype(statement)>; 23502this->assert_mapped_type<object_type>(); 23503return this->prepare_impl(std::move(statement)); 23504} 23505 23506template<class... Args> 23507void execute(const prepared_statement_t<replace_raw_t<Args...>>& statement) { 23508sqlite3_stmt* stmt = reset_stmt(statement.stmt); 23509iterate_ast(statement.expression, conditional_binder{stmt}); 23510perform_step(stmt); 23511} 23512 23513#if (SQLITE_VERSION_NUMBER >= 3008003) && defined(SQLITE_ORM_WITH_CTE) 23514template< 23515class... CTEs, 23516class E, 23517std::enable_if_t< 23518polyfill::disjunction_v<is_insert_raw<E>, is_replace_raw<E>, is_update_all<E>, is_remove_all<E>>, 23519bool> = true> 23520void execute(const prepared_statement_t<with_t<E, CTEs...>>& statement) { 23521sqlite3_stmt* stmt = reset_stmt(statement.stmt); 23522iterate_ast(statement.expression, conditional_binder{stmt}); 23523perform_step(stmt); 23524} 23525#endif 23526 23527template<class... Args> 23528void execute(const prepared_statement_t<insert_raw_t<Args...>>& statement) { 23529sqlite3_stmt* stmt = reset_stmt(statement.stmt); 23530iterate_ast(statement.expression, conditional_binder{stmt}); 23531perform_step(stmt); 23532} 23533 23534template<class T, class... Cols> 23535int64 execute(const prepared_statement_t<insert_explicit<T, Cols...>>& statement) { 23536using object_type = statement_object_type_t<decltype(statement)>; 23537 23538sqlite3_stmt* stmt = reset_stmt(statement.stmt); 23539 23540tuple_value_binder{stmt}( 23541statement.expression.columns.columns, 23542[&table = this->get_table<object_type>(), &object = statement.expression.obj](auto& memberPointer) { 23543return table.object_field_value(object, memberPointer); 23544}); 23545perform_step(stmt); 23546return sqlite3_last_insert_rowid(sqlite3_db_handle(stmt)); 23547} 23548 23549template<class T, 23550std::enable_if_t<polyfill::disjunction<is_replace<T>, is_replace_range<T>>::value, bool> = true> 23551void execute(const prepared_statement_t<T>& statement) { 23552using object_type = statement_object_type_t<decltype(statement)>; 23553 23554sqlite3_stmt* stmt = reset_stmt(statement.stmt); 23555 23556auto processObject = [&table = this->get_table<object_type>(), 23557bindValue = field_value_binder{stmt}](auto& object) mutable { 23558table.template for_each_column_excluding<is_generated_always>( 23559call_as_template_base<column_field>([&bindValue, &object](auto& column) { 23560bindValue(polyfill::invoke(column.member_pointer, object)); 23561})); 23562}; 23563 23564static_if<is_replace_range<T>::value>( 23565[&processObject](auto& expression) { 23566#if __cpp_lib_ranges >= 201911L 23567std::ranges::for_each(expression.range.first, 23568expression.range.second, 23569std::ref(processObject), 23570std::ref(expression.transformer)); 23571#else 23572auto& transformer = expression.transformer; 23573std::for_each(expression.range.first, 23574expression.range.second, 23575[&processObject, &transformer](auto& item) { 23576const object_type& object = polyfill::invoke(transformer, item); 23577processObject(object); 23578}); 23579#endif 23580}, 23581[&processObject](auto& expression) { 23582const object_type& o = get_object(expression); 23583processObject(o); 23584})(statement.expression); 23585 23586perform_step(stmt); 23587} 23588 23589template<class T, 23590std::enable_if_t<polyfill::disjunction<is_insert<T>, is_insert_range<T>>::value, bool> = true> 23591int64 execute(const prepared_statement_t<T>& statement) { 23592using object_type = statement_object_type_t<decltype(statement)>; 23593 23594sqlite3_stmt* stmt = reset_stmt(statement.stmt); 23595 23596auto processObject = [&table = this->get_table<object_type>(), 23597bindValue = field_value_binder{stmt}](auto& object) mutable { 23598using is_without_rowid = typename std::remove_reference_t<decltype(table)>::is_without_rowid; 23599table.template for_each_column_excluding< 23600mpl::conjunction<mpl::not_<mpl::always<is_without_rowid>>, 23601mpl::disjunction_fn<is_primary_key, is_generated_always>>>( 23602call_as_template_base<column_field>([&table, &bindValue, &object](auto& column) { 23603if (!exists_in_composite_primary_key(table, column)) { 23604bindValue(polyfill::invoke(column.member_pointer, object)); 23605} 23606})); 23607}; 23608 23609static_if<is_insert_range<T>::value>( 23610[&processObject](auto& expression) { 23611#if __cpp_lib_ranges >= 201911L 23612std::ranges::for_each(expression.range.first, 23613expression.range.second, 23614std::ref(processObject), 23615std::ref(expression.transformer)); 23616#else 23617auto& transformer = expression.transformer; 23618std::for_each(expression.range.first, 23619expression.range.second, 23620[&processObject, &transformer](auto& item) { 23621const object_type& object = polyfill::invoke(transformer, item); 23622processObject(object); 23623}); 23624#endif 23625}, 23626[&processObject](auto& expression) { 23627const object_type& o = get_object(expression); 23628processObject(o); 23629})(statement.expression); 23630 23631perform_step(stmt); 23632return sqlite3_last_insert_rowid(sqlite3_db_handle(stmt)); 23633} 23634 23635template<class T, class... Ids> 23636void execute(const prepared_statement_t<remove_t<T, Ids...>>& statement) { 23637sqlite3_stmt* stmt = reset_stmt(statement.stmt); 23638iterate_ast(statement.expression.ids, conditional_binder{stmt}); 23639perform_step(stmt); 23640} 23641 23642template<class T> 23643void execute(const prepared_statement_t<update_t<T>>& statement) { 23644using object_type = statement_object_type_t<decltype(statement)>; 23645 23646sqlite3_stmt* stmt = reset_stmt(statement.stmt); 23647auto& table = this->get_table<object_type>(); 23648 23649field_value_binder bindValue{stmt}; 23650auto& object = get_object(statement.expression); 23651table.template for_each_column_excluding<mpl::disjunction_fn<is_primary_key, is_generated_always>>( 23652call_as_template_base<column_field>([&table, &bindValue, &object](auto& column) { 23653if (!exists_in_composite_primary_key(table, column)) { 23654bindValue(polyfill::invoke(column.member_pointer, object)); 23655} 23656})); 23657table.for_each_column([&table, &bindValue, &object](auto& column) { 23658if (column.template is<is_primary_key>() || exists_in_composite_primary_key(table, column)) { 23659bindValue(polyfill::invoke(column.member_pointer, object)); 23660} 23661}); 23662perform_step(stmt); 23663} 23664 23665template<class T, class... Ids> 23666std::unique_ptr<T> execute(const prepared_statement_t<get_pointer_t<T, Ids...>>& statement) { 23667sqlite3_stmt* stmt = reset_stmt(statement.stmt); 23668 23669iterate_ast(statement.expression.ids, conditional_binder{stmt}); 23670 23671std::unique_ptr<T> res; 23672perform_step(stmt, [&table = this->get_table<T>(), &res](sqlite3_stmt* stmt) { 23673res = std::make_unique<T>(); 23674object_from_column_builder<T> builder{*res, stmt}; 23675table.for_each_column(builder); 23676}); 23677return res; 23678} 23679 23680#ifdef SQLITE_ORM_OPTIONAL_SUPPORTED 23681template<class T, class... Ids> 23682std::optional<T> execute(const prepared_statement_t<get_optional_t<T, Ids...>>& statement) { 23683sqlite3_stmt* stmt = reset_stmt(statement.stmt); 23684 23685iterate_ast(statement.expression.ids, conditional_binder{stmt}); 23686 23687std::optional<T> res; 23688perform_step(stmt, [&table = this->get_table<T>(), &res](sqlite3_stmt* stmt) { 23689object_from_column_builder<T> builder{res.emplace(), stmt}; 23690table.for_each_column(builder); 23691}); 23692return res; 23693} 23694#endif // SQLITE_ORM_OPTIONAL_SUPPORTED 23695 23696template<class T, class... Ids> 23697T execute(const prepared_statement_t<get_t<T, Ids...>>& statement) { 23698sqlite3_stmt* stmt = reset_stmt(statement.stmt); 23699 23700iterate_ast(statement.expression.ids, conditional_binder{stmt}); 23701 23702#ifdef SQLITE_ORM_OPTIONAL_SUPPORTED 23703std::optional<T> res; 23704perform_step(stmt, [&table = this->get_table<T>(), &res](sqlite3_stmt* stmt) { 23705object_from_column_builder<T> builder{res.emplace(), stmt}; 23706table.for_each_column(builder); 23707}); 23708if (!res.has_value()) { 23709throw std::system_error{orm_error_code::not_found}; 23710} 23711return std::move(res).value(); 23712#else 23713auto& table = this->get_table<T>(); 23714auto stepRes = sqlite3_step(stmt); 23715switch (stepRes) { 23716case SQLITE_ROW: { 23717T res; 23718object_from_column_builder<T> builder{res, stmt}; 23719table.for_each_column(builder); 23720return res; 23721} break; 23722case SQLITE_DONE: { 23723throw std::system_error{orm_error_code::not_found}; 23724} break; 23725default: { 23726throw_translated_sqlite_error(stmt); 23727} 23728} 23729#endif 23730} 23731 23732template<class T, class... Args> 23733void execute(const prepared_statement_t<remove_all_t<T, Args...>>& statement) { 23734sqlite3_stmt* stmt = reset_stmt(statement.stmt); 23735iterate_ast(statement.expression.conditions, conditional_binder{stmt}); 23736perform_step(stmt); 23737} 23738 23739template<class S, class... Wargs> 23740void execute(const prepared_statement_t<update_all_t<S, Wargs...>>& statement) { 23741sqlite3_stmt* stmt = reset_stmt(statement.stmt); 23742conditional_binder bindNode{stmt}; 23743iterate_ast(statement.expression.set, bindNode); 23744iterate_ast(statement.expression.conditions, bindNode); 23745perform_step(stmt); 23746} 23747 23748#if (SQLITE_VERSION_NUMBER >= 3008003) && defined(SQLITE_ORM_WITH_CTE) 23749template<class... CTEs, class T, class... Args> 23750auto execute(const prepared_statement_t<with_t<select_t<T, Args...>, CTEs...>>& statement) { 23751using 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. 23754using ColResult = column_result_of_t<ExprDBOs, T>; 23755return this->execute_select<ColResult>(statement); 23756} 23757#endif 23758 23759template<class T, class... Args> 23760auto execute(const prepared_statement_t<select_t<T, Args...>>& statement) { 23761using ColResult = column_result_of_t<db_objects_type, T>; 23762return this->execute_select<ColResult>(statement); 23763} 23764 23765template<class T, class R, class... Args, class O = mapped_type_proxy_t<T>> 23766R execute(const prepared_statement_t<get_all_t<T, R, Args...>>& statement) { 23767sqlite3_stmt* stmt = reset_stmt(statement.stmt); 23768 23769iterate_ast(statement.expression, conditional_binder{stmt}); 23770 23771R res; 23772perform_steps(stmt, [&table = this->get_table<O>(), &res](sqlite3_stmt* stmt) { 23773O obj; 23774object_from_column_builder<O> builder{obj, stmt}; 23775table.for_each_column(builder); 23776res.push_back(std::move(obj)); 23777}); 23778#ifdef SQLITE_ORM_IF_CONSTEXPR_SUPPORTED 23779if constexpr (polyfill::is_specialization_of_v<R, std::vector>) { 23780res.shrink_to_fit(); 23781} 23782#endif 23783return res; 23784} 23785 23786template<class T, class R, class... Args> 23787R execute(const prepared_statement_t<get_all_pointer_t<T, R, Args...>>& statement) { 23788sqlite3_stmt* stmt = reset_stmt(statement.stmt); 23789 23790iterate_ast(statement.expression, conditional_binder{stmt}); 23791 23792R res; 23793perform_steps(stmt, [&table = this->get_table<T>(), &res](sqlite3_stmt* stmt) { 23794auto obj = std::make_unique<T>(); 23795object_from_column_builder<T> builder{*obj, stmt}; 23796table.for_each_column(builder); 23797res.push_back(std::move(obj)); 23798}); 23799#ifdef SQLITE_ORM_IF_CONSTEXPR_SUPPORTED 23800if constexpr (polyfill::is_specialization_of_v<R, std::vector>) { 23801res.shrink_to_fit(); 23802} 23803#endif 23804return res; 23805} 23806 23807#ifdef SQLITE_ORM_OPTIONAL_SUPPORTED 23808template<class T, class R, class... Args> 23809R execute(const prepared_statement_t<get_all_optional_t<T, R, Args...>>& statement) { 23810sqlite3_stmt* stmt = reset_stmt(statement.stmt); 23811 23812iterate_ast(statement.expression, conditional_binder{stmt}); 23813 23814R res; 23815perform_steps(stmt, [&table = this->get_table<T>(), &res](sqlite3_stmt* stmt) { 23816auto obj = std::make_optional<T>(); 23817object_from_column_builder<T> builder{*obj, stmt}; 23818table.for_each_column(builder); 23819res.push_back(std::move(obj)); 23820}); 23821#ifdef SQLITE_ORM_IF_CONSTEXPR_SUPPORTED 23822if constexpr (polyfill::is_specialization_of_v<R, std::vector>) { 23823res.shrink_to_fit(); 23824} 23825#endif 23826return 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*/ 23835template<class... DBO> 23836internal::storage_t<DBO...> make_storage(std::string filename, DBO... dbObjects) { 23837return {std::move(filename), internal::db_objects_tuple<DBO...>{std::forward<DBO>(dbObjects)...}}; 23838} 23839 23840/** 23841* sqlite3_threadsafe() interface. 23842*/ 23843inline int threadsafe() { 23844return 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 23875namespace sqlite_orm { 23876 23877namespace internal { 23878 23879template<class T, class Ctx> 23880auto serialize(const T& t, const Ctx& context); 23881 23882/** 23883* Serialize a column's default value. 23884*/ 23885template<class T> 23886std::string serialize_default_value(const default_t<T>& dft) { 23887db_objects_tuple<> dbObjects; 23888serializer_context<db_objects_tuple<>> context{dbObjects}; 23889return serialize(dft.value, context); 23890} 23891 23892} 23893 23894} 23895 23896// #include "../schema/column.h" 23897 23898namespace sqlite_orm { 23899namespace internal { 23900 23901template<class... Op> 23902std::unique_ptr<std::string> column_constraints<Op...>::default_value() const { 23903static constexpr size_t default_op_index = find_tuple_template<constraints_type, default_t>::value; 23904 23905std::unique_ptr<std::string> value; 23906call_if_constexpr<default_op_index != std::tuple_size<constraints_type>::value>( 23907[&value](auto& constraints) { 23908value = 23909std::make_unique<std::string>(serialize_default_value(std::get<default_op_index>(constraints))); 23910}, 23911this->constraints); 23912return 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 23938namespace sqlite_orm { 23939namespace internal { 23940 23941template<class T, bool WithoutRowId, class... Cs> 23942std::vector<table_xinfo> table_t<T, WithoutRowId, Cs...>::get_table_info() const { 23943std::vector<table_xinfo> res; 23944res.reserve(filter_tuple_sequence_t<elements_type, is_column>::size()); 23945this->for_each_column([&res](auto& column) { 23946using field_type = field_type_t<std::remove_reference_t<decltype(column)>>; 23947std::string dft; 23948if (auto d = column.default_value()) { 23949dft = std::move(*d); 23950} 23951using constraints_tuple = decltype(column.constraints); 23952constexpr bool hasExplicitNull = 23953mpl::invoke_t<mpl::disjunction<check_if_has_type<null_t>>, constraints_tuple>::value; 23954constexpr bool hasExplicitNotNull = 23955mpl::invoke_t<mpl::disjunction<check_if_has_type<not_null_t>>, constraints_tuple>::value; 23956res.emplace_back(-1, 23957column.name, 23958type_printer<field_type>().print(), 23959!hasExplicitNull && !hasExplicitNotNull 23960? column.is_not_null() 23961: (hasExplicitNull ? !hasExplicitNull : hasExplicitNotNull), 23962std::move(dft), 23963column.template is<is_primary_key>(), 23964column.template is<is_generated_always>()); 23965}); 23966auto compositeKeyColumnNames = this->composite_key_columns_names(); 23967for (size_t i = 0; i < compositeKeyColumnNames.size(); ++i) { 23968const std::string& columnName = compositeKeyColumnNames[i]; 23969#if __cpp_lib_ranges >= 201911L 23970auto it = std::ranges::find(res, columnName, &table_xinfo::name); 23971#else 23972auto it = std::find_if(res.begin(), res.end(), [&columnName](const table_xinfo& ti) { 23973return ti.name == columnName; 23974}); 23975#endif 23976if (it != res.end()) { 23977it->pk = static_cast<int>(i + 1); 23978} 23979} 23980return 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 24012namespace 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*/ 24022struct sqlite_master { 24023std::string type; 24024std::string name; 24025std::string tbl_name; 24026int rootpage = 0; 24027std::string sql; 24028 24029#ifdef SQLITE_ORM_DEFAULT_COMPARISONS_SUPPORTED 24030friend bool operator==(const sqlite_master&, const sqlite_master&) = default; 24031#endif 24032}; 24033 24034inline auto make_sqlite_schema_table() { 24035return make_table("sqlite_master", 24036make_column("type", &sqlite_master::type), 24037make_column("name", &sqlite_master::name), 24038make_column("tbl_name", &sqlite_master::tbl_name), 24039make_column("rootpage", &sqlite_master::rootpage), 24040make_column("sql", &sqlite_master::sql)); 24041} 24042 24043#ifdef SQLITE_ORM_WITH_CPP20_ALIASES 24044inline constexpr orm_table_reference auto sqlite_master_table = c<sqlite_master>(); 24045inline 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 24061namespace sqlite_orm { 24062#ifdef SQLITE_ENABLE_DBSTAT_VTAB 24063struct dbstat { 24064std::string name; 24065std::string path; 24066int pageno = 0; 24067std::string pagetype; 24068int ncell = 0; 24069int payload = 0; 24070int unused = 0; 24071int mx_payload = 0; 24072int pgoffset = 0; 24073int pgsize = 0; 24074}; 24075 24076inline auto make_dbstat_table() { 24077return make_table("dbstat", 24078make_column("name", &dbstat::name), 24079make_column("path", &dbstat::path), 24080make_column("pageno", &dbstat::pageno), 24081make_column("pagetype", &dbstat::pagetype), 24082make_column("ncell", &dbstat::ncell), 24083make_column("payload", &dbstat::payload), 24084make_column("unused", &dbstat::unused), 24085make_column("mx_payload", &dbstat::mx_payload), 24086make_column("pgoffset", &dbstat::pgoffset), 24087make_column("pgsize", &dbstat::pgsize)); 24088} 24089 24090#ifdef SQLITE_ORM_WITH_CPP20_ALIASES 24091inline 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 24104namespace sqlite_orm { 24105namespace internal { 24106 24107template<class... DBO> 24108template<class Table, satisfies<is_table, Table>> 24109sync_schema_result storage_t<DBO...>::sync_table(const Table& table, sqlite3* db, bool preserve) { 24110if (std::is_same<object_type_t<Table>, sqlite_master>::value) { 24111return sync_schema_result::already_in_sync; 24112} 24113#ifdef SQLITE_ENABLE_DBSTAT_VTAB 24114if (std::is_same<object_type_t<Table>, dbstat>::value) { 24115return sync_schema_result::already_in_sync; 24116} 24117#endif // SQLITE_ENABLE_DBSTAT_VTAB 24118auto res = sync_schema_result::already_in_sync; 24119bool attempt_to_preserve = true; 24120 24121auto schema_stat = this->schema_status(table, db, preserve, &attempt_to_preserve); 24122if (schema_stat != sync_schema_result::already_in_sync) { 24123if (schema_stat == sync_schema_result::new_table_created) { 24124this->create_table(db, table.name, table); 24125res = sync_schema_result::new_table_created; 24126} else { 24127if (schema_stat == sync_schema_result::old_columns_removed || 24128schema_stat == sync_schema_result::new_columns_added || 24129schema_stat == sync_schema_result::new_columns_added_and_old_columns_removed) { 24130 24131// get table info provided in `make_table` call.. 24132auto storageTableInfo = table.get_table_info(); 24133 24134// now get current table info from db using `PRAGMA table_xinfo` query.. 24135auto dbTableInfo = this->pragma.table_xinfo(table.name); // should include generated columns 24136 24137// this vector will contain pointers to columns that gotta be added.. 24138std::vector<const table_xinfo*> columnsToAdd; 24139 24140this->calculate_remove_add_columns(columnsToAdd, storageTableInfo, dbTableInfo); 24141 24142if (schema_stat == sync_schema_result::old_columns_removed) { 24143#if SQLITE_VERSION_NUMBER >= 3035000 // DROP COLUMN feature exists (v3.35.0) 24144for (auto& tableInfo: dbTableInfo) { 24145this->drop_column(db, table.name, tableInfo.name); 24146} 24147res = sync_schema_result::old_columns_removed; 24148#else 24149// extra table columns than storage columns 24150this->backup_table(db, table, {}); 24151res = sync_schema_result::old_columns_removed; 24152#endif 24153} 24154 24155if (schema_stat == sync_schema_result::new_columns_added) { 24156for (const table_xinfo* colInfo: columnsToAdd) { 24157table.for_each_column([this, colInfo, &tableName = table.name, db](auto& column) { 24158if (column.name != colInfo->name) { 24159return; 24160} 24161this->add_column(db, tableName, column); 24162}); 24163} 24164res = sync_schema_result::new_columns_added; 24165} 24166 24167if (schema_stat == sync_schema_result::new_columns_added_and_old_columns_removed) { 24168 24169auto storageTableInfo = table.get_table_info(); 24170this->add_generated_cols(columnsToAdd, storageTableInfo); 24171 24172// remove extra columns and generated columns 24173this->backup_table(db, table, columnsToAdd); 24174res = 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.. 24178auto dbTableInfo = this->pragma.table_xinfo(table.name); // should include generated columns 24179auto storageTableInfo = table.get_table_info(); 24180 24181// this vector will contain pointers to columns that gotta be added.. 24182std::vector<const table_xinfo*> columnsToAdd; 24183 24184this->calculate_remove_add_columns(columnsToAdd, storageTableInfo, dbTableInfo); 24185 24186this->add_generated_cols(columnsToAdd, storageTableInfo); 24187 24188if (preserve && attempt_to_preserve) { 24189this->backup_table(db, table, columnsToAdd); 24190} else { 24191this->drop_create_with_loss(db, table); 24192} 24193res = schema_stat; 24194} 24195} 24196} 24197return res; 24198} 24199 24200template<class... DBO> 24201template<class Table> 24202void storage_t<DBO...>::copy_table( 24203sqlite3* db, 24204const std::string& sourceTableName, 24205const std::string& destinationTableName, 24206const Table& table, 24207const std::vector<const table_xinfo*>& columnsToIgnore) const { // must ignore generated columns 24208std::vector<std::reference_wrapper<const std::string>> columnNames; 24209columnNames.reserve(table.template count_of<is_column>()); 24210table.for_each_column([&columnNames, &columnsToIgnore](const column_identifier& column) { 24211auto& columnName = column.name; 24212#if __cpp_lib_ranges >= 201911L 24213auto columnToIgnoreIt = std::ranges::find(columnsToIgnore, columnName, &table_xinfo::name); 24214#else 24215auto columnToIgnoreIt = std::find_if(columnsToIgnore.begin(), 24216columnsToIgnore.end(), 24217[&columnName](const table_xinfo* tableInfo) { 24218return columnName == tableInfo->name; 24219}); 24220#endif 24221if (columnToIgnoreIt == columnsToIgnore.end()) { 24222columnNames.push_back(cref(columnName)); 24223} 24224}); 24225 24226std::stringstream ss; 24227ss << "INSERT INTO " << streaming_identifier(destinationTableName) << " (" 24228<< streaming_identifiers(columnNames) << ") " 24229<< "SELECT " << streaming_identifiers(columnNames) << " FROM " << streaming_identifier(sourceTableName) 24230<< std::flush; 24231perform_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 24291namespace sqlite_orm { 24292namespace internal { 24293 24294template<class T, class SFINAE = void> 24295struct node_tuple { 24296using type = std::tuple<T>; 24297}; 24298 24299template<class T> 24300using node_tuple_t = typename node_tuple<T>::type; 24301 24302/* 24303* Node tuple for several types. 24304*/ 24305template<class... T> 24306using node_tuple_for = conc_tuple<typename node_tuple<T>::type...>; 24307 24308template<> 24309struct node_tuple<void, void> { 24310using type = std::tuple<>; 24311}; 24312 24313template<class T> 24314struct node_tuple<std::reference_wrapper<T>, void> : node_tuple<T> {}; 24315 24316template<class... Args> 24317struct node_tuple<std::tuple<Args...>, void> : node_tuple_for<Args...> {}; 24318 24319#ifdef SQLITE_ORM_OPTIONAL_SUPPORTED 24320template<class T> 24321struct node_tuple<as_optional_t<T>, void> : node_tuple<T> {}; 24322#endif // SQLITE_ORM_OPTIONAL_SUPPORTED 24323 24324template<class... Args> 24325struct node_tuple<group_by_t<Args...>, void> : node_tuple_for<Args...> {}; 24326 24327template<class T, class... Args> 24328struct node_tuple<group_by_with_having<T, Args...>, void> : node_tuple_for<Args..., T> {}; 24329 24330#if SQLITE_VERSION_NUMBER >= 3024000 24331template<class Targets, class Actions> 24332struct node_tuple<upsert_clause<Targets, Actions>, void> : node_tuple<Actions> {}; 24333#endif 24334 24335template<class... Args> 24336struct node_tuple<set_t<Args...>, void> : node_tuple_for<Args...> {}; 24337 24338template<class T, class X, class Y, class Z> 24339struct node_tuple<highlight_t<T, X, Y, Z>, void> : node_tuple_for<X, Y, Z> {}; 24340 24341template<class T> 24342struct node_tuple<excluded_t<T>, void> : node_tuple<T> {}; 24343 24344template<class C> 24345struct node_tuple<where_t<C>, void> : node_tuple<C> {}; 24346 24347template<class T, class X> 24348struct node_tuple<match_t<T, X>, void> : node_tuple<X> {}; 24349 24350/** 24351* Column alias 24352*/ 24353template<class A> 24354struct node_tuple<alias_holder<A>, void> : node_tuple<void> {}; 24355 24356/** 24357* Column alias 24358*/ 24359template<char... C> 24360struct node_tuple<column_alias<C...>, void> : node_tuple<void> {}; 24361 24362/** 24363* Literal 24364*/ 24365template<class T> 24366struct node_tuple<literal_holder<T>, void> : node_tuple<void> {}; 24367 24368template<class E> 24369struct node_tuple<order_by_t<E>, void> : node_tuple<E> {}; 24370 24371template<class L, class R> 24372struct node_tuple<is_equal_with_table_t<L, R>, void> : node_tuple<R> {}; 24373 24374template<class T> 24375struct node_tuple<T, match_if<is_binary_condition, T>> : node_tuple_for<left_type_t<T>, right_type_t<T>> {}; 24376 24377template<class T> 24378struct node_tuple<T, match_if<is_binary_operator, T>> : node_tuple_for<left_type_t<T>, right_type_t<T>> {}; 24379 24380template<class... Args> 24381struct node_tuple<columns_t<Args...>, void> : node_tuple_for<Args...> {}; 24382 24383template<class T, class... Args> 24384struct node_tuple<struct_t<T, Args...>, void> : node_tuple_for<Args...> {}; 24385 24386template<class L, class A> 24387struct node_tuple<dynamic_in_t<L, A>, void> : node_tuple_for<L, A> {}; 24388 24389template<class L, class... Args> 24390struct node_tuple<in_t<L, Args...>, void> : node_tuple_for<L, Args...> {}; 24391 24392template<class T> 24393struct 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) 24396template<class CTE> 24397struct node_tuple<CTE, match_specialization_of<CTE, common_table_expression>> 24398: node_tuple<typename CTE::expression_type> {}; 24399 24400template<class With> 24401struct node_tuple<With, match_specialization_of<With, with_t>> 24402: node_tuple_for<typename With::cte_type, typename With::expression_type> {}; 24403#endif 24404 24405template<class T, class... Args> 24406struct node_tuple<select_t<T, Args...>, void> : node_tuple_for<T, Args...> {}; 24407 24408template<class... Args> 24409struct node_tuple<insert_raw_t<Args...>, void> : node_tuple_for<Args...> {}; 24410 24411template<class... Args> 24412struct node_tuple<replace_raw_t<Args...>, void> : node_tuple_for<Args...> {}; 24413 24414template<class T> 24415struct node_tuple<into_t<T>, void> : node_tuple<void> {}; 24416 24417template<class... Args> 24418struct node_tuple<values_t<Args...>, void> : node_tuple_for<Args...> {}; 24419 24420template<class T, class R, class... Args> 24421struct node_tuple<get_all_t<T, R, Args...>, void> : node_tuple_for<Args...> {}; 24422 24423template<class T, class... Args> 24424struct node_tuple<get_all_pointer_t<T, Args...>, void> : node_tuple_for<Args...> {}; 24425 24426#ifdef SQLITE_ORM_OPTIONAL_SUPPORTED 24427template<class T, class... Args> 24428struct node_tuple<get_all_optional_t<T, Args...>, void> : node_tuple_for<Args...> {}; 24429#endif // SQLITE_ORM_OPTIONAL_SUPPORTED 24430 24431template<class... Args, class... Wargs> 24432struct node_tuple<update_all_t<set_t<Args...>, Wargs...>, void> : node_tuple_for<Args..., Wargs...> {}; 24433 24434template<class T, class... Args> 24435struct node_tuple<remove_all_t<T, Args...>, void> : node_tuple_for<Args...> {}; 24436 24437template<class T, class E> 24438struct node_tuple<cast_t<T, E>, void> : node_tuple<E> {}; 24439 24440template<class T> 24441struct node_tuple<exists_t<T>, void> : node_tuple<T> {}; 24442 24443template<class T> 24444struct node_tuple<optional_container<T>, void> : node_tuple<T> {}; 24445 24446template<class A, class T, class E> 24447struct node_tuple<like_t<A, T, E>, void> : node_tuple_for<A, T, E> {}; 24448 24449template<class A, class T> 24450struct node_tuple<glob_t<A, T>, void> : node_tuple_for<A, T> {}; 24451 24452template<class A, class T> 24453struct node_tuple<between_t<A, T>, void> : node_tuple_for<A, T, T> {}; 24454 24455template<class T> 24456struct node_tuple<named_collate<T>, void> : node_tuple<T> {}; 24457 24458template<class T> 24459struct node_tuple<is_null_t<T>, void> : node_tuple<T> {}; 24460 24461template<class T> 24462struct node_tuple<is_not_null_t<T>, void> : node_tuple<T> {}; 24463 24464template<class C> 24465struct node_tuple<negated_condition_t<C>, void> : node_tuple<C> {}; 24466 24467template<class T> 24468struct node_tuple<unary_minus_t<T>, void> : node_tuple<T> {}; 24469 24470template<class T> 24471struct node_tuple<bitwise_not_t<T>, void> : node_tuple<T> {}; 24472 24473template<class R, class S, class... Args> 24474struct node_tuple<built_in_function_t<R, S, Args...>, void> : node_tuple_for<Args...> {}; 24475 24476template<class R, class S, class... Args> 24477struct node_tuple<built_in_aggregate_function_t<R, S, Args...>, void> : node_tuple_for<Args...> {}; 24478 24479template<class F, class W> 24480struct node_tuple<filtered_aggregate_function<F, W>, void> : node_tuple_for<F, W> {}; 24481 24482template<class F, class... Args> 24483struct node_tuple<function_call<F, Args...>, void> : node_tuple_for<Args...> {}; 24484 24485template<class T, class O> 24486struct node_tuple<left_join_t<T, O>, void> : node_tuple<O> {}; 24487 24488template<class T> 24489struct 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. 24493template<class T, class M> 24494struct node_tuple<using_t<T, M>, void> : node_tuple<column_pointer<T, M>> {}; 24495 24496template<class T, class O> 24497struct node_tuple<join_t<T, O>, void> : node_tuple<O> {}; 24498 24499template<class T, class O> 24500struct node_tuple<left_outer_join_t<T, O>, void> : node_tuple<O> {}; 24501 24502template<class T, class O> 24503struct node_tuple<inner_join_t<T, O>, void> : node_tuple<O> {}; 24504 24505template<class R, class T, class E, class... Args> 24506struct node_tuple<simple_case_t<R, T, E, Args...>, void> : node_tuple_for<T, Args..., E> {}; 24507 24508template<class L, class R> 24509struct node_tuple<std::pair<L, R>, void> : node_tuple_for<L, R> {}; 24510 24511template<class T, class E> 24512struct node_tuple<as_t<T, E>, void> : node_tuple<E> {}; 24513 24514template<class T> 24515struct node_tuple<limit_t<T, false, false, void>, void> : node_tuple<T> {}; 24516 24517template<class T, class O> 24518struct node_tuple<limit_t<T, true, false, O>, void> : node_tuple_for<T, O> {}; 24519 24520template<class T, class O> 24521struct node_tuple<limit_t<T, true, true, O>, void> : node_tuple_for<O, T> {}; 24522} 24523} 24524 24525// #include "expression_object_type.h" 24526 24527namespace sqlite_orm { 24528 24529template<int N, class It, class L, class O> 24530auto& get(internal::prepared_statement_t<internal::insert_range_t<It, L, O>>& statement) { 24531return std::get<N>(statement.expression.range); 24532} 24533 24534template<int N, class It, class L, class O> 24535const auto& get(const internal::prepared_statement_t<internal::insert_range_t<It, L, O>>& statement) { 24536return std::get<N>(statement.expression.range); 24537} 24538 24539template<int N, class It, class L, class O> 24540auto& get(internal::prepared_statement_t<internal::replace_range_t<It, L, O>>& statement) { 24541return std::get<N>(statement.expression.range); 24542} 24543 24544template<int N, class It, class L, class O> 24545const auto& get(const internal::prepared_statement_t<internal::replace_range_t<It, L, O>>& statement) { 24546return std::get<N>(statement.expression.range); 24547} 24548 24549template<int N, class T, class... Ids> 24550auto& get(internal::prepared_statement_t<internal::get_t<T, Ids...>>& statement) { 24551return internal::get_ref(std::get<N>(statement.expression.ids)); 24552} 24553 24554template<int N, class T, class... Ids> 24555const auto& get(const internal::prepared_statement_t<internal::get_t<T, Ids...>>& statement) { 24556return internal::get_ref(std::get<N>(statement.expression.ids)); 24557} 24558 24559template<int N, class T, class... Ids> 24560auto& get(internal::prepared_statement_t<internal::get_pointer_t<T, Ids...>>& statement) { 24561return internal::get_ref(std::get<N>(statement.expression.ids)); 24562} 24563 24564template<int N, class T, class... Ids> 24565const auto& get(const internal::prepared_statement_t<internal::get_pointer_t<T, Ids...>>& statement) { 24566return internal::get_ref(std::get<N>(statement.expression.ids)); 24567} 24568 24569#ifdef SQLITE_ORM_OPTIONAL_SUPPORTED 24570template<int N, class T, class... Ids> 24571auto& get(internal::prepared_statement_t<internal::get_optional_t<T, Ids...>>& statement) { 24572return internal::get_ref(std::get<N>(statement.expression.ids)); 24573} 24574 24575template<int N, class T, class... Ids> 24576const auto& get(const internal::prepared_statement_t<internal::get_optional_t<T, Ids...>>& statement) { 24577return internal::get_ref(std::get<N>(statement.expression.ids)); 24578} 24579#endif // SQLITE_ORM_OPTIONAL_SUPPORTED 24580 24581template<int N, class T, class... Ids> 24582auto& get(internal::prepared_statement_t<internal::remove_t<T, Ids...>>& statement) { 24583return internal::get_ref(std::get<N>(statement.expression.ids)); 24584} 24585 24586template<int N, class T, class... Ids> 24587const auto& get(const internal::prepared_statement_t<internal::remove_t<T, Ids...>>& statement) { 24588return internal::get_ref(std::get<N>(statement.expression.ids)); 24589} 24590 24591template<int N, class T> 24592auto& get(internal::prepared_statement_t<internal::update_t<T>>& statement) { 24593static_assert(N == 0, "get<> works only with 0 argument for update statement"); 24594return internal::get_ref(statement.expression.object); 24595} 24596 24597template<int N, class T> 24598const auto& get(const internal::prepared_statement_t<internal::update_t<T>>& statement) { 24599static_assert(N == 0, "get<> works only with 0 argument for update statement"); 24600return internal::get_ref(statement.expression.object); 24601} 24602 24603template<int N, class T, class... Cols> 24604auto& get(internal::prepared_statement_t<internal::insert_explicit<T, Cols...>>& statement) { 24605static_assert(N == 0, "get<> works only with 0 argument for insert statement"); 24606return internal::get_ref(statement.expression.obj); 24607} 24608 24609template<int N, class T, class... Cols> 24610const auto& get(const internal::prepared_statement_t<internal::insert_explicit<T, Cols...>>& statement) { 24611static_assert(N == 0, "get<> works only with 0 argument for insert statement"); 24612return internal::get_ref(statement.expression.obj); 24613} 24614 24615template<int N, class T> 24616auto& get(internal::prepared_statement_t<internal::replace_t<T>>& statement) { 24617static_assert(N == 0, "get<> works only with 0 argument for replace statement"); 24618return internal::get_ref(statement.expression.object); 24619} 24620 24621template<int N, class T> 24622const auto& get(const internal::prepared_statement_t<internal::replace_t<T>>& statement) { 24623static_assert(N == 0, "get<> works only with 0 argument for replace statement"); 24624return internal::get_ref(statement.expression.object); 24625} 24626 24627template<int N, class T> 24628auto& get(internal::prepared_statement_t<internal::insert_t<T>>& statement) { 24629static_assert(N == 0, "get<> works only with 0 argument for insert statement"); 24630return internal::get_ref(statement.expression.object); 24631} 24632 24633template<int N, class T> 24634const auto& get(const internal::prepared_statement_t<internal::insert_t<T>>& statement) { 24635static_assert(N == 0, "get<> works only with 0 argument for insert statement"); 24636return internal::get_ref(statement.expression.object); 24637} 24638 24639template<int N, class T> 24640const auto& get(const internal::prepared_statement_t<T>& statement) { 24641using statement_type = polyfill::remove_cvref_t<decltype(statement)>; 24642using expression_type = internal::expression_type_t<statement_type>; 24643using node_tuple = internal::node_tuple_t<expression_type>; 24644using bind_tuple = internal::bindable_filter_t<node_tuple>; 24645using result_type = std::tuple_element_t<static_cast<size_t>(N), bind_tuple>; 24646const result_type* result = nullptr; 24647internal::iterate_ast(statement.expression, [&result, index = -1](auto& node) mutable { 24648using node_type = polyfill::remove_cvref_t<decltype(node)>; 24649if (internal::is_bindable<node_type>::value) { 24650++index; 24651} 24652if (index == N) { 24653internal::call_if_constexpr<std::is_same<result_type, node_type>::value>( 24654[](auto& r, auto& n) { 24655r = &n; 24656}, 24657result, 24658node); 24659} 24660}); 24661return internal::get_ref(*result); 24662} 24663 24664template<int N, class T> 24665auto& get(internal::prepared_statement_t<T>& statement) { 24666using statement_type = std::remove_reference_t<decltype(statement)>; 24667using expression_type = internal::expression_type_t<statement_type>; 24668using node_tuple = internal::node_tuple_t<expression_type>; 24669using bind_tuple = internal::bindable_filter_t<node_tuple>; 24670using result_type = std::tuple_element_t<static_cast<size_t>(N), bind_tuple>; 24671result_type* result = nullptr; 24672 24673internal::iterate_ast(statement.expression, [&result, index = -1](auto& node) mutable { 24674using node_type = polyfill::remove_cvref_t<decltype(node)>; 24675if (internal::is_bindable<node_type>::value) { 24676++index; 24677} 24678if (index == N) { 24679internal::call_if_constexpr<std::is_same<result_type, node_type>::value>( 24680[](auto& r, auto& n) { 24681r = const_cast<std::remove_reference_t<decltype(r)>>(&n); 24682}, 24683result, 24684node); 24685} 24686}); 24687return 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 24711namespace sqlite_orm { 24712 24713#ifdef SQLITE_ORM_WITH_CPP20_ALIASES 24714inline 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. 24716using carray_pvt [[deprecated]] = decltype("carray"_pointer_type); 24717 24718template<typename P> 24719using carray_pointer_arg = pointer_arg_t<P, carray_pointer_tag>; 24720template<typename P, typename D> 24721using carray_pointer_binding = pointer_binding_t<P, carray_pointer_tag, D>; 24722template<typename P> 24723using 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*/ 24732template<class P, class D> 24733carray_pointer_binding<P, D> bind_carray_pointer(P* p, D d) noexcept { 24734return bind_pointer<carray_pointer_tag>(p, std::move(d)); 24735} 24736 24737template<class P> 24738static_carray_pointer_binding<P> bind_carray_pointer_statically(P* p) noexcept { 24739return 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*/ 24748template<class P, class D> 24749[[deprecated("Use the better named function `bind_carray_pointer(...)`")]] carray_pointer_binding<P, D> 24750bindable_carray_pointer(P* p, D d) noexcept { 24751return bind_pointer<carray_pointer_tag>(p, std::move(d)); 24752} 24753 24754template<class P> 24755[[deprecated( 24756"Use the better named function `bind_carray_pointer_statically(...)` ")]] static_carray_pointer_binding<P> 24757statically_bindable_carray_pointer(P* p) noexcept { 24758return bind_pointer_statically<carray_pointer_tag>(p); 24759} 24760#else 24761inline constexpr const char carray_pointer_name[] = "carray"; 24762using 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. 24764using carray_pvt [[deprecated]] = carray_pointer_type; 24765 24766template<typename P> 24767using carray_pointer_arg = pointer_arg<P, carray_pointer_type>; 24768template<typename P, typename D> 24769using carray_pointer_binding = pointer_binding<P, carray_pointer_type, D>; 24770template<typename P> 24771using 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*/ 24780template<class P, class D> 24781carray_pointer_binding<P, D> bind_carray_pointer(P* p, D d) noexcept { 24782return 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*/ 24791template<class P> 24792static_carray_pointer_binding<P> bind_carray_pointer_statically(P* p) noexcept { 24793return bind_pointer_statically<carray_pointer_type>(p); 24794} 24795 24796template<class P, class D> 24797[[deprecated("Use the better named function `bind_carray_pointer(...)`")]] carray_pointer_binding<P, D> 24798bindable_carray_pointer(P* p, D d) noexcept { 24799return bind_carray_pointer(p, std::move(d)); 24800} 24801 24802template<class P> 24803[[deprecated( 24804"Use the better named function `bind_carray_pointer_statically(...)` ")]] static_carray_pointer_binding<P> 24805statically_bindable_carray_pointer(P* p) noexcept { 24806return 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*/ 24815template<typename P> 24816struct note_value_fn { 24817P operator()(P&& value, carray_pointer_arg<P> pv) const { 24818if (P* observer = pv) { 24819*observer = value; 24820} 24821return std::move(value); 24822} 24823}; 24824 24825/** 24826* remember(V, $PTR) extension function https://sqlite.org/src/file/ext/misc/remember.c 24827*/ 24828struct remember_fn : note_value_fn<int64> { 24829static constexpr const char* name() { 24830return "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