diff --git a/.gitignore b/.gitignore index f5cff1a34..1876c6a58 100644 --- a/.gitignore +++ b/.gitignore @@ -6,3 +6,4 @@ cmake-build-debug/ .idea/ /compile +build diff --git a/dev/ast/match.h b/dev/ast/match.h new file mode 100644 index 000000000..5fa58f1e7 --- /dev/null +++ b/dev/ast/match.h @@ -0,0 +1,22 @@ +#pragma once + +namespace sqlite_orm { + namespace internal { + + template + struct match_t { + using mapped_type = T; + using argument_type = X; + + argument_type argument; + + match_t(argument_type argument): argument(std::move(argument)) {} + }; + } + + template + internal::match_t match(X argument) { + return {std::move(argument)}; + } + +} \ No newline at end of file diff --git a/dev/ast_iterator.h b/dev/ast_iterator.h index bdef0d0f4..bd0135282 100644 --- a/dev/ast_iterator.h +++ b/dev/ast_iterator.h @@ -20,6 +20,7 @@ #include "ast/group_by.h" #include "ast/exists.h" #include "ast/set.h" +#include "ast/match.h" namespace sqlite_orm { @@ -141,9 +142,19 @@ namespace sqlite_orm { using node_type = binary_operator; template - void operator()(const node_type& binaryOperator, C& lambda) const { - iterate_ast(binaryOperator.lhs, lambda); - iterate_ast(binaryOperator.rhs, lambda); + void operator()(const node_type& node, C& lambda) const { + iterate_ast(node.lhs, lambda); + iterate_ast(node.rhs, lambda); + } + }; + + template + struct ast_iterator, void> { + using node_type = is_equal_with_table_t; + + template + void operator()(const node_type& node, C& lambda) const { + iterate_ast(node.rhs, lambda); } }; @@ -212,6 +223,16 @@ namespace sqlite_orm { } }; + template + struct ast_iterator, void> { + using node_type = match_t; + + template + void operator()(const node_type& node, L& lambda) const { + iterate_ast(node.argument, lambda); + } + }; + template struct ast_iterator, void> { using node_type = into_t; diff --git a/dev/column_names_getter.h b/dev/column_names_getter.h index b35a4e359..63ea1082a 100644 --- a/dev/column_names_getter.h +++ b/dev/column_names_getter.h @@ -21,8 +21,8 @@ namespace sqlite_orm { namespace internal { - template - std::string serialize(const T&, const serializer_context&); + template + std::string serialize(const T& t, const C& context); template std::vector& collect_table_column_names(std::vector& collectedExpressions, diff --git a/dev/conditions.h b/dev/conditions.h index 496705ea8..980c7979f 100644 --- a/dev/conditions.h +++ b/dev/conditions.h @@ -210,6 +210,16 @@ namespace sqlite_orm { } }; + template + struct is_equal_with_table_t: negatable_t { + using left_type = L; + using right_type = R; + + right_type rhs; + + is_equal_with_table_t(right_type rhs): rhs(std::move(rhs)) {} + }; + struct is_not_equal_string { operator std::string() const { return "!="; @@ -1085,6 +1095,11 @@ namespace sqlite_orm { return {std::move(l), std::move(r)}; } + template + 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) { return {std::move(l), std::move(r)}; diff --git a/dev/default_value_extractor.h b/dev/default_value_extractor.h index ae8d90e20..071a20387 100644 --- a/dev/default_value_extractor.h +++ b/dev/default_value_extractor.h @@ -10,8 +10,8 @@ namespace sqlite_orm { namespace internal { - template - std::string serialize(const T&, const serializer_context&); + template + std::string serialize(const T& t, const C& context); /** * Serialize default value of a column's default valu diff --git a/dev/eponymous_vtabs/dbstat.h b/dev/eponymous_vtabs/dbstat.h index 7ac28a428..723b8d846 100644 --- a/dev/eponymous_vtabs/dbstat.h +++ b/dev/eponymous_vtabs/dbstat.h @@ -5,7 +5,7 @@ #endif #include "../column.h" -#include "../table.h" +#include "../schema/table.h" namespace sqlite_orm { #ifdef SQLITE_ENABLE_DBSTAT_VTAB diff --git a/dev/implementations/table_definitions.h b/dev/implementations/table_definitions.h index e94c50fdd..4f6a18928 100644 --- a/dev/implementations/table_definitions.h +++ b/dev/implementations/table_definitions.h @@ -10,7 +10,7 @@ #include "../functional/cxx_universal.h" // ::size_t #include "../type_printer.h" #include "../column.h" -#include "../table.h" +#include "../schema/table.h" namespace sqlite_orm { namespace internal { diff --git a/dev/node_tuple.h b/dev/node_tuple.h index b86c3eda5..53b7ad37b 100644 --- a/dev/node_tuple.h +++ b/dev/node_tuple.h @@ -20,9 +20,9 @@ #include "ast/where.h" #include "ast/into.h" #include "ast/group_by.h" +#include "ast/match.h" namespace sqlite_orm { - namespace internal { template @@ -89,6 +89,9 @@ namespace sqlite_orm { template struct node_tuple, void> : node_tuple {}; + template + struct node_tuple, void> : node_tuple {}; + template struct node_tuple> { using node_type = T; @@ -158,6 +161,9 @@ namespace sqlite_orm { template struct node_tuple, void> : node_tuple {}; + template + struct node_tuple, void> : node_tuple {}; + template struct node_tuple, void> { using type = tuple_cat_t...>; diff --git a/dev/index.h b/dev/schema/index.h similarity index 100% rename from dev/index.h rename to dev/schema/index.h diff --git a/dev/table.h b/dev/schema/table.h similarity index 70% rename from dev/table.h rename to dev/schema/table.h index b2574d1d7..527b2d478 100644 --- a/dev/table.h +++ b/dev/schema/table.h @@ -116,25 +116,6 @@ namespace sqlite_orm { return result; } - template - bool exists_in_composite_primary_key(const column_field& column) const { - bool res = false; - this->for_each_primary_key([&column, &res](auto& primaryKey) { - using colrefs_tuple = decltype(primaryKey.columns); - using same_type_index_sequence = - filter_tuple_sequence_t>::template fn, - member_field_type_t>; - iterate_tuple(primaryKey.columns, same_type_index_sequence{}, [&res, &column](auto& memberPointer) { - if(compare_any(memberPointer, column.member_pointer) || - compare_any(memberPointer, column.setter)) { - res = true; - } - }); - }); - return res; - } - /** * Call passed lambda with all defined primary keys. */ @@ -284,6 +265,128 @@ namespace sqlite_orm { template struct is_table> : std::true_type {}; + + template + struct virtual_table_t: basic_table { + using module_details_type = M; + using object_type = typename module_details_type::object_type; + using elements_type = typename module_details_type::columns_type; + + static constexpr bool is_without_rowid_v = false; + using is_without_rowid = polyfill::bool_constant; + + module_details_type module_details; + + virtual_table_t(std::string name, module_details_type module_details): + basic_table{std::move(name)}, module_details{std::move(module_details)} {} + + /** + * Call passed lambda with columns not having the specified constraint trait `OpTrait`. + * @param lambda Lambda called for each column. + */ + template class OpTraitFn, class L> + void for_each_column_excluding(L&& lambda) const { + this->module_details.template for_each_column_excluding(lambda); + } + + /** + * Call passed lambda with columns not having the specified constraint trait `OpTrait`. + * @param lambda Lambda called for each column. + */ + template = true> + void for_each_column_excluding(L&& lambda) const { + this->module_details.template for_each_column_excluding(lambda); + } + + /** + * Call passed lambda with all defined columns. + * @param lambda Lambda called for each column. Function signature: `void(auto& column)` + */ + template + void for_each_column(L&& lambda) const { + this->module_details.for_each_column(lambda); + } + }; + + template + struct is_virtual_table : std::false_type {}; + + template + struct is_virtual_table> : std::true_type {}; + + template + struct using_fts5_t { + using object_type = T; + using columns_type = std::tuple; + + columns_type columns; + + using_fts5_t(columns_type columns): columns(std::move(columns)) {} + + /** + * Call passed lambda with columns not having the specified constraint trait `OpTrait`. + * @param lambda Lambda called for each column. + */ + template class OpTraitFn, class L> + void for_each_column_excluding(L&& lambda) const { + iterate_tuple(this->columns, col_index_sequence_excluding{}, lambda); + } + + /** + * Call passed lambda with columns not having the specified constraint trait `OpTrait`. + * @param lambda Lambda called for each column. + */ + template = true> + void for_each_column_excluding(L&& lambda) const { + this->for_each_column_excluding(lambda); + } + + /** + * Call passed lambda with all defined columns. + * @param lambda Lambda called for each column. Function signature: `void(auto& column)` + */ + template + void for_each_column(L&& lambda) const { + using col_index_sequence = filter_tuple_sequence_t; + iterate_tuple(this->columns, col_index_sequence{}, lambda); + } + }; + + template + bool exists_in_composite_primary_key(const table_t &table, const column_field& column) { + bool res = false; + table.for_each_primary_key([&column, &res](auto& primaryKey) { + using colrefs_tuple = decltype(primaryKey.columns); + using same_type_index_sequence = + filter_tuple_sequence_t>::template fn, + member_field_type_t>; + iterate_tuple(primaryKey.columns, same_type_index_sequence{}, [&res, &column](auto& memberPointer) { + if(compare_any(memberPointer, column.member_pointer) || + compare_any(memberPointer, column.setter)) { + res = true; + } + }); + }); + return res; + } + + template + bool exists_in_composite_primary_key(const virtual_table_t &virtualTable, const column_field& column) { + return false; + } + } + + template>::object_type> + internal::using_fts5_t using_fts5(Cs... columns) { + SQLITE_ORM_CLANG_SUPPRESS_MISSING_BRACES( + return {std::make_tuple(std::forward(columns)...)}); + } + + template + internal::using_fts5_t using_fts5(Cs... columns) { + SQLITE_ORM_CLANG_SUPPRESS_MISSING_BRACES( + return {std::make_tuple(std::forward(columns)...)}); } /** @@ -307,4 +410,9 @@ namespace sqlite_orm { SQLITE_ORM_CLANG_SUPPRESS_MISSING_BRACES( return {std::move(name), std::make_tuple(std::forward(args)...)}); } + + template + internal::virtual_table_t make_virtual_table(std::string name, M module_details) { + return internal::virtual_table_t(std::move(name), std::move(module_details)); + } } diff --git a/dev/triggers.h b/dev/schema/triggers.h similarity index 99% rename from dev/triggers.h rename to dev/schema/triggers.h index c85e65a13..a090c4015 100644 --- a/dev/triggers.h +++ b/dev/schema/triggers.h @@ -5,8 +5,8 @@ #include #include -#include "functional/cxx_universal.h" -#include "optional_container.h" +#include "../functional/cxx_universal.h" +#include "../optional_container.h" // NOTE Idea : Maybe also implement a custom trigger system to call a c++ callback when a trigger triggers ? // (Could be implemented with a normal trigger that insert or update an internal table and then retreive diff --git a/dev/serializer_context.h b/dev/serializer_context.h index 8536f3d9f..ee259e0dd 100644 --- a/dev/serializer_context.h +++ b/dev/serializer_context.h @@ -19,6 +19,18 @@ namespace sqlite_orm { serializer_context(const db_objects_type& dbObjects) : db_objects{dbObjects} {} }; + template + struct serializer_context_with_no_types_and_constraints: serializer_context { + using super = serializer_context; + + serializer_context_with_no_types_and_constraints(const super &parentContext): super(parentContext) {} + }; + + template + serializer_context_with_no_types_and_constraints make_serializer_context_with_no_types_and_constraints(const serializer_context &parentContext) { + return {parentContext}; + } + template struct serializer_context_builder { using storage_type = S; @@ -33,6 +45,11 @@ namespace sqlite_orm { const storage_type& storage; }; + template + struct no_need_types_and_constraints: std::false_type {}; + + template + struct no_need_types_and_constraints>: std::true_type {}; } } diff --git a/dev/serializing_util.h b/dev/serializing_util.h index ef7dca0c0..8699ab743 100644 --- a/dev/serializing_util.h +++ b/dev/serializing_util.h @@ -20,8 +20,8 @@ namespace sqlite_orm { template struct order_by_t; - template - std::string serialize(const T&, const serializer_context&); + template + std::string serialize(const T& t, const C& context); template std::string serialize_order_by(const T&, const Ctx&); @@ -369,7 +369,7 @@ namespace sqlite_orm { ss << serialize(constraint, context) << ' '; }); if(isNotNull) { - ss << "NOT NULL "; + ss << "NOT NULL"; } return ss; diff --git a/dev/sqlite_schema_table.h b/dev/sqlite_schema_table.h index d84a6c030..1ddb2520a 100644 --- a/dev/sqlite_schema_table.h +++ b/dev/sqlite_schema_table.h @@ -3,7 +3,7 @@ #include // std::string #include "column.h" -#include "table.h" +#include "schema/table.h" #include "alias.h" namespace sqlite_orm { diff --git a/dev/statement_serializer.h b/dev/statement_serializer.h index 9eabff768..7b3008aea 100644 --- a/dev/statement_serializer.h +++ b/dev/statement_serializer.h @@ -21,6 +21,7 @@ #include "ast/excluded.h" #include "ast/group_by.h" #include "ast/into.h" +#include "ast/match.h" #include "core_functions.h" #include "constraints.h" #include "conditions.h" @@ -39,9 +40,9 @@ #include "serializing_util.h" #include "statement_binder.h" #include "values.h" -#include "triggers.h" +#include "schema/triggers.h" #include "table_type_of.h" -#include "index.h" +#include "schema/index.h" #include "util.h" namespace sqlite_orm { @@ -51,8 +52,8 @@ namespace sqlite_orm { template struct statement_serializer; - template - std::string serialize(const T& t, const serializer_context& context) { + template + std::string serialize(const T& t, const C& context) { statement_serializer serializer; return serializer(t, context); } @@ -405,12 +406,27 @@ namespace sqlite_orm { using statement_type = table__rowid_t; template - std::string operator()(const statement_type& s, const Ctx& context) const { + std::string operator()(const statement_type& statement, const Ctx& context) const { std::stringstream ss; if(!context.skip_table_name) { ss << streaming_identifier(lookup_table_name(context.db_objects)) << "."; } - ss << static_cast(s); + ss << static_cast(statement); + return ss.str(); + } + }; + + template + struct statement_serializer, void> { + using statement_type = is_equal_with_table_t; + + template + std::string operator()(const statement_type& statement, const Ctx& context) const { + std::stringstream ss; + const auto tableName = lookup_table_name(context.db_objects); + ss << streaming_identifier(tableName); + ss << " = "; + ss << serialize(statement.rhs, context); return ss.str(); } }; @@ -942,12 +958,17 @@ namespace sqlite_orm { using column_type = statement_type; std::stringstream ss; - ss << streaming_identifier(column.name) << " " << type_printer>().print() - << " " - << streaming_column_constraints( - call_as_template_base(polyfill::identity{})(column), - column.is_not_null(), - context); + ss << streaming_identifier(column.name); + if (!no_need_types_and_constraints::value) { + ss << " " << type_printer>().print(); + auto constraintsTuple = streaming_column_constraints( + call_as_template_base(polyfill::identity{})(column), + column.is_not_null(), + context); + if (std::tuple_size::value > 0) { + ss << " " << constraintsTuple; + } + } return ss.str(); } }; @@ -1033,7 +1054,7 @@ namespace sqlite_orm { ss << "UPDATE " << streaming_identifier(table.name) << " SET "; table.template for_each_column_excluding>( [&table, &ss, &context, &object = get_ref(statement.object), first = true](auto& column) mutable { - if(table.exists_in_composite_primary_key(column)) { + if(exists_in_composite_primary_key(table, column)) { return; } @@ -1044,7 +1065,7 @@ namespace sqlite_orm { ss << " WHERE "; table.for_each_column( [&table, &context, &ss, &object = get_ref(statement.object), first = true](auto& column) mutable { - if(!column.template is() && !table.exists_in_composite_primary_key(column)) { + if(!column.template is() && !exists_in_composite_primary_key(table, column)) { return; } @@ -1150,7 +1171,7 @@ namespace sqlite_orm { mpl::conjunction>, mpl::disjunction_fn>>( [&table, &columnNames](auto& column) { - if(table.exists_in_composite_primary_key(column)) { + if(exists_in_composite_primary_key(table, column)) { return; } @@ -1172,7 +1193,7 @@ namespace sqlite_orm { mpl::conjunction>, mpl::disjunction_fn>{}, [&table](auto& column) { - return table.exists_in_composite_primary_key(column); + return exists_in_composite_primary_key(table, column); }, context, get_ref(statement.object)) @@ -1183,6 +1204,19 @@ namespace sqlite_orm { } }; + template + struct statement_serializer, void> { + using statement_type = match_t; + + template + std::string operator()(const statement_type &statement, const Ctx& context) const { + auto& table = pick_table(context.db_objects); + std::stringstream ss; + ss << streaming_identifier(table.name) << " MATCH " << serialize(statement.argument, context); + return ss.str(); + } + }; + template struct statement_serializer, void> { using statement_type = into_t; @@ -1312,7 +1346,7 @@ namespace sqlite_orm { mpl::conjunction>, mpl::disjunction_fn>>( [&table, &columnNames](auto& column) { - if(table.exists_in_composite_primary_key(column)) { + if(exists_in_composite_primary_key(table, column)) { return; } @@ -1543,6 +1577,34 @@ namespace sqlite_orm { } }; + template + struct statement_serializer, void> { + using statement_type = using_fts5_t; + + template + std::string operator()(const statement_type& statement, const Ctx& context) const { + std::stringstream ss; + ss << "USING FTS5("; + auto subContext = make_serializer_context_with_no_types_and_constraints(context); + ss << streaming_expressions_tuple(statement.columns, subContext) << ")"; + return ss.str(); + } + }; + + template + struct statement_serializer, void> { + using statement_type = virtual_table_t; + + template + std::string operator()(const statement_type& statement, const Ctx& context) const { + std::stringstream ss; + ss << "CREATE VIRTUAL TABLE IF NOT EXISTS "; + ss << streaming_identifier(statement.name) << ' '; + ss << serialize(statement.module_details, context); + return ss.str(); + } + }; + template struct statement_serializer, void> { using statement_type = index_t; diff --git a/dev/storage.h b/dev/storage.h index 5cc8e196b..fcad5d0f6 100644 --- a/dev/storage.h +++ b/dev/storage.h @@ -45,11 +45,11 @@ #include "prepared_statement.h" #include "expression_object_type.h" #include "statement_serializer.h" -#include "triggers.h" +#include "schema/triggers.h" #include "object_from_column_builder.h" -#include "table.h" +#include "schema/table.h" #include "column.h" -#include "index.h" +#include "schema/index.h" #include "util.h" #include "serializing_util.h" @@ -913,6 +913,16 @@ namespace sqlite_orm { return res; } + template + sync_schema_result sync_table(const virtual_table_t& virtualTable, sqlite3* db, bool) { + auto res = sync_schema_result::already_in_sync; + using context_t = serializer_context; + context_t context{this->db_objects}; + auto query = serialize(virtualTable, context); + perform_void_exec(db, query); + return res; + } + template sync_schema_result sync_table(const index_t& index, sqlite3* db, bool) { auto res = sync_schema_result::already_in_sync; @@ -928,7 +938,8 @@ namespace sqlite_orm { auto res = sync_schema_result::already_in_sync; // TODO Change accordingly using context_t = serializer_context; context_t context{this->db_objects}; - perform_void_exec(db, serialize(trigger, context)); + auto query = serialize(trigger, context); + perform_void_exec(db, query); return res; } @@ -1210,7 +1221,7 @@ namespace sqlite_orm { mpl::conjunction>, mpl::disjunction_fn>>( call_as_template_base([&table, &bindValue, &object](auto& column) { - if(!table.exists_in_composite_primary_key(column)) { + if(!exists_in_composite_primary_key(table, column)) { bindValue(polyfill::invoke(column.member_pointer, object)); } })); @@ -1262,12 +1273,12 @@ namespace sqlite_orm { auto& object = get_object(statement.expression); table.template for_each_column_excluding>( call_as_template_base([&table, &bindValue, &object](auto& column) { - if(!table.exists_in_composite_primary_key(column)) { + if(!exists_in_composite_primary_key(table, column)) { bindValue(polyfill::invoke(column.member_pointer, object)); } })); table.for_each_column([&table, &bindValue, &object](auto& column) { - if(column.template is() || table.exists_in_composite_primary_key(column)) { + if(column.template is() || exists_in_composite_primary_key(table, column)) { bindValue(polyfill::invoke(column.member_pointer, object)); } }); diff --git a/include/sqlite_orm/sqlite_orm.h b/include/sqlite_orm/sqlite_orm.h index 2e440a4ab..eb13eb682 100644 --- a/include/sqlite_orm/sqlite_orm.h +++ b/include/sqlite_orm/sqlite_orm.h @@ -10,6 +10,7 @@ __pragma(push_macro("max")) // #include "cxx_universal.h" + /* * This header makes central C++ functionality on which sqlite_orm depends universally available: * - alternative operator representations @@ -28,6 +29,7 @@ using std::nullptr_t; // #include "cxx_core_features.h" + /* * This header detects core C++ language features on which sqlite_orm depends. * May be updated/overwritten by cxx_compiler_quirks.h @@ -108,6 +110,7 @@ using std::nullptr_t; // #include "cxx_compiler_quirks.h" + /* * This header defines macros for circumventing compiler quirks on which sqlite_orm depends. * May amend cxx_core_features.h @@ -167,6 +170,8 @@ using std::nullptr_t; #define SQLITE_ORM_BROKEN_NONTEMPLATE_CONCEPTS #endif + + #if SQLITE_ORM_HAS_INCLUDE() #include #endif @@ -211,6 +216,7 @@ using std::nullptr_t; // #include "cxx_universal.h" + namespace sqlite_orm { namespace internal { namespace polyfill { @@ -352,6 +358,7 @@ namespace sqlite_orm { namespace polyfill = internal::polyfill; } + namespace sqlite_orm { // C++ generic traits used throughout the library namespace internal { @@ -588,8 +595,10 @@ namespace sqlite_orm { #include // std::vector // #include "functional/cxx_optional.h" + // #include "cxx_core_features.h" + #if SQLITE_ORM_HAS_INCLUDE() #include #endif @@ -598,6 +607,7 @@ namespace sqlite_orm { #define SQLITE_ORM_OPTIONAL_SUPPORTED #endif + // #include "functional/cxx_type_traits_polyfill.h" // #include "type_traits.h" @@ -634,6 +644,7 @@ namespace sqlite_orm { }; } + namespace sqlite_orm { /** @@ -732,6 +743,7 @@ namespace sqlite_orm { // #include "functional/mpl.h" + /* * Symbols for 'template metaprogramming' (compile-time template programming), * inspired by the MPL of Aleksey Gurtovoy and David Abrahams. @@ -760,6 +772,7 @@ namespace sqlite_orm { // #include "cxx_type_traits_polyfill.h" + namespace sqlite_orm { namespace internal { namespace mpl { @@ -1045,6 +1058,7 @@ namespace sqlite_orm { // #include "tuple_helper/same_or_void.h" + namespace sqlite_orm { namespace internal { @@ -1074,6 +1088,7 @@ namespace sqlite_orm { // #include "tuple_helper/tuple_traits.h" + #include // std::is_same #include @@ -1081,6 +1096,7 @@ namespace sqlite_orm { // #include "../functional/mpl.h" + namespace sqlite_orm { namespace internal { /* @@ -1129,6 +1145,7 @@ namespace sqlite_orm { } // #include "tuple_helper/tuple_filter.h" + #include // std::integral_constant, std::index_sequence, std::conditional, std::declval #include // std::tuple @@ -1136,10 +1153,12 @@ namespace sqlite_orm { // #include "../functional/index_sequence_util.h" + #include // std::index_sequence, std::make_index_sequence // #include "../functional/cxx_universal.h" + namespace sqlite_orm { namespace internal { /** @@ -1169,6 +1188,7 @@ namespace sqlite_orm { } } + namespace sqlite_orm { namespace internal { @@ -1260,6 +1280,7 @@ namespace sqlite_orm { // #include "table_type_of.h" + namespace sqlite_orm { namespace internal { @@ -1304,6 +1325,7 @@ namespace sqlite_orm { // #include "type_printer.h" + namespace sqlite_orm { namespace internal { @@ -1829,8 +1851,10 @@ namespace sqlite_orm { #include // std::shared_ptr, std::unique_ptr // #include "functional/cxx_optional.h" + // #include "functional/cxx_type_traits_polyfill.h" + namespace sqlite_orm { /** @@ -1871,6 +1895,7 @@ namespace sqlite_orm { // #include "tags.h" + namespace sqlite_orm { namespace internal { struct negatable_t {}; @@ -1884,10 +1909,13 @@ namespace sqlite_orm { // #include "serialize_result_type.h" + // #include "functional/cxx_string_view.h" + // #include "cxx_core_features.h" + #if SQLITE_ORM_HAS_INCLUDE() #include #endif @@ -1912,6 +1940,7 @@ namespace sqlite_orm { } } + namespace sqlite_orm { namespace internal { @@ -2201,12 +2230,14 @@ namespace sqlite_orm { // #include "member_traits/member_traits.h" + #include // std::enable_if, std::is_function, std::true_type, std::false_type // #include "../functional/cxx_universal.h" // #include "../functional/cxx_type_traits_polyfill.h" + namespace sqlite_orm { namespace internal { // SFINAE friendly trait to get a member object pointer's field type @@ -2298,6 +2329,7 @@ namespace sqlite_orm { // #include "constraints.h" + namespace sqlite_orm { namespace internal { @@ -2485,12 +2517,14 @@ namespace sqlite_orm { #endif // SQLITE_ORM_OMITS_CODECVT // #include "functional/cxx_optional.h" + // #include "functional/cxx_universal.h" // #include "functional/cxx_type_traits_polyfill.h" // #include "is_std_ptr.h" + namespace sqlite_orm { /** @@ -2655,6 +2689,7 @@ namespace sqlite_orm { // #include "is_base_of_template.h" + #include // std::true_type, std::false_type, std::declval namespace sqlite_orm { @@ -2700,6 +2735,7 @@ namespace sqlite_orm { // #include "optional_container.h" + namespace sqlite_orm { namespace internal { @@ -2734,6 +2770,7 @@ namespace sqlite_orm { // #include "serializer_context.h" + namespace sqlite_orm { namespace internal { @@ -2753,6 +2790,18 @@ namespace sqlite_orm { serializer_context(const db_objects_type& dbObjects) : db_objects{dbObjects} {} }; + template + struct serializer_context_with_no_types_and_constraints: serializer_context { + using super = serializer_context; + + serializer_context_with_no_types_and_constraints(const super &parentContext): super(parentContext) {} + }; + + template + serializer_context_with_no_types_and_constraints make_serializer_context_with_no_types_and_constraints(const serializer_context &parentContext) { + return {parentContext}; + } + template struct serializer_context_builder { using storage_type = S; @@ -2767,6 +2816,11 @@ namespace sqlite_orm { const storage_type& storage; }; + template + struct no_need_types_and_constraints: std::false_type {}; + + template + struct no_need_types_and_constraints>: std::true_type {}; } } @@ -2775,6 +2829,7 @@ namespace sqlite_orm { // #include "alias_traits.h" + #include // std::remove_const, std::is_base_of, std::is_same #ifdef SQLITE_ORM_WITH_CPP20_ALIASES #include @@ -2786,6 +2841,7 @@ namespace sqlite_orm { // #include "type_traits.h" + namespace sqlite_orm { /** @short Base class for a custom table alias, column alias or expression alias. @@ -2864,14 +2920,17 @@ namespace sqlite_orm { // #include "expression.h" + #include #include // std::move, std::forward // #include "functional/cxx_optional.h" + // #include "functional/cxx_universal.h" // #include "operators.h" + namespace sqlite_orm { namespace internal { @@ -2953,6 +3012,7 @@ namespace sqlite_orm { // #include "literal.h" + namespace sqlite_orm { namespace internal { @@ -2969,6 +3029,7 @@ namespace sqlite_orm { } } + namespace sqlite_orm { namespace internal { @@ -3158,6 +3219,16 @@ namespace sqlite_orm { } }; + template + struct is_equal_with_table_t: negatable_t { + using left_type = L; + using right_type = R; + + right_type rhs; + + is_equal_with_table_t(right_type rhs): rhs(std::move(rhs)) {} + }; + struct is_not_equal_string { operator std::string() const { return "!="; @@ -4033,6 +4104,11 @@ namespace sqlite_orm { return {std::move(l), std::move(r)}; } + template + 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) { return {std::move(l), std::move(r)}; @@ -4206,13 +4282,14 @@ namespace sqlite_orm { #include // std::copy_n // #include "functional/cxx_universal.h" -// ::size_t + // ::size_t // #include "functional/cxx_type_traits_polyfill.h" // #include "type_traits.h" // #include "alias_traits.h" + namespace sqlite_orm { namespace internal { @@ -4538,8 +4615,10 @@ namespace sqlite_orm { // #include "ast/into.h" + // #include "../functional/cxx_type_traits_polyfill.h" + namespace sqlite_orm { namespace internal { @@ -4558,6 +4637,7 @@ namespace sqlite_orm { } } + namespace sqlite_orm { using int64 = sqlite_int64; @@ -6670,6 +6750,7 @@ namespace sqlite_orm { #include // std::tuple, std::get, std::tuple_size // #include "functional/cxx_optional.h" + // #include "functional/cxx_universal.h" // #include "functional/cxx_type_traits_polyfill.h" @@ -6682,6 +6763,7 @@ namespace sqlite_orm { // #include "ast/where.h" + #include // std::false_type, std::true_type #include // std::move @@ -6691,6 +6773,7 @@ namespace sqlite_orm { // #include "../serialize_result_type.h" + namespace sqlite_orm { namespace internal { @@ -6738,12 +6821,14 @@ namespace sqlite_orm { // #include "ast/group_by.h" + #include // std::tuple, std::make_tuple #include // std::true_type, std::false_type #include // std::forward, std::move // #include "../functional/cxx_type_traits_polyfill.h" + namespace sqlite_orm { namespace internal { @@ -6792,6 +6877,7 @@ namespace sqlite_orm { // #include "column_pointer.h" + #include // std::string #include // std::move @@ -6801,6 +6887,7 @@ namespace sqlite_orm { // #include "alias_traits.h" + namespace sqlite_orm { namespace internal { /** @@ -6855,6 +6942,7 @@ namespace sqlite_orm { } } + namespace sqlite_orm { namespace internal { @@ -7288,6 +7376,7 @@ namespace sqlite_orm { // #include "functional/cxx_universal.h" + namespace sqlite_orm { struct table_info { @@ -7341,9 +7430,10 @@ namespace sqlite_orm { #include #include -// #include "functional/cxx_universal.h" +// #include "../functional/cxx_universal.h" + +// #include "../optional_container.h" -// #include "optional_container.h" // NOTE Idea : Maybe also implement a custom trigger system to call a c++ callback when a trigger triggers ? // (Could be implemented with a normal trigger that insert or update an internal table and then retreive @@ -7668,6 +7758,7 @@ namespace sqlite_orm { // #include "xdestroy_handling.h" + #include // std::integral_constant #ifdef SQLITE_ORM_CPP20_CONCEPTS_SUPPORTED #include @@ -7677,6 +7768,7 @@ namespace sqlite_orm { // #include "functional/cxx_type_traits_polyfill.h" + namespace sqlite_orm { using xdestroy_fn_t = void (*)(void*); @@ -7918,6 +8010,7 @@ namespace sqlite_orm { #endif } + namespace sqlite_orm { /** @@ -8114,6 +8207,7 @@ namespace sqlite_orm { #endif // #include "../member_traits/member_traits.h" + namespace sqlite_orm { namespace internal { namespace polyfill { @@ -8197,6 +8291,7 @@ namespace sqlite_orm { // #include "pointer_value.h" + namespace sqlite_orm { /** @@ -8567,6 +8662,7 @@ namespace sqlite_orm { // #include "journal_mode.h" + #include // std::back_inserter #include // std::string #include // std::unique_ptr @@ -8643,6 +8739,7 @@ namespace sqlite_orm { // #include "is_std_ptr.h" + namespace sqlite_orm { /** @@ -9073,6 +9170,7 @@ namespace sqlite_orm { // #include "error_code.h" + namespace sqlite_orm { /** @@ -9268,6 +9366,7 @@ namespace sqlite_orm { // #include "indexed_column.h" + #include // std::string #include // std::move @@ -9275,6 +9374,7 @@ namespace sqlite_orm { // #include "ast/where.h" + namespace sqlite_orm { namespace internal { @@ -9340,6 +9440,7 @@ namespace sqlite_orm { // #include "table_type_of.h" + namespace sqlite_orm { namespace internal { @@ -9478,13 +9579,14 @@ namespace sqlite_orm { #include // std::forward, std::move // #include "functional/cxx_universal.h" -// ::size_t + // ::size_t // #include "functional/cxx_type_traits_polyfill.h" // #include "functional/cxx_functional_polyfill.h" // #include "functional/static_magic.h" + #ifndef SQLITE_ORM_IF_CONSTEXPR_SUPPORTED #include // std::false_type, std::true_type, std::integral_constant #endif @@ -9569,16 +9671,18 @@ namespace sqlite_orm { // #include "tuple_helper/tuple_iteration.h" + #include // std::tuple, std::get, std::tuple_element, std::tuple_size #include // std::remove_reference, std::index_sequence, std::make_index_sequence #include // std::forward, std::move // #include "../functional/cxx_universal.h" -// ::size_t + // ::size_t // #include "../functional/cxx_type_traits_polyfill.h" // #include "../functional/cxx_functional_polyfill.h" + namespace sqlite_orm { namespace internal { @@ -9717,6 +9821,7 @@ namespace sqlite_orm { // #include "column.h" + namespace sqlite_orm { namespace internal { @@ -9811,25 +9916,6 @@ namespace sqlite_orm { return result; } - template - bool exists_in_composite_primary_key(const column_field& column) const { - bool res = false; - this->for_each_primary_key([&column, &res](auto& primaryKey) { - using colrefs_tuple = decltype(primaryKey.columns); - using same_type_index_sequence = - filter_tuple_sequence_t>::template fn, - member_field_type_t>; - iterate_tuple(primaryKey.columns, same_type_index_sequence{}, [&res, &column](auto& memberPointer) { - if(compare_any(memberPointer, column.member_pointer) || - compare_any(memberPointer, column.setter)) { - res = true; - } - }); - }); - return res; - } - /** * Call passed lambda with all defined primary keys. */ @@ -9979,6 +10065,128 @@ namespace sqlite_orm { template struct is_table> : std::true_type {}; + + template + struct virtual_table_t: basic_table { + using module_details_type = M; + using object_type = typename module_details_type::object_type; + using elements_type = typename module_details_type::columns_type; + + static constexpr bool is_without_rowid_v = false; + using is_without_rowid = polyfill::bool_constant; + + module_details_type module_details; + + virtual_table_t(std::string name, module_details_type module_details): + basic_table{std::move(name)}, module_details{std::move(module_details)} {} + + /** + * Call passed lambda with columns not having the specified constraint trait `OpTrait`. + * @param lambda Lambda called for each column. + */ + template class OpTraitFn, class L> + void for_each_column_excluding(L&& lambda) const { + this->module_details.template for_each_column_excluding(lambda); + } + + /** + * Call passed lambda with columns not having the specified constraint trait `OpTrait`. + * @param lambda Lambda called for each column. + */ + template = true> + void for_each_column_excluding(L&& lambda) const { + this->module_details.template for_each_column_excluding(lambda); + } + + /** + * Call passed lambda with all defined columns. + * @param lambda Lambda called for each column. Function signature: `void(auto& column)` + */ + template + void for_each_column(L&& lambda) const { + this->module_details.for_each_column(lambda); + } + }; + + template + struct is_virtual_table : std::false_type {}; + + template + struct is_virtual_table> : std::true_type {}; + + template + struct using_fts5_t { + using object_type = T; + using columns_type = std::tuple; + + columns_type columns; + + using_fts5_t(columns_type columns): columns(std::move(columns)) {} + + /** + * Call passed lambda with columns not having the specified constraint trait `OpTrait`. + * @param lambda Lambda called for each column. + */ + template class OpTraitFn, class L> + void for_each_column_excluding(L&& lambda) const { + iterate_tuple(this->columns, col_index_sequence_excluding{}, lambda); + } + + /** + * Call passed lambda with columns not having the specified constraint trait `OpTrait`. + * @param lambda Lambda called for each column. + */ + template = true> + void for_each_column_excluding(L&& lambda) const { + this->for_each_column_excluding(lambda); + } + + /** + * Call passed lambda with all defined columns. + * @param lambda Lambda called for each column. Function signature: `void(auto& column)` + */ + template + void for_each_column(L&& lambda) const { + using col_index_sequence = filter_tuple_sequence_t; + iterate_tuple(this->columns, col_index_sequence{}, lambda); + } + }; + + template + bool exists_in_composite_primary_key(const table_t &table, const column_field& column) { + bool res = false; + table.for_each_primary_key([&column, &res](auto& primaryKey) { + using colrefs_tuple = decltype(primaryKey.columns); + using same_type_index_sequence = + filter_tuple_sequence_t>::template fn, + member_field_type_t>; + iterate_tuple(primaryKey.columns, same_type_index_sequence{}, [&res, &column](auto& memberPointer) { + if(compare_any(memberPointer, column.member_pointer) || + compare_any(memberPointer, column.setter)) { + res = true; + } + }); + }); + return res; + } + + template + bool exists_in_composite_primary_key(const virtual_table_t &virtualTable, const column_field& column) { + return false; + } + } + + template>::object_type> + internal::using_fts5_t using_fts5(Cs... columns) { + SQLITE_ORM_CLANG_SUPPRESS_MISSING_BRACES( + return {std::make_tuple(std::forward(columns)...)}); + } + + template + internal::using_fts5_t using_fts5(Cs... columns) { + SQLITE_ORM_CLANG_SUPPRESS_MISSING_BRACES( + return {std::make_tuple(std::forward(columns)...)}); } /** @@ -10002,13 +10210,18 @@ namespace sqlite_orm { SQLITE_ORM_CLANG_SUPPRESS_MISSING_BRACES( return {std::move(name), std::make_tuple(std::forward(args)...)}); } + + template + internal::virtual_table_t make_virtual_table(std::string name, M module_details) { + return internal::virtual_table_t(std::move(name), std::move(module_details)); + } } #pragma once #include // std::string // #include "functional/cxx_universal.h" -// ::nullptr_t + // ::nullptr_t // #include "functional/static_magic.h" // #include "tuple_helper/tuple_filter.h" @@ -10021,6 +10234,7 @@ namespace sqlite_orm { // #include "storage_lookup.h" + #include // std::true_type, std::false_type, std::remove_const, std::enable_if, std::is_base_of, std::is_void #include #include // std::index_sequence, std::make_index_sequence @@ -10031,6 +10245,7 @@ namespace sqlite_orm { // #include "type_traits.h" + namespace sqlite_orm { namespace internal { @@ -10163,6 +10378,7 @@ namespace sqlite_orm { } } + // interface functions namespace sqlite_orm { namespace internal { @@ -10226,12 +10442,13 @@ namespace sqlite_orm { // #include "storage_lookup.h" + namespace sqlite_orm { namespace internal { - template - std::string serialize(const T&, const serializer_context&); + template + std::string serialize(const T& t, const C& context); /** * Serialize default value of a column's default valu @@ -10262,6 +10479,7 @@ namespace sqlite_orm { #include // std::for_each, std::ranges::for_each // #include "functional/cxx_optional.h" + // #include "functional/cxx_universal.h" // #include "functional/cxx_functional_polyfill.h" @@ -10302,6 +10520,7 @@ namespace sqlite_orm { // #include "column_result.h" + #include // std::enable_if, std::is_same, std::decay, std::is_arithmetic, std::is_base_of #include // std::tuple #include // std::reference_wrapper @@ -10312,6 +10531,7 @@ namespace sqlite_orm { // #include "tuple_helper/tuple_fy.h" + #include namespace sqlite_orm { @@ -10340,12 +10560,14 @@ namespace sqlite_orm { // #include "mapped_type_proxy.h" + #include // std::remove_const // #include "type_traits.h" // #include "alias_traits.h" + namespace sqlite_orm { namespace internal { @@ -10377,6 +10599,7 @@ namespace sqlite_orm { // #include "storage_traits.h" + #include // std::tuple // #include "functional/cxx_type_traits_polyfill.h" @@ -10385,10 +10608,12 @@ namespace sqlite_orm { // #include "tuple_helper/tuple_transformer.h" + #include // std::tuple // #include "../functional/mpl.h" + namespace sqlite_orm { namespace internal { @@ -10414,6 +10639,7 @@ namespace sqlite_orm { // #include "storage_lookup.h" + namespace sqlite_orm { namespace internal { @@ -10444,6 +10670,7 @@ namespace sqlite_orm { // #include "function.h" + #include #include #include // std::string @@ -10456,6 +10683,7 @@ namespace sqlite_orm { // #include "functional/cxx_type_traits_polyfill.h" + namespace sqlite_orm { struct arg_values; @@ -10690,6 +10918,7 @@ namespace sqlite_orm { } + namespace sqlite_orm { namespace internal { @@ -10971,6 +11200,7 @@ namespace sqlite_orm { // #include "view.h" + #include #include // std::string #include // std::forward, std::move @@ -10982,6 +11212,7 @@ namespace sqlite_orm { // #include "iterator.h" + #include #include // std::shared_ptr, std::unique_ptr, std::make_shared #include // std::decay @@ -10998,6 +11229,7 @@ namespace sqlite_orm { // #include "object_from_column_builder.h" + #include #include // std::is_member_object_pointer @@ -11005,6 +11237,7 @@ namespace sqlite_orm { // #include "row_extractor.h" + namespace sqlite_orm { namespace internal { @@ -11050,6 +11283,7 @@ namespace sqlite_orm { // #include "util.h" + namespace sqlite_orm { namespace internal { @@ -11137,6 +11371,7 @@ namespace sqlite_orm { // #include "ast_iterator.h" + #include // std::vector #include // std::reference_wrapper @@ -11156,6 +11391,7 @@ namespace sqlite_orm { // #include "prepared_statement.h" + #include #include // std::unique_ptr #include // std::iterator_traits @@ -11173,12 +11409,14 @@ namespace sqlite_orm { // #include "connection_holder.h" + #include #include #include // std::string // #include "error_code.h" + namespace sqlite_orm { namespace internal { @@ -11251,6 +11489,7 @@ namespace sqlite_orm { // #include "values.h" + #include // std::vector #include // std::tuple #include // std::forward @@ -11259,6 +11498,7 @@ namespace sqlite_orm { // #include "functional/cxx_type_traits_polyfill.h" + namespace sqlite_orm { namespace internal { @@ -11299,6 +11539,7 @@ namespace sqlite_orm { // #include "ast/upsert_clause.h" + #if SQLITE_VERSION_NUMBER >= 3024000 #include // std::tuple #include // std::forward, std::move @@ -11306,6 +11547,7 @@ namespace sqlite_orm { // #include "../functional/cxx_type_traits_polyfill.h" + namespace sqlite_orm { namespace internal { #if SQLITE_VERSION_NUMBER >= 3024000 @@ -11368,6 +11610,7 @@ namespace sqlite_orm { // #include "ast/set.h" + #include // std::tuple, std::tuple_size #include // std::string #include // std::vector @@ -11376,6 +11619,7 @@ namespace sqlite_orm { // #include "../table_name_collector.h" + #include // std::set #include // std::string #include // std::pair, std::move @@ -11394,6 +11638,7 @@ namespace sqlite_orm { // #include "storage_lookup.h" + namespace sqlite_orm { namespace internal { @@ -11478,6 +11723,7 @@ namespace sqlite_orm { } + namespace sqlite_orm { namespace internal { @@ -11577,6 +11823,7 @@ namespace sqlite_orm { } } + namespace sqlite_orm { namespace internal { @@ -12294,6 +12541,7 @@ namespace sqlite_orm { // #include "ast/excluded.h" + #include // std::move namespace sqlite_orm { @@ -12323,10 +12571,12 @@ namespace sqlite_orm { // #include "ast/exists.h" + #include // std::move // #include "../tags.h" + namespace sqlite_orm { namespace internal { @@ -12357,6 +12607,30 @@ namespace sqlite_orm { // #include "ast/set.h" +// #include "ast/match.h" + + +namespace sqlite_orm { + namespace internal { + + template + struct match_t { + using mapped_type = T; + using argument_type = X; + + argument_type argument; + + match_t(argument_type argument): argument(std::move(argument)) {} + }; + } + + template + internal::match_t match(X argument) { + return {std::move(argument)}; + } + +} + namespace sqlite_orm { namespace internal { @@ -12477,9 +12751,19 @@ namespace sqlite_orm { using node_type = binary_operator; template - void operator()(const node_type& binaryOperator, C& lambda) const { - iterate_ast(binaryOperator.lhs, lambda); - iterate_ast(binaryOperator.rhs, lambda); + void operator()(const node_type& node, C& lambda) const { + iterate_ast(node.lhs, lambda); + iterate_ast(node.rhs, lambda); + } + }; + + template + struct ast_iterator, void> { + using node_type = is_equal_with_table_t; + + template + void operator()(const node_type& node, C& lambda) const { + iterate_ast(node.rhs, lambda); } }; @@ -12548,6 +12832,16 @@ namespace sqlite_orm { } }; + template + struct ast_iterator, void> { + using node_type = match_t; + + template + void operator()(const node_type& node, L& lambda) const { + iterate_ast(node.argument, lambda); + } + }; + template struct ast_iterator, void> { using node_type = into_t; @@ -13013,6 +13307,7 @@ namespace sqlite_orm { // #include "util.h" + namespace sqlite_orm { namespace internal { @@ -13069,6 +13364,7 @@ namespace sqlite_orm { // #include "storage_base.h" + #include #include // std::function, std::bind #include // std::string @@ -13082,11 +13378,12 @@ namespace sqlite_orm { #include // std::find_if // #include "functional/cxx_universal.h" -// ::size_t + // ::size_t // #include "tuple_helper/tuple_iteration.h" // #include "pragma.h" + #include #include // std::string #include // std::function @@ -13106,6 +13403,7 @@ namespace sqlite_orm { // #include "serializing_util.h" + #include // std::index_sequence #include #include @@ -13114,7 +13412,7 @@ namespace sqlite_orm { #include // std::exchange, std::tuple_size // #include "functional/cxx_universal.h" -// ::size_t + // ::size_t // #include "functional/cxx_type_traits_polyfill.h" // #include "tuple_helper/tuple_iteration.h" @@ -13127,13 +13425,14 @@ namespace sqlite_orm { // #include "util.h" + namespace sqlite_orm { namespace internal { template struct order_by_t; - template - std::string serialize(const T&, const serializer_context&); + template + std::string serialize(const T& t, const C& context); template std::string serialize_order_by(const T&, const Ctx&); @@ -13481,7 +13780,7 @@ namespace sqlite_orm { ss << serialize(constraint, context) << ' '; }); if(isNotNull) { - ss << "NOT NULL "; + ss << "NOT NULL"; } return ss; @@ -13489,6 +13788,7 @@ namespace sqlite_orm { } } + namespace sqlite_orm { namespace internal { @@ -13704,6 +14004,7 @@ namespace sqlite_orm { // #include "limit_accessor.h" + #include #include // std::map #include // std::function @@ -13711,6 +14012,7 @@ namespace sqlite_orm { // #include "connection_holder.h" + namespace sqlite_orm { namespace internal { @@ -13844,11 +14146,13 @@ namespace sqlite_orm { // #include "transaction_guard.h" + #include // std::function #include // std::move // #include "connection_holder.h" + namespace sqlite_orm { namespace internal { @@ -13929,6 +14233,7 @@ namespace sqlite_orm { // #include "backup.h" + #include #include // std::system_error #include // std::string @@ -13939,6 +14244,7 @@ namespace sqlite_orm { // #include "connection_holder.h" + namespace sqlite_orm { namespace internal { @@ -14006,6 +14312,7 @@ namespace sqlite_orm { // #include "values_to_tuple.h" + #include #include // std::index_sequence, std::make_index_sequence #include // std::tuple, std::tuple_size, std::get @@ -14016,10 +14323,12 @@ namespace sqlite_orm { // #include "arg_values.h" + #include // #include "row_extractor.h" + namespace sqlite_orm { /** @short Wrapper around a dynamically typed value object. @@ -14163,6 +14472,7 @@ namespace sqlite_orm { }; } + namespace sqlite_orm { namespace internal { @@ -14207,6 +14517,7 @@ namespace sqlite_orm { // #include "serializing_util.h" + namespace sqlite_orm { namespace internal { @@ -14974,11 +15285,13 @@ namespace sqlite_orm { // #include "expression_object_type.h" + #include // std::decay #include // std::reference_wrapper // #include "prepared_statement.h" + namespace sqlite_orm { namespace internal { @@ -15112,6 +15425,7 @@ namespace sqlite_orm { // #include "statement_serializer.h" + #include // std::stringstream #include // std::string #include // std::enable_if, std::remove_pointer @@ -15126,6 +15440,7 @@ namespace sqlite_orm { // #include "functional/cxx_optional.h" + // #include "functional/cxx_universal.h" // #include "functional/cxx_functional_polyfill.h" @@ -15142,6 +15457,8 @@ namespace sqlite_orm { // #include "ast/into.h" +// #include "ast/match.h" + // #include "core_functions.h" // #include "constraints.h" @@ -15170,6 +15487,7 @@ namespace sqlite_orm { // #include "column_names_getter.h" + #include // std::is_base_of #include // std::string #include // std::vector @@ -15190,17 +15508,18 @@ namespace sqlite_orm { // #include "select_constraints.h" // #include "storage_lookup.h" -// pick_table + // pick_table // #include "serializer_context.h" // #include "util.h" + namespace sqlite_orm { namespace internal { - template - std::string serialize(const T&, const serializer_context&); + template + std::string serialize(const T& t, const C& context); template std::vector& collect_table_column_names(std::vector& collectedExpressions, @@ -15297,6 +15616,7 @@ namespace sqlite_orm { // #include "order_by_serializer.h" + #include // std::string #include // std::stringstream @@ -15380,14 +15700,15 @@ namespace sqlite_orm { // #include "values.h" -// #include "triggers.h" +// #include "schema/triggers.h" // #include "table_type_of.h" -// #include "index.h" +// #include "schema/index.h" // #include "util.h" + namespace sqlite_orm { namespace internal { @@ -15395,8 +15716,8 @@ namespace sqlite_orm { template struct statement_serializer; - template - std::string serialize(const T& t, const serializer_context& context) { + template + std::string serialize(const T& t, const C& context) { statement_serializer serializer; return serializer(t, context); } @@ -15749,12 +16070,27 @@ namespace sqlite_orm { using statement_type = table__rowid_t; template - std::string operator()(const statement_type& s, const Ctx& context) const { + std::string operator()(const statement_type& statement, const Ctx& context) const { std::stringstream ss; if(!context.skip_table_name) { ss << streaming_identifier(lookup_table_name(context.db_objects)) << "."; } - ss << static_cast(s); + ss << static_cast(statement); + return ss.str(); + } + }; + + template + struct statement_serializer, void> { + using statement_type = is_equal_with_table_t; + + template + std::string operator()(const statement_type& statement, const Ctx& context) const { + std::stringstream ss; + const auto tableName = lookup_table_name(context.db_objects); + ss << streaming_identifier(tableName); + ss << " = "; + ss << serialize(statement.rhs, context); return ss.str(); } }; @@ -16286,12 +16622,17 @@ namespace sqlite_orm { using column_type = statement_type; std::stringstream ss; - ss << streaming_identifier(column.name) << " " << type_printer>().print() - << " " - << streaming_column_constraints( - call_as_template_base(polyfill::identity{})(column), - column.is_not_null(), - context); + ss << streaming_identifier(column.name); + if (!no_need_types_and_constraints::value) { + ss << " " << type_printer>().print(); + auto constraintsTuple = streaming_column_constraints( + call_as_template_base(polyfill::identity{})(column), + column.is_not_null(), + context); + if (std::tuple_size::value > 0) { + ss << " " << constraintsTuple; + } + } return ss.str(); } }; @@ -16377,7 +16718,7 @@ namespace sqlite_orm { ss << "UPDATE " << streaming_identifier(table.name) << " SET "; table.template for_each_column_excluding>( [&table, &ss, &context, &object = get_ref(statement.object), first = true](auto& column) mutable { - if(table.exists_in_composite_primary_key(column)) { + if(exists_in_composite_primary_key(table, column)) { return; } @@ -16388,7 +16729,7 @@ namespace sqlite_orm { ss << " WHERE "; table.for_each_column( [&table, &context, &ss, &object = get_ref(statement.object), first = true](auto& column) mutable { - if(!column.template is() && !table.exists_in_composite_primary_key(column)) { + if(!column.template is() && !exists_in_composite_primary_key(table, column)) { return; } @@ -16494,7 +16835,7 @@ namespace sqlite_orm { mpl::conjunction>, mpl::disjunction_fn>>( [&table, &columnNames](auto& column) { - if(table.exists_in_composite_primary_key(column)) { + if(exists_in_composite_primary_key(table, column)) { return; } @@ -16516,7 +16857,7 @@ namespace sqlite_orm { mpl::conjunction>, mpl::disjunction_fn>{}, [&table](auto& column) { - return table.exists_in_composite_primary_key(column); + return exists_in_composite_primary_key(table, column); }, context, get_ref(statement.object)) @@ -16527,6 +16868,19 @@ namespace sqlite_orm { } }; + template + struct statement_serializer, void> { + using statement_type = match_t; + + template + std::string operator()(const statement_type &statement, const Ctx& context) const { + auto& table = pick_table(context.db_objects); + std::stringstream ss; + ss << streaming_identifier(table.name) << " MATCH " << serialize(statement.argument, context); + return ss.str(); + } + }; + template struct statement_serializer, void> { using statement_type = into_t; @@ -16656,7 +17010,7 @@ namespace sqlite_orm { mpl::conjunction>, mpl::disjunction_fn>>( [&table, &columnNames](auto& column) { - if(table.exists_in_composite_primary_key(column)) { + if(exists_in_composite_primary_key(table, column)) { return; } @@ -16887,6 +17241,34 @@ namespace sqlite_orm { } }; + template + struct statement_serializer, void> { + using statement_type = using_fts5_t; + + template + std::string operator()(const statement_type& statement, const Ctx& context) const { + std::stringstream ss; + ss << "USING FTS5("; + auto subContext = make_serializer_context_with_no_types_and_constraints(context); + ss << streaming_expressions_tuple(statement.columns, subContext) << ")"; + return ss.str(); + } + }; + + template + struct statement_serializer, void> { + using statement_type = virtual_table_t; + + template + std::string operator()(const statement_type& statement, const Ctx& context) const { + std::stringstream ss; + ss << "CREATE VIRTUAL TABLE IF NOT EXISTS "; + ss << streaming_identifier(statement.name) << ' '; + ss << serialize(statement.module_details, context); + return ss.str(); + } + }; + template struct statement_serializer, void> { using statement_type = index_t; @@ -17348,20 +17730,21 @@ namespace sqlite_orm { } } -// #include "triggers.h" +// #include "schema/triggers.h" // #include "object_from_column_builder.h" -// #include "table.h" +// #include "schema/table.h" // #include "column.h" -// #include "index.h" +// #include "schema/index.h" // #include "util.h" // #include "serializing_util.h" + namespace sqlite_orm { namespace internal { @@ -18222,6 +18605,16 @@ namespace sqlite_orm { return res; } + template + sync_schema_result sync_table(const virtual_table_t& virtualTable, sqlite3* db, bool) { + auto res = sync_schema_result::already_in_sync; + using context_t = serializer_context; + context_t context{this->db_objects}; + auto query = serialize(virtualTable, context); + perform_void_exec(db, query); + return res; + } + template sync_schema_result sync_table(const index_t& index, sqlite3* db, bool) { auto res = sync_schema_result::already_in_sync; @@ -18237,7 +18630,8 @@ namespace sqlite_orm { auto res = sync_schema_result::already_in_sync; // TODO Change accordingly using context_t = serializer_context; context_t context{this->db_objects}; - perform_void_exec(db, serialize(trigger, context)); + auto query = serialize(trigger, context); + perform_void_exec(db, query); return res; } @@ -18519,7 +18913,7 @@ namespace sqlite_orm { mpl::conjunction>, mpl::disjunction_fn>>( call_as_template_base([&table, &bindValue, &object](auto& column) { - if(!table.exists_in_composite_primary_key(column)) { + if(!exists_in_composite_primary_key(table, column)) { bindValue(polyfill::invoke(column.member_pointer, object)); } })); @@ -18571,12 +18965,12 @@ namespace sqlite_orm { auto& object = get_object(statement.expression); table.template for_each_column_excluding>( call_as_template_base([&table, &bindValue, &object](auto& column) { - if(!table.exists_in_composite_primary_key(column)) { + if(!exists_in_composite_primary_key(table, column)) { bindValue(polyfill::invoke(column.member_pointer, object)); } })); table.for_each_column([&table, &bindValue, &object](auto& column) { - if(column.template is() || table.exists_in_composite_primary_key(column)) { + if(column.template is() || exists_in_composite_primary_key(table, column)) { bindValue(polyfill::invoke(column.member_pointer, object)); } }); @@ -18793,7 +19187,7 @@ namespace sqlite_orm { #include // std::get // #include "functional/cxx_universal.h" -// ::size_t + // ::size_t // #include "functional/static_magic.h" // #include "prepared_statement.h" @@ -18802,12 +19196,14 @@ namespace sqlite_orm { // #include "node_tuple.h" + #include // std::enable_if #include // std::tuple #include // std::pair #include // std::reference_wrapper // #include "functional/cxx_optional.h" + // #include "functional/cxx_type_traits_polyfill.h" // #include "tuple_helper/tuple_filter.h" @@ -18836,8 +19232,10 @@ namespace sqlite_orm { // #include "ast/group_by.h" -namespace sqlite_orm { +// #include "ast/match.h" + +namespace sqlite_orm { namespace internal { template @@ -18904,6 +19302,9 @@ namespace sqlite_orm { template struct node_tuple, void> : node_tuple {}; + template + struct node_tuple, void> : node_tuple {}; + template struct node_tuple> { using node_type = T; @@ -18973,6 +19374,9 @@ namespace sqlite_orm { template struct node_tuple, void> : node_tuple {}; + template + struct node_tuple, void> : node_tuple {}; + template struct node_tuple, void> { using type = tuple_cat_t...>; @@ -19133,6 +19537,7 @@ namespace sqlite_orm { // #include "expression_object_type.h" + namespace sqlite_orm { template @@ -19312,6 +19717,7 @@ namespace sqlite_orm { // #include "pointer_value.h" + namespace sqlite_orm { inline constexpr const char carray_pvt_name[] = "carray"; @@ -19382,10 +19788,11 @@ namespace sqlite_orm { // #include "column.h" -// #include "table.h" +// #include "schema/table.h" // #include "alias.h" + namespace sqlite_orm { /** * SQLite's "schema table" that stores the schema for a database. @@ -19429,7 +19836,8 @@ namespace sqlite_orm { // #include "../column.h" -// #include "../table.h" +// #include "../schema/table.h" + namespace sqlite_orm { #ifdef SQLITE_ENABLE_DBSTAT_VTAB @@ -19473,6 +19881,7 @@ namespace sqlite_orm { * this file is also used to provide definitions of interface methods 'hitting the database'. */ + #include // std::make_unique // #include "../functional/cxx_core_features.h" @@ -19489,6 +19898,7 @@ namespace sqlite_orm { // #include "../column.h" + namespace sqlite_orm { namespace internal { @@ -19523,12 +19933,13 @@ namespace sqlite_orm { #include // std::find_if, std::ranges::find // #include "../functional/cxx_universal.h" -// ::size_t + // ::size_t // #include "../type_printer.h" // #include "../column.h" -// #include "../table.h" +// #include "../schema/table.h" + namespace sqlite_orm { namespace internal { @@ -19594,6 +20005,7 @@ namespace sqlite_orm { // #include "../storage.h" + namespace sqlite_orm { namespace internal { diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 8b7366452..4d8db563c 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -39,14 +39,16 @@ add_executable(unit_tests tests3.cpp tests4.cpp tests5.cpp - column_tests.cpp + schema/column_tests.cpp + schema/index_tests.cpp + schema/table_tests.cpp + schema/explicit_columns.cpp + schema/virtual_table.cpp private_getters_tests.cpp pragma_tests.cpp - explicit_columns.cpp built_in_functions_tests/core_functions_tests.cpp built_in_functions_tests/datetime_function_tests.cpp built_in_functions_tests/math_functions.cpp - index_tests.cpp constraints/composite_key.cpp operators/arithmetic_operators.cpp operators/like.cpp @@ -80,7 +82,6 @@ add_executable(unit_tests constraints/unique.cpp constraints/foreign_key.cpp constraints/check.cpp - table_tests.cpp statement_serializer_tests/column_constraints/generated.cpp statement_serializer_tests/column_constraints/default.cpp statement_serializer_tests/column_constraints/primary_key.cpp @@ -90,6 +91,7 @@ add_executable(unit_tests statement_serializer_tests/ast/upsert_clause.cpp statement_serializer_tests/ast/excluded.cpp statement_serializer_tests/ast/set.cpp + statement_serializer_tests/ast/match.cpp statement_serializer_tests/arithmetic_operators.cpp statement_serializer_tests/base_types.cpp statement_serializer_tests/collate.cpp @@ -102,6 +104,8 @@ add_executable(unit_tests statement_serializer_tests/schema/trigger.cpp statement_serializer_tests/schema/new_old.cpp statement_serializer_tests/schema/raise.cpp + statement_serializer_tests/schema/using_fts5.cpp + statement_serializer_tests/schema/virtual_table.cpp statement_serializer_tests/indexed_column.cpp statement_serializer_tests/logical_operators.cpp statement_serializer_tests/statements/select.cpp diff --git a/tests/ast_iterator_tests.cpp b/tests/ast_iterator_tests.cpp index 6dfe212c2..3cb1499ef 100644 --- a/tests/ast_iterator_tests.cpp +++ b/tests/ast_iterator_tests.cpp @@ -219,6 +219,11 @@ TEST_CASE("ast_iterator") { auto node = into(); iterate_ast(node, lambda); } + SECTION("match") { + auto node = match(std::string("Plazma")); + expected.push_back(typeid(std::string)); + iterate_ast(node, lambda); + } SECTION("replace") { auto node = replace(into(), columns(&User::id, &User::name), values(std::make_tuple(1, std::string("Ellie")))); @@ -293,6 +298,11 @@ TEST_CASE("ast_iterator") { } #endif } + SECTION("is_equal_with_table_t") { + auto expression = is_equal(std::string("Claude")); + expected.push_back(typeid(std::string)); + iterate_ast(expression, lambda); + } SECTION("aliased regular column") { using als = alias_z; auto expression = alias_column(&User::id); diff --git a/tests/column_tests.cpp b/tests/schema/column_tests.cpp similarity index 100% rename from tests/column_tests.cpp rename to tests/schema/column_tests.cpp diff --git a/tests/explicit_columns.cpp b/tests/schema/explicit_columns.cpp similarity index 100% rename from tests/explicit_columns.cpp rename to tests/schema/explicit_columns.cpp diff --git a/tests/index_tests.cpp b/tests/schema/index_tests.cpp similarity index 100% rename from tests/index_tests.cpp rename to tests/schema/index_tests.cpp diff --git a/tests/table_tests.cpp b/tests/schema/table_tests.cpp similarity index 100% rename from tests/table_tests.cpp rename to tests/schema/table_tests.cpp diff --git a/tests/schema/virtual_table.cpp b/tests/schema/virtual_table.cpp new file mode 100644 index 000000000..a382617d0 --- /dev/null +++ b/tests/schema/virtual_table.cpp @@ -0,0 +1,67 @@ +#include +#include + +using namespace sqlite_orm; + +TEST_CASE("virtual table") { + using Catch::Matchers::UnorderedEquals; + + struct Post { + std::string title; + std::string body; + + bool operator==(const Post &other) const { + return this->title == other.title && this->body == other.body; + } + }; + + /// CREATE VIRTUAL TABLE posts + /// USING FTS5(title, body); + auto storage = make_storage("", + make_virtual_table("posts", using_fts5( + make_column("title", &Post::title), + make_column("body", &Post::body)))); + storage.sync_schema(); + REQUIRE(storage.table_exists("posts")); + + const std::vector postsToInsert = { + Post{"Learn SQlite FTS5", "This tutorial teaches you how to perform full-text search in SQLite using FTS5"}, + Post{"Advanced SQlite Full-text Search", "Show you some advanced techniques in SQLite full-text searching"}, + Post{"SQLite Tutorial", "Help you learn SQLite quickly and effectively"}, + }; + +// storage.remove_all(); + + /// INSERT INTO posts(title,body) + /// VALUES('Learn SQlite FTS5','This tutorial teaches you how to perform full-text search in SQLite using FTS5'), + /// ('Advanced SQlite Full-text Search','Show you some advanced techniques in SQLite full-text searching'), + /// ('SQLite Tutorial','Help you learn SQLite quickly and effectively'); + storage.insert_range(postsToInsert.begin(), postsToInsert.end()); + + /// SELECT * FROM posts; + auto posts = storage.get_all(); + + // check that all the posts are there + REQUIRE_THAT(posts, UnorderedEquals(postsToInsert)); + + /// SELECT * + /// FROM posts + /// WHERE posts MATCH 'fts5'; + auto specificPosts = storage.get_all(where(match("fts5"))); + decltype(specificPosts) expectedSpecificPosts = { + {"Learn SQlite FTS5", "This tutorial teaches you how to perform full-text search in SQLite using FTS5"}, + }; + REQUIRE(specificPosts == expectedSpecificPosts); + + /// SELECT * + /// FROM posts + /// WHERE posts = 'fts5'; + auto specificPosts2 = storage.get_all(where(is_equal("fts5"))); + REQUIRE(specificPosts2 == specificPosts); + + /// SELECT * + /// FROM posts + /// WHERE posts MATCH 'text' + /// ORDER BY rank; + auto orderedPosts = storage.get_all(where(match("fts5"), order_by(rank()))); +} diff --git a/tests/statement_serializer_tests/ast/match.cpp b/tests/statement_serializer_tests/ast/match.cpp new file mode 100644 index 000000000..821b36241 --- /dev/null +++ b/tests/statement_serializer_tests/ast/match.cpp @@ -0,0 +1,21 @@ +#include +#include + +using namespace sqlite_orm; + +TEST_CASE("statement_serializer match") { + struct User { + int id = 0; + std::string name; + }; + auto table = make_virtual_table("users", + using_fts5(make_column("id", &User::id), + make_column("name", &User::name))); + using db_objects_t = internal::db_objects_tuple; + auto dbObjects = db_objects_t{table}; + using context_t = internal::serializer_context; + context_t context{dbObjects}; + auto node = match("Claude"); + auto value = serialize(node, context); + REQUIRE(value == "\"users\" MATCH 'Claude'"); +} diff --git a/tests/statement_serializer_tests/collate.cpp b/tests/statement_serializer_tests/collate.cpp index df60624f5..056cf78ac 100644 --- a/tests/statement_serializer_tests/collate.cpp +++ b/tests/statement_serializer_tests/collate.cpp @@ -6,19 +6,22 @@ using namespace sqlite_orm; TEST_CASE("statement_serializer collate") { internal::db_objects_tuple<> storage; internal::serializer_context> context{storage}; - { + std::string value; + std::string expected; + SECTION("COLLATE NOCASE") { auto col = collate_nocase(); - auto value = serialize(col, context); - REQUIRE(value == "COLLATE NOCASE"); + value = serialize(col, context); + expected = "COLLATE NOCASE"; } - { + SECTION("COLLATE BINARY") { auto col = collate_binary(); - auto value = serialize(col, context); - REQUIRE(value == "COLLATE BINARY"); + value = serialize(col, context); + expected = "COLLATE BINARY"; } - { + SECTION("COLLATE RTRIM") { auto col = collate_rtrim(); - auto value = serialize(col, context); - REQUIRE(value == "COLLATE RTRIM"); + value = serialize(col, context); + expected = "COLLATE RTRIM"; } + REQUIRE(value == expected); } diff --git a/tests/statement_serializer_tests/comparison_operators.cpp b/tests/statement_serializer_tests/comparison_operators.cpp index 125d72540..af53eec0c 100644 --- a/tests/statement_serializer_tests/comparison_operators.cpp +++ b/tests/statement_serializer_tests/comparison_operators.cpp @@ -4,8 +4,15 @@ using namespace sqlite_orm; TEST_CASE("statement_serializer comparison operators") { - internal::db_objects_tuple<> storage; - internal::serializer_context> context{storage}; + struct User { + int id = 0; + std::string name; + }; + auto table = make_table("users", make_column("id", &User::id), make_column("name", &User::name)); + using db_objects_t = internal::db_objects_tuple; + auto dbObjects = db_objects_t{table}; + using context_t = internal::serializer_context; + context_t context{dbObjects}; std::string value; std::string expected; SECTION("less_than") { @@ -80,5 +87,9 @@ TEST_CASE("statement_serializer comparison operators") { } expected = "('lala' != 7)"; } + SECTION("is_equal_with_table_t") { + value = serialize(is_equal("Tom Gregory"), context); + expected = "\"users\" = 'Tom Gregory'"; + } REQUIRE(value == expected); } diff --git a/tests/statement_serializer_tests/schema/column.cpp b/tests/statement_serializer_tests/schema/column.cpp new file mode 100644 index 000000000..1ecbcc67d --- /dev/null +++ b/tests/statement_serializer_tests/schema/column.cpp @@ -0,0 +1,41 @@ +#include +#include + +using namespace sqlite_orm; + +TEST_CASE("statement_serializer column") { + struct User { + int id = 0; + std::string name; + }; + internal::db_objects_tuple<> storage; + internal::serializer_context> context{storage}; + std::string value; + std::string expected; + SECTION("with types and constraints") { + SECTION("id INTEGER NOT NULL") { + auto column = make_column("id", &User::id); + value = serialize(column, context); + expected = "\"id\" INTEGER NOT NULL"; + } + SECTION("name TEXT NOT NULL") { + auto column = make_column("name", &User::name); + value = serialize(column, context); + expected = "\"name\" TEXT NOT NULL"; + } + } + SECTION("without types and constraints") { + auto subContext = internal::make_serializer_context_with_no_types_and_constraints(context); + SECTION("id INTEGER NOT NULL") { + auto column = make_column("id", &User::id); + value = serialize(column, context); + expected = "\"id\""; + } + SECTION("name TEXT NOT NULL") { + auto column = make_column("name", &User::name); + value = serialize(column, context); + expected = "\"name\""; + } + } + REQUIRE(value == expected); +} diff --git a/tests/statement_serializer_tests/schema/using_fts5.cpp b/tests/statement_serializer_tests/schema/using_fts5.cpp new file mode 100644 index 000000000..b48a9d642 --- /dev/null +++ b/tests/statement_serializer_tests/schema/using_fts5.cpp @@ -0,0 +1,18 @@ +#include +#include + +using namespace sqlite_orm; + +TEST_CASE("statement_serializer using_fts5") { + struct Post { + std::string title; + std::string body; + }; + internal::db_objects_tuple<> storage; + internal::serializer_context> context{storage}; + auto node = using_fts5( + make_column("title", &Post::title), + make_column("body", &Post::body)); + auto value = serialize(node, context); + REQUIRE(value == "USING FTS5(\"title\", \"body\")"); +} diff --git a/tests/statement_serializer_tests/schema/virtual_table.cpp b/tests/statement_serializer_tests/schema/virtual_table.cpp new file mode 100644 index 000000000..5cf64fff8 --- /dev/null +++ b/tests/statement_serializer_tests/schema/virtual_table.cpp @@ -0,0 +1,18 @@ +#include +#include + +using namespace sqlite_orm; + +TEST_CASE("statement_serializer FTS5") { + struct Post { + std::string title; + std::string body; + }; + internal::db_objects_tuple<> storage; + internal::serializer_context> context{storage}; + auto node = make_virtual_table("posts", using_fts5( + make_column("title", &Post::title), + make_column("body", &Post::body))); + auto value = serialize(node, context); + REQUIRE(value == "CREATE VIRTUAL TABLE IF NOT EXISTS \"posts\" USING FTS5(\"title\", \"body\")"); +} diff --git a/tests/static_tests/node_tuple.cpp b/tests/static_tests/node_tuple.cpp index 874dada68..3a5080407 100644 --- a/tests/static_tests/node_tuple.cpp +++ b/tests/static_tests/node_tuple.cpp @@ -52,6 +52,14 @@ TEST_CASE("Node tuple") { static_assert(is_same::value, "literal int"); STATIC_REQUIRE(is_same, tuple<>>::value); } + SECTION("is_equal_with_table_t") { + auto node = is_equal(std::string("Claude")); + using Node = decltype(node); + using Tuple = node_tuple_t; + using Expected = tuple; + static_assert(is_same::value, "is_equal_with_table_t"); + STATIC_REQUIRE(is_same, tuple>::value); + } SECTION("binary_condition") { using namespace internal; SECTION("5 < 6.0f") { @@ -433,6 +441,12 @@ TEST_CASE("Node tuple") { using Tuple = node_tuple_t; STATIC_REQUIRE(is_same>::value); } + SECTION("match") { + auto expression = match(std::string("Plazma")); + using Expression = decltype(expression); + using Tuple = node_tuple_t; + STATIC_REQUIRE(is_same>::value); + } SECTION("select") { SECTION("select(&User::id)") { auto sel = select(&User::id); diff --git a/third_party/amalgamate/config.json b/third_party/amalgamate/config.json index 21d8a0659..c3f1d9f9c 100755 --- a/third_party/amalgamate/config.json +++ b/third_party/amalgamate/config.json @@ -19,7 +19,7 @@ "dev/typed_comparator.h", "dev/select_constraints.h", "dev/table_info.h", - "dev/triggers.h", + "dev/schema/triggers.h", "dev/statement_finalizer.h", "dev/arithmetic_tag.h", "dev/pointer_value.h", @@ -27,9 +27,9 @@ "dev/row_extractor.h", "dev/util.h", "dev/sync_schema_result.h", - "dev/index.h", + "dev/schema/index.h", "dev/rowid.h", - "dev/table.h", + "dev/schema/table.h", "dev/storage_impl.h", "dev/default_value_extractor.h", "dev/storage.h",