diff --git a/dev/ast/set.h b/dev/ast/set.h index b6a73013..0077f357 100644 --- a/dev/ast/set.h +++ b/dev/ast/set.h @@ -52,7 +52,8 @@ namespace sqlite_orm { void push_back(assign_t assign) { auto newContext = this->context; newContext.skip_table_name = true; - iterate_ast(assign, this->collector); + // note: we are only interested in the table name on the left-hand side of the assignment operator expression + iterate_ast(assign.lhs, this->collector); std::stringstream ss; ss << serialize(assign.lhs, newContext) << ' ' << assign.serialize() << ' ' << serialize(assign.rhs, context); diff --git a/dev/ast/where.h b/dev/ast/where.h index 38bb6a3f..ddf8ef73 100644 --- a/dev/ast/where.h +++ b/dev/ast/where.h @@ -28,7 +28,7 @@ namespace sqlite_orm { expression_type expression; - where_t(expression_type expression_) : expression(std::move(expression_)) {} + constexpr where_t(expression_type expression_) : expression(std::move(expression_)) {} }; template @@ -50,7 +50,7 @@ _EXPORT_SQLITE_ORM namespace sqlite_orm { * auto rows = storage.select(&Letter::name, where(greater_than(&Letter::id, 3))); */ template - internal::where_t where(C expression) { + constexpr internal::where_t where(C expression) { return {std::move(expression)}; } } diff --git a/dev/conditions.h b/dev/conditions.h index 1a26b36d..1316a1e7 100644 --- a/dev/conditions.h +++ b/dev/conditions.h @@ -115,7 +115,7 @@ namespace sqlite_orm { struct negated_condition_t : condition_t, negated_condition_string { C c; - negated_condition_t(C c_) : c(std::move(c_)) {} + constexpr negated_condition_t(C c_) : c(std::move(c_)) {} }; /** @@ -134,9 +134,9 @@ namespace sqlite_orm { left_type lhs; right_type rhs; - binary_condition() = default; + constexpr binary_condition() = default; - binary_condition(left_type l_, right_type r_) : lhs(std::move(l_)), rhs(std::move(r_)) {} + constexpr binary_condition(left_type l_, right_type r_) : lhs(std::move(l_)), rhs(std::move(r_)) {} }; template @@ -853,7 +853,7 @@ _EXPORT_SQLITE_ORM namespace sqlite_orm { class T, std::enable_if_t, is_operator_argument>::value, bool> = true> - negated_condition_t operator!(T arg) { + constexpr negated_condition_t operator!(T arg) { return {std::move(arg)}; } @@ -864,7 +864,7 @@ _EXPORT_SQLITE_ORM namespace sqlite_orm { is_operator_argument, is_operator_argument>::value, bool> = true> - less_than_t, unwrap_expression_t> operator<(L l, R r) { + constexpr less_than_t, unwrap_expression_t> operator<(L l, R r) { return {get_from_expression(std::forward(l)), get_from_expression(std::forward(r))}; } @@ -875,7 +875,7 @@ _EXPORT_SQLITE_ORM namespace sqlite_orm { is_operator_argument, is_operator_argument>::value, bool> = true> - less_or_equal_t, unwrap_expression_t> operator<=(L l, R r) { + constexpr less_or_equal_t, unwrap_expression_t> operator<=(L l, R r) { return {get_from_expression(std::forward(l)), get_from_expression(std::forward(r))}; } @@ -886,7 +886,7 @@ _EXPORT_SQLITE_ORM namespace sqlite_orm { is_operator_argument, is_operator_argument>::value, bool> = true> - greater_than_t, unwrap_expression_t> operator>(L l, R r) { + constexpr greater_than_t, unwrap_expression_t> operator>(L l, R r) { return {get_from_expression(std::forward(l)), get_from_expression(std::forward(r))}; } @@ -897,7 +897,7 @@ _EXPORT_SQLITE_ORM namespace sqlite_orm { is_operator_argument, is_operator_argument>::value, bool> = true> - greater_or_equal_t, unwrap_expression_t> operator>=(L l, R r) { + constexpr greater_or_equal_t, unwrap_expression_t> operator>=(L l, R r) { return {get_from_expression(std::forward(l)), get_from_expression(std::forward(r))}; } @@ -910,7 +910,7 @@ _EXPORT_SQLITE_ORM namespace sqlite_orm { is_operator_argument, is_operator_argument>::value, bool> = true> - is_equal_t, unwrap_expression_t> operator==(L l, R r) { + constexpr is_equal_t, unwrap_expression_t> operator==(L l, R r) { return {get_from_expression(std::forward(l)), get_from_expression(std::forward(r))}; } @@ -923,7 +923,7 @@ _EXPORT_SQLITE_ORM namespace sqlite_orm { is_operator_argument, is_operator_argument>::value, bool> = true> - is_not_equal_t, unwrap_expression_t> operator!=(L l, R r) { + constexpr is_not_equal_t, unwrap_expression_t> operator!=(L l, R r) { return {get_from_expression(std::forward(l)), get_from_expression(std::forward(r))}; } @@ -934,7 +934,7 @@ _EXPORT_SQLITE_ORM namespace sqlite_orm { is_operator_argument, is_operator_argument>::value, bool> = true> - and_condition_t, unwrap_expression_t> operator&&(L l, R r) { + constexpr and_condition_t, unwrap_expression_t> operator&&(L l, R r) { return {get_from_expression(std::forward(l)), get_from_expression(std::forward(r))}; } @@ -943,7 +943,7 @@ _EXPORT_SQLITE_ORM namespace sqlite_orm { std::enable_if_t< polyfill::disjunction, std::is_base_of>::value, bool> = true> - or_condition_t, unwrap_expression_t> operator||(L l, R r) { + constexpr or_condition_t, unwrap_expression_t> operator||(L l, R r) { return {get_from_expression(std::forward(l)), get_from_expression(std::forward(r))}; } @@ -959,7 +959,7 @@ _EXPORT_SQLITE_ORM namespace sqlite_orm { polyfill::negation, std::is_base_of>>>::value, bool> = true> - conc_t, unwrap_expression_t> operator||(L l, R r) { + constexpr conc_t, unwrap_expression_t> operator||(L l, R r) { return {get_from_expression(std::forward(l)), get_from_expression(std::forward(r))}; } } @@ -1057,14 +1057,14 @@ _EXPORT_SQLITE_ORM namespace sqlite_orm { } template - auto and_(L l, R r) { + constexpr auto and_(L l, R r) { using namespace ::sqlite_orm::internal; return and_condition_t, unwrap_expression_t>{get_from_expression(std::forward(l)), get_from_expression(std::forward(r))}; } template - auto or_(L l, R r) { + constexpr auto or_(L l, R r) { using namespace ::sqlite_orm::internal; return or_condition_t, unwrap_expression_t>{get_from_expression(std::forward(l)), get_from_expression(std::forward(r))}; @@ -1111,52 +1111,52 @@ _EXPORT_SQLITE_ORM namespace sqlite_orm { } template - internal::is_equal_t is_equal(L l, R r) { + constexpr internal::is_equal_t is_equal(L l, R r) { return {std::move(l), std::move(r)}; } template - internal::is_equal_t eq(L l, R r) { + constexpr internal::is_equal_t eq(L l, R r) { return {std::move(l), std::move(r)}; } template - internal::is_equal_with_table_t is_equal(R rhs) { + constexpr internal::is_equal_with_table_t is_equal(R rhs) { return {std::move(rhs)}; } template - internal::is_not_equal_t is_not_equal(L l, R r) { + constexpr internal::is_not_equal_t is_not_equal(L l, R r) { return {std::move(l), std::move(r)}; } template - internal::is_not_equal_t ne(L l, R r) { + constexpr internal::is_not_equal_t ne(L l, R r) { return {std::move(l), std::move(r)}; } template - internal::greater_than_t greater_than(L l, R r) { + constexpr internal::greater_than_t greater_than(L l, R r) { return {std::move(l), std::move(r)}; } template - internal::greater_than_t gt(L l, R r) { + constexpr internal::greater_than_t gt(L l, R r) { return {std::move(l), std::move(r)}; } template - internal::greater_or_equal_t greater_or_equal(L l, R r) { + constexpr internal::greater_or_equal_t greater_or_equal(L l, R r) { return {std::move(l), std::move(r)}; } template - internal::greater_or_equal_t ge(L l, R r) { + constexpr internal::greater_or_equal_t ge(L l, R r) { return {std::move(l), std::move(r)}; } template - internal::less_than_t less_than(L l, R r) { + constexpr internal::less_than_t less_than(L l, R r) { return {std::move(l), std::move(r)}; } @@ -1170,12 +1170,12 @@ _EXPORT_SQLITE_ORM namespace sqlite_orm { } template - internal::less_than_t lt(L l, R r) { + constexpr internal::less_than_t lt(L l, R r) { return {std::move(l), std::move(r)}; } template - internal::less_or_equal_t less_or_equal(L l, R r) { + constexpr internal::less_or_equal_t less_or_equal(L l, R r) { return {std::move(l), std::move(r)}; } @@ -1189,7 +1189,7 @@ _EXPORT_SQLITE_ORM namespace sqlite_orm { } template - internal::less_or_equal_t le(L l, R r) { + constexpr internal::less_or_equal_t le(L l, R r) { return {std::move(l), std::move(r)}; } diff --git a/dev/core_functions.h b/dev/core_functions.h index de91b347..0d729a24 100644 --- a/dev/core_functions.h +++ b/dev/core_functions.h @@ -2056,7 +2056,7 @@ _EXPORT_SQLITE_ORM namespace sqlite_orm { is_operator_argument, is_operator_argument>::value, bool> = true> - add_t, unwrap_expression_t> operator+(L l, R r) { + constexpr add_t, unwrap_expression_t> operator+(L l, R r) { return {get_from_expression(std::forward(l)), get_from_expression(std::forward(r))}; } @@ -2067,7 +2067,7 @@ _EXPORT_SQLITE_ORM namespace sqlite_orm { is_operator_argument, is_operator_argument>::value, bool> = true> - sub_t, unwrap_expression_t> operator-(L l, R r) { + constexpr sub_t, unwrap_expression_t> operator-(L l, R r) { return {get_from_expression(std::forward(l)), get_from_expression(std::forward(r))}; } @@ -2078,7 +2078,7 @@ _EXPORT_SQLITE_ORM namespace sqlite_orm { is_operator_argument, is_operator_argument>::value, bool> = true> - mul_t, unwrap_expression_t> operator*(L l, R r) { + constexpr mul_t, unwrap_expression_t> operator*(L l, R r) { return {get_from_expression(std::forward(l)), get_from_expression(std::forward(r))}; } @@ -2089,7 +2089,7 @@ _EXPORT_SQLITE_ORM namespace sqlite_orm { is_operator_argument, is_operator_argument>::value, bool> = true> - div_t, unwrap_expression_t> operator/(L l, R r) { + constexpr div_t, unwrap_expression_t> operator/(L l, R r) { return {get_from_expression(std::forward(l)), get_from_expression(std::forward(r))}; } @@ -2100,7 +2100,7 @@ _EXPORT_SQLITE_ORM namespace sqlite_orm { is_operator_argument, is_operator_argument>::value, bool> = true> - mod_t, unwrap_expression_t> operator%(L l, R r) { + constexpr mod_t, unwrap_expression_t> operator%(L l, R r) { return {get_from_expression(std::forward(l)), get_from_expression(std::forward(r))}; } } diff --git a/dev/cte_moniker.h b/dev/cte_moniker.h index 0df1c768..6e25f144 100644 --- a/dev/cte_moniker.h +++ b/dev/cte_moniker.h @@ -52,7 +52,7 @@ namespace sqlite_orm { std::same_as> || std::convertible_to) && ...) - auto operator()(ExplicitCols... explicitColumns) const; + constexpr auto operator()(ExplicitCols... explicitColumns) const; #else template>, std::is_convertible>...>, bool> = true> - auto operator()(ExplicitCols... explicitColumns) const; + constexpr auto operator()(ExplicitCols... explicitColumns) const; #endif }; } diff --git a/dev/eponymous_vtabs/dbstat.h b/dev/eponymous_vtabs/dbstat.h index 75b82af8..03d6b06f 100644 --- a/dev/eponymous_vtabs/dbstat.h +++ b/dev/eponymous_vtabs/dbstat.h @@ -8,6 +8,7 @@ #include "../schema/column.h" #include "../schema/table.h" +#include "../column_pointer.h" _EXPORT_SQLITE_ORM namespace sqlite_orm { #ifdef SQLITE_ENABLE_DBSTAT_VTAB @@ -37,5 +38,9 @@ _EXPORT_SQLITE_ORM namespace sqlite_orm { make_column("pgoffset", &dbstat::pgoffset), make_column("pgsize", &dbstat::pgsize)); } + +#ifdef SQLITE_ORM_WITH_CPP20_ALIASES + inline constexpr orm_table_reference auto dbstat_table = c(); +#endif #endif // SQLITE_ENABLE_DBSTAT_VTAB } diff --git a/dev/expression.h b/dev/expression.h index b13d070b..9593a4fa 100644 --- a/dev/expression.h +++ b/dev/expression.h @@ -70,12 +70,12 @@ namespace sqlite_orm { is_operator_argument_v::value>> = true; template - T get_from_expression(T value) { + constexpr T get_from_expression(T value) { return std::move(value); } template - T get_from_expression(expression_t expression) { + constexpr T get_from_expression(expression_t expression) { return std::move(expression.value); } @@ -90,7 +90,7 @@ _EXPORT_SQLITE_ORM namespace sqlite_orm { * `storage.update(set(c(&User::name) = "Dua Lipa")); */ template - internal::expression_t c(T value) { + constexpr internal::expression_t c(T value) { return {std::move(value)}; } } diff --git a/dev/operators.h b/dev/operators.h index ffb20542..90548b7f 100644 --- a/dev/operators.h +++ b/dev/operators.h @@ -22,7 +22,7 @@ namespace sqlite_orm { left_type lhs; right_type rhs; - binary_operator(left_type lhs_, right_type rhs_) : lhs(std::move(lhs_)), rhs(std::move(rhs_)) {} + constexpr binary_operator(left_type lhs_, right_type rhs_) : lhs(std::move(lhs_)), rhs(std::move(rhs_)) {} }; template @@ -201,7 +201,7 @@ _EXPORT_SQLITE_ORM namespace sqlite_orm { * name || '@gmail.com' FROM users */ template - internal::conc_t conc(L l, R r) { + constexpr internal::conc_t conc(L l, R r) { return {std::move(l), std::move(r)}; } @@ -209,7 +209,7 @@ _EXPORT_SQLITE_ORM namespace sqlite_orm { * Public interface for + operator. Example: `select(add(&User::age, 100));` => SELECT age + 100 FROM users */ template - internal::add_t add(L l, R r) { + constexpr internal::add_t add(L l, R r) { return {std::move(l), std::move(r)}; } @@ -217,7 +217,7 @@ _EXPORT_SQLITE_ORM namespace sqlite_orm { * Public interface for - operator. Example: `select(sub(&User::age, 1));` => SELECT age - 1 FROM users */ template - internal::sub_t sub(L l, R r) { + constexpr internal::sub_t sub(L l, R r) { return {std::move(l), std::move(r)}; } @@ -225,7 +225,7 @@ _EXPORT_SQLITE_ORM namespace sqlite_orm { * Public interface for * operator. Example: `select(mul(&User::salary, 2));` => SELECT salary * 2 FROM users */ template - internal::mul_t mul(L l, R r) { + constexpr internal::mul_t mul(L l, R r) { return {std::move(l), std::move(r)}; } @@ -235,7 +235,7 @@ _EXPORT_SQLITE_ORM namespace sqlite_orm { * If you use `using namespace sqlite_orm` directive you an specify which `div` you call explicitly using `::div` or `sqlite_orm::div` statements. */ template - internal::div_t div(L l, R r) { + constexpr internal::div_t div(L l, R r) { return {std::move(l), std::move(r)}; } @@ -243,32 +243,32 @@ _EXPORT_SQLITE_ORM namespace sqlite_orm { * Public interface for % operator. Example: `select(mod(&User::age, 5));` => SELECT age % 5 FROM users */ template - internal::mod_t mod(L l, R r) { + constexpr internal::mod_t mod(L l, R r) { return {std::move(l), std::move(r)}; } template - internal::bitwise_shift_left_t bitwise_shift_left(L l, R r) { + constexpr internal::bitwise_shift_left_t bitwise_shift_left(L l, R r) { return {std::move(l), std::move(r)}; } template - internal::bitwise_shift_right_t bitwise_shift_right(L l, R r) { + constexpr internal::bitwise_shift_right_t bitwise_shift_right(L l, R r) { return {std::move(l), std::move(r)}; } template - internal::bitwise_and_t bitwise_and(L l, R r) { + constexpr internal::bitwise_and_t bitwise_and(L l, R r) { return {std::move(l), std::move(r)}; } template - internal::bitwise_or_t bitwise_or(L l, R r) { + constexpr internal::bitwise_or_t bitwise_or(L l, R r) { return {std::move(l), std::move(r)}; } template - internal::bitwise_not_t bitwise_not(T t) { + constexpr internal::bitwise_not_t bitwise_not(T t) { return {std::move(t)}; } diff --git a/dev/prepared_statement.h b/dev/prepared_statement.h index b0970624..426f12a8 100644 --- a/dev/prepared_statement.h +++ b/dev/prepared_statement.h @@ -144,6 +144,12 @@ namespace sqlite_orm { conditions_type conditions; }; + template + SQLITE_ORM_INLINE_VAR constexpr bool is_update_all_v = polyfill::is_specialization_of::value; + + template + using is_update_all = polyfill::bool_constant>; + template struct remove_all_t { using type = T; @@ -152,6 +158,12 @@ namespace sqlite_orm { conditions_type conditions; }; + template + SQLITE_ORM_INLINE_VAR constexpr bool is_remove_all_v = polyfill::is_specialization_of::value; + + template + using is_remove_all = polyfill::bool_constant>; + template struct get_t { using type = T; diff --git a/dev/select_constraints.h b/dev/select_constraints.h index c64a0624..102c8b70 100644 --- a/dev/select_constraints.h +++ b/dev/select_constraints.h @@ -148,7 +148,7 @@ namespace sqlite_orm { expressions_tuple compound; - compound_operator(expressions_tuple compound) : compound{std::move(compound)} { + constexpr compound_operator(expressions_tuple compound) : compound{std::move(compound)} { iterate_tuple(this->compound, [](auto& expression) { expression.highest_level = true; }); @@ -184,7 +184,7 @@ namespace sqlite_orm { struct union_t : public compound_operator, union_base { using typename compound_operator::expressions_tuple; - union_t(expressions_tuple compound, bool all) : + constexpr union_t(expressions_tuple compound, bool all) : compound_operator{std::move(compound)}, union_base{all} {} }; @@ -265,7 +265,7 @@ namespace sqlite_orm { explicit_colrefs_tuple explicitColumns; expression_type subselect; - common_table_expression(explicit_colrefs_tuple explicitColumns, expression_type subselect) : + constexpr common_table_expression(explicit_colrefs_tuple explicitColumns, expression_type subselect) : explicitColumns{std::move(explicitColumns)}, subselect{std::move(subselect)} { this->subselect.highest_level = true; } @@ -280,23 +280,25 @@ namespace sqlite_orm { #if SQLITE_VERSION_NUMBER >= 3035000 && defined(SQLITE_ORM_WITH_CPP20_ALIASES) template = true> - common_table_expression, Select> as(Select sel) && { + constexpr common_table_expression, Select> + as(Select sel) && { return {std::move(this->explicitColumns), std::move(sel)}; } template = true> - common_table_expression, select_t> + constexpr common_table_expression, select_t> as(Compound sel) && { return {std::move(this->explicitColumns), {std::move(sel)}}; } #else template = true> - common_table_expression, Select> as(Select sel) && { + constexpr common_table_expression, Select> as(Select sel) && { return {std::move(this->explicitColumns), std::move(sel)}; } template = true> - common_table_expression, select_t> as(Compound sel) && { + constexpr common_table_expression, select_t> + as(Compound sel) && { return {std::move(this->explicitColumns), {std::move(sel)}}; } #endif @@ -418,7 +420,7 @@ namespace sqlite_orm { }; template - void validate_conditions() { + constexpr void validate_conditions() { static_assert(count_tuple::value <= 1, "a single query cannot contain > 1 WHERE blocks"); static_assert(count_tuple::value <= 1, "a single query cannot contain > 1 GROUP BY blocks"); static_assert(count_tuple::value <= 1, "a single query cannot contain > 1 ORDER BY blocks"); @@ -487,7 +489,7 @@ _EXPORT_SQLITE_ORM namespace sqlite_orm { * Public function for subselect query. Is useful in UNION queries. */ template - internal::select_t select(T t, Args... args) { + constexpr internal::select_t select(T t, Args... args) { using args_tuple = std::tuple; internal::validate_conditions(); return {std::move(t), {std::forward(args)...}}; @@ -499,7 +501,7 @@ _EXPORT_SQLITE_ORM namespace sqlite_orm { * Look through example in examples/union.cpp */ template - internal::union_t union_(E... expressions) { + constexpr internal::union_t union_(E... expressions) { static_assert(sizeof...(E) >= 2, "Compound operators must have at least 2 select statements"); return {{std::forward(expressions)...}, false}; } @@ -510,7 +512,7 @@ _EXPORT_SQLITE_ORM namespace sqlite_orm { * Look through example in examples/union.cpp */ template - internal::union_t union_all(E... expressions) { + constexpr internal::union_t union_all(E... expressions) { static_assert(sizeof...(E) >= 2, "Compound operators must have at least 2 select statements"); return {{std::forward(expressions)...}, true}; } @@ -521,13 +523,13 @@ _EXPORT_SQLITE_ORM namespace sqlite_orm { * Look through example in examples/except.cpp */ template - internal::except_t except(E... expressions) { + constexpr internal::except_t except(E... expressions) { static_assert(sizeof...(E) >= 2, "Compound operators must have at least 2 select statements"); return {{std::forward(expressions)...}}; } template - internal::intersect_t intersect(E... expressions) { + constexpr internal::intersect_t intersect(E... expressions) { static_assert(sizeof...(E) >= 2, "Compound operators must have at least 2 select statements"); return {{std::forward(expressions)...}}; } @@ -581,7 +583,7 @@ _EXPORT_SQLITE_ORM namespace sqlite_orm { std::is_same>, std::is_convertible>...>, bool> = true> - auto cte(ExplicitCols... explicitColumns) { + constexpr auto cte(ExplicitCols... explicitColumns) { using namespace ::sqlite_orm::internal; static_assert(is_cte_moniker_v, "Moniker must be a CTE moniker"); static_assert((!is_builtin_numeric_column_alias_v && ...), @@ -599,7 +601,7 @@ _EXPORT_SQLITE_ORM namespace sqlite_orm { std::same_as> || std::convertible_to) && ...) - auto cte(ExplicitCols... explicitColumns) { + constexpr auto cte(ExplicitCols... explicitColumns) { using namespace ::sqlite_orm::internal; static_assert((!is_builtin_numeric_column_alias_v && ...), "Numeric column aliases are reserved for referencing columns locally within a single CTE."); @@ -618,7 +620,7 @@ _EXPORT_SQLITE_ORM namespace sqlite_orm { std::same_as> || std::convertible_to) && ...) - auto cte_moniker::operator()(ExplicitCols... explicitColumns) const { + constexpr auto cte_moniker::operator()(ExplicitCols... explicitColumns) const { return cte>(std::forward(explicitColumns)...); } #else @@ -630,7 +632,7 @@ _EXPORT_SQLITE_ORM namespace sqlite_orm { std::is_same>, std::is_convertible>...>, bool>> - auto cte_moniker::operator()(ExplicitCols... explicitColumns) const { + constexpr auto cte_moniker::operator()(ExplicitCols... explicitColumns) const { return cte>(std::forward(explicitColumns)...); } #endif @@ -768,7 +770,7 @@ _EXPORT_SQLITE_ORM namespace sqlite_orm { * If you need to fetch results as objects instead of tuples please use `object()`. */ template - internal::asterisk_t asterisk(bool definedOrder = false) { + constexpr internal::asterisk_t asterisk(bool definedOrder = false) { return {definedOrder}; } @@ -780,7 +782,7 @@ _EXPORT_SQLITE_ORM namespace sqlite_orm { * storage.select(asterisk(), inner_join(on(m->*&Employee::reportsTo == &Employee::employeeId))); */ template - auto asterisk(bool definedOrder = false) { + constexpr auto asterisk(bool definedOrder = false) { return asterisk>(definedOrder); } #endif @@ -797,13 +799,13 @@ _EXPORT_SQLITE_ORM namespace sqlite_orm { * If you need to fetch results as tuples instead of objects please use `asterisk()`. */ template - internal::object_t object(bool definedOrder = false) { + constexpr internal::object_t object(bool definedOrder = false) { return {definedOrder}; } #ifdef SQLITE_ORM_WITH_CPP20_ALIASES template - auto object(bool definedOrder = false) { + constexpr auto object(bool definedOrder = false) { return object>(definedOrder); } #endif diff --git a/dev/statement_serializer.h b/dev/statement_serializer.h index 70b1dbff..4a39770a 100644 --- a/dev/statement_serializer.h +++ b/dev/statement_serializer.h @@ -1364,7 +1364,10 @@ namespace sqlite_orm { template std::set> collect_table_names(const set_t& set, const Ctx& ctx) { auto collector = make_table_name_collector(ctx.db_objects); - iterate_ast(set, collector); + // note: we are only interested in the table name on the left-hand side of the assignment operator expression + iterate_tuple(set.assigns, [&collector](const auto& assignmentOperator) { + iterate_ast(assignmentOperator.lhs, collector); + }); return std::move(collector.table_names); } @@ -1377,8 +1380,7 @@ namespace sqlite_orm { template = true> std::set> collect_table_names(const T& sel, const Ctx& ctx) { auto collector = make_table_name_collector(ctx.db_objects); - iterate_ast(sel.col, collector); - iterate_ast(sel.conditions, collector); + iterate_ast(sel, collector); return std::move(collector.table_names); } diff --git a/dev/storage.h b/dev/storage.h index 976ffbea..ae593e6d 100644 --- a/dev/storage.h +++ b/dev/storage.h @@ -1255,7 +1255,12 @@ namespace sqlite_orm { #if(SQLITE_VERSION_NUMBER >= 3008003) && defined(SQLITE_ORM_WITH_CTE) template, is_insert_raw>, bool> = true> + std::enable_if_t, + is_insert_raw, + is_replace_raw, + is_update_all, + is_remove_all>, + bool> = true> prepared_statement_t> prepare(with_t sel) { return this->prepare_impl>(std::move(sel)); } @@ -1382,7 +1387,12 @@ namespace sqlite_orm { } #if(SQLITE_VERSION_NUMBER >= 3008003) && defined(SQLITE_ORM_WITH_CTE) - template = true> + template< + class... CTEs, + class E, + std::enable_if_t< + polyfill::disjunction_v, is_replace_raw, is_update_all, is_remove_all>, + bool> = true> void execute(const prepared_statement_t>& statement) { sqlite3_stmt* stmt = reset_stmt(statement.stmt); iterate_ast(statement.expression, conditional_binder{stmt}); diff --git a/dev/tuple_helper/tuple_iteration.h b/dev/tuple_helper/tuple_iteration.h index 55f968b5..0dc4ecc2 100644 --- a/dev/tuple_helper/tuple_iteration.h +++ b/dev/tuple_helper/tuple_iteration.h @@ -10,7 +10,7 @@ namespace sqlite_orm { namespace internal { #if defined(SQLITE_ORM_FOLD_EXPRESSIONS_SUPPORTED) && defined(SQLITE_ORM_IF_CONSTEXPR_SUPPORTED) template - void iterate_tuple(Tpl& tpl, std::index_sequence, L&& lambda) { + constexpr void iterate_tuple(Tpl& tpl, std::index_sequence, L&& lambda) { if constexpr(reversed) { // nifty fold expression trick: make use of guaranteed right-to-left evaluation order when folding over operator= int sink; @@ -36,7 +36,7 @@ namespace sqlite_orm { } #endif template - void iterate_tuple(Tpl&& tpl, L&& lambda) { + constexpr void iterate_tuple(Tpl&& tpl, L&& lambda) { iterate_tuple(tpl, std::make_index_sequence>::value>{}, std::forward(lambda)); diff --git a/include/sqlite_orm/sqlite_orm.h b/include/sqlite_orm/sqlite_orm.h index 9605d7e3..cda583de 100644 --- a/include/sqlite_orm/sqlite_orm.h +++ b/include/sqlite_orm/sqlite_orm.h @@ -1677,7 +1677,7 @@ namespace sqlite_orm { namespace internal { #if defined(SQLITE_ORM_FOLD_EXPRESSIONS_SUPPORTED) && defined(SQLITE_ORM_IF_CONSTEXPR_SUPPORTED) template - void iterate_tuple(Tpl& tpl, std::index_sequence, L&& lambda) { + constexpr void iterate_tuple(Tpl& tpl, std::index_sequence, L&& lambda) { if constexpr(reversed) { // nifty fold expression trick: make use of guaranteed right-to-left evaluation order when folding over operator= int sink; @@ -1703,7 +1703,7 @@ namespace sqlite_orm { } #endif template - void iterate_tuple(Tpl&& tpl, L&& lambda) { + constexpr void iterate_tuple(Tpl&& tpl, L&& lambda) { iterate_tuple(tpl, std::make_index_sequence>::value>{}, std::forward(lambda)); @@ -4242,7 +4242,7 @@ namespace sqlite_orm { left_type lhs; right_type rhs; - binary_operator(left_type lhs_, right_type rhs_) : lhs(std::move(lhs_)), rhs(std::move(rhs_)) {} + constexpr binary_operator(left_type lhs_, right_type rhs_) : lhs(std::move(lhs_)), rhs(std::move(rhs_)) {} }; template @@ -4421,7 +4421,7 @@ _EXPORT_SQLITE_ORM namespace sqlite_orm { * name || '@gmail.com' FROM users */ template - internal::conc_t conc(L l, R r) { + constexpr internal::conc_t conc(L l, R r) { return {std::move(l), std::move(r)}; } @@ -4429,7 +4429,7 @@ _EXPORT_SQLITE_ORM namespace sqlite_orm { * Public interface for + operator. Example: `select(add(&User::age, 100));` => SELECT age + 100 FROM users */ template - internal::add_t add(L l, R r) { + constexpr internal::add_t add(L l, R r) { return {std::move(l), std::move(r)}; } @@ -4437,7 +4437,7 @@ _EXPORT_SQLITE_ORM namespace sqlite_orm { * Public interface for - operator. Example: `select(sub(&User::age, 1));` => SELECT age - 1 FROM users */ template - internal::sub_t sub(L l, R r) { + constexpr internal::sub_t sub(L l, R r) { return {std::move(l), std::move(r)}; } @@ -4445,7 +4445,7 @@ _EXPORT_SQLITE_ORM namespace sqlite_orm { * Public interface for * operator. Example: `select(mul(&User::salary, 2));` => SELECT salary * 2 FROM users */ template - internal::mul_t mul(L l, R r) { + constexpr internal::mul_t mul(L l, R r) { return {std::move(l), std::move(r)}; } @@ -4455,7 +4455,7 @@ _EXPORT_SQLITE_ORM namespace sqlite_orm { * If you use `using namespace sqlite_orm` directive you an specify which `div` you call explicitly using `::div` or `sqlite_orm::div` statements. */ template - internal::div_t div(L l, R r) { + constexpr internal::div_t div(L l, R r) { return {std::move(l), std::move(r)}; } @@ -4463,32 +4463,32 @@ _EXPORT_SQLITE_ORM namespace sqlite_orm { * Public interface for % operator. Example: `select(mod(&User::age, 5));` => SELECT age % 5 FROM users */ template - internal::mod_t mod(L l, R r) { + constexpr internal::mod_t mod(L l, R r) { return {std::move(l), std::move(r)}; } template - internal::bitwise_shift_left_t bitwise_shift_left(L l, R r) { + constexpr internal::bitwise_shift_left_t bitwise_shift_left(L l, R r) { return {std::move(l), std::move(r)}; } template - internal::bitwise_shift_right_t bitwise_shift_right(L l, R r) { + constexpr internal::bitwise_shift_right_t bitwise_shift_right(L l, R r) { return {std::move(l), std::move(r)}; } template - internal::bitwise_and_t bitwise_and(L l, R r) { + constexpr internal::bitwise_and_t bitwise_and(L l, R r) { return {std::move(l), std::move(r)}; } template - internal::bitwise_or_t bitwise_or(L l, R r) { + constexpr internal::bitwise_or_t bitwise_or(L l, R r) { return {std::move(l), std::move(r)}; } template - internal::bitwise_not_t bitwise_not(T t) { + constexpr internal::bitwise_not_t bitwise_not(T t) { return {std::move(t)}; } @@ -4586,7 +4586,7 @@ namespace sqlite_orm { expression_type expression; - where_t(expression_type expression_) : expression(std::move(expression_)) {} + constexpr where_t(expression_type expression_) : expression(std::move(expression_)) {} }; template @@ -4608,7 +4608,7 @@ _EXPORT_SQLITE_ORM namespace sqlite_orm { * auto rows = storage.select(&Letter::name, where(greater_than(&Letter::id, 3))); */ template - internal::where_t where(C expression) { + constexpr internal::where_t where(C expression) { return {std::move(expression)}; } } @@ -4830,12 +4830,12 @@ namespace sqlite_orm { is_operator_argument_v::value>> = true; template - T get_from_expression(T value) { + constexpr T get_from_expression(T value) { return std::move(value); } template - T get_from_expression(expression_t expression) { + constexpr T get_from_expression(expression_t expression) { return std::move(expression.value); } @@ -4850,7 +4850,7 @@ _EXPORT_SQLITE_ORM namespace sqlite_orm { * `storage.update(set(c(&User::name) = "Dua Lipa")); */ template - internal::expression_t c(T value) { + constexpr internal::expression_t c(T value) { return {std::move(value)}; } } @@ -4967,7 +4967,7 @@ namespace sqlite_orm { struct negated_condition_t : condition_t, negated_condition_string { C c; - negated_condition_t(C c_) : c(std::move(c_)) {} + constexpr negated_condition_t(C c_) : c(std::move(c_)) {} }; /** @@ -4986,9 +4986,9 @@ namespace sqlite_orm { left_type lhs; right_type rhs; - binary_condition() = default; + constexpr binary_condition() = default; - binary_condition(left_type l_, right_type r_) : lhs(std::move(l_)), rhs(std::move(r_)) {} + constexpr binary_condition(left_type l_, right_type r_) : lhs(std::move(l_)), rhs(std::move(r_)) {} }; template @@ -5705,7 +5705,7 @@ _EXPORT_SQLITE_ORM namespace sqlite_orm { class T, std::enable_if_t, is_operator_argument>::value, bool> = true> - negated_condition_t operator!(T arg) { + constexpr negated_condition_t operator!(T arg) { return {std::move(arg)}; } @@ -5716,7 +5716,7 @@ _EXPORT_SQLITE_ORM namespace sqlite_orm { is_operator_argument, is_operator_argument>::value, bool> = true> - less_than_t, unwrap_expression_t> operator<(L l, R r) { + constexpr less_than_t, unwrap_expression_t> operator<(L l, R r) { return {get_from_expression(std::forward(l)), get_from_expression(std::forward(r))}; } @@ -5727,7 +5727,7 @@ _EXPORT_SQLITE_ORM namespace sqlite_orm { is_operator_argument, is_operator_argument>::value, bool> = true> - less_or_equal_t, unwrap_expression_t> operator<=(L l, R r) { + constexpr less_or_equal_t, unwrap_expression_t> operator<=(L l, R r) { return {get_from_expression(std::forward(l)), get_from_expression(std::forward(r))}; } @@ -5738,7 +5738,7 @@ _EXPORT_SQLITE_ORM namespace sqlite_orm { is_operator_argument, is_operator_argument>::value, bool> = true> - greater_than_t, unwrap_expression_t> operator>(L l, R r) { + constexpr greater_than_t, unwrap_expression_t> operator>(L l, R r) { return {get_from_expression(std::forward(l)), get_from_expression(std::forward(r))}; } @@ -5749,7 +5749,7 @@ _EXPORT_SQLITE_ORM namespace sqlite_orm { is_operator_argument, is_operator_argument>::value, bool> = true> - greater_or_equal_t, unwrap_expression_t> operator>=(L l, R r) { + constexpr greater_or_equal_t, unwrap_expression_t> operator>=(L l, R r) { return {get_from_expression(std::forward(l)), get_from_expression(std::forward(r))}; } @@ -5762,7 +5762,7 @@ _EXPORT_SQLITE_ORM namespace sqlite_orm { is_operator_argument, is_operator_argument>::value, bool> = true> - is_equal_t, unwrap_expression_t> operator==(L l, R r) { + constexpr is_equal_t, unwrap_expression_t> operator==(L l, R r) { return {get_from_expression(std::forward(l)), get_from_expression(std::forward(r))}; } @@ -5775,7 +5775,7 @@ _EXPORT_SQLITE_ORM namespace sqlite_orm { is_operator_argument, is_operator_argument>::value, bool> = true> - is_not_equal_t, unwrap_expression_t> operator!=(L l, R r) { + constexpr is_not_equal_t, unwrap_expression_t> operator!=(L l, R r) { return {get_from_expression(std::forward(l)), get_from_expression(std::forward(r))}; } @@ -5786,7 +5786,7 @@ _EXPORT_SQLITE_ORM namespace sqlite_orm { is_operator_argument, is_operator_argument>::value, bool> = true> - and_condition_t, unwrap_expression_t> operator&&(L l, R r) { + constexpr and_condition_t, unwrap_expression_t> operator&&(L l, R r) { return {get_from_expression(std::forward(l)), get_from_expression(std::forward(r))}; } @@ -5795,7 +5795,7 @@ _EXPORT_SQLITE_ORM namespace sqlite_orm { std::enable_if_t< polyfill::disjunction, std::is_base_of>::value, bool> = true> - or_condition_t, unwrap_expression_t> operator||(L l, R r) { + constexpr or_condition_t, unwrap_expression_t> operator||(L l, R r) { return {get_from_expression(std::forward(l)), get_from_expression(std::forward(r))}; } @@ -5811,7 +5811,7 @@ _EXPORT_SQLITE_ORM namespace sqlite_orm { polyfill::negation, std::is_base_of>>>::value, bool> = true> - conc_t, unwrap_expression_t> operator||(L l, R r) { + constexpr conc_t, unwrap_expression_t> operator||(L l, R r) { return {get_from_expression(std::forward(l)), get_from_expression(std::forward(r))}; } } @@ -5909,14 +5909,14 @@ _EXPORT_SQLITE_ORM namespace sqlite_orm { } template - auto and_(L l, R r) { + constexpr auto and_(L l, R r) { using namespace ::sqlite_orm::internal; return and_condition_t, unwrap_expression_t>{get_from_expression(std::forward(l)), get_from_expression(std::forward(r))}; } template - auto or_(L l, R r) { + constexpr auto or_(L l, R r) { using namespace ::sqlite_orm::internal; return or_condition_t, unwrap_expression_t>{get_from_expression(std::forward(l)), get_from_expression(std::forward(r))}; @@ -5963,52 +5963,52 @@ _EXPORT_SQLITE_ORM namespace sqlite_orm { } template - internal::is_equal_t is_equal(L l, R r) { + constexpr internal::is_equal_t is_equal(L l, R r) { return {std::move(l), std::move(r)}; } template - internal::is_equal_t eq(L l, R r) { + constexpr internal::is_equal_t eq(L l, R r) { return {std::move(l), std::move(r)}; } template - internal::is_equal_with_table_t is_equal(R rhs) { + constexpr internal::is_equal_with_table_t is_equal(R rhs) { return {std::move(rhs)}; } template - internal::is_not_equal_t is_not_equal(L l, R r) { + constexpr internal::is_not_equal_t is_not_equal(L l, R r) { return {std::move(l), std::move(r)}; } template - internal::is_not_equal_t ne(L l, R r) { + constexpr internal::is_not_equal_t ne(L l, R r) { return {std::move(l), std::move(r)}; } template - internal::greater_than_t greater_than(L l, R r) { + constexpr internal::greater_than_t greater_than(L l, R r) { return {std::move(l), std::move(r)}; } template - internal::greater_than_t gt(L l, R r) { + constexpr internal::greater_than_t gt(L l, R r) { return {std::move(l), std::move(r)}; } template - internal::greater_or_equal_t greater_or_equal(L l, R r) { + constexpr internal::greater_or_equal_t greater_or_equal(L l, R r) { return {std::move(l), std::move(r)}; } template - internal::greater_or_equal_t ge(L l, R r) { + constexpr internal::greater_or_equal_t ge(L l, R r) { return {std::move(l), std::move(r)}; } template - internal::less_than_t less_than(L l, R r) { + constexpr internal::less_than_t less_than(L l, R r) { return {std::move(l), std::move(r)}; } @@ -6022,12 +6022,12 @@ _EXPORT_SQLITE_ORM namespace sqlite_orm { } template - internal::less_than_t lt(L l, R r) { + constexpr internal::less_than_t lt(L l, R r) { return {std::move(l), std::move(r)}; } template - internal::less_or_equal_t less_or_equal(L l, R r) { + constexpr internal::less_or_equal_t less_or_equal(L l, R r) { return {std::move(l), std::move(r)}; } @@ -6041,7 +6041,7 @@ _EXPORT_SQLITE_ORM namespace sqlite_orm { } template - internal::less_or_equal_t le(L l, R r) { + constexpr internal::less_or_equal_t le(L l, R r) { return {std::move(l), std::move(r)}; } @@ -8211,7 +8211,7 @@ _EXPORT_SQLITE_ORM namespace sqlite_orm { is_operator_argument, is_operator_argument>::value, bool> = true> - add_t, unwrap_expression_t> operator+(L l, R r) { + constexpr add_t, unwrap_expression_t> operator+(L l, R r) { return {get_from_expression(std::forward(l)), get_from_expression(std::forward(r))}; } @@ -8222,7 +8222,7 @@ _EXPORT_SQLITE_ORM namespace sqlite_orm { is_operator_argument, is_operator_argument>::value, bool> = true> - sub_t, unwrap_expression_t> operator-(L l, R r) { + constexpr sub_t, unwrap_expression_t> operator-(L l, R r) { return {get_from_expression(std::forward(l)), get_from_expression(std::forward(r))}; } @@ -8233,7 +8233,7 @@ _EXPORT_SQLITE_ORM namespace sqlite_orm { is_operator_argument, is_operator_argument>::value, bool> = true> - mul_t, unwrap_expression_t> operator*(L l, R r) { + constexpr mul_t, unwrap_expression_t> operator*(L l, R r) { return {get_from_expression(std::forward(l)), get_from_expression(std::forward(r))}; } @@ -8244,7 +8244,7 @@ _EXPORT_SQLITE_ORM namespace sqlite_orm { is_operator_argument, is_operator_argument>::value, bool> = true> - div_t, unwrap_expression_t> operator/(L l, R r) { + constexpr div_t, unwrap_expression_t> operator/(L l, R r) { return {get_from_expression(std::forward(l)), get_from_expression(std::forward(r))}; } @@ -8255,7 +8255,7 @@ _EXPORT_SQLITE_ORM namespace sqlite_orm { is_operator_argument, is_operator_argument>::value, bool> = true> - mod_t, unwrap_expression_t> operator%(L l, R r) { + constexpr mod_t, unwrap_expression_t> operator%(L l, R r) { return {get_from_expression(std::forward(l)), get_from_expression(std::forward(r))}; } } @@ -8323,7 +8323,7 @@ namespace sqlite_orm { std::same_as> || std::convertible_to) && ...) - auto operator()(ExplicitCols... explicitColumns) const; + constexpr auto operator()(ExplicitCols... explicitColumns) const; #else template>, std::is_convertible>...>, bool> = true> - auto operator()(ExplicitCols... explicitColumns) const; + constexpr auto operator()(ExplicitCols... explicitColumns) const; #endif }; } @@ -8736,7 +8736,7 @@ namespace sqlite_orm { expressions_tuple compound; - compound_operator(expressions_tuple compound) : compound{std::move(compound)} { + constexpr compound_operator(expressions_tuple compound) : compound{std::move(compound)} { iterate_tuple(this->compound, [](auto& expression) { expression.highest_level = true; }); @@ -8772,7 +8772,7 @@ namespace sqlite_orm { struct union_t : public compound_operator, union_base { using typename compound_operator::expressions_tuple; - union_t(expressions_tuple compound, bool all) : + constexpr union_t(expressions_tuple compound, bool all) : compound_operator{std::move(compound)}, union_base{all} {} }; @@ -8853,7 +8853,7 @@ namespace sqlite_orm { explicit_colrefs_tuple explicitColumns; expression_type subselect; - common_table_expression(explicit_colrefs_tuple explicitColumns, expression_type subselect) : + constexpr common_table_expression(explicit_colrefs_tuple explicitColumns, expression_type subselect) : explicitColumns{std::move(explicitColumns)}, subselect{std::move(subselect)} { this->subselect.highest_level = true; } @@ -8868,23 +8868,25 @@ namespace sqlite_orm { #if SQLITE_VERSION_NUMBER >= 3035000 && defined(SQLITE_ORM_WITH_CPP20_ALIASES) template = true> - common_table_expression, Select> as(Select sel) && { + constexpr common_table_expression, Select> + as(Select sel) && { return {std::move(this->explicitColumns), std::move(sel)}; } template = true> - common_table_expression, select_t> + constexpr common_table_expression, select_t> as(Compound sel) && { return {std::move(this->explicitColumns), {std::move(sel)}}; } #else template = true> - common_table_expression, Select> as(Select sel) && { + constexpr common_table_expression, Select> as(Select sel) && { return {std::move(this->explicitColumns), std::move(sel)}; } template = true> - common_table_expression, select_t> as(Compound sel) && { + constexpr common_table_expression, select_t> + as(Compound sel) && { return {std::move(this->explicitColumns), {std::move(sel)}}; } #endif @@ -9006,7 +9008,7 @@ namespace sqlite_orm { }; template - void validate_conditions() { + constexpr void validate_conditions() { static_assert(count_tuple::value <= 1, "a single query cannot contain > 1 WHERE blocks"); static_assert(count_tuple::value <= 1, "a single query cannot contain > 1 GROUP BY blocks"); static_assert(count_tuple::value <= 1, "a single query cannot contain > 1 ORDER BY blocks"); @@ -9075,7 +9077,7 @@ _EXPORT_SQLITE_ORM namespace sqlite_orm { * Public function for subselect query. Is useful in UNION queries. */ template - internal::select_t select(T t, Args... args) { + constexpr internal::select_t select(T t, Args... args) { using args_tuple = std::tuple; internal::validate_conditions(); return {std::move(t), {std::forward(args)...}}; @@ -9087,7 +9089,7 @@ _EXPORT_SQLITE_ORM namespace sqlite_orm { * Look through example in examples/union.cpp */ template - internal::union_t union_(E... expressions) { + constexpr internal::union_t union_(E... expressions) { static_assert(sizeof...(E) >= 2, "Compound operators must have at least 2 select statements"); return {{std::forward(expressions)...}, false}; } @@ -9098,7 +9100,7 @@ _EXPORT_SQLITE_ORM namespace sqlite_orm { * Look through example in examples/union.cpp */ template - internal::union_t union_all(E... expressions) { + constexpr internal::union_t union_all(E... expressions) { static_assert(sizeof...(E) >= 2, "Compound operators must have at least 2 select statements"); return {{std::forward(expressions)...}, true}; } @@ -9109,13 +9111,13 @@ _EXPORT_SQLITE_ORM namespace sqlite_orm { * Look through example in examples/except.cpp */ template - internal::except_t except(E... expressions) { + constexpr internal::except_t except(E... expressions) { static_assert(sizeof...(E) >= 2, "Compound operators must have at least 2 select statements"); return {{std::forward(expressions)...}}; } template - internal::intersect_t intersect(E... expressions) { + constexpr internal::intersect_t intersect(E... expressions) { static_assert(sizeof...(E) >= 2, "Compound operators must have at least 2 select statements"); return {{std::forward(expressions)...}}; } @@ -9169,7 +9171,7 @@ _EXPORT_SQLITE_ORM namespace sqlite_orm { std::is_same>, std::is_convertible>...>, bool> = true> - auto cte(ExplicitCols... explicitColumns) { + constexpr auto cte(ExplicitCols... explicitColumns) { using namespace ::sqlite_orm::internal; static_assert(is_cte_moniker_v, "Moniker must be a CTE moniker"); static_assert((!is_builtin_numeric_column_alias_v && ...), @@ -9187,7 +9189,7 @@ _EXPORT_SQLITE_ORM namespace sqlite_orm { std::same_as> || std::convertible_to) && ...) - auto cte(ExplicitCols... explicitColumns) { + constexpr auto cte(ExplicitCols... explicitColumns) { using namespace ::sqlite_orm::internal; static_assert((!is_builtin_numeric_column_alias_v && ...), "Numeric column aliases are reserved for referencing columns locally within a single CTE."); @@ -9206,7 +9208,7 @@ _EXPORT_SQLITE_ORM namespace sqlite_orm { std::same_as> || std::convertible_to) && ...) - auto cte_moniker::operator()(ExplicitCols... explicitColumns) const { + constexpr auto cte_moniker::operator()(ExplicitCols... explicitColumns) const { return cte>(std::forward(explicitColumns)...); } #else @@ -9218,7 +9220,7 @@ _EXPORT_SQLITE_ORM namespace sqlite_orm { std::is_same>, std::is_convertible>...>, bool>> - auto cte_moniker::operator()(ExplicitCols... explicitColumns) const { + constexpr auto cte_moniker::operator()(ExplicitCols... explicitColumns) const { return cte>(std::forward(explicitColumns)...); } #endif @@ -9356,7 +9358,7 @@ _EXPORT_SQLITE_ORM namespace sqlite_orm { * If you need to fetch results as objects instead of tuples please use `object()`. */ template - internal::asterisk_t asterisk(bool definedOrder = false) { + constexpr internal::asterisk_t asterisk(bool definedOrder = false) { return {definedOrder}; } @@ -9368,7 +9370,7 @@ _EXPORT_SQLITE_ORM namespace sqlite_orm { * storage.select(asterisk(), inner_join(on(m->*&Employee::reportsTo == &Employee::employeeId))); */ template - auto asterisk(bool definedOrder = false) { + constexpr auto asterisk(bool definedOrder = false) { return asterisk>(definedOrder); } #endif @@ -9385,13 +9387,13 @@ _EXPORT_SQLITE_ORM namespace sqlite_orm { * If you need to fetch results as tuples instead of objects please use `asterisk()`. */ template - internal::object_t object(bool definedOrder = false) { + constexpr internal::object_t object(bool definedOrder = false) { return {definedOrder}; } #ifdef SQLITE_ORM_WITH_CPP20_ALIASES template - auto object(bool definedOrder = false) { + constexpr auto object(bool definedOrder = false) { return object>(definedOrder); } #endif @@ -14132,7 +14134,8 @@ namespace sqlite_orm { void push_back(assign_t assign) { auto newContext = this->context; newContext.skip_table_name = true; - iterate_ast(assign, this->collector); + // note: we are only interested in the table name on the left-hand side of the assignment operator expression + iterate_ast(assign.lhs, this->collector); std::stringstream ss; ss << serialize(assign.lhs, newContext) << ' ' << assign.serialize() << ' ' << serialize(assign.rhs, context); @@ -14315,6 +14318,12 @@ namespace sqlite_orm { conditions_type conditions; }; + template + SQLITE_ORM_INLINE_VAR constexpr bool is_update_all_v = polyfill::is_specialization_of::value; + + template + using is_update_all = polyfill::bool_constant>; + template struct remove_all_t { using type = T; @@ -14323,6 +14332,12 @@ namespace sqlite_orm { conditions_type conditions; }; + template + SQLITE_ORM_INLINE_VAR constexpr bool is_remove_all_v = polyfill::is_specialization_of::value; + + template + using is_remove_all = polyfill::bool_constant>; + template struct get_t { using type = T; @@ -20795,7 +20810,10 @@ namespace sqlite_orm { template std::set> collect_table_names(const set_t& set, const Ctx& ctx) { auto collector = make_table_name_collector(ctx.db_objects); - iterate_ast(set, collector); + // note: we are only interested in the table name on the left-hand side of the assignment operator expression + iterate_tuple(set.assigns, [&collector](const auto& assignmentOperator) { + iterate_ast(assignmentOperator.lhs, collector); + }); return std::move(collector.table_names); } @@ -20808,8 +20826,7 @@ namespace sqlite_orm { template = true> std::set> collect_table_names(const T& sel, const Ctx& ctx) { auto collector = make_table_name_collector(ctx.db_objects); - iterate_ast(sel.col, collector); - iterate_ast(sel.conditions, collector); + iterate_ast(sel, collector); return std::move(collector.table_names); } @@ -23406,7 +23423,12 @@ namespace sqlite_orm { #if(SQLITE_VERSION_NUMBER >= 3008003) && defined(SQLITE_ORM_WITH_CTE) template, is_insert_raw>, bool> = true> + std::enable_if_t, + is_insert_raw, + is_replace_raw, + is_update_all, + is_remove_all>, + bool> = true> prepared_statement_t> prepare(with_t sel) { return this->prepare_impl>(std::move(sel)); } @@ -23533,7 +23555,12 @@ namespace sqlite_orm { } #if(SQLITE_VERSION_NUMBER >= 3008003) && defined(SQLITE_ORM_WITH_CTE) - template = true> + template< + class... CTEs, + class E, + std::enable_if_t< + polyfill::disjunction_v, is_replace_raw, is_update_all, is_remove_all>, + bool> = true> void execute(const prepared_statement_t>& statement) { sqlite3_stmt* stmt = reset_stmt(statement.stmt); iterate_ast(statement.expression, conditional_binder{stmt}); @@ -24076,6 +24103,8 @@ _EXPORT_SQLITE_ORM namespace sqlite_orm { // #include "../schema/table.h" +// #include "../column_pointer.h" + _EXPORT_SQLITE_ORM namespace sqlite_orm { #ifdef SQLITE_ENABLE_DBSTAT_VTAB struct dbstat { @@ -24104,6 +24133,10 @@ _EXPORT_SQLITE_ORM namespace sqlite_orm { make_column("pgoffset", &dbstat::pgoffset), make_column("pgsize", &dbstat::pgsize)); } + +#ifdef SQLITE_ORM_WITH_CPP20_ALIASES + inline constexpr orm_table_reference auto dbstat_table = c(); +#endif #endif // SQLITE_ENABLE_DBSTAT_VTAB } diff --git a/tests/builtin_tables.cpp b/tests/builtin_tables.cpp index 41fe960a..e82d8b7a 100644 --- a/tests/builtin_tables.cpp +++ b/tests/builtin_tables.cpp @@ -50,6 +50,10 @@ TEST_CASE("builtin tables") { auto dbstatRows = storage.get_all(); std::ignore = dbstatRows; + +#ifdef SQLITE_ORM_WITH_CPP20_ALIASES + dbstatRows = storage.get_all(); +#endif } #endif // SQLITE_ENABLE_DBSTAT_VTAB } diff --git a/tests/prepared_statement_tests/get_all.cpp b/tests/prepared_statement_tests/get_all.cpp index ff7dd3d1..26906a12 100644 --- a/tests/prepared_statement_tests/get_all.cpp +++ b/tests/prepared_statement_tests/get_all.cpp @@ -217,8 +217,8 @@ TEST_CASE("Prepared get all") { } #ifdef SQLITE_ORM_WITH_CPP20_ALIASES SECTION("from table reference") { - constexpr auto schema = c(); - auto statement = storage.prepare(get_all(where(schema->*&sqlite_master::type == "table"))); + auto statement = + storage.prepare(get_all(where(sqlite_master_table->*&sqlite_master::type == "table"))); auto str = storage.dump(statement); testSerializing(statement); } diff --git a/tests/statement_serializer_tests/statements/insert_replace.cpp b/tests/statement_serializer_tests/statements/insert_replace.cpp index e30be740..b3882fe2 100644 --- a/tests/statement_serializer_tests/statements/insert_replace.cpp +++ b/tests/statement_serializer_tests/statements/insert_replace.cpp @@ -80,6 +80,23 @@ TEST_CASE("statement_serializer insert/replace") { expected = R"(REPLACE INTO "users" SELECT "users_backup"."id", "users_backup"."name" FROM "users_backup")"; } +#if(SQLITE_VERSION_NUMBER >= 3008003) && defined(SQLITE_ORM_WITH_CTE) +#ifdef SQLITE_ORM_WITH_CPP20_ALIASES + SECTION("With clause") { + constexpr orm_cte_moniker auto data = "data"_cte; + constexpr auto cteExpression = cte().as(select(asterisk())); + auto dbObjects2 = + internal::db_objects_cat(dbObjects, internal::make_cte_table(dbObjects, cteExpression)); + using context_t = internal::serializer_context; + context_t context2{dbObjects2}; + + auto expression = with(cteExpression, replace(into(), select(asterisk()))); + value = serialize(expression, context2); + expected = + R"(WITH "data"("id", "name") AS (SELECT "users_backup".* FROM "users_backup") REPLACE INTO "users" SELECT "data".* FROM "data")"; + } +#endif +#endif } SECTION("range") { context.replace_bindable_with_question = false; @@ -356,6 +373,23 @@ TEST_CASE("statement_serializer insert/replace") { R"(INSERT OR ROLLBACK INTO "users" SELECT "users_backup"."id", "users_backup"."name" FROM "users_backup")"; } } + SECTION("With clause") { +#if(SQLITE_VERSION_NUMBER >= 3008003) && defined(SQLITE_ORM_WITH_CTE) +#ifdef SQLITE_ORM_WITH_CPP20_ALIASES + constexpr orm_cte_moniker auto data = "data"_cte; + constexpr auto cteExpression = cte().as(select(asterisk())); + auto dbObjects2 = + internal::db_objects_cat(dbObjects, internal::make_cte_table(dbObjects, cteExpression)); + using context_t = internal::serializer_context; + context_t context2{dbObjects2}; + + auto expression = with(cteExpression, insert(into(), select(asterisk()))); + value = serialize(expression, context2); + expected = + R"(WITH "data"("id", "name") AS (SELECT "users_backup".* FROM "users_backup") INSERT INTO "users" SELECT "data".* FROM "data")"; +#endif +#endif + } } SECTION("range") { context.replace_bindable_with_question = false; diff --git a/tests/statement_serializer_tests/statements/remove_all.cpp b/tests/statement_serializer_tests/statements/remove_all.cpp index 1bfd6c3c..ba30b9c0 100644 --- a/tests/statement_serializer_tests/statements/remove_all.cpp +++ b/tests/statement_serializer_tests/statements/remove_all.cpp @@ -19,19 +19,35 @@ TEST_CASE("statement_serializer remove_all") { std::string expected; SECTION("all") { - auto statement = remove_all(); - value = serialize(statement, context); + auto expression = remove_all(); + value = serialize(expression, context); expected = R"(DELETE FROM "users")"; } SECTION("where") { - auto statement = remove_all(where(&User::id == c(1))); - value = serialize(statement, context); + auto expression = remove_all(where(&User::id == c(1))); + value = serialize(expression, context); expected = R"(DELETE FROM "users" WHERE ("id" = 1))"; } SECTION("conditions") { - auto statement = remove_all(where(&User::id == c(1)), limit(1)); - value = serialize(statement, context); + auto expression = remove_all(where(&User::id == c(1)), limit(1)); + value = serialize(expression, context); expected = R"(DELETE FROM "users" WHERE ("id" = 1) LIMIT 1)"; } +#if(SQLITE_VERSION_NUMBER >= 3008003) && defined(SQLITE_ORM_WITH_CTE) +#ifdef SQLITE_ORM_WITH_CPP20_ALIASES + SECTION("With clause") { + constexpr orm_cte_moniker auto data = "data"_cte; + constexpr auto cteExpression = cte().as(select(1)); + auto dbObjects2 = internal::db_objects_cat(dbObjects, internal::make_cte_table(dbObjects, cteExpression)); + using context_t = internal::serializer_context; + context_t context2{dbObjects2}; + + auto expression = with(cteExpression, remove_all(where(c(&User::id).in(select(data->*1_colalias))))); + value = serialize(expression, context2); + expected = + R"(WITH "data"("1") AS (SELECT 1) DELETE FROM "users" WHERE ("id" IN (SELECT "data"."1" FROM "data")))"; + } +#endif +#endif REQUIRE(value == expected); } diff --git a/tests/statement_serializer_tests/statements/update_all.cpp b/tests/statement_serializer_tests/statements/update_all.cpp index 4110a1db..006255c8 100644 --- a/tests/statement_serializer_tests/statements/update_all.cpp +++ b/tests/statement_serializer_tests/statements/update_all.cpp @@ -51,10 +51,33 @@ TEST_CASE("statement_serializer update_all") { using context_t = internal::serializer_context; context_t context{dbObjects}; - auto statement = - update_all(set(c(&Contact::phone) = select(&Customer::phone, from(), where(c(&Customer::id) == 1)))); - auto value = serialize(statement, context); - decltype(value) expected = - R"(UPDATE "contacts" SET "phone" = (SELECT "customers"."Phone" FROM "customers" WHERE ("customers"."CustomerId" = 1)))"; + std::string value; + std::string expected; + SECTION("select") { + auto expression = update_all(set(c(&Contact::phone) = select(&Customer::phone, where(c(&Customer::id) == 1))), + where(c(&Contact::id) == 1)); + value = serialize(expression, context); + expected = + R"(UPDATE "contacts" SET "phone" = (SELECT "customers"."Phone" FROM "customers" WHERE ("customers"."CustomerId" = 1)) WHERE ("contact_id" = 1))"; + } +#if(SQLITE_VERSION_NUMBER >= 3008003) && defined(SQLITE_ORM_WITH_CTE) +#ifdef SQLITE_ORM_WITH_CPP20_ALIASES + SECTION("With clause") { + constexpr orm_cte_moniker auto data = "data"_cte; + constexpr auto cteExpression = cte().as(select(&Customer::phone, where(c(&Customer::id) == 1))); + auto dbObjects2 = internal::db_objects_cat(dbObjects, internal::make_cte_table(dbObjects, cteExpression)); + using context_t = internal::serializer_context; + context_t context2{dbObjects2}; + + auto expression = + with(cteExpression, + update_all(set(c(&Contact::phone) = select(data->*&Customer::phone)), where(c(&Contact::id) == 1))); + + value = serialize(expression, context2); + expected = + R"(WITH "data"("Phone") AS (SELECT "customers"."Phone" FROM "customers" WHERE ("customers"."CustomerId" = 1)) UPDATE "contacts" SET "phone" = (SELECT "data"."Phone" FROM "data") WHERE ("contact_id" = 1))"; + } +#endif +#endif REQUIRE(value == expected); } diff --git a/tests/storage_tests.cpp b/tests/storage_tests.cpp index e9e2244a..b241d78e 100644 --- a/tests/storage_tests.cpp +++ b/tests/storage_tests.cpp @@ -583,7 +583,7 @@ TEST_CASE("With clause") { } #ifdef SQLITE_ORM_WITH_CPP20_ALIASES - SECTION("insert") { + SECTION("crud") { struct Object { int id; }; @@ -592,10 +592,24 @@ TEST_CASE("With clause") { storage.sync_schema(); - constexpr auto data = "data"_cte; - storage.with(cte().as(select(2)), - insert(into(), columns(&Object::id), select(data->*1_colalias))); - REQUIRE(2 == storage.last_insert_rowid()); + constexpr orm_cte_moniker auto data = "data"_cte; + constexpr auto cteExpression = cte().as(union_all(select(2), select(3))); + + storage.with(cteExpression, insert(into(), columns(&Object::id), select(data->*1_colalias))); + REQUIRE(3 == storage.last_insert_rowid()); + + storage.with(cteExpression, replace(into(), columns(&Object::id), select(data->*1_colalias))); + REQUIRE(storage.changes() == 2); + + storage.with( + cteExpression, + update_all( + set(c(&Object::id) = select(data->*1_colalias, from(), where(data->*1_colalias == &Object::id))), + where(c(&Object::id).in(select(data->*1_colalias))))); + REQUIRE(storage.changes() == 2); + + storage.with(cteExpression, remove_all(where(c(&Object::id).in(select(data->*1_colalias))))); + REQUIRE(storage.changes() == 2); } #endif }