diff --git a/dev/ast/set.h b/dev/ast/set.h index aa9c20846..ed5aa3751 100644 --- a/dev/ast/set.h +++ b/dev/ast/set.h @@ -51,7 +51,7 @@ namespace sqlite_orm { template void push_back(assign_t assign) { auto newContext = this->context; - newContext.skip_table_name = true; + newContext.omit_table_name = true; // 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; @@ -108,7 +108,6 @@ SQLITE_ORM_EXPORT namespace sqlite_orm { */ template internal::dynamic_set_t> dynamic_set(const S& storage) { - internal::serializer_context_builder builder(storage); - return builder(); + return {obtain_db_objects(storage)}; } } diff --git a/dev/column_names_getter.h b/dev/column_names_getter.h index 3b5dfc658..1200cc5dd 100644 --- a/dev/column_names_getter.h +++ b/dev/column_names_getter.h @@ -33,7 +33,7 @@ namespace sqlite_orm { if (definedOrder) { auto& table = pick_table>(context.db_objects); collectedExpressions.reserve(collectedExpressions.size() + table.template count_of()); - table.for_each_column([qualified = !context.skip_table_name, + table.for_each_column([qualified = !context.omit_table_name, &tableName = table.name, &collectedExpressions](const column_identifier& column) { if constexpr (is_alias::value) { @@ -50,7 +50,7 @@ namespace sqlite_orm { collectedExpressions.reserve(collectedExpressions.size() + 1); if constexpr (is_alias::value) { collectedExpressions.push_back(quote_identifier(alias_extractor::extract()) + ".*"); - } else if (!context.skip_table_name) { + } else if (!context.omit_table_name) { const basic_table& table = pick_table>(context.db_objects); collectedExpressions.push_back(quote_identifier(table.name) + ".*"); } else { diff --git a/dev/conditions.h b/dev/conditions.h index f565912d0..24ae7446c 100644 --- a/dev/conditions.h +++ b/dev/conditions.h @@ -493,7 +493,7 @@ namespace sqlite_orm { template void push_back(order_by_t orderBy) { auto newContext = this->context; - newContext.skip_table_name = false; + newContext.omit_table_name = false; auto columnName = serialize(orderBy._expression, newContext); this->entries.emplace_back(std::move(columnName), std::move(orderBy._collate_argument), orderBy._order); } @@ -1149,8 +1149,7 @@ SQLITE_ORM_EXPORT namespace sqlite_orm { template internal::dynamic_order_by_t> dynamic_order_by(const S& storage) { - internal::serializer_context_builder builder(storage); - return builder(); + return {obtain_db_objects(storage)}; } /** diff --git a/dev/cte_column_names_collector.h b/dev/cte_column_names_collector.h index fc3c42d4a..b02fbf204 100644 --- a/dev/cte_column_names_collector.h +++ b/dev/cte_column_names_collector.h @@ -57,7 +57,7 @@ namespace sqlite_orm { SQLITE_ORM_STATIC_CALLOP std::vector operator()(const expression_type& t, const Ctx& context) SQLITE_ORM_OR_CONST_CALLOP { auto newContext = context; - newContext.skip_table_name = true; + newContext.omit_table_name = true; std::string columnName = serialize(t, newContext); if (columnName.empty()) { throw std::system_error{orm_error_code::column_not_found}; @@ -137,7 +137,7 @@ namespace sqlite_orm { std::vector columnNames; columnNames.reserve(size_t(cols.count)); auto newContext = context; - newContext.skip_table_name = true; + newContext.omit_table_name = true; iterate_tuple(cols.columns, [&columnNames, &newContext](auto& m) { using value_type = polyfill::remove_cvref_t; diff --git a/dev/implementations/storage_definitions.h b/dev/implementations/storage_definitions.h index 2bb22103f..74a180141 100644 --- a/dev/implementations/storage_definitions.h +++ b/dev/implementations/storage_definitions.h @@ -24,9 +24,9 @@ namespace sqlite_orm { namespace internal { template template> - sync_schema_result storage_t::sync_table([[maybe_unused]] const Table& table, - [[maybe_unused]] sqlite3* db, - [[maybe_unused]] bool preserve) { + sync_schema_result storage_t::sync_dbo([[maybe_unused]] const Table& table, + [[maybe_unused]] sqlite3* db, + [[maybe_unused]] bool preserve) { if constexpr ( #ifdef SQLITE_ENABLE_DBSTAT_VTAB std::is_same, dbstat>::value || diff --git a/dev/mapped_view.h b/dev/mapped_view.h index aa72d1f66..57ffc8a92 100644 --- a/dev/mapped_view.h +++ b/dev/mapped_view.h @@ -42,7 +42,7 @@ namespace sqlite_orm { auto& dbObjects = obtain_db_objects(this->storage); context_t context{dbObjects}; - context.skip_table_name = false; + context.omit_table_name = false; context.replace_bindable_with_question = true; const std::string sql = serialize(this->expression, context); diff --git a/dev/order_by_serializer.h b/dev/order_by_serializer.h index 1782ca39a..f862c6939 100644 --- a/dev/order_by_serializer.h +++ b/dev/order_by_serializer.h @@ -45,7 +45,7 @@ namespace sqlite_orm { const Ctx& context) SQLITE_ORM_OR_CONST_CALLOP { std::stringstream ss; auto newContext = context; - newContext.skip_table_name = false; + newContext.omit_table_name = false; ss << serialize(orderBy._expression, newContext); seralize_collate(ss, orderBy); diff --git a/dev/prepared_statement.h b/dev/prepared_statement.h index a3b687812..9cfd8477f 100644 --- a/dev/prepared_statement.h +++ b/dev/prepared_statement.h @@ -310,6 +310,48 @@ namespace sqlite_orm { template using is_insert_constraint = std::is_same; + + /** + * Specialize if a type is a DML statement expression. + */ + template + inline constexpr bool is_raw_dml_expression_v = false; + + template + using is_raw_dml_expression = polyfill::bool_constant>; + + template + inline constexpr bool is_raw_dml_expression_v< + DML, + std::enable_if_t< + polyfill:: + disjunction_v, is_replace_raw, is_update_all, is_remove_all>>> = + true; + + template + inline constexpr bool is_raw_dml_expression_v< + With, + std::enable_if_t, + polyfill::disjunction>, + is_replace_raw>, + is_update_all>, + is_remove_all>>>>> = + true; + + /* + * Access the main select expression of a with clause or the passed in select expression. + */ + template = true> + constexpr decltype(auto) access_main_dml(const DML& dml) { + if constexpr (is_with_clause_v) { + return (dml.expression); + } else { + return dml; + } + } + + template + using main_dml_t = polyfill::remove_cvref_t()))>; } } diff --git a/dev/result_set_view.h b/dev/result_set_view.h index 2aa6b2377..53a016855 100644 --- a/dev/result_set_view.h +++ b/dev/result_set_view.h @@ -53,7 +53,7 @@ namespace sqlite_orm::internal { using context_t = serializer_context; context_t context{exprDBOs}; - context.skip_table_name = false; + context.omit_table_name = false; context.replace_bindable_with_question = true; const std::string sql = serialize(this->expression, context); diff --git a/dev/schema/column.h b/dev/schema/column.h index 4d7b02a87..9f1750ff0 100644 --- a/dev/schema/column.h +++ b/dev/schema/column.h @@ -118,6 +118,9 @@ namespace sqlite_orm { template using is_column = polyfill::bool_constant>; + template + using col_index_sequence_of = filter_tuple_sequence_t; + template using col_index_sequence_with_field_type = filter_tuple_sequence_t void for_each_column(L&& lambda) const { - using col_index_sequence = filter_tuple_sequence_t; - iterate_tuple(this->elements, col_index_sequence{}, lambda); + iterate_tuple(this->elements, col_index_sequence_of{}, lambda); } /** @@ -379,8 +378,7 @@ namespace sqlite_orm { */ template void for_each_column(L&& lambda) const { - using col_index_sequence = filter_tuple_sequence_t; - iterate_tuple(this->columns, col_index_sequence{}, lambda); + iterate_tuple(this->columns, col_index_sequence_of{}, lambda); } template = true> diff --git a/dev/select_constraints.h b/dev/select_constraints.h index 2d74ece6c..b374f6e65 100644 --- a/dev/select_constraints.h +++ b/dev/select_constraints.h @@ -318,8 +318,17 @@ namespace sqlite_orm { } } }; + + template + inline constexpr bool is_with_clause_v = polyfill::is_specialization_of::value; +#else + template + inline constexpr bool is_with_clause_v = false; #endif + template + using is_with_clause = polyfill::bool_constant>; + template struct asterisk_t { using type = T; @@ -388,6 +397,38 @@ namespace sqlite_orm { } }; + /** + * Specialize if a type is a select statement expression. + */ + template + inline constexpr bool is_select_expression_v = false; + + template + using is_select_expression = polyfill::bool_constant>; + + template + inline constexpr bool is_select_expression_v>> = true; + + template + inline constexpr bool is_select_expression_v< + With, + std::enable_if_t, is_select>>>> = true; + + /* + * Access the main select expression of a with clause or the passed in select expression. + */ + template = true> + constexpr decltype(auto) access_main_select(const Select& select) { + if constexpr (is_with_clause_v) +#ifdef SQLITE_ORM_CPP20_CONCEPTS_SUPPORTED + requires (is_select_expression_v, + "SQL expression must be a select expression or a with-clause with a select expression"); +#endif + if constexpr (is_select_v) + requires (is_select_expression_v prepare(Select statement) { + if constexpr (is_select_v& statement) { + using ExprDBOs = polyfill::remove_cvref_tdb_objects, + statement.expression))>; // note: it is enough to only use the 'expression DBOs' at compile-time to determine the column results; // because we cannot select objects/structs from a CTE, passing the permanently defined DBOs are enough. - using ColResult = column_result_of_t; - return this->execute_select(statement); - } -#endif - - template - auto execute(const prepared_statement_t>& statement) { - using ColResult = column_result_of_t; + using ColResult = column_result_of_t>; return this->execute_select(statement); } diff --git a/dev/storage_base.h b/dev/storage_base.h index b60ede12a..ecb7417dc 100644 --- a/dev/storage_base.h +++ b/dev/storage_base.h @@ -156,7 +156,7 @@ namespace sqlite_orm { << streaming_identifier(newName) << std::flush; sql = ss.str(); } - this->executor.perform_void_exec(db, sql.data()); + this->executor.perform_void_exec(db, sql.c_str()); } /** @@ -745,7 +745,7 @@ namespace sqlite_orm { void begin_transaction_internal(const std::string& sql) { this->connection->retain(); sqlite3* db = this->connection->get(); - this->executor.perform_void_exec(db, sql.data()); + this->executor.perform_void_exec(db, sql.c_str()); } connection_ref get_connection() { @@ -781,7 +781,7 @@ namespace sqlite_orm { ss << "PRAGMA foreign_keys = " << value << std::flush; sql = ss.str(); } - this->executor.perform_void_exec(db, sql.data()); + this->executor.perform_void_exec(db, sql.c_str()); } bool foreign_keys(sqlite3* db) { @@ -1004,7 +1004,7 @@ namespace sqlite_orm { ss << ' ' << streaming_identifier(tableName) << std::flush; sql = ss.str(); } - this->executor.perform_void_exec(db, sql.data()); + this->executor.perform_void_exec(db, sql.c_str()); } void drop_index_internal(const std::string& indexName, bool ifExists) { @@ -1019,7 +1019,7 @@ namespace sqlite_orm { sql = ss.str(); } auto connection = this->get_connection(); - this->executor.perform_void_exec(connection.get(), sql.data()); + this->executor.perform_void_exec(connection.get(), sql.c_str()); } void drop_trigger_internal(const std::string& triggerName, bool ifExists) { @@ -1034,7 +1034,7 @@ namespace sqlite_orm { sql = ss.str(); } auto connection = this->get_connection(); - this->executor.perform_void_exec(connection.get(), sql.data()); + this->executor.perform_void_exec(connection.get(), sql.c_str()); } static int diff --git a/dev/storage_impl.h b/dev/storage_impl.h index 27e51c72e..e35c7a8d9 100644 --- a/dev/storage_impl.h +++ b/dev/storage_impl.h @@ -103,7 +103,7 @@ namespace sqlite_orm { const column_pointer>&) { using table_type = storage_pick_table_t; using cte_colrefs_tuple = typename cte_mapper_type_t::final_colrefs_tuple; - using column_index_sequence = filter_tuple_sequence_t, is_column>; + using column_index_sequence = col_index_sequence_of>; // note: even though the columns contain the [`aliased_field<>::*`] we perform the lookup using the column references. // lookup ColAlias in the final column references diff --git a/dev/util.h b/dev/util.h index 7e727f352..1b88f5892 100644 --- a/dev/util.h +++ b/dev/util.h @@ -5,9 +5,6 @@ #include // std::string #include // std::move #include // std::function -#ifdef SQLITE_ORM_STRING_VIEW_SUPPORTED -#include // std::string_view -#endif #endif #include "functional/gsl.h" @@ -59,6 +56,28 @@ SQLITE_ORM_EXPORT namespace sqlite_orm { namespace sqlite_orm { namespace internal { + // Wrapper to reduce boiler-plate code + inline sqlite3_stmt* reset_stmt(sqlite3_stmt* stmt) { + sqlite3_reset(stmt); + return stmt; + } + + inline sqlite3_stmt* prepare_stmt(sqlite3* db, serialize_arg_type query) { + sqlite3_stmt* stmt; + const int rc = sqlite3_prepare_v2(db, query.data(), int(query.size()), &stmt, nullptr); + if (rc != SQLITE_OK) SQLITE_ORM_CPP_UNLIKELY /*possible but unexpected*/ { + throw_translated_sqlite_error(rc); + } + return stmt; + } + + template + void perform_single_step(sqlite3_stmt* stmt) { + const int rc = sqlite3_step(stmt); + if (rc != expected) SQLITE_ORM_CPP_UNLIKELY /*possible but unexpected*/ { + throw_translated_sqlite_error(rc); + } + } template void perform_step(sqlite3_stmt* stmt, L&& lambda) { @@ -68,8 +87,26 @@ namespace sqlite_orm { } break; case SQLITE_DONE: return; - default: { - throw_translated_sqlite_error(stmt); + default: + SQLITE_ORM_CPP_UNLIKELY /*possible but unexpected*/ { + throw_translated_sqlite_error(stmt); + } + } + } + + template + void perform_steps(sqlite3_stmt* stmt, L&& lambda) { + for (;;) { + switch (int rc = sqlite3_step(stmt)) { + case SQLITE_ROW: { + lambda(stmt); + } break; + case SQLITE_DONE: + return; + default: + SQLITE_ORM_CPP_UNLIKELY /*possible but unexpected*/ { + throw_translated_sqlite_error(stmt); + } } } } @@ -78,44 +115,48 @@ namespace sqlite_orm { std::function will_run_query; std::function did_run_query; - inline void perform_void_exec(sqlite3* db, orm_gsl::czstring sql) const { + void perform_void_exec(sqlite3* db, orm_gsl::czstring sql) const { if (this->will_run_query) { this->will_run_query(sql); } + const int rc = sqlite3_exec(db, sql, nullptr, nullptr, nullptr); - if (rc != SQLITE_OK) { + if (rc != SQLITE_OK) SQLITE_ORM_CPP_UNLIKELY /*possible but unexpected*/ { throw_translated_sqlite_error(rc); } + if (this->did_run_query) { this->did_run_query(sql); } } - inline void perform_exec(sqlite3* db, - orm_gsl::czstring sql, - int (*callback)(void*, int, orm_gsl::zstring*, orm_gsl::zstring*), - void* user_data) const { + void perform_exec(sqlite3* db, + orm_gsl::czstring sql, + int (*callback)(void*, int, orm_gsl::zstring*, orm_gsl::zstring*), + void* user_data) const { if (this->will_run_query) { this->will_run_query(sql); } + const int rc = sqlite3_exec(db, sql, callback, user_data, nullptr); - if (rc != SQLITE_OK) { + if (rc != SQLITE_OK) SQLITE_ORM_CPP_UNLIKELY /*possible but unexpected*/ { throw_translated_sqlite_error(rc); } + if (this->did_run_query) { this->did_run_query(sql); } } - inline void perform_exec(sqlite3* db, - const std::string& query, - int (*callback)(void*, int, orm_gsl::zstring*, orm_gsl::zstring*), - void* user_data) const { + void perform_exec(sqlite3* db, + const std::string& query, + int (*callback)(void*, int, orm_gsl::zstring*, orm_gsl::zstring*), + void* user_data) const { return perform_exec(db, query.c_str(), callback, user_data); } - template - void perform_steps(sqlite3_stmt* stmt, L&& lambda) const { + template + void perform_single_step(sqlite3_stmt* stmt) const { orm_gsl::czstring sql = nullptr; if (this->will_run_query || this->did_run_query) { sql = sqlite3_sql(stmt); @@ -123,45 +164,47 @@ namespace sqlite_orm { if (this->will_run_query) { this->will_run_query(sql); } - for (;;) { - switch (int rc = sqlite3_step(stmt)) { - case SQLITE_ROW: { - lambda(stmt); - } break; - case SQLITE_DONE: - if (this->did_run_query) { - this->did_run_query(sql); - } - return; - default: { - throw_translated_sqlite_error(stmt); - } - } + + internal::perform_single_step(stmt); + + if (this->did_run_query) { + this->did_run_query(sql); } } - }; - // Wrapper to reduce boiler-plate code - inline sqlite3_stmt* reset_stmt(sqlite3_stmt* stmt) { - sqlite3_reset(stmt); - return stmt; - } + template + void perform_step(sqlite3_stmt* stmt, L&& lambda) const { + orm_gsl::czstring sql = nullptr; + if (this->will_run_query || this->did_run_query) { + sql = sqlite3_sql(stmt); + } + if (this->will_run_query) { + this->will_run_query(sql); + } - inline sqlite3_stmt* prepare_stmt(sqlite3* db, serialize_arg_type query) { - sqlite3_stmt* stmt; - const int rc = sqlite3_prepare_v2(db, query.data(), int(query.size()), &stmt, nullptr); - if (rc != SQLITE_OK) SQLITE_ORM_CPP_UNLIKELY /*possible but unexpected*/ { - throw_translated_sqlite_error(rc); + internal::perform_step(stmt, lambda); + + if (this->did_run_query) { + this->did_run_query(sql); + } } - return stmt; - } - template - void perform_step(sqlite3_stmt* stmt) { - const int rc = sqlite3_step(stmt); - if (rc != expected) { - throw_translated_sqlite_error(rc); + template + void perform_steps(sqlite3_stmt* stmt, L&& lambda) const { + orm_gsl::czstring sql = nullptr; + if (this->will_run_query || this->did_run_query) { + sql = sqlite3_sql(stmt); + } + if (this->will_run_query) { + this->will_run_query(sql); + } + + internal::perform_steps(stmt, lambda); + + if (this->did_run_query) { + this->did_run_query(sql); + } } - } + }; } } diff --git a/include/sqlite_orm/sqlite_orm.h b/include/sqlite_orm/sqlite_orm.h index 214b3559a..2ed7e0fb0 100644 --- a/include/sqlite_orm/sqlite_orm.h +++ b/include/sqlite_orm/sqlite_orm.h @@ -4994,9 +4994,9 @@ namespace sqlite_orm { struct serializer_context_base { bool replace_bindable_with_question = false; - bool skip_table_name = true; + bool omit_table_name = true; bool use_parentheses = true; - bool fts5_columns = false; + bool omit_column_type = false; }; template @@ -5007,20 +5007,6 @@ namespace sqlite_orm { serializer_context(const db_objects_type& dbObjects) : db_objects{dbObjects} {} }; - - template - struct serializer_context_builder { - using storage_type = S; - using db_objects_type = typename storage_type::db_objects_type; - - serializer_context_builder(const storage_type& storage_) : storage{storage_} {} - - serializer_context operator()() const { - return {obtain_db_objects(this->storage)}; - } - - const storage_type& storage; - }; } } @@ -5632,7 +5618,7 @@ namespace sqlite_orm { template void push_back(order_by_t orderBy) { auto newContext = this->context; - newContext.skip_table_name = false; + newContext.omit_table_name = false; auto columnName = serialize(orderBy._expression, newContext); this->entries.emplace_back(std::move(columnName), std::move(orderBy._collate_argument), orderBy._order); } @@ -6288,8 +6274,7 @@ SQLITE_ORM_EXPORT namespace sqlite_orm { template internal::dynamic_order_by_t> dynamic_order_by(const S& storage) { - internal::serializer_context_builder builder(storage); - return builder(); + return {obtain_db_objects(storage)}; } /** @@ -8770,6 +8755,9 @@ namespace sqlite_orm { template using is_column = polyfill::bool_constant>; + template + using col_index_sequence_of = filter_tuple_sequence_t; + template using col_index_sequence_with_field_type = filter_tuple_sequence_t + inline constexpr bool is_with_clause_v = polyfill::is_specialization_of::value; +#else + template + inline constexpr bool is_with_clause_v = false; #endif + template + using is_with_clause = polyfill::bool_constant>; + template struct asterisk_t { using type = T; @@ -9208,6 +9205,38 @@ namespace sqlite_orm { } }; + /** + * Specialize if a type is a select statement expression. + */ + template + inline constexpr bool is_select_expression_v = false; + + template + using is_select_expression = polyfill::bool_constant>; + + template + inline constexpr bool is_select_expression_v>> = true; + + template + inline constexpr bool is_select_expression_v< + With, + std::enable_if_t, is_select>>>> = true; + + /* + * Access the main select expression of a with clause or the passed in select expression. + */ + template = true> + constexpr decltype(auto) access_main_select(const Select& select) { + if constexpr (is_with_clause_v) +#ifdef SQLITE_ORM_CPP20_CONCEPTS_SUPPORTED + requires (is_select_expression_v, + "SQL expression must be a select expression or a with-clause with a select expression"); +#endif + if constexpr (is_select_v) + requires (is_select_expression_v prepare(Select statement) { + if constexpr (is_select_v& statement) { + using ExprDBOs = polyfill::remove_cvref_tdb_objects, + statement.expression))>; // note: it is enough to only use the 'expression DBOs' at compile-time to determine the column results; // because we cannot select objects/structs from a CTE, passing the permanently defined DBOs are enough. - using ColResult = column_result_of_t; - return this->execute_select(statement); - } -#endif - - template - auto execute(const prepared_statement_t>& statement) { - using ColResult = column_result_of_t; + using ColResult = column_result_of_t>; return this->execute_select(statement); } @@ -25416,9 +25309,9 @@ namespace sqlite_orm { namespace internal { template template> - sync_schema_result storage_t::sync_table([[maybe_unused]] const Table& table, - [[maybe_unused]] sqlite3* db, - [[maybe_unused]] bool preserve) { + sync_schema_result storage_t::sync_dbo([[maybe_unused]] const Table& table, + [[maybe_unused]] sqlite3* db, + [[maybe_unused]] bool preserve) { if constexpr ( #ifdef SQLITE_ENABLE_DBSTAT_VTAB std::is_same, dbstat>::value || diff --git a/tests/statement_serializer_tests/column_names.cpp b/tests/statement_serializer_tests/column_names.cpp index b1963cf82..31bbb9dc8 100644 --- a/tests/statement_serializer_tests/column_names.cpp +++ b/tests/statement_serializer_tests/column_names.cpp @@ -21,7 +21,7 @@ TEST_CASE("statement_serializer column names") { REQUIRE(value == R"("id")"); } SECTION("don't skip table name") { - context.skip_table_name = false; + context.omit_table_name = false; auto value = serialize(&User::id, context); REQUIRE(value == R"("users"."id")"); } @@ -159,7 +159,7 @@ TEST_CASE("statement_serializer column names") { SECTION("regular") { using context_t = internal::serializer_context; context_t context{dbObjects}; - context.skip_table_name = false; + context.omit_table_name = false; using als = alias_a; auto value = serialize(alias_column(&Object::id), context); REQUIRE(value == R"("a"."id")"); @@ -171,7 +171,7 @@ TEST_CASE("statement_serializer column names") { internal::db_objects_cat(dbObjects, internal::make_cte_table(dbObjects, 1_ctealias().as(select(1)))); using context_t = internal::serializer_context; context_t context{dbObjects2}; - context.skip_table_name = false; + context.omit_table_name = false; constexpr auto als = "a"_alias.for_<1_ctealias>(); auto value = serialize(als->*1_colalias, context); REQUIRE(value == R"("a"."1")"); diff --git a/tests/statement_serializer_tests/schema/column.cpp b/tests/statement_serializer_tests/schema/column.cpp index 0dec2393c..9fad196c6 100644 --- a/tests/statement_serializer_tests/schema/column.cpp +++ b/tests/statement_serializer_tests/schema/column.cpp @@ -14,7 +14,7 @@ TEST_CASE("statement_serializer column") { std::string value; std::string expected; SECTION("with types and constraints") { - context.fts5_columns = false; + context.omit_column_type = false; SECTION("id INTEGER (implicit) NOT NULL") { auto column = make_column("id", &User::id); value = serialize(column, context); @@ -82,7 +82,7 @@ TEST_CASE("statement_serializer column") { } } SECTION("without types and constraints") { - context.fts5_columns = true; + context.omit_column_type = true; SECTION("id INTEGER NOT NULL") { auto column = make_column("id", &User::id); value = serialize(column, context); diff --git a/tests/statement_serializer_tests/statements/select.cpp b/tests/statement_serializer_tests/statements/select.cpp index f21b125e8..1402562fb 100644 --- a/tests/statement_serializer_tests/statements/select.cpp +++ b/tests/statement_serializer_tests/statements/select.cpp @@ -192,7 +192,7 @@ TEST_CASE("statement_serializer select_t") { // issue #1106 SECTION("multi") { auto expression = columns(asterisk(), asterisk(true)); - context.skip_table_name = false; + context.omit_table_name = false; context.use_parentheses = false; stringValue = serialize(expression, context); expected = R"("users".*, "users"."id", "users"."name")"; @@ -228,7 +228,7 @@ TEST_CASE("statement_serializer select_t") { where(is_null(alias_column(&Employee::m_deptno)))); expression.highest_level = true; internal::serializer_context context{storage}; - context.skip_table_name = false; + context.omit_table_name = false; stringValue = serialize(expression, context); expected = R"(SELECT "d".* FROM "Dept" "d" LEFT JOIN "Emp" "e" ON "d"."deptno" = "e"."deptno" WHERE ("e"."deptno" IS NULL))"; diff --git a/tests/statement_serializer_tests/table_constraints/primary_key.cpp b/tests/statement_serializer_tests/table_constraints/primary_key.cpp index d843e3320..e55cb4d02 100644 --- a/tests/statement_serializer_tests/table_constraints/primary_key.cpp +++ b/tests/statement_serializer_tests/table_constraints/primary_key.cpp @@ -24,7 +24,7 @@ TEST_CASE("statement_serializer primary key table constraint") { auto dbObjects = db_objects_t{table1, table2}; using context_t = internal::serializer_context; context_t context{dbObjects}; - context.skip_table_name = false; + context.omit_table_name = false; SECTION("single column pk") { constexpr auto pk = primary_key(&User::id); diff --git a/tests/static_tests/table_static_tests.cpp b/tests/static_tests/table_static_tests.cpp index 7020a7969..d35d9318f 100644 --- a/tests/static_tests/table_static_tests.cpp +++ b/tests/static_tests/table_static_tests.cpp @@ -2,6 +2,8 @@ #include using namespace sqlite_orm; +using internal::col_index_sequence_of, internal::col_index_sequence_excluding, internal::col_index_sequence_with, + internal::col_index_sequence_with_field_type; using internal::is_column; using internal::is_primary_key; @@ -18,84 +20,139 @@ TEST_CASE("table static count_of()") { }; { // 1 column no pk auto table = make_table("users", make_column("id", &User::id)); + using elements_type = decltype(table.elements); STATIC_REQUIRE(table.count_of() == 1); STATIC_REQUIRE(table.count_of() == 0); STATIC_REQUIRE(table.count_of_columns_with() == 0); - STATIC_REQUIRE(dedicated_pk_columns_count_t::value == 0); + STATIC_REQUIRE(col_index_sequence_of::size() == 1); + STATIC_REQUIRE(col_index_sequence_with::size() == 0); + STATIC_REQUIRE(col_index_sequence_excluding::size() == 1); + STATIC_REQUIRE(col_index_sequence_with_field_type::size() == 1); + STATIC_REQUIRE(dedicated_pk_columns_count_t::value == 0); } { // 1 column with 1 inline pk auto table = make_table("users", make_column("id", &User::id, primary_key())); + using elements_type = decltype(table.elements); STATIC_REQUIRE(table.count_of() == 1); STATIC_REQUIRE(table.count_of() == 0); STATIC_REQUIRE(table.count_of_columns_with() == 1); - STATIC_REQUIRE(dedicated_pk_columns_count_t::value == 0); + STATIC_REQUIRE(col_index_sequence_of::size() == 1); + STATIC_REQUIRE(col_index_sequence_with::size() == 1); + STATIC_REQUIRE(col_index_sequence_excluding::size() == 0); + STATIC_REQUIRE(col_index_sequence_with_field_type::size() == 1); + STATIC_REQUIRE(dedicated_pk_columns_count_t::value == 0); } { // 1 column with 1 inline pk autoincrement auto table = make_table("users", make_column("id", &User::id, primary_key().autoincrement())); + using elements_type = decltype(table.elements); STATIC_REQUIRE(table.count_of() == 1); STATIC_REQUIRE(table.count_of() == 0); STATIC_REQUIRE(table.count_of_columns_with() == 1); - STATIC_REQUIRE(dedicated_pk_columns_count_t::value == 0); + STATIC_REQUIRE(col_index_sequence_of::size() == 1); + STATIC_REQUIRE(col_index_sequence_with::size() == 1); + STATIC_REQUIRE(col_index_sequence_excluding::size() == 0); + STATIC_REQUIRE(col_index_sequence_with_field_type::size() == 1); + STATIC_REQUIRE(dedicated_pk_columns_count_t::value == 0); } { // 1 column with 1 dedicated pk auto table = make_table("users", make_column("id", &User::id), primary_key(&User::id)); + using elements_type = decltype(table.elements); STATIC_REQUIRE(table.count_of() == 1); STATIC_REQUIRE(table.count_of() == 1); STATIC_REQUIRE(table.count_of_columns_with() == 0); - STATIC_REQUIRE(dedicated_pk_columns_count_t::value == 1); + STATIC_REQUIRE(dedicated_pk_columns_count_t::value == 1); + STATIC_REQUIRE(col_index_sequence_of::size() == 1); + STATIC_REQUIRE(col_index_sequence_with::size() == 0); + STATIC_REQUIRE(col_index_sequence_excluding::size() == 1); + STATIC_REQUIRE(col_index_sequence_with_field_type::size() == 1); } { // 1 column with 1 dedicated pk autoincrement auto table = make_table("users", make_column("id", &User::id), primary_key(&User::id).autoincrement()); + using elements_type = decltype(table.elements); STATIC_REQUIRE(table.count_of() == 1); STATIC_REQUIRE(table.count_of() == 1); STATIC_REQUIRE(table.count_of_columns_with() == 0); - STATIC_REQUIRE(dedicated_pk_columns_count_t::value == 1); + STATIC_REQUIRE(col_index_sequence_of::size() == 1); + STATIC_REQUIRE(col_index_sequence_with::size() == 0); + STATIC_REQUIRE(col_index_sequence_excluding::size() == 1); + STATIC_REQUIRE(col_index_sequence_with_field_type::size() == 1); + STATIC_REQUIRE(dedicated_pk_columns_count_t::value == 1); } { // 2 columns no pk auto table = make_table("users", make_column("id", &User::id), make_column("id", &User::name)); + using elements_type = decltype(table.elements); STATIC_REQUIRE(table.count_of() == 2); STATIC_REQUIRE(table.count_of() == 0); STATIC_REQUIRE(table.count_of_columns_with() == 0); - STATIC_REQUIRE(dedicated_pk_columns_count_t::value == 0); + STATIC_REQUIRE(col_index_sequence_of::size() == 2); + STATIC_REQUIRE(col_index_sequence_with::size() == 0); + STATIC_REQUIRE(col_index_sequence_excluding::size() == 2); + STATIC_REQUIRE(col_index_sequence_with_field_type::size() == 1); + STATIC_REQUIRE(dedicated_pk_columns_count_t::value == 0); } { // 2 columns with 1 inline id pk auto table = make_table("users", make_column("id", &User::id, primary_key()), make_column("id", &User::name)); + using elements_type = decltype(table.elements); STATIC_REQUIRE(table.count_of() == 2); STATIC_REQUIRE(table.count_of() == 0); STATIC_REQUIRE(table.count_of_columns_with() == 1); - STATIC_REQUIRE(dedicated_pk_columns_count_t::value == 0); + STATIC_REQUIRE(col_index_sequence_of::size() == 2); + STATIC_REQUIRE(col_index_sequence_with::size() == 1); + STATIC_REQUIRE(col_index_sequence_excluding::size() == 1); + STATIC_REQUIRE(col_index_sequence_with_field_type::size() == 1); + STATIC_REQUIRE(dedicated_pk_columns_count_t::value == 0); } { // 2 columns with 1 inline name pk auto table = make_table("users", make_column("id", &User::id), make_column("id", &User::name, primary_key())); + using elements_type = decltype(table.elements); STATIC_REQUIRE(table.count_of() == 2); STATIC_REQUIRE(table.count_of() == 0); STATIC_REQUIRE(table.count_of_columns_with() == 1); - STATIC_REQUIRE(dedicated_pk_columns_count_t::value == 0); + STATIC_REQUIRE(col_index_sequence_of::size() == 2); + STATIC_REQUIRE(col_index_sequence_with::size() == 1); + STATIC_REQUIRE(col_index_sequence_excluding::size() == 1); + STATIC_REQUIRE(col_index_sequence_with_field_type::size() == 1); + STATIC_REQUIRE(dedicated_pk_columns_count_t::value == 0); } { // 2 columns with 1 dedicated id pk auto table = make_table("users", make_column("id", &User::id), make_column("id", &User::name), primary_key(&User::id)); + using elements_type = decltype(table.elements); STATIC_REQUIRE(table.count_of() == 2); STATIC_REQUIRE(table.count_of() == 1); STATIC_REQUIRE(table.count_of_columns_with() == 0); - STATIC_REQUIRE(dedicated_pk_columns_count_t::value == 1); + STATIC_REQUIRE(col_index_sequence_of::size() == 2); + STATIC_REQUIRE(col_index_sequence_with::size() == 0); + STATIC_REQUIRE(col_index_sequence_excluding::size() == 2); + STATIC_REQUIRE(col_index_sequence_with_field_type::size() == 1); + STATIC_REQUIRE(dedicated_pk_columns_count_t::value == 1); } { // 2 columns with 1 dedicated name pk auto table = make_table("users", make_column("id", &User::id), make_column("id", &User::name), primary_key(&User::name)); + using elements_type = decltype(table.elements); STATIC_REQUIRE(table.count_of() == 2); STATIC_REQUIRE(table.count_of() == 1); STATIC_REQUIRE(table.count_of_columns_with() == 0); - STATIC_REQUIRE(dedicated_pk_columns_count_t::value == 1); + STATIC_REQUIRE(col_index_sequence_of::size() == 2); + STATIC_REQUIRE(col_index_sequence_with::size() == 0); + STATIC_REQUIRE(col_index_sequence_excluding::size() == 2); + STATIC_REQUIRE(col_index_sequence_with_field_type::size() == 1); + STATIC_REQUIRE(dedicated_pk_columns_count_t::value == 1); } { // 2 columns with 2 dedicated pks auto table = make_table("users", make_column("id", &User::id), make_column("id", &User::name), primary_key(&User::id, &User::name)); + using elements_type = decltype(table.elements); STATIC_REQUIRE(table.count_of() == 2); STATIC_REQUIRE(table.count_of() == 1); STATIC_REQUIRE(table.count_of_columns_with() == 0); - STATIC_REQUIRE(dedicated_pk_columns_count_t::value == 2); + STATIC_REQUIRE(col_index_sequence_of::size() == 2); + STATIC_REQUIRE(col_index_sequence_with::size() == 0); + STATIC_REQUIRE(col_index_sequence_excluding::size() == 2); + STATIC_REQUIRE(col_index_sequence_with_field_type::size() == 1); + STATIC_REQUIRE(dedicated_pk_columns_count_t::value == 2); } }