From 028d1b0d48a90bd744e4fc87845f39855ddbef76 Mon Sep 17 00:00:00 2001 From: fnc12 Date: Wed, 1 Jan 2020 15:57:01 +0600 Subject: [PATCH 001/132] added hex core function --- dev/core_functions.h | 12 ++++++ examples/core_functions.cpp | 3 ++ include/sqlite_orm/sqlite_orm.h | 76 +++++++++++++++++++++++++++++---- tests/core_functions_tests.cpp | 19 +++++++++ 4 files changed, 102 insertions(+), 8 deletions(-) diff --git a/dev/core_functions.h b/dev/core_functions.h index e3091c9c1..5481fb6d3 100644 --- a/dev/core_functions.h +++ b/dev/core_functions.h @@ -81,6 +81,12 @@ namespace sqlite_orm { } }; + struct hex_string { + operator std::string() const { + return "HEX"; + } + }; + #if SQLITE_VERSION_NUMBER >= 3007016 struct char_string { @@ -283,6 +289,12 @@ namespace sqlite_orm { return {std::move(args)}; } + template + core_functions::core_function_t hex(X x) { + std::tuple args{std::forward(x)}; + return {std::move(args)}; + } + #if SQLITE_VERSION_NUMBER >= 3007016 /** diff --git a/examples/core_functions.cpp b/examples/core_functions.cpp index 121040cf9..050e27731 100644 --- a/examples/core_functions.cpp +++ b/examples/core_functions.cpp @@ -257,5 +257,8 @@ int main(int, char **argv) { // SELECT substr('SQLite substr', 1, 6); cout << "substr('SQLite substr', 1, 6) = " << storage.select(substr("SQLite substr", 1, 6)).front() << endl; + // SELECT hex(67); + cout << "hex(67) = " << storage.select(hex(67)).front() << endl; + return 0; } diff --git a/include/sqlite_orm/sqlite_orm.h b/include/sqlite_orm/sqlite_orm.h index d908f3d98..1776bcf5e 100644 --- a/include/sqlite_orm/sqlite_orm.h +++ b/include/sqlite_orm/sqlite_orm.h @@ -27,7 +27,7 @@ __pragma(push_macro("min")) #include #include // std::ostringstream - namespace sqlite_orm { +namespace sqlite_orm { enum class orm_error_code { not_found = 1, @@ -43,6 +43,7 @@ __pragma(push_macro("min")) invalid_collate_argument_enum, failed_to_init_a_backup, }; + } namespace sqlite_orm { @@ -220,6 +221,7 @@ namespace sqlite_orm { // #include "static_magic.h" + #include // std::false_type, std::true_type, std::integral_constant namespace sqlite_orm { @@ -251,6 +253,7 @@ namespace sqlite_orm { } + namespace sqlite_orm { // got from here http://stackoverflow.com/questions/25958259/how-do-i-find-out-if-a-tuple-contains-a-type @@ -962,6 +965,7 @@ namespace sqlite_orm { // #include "constraints.h" + namespace sqlite_orm { namespace internal { @@ -1200,6 +1204,7 @@ namespace sqlite_orm { // #include "constraints.h" + namespace sqlite_orm { namespace internal { @@ -1655,6 +1660,7 @@ namespace sqlite_orm { // #include "optional_container.h" + namespace sqlite_orm { namespace internal { @@ -1687,6 +1693,7 @@ namespace sqlite_orm { } } + namespace sqlite_orm { namespace internal { @@ -3175,6 +3182,7 @@ namespace sqlite_orm { // #include "conditions.h" + namespace sqlite_orm { namespace internal { @@ -3294,6 +3302,7 @@ namespace sqlite_orm { // #include "is_base_of_template.h" + #include // std::true_type, std::false_type, std::declval namespace sqlite_orm { @@ -3331,6 +3340,7 @@ namespace sqlite_orm { } } + namespace sqlite_orm { namespace core_functions { @@ -3402,6 +3412,12 @@ namespace sqlite_orm { } }; + struct hex_string { + operator std::string() const { + return "HEX"; + } + }; + #if SQLITE_VERSION_NUMBER >= 3007016 struct char_string { @@ -3604,6 +3620,12 @@ namespace sqlite_orm { return {std::move(args)}; } + template + core_functions::core_function_t hex(X x) { + std::tuple args{std::forward(x)}; + return {std::move(args)}; + } + #if SQLITE_VERSION_NUMBER >= 3007016 /** @@ -4043,6 +4065,7 @@ namespace sqlite_orm { // #include "optional_container.h" + namespace sqlite_orm { namespace internal { @@ -4399,6 +4422,7 @@ namespace sqlite_orm { // #include "column.h" + namespace sqlite_orm { namespace internal { @@ -4505,6 +4529,7 @@ namespace sqlite_orm { // #include "is_std_ptr.h" + namespace sqlite_orm { /** @@ -4532,6 +4557,7 @@ namespace sqlite_orm { }; } + namespace sqlite_orm { /** @@ -4742,6 +4768,7 @@ namespace sqlite_orm { // #include "journal_mode.h" + #include // std::string #include // std::unique_ptr #include // std::array @@ -4802,6 +4829,7 @@ namespace sqlite_orm { // #include "error_code.h" + namespace sqlite_orm { /** @@ -5181,6 +5209,7 @@ namespace sqlite_orm { // #include "alias.h" + namespace sqlite_orm { namespace internal { @@ -5429,6 +5458,7 @@ namespace sqlite_orm { } } + namespace sqlite_orm { namespace internal { @@ -5706,6 +5736,7 @@ namespace sqlite_orm { // #include "column.h" + namespace sqlite_orm { namespace internal { @@ -6007,10 +6038,12 @@ namespace sqlite_orm { // #include "field_value_holder.h" + #include // std::enable_if // #include "column.h" + namespace sqlite_orm { namespace internal { @@ -6033,6 +6066,7 @@ namespace sqlite_orm { } } + namespace sqlite_orm { namespace internal { @@ -6593,6 +6627,7 @@ namespace sqlite_orm { // #include "view.h" + #include // std::shared_ptr #include // std::string #include // std::forward, std::move @@ -6608,6 +6643,7 @@ namespace sqlite_orm { // #include "iterator.h" + #include // std::shared_ptr, std::unique_ptr, std::make_shared #include #include // std::decay @@ -6623,6 +6659,7 @@ namespace sqlite_orm { // #include "error_code.h" + namespace sqlite_orm { namespace internal { @@ -6751,6 +6788,7 @@ namespace sqlite_orm { // #include "ast_iterator.h" + #include // std::vector #include // std::reference_wrapper @@ -6766,6 +6804,7 @@ namespace sqlite_orm { // #include "prepared_statement.h" + #include #include // std::iterator_traits #include // std::string @@ -6774,12 +6813,14 @@ namespace sqlite_orm { // #include "connection_holder.h" + #include #include // std::string #include // std::system_error // #include "error_code.h" + namespace sqlite_orm { namespace internal { @@ -6854,6 +6895,7 @@ namespace sqlite_orm { // #include "select_constraints.h" + namespace sqlite_orm { namespace internal { @@ -7225,6 +7267,7 @@ namespace sqlite_orm { #endif // SQLITE_ORM_OPTIONAL_SUPPORTED } + namespace sqlite_orm { namespace internal { @@ -7682,6 +7725,7 @@ namespace sqlite_orm { // #include "connection_holder.h" + namespace sqlite_orm { namespace internal { @@ -7740,6 +7784,7 @@ namespace sqlite_orm { // #include "storage_base.h" + #include // std::function, std::bind #include #include // std::string @@ -7754,6 +7799,7 @@ namespace sqlite_orm { // #include "pragma.h" + #include // std::string #include #include // std::function @@ -7767,6 +7813,7 @@ namespace sqlite_orm { // #include "connection_holder.h" + namespace sqlite_orm { namespace internal { @@ -7887,6 +7934,7 @@ namespace sqlite_orm { // #include "limit_accesor.h" + #include #include // std::map #include // std::function @@ -7894,6 +7942,7 @@ namespace sqlite_orm { // #include "connection_holder.h" + namespace sqlite_orm { namespace internal { @@ -8027,10 +8076,12 @@ namespace sqlite_orm { // #include "transaction_guard.h" + #include // std::function // #include "connection_holder.h" + namespace sqlite_orm { namespace internal { @@ -8105,6 +8156,7 @@ namespace sqlite_orm { // #include "backup.h" + #include #include // std::string #include @@ -8113,6 +8165,7 @@ namespace sqlite_orm { // #include "connection_holder.h" + namespace sqlite_orm { namespace internal { @@ -8178,6 +8231,7 @@ namespace sqlite_orm { } } + namespace sqlite_orm { namespace internal { @@ -8713,11 +8767,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 { @@ -8835,6 +8891,7 @@ namespace sqlite_orm { } } + namespace sqlite_orm { namespace conditions { @@ -11863,19 +11920,20 @@ __pragma(pop_macro("min")) #include // std::pair #include // std::reference_wrapper - // #include "conditions.h" +// #include "conditions.h" + +// #include "operators.h" - // #include "operators.h" +// #include "select_constraints.h" - // #include "select_constraints.h" +// #include "prepared_statement.h" - // #include "prepared_statement.h" +// #include "optional_container.h" - // #include "optional_container.h" +// #include "core_functions.h" - // #include "core_functions.h" - namespace sqlite_orm { +namespace sqlite_orm { namespace internal { @@ -12157,6 +12215,7 @@ __pragma(pop_macro("min")) // #include "expression_object_type.h" + namespace sqlite_orm { template @@ -12324,6 +12383,7 @@ namespace sqlite_orm { // #include "constraints.h" + namespace sqlite_orm { namespace internal { diff --git a/tests/core_functions_tests.cpp b/tests/core_functions_tests.cpp index f8edb59e2..4912ab3bb 100644 --- a/tests/core_functions_tests.cpp +++ b/tests/core_functions_tests.cpp @@ -182,3 +182,22 @@ TEST_CASE("abs") { REQUIRE(rows.front()); REQUIRE(*rows.front() == 10); } + +TEST_CASE("hex") { + auto storage = make_storage({}); + { + auto rows = storage.select(hex(67)); + REQUIRE(rows.size() == 1); + REQUIRE(rows.front() == "3637"); + } + { + auto rows = storage.select(hex("รค")); + REQUIRE(rows.size() == 1); + REQUIRE(rows.front() == "C3A4"); + } + { + auto rows = storage.select(hex(nullptr)); + REQUIRE(rows.size() == 1); + REQUIRE(rows.front() == std::string()); + } +} From 01ac9414d6ad269ae346bf1e09aae8b42aa2e9b1 Mon Sep 17 00:00:00 2001 From: fnc12 Date: Wed, 1 Jan 2020 15:59:16 +0600 Subject: [PATCH 002/132] added a comment --- dev/core_functions.h | 3 +++ include/sqlite_orm/sqlite_orm.h | 3 +++ 2 files changed, 6 insertions(+) diff --git a/dev/core_functions.h b/dev/core_functions.h index 5481fb6d3..a6e98f334 100644 --- a/dev/core_functions.h +++ b/dev/core_functions.h @@ -289,6 +289,9 @@ namespace sqlite_orm { return {std::move(args)}; } + /** + * HEX(X) function https://sqlite.org/lang_corefunc.html#hex + */ template core_functions::core_function_t hex(X x) { std::tuple args{std::forward(x)}; diff --git a/include/sqlite_orm/sqlite_orm.h b/include/sqlite_orm/sqlite_orm.h index 1776bcf5e..688e10749 100644 --- a/include/sqlite_orm/sqlite_orm.h +++ b/include/sqlite_orm/sqlite_orm.h @@ -3620,6 +3620,9 @@ namespace sqlite_orm { return {std::move(args)}; } + /** + * HEX(X) function https://sqlite.org/lang_corefunc.html#hex + */ template core_functions::core_function_t hex(X x) { std::tuple args{std::forward(x)}; From a8af06ce32bed481121d3ab8eaa74879fdafcd4f Mon Sep 17 00:00:00 2001 From: fnc12 Date: Wed, 1 Jan 2020 16:01:07 +0600 Subject: [PATCH 003/132] fixed tab for the comment --- dev/core_functions.h | 4 ++-- include/sqlite_orm/sqlite_orm.h | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/dev/core_functions.h b/dev/core_functions.h index a6e98f334..2aa9267a8 100644 --- a/dev/core_functions.h +++ b/dev/core_functions.h @@ -290,8 +290,8 @@ namespace sqlite_orm { } /** - * HEX(X) function https://sqlite.org/lang_corefunc.html#hex - */ + * HEX(X) function https://sqlite.org/lang_corefunc.html#hex + */ template core_functions::core_function_t hex(X x) { std::tuple args{std::forward(x)}; diff --git a/include/sqlite_orm/sqlite_orm.h b/include/sqlite_orm/sqlite_orm.h index 688e10749..d439fde26 100644 --- a/include/sqlite_orm/sqlite_orm.h +++ b/include/sqlite_orm/sqlite_orm.h @@ -3621,8 +3621,8 @@ namespace sqlite_orm { } /** - * HEX(X) function https://sqlite.org/lang_corefunc.html#hex - */ + * HEX(X) function https://sqlite.org/lang_corefunc.html#hex + */ template core_functions::core_function_t hex(X x) { std::tuple args{std::forward(x)}; From 124120b9727d3e84274689e00c9e9558a70761b1 Mon Sep 17 00:00:00 2001 From: fnc12 Date: Thu, 2 Jan 2020 14:38:07 +0600 Subject: [PATCH 004/132] added main header to code format check --- .github/workflows/clang-format-lint.yaml | 2 -- 1 file changed, 2 deletions(-) diff --git a/.github/workflows/clang-format-lint.yaml b/.github/workflows/clang-format-lint.yaml index 56ff33638..fa76253c1 100644 --- a/.github/workflows/clang-format-lint.yaml +++ b/.github/workflows/clang-format-lint.yaml @@ -10,5 +10,3 @@ jobs: - uses: actions/checkout@v1 - name: clang-format lint uses: DoozyX/clang-format-lint-action@v0.3.1 - with: - exclude: ./include From d3234fd1144ce8694d36bb452b47a5cfd091474e Mon Sep 17 00:00:00 2001 From: fnc12 Date: Thu, 2 Jan 2020 14:43:37 +0600 Subject: [PATCH 005/132] formatted main header --- include/sqlite_orm/sqlite_orm.h | 64 +++++---------------------------- 1 file changed, 8 insertions(+), 56 deletions(-) diff --git a/include/sqlite_orm/sqlite_orm.h b/include/sqlite_orm/sqlite_orm.h index d439fde26..2bd26bf9a 100644 --- a/include/sqlite_orm/sqlite_orm.h +++ b/include/sqlite_orm/sqlite_orm.h @@ -27,7 +27,7 @@ __pragma(push_macro("min")) #include #include // std::ostringstream -namespace sqlite_orm { + namespace sqlite_orm { enum class orm_error_code { not_found = 1, @@ -43,7 +43,6 @@ namespace sqlite_orm { invalid_collate_argument_enum, failed_to_init_a_backup, }; - } namespace sqlite_orm { @@ -221,7 +220,6 @@ namespace sqlite_orm { // #include "static_magic.h" - #include // std::false_type, std::true_type, std::integral_constant namespace sqlite_orm { @@ -253,7 +251,6 @@ namespace sqlite_orm { } - namespace sqlite_orm { // got from here http://stackoverflow.com/questions/25958259/how-do-i-find-out-if-a-tuple-contains-a-type @@ -965,7 +962,6 @@ namespace sqlite_orm { // #include "constraints.h" - namespace sqlite_orm { namespace internal { @@ -1204,7 +1200,6 @@ namespace sqlite_orm { // #include "constraints.h" - namespace sqlite_orm { namespace internal { @@ -1660,7 +1655,6 @@ namespace sqlite_orm { // #include "optional_container.h" - namespace sqlite_orm { namespace internal { @@ -1693,7 +1687,6 @@ namespace sqlite_orm { } } - namespace sqlite_orm { namespace internal { @@ -3182,7 +3175,6 @@ namespace sqlite_orm { // #include "conditions.h" - namespace sqlite_orm { namespace internal { @@ -3302,7 +3294,6 @@ namespace sqlite_orm { // #include "is_base_of_template.h" - #include // std::true_type, std::false_type, std::declval namespace sqlite_orm { @@ -3340,7 +3331,6 @@ namespace sqlite_orm { } } - namespace sqlite_orm { namespace core_functions { @@ -4068,7 +4058,6 @@ namespace sqlite_orm { // #include "optional_container.h" - namespace sqlite_orm { namespace internal { @@ -4425,7 +4414,6 @@ namespace sqlite_orm { // #include "column.h" - namespace sqlite_orm { namespace internal { @@ -4532,7 +4520,6 @@ namespace sqlite_orm { // #include "is_std_ptr.h" - namespace sqlite_orm { /** @@ -4560,7 +4547,6 @@ namespace sqlite_orm { }; } - namespace sqlite_orm { /** @@ -4771,7 +4757,6 @@ namespace sqlite_orm { // #include "journal_mode.h" - #include // std::string #include // std::unique_ptr #include // std::array @@ -4832,7 +4817,6 @@ namespace sqlite_orm { // #include "error_code.h" - namespace sqlite_orm { /** @@ -5212,7 +5196,6 @@ namespace sqlite_orm { // #include "alias.h" - namespace sqlite_orm { namespace internal { @@ -5461,7 +5444,6 @@ namespace sqlite_orm { } } - namespace sqlite_orm { namespace internal { @@ -5739,7 +5721,6 @@ namespace sqlite_orm { // #include "column.h" - namespace sqlite_orm { namespace internal { @@ -6041,12 +6022,10 @@ namespace sqlite_orm { // #include "field_value_holder.h" - #include // std::enable_if // #include "column.h" - namespace sqlite_orm { namespace internal { @@ -6069,7 +6048,6 @@ namespace sqlite_orm { } } - namespace sqlite_orm { namespace internal { @@ -6630,7 +6608,6 @@ namespace sqlite_orm { // #include "view.h" - #include // std::shared_ptr #include // std::string #include // std::forward, std::move @@ -6646,7 +6623,6 @@ namespace sqlite_orm { // #include "iterator.h" - #include // std::shared_ptr, std::unique_ptr, std::make_shared #include #include // std::decay @@ -6662,7 +6638,6 @@ namespace sqlite_orm { // #include "error_code.h" - namespace sqlite_orm { namespace internal { @@ -6791,7 +6766,6 @@ namespace sqlite_orm { // #include "ast_iterator.h" - #include // std::vector #include // std::reference_wrapper @@ -6807,7 +6781,6 @@ namespace sqlite_orm { // #include "prepared_statement.h" - #include #include // std::iterator_traits #include // std::string @@ -6816,14 +6789,12 @@ namespace sqlite_orm { // #include "connection_holder.h" - #include #include // std::string #include // std::system_error // #include "error_code.h" - namespace sqlite_orm { namespace internal { @@ -6898,7 +6869,6 @@ namespace sqlite_orm { // #include "select_constraints.h" - namespace sqlite_orm { namespace internal { @@ -7270,7 +7240,6 @@ namespace sqlite_orm { #endif // SQLITE_ORM_OPTIONAL_SUPPORTED } - namespace sqlite_orm { namespace internal { @@ -7728,7 +7697,6 @@ namespace sqlite_orm { // #include "connection_holder.h" - namespace sqlite_orm { namespace internal { @@ -7787,7 +7755,6 @@ namespace sqlite_orm { // #include "storage_base.h" - #include // std::function, std::bind #include #include // std::string @@ -7802,7 +7769,6 @@ namespace sqlite_orm { // #include "pragma.h" - #include // std::string #include #include // std::function @@ -7816,7 +7782,6 @@ namespace sqlite_orm { // #include "connection_holder.h" - namespace sqlite_orm { namespace internal { @@ -7937,7 +7902,6 @@ namespace sqlite_orm { // #include "limit_accesor.h" - #include #include // std::map #include // std::function @@ -7945,7 +7909,6 @@ namespace sqlite_orm { // #include "connection_holder.h" - namespace sqlite_orm { namespace internal { @@ -8079,12 +8042,10 @@ namespace sqlite_orm { // #include "transaction_guard.h" - #include // std::function // #include "connection_holder.h" - namespace sqlite_orm { namespace internal { @@ -8159,7 +8120,6 @@ namespace sqlite_orm { // #include "backup.h" - #include #include // std::string #include @@ -8168,7 +8128,6 @@ namespace sqlite_orm { // #include "connection_holder.h" - namespace sqlite_orm { namespace internal { @@ -8234,7 +8193,6 @@ namespace sqlite_orm { } } - namespace sqlite_orm { namespace internal { @@ -8770,13 +8728,11 @@ namespace sqlite_orm { // #include "expression_object_type.h" - #include // std::decay #include // std::reference_wrapper // #include "prepared_statement.h" - namespace sqlite_orm { namespace internal { @@ -8894,7 +8850,6 @@ namespace sqlite_orm { } } - namespace sqlite_orm { namespace conditions { @@ -11923,20 +11878,19 @@ __pragma(pop_macro("min")) #include // std::pair #include // std::reference_wrapper -// #include "conditions.h" - -// #include "operators.h" + // #include "conditions.h" -// #include "select_constraints.h" + // #include "operators.h" -// #include "prepared_statement.h" + // #include "select_constraints.h" -// #include "optional_container.h" + // #include "prepared_statement.h" -// #include "core_functions.h" + // #include "optional_container.h" + // #include "core_functions.h" -namespace sqlite_orm { + namespace sqlite_orm { namespace internal { @@ -12218,7 +12172,6 @@ namespace sqlite_orm { // #include "expression_object_type.h" - namespace sqlite_orm { template @@ -12386,7 +12339,6 @@ namespace sqlite_orm { // #include "constraints.h" - namespace sqlite_orm { namespace internal { From 4a87844e48351e42c7d97d72844045a5a189d166 Mon Sep 17 00:00:00 2001 From: fnc12 Date: Thu, 2 Jan 2020 21:11:15 +0600 Subject: [PATCH 006/132] added quote function --- dev/core_functions.h | 37 ++++++++++++------ examples/core_functions.cpp | 3 ++ include/sqlite_orm/sqlite_orm.h | 37 ++++++++++++------ tests/core_functions_tests.cpp | 67 +++++++++++++++++++++++++++++++++ 4 files changed, 122 insertions(+), 22 deletions(-) diff --git a/dev/core_functions.h b/dev/core_functions.h index 2aa9267a8..5ed85ce17 100644 --- a/dev/core_functions.h +++ b/dev/core_functions.h @@ -87,6 +87,12 @@ namespace sqlite_orm { } }; + struct quote_string { + operator std::string() const { + return "QUOTE"; + } + }; + #if SQLITE_VERSION_NUMBER >= 3007016 struct char_string { @@ -198,7 +204,7 @@ namespace sqlite_orm { template core_functions::core_function_t length(T t) { std::tuple args{std::forward(t)}; - return {std::move(args)}; + return {move(args)}; } /** @@ -207,7 +213,7 @@ namespace sqlite_orm { template core_functions::core_function_t, core_functions::abs_string, T> abs(T t) { std::tuple args{std::forward(t)}; - return {std::move(args)}; + return {move(args)}; } /** @@ -216,7 +222,7 @@ namespace sqlite_orm { template core_functions::core_function_t lower(T t) { std::tuple args{std::forward(t)}; - return {std::move(args)}; + return {move(args)}; } /** @@ -225,7 +231,7 @@ namespace sqlite_orm { template core_functions::core_function_t upper(T t) { std::tuple args{std::forward(t)}; - return {std::move(args)}; + return {move(args)}; } /** @@ -241,7 +247,7 @@ namespace sqlite_orm { template core_functions::core_function_t trim(T t) { std::tuple args{std::forward(t)}; - return {std::move(args)}; + return {move(args)}; } /** @@ -250,7 +256,7 @@ namespace sqlite_orm { template core_functions::core_function_t trim(X x, Y y) { std::tuple args{std::forward(x), std::forward(y)}; - return {std::move(args)}; + return {move(args)}; } /** @@ -259,7 +265,7 @@ namespace sqlite_orm { template core_functions::core_function_t ltrim(X x) { std::tuple args{std::forward(x)}; - return {std::move(args)}; + return {move(args)}; } /** @@ -268,7 +274,7 @@ namespace sqlite_orm { template core_functions::core_function_t ltrim(X x, Y y) { std::tuple args{std::forward(x), std::forward(y)}; - return {std::move(args)}; + return {move(args)}; } /** @@ -277,7 +283,7 @@ namespace sqlite_orm { template core_functions::core_function_t rtrim(X x) { std::tuple args{std::forward(x)}; - return {std::move(args)}; + return {move(args)}; } /** @@ -286,7 +292,7 @@ namespace sqlite_orm { template core_functions::core_function_t rtrim(X x, Y y) { std::tuple args{std::forward(x), std::forward(y)}; - return {std::move(args)}; + return {move(args)}; } /** @@ -295,7 +301,16 @@ namespace sqlite_orm { template core_functions::core_function_t hex(X x) { std::tuple args{std::forward(x)}; - return {std::move(args)}; + return {move(args)}; + } + + /** + * QUOTE(X) function https://sqlite.org/lang_corefunc.html#quote + */ + template + core_functions::core_function_t quote(X x) { + std::tuple args{std::forward(x)}; + return {move(args)}; } #if SQLITE_VERSION_NUMBER >= 3007016 diff --git a/examples/core_functions.cpp b/examples/core_functions.cpp index 050e27731..8d9252b5e 100644 --- a/examples/core_functions.cpp +++ b/examples/core_functions.cpp @@ -260,5 +260,8 @@ int main(int, char **argv) { // SELECT hex(67); cout << "hex(67) = " << storage.select(hex(67)).front() << endl; + // SELECT quote('hi') + cout << "SELECT quote('hi') = " << storage.select(quote("hi")).front() << endl; + return 0; } diff --git a/include/sqlite_orm/sqlite_orm.h b/include/sqlite_orm/sqlite_orm.h index d439fde26..ce52e1ba4 100644 --- a/include/sqlite_orm/sqlite_orm.h +++ b/include/sqlite_orm/sqlite_orm.h @@ -3418,6 +3418,12 @@ namespace sqlite_orm { } }; + struct quote_string { + operator std::string() const { + return "QUOTE"; + } + }; + #if SQLITE_VERSION_NUMBER >= 3007016 struct char_string { @@ -3529,7 +3535,7 @@ namespace sqlite_orm { template core_functions::core_function_t length(T t) { std::tuple args{std::forward(t)}; - return {std::move(args)}; + return {move(args)}; } /** @@ -3538,7 +3544,7 @@ namespace sqlite_orm { template core_functions::core_function_t, core_functions::abs_string, T> abs(T t) { std::tuple args{std::forward(t)}; - return {std::move(args)}; + return {move(args)}; } /** @@ -3547,7 +3553,7 @@ namespace sqlite_orm { template core_functions::core_function_t lower(T t) { std::tuple args{std::forward(t)}; - return {std::move(args)}; + return {move(args)}; } /** @@ -3556,7 +3562,7 @@ namespace sqlite_orm { template core_functions::core_function_t upper(T t) { std::tuple args{std::forward(t)}; - return {std::move(args)}; + return {move(args)}; } /** @@ -3572,7 +3578,7 @@ namespace sqlite_orm { template core_functions::core_function_t trim(T t) { std::tuple args{std::forward(t)}; - return {std::move(args)}; + return {move(args)}; } /** @@ -3581,7 +3587,7 @@ namespace sqlite_orm { template core_functions::core_function_t trim(X x, Y y) { std::tuple args{std::forward(x), std::forward(y)}; - return {std::move(args)}; + return {move(args)}; } /** @@ -3590,7 +3596,7 @@ namespace sqlite_orm { template core_functions::core_function_t ltrim(X x) { std::tuple args{std::forward(x)}; - return {std::move(args)}; + return {move(args)}; } /** @@ -3599,7 +3605,7 @@ namespace sqlite_orm { template core_functions::core_function_t ltrim(X x, Y y) { std::tuple args{std::forward(x), std::forward(y)}; - return {std::move(args)}; + return {move(args)}; } /** @@ -3608,7 +3614,7 @@ namespace sqlite_orm { template core_functions::core_function_t rtrim(X x) { std::tuple args{std::forward(x)}; - return {std::move(args)}; + return {move(args)}; } /** @@ -3617,7 +3623,7 @@ namespace sqlite_orm { template core_functions::core_function_t rtrim(X x, Y y) { std::tuple args{std::forward(x), std::forward(y)}; - return {std::move(args)}; + return {move(args)}; } /** @@ -3626,7 +3632,16 @@ namespace sqlite_orm { template core_functions::core_function_t hex(X x) { std::tuple args{std::forward(x)}; - return {std::move(args)}; + return {move(args)}; + } + + /** + * QUOTE(X) function https://sqlite.org/lang_corefunc.html#quote + */ + template + core_functions::core_function_t quote(X x) { + std::tuple args{std::forward(x)}; + return {move(args)}; } #if SQLITE_VERSION_NUMBER >= 3007016 diff --git a/tests/core_functions_tests.cpp b/tests/core_functions_tests.cpp index 4912ab3bb..cc92f993a 100644 --- a/tests/core_functions_tests.cpp +++ b/tests/core_functions_tests.cpp @@ -201,3 +201,70 @@ TEST_CASE("hex") { REQUIRE(rows.front() == std::string()); } } + +TEST_CASE("quote") { + using Catch::Matchers::UnorderedEquals; + struct Department { + int id = 0; + std::string name; + int managerId = 0; + int locationId = 0; + }; + auto storage = make_storage({}, + make_table("departments", + make_column("department_id", &Department::id, primary_key()), + make_column("department_name", &Department::name), + make_column("manager_id", &Department::managerId), + make_column("location_id", &Department::locationId))); + storage.sync_schema(); + storage.replace(Department{10, "Administration", 200, 1700}); + storage.replace(Department{20, "Marketing", 201, 1800}); + storage.replace(Department{30, "Purchasing", 114, 1700}); + storage.replace(Department{40, "Human Resources", 203, 2400}); + storage.replace(Department{50, "Shipping", 121, 1500}); + storage.replace(Department{60, "IT", 103, 1400}); + storage.replace(Department{70, "Public Relation", 204, 2700}); + storage.replace(Department{80, "Sales", 145, 2500}); + storage.replace(Department{90, "Executive", 100, 1700}); + storage.replace(Department{100, "Finance", 108, 1700}); + storage.replace(Department{110, "Accounting", 205, 1700}); + storage.replace(Department{120, "Treasury", 0, 1700}); + storage.replace(Department{130, "Corporate Tax", 0, 1700}); + storage.replace(Department{140, "Control And Cre", 0, 1700}); + storage.replace(Department{150, "Shareholder Ser", 0, 1700}); + storage.replace(Department{160, "Benefits", 0, 1700}); + storage.replace(Department{170, "Manufacturing", 0, 1700}); + storage.replace(Department{180, "Construction", 0, 1700}); + storage.replace(Department{190, "Contracting", 0, 1700}); + storage.replace(Department{200, "Operations", 0, 1700}); + storage.replace(Department{210, "IT Support", 0, 1700}); + storage.replace(Department{220, "NOC", 0, 1700}); + storage.replace(Department{230, "IT Helpdesk", 0, 1700}); + storage.replace(Department{240, "Government Sale", 0, 1700}); + storage.replace(Department{250, "Retail Sales", 0, 1700}); + storage.replace(Department{260, "Recruiting", 0, 1700}); + storage.replace(Department{270, "Payroll", 0, 1700}); + { + auto rows = storage.select(quote("hi")); + REQUIRE(rows.size() == 1); + REQUIRE(rows.front() == "'hi'"); + } + { + auto rows = + storage.select(columns(&Department::name, quote(&Department::name)), where(c(&Department::id) > 150)); + std::vector> expected; + expected.push_back(std::make_tuple("Benefits", "'Benefits'")); + expected.push_back(std::make_tuple("Manufacturing", "'Manufacturing'")); + expected.push_back(std::make_tuple("Construction", "'Construction'")); + expected.push_back(std::make_tuple("Contracting", "'Contracting'")); + expected.push_back(std::make_tuple("Operations", "'Operations'")); + expected.push_back(std::make_tuple("IT Support", "'IT Support'")); + expected.push_back(std::make_tuple("NOC", "'NOC'")); + expected.push_back(std::make_tuple("IT Helpdesk", "'IT Helpdesk'")); + expected.push_back(std::make_tuple("Government Sale", "'Government Sale'")); + expected.push_back(std::make_tuple("Retail Sales", "'Retail Sales'")); + expected.push_back(std::make_tuple("Recruiting", "'Recruiting'")); + expected.push_back(std::make_tuple("Payroll", "'Payroll'")); + REQUIRE_THAT(rows, UnorderedEquals(expected)); + } +} From c56f0e55a062f8bf192e45920ca0272a7629ee4e Mon Sep 17 00:00:00 2001 From: fnc12 Date: Sun, 5 Jan 2020 00:44:40 +0600 Subject: [PATCH 007/132] added randomblob func --- dev/core_functions.h | 15 +++++++ examples/core_functions.cpp | 3 ++ include/sqlite_orm/sqlite_orm.h | 79 +++++++++++++++++++++++++++++---- tests/core_functions_tests.cpp | 10 +++++ 4 files changed, 99 insertions(+), 8 deletions(-) diff --git a/dev/core_functions.h b/dev/core_functions.h index 5ed85ce17..add041711 100644 --- a/dev/core_functions.h +++ b/dev/core_functions.h @@ -93,6 +93,12 @@ namespace sqlite_orm { } }; + struct randomblob_string { + operator std::string() const { + return "RANDOMBLOB"; + } + }; + #if SQLITE_VERSION_NUMBER >= 3007016 struct char_string { @@ -313,6 +319,15 @@ namespace sqlite_orm { return {move(args)}; } + /** + * RANDOMBLOB(X) function https://sqlite.org/lang_corefunc.html#randomblob + */ + template + core_functions::core_function_t, core_functions::randomblob_string, X> randomblob(X x) { + std::tuple args{std::forward(x)}; + return {move(args)}; + } + #if SQLITE_VERSION_NUMBER >= 3007016 /** diff --git a/examples/core_functions.cpp b/examples/core_functions.cpp index 8d9252b5e..30524d27f 100644 --- a/examples/core_functions.cpp +++ b/examples/core_functions.cpp @@ -263,5 +263,8 @@ int main(int, char **argv) { // SELECT quote('hi') cout << "SELECT quote('hi') = " << storage.select(quote("hi")).front() << endl; + // SELECT hex(randomblob(10)) + cout << "SELECT hex(randomblob(10)) = " << storage.select(hex(randomblob(10))).front() << endl; + return 0; } diff --git a/include/sqlite_orm/sqlite_orm.h b/include/sqlite_orm/sqlite_orm.h index cb98af0b1..70ae02929 100644 --- a/include/sqlite_orm/sqlite_orm.h +++ b/include/sqlite_orm/sqlite_orm.h @@ -27,7 +27,7 @@ __pragma(push_macro("min")) #include #include // std::ostringstream - namespace sqlite_orm { +namespace sqlite_orm { enum class orm_error_code { not_found = 1, @@ -43,6 +43,7 @@ __pragma(push_macro("min")) invalid_collate_argument_enum, failed_to_init_a_backup, }; + } namespace sqlite_orm { @@ -220,6 +221,7 @@ namespace sqlite_orm { // #include "static_magic.h" + #include // std::false_type, std::true_type, std::integral_constant namespace sqlite_orm { @@ -251,6 +253,7 @@ namespace sqlite_orm { } + namespace sqlite_orm { // got from here http://stackoverflow.com/questions/25958259/how-do-i-find-out-if-a-tuple-contains-a-type @@ -962,6 +965,7 @@ namespace sqlite_orm { // #include "constraints.h" + namespace sqlite_orm { namespace internal { @@ -1200,6 +1204,7 @@ namespace sqlite_orm { // #include "constraints.h" + namespace sqlite_orm { namespace internal { @@ -1655,6 +1660,7 @@ namespace sqlite_orm { // #include "optional_container.h" + namespace sqlite_orm { namespace internal { @@ -1687,6 +1693,7 @@ namespace sqlite_orm { } } + namespace sqlite_orm { namespace internal { @@ -3175,6 +3182,7 @@ namespace sqlite_orm { // #include "conditions.h" + namespace sqlite_orm { namespace internal { @@ -3294,6 +3302,7 @@ namespace sqlite_orm { // #include "is_base_of_template.h" + #include // std::true_type, std::false_type, std::declval namespace sqlite_orm { @@ -3331,6 +3340,7 @@ namespace sqlite_orm { } } + namespace sqlite_orm { namespace core_functions { @@ -3414,6 +3424,12 @@ namespace sqlite_orm { } }; + struct randomblob_string { + operator std::string() const { + return "RANDOMBLOB"; + } + }; + #if SQLITE_VERSION_NUMBER >= 3007016 struct char_string { @@ -3634,6 +3650,15 @@ namespace sqlite_orm { return {move(args)}; } + /** + * RANDOMBLOB(X) function https://sqlite.org/lang_corefunc.html#randomblob + */ + template + core_functions::core_function_t, core_functions::randomblob_string, X> randomblob(X x) { + std::tuple args{std::forward(x)}; + return {move(args)}; + } + #if SQLITE_VERSION_NUMBER >= 3007016 /** @@ -4073,6 +4098,7 @@ namespace sqlite_orm { // #include "optional_container.h" + namespace sqlite_orm { namespace internal { @@ -4429,6 +4455,7 @@ namespace sqlite_orm { // #include "column.h" + namespace sqlite_orm { namespace internal { @@ -4535,6 +4562,7 @@ namespace sqlite_orm { // #include "is_std_ptr.h" + namespace sqlite_orm { /** @@ -4562,6 +4590,7 @@ namespace sqlite_orm { }; } + namespace sqlite_orm { /** @@ -4772,6 +4801,7 @@ namespace sqlite_orm { // #include "journal_mode.h" + #include // std::string #include // std::unique_ptr #include // std::array @@ -4832,6 +4862,7 @@ namespace sqlite_orm { // #include "error_code.h" + namespace sqlite_orm { /** @@ -5211,6 +5242,7 @@ namespace sqlite_orm { // #include "alias.h" + namespace sqlite_orm { namespace internal { @@ -5459,6 +5491,7 @@ namespace sqlite_orm { } } + namespace sqlite_orm { namespace internal { @@ -5736,6 +5769,7 @@ namespace sqlite_orm { // #include "column.h" + namespace sqlite_orm { namespace internal { @@ -6037,10 +6071,12 @@ namespace sqlite_orm { // #include "field_value_holder.h" + #include // std::enable_if // #include "column.h" + namespace sqlite_orm { namespace internal { @@ -6063,6 +6099,7 @@ namespace sqlite_orm { } } + namespace sqlite_orm { namespace internal { @@ -6623,6 +6660,7 @@ namespace sqlite_orm { // #include "view.h" + #include // std::shared_ptr #include // std::string #include // std::forward, std::move @@ -6638,6 +6676,7 @@ namespace sqlite_orm { // #include "iterator.h" + #include // std::shared_ptr, std::unique_ptr, std::make_shared #include #include // std::decay @@ -6653,6 +6692,7 @@ namespace sqlite_orm { // #include "error_code.h" + namespace sqlite_orm { namespace internal { @@ -6781,6 +6821,7 @@ namespace sqlite_orm { // #include "ast_iterator.h" + #include // std::vector #include // std::reference_wrapper @@ -6796,6 +6837,7 @@ namespace sqlite_orm { // #include "prepared_statement.h" + #include #include // std::iterator_traits #include // std::string @@ -6804,12 +6846,14 @@ namespace sqlite_orm { // #include "connection_holder.h" + #include #include // std::string #include // std::system_error // #include "error_code.h" + namespace sqlite_orm { namespace internal { @@ -6884,6 +6928,7 @@ namespace sqlite_orm { // #include "select_constraints.h" + namespace sqlite_orm { namespace internal { @@ -7255,6 +7300,7 @@ namespace sqlite_orm { #endif // SQLITE_ORM_OPTIONAL_SUPPORTED } + namespace sqlite_orm { namespace internal { @@ -7712,6 +7758,7 @@ namespace sqlite_orm { // #include "connection_holder.h" + namespace sqlite_orm { namespace internal { @@ -7770,6 +7817,7 @@ namespace sqlite_orm { // #include "storage_base.h" + #include // std::function, std::bind #include #include // std::string @@ -7784,6 +7832,7 @@ namespace sqlite_orm { // #include "pragma.h" + #include // std::string #include #include // std::function @@ -7797,6 +7846,7 @@ namespace sqlite_orm { // #include "connection_holder.h" + namespace sqlite_orm { namespace internal { @@ -7917,6 +7967,7 @@ namespace sqlite_orm { // #include "limit_accesor.h" + #include #include // std::map #include // std::function @@ -7924,6 +7975,7 @@ namespace sqlite_orm { // #include "connection_holder.h" + namespace sqlite_orm { namespace internal { @@ -8057,10 +8109,12 @@ namespace sqlite_orm { // #include "transaction_guard.h" + #include // std::function // #include "connection_holder.h" + namespace sqlite_orm { namespace internal { @@ -8135,6 +8189,7 @@ namespace sqlite_orm { // #include "backup.h" + #include #include // std::string #include @@ -8143,6 +8198,7 @@ namespace sqlite_orm { // #include "connection_holder.h" + namespace sqlite_orm { namespace internal { @@ -8208,6 +8264,7 @@ namespace sqlite_orm { } } + namespace sqlite_orm { namespace internal { @@ -8743,11 +8800,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 { @@ -8865,6 +8924,7 @@ namespace sqlite_orm { } } + namespace sqlite_orm { namespace conditions { @@ -11893,19 +11953,20 @@ __pragma(pop_macro("min")) #include // std::pair #include // std::reference_wrapper - // #include "conditions.h" +// #include "conditions.h" + +// #include "operators.h" - // #include "operators.h" +// #include "select_constraints.h" - // #include "select_constraints.h" +// #include "prepared_statement.h" - // #include "prepared_statement.h" +// #include "optional_container.h" - // #include "optional_container.h" +// #include "core_functions.h" - // #include "core_functions.h" - namespace sqlite_orm { +namespace sqlite_orm { namespace internal { @@ -12187,6 +12248,7 @@ __pragma(pop_macro("min")) // #include "expression_object_type.h" + namespace sqlite_orm { template @@ -12354,6 +12416,7 @@ namespace sqlite_orm { // #include "constraints.h" + namespace sqlite_orm { namespace internal { diff --git a/tests/core_functions_tests.cpp b/tests/core_functions_tests.cpp index cc92f993a..e435f5045 100644 --- a/tests/core_functions_tests.cpp +++ b/tests/core_functions_tests.cpp @@ -268,3 +268,13 @@ TEST_CASE("quote") { REQUIRE_THAT(rows, UnorderedEquals(expected)); } } + +TEST_CASE("randomblob") { + auto storage = make_storage({}); + for(auto i = 0; i < 20; ++i) { + auto blobLength = i + 1; + auto rows = storage.select(randomblob(blobLength)); + REQUIRE(rows.size() == 1); + REQUIRE(rows.front().size() == size_t(blobLength)); + } +} From b4097884a8f62cb06b41e9c2b8e0ee5173dc7b43 Mon Sep 17 00:00:00 2001 From: fnc12 Date: Sun, 5 Jan 2020 00:45:47 +0600 Subject: [PATCH 008/132] code format --- include/sqlite_orm/sqlite_orm.h | 64 +++++---------------------------- 1 file changed, 8 insertions(+), 56 deletions(-) diff --git a/include/sqlite_orm/sqlite_orm.h b/include/sqlite_orm/sqlite_orm.h index 70ae02929..6a7ae77f6 100644 --- a/include/sqlite_orm/sqlite_orm.h +++ b/include/sqlite_orm/sqlite_orm.h @@ -27,7 +27,7 @@ __pragma(push_macro("min")) #include #include // std::ostringstream -namespace sqlite_orm { + namespace sqlite_orm { enum class orm_error_code { not_found = 1, @@ -43,7 +43,6 @@ namespace sqlite_orm { invalid_collate_argument_enum, failed_to_init_a_backup, }; - } namespace sqlite_orm { @@ -221,7 +220,6 @@ namespace sqlite_orm { // #include "static_magic.h" - #include // std::false_type, std::true_type, std::integral_constant namespace sqlite_orm { @@ -253,7 +251,6 @@ namespace sqlite_orm { } - namespace sqlite_orm { // got from here http://stackoverflow.com/questions/25958259/how-do-i-find-out-if-a-tuple-contains-a-type @@ -965,7 +962,6 @@ namespace sqlite_orm { // #include "constraints.h" - namespace sqlite_orm { namespace internal { @@ -1204,7 +1200,6 @@ namespace sqlite_orm { // #include "constraints.h" - namespace sqlite_orm { namespace internal { @@ -1660,7 +1655,6 @@ namespace sqlite_orm { // #include "optional_container.h" - namespace sqlite_orm { namespace internal { @@ -1693,7 +1687,6 @@ namespace sqlite_orm { } } - namespace sqlite_orm { namespace internal { @@ -3182,7 +3175,6 @@ namespace sqlite_orm { // #include "conditions.h" - namespace sqlite_orm { namespace internal { @@ -3302,7 +3294,6 @@ namespace sqlite_orm { // #include "is_base_of_template.h" - #include // std::true_type, std::false_type, std::declval namespace sqlite_orm { @@ -3340,7 +3331,6 @@ namespace sqlite_orm { } } - namespace sqlite_orm { namespace core_functions { @@ -4098,7 +4088,6 @@ namespace sqlite_orm { // #include "optional_container.h" - namespace sqlite_orm { namespace internal { @@ -4455,7 +4444,6 @@ namespace sqlite_orm { // #include "column.h" - namespace sqlite_orm { namespace internal { @@ -4562,7 +4550,6 @@ namespace sqlite_orm { // #include "is_std_ptr.h" - namespace sqlite_orm { /** @@ -4590,7 +4577,6 @@ namespace sqlite_orm { }; } - namespace sqlite_orm { /** @@ -4801,7 +4787,6 @@ namespace sqlite_orm { // #include "journal_mode.h" - #include // std::string #include // std::unique_ptr #include // std::array @@ -4862,7 +4847,6 @@ namespace sqlite_orm { // #include "error_code.h" - namespace sqlite_orm { /** @@ -5242,7 +5226,6 @@ namespace sqlite_orm { // #include "alias.h" - namespace sqlite_orm { namespace internal { @@ -5491,7 +5474,6 @@ namespace sqlite_orm { } } - namespace sqlite_orm { namespace internal { @@ -5769,7 +5751,6 @@ namespace sqlite_orm { // #include "column.h" - namespace sqlite_orm { namespace internal { @@ -6071,12 +6052,10 @@ namespace sqlite_orm { // #include "field_value_holder.h" - #include // std::enable_if // #include "column.h" - namespace sqlite_orm { namespace internal { @@ -6099,7 +6078,6 @@ namespace sqlite_orm { } } - namespace sqlite_orm { namespace internal { @@ -6660,7 +6638,6 @@ namespace sqlite_orm { // #include "view.h" - #include // std::shared_ptr #include // std::string #include // std::forward, std::move @@ -6676,7 +6653,6 @@ namespace sqlite_orm { // #include "iterator.h" - #include // std::shared_ptr, std::unique_ptr, std::make_shared #include #include // std::decay @@ -6692,7 +6668,6 @@ namespace sqlite_orm { // #include "error_code.h" - namespace sqlite_orm { namespace internal { @@ -6821,7 +6796,6 @@ namespace sqlite_orm { // #include "ast_iterator.h" - #include // std::vector #include // std::reference_wrapper @@ -6837,7 +6811,6 @@ namespace sqlite_orm { // #include "prepared_statement.h" - #include #include // std::iterator_traits #include // std::string @@ -6846,14 +6819,12 @@ namespace sqlite_orm { // #include "connection_holder.h" - #include #include // std::string #include // std::system_error // #include "error_code.h" - namespace sqlite_orm { namespace internal { @@ -6928,7 +6899,6 @@ namespace sqlite_orm { // #include "select_constraints.h" - namespace sqlite_orm { namespace internal { @@ -7300,7 +7270,6 @@ namespace sqlite_orm { #endif // SQLITE_ORM_OPTIONAL_SUPPORTED } - namespace sqlite_orm { namespace internal { @@ -7758,7 +7727,6 @@ namespace sqlite_orm { // #include "connection_holder.h" - namespace sqlite_orm { namespace internal { @@ -7817,7 +7785,6 @@ namespace sqlite_orm { // #include "storage_base.h" - #include // std::function, std::bind #include #include // std::string @@ -7832,7 +7799,6 @@ namespace sqlite_orm { // #include "pragma.h" - #include // std::string #include #include // std::function @@ -7846,7 +7812,6 @@ namespace sqlite_orm { // #include "connection_holder.h" - namespace sqlite_orm { namespace internal { @@ -7967,7 +7932,6 @@ namespace sqlite_orm { // #include "limit_accesor.h" - #include #include // std::map #include // std::function @@ -7975,7 +7939,6 @@ namespace sqlite_orm { // #include "connection_holder.h" - namespace sqlite_orm { namespace internal { @@ -8109,12 +8072,10 @@ namespace sqlite_orm { // #include "transaction_guard.h" - #include // std::function // #include "connection_holder.h" - namespace sqlite_orm { namespace internal { @@ -8189,7 +8150,6 @@ namespace sqlite_orm { // #include "backup.h" - #include #include // std::string #include @@ -8198,7 +8158,6 @@ namespace sqlite_orm { // #include "connection_holder.h" - namespace sqlite_orm { namespace internal { @@ -8264,7 +8223,6 @@ namespace sqlite_orm { } } - namespace sqlite_orm { namespace internal { @@ -8800,13 +8758,11 @@ namespace sqlite_orm { // #include "expression_object_type.h" - #include // std::decay #include // std::reference_wrapper // #include "prepared_statement.h" - namespace sqlite_orm { namespace internal { @@ -8924,7 +8880,6 @@ namespace sqlite_orm { } } - namespace sqlite_orm { namespace conditions { @@ -11953,20 +11908,19 @@ __pragma(pop_macro("min")) #include // std::pair #include // std::reference_wrapper -// #include "conditions.h" - -// #include "operators.h" + // #include "conditions.h" -// #include "select_constraints.h" + // #include "operators.h" -// #include "prepared_statement.h" + // #include "select_constraints.h" -// #include "optional_container.h" + // #include "prepared_statement.h" -// #include "core_functions.h" + // #include "optional_container.h" + // #include "core_functions.h" -namespace sqlite_orm { + namespace sqlite_orm { namespace internal { @@ -12248,7 +12202,6 @@ namespace sqlite_orm { // #include "expression_object_type.h" - namespace sqlite_orm { template @@ -12416,7 +12369,6 @@ namespace sqlite_orm { // #include "constraints.h" - namespace sqlite_orm { namespace internal { From a7f1bd0f21e28370711bee27da0be07657f09b02 Mon Sep 17 00:00:00 2001 From: fnc12 Date: Mon, 6 Jan 2020 23:59:04 +0600 Subject: [PATCH 009/132] added instr core function --- dev/core_functions.h | 15 ++++++++ examples/core_functions.cpp | 29 +++++++++++++- include/sqlite_orm/sqlite_orm.h | 15 ++++++++ tests/core_functions_tests.cpp | 68 +++++++++++++++++++++++++++++++++ 4 files changed, 125 insertions(+), 2 deletions(-) diff --git a/dev/core_functions.h b/dev/core_functions.h index add041711..145772c73 100644 --- a/dev/core_functions.h +++ b/dev/core_functions.h @@ -99,6 +99,12 @@ namespace sqlite_orm { } }; + struct instr_string { + operator std::string() const { + return "INSTR"; + } + }; + #if SQLITE_VERSION_NUMBER >= 3007016 struct char_string { @@ -328,6 +334,15 @@ namespace sqlite_orm { return {move(args)}; } + /** + * INSTR(X) function https://sqlite.org/lang_corefunc.html#instr + */ + template + core_functions::core_function_t instr(X x, Y y) { + std::tuple args{std::forward(x), std::forward(y)}; + return {move(args)}; + } + #if SQLITE_VERSION_NUMBER >= 3007016 /** diff --git a/examples/core_functions.cpp b/examples/core_functions.cpp index 30524d27f..f778f6e4b 100644 --- a/examples/core_functions.cpp +++ b/examples/core_functions.cpp @@ -139,11 +139,12 @@ int main(int, char **argv) { #if SQLITE_VERSION_NUMBER >= 3007016 - // SELECT CHAR(67,72,65,82) + // SELECT CHAR(67, 72, 65, 82) auto charString = storage.select(char_(67, 72, 65, 82)).front(); cout << "SELECT CHAR(67,72,65,82) = *" << charString << "*" << endl; - // SELECT LOWER(name) || '@marvel.com' FROM marvel + // SELECT LOWER(name) || '@marvel.com' + // FROM marvel auto emails = storage.select(lower(&MarvelHero::name) || c("@marvel.com")); cout << "emails.size = " << emails.size() << endl; for(auto &email: emails) { @@ -266,5 +267,29 @@ int main(int, char **argv) { // SELECT hex(randomblob(10)) cout << "SELECT hex(randomblob(10)) = " << storage.select(hex(randomblob(10))).front() << endl; + // SELECT instr('something about it', 't') + cout << "SELECT instr('something about it', 't') = " << storage.select(instr("something about it", "t")).front() + << endl; + + { + cout << endl; + struct o_pos : alias_tag { + static const std::string &get() { + static const std::string res = "o_pos"; + return res; + } + }; + + // SELECT name, INSTR(abilities, 'o') o_pos + // FROM marvel + // WHERE o_pos > 0 + auto rows = storage.select(columns(&MarvelHero::name, as(instr(&MarvelHero::abilities, "o"))), + where(greater_than(get(), 0))); + for(auto &row: rows) { + cout << get<0>(row) << '\t' << get<1>(row) << endl; + } + cout << endl; + } + return 0; } diff --git a/include/sqlite_orm/sqlite_orm.h b/include/sqlite_orm/sqlite_orm.h index 6a7ae77f6..7809179d5 100644 --- a/include/sqlite_orm/sqlite_orm.h +++ b/include/sqlite_orm/sqlite_orm.h @@ -3420,6 +3420,12 @@ namespace sqlite_orm { } }; + struct instr_string { + operator std::string() const { + return "INSTR"; + } + }; + #if SQLITE_VERSION_NUMBER >= 3007016 struct char_string { @@ -3649,6 +3655,15 @@ namespace sqlite_orm { return {move(args)}; } + /** + * INSTR(X) function https://sqlite.org/lang_corefunc.html#instr + */ + template + core_functions::core_function_t instr(X x, Y y) { + std::tuple args{std::forward(x), std::forward(y)}; + return {move(args)}; + } + #if SQLITE_VERSION_NUMBER >= 3007016 /** diff --git a/tests/core_functions_tests.cpp b/tests/core_functions_tests.cpp index e435f5045..126178e25 100644 --- a/tests/core_functions_tests.cpp +++ b/tests/core_functions_tests.cpp @@ -278,3 +278,71 @@ TEST_CASE("randomblob") { REQUIRE(rows.front().size() == size_t(blobLength)); } } + +TEST_CASE("instr") { + using Catch::Matchers::UnorderedEquals; + + struct Employee { + int id = 0; + std::string firstName; + std::string lastName; + std::string address; + }; + + struct sw : alias_tag { + static const std::string &get() { + static const std::string res = "sw"; + return res; + } + }; + auto storage = make_storage({}, + make_table("employees", + make_column("id", &Employee::id, primary_key()), + make_column("first_name", &Employee::firstName), + make_column("last_name", &Employee::lastName), + make_column("address", &Employee::address))); + storage.sync_schema(); + { + auto rows = storage.select(instr("SQLite Tutorial", "Tutorial")); + REQUIRE(rows.size() == 1); + REQUIRE(rows.front() == 8); + } + { + auto rows = storage.select(instr("SQLite Tutorial", "I")); + REQUIRE(rows.size() == 1); + REQUIRE(rows.front() == 0); + } + Employee nancy{1, "Nancy", "Edwards", "825 8 Ave SW"}; + Employee jane{2, "Jane", "Peacock", "1111 6 Ave SW"}; + Employee margaret{3, "Margaret", "Park", "683 10 Street SW"}; + Employee patrick{4, "Patrick", "Jane", "Sacramento Empty House"}; + Employee teresa{5, "Terese", "Lisbon", "Secramento Middle of Nowhere"}; + storage.replace(nancy); + storage.replace(jane); + storage.replace(margaret); + storage.replace(patrick); + storage.replace(teresa); + { + auto rows = storage.select( + columns(&Employee::lastName, &Employee::firstName, &Employee::address, instr(&Employee::address, "SW"))); + std::vector> expected; + expected.push_back(std::make_tuple(nancy.lastName, nancy.firstName, nancy.address, 11)); + expected.push_back(std::make_tuple(jane.lastName, jane.firstName, jane.address, 12)); + expected.push_back(std::make_tuple(margaret.lastName, margaret.firstName, margaret.address, 15)); + expected.push_back(std::make_tuple(patrick.lastName, patrick.firstName, patrick.address, 0)); + expected.push_back(std::make_tuple(teresa.lastName, teresa.firstName, teresa.address, 0)); + REQUIRE_THAT(rows, UnorderedEquals(expected)); + } + { + auto rows = storage.select(columns(&Employee::lastName, + &Employee::firstName, + &Employee::address, + as(instr(&Employee::address, "SW"))), + where(greater_than(get(), 0))); + std::vector> expected; + expected.push_back(std::make_tuple(nancy.lastName, nancy.firstName, nancy.address, 11)); + expected.push_back(std::make_tuple(jane.lastName, jane.firstName, jane.address, 12)); + expected.push_back(std::make_tuple(margaret.lastName, margaret.firstName, margaret.address, 15)); + REQUIRE_THAT(rows, UnorderedEquals(expected)); + } +} From 5517d99c1e7f80bdd2cd92eee01c7fbbbb76687b Mon Sep 17 00:00:00 2001 From: fnc12 Date: Tue, 7 Jan 2020 21:53:43 +0300 Subject: [PATCH 010/132] added time function --- dev/core_functions.h | 15 +++++ examples/date_time.cpp | 13 ++++- include/sqlite_orm/sqlite_orm.h | 15 +++++ tests/constraints/foreign_key.cpp | 4 +- tests/core_functions_tests.cpp | 40 ------------- tests/datetime_function_tests.cpp | 58 +++++++++++++++++++ .../arithmetic_operators.cpp} | 14 ++--- tests/operators/between.cpp | 24 ++++++++ tests/tests.cpp | 2 +- tests/tests4.cpp | 20 ------- 10 files changed, 133 insertions(+), 72 deletions(-) create mode 100644 tests/datetime_function_tests.cpp rename tests/{operators.cpp => operators/arithmetic_operators.cpp} (98%) create mode 100644 tests/operators/between.cpp diff --git a/dev/core_functions.h b/dev/core_functions.h index 145772c73..3c2d04b55 100644 --- a/dev/core_functions.h +++ b/dev/core_functions.h @@ -133,6 +133,12 @@ namespace sqlite_orm { } }; + struct time_string { + operator std::string() const { + return "TIME"; + } + }; + struct datetime_string { operator std::string() const { return "DATETIME"; @@ -379,6 +385,15 @@ namespace sqlite_orm { return {std::move(t)}; } + /** + * TIME(timestring, modifier, modifier, ...) function https://www.sqlite.org/lang_datefunc.html + */ + template + core_functions::core_function_t time(Args... args) { + std::tuple t{std::forward(args)...}; + return {std::move(t)}; + } + /** * DATETIME(timestring, modifier, modifier, ...) function https://www.sqlite.org/lang_datefunc.html */ diff --git a/examples/date_time.cpp b/examples/date_time.cpp index 2fa68b9ee..6bc0b2ecf 100644 --- a/examples/date_time.cpp +++ b/examples/date_time.cpp @@ -69,8 +69,17 @@ int main() { auto julianDiff = storage.select(julianday("now") - julianday("1776-07-04")).front(); cout << "SELECT julianday('now') - julianday('1776-07-04') = " << julianDiff << endl; - // SELECT (julianday('now') - 2440587.5)*86400.0; - auto julianConverted = storage.select((julianday("now") - 2440587.5) * 86400.0); + // SELECT (julianday('now') - 2440587.5) * 86400.0 + auto julianConverted = storage.select((julianday("now") - 2440587.5) * 86400.0).front(); + cout << "SELECT (julianday('now') - 2440587.5) * 86400.0 = " << julianConverted << endl; + + // SELECT time('12:00', 'localtime') + auto time12Local = storage.select(time("12:00", "localtime")).front(); + cout << "SELECT time('12:00', 'localtime') = " << time12Local << endl; + + // SELECT time('12:00', 'utc') + auto time12utc = storage.select(time("12:00", "utc")).front(); + cout << "SELECT time('12:00', 'utc') = " << time12utc << endl; return 0; } diff --git a/include/sqlite_orm/sqlite_orm.h b/include/sqlite_orm/sqlite_orm.h index 7809179d5..b48cab78a 100644 --- a/include/sqlite_orm/sqlite_orm.h +++ b/include/sqlite_orm/sqlite_orm.h @@ -3454,6 +3454,12 @@ namespace sqlite_orm { } }; + struct time_string { + operator std::string() const { + return "TIME"; + } + }; + struct datetime_string { operator std::string() const { return "DATETIME"; @@ -3700,6 +3706,15 @@ namespace sqlite_orm { return {std::move(t)}; } + /** + * TIME(timestring, modifier, modifier, ...) function https://www.sqlite.org/lang_datefunc.html + */ + template + core_functions::core_function_t time(Args... args) { + std::tuple t{std::forward(args)...}; + return {std::move(t)}; + } + /** * DATETIME(timestring, modifier, modifier, ...) function https://www.sqlite.org/lang_datefunc.html */ diff --git a/tests/constraints/foreign_key.cpp b/tests/constraints/foreign_key.cpp index 1003644a0..328e5ce5e 100644 --- a/tests/constraints/foreign_key.cpp +++ b/tests/constraints/foreign_key.cpp @@ -38,8 +38,8 @@ TEST_CASE("Foreign key") { foreign_key(&Visit::location).references(&Location::id))); storage.sync_schema(); - int fromDate = int(time(nullptr)); - int toDate = int(time(nullptr)); + int fromDate = int(std::time(nullptr)); + int toDate = int(std::time(nullptr)); int toDistance = 100; auto id = 10; storage.select(columns(&Visit::mark, &Visit::visited_at, &Location::place), diff --git a/tests/core_functions_tests.cpp b/tests/core_functions_tests.cpp index 126178e25..3a57ad15f 100644 --- a/tests/core_functions_tests.cpp +++ b/tests/core_functions_tests.cpp @@ -72,46 +72,6 @@ TEST_CASE("zeroblob") { } } -TEST_CASE("julianday") { - struct Test { - std::string text; - }; - - auto storage = make_storage({}, make_table("test", make_column("text", &Test::text))); - storage.sync_schema(); - auto singleTestCase = [&storage](const std::string &arg, double expected) { - { - auto rows = storage.select(julianday(arg)); - REQUIRE(rows.size() == 1); - REQUIRE((rows.front() - expected) < 0.001); // too much precision - } - { - storage.insert(Test{arg}); - auto rows = storage.select(julianday(&Test::text)); - REQUIRE(rows.size() == 1); - REQUIRE((rows.front() - expected) < 0.001); - storage.remove_all(); - } - }; - singleTestCase("2016-10-18", 2457679.5); - singleTestCase("2016-10-18 16:45", 2457680.19791667); - singleTestCase("2016-10-18 16:45:30", 2457680.19826389); -} - -TEST_CASE("datetime") { - auto storage = make_storage({}); - auto rows = storage.select(datetime("now")); - REQUIRE(rows.size() == 1); - REQUIRE(!rows.front().empty()); -} - -TEST_CASE("date") { - auto storage = make_storage({}); - auto rows = storage.select(date("now", "start of month", "+1 month", "-1 day")); - REQUIRE(rows.size() == 1); - REQUIRE(!rows.front().empty()); -} - #if SQLITE_VERSION_NUMBER >= 3007016 TEST_CASE("char") { auto storage = make_storage({}); diff --git a/tests/datetime_function_tests.cpp b/tests/datetime_function_tests.cpp new file mode 100644 index 000000000..b8d807fe1 --- /dev/null +++ b/tests/datetime_function_tests.cpp @@ -0,0 +1,58 @@ +#include +#include + +using namespace sqlite_orm; + +TEST_CASE("time") { + auto storage = make_storage({}); + { + auto rows = storage.select(time("12:00", "localtime")); + REQUIRE(rows.size() == 1); + REQUIRE(!rows.front().empty()); + } + { + auto rows = storage.select(time("12:00", "utc")); + REQUIRE(rows.size() == 1); + REQUIRE(!rows.front().empty()); + } +} + +TEST_CASE("julianday") { + struct Test { + std::string text; + }; + + auto storage = make_storage({}, make_table("test", make_column("text", &Test::text))); + storage.sync_schema(); + auto singleTestCase = [&storage](const std::string &arg, double expected) { + { + auto rows = storage.select(julianday(arg)); + REQUIRE(rows.size() == 1); + REQUIRE((rows.front() - expected) < 0.001); // too much precision + } + { + storage.insert(Test{arg}); + auto rows = storage.select(julianday(&Test::text)); + REQUIRE(rows.size() == 1); + REQUIRE((rows.front() - expected) < 0.001); + storage.remove_all(); + } + }; + singleTestCase("2016-10-18", 2457679.5); + singleTestCase("2016-10-18 16:45", 2457680.19791667); + singleTestCase("2016-10-18 16:45:30", 2457680.19826389); +} + +TEST_CASE("datetime") { + auto storage = make_storage({}); + auto rows = storage.select(datetime("now")); + REQUIRE(rows.size() == 1); + REQUIRE(!rows.front().empty()); +} + +TEST_CASE("date") { + auto storage = make_storage({}); + auto rows = storage.select(date("now", "start of month", "+1 month", "-1 day")); + REQUIRE(rows.size() == 1); + REQUIRE(!rows.front().empty()); +} diff --git a/tests/operators.cpp b/tests/operators/arithmetic_operators.cpp similarity index 98% rename from tests/operators.cpp rename to tests/operators/arithmetic_operators.cpp index 8cdc970a9..85318eacb 100644 --- a/tests/operators.cpp +++ b/tests/operators/arithmetic_operators.cpp @@ -3,7 +3,7 @@ using namespace sqlite_orm; -TEST_CASE("Operators") { +TEST_CASE("Arithmetic operators") { struct Object { std::string name; int nameLen; @@ -26,7 +26,7 @@ TEST_CASE("Operators") { for(auto &name: names) { storage.insert(Object{name, int(name.length()), number}); } - { + { // + auto rows = storage.select(c(&Object::nameLen) + 1000); for(size_t i = 0; i < rows.size(); ++i) { auto &row = rows[i]; @@ -34,7 +34,7 @@ TEST_CASE("Operators") { REQUIRE(int(row) == name.length() + 1000); } } - { + { // + auto rows = storage.select(columns(c(&Object::nameLen) + 1000)); for(size_t i = 0; i < rows.size(); ++i) { auto &row = rows[i]; @@ -42,7 +42,7 @@ TEST_CASE("Operators") { REQUIRE(int(std::get<0>(row)) == name.length() + 1000); } } - { + { // || std::string suffix = "ototo"; auto rows = storage.select(c(&Object::name) || suffix); for(size_t i = 0; i < rows.size(); ++i) { @@ -51,7 +51,7 @@ TEST_CASE("Operators") { REQUIRE(row == name + suffix); } } - { + { // || std::string suffix = "ototo"; auto rows = storage.select(columns(conc(&Object::name, suffix))); for(size_t i = 0; i < rows.size(); ++i) { @@ -60,7 +60,7 @@ TEST_CASE("Operators") { REQUIRE(std::get<0>(row) == name + suffix); } } - { + { // different std::string suffix = "ototo"; auto rows = storage.select(columns(conc(&Object::name, suffix), c(&Object::name) || suffix, @@ -131,7 +131,7 @@ TEST_CASE("Operators") { REQUIRE(std::get<23>(row) == int(name.length()) / 2); } } - { + { // % auto rows = storage.select(columns(mod(&Object::nameLen, &Object::number), c(&Object::nameLen) % &Object::number, &Object::nameLen % c(&Object::number), diff --git a/tests/operators/between.cpp b/tests/operators/between.cpp new file mode 100644 index 000000000..341c64ad5 --- /dev/null +++ b/tests/operators/between.cpp @@ -0,0 +1,24 @@ +#include +#include + +using namespace sqlite_orm; + +TEST_CASE("Between") { + struct Object { + int id = 0; + }; + + auto storage = + make_storage("", make_table("objects", make_column("id", &Object::id, autoincrement(), primary_key()))); + storage.sync_schema(); + + storage.insert(Object{}); + storage.insert(Object{}); + storage.insert(Object{}); + storage.insert(Object{}); + storage.insert(Object{}); + + auto allObjects = storage.get_all(); + auto rows = storage.select(&Object::id, where(between(&Object::id, 1, 3))); + REQUIRE(rows.size() == 3); +} diff --git a/tests/tests.cpp b/tests/tests.cpp index 73d4900fc..e295662ac 100644 --- a/tests/tests.cpp +++ b/tests/tests.cpp @@ -50,7 +50,7 @@ TEST_CASE("Join iterator ctor compilation error") { } } -TEST_CASE("limits") { +TEST_CASE("Limits") { auto storage2 = make_storage("limits.sqlite"); auto storage = storage2; storage.sync_schema(); diff --git a/tests/tests4.cpp b/tests/tests4.cpp index 6a96348a6..210a14aa0 100644 --- a/tests/tests4.cpp +++ b/tests/tests4.cpp @@ -361,26 +361,6 @@ TEST_CASE("Not operator") { REQUIRE(rows.front() == 2); } -TEST_CASE("Between operator") { - struct Object { - int id = 0; - }; - - auto storage = - make_storage("", make_table("objects", make_column("id", &Object::id, autoincrement(), primary_key()))); - storage.sync_schema(); - - storage.insert(Object{}); - storage.insert(Object{}); - storage.insert(Object{}); - storage.insert(Object{}); - storage.insert(Object{}); - - auto allObjects = storage.get_all(); - auto rows = storage.select(&Object::id, where(between(&Object::id, 1, 3))); - REQUIRE(rows.size() == 3); -} - TEST_CASE("Exists") { struct User { int id = 0; From 9cd70c2368e491bb5f8922ccde18a779f847c4fb Mon Sep 17 00:00:00 2001 From: fnc12 Date: Tue, 7 Jan 2020 22:13:41 +0300 Subject: [PATCH 011/132] fixed cmake --- dev/core_functions.h | 14 +++++++------- tests/CMakeLists.txt | 2 +- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/dev/core_functions.h b/dev/core_functions.h index 3c2d04b55..6b2cc6759 100644 --- a/dev/core_functions.h +++ b/dev/core_functions.h @@ -382,7 +382,7 @@ namespace sqlite_orm { template core_functions::core_function_t date(Args... args) { std::tuple t{std::forward(args)...}; - return {std::move(t)}; + return {move(t)}; } /** @@ -391,7 +391,7 @@ namespace sqlite_orm { template core_functions::core_function_t time(Args... args) { std::tuple t{std::forward(args)...}; - return {std::move(t)}; + return {move(t)}; } /** @@ -400,7 +400,7 @@ namespace sqlite_orm { template core_functions::core_function_t datetime(Args... args) { std::tuple t{std::forward(args)...}; - return {std::move(t)}; + return {move(t)}; } /** @@ -409,7 +409,7 @@ namespace sqlite_orm { template core_functions::core_function_t julianday(Args... args) { std::tuple t{std::forward(args)...}; - return {std::move(t)}; + return {move(t)}; } /** @@ -418,7 +418,7 @@ namespace sqlite_orm { template core_functions::core_function_t, core_functions::zeroblob_string, N> zeroblob(N n) { std::tuple args{std::forward(n)}; - return {std::move(args)}; + return {move(args)}; } /** @@ -427,7 +427,7 @@ namespace sqlite_orm { template core_functions::core_function_t substr(X x, Y y) { std::tuple args{std::forward(x), std::forward(y)}; - return {std::move(args)}; + return {move(args)}; } /** @@ -436,7 +436,7 @@ namespace sqlite_orm { template core_functions::core_function_t substr(X x, Y y, Z z) { std::tuple args{std::forward(x), std::forward(y), std::forward(z)}; - return {std::move(args)}; + return {move(args)}; } template Date: Wed, 8 Jan 2020 00:20:29 +0300 Subject: [PATCH 012/132] fixed collate example compilation --- examples/collate.cpp | 6 +++--- include/sqlite_orm/sqlite_orm.h | 14 +++++++------- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/examples/collate.cpp b/examples/collate.cpp index 5491307df..e925f6f28 100644 --- a/examples/collate.cpp +++ b/examples/collate.cpp @@ -33,9 +33,9 @@ int main(int, char **) { storage.remove_all(); storage.remove_all(); - storage.insert(User{0, "Lil Kim", time(nullptr)}); - storage.insert(User{0, "lil kim", time(nullptr)}); - storage.insert(User{0, "Nicki Minaj", time(nullptr)}); + storage.insert(User{0, "Lil Kim", std::time(nullptr)}); + storage.insert(User{0, "lil kim", std::time(nullptr)}); + storage.insert(User{0, "Nicki Minaj", std::time(nullptr)}); // SELECT COUNT(*) // FROM users diff --git a/include/sqlite_orm/sqlite_orm.h b/include/sqlite_orm/sqlite_orm.h index b48cab78a..eb4f3d717 100644 --- a/include/sqlite_orm/sqlite_orm.h +++ b/include/sqlite_orm/sqlite_orm.h @@ -3703,7 +3703,7 @@ namespace sqlite_orm { template core_functions::core_function_t date(Args... args) { std::tuple t{std::forward(args)...}; - return {std::move(t)}; + return {move(t)}; } /** @@ -3712,7 +3712,7 @@ namespace sqlite_orm { template core_functions::core_function_t time(Args... args) { std::tuple t{std::forward(args)...}; - return {std::move(t)}; + return {move(t)}; } /** @@ -3721,7 +3721,7 @@ namespace sqlite_orm { template core_functions::core_function_t datetime(Args... args) { std::tuple t{std::forward(args)...}; - return {std::move(t)}; + return {move(t)}; } /** @@ -3730,7 +3730,7 @@ namespace sqlite_orm { template core_functions::core_function_t julianday(Args... args) { std::tuple t{std::forward(args)...}; - return {std::move(t)}; + return {move(t)}; } /** @@ -3739,7 +3739,7 @@ namespace sqlite_orm { template core_functions::core_function_t, core_functions::zeroblob_string, N> zeroblob(N n) { std::tuple args{std::forward(n)}; - return {std::move(args)}; + return {move(args)}; } /** @@ -3748,7 +3748,7 @@ namespace sqlite_orm { template core_functions::core_function_t substr(X x, Y y) { std::tuple args{std::forward(x), std::forward(y)}; - return {std::move(args)}; + return {move(args)}; } /** @@ -3757,7 +3757,7 @@ namespace sqlite_orm { template core_functions::core_function_t substr(X x, Y y, Z z) { std::tuple args{std::forward(x), std::forward(y), std::forward(z)}; - return {std::move(args)}; + return {move(args)}; } template Date: Wed, 8 Jan 2020 19:06:23 +0300 Subject: [PATCH 013/132] added replace core func --- dev/core_functions.h | 15 +++++++++ examples/core_functions.cpp | 35 +++++++++++++++++++- include/sqlite_orm/sqlite_orm.h | 15 +++++++++ tests/core_functions_tests.cpp | 58 +++++++++++++++++++++++++++++++++ tests/tests2.cpp | 2 +- 5 files changed, 123 insertions(+), 2 deletions(-) diff --git a/dev/core_functions.h b/dev/core_functions.h index 6b2cc6759..685cb31c5 100644 --- a/dev/core_functions.h +++ b/dev/core_functions.h @@ -105,6 +105,12 @@ namespace sqlite_orm { } }; + struct replace_string { + operator std::string() const { + return "REPLACE"; + } + }; + #if SQLITE_VERSION_NUMBER >= 3007016 struct char_string { @@ -349,6 +355,15 @@ namespace sqlite_orm { return {move(args)}; } + /** + * REPLACE(X) function https://sqlite.org/lang_corefunc.html#replace + */ + template + core_functions::core_function_t replace(X x, Y y, Z z) { + std::tuple args{std::forward(x), std::forward(y), std::forward(z)}; + return {move(args)}; + } + #if SQLITE_VERSION_NUMBER >= 3007016 /** diff --git a/examples/core_functions.cpp b/examples/core_functions.cpp index f778f6e4b..91da9e09e 100644 --- a/examples/core_functions.cpp +++ b/examples/core_functions.cpp @@ -13,6 +13,13 @@ struct MarvelHero { short points; }; +struct Contact { + int id = 0; + std::string firstName; + std::string lastName; + std::string phone; +}; + int main(int, char **argv) { cout << "path = " << argv[0] << endl; @@ -22,7 +29,12 @@ int main(int, char **argv) { make_column("id", &MarvelHero::id, primary_key()), make_column("name", &MarvelHero::name), make_column("abilities", &MarvelHero::abilities), - make_column("points", &MarvelHero::points))); + make_column("points", &MarvelHero::points)), + make_table("contacts", + make_column("contact_id", &Contact::id, primary_key()), + make_column("first_name", &Contact::firstName), + make_column("last_name", &Contact::lastName), + make_column("phone", &Contact::phone))); storage.sync_schema(); storage.remove_all(); @@ -42,6 +54,11 @@ int main(int, char **argv) { return true; }); + Contact john{0, "John", "Doe", "410-555-0168"}; + Contact lily{0, "Lily", "Bush", "410-444-9862"}; + john.id = storage.insert(john); + lily.id = storage.insert(lily); + // SELECT LENGTH(name) // FROM marvel auto nameLengths = storage.select(length(&MarvelHero::name)); // nameLengths is std::vector @@ -291,5 +308,21 @@ int main(int, char **argv) { cout << endl; } + // SELECT REPLACE('AA B CC AAA','A','Z') + cout << "SELECT REPLACE('AA B CC AAA','A','Z') = " << storage.select(replace("AA B CC AAA", "A", "Z")).front() + << endl; + + // SELECT REPLACE('This is a cat','This','That') + cout << "SELECT REPLACE('This is a cat','This','That') = " + << storage.select(replace("This is a cat", "This", "That")).front() << endl; + + // UPDATE contacts + // SET phone = REPLACE(phone, '410', '+1-410') + storage.update_all(set(c(&Contact::phone) = replace(&Contact::phone, "410", "+1-410"))); + cout << "Contacts:" << endl; + for(auto &contact: storage.iterate()) { + cout << storage.dump(contact) << endl; + } + return 0; } diff --git a/include/sqlite_orm/sqlite_orm.h b/include/sqlite_orm/sqlite_orm.h index eb4f3d717..9e722eba0 100644 --- a/include/sqlite_orm/sqlite_orm.h +++ b/include/sqlite_orm/sqlite_orm.h @@ -3426,6 +3426,12 @@ namespace sqlite_orm { } }; + struct replace_string { + operator std::string() const { + return "REPLACE"; + } + }; + #if SQLITE_VERSION_NUMBER >= 3007016 struct char_string { @@ -3670,6 +3676,15 @@ namespace sqlite_orm { return {move(args)}; } + /** + * REPLACE(X) function https://sqlite.org/lang_corefunc.html#replace + */ + template + core_functions::core_function_t replace(X x, Y y, Z z) { + std::tuple args{std::forward(x), std::forward(y), std::forward(z)}; + return {move(args)}; + } + #if SQLITE_VERSION_NUMBER >= 3007016 /** diff --git a/tests/core_functions_tests.cpp b/tests/core_functions_tests.cpp index 3a57ad15f..06ee00540 100644 --- a/tests/core_functions_tests.cpp +++ b/tests/core_functions_tests.cpp @@ -306,3 +306,61 @@ TEST_CASE("instr") { REQUIRE_THAT(rows, UnorderedEquals(expected)); } } + +namespace replace_func_local { + struct Contact { + int id = 0; + std::string firstName; + std::string lastName; + std::string phone; + }; + + bool operator==(const Contact &lhs, const Contact &rhs) { + return lhs.id == rhs.id && lhs.firstName == rhs.firstName && lhs.lastName == rhs.lastName && + lhs.phone == rhs.phone; + } +} + +TEST_CASE("replace func") { + using Catch::Matchers::UnorderedEquals; + using namespace replace_func_local; + + auto storage = make_storage({}, + make_table("contacts", + make_column("contact_id", &Contact::id, primary_key()), + make_column("first_name", &Contact::firstName), + make_column("last_name", &Contact::lastName), + make_column("phone", &Contact::phone))); + storage.sync_schema(); + { + auto rows = storage.select(replace("AA B CC AAA", "A", "Z")); + REQUIRE(rows.size() == 1); + REQUIRE(rows.front() == "ZZ B CC ZZZ"); + } + { + auto rows = storage.select(replace("This is a cat", "This", "That")); + REQUIRE(rows.size() == 1); + REQUIRE(rows.front() == "That is a cat"); + } + Contact john{0, "John", "Doe", "410-555-0168"}; + Contact lily{0, "Lily", "Bush", "410-444-9862"}; + john.id = storage.insert(john); + lily.id = storage.insert(lily); + { + auto contacts = storage.get_all(); + std::vector expected; + expected.push_back(john); + expected.push_back(lily); + REQUIRE_THAT(contacts, UnorderedEquals(expected)); + } + storage.update_all(set(c(&Contact::phone) = replace(&Contact::phone, "410", "+1-410"))); + { + auto contacts = storage.get_all(); + john.phone = "+1-410-555-0168"; + lily.phone = "+1-410-444-9862"; + std::vector expected; + expected.push_back(john); + expected.push_back(lily); + REQUIRE_THAT(contacts, UnorderedEquals(expected)); + } +} diff --git a/tests/tests2.cpp b/tests/tests2.cpp index 2ffe3eee5..b9dc64cf1 100644 --- a/tests/tests2.cpp +++ b/tests/tests2.cpp @@ -254,7 +254,7 @@ TEST_CASE("Select") { REQUIRE(storage.get(firstId).currentWord == "ototo"); } -TEST_CASE("Replace") { +TEST_CASE("Replace query") { struct Object { int id; std::string name; From bfa3e075f32ce2b9e1bab3350ed04f6a2ada1e4e Mon Sep 17 00:00:00 2001 From: fnc12 Date: Thu, 9 Jan 2020 22:28:38 +0300 Subject: [PATCH 014/132] added round core function --- dev/core_functions.h | 24 ++++++++++++++++++++++++ examples/core_functions.cpp | 22 +++++++++++++++++----- include/sqlite_orm/sqlite_orm.h | 24 ++++++++++++++++++++++++ tests/core_functions_tests.cpp | 29 +++++++++++++++++++++++++++++ 4 files changed, 94 insertions(+), 5 deletions(-) diff --git a/dev/core_functions.h b/dev/core_functions.h index 685cb31c5..4dcbe2c79 100644 --- a/dev/core_functions.h +++ b/dev/core_functions.h @@ -111,6 +111,12 @@ namespace sqlite_orm { } }; + struct round_string { + operator std::string() const { + return "ROUND"; + } + }; + #if SQLITE_VERSION_NUMBER >= 3007016 struct char_string { @@ -364,6 +370,24 @@ namespace sqlite_orm { return {move(args)}; } + /** + * ROUND(X) function https://sqlite.org/lang_corefunc.html#round + */ + template + core_functions::core_function_t round(X x) { + std::tuple args{std::forward(x)}; + return {move(args)}; + } + + /** + * ROUND(X, Y) function https://sqlite.org/lang_corefunc.html#round + */ + template + core_functions::core_function_t round(X x, Y y) { + std::tuple args{std::forward(x), std::forward(y)}; + return {move(args)}; + } + #if SQLITE_VERSION_NUMBER >= 3007016 /** diff --git a/examples/core_functions.cpp b/examples/core_functions.cpp index 91da9e09e..f94a38102 100644 --- a/examples/core_functions.cpp +++ b/examples/core_functions.cpp @@ -297,7 +297,7 @@ int main(int, char **argv) { } }; - // SELECT name, INSTR(abilities, 'o') o_pos + // SELECT name, instr(abilities, 'o') o_pos // FROM marvel // WHERE o_pos > 0 auto rows = storage.select(columns(&MarvelHero::name, as(instr(&MarvelHero::abilities, "o"))), @@ -308,12 +308,12 @@ int main(int, char **argv) { cout << endl; } - // SELECT REPLACE('AA B CC AAA','A','Z') - cout << "SELECT REPLACE('AA B CC AAA','A','Z') = " << storage.select(replace("AA B CC AAA", "A", "Z")).front() + // SELECT replace('AA B CC AAA','A','Z') + cout << "SELECT replace('AA B CC AAA','A','Z') = " << storage.select(replace("AA B CC AAA", "A", "Z")).front() << endl; - // SELECT REPLACE('This is a cat','This','That') - cout << "SELECT REPLACE('This is a cat','This','That') = " + // SELECT replace('This is a cat','This','That') + cout << "SELECT replace('This is a cat','This','That') = " << storage.select(replace("This is a cat", "This", "That")).front() << endl; // UPDATE contacts @@ -324,5 +324,17 @@ int main(int, char **argv) { cout << storage.dump(contact) << endl; } + // SELECT round(1929.236, 2) + cout << "SELECT round(1929.236, 2) = " << storage.select(round(1929.236, 2)).front() << endl; + + // SELECT round(1929.236, 1) + cout << "SELECT round(1929.236, 1) = " << storage.select(round(1929.236, 1)).front() << endl; + + // SELECT round(1929.236) + cout << "SELECT round(1929.236) = " << storage.select(round(1929.236)).front() << endl; + + // SELECT round(0.5) + cout << "SELECT round(0.5) = " << storage.select(round(0.5)).front() << endl; + return 0; } diff --git a/include/sqlite_orm/sqlite_orm.h b/include/sqlite_orm/sqlite_orm.h index 9e722eba0..0fad8347f 100644 --- a/include/sqlite_orm/sqlite_orm.h +++ b/include/sqlite_orm/sqlite_orm.h @@ -3432,6 +3432,12 @@ namespace sqlite_orm { } }; + struct round_string { + operator std::string() const { + return "ROUND"; + } + }; + #if SQLITE_VERSION_NUMBER >= 3007016 struct char_string { @@ -3685,6 +3691,24 @@ namespace sqlite_orm { return {move(args)}; } + /** + * ROUND(X) function https://sqlite.org/lang_corefunc.html#round + */ + template + core_functions::core_function_t round(X x) { + std::tuple args{std::forward(x)}; + return {move(args)}; + } + + /** + * ROUND(X, Y) function https://sqlite.org/lang_corefunc.html#round + */ + template + core_functions::core_function_t round(X x, Y y) { + std::tuple args{std::forward(x), std::forward(y)}; + return {move(args)}; + } + #if SQLITE_VERSION_NUMBER >= 3007016 /** diff --git a/tests/core_functions_tests.cpp b/tests/core_functions_tests.cpp index 06ee00540..0ea38cae0 100644 --- a/tests/core_functions_tests.cpp +++ b/tests/core_functions_tests.cpp @@ -364,3 +364,32 @@ TEST_CASE("replace func") { REQUIRE_THAT(contacts, UnorderedEquals(expected)); } } + +TEST_CASE("round") { + auto storage = make_storage({}); + auto test = [&storage](auto input, double expected) { + auto rows = storage.select(round(input)); + REQUIRE(rows.size() == 1); + REQUIRE(rows.front() == expected); + }; + auto test2 = [&storage](auto inputA, auto inputB, double expected) { + auto rows = storage.select(round(inputA, inputB)); + REQUIRE(rows.size() == 1); + REQUIRE(rows.front() == expected); + }; + test(23.4, 23.0); + test(23.6, 24.0); + test2(23.6985, 2, 23.7); + test2(190.3985, 3, 190.399); + test2(99.9, 0, 100.0); + test2(23.3985, nullptr, 0); // maybe this is an error but noone cares AFAIK + test2(1304.67, -1, 1305.0); + test2(1929.236, 2, 1929.24); + test2(1929.236, 1, 1929.2); + test(1929.236, 1929); + test(0.5, 1); + test2(59.9, 0, 60.0); + test2(-59.9, 0, -60.0); + test2(-4.535, 2, -4.54); + test2(34.4158, -1, 34.0); +} From 23290def817e4367c72db58fe3ecec86f91c6bf7 Mon Sep 17 00:00:00 2001 From: fnc12 Date: Wed, 15 Jan 2020 19:49:59 +0300 Subject: [PATCH 015/132] added UNSIGNED INT(6) support --- dev/sqlite_type.h | 1 + include/sqlite_orm/sqlite_orm.h | 1 + tests/tests2.cpp | 1 + 3 files changed, 3 insertions(+) diff --git a/dev/sqlite_type.h b/dev/sqlite_type.h index ce51889a6..5658e16cd 100644 --- a/dev/sqlite_type.h +++ b/dev/sqlite_type.h @@ -43,6 +43,7 @@ namespace sqlite_orm { std::regex("UNSIGNED BIG INT"), std::regex("INT2"), std::regex("INT8"), + std::regex("UNSIGNED INT\\([[:digit:]]+\\)"), }}, {sqlite_type::TEXT, { diff --git a/include/sqlite_orm/sqlite_orm.h b/include/sqlite_orm/sqlite_orm.h index 0fad8347f..9f060c73a 100644 --- a/include/sqlite_orm/sqlite_orm.h +++ b/include/sqlite_orm/sqlite_orm.h @@ -173,6 +173,7 @@ namespace sqlite_orm { std::regex("UNSIGNED BIG INT"), std::regex("INT2"), std::regex("INT8"), + std::regex("UNSIGNED INT\\([[:digit:]]+\\)"), }}, {sqlite_type::TEXT, { diff --git a/tests/tests2.cpp b/tests/tests2.cpp index b9dc64cf1..9dcc9f3f4 100644 --- a/tests/tests2.cpp +++ b/tests/tests2.cpp @@ -418,6 +418,7 @@ TEST_CASE("Type parsing") { REQUIRE(*to_sqlite_type("UNSIGNED BIG INT") == sqlite_type::INTEGER); REQUIRE(*to_sqlite_type("INT2") == sqlite_type::INTEGER); REQUIRE(*to_sqlite_type("INT8") == sqlite_type::INTEGER); + REQUIRE(*to_sqlite_type("UNSIGNED INT(6)") == sqlite_type::INTEGER); // text REQUIRE(*to_sqlite_type("TEXT") == sqlite_type::TEXT); From 252db48d8680d1ca5a97b5c7d9e9dc4dd4f2a48d Mon Sep 17 00:00:00 2001 From: fnc12 Date: Thu, 23 Jan 2020 20:02:17 +0300 Subject: [PATCH 016/132] added two or more spaces support --- dev/sqlite_type.h | 2 +- include/sqlite_orm/sqlite_orm.h | 2 +- tests/tests2.cpp | 1 + 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/dev/sqlite_type.h b/dev/sqlite_type.h index 5658e16cd..a3b09535f 100644 --- a/dev/sqlite_type.h +++ b/dev/sqlite_type.h @@ -43,7 +43,7 @@ namespace sqlite_orm { std::regex("UNSIGNED BIG INT"), std::regex("INT2"), std::regex("INT8"), - std::regex("UNSIGNED INT\\([[:digit:]]+\\)"), + std::regex("UNSIGNED\\s+INT\\([[:digit:]]+\\)"), }}, {sqlite_type::TEXT, { diff --git a/include/sqlite_orm/sqlite_orm.h b/include/sqlite_orm/sqlite_orm.h index 9f060c73a..2c9a01536 100644 --- a/include/sqlite_orm/sqlite_orm.h +++ b/include/sqlite_orm/sqlite_orm.h @@ -173,7 +173,7 @@ namespace sqlite_orm { std::regex("UNSIGNED BIG INT"), std::regex("INT2"), std::regex("INT8"), - std::regex("UNSIGNED INT\\([[:digit:]]+\\)"), + std::regex("UNSIGNED\\s+INT\\([[:digit:]]+\\)"), }}, {sqlite_type::TEXT, { diff --git a/tests/tests2.cpp b/tests/tests2.cpp index 9dcc9f3f4..9b1172768 100644 --- a/tests/tests2.cpp +++ b/tests/tests2.cpp @@ -419,6 +419,7 @@ TEST_CASE("Type parsing") { REQUIRE(*to_sqlite_type("INT2") == sqlite_type::INTEGER); REQUIRE(*to_sqlite_type("INT8") == sqlite_type::INTEGER); REQUIRE(*to_sqlite_type("UNSIGNED INT(6)") == sqlite_type::INTEGER); + REQUIRE(*to_sqlite_type("UNSIGNED INT(4)") == sqlite_type::INTEGER); // text REQUIRE(*to_sqlite_type("TEXT") == sqlite_type::TEXT); From ad7dba322073cb47f7788904d97fe22438bd1e00 Mon Sep 17 00:00:00 2001 From: fnc12 Date: Sun, 2 Feb 2020 13:39:18 +0300 Subject: [PATCH 017/132] added check constraint --- dev/column.h | 152 +-- dev/constraints.h | 34 +- dev/default_value_extractor.h | 4 +- dev/error_code.h | 3 + dev/getter_traits.h | 184 +++ dev/index.h | 3 - dev/serializator_context.h | 31 + dev/statement_serializator.h | 231 +++- dev/static_magic.h | 3 + dev/storage.h | 154 +-- dev/storage_impl.h | 75 +- dev/table.h | 15 +- examples/check.cpp | 62 + examples/in_memory.cpp | 1 - include/sqlite_orm/sqlite_orm.h | 1119 +++++++++-------- tests/CMakeLists.txt | 2 +- tests/constraints/check.cpp | 40 + tests/explicit_columns.cpp | 2 +- tests/operators/is_null.cpp | 4 +- .../arithmetic_operators.cpp | 58 + .../autoincrement.cpp | 11 + tests/statement_serializator_tests/check.cpp | 52 + .../statement_serializator_tests/collate.cpp | 23 + .../column_names.cpp | 106 ++ .../comparison_operators.cpp | 86 ++ .../core_functions.cpp | 122 ++ .../statement_serializator_tests/default.cpp | 23 + .../foreign_key.cpp | 313 +++++ .../primary_key.cpp | 44 + tests/statement_serializator_tests/unique.cpp | 11 + tests/static_if_tests.cpp | 67 + tests/static_tests.cpp | 2 +- tests/static_tests/member_traits_tests.cpp | 109 ++ tests/table_tests.cpp | 125 ++ tests/tests2.cpp | 52 + tests/tests3.cpp | 14 +- tests/tests4.cpp | 8 + third_party/amalgamate/config.json | 3 +- 38 files changed, 2462 insertions(+), 886 deletions(-) create mode 100644 dev/getter_traits.h create mode 100644 dev/serializator_context.h create mode 100644 examples/check.cpp create mode 100644 tests/constraints/check.cpp create mode 100644 tests/statement_serializator_tests/arithmetic_operators.cpp create mode 100644 tests/statement_serializator_tests/autoincrement.cpp create mode 100644 tests/statement_serializator_tests/check.cpp create mode 100644 tests/statement_serializator_tests/collate.cpp create mode 100644 tests/statement_serializator_tests/column_names.cpp create mode 100644 tests/statement_serializator_tests/comparison_operators.cpp create mode 100644 tests/statement_serializator_tests/core_functions.cpp create mode 100644 tests/statement_serializator_tests/default.cpp create mode 100644 tests/statement_serializator_tests/foreign_key.cpp create mode 100644 tests/statement_serializator_tests/primary_key.cpp create mode 100644 tests/statement_serializator_tests/unique.cpp create mode 100644 tests/static_if_tests.cpp create mode 100644 tests/static_tests/member_traits_tests.cpp create mode 100644 tests/table_tests.cpp diff --git a/dev/column.h b/dev/column.h index 3b02d9440..b42ce4a0a 100644 --- a/dev/column.h +++ b/dev/column.h @@ -9,6 +9,7 @@ #include "tuple_helper.h" #include "default_value_extractor.h" #include "constraints.h" +#include "getter_traits.h" namespace sqlite_orm { @@ -64,8 +65,7 @@ namespace sqlite_orm { setter_type setter_, constraints_type constraints_) : column_base{std::move(name)}, - member_pointer(member_pointer_), getter(getter_), setter(setter_), - constraints(std::move(constraints_)) {} + member_pointer(member_pointer_), getter(getter_), setter(setter_), constraints(move(constraints_)) {} /** * Simplified interface for `NOT NULL` constraint @@ -121,152 +121,26 @@ namespace sqlite_orm { template struct is_column> : public std::true_type {}; - template - struct is_field_member_pointer : std::false_type {}; - template - struct is_field_member_pointer::value && - !std::is_member_function_pointer::value>::type> - : std::true_type {}; - - /** - * Getters aliases - */ - template - using getter_by_value_const = T (O::*)() const; - - template - using getter_by_value = T (O::*)(); - - template - using getter_by_ref_const = T &(O::*)() const; - - template - using getter_by_ref = T &(O::*)(); - - template - using getter_by_const_ref_const = const T &(O::*)() const; - - template - using getter_by_const_ref = const T &(O::*)(); - - /** - * Setters aliases - */ - template - using setter_by_value = void (O::*)(T); - - template - using setter_by_ref = void (O::*)(T &); - - template - using setter_by_const_ref = void (O::*)(const T &); - - template - struct is_getter : std::false_type {}; - - template - struct is_getter> : std::true_type {}; - - template - struct is_getter> : std::true_type {}; - - template - struct is_getter> : std::true_type {}; - - template - struct is_getter> : std::true_type {}; - - template - struct is_getter> : std::true_type {}; - - template - struct is_getter> : std::true_type {}; - - template - struct is_setter : std::false_type {}; - - template - struct is_setter> : std::true_type {}; - - template - struct is_setter> : std::true_type {}; - - template - struct is_setter> : std::true_type {}; - - template - struct getter_traits; - - template - struct getter_traits> { - using object_type = O; - using field_type = T; - - static constexpr const bool returns_lvalue = false; + struct column_field_type { + using type = void; }; - template - struct getter_traits> { - using object_type = O; - using field_type = T; - - static constexpr const bool returns_lvalue = false; - }; - - template - struct getter_traits> { - using object_type = O; - using field_type = T; - - static constexpr const bool returns_lvalue = true; - }; - - template - struct getter_traits> { - using object_type = O; - using field_type = T; - - static constexpr const bool returns_lvalue = true; - }; - - template - struct getter_traits> { - using object_type = O; - using field_type = T; - - static constexpr const bool returns_lvalue = true; - }; - - template - struct getter_traits> { - using object_type = O; - using field_type = T; - - static constexpr const bool returns_lvalue = true; + template + struct column_field_type> { + using type = typename column_t::field_type; }; template - struct setter_traits; - - template - struct setter_traits> { - using object_type = O; - using field_type = T; + struct column_constraints_type { + using type = std::tuple<>; }; - template - struct setter_traits> { - using object_type = O; - using field_type = T; + template + struct column_constraints_type> { + using type = typename column_t::constraints_type; }; - template - struct setter_traits> { - using object_type = O; - using field_type = T; - }; } /** @@ -280,6 +154,8 @@ namespace sqlite_orm { make_column(const std::string &name, T O::*m, Op... constraints) { static_assert(constraints::constraints_size::value == std::tuple_size>::value, "Incorrect constraints pack"); + static_assert(internal::is_field_member_pointer::value, + "second argument expected as a member field pointer, not member function pointer"); return {name, m, nullptr, nullptr, std::make_tuple(constraints...)}; } diff --git a/dev/constraints.h b/dev/constraints.h index 6ba75e7b6..3657eec3d 100644 --- a/dev/constraints.h +++ b/dev/constraints.h @@ -53,13 +53,13 @@ namespace sqlite_orm { template struct primary_key_t : primary_key_base { using order_by = primary_key_base::order_by; + using columns_tuple = std::tuple; - std::tuple columns; + columns_tuple columns; - primary_key_t(decltype(columns) c) : columns(std::move(c)) {} + primary_key_t(decltype(columns) c) : columns(move(c)) {} - using field_type = void; // for column iteration. Better be deleted - using constraints_type = std::tuple<>; + // using constraints_type = std::tuple<>; primary_key_t asc() const { auto res = *this; @@ -255,8 +255,7 @@ namespace sqlite_orm { return *this; } - using field_type = void; // for column iteration. Better be deleted - using constraints_type = std::tuple<>; + // using constraints_type = std::tuple<>; template void for_each_column(const L &) {} @@ -310,6 +309,21 @@ namespace sqlite_orm { } }; + struct check_string { + operator std::string() const { + return "CHECK"; + } + }; + + template + struct check_t : check_string { + using expression_type = T; + + expression_type expression; + + check_t(expression_type expression_) : expression(std::move(expression_)) {} + }; + template struct is_constraint : std::false_type {}; @@ -331,6 +345,9 @@ namespace sqlite_orm { template<> struct is_constraint : std::true_type {}; + template + struct is_constraint> : std::true_type {}; + template struct constraints_size; @@ -391,6 +408,11 @@ namespace sqlite_orm { return {internal::collate_argument::rtrim}; } + template + constraints::check_t check(T t) { + return {std::move(t)}; + } + namespace internal { /** diff --git a/dev/default_value_extractor.h b/dev/default_value_extractor.h index dd5ad9733..1c231e140 100644 --- a/dev/default_value_extractor.h +++ b/dev/default_value_extractor.h @@ -5,6 +5,7 @@ #include // std::stringstream #include "constraints.h" +#include "serializator_context.h" namespace sqlite_orm { @@ -26,7 +27,8 @@ namespace sqlite_orm { template std::unique_ptr operator()(const constraints::default_t &t) { - return std::make_unique(serialize(t.value)); + serializator_context_base context; + return std::make_unique(serialize(t.value, context)); } }; diff --git a/dev/error_code.h b/dev/error_code.h index a862ab754..0dd1f1b25 100644 --- a/dev/error_code.h +++ b/dev/error_code.h @@ -21,6 +21,7 @@ namespace sqlite_orm { incorrect_journal_mode_string, invalid_collate_argument_enum, failed_to_init_a_backup, + unknown_member_value, }; } @@ -57,6 +58,8 @@ namespace sqlite_orm { return "Invalid collate_argument enum"; case orm_error_code::failed_to_init_a_backup: return "Failed to init a backup"; + case orm_error_code::unknown_member_value: + return "Unknown member value"; default: return "unknown error"; } diff --git a/dev/getter_traits.h b/dev/getter_traits.h new file mode 100644 index 000000000..07b1b7585 --- /dev/null +++ b/dev/getter_traits.h @@ -0,0 +1,184 @@ +#pragma once + +namespace sqlite_orm { + + namespace internal { + + template + struct is_field_member_pointer : std::false_type {}; + + template + struct is_field_member_pointer::value && + !std::is_member_function_pointer::value>::type> + : std::true_type {}; + + template + struct field_member_traits; + + template + struct field_member_traits::value>::type> { + using object_type = O; + using field_type = F; + }; + + /** + * Getters aliases + */ + template + using getter_by_value_const = T (O::*)() const; + + template + using getter_by_value = T (O::*)(); + + template + using getter_by_ref_const = T &(O::*)() const; + + template + using getter_by_ref = T &(O::*)(); + + template + using getter_by_const_ref_const = const T &(O::*)() const; + + template + using getter_by_const_ref = const T &(O::*)(); + + /** + * Setters aliases + */ + template + using setter_by_value = void (O::*)(T); + + template + using setter_by_ref = void (O::*)(T &); + + template + using setter_by_const_ref = void (O::*)(const T &); + + template + struct is_getter : std::false_type {}; + + template + struct is_getter> : std::true_type {}; + + template + struct is_getter> : std::true_type {}; + + template + struct is_getter> : std::true_type {}; + + template + struct is_getter> : std::true_type {}; + + template + struct is_getter> : std::true_type {}; + + template + struct is_getter> : std::true_type {}; + + template + struct is_setter : std::false_type {}; + + template + struct is_setter> : std::true_type {}; + + template + struct is_setter> : std::true_type {}; + + template + struct is_setter> : std::true_type {}; + + template + struct getter_traits; + + template + struct getter_traits> { + using object_type = O; + using field_type = T; + + static constexpr const bool returns_lvalue = false; + }; + + template + struct getter_traits> { + using object_type = O; + using field_type = T; + + static constexpr const bool returns_lvalue = false; + }; + + template + struct getter_traits> { + using object_type = O; + using field_type = T; + + static constexpr const bool returns_lvalue = true; + }; + + template + struct getter_traits> { + using object_type = O; + using field_type = T; + + static constexpr const bool returns_lvalue = true; + }; + + template + struct getter_traits> { + using object_type = O; + using field_type = T; + + static constexpr const bool returns_lvalue = true; + }; + + template + struct getter_traits> { + using object_type = O; + using field_type = T; + + static constexpr const bool returns_lvalue = true; + }; + + template + struct setter_traits; + + template + struct setter_traits> { + using object_type = O; + using field_type = T; + }; + + template + struct setter_traits> { + using object_type = O; + using field_type = T; + }; + + template + struct setter_traits> { + using object_type = O; + using field_type = T; + }; + + template + struct member_traits; + + template + struct member_traits::value>::type> { + using object_type = typename field_member_traits::object_type; + using field_type = typename field_member_traits::field_type; + }; + + template + struct member_traits::value>::type> { + using object_type = typename getter_traits::object_type; + using field_type = typename getter_traits::field_type; + }; + + template + struct member_traits::value>::type> { + using object_type = typename setter_traits::object_type; + using field_type = typename setter_traits::field_type; + }; + } +} diff --git a/dev/index.h b/dev/index.h index ba6c3e0fd..2b68750f1 100644 --- a/dev/index.h +++ b/dev/index.h @@ -16,9 +16,6 @@ namespace sqlite_orm { std::string name; bool unique; columns_type columns; - - template - void for_each_column_with_constraints(const L &) {} }; } diff --git a/dev/serializator_context.h b/dev/serializator_context.h new file mode 100644 index 000000000..fa679eacd --- /dev/null +++ b/dev/serializator_context.h @@ -0,0 +1,31 @@ +#pragma once + +namespace sqlite_orm { + + namespace internal { + + struct serializator_context_base { + + template + std::string column_name(F O::*m) const { + return {}; + } + }; + + template + struct serializator_context : serializator_context_base { + using impl_type = I; + + const impl_type &impl; + + serializator_context(const impl_type &impl_) : impl(impl_) {} + + template + std::string column_name(F O::*m) const { + return this->impl.column_name(m); + } + }; + + } + +} diff --git a/dev/statement_serializator.h b/dev/statement_serializator.h index ac0a18342..d0e41a9ed 100644 --- a/dev/statement_serializator.h +++ b/dev/statement_serializator.h @@ -1,44 +1,52 @@ #pragma once -#include +#include // std::stringstream #include // std::string +#include // std::is_arithmetic, std::enable_if +#include // std::vector +#include // std::iter_swap #include "core_functions.h" #include "constraints.h" +#include "conditions.h" +#include "column.h" namespace sqlite_orm { namespace internal { template - struct statement_serializator { - using statement_type = T; + struct statement_serializator; - std::string operator()(const statement_type &t) const { - std::stringstream ss; - ss << t; - return ss.str(); - } - }; - - template - std::string serialize(const T &t) { + template + std::string serialize(const T &t, const C &context) { statement_serializator serializator; - return serializator(t); + return serializator(t, context); } + template + struct statement_serializator { + using statement_type = F O::*; + + template + std::string operator()(const statement_type &c, const C &context) const { + return context.impl.column_name(c); + } + }; + template struct statement_serializator, void> { using statement_type = core_functions::core_function_t; - std::string operator()(const statement_type &c) const { + template + std::string operator()(const statement_type &c, const C &context) const { std::stringstream ss; ss << static_cast(c) << "("; std::vector args; using args_type = typename std::decay::type::args_type; args.reserve(std::tuple_size::value); - iterate_tuple(c.args, [&args](auto &v) { - args.push_back(serialize(v)); + iterate_tuple(c.args, [&args, &context](auto &v) { + args.push_back(serialize(v, context)); }); for(size_t i = 0; i < args.size(); ++i) { ss << args[i]; @@ -55,7 +63,8 @@ namespace sqlite_orm { struct statement_serializator { using statement_type = constraints::autoincrement_t; - std::string operator()(const statement_type &c) const { + template + std::string operator()(const statement_type &c, const C &context) const { return static_cast(c); } }; @@ -64,8 +73,24 @@ namespace sqlite_orm { struct statement_serializator, void> { using statement_type = constraints::primary_key_t; - std::string operator()(const statement_type &c) const { - return static_cast(c); + template + std::string operator()(const statement_type &c, const C &context) const { + auto res = static_cast(c); + using columns_tuple = typename statement_type::columns_tuple; + auto columnsCount = std::tuple_size::value; + if(columnsCount) { + res += "("; + decltype(columnsCount) columnIndex = 0; + iterate_tuple(c.columns, [&context, &res, &columnIndex, columnsCount](auto &column) { + res += context.column_name(column); + if(columnIndex < columnsCount - 1) { + res += ", "; + } + ++columnIndex; + }); + res += ")"; + } + return res; } }; @@ -73,7 +98,8 @@ namespace sqlite_orm { struct statement_serializator { using statement_type = constraints::unique_t; - std::string operator()(const statement_type &c) const { + template + std::string operator()(const statement_type &c, const C &context) const { return static_cast(c); } }; @@ -82,7 +108,8 @@ namespace sqlite_orm { struct statement_serializator { using statement_type = constraints::collate_t; - std::string operator()(const statement_type &c) const { + template + std::string operator()(const statement_type &c, const C &context) const { return static_cast(c); } }; @@ -91,8 +118,9 @@ namespace sqlite_orm { struct statement_serializator, void> { using statement_type = constraints::default_t; - std::string operator()(const statement_type &c) const { - return static_cast(c) + " (" + serialize(c.value) + ")"; + template + std::string operator()(const statement_type &c, const C &context) const { + return static_cast(c) + " (" + serialize(c.value, context) + ")"; } }; @@ -100,7 +128,8 @@ namespace sqlite_orm { struct statement_serializator { using statement_type = std::string; - std::string operator()(const statement_type &c) const { + template + std::string operator()(const statement_type &c, const C &context) const { return "\"" + c + "\""; } }; @@ -109,10 +138,162 @@ namespace sqlite_orm { struct statement_serializator { using statement_type = const char *; - std::string operator()(const char *c) const { + template + std::string operator()(const char *c, const C &context) const { return std::string("'") + c + "'"; } }; + template + struct statement_serializator, std::tuple>, void> { + using statement_type = constraints::foreign_key_t, std::tuple>; + + template + std::string operator()(const statement_type &fk, const C &context) const { + std::stringstream ss; + std::vector columnNames; + using columns_type_t = typename std::decay::type::columns_type; + constexpr const size_t columnsCount = std::tuple_size::value; + columnNames.reserve(columnsCount); + iterate_tuple(fk.columns, [&columnNames, &context](auto &v) { + columnNames.push_back(context.impl.column_name(v)); + }); + ss << "FOREIGN KEY("; + for(size_t i = 0; i < columnNames.size(); ++i) { + ss << columnNames[i]; + if(i < columnNames.size() - 1) { + ss << ", "; + } + } + ss << ") REFERENCES "; + std::vector referencesNames; + using references_type_t = typename std::decay::type::references_type; + constexpr const size_t referencesCount = std::tuple_size::value; + referencesNames.reserve(referencesCount); + { + using first_reference_t = typename std::tuple_element<0, references_type_t>::type; + using first_reference_mapped_type = typename internal::table_type::type; + auto refTableName = context.impl.find_table_name(typeid(first_reference_mapped_type)); + ss << refTableName; + } + iterate_tuple(fk.references, [&referencesNames, &context](auto &v) { + referencesNames.push_back(context.impl.column_name(v)); + }); + ss << "("; + for(size_t i = 0; i < referencesNames.size(); ++i) { + ss << referencesNames[i]; + if(i < referencesNames.size() - 1) { + ss << ", "; + } + } + ss << ")"; + if(fk.on_update) { + ss << ' ' << static_cast(fk.on_update) << " " << fk.on_update._action; + } + if(fk.on_delete) { + ss << ' ' << static_cast(fk.on_delete) << " " << fk.on_delete._action; + } + return ss.str(); + } + }; + + template + struct statement_serializator, void> { + using statement_type = constraints::check_t; + + template + std::string operator()(const statement_type &c, const C &context) const { + return static_cast(c) + " " + serialize(c.expression, context); + } + }; + + template + struct statement_serializator, void> { + using statement_type = column_t; + + template + std::string operator()(const statement_type &c, const C &context) const { + std::stringstream ss; + ss << "'" << c.name << "' "; + using column_type = typename std::decay::type; + using field_type = typename column_type::field_type; + using constraints_type = typename column_type::constraints_type; + ss << type_printer().print() << " "; + { + std::vector constraintsStrings; + constexpr const size_t constraintsCount = std::tuple_size::value; + constraintsStrings.reserve(constraintsCount); + int primaryKeyIndex = -1; + int autoincrementIndex = -1; + int tupleIndex = 0; + iterate_tuple( + c.constraints, + [&constraintsStrings, &primaryKeyIndex, &autoincrementIndex, &tupleIndex, &context](auto &v) { + using constraint_type = typename std::decay::type; + constraintsStrings.push_back(serialize(v, context)); + if(is_primary_key::value) { + primaryKeyIndex = tupleIndex; + } else if(std::is_same::value) { + autoincrementIndex = tupleIndex; + } + ++tupleIndex; + }); + if(primaryKeyIndex != -1 && autoincrementIndex != -1 && autoincrementIndex < primaryKeyIndex) { + iter_swap(constraintsStrings.begin() + primaryKeyIndex, + constraintsStrings.begin() + autoincrementIndex); + } + for(auto &str: constraintsStrings) { + ss << str << ' '; + } + } + if(c.not_null()) { + ss << "NOT NULL "; + } + return ss.str(); + } + }; + + template + struct statement_serializator< + T, + typename std::enable_if::value>::type> { + using statement_type = T; + + template + std::string operator()(const statement_type &c, const C &context) const { + auto leftString = serialize(c.l, context); + auto rightString = serialize(c.r, context); + std::stringstream ss; + ss << "(" << leftString << " " << static_cast(c) << " " << rightString << ")"; + return ss.str(); + } + }; + + template + struct statement_serializator::value>::type> { + using statement_type = T; + + template + std::string operator()(const statement_type &t, const C &context) const { + std::stringstream ss; + ss << t; + return ss.str(); + } + }; + + template + struct statement_serializator, void> { + using statement_type = binary_operator; + + template + std::string operator()(const statement_type &c, const C &context) const { + auto lhs = serialize(c.lhs, context); + auto rhs = serialize(c.rhs, context); + std::stringstream ss; + ss << "(" << lhs << " " << static_cast(c) << " " << rhs << ")"; + return ss.str(); + } + }; + } } diff --git a/dev/static_magic.h b/dev/static_magic.h index 198f42297..96187120e 100644 --- a/dev/static_magic.h +++ b/dev/static_magic.h @@ -27,6 +27,9 @@ namespace sqlite_orm { auto static_if(T t) { return static_if(std::integral_constant{}, t, [](auto &&...) {}); } + + template + using static_not = std::integral_constant; } } diff --git a/dev/storage.h b/dev/storage.h index 2544642d8..3b1e24a4f 100644 --- a/dev/storage.h +++ b/dev/storage.h @@ -47,6 +47,7 @@ #include "storage_base.h" #include "prepared_statement.h" #include "expression_object_type.h" +#include "statement_serializator.h" namespace sqlite_orm { @@ -88,127 +89,16 @@ namespace sqlite_orm { template friend struct iterator_t; - template - std::string serialize_column_schema(const internal::column_t &c) { - std::stringstream ss; - ss << "'" << c.name << "' "; - using column_type = typename std::decay::type; - using field_type = typename column_type::field_type; - using constraints_type = typename column_type::constraints_type; - ss << type_printer().print() << " "; - { - std::vector constraintsStrings; - constexpr const size_t constraintsCount = std::tuple_size::value; - constraintsStrings.reserve(constraintsCount); - int primaryKeyIndex = -1; - int autoincrementIndex = -1; - int tupleIndex = 0; - iterate_tuple(c.constraints, - [&constraintsStrings, &primaryKeyIndex, &autoincrementIndex, &tupleIndex](auto &v) { - using constraint_type = typename std::decay::type; - constraintsStrings.push_back(serialize(v)); - if(is_primary_key::value) { - primaryKeyIndex = tupleIndex; - } else if(std::is_same::value) { - autoincrementIndex = tupleIndex; - } - ++tupleIndex; - }); - if(primaryKeyIndex != -1 && autoincrementIndex != -1 && autoincrementIndex < primaryKeyIndex) { - iter_swap(constraintsStrings.begin() + primaryKeyIndex, - constraintsStrings.begin() + autoincrementIndex); - } - for(auto &str: constraintsStrings) { - ss << str << ' '; - } - } - if(c.not_null()) { - ss << "NOT NULL "; - } - return ss.str(); - } - - template - std::string serialize_column_schema(const constraints::primary_key_t &fk) { - std::stringstream ss; - ss << static_cast(fk) << " ("; - std::vector columnNames; - columnNames.reserve(std::tuple_size::value); - iterate_tuple(fk.columns, [&columnNames, this](auto &c) { - columnNames.push_back(this->impl.column_name(c)); - }); - for(size_t i = 0; i < columnNames.size(); ++i) { - ss << columnNames[i]; - if(i < columnNames.size() - 1) { - ss << ", "; - } - } - ss << ") "; - return ss.str(); - } - -#if SQLITE_VERSION_NUMBER >= 3006019 - - template - std::string - serialize_column_schema(const constraints::foreign_key_t, std::tuple> &fk) { - std::stringstream ss; - std::vector columnNames; - using columns_type_t = typename std::decay::type::columns_type; - constexpr const size_t columnsCount = std::tuple_size::value; - columnNames.reserve(columnsCount); - iterate_tuple(fk.columns, [&columnNames, this](auto &v) { - columnNames.push_back(this->impl.column_name(v)); - }); - ss << "FOREIGN KEY( "; - for(size_t i = 0; i < columnNames.size(); ++i) { - ss << columnNames[i]; - if(i < columnNames.size() - 1) { - ss << ","; - } - ss << " "; - } - ss << ") REFERENCES "; - std::vector referencesNames; - using references_type_t = typename std::decay::type::references_type; - constexpr const size_t referencesCount = std::tuple_size::value; - referencesNames.reserve(referencesCount); - { - using first_reference_t = typename std::tuple_element<0, references_type_t>::type; - using first_reference_mapped_type = typename internal::table_type::type; - auto refTableName = this->impl.template find_table_name(); - ss << refTableName << " "; - } - iterate_tuple(fk.references, [&referencesNames, this](auto &v) { - referencesNames.push_back(this->impl.column_name(v)); - }); - ss << "( "; - for(size_t i = 0; i < referencesNames.size(); ++i) { - ss << referencesNames[i]; - if(i < referencesNames.size() - 1) { - ss << ","; - } - ss << " "; - } - ss << ") "; - if(fk.on_update) { - ss << static_cast(fk.on_update) << " " << fk.on_update._action << " "; - } - if(fk.on_delete) { - ss << static_cast(fk.on_delete) << " " << fk.on_delete._action << " "; - } - return ss.str(); - } -#endif - template void create_table(sqlite3 *db, const std::string &tableName, I *impl) { std::stringstream ss; ss << "CREATE TABLE '" << tableName << "' ( "; auto columnsCount = impl->table.columns_count; auto index = 0; - impl->table.for_each_column_with_constraints([columnsCount, &index, &ss, this](auto &c) { - ss << this->serialize_column_schema(c); + using context_t = serializator_context; + context_t context{this->impl}; + iterate_tuple(impl->table.columns, [columnsCount, &index, &ss, &context](auto &c) { + ss << serialize(c, context); if(index < columnsCount - 1) { ss << ", "; } @@ -343,7 +233,7 @@ namespace sqlite_orm { std::string string_from_expression(F O::*m, bool noTableName) const { std::stringstream ss; if(!noTableName) { - ss << "'" << this->impl.template find_table_name() << "'."; + ss << "'" << this->impl.find_table_name(typeid(O)) << "'."; } ss << "\"" << this->impl.column_name(m) << "\""; return ss.str(); @@ -365,7 +255,7 @@ namespace sqlite_orm { std::string string_from_expression(const table_rowid_t &rid, bool noTableName) const { std::stringstream ss; if(!noTableName) { - ss << "'" << this->impl.template find_table_name() << "'."; + ss << "'" << this->impl.find_table_name(typeid(O)) << "'."; } ss << static_cast(rid); return ss.str(); @@ -375,7 +265,7 @@ namespace sqlite_orm { std::string string_from_expression(const table_oid_t &rid, bool noTableName) const { std::stringstream ss; if(!noTableName) { - ss << "'" << this->impl.template find_table_name() << "'."; + ss << "'" << this->impl.find_table_name(typeid(O)) << "'."; } ss << static_cast(rid); return ss.str(); @@ -385,7 +275,7 @@ namespace sqlite_orm { std::string string_from_expression(const table__rowid_t &rid, bool noTableName) const { std::stringstream ss; if(!noTableName) { - ss << "'" << this->impl.template find_table_name() << "'."; + ss << "'" << this->impl.find_table_name(typeid(O)) << "'."; } ss << static_cast(rid); return ss.str(); @@ -500,7 +390,7 @@ namespace sqlite_orm { std::string string_from_expression(const column_pointer &c, bool noTableName) const { std::stringstream ss; if(!noTableName) { - ss << "'" << this->impl.template find_table_name() << "'."; + ss << "'" << this->impl.find_table_name(typeid(T)) << "'."; } auto &impl = this->get_impl(); ss << "\"" << impl.column_name_simple(c.field) << "\""; @@ -571,7 +461,7 @@ namespace sqlite_orm { internal::join_iterator()([&tableNamesSet, this](const auto &c) { using original_join_type = typename std::decay::type::join_type::type; using cross_join_type = typename internal::mapped_type_proxy::type; - auto crossJoinedTableName = this->impl.template find_table_name(); + auto crossJoinedTableName = this->impl.find_table_name(typeid(cross_join_type)); auto tableAliasString = alias_extractor::get(); std::pair tableNameWithAlias(std::move(crossJoinedTableName), std::move(tableAliasString)); @@ -1227,20 +1117,20 @@ namespace sqlite_orm { template void process_single_condition(std::stringstream &ss, const conditions::cross_join_t &c) const { ss << static_cast(c) << " "; - ss << " '" << this->impl.template find_table_name() << "'"; + ss << " '" << this->impl.find_table_name(typeid(O)) << "'"; } template void process_single_condition(std::stringstream &ss, const conditions::natural_join_t &c) const { ss << static_cast(c) << " "; - ss << " '" << this->impl.template find_table_name() << "'"; + ss << " '" << this->impl.find_table_name(typeid(O)) << "'"; } template void process_single_condition(std::stringstream &ss, const conditions::inner_join_t &l) const { ss << static_cast(l) << " "; auto aliasString = alias_extractor::get(); - ss << " '" << this->impl.template find_table_name::type>() << "' "; + ss << " '" << this->impl.find_table_name(typeid(typename mapped_type_proxy::type)) << "' "; if(aliasString.length()) { ss << "'" << aliasString << "' "; } @@ -1250,21 +1140,21 @@ namespace sqlite_orm { template void process_single_condition(std::stringstream &ss, const conditions::left_outer_join_t &l) const { ss << static_cast(l) << " "; - ss << " '" << this->impl.template find_table_name() << "' "; + ss << " '" << this->impl.find_table_name(typeid(T)) << "' "; this->process_join_constraint(ss, l.constraint); } template void process_single_condition(std::stringstream &ss, const conditions::left_join_t &l) const { ss << static_cast(l) << " "; - ss << " '" << this->impl.template find_table_name() << "' "; + ss << " '" << this->impl.find_table_name(typeid(T)) << "' "; this->process_join_constraint(ss, l.constraint); } template void process_single_condition(std::stringstream &ss, const conditions::join_t &l) const { ss << static_cast(l) << " "; - ss << " '" << this->impl.template find_table_name() << "' "; + ss << " '" << this->impl.find_table_name(typeid(T)) << "' "; this->process_join_constraint(ss, l.constraint); } @@ -1391,7 +1281,7 @@ namespace sqlite_orm { template std::set> parse_table_name(F O::*, std::string alias = {}) const { - return {std::make_pair(this->impl.template find_table_name(), std::move(alias))}; + return {std::make_pair(this->impl.find_table_name(typeid(O)), std::move(alias))}; } template @@ -1480,7 +1370,7 @@ namespace sqlite_orm { template std::set> parse_table_name(const column_pointer &) const { std::set> res; - res.insert({this->impl.template find_table_name(), ""}); + res.insert({this->impl.find_table_name(typeid(T)), ""}); return res; } @@ -1492,7 +1382,7 @@ namespace sqlite_orm { template std::set> parse_table_name(const aggregate_functions::count_asterisk_t &) const { - auto tableName = this->impl.template find_table_name(); + auto tableName = this->impl.find_table_name(typeid(T)); if(!tableName.empty()) { return {std::make_pair(std::move(tableName), "")}; } else { @@ -1507,7 +1397,7 @@ namespace sqlite_orm { template std::set> parse_table_name(const asterisk_t &) const { - auto tableName = this->impl.template find_table_name(); + auto tableName = this->impl.find_table_name(typeid(T)); return {std::make_pair(std::move(tableName), "")}; } @@ -2022,7 +1912,7 @@ namespace sqlite_orm { using head_t = typename std::tuple_element<0, columns_type>::type; using indexed_type = typename internal::table_type::type; ss << "INDEX IF NOT EXISTS '" << impl->table.name << "' ON '" - << this->impl.template find_table_name() << "' ( "; + << this->impl.find_table_name(typeid(indexed_type)) << "' ( "; std::vector columnNames; iterate_tuple(impl->table.columns, [&columnNames, this](auto &v) { columnNames.push_back(this->impl.column_name(v)); diff --git a/dev/storage_impl.h b/dev/storage_impl.h index 0be48cfe5..2cf029180 100644 --- a/dev/storage_impl.h +++ b/dev/storage_impl.h @@ -10,6 +10,7 @@ #include // std::pair, std::make_pair #include // std::vector #include // std::find_if +#include // std::type_index #include "error_code.h" #include "statement_finalizer.h" @@ -181,7 +182,7 @@ namespace sqlite_orm { */ int foreign_keys_count() { auto res = 0; - this->table.for_each_column_with_constraints([&res](auto &c) { + iterate_tuple(this->table.columns, [&res](auto &c) { if(internal::is_foreign_key::type>::value) { ++res; } @@ -201,22 +202,6 @@ namespace sqlite_orm { return this->table.find_column_name(m); } - /** - * Same thing as above for getter. - */ - template::value>::type> - std::string column_name_simple(T g) const { - return this->table.find_column_name(g); - } - - /** - * Same thing as above for setter. - */ - template::value>::type> - std::string column_name_simple(T s) const { - return this->table.find_column_name(s); - } - /** * Cute function used to find column name by its type and member pointer. Uses SFINAE to * skip inequal type O. @@ -236,44 +221,6 @@ namespace sqlite_orm { return this->super::column_name(m); } - /** - * Cute function used to find column name by its type and getter pointer. Uses SFINAE to - * skip inequal type O. - */ - template - std::string column_name(const F &(O::*g)() const, - typename std::enable_if::value>::type * = nullptr) const { - return this->table.find_column_name(g); - } - - /** - * Opposite version of function defined above. Just calls same function in superclass. - */ - template - std::string column_name(const F &(O::*g)() const, - typename std::enable_if::value>::type * = nullptr) const { - return this->super::column_name(g); - } - - /** - * Cute function used to find column name by its type and setter pointer. Uses SFINAE to - * skip inequal type O. - */ - template - std::string column_name(void (O::*s)(F), - typename std::enable_if::value>::type * = nullptr) const { - return this->table.find_column_name(s); - } - - /** - * Opposite version of function defined above. Just calls same function in superclass. - */ - template - std::string column_name(void (O::*s)(F), - typename std::enable_if::value>::type * = nullptr) const { - return this->super::column_name(s); - } - template std::string column_name(const column_pointer &c, typename std::enable_if::value>::type * = nullptr) const { @@ -296,14 +243,13 @@ namespace sqlite_orm { return this->super::template get_impl(); } - template - std::string find_table_name(typename std::enable_if::value>::type * = nullptr) const { - return this->table.name; - } - - template - std::string find_table_name(typename std::enable_if::value>::type * = nullptr) const { - return this->super::template find_table_name(); + std::string find_table_name(std::type_index ti) const { + std::type_index thisTypeIndex{typeid(typename H::object_type)}; + if(thisTypeIndex == ti) { + return this->table.name; + } else { + return this->super::find_table_name(ti); + } } template @@ -488,8 +434,7 @@ namespace sqlite_orm { template<> struct storage_impl<> : storage_impl_base { - template - std::string find_table_name() const { + std::string find_table_name(std::type_index ti) const { return {}; } diff --git a/dev/table.h b/dev/table.h index 05e0124ac..a82c5cb81 100644 --- a/dev/table.h +++ b/dev/table.h @@ -141,7 +141,7 @@ namespace sqlite_orm { } /** - * Searches column name by class member pointer passed as first argument. + * Searches column name by class member pointer passed as the first argument. * @return column name or empty string if nothing found. */ template void {} */ @@ -207,16 +207,12 @@ namespace sqlite_orm { }); } - template - void for_each_column_with_constraints(const L &l) const { - iterate_tuple(this->columns, l); - } - template void for_each_column_with_field_type(const L &l) const { iterate_tuple(this->columns, [&l](auto &column) { using column_type = typename std::decay::type; - static_if{}>(l)(column); + using field_type = typename column_field_type::type; + static_if{}>(l)(column); }); } @@ -231,7 +227,8 @@ namespace sqlite_orm { using tuple_helper::tuple_contains_type; iterate_tuple(this->columns, [&l](auto &column) { using column_type = typename std::decay::type; - static_if{}>(l)(column); + using constraints_type = typename column_constraints_type::type; + static_if{}>(l)(column); }); } diff --git a/examples/check.cpp b/examples/check.cpp new file mode 100644 index 000000000..865a6f16a --- /dev/null +++ b/examples/check.cpp @@ -0,0 +1,62 @@ +#include +#include +#include + +using namespace sqlite_orm; +using std::cout; +using std::endl; + +int main() { + struct Contact { + int id = 0; + std::string firstName; + std::string lastName; + std::string email; + std::string phone; + }; + + struct Product { + int id = 0; + std::string name; + float listPrice = 0; + float discount = 0; + }; + + auto storage = make_storage(":memory:", + make_table("contacts", + make_column("contact_id", &Contact::id, primary_key()), + make_column("first_name", &Contact::firstName), + make_column("last_name", &Contact::lastName), + make_column("email", &Contact::email), + make_column("phone", &Contact::phone), + check(length(&Contact::phone) >= 10)), + make_table("products", + make_column("product_id", &Product::id, primary_key()), + make_column("product_name", &Product::name), + make_column("list_price", &Product::listPrice), + make_column("discount", &Product::discount, default_value(0)), + check(c(&Product::listPrice) >= &Product::discount and + c(&Product::discount) >= 0 and c(&Product::listPrice) >= 0))); + storage.sync_schema(); + + try { + storage.insert(Contact{0, "John", "Doe", {}, "408123456"}); + } catch(const std::system_error &e) { + cout << e.what() << endl; + } + storage.insert(Contact{0, "John", "Doe", {}, "(408)-123-456"}); + + try { + storage.insert(Product{0, "New Product", 900, 1000}); + } catch(const std::system_error &e) { + cout << e.what() << endl; + } + + try { + storage.insert(Product{0, "New XFactor", 1000, -10}); + } catch(const std::system_error &e) { + cout << e.what() << endl; + } + + return 0; +} diff --git a/examples/in_memory.cpp b/examples/in_memory.cpp index 95c7a9ad8..f3f534aff 100644 --- a/examples/in_memory.cpp +++ b/examples/in_memory.cpp @@ -1,4 +1,3 @@ - #include #include diff --git a/include/sqlite_orm/sqlite_orm.h b/include/sqlite_orm/sqlite_orm.h index 2c9a01536..dba54e630 100644 --- a/include/sqlite_orm/sqlite_orm.h +++ b/include/sqlite_orm/sqlite_orm.h @@ -42,6 +42,7 @@ __pragma(push_macro("min")) incorrect_journal_mode_string, invalid_collate_argument_enum, failed_to_init_a_backup, + unknown_member_value, }; } @@ -77,6 +78,8 @@ namespace sqlite_orm { return "Invalid collate_argument enum"; case orm_error_code::failed_to_init_a_backup: return "Failed to init a backup"; + case orm_error_code::unknown_member_value: + return "Unknown member value"; default: return "unknown error"; } @@ -248,6 +251,9 @@ namespace sqlite_orm { auto static_if(T t) { return static_if(std::integral_constant{}, t, [](auto &&...) {}); } + + template + using static_not = std::integral_constant; } } @@ -532,13 +538,13 @@ namespace sqlite_orm { template struct primary_key_t : primary_key_base { using order_by = primary_key_base::order_by; + using columns_tuple = std::tuple; - std::tuple columns; + columns_tuple columns; - primary_key_t(decltype(columns) c) : columns(std::move(c)) {} + primary_key_t(decltype(columns) c) : columns(move(c)) {} - using field_type = void; // for column iteration. Better be deleted - using constraints_type = std::tuple<>; + // using constraints_type = std::tuple<>; primary_key_t asc() const { auto res = *this; @@ -734,8 +740,7 @@ namespace sqlite_orm { return *this; } - using field_type = void; // for column iteration. Better be deleted - using constraints_type = std::tuple<>; + // using constraints_type = std::tuple<>; template void for_each_column(const L &) {} @@ -789,6 +794,21 @@ namespace sqlite_orm { } }; + struct check_string { + operator std::string() const { + return "CHECK"; + } + }; + + template + struct check_t : check_string { + using expression_type = T; + + expression_type expression; + + check_t(expression_type expression_) : expression(std::move(expression_)) {} + }; + template struct is_constraint : std::false_type {}; @@ -810,6 +830,9 @@ namespace sqlite_orm { template<> struct is_constraint : std::true_type {}; + template + struct is_constraint> : std::true_type {}; + template struct constraints_size; @@ -870,6 +893,11 @@ namespace sqlite_orm { return {internal::collate_argument::rtrim}; } + template + constraints::check_t check(T t) { + return {std::move(t)}; + } + namespace internal { /** @@ -963,6 +991,38 @@ namespace sqlite_orm { // #include "constraints.h" +// #include "serializator_context.h" + +namespace sqlite_orm { + + namespace internal { + + struct serializator_context_base { + + template + std::string column_name(F O::*m) const { + return {}; + } + }; + + template + struct serializator_context : serializator_context_base { + using impl_type = I; + + const impl_type &impl; + + serializator_context(const impl_type &impl_) : impl(impl_) {} + + template + std::string column_name(F O::*m) const { + return this->impl.column_name(m); + } + }; + + } + +} + namespace sqlite_orm { namespace internal { @@ -983,7 +1043,8 @@ namespace sqlite_orm { template std::unique_ptr operator()(const constraints::default_t &t) { - return std::make_unique(serialize(t.value)); + serializator_context_base context; + return std::make_unique(serialize(t.value, context)); } }; @@ -1201,117 +1262,12 @@ namespace sqlite_orm { // #include "constraints.h" +// #include "getter_traits.h" + namespace sqlite_orm { namespace internal { - struct column_base { - - /** - * Column name. Specified during construction in `make_column`. - */ - const std::string name; - }; - - /** - * This class stores single column info. column_t is a pair of [column_name:member_pointer] mapped to a storage - * O is a mapped class, e.g. User - * T is a mapped class'es field type, e.g. &User::name - * Op... is a constraints pack, e.g. primary_key_t, autoincrement_t etc - */ - template - struct column_t : column_base { - using object_type = O; - using field_type = T; - using constraints_type = std::tuple; - using member_pointer_t = field_type object_type::*; - using getter_type = G; - using setter_type = S; - - /** - * Member pointer used to read/write member - */ - member_pointer_t member_pointer /* = nullptr*/; - - /** - * Getter member function pointer to get a value. If member_pointer is null than - * `getter` and `setter` must be not null - */ - getter_type getter /* = nullptr*/; - - /** - * Setter member function - */ - setter_type setter /* = nullptr*/; - - /** - * Constraints tuple - */ - constraints_type constraints; - - column_t(std::string name, - member_pointer_t member_pointer_, - getter_type getter_, - setter_type setter_, - constraints_type constraints_) : - column_base{std::move(name)}, - member_pointer(member_pointer_), getter(getter_), setter(setter_), - constraints(std::move(constraints_)) {} - - /** - * Simplified interface for `NOT NULL` constraint - */ - bool not_null() const { - return !type_is_nullable::value; - } - - template - constexpr bool has() const { - return tuple_helper::tuple_contains_type::value; - } - - template - constexpr bool has_every() const { - if(has() && has()) { - return true; - } else { - return has_every(); - } - } - - template - constexpr bool has_every() const { - return has(); - } - - /** - * Simplified interface for `DEFAULT` constraint - * @return string representation of default value if it exists otherwise nullptr - */ - std::unique_ptr default_value() const { - std::unique_ptr res; - iterate_tuple(this->constraints, [&res](auto &v) { - auto dft = internal::default_value_extractor()(v); - if(dft) { - res = std::move(dft); - } - }); - return res; - } - }; - - /** - * Column traits. Common case. - */ - template - struct is_column : public std::false_type {}; - - /** - * Column traits. Specialized case case. - */ - template - struct is_column> : public std::true_type {}; - template struct is_field_member_pointer : std::false_type {}; @@ -1321,9 +1277,18 @@ namespace sqlite_orm { !std::is_member_function_pointer::value>::type> : std::true_type {}; + template + struct field_member_traits; + + template + struct field_member_traits::value>::type> { + using object_type = O; + using field_type = F; + }; + /** - * Getters aliases - */ + * Getters aliases + */ template using getter_by_value_const = T (O::*)() const; @@ -1343,8 +1308,8 @@ namespace sqlite_orm { using getter_by_const_ref = const T &(O::*)(); /** - * Setters aliases - */ + * Setters aliases + */ template using setter_by_value = void (O::*)(T); @@ -1458,6 +1423,160 @@ namespace sqlite_orm { using object_type = O; using field_type = T; }; + + template + struct member_traits; + + template + struct member_traits::value>::type> { + using object_type = typename field_member_traits::object_type; + using field_type = typename field_member_traits::field_type; + }; + + template + struct member_traits::value>::type> { + using object_type = typename getter_traits::object_type; + using field_type = typename getter_traits::field_type; + }; + + template + struct member_traits::value>::type> { + using object_type = typename setter_traits::object_type; + using field_type = typename setter_traits::field_type; + }; + } +} + +namespace sqlite_orm { + + namespace internal { + + struct column_base { + + /** + * Column name. Specified during construction in `make_column`. + */ + const std::string name; + }; + + /** + * This class stores single column info. column_t is a pair of [column_name:member_pointer] mapped to a storage + * O is a mapped class, e.g. User + * T is a mapped class'es field type, e.g. &User::name + * Op... is a constraints pack, e.g. primary_key_t, autoincrement_t etc + */ + template + struct column_t : column_base { + using object_type = O; + using field_type = T; + using constraints_type = std::tuple; + using member_pointer_t = field_type object_type::*; + using getter_type = G; + using setter_type = S; + + /** + * Member pointer used to read/write member + */ + member_pointer_t member_pointer /* = nullptr*/; + + /** + * Getter member function pointer to get a value. If member_pointer is null than + * `getter` and `setter` must be not null + */ + getter_type getter /* = nullptr*/; + + /** + * Setter member function + */ + setter_type setter /* = nullptr*/; + + /** + * Constraints tuple + */ + constraints_type constraints; + + column_t(std::string name, + member_pointer_t member_pointer_, + getter_type getter_, + setter_type setter_, + constraints_type constraints_) : + column_base{std::move(name)}, + member_pointer(member_pointer_), getter(getter_), setter(setter_), constraints(move(constraints_)) {} + + /** + * Simplified interface for `NOT NULL` constraint + */ + bool not_null() const { + return !type_is_nullable::value; + } + + template + constexpr bool has() const { + return tuple_helper::tuple_contains_type::value; + } + + template + constexpr bool has_every() const { + if(has() && has()) { + return true; + } else { + return has_every(); + } + } + + template + constexpr bool has_every() const { + return has(); + } + + /** + * Simplified interface for `DEFAULT` constraint + * @return string representation of default value if it exists otherwise nullptr + */ + std::unique_ptr default_value() const { + std::unique_ptr res; + iterate_tuple(this->constraints, [&res](auto &v) { + auto dft = internal::default_value_extractor()(v); + if(dft) { + res = std::move(dft); + } + }); + return res; + } + }; + + /** + * Column traits. Common case. + */ + template + struct is_column : public std::false_type {}; + + /** + * Column traits. Specialized case case. + */ + template + struct is_column> : public std::true_type {}; + + template + struct column_field_type { + using type = void; + }; + + template + struct column_field_type> { + using type = typename column_t::field_type; + }; + + template + struct column_constraints_type { + using type = std::tuple<>; + }; + + template + struct column_constraints_type> { + using type = typename column_t::constraints_type; + }; + } /** @@ -1471,6 +1590,8 @@ namespace sqlite_orm { make_column(const std::string &name, T O::*m, Op... constraints) { static_assert(constraints::constraints_size::value == std::tuple_size>::value, "Incorrect constraints pack"); + static_assert(internal::is_field_member_pointer::value, + "second argument expected as a member field pointer, not member function pointer"); return {name, m, nullptr, nullptr, std::make_tuple(constraints...)}; } @@ -5276,9 +5397,6 @@ namespace sqlite_orm { std::string name; bool unique; columns_type columns; - - template - void for_each_column_with_constraints(const L &) {} }; } @@ -5947,7 +6065,7 @@ namespace sqlite_orm { } /** - * Searches column name by class member pointer passed as first argument. + * Searches column name by class member pointer passed as the first argument. * @return column name or empty string if nothing found. */ template void {} */ @@ -6013,16 +6131,12 @@ namespace sqlite_orm { }); } - template - void for_each_column_with_constraints(const L &l) const { - iterate_tuple(this->columns, l); - } - template void for_each_column_with_field_type(const L &l) const { iterate_tuple(this->columns, [&l](auto &column) { using column_type = typename std::decay::type; - static_if{}>(l)(column); + using field_type = typename column_field_type::type; + static_if{}>(l)(column); }); } @@ -6037,7 +6151,8 @@ namespace sqlite_orm { using tuple_helper::tuple_contains_type; iterate_tuple(this->columns, [&l](auto &column) { using column_type = typename std::decay::type; - static_if{}>(l)(column); + using constraints_type = typename column_constraints_type::type; + static_if{}>(l)(column); }); } @@ -6101,6 +6216,7 @@ namespace sqlite_orm { #include // std::pair, std::make_pair #include // std::vector #include // std::find_if +#include // std::type_index // #include "error_code.h" @@ -6307,7 +6423,7 @@ namespace sqlite_orm { */ int foreign_keys_count() { auto res = 0; - this->table.for_each_column_with_constraints([&res](auto &c) { + iterate_tuple(this->table.columns, [&res](auto &c) { if(internal::is_foreign_key::type>::value) { ++res; } @@ -6327,22 +6443,6 @@ namespace sqlite_orm { return this->table.find_column_name(m); } - /** - * Same thing as above for getter. - */ - template::value>::type> - std::string column_name_simple(T g) const { - return this->table.find_column_name(g); - } - - /** - * Same thing as above for setter. - */ - template::value>::type> - std::string column_name_simple(T s) const { - return this->table.find_column_name(s); - } - /** * Cute function used to find column name by its type and member pointer. Uses SFINAE to * skip inequal type O. @@ -6350,54 +6450,16 @@ namespace sqlite_orm { template std::string column_name(F O::*m, typename std::enable_if::value>::type * = nullptr) const { - return this->table.find_column_name(m); - } - - /** - * Opposite version of function defined above. Just calls same function in superclass. - */ - template - std::string column_name(F O::*m, - typename std::enable_if::value>::type * = nullptr) const { - return this->super::column_name(m); - } - - /** - * Cute function used to find column name by its type and getter pointer. Uses SFINAE to - * skip inequal type O. - */ - template - std::string column_name(const F &(O::*g)() const, - typename std::enable_if::value>::type * = nullptr) const { - return this->table.find_column_name(g); - } - - /** - * Opposite version of function defined above. Just calls same function in superclass. - */ - template - std::string column_name(const F &(O::*g)() const, - typename std::enable_if::value>::type * = nullptr) const { - return this->super::column_name(g); - } - - /** - * Cute function used to find column name by its type and setter pointer. Uses SFINAE to - * skip inequal type O. - */ - template - std::string column_name(void (O::*s)(F), - typename std::enable_if::value>::type * = nullptr) const { - return this->table.find_column_name(s); + return this->table.find_column_name(m); } /** * Opposite version of function defined above. Just calls same function in superclass. */ template - std::string column_name(void (O::*s)(F), + std::string column_name(F O::*m, typename std::enable_if::value>::type * = nullptr) const { - return this->super::column_name(s); + return this->super::column_name(m); } template @@ -6422,14 +6484,13 @@ namespace sqlite_orm { return this->super::template get_impl(); } - template - std::string find_table_name(typename std::enable_if::value>::type * = nullptr) const { - return this->table.name; - } - - template - std::string find_table_name(typename std::enable_if::value>::type * = nullptr) const { - return this->super::template find_table_name(); + std::string find_table_name(std::type_index ti) const { + std::type_index thisTypeIndex{typeid(typename H::object_type)}; + if(thisTypeIndex == ti) { + return this->table.name; + } else { + return this->super::find_table_name(ti); + } } template @@ -6614,8 +6675,7 @@ namespace sqlite_orm { template<> struct storage_impl<> : storage_impl_base { - template - std::string find_table_name() const { + std::string find_table_name(std::type_index ti) const { return {}; } @@ -8890,63 +8950,366 @@ namespace sqlite_orm { }; template - struct get_ref_t> { + struct get_ref_t> { + + template + auto &operator()(O &t) const { + return t.get(); + } + }; + + template + auto &get_ref(T &t) { + using arg_type = typename std::decay::type; + get_ref_t g; + return g(t); + } + + template + struct get_object_t; + + template + struct get_object_t : get_object_t {}; + + template + auto &get_object(T &t) { + using expression_type = typename std::decay::type; + get_object_t obj; + return obj(t); + } + + template + struct get_object_t> { + using expression_type = replace_t; + + template + auto &operator()(O &e) const { + return get_ref(e.obj); + } + }; + + template + struct get_object_t> { + using expression_type = insert_t; + + template + auto &operator()(O &e) const { + return get_ref(e.obj); + } + }; + + template + struct get_object_t> { + using expression_type = update_t; + + template + auto &operator()(O &e) const { + return get_ref(e.obj); + } + }; + } +} + +// #include "statement_serializator.h" + +#include // std::stringstream +#include // std::string +#include // std::is_arithmetic, std::enable_if +#include // std::vector +#include // std::iter_swap + +// #include "core_functions.h" + +// #include "constraints.h" + +// #include "conditions.h" + +// #include "column.h" + +namespace sqlite_orm { + + namespace internal { + + template + struct statement_serializator; + + template + std::string serialize(const T &t, const C &context) { + statement_serializator serializator; + return serializator(t, context); + } + + template + struct statement_serializator { + using statement_type = F O::*; + + template + std::string operator()(const statement_type &c, const C &context) const { + return context.impl.column_name(c); + } + }; + + template + struct statement_serializator, void> { + using statement_type = core_functions::core_function_t; + + template + std::string operator()(const statement_type &c, const C &context) const { + std::stringstream ss; + ss << static_cast(c) << "("; + std::vector args; + using args_type = typename std::decay::type::args_type; + args.reserve(std::tuple_size::value); + iterate_tuple(c.args, [&args, &context](auto &v) { + args.push_back(serialize(v, context)); + }); + for(size_t i = 0; i < args.size(); ++i) { + ss << args[i]; + if(i < args.size() - 1) { + ss << ", "; + } + } + ss << ")"; + return ss.str(); + } + }; + + template<> + struct statement_serializator { + using statement_type = constraints::autoincrement_t; + + template + std::string operator()(const statement_type &c, const C &context) const { + return static_cast(c); + } + }; + + template + struct statement_serializator, void> { + using statement_type = constraints::primary_key_t; + + template + std::string operator()(const statement_type &c, const C &context) const { + auto res = static_cast(c); + using columns_tuple = typename statement_type::columns_tuple; + auto columnsCount = std::tuple_size::value; + if(columnsCount) { + res += "("; + decltype(columnsCount) columnIndex = 0; + iterate_tuple(c.columns, [&context, &res, &columnIndex, columnsCount](auto &column) { + res += context.column_name(column); + if(columnIndex < columnsCount - 1) { + res += ", "; + } + ++columnIndex; + }); + res += ")"; + } + return res; + } + }; + + template<> + struct statement_serializator { + using statement_type = constraints::unique_t; + + template + std::string operator()(const statement_type &c, const C &context) const { + return static_cast(c); + } + }; + + template<> + struct statement_serializator { + using statement_type = constraints::collate_t; + + template + std::string operator()(const statement_type &c, const C &context) const { + return static_cast(c); + } + }; + + template + struct statement_serializator, void> { + using statement_type = constraints::default_t; + + template + std::string operator()(const statement_type &c, const C &context) const { + return static_cast(c) + " (" + serialize(c.value, context) + ")"; + } + }; + + template<> + struct statement_serializator { + using statement_type = std::string; + + template + std::string operator()(const statement_type &c, const C &context) const { + return "\"" + c + "\""; + } + }; + + template<> + struct statement_serializator { + using statement_type = const char *; + + template + std::string operator()(const char *c, const C &context) const { + return std::string("'") + c + "'"; + } + }; + + template + struct statement_serializator, std::tuple>, void> { + using statement_type = constraints::foreign_key_t, std::tuple>; + + template + std::string operator()(const statement_type &fk, const C &context) const { + std::stringstream ss; + std::vector columnNames; + using columns_type_t = typename std::decay::type::columns_type; + constexpr const size_t columnsCount = std::tuple_size::value; + columnNames.reserve(columnsCount); + iterate_tuple(fk.columns, [&columnNames, &context](auto &v) { + columnNames.push_back(context.impl.column_name(v)); + }); + ss << "FOREIGN KEY("; + for(size_t i = 0; i < columnNames.size(); ++i) { + ss << columnNames[i]; + if(i < columnNames.size() - 1) { + ss << ", "; + } + } + ss << ") REFERENCES "; + std::vector referencesNames; + using references_type_t = typename std::decay::type::references_type; + constexpr const size_t referencesCount = std::tuple_size::value; + referencesNames.reserve(referencesCount); + { + using first_reference_t = typename std::tuple_element<0, references_type_t>::type; + using first_reference_mapped_type = typename internal::table_type::type; + auto refTableName = context.impl.find_table_name(typeid(first_reference_mapped_type)); + ss << refTableName; + } + iterate_tuple(fk.references, [&referencesNames, &context](auto &v) { + referencesNames.push_back(context.impl.column_name(v)); + }); + ss << "("; + for(size_t i = 0; i < referencesNames.size(); ++i) { + ss << referencesNames[i]; + if(i < referencesNames.size() - 1) { + ss << ", "; + } + } + ss << ")"; + if(fk.on_update) { + ss << ' ' << static_cast(fk.on_update) << " " << fk.on_update._action; + } + if(fk.on_delete) { + ss << ' ' << static_cast(fk.on_delete) << " " << fk.on_delete._action; + } + return ss.str(); + } + }; + + template + struct statement_serializator, void> { + using statement_type = constraints::check_t; + + template + std::string operator()(const statement_type &c, const C &context) const { + return static_cast(c) + " " + serialize(c.expression, context); + } + }; + + template + struct statement_serializator, void> { + using statement_type = column_t; + + template + std::string operator()(const statement_type &c, const C &context) const { + std::stringstream ss; + ss << "'" << c.name << "' "; + using column_type = typename std::decay::type; + using field_type = typename column_type::field_type; + using constraints_type = typename column_type::constraints_type; + ss << type_printer().print() << " "; + { + std::vector constraintsStrings; + constexpr const size_t constraintsCount = std::tuple_size::value; + constraintsStrings.reserve(constraintsCount); + int primaryKeyIndex = -1; + int autoincrementIndex = -1; + int tupleIndex = 0; + iterate_tuple( + c.constraints, + [&constraintsStrings, &primaryKeyIndex, &autoincrementIndex, &tupleIndex, &context](auto &v) { + using constraint_type = typename std::decay::type; + constraintsStrings.push_back(serialize(v, context)); + if(is_primary_key::value) { + primaryKeyIndex = tupleIndex; + } else if(std::is_same::value) { + autoincrementIndex = tupleIndex; + } + ++tupleIndex; + }); + if(primaryKeyIndex != -1 && autoincrementIndex != -1 && autoincrementIndex < primaryKeyIndex) { + iter_swap(constraintsStrings.begin() + primaryKeyIndex, + constraintsStrings.begin() + autoincrementIndex); + } + for(auto &str: constraintsStrings) { + ss << str << ' '; + } + } + if(c.not_null()) { + ss << "NOT NULL "; + } + return ss.str(); + } + }; + + template + struct statement_serializator< + T, + typename std::enable_if::value>::type> { + using statement_type = T; - template - auto &operator()(O &t) const { - return t.get(); + template + std::string operator()(const statement_type &c, const C &context) const { + auto leftString = serialize(c.l, context); + auto rightString = serialize(c.r, context); + std::stringstream ss; + ss << "(" << leftString << " " << static_cast(c) << " " << rightString << ")"; + return ss.str(); } }; template - auto &get_ref(T &t) { - using arg_type = typename std::decay::type; - get_ref_t g; - return g(t); - } - - template - struct get_object_t; - - template - struct get_object_t : get_object_t {}; - - template - auto &get_object(T &t) { - using expression_type = typename std::decay::type; - get_object_t obj; - return obj(t); - } - - template - struct get_object_t> { - using expression_type = replace_t; + struct statement_serializator::value>::type> { + using statement_type = T; - template - auto &operator()(O &e) const { - return get_ref(e.obj); + template + std::string operator()(const statement_type &t, const C &context) const { + std::stringstream ss; + ss << t; + return ss.str(); } }; - template - struct get_object_t> { - using expression_type = insert_t; + template + struct statement_serializator, void> { + using statement_type = binary_operator; - template - auto &operator()(O &e) const { - return get_ref(e.obj); + template + std::string operator()(const statement_type &c, const C &context) const { + auto lhs = serialize(c.lhs, context); + auto rhs = serialize(c.rhs, context); + std::stringstream ss; + ss << "(" << lhs << " " << static_cast(c) << " " << rhs << ")"; + return ss.str(); } }; - template - struct get_object_t> { - using expression_type = update_t; - - template - auto &operator()(O &e) const { - return get_ref(e.obj); - } - }; } } @@ -8990,127 +9353,16 @@ namespace sqlite_orm { template friend struct iterator_t; - template - std::string serialize_column_schema(const internal::column_t &c) { - std::stringstream ss; - ss << "'" << c.name << "' "; - using column_type = typename std::decay::type; - using field_type = typename column_type::field_type; - using constraints_type = typename column_type::constraints_type; - ss << type_printer().print() << " "; - { - std::vector constraintsStrings; - constexpr const size_t constraintsCount = std::tuple_size::value; - constraintsStrings.reserve(constraintsCount); - int primaryKeyIndex = -1; - int autoincrementIndex = -1; - int tupleIndex = 0; - iterate_tuple(c.constraints, - [&constraintsStrings, &primaryKeyIndex, &autoincrementIndex, &tupleIndex](auto &v) { - using constraint_type = typename std::decay::type; - constraintsStrings.push_back(serialize(v)); - if(is_primary_key::value) { - primaryKeyIndex = tupleIndex; - } else if(std::is_same::value) { - autoincrementIndex = tupleIndex; - } - ++tupleIndex; - }); - if(primaryKeyIndex != -1 && autoincrementIndex != -1 && autoincrementIndex < primaryKeyIndex) { - iter_swap(constraintsStrings.begin() + primaryKeyIndex, - constraintsStrings.begin() + autoincrementIndex); - } - for(auto &str: constraintsStrings) { - ss << str << ' '; - } - } - if(c.not_null()) { - ss << "NOT NULL "; - } - return ss.str(); - } - - template - std::string serialize_column_schema(const constraints::primary_key_t &fk) { - std::stringstream ss; - ss << static_cast(fk) << " ("; - std::vector columnNames; - columnNames.reserve(std::tuple_size::value); - iterate_tuple(fk.columns, [&columnNames, this](auto &c) { - columnNames.push_back(this->impl.column_name(c)); - }); - for(size_t i = 0; i < columnNames.size(); ++i) { - ss << columnNames[i]; - if(i < columnNames.size() - 1) { - ss << ", "; - } - } - ss << ") "; - return ss.str(); - } - -#if SQLITE_VERSION_NUMBER >= 3006019 - - template - std::string - serialize_column_schema(const constraints::foreign_key_t, std::tuple> &fk) { - std::stringstream ss; - std::vector columnNames; - using columns_type_t = typename std::decay::type::columns_type; - constexpr const size_t columnsCount = std::tuple_size::value; - columnNames.reserve(columnsCount); - iterate_tuple(fk.columns, [&columnNames, this](auto &v) { - columnNames.push_back(this->impl.column_name(v)); - }); - ss << "FOREIGN KEY( "; - for(size_t i = 0; i < columnNames.size(); ++i) { - ss << columnNames[i]; - if(i < columnNames.size() - 1) { - ss << ","; - } - ss << " "; - } - ss << ") REFERENCES "; - std::vector referencesNames; - using references_type_t = typename std::decay::type::references_type; - constexpr const size_t referencesCount = std::tuple_size::value; - referencesNames.reserve(referencesCount); - { - using first_reference_t = typename std::tuple_element<0, references_type_t>::type; - using first_reference_mapped_type = typename internal::table_type::type; - auto refTableName = this->impl.template find_table_name(); - ss << refTableName << " "; - } - iterate_tuple(fk.references, [&referencesNames, this](auto &v) { - referencesNames.push_back(this->impl.column_name(v)); - }); - ss << "( "; - for(size_t i = 0; i < referencesNames.size(); ++i) { - ss << referencesNames[i]; - if(i < referencesNames.size() - 1) { - ss << ","; - } - ss << " "; - } - ss << ") "; - if(fk.on_update) { - ss << static_cast(fk.on_update) << " " << fk.on_update._action << " "; - } - if(fk.on_delete) { - ss << static_cast(fk.on_delete) << " " << fk.on_delete._action << " "; - } - return ss.str(); - } -#endif - template void create_table(sqlite3 *db, const std::string &tableName, I *impl) { std::stringstream ss; ss << "CREATE TABLE '" << tableName << "' ( "; auto columnsCount = impl->table.columns_count; auto index = 0; - impl->table.for_each_column_with_constraints([columnsCount, &index, &ss, this](auto &c) { - ss << this->serialize_column_schema(c); + using context_t = serializator_context; + context_t context{this->impl}; + iterate_tuple(impl->table.columns, [columnsCount, &index, &ss, &context](auto &c) { + ss << serialize(c, context); if(index < columnsCount - 1) { ss << ", "; } @@ -9245,7 +9497,7 @@ namespace sqlite_orm { std::string string_from_expression(F O::*m, bool noTableName) const { std::stringstream ss; if(!noTableName) { - ss << "'" << this->impl.template find_table_name() << "'."; + ss << "'" << this->impl.find_table_name(typeid(O)) << "'."; } ss << "\"" << this->impl.column_name(m) << "\""; return ss.str(); @@ -9267,7 +9519,7 @@ namespace sqlite_orm { std::string string_from_expression(const table_rowid_t &rid, bool noTableName) const { std::stringstream ss; if(!noTableName) { - ss << "'" << this->impl.template find_table_name() << "'."; + ss << "'" << this->impl.find_table_name(typeid(O)) << "'."; } ss << static_cast(rid); return ss.str(); @@ -9277,7 +9529,7 @@ namespace sqlite_orm { std::string string_from_expression(const table_oid_t &rid, bool noTableName) const { std::stringstream ss; if(!noTableName) { - ss << "'" << this->impl.template find_table_name() << "'."; + ss << "'" << this->impl.find_table_name(typeid(O)) << "'."; } ss << static_cast(rid); return ss.str(); @@ -9287,7 +9539,7 @@ namespace sqlite_orm { std::string string_from_expression(const table__rowid_t &rid, bool noTableName) const { std::stringstream ss; if(!noTableName) { - ss << "'" << this->impl.template find_table_name() << "'."; + ss << "'" << this->impl.find_table_name(typeid(O)) << "'."; } ss << static_cast(rid); return ss.str(); @@ -9402,7 +9654,7 @@ namespace sqlite_orm { std::string string_from_expression(const column_pointer &c, bool noTableName) const { std::stringstream ss; if(!noTableName) { - ss << "'" << this->impl.template find_table_name() << "'."; + ss << "'" << this->impl.find_table_name(typeid(T)) << "'."; } auto &impl = this->get_impl(); ss << "\"" << impl.column_name_simple(c.field) << "\""; @@ -9473,7 +9725,7 @@ namespace sqlite_orm { internal::join_iterator()([&tableNamesSet, this](const auto &c) { using original_join_type = typename std::decay::type::join_type::type; using cross_join_type = typename internal::mapped_type_proxy::type; - auto crossJoinedTableName = this->impl.template find_table_name(); + auto crossJoinedTableName = this->impl.find_table_name(typeid(cross_join_type)); auto tableAliasString = alias_extractor::get(); std::pair tableNameWithAlias(std::move(crossJoinedTableName), std::move(tableAliasString)); @@ -10129,20 +10381,20 @@ namespace sqlite_orm { template void process_single_condition(std::stringstream &ss, const conditions::cross_join_t &c) const { ss << static_cast(c) << " "; - ss << " '" << this->impl.template find_table_name() << "'"; + ss << " '" << this->impl.find_table_name(typeid(O)) << "'"; } template void process_single_condition(std::stringstream &ss, const conditions::natural_join_t &c) const { ss << static_cast(c) << " "; - ss << " '" << this->impl.template find_table_name() << "'"; + ss << " '" << this->impl.find_table_name(typeid(O)) << "'"; } template void process_single_condition(std::stringstream &ss, const conditions::inner_join_t &l) const { ss << static_cast(l) << " "; auto aliasString = alias_extractor::get(); - ss << " '" << this->impl.template find_table_name::type>() << "' "; + ss << " '" << this->impl.find_table_name(typeid(typename mapped_type_proxy::type)) << "' "; if(aliasString.length()) { ss << "'" << aliasString << "' "; } @@ -10152,21 +10404,21 @@ namespace sqlite_orm { template void process_single_condition(std::stringstream &ss, const conditions::left_outer_join_t &l) const { ss << static_cast(l) << " "; - ss << " '" << this->impl.template find_table_name() << "' "; + ss << " '" << this->impl.find_table_name(typeid(T)) << "' "; this->process_join_constraint(ss, l.constraint); } template void process_single_condition(std::stringstream &ss, const conditions::left_join_t &l) const { ss << static_cast(l) << " "; - ss << " '" << this->impl.template find_table_name() << "' "; + ss << " '" << this->impl.find_table_name(typeid(T)) << "' "; this->process_join_constraint(ss, l.constraint); } template void process_single_condition(std::stringstream &ss, const conditions::join_t &l) const { ss << static_cast(l) << " "; - ss << " '" << this->impl.template find_table_name() << "' "; + ss << " '" << this->impl.find_table_name(typeid(T)) << "' "; this->process_join_constraint(ss, l.constraint); } @@ -10293,7 +10545,7 @@ namespace sqlite_orm { template std::set> parse_table_name(F O::*, std::string alias = {}) const { - return {std::make_pair(this->impl.template find_table_name(), std::move(alias))}; + return {std::make_pair(this->impl.find_table_name(typeid(O)), std::move(alias))}; } template @@ -10382,7 +10634,7 @@ namespace sqlite_orm { template std::set> parse_table_name(const column_pointer &) const { std::set> res; - res.insert({this->impl.template find_table_name(), ""}); + res.insert({this->impl.find_table_name(typeid(T)), ""}); return res; } @@ -10394,7 +10646,7 @@ namespace sqlite_orm { template std::set> parse_table_name(const aggregate_functions::count_asterisk_t &) const { - auto tableName = this->impl.template find_table_name(); + auto tableName = this->impl.find_table_name(typeid(T)); if(!tableName.empty()) { return {std::make_pair(std::move(tableName), "")}; } else { @@ -10409,7 +10661,7 @@ namespace sqlite_orm { template std::set> parse_table_name(const asterisk_t &) const { - auto tableName = this->impl.template find_table_name(); + auto tableName = this->impl.find_table_name(typeid(T)); return {std::make_pair(std::move(tableName), "")}; } @@ -10924,7 +11176,7 @@ namespace sqlite_orm { using head_t = typename std::tuple_element<0, columns_type>::type; using indexed_type = typename internal::table_type::type; ss << "INDEX IF NOT EXISTS '" << impl->table.name << "' ON '" - << this->impl.template find_table_name() << "' ( "; + << this->impl.find_table_name(typeid(indexed_type)) << "' ( "; std::vector columnNames; iterate_tuple(impl->table.columns, [&columnNames, this](auto &v) { columnNames.push_back(this->impl.column_name(v)); @@ -12430,122 +12682,3 @@ namespace sqlite_orm { return internal::get_ref(*result); } } -#pragma once - -#include -#include // std::string - -// #include "core_functions.h" - -// #include "constraints.h" - -namespace sqlite_orm { - - namespace internal { - - template - struct statement_serializator { - using statement_type = T; - - std::string operator()(const statement_type &t) const { - std::stringstream ss; - ss << t; - return ss.str(); - } - }; - - template - std::string serialize(const T &t) { - statement_serializator serializator; - return serializator(t); - } - - template - struct statement_serializator, void> { - using statement_type = core_functions::core_function_t; - - std::string operator()(const statement_type &c) const { - std::stringstream ss; - ss << static_cast(c) << "("; - std::vector args; - using args_type = typename std::decay::type::args_type; - args.reserve(std::tuple_size::value); - iterate_tuple(c.args, [&args](auto &v) { - args.push_back(serialize(v)); - }); - for(size_t i = 0; i < args.size(); ++i) { - ss << args[i]; - if(i < args.size() - 1) { - ss << ", "; - } - } - ss << ")"; - return ss.str(); - } - }; - - template<> - struct statement_serializator { - using statement_type = constraints::autoincrement_t; - - std::string operator()(const statement_type &c) const { - return static_cast(c); - } - }; - - template - struct statement_serializator, void> { - using statement_type = constraints::primary_key_t; - - std::string operator()(const statement_type &c) const { - return static_cast(c); - } - }; - - template<> - struct statement_serializator { - using statement_type = constraints::unique_t; - - std::string operator()(const statement_type &c) const { - return static_cast(c); - } - }; - - template<> - struct statement_serializator { - using statement_type = constraints::collate_t; - - std::string operator()(const statement_type &c) const { - return static_cast(c); - } - }; - - template - struct statement_serializator, void> { - using statement_type = constraints::default_t; - - std::string operator()(const statement_type &c) const { - return static_cast(c) + " (" + serialize(c.value) + ")"; - } - }; - - template<> - struct statement_serializator { - using statement_type = std::string; - - std::string operator()(const statement_type &c) const { - return "\"" + c + "\""; - } - }; - - template<> - struct statement_serializator { - using statement_type = const char *; - - std::string operator()(const char *c) const { - return std::string("'") + c + "'"; - } - }; - - } -} diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 768caf4aa..17c01152e 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -10,7 +10,7 @@ else() add_subdirectory(third_party/sqlite) endif() -add_executable(unit_tests tests.cpp tests2.cpp tests3.cpp tests4.cpp tests4.cpp private_getters_tests.cpp pragma_tests.cpp explicit_columns.cpp core_functions_tests.cpp composite_key.cpp static_tests.cpp operators/arithmetic_operators.cpp operators/like.cpp operators/glob.cpp operators/in.cpp operators/cast.cpp operators/is_null.cpp dynamic_order_by.cpp prepared_statement_tests/select.cpp prepared_statement_tests/get_all.cpp prepared_statement_tests/get_all_pointer.cpp prepared_statement_tests/get_all_optional.cpp prepared_statement_tests/update_all.cpp prepared_statement_tests/remove_all.cpp prepared_statement_tests/get.cpp prepared_statement_tests/get_pointer.cpp prepared_statement_tests/get_optional.cpp prepared_statement_tests/update.cpp prepared_statement_tests/remove.cpp prepared_statement_tests/insert.cpp prepared_statement_tests/replace.cpp prepared_statement_tests/insert_range.cpp prepared_statement_tests/replace_range.cpp prepared_statement_tests/insert_explicit.cpp pragma_tests.cpp simple_query.cpp static_tests/is_bindable.cpp static_tests/arithmetic_operators_result_type.cpp static_tests/tuple_conc.cpp static_tests/node_tuple.cpp static_tests/bindable_filter.cpp static_tests/count_tuple.cpp constraints/default.cpp constraints/foreign_key.cpp) +add_executable(unit_tests tests.cpp tests2.cpp tests3.cpp tests4.cpp tests4.cpp private_getters_tests.cpp pragma_tests.cpp explicit_columns.cpp core_functions_tests.cpp composite_key.cpp static_tests.cpp operators/arithmetic_operators.cpp operators/like.cpp operators/glob.cpp operators/in.cpp operators/cast.cpp operators/is_null.cpp dynamic_order_by.cpp prepared_statement_tests/select.cpp prepared_statement_tests/get_all.cpp prepared_statement_tests/get_all_pointer.cpp prepared_statement_tests/get_all_optional.cpp prepared_statement_tests/update_all.cpp prepared_statement_tests/remove_all.cpp prepared_statement_tests/get.cpp prepared_statement_tests/get_pointer.cpp prepared_statement_tests/get_optional.cpp prepared_statement_tests/update.cpp prepared_statement_tests/remove.cpp prepared_statement_tests/insert.cpp prepared_statement_tests/replace.cpp prepared_statement_tests/insert_range.cpp prepared_statement_tests/replace_range.cpp prepared_statement_tests/insert_explicit.cpp pragma_tests.cpp simple_query.cpp static_tests/is_bindable.cpp static_tests/arithmetic_operators_result_type.cpp static_tests/tuple_conc.cpp static_tests/node_tuple.cpp static_tests/bindable_filter.cpp static_tests/count_tuple.cpp static_tests/member_traits_tests.cpp constraints/default.cpp constraints/foreign_key.cpp constraints/check.cpp table_tests.cpp statement_serializator_tests/primary_key.cpp statement_serializator_tests/column_names.cpp statement_serializator_tests/autoincrement.cpp statement_serializator_tests/arithmetic_operators.cpp statement_serializator_tests/core_functions.cpp statement_serializator_tests/comparison_operators.cpp statement_serializator_tests/unique.cpp statement_serializator_tests/foreign_key.cpp statement_serializator_tests/collate.cpp statement_serializator_tests/check.cpp) if(SQLITE_ORM_OMITS_CODECVT) diff --git a/tests/constraints/check.cpp b/tests/constraints/check.cpp new file mode 100644 index 000000000..083c4da17 --- /dev/null +++ b/tests/constraints/check.cpp @@ -0,0 +1,40 @@ +#include +#include + +using namespace sqlite_orm; + +TEST_CASE("check") { + { + struct Contact { + int id = 0; + std::string firstName; + std::string lastName; + std::unique_ptr email; + std::string phone; + }; + auto storage = make_storage({}, + make_table("contacts", + make_column("contact_id", &Contact::id, primary_key()), + make_column("first_name", &Contact::firstName), + make_column("last_name", &Contact::lastName), + make_column("email", &Contact::email), + make_column("phone", &Contact::phone), + check(length(&Contact::phone) >= 10))); + storage.sync_schema(); + } + { + struct Book { + int id = 0; + std::string name; + std::string pubName; + int price = 0; + }; + auto storage = make_storage({}, + make_table("BOOK", + make_column("Book_id", &Book::id, primary_key()), + make_column("Book_name", &Book::name), + make_column("Pub_name", &Book::pubName), + make_column("PRICE", &Book::price, check(c(&Book::price) > 0)))); + storage.sync_schema(); + } +} diff --git a/tests/explicit_columns.cpp b/tests/explicit_columns.cpp index 665adc6f3..3ea6e77c5 100644 --- a/tests/explicit_columns.cpp +++ b/tests/explicit_columns.cpp @@ -28,7 +28,7 @@ TEST_CASE("Explicit colums") { make_table("tokens", make_column("id", &Token::id, primary_key()), make_column("token", &Token::token), - make_column("used_id", &Token::usedId), + make_column("user_id", &Token::usedId), foreign_key(&Token::usedId).references(column(&User::id)))); storage.sync_schema(); REQUIRE(storage.table_exists("users")); diff --git a/tests/operators/is_null.cpp b/tests/operators/is_null.cpp index d7137f5ac..5d7b7e6e9 100644 --- a/tests/operators/is_null.cpp +++ b/tests/operators/is_null.cpp @@ -13,10 +13,12 @@ TEST_CASE("Is null") { make_table("users", make_column("id", &User::id, primary_key()), make_column("name", &User::name))); storage.sync_schema(); + REQUIRE(storage.count() == 0); storage.replace(User{1, std::make_unique("Sheldon")}); + REQUIRE(storage.count() == 1); storage.replace(User{2}); + REQUIRE(storage.count() == 2); storage.replace(User{3, std::make_unique("Leonard")}); - REQUIRE(storage.count() == 3); REQUIRE(storage.count(where(is_null(&User::name))) == 1); REQUIRE(storage.count(where(is_not_null(&User::name))) == 2); diff --git a/tests/statement_serializator_tests/arithmetic_operators.cpp b/tests/statement_serializator_tests/arithmetic_operators.cpp new file mode 100644 index 000000000..5c82413d5 --- /dev/null +++ b/tests/statement_serializator_tests/arithmetic_operators.cpp @@ -0,0 +1,58 @@ +#include +#include + +using namespace sqlite_orm; + +TEST_CASE("statement_serializator arithmetic operators") { + internal::serializator_context_base context; + SECTION("add") { + std::string value; + SECTION("func") { + value = serialize(add(3, 5), context); + } + SECTION("operator") { + value = serialize(c(3) + 5, context); + } + REQUIRE(value == "(3 + 5)"); + } + SECTION("sub") { + std::string value; + SECTION("func") { + value = serialize(sub(5, -9), context); + } + SECTION("operator") { + value = serialize(c(5) - -9, context); + } + REQUIRE(value == "(5 - -9)"); + } + SECTION("mul") { + std::string value; + SECTION("func") { + value = serialize(mul(10, 0.5), context); + } + SECTION("operator") { + value = serialize(c(10) * 0.5, context); + } + REQUIRE(value == "(10 * 0.5)"); + } + SECTION("div") { + std::string value; + SECTION("func") { + value = serialize(sqlite_orm::div(10, 2), context); + } + SECTION("operator") { + value = serialize(c(10) / 2, context); + } + REQUIRE(value == "(10 / 2)"); + } + SECTION("mod") { + std::string value; + SECTION("func") { + value = serialize(mod(20, 3), context); + } + SECTION("operator") { + value = serialize(c(20) % 3, context); + } + REQUIRE(value == "(20 % 3)"); + } +} diff --git a/tests/statement_serializator_tests/autoincrement.cpp b/tests/statement_serializator_tests/autoincrement.cpp new file mode 100644 index 000000000..a1e2f4f50 --- /dev/null +++ b/tests/statement_serializator_tests/autoincrement.cpp @@ -0,0 +1,11 @@ +#include +#include + +using namespace sqlite_orm; + +TEST_CASE("statement_serializator autoincrement") { + internal::serializator_context_base context; + auto autoinc = autoincrement(); + auto value = serialize(autoinc, context); + REQUIRE(value == "AUTOINCREMENT"); +} diff --git a/tests/statement_serializator_tests/check.cpp b/tests/statement_serializator_tests/check.cpp new file mode 100644 index 000000000..12a649606 --- /dev/null +++ b/tests/statement_serializator_tests/check.cpp @@ -0,0 +1,52 @@ +#include +#include + +using namespace sqlite_orm; + +TEST_CASE("statement_serializator check") { + { + struct Table { + int col1 = 0; + std::string col2; + int col3 = 0; + }; + auto ch = check(greater_than(&Table::col3, 0)); + auto table = make_table("tablename", + make_column("col1", &Table::col1, primary_key()), + make_column("col2", &Table::col2), + make_column("col3", &Table::col3, ch)); + + using storage_impl_t = internal::storage_impl; + + storage_impl_t storageImpl{table}; + + using context_t = internal::serializator_context; + + context_t context{storageImpl}; + auto value = serialize(ch, context); + REQUIRE(value == "CHECK (col3 > 0)"); + } + { + struct Book { + int id = 0; + std::string name; + std::string pubName; + int price = 0; + }; + auto ch = check(lesser_than(0, &Book::price)); + auto table = make_table("BOOK", + make_column("Book_id", &Book::id, primary_key()), + make_column("Book_name", &Book::name), + make_column("Pub_name", &Book::pubName), + make_column("PRICE", &Book::price, ch)); + using storage_impl_t = internal::storage_impl; + + storage_impl_t storageImpl{table}; + + using context_t = internal::serializator_context; + + context_t context{storageImpl}; + auto value = serialize(ch, context); + REQUIRE(value == "CHECK (0 < PRICE)"); + } +} diff --git a/tests/statement_serializator_tests/collate.cpp b/tests/statement_serializator_tests/collate.cpp new file mode 100644 index 000000000..4d1b97d39 --- /dev/null +++ b/tests/statement_serializator_tests/collate.cpp @@ -0,0 +1,23 @@ +#include +#include + +using namespace sqlite_orm; + +TEST_CASE("statement_serializator collate") { + internal::serializator_context_base context; + { + auto col = collate_nocase(); + auto value = serialize(col, context); + REQUIRE(value == "COLLATE NOCASE"); + } + { + auto col = collate_binary(); + auto value = serialize(col, context); + REQUIRE(value == "COLLATE BINARY"); + } + { + auto col = collate_rtrim(); + auto value = serialize(col, context); + REQUIRE(value == "COLLATE RTRIM"); + } +} diff --git a/tests/statement_serializator_tests/column_names.cpp b/tests/statement_serializator_tests/column_names.cpp new file mode 100644 index 000000000..d6b12248e --- /dev/null +++ b/tests/statement_serializator_tests/column_names.cpp @@ -0,0 +1,106 @@ +#include +#include + +using namespace sqlite_orm; + +TEST_CASE("statement_serializator column names") { + { // by member field pointer + struct User { + int id = 0; + std::string name; + }; + auto table = make_table("users", make_column("id", &User::id), make_column("name", &User::name)); + using storage_impl_t = internal::storage_impl; + storage_impl_t storageImpl{table}; + { + using context_t = internal::serializator_context; + context_t context{storageImpl}; + { + auto value = serialize(&User::id, context); + REQUIRE(value == "id"); + } + { + auto value = serialize(&User::name, context); + REQUIRE(value == "name"); + } + } + } + { // by getters and setters pointers + struct User { + + int getId() const { + return this->id; + } + + void setId(int value) { + this->id = value; + } + + const std::string &getName() const { + return this->name; + } + + void setName(std::string value) { + this->name = move(value); + } + + private: + int id = 0; + std::string name; + }; + { + auto table = make_table("users", + make_column("id", &User::getId, &User::setId), + make_column("name", &User::getName, &User::setName)); + using storage_impl_t = internal::storage_impl; + storage_impl_t storageImpl{table}; + { + using context_t = internal::serializator_context; + context_t context{storageImpl}; + { + auto value = serialize(&User::getId, context); + REQUIRE(value == "id"); + } + { + auto value = serialize(&User::setId, context); + REQUIRE(value == "id"); + } + { + auto value = serialize(&User::getName, context); + REQUIRE(value == "name"); + } + { + auto value = serialize(&User::setName, context); + REQUIRE(value == "name"); + } + } + } + { // column names by setters and getters pointers (reverse order) + auto table = make_table("users", + make_column("id", &User::setId, &User::getId), + make_column("name", &User::setName, &User::getName)); + using storage_impl_t = internal::storage_impl; + storage_impl_t storageImpl{table}; + { + using context_t = internal::serializator_context; + context_t context{storageImpl}; + { + auto value = serialize(&User::getId, context); + REQUIRE(value == "id"); + } + { + auto value = serialize(&User::setId, context); + REQUIRE(value == "id"); + } + { + auto value = serialize(&User::getName, context); + REQUIRE(value == "name"); + } + { + auto value = serialize(&User::setName, context); + REQUIRE(value == "name"); + } + } + } + } +} diff --git a/tests/statement_serializator_tests/comparison_operators.cpp b/tests/statement_serializator_tests/comparison_operators.cpp new file mode 100644 index 000000000..d4839046a --- /dev/null +++ b/tests/statement_serializator_tests/comparison_operators.cpp @@ -0,0 +1,86 @@ +#include +#include + +using namespace sqlite_orm; + +TEST_CASE("statement_serializator comparison operators") { + internal::serializator_context_base context; + SECTION("lesser_than") { + std::string value; + SECTION("func") { + value = serialize(lesser_than(4, 5), context); + } + SECTION("short func") { + value = serialize(lt(4, 5), context); + } + SECTION("operator") { + value = serialize(c(4) < 5, context); + } + REQUIRE(value == "(4 < 5)"); + } + SECTION("lesser_or_equal") { + std::string value; + SECTION("func") { + value = serialize(lesser_or_equal(10, 15), context); + } + SECTION("short func") { + value = serialize(le(10, 15), context); + } + SECTION("operator") { + value = serialize(c(10) <= 15, context); + } + REQUIRE(value == "(10 <= 15)"); + } + SECTION("greater_than") { + std::string value; + SECTION("func") { + value = serialize(greater_than(1, 0.5), context); + } + SECTION("short func") { + value = serialize(gt(1, 0.5), context); + } + SECTION("operator") { + value = serialize(c(1) > 0.5, context); + } + REQUIRE(value == "(1 > 0.5)"); + } + SECTION("greater_or_equal") { + std::string value; + SECTION("func") { + value = serialize(greater_or_equal(10, -5), context); + } + SECTION("short func") { + value = serialize(ge(10, -5), context); + } + SECTION("operator") { + value = serialize(c(10) >= -5, context); + } + REQUIRE(value == "(10 >= -5)"); + } + SECTION("is_equal") { + std::string value; + SECTION("func") { + value = serialize(is_equal("ototo", "Hey"), context); + } + SECTION("short func") { + value = serialize(eq("ototo", "Hey"), context); + } + SECTION("operator") { + value = serialize(c("ototo") == "Hey", context); + } + REQUIRE(value == "('ototo' = 'Hey')"); + } + SECTION("is_not_equal") { + std::string value; + SECTION("func") { + value = serialize(is_not_equal("lala", 7), context); + } + SECTION("short func") { + value = serialize(ne("lala", 7), context); + } + SECTION("operator") { + value = serialize(c("lala") != 7, context); + } + REQUIRE(value == "('lala' != 7)"); + } +} diff --git a/tests/statement_serializator_tests/core_functions.cpp b/tests/statement_serializator_tests/core_functions.cpp new file mode 100644 index 000000000..9ebae58a2 --- /dev/null +++ b/tests/statement_serializator_tests/core_functions.cpp @@ -0,0 +1,122 @@ +#include +#include + +using namespace sqlite_orm; + +TEST_CASE("statement_serializator core functions") { + internal::serializator_context_base context; + { + auto value = serialize(length("hi"), context); + REQUIRE(value == "LENGTH('hi')"); + } + { + auto value = serialize(sqlite_orm::abs(-100), context); + REQUIRE(value == "ABS(-100)"); + } + { + auto value = serialize(lower("dancefloor"), context); + REQUIRE(value == "LOWER('dancefloor')"); + } + { + auto value = serialize(upper("call"), context); + REQUIRE(value == "UPPER('call')"); + } + { + auto value = serialize(changes(), context); + REQUIRE(value == "CHANGES()"); + } + { + auto value = serialize(trim("hey"), context); + REQUIRE(value == "TRIM('hey')"); + } + { + auto value = serialize(trim("hey", "h"), context); + REQUIRE(value == "TRIM('hey', 'h')"); + } + { + auto value = serialize(ltrim("hey"), context); + REQUIRE(value == "LTRIM('hey')"); + } + { + auto value = serialize(ltrim("hey", "h"), context); + REQUIRE(value == "LTRIM('hey', 'h')"); + } + { + auto value = serialize(rtrim("hey"), context); + REQUIRE(value == "RTRIM('hey')"); + } + { + auto value = serialize(rtrim("hey", "h"), context); + REQUIRE(value == "RTRIM('hey', 'h')"); + } + { + auto value = serialize(hex("love"), context); + REQUIRE(value == "HEX('love')"); + } + { + auto value = serialize(quote("one"), context); + REQUIRE(value == "QUOTE('one')"); + } + { + auto value = serialize(randomblob(5), context); + REQUIRE(value == "RANDOMBLOB(5)"); + } + { + auto value = serialize(instr("hi", "i"), context); + REQUIRE(value == "INSTR('hi', 'i')"); + } + { + auto value = serialize(replace("contigo", "o", "a"), context); + REQUIRE(value == "REPLACE('contigo', 'o', 'a')"); + } + { + auto value = serialize(sqlite_orm::round(10.5), context); + REQUIRE(value == "ROUND(10.5)"); + } + { + auto value = serialize(sqlite_orm::round(10.5, 0.5), context); + REQUIRE(value == "ROUND(10.5, 0.5)"); + } +#if SQLITE_VERSION_NUMBER >= 3007016 + { + auto value = serialize(char_(40, 45), context); + REQUIRE(value == "CHAR(40, 45)"); + } + { + auto value = serialize(sqlite_orm::random(), context); + REQUIRE(value == "RANDOM()"); + } +#endif + { + auto value = serialize(coalesce(10, 15), context); + REQUIRE(value == "COALESCE(10, 15)"); + } + { + auto value = serialize(date("now"), context); + REQUIRE(value == "DATE('now')"); + } + { + auto value = serialize(time("12:00", "localtime"), context); + REQUIRE(value == "TIME('12:00', 'localtime')"); + } + { + auto value = serialize(datetime("now"), context); + REQUIRE(value == "DATETIME('now')"); + } + { + auto value = serialize(julianday("now"), context); + REQUIRE(value == "JULIANDAY('now')"); + } + { + auto value = serialize(zeroblob(5), context); + REQUIRE(value == "ZEROBLOB(5)"); + } + { + auto value = serialize(substr("Zara", 2), context); + REQUIRE(value == "SUBSTR('Zara', 2)"); + } + { + auto value = serialize(substr("Natasha", 3, 2), context); + REQUIRE(value == "SUBSTR('Natasha', 3, 2)"); + } +} diff --git a/tests/statement_serializator_tests/default.cpp b/tests/statement_serializator_tests/default.cpp new file mode 100644 index 000000000..f7a9146c1 --- /dev/null +++ b/tests/statement_serializator_tests/default.cpp @@ -0,0 +1,23 @@ +#include +#include + +using namespace sqlite_orm; + +TEST_CASE("statement_serializator default") { + internal::serializator_context_base context; + { // int literal + auto def = default_value(1); + auto value = serialize(def, context); + REQUIRE(value == "DEFAULT (1)"); + } + { // string literal + auto def = default_value("hi"); + auto value = serialize(def, context); + REQUIRE(value == "DEFAULT ('hi')"); + } + { // func + auto def = default_value(datetime("now")); + auto value = serialize(def, context); + REQUIRE(value == "DEFAULT (DATETIME('now'))"); + } +} diff --git a/tests/statement_serializator_tests/foreign_key.cpp b/tests/statement_serializator_tests/foreign_key.cpp new file mode 100644 index 000000000..a6e4715b4 --- /dev/null +++ b/tests/statement_serializator_tests/foreign_key.cpp @@ -0,0 +1,313 @@ +#include +#include + +using namespace sqlite_orm; + +#if SQLITE_VERSION_NUMBER >= 3006019 + +TEST_CASE("statement_serializator foreign key") { + SECTION("one to one") { + struct User { + int id = 0; + std::string name; + }; + + struct Visit { + int id = 0; + decltype(User::id) userId; + long time = 0; + }; + + auto usersTable = make_table("users", + make_column("id", &User::id, primary_key(), autoincrement()), + make_column("name", &User::name)); + + SECTION("simple") { + auto fk = foreign_key(&Visit::userId).references(&User::id); + + auto visitsTable = make_table("visits", + make_column("id", &Visit::id, primary_key(), autoincrement()), + make_column("user_id", &Visit::userId), + make_column("time", &Visit::time), + fk); + + using storage_impl_t = internal::storage_impl; + + storage_impl_t storageImpl{usersTable, visitsTable}; + + using context_t = internal::serializator_context; + + context_t context{storageImpl}; + auto value = serialize(fk, context); + REQUIRE(value == "FOREIGN KEY(user_id) REFERENCES users(id)"); + } + SECTION("on update") { + SECTION("no_action") { + auto fk = foreign_key(&Visit::userId).references(&User::id).on_update.no_action(); + + auto visitsTable = make_table("visits", + make_column("id", &Visit::id, primary_key(), autoincrement()), + make_column("user_id", &Visit::userId), + make_column("time", &Visit::time), + fk); + + using storage_impl_t = internal::storage_impl; + + storage_impl_t storageImpl{usersTable, visitsTable}; + + using context_t = internal::serializator_context; + + context_t context{storageImpl}; + auto value = serialize(fk, context); + REQUIRE(value == "FOREIGN KEY(user_id) REFERENCES users(id) ON UPDATE NO ACTION"); + } + SECTION("restrict_") { + auto fk = foreign_key(&Visit::userId).references(&User::id).on_update.restrict_(); + + auto visitsTable = make_table("visits", + make_column("id", &Visit::id, primary_key(), autoincrement()), + make_column("user_id", &Visit::userId), + make_column("time", &Visit::time), + fk); + + using storage_impl_t = internal::storage_impl; + + storage_impl_t storageImpl{usersTable, visitsTable}; + + using context_t = internal::serializator_context; + + context_t context{storageImpl}; + auto value = serialize(fk, context); + REQUIRE(value == "FOREIGN KEY(user_id) REFERENCES users(id) ON UPDATE RESTRICT"); + } + SECTION("set_null") { + auto fk = foreign_key(&Visit::userId).references(&User::id).on_update.set_null(); + + auto visitsTable = make_table("visits", + make_column("id", &Visit::id, primary_key(), autoincrement()), + make_column("user_id", &Visit::userId), + make_column("time", &Visit::time), + fk); + + using storage_impl_t = internal::storage_impl; + + storage_impl_t storageImpl{usersTable, visitsTable}; + + using context_t = internal::serializator_context; + + context_t context{storageImpl}; + auto value = serialize(fk, context); + REQUIRE(value == "FOREIGN KEY(user_id) REFERENCES users(id) ON UPDATE SET NULL"); + } + SECTION("set_default") { + auto fk = foreign_key(&Visit::userId).references(&User::id).on_update.set_default(); + + auto visitsTable = make_table("visits", + make_column("id", &Visit::id, primary_key(), autoincrement()), + make_column("user_id", &Visit::userId), + make_column("time", &Visit::time), + fk); + + using storage_impl_t = internal::storage_impl; + + storage_impl_t storageImpl{usersTable, visitsTable}; + + using context_t = internal::serializator_context; + + context_t context{storageImpl}; + auto value = serialize(fk, context); + REQUIRE(value == "FOREIGN KEY(user_id) REFERENCES users(id) ON UPDATE SET DEFAULT"); + } + SECTION("cascade") { + auto fk = foreign_key(&Visit::userId).references(&User::id).on_update.cascade(); + + auto visitsTable = make_table("visits", + make_column("id", &Visit::id, primary_key(), autoincrement()), + make_column("user_id", &Visit::userId), + make_column("time", &Visit::time), + fk); + + using storage_impl_t = internal::storage_impl; + + storage_impl_t storageImpl{usersTable, visitsTable}; + + using context_t = internal::serializator_context; + + context_t context{storageImpl}; + auto value = serialize(fk, context); + REQUIRE(value == "FOREIGN KEY(user_id) REFERENCES users(id) ON UPDATE CASCADE"); + } + } + SECTION("on delete") { + SECTION("no_action") { + auto fk = foreign_key(&Visit::userId).references(&User::id).on_delete.no_action(); + + auto visitsTable = make_table("visits", + make_column("id", &Visit::id, primary_key(), autoincrement()), + make_column("user_id", &Visit::userId), + make_column("time", &Visit::time), + fk); + + using storage_impl_t = internal::storage_impl; + + storage_impl_t storageImpl{usersTable, visitsTable}; + + using context_t = internal::serializator_context; + + context_t context{storageImpl}; + auto value = serialize(fk, context); + REQUIRE(value == "FOREIGN KEY(user_id) REFERENCES users(id) ON DELETE NO ACTION"); + } + SECTION("restrict_") { + auto fk = foreign_key(&Visit::userId).references(&User::id).on_delete.restrict_(); + + auto visitsTable = make_table("visits", + make_column("id", &Visit::id, primary_key(), autoincrement()), + make_column("user_id", &Visit::userId), + make_column("time", &Visit::time), + fk); + + using storage_impl_t = internal::storage_impl; + + storage_impl_t storageImpl{usersTable, visitsTable}; + + using context_t = internal::serializator_context; + + context_t context{storageImpl}; + auto value = serialize(fk, context); + REQUIRE(value == "FOREIGN KEY(user_id) REFERENCES users(id) ON DELETE RESTRICT"); + } + SECTION("set_null") { + auto fk = foreign_key(&Visit::userId).references(&User::id).on_delete.set_null(); + + auto visitsTable = make_table("visits", + make_column("id", &Visit::id, primary_key(), autoincrement()), + make_column("user_id", &Visit::userId), + make_column("time", &Visit::time), + fk); + + using storage_impl_t = internal::storage_impl; + + storage_impl_t storageImpl{usersTable, visitsTable}; + + using context_t = internal::serializator_context; + + context_t context{storageImpl}; + auto value = serialize(fk, context); + REQUIRE(value == "FOREIGN KEY(user_id) REFERENCES users(id) ON DELETE SET NULL"); + } + SECTION("set_default") { + auto fk = foreign_key(&Visit::userId).references(&User::id).on_delete.set_default(); + + auto visitsTable = make_table("visits", + make_column("id", &Visit::id, primary_key(), autoincrement()), + make_column("user_id", &Visit::userId), + make_column("time", &Visit::time), + fk); + + using storage_impl_t = internal::storage_impl; + + storage_impl_t storageImpl{usersTable, visitsTable}; + + using context_t = internal::serializator_context; + + context_t context{storageImpl}; + auto value = serialize(fk, context); + REQUIRE(value == "FOREIGN KEY(user_id) REFERENCES users(id) ON DELETE SET DEFAULT"); + } + SECTION("cascade") { + auto fk = foreign_key(&Visit::userId).references(&User::id).on_delete.cascade(); + + auto visitsTable = make_table("visits", + make_column("id", &Visit::id, primary_key(), autoincrement()), + make_column("user_id", &Visit::userId), + make_column("time", &Visit::time), + fk); + + using storage_impl_t = internal::storage_impl; + + storage_impl_t storageImpl{usersTable, visitsTable}; + + using context_t = internal::serializator_context; + + context_t context{storageImpl}; + auto value = serialize(fk, context); + REQUIRE(value == "FOREIGN KEY(user_id) REFERENCES users(id) ON DELETE CASCADE"); + } + } + } + SECTION("one to explicit one") { + struct Object { + int id = 0; + }; + + struct User : Object { + std::string name; + + User(decltype(id) id_, decltype(name) name_) : Object{id_}, name(move(name_)) {} + }; + + struct Token : Object { + std::string token; + int usedId = 0; + + Token(decltype(id) id_, decltype(token) token_, decltype(usedId) usedId_) : + Object{id_}, token(std::move(token_)), usedId(usedId_) {} + }; + auto fk = foreign_key(&Token::usedId).references(column(&User::id)); + auto usersTable = + make_table("users", make_column("id", &User::id, primary_key()), make_column("name", &User::name)); + auto tokensTable = make_table("tokens", + make_column("id", &Token::id, primary_key()), + make_column("token", &Token::token), + make_column("user_id", &Token::usedId), + fk); + + using storage_impl_t = internal::storage_impl; + + storage_impl_t storageImpl{usersTable, tokensTable}; + + using context_t = internal::serializator_context; + + context_t context{storageImpl}; + auto value = serialize(fk, context); + REQUIRE(value == "FOREIGN KEY(user_id) REFERENCES users(id)"); + } + SECTION("composite key") { + struct User { + int id = 0; + std::string firstName; + std::string lastName; + }; + + struct UserVisit { + int userId = 0; + std::string userFirstName; + time_t time = 0; + }; + + auto fk = foreign_key(&UserVisit::userId, &UserVisit::userFirstName).references(&User::id, &User::firstName); + auto usersTable = make_table("users", + make_column("id", &User::id), + make_column("first_name", &User::firstName), + make_column("last_name", &User::lastName), + primary_key(&User::id, &User::firstName)); + auto visitsTable = make_table("visits", + make_column("user_id", &UserVisit::userId), + make_column("user_first_name", &UserVisit::userFirstName), + make_column("time", &UserVisit::time), + fk); + + using storage_impl_t = internal::storage_impl; + + storage_impl_t storageImpl{usersTable, visitsTable}; + + using context_t = internal::serializator_context; + + context_t context{storageImpl}; + auto value = serialize(fk, context); + REQUIRE(value == "FOREIGN KEY(user_id, user_first_name) REFERENCES users(id, first_name)"); + } +} + +#endif // SQLITE_VERSION_NUMBER diff --git a/tests/statement_serializator_tests/primary_key.cpp b/tests/statement_serializator_tests/primary_key.cpp new file mode 100644 index 000000000..e6593d19f --- /dev/null +++ b/tests/statement_serializator_tests/primary_key.cpp @@ -0,0 +1,44 @@ +#include +#include + +using namespace sqlite_orm; + +TEST_CASE("statement_serializator primary key") { + { // empty pk + internal::serializator_context_base context; + auto pk = primary_key(); + auto value = serialize(pk, context); + REQUIRE(value == "PRIMARY KEY"); + } + { + struct User { + int id = 0; + std::string name; + }; + auto table = make_table("users", make_column("id", &User::id), make_column("name", &User::name)); + using storage_impl_t = internal::storage_impl; + auto storageImpl = storage_impl_t{table}; + using context_t = internal::serializator_context; + context_t context{storageImpl}; + { // single column pk + auto pk = primary_key(&User::id); + auto value = serialize(pk, context); + REQUIRE(value == "PRIMARY KEY(id)"); + } + { // double column pk + auto pk = primary_key(&User::id, &User::name); + auto value = serialize(pk, context); + REQUIRE(value == "PRIMARY KEY(id, name)"); + } + { // empty pk asc + auto pk = primary_key().asc(); + auto value = serialize(pk, context); + REQUIRE(value == "PRIMARY KEY ASC"); + } + { // empty pk desc + auto pk = primary_key().desc(); + auto value = serialize(pk, context); + REQUIRE(value == "PRIMARY KEY DESC"); + } + } +} diff --git a/tests/statement_serializator_tests/unique.cpp b/tests/statement_serializator_tests/unique.cpp new file mode 100644 index 000000000..4f64be198 --- /dev/null +++ b/tests/statement_serializator_tests/unique.cpp @@ -0,0 +1,11 @@ +#include +#include + +using namespace sqlite_orm; + +TEST_CASE("statement_serializator unique") { + internal::serializator_context_base context; + auto un = unique(); + auto value = serialize(un, context); + REQUIRE(value == "UNIQUE"); +} diff --git a/tests/static_if_tests.cpp b/tests/static_if_tests.cpp new file mode 100644 index 000000000..f56fffafb --- /dev/null +++ b/tests/static_if_tests.cpp @@ -0,0 +1,67 @@ +#include +#include + +using namespace sqlite_orm; + +TEST_CASE("static_if") { + { // simple true + auto value = 0; + internal::static_if( + [&value] { + value = 1; + }, + [&value] { + value = -1; + })(); + REQUIRE(value == 1); + } + { // simple false + auto value = 0; + internal::static_if( + [&value] { + value = 1; + }, + [&value] { + value = -1; + })(); + REQUIRE(value == -1); + } + { // tuple is empty + auto value = 0; + internal::static_if>{}>( + [&value] { + value = 1; + }, + [&value] { + value = -1; + })(); + REQUIRE(value == 1); + } + { // tuple is not empty + auto value = 0; + internal::static_if>>{}>( + [&value] { + value = 1; + }, + [&value] { + value = -1; + })(); + REQUIRE(value == -1); + } + { + struct User { + std::string name; + }; + auto ch = check(length(&User::name) > 5); + static_assert(!internal::is_column::value, ""); + int called = 0; + internal::static_if{}>( + [&called] { + called = 1; + }, + [&called] { + called = -1; + })(); + REQUIRE(called == -1); + } +} diff --git a/tests/static_tests.cpp b/tests/static_tests.cpp index f78062115..fb91fec04 100644 --- a/tests/static_tests.cpp +++ b/tests/static_tests.cpp @@ -291,7 +291,7 @@ TEST_CASE("Select return types") { { // test storage traits struct Visit { - int id; + int id = 0; std::string date; }; using namespace sqlite_orm::internal::storage_traits; diff --git a/tests/static_tests/member_traits_tests.cpp b/tests/static_tests/member_traits_tests.cpp new file mode 100644 index 000000000..4a5a335c5 --- /dev/null +++ b/tests/static_tests/member_traits_tests.cpp @@ -0,0 +1,109 @@ +#include +#include + +using namespace sqlite_orm; + +TEST_CASE("member_traits_tests") { + using internal::field_member_traits; + using internal::getter_traits; + using internal::is_field_member_pointer; + using internal::is_getter; + using internal::is_setter; + using internal::member_traits; + using internal::setter_traits; + using std::is_same; + + struct User { + int id; + + const int &getIdByRefConst() const { + return this->id; + } + + const int &getIdByRef() { + return this->id; + } + + int getIdByValConst() const { + return this->id; + } + + void setIdByVal(int id) { + this->id = id; + } + + void setIdByConstRef(const int &id) { + this->id = id; + } + + void setIdByRef(int &id) { + this->id = id; + } + }; + + static_assert(is_field_member_pointer::value, ""); + static_assert(!is_field_member_pointer::value, ""); + static_assert(!is_field_member_pointer::value, ""); + static_assert(!is_field_member_pointer::value, ""); + static_assert(!is_field_member_pointer::value, ""); + static_assert(!is_field_member_pointer::value, ""); + static_assert(!is_field_member_pointer::value, ""); + + static_assert(!is_getter::value, ""); + static_assert(is_getter::value, ""); + static_assert(is_getter::value, ""); + static_assert(is_getter::value, ""); + static_assert(!is_getter::value, ""); + static_assert(!is_getter::value, ""); + static_assert(!is_getter::value, ""); + + static_assert(!is_setter::value, ""); + static_assert(!is_setter::value, ""); + static_assert(!is_setter::value, ""); + static_assert(!is_setter::value, ""); + static_assert(is_setter::value, ""); + static_assert(is_setter::value, ""); + static_assert(is_setter::value, ""); + + static_assert(is_same::object_type, User>::value, ""); + static_assert(is_same::field_type, int>::value, ""); + + static_assert(is_same::object_type, User>::value, ""); + static_assert(is_same::field_type, int>::value, ""); + + static_assert(is_same::object_type, User>::value, ""); + static_assert(is_same::field_type, int>::value, ""); + + static_assert(is_same::object_type, User>::value, ""); + static_assert(is_same::field_type, int>::value, ""); + + static_assert(is_same::object_type, User>::value, ""); + static_assert(is_same::field_type, int>::value, ""); + + static_assert(is_same::object_type, User>::value, ""); + static_assert(is_same::field_type, int>::value, ""); + + static_assert(is_same::object_type, User>::value, ""); + static_assert(is_same::field_type, int>::value, ""); + + static_assert(is_same::object_type, User>::value, ""); + static_assert(is_same::field_type, int>::value, ""); + + static_assert(is_same::object_type, User>::value, ""); + static_assert(is_same::field_type, int>::value, ""); + + static_assert(is_same::object_type, User>::value, ""); + static_assert(is_same::field_type, int>::value, ""); + + static_assert(is_same::object_type, User>::value, ""); + static_assert(is_same::field_type, int>::value, ""); + + static_assert(is_same::object_type, User>::value, ""); + static_assert(is_same::field_type, int>::value, ""); + + static_assert(is_same::object_type, User>::value, ""); + static_assert(is_same::field_type, int>::value, ""); + + static_assert(is_same::object_type, User>::value, ""); + static_assert(is_same::field_type, int>::value, ""); +} diff --git a/tests/table_tests.cpp b/tests/table_tests.cpp new file mode 100644 index 000000000..21aa89b69 --- /dev/null +++ b/tests/table_tests.cpp @@ -0,0 +1,125 @@ +#include +#include +#include + +using namespace sqlite_orm; +using std::cout; +using std::endl; + +TEST_CASE("table") { + { + struct Contact { + int id = 0; + std::string firstName; + std::string lastName; + int countryCode = 0; + std::string phoneNumber; + int visitsCount = 0; + }; + auto contactIdColumn = make_column("contact_id", &Contact::id, primary_key(), autoincrement()); + { + using column_type = decltype(contactIdColumn); + static_assert(internal::is_column::value, ""); + } + + auto table = make_table("contacts", + contactIdColumn, + make_column("first_name", &Contact::firstName), + make_column("last_name", &Contact::lastName), + make_column("country_code", &Contact::countryCode), + make_column("phone_number", &Contact::phoneNumber), + make_column("visits_count", &Contact::visitsCount)); + REQUIRE(table.find_column_name(&Contact::id) == "contact_id"); + REQUIRE(table.find_column_name(&Contact::firstName) == "first_name"); + REQUIRE(table.find_column_name(&Contact::lastName) == "last_name"); + REQUIRE(table.find_column_name(&Contact::countryCode) == "country_code"); + REQUIRE(table.find_column_name(&Contact::phoneNumber) == "phone_number"); + REQUIRE(table.find_column_name(&Contact::visitsCount) == "visits_count"); + } + { + struct Contact { + private: + int _id = 0; + std::string _firstName; + std::string _lastName; + int _countryCode = 0; + std::string _phoneNumber; + int _visitsCount = 0; + + public: + int id() const { + return this->_id; + } + + void setId(int value) { + this->_id = value; + } + + const std::string &firstName() const { + return this->_firstName; + } + + void setFirstName(std::string value) { + this->_firstName = move(value); + } + + const std::string &lastName() const { + return this->_lastName; + } + + void setLastName(std::string value) { + this->_lastName = move(value); + } + + int countryCode() const { + return this->_countryCode; + } + + void setCountryCode(int value) { + this->_countryCode = value; + } + + const std::string &phoneNumber() const { + return this->_phoneNumber; + } + + void setPhoneNumber(std::string value) { + this->_phoneNumber = move(value); + } + + int visitsCount() const { + return this->_visitsCount; + } + + void setVisitsCount(int value) { + this->_visitsCount = value; + } + }; + auto table = + make_table("contacts", + make_column("contact_id", &Contact::id, &Contact::setId, primary_key(), autoincrement()), + make_column("first_name", &Contact::firstName, &Contact::setFirstName), + make_column("last_name", &Contact::lastName, &Contact::setLastName), + make_column("country_code", &Contact::countryCode, &Contact::setCountryCode), + make_column("phone_number", &Contact::phoneNumber, &Contact::setPhoneNumber), + make_column("visits_count", &Contact::visitsCount, &Contact::setVisitsCount)); + + REQUIRE(table.find_column_name(&Contact::id) == "contact_id"); + REQUIRE(table.find_column_name(&Contact::setId) == "contact_id"); + + REQUIRE(table.find_column_name(&Contact::firstName) == "first_name"); + REQUIRE(table.find_column_name(&Contact::setFirstName) == "first_name"); + + REQUIRE(table.find_column_name(&Contact::lastName) == "last_name"); + REQUIRE(table.find_column_name(&Contact::setLastName) == "last_name"); + + REQUIRE(table.find_column_name(&Contact::countryCode) == "country_code"); + REQUIRE(table.find_column_name(&Contact::setCountryCode) == "country_code"); + + REQUIRE(table.find_column_name(&Contact::phoneNumber) == "phone_number"); + REQUIRE(table.find_column_name(&Contact::setPhoneNumber) == "phone_number"); + + REQUIRE(table.find_column_name(&Contact::visitsCount) == "visits_count"); + REQUIRE(table.find_column_name(&Contact::setVisitsCount) == "visits_count"); + } +} diff --git a/tests/tests2.cpp b/tests/tests2.cpp index 9b1172768..d7aeb6e69 100644 --- a/tests/tests2.cpp +++ b/tests/tests2.cpp @@ -254,6 +254,58 @@ TEST_CASE("Select") { REQUIRE(storage.get(firstId).currentWord == "ototo"); } +TEST_CASE("select asterisk") { + using Catch::Matchers::UnorderedEquals; + + struct Employee { + int id; + std::string name; + int age; + std::string address; // optional + double salary; // optional + }; + + auto storage = make_storage({}, + make_table("COMPANY", + make_column("ID", &Employee::id, primary_key()), + make_column("NAME", &Employee::name), + make_column("AGE", &Employee::age), + make_column("ADDRESS", &Employee::address), + make_column("SALARY", &Employee::salary))); + storage.sync_schema(); + + // create employees.. + Employee paul{-1, "Paul", 32, "California", 20000.0}; + Employee allen{-1, "Allen", 25, "Texas", 15000.0}; + Employee teddy{-1, "Teddy", 23, "Norway", 20000.0}; + Employee mark{-1, "Mark", 25, "Rich-Mond", 65000.0}; + Employee david{-1, "David", 27, "Texas", 85000.0}; + Employee kim{-1, "Kim", 22, "South-Hall", 45000.0}; + Employee james{-1, "James", 24, "Houston", 10000.0}; + + // insert employees. `insert` function returns id of inserted object.. + paul.id = storage.insert(paul); + allen.id = storage.insert(allen); + teddy.id = storage.insert(teddy); + mark.id = storage.insert(mark); + david.id = storage.insert(david); + kim.id = storage.insert(kim); + james.id = storage.insert(james); + + auto allEmployeesTuples = storage.select(asterisk()); + + std::vector> expected; + + expected.push_back(std::make_tuple(paul.id, "Paul", 32, "California", 20000.0)); + expected.push_back(std::make_tuple(allen.id, "Allen", 25, "Texas", 15000.0)); + expected.push_back(std::make_tuple(teddy.id, "Teddy", 23, "Norway", 20000.0)); + expected.push_back(std::make_tuple(mark.id, "Mark", 25, "Rich-Mond", 65000.0)); + expected.push_back(std::make_tuple(david.id, "David", 27, "Texas", 85000.0)); + expected.push_back(std::make_tuple(kim.id, "Kim", 22, "South-Hall", 45000.0)); + expected.push_back(std::make_tuple(james.id, "James", 24, "Houston", 10000.0)); + REQUIRE_THAT(allEmployeesTuples, UnorderedEquals(expected)); +} + TEST_CASE("Replace query") { struct Object { int id; diff --git a/tests/tests3.cpp b/tests/tests3.cpp index 0ca8b9de5..1cd65daa7 100644 --- a/tests/tests3.cpp +++ b/tests/tests3.cpp @@ -98,13 +98,13 @@ TEST_CASE("Row id") { TEST_CASE("Issue 87") { struct Data { - uint8_t mDefault; /**< 0=User or 1=Default*/ - uint8_t mAppLang; // en_GB - uint8_t mContentLang1; // de_DE - uint8_t mContentLang2; // en_GB - uint8_t mContentLang3; - uint8_t mContentLang4; - uint8_t mContentLang5; + uint8_t mDefault = 0; /**< 0=User or 1=Default*/ + uint8_t mAppLang = 0; // en_GB + uint8_t mContentLang1 = 0; // de_DE + uint8_t mContentLang2 = 0; // en_GB + uint8_t mContentLang3 = 0; + uint8_t mContentLang4 = 0; + uint8_t mContentLang5 = 0; }; Data data; diff --git a/tests/tests4.cpp b/tests/tests4.cpp index 210a14aa0..998f97438 100644 --- a/tests/tests4.cpp +++ b/tests/tests4.cpp @@ -226,6 +226,14 @@ TEST_CASE("Join") { auto rows = storage.get_all(inner_join(on(is_equal(&Visit::userId, 2)))); REQUIRE(rows.size() == 6); } + { + auto rows = storage.get_all(cross_join()); + REQUIRE(rows.size() == 15); + } + { + auto rows = storage.get_all(natural_join()); + REQUIRE(rows.size() == 3); + } } TEST_CASE("Storage copy") { diff --git a/third_party/amalgamate/config.json b/third_party/amalgamate/config.json index b5345fc1e..ff567afee 100755 --- a/third_party/amalgamate/config.json +++ b/third_party/amalgamate/config.json @@ -37,8 +37,7 @@ "dev/storage.h", "dev/finish_macros.h", "dev/node_tuple.h", - "dev/get_prepared_statement.h", - "dev/statement_serializator.h" + "dev/get_prepared_statement.h" ], "include_paths": ["dev"] } From 46c732a90197b01e20ec8e6850fedc9e062f55e9 Mon Sep 17 00:00:00 2001 From: fnc12 Date: Sun, 2 Feb 2020 13:45:20 +0300 Subject: [PATCH 018/132] removed comments --- dev/constraints.h | 4 -- include/sqlite_orm/sqlite_orm.h | 71 +++++++++++++++++++++++++++------ 2 files changed, 59 insertions(+), 16 deletions(-) diff --git a/dev/constraints.h b/dev/constraints.h index 3657eec3d..ea9b6c0d2 100644 --- a/dev/constraints.h +++ b/dev/constraints.h @@ -59,8 +59,6 @@ namespace sqlite_orm { primary_key_t(decltype(columns) c) : columns(move(c)) {} - // using constraints_type = std::tuple<>; - primary_key_t asc() const { auto res = *this; res.asc_option = order_by::ascending; @@ -255,8 +253,6 @@ namespace sqlite_orm { return *this; } - // using constraints_type = std::tuple<>; - template void for_each_column(const L &) {} diff --git a/include/sqlite_orm/sqlite_orm.h b/include/sqlite_orm/sqlite_orm.h index dba54e630..479ff9616 100644 --- a/include/sqlite_orm/sqlite_orm.h +++ b/include/sqlite_orm/sqlite_orm.h @@ -27,7 +27,7 @@ __pragma(push_macro("min")) #include #include // std::ostringstream - namespace sqlite_orm { +namespace sqlite_orm { enum class orm_error_code { not_found = 1, @@ -44,6 +44,7 @@ __pragma(push_macro("min")) failed_to_init_a_backup, unknown_member_value, }; + } namespace sqlite_orm { @@ -224,6 +225,7 @@ namespace sqlite_orm { // #include "static_magic.h" + #include // std::false_type, std::true_type, std::integral_constant namespace sqlite_orm { @@ -258,6 +260,7 @@ namespace sqlite_orm { } + namespace sqlite_orm { // got from here http://stackoverflow.com/questions/25958259/how-do-i-find-out-if-a-tuple-contains-a-type @@ -544,8 +547,6 @@ namespace sqlite_orm { primary_key_t(decltype(columns) c) : columns(move(c)) {} - // using constraints_type = std::tuple<>; - primary_key_t asc() const { auto res = *this; res.asc_option = order_by::ascending; @@ -740,8 +741,6 @@ namespace sqlite_orm { return *this; } - // using constraints_type = std::tuple<>; - template void for_each_column(const L &) {} @@ -993,6 +992,7 @@ namespace sqlite_orm { // #include "serializator_context.h" + namespace sqlite_orm { namespace internal { @@ -1023,6 +1023,7 @@ namespace sqlite_orm { } + namespace sqlite_orm { namespace internal { @@ -1264,6 +1265,7 @@ namespace sqlite_orm { // #include "getter_traits.h" + namespace sqlite_orm { namespace internal { @@ -1447,6 +1449,7 @@ namespace sqlite_orm { } } + namespace sqlite_orm { namespace internal { @@ -1777,6 +1780,7 @@ namespace sqlite_orm { // #include "optional_container.h" + namespace sqlite_orm { namespace internal { @@ -1809,6 +1813,7 @@ namespace sqlite_orm { } } + namespace sqlite_orm { namespace internal { @@ -3297,6 +3302,7 @@ namespace sqlite_orm { // #include "conditions.h" + namespace sqlite_orm { namespace internal { @@ -3416,6 +3422,7 @@ namespace sqlite_orm { // #include "is_base_of_template.h" + #include // std::true_type, std::false_type, std::declval namespace sqlite_orm { @@ -3453,6 +3460,7 @@ namespace sqlite_orm { } } + namespace sqlite_orm { namespace core_functions { @@ -4279,6 +4287,7 @@ namespace sqlite_orm { // #include "optional_container.h" + namespace sqlite_orm { namespace internal { @@ -4635,6 +4644,7 @@ namespace sqlite_orm { // #include "column.h" + namespace sqlite_orm { namespace internal { @@ -4741,6 +4751,7 @@ namespace sqlite_orm { // #include "is_std_ptr.h" + namespace sqlite_orm { /** @@ -4768,6 +4779,7 @@ namespace sqlite_orm { }; } + namespace sqlite_orm { /** @@ -4978,6 +4990,7 @@ namespace sqlite_orm { // #include "journal_mode.h" + #include // std::string #include // std::unique_ptr #include // std::array @@ -5038,6 +5051,7 @@ namespace sqlite_orm { // #include "error_code.h" + namespace sqlite_orm { /** @@ -5414,6 +5428,7 @@ namespace sqlite_orm { // #include "alias.h" + namespace sqlite_orm { namespace internal { @@ -5662,6 +5677,7 @@ namespace sqlite_orm { } } + namespace sqlite_orm { namespace internal { @@ -5939,6 +5955,7 @@ namespace sqlite_orm { // #include "column.h" + namespace sqlite_orm { namespace internal { @@ -6238,10 +6255,12 @@ namespace sqlite_orm { // #include "field_value_holder.h" + #include // std::enable_if // #include "column.h" + namespace sqlite_orm { namespace internal { @@ -6264,6 +6283,7 @@ namespace sqlite_orm { } } + namespace sqlite_orm { namespace internal { @@ -6768,6 +6788,7 @@ namespace sqlite_orm { // #include "view.h" + #include // std::shared_ptr #include // std::string #include // std::forward, std::move @@ -6783,6 +6804,7 @@ namespace sqlite_orm { // #include "iterator.h" + #include // std::shared_ptr, std::unique_ptr, std::make_shared #include #include // std::decay @@ -6798,6 +6820,7 @@ namespace sqlite_orm { // #include "error_code.h" + namespace sqlite_orm { namespace internal { @@ -6926,6 +6949,7 @@ namespace sqlite_orm { // #include "ast_iterator.h" + #include // std::vector #include // std::reference_wrapper @@ -6941,6 +6965,7 @@ namespace sqlite_orm { // #include "prepared_statement.h" + #include #include // std::iterator_traits #include // std::string @@ -6949,12 +6974,14 @@ namespace sqlite_orm { // #include "connection_holder.h" + #include #include // std::string #include // std::system_error // #include "error_code.h" + namespace sqlite_orm { namespace internal { @@ -7029,6 +7056,7 @@ namespace sqlite_orm { // #include "select_constraints.h" + namespace sqlite_orm { namespace internal { @@ -7400,6 +7428,7 @@ namespace sqlite_orm { #endif // SQLITE_ORM_OPTIONAL_SUPPORTED } + namespace sqlite_orm { namespace internal { @@ -7857,6 +7886,7 @@ namespace sqlite_orm { // #include "connection_holder.h" + namespace sqlite_orm { namespace internal { @@ -7915,6 +7945,7 @@ namespace sqlite_orm { // #include "storage_base.h" + #include // std::function, std::bind #include #include // std::string @@ -7929,6 +7960,7 @@ namespace sqlite_orm { // #include "pragma.h" + #include // std::string #include #include // std::function @@ -7942,6 +7974,7 @@ namespace sqlite_orm { // #include "connection_holder.h" + namespace sqlite_orm { namespace internal { @@ -8062,6 +8095,7 @@ namespace sqlite_orm { // #include "limit_accesor.h" + #include #include // std::map #include // std::function @@ -8069,6 +8103,7 @@ namespace sqlite_orm { // #include "connection_holder.h" + namespace sqlite_orm { namespace internal { @@ -8202,10 +8237,12 @@ namespace sqlite_orm { // #include "transaction_guard.h" + #include // std::function // #include "connection_holder.h" + namespace sqlite_orm { namespace internal { @@ -8280,6 +8317,7 @@ namespace sqlite_orm { // #include "backup.h" + #include #include // std::string #include @@ -8288,6 +8326,7 @@ namespace sqlite_orm { // #include "connection_holder.h" + namespace sqlite_orm { namespace internal { @@ -8353,6 +8392,7 @@ namespace sqlite_orm { } } + namespace sqlite_orm { namespace internal { @@ -8888,11 +8928,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 { @@ -9012,6 +9054,7 @@ namespace sqlite_orm { // #include "statement_serializator.h" + #include // std::stringstream #include // std::string #include // std::is_arithmetic, std::enable_if @@ -9026,6 +9069,7 @@ namespace sqlite_orm { // #include "column.h" + namespace sqlite_orm { namespace internal { @@ -9313,6 +9357,7 @@ namespace sqlite_orm { } } + namespace sqlite_orm { namespace conditions { @@ -12230,19 +12275,20 @@ __pragma(pop_macro("min")) #include // std::pair #include // std::reference_wrapper - // #include "conditions.h" +// #include "conditions.h" - // #include "operators.h" +// #include "operators.h" - // #include "select_constraints.h" +// #include "select_constraints.h" - // #include "prepared_statement.h" +// #include "prepared_statement.h" - // #include "optional_container.h" +// #include "optional_container.h" - // #include "core_functions.h" +// #include "core_functions.h" - namespace sqlite_orm { + +namespace sqlite_orm { namespace internal { @@ -12524,6 +12570,7 @@ __pragma(pop_macro("min")) // #include "expression_object_type.h" + namespace sqlite_orm { template From 9074ff70d9429efb0a93fc4e374fee5328be3912 Mon Sep 17 00:00:00 2001 From: fnc12 Date: Sun, 2 Feb 2020 13:46:57 +0300 Subject: [PATCH 019/132] code format --- include/sqlite_orm/sqlite_orm.h | 67 ++++----------------------------- 1 file changed, 8 insertions(+), 59 deletions(-) diff --git a/include/sqlite_orm/sqlite_orm.h b/include/sqlite_orm/sqlite_orm.h index 479ff9616..49294e3dd 100644 --- a/include/sqlite_orm/sqlite_orm.h +++ b/include/sqlite_orm/sqlite_orm.h @@ -27,7 +27,7 @@ __pragma(push_macro("min")) #include #include // std::ostringstream -namespace sqlite_orm { + namespace sqlite_orm { enum class orm_error_code { not_found = 1, @@ -44,7 +44,6 @@ namespace sqlite_orm { failed_to_init_a_backup, unknown_member_value, }; - } namespace sqlite_orm { @@ -225,7 +224,6 @@ namespace sqlite_orm { // #include "static_magic.h" - #include // std::false_type, std::true_type, std::integral_constant namespace sqlite_orm { @@ -260,7 +258,6 @@ namespace sqlite_orm { } - namespace sqlite_orm { // got from here http://stackoverflow.com/questions/25958259/how-do-i-find-out-if-a-tuple-contains-a-type @@ -992,7 +989,6 @@ namespace sqlite_orm { // #include "serializator_context.h" - namespace sqlite_orm { namespace internal { @@ -1023,7 +1019,6 @@ namespace sqlite_orm { } - namespace sqlite_orm { namespace internal { @@ -1265,7 +1260,6 @@ namespace sqlite_orm { // #include "getter_traits.h" - namespace sqlite_orm { namespace internal { @@ -1449,7 +1443,6 @@ namespace sqlite_orm { } } - namespace sqlite_orm { namespace internal { @@ -1780,7 +1773,6 @@ namespace sqlite_orm { // #include "optional_container.h" - namespace sqlite_orm { namespace internal { @@ -1813,7 +1805,6 @@ namespace sqlite_orm { } } - namespace sqlite_orm { namespace internal { @@ -3302,7 +3293,6 @@ namespace sqlite_orm { // #include "conditions.h" - namespace sqlite_orm { namespace internal { @@ -3422,7 +3412,6 @@ namespace sqlite_orm { // #include "is_base_of_template.h" - #include // std::true_type, std::false_type, std::declval namespace sqlite_orm { @@ -3460,7 +3449,6 @@ namespace sqlite_orm { } } - namespace sqlite_orm { namespace core_functions { @@ -4287,7 +4275,6 @@ namespace sqlite_orm { // #include "optional_container.h" - namespace sqlite_orm { namespace internal { @@ -4644,7 +4631,6 @@ namespace sqlite_orm { // #include "column.h" - namespace sqlite_orm { namespace internal { @@ -4751,7 +4737,6 @@ namespace sqlite_orm { // #include "is_std_ptr.h" - namespace sqlite_orm { /** @@ -4779,7 +4764,6 @@ namespace sqlite_orm { }; } - namespace sqlite_orm { /** @@ -4990,7 +4974,6 @@ namespace sqlite_orm { // #include "journal_mode.h" - #include // std::string #include // std::unique_ptr #include // std::array @@ -5051,7 +5034,6 @@ namespace sqlite_orm { // #include "error_code.h" - namespace sqlite_orm { /** @@ -5428,7 +5410,6 @@ namespace sqlite_orm { // #include "alias.h" - namespace sqlite_orm { namespace internal { @@ -5677,7 +5658,6 @@ namespace sqlite_orm { } } - namespace sqlite_orm { namespace internal { @@ -5955,7 +5935,6 @@ namespace sqlite_orm { // #include "column.h" - namespace sqlite_orm { namespace internal { @@ -6255,12 +6234,10 @@ namespace sqlite_orm { // #include "field_value_holder.h" - #include // std::enable_if // #include "column.h" - namespace sqlite_orm { namespace internal { @@ -6283,7 +6260,6 @@ namespace sqlite_orm { } } - namespace sqlite_orm { namespace internal { @@ -6788,7 +6764,6 @@ namespace sqlite_orm { // #include "view.h" - #include // std::shared_ptr #include // std::string #include // std::forward, std::move @@ -6804,7 +6779,6 @@ namespace sqlite_orm { // #include "iterator.h" - #include // std::shared_ptr, std::unique_ptr, std::make_shared #include #include // std::decay @@ -6820,7 +6794,6 @@ namespace sqlite_orm { // #include "error_code.h" - namespace sqlite_orm { namespace internal { @@ -6949,7 +6922,6 @@ namespace sqlite_orm { // #include "ast_iterator.h" - #include // std::vector #include // std::reference_wrapper @@ -6965,7 +6937,6 @@ namespace sqlite_orm { // #include "prepared_statement.h" - #include #include // std::iterator_traits #include // std::string @@ -6974,14 +6945,12 @@ namespace sqlite_orm { // #include "connection_holder.h" - #include #include // std::string #include // std::system_error // #include "error_code.h" - namespace sqlite_orm { namespace internal { @@ -7056,7 +7025,6 @@ namespace sqlite_orm { // #include "select_constraints.h" - namespace sqlite_orm { namespace internal { @@ -7428,7 +7396,6 @@ namespace sqlite_orm { #endif // SQLITE_ORM_OPTIONAL_SUPPORTED } - namespace sqlite_orm { namespace internal { @@ -7886,7 +7853,6 @@ namespace sqlite_orm { // #include "connection_holder.h" - namespace sqlite_orm { namespace internal { @@ -7945,7 +7911,6 @@ namespace sqlite_orm { // #include "storage_base.h" - #include // std::function, std::bind #include #include // std::string @@ -7960,7 +7925,6 @@ namespace sqlite_orm { // #include "pragma.h" - #include // std::string #include #include // std::function @@ -7974,7 +7938,6 @@ namespace sqlite_orm { // #include "connection_holder.h" - namespace sqlite_orm { namespace internal { @@ -8095,7 +8058,6 @@ namespace sqlite_orm { // #include "limit_accesor.h" - #include #include // std::map #include // std::function @@ -8103,7 +8065,6 @@ namespace sqlite_orm { // #include "connection_holder.h" - namespace sqlite_orm { namespace internal { @@ -8237,12 +8198,10 @@ namespace sqlite_orm { // #include "transaction_guard.h" - #include // std::function // #include "connection_holder.h" - namespace sqlite_orm { namespace internal { @@ -8317,7 +8276,6 @@ namespace sqlite_orm { // #include "backup.h" - #include #include // std::string #include @@ -8326,7 +8284,6 @@ namespace sqlite_orm { // #include "connection_holder.h" - namespace sqlite_orm { namespace internal { @@ -8392,7 +8349,6 @@ namespace sqlite_orm { } } - namespace sqlite_orm { namespace internal { @@ -8928,13 +8884,11 @@ namespace sqlite_orm { // #include "expression_object_type.h" - #include // std::decay #include // std::reference_wrapper // #include "prepared_statement.h" - namespace sqlite_orm { namespace internal { @@ -9054,7 +9008,6 @@ namespace sqlite_orm { // #include "statement_serializator.h" - #include // std::stringstream #include // std::string #include // std::is_arithmetic, std::enable_if @@ -9069,7 +9022,6 @@ namespace sqlite_orm { // #include "column.h" - namespace sqlite_orm { namespace internal { @@ -9357,7 +9309,6 @@ namespace sqlite_orm { } } - namespace sqlite_orm { namespace conditions { @@ -12275,20 +12226,19 @@ __pragma(pop_macro("min")) #include // std::pair #include // std::reference_wrapper -// #include "conditions.h" - -// #include "operators.h" + // #include "conditions.h" -// #include "select_constraints.h" + // #include "operators.h" -// #include "prepared_statement.h" + // #include "select_constraints.h" -// #include "optional_container.h" + // #include "prepared_statement.h" -// #include "core_functions.h" + // #include "optional_container.h" + // #include "core_functions.h" -namespace sqlite_orm { + namespace sqlite_orm { namespace internal { @@ -12570,7 +12520,6 @@ namespace sqlite_orm { // #include "expression_object_type.h" - namespace sqlite_orm { template From d29fd4be93874e5a549171f8352072d15d39d1be Mon Sep 17 00:00:00 2001 From: fnc12 Date: Mon, 3 Feb 2020 01:15:37 +0300 Subject: [PATCH 020/132] added soundex func --- dev/core_functions.h | 18 ++++++++++++++++++ examples/core_functions.cpp | 5 ++++- include/sqlite_orm/sqlite_orm.h | 15 +++++++++++++++ .../core_functions.cpp | 6 ++++++ 4 files changed, 43 insertions(+), 1 deletion(-) diff --git a/dev/core_functions.h b/dev/core_functions.h index 4dcbe2c79..61c347ee0 100644 --- a/dev/core_functions.h +++ b/dev/core_functions.h @@ -174,6 +174,13 @@ namespace sqlite_orm { return "SUBSTR"; } }; +#ifdef SQLITE_SOUNDEX + struct soundex_string { + operator std::string() const { + return "SOUNDEX"; + } + }; +#endif } /** @@ -478,6 +485,17 @@ namespace sqlite_orm { return {move(args)}; } +#ifdef SQLITE_SOUNDEX + /** + * SOUNDEX(X) function https://www.sqlite.org/lang_corefunc.html#soundex + */ + template + core_functions::core_function_t soundex(X x) { + std::tuple args{std::forward(x)}; + return {move(args)}; + } +#endif + template::value + diff --git a/examples/core_functions.cpp b/examples/core_functions.cpp index f94a38102..0029fbe9d 100644 --- a/examples/core_functions.cpp +++ b/examples/core_functions.cpp @@ -335,6 +335,9 @@ int main(int, char **argv) { // SELECT round(0.5) cout << "SELECT round(0.5) = " << storage.select(round(0.5)).front() << endl; - +#ifdef SQLITE_SOUNDEX + // SELECT soundex('Schn Thomson') + cout << "SELECT soundex('Schn Thomson') = " << storage.select(soundex("Schn Thomson")).front() << endl; +#endif return 0; } diff --git a/include/sqlite_orm/sqlite_orm.h b/include/sqlite_orm/sqlite_orm.h index 49294e3dd..4253c252b 100644 --- a/include/sqlite_orm/sqlite_orm.h +++ b/include/sqlite_orm/sqlite_orm.h @@ -3613,6 +3613,12 @@ namespace sqlite_orm { return "SUBSTR"; } }; + + struct soundex_string { + operator std::string() const { + return "SOUNDEX"; + } + }; } /** @@ -3917,6 +3923,15 @@ namespace sqlite_orm { return {move(args)}; } + /** + * SOUNDEX(X) function https://www.sqlite.org/lang_corefunc.html#soundex + */ + template + core_functions::core_function_t soundex(X x) { + std::tuple args{std::forward(x)}; + return {move(args)}; + } + template::value + diff --git a/tests/statement_serializator_tests/core_functions.cpp b/tests/statement_serializator_tests/core_functions.cpp index 9ebae58a2..c60923d27 100644 --- a/tests/statement_serializator_tests/core_functions.cpp +++ b/tests/statement_serializator_tests/core_functions.cpp @@ -119,4 +119,10 @@ TEST_CASE("statement_serializator core functions") { auto value = serialize(substr("Natasha", 3, 2), context); REQUIRE(value == "SUBSTR('Natasha', 3, 2)"); } + { +#ifdef SQLITE_SOUNDEX + auto value = serialize(soundex("Vaso"), context); + REQUIRE(value == "SOUNDEX('Vaso')"); +#endif + } } From 6bfdd57a49a544dc2735aad6682a07ba85bd13c5 Mon Sep 17 00:00:00 2001 From: fnc12 Date: Tue, 4 Feb 2020 20:00:54 +0300 Subject: [PATCH 021/132] added strftime func --- dev/core_functions.h | 15 ++++++++++++++ examples/date_time.cpp | 12 +++++++++++ include/sqlite_orm/sqlite_orm.h | 20 ++++++++++++++++++- tests/datetime_function_tests.cpp | 7 +++++++ .../core_functions.cpp | 4 ++++ 5 files changed, 57 insertions(+), 1 deletion(-) diff --git a/dev/core_functions.h b/dev/core_functions.h index 61c347ee0..f95398e35 100644 --- a/dev/core_functions.h +++ b/dev/core_functions.h @@ -163,6 +163,12 @@ namespace sqlite_orm { } }; + struct strftime_string { + operator std::string() const { + return "STRFTIME"; + } + }; + struct zeroblob_string { operator std::string() const { return "ZEROBLOB"; @@ -458,6 +464,15 @@ namespace sqlite_orm { return {move(t)}; } + /** + * STRFTIME(timestring, modifier, modifier, ...) function https://www.sqlite.org/lang_datefunc.html + */ + template + core_functions::core_function_t strftime(Args... args) { + std::tuple t{std::forward(args)...}; + return {move(t)}; + } + /** * ZEROBLOB(N) function https://www.sqlite.org/lang_corefunc.html#zeroblob */ diff --git a/examples/date_time.cpp b/examples/date_time.cpp index 6bc0b2ecf..63ca31c46 100644 --- a/examples/date_time.cpp +++ b/examples/date_time.cpp @@ -81,5 +81,17 @@ int main() { auto time12utc = storage.select(time("12:00", "utc")).front(); cout << "SELECT time('12:00', 'utc') = " << time12utc << endl; + // SELECT strftime('%Y %m %d','now') + auto strftimeRes = storage.select(strftime("%Y %m %d", "now")).front(); + cout << "SELECT strftime('%Y %m %d','now') = " << strftimeRes << endl; + + // SELECT strftime('%H %M %S %s','now') + auto strftimeRes2 = storage.select(strftime("%H %M %S %s", "now")).front(); + cout << "SELECT strftime('%H %M %S %s','now') = " << strftimeRes2 << endl; + + // SELECT strftime('%s','now') - strftime('%s','2014-10-07 02:34:56') + auto strftimeResSub = storage.select(strftime("%s", "now") - strftime("%s", "2014-10-07 02:34:56")).front(); + cout << "SELECT strftime('%s','now') - strftime('%s','2014-10-07 02:34:56') = " << strftimeResSub << endl; + return 0; } diff --git a/include/sqlite_orm/sqlite_orm.h b/include/sqlite_orm/sqlite_orm.h index 4253c252b..cb65d11da 100644 --- a/include/sqlite_orm/sqlite_orm.h +++ b/include/sqlite_orm/sqlite_orm.h @@ -3602,6 +3602,12 @@ namespace sqlite_orm { } }; + struct strftime_string { + operator std::string() const { + return "STRFTIME"; + } + }; + struct zeroblob_string { operator std::string() const { return "ZEROBLOB"; @@ -3613,12 +3619,13 @@ namespace sqlite_orm { return "SUBSTR"; } }; - +#ifdef SQLITE_SOUNDEX struct soundex_string { operator std::string() const { return "SOUNDEX"; } }; +#endif } /** @@ -3896,6 +3903,15 @@ namespace sqlite_orm { return {move(t)}; } + /** + * STRFTIME(timestring, modifier, modifier, ...) function https://www.sqlite.org/lang_datefunc.html + */ + template + core_functions::core_function_t strftime(Args... args) { + std::tuple t{std::forward(args)...}; + return {move(t)}; + } + /** * ZEROBLOB(N) function https://www.sqlite.org/lang_corefunc.html#zeroblob */ @@ -3923,6 +3939,7 @@ namespace sqlite_orm { return {move(args)}; } +#ifdef SQLITE_SOUNDEX /** * SOUNDEX(X) function https://www.sqlite.org/lang_corefunc.html#soundex */ @@ -3931,6 +3948,7 @@ namespace sqlite_orm { std::tuple args{std::forward(x)}; return {move(args)}; } +#endif template Date: Fri, 7 Feb 2020 19:24:08 +0300 Subject: [PATCH 022/132] started serialization refactoring --- dev/serializator_context.h | 4 +- dev/statement_serializator.h | 52 +++++- dev/storage.h | 31 ++-- include/sqlite_orm/sqlite_orm.h | 155 +++++++++++++++--- .../base_types.cpp | 32 ++++ tests/statement_serializator_tests/check.cpp | 4 +- .../column_names.cpp | 39 +++-- tests/statement_serializator_tests/rowid.cpp | 12 ++ 8 files changed, 267 insertions(+), 62 deletions(-) create mode 100644 tests/statement_serializator_tests/base_types.cpp create mode 100644 tests/statement_serializator_tests/rowid.cpp diff --git a/dev/serializator_context.h b/dev/serializator_context.h index fa679eacd..1c35b1063 100644 --- a/dev/serializator_context.h +++ b/dev/serializator_context.h @@ -5,7 +5,9 @@ namespace sqlite_orm { namespace internal { struct serializator_context_base { - + bool replace_bindable_with_question = false; + bool skip_table_name = true; + template std::string column_name(F O::*m) const { return {}; diff --git a/dev/statement_serializator.h b/dev/statement_serializator.h index d0e41a9ed..57e0bc5d2 100644 --- a/dev/statement_serializator.h +++ b/dev/statement_serializator.h @@ -10,6 +10,7 @@ #include "constraints.h" #include "conditions.h" #include "column.h" +#include "rowid.h" namespace sqlite_orm { @@ -23,14 +24,49 @@ namespace sqlite_orm { statement_serializator serializator; return serializator(t, context); } + + template<> + struct statement_serializator { + using statement_type = rowid_t; + + template + std::string operator()(const statement_type &s, const C &context) { + return static_cast(s); + } + }; + + template<> + struct statement_serializator<_rowid_t, void> { + using statement_type = _rowid_t; + + template + std::string operator()(const statement_type &s, const C &context) { + return static_cast(s); + } + }; + + template<> + struct statement_serializator { + using statement_type = oid_t; + + template + std::string operator()(const statement_type &s, const C &context) { + return static_cast(s); + } + }; template struct statement_serializator { using statement_type = F O::*; template - std::string operator()(const statement_type &c, const C &context) const { - return context.impl.column_name(c); + std::string operator()(const statement_type &m, const C &context) const { + std::stringstream ss; + if(!context.skip_table_name) { + ss << "\"" << context.impl.find_table_name(typeid(O)) << "\"."; + } + ss << "\"" << context.column_name(m) << "\""; + return ss.str(); } }; @@ -130,7 +166,11 @@ namespace sqlite_orm { template std::string operator()(const statement_type &c, const C &context) const { - return "\"" + c + "\""; + if(context.replace_bindable_with_question){ + return "?"; + }else{ + return "\'" + c + "\'"; + } } }; @@ -140,7 +180,11 @@ namespace sqlite_orm { template std::string operator()(const char *c, const C &context) const { - return std::string("'") + c + "'"; + if(context.replace_bindable_with_question){ + return "?"; + }else{ + return std::string("'") + c + "'"; + } } }; diff --git a/dev/storage.h b/dev/storage.h index 3b1e24a4f..8dc91a560 100644 --- a/dev/storage.h +++ b/dev/storage.h @@ -221,34 +221,39 @@ namespace sqlite_orm { return ss.str(); } - std::string string_from_expression(const std::string &, bool /*noTableName*/) const { - return "?"; + std::string string_from_expression(const std::string &s, bool /*noTableName*/) const { + serializator_context_base context; + context.replace_bindable_with_question = true; + return serialize(s, context); } - std::string string_from_expression(const char *, bool /*noTableName*/) const { - return "?"; + std::string string_from_expression(const char *s, bool /*noTableName*/) const { + serializator_context_base context; + context.replace_bindable_with_question = true; + return serialize(s, context); } template std::string string_from_expression(F O::*m, bool noTableName) const { - std::stringstream ss; - if(!noTableName) { - ss << "'" << this->impl.find_table_name(typeid(O)) << "'."; - } - ss << "\"" << this->impl.column_name(m) << "\""; - return ss.str(); + using context_t = serializator_context; + context_t context{this->impl}; + context.skip_table_name = noTableName; + return serialize(m, context); } std::string string_from_expression(const rowid_t &rid, bool /*noTableName*/) const { - return static_cast(rid); + serializator_context_base context; + return serialize(rid, context); } std::string string_from_expression(const oid_t &rid, bool /*noTableName*/) const { - return static_cast(rid); + serializator_context_base context; + return serialize(rid, context); } std::string string_from_expression(const _rowid_t &rid, bool /*noTableName*/) const { - return static_cast(rid); + serializator_context_base context; + return serialize(rid, context); } template diff --git a/include/sqlite_orm/sqlite_orm.h b/include/sqlite_orm/sqlite_orm.h index cb65d11da..69999ed59 100644 --- a/include/sqlite_orm/sqlite_orm.h +++ b/include/sqlite_orm/sqlite_orm.h @@ -27,7 +27,7 @@ __pragma(push_macro("min")) #include #include // std::ostringstream - namespace sqlite_orm { +namespace sqlite_orm { enum class orm_error_code { not_found = 1, @@ -44,6 +44,7 @@ __pragma(push_macro("min")) failed_to_init_a_backup, unknown_member_value, }; + } namespace sqlite_orm { @@ -224,6 +225,7 @@ namespace sqlite_orm { // #include "static_magic.h" + #include // std::false_type, std::true_type, std::integral_constant namespace sqlite_orm { @@ -258,6 +260,7 @@ namespace sqlite_orm { } + namespace sqlite_orm { // got from here http://stackoverflow.com/questions/25958259/how-do-i-find-out-if-a-tuple-contains-a-type @@ -989,12 +992,15 @@ namespace sqlite_orm { // #include "serializator_context.h" + namespace sqlite_orm { namespace internal { struct serializator_context_base { - + bool replace_bindable_with_question = false; + bool skip_table_name = true; + template std::string column_name(F O::*m) const { return {}; @@ -1019,6 +1025,7 @@ namespace sqlite_orm { } + namespace sqlite_orm { namespace internal { @@ -1260,6 +1267,7 @@ namespace sqlite_orm { // #include "getter_traits.h" + namespace sqlite_orm { namespace internal { @@ -1443,6 +1451,7 @@ namespace sqlite_orm { } } + namespace sqlite_orm { namespace internal { @@ -1773,6 +1782,7 @@ namespace sqlite_orm { // #include "optional_container.h" + namespace sqlite_orm { namespace internal { @@ -1805,6 +1815,7 @@ namespace sqlite_orm { } } + namespace sqlite_orm { namespace internal { @@ -3293,6 +3304,7 @@ namespace sqlite_orm { // #include "conditions.h" + namespace sqlite_orm { namespace internal { @@ -3412,6 +3424,7 @@ namespace sqlite_orm { // #include "is_base_of_template.h" + #include // std::true_type, std::false_type, std::declval namespace sqlite_orm { @@ -3449,6 +3462,7 @@ namespace sqlite_orm { } } + namespace sqlite_orm { namespace core_functions { @@ -4308,6 +4322,7 @@ namespace sqlite_orm { // #include "optional_container.h" + namespace sqlite_orm { namespace internal { @@ -4664,6 +4679,7 @@ namespace sqlite_orm { // #include "column.h" + namespace sqlite_orm { namespace internal { @@ -4770,6 +4786,7 @@ namespace sqlite_orm { // #include "is_std_ptr.h" + namespace sqlite_orm { /** @@ -4797,6 +4814,7 @@ namespace sqlite_orm { }; } + namespace sqlite_orm { /** @@ -5007,6 +5025,7 @@ namespace sqlite_orm { // #include "journal_mode.h" + #include // std::string #include // std::unique_ptr #include // std::array @@ -5067,6 +5086,7 @@ namespace sqlite_orm { // #include "error_code.h" + namespace sqlite_orm { /** @@ -5443,6 +5463,7 @@ namespace sqlite_orm { // #include "alias.h" + namespace sqlite_orm { namespace internal { @@ -5691,6 +5712,7 @@ namespace sqlite_orm { } } + namespace sqlite_orm { namespace internal { @@ -5968,6 +5990,7 @@ namespace sqlite_orm { // #include "column.h" + namespace sqlite_orm { namespace internal { @@ -6267,10 +6290,12 @@ namespace sqlite_orm { // #include "field_value_holder.h" + #include // std::enable_if // #include "column.h" + namespace sqlite_orm { namespace internal { @@ -6293,6 +6318,7 @@ namespace sqlite_orm { } } + namespace sqlite_orm { namespace internal { @@ -6797,6 +6823,7 @@ namespace sqlite_orm { // #include "view.h" + #include // std::shared_ptr #include // std::string #include // std::forward, std::move @@ -6812,6 +6839,7 @@ namespace sqlite_orm { // #include "iterator.h" + #include // std::shared_ptr, std::unique_ptr, std::make_shared #include #include // std::decay @@ -6827,6 +6855,7 @@ namespace sqlite_orm { // #include "error_code.h" + namespace sqlite_orm { namespace internal { @@ -6955,6 +6984,7 @@ namespace sqlite_orm { // #include "ast_iterator.h" + #include // std::vector #include // std::reference_wrapper @@ -6970,6 +7000,7 @@ namespace sqlite_orm { // #include "prepared_statement.h" + #include #include // std::iterator_traits #include // std::string @@ -6978,12 +7009,14 @@ namespace sqlite_orm { // #include "connection_holder.h" + #include #include // std::string #include // std::system_error // #include "error_code.h" + namespace sqlite_orm { namespace internal { @@ -7058,6 +7091,7 @@ namespace sqlite_orm { // #include "select_constraints.h" + namespace sqlite_orm { namespace internal { @@ -7429,6 +7463,7 @@ namespace sqlite_orm { #endif // SQLITE_ORM_OPTIONAL_SUPPORTED } + namespace sqlite_orm { namespace internal { @@ -7886,6 +7921,7 @@ namespace sqlite_orm { // #include "connection_holder.h" + namespace sqlite_orm { namespace internal { @@ -7944,6 +7980,7 @@ namespace sqlite_orm { // #include "storage_base.h" + #include // std::function, std::bind #include #include // std::string @@ -7958,6 +7995,7 @@ namespace sqlite_orm { // #include "pragma.h" + #include // std::string #include #include // std::function @@ -7971,6 +8009,7 @@ namespace sqlite_orm { // #include "connection_holder.h" + namespace sqlite_orm { namespace internal { @@ -8091,6 +8130,7 @@ namespace sqlite_orm { // #include "limit_accesor.h" + #include #include // std::map #include // std::function @@ -8098,6 +8138,7 @@ namespace sqlite_orm { // #include "connection_holder.h" + namespace sqlite_orm { namespace internal { @@ -8231,10 +8272,12 @@ namespace sqlite_orm { // #include "transaction_guard.h" + #include // std::function // #include "connection_holder.h" + namespace sqlite_orm { namespace internal { @@ -8309,6 +8352,7 @@ namespace sqlite_orm { // #include "backup.h" + #include #include // std::string #include @@ -8317,6 +8361,7 @@ namespace sqlite_orm { // #include "connection_holder.h" + namespace sqlite_orm { namespace internal { @@ -8382,6 +8427,7 @@ namespace sqlite_orm { } } + namespace sqlite_orm { namespace internal { @@ -8917,11 +8963,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 { @@ -9041,6 +9089,7 @@ namespace sqlite_orm { // #include "statement_serializator.h" + #include // std::stringstream #include // std::string #include // std::is_arithmetic, std::enable_if @@ -9055,6 +9104,9 @@ namespace sqlite_orm { // #include "column.h" +// #include "rowid.h" + + namespace sqlite_orm { namespace internal { @@ -9067,14 +9119,49 @@ namespace sqlite_orm { statement_serializator serializator; return serializator(t, context); } + + template<> + struct statement_serializator { + using statement_type = rowid_t; + + template + std::string operator()(const statement_type &s, const C &context) { + return static_cast(s); + } + }; + + template<> + struct statement_serializator<_rowid_t, void> { + using statement_type = _rowid_t; + + template + std::string operator()(const statement_type &s, const C &context) { + return static_cast(s); + } + }; + + template<> + struct statement_serializator { + using statement_type = oid_t; + + template + std::string operator()(const statement_type &s, const C &context) { + return static_cast(s); + } + }; template struct statement_serializator { using statement_type = F O::*; template - std::string operator()(const statement_type &c, const C &context) const { - return context.impl.column_name(c); + std::string operator()(const statement_type &m, const C &context) const { + std::stringstream ss; + if(!context.skip_table_name) { + ss << "\"" << context.impl.find_table_name(typeid(O)) << "\"."; + } + ss << "\"" << context.column_name(m) << "\""; + return ss.str(); } }; @@ -9174,7 +9261,11 @@ namespace sqlite_orm { template std::string operator()(const statement_type &c, const C &context) const { - return "\"" + c + "\""; + if(context.replace_bindable_with_question){ + return "?"; + }else{ + return "\'" + c + "\'"; + } } }; @@ -9184,7 +9275,11 @@ namespace sqlite_orm { template std::string operator()(const char *c, const C &context) const { - return std::string("'") + c + "'"; + if(context.replace_bindable_with_question){ + return "?"; + }else{ + return std::string("'") + c + "'"; + } } }; @@ -9342,6 +9437,7 @@ namespace sqlite_orm { } } + namespace sqlite_orm { namespace conditions { @@ -9514,34 +9610,39 @@ namespace sqlite_orm { return ss.str(); } - std::string string_from_expression(const std::string &, bool /*noTableName*/) const { - return "?"; + std::string string_from_expression(const std::string &s, bool /*noTableName*/) const { + serializator_context_base context; + context.replace_bindable_with_question = true; + return serialize(s, context); } - std::string string_from_expression(const char *, bool /*noTableName*/) const { - return "?"; + std::string string_from_expression(const char *s, bool /*noTableName*/) const { + serializator_context_base context; + context.replace_bindable_with_question = true; + return serialize(s, context); } template std::string string_from_expression(F O::*m, bool noTableName) const { - std::stringstream ss; - if(!noTableName) { - ss << "'" << this->impl.find_table_name(typeid(O)) << "'."; - } - ss << "\"" << this->impl.column_name(m) << "\""; - return ss.str(); + using context_t = serializator_context; + context_t context{this->impl}; + context.skip_table_name = noTableName; + return serialize(m, context); } std::string string_from_expression(const rowid_t &rid, bool /*noTableName*/) const { - return static_cast(rid); + serializator_context_base context; + return serialize(rid, context); } std::string string_from_expression(const oid_t &rid, bool /*noTableName*/) const { - return static_cast(rid); + serializator_context_base context; + return serialize(rid, context); } std::string string_from_expression(const _rowid_t &rid, bool /*noTableName*/) const { - return static_cast(rid); + serializator_context_base context; + return serialize(rid, context); } template @@ -12259,19 +12360,20 @@ __pragma(pop_macro("min")) #include // std::pair #include // std::reference_wrapper - // #include "conditions.h" +// #include "conditions.h" - // #include "operators.h" +// #include "operators.h" - // #include "select_constraints.h" +// #include "select_constraints.h" - // #include "prepared_statement.h" +// #include "prepared_statement.h" - // #include "optional_container.h" +// #include "optional_container.h" - // #include "core_functions.h" +// #include "core_functions.h" - namespace sqlite_orm { + +namespace sqlite_orm { namespace internal { @@ -12553,6 +12655,7 @@ __pragma(pop_macro("min")) // #include "expression_object_type.h" + namespace sqlite_orm { template diff --git a/tests/statement_serializator_tests/base_types.cpp b/tests/statement_serializator_tests/base_types.cpp new file mode 100644 index 000000000..2675c312c --- /dev/null +++ b/tests/statement_serializator_tests/base_types.cpp @@ -0,0 +1,32 @@ +#include +#include + +using namespace sqlite_orm; + +TEST_CASE("statement_serializator base types") { + internal::serializator_context_base context; + SECTION("std::string") { + std::string str("calma"); + SECTION("no question") { + auto value = serialize(str, context); + REQUIRE(value == "\'calma\'"); + } + SECTION("question") { + context.replace_bindable_with_question = true; + auto value = serialize(str, context); + REQUIRE(value == "?"); + } + } + SECTION("const char *"){ + const char *str = "baby"; + SECTION("no question") { + auto value = serialize(str, context); + REQUIRE(value == "\'baby\'"); + } + SECTION("question") { + context.replace_bindable_with_question = true; + auto value = serialize(str, context); + REQUIRE(value == "?"); + } + } +} diff --git a/tests/statement_serializator_tests/check.cpp b/tests/statement_serializator_tests/check.cpp index 12a649606..583ec17db 100644 --- a/tests/statement_serializator_tests/check.cpp +++ b/tests/statement_serializator_tests/check.cpp @@ -24,7 +24,7 @@ TEST_CASE("statement_serializator check") { context_t context{storageImpl}; auto value = serialize(ch, context); - REQUIRE(value == "CHECK (col3 > 0)"); + REQUIRE(value == "CHECK (\"col3\" > 0)"); } { struct Book { @@ -47,6 +47,6 @@ TEST_CASE("statement_serializator check") { context_t context{storageImpl}; auto value = serialize(ch, context); - REQUIRE(value == "CHECK (0 < PRICE)"); + REQUIRE(value == "CHECK (0 < \"PRICE\")"); } } diff --git a/tests/statement_serializator_tests/column_names.cpp b/tests/statement_serializator_tests/column_names.cpp index d6b12248e..fa27e351f 100644 --- a/tests/statement_serializator_tests/column_names.cpp +++ b/tests/statement_serializator_tests/column_names.cpp @@ -3,8 +3,8 @@ using namespace sqlite_orm; -TEST_CASE("statement_serializator column names") { - { // by member field pointer +TEST_CASE("statement_serializator column names") { + SECTION("by member field pointer") { struct User { int id = 0; std::string name; @@ -15,17 +15,24 @@ TEST_CASE("statement_serializator column names") { { using context_t = internal::serializator_context; context_t context{storageImpl}; - { - auto value = serialize(&User::id, context); - REQUIRE(value == "id"); + SECTION("id") { + SECTION("skip table name") { + auto value = serialize(&User::id, context); + REQUIRE(value == "\"id\""); + } + SECTION("don't skip table name") { + context.skip_table_name = false; + auto value = serialize(&User::id, context); + REQUIRE(value == "\"users\".\"id\""); + } } - { + SECTION("name") { auto value = serialize(&User::name, context); - REQUIRE(value == "name"); + REQUIRE(value == "\"name\""); } } } - { // by getters and setters pointers + SECTION("by getters and setters pointers") { struct User { int getId() const { @@ -59,19 +66,19 @@ TEST_CASE("statement_serializator column names") { context_t context{storageImpl}; { auto value = serialize(&User::getId, context); - REQUIRE(value == "id"); + REQUIRE(value == "\"id\""); } { auto value = serialize(&User::setId, context); - REQUIRE(value == "id"); + REQUIRE(value == "\"id\""); } { auto value = serialize(&User::getName, context); - REQUIRE(value == "name"); + REQUIRE(value == "\"name\""); } { auto value = serialize(&User::setName, context); - REQUIRE(value == "name"); + REQUIRE(value == "\"name\""); } } } @@ -86,19 +93,19 @@ TEST_CASE("statement_serializator column names") { context_t context{storageImpl}; { auto value = serialize(&User::getId, context); - REQUIRE(value == "id"); + REQUIRE(value == "\"id\""); } { auto value = serialize(&User::setId, context); - REQUIRE(value == "id"); + REQUIRE(value == "\"id\""); } { auto value = serialize(&User::getName, context); - REQUIRE(value == "name"); + REQUIRE(value == "\"name\""); } { auto value = serialize(&User::setName, context); - REQUIRE(value == "name"); + REQUIRE(value == "\"name\""); } } } diff --git a/tests/statement_serializator_tests/rowid.cpp b/tests/statement_serializator_tests/rowid.cpp new file mode 100644 index 000000000..68fa97432 --- /dev/null +++ b/tests/statement_serializator_tests/rowid.cpp @@ -0,0 +1,12 @@ +#include +#include + +using namespace sqlite_orm; + +TEST_CASE("statement_serializator rowid") { + { + internal::serializator_context_base context; + auto value = serialize(rowid(), context); + REQUIRE(value == "rowid"); + } +} From 105d214e926516b0dda2f93cdb84cfd5a7a75d3b Mon Sep 17 00:00:00 2001 From: fnc12 Date: Wed, 12 Feb 2020 20:34:09 +0300 Subject: [PATCH 023/132] removed aggredate functions file and refactored aggregate functions with core_function_t class --- dev/aggregate_functions.h | 272 ----------- dev/ast_iterator.h | 4 +- dev/column_result.h | 57 +-- dev/core_functions.h | 279 ++++++++--- dev/node_tuple.h | 4 +- dev/statement_serializator.h | 4 +- dev/storage.h | 135 +----- include/sqlite_orm/sqlite_orm.h | 749 +++++++++-------------------- third_party/amalgamate/config.json | 1 - 9 files changed, 484 insertions(+), 1021 deletions(-) delete mode 100644 dev/aggregate_functions.h diff --git a/dev/aggregate_functions.h b/dev/aggregate_functions.h deleted file mode 100644 index 5d8340e6d..000000000 --- a/dev/aggregate_functions.h +++ /dev/null @@ -1,272 +0,0 @@ -#pragma once - -namespace sqlite_orm { - - namespace aggregate_functions { - - struct avg_string { - operator std::string() const { - return "AVG"; - } - }; - - /** - * Result of avg(...) call. - * T is an argument type - */ - template - struct avg_t : avg_string { - using arg_type = T; - - arg_type arg; - - avg_t(arg_type arg_) : arg(std::move(arg_)) {} - }; - - struct count_string { - operator std::string() const { - return "COUNT"; - } - }; - - /** - * Result of count(...) call. - * T is an argument type - */ - template - struct count_t : count_string { - using arg_type = T; - - arg_type arg; - - count_t(arg_type arg_) : arg(std::move(arg_)) {} - }; - - /** - * T is use to specify type explicitly for queries like - * SELECT COUNT(*) FROM table_name; - * T can be omitted with void. - */ - template - struct count_asterisk_t : count_string { - using type = T; - }; - - /** - * The same thing as count() but without T arg. - * Is used in cases like this: - * SELECT cust_code, cust_name, cust_city, grade - * FROM customer - * WHERE grade=2 AND EXISTS - * (SELECT COUNT(*) - * FROM customer - * WHERE grade=2 - * GROUP BY grade - * HAVING COUNT(*)>2); - * `c++` - * auto rows = - * storage.select(columns(&Customer::code, &Customer::name, &Customer::city, &Customer::grade), - * where(is_equal(&Customer::grade, 2) - * and exists(select(count(), - * where(is_equal(&Customer::grade, 2)), - * group_by(&Customer::grade), - * having(greater_than(count(), 2)))))); - */ - struct count_asterisk_without_type : count_string {}; - - struct sum_string { - operator std::string() const { - return "SUM"; - } - }; - - /** - * Result of sum(...) call. - * T is an argument type - */ - template - struct sum_t : sum_string { - using arg_type = T; - - arg_type arg; - - sum_t(arg_type arg_) : arg(std::move(arg_)) {} - }; - - struct total_string { - operator std::string() const { - return "TOTAL"; - } - }; - - /** - * Result of total(...) call. - * T is an argument type - */ - template - struct total_t : total_string { - using arg_type = T; - - arg_type arg; - - total_t(arg_type arg_) : arg(std::move(arg_)) {} - }; - - struct max_string { - operator std::string() const { - return "MAX"; - } - }; - - /** - * Result of max(...) call. - * T is an argument type - */ - template - struct max_t : max_string { - using arg_type = T; - - arg_type arg; - - max_t(arg_type arg_) : arg(std::move(arg_)) {} - }; - - struct min_string { - operator std::string() const { - return "MIN"; - } - }; - - /** - * Result of min(...) call. - * T is an argument type - */ - template - struct min_t : min_string { - using arg_type = T; - - arg_type arg; - - min_t(arg_type arg_) : arg(std::move(arg_)) {} - }; - - struct group_concat_string { - operator std::string() const { - return "GROUP_CONCAT"; - } - }; - - /** - * Result of group_concat(X) call. - * T is an argument type - */ - template - struct group_concat_single_t : group_concat_string { - using arg_type = T; - - arg_type arg; - - group_concat_single_t(arg_type arg_) : arg(std::move(arg_)) {} - }; - - struct group_concat_double_base : group_concat_string { - std::string y; - - group_concat_double_base(std::string y_) : y(move(y_)) {} - }; - - /** - * Result of group_concat(X, Y) call. - * T is an argument type - */ - template - struct group_concat_double_t : group_concat_double_base { - using arg_type = T; - - arg_type arg; - - group_concat_double_t(arg_type arg_, std::string y) : - group_concat_double_base(move(y)), arg(std::move(arg_)) {} - }; - } - - /** - * AVG(X) aggregate function. - */ - template - aggregate_functions::avg_t avg(T t) { - return {std::move(t)}; - } - - /** - * COUNT(X) aggregate function. - */ - template - aggregate_functions::count_t count(T t) { - return {std::move(t)}; - } - - /** - * COUNT(*) without FROM function. - */ - inline aggregate_functions::count_asterisk_without_type count() { - return {}; - } - - /** - * COUNT(*) with FROM function. Specified type T will be serializeed as - * a from argument. - */ - template - aggregate_functions::count_asterisk_t count() { - return {}; - } - - /** - * SUM(X) aggregate function. - */ - template - aggregate_functions::sum_t sum(T t) { - return {std::move(t)}; - } - - /** - * MAX(X) aggregate function. - */ - template - aggregate_functions::max_t max(T t) { - return {std::move(t)}; - } - - /** - * MIN(X) aggregate function. - */ - template - aggregate_functions::min_t min(T t) { - return {std::move(t)}; - } - - /** - * TOTAL(X) aggregate function. - */ - template - aggregate_functions::total_t total(T t) { - return {std::move(t)}; - } - - /** - * GROUP_CONCAT(X) aggregate function. - */ - template - aggregate_functions::group_concat_single_t group_concat(T t) { - return {std::move(t)}; - } - - /** - * GROUP_CONCAT(X, Y) aggregate function. - */ - template - aggregate_functions::group_concat_double_t group_concat(T t, Y y) { - return {std::move(t), std::move(y)}; - } -} diff --git a/dev/ast_iterator.h b/dev/ast_iterator.h index 61cae1764..bb5289ec6 100644 --- a/dev/ast_iterator.h +++ b/dev/ast_iterator.h @@ -337,8 +337,8 @@ namespace sqlite_orm { }; template - struct ast_iterator, void> { - using node_type = core_functions::core_function_t; + struct ast_iterator, void> { + using node_type = core_function_t; template void operator()(const node_type &f, const L &l) const { diff --git a/dev/column_result.h b/dev/column_result.h index e0c868448..7f04c0213 100644 --- a/dev/column_result.h +++ b/dev/column_result.h @@ -5,7 +5,6 @@ #include // std::reference_wrapper #include "core_functions.h" -#include "aggregate_functions.h" #include "select_constraints.h" #include "operators.h" #include "rowid.h" @@ -20,7 +19,7 @@ namespace sqlite_orm { /** * This is a proxy class used to define what type must have result type depending on select * arguments (member pointer, aggregate functions, etc). Below you can see specializations - * for different types. E.g. specialization for core_functions::length_t has `type` int cause + * for different types. E.g. specialization for internal::length_t has `type` int cause * LENGTH returns INTEGER in sqlite. Every column_result_t must have `type` type that equals * c++ SELECT return type for T * T - C++ type @@ -53,61 +52,23 @@ namespace sqlite_orm { using type = typename setter_traits::field_type; }; - template - struct column_result_t< - St, - T, - typename std::enable_if::value>::type> { - using type = typename T::return_type; - }; - - template - struct column_result_t, void> { - using type = double; + template + struct column_result_t, void> { + using type = R; }; - template - struct column_result_t, void> { - using type = int; + template + struct column_result_t, S, X>, void> { + using type = std::unique_ptr::type>; }; template - struct column_result_t, void> { + struct column_result_t, void> { using type = int; }; - template - struct column_result_t, void> { - using type = std::unique_ptr; - }; - - template - struct column_result_t, void> { - using type = double; - }; - - template - struct column_result_t, void> { - using type = std::string; - }; - - template - struct column_result_t, void> { - using type = std::string; - }; - - template - struct column_result_t, void> { - using type = std::unique_ptr::type>; - }; - - template - struct column_result_t, void> { - using type = std::unique_ptr::type>; - }; - template - struct column_result_t { + struct column_result_t { using type = int; }; diff --git a/dev/core_functions.h b/dev/core_functions.h index f95398e35..6518e1652 100644 --- a/dev/core_functions.h +++ b/dev/core_functions.h @@ -12,7 +12,10 @@ namespace sqlite_orm { - namespace core_functions { + namespace internal { + + template + struct unique_ptr_result_of {}; /** * Base class for operator overloading @@ -187,56 +190,130 @@ namespace sqlite_orm { } }; #endif + struct total_string { + operator std::string() const { + return "TOTAL"; + } + }; + + struct sum_string { + operator std::string() const { + return "SUM"; + } + }; + + struct count_string { + operator std::string() const { + return "COUNT"; + } + }; + + /** + * T is use to specify type explicitly for queries like + * SELECT COUNT(*) FROM table_name; + * T can be omitted with void. + */ + template + struct count_asterisk_t : count_string { + using type = T; + }; + + /** + * The same thing as count() but without T arg. + * Is used in cases like this: + * SELECT cust_code, cust_name, cust_city, grade + * FROM customer + * WHERE grade=2 AND EXISTS + * (SELECT COUNT(*) + * FROM customer + * WHERE grade=2 + * GROUP BY grade + * HAVING COUNT(*)>2); + * `c++` + * auto rows = + * storage.select(columns(&Customer::code, &Customer::name, &Customer::city, &Customer::grade), + * where(is_equal(&Customer::grade, 2) + * and exists(select(count(), + * where(is_equal(&Customer::grade, 2)), + * group_by(&Customer::grade), + * having(greater_than(count(), 2)))))); + */ + struct count_asterisk_without_type : count_string {}; + + struct avg_string { + operator std::string() const { + return "AVG"; + } + }; + + struct max_string { + operator std::string() const { + return "MAX"; + } + }; + + struct min_string { + operator std::string() const { + return "MIN"; + } + }; + + struct group_concat_string { + operator std::string() const { + return "GROUP_CONCAT"; + } + }; + } /** * Cute operators for core functions */ - template::value>::type> + template< + class F, + class R, + typename = typename std::enable_if::value>::type> conditions::lesser_than_t operator<(F f, R r) { return {std::move(f), std::move(r)}; } - template::value>::type> + template< + class F, + class R, + typename = typename std::enable_if::value>::type> conditions::lesser_or_equal_t operator<=(F f, R r) { return {std::move(f), std::move(r)}; } - template::value>::type> + template< + class F, + class R, + typename = typename std::enable_if::value>::type> conditions::greater_than_t operator>(F f, R r) { return {std::move(f), std::move(r)}; } - template::value>::type> + template< + class F, + class R, + typename = typename std::enable_if::value>::type> conditions::greater_or_equal_t operator>=(F f, R r) { return {std::move(f), std::move(r)}; } - template::value>::type> + template< + class F, + class R, + typename = typename std::enable_if::value>::type> conditions::is_equal_t operator==(F f, R r) { return {std::move(f), std::move(r)}; } - template::value>::type> + template< + class F, + class R, + typename = typename std::enable_if::value>::type> conditions::is_not_equal_t operator!=(F f, R r) { return {std::move(f), std::move(r)}; } @@ -245,7 +322,7 @@ namespace sqlite_orm { * LENGTH(x) function https://sqlite.org/lang_corefunc.html#length */ template - core_functions::core_function_t length(T t) { + internal::core_function_t length(T t) { std::tuple args{std::forward(t)}; return {move(args)}; } @@ -254,7 +331,7 @@ namespace sqlite_orm { * ABS(x) function https://sqlite.org/lang_corefunc.html#abs */ template - core_functions::core_function_t, core_functions::abs_string, T> abs(T t) { + internal::core_function_t, internal::abs_string, T> abs(T t) { std::tuple args{std::forward(t)}; return {move(args)}; } @@ -263,7 +340,7 @@ namespace sqlite_orm { * LOWER(x) function https://sqlite.org/lang_corefunc.html#lower */ template - core_functions::core_function_t lower(T t) { + internal::core_function_t lower(T t) { std::tuple args{std::forward(t)}; return {move(args)}; } @@ -272,7 +349,7 @@ namespace sqlite_orm { * UPPER(x) function https://sqlite.org/lang_corefunc.html#upper */ template - core_functions::core_function_t upper(T t) { + internal::core_function_t upper(T t) { std::tuple args{std::forward(t)}; return {move(args)}; } @@ -280,7 +357,7 @@ namespace sqlite_orm { /** * CHANGES() function https://sqlite.org/lang_corefunc.html#changes */ - inline core_functions::core_function_t changes() { + inline internal::core_function_t changes() { return {{}}; } @@ -288,7 +365,7 @@ namespace sqlite_orm { * TRIM(X) function https://sqlite.org/lang_corefunc.html#trim */ template - core_functions::core_function_t trim(T t) { + internal::core_function_t trim(T t) { std::tuple args{std::forward(t)}; return {move(args)}; } @@ -297,7 +374,7 @@ namespace sqlite_orm { * TRIM(X,Y) function https://sqlite.org/lang_corefunc.html#trim */ template - core_functions::core_function_t trim(X x, Y y) { + internal::core_function_t trim(X x, Y y) { std::tuple args{std::forward(x), std::forward(y)}; return {move(args)}; } @@ -306,7 +383,7 @@ namespace sqlite_orm { * LTRIM(X) function https://sqlite.org/lang_corefunc.html#ltrim */ template - core_functions::core_function_t ltrim(X x) { + internal::core_function_t ltrim(X x) { std::tuple args{std::forward(x)}; return {move(args)}; } @@ -315,7 +392,7 @@ namespace sqlite_orm { * LTRIM(X,Y) function https://sqlite.org/lang_corefunc.html#ltrim */ template - core_functions::core_function_t ltrim(X x, Y y) { + internal::core_function_t ltrim(X x, Y y) { std::tuple args{std::forward(x), std::forward(y)}; return {move(args)}; } @@ -324,7 +401,7 @@ namespace sqlite_orm { * RTRIM(X) function https://sqlite.org/lang_corefunc.html#rtrim */ template - core_functions::core_function_t rtrim(X x) { + internal::core_function_t rtrim(X x) { std::tuple args{std::forward(x)}; return {move(args)}; } @@ -333,7 +410,7 @@ namespace sqlite_orm { * RTRIM(X,Y) function https://sqlite.org/lang_corefunc.html#rtrim */ template - core_functions::core_function_t rtrim(X x, Y y) { + internal::core_function_t rtrim(X x, Y y) { std::tuple args{std::forward(x), std::forward(y)}; return {move(args)}; } @@ -342,7 +419,7 @@ namespace sqlite_orm { * HEX(X) function https://sqlite.org/lang_corefunc.html#hex */ template - core_functions::core_function_t hex(X x) { + internal::core_function_t hex(X x) { std::tuple args{std::forward(x)}; return {move(args)}; } @@ -351,7 +428,7 @@ namespace sqlite_orm { * QUOTE(X) function https://sqlite.org/lang_corefunc.html#quote */ template - core_functions::core_function_t quote(X x) { + internal::core_function_t quote(X x) { std::tuple args{std::forward(x)}; return {move(args)}; } @@ -360,7 +437,7 @@ namespace sqlite_orm { * RANDOMBLOB(X) function https://sqlite.org/lang_corefunc.html#randomblob */ template - core_functions::core_function_t, core_functions::randomblob_string, X> randomblob(X x) { + internal::core_function_t, internal::randomblob_string, X> randomblob(X x) { std::tuple args{std::forward(x)}; return {move(args)}; } @@ -369,7 +446,7 @@ namespace sqlite_orm { * INSTR(X) function https://sqlite.org/lang_corefunc.html#instr */ template - core_functions::core_function_t instr(X x, Y y) { + internal::core_function_t instr(X x, Y y) { std::tuple args{std::forward(x), std::forward(y)}; return {move(args)}; } @@ -378,7 +455,7 @@ namespace sqlite_orm { * REPLACE(X) function https://sqlite.org/lang_corefunc.html#replace */ template - core_functions::core_function_t replace(X x, Y y, Z z) { + internal::core_function_t replace(X x, Y y, Z z) { std::tuple args{std::forward(x), std::forward(y), std::forward(z)}; return {move(args)}; } @@ -387,7 +464,7 @@ namespace sqlite_orm { * ROUND(X) function https://sqlite.org/lang_corefunc.html#round */ template - core_functions::core_function_t round(X x) { + internal::core_function_t round(X x) { std::tuple args{std::forward(x)}; return {move(args)}; } @@ -396,7 +473,7 @@ namespace sqlite_orm { * ROUND(X, Y) function https://sqlite.org/lang_corefunc.html#round */ template - core_functions::core_function_t round(X x, Y y) { + internal::core_function_t round(X x, Y y) { std::tuple args{std::forward(x), std::forward(y)}; return {move(args)}; } @@ -407,14 +484,14 @@ namespace sqlite_orm { * CHAR(X1,X2,...,XN) function https://sqlite.org/lang_corefunc.html#char */ template - core_functions::core_function_t char_(Args... args) { + internal::core_function_t char_(Args... args) { return {std::make_tuple(std::forward(args)...)}; } /** * RANDOM() function https://www.sqlite.org/lang_corefunc.html#random */ - inline core_functions::core_function_t random() { + inline internal::core_function_t random() { return {{}}; } @@ -424,7 +501,7 @@ namespace sqlite_orm { * COALESCE(X,Y,...) function https://www.sqlite.org/lang_corefunc.html#coalesce */ template - core_functions::core_function_t coalesce(Args... args) { + internal::core_function_t coalesce(Args... args) { return {std::make_tuple(std::forward(args)...)}; } @@ -432,7 +509,7 @@ namespace sqlite_orm { * DATE(timestring, modifier, modifier, ...) function https://www.sqlite.org/lang_datefunc.html */ template - core_functions::core_function_t date(Args... args) { + internal::core_function_t date(Args... args) { std::tuple t{std::forward(args)...}; return {move(t)}; } @@ -441,7 +518,7 @@ namespace sqlite_orm { * TIME(timestring, modifier, modifier, ...) function https://www.sqlite.org/lang_datefunc.html */ template - core_functions::core_function_t time(Args... args) { + internal::core_function_t time(Args... args) { std::tuple t{std::forward(args)...}; return {move(t)}; } @@ -450,7 +527,7 @@ namespace sqlite_orm { * DATETIME(timestring, modifier, modifier, ...) function https://www.sqlite.org/lang_datefunc.html */ template - core_functions::core_function_t datetime(Args... args) { + internal::core_function_t datetime(Args... args) { std::tuple t{std::forward(args)...}; return {move(t)}; } @@ -459,7 +536,7 @@ namespace sqlite_orm { * JULIANDAY(timestring, modifier, modifier, ...) function https://www.sqlite.org/lang_datefunc.html */ template - core_functions::core_function_t julianday(Args... args) { + internal::core_function_t julianday(Args... args) { std::tuple t{std::forward(args)...}; return {move(t)}; } @@ -468,7 +545,7 @@ namespace sqlite_orm { * STRFTIME(timestring, modifier, modifier, ...) function https://www.sqlite.org/lang_datefunc.html */ template - core_functions::core_function_t strftime(Args... args) { + internal::core_function_t strftime(Args... args) { std::tuple t{std::forward(args)...}; return {move(t)}; } @@ -477,7 +554,7 @@ namespace sqlite_orm { * ZEROBLOB(N) function https://www.sqlite.org/lang_corefunc.html#zeroblob */ template - core_functions::core_function_t, core_functions::zeroblob_string, N> zeroblob(N n) { + internal::core_function_t, internal::zeroblob_string, N> zeroblob(N n) { std::tuple args{std::forward(n)}; return {move(args)}; } @@ -486,7 +563,7 @@ namespace sqlite_orm { * SUBSTR(X,Y) function https://www.sqlite.org/lang_corefunc.html#substr */ template - core_functions::core_function_t substr(X x, Y y) { + internal::core_function_t substr(X x, Y y) { std::tuple args{std::forward(x), std::forward(y)}; return {move(args)}; } @@ -495,22 +572,110 @@ namespace sqlite_orm { * SUBSTR(X,Y,Z) function https://www.sqlite.org/lang_corefunc.html#substr */ template - core_functions::core_function_t substr(X x, Y y, Z z) { + internal::core_function_t substr(X x, Y y, Z z) { std::tuple args{std::forward(x), std::forward(y), std::forward(z)}; return {move(args)}; } #ifdef SQLITE_SOUNDEX /** - * SOUNDEX(X) function https://www.sqlite.org/lang_corefunc.html#soundex - */ + * SOUNDEX(X) function https://www.sqlite.org/lang_corefunc.html#soundex + */ template - core_functions::core_function_t soundex(X x) { + internal::core_function_t soundex(X x) { std::tuple args{std::forward(x)}; return {move(args)}; } #endif + /** + * TOTAL(X) aggregate function. + */ + template + internal::core_function_t total(X x) { + std::tuple args{std::forward(x)}; + return {move(args)}; + } + + /** + * SUM(X) aggregate function. + */ + template + internal::core_function_t, internal::sum_string, X> sum(X x) { + std::tuple args{std::forward(x)}; + return {move(args)}; + } + + /** + * COUNT(X) aggregate function. + */ + template + internal::core_function_t count(X x) { + std::tuple args{std::forward(x)}; + return {move(args)}; + } + + /** + * COUNT(*) without FROM function. + */ + inline internal::count_asterisk_without_type count() { + return {}; + } + + /** + * COUNT(*) with FROM function. Specified type T will be serializeed as + * a from argument. + */ + template + internal::count_asterisk_t count() { + return {}; + } + + /** + * AVG(X) aggregate function. + */ + template + internal::core_function_t avg(X x) { + std::tuple args{std::forward(x)}; + return {move(args)}; + } + + /** + * MAX(X) aggregate function. + */ + template + internal::core_function_t, internal::max_string, X> max(X x) { + std::tuple args{std::forward(x)}; + return {move(args)}; + } + + /** + * MIN(X) aggregate function. + */ + template + internal::core_function_t, internal::min_string, X> min(X x) { + std::tuple args{std::forward(x)}; + return {move(args)}; + } + + /** + * GROUP_CONCAT(X) aggregate function. + */ + template + internal::core_function_t group_concat(X x) { + std::tuple args{std::forward(x)}; + return {move(args)}; + } + + /** + * GROUP_CONCAT(X, Y) aggregate function. + */ + template + internal::core_function_t group_concat(X x, Y y) { + std::tuple args{std::forward(x), std::forward(y)}; + return {move(args)}; + } + template::value + diff --git a/dev/node_tuple.h b/dev/node_tuple.h index 5ffd2e10f..64291e135 100644 --- a/dev/node_tuple.h +++ b/dev/node_tuple.h @@ -204,8 +204,8 @@ namespace sqlite_orm { }; template - struct node_tuple, void> { - using node_type = core_functions::core_function_t; + struct node_tuple, void> { + using node_type = core_function_t; using type = typename conc_tuple::type...>::type; }; diff --git a/dev/statement_serializator.h b/dev/statement_serializator.h index d0e41a9ed..38efd648d 100644 --- a/dev/statement_serializator.h +++ b/dev/statement_serializator.h @@ -35,8 +35,8 @@ namespace sqlite_orm { }; template - struct statement_serializator, void> { - using statement_type = core_functions::core_function_t; + struct statement_serializator, void> { + using statement_type = core_function_t; template std::string operator()(const statement_type &c, const C &context) const { diff --git a/dev/storage.h b/dev/storage.h index 3b1e24a4f..973fff12d 100644 --- a/dev/storage.h +++ b/dev/storage.h @@ -29,7 +29,6 @@ #include "type_is_nullable.h" #include "field_printer.h" #include "rowid.h" -#include "aggregate_functions.h" #include "operators.h" #include "select_constraints.h" #include "core_functions.h" @@ -185,8 +184,7 @@ namespace sqlite_orm { } template - std::string string_from_expression(const core_functions::core_function_t &c, - bool noTableName) const { + std::string string_from_expression(const core_function_t &c, bool noTableName) const { std::stringstream ss; ss << static_cast(c) << "("; std::vector args; @@ -281,25 +279,6 @@ namespace sqlite_orm { return ss.str(); } - template - std::string string_from_expression(const aggregate_functions::group_concat_double_t &f, - bool noTableName) const { - std::stringstream ss; - auto expr = this->string_from_expression(f.arg, noTableName); - auto expr2 = this->string_from_expression(f.y, noTableName); - ss << static_cast(f) << "(" << expr << ", " << expr2 << ")"; - return ss.str(); - } - - template - std::string string_from_expression(const aggregate_functions::group_concat_single_t &f, - bool noTableName) const { - std::stringstream ss; - auto expr = this->string_from_expression(f.arg, noTableName); - ss << static_cast(f) << "(" << expr << ")"; - return ss.str(); - } - template std::string string_from_expression(const binary_operator &f, bool noTableName) const { std::stringstream ss; @@ -310,66 +289,17 @@ namespace sqlite_orm { } template - std::string string_from_expression(const aggregate_functions::min_t &f, bool noTableName) const { - std::stringstream ss; - auto expr = this->string_from_expression(f.arg, noTableName); - ss << static_cast(f) << "(" << expr << ")"; - return ss.str(); - } - - template - std::string string_from_expression(const aggregate_functions::max_t &f, bool noTableName) const { - std::stringstream ss; - auto expr = this->string_from_expression(f.arg, noTableName); - ss << static_cast(f) << "(" << expr << ")"; - return ss.str(); + std::string string_from_expression(const internal::count_asterisk_t &, bool noTableName) const { + return this->string_from_expression(internal::count_asterisk_without_type{}, noTableName); } - template - std::string string_from_expression(const aggregate_functions::total_t &f, bool noTableName) const { - std::stringstream ss; - auto expr = this->string_from_expression(f.arg, noTableName); - ss << static_cast(f) << "(" << expr << ")"; - return ss.str(); - } - - template - std::string string_from_expression(const aggregate_functions::sum_t &f, bool noTableName) const { - std::stringstream ss; - auto expr = this->string_from_expression(f.arg, noTableName); - ss << static_cast(f) << "(" << expr << ")"; - return ss.str(); - } - - template - std::string string_from_expression(const aggregate_functions::count_asterisk_t &, - bool noTableName) const { - return this->string_from_expression(aggregate_functions::count_asterisk_without_type{}, noTableName); - } - - std::string string_from_expression(const aggregate_functions::count_asterisk_without_type &f, + std::string string_from_expression(const internal::count_asterisk_without_type &f, bool /*noTableName*/) const { std::stringstream ss; ss << static_cast(f) << "(*)"; return ss.str(); } - template - std::string string_from_expression(const aggregate_functions::count_t &f, bool noTableName) const { - std::stringstream ss; - auto expr = this->string_from_expression(f.arg, noTableName); - ss << static_cast(f) << "(" << expr << ")"; - return ss.str(); - } - - template - std::string string_from_expression(const aggregate_functions::avg_t &a, bool noTableName) const { - std::stringstream ss; - auto expr = this->string_from_expression(a.arg, noTableName); - ss << static_cast(a) << "(" << expr << ") "; - return ss.str(); - } - template std::string string_from_expression(const distinct_t &f, bool noTableName) const { std::stringstream ss; @@ -1284,60 +1214,9 @@ namespace sqlite_orm { return {std::make_pair(this->impl.find_table_name(typeid(O)), std::move(alias))}; } - template - std::set> - parse_table_name(const aggregate_functions::min_t &f) const { - return this->parse_table_name(f.arg); - } - - template - std::set> - parse_table_name(const aggregate_functions::max_t &f) const { - return this->parse_table_name(f.arg); - } - - template - std::set> - parse_table_name(const aggregate_functions::sum_t &f) const { - return this->parse_table_name(f.arg); - } - - template - std::set> - parse_table_name(const aggregate_functions::total_t &f) const { - return this->parse_table_name(f.arg); - } - - template - std::set> - parse_table_name(const aggregate_functions::group_concat_double_t &f) const { - auto res = this->parse_table_name(f.arg); - auto secondSet = this->parse_table_name(f.y); - res.insert(secondSet.begin(), secondSet.end()); - return res; - } - - template - std::set> - parse_table_name(const aggregate_functions::group_concat_single_t &f) const { - return this->parse_table_name(f.arg); - } - - template - std::set> - parse_table_name(const aggregate_functions::count_t &f) const { - return this->parse_table_name(f.arg); - } - - template - std::set> - parse_table_name(const aggregate_functions::avg_t &a) const { - return this->parse_table_name(a.arg); - } - template std::set> - parse_table_name(const core_functions::core_function_t &f) const { + parse_table_name(const core_function_t &f) const { std::set> res; iterate_tuple(f.args, [&res, this](auto &v) { auto tableNames = this->parse_table_name(v); @@ -1381,7 +1260,7 @@ namespace sqlite_orm { template std::set> - parse_table_name(const aggregate_functions::count_asterisk_t &) const { + parse_table_name(const internal::count_asterisk_t &) const { auto tableName = this->impl.find_table_name(typeid(T)); if(!tableName.empty()) { return {std::make_pair(std::move(tableName), "")}; @@ -1391,7 +1270,7 @@ namespace sqlite_orm { } std::set> - parse_table_name(const aggregate_functions::count_asterisk_without_type &) const { + parse_table_name(const internal::count_asterisk_without_type &) const { return {}; } diff --git a/include/sqlite_orm/sqlite_orm.h b/include/sqlite_orm/sqlite_orm.h index cb65d11da..6651950ea 100644 --- a/include/sqlite_orm/sqlite_orm.h +++ b/include/sqlite_orm/sqlite_orm.h @@ -3451,7 +3451,10 @@ namespace sqlite_orm { namespace sqlite_orm { - namespace core_functions { + namespace internal { + + template + struct unique_ptr_result_of {}; /** * Base class for operator overloading @@ -3626,56 +3629,130 @@ namespace sqlite_orm { } }; #endif + struct total_string { + operator std::string() const { + return "TOTAL"; + } + }; + + struct sum_string { + operator std::string() const { + return "SUM"; + } + }; + + struct count_string { + operator std::string() const { + return "COUNT"; + } + }; + + /** + * T is use to specify type explicitly for queries like + * SELECT COUNT(*) FROM table_name; + * T can be omitted with void. + */ + template + struct count_asterisk_t : count_string { + using type = T; + }; + + /** + * The same thing as count() but without T arg. + * Is used in cases like this: + * SELECT cust_code, cust_name, cust_city, grade + * FROM customer + * WHERE grade=2 AND EXISTS + * (SELECT COUNT(*) + * FROM customer + * WHERE grade=2 + * GROUP BY grade + * HAVING COUNT(*)>2); + * `c++` + * auto rows = + * storage.select(columns(&Customer::code, &Customer::name, &Customer::city, &Customer::grade), + * where(is_equal(&Customer::grade, 2) + * and exists(select(count(), + * where(is_equal(&Customer::grade, 2)), + * group_by(&Customer::grade), + * having(greater_than(count(), 2)))))); + */ + struct count_asterisk_without_type : count_string {}; + + struct avg_string { + operator std::string() const { + return "AVG"; + } + }; + + struct max_string { + operator std::string() const { + return "MAX"; + } + }; + + struct min_string { + operator std::string() const { + return "MIN"; + } + }; + + struct group_concat_string { + operator std::string() const { + return "GROUP_CONCAT"; + } + }; + } /** * Cute operators for core functions */ - template::value>::type> + template< + class F, + class R, + typename = typename std::enable_if::value>::type> conditions::lesser_than_t operator<(F f, R r) { return {std::move(f), std::move(r)}; } - template::value>::type> + template< + class F, + class R, + typename = typename std::enable_if::value>::type> conditions::lesser_or_equal_t operator<=(F f, R r) { return {std::move(f), std::move(r)}; } - template::value>::type> + template< + class F, + class R, + typename = typename std::enable_if::value>::type> conditions::greater_than_t operator>(F f, R r) { return {std::move(f), std::move(r)}; } - template::value>::type> + template< + class F, + class R, + typename = typename std::enable_if::value>::type> conditions::greater_or_equal_t operator>=(F f, R r) { return {std::move(f), std::move(r)}; } - template::value>::type> + template< + class F, + class R, + typename = typename std::enable_if::value>::type> conditions::is_equal_t operator==(F f, R r) { return {std::move(f), std::move(r)}; } - template::value>::type> + template< + class F, + class R, + typename = typename std::enable_if::value>::type> conditions::is_not_equal_t operator!=(F f, R r) { return {std::move(f), std::move(r)}; } @@ -3684,7 +3761,7 @@ namespace sqlite_orm { * LENGTH(x) function https://sqlite.org/lang_corefunc.html#length */ template - core_functions::core_function_t length(T t) { + internal::core_function_t length(T t) { std::tuple args{std::forward(t)}; return {move(args)}; } @@ -3693,7 +3770,7 @@ namespace sqlite_orm { * ABS(x) function https://sqlite.org/lang_corefunc.html#abs */ template - core_functions::core_function_t, core_functions::abs_string, T> abs(T t) { + internal::core_function_t, internal::abs_string, T> abs(T t) { std::tuple args{std::forward(t)}; return {move(args)}; } @@ -3702,7 +3779,7 @@ namespace sqlite_orm { * LOWER(x) function https://sqlite.org/lang_corefunc.html#lower */ template - core_functions::core_function_t lower(T t) { + internal::core_function_t lower(T t) { std::tuple args{std::forward(t)}; return {move(args)}; } @@ -3711,7 +3788,7 @@ namespace sqlite_orm { * UPPER(x) function https://sqlite.org/lang_corefunc.html#upper */ template - core_functions::core_function_t upper(T t) { + internal::core_function_t upper(T t) { std::tuple args{std::forward(t)}; return {move(args)}; } @@ -3719,7 +3796,7 @@ namespace sqlite_orm { /** * CHANGES() function https://sqlite.org/lang_corefunc.html#changes */ - inline core_functions::core_function_t changes() { + inline internal::core_function_t changes() { return {{}}; } @@ -3727,7 +3804,7 @@ namespace sqlite_orm { * TRIM(X) function https://sqlite.org/lang_corefunc.html#trim */ template - core_functions::core_function_t trim(T t) { + internal::core_function_t trim(T t) { std::tuple args{std::forward(t)}; return {move(args)}; } @@ -3736,7 +3813,7 @@ namespace sqlite_orm { * TRIM(X,Y) function https://sqlite.org/lang_corefunc.html#trim */ template - core_functions::core_function_t trim(X x, Y y) { + internal::core_function_t trim(X x, Y y) { std::tuple args{std::forward(x), std::forward(y)}; return {move(args)}; } @@ -3745,7 +3822,7 @@ namespace sqlite_orm { * LTRIM(X) function https://sqlite.org/lang_corefunc.html#ltrim */ template - core_functions::core_function_t ltrim(X x) { + internal::core_function_t ltrim(X x) { std::tuple args{std::forward(x)}; return {move(args)}; } @@ -3754,7 +3831,7 @@ namespace sqlite_orm { * LTRIM(X,Y) function https://sqlite.org/lang_corefunc.html#ltrim */ template - core_functions::core_function_t ltrim(X x, Y y) { + internal::core_function_t ltrim(X x, Y y) { std::tuple args{std::forward(x), std::forward(y)}; return {move(args)}; } @@ -3763,7 +3840,7 @@ namespace sqlite_orm { * RTRIM(X) function https://sqlite.org/lang_corefunc.html#rtrim */ template - core_functions::core_function_t rtrim(X x) { + internal::core_function_t rtrim(X x) { std::tuple args{std::forward(x)}; return {move(args)}; } @@ -3772,7 +3849,7 @@ namespace sqlite_orm { * RTRIM(X,Y) function https://sqlite.org/lang_corefunc.html#rtrim */ template - core_functions::core_function_t rtrim(X x, Y y) { + internal::core_function_t rtrim(X x, Y y) { std::tuple args{std::forward(x), std::forward(y)}; return {move(args)}; } @@ -3781,7 +3858,7 @@ namespace sqlite_orm { * HEX(X) function https://sqlite.org/lang_corefunc.html#hex */ template - core_functions::core_function_t hex(X x) { + internal::core_function_t hex(X x) { std::tuple args{std::forward(x)}; return {move(args)}; } @@ -3790,7 +3867,7 @@ namespace sqlite_orm { * QUOTE(X) function https://sqlite.org/lang_corefunc.html#quote */ template - core_functions::core_function_t quote(X x) { + internal::core_function_t quote(X x) { std::tuple args{std::forward(x)}; return {move(args)}; } @@ -3799,7 +3876,7 @@ namespace sqlite_orm { * RANDOMBLOB(X) function https://sqlite.org/lang_corefunc.html#randomblob */ template - core_functions::core_function_t, core_functions::randomblob_string, X> randomblob(X x) { + internal::core_function_t, internal::randomblob_string, X> randomblob(X x) { std::tuple args{std::forward(x)}; return {move(args)}; } @@ -3808,7 +3885,7 @@ namespace sqlite_orm { * INSTR(X) function https://sqlite.org/lang_corefunc.html#instr */ template - core_functions::core_function_t instr(X x, Y y) { + internal::core_function_t instr(X x, Y y) { std::tuple args{std::forward(x), std::forward(y)}; return {move(args)}; } @@ -3817,7 +3894,7 @@ namespace sqlite_orm { * REPLACE(X) function https://sqlite.org/lang_corefunc.html#replace */ template - core_functions::core_function_t replace(X x, Y y, Z z) { + internal::core_function_t replace(X x, Y y, Z z) { std::tuple args{std::forward(x), std::forward(y), std::forward(z)}; return {move(args)}; } @@ -3826,7 +3903,7 @@ namespace sqlite_orm { * ROUND(X) function https://sqlite.org/lang_corefunc.html#round */ template - core_functions::core_function_t round(X x) { + internal::core_function_t round(X x) { std::tuple args{std::forward(x)}; return {move(args)}; } @@ -3835,7 +3912,7 @@ namespace sqlite_orm { * ROUND(X, Y) function https://sqlite.org/lang_corefunc.html#round */ template - core_functions::core_function_t round(X x, Y y) { + internal::core_function_t round(X x, Y y) { std::tuple args{std::forward(x), std::forward(y)}; return {move(args)}; } @@ -3846,14 +3923,14 @@ namespace sqlite_orm { * CHAR(X1,X2,...,XN) function https://sqlite.org/lang_corefunc.html#char */ template - core_functions::core_function_t char_(Args... args) { + internal::core_function_t char_(Args... args) { return {std::make_tuple(std::forward(args)...)}; } /** * RANDOM() function https://www.sqlite.org/lang_corefunc.html#random */ - inline core_functions::core_function_t random() { + inline internal::core_function_t random() { return {{}}; } @@ -3863,7 +3940,7 @@ namespace sqlite_orm { * COALESCE(X,Y,...) function https://www.sqlite.org/lang_corefunc.html#coalesce */ template - core_functions::core_function_t coalesce(Args... args) { + internal::core_function_t coalesce(Args... args) { return {std::make_tuple(std::forward(args)...)}; } @@ -3871,7 +3948,7 @@ namespace sqlite_orm { * DATE(timestring, modifier, modifier, ...) function https://www.sqlite.org/lang_datefunc.html */ template - core_functions::core_function_t date(Args... args) { + internal::core_function_t date(Args... args) { std::tuple t{std::forward(args)...}; return {move(t)}; } @@ -3880,7 +3957,7 @@ namespace sqlite_orm { * TIME(timestring, modifier, modifier, ...) function https://www.sqlite.org/lang_datefunc.html */ template - core_functions::core_function_t time(Args... args) { + internal::core_function_t time(Args... args) { std::tuple t{std::forward(args)...}; return {move(t)}; } @@ -3889,7 +3966,7 @@ namespace sqlite_orm { * DATETIME(timestring, modifier, modifier, ...) function https://www.sqlite.org/lang_datefunc.html */ template - core_functions::core_function_t datetime(Args... args) { + internal::core_function_t datetime(Args... args) { std::tuple t{std::forward(args)...}; return {move(t)}; } @@ -3898,7 +3975,7 @@ namespace sqlite_orm { * JULIANDAY(timestring, modifier, modifier, ...) function https://www.sqlite.org/lang_datefunc.html */ template - core_functions::core_function_t julianday(Args... args) { + internal::core_function_t julianday(Args... args) { std::tuple t{std::forward(args)...}; return {move(t)}; } @@ -3907,7 +3984,7 @@ namespace sqlite_orm { * STRFTIME(timestring, modifier, modifier, ...) function https://www.sqlite.org/lang_datefunc.html */ template - core_functions::core_function_t strftime(Args... args) { + internal::core_function_t strftime(Args... args) { std::tuple t{std::forward(args)...}; return {move(t)}; } @@ -3916,7 +3993,7 @@ namespace sqlite_orm { * ZEROBLOB(N) function https://www.sqlite.org/lang_corefunc.html#zeroblob */ template - core_functions::core_function_t, core_functions::zeroblob_string, N> zeroblob(N n) { + internal::core_function_t, internal::zeroblob_string, N> zeroblob(N n) { std::tuple args{std::forward(n)}; return {move(args)}; } @@ -3925,7 +4002,7 @@ namespace sqlite_orm { * SUBSTR(X,Y) function https://www.sqlite.org/lang_corefunc.html#substr */ template - core_functions::core_function_t substr(X x, Y y) { + internal::core_function_t substr(X x, Y y) { std::tuple args{std::forward(x), std::forward(y)}; return {move(args)}; } @@ -3934,279 +4011,53 @@ namespace sqlite_orm { * SUBSTR(X,Y,Z) function https://www.sqlite.org/lang_corefunc.html#substr */ template - core_functions::core_function_t substr(X x, Y y, Z z) { + internal::core_function_t substr(X x, Y y, Z z) { std::tuple args{std::forward(x), std::forward(y), std::forward(z)}; return {move(args)}; } #ifdef SQLITE_SOUNDEX /** - * SOUNDEX(X) function https://www.sqlite.org/lang_corefunc.html#soundex - */ + * SOUNDEX(X) function https://www.sqlite.org/lang_corefunc.html#soundex + */ template - core_functions::core_function_t soundex(X x) { + internal::core_function_t soundex(X x) { std::tuple args{std::forward(x)}; return {move(args)}; } #endif - template::value + - std::is_base_of::value > - 0)>::type> - internal::add_t operator+(L l, R r) { - return {std::move(l), std::move(r)}; - } - - template::value + - std::is_base_of::value > - 0)>::type> - internal::sub_t operator-(L l, R r) { - return {std::move(l), std::move(r)}; - } - - template::value + - std::is_base_of::value > - 0)>::type> - internal::mul_t operator*(L l, R r) { - return {std::move(l), std::move(r)}; - } - - template::value + - std::is_base_of::value > - 0)>::type> - internal::div_t operator/(L l, R r) { - return {std::move(l), std::move(r)}; - } - - template::value + - std::is_base_of::value > - 0)>::type> - internal::mod_t operator%(L l, R r) { - return {std::move(l), std::move(r)}; - } -} -#pragma once - -namespace sqlite_orm { - - namespace aggregate_functions { - - struct avg_string { - operator std::string() const { - return "AVG"; - } - }; - - /** - * Result of avg(...) call. - * T is an argument type - */ - template - struct avg_t : avg_string { - using arg_type = T; - - arg_type arg; - - avg_t(arg_type arg_) : arg(std::move(arg_)) {} - }; - - struct count_string { - operator std::string() const { - return "COUNT"; - } - }; - - /** - * Result of count(...) call. - * T is an argument type - */ - template - struct count_t : count_string { - using arg_type = T; - - arg_type arg; - - count_t(arg_type arg_) : arg(std::move(arg_)) {} - }; - - /** - * T is use to specify type explicitly for queries like - * SELECT COUNT(*) FROM table_name; - * T can be omitted with void. - */ - template - struct count_asterisk_t : count_string { - using type = T; - }; - - /** - * The same thing as count() but without T arg. - * Is used in cases like this: - * SELECT cust_code, cust_name, cust_city, grade - * FROM customer - * WHERE grade=2 AND EXISTS - * (SELECT COUNT(*) - * FROM customer - * WHERE grade=2 - * GROUP BY grade - * HAVING COUNT(*)>2); - * `c++` - * auto rows = - * storage.select(columns(&Customer::code, &Customer::name, &Customer::city, &Customer::grade), - * where(is_equal(&Customer::grade, 2) - * and exists(select(count(), - * where(is_equal(&Customer::grade, 2)), - * group_by(&Customer::grade), - * having(greater_than(count(), 2)))))); - */ - struct count_asterisk_without_type : count_string {}; - - struct sum_string { - operator std::string() const { - return "SUM"; - } - }; - - /** - * Result of sum(...) call. - * T is an argument type - */ - template - struct sum_t : sum_string { - using arg_type = T; - - arg_type arg; - - sum_t(arg_type arg_) : arg(std::move(arg_)) {} - }; - - struct total_string { - operator std::string() const { - return "TOTAL"; - } - }; - - /** - * Result of total(...) call. - * T is an argument type - */ - template - struct total_t : total_string { - using arg_type = T; - - arg_type arg; - - total_t(arg_type arg_) : arg(std::move(arg_)) {} - }; - - struct max_string { - operator std::string() const { - return "MAX"; - } - }; - - /** - * Result of max(...) call. - * T is an argument type - */ - template - struct max_t : max_string { - using arg_type = T; - - arg_type arg; - - max_t(arg_type arg_) : arg(std::move(arg_)) {} - }; - - struct min_string { - operator std::string() const { - return "MIN"; - } - }; - - /** - * Result of min(...) call. - * T is an argument type - */ - template - struct min_t : min_string { - using arg_type = T; - - arg_type arg; - - min_t(arg_type arg_) : arg(std::move(arg_)) {} - }; - - struct group_concat_string { - operator std::string() const { - return "GROUP_CONCAT"; - } - }; - - /** - * Result of group_concat(X) call. - * T is an argument type - */ - template - struct group_concat_single_t : group_concat_string { - using arg_type = T; - - arg_type arg; - - group_concat_single_t(arg_type arg_) : arg(std::move(arg_)) {} - }; - - struct group_concat_double_base : group_concat_string { - std::string y; - - group_concat_double_base(std::string y_) : y(move(y_)) {} - }; - - /** - * Result of group_concat(X, Y) call. - * T is an argument type - */ - template - struct group_concat_double_t : group_concat_double_base { - using arg_type = T; - - arg_type arg; - - group_concat_double_t(arg_type arg_, std::string y) : - group_concat_double_base(move(y)), arg(std::move(arg_)) {} - }; + /** + * TOTAL(X) aggregate function. + */ + template + internal::core_function_t total(X x) { + std::tuple args{std::forward(x)}; + return {move(args)}; } /** - * AVG(X) aggregate function. + * SUM(X) aggregate function. */ - template - aggregate_functions::avg_t avg(T t) { - return {std::move(t)}; + template + internal::core_function_t, internal::sum_string, X> sum(X x) { + std::tuple args{std::forward(x)}; + return {move(args)}; } /** * COUNT(X) aggregate function. */ - template - aggregate_functions::count_t count(T t) { - return {std::move(t)}; + template + internal::core_function_t count(X x) { + std::tuple args{std::forward(x)}; + return {move(args)}; } /** * COUNT(*) without FROM function. */ - inline aggregate_functions::count_asterisk_without_type count() { + inline internal::count_asterisk_without_type count() { return {}; } @@ -4215,56 +4066,98 @@ namespace sqlite_orm { * a from argument. */ template - aggregate_functions::count_asterisk_t count() { + internal::count_asterisk_t count() { return {}; } /** - * SUM(X) aggregate function. + * AVG(X) aggregate function. */ - template - aggregate_functions::sum_t sum(T t) { - return {std::move(t)}; + template + internal::core_function_t avg(X x) { + std::tuple args{std::forward(x)}; + return {move(args)}; } /** * MAX(X) aggregate function. */ - template - aggregate_functions::max_t max(T t) { - return {std::move(t)}; + template + internal::core_function_t, internal::max_string, X> max(X x) { + std::tuple args{std::forward(x)}; + return {move(args)}; } /** * MIN(X) aggregate function. */ - template - aggregate_functions::min_t min(T t) { - return {std::move(t)}; - } - - /** - * TOTAL(X) aggregate function. - */ - template - aggregate_functions::total_t total(T t) { - return {std::move(t)}; + template + internal::core_function_t, internal::min_string, X> min(X x) { + std::tuple args{std::forward(x)}; + return {move(args)}; } /** * GROUP_CONCAT(X) aggregate function. */ - template - aggregate_functions::group_concat_single_t group_concat(T t) { - return {std::move(t)}; + template + internal::core_function_t group_concat(X x) { + std::tuple args{std::forward(x)}; + return {move(args)}; } /** * GROUP_CONCAT(X, Y) aggregate function. */ - template - aggregate_functions::group_concat_double_t group_concat(T t, Y y) { - return {std::move(t), std::move(y)}; + template + internal::core_function_t group_concat(X x, Y y) { + std::tuple args{std::forward(x), std::forward(y)}; + return {move(args)}; + } + + template::value + + std::is_base_of::value > + 0)>::type> + internal::add_t operator+(L l, R r) { + return {std::move(l), std::move(r)}; + } + + template::value + + std::is_base_of::value > + 0)>::type> + internal::sub_t operator-(L l, R r) { + return {std::move(l), std::move(r)}; + } + + template::value + + std::is_base_of::value > + 0)>::type> + internal::mul_t operator*(L l, R r) { + return {std::move(l), std::move(r)}; + } + + template::value + + std::is_base_of::value > + 0)>::type> + internal::div_t operator/(L l, R r) { + return {std::move(l), std::move(r)}; + } + + template::value + + std::is_base_of::value > + 0)>::type> + internal::mod_t operator%(L l, R r) { + return {std::move(l), std::move(r)}; } } #pragma once @@ -5539,8 +5432,6 @@ namespace sqlite_orm { // #include "core_functions.h" -// #include "aggregate_functions.h" - // #include "select_constraints.h" // #include "operators.h" @@ -5698,7 +5589,7 @@ namespace sqlite_orm { /** * This is a proxy class used to define what type must have result type depending on select * arguments (member pointer, aggregate functions, etc). Below you can see specializations - * for different types. E.g. specialization for core_functions::length_t has `type` int cause + * for different types. E.g. specialization for internal::length_t has `type` int cause * LENGTH returns INTEGER in sqlite. Every column_result_t must have `type` type that equals * c++ SELECT return type for T * T - C++ type @@ -5731,61 +5622,23 @@ namespace sqlite_orm { using type = typename setter_traits::field_type; }; - template - struct column_result_t< - St, - T, - typename std::enable_if::value>::type> { - using type = typename T::return_type; - }; - - template - struct column_result_t, void> { - using type = double; + template + struct column_result_t, void> { + using type = R; }; - template - struct column_result_t, void> { - using type = int; + template + struct column_result_t, S, X>, void> { + using type = std::unique_ptr::type>; }; template - struct column_result_t, void> { + struct column_result_t, void> { using type = int; }; - template - struct column_result_t, void> { - using type = std::unique_ptr; - }; - - template - struct column_result_t, void> { - using type = double; - }; - - template - struct column_result_t, void> { - using type = std::string; - }; - - template - struct column_result_t, void> { - using type = std::string; - }; - - template - struct column_result_t, void> { - using type = std::unique_ptr::type>; - }; - - template - struct column_result_t, void> { - using type = std::unique_ptr::type>; - }; - template - struct column_result_t { + struct column_result_t { using type = int; }; @@ -6769,8 +6622,6 @@ namespace sqlite_orm { // #include "rowid.h" -// #include "aggregate_functions.h" - // #include "operators.h" // #include "select_constraints.h" @@ -7756,8 +7607,8 @@ namespace sqlite_orm { }; template - struct ast_iterator, void> { - using node_type = core_functions::core_function_t; + struct ast_iterator, void> { + using node_type = core_function_t; template void operator()(const node_type &f, const L &l) const { @@ -9079,8 +8930,8 @@ namespace sqlite_orm { }; template - struct statement_serializator, void> { - using statement_type = core_functions::core_function_t; + struct statement_serializator, void> { + using statement_type = core_function_t; template std::string operator()(const statement_type &c, const C &context) const { @@ -9478,8 +9329,7 @@ namespace sqlite_orm { } template - std::string string_from_expression(const core_functions::core_function_t &c, - bool noTableName) const { + std::string string_from_expression(const core_function_t &c, bool noTableName) const { std::stringstream ss; ss << static_cast(c) << "("; std::vector args; @@ -9574,25 +9424,6 @@ namespace sqlite_orm { return ss.str(); } - template - std::string string_from_expression(const aggregate_functions::group_concat_double_t &f, - bool noTableName) const { - std::stringstream ss; - auto expr = this->string_from_expression(f.arg, noTableName); - auto expr2 = this->string_from_expression(f.y, noTableName); - ss << static_cast(f) << "(" << expr << ", " << expr2 << ")"; - return ss.str(); - } - - template - std::string string_from_expression(const aggregate_functions::group_concat_single_t &f, - bool noTableName) const { - std::stringstream ss; - auto expr = this->string_from_expression(f.arg, noTableName); - ss << static_cast(f) << "(" << expr << ")"; - return ss.str(); - } - template std::string string_from_expression(const binary_operator &f, bool noTableName) const { std::stringstream ss; @@ -9603,66 +9434,17 @@ namespace sqlite_orm { } template - std::string string_from_expression(const aggregate_functions::min_t &f, bool noTableName) const { - std::stringstream ss; - auto expr = this->string_from_expression(f.arg, noTableName); - ss << static_cast(f) << "(" << expr << ")"; - return ss.str(); + std::string string_from_expression(const internal::count_asterisk_t &, bool noTableName) const { + return this->string_from_expression(internal::count_asterisk_without_type{}, noTableName); } - template - std::string string_from_expression(const aggregate_functions::max_t &f, bool noTableName) const { - std::stringstream ss; - auto expr = this->string_from_expression(f.arg, noTableName); - ss << static_cast(f) << "(" << expr << ")"; - return ss.str(); - } - - template - std::string string_from_expression(const aggregate_functions::total_t &f, bool noTableName) const { - std::stringstream ss; - auto expr = this->string_from_expression(f.arg, noTableName); - ss << static_cast(f) << "(" << expr << ")"; - return ss.str(); - } - - template - std::string string_from_expression(const aggregate_functions::sum_t &f, bool noTableName) const { - std::stringstream ss; - auto expr = this->string_from_expression(f.arg, noTableName); - ss << static_cast(f) << "(" << expr << ")"; - return ss.str(); - } - - template - std::string string_from_expression(const aggregate_functions::count_asterisk_t &, - bool noTableName) const { - return this->string_from_expression(aggregate_functions::count_asterisk_without_type{}, noTableName); - } - - std::string string_from_expression(const aggregate_functions::count_asterisk_without_type &f, + std::string string_from_expression(const internal::count_asterisk_without_type &f, bool /*noTableName*/) const { std::stringstream ss; ss << static_cast(f) << "(*)"; return ss.str(); } - template - std::string string_from_expression(const aggregate_functions::count_t &f, bool noTableName) const { - std::stringstream ss; - auto expr = this->string_from_expression(f.arg, noTableName); - ss << static_cast(f) << "(" << expr << ")"; - return ss.str(); - } - - template - std::string string_from_expression(const aggregate_functions::avg_t &a, bool noTableName) const { - std::stringstream ss; - auto expr = this->string_from_expression(a.arg, noTableName); - ss << static_cast(a) << "(" << expr << ") "; - return ss.str(); - } - template std::string string_from_expression(const distinct_t &f, bool noTableName) const { std::stringstream ss; @@ -10577,60 +10359,9 @@ namespace sqlite_orm { return {std::make_pair(this->impl.find_table_name(typeid(O)), std::move(alias))}; } - template - std::set> - parse_table_name(const aggregate_functions::min_t &f) const { - return this->parse_table_name(f.arg); - } - - template - std::set> - parse_table_name(const aggregate_functions::max_t &f) const { - return this->parse_table_name(f.arg); - } - - template - std::set> - parse_table_name(const aggregate_functions::sum_t &f) const { - return this->parse_table_name(f.arg); - } - - template - std::set> - parse_table_name(const aggregate_functions::total_t &f) const { - return this->parse_table_name(f.arg); - } - - template - std::set> - parse_table_name(const aggregate_functions::group_concat_double_t &f) const { - auto res = this->parse_table_name(f.arg); - auto secondSet = this->parse_table_name(f.y); - res.insert(secondSet.begin(), secondSet.end()); - return res; - } - - template - std::set> - parse_table_name(const aggregate_functions::group_concat_single_t &f) const { - return this->parse_table_name(f.arg); - } - - template - std::set> - parse_table_name(const aggregate_functions::count_t &f) const { - return this->parse_table_name(f.arg); - } - - template - std::set> - parse_table_name(const aggregate_functions::avg_t &a) const { - return this->parse_table_name(a.arg); - } - template std::set> - parse_table_name(const core_functions::core_function_t &f) const { + parse_table_name(const core_function_t &f) const { std::set> res; iterate_tuple(f.args, [&res, this](auto &v) { auto tableNames = this->parse_table_name(v); @@ -10674,7 +10405,7 @@ namespace sqlite_orm { template std::set> - parse_table_name(const aggregate_functions::count_asterisk_t &) const { + parse_table_name(const internal::count_asterisk_t &) const { auto tableName = this->impl.find_table_name(typeid(T)); if(!tableName.empty()) { return {std::make_pair(std::move(tableName), "")}; @@ -10684,7 +10415,7 @@ namespace sqlite_orm { } std::set> - parse_table_name(const aggregate_functions::count_asterisk_without_type &) const { + parse_table_name(const internal::count_asterisk_without_type &) const { return {}; } @@ -12464,8 +12195,8 @@ __pragma(pop_macro("min")) }; template - struct node_tuple, void> { - using node_type = core_functions::core_function_t; + struct node_tuple, void> { + using node_type = core_function_t; using type = typename conc_tuple::type...>::type; }; diff --git a/third_party/amalgamate/config.json b/third_party/amalgamate/config.json index ff567afee..65093054e 100755 --- a/third_party/amalgamate/config.json +++ b/third_party/amalgamate/config.json @@ -18,7 +18,6 @@ "dev/alias.h", "dev/join_iterator.h", "dev/core_functions.h", - "dev/aggregate_functions.h", "dev/typed_comparator.h", "dev/select_constraints.h", "dev/table_type.h", From f896237af744af7a5177a4c3739a8047068f843e Mon Sep 17 00:00:00 2001 From: fnc12 Date: Thu, 13 Feb 2020 22:28:27 +0300 Subject: [PATCH 024/132] removed most overrides of storage_t::parse_table_name --- dev/ast_iterator.h | 20 +++ dev/storage.h | 206 +---------------------------- include/sqlite_orm/sqlite_orm.h | 223 ++++---------------------------- 3 files changed, 51 insertions(+), 398 deletions(-) diff --git a/dev/ast_iterator.h b/dev/ast_iterator.h index bb5289ec6..86f24773c 100644 --- a/dev/ast_iterator.h +++ b/dev/ast_iterator.h @@ -460,5 +460,25 @@ namespace sqlite_orm { iterate_ast(a.lim, l); } }; + + template + struct ast_iterator, void> { + using node_type = distinct_t; + + template + void operator()(const node_type &a, const L &l) const { + iterate_ast(a.t, l); + } + }; + + template + struct ast_iterator, void> { + using node_type = all_t; + + template + void operator()(const node_type &a, const L &l) const { + iterate_ast(a.t, l); + } + }; } } diff --git a/dev/storage.h b/dev/storage.h index 973fff12d..fd7b04937 100644 --- a/dev/storage.h +++ b/dev/storage.h @@ -387,7 +387,11 @@ namespace sqlite_orm { } ss << " "; } - auto tableNamesSet = this->parse_table_name(sel.col); + std::set> tableNamesSet; + iterate_ast(sel.col, [this, &tableNamesSet](auto &node) { + auto tableNames = this->parse_table_name(node); + tableNamesSet.insert(tableNames.begin(), tableNames.end()); + }); internal::join_iterator()([&tableNamesSet, this](const auto &c) { using original_join_type = typename std::decay::type::join_type::type; using cross_join_type = typename internal::mapped_type_proxy::type; @@ -1214,38 +1218,6 @@ namespace sqlite_orm { return {std::make_pair(this->impl.find_table_name(typeid(O)), std::move(alias))}; } - template - std::set> - parse_table_name(const core_function_t &f) const { - std::set> res; - iterate_tuple(f.args, [&res, this](auto &v) { - auto tableNames = this->parse_table_name(v); - res.insert(tableNames.begin(), tableNames.end()); - }); - return res; - } - - template - std::set> parse_table_name(const distinct_t &f) const { - return this->parse_table_name(f.t); - } - - template - std::set> parse_table_name(const all_t &f) const { - return this->parse_table_name(f.t); - } - - template - std::set> - parse_table_name(const binary_operator &f) const { - std::set> res; - auto leftSet = this->parse_table_name(f.lhs); - res.insert(leftSet.begin(), leftSet.end()); - auto rightSet = this->parse_table_name(f.rhs); - res.insert(rightSet.begin(), rightSet.end()); - return res; - } - template std::set> parse_table_name(const column_pointer &) const { std::set> res; @@ -1259,8 +1231,7 @@ namespace sqlite_orm { } template - std::set> - parse_table_name(const internal::count_asterisk_t &) const { + std::set> parse_table_name(const count_asterisk_t &) const { auto tableName = this->impl.find_table_name(typeid(T)); if(!tableName.empty()) { return {std::make_pair(std::move(tableName), "")}; @@ -1269,177 +1240,12 @@ namespace sqlite_orm { } } - std::set> - parse_table_name(const internal::count_asterisk_without_type &) const { - return {}; - } - template std::set> parse_table_name(const asterisk_t &) const { auto tableName = this->impl.find_table_name(typeid(T)); return {std::make_pair(std::move(tableName), "")}; } - template - std::set> parse_table_name(const conditions::cast_t &c) const { - return this->parse_table_name(c.expression); - } - - template - std::set> - parse_table_name(const simple_case_t &c) const { - std::set> res; - c.case_expression.apply([this, &res](auto &c) { - auto caseExpressionSet = this->parse_table_name(c); - res.insert(caseExpressionSet.begin(), caseExpressionSet.end()); - }); - iterate_tuple(c.args, [this, &res](auto &pair) { - auto leftSet = this->parse_table_name(pair.first); - res.insert(leftSet.begin(), leftSet.end()); - auto rightSet = this->parse_table_name(pair.second); - res.insert(rightSet.begin(), rightSet.end()); - }); - c.else_expression.apply([this, &res](auto &el) { - auto tableNames = this->parse_table_name(el); - res.insert(tableNames.begin(), tableNames.end()); - }); - return res; - } - - template - std::set> - parse_table_name(const conditions::and_condition_t &c) const { - std::set> res; - auto leftTableNames = this->parse_table_name(c.l); - res.insert(leftTableNames.begin(), leftTableNames.end()); - auto rightTableNames = this->parse_table_name(c.r); - res.insert(rightTableNames.begin(), rightTableNames.end()); - return res; - } - - template - std::set> - parse_table_name(const conditions::or_condition_t &c) const { - std::set> res; - auto leftTableNames = this->parse_table_name(c.l); - res.insert(leftTableNames.begin(), leftTableNames.end()); - auto rightTableNames = this->parse_table_name(c.r); - res.insert(rightTableNames.begin(), rightTableNames.end()); - return res; - } - - template - std::set> - parse_table_name(const conditions::is_equal_t &c) const { - std::set> res; - auto leftTableNames = this->parse_table_name(c.l); - res.insert(leftTableNames.begin(), leftTableNames.end()); - auto rightTableNames = this->parse_table_name(c.r); - res.insert(rightTableNames.begin(), rightTableNames.end()); - return res; - } - - template - std::set> - parse_table_name(const conditions::is_not_equal_t &c) const { - std::set> res; - auto leftTableNames = this->parse_table_name(c.l); - res.insert(leftTableNames.begin(), leftTableNames.end()); - auto rightTableNames = this->parse_table_name(c.r); - res.insert(rightTableNames.begin(), rightTableNames.end()); - return res; - } - - template - std::set> - parse_table_name(const conditions::greater_than_t &c) const { - std::set> res; - auto leftTableNames = this->parse_table_name(c.l); - res.insert(leftTableNames.begin(), leftTableNames.end()); - auto rightTableNames = this->parse_table_name(c.r); - res.insert(rightTableNames.begin(), rightTableNames.end()); - return res; - } - - template - std::set> - parse_table_name(const conditions::greater_or_equal_t &c) const { - std::set> res; - auto leftTableNames = this->parse_table_name(c.l); - res.insert(leftTableNames.begin(), leftTableNames.end()); - auto rightTableNames = this->parse_table_name(c.r); - res.insert(rightTableNames.begin(), rightTableNames.end()); - return res; - } - - template - std::set> - parse_table_name(const conditions::lesser_than_t &c) const { - std::set> res; - auto leftTableNames = this->parse_table_name(c.l); - res.insert(leftTableNames.begin(), leftTableNames.end()); - auto rightTableNames = this->parse_table_name(c.r); - res.insert(rightTableNames.begin(), rightTableNames.end()); - return res; - } - - template - std::set> - parse_table_name(const conditions::lesser_or_equal_t &c) const { - std::set> res; - auto leftTableNames = this->parse_table_name(c.l); - res.insert(leftTableNames.begin(), leftTableNames.end()); - auto rightTableNames = this->parse_table_name(c.r); - res.insert(rightTableNames.begin(), rightTableNames.end()); - return res; - } - - template - std::set> parse_table_name(const conditions::like_t &l) const { - std::set> res; - auto argTableNames = this->parse_table_name(l.arg); - res.insert(argTableNames.begin(), argTableNames.end()); - auto patternTableNames = this->parse_table_name(l.pattern); - res.insert(patternTableNames.begin(), patternTableNames.end()); - l.arg3.apply([&res, this](auto &value) { - auto escapeTableNames = this->parse_table_name(value); - res.insert(escapeTableNames.begin(), escapeTableNames.end()); - }); - return res; - } - - template - std::set> parse_table_name(const conditions::glob_t &l) const { - std::set> res; - auto argTableNames = this->parse_table_name(l.arg); - res.insert(argTableNames.begin(), argTableNames.end()); - auto patternTableNames = this->parse_table_name(l.pattern); - res.insert(patternTableNames.begin(), patternTableNames.end()); - return res; - } - - template - std::set> - parse_table_name(const conditions::negated_condition_t &c) const { - return this->parse_table_name(c.c); - } - - template - std::set> parse_table_name(const as_t &a) const { - return this->parse_table_name(a.expression); - } - - template - std::set> - parse_table_name(const internal::columns_t &cols) const { - std::set> res; - iterate_tuple(cols.columns, [&res, this](auto &m) { - auto tableName = this->parse_table_name(m); - res.insert(tableName.begin(), tableName.end()); - }); - return res; - } - template std::string group_concat_internal(F O::*m, std::unique_ptr y, Args &&... args) { this->assert_mapped_type(); diff --git a/include/sqlite_orm/sqlite_orm.h b/include/sqlite_orm/sqlite_orm.h index 6651950ea..a479d98b0 100644 --- a/include/sqlite_orm/sqlite_orm.h +++ b/include/sqlite_orm/sqlite_orm.h @@ -7730,6 +7730,26 @@ namespace sqlite_orm { iterate_ast(a.lim, l); } }; + + template + struct ast_iterator, void> { + using node_type = distinct_t; + + template + void operator()(const node_type &a, const L &l) const { + iterate_ast(a.t, l); + } + }; + + template + struct ast_iterator, void> { + using node_type = all_t; + + template + void operator()(const node_type &a, const L &l) const { + iterate_ast(a.t, l); + } + }; } } @@ -9532,7 +9552,11 @@ namespace sqlite_orm { } ss << " "; } - auto tableNamesSet = this->parse_table_name(sel.col); + std::set> tableNamesSet; + iterate_ast(sel.col, [this, &tableNamesSet](auto &node) { + auto tableNames = this->parse_table_name(node); + tableNamesSet.insert(tableNames.begin(), tableNames.end()); + }); internal::join_iterator()([&tableNamesSet, this](const auto &c) { using original_join_type = typename std::decay::type::join_type::type; using cross_join_type = typename internal::mapped_type_proxy::type; @@ -10359,38 +10383,6 @@ namespace sqlite_orm { return {std::make_pair(this->impl.find_table_name(typeid(O)), std::move(alias))}; } - template - std::set> - parse_table_name(const core_function_t &f) const { - std::set> res; - iterate_tuple(f.args, [&res, this](auto &v) { - auto tableNames = this->parse_table_name(v); - res.insert(tableNames.begin(), tableNames.end()); - }); - return res; - } - - template - std::set> parse_table_name(const distinct_t &f) const { - return this->parse_table_name(f.t); - } - - template - std::set> parse_table_name(const all_t &f) const { - return this->parse_table_name(f.t); - } - - template - std::set> - parse_table_name(const binary_operator &f) const { - std::set> res; - auto leftSet = this->parse_table_name(f.lhs); - res.insert(leftSet.begin(), leftSet.end()); - auto rightSet = this->parse_table_name(f.rhs); - res.insert(rightSet.begin(), rightSet.end()); - return res; - } - template std::set> parse_table_name(const column_pointer &) const { std::set> res; @@ -10414,177 +10406,12 @@ namespace sqlite_orm { } } - std::set> - parse_table_name(const internal::count_asterisk_without_type &) const { - return {}; - } - template std::set> parse_table_name(const asterisk_t &) const { auto tableName = this->impl.find_table_name(typeid(T)); return {std::make_pair(std::move(tableName), "")}; } - template - std::set> parse_table_name(const conditions::cast_t &c) const { - return this->parse_table_name(c.expression); - } - - template - std::set> - parse_table_name(const simple_case_t &c) const { - std::set> res; - c.case_expression.apply([this, &res](auto &c) { - auto caseExpressionSet = this->parse_table_name(c); - res.insert(caseExpressionSet.begin(), caseExpressionSet.end()); - }); - iterate_tuple(c.args, [this, &res](auto &pair) { - auto leftSet = this->parse_table_name(pair.first); - res.insert(leftSet.begin(), leftSet.end()); - auto rightSet = this->parse_table_name(pair.second); - res.insert(rightSet.begin(), rightSet.end()); - }); - c.else_expression.apply([this, &res](auto &el) { - auto tableNames = this->parse_table_name(el); - res.insert(tableNames.begin(), tableNames.end()); - }); - return res; - } - - template - std::set> - parse_table_name(const conditions::and_condition_t &c) const { - std::set> res; - auto leftTableNames = this->parse_table_name(c.l); - res.insert(leftTableNames.begin(), leftTableNames.end()); - auto rightTableNames = this->parse_table_name(c.r); - res.insert(rightTableNames.begin(), rightTableNames.end()); - return res; - } - - template - std::set> - parse_table_name(const conditions::or_condition_t &c) const { - std::set> res; - auto leftTableNames = this->parse_table_name(c.l); - res.insert(leftTableNames.begin(), leftTableNames.end()); - auto rightTableNames = this->parse_table_name(c.r); - res.insert(rightTableNames.begin(), rightTableNames.end()); - return res; - } - - template - std::set> - parse_table_name(const conditions::is_equal_t &c) const { - std::set> res; - auto leftTableNames = this->parse_table_name(c.l); - res.insert(leftTableNames.begin(), leftTableNames.end()); - auto rightTableNames = this->parse_table_name(c.r); - res.insert(rightTableNames.begin(), rightTableNames.end()); - return res; - } - - template - std::set> - parse_table_name(const conditions::is_not_equal_t &c) const { - std::set> res; - auto leftTableNames = this->parse_table_name(c.l); - res.insert(leftTableNames.begin(), leftTableNames.end()); - auto rightTableNames = this->parse_table_name(c.r); - res.insert(rightTableNames.begin(), rightTableNames.end()); - return res; - } - - template - std::set> - parse_table_name(const conditions::greater_than_t &c) const { - std::set> res; - auto leftTableNames = this->parse_table_name(c.l); - res.insert(leftTableNames.begin(), leftTableNames.end()); - auto rightTableNames = this->parse_table_name(c.r); - res.insert(rightTableNames.begin(), rightTableNames.end()); - return res; - } - - template - std::set> - parse_table_name(const conditions::greater_or_equal_t &c) const { - std::set> res; - auto leftTableNames = this->parse_table_name(c.l); - res.insert(leftTableNames.begin(), leftTableNames.end()); - auto rightTableNames = this->parse_table_name(c.r); - res.insert(rightTableNames.begin(), rightTableNames.end()); - return res; - } - - template - std::set> - parse_table_name(const conditions::lesser_than_t &c) const { - std::set> res; - auto leftTableNames = this->parse_table_name(c.l); - res.insert(leftTableNames.begin(), leftTableNames.end()); - auto rightTableNames = this->parse_table_name(c.r); - res.insert(rightTableNames.begin(), rightTableNames.end()); - return res; - } - - template - std::set> - parse_table_name(const conditions::lesser_or_equal_t &c) const { - std::set> res; - auto leftTableNames = this->parse_table_name(c.l); - res.insert(leftTableNames.begin(), leftTableNames.end()); - auto rightTableNames = this->parse_table_name(c.r); - res.insert(rightTableNames.begin(), rightTableNames.end()); - return res; - } - - template - std::set> parse_table_name(const conditions::like_t &l) const { - std::set> res; - auto argTableNames = this->parse_table_name(l.arg); - res.insert(argTableNames.begin(), argTableNames.end()); - auto patternTableNames = this->parse_table_name(l.pattern); - res.insert(patternTableNames.begin(), patternTableNames.end()); - l.arg3.apply([&res, this](auto &value) { - auto escapeTableNames = this->parse_table_name(value); - res.insert(escapeTableNames.begin(), escapeTableNames.end()); - }); - return res; - } - - template - std::set> parse_table_name(const conditions::glob_t &l) const { - std::set> res; - auto argTableNames = this->parse_table_name(l.arg); - res.insert(argTableNames.begin(), argTableNames.end()); - auto patternTableNames = this->parse_table_name(l.pattern); - res.insert(patternTableNames.begin(), patternTableNames.end()); - return res; - } - - template - std::set> - parse_table_name(const conditions::negated_condition_t &c) const { - return this->parse_table_name(c.c); - } - - template - std::set> parse_table_name(const as_t &a) const { - return this->parse_table_name(a.expression); - } - - template - std::set> - parse_table_name(const internal::columns_t &cols) const { - std::set> res; - iterate_tuple(cols.columns, [&res, this](auto &m) { - auto tableName = this->parse_table_name(m); - res.insert(tableName.begin(), tableName.end()); - }); - return res; - } - template std::string group_concat_internal(F O::*m, std::unique_ptr y, Args &&... args) { this->assert_mapped_type(); From c440fec2183bd12b5915a842fea6836ab5f1785a Mon Sep 17 00:00:00 2001 From: Cyril LEVACHER Date: Fri, 14 Feb 2020 17:08:48 +0100 Subject: [PATCH 025/132] Avoid foreign and/or references to be understand as SQLite command --- dev/statement_serializator.h | 4 ++-- include/sqlite_orm/sqlite_orm.h | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/dev/statement_serializator.h b/dev/statement_serializator.h index 38efd648d..d8a35a8fd 100644 --- a/dev/statement_serializator.h +++ b/dev/statement_serializator.h @@ -160,7 +160,7 @@ namespace sqlite_orm { }); ss << "FOREIGN KEY("; for(size_t i = 0; i < columnNames.size(); ++i) { - ss << columnNames[i]; + ss << "'" << columnNames[i] << "'"; if(i < columnNames.size() - 1) { ss << ", "; } @@ -181,7 +181,7 @@ namespace sqlite_orm { }); ss << "("; for(size_t i = 0; i < referencesNames.size(); ++i) { - ss << referencesNames[i]; + ss << "'" << referencesNames[i] << "'"; if(i < referencesNames.size() - 1) { ss << ", "; } diff --git a/include/sqlite_orm/sqlite_orm.h b/include/sqlite_orm/sqlite_orm.h index 6651950ea..781bbf77f 100644 --- a/include/sqlite_orm/sqlite_orm.h +++ b/include/sqlite_orm/sqlite_orm.h @@ -9055,7 +9055,7 @@ namespace sqlite_orm { }); ss << "FOREIGN KEY("; for(size_t i = 0; i < columnNames.size(); ++i) { - ss << columnNames[i]; + ss << "'" << columnNames[i] << "'"; if(i < columnNames.size() - 1) { ss << ", "; } @@ -9076,7 +9076,7 @@ namespace sqlite_orm { }); ss << "("; for(size_t i = 0; i < referencesNames.size(); ++i) { - ss << referencesNames[i]; + ss << "'" << referencesNames[i] << "'"; if(i < referencesNames.size() - 1) { ss << ", "; } From a1121e49a95390c9c3488cf99c21e87020656fdf Mon Sep 17 00:00:00 2001 From: Cyril LEVACHER Date: Mon, 17 Feb 2020 12:55:44 +0100 Subject: [PATCH 026/132] update tests --- .../foreign_key.cpp | 26 +++++++++---------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/tests/statement_serializator_tests/foreign_key.cpp b/tests/statement_serializator_tests/foreign_key.cpp index a6e4715b4..b32a51ed5 100644 --- a/tests/statement_serializator_tests/foreign_key.cpp +++ b/tests/statement_serializator_tests/foreign_key.cpp @@ -39,7 +39,7 @@ TEST_CASE("statement_serializator foreign key") { context_t context{storageImpl}; auto value = serialize(fk, context); - REQUIRE(value == "FOREIGN KEY(user_id) REFERENCES users(id)"); + REQUIRE(value == "FOREIGN KEY('user_id') REFERENCES users('id')"); } SECTION("on update") { SECTION("no_action") { @@ -59,7 +59,7 @@ TEST_CASE("statement_serializator foreign key") { context_t context{storageImpl}; auto value = serialize(fk, context); - REQUIRE(value == "FOREIGN KEY(user_id) REFERENCES users(id) ON UPDATE NO ACTION"); + REQUIRE(value == "FOREIGN KEY('user_id') REFERENCES users('id') ON UPDATE NO ACTION"); } SECTION("restrict_") { auto fk = foreign_key(&Visit::userId).references(&User::id).on_update.restrict_(); @@ -78,7 +78,7 @@ TEST_CASE("statement_serializator foreign key") { context_t context{storageImpl}; auto value = serialize(fk, context); - REQUIRE(value == "FOREIGN KEY(user_id) REFERENCES users(id) ON UPDATE RESTRICT"); + REQUIRE(value == "FOREIGN KEY('user_id') REFERENCES users('id') ON UPDATE RESTRICT"); } SECTION("set_null") { auto fk = foreign_key(&Visit::userId).references(&User::id).on_update.set_null(); @@ -97,7 +97,7 @@ TEST_CASE("statement_serializator foreign key") { context_t context{storageImpl}; auto value = serialize(fk, context); - REQUIRE(value == "FOREIGN KEY(user_id) REFERENCES users(id) ON UPDATE SET NULL"); + REQUIRE(value == "FOREIGN KEY('user_id') REFERENCES users('id') ON UPDATE SET NULL"); } SECTION("set_default") { auto fk = foreign_key(&Visit::userId).references(&User::id).on_update.set_default(); @@ -116,7 +116,7 @@ TEST_CASE("statement_serializator foreign key") { context_t context{storageImpl}; auto value = serialize(fk, context); - REQUIRE(value == "FOREIGN KEY(user_id) REFERENCES users(id) ON UPDATE SET DEFAULT"); + REQUIRE(value == "FOREIGN KEY('user_id') REFERENCES users('id') ON UPDATE SET DEFAULT"); } SECTION("cascade") { auto fk = foreign_key(&Visit::userId).references(&User::id).on_update.cascade(); @@ -135,7 +135,7 @@ TEST_CASE("statement_serializator foreign key") { context_t context{storageImpl}; auto value = serialize(fk, context); - REQUIRE(value == "FOREIGN KEY(user_id) REFERENCES users(id) ON UPDATE CASCADE"); + REQUIRE(value == "FOREIGN KEY('user_id') REFERENCES users('id') ON UPDATE CASCADE"); } } SECTION("on delete") { @@ -156,7 +156,7 @@ TEST_CASE("statement_serializator foreign key") { context_t context{storageImpl}; auto value = serialize(fk, context); - REQUIRE(value == "FOREIGN KEY(user_id) REFERENCES users(id) ON DELETE NO ACTION"); + REQUIRE(value == "FOREIGN KEY('user_id') REFERENCES users('id') ON DELETE NO ACTION"); } SECTION("restrict_") { auto fk = foreign_key(&Visit::userId).references(&User::id).on_delete.restrict_(); @@ -175,7 +175,7 @@ TEST_CASE("statement_serializator foreign key") { context_t context{storageImpl}; auto value = serialize(fk, context); - REQUIRE(value == "FOREIGN KEY(user_id) REFERENCES users(id) ON DELETE RESTRICT"); + REQUIRE(value == "FOREIGN KEY('user_id') REFERENCES users('id') ON DELETE RESTRICT"); } SECTION("set_null") { auto fk = foreign_key(&Visit::userId).references(&User::id).on_delete.set_null(); @@ -194,7 +194,7 @@ TEST_CASE("statement_serializator foreign key") { context_t context{storageImpl}; auto value = serialize(fk, context); - REQUIRE(value == "FOREIGN KEY(user_id) REFERENCES users(id) ON DELETE SET NULL"); + REQUIRE(value == "FOREIGN KEY('user_id') REFERENCES users('id') ON DELETE SET NULL"); } SECTION("set_default") { auto fk = foreign_key(&Visit::userId).references(&User::id).on_delete.set_default(); @@ -213,7 +213,7 @@ TEST_CASE("statement_serializator foreign key") { context_t context{storageImpl}; auto value = serialize(fk, context); - REQUIRE(value == "FOREIGN KEY(user_id) REFERENCES users(id) ON DELETE SET DEFAULT"); + REQUIRE(value == "FOREIGN KEY('user_id') REFERENCES users('id') ON DELETE SET DEFAULT"); } SECTION("cascade") { auto fk = foreign_key(&Visit::userId).references(&User::id).on_delete.cascade(); @@ -232,7 +232,7 @@ TEST_CASE("statement_serializator foreign key") { context_t context{storageImpl}; auto value = serialize(fk, context); - REQUIRE(value == "FOREIGN KEY(user_id) REFERENCES users(id) ON DELETE CASCADE"); + REQUIRE(value == "FOREIGN KEY('user_id') REFERENCES users('id') ON DELETE CASCADE"); } } } @@ -271,7 +271,7 @@ TEST_CASE("statement_serializator foreign key") { context_t context{storageImpl}; auto value = serialize(fk, context); - REQUIRE(value == "FOREIGN KEY(user_id) REFERENCES users(id)"); + REQUIRE(value == "FOREIGN KEY('user_id') REFERENCES users('id')"); } SECTION("composite key") { struct User { @@ -306,7 +306,7 @@ TEST_CASE("statement_serializator foreign key") { context_t context{storageImpl}; auto value = serialize(fk, context); - REQUIRE(value == "FOREIGN KEY(user_id, user_first_name) REFERENCES users(id, first_name)"); + REQUIRE(value == "FOREIGN KEY('user_id', 'user_first_name') REFERENCES users('id', 'first_name')"); } } From 161475f103760b53a30a5382134382746bb3c63b Mon Sep 17 00:00:00 2001 From: fnc12 Date: Tue, 18 Feb 2020 19:15:56 +0300 Subject: [PATCH 027/132] refactored parsing table names in raw select --- dev/storage.h | 109 ++++---- dev/table_name_collector.h | 68 +++++ include/sqlite_orm/sqlite_orm.h | 249 +++++++++++++----- tests/CMakeLists.txt | 2 +- .../unique_cases/get_all_with_two_tables.cpp | 52 ++++ 5 files changed, 342 insertions(+), 138 deletions(-) create mode 100644 dev/table_name_collector.h create mode 100644 tests/unique_cases/get_all_with_two_tables.cpp diff --git a/dev/storage.h b/dev/storage.h index fd7b04937..d17d442d3 100644 --- a/dev/storage.h +++ b/dev/storage.h @@ -12,7 +12,6 @@ #include // std::vector #include // std::tuple_size, std::tuple, std::make_tuple #include // std::forward, std::pair -#include // std::set #include // std::find #ifdef SQLITE_ORM_OPTIONAL_SUPPORTED @@ -47,6 +46,7 @@ #include "prepared_statement.h" #include "expression_object_type.h" #include "statement_serializator.h" +#include "table_name_collector.h" namespace sqlite_orm { @@ -387,24 +387,24 @@ namespace sqlite_orm { } ss << " "; } - std::set> tableNamesSet; - iterate_ast(sel.col, [this, &tableNamesSet](auto &node) { - auto tableNames = this->parse_table_name(node); - tableNamesSet.insert(tableNames.begin(), tableNames.end()); - }); - internal::join_iterator()([&tableNamesSet, this](const auto &c) { + table_name_collector collector{[this](std::type_index ti) { + return this->impl.find_table_name(ti); + }}; + iterate_ast(sel.col, collector); + iterate_ast(sel.conditions, collector); + internal::join_iterator()([&collector, this](const auto &c) { using original_join_type = typename std::decay::type::join_type::type; using cross_join_type = typename internal::mapped_type_proxy::type; auto crossJoinedTableName = this->impl.find_table_name(typeid(cross_join_type)); auto tableAliasString = alias_extractor::get(); std::pair tableNameWithAlias(std::move(crossJoinedTableName), std::move(tableAliasString)); - tableNamesSet.erase(tableNameWithAlias); + collector.table_names.erase(tableNameWithAlias); }); - if(!tableNamesSet.empty()) { + if(!collector.table_names.empty()) { ss << "FROM "; - std::vector> tableNames(tableNamesSet.begin(), - tableNamesSet.end()); + std::vector> tableNames(collector.table_names.begin(), + collector.table_names.end()); for(size_t i = 0; i < tableNames.size(); ++i) { auto &tableNamePair = tableNames[i]; ss << "'" << tableNamePair.first << "' "; @@ -430,11 +430,17 @@ namespace sqlite_orm { // Common code for statements returning the whole content of a table: get_all_t, get_all_pointer_t, // get_all_optional_t. - template - std::stringstream string_from_expression_impl_get_all(bool /*noTableName*/) const { + template + std::stringstream string_from_expression_impl_get_all(const T &get_query, bool /*noTableName*/) const { + using primary_type = typename T::type; + + table_name_collector collector; + collector.table_names.insert( + std::make_pair(this->impl.find_table_name(typeid(primary_type)), std::string{})); + iterate_ast(get_query.conditions, collector); std::stringstream ss; ss << "SELECT "; - auto &impl = this->get_impl(); + auto &impl = this->get_impl(); auto columnNames = impl.table.column_names(); for(size_t i = 0; i < columnNames.size(); ++i) { ss << "\"" << impl.table.name << "\"." @@ -445,20 +451,34 @@ namespace sqlite_orm { ss << " "; } } - ss << "FROM '" << impl.table.name << "' "; + // ss << "FROM '" << impl.table.name << "' "; + ss << "FROM "; + std::vector> tableNames(collector.table_names.begin(), + collector.table_names.end()); + for(size_t i = 0; i < tableNames.size(); ++i) { + auto &tableNamePair = tableNames[i]; + ss << "'" << tableNamePair.first << "' "; + if(!tableNamePair.second.empty()) { + ss << tableNamePair.second << " "; + } + if(int(i) < int(tableNames.size()) - 1) { + ss << ","; + } + ss << " "; + } return ss; } template std::string string_from_expression(const get_all_t &get, bool noTableName) const { - std::stringstream ss = this->string_from_expression_impl_get_all(noTableName); + std::stringstream ss = this->string_from_expression_impl_get_all(get, noTableName); this->process_conditions(ss, get.conditions); return ss.str(); } template std::string string_from_expression(const get_all_pointer_t &get, bool noTableName) const { - std::stringstream ss = this->string_from_expression_impl_get_all(noTableName); + std::stringstream ss = this->string_from_expression_impl_get_all(get, noTableName); this->process_conditions(ss, get.conditions); return ss.str(); } @@ -466,7 +486,7 @@ namespace sqlite_orm { #ifdef SQLITE_ORM_OPTIONAL_SUPPORTED template std::string string_from_expression(const get_all_optional_t &get, bool noTableName) const { - std::stringstream ss = this->string_from_expression_impl_get_all(noTableName); + std::stringstream ss = this->string_from_expression_impl_get_all(get, noTableName); this->process_conditions(ss, get.conditions); return ss.str(); } @@ -477,14 +497,13 @@ namespace sqlite_orm { bool /*noTableName*/) const { std::stringstream ss; ss << "UPDATE "; - std::set> tableNamesSet; - iterate_tuple(upd.set.assigns, [this, &tableNamesSet](auto &asgn) { - auto tableName = this->parse_table_name(asgn.lhs); - tableNamesSet.insert(tableName.begin(), tableName.end()); - }); - if(!tableNamesSet.empty()) { - if(tableNamesSet.size() == 1) { - ss << " '" << tableNamesSet.begin()->first << "' "; + table_name_collector collector{[this](std::type_index ti) { + return this->impl.find_table_name(ti); + }}; + iterate_ast(upd.set.assigns, collector); + if(!collector.table_names.empty()) { + if(collector.table_names.size() == 1) { + ss << " '" << collector.table_names.begin()->first << "' "; ss << static_cast(upd.set) << " "; std::vector setPairs; iterate_tuple(upd.set.assigns, [this, &setPairs](auto &asgn) { @@ -1208,44 +1227,6 @@ namespace sqlite_orm { } protected: - template - std::set> parse_table_name(const T &) const { - return {}; - } - - template - std::set> parse_table_name(F O::*, std::string alias = {}) const { - return {std::make_pair(this->impl.find_table_name(typeid(O)), std::move(alias))}; - } - - template - std::set> parse_table_name(const column_pointer &) const { - std::set> res; - res.insert({this->impl.find_table_name(typeid(T)), ""}); - return res; - } - - template - std::set> parse_table_name(const alias_column_t &a) const { - return this->parse_table_name(a.column, alias_extractor::get()); - } - - template - std::set> parse_table_name(const count_asterisk_t &) const { - auto tableName = this->impl.find_table_name(typeid(T)); - if(!tableName.empty()) { - return {std::make_pair(std::move(tableName), "")}; - } else { - return {}; - } - } - - template - std::set> parse_table_name(const asterisk_t &) const { - auto tableName = this->impl.find_table_name(typeid(T)); - return {std::make_pair(std::move(tableName), "")}; - } - template std::string group_concat_internal(F O::*m, std::unique_ptr y, Args &&... args) { this->assert_mapped_type(); diff --git a/dev/table_name_collector.h b/dev/table_name_collector.h new file mode 100644 index 000000000..0c966a0d6 --- /dev/null +++ b/dev/table_name_collector.h @@ -0,0 +1,68 @@ +#pragma once + +#include // std::set +#include // std::string +#include // std::function +#include // std::type_index + +#include "select_constraints.h" +#include "alias.h" +#include "core_functions.h" + +namespace sqlite_orm { + + namespace internal { + + struct table_name_collector { + using table_name_set = std::set>; + using find_table_name_t = std::function; + + find_table_name_t find_table_name; + mutable table_name_set table_names; + + template + table_name_set operator()(const T &t) const { + return {}; + } + + template + void operator()(F O::*, std::string alias = {}) const { + if(this->find_table_name) { + table_names.insert(std::make_pair(this->find_table_name(typeid(O)), move(alias))); + } + } + + template + void operator()(const column_pointer &) const { + if(this->find_table_name) { + table_names.insert({this->find_table_name(typeid(T)), ""}); + } + } + + template + void operator()(const alias_column_t &a) const { + *this(a.column, alias_extractor::get()); + } + + template + void operator()(const count_asterisk_t &) const { + if(this->find_table_name) { + auto tableName = this->find_table_name(typeid(T)); + if(!tableName.empty()) { + table_names.insert(std::make_pair(move(tableName), "")); + } + } + } + + template + void operator()(const asterisk_t &) const { + if(this->find_table_name) { + auto tableName = this->find_table_name(typeid(T)); + table_names.insert(std::make_pair(move(tableName), "")); + } + } + }; + + } + +} diff --git a/include/sqlite_orm/sqlite_orm.h b/include/sqlite_orm/sqlite_orm.h index a479d98b0..cb715a734 100644 --- a/include/sqlite_orm/sqlite_orm.h +++ b/include/sqlite_orm/sqlite_orm.h @@ -27,7 +27,7 @@ __pragma(push_macro("min")) #include #include // std::ostringstream - namespace sqlite_orm { +namespace sqlite_orm { enum class orm_error_code { not_found = 1, @@ -44,6 +44,7 @@ __pragma(push_macro("min")) failed_to_init_a_backup, unknown_member_value, }; + } namespace sqlite_orm { @@ -224,6 +225,7 @@ namespace sqlite_orm { // #include "static_magic.h" + #include // std::false_type, std::true_type, std::integral_constant namespace sqlite_orm { @@ -258,6 +260,7 @@ namespace sqlite_orm { } + namespace sqlite_orm { // got from here http://stackoverflow.com/questions/25958259/how-do-i-find-out-if-a-tuple-contains-a-type @@ -989,6 +992,7 @@ namespace sqlite_orm { // #include "serializator_context.h" + namespace sqlite_orm { namespace internal { @@ -1019,6 +1023,7 @@ namespace sqlite_orm { } + namespace sqlite_orm { namespace internal { @@ -1260,6 +1265,7 @@ namespace sqlite_orm { // #include "getter_traits.h" + namespace sqlite_orm { namespace internal { @@ -1443,6 +1449,7 @@ namespace sqlite_orm { } } + namespace sqlite_orm { namespace internal { @@ -1773,6 +1780,7 @@ namespace sqlite_orm { // #include "optional_container.h" + namespace sqlite_orm { namespace internal { @@ -1805,6 +1813,7 @@ namespace sqlite_orm { } } + namespace sqlite_orm { namespace internal { @@ -3293,6 +3302,7 @@ namespace sqlite_orm { // #include "conditions.h" + namespace sqlite_orm { namespace internal { @@ -3412,6 +3422,7 @@ namespace sqlite_orm { // #include "is_base_of_template.h" + #include // std::true_type, std::false_type, std::declval namespace sqlite_orm { @@ -3449,6 +3460,7 @@ namespace sqlite_orm { } } + namespace sqlite_orm { namespace internal { @@ -4201,6 +4213,7 @@ namespace sqlite_orm { // #include "optional_container.h" + namespace sqlite_orm { namespace internal { @@ -4557,6 +4570,7 @@ namespace sqlite_orm { // #include "column.h" + namespace sqlite_orm { namespace internal { @@ -4663,6 +4677,7 @@ namespace sqlite_orm { // #include "is_std_ptr.h" + namespace sqlite_orm { /** @@ -4690,6 +4705,7 @@ namespace sqlite_orm { }; } + namespace sqlite_orm { /** @@ -4900,6 +4916,7 @@ namespace sqlite_orm { // #include "journal_mode.h" + #include // std::string #include // std::unique_ptr #include // std::array @@ -4960,6 +4977,7 @@ namespace sqlite_orm { // #include "error_code.h" + namespace sqlite_orm { /** @@ -5336,6 +5354,7 @@ namespace sqlite_orm { // #include "alias.h" + namespace sqlite_orm { namespace internal { @@ -5582,6 +5601,7 @@ namespace sqlite_orm { } } + namespace sqlite_orm { namespace internal { @@ -5821,6 +5841,7 @@ namespace sqlite_orm { // #include "column.h" + namespace sqlite_orm { namespace internal { @@ -6120,10 +6141,12 @@ namespace sqlite_orm { // #include "field_value_holder.h" + #include // std::enable_if // #include "column.h" + namespace sqlite_orm { namespace internal { @@ -6146,6 +6169,7 @@ namespace sqlite_orm { } } + namespace sqlite_orm { namespace internal { @@ -6595,7 +6619,6 @@ namespace sqlite_orm { #include // std::vector #include // std::tuple_size, std::tuple, std::make_tuple #include // std::forward, std::pair -#include // std::set #include // std::find #ifdef SQLITE_ORM_OPTIONAL_SUPPORTED @@ -6648,6 +6671,7 @@ namespace sqlite_orm { // #include "view.h" + #include // std::shared_ptr #include // std::string #include // std::forward, std::move @@ -6663,6 +6687,7 @@ namespace sqlite_orm { // #include "iterator.h" + #include // std::shared_ptr, std::unique_ptr, std::make_shared #include #include // std::decay @@ -6678,6 +6703,7 @@ namespace sqlite_orm { // #include "error_code.h" + namespace sqlite_orm { namespace internal { @@ -6806,6 +6832,7 @@ namespace sqlite_orm { // #include "ast_iterator.h" + #include // std::vector #include // std::reference_wrapper @@ -6821,6 +6848,7 @@ namespace sqlite_orm { // #include "prepared_statement.h" + #include #include // std::iterator_traits #include // std::string @@ -6829,12 +6857,14 @@ namespace sqlite_orm { // #include "connection_holder.h" + #include #include // std::string #include // std::system_error // #include "error_code.h" + namespace sqlite_orm { namespace internal { @@ -6909,6 +6939,7 @@ namespace sqlite_orm { // #include "select_constraints.h" + namespace sqlite_orm { namespace internal { @@ -7280,6 +7311,7 @@ namespace sqlite_orm { #endif // SQLITE_ORM_OPTIONAL_SUPPORTED } + namespace sqlite_orm { namespace internal { @@ -7757,6 +7789,7 @@ namespace sqlite_orm { // #include "connection_holder.h" + namespace sqlite_orm { namespace internal { @@ -7815,6 +7848,7 @@ namespace sqlite_orm { // #include "storage_base.h" + #include // std::function, std::bind #include #include // std::string @@ -7829,6 +7863,7 @@ namespace sqlite_orm { // #include "pragma.h" + #include // std::string #include #include // std::function @@ -7842,6 +7877,7 @@ namespace sqlite_orm { // #include "connection_holder.h" + namespace sqlite_orm { namespace internal { @@ -7962,6 +7998,7 @@ namespace sqlite_orm { // #include "limit_accesor.h" + #include #include // std::map #include // std::function @@ -7969,6 +8006,7 @@ namespace sqlite_orm { // #include "connection_holder.h" + namespace sqlite_orm { namespace internal { @@ -8102,10 +8140,12 @@ namespace sqlite_orm { // #include "transaction_guard.h" + #include // std::function // #include "connection_holder.h" + namespace sqlite_orm { namespace internal { @@ -8180,6 +8220,7 @@ namespace sqlite_orm { // #include "backup.h" + #include #include // std::string #include @@ -8188,6 +8229,7 @@ namespace sqlite_orm { // #include "connection_holder.h" + namespace sqlite_orm { namespace internal { @@ -8253,6 +8295,7 @@ namespace sqlite_orm { } } + namespace sqlite_orm { namespace internal { @@ -8788,11 +8831,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 { @@ -8912,6 +8957,7 @@ namespace sqlite_orm { // #include "statement_serializator.h" + #include // std::stringstream #include // std::string #include // std::is_arithmetic, std::enable_if @@ -8926,6 +8972,7 @@ namespace sqlite_orm { // #include "column.h" + namespace sqlite_orm { namespace internal { @@ -9213,6 +9260,80 @@ namespace sqlite_orm { } } +// #include "table_name_collector.h" + + +#include // std::set +#include // std::string +#include // std::function +#include // std::type_index + +// #include "select_constraints.h" + +// #include "alias.h" + +// #include "core_functions.h" + + +namespace sqlite_orm { + + namespace internal { + + struct table_name_collector { + using table_name_set = std::set>; + using find_table_name_t = std::function; + + find_table_name_t find_table_name; + mutable table_name_set table_names; + + template + table_name_set operator()(const T &t) const { + return {}; + } + + template + void operator()(F O::*, std::string alias = {}) const { + if(this->find_table_name) { + table_names.insert(std::make_pair(this->find_table_name(typeid(O)), move(alias))); + } + } + + template + void operator()(const column_pointer &) const { + if(this->find_table_name) { + table_names.insert({this->find_table_name(typeid(T)), ""}); + } + } + + template + void operator()(const alias_column_t &a) const { + *this(a.column, alias_extractor::get()); + } + + template + void operator()(const count_asterisk_t &) const { + if(this->find_table_name) { + auto tableName = this->find_table_name(typeid(T)); + if(!tableName.empty()) { + table_names.insert(std::make_pair(move(tableName), "")); + } + } + } + + template + void operator()(const asterisk_t &) const { + if(this->find_table_name) { + auto tableName = this->find_table_name(typeid(T)); + table_names.insert(std::make_pair(move(tableName), "")); + } + } + }; + + } + +} + + namespace sqlite_orm { namespace conditions { @@ -9552,24 +9673,24 @@ namespace sqlite_orm { } ss << " "; } - std::set> tableNamesSet; - iterate_ast(sel.col, [this, &tableNamesSet](auto &node) { - auto tableNames = this->parse_table_name(node); - tableNamesSet.insert(tableNames.begin(), tableNames.end()); - }); - internal::join_iterator()([&tableNamesSet, this](const auto &c) { + table_name_collector collector{[this](std::type_index ti) { + return this->impl.find_table_name(ti); + }}; + iterate_ast(sel.col, collector); + iterate_ast(sel.conditions, collector); + internal::join_iterator()([&collector, this](const auto &c) { using original_join_type = typename std::decay::type::join_type::type; using cross_join_type = typename internal::mapped_type_proxy::type; auto crossJoinedTableName = this->impl.find_table_name(typeid(cross_join_type)); auto tableAliasString = alias_extractor::get(); std::pair tableNameWithAlias(std::move(crossJoinedTableName), std::move(tableAliasString)); - tableNamesSet.erase(tableNameWithAlias); + collector.table_names.erase(tableNameWithAlias); }); - if(!tableNamesSet.empty()) { + if(!collector.table_names.empty()) { ss << "FROM "; - std::vector> tableNames(tableNamesSet.begin(), - tableNamesSet.end()); + std::vector> tableNames(collector.table_names.begin(), + collector.table_names.end()); for(size_t i = 0; i < tableNames.size(); ++i) { auto &tableNamePair = tableNames[i]; ss << "'" << tableNamePair.first << "' "; @@ -9595,11 +9716,17 @@ namespace sqlite_orm { // Common code for statements returning the whole content of a table: get_all_t, get_all_pointer_t, // get_all_optional_t. - template - std::stringstream string_from_expression_impl_get_all(bool /*noTableName*/) const { + template + std::stringstream string_from_expression_impl_get_all(const T &get_query, bool /*noTableName*/) const { + using primary_type = typename T::type; + + table_name_collector collector; + collector.table_names.insert( + std::make_pair(this->impl.find_table_name(typeid(primary_type)), std::string{})); + iterate_ast(get_query.conditions, collector); std::stringstream ss; ss << "SELECT "; - auto &impl = this->get_impl(); + auto &impl = this->get_impl(); auto columnNames = impl.table.column_names(); for(size_t i = 0; i < columnNames.size(); ++i) { ss << "\"" << impl.table.name << "\"." @@ -9610,20 +9737,34 @@ namespace sqlite_orm { ss << " "; } } - ss << "FROM '" << impl.table.name << "' "; + // ss << "FROM '" << impl.table.name << "' "; + ss << "FROM "; + std::vector> tableNames(collector.table_names.begin(), + collector.table_names.end()); + for(size_t i = 0; i < tableNames.size(); ++i) { + auto &tableNamePair = tableNames[i]; + ss << "'" << tableNamePair.first << "' "; + if(!tableNamePair.second.empty()) { + ss << tableNamePair.second << " "; + } + if(int(i) < int(tableNames.size()) - 1) { + ss << ","; + } + ss << " "; + } return ss; } template std::string string_from_expression(const get_all_t &get, bool noTableName) const { - std::stringstream ss = this->string_from_expression_impl_get_all(noTableName); + std::stringstream ss = this->string_from_expression_impl_get_all(get, noTableName); this->process_conditions(ss, get.conditions); return ss.str(); } template std::string string_from_expression(const get_all_pointer_t &get, bool noTableName) const { - std::stringstream ss = this->string_from_expression_impl_get_all(noTableName); + std::stringstream ss = this->string_from_expression_impl_get_all(get, noTableName); this->process_conditions(ss, get.conditions); return ss.str(); } @@ -9631,7 +9772,7 @@ namespace sqlite_orm { #ifdef SQLITE_ORM_OPTIONAL_SUPPORTED template std::string string_from_expression(const get_all_optional_t &get, bool noTableName) const { - std::stringstream ss = this->string_from_expression_impl_get_all(noTableName); + std::stringstream ss = this->string_from_expression_impl_get_all(get, noTableName); this->process_conditions(ss, get.conditions); return ss.str(); } @@ -9642,14 +9783,13 @@ namespace sqlite_orm { bool /*noTableName*/) const { std::stringstream ss; ss << "UPDATE "; - std::set> tableNamesSet; - iterate_tuple(upd.set.assigns, [this, &tableNamesSet](auto &asgn) { - auto tableName = this->parse_table_name(asgn.lhs); - tableNamesSet.insert(tableName.begin(), tableName.end()); - }); - if(!tableNamesSet.empty()) { - if(tableNamesSet.size() == 1) { - ss << " '" << tableNamesSet.begin()->first << "' "; + table_name_collector collector{[this](std::type_index ti) { + return this->impl.find_table_name(ti); + }}; + iterate_ast(upd.set.assigns, collector); + if(!collector.table_names.empty()) { + if(collector.table_names.size() == 1) { + ss << " '" << collector.table_names.begin()->first << "' "; ss << static_cast(upd.set) << " "; std::vector setPairs; iterate_tuple(upd.set.assigns, [this, &setPairs](auto &asgn) { @@ -10373,45 +10513,6 @@ namespace sqlite_orm { } protected: - template - std::set> parse_table_name(const T &) const { - return {}; - } - - template - std::set> parse_table_name(F O::*, std::string alias = {}) const { - return {std::make_pair(this->impl.find_table_name(typeid(O)), std::move(alias))}; - } - - template - std::set> parse_table_name(const column_pointer &) const { - std::set> res; - res.insert({this->impl.find_table_name(typeid(T)), ""}); - return res; - } - - template - std::set> parse_table_name(const alias_column_t &a) const { - return this->parse_table_name(a.column, alias_extractor::get()); - } - - template - std::set> - parse_table_name(const internal::count_asterisk_t &) const { - auto tableName = this->impl.find_table_name(typeid(T)); - if(!tableName.empty()) { - return {std::make_pair(std::move(tableName), "")}; - } else { - return {}; - } - } - - template - std::set> parse_table_name(const asterisk_t &) const { - auto tableName = this->impl.find_table_name(typeid(T)); - return {std::make_pair(std::move(tableName), "")}; - } - template std::string group_concat_internal(F O::*m, std::unique_ptr y, Args &&... args) { this->assert_mapped_type(); @@ -11817,19 +11918,20 @@ __pragma(pop_macro("min")) #include // std::pair #include // std::reference_wrapper - // #include "conditions.h" +// #include "conditions.h" - // #include "operators.h" +// #include "operators.h" + +// #include "select_constraints.h" - // #include "select_constraints.h" +// #include "prepared_statement.h" - // #include "prepared_statement.h" +// #include "optional_container.h" - // #include "optional_container.h" +// #include "core_functions.h" - // #include "core_functions.h" - namespace sqlite_orm { +namespace sqlite_orm { namespace internal { @@ -12111,6 +12213,7 @@ __pragma(pop_macro("min")) // #include "expression_object_type.h" + namespace sqlite_orm { template diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 17c01152e..73f69dcbc 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -10,7 +10,7 @@ else() add_subdirectory(third_party/sqlite) endif() -add_executable(unit_tests tests.cpp tests2.cpp tests3.cpp tests4.cpp tests4.cpp private_getters_tests.cpp pragma_tests.cpp explicit_columns.cpp core_functions_tests.cpp composite_key.cpp static_tests.cpp operators/arithmetic_operators.cpp operators/like.cpp operators/glob.cpp operators/in.cpp operators/cast.cpp operators/is_null.cpp dynamic_order_by.cpp prepared_statement_tests/select.cpp prepared_statement_tests/get_all.cpp prepared_statement_tests/get_all_pointer.cpp prepared_statement_tests/get_all_optional.cpp prepared_statement_tests/update_all.cpp prepared_statement_tests/remove_all.cpp prepared_statement_tests/get.cpp prepared_statement_tests/get_pointer.cpp prepared_statement_tests/get_optional.cpp prepared_statement_tests/update.cpp prepared_statement_tests/remove.cpp prepared_statement_tests/insert.cpp prepared_statement_tests/replace.cpp prepared_statement_tests/insert_range.cpp prepared_statement_tests/replace_range.cpp prepared_statement_tests/insert_explicit.cpp pragma_tests.cpp simple_query.cpp static_tests/is_bindable.cpp static_tests/arithmetic_operators_result_type.cpp static_tests/tuple_conc.cpp static_tests/node_tuple.cpp static_tests/bindable_filter.cpp static_tests/count_tuple.cpp static_tests/member_traits_tests.cpp constraints/default.cpp constraints/foreign_key.cpp constraints/check.cpp table_tests.cpp statement_serializator_tests/primary_key.cpp statement_serializator_tests/column_names.cpp statement_serializator_tests/autoincrement.cpp statement_serializator_tests/arithmetic_operators.cpp statement_serializator_tests/core_functions.cpp statement_serializator_tests/comparison_operators.cpp statement_serializator_tests/unique.cpp statement_serializator_tests/foreign_key.cpp statement_serializator_tests/collate.cpp statement_serializator_tests/check.cpp) +add_executable(unit_tests tests.cpp tests2.cpp tests3.cpp tests4.cpp tests4.cpp private_getters_tests.cpp pragma_tests.cpp explicit_columns.cpp core_functions_tests.cpp composite_key.cpp static_tests.cpp operators/arithmetic_operators.cpp operators/like.cpp operators/glob.cpp operators/in.cpp operators/cast.cpp operators/is_null.cpp dynamic_order_by.cpp prepared_statement_tests/select.cpp prepared_statement_tests/get_all.cpp prepared_statement_tests/get_all_pointer.cpp prepared_statement_tests/get_all_optional.cpp prepared_statement_tests/update_all.cpp prepared_statement_tests/remove_all.cpp prepared_statement_tests/get.cpp prepared_statement_tests/get_pointer.cpp prepared_statement_tests/get_optional.cpp prepared_statement_tests/update.cpp prepared_statement_tests/remove.cpp prepared_statement_tests/insert.cpp prepared_statement_tests/replace.cpp prepared_statement_tests/insert_range.cpp prepared_statement_tests/replace_range.cpp prepared_statement_tests/insert_explicit.cpp pragma_tests.cpp simple_query.cpp static_tests/is_bindable.cpp static_tests/arithmetic_operators_result_type.cpp static_tests/tuple_conc.cpp static_tests/node_tuple.cpp static_tests/bindable_filter.cpp static_tests/count_tuple.cpp static_tests/member_traits_tests.cpp constraints/default.cpp constraints/foreign_key.cpp constraints/check.cpp table_tests.cpp statement_serializator_tests/primary_key.cpp statement_serializator_tests/column_names.cpp statement_serializator_tests/autoincrement.cpp statement_serializator_tests/arithmetic_operators.cpp statement_serializator_tests/core_functions.cpp statement_serializator_tests/comparison_operators.cpp statement_serializator_tests/unique.cpp statement_serializator_tests/foreign_key.cpp statement_serializator_tests/collate.cpp statement_serializator_tests/check.cpp unique_cases/get_all_with_two_tables.cpp) if(SQLITE_ORM_OMITS_CODECVT) diff --git a/tests/unique_cases/get_all_with_two_tables.cpp b/tests/unique_cases/get_all_with_two_tables.cpp new file mode 100644 index 000000000..cd15c9252 --- /dev/null +++ b/tests/unique_cases/get_all_with_two_tables.cpp @@ -0,0 +1,52 @@ +#include +#include + +using namespace sqlite_orm; + +namespace GetAllWithTwoTablesInternal { + struct Pattern { + std::string value; + }; + struct Item { + int id = 0; + std::string attributes; + }; + + inline bool operator==(const Item &lhs, const Item &rhs) { + return lhs.id == rhs.id && lhs.attributes == rhs.attributes; + } +} + +TEST_CASE("get_all with two tables") { + using Catch::Matchers::UnorderedEquals; + using namespace GetAllWithTwoTablesInternal; + + auto storage = make_storage( + {}, + make_table("patterns", make_column("pattern", &Pattern::value)), + make_table("items", make_column("id", &Item::id, primary_key()), make_column("attributes", &Item::attributes))); + storage.sync_schema(); + + const Item item1{1, "one"}; + const Item item2{2, "two"}; + const Item item3{3, "three"}; + storage.replace(item1); + storage.replace(item2); + storage.replace(item3); + + std::vector patterns; + patterns.push_back({"n"}); + patterns.push_back({"w"}); + + storage.begin_transaction(); + storage.insert_range(patterns.begin(), patterns.end()); + { + auto rows = storage.select(&Item::id, where(like(&Item::attributes, conc(conc("%", &Pattern::value), "%")))); + REQUIRE_THAT(rows, UnorderedEquals({1, 2})); + } + auto items = storage.get_all( + where(in(&Item::id, select(&Item::id, where(like(&Item::attributes, conc(conc("%", &Pattern::value), "%"))))))); + storage.rollback(); + + REQUIRE_THAT(items, UnorderedEquals({item1, item2})); +} From 631eed515a1fd3695bbdf35846e59ac21244d136 Mon Sep 17 00:00:00 2001 From: fnc12 Date: Tue, 18 Feb 2020 19:18:23 +0300 Subject: [PATCH 028/132] format fixed --- include/sqlite_orm/sqlite_orm.h | 69 ++++----------------------------- 1 file changed, 8 insertions(+), 61 deletions(-) diff --git a/include/sqlite_orm/sqlite_orm.h b/include/sqlite_orm/sqlite_orm.h index 315f01fc2..9b16109b6 100644 --- a/include/sqlite_orm/sqlite_orm.h +++ b/include/sqlite_orm/sqlite_orm.h @@ -27,7 +27,7 @@ __pragma(push_macro("min")) #include #include // std::ostringstream -namespace sqlite_orm { + namespace sqlite_orm { enum class orm_error_code { not_found = 1, @@ -44,7 +44,6 @@ namespace sqlite_orm { failed_to_init_a_backup, unknown_member_value, }; - } namespace sqlite_orm { @@ -225,7 +224,6 @@ namespace sqlite_orm { // #include "static_magic.h" - #include // std::false_type, std::true_type, std::integral_constant namespace sqlite_orm { @@ -260,7 +258,6 @@ namespace sqlite_orm { } - namespace sqlite_orm { // got from here http://stackoverflow.com/questions/25958259/how-do-i-find-out-if-a-tuple-contains-a-type @@ -992,7 +989,6 @@ namespace sqlite_orm { // #include "serializator_context.h" - namespace sqlite_orm { namespace internal { @@ -1023,7 +1019,6 @@ namespace sqlite_orm { } - namespace sqlite_orm { namespace internal { @@ -1265,7 +1260,6 @@ namespace sqlite_orm { // #include "getter_traits.h" - namespace sqlite_orm { namespace internal { @@ -1449,7 +1443,6 @@ namespace sqlite_orm { } } - namespace sqlite_orm { namespace internal { @@ -1780,7 +1773,6 @@ namespace sqlite_orm { // #include "optional_container.h" - namespace sqlite_orm { namespace internal { @@ -1813,7 +1805,6 @@ namespace sqlite_orm { } } - namespace sqlite_orm { namespace internal { @@ -3302,7 +3293,6 @@ namespace sqlite_orm { // #include "conditions.h" - namespace sqlite_orm { namespace internal { @@ -3422,7 +3412,6 @@ namespace sqlite_orm { // #include "is_base_of_template.h" - #include // std::true_type, std::false_type, std::declval namespace sqlite_orm { @@ -3460,7 +3449,6 @@ namespace sqlite_orm { } } - namespace sqlite_orm { namespace internal { @@ -4213,7 +4201,6 @@ namespace sqlite_orm { // #include "optional_container.h" - namespace sqlite_orm { namespace internal { @@ -4570,7 +4557,6 @@ namespace sqlite_orm { // #include "column.h" - namespace sqlite_orm { namespace internal { @@ -4677,7 +4663,6 @@ namespace sqlite_orm { // #include "is_std_ptr.h" - namespace sqlite_orm { /** @@ -4705,7 +4690,6 @@ namespace sqlite_orm { }; } - namespace sqlite_orm { /** @@ -4916,7 +4900,6 @@ namespace sqlite_orm { // #include "journal_mode.h" - #include // std::string #include // std::unique_ptr #include // std::array @@ -4977,7 +4960,6 @@ namespace sqlite_orm { // #include "error_code.h" - namespace sqlite_orm { /** @@ -5354,7 +5336,6 @@ namespace sqlite_orm { // #include "alias.h" - namespace sqlite_orm { namespace internal { @@ -5601,7 +5582,6 @@ namespace sqlite_orm { } } - namespace sqlite_orm { namespace internal { @@ -5841,7 +5821,6 @@ namespace sqlite_orm { // #include "column.h" - namespace sqlite_orm { namespace internal { @@ -6141,12 +6120,10 @@ namespace sqlite_orm { // #include "field_value_holder.h" - #include // std::enable_if // #include "column.h" - namespace sqlite_orm { namespace internal { @@ -6169,7 +6146,6 @@ namespace sqlite_orm { } } - namespace sqlite_orm { namespace internal { @@ -6671,7 +6647,6 @@ namespace sqlite_orm { // #include "view.h" - #include // std::shared_ptr #include // std::string #include // std::forward, std::move @@ -6687,7 +6662,6 @@ namespace sqlite_orm { // #include "iterator.h" - #include // std::shared_ptr, std::unique_ptr, std::make_shared #include #include // std::decay @@ -6703,7 +6677,6 @@ namespace sqlite_orm { // #include "error_code.h" - namespace sqlite_orm { namespace internal { @@ -6832,7 +6805,6 @@ namespace sqlite_orm { // #include "ast_iterator.h" - #include // std::vector #include // std::reference_wrapper @@ -6848,7 +6820,6 @@ namespace sqlite_orm { // #include "prepared_statement.h" - #include #include // std::iterator_traits #include // std::string @@ -6857,14 +6828,12 @@ namespace sqlite_orm { // #include "connection_holder.h" - #include #include // std::string #include // std::system_error // #include "error_code.h" - namespace sqlite_orm { namespace internal { @@ -6939,7 +6908,6 @@ namespace sqlite_orm { // #include "select_constraints.h" - namespace sqlite_orm { namespace internal { @@ -7311,7 +7279,6 @@ namespace sqlite_orm { #endif // SQLITE_ORM_OPTIONAL_SUPPORTED } - namespace sqlite_orm { namespace internal { @@ -7789,7 +7756,6 @@ namespace sqlite_orm { // #include "connection_holder.h" - namespace sqlite_orm { namespace internal { @@ -7848,7 +7814,6 @@ namespace sqlite_orm { // #include "storage_base.h" - #include // std::function, std::bind #include #include // std::string @@ -7863,7 +7828,6 @@ namespace sqlite_orm { // #include "pragma.h" - #include // std::string #include #include // std::function @@ -7877,7 +7841,6 @@ namespace sqlite_orm { // #include "connection_holder.h" - namespace sqlite_orm { namespace internal { @@ -7998,7 +7961,6 @@ namespace sqlite_orm { // #include "limit_accesor.h" - #include #include // std::map #include // std::function @@ -8006,7 +7968,6 @@ namespace sqlite_orm { // #include "connection_holder.h" - namespace sqlite_orm { namespace internal { @@ -8140,12 +8101,10 @@ namespace sqlite_orm { // #include "transaction_guard.h" - #include // std::function // #include "connection_holder.h" - namespace sqlite_orm { namespace internal { @@ -8220,7 +8179,6 @@ namespace sqlite_orm { // #include "backup.h" - #include #include // std::string #include @@ -8229,7 +8187,6 @@ namespace sqlite_orm { // #include "connection_holder.h" - namespace sqlite_orm { namespace internal { @@ -8295,7 +8252,6 @@ namespace sqlite_orm { } } - namespace sqlite_orm { namespace internal { @@ -8831,13 +8787,11 @@ namespace sqlite_orm { // #include "expression_object_type.h" - #include // std::decay #include // std::reference_wrapper // #include "prepared_statement.h" - namespace sqlite_orm { namespace internal { @@ -8957,7 +8911,6 @@ namespace sqlite_orm { // #include "statement_serializator.h" - #include // std::stringstream #include // std::string #include // std::is_arithmetic, std::enable_if @@ -8972,7 +8925,6 @@ namespace sqlite_orm { // #include "column.h" - namespace sqlite_orm { namespace internal { @@ -9262,7 +9214,6 @@ namespace sqlite_orm { // #include "table_name_collector.h" - #include // std::set #include // std::string #include // std::function @@ -9274,7 +9225,6 @@ namespace sqlite_orm { // #include "core_functions.h" - namespace sqlite_orm { namespace internal { @@ -9333,7 +9283,6 @@ namespace sqlite_orm { } - namespace sqlite_orm { namespace conditions { @@ -11918,20 +11867,19 @@ __pragma(pop_macro("min")) #include // std::pair #include // std::reference_wrapper -// #include "conditions.h" + // #include "conditions.h" -// #include "operators.h" + // #include "operators.h" -// #include "select_constraints.h" + // #include "select_constraints.h" -// #include "prepared_statement.h" + // #include "prepared_statement.h" -// #include "optional_container.h" + // #include "optional_container.h" -// #include "core_functions.h" + // #include "core_functions.h" - -namespace sqlite_orm { + namespace sqlite_orm { namespace internal { @@ -12213,7 +12161,6 @@ namespace sqlite_orm { // #include "expression_object_type.h" - namespace sqlite_orm { template From 67f3375ce2dfd0d4284399d35c16fdd0b9aa52f1 Mon Sep 17 00:00:00 2001 From: fnc12 Date: Tue, 18 Feb 2020 19:21:41 +0300 Subject: [PATCH 029/132] removed a comment --- dev/storage.h | 1 - include/sqlite_orm/sqlite_orm.h | 1 - 2 files changed, 2 deletions(-) diff --git a/dev/storage.h b/dev/storage.h index d17d442d3..8aefb3b74 100644 --- a/dev/storage.h +++ b/dev/storage.h @@ -451,7 +451,6 @@ namespace sqlite_orm { ss << " "; } } - // ss << "FROM '" << impl.table.name << "' "; ss << "FROM "; std::vector> tableNames(collector.table_names.begin(), collector.table_names.end()); diff --git a/include/sqlite_orm/sqlite_orm.h b/include/sqlite_orm/sqlite_orm.h index 9b16109b6..205fed714 100644 --- a/include/sqlite_orm/sqlite_orm.h +++ b/include/sqlite_orm/sqlite_orm.h @@ -9686,7 +9686,6 @@ namespace sqlite_orm { ss << " "; } } - // ss << "FROM '" << impl.table.name << "' "; ss << "FROM "; std::vector> tableNames(collector.table_names.begin(), collector.table_names.end()); From 24359b0c807a3a84285874de315a7f60e8032cf7 Mon Sep 17 00:00:00 2001 From: fnc12 Date: Wed, 19 Feb 2020 08:37:34 +0300 Subject: [PATCH 030/132] fixed alias column --- dev/table_name_collector.h | 2 +- include/sqlite_orm/sqlite_orm.h | 71 ++++++++++++++++++++++++++++----- 2 files changed, 63 insertions(+), 10 deletions(-) diff --git a/dev/table_name_collector.h b/dev/table_name_collector.h index 0c966a0d6..d3106eb32 100644 --- a/dev/table_name_collector.h +++ b/dev/table_name_collector.h @@ -41,7 +41,7 @@ namespace sqlite_orm { template void operator()(const alias_column_t &a) const { - *this(a.column, alias_extractor::get()); + (*this)(a.column, alias_extractor::get()); } template diff --git a/include/sqlite_orm/sqlite_orm.h b/include/sqlite_orm/sqlite_orm.h index 205fed714..46c9ba4b0 100644 --- a/include/sqlite_orm/sqlite_orm.h +++ b/include/sqlite_orm/sqlite_orm.h @@ -27,7 +27,7 @@ __pragma(push_macro("min")) #include #include // std::ostringstream - namespace sqlite_orm { +namespace sqlite_orm { enum class orm_error_code { not_found = 1, @@ -44,6 +44,7 @@ __pragma(push_macro("min")) failed_to_init_a_backup, unknown_member_value, }; + } namespace sqlite_orm { @@ -224,6 +225,7 @@ namespace sqlite_orm { // #include "static_magic.h" + #include // std::false_type, std::true_type, std::integral_constant namespace sqlite_orm { @@ -258,6 +260,7 @@ namespace sqlite_orm { } + namespace sqlite_orm { // got from here http://stackoverflow.com/questions/25958259/how-do-i-find-out-if-a-tuple-contains-a-type @@ -989,6 +992,7 @@ namespace sqlite_orm { // #include "serializator_context.h" + namespace sqlite_orm { namespace internal { @@ -1019,6 +1023,7 @@ namespace sqlite_orm { } + namespace sqlite_orm { namespace internal { @@ -1260,6 +1265,7 @@ namespace sqlite_orm { // #include "getter_traits.h" + namespace sqlite_orm { namespace internal { @@ -1443,6 +1449,7 @@ namespace sqlite_orm { } } + namespace sqlite_orm { namespace internal { @@ -1773,6 +1780,7 @@ namespace sqlite_orm { // #include "optional_container.h" + namespace sqlite_orm { namespace internal { @@ -1805,6 +1813,7 @@ namespace sqlite_orm { } } + namespace sqlite_orm { namespace internal { @@ -3293,6 +3302,7 @@ namespace sqlite_orm { // #include "conditions.h" + namespace sqlite_orm { namespace internal { @@ -3412,6 +3422,7 @@ namespace sqlite_orm { // #include "is_base_of_template.h" + #include // std::true_type, std::false_type, std::declval namespace sqlite_orm { @@ -3449,6 +3460,7 @@ namespace sqlite_orm { } } + namespace sqlite_orm { namespace internal { @@ -4201,6 +4213,7 @@ namespace sqlite_orm { // #include "optional_container.h" + namespace sqlite_orm { namespace internal { @@ -4557,6 +4570,7 @@ namespace sqlite_orm { // #include "column.h" + namespace sqlite_orm { namespace internal { @@ -4663,6 +4677,7 @@ namespace sqlite_orm { // #include "is_std_ptr.h" + namespace sqlite_orm { /** @@ -4690,6 +4705,7 @@ namespace sqlite_orm { }; } + namespace sqlite_orm { /** @@ -4900,6 +4916,7 @@ namespace sqlite_orm { // #include "journal_mode.h" + #include // std::string #include // std::unique_ptr #include // std::array @@ -4960,6 +4977,7 @@ namespace sqlite_orm { // #include "error_code.h" + namespace sqlite_orm { /** @@ -5336,6 +5354,7 @@ namespace sqlite_orm { // #include "alias.h" + namespace sqlite_orm { namespace internal { @@ -5582,6 +5601,7 @@ namespace sqlite_orm { } } + namespace sqlite_orm { namespace internal { @@ -5821,6 +5841,7 @@ namespace sqlite_orm { // #include "column.h" + namespace sqlite_orm { namespace internal { @@ -6120,10 +6141,12 @@ namespace sqlite_orm { // #include "field_value_holder.h" + #include // std::enable_if // #include "column.h" + namespace sqlite_orm { namespace internal { @@ -6146,6 +6169,7 @@ namespace sqlite_orm { } } + namespace sqlite_orm { namespace internal { @@ -6647,6 +6671,7 @@ namespace sqlite_orm { // #include "view.h" + #include // std::shared_ptr #include // std::string #include // std::forward, std::move @@ -6662,6 +6687,7 @@ namespace sqlite_orm { // #include "iterator.h" + #include // std::shared_ptr, std::unique_ptr, std::make_shared #include #include // std::decay @@ -6677,6 +6703,7 @@ namespace sqlite_orm { // #include "error_code.h" + namespace sqlite_orm { namespace internal { @@ -6805,6 +6832,7 @@ namespace sqlite_orm { // #include "ast_iterator.h" + #include // std::vector #include // std::reference_wrapper @@ -6820,6 +6848,7 @@ namespace sqlite_orm { // #include "prepared_statement.h" + #include #include // std::iterator_traits #include // std::string @@ -6828,12 +6857,14 @@ namespace sqlite_orm { // #include "connection_holder.h" + #include #include // std::string #include // std::system_error // #include "error_code.h" + namespace sqlite_orm { namespace internal { @@ -6908,6 +6939,7 @@ namespace sqlite_orm { // #include "select_constraints.h" + namespace sqlite_orm { namespace internal { @@ -7279,6 +7311,7 @@ namespace sqlite_orm { #endif // SQLITE_ORM_OPTIONAL_SUPPORTED } + namespace sqlite_orm { namespace internal { @@ -7756,6 +7789,7 @@ namespace sqlite_orm { // #include "connection_holder.h" + namespace sqlite_orm { namespace internal { @@ -7814,6 +7848,7 @@ namespace sqlite_orm { // #include "storage_base.h" + #include // std::function, std::bind #include #include // std::string @@ -7828,6 +7863,7 @@ namespace sqlite_orm { // #include "pragma.h" + #include // std::string #include #include // std::function @@ -7841,6 +7877,7 @@ namespace sqlite_orm { // #include "connection_holder.h" + namespace sqlite_orm { namespace internal { @@ -7961,6 +7998,7 @@ namespace sqlite_orm { // #include "limit_accesor.h" + #include #include // std::map #include // std::function @@ -7968,6 +8006,7 @@ namespace sqlite_orm { // #include "connection_holder.h" + namespace sqlite_orm { namespace internal { @@ -8101,10 +8140,12 @@ namespace sqlite_orm { // #include "transaction_guard.h" + #include // std::function // #include "connection_holder.h" + namespace sqlite_orm { namespace internal { @@ -8179,6 +8220,7 @@ namespace sqlite_orm { // #include "backup.h" + #include #include // std::string #include @@ -8187,6 +8229,7 @@ namespace sqlite_orm { // #include "connection_holder.h" + namespace sqlite_orm { namespace internal { @@ -8252,6 +8295,7 @@ namespace sqlite_orm { } } + namespace sqlite_orm { namespace internal { @@ -8787,11 +8831,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 { @@ -8911,6 +8957,7 @@ namespace sqlite_orm { // #include "statement_serializator.h" + #include // std::stringstream #include // std::string #include // std::is_arithmetic, std::enable_if @@ -8925,6 +8972,7 @@ namespace sqlite_orm { // #include "column.h" + namespace sqlite_orm { namespace internal { @@ -9214,6 +9262,7 @@ namespace sqlite_orm { // #include "table_name_collector.h" + #include // std::set #include // std::string #include // std::function @@ -9225,6 +9274,7 @@ namespace sqlite_orm { // #include "core_functions.h" + namespace sqlite_orm { namespace internal { @@ -9257,7 +9307,7 @@ namespace sqlite_orm { template void operator()(const alias_column_t &a) const { - *this(a.column, alias_extractor::get()); + (*this)(a.column, alias_extractor::get()); } template @@ -9283,6 +9333,7 @@ namespace sqlite_orm { } + namespace sqlite_orm { namespace conditions { @@ -11866,19 +11917,20 @@ __pragma(pop_macro("min")) #include // std::pair #include // std::reference_wrapper - // #include "conditions.h" +// #include "conditions.h" - // #include "operators.h" +// #include "operators.h" - // #include "select_constraints.h" +// #include "select_constraints.h" - // #include "prepared_statement.h" +// #include "prepared_statement.h" - // #include "optional_container.h" +// #include "optional_container.h" - // #include "core_functions.h" +// #include "core_functions.h" - namespace sqlite_orm { + +namespace sqlite_orm { namespace internal { @@ -12160,6 +12212,7 @@ __pragma(pop_macro("min")) // #include "expression_object_type.h" + namespace sqlite_orm { template From 92d1c087e6ee8dcbe42273ce41cb5bb7d45e8d90 Mon Sep 17 00:00:00 2001 From: fnc12 Date: Thu, 20 Feb 2020 08:45:34 +0300 Subject: [PATCH 031/132] moved not operator test to a dedicted file --- tests/CMakeLists.txt | 2 +- tests/operators/not_operator.cpp | 19 +++++++++++++++++++ tests/tests4.cpp | 15 --------------- 3 files changed, 20 insertions(+), 16 deletions(-) create mode 100644 tests/operators/not_operator.cpp diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 73f69dcbc..a70e0071b 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -10,7 +10,7 @@ else() add_subdirectory(third_party/sqlite) endif() -add_executable(unit_tests tests.cpp tests2.cpp tests3.cpp tests4.cpp tests4.cpp private_getters_tests.cpp pragma_tests.cpp explicit_columns.cpp core_functions_tests.cpp composite_key.cpp static_tests.cpp operators/arithmetic_operators.cpp operators/like.cpp operators/glob.cpp operators/in.cpp operators/cast.cpp operators/is_null.cpp dynamic_order_by.cpp prepared_statement_tests/select.cpp prepared_statement_tests/get_all.cpp prepared_statement_tests/get_all_pointer.cpp prepared_statement_tests/get_all_optional.cpp prepared_statement_tests/update_all.cpp prepared_statement_tests/remove_all.cpp prepared_statement_tests/get.cpp prepared_statement_tests/get_pointer.cpp prepared_statement_tests/get_optional.cpp prepared_statement_tests/update.cpp prepared_statement_tests/remove.cpp prepared_statement_tests/insert.cpp prepared_statement_tests/replace.cpp prepared_statement_tests/insert_range.cpp prepared_statement_tests/replace_range.cpp prepared_statement_tests/insert_explicit.cpp pragma_tests.cpp simple_query.cpp static_tests/is_bindable.cpp static_tests/arithmetic_operators_result_type.cpp static_tests/tuple_conc.cpp static_tests/node_tuple.cpp static_tests/bindable_filter.cpp static_tests/count_tuple.cpp static_tests/member_traits_tests.cpp constraints/default.cpp constraints/foreign_key.cpp constraints/check.cpp table_tests.cpp statement_serializator_tests/primary_key.cpp statement_serializator_tests/column_names.cpp statement_serializator_tests/autoincrement.cpp statement_serializator_tests/arithmetic_operators.cpp statement_serializator_tests/core_functions.cpp statement_serializator_tests/comparison_operators.cpp statement_serializator_tests/unique.cpp statement_serializator_tests/foreign_key.cpp statement_serializator_tests/collate.cpp statement_serializator_tests/check.cpp unique_cases/get_all_with_two_tables.cpp) +add_executable(unit_tests tests.cpp tests2.cpp tests3.cpp tests4.cpp tests4.cpp private_getters_tests.cpp pragma_tests.cpp explicit_columns.cpp core_functions_tests.cpp composite_key.cpp static_tests.cpp operators/arithmetic_operators.cpp operators/like.cpp operators/glob.cpp operators/in.cpp operators/cast.cpp operators/is_null.cpp operators/not_operator.cpp dynamic_order_by.cpp prepared_statement_tests/select.cpp prepared_statement_tests/get_all.cpp prepared_statement_tests/get_all_pointer.cpp prepared_statement_tests/get_all_optional.cpp prepared_statement_tests/update_all.cpp prepared_statement_tests/remove_all.cpp prepared_statement_tests/get.cpp prepared_statement_tests/get_pointer.cpp prepared_statement_tests/get_optional.cpp prepared_statement_tests/update.cpp prepared_statement_tests/remove.cpp prepared_statement_tests/insert.cpp prepared_statement_tests/replace.cpp prepared_statement_tests/insert_range.cpp prepared_statement_tests/replace_range.cpp prepared_statement_tests/insert_explicit.cpp pragma_tests.cpp simple_query.cpp static_tests/is_bindable.cpp static_tests/arithmetic_operators_result_type.cpp static_tests/tuple_conc.cpp static_tests/node_tuple.cpp static_tests/bindable_filter.cpp static_tests/count_tuple.cpp static_tests/member_traits_tests.cpp constraints/default.cpp constraints/foreign_key.cpp constraints/check.cpp table_tests.cpp statement_serializator_tests/primary_key.cpp statement_serializator_tests/column_names.cpp statement_serializator_tests/autoincrement.cpp statement_serializator_tests/arithmetic_operators.cpp statement_serializator_tests/core_functions.cpp statement_serializator_tests/comparison_operators.cpp statement_serializator_tests/unique.cpp statement_serializator_tests/foreign_key.cpp statement_serializator_tests/collate.cpp statement_serializator_tests/check.cpp unique_cases/get_all_with_two_tables.cpp) if(SQLITE_ORM_OMITS_CODECVT) diff --git a/tests/operators/not_operator.cpp b/tests/operators/not_operator.cpp new file mode 100644 index 000000000..889751812 --- /dev/null +++ b/tests/operators/not_operator.cpp @@ -0,0 +1,19 @@ +#include +#include + +using namespace sqlite_orm; + +TEST_CASE("Not operator") { + struct Object { + int id = 0; + }; + + auto storage = make_storage("", make_table("objects", make_column("id", &Object::id, primary_key()))); + storage.sync_schema(); + + storage.replace(Object{2}); + + auto rows = storage.select(&Object::id, where(not is_equal(&Object::id, 1))); + REQUIRE(rows.size() == 1); + REQUIRE(rows.front() == 2); +} diff --git a/tests/tests4.cpp b/tests/tests4.cpp index 998f97438..d6f02d2d3 100644 --- a/tests/tests4.cpp +++ b/tests/tests4.cpp @@ -354,21 +354,6 @@ TEST_CASE("Composite key column names") { } } -TEST_CASE("Not operator") { - struct Object { - int id = 0; - }; - - auto storage = make_storage("", make_table("objects", make_column("id", &Object::id, primary_key()))); - storage.sync_schema(); - - storage.replace(Object{2}); - - auto rows = storage.select(&Object::id, where(not is_equal(&Object::id, 1))); - REQUIRE(rows.size() == 1); - REQUIRE(rows.front() == 2); -} - TEST_CASE("Exists") { struct User { int id = 0; From 519fb72d377859835fc9004b815a8ef6102d295f Mon Sep 17 00:00:00 2001 From: fnc12 Date: Thu, 20 Feb 2020 09:00:40 +0300 Subject: [PATCH 032/132] code format --- include/sqlite_orm/sqlite_orm.h | 69 ++++----------------------------- 1 file changed, 8 insertions(+), 61 deletions(-) diff --git a/include/sqlite_orm/sqlite_orm.h b/include/sqlite_orm/sqlite_orm.h index 46c9ba4b0..fd118a38a 100644 --- a/include/sqlite_orm/sqlite_orm.h +++ b/include/sqlite_orm/sqlite_orm.h @@ -27,7 +27,7 @@ __pragma(push_macro("min")) #include #include // std::ostringstream -namespace sqlite_orm { + namespace sqlite_orm { enum class orm_error_code { not_found = 1, @@ -44,7 +44,6 @@ namespace sqlite_orm { failed_to_init_a_backup, unknown_member_value, }; - } namespace sqlite_orm { @@ -225,7 +224,6 @@ namespace sqlite_orm { // #include "static_magic.h" - #include // std::false_type, std::true_type, std::integral_constant namespace sqlite_orm { @@ -260,7 +258,6 @@ namespace sqlite_orm { } - namespace sqlite_orm { // got from here http://stackoverflow.com/questions/25958259/how-do-i-find-out-if-a-tuple-contains-a-type @@ -992,7 +989,6 @@ namespace sqlite_orm { // #include "serializator_context.h" - namespace sqlite_orm { namespace internal { @@ -1023,7 +1019,6 @@ namespace sqlite_orm { } - namespace sqlite_orm { namespace internal { @@ -1265,7 +1260,6 @@ namespace sqlite_orm { // #include "getter_traits.h" - namespace sqlite_orm { namespace internal { @@ -1449,7 +1443,6 @@ namespace sqlite_orm { } } - namespace sqlite_orm { namespace internal { @@ -1780,7 +1773,6 @@ namespace sqlite_orm { // #include "optional_container.h" - namespace sqlite_orm { namespace internal { @@ -1813,7 +1805,6 @@ namespace sqlite_orm { } } - namespace sqlite_orm { namespace internal { @@ -3302,7 +3293,6 @@ namespace sqlite_orm { // #include "conditions.h" - namespace sqlite_orm { namespace internal { @@ -3422,7 +3412,6 @@ namespace sqlite_orm { // #include "is_base_of_template.h" - #include // std::true_type, std::false_type, std::declval namespace sqlite_orm { @@ -3460,7 +3449,6 @@ namespace sqlite_orm { } } - namespace sqlite_orm { namespace internal { @@ -4213,7 +4201,6 @@ namespace sqlite_orm { // #include "optional_container.h" - namespace sqlite_orm { namespace internal { @@ -4570,7 +4557,6 @@ namespace sqlite_orm { // #include "column.h" - namespace sqlite_orm { namespace internal { @@ -4677,7 +4663,6 @@ namespace sqlite_orm { // #include "is_std_ptr.h" - namespace sqlite_orm { /** @@ -4705,7 +4690,6 @@ namespace sqlite_orm { }; } - namespace sqlite_orm { /** @@ -4916,7 +4900,6 @@ namespace sqlite_orm { // #include "journal_mode.h" - #include // std::string #include // std::unique_ptr #include // std::array @@ -4977,7 +4960,6 @@ namespace sqlite_orm { // #include "error_code.h" - namespace sqlite_orm { /** @@ -5354,7 +5336,6 @@ namespace sqlite_orm { // #include "alias.h" - namespace sqlite_orm { namespace internal { @@ -5601,7 +5582,6 @@ namespace sqlite_orm { } } - namespace sqlite_orm { namespace internal { @@ -5841,7 +5821,6 @@ namespace sqlite_orm { // #include "column.h" - namespace sqlite_orm { namespace internal { @@ -6141,12 +6120,10 @@ namespace sqlite_orm { // #include "field_value_holder.h" - #include // std::enable_if // #include "column.h" - namespace sqlite_orm { namespace internal { @@ -6169,7 +6146,6 @@ namespace sqlite_orm { } } - namespace sqlite_orm { namespace internal { @@ -6671,7 +6647,6 @@ namespace sqlite_orm { // #include "view.h" - #include // std::shared_ptr #include // std::string #include // std::forward, std::move @@ -6687,7 +6662,6 @@ namespace sqlite_orm { // #include "iterator.h" - #include // std::shared_ptr, std::unique_ptr, std::make_shared #include #include // std::decay @@ -6703,7 +6677,6 @@ namespace sqlite_orm { // #include "error_code.h" - namespace sqlite_orm { namespace internal { @@ -6832,7 +6805,6 @@ namespace sqlite_orm { // #include "ast_iterator.h" - #include // std::vector #include // std::reference_wrapper @@ -6848,7 +6820,6 @@ namespace sqlite_orm { // #include "prepared_statement.h" - #include #include // std::iterator_traits #include // std::string @@ -6857,14 +6828,12 @@ namespace sqlite_orm { // #include "connection_holder.h" - #include #include // std::string #include // std::system_error // #include "error_code.h" - namespace sqlite_orm { namespace internal { @@ -6939,7 +6908,6 @@ namespace sqlite_orm { // #include "select_constraints.h" - namespace sqlite_orm { namespace internal { @@ -7311,7 +7279,6 @@ namespace sqlite_orm { #endif // SQLITE_ORM_OPTIONAL_SUPPORTED } - namespace sqlite_orm { namespace internal { @@ -7789,7 +7756,6 @@ namespace sqlite_orm { // #include "connection_holder.h" - namespace sqlite_orm { namespace internal { @@ -7848,7 +7814,6 @@ namespace sqlite_orm { // #include "storage_base.h" - #include // std::function, std::bind #include #include // std::string @@ -7863,7 +7828,6 @@ namespace sqlite_orm { // #include "pragma.h" - #include // std::string #include #include // std::function @@ -7877,7 +7841,6 @@ namespace sqlite_orm { // #include "connection_holder.h" - namespace sqlite_orm { namespace internal { @@ -7998,7 +7961,6 @@ namespace sqlite_orm { // #include "limit_accesor.h" - #include #include // std::map #include // std::function @@ -8006,7 +7968,6 @@ namespace sqlite_orm { // #include "connection_holder.h" - namespace sqlite_orm { namespace internal { @@ -8140,12 +8101,10 @@ namespace sqlite_orm { // #include "transaction_guard.h" - #include // std::function // #include "connection_holder.h" - namespace sqlite_orm { namespace internal { @@ -8220,7 +8179,6 @@ namespace sqlite_orm { // #include "backup.h" - #include #include // std::string #include @@ -8229,7 +8187,6 @@ namespace sqlite_orm { // #include "connection_holder.h" - namespace sqlite_orm { namespace internal { @@ -8295,7 +8252,6 @@ namespace sqlite_orm { } } - namespace sqlite_orm { namespace internal { @@ -8831,13 +8787,11 @@ namespace sqlite_orm { // #include "expression_object_type.h" - #include // std::decay #include // std::reference_wrapper // #include "prepared_statement.h" - namespace sqlite_orm { namespace internal { @@ -8957,7 +8911,6 @@ namespace sqlite_orm { // #include "statement_serializator.h" - #include // std::stringstream #include // std::string #include // std::is_arithmetic, std::enable_if @@ -8972,7 +8925,6 @@ namespace sqlite_orm { // #include "column.h" - namespace sqlite_orm { namespace internal { @@ -9262,7 +9214,6 @@ namespace sqlite_orm { // #include "table_name_collector.h" - #include // std::set #include // std::string #include // std::function @@ -9274,7 +9225,6 @@ namespace sqlite_orm { // #include "core_functions.h" - namespace sqlite_orm { namespace internal { @@ -9333,7 +9283,6 @@ namespace sqlite_orm { } - namespace sqlite_orm { namespace conditions { @@ -11917,20 +11866,19 @@ __pragma(pop_macro("min")) #include // std::pair #include // std::reference_wrapper -// #include "conditions.h" + // #include "conditions.h" -// #include "operators.h" + // #include "operators.h" -// #include "select_constraints.h" + // #include "select_constraints.h" -// #include "prepared_statement.h" + // #include "prepared_statement.h" -// #include "optional_container.h" + // #include "optional_container.h" -// #include "core_functions.h" + // #include "core_functions.h" - -namespace sqlite_orm { + namespace sqlite_orm { namespace internal { @@ -12212,7 +12160,6 @@ namespace sqlite_orm { // #include "expression_object_type.h" - namespace sqlite_orm { template From 4d8cfa07ed50dcd3d13afe0733b7a4022132cc66 Mon Sep 17 00:00:00 2001 From: fnc12 Date: Thu, 20 Feb 2020 19:12:46 +0300 Subject: [PATCH 033/132] removed dup from cmake --- tests/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index a70e0071b..f1aeca35c 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -10,7 +10,7 @@ else() add_subdirectory(third_party/sqlite) endif() -add_executable(unit_tests tests.cpp tests2.cpp tests3.cpp tests4.cpp tests4.cpp private_getters_tests.cpp pragma_tests.cpp explicit_columns.cpp core_functions_tests.cpp composite_key.cpp static_tests.cpp operators/arithmetic_operators.cpp operators/like.cpp operators/glob.cpp operators/in.cpp operators/cast.cpp operators/is_null.cpp operators/not_operator.cpp dynamic_order_by.cpp prepared_statement_tests/select.cpp prepared_statement_tests/get_all.cpp prepared_statement_tests/get_all_pointer.cpp prepared_statement_tests/get_all_optional.cpp prepared_statement_tests/update_all.cpp prepared_statement_tests/remove_all.cpp prepared_statement_tests/get.cpp prepared_statement_tests/get_pointer.cpp prepared_statement_tests/get_optional.cpp prepared_statement_tests/update.cpp prepared_statement_tests/remove.cpp prepared_statement_tests/insert.cpp prepared_statement_tests/replace.cpp prepared_statement_tests/insert_range.cpp prepared_statement_tests/replace_range.cpp prepared_statement_tests/insert_explicit.cpp pragma_tests.cpp simple_query.cpp static_tests/is_bindable.cpp static_tests/arithmetic_operators_result_type.cpp static_tests/tuple_conc.cpp static_tests/node_tuple.cpp static_tests/bindable_filter.cpp static_tests/count_tuple.cpp static_tests/member_traits_tests.cpp constraints/default.cpp constraints/foreign_key.cpp constraints/check.cpp table_tests.cpp statement_serializator_tests/primary_key.cpp statement_serializator_tests/column_names.cpp statement_serializator_tests/autoincrement.cpp statement_serializator_tests/arithmetic_operators.cpp statement_serializator_tests/core_functions.cpp statement_serializator_tests/comparison_operators.cpp statement_serializator_tests/unique.cpp statement_serializator_tests/foreign_key.cpp statement_serializator_tests/collate.cpp statement_serializator_tests/check.cpp unique_cases/get_all_with_two_tables.cpp) +add_executable(unit_tests tests.cpp tests2.cpp tests3.cpp tests4.cpp private_getters_tests.cpp pragma_tests.cpp explicit_columns.cpp core_functions_tests.cpp composite_key.cpp static_tests.cpp operators/arithmetic_operators.cpp operators/like.cpp operators/glob.cpp operators/in.cpp operators/cast.cpp operators/is_null.cpp operators/not_operator.cpp dynamic_order_by.cpp prepared_statement_tests/select.cpp prepared_statement_tests/get_all.cpp prepared_statement_tests/get_all_pointer.cpp prepared_statement_tests/get_all_optional.cpp prepared_statement_tests/update_all.cpp prepared_statement_tests/remove_all.cpp prepared_statement_tests/get.cpp prepared_statement_tests/get_pointer.cpp prepared_statement_tests/get_optional.cpp prepared_statement_tests/update.cpp prepared_statement_tests/remove.cpp prepared_statement_tests/insert.cpp prepared_statement_tests/replace.cpp prepared_statement_tests/insert_range.cpp prepared_statement_tests/replace_range.cpp prepared_statement_tests/insert_explicit.cpp pragma_tests.cpp simple_query.cpp static_tests/is_bindable.cpp static_tests/arithmetic_operators_result_type.cpp static_tests/tuple_conc.cpp static_tests/node_tuple.cpp static_tests/bindable_filter.cpp static_tests/count_tuple.cpp static_tests/member_traits_tests.cpp constraints/default.cpp constraints/foreign_key.cpp constraints/check.cpp table_tests.cpp statement_serializator_tests/primary_key.cpp statement_serializator_tests/column_names.cpp statement_serializator_tests/autoincrement.cpp statement_serializator_tests/arithmetic_operators.cpp statement_serializator_tests/core_functions.cpp statement_serializator_tests/comparison_operators.cpp statement_serializator_tests/unique.cpp statement_serializator_tests/foreign_key.cpp statement_serializator_tests/collate.cpp statement_serializator_tests/check.cpp unique_cases/get_all_with_two_tables.cpp) if(SQLITE_ORM_OMITS_CODECVT) From d29bc7ae166ce9b3f650833a09e5e537d1eb8d39 Mon Sep 17 00:00:00 2001 From: fnc12 Date: Thu, 20 Feb 2020 22:46:55 +0300 Subject: [PATCH 034/132] split tests4 into two files --- include/sqlite_orm/sqlite_orm.h | 69 ++++++- tests/CMakeLists.txt | 2 +- tests/tests4.cpp | 348 -------------------------------- tests/tests5.cpp | 347 +++++++++++++++++++++++++++++++ 4 files changed, 409 insertions(+), 357 deletions(-) create mode 100644 tests/tests5.cpp diff --git a/include/sqlite_orm/sqlite_orm.h b/include/sqlite_orm/sqlite_orm.h index fd118a38a..46c9ba4b0 100644 --- a/include/sqlite_orm/sqlite_orm.h +++ b/include/sqlite_orm/sqlite_orm.h @@ -27,7 +27,7 @@ __pragma(push_macro("min")) #include #include // std::ostringstream - namespace sqlite_orm { +namespace sqlite_orm { enum class orm_error_code { not_found = 1, @@ -44,6 +44,7 @@ __pragma(push_macro("min")) failed_to_init_a_backup, unknown_member_value, }; + } namespace sqlite_orm { @@ -224,6 +225,7 @@ namespace sqlite_orm { // #include "static_magic.h" + #include // std::false_type, std::true_type, std::integral_constant namespace sqlite_orm { @@ -258,6 +260,7 @@ namespace sqlite_orm { } + namespace sqlite_orm { // got from here http://stackoverflow.com/questions/25958259/how-do-i-find-out-if-a-tuple-contains-a-type @@ -989,6 +992,7 @@ namespace sqlite_orm { // #include "serializator_context.h" + namespace sqlite_orm { namespace internal { @@ -1019,6 +1023,7 @@ namespace sqlite_orm { } + namespace sqlite_orm { namespace internal { @@ -1260,6 +1265,7 @@ namespace sqlite_orm { // #include "getter_traits.h" + namespace sqlite_orm { namespace internal { @@ -1443,6 +1449,7 @@ namespace sqlite_orm { } } + namespace sqlite_orm { namespace internal { @@ -1773,6 +1780,7 @@ namespace sqlite_orm { // #include "optional_container.h" + namespace sqlite_orm { namespace internal { @@ -1805,6 +1813,7 @@ namespace sqlite_orm { } } + namespace sqlite_orm { namespace internal { @@ -3293,6 +3302,7 @@ namespace sqlite_orm { // #include "conditions.h" + namespace sqlite_orm { namespace internal { @@ -3412,6 +3422,7 @@ namespace sqlite_orm { // #include "is_base_of_template.h" + #include // std::true_type, std::false_type, std::declval namespace sqlite_orm { @@ -3449,6 +3460,7 @@ namespace sqlite_orm { } } + namespace sqlite_orm { namespace internal { @@ -4201,6 +4213,7 @@ namespace sqlite_orm { // #include "optional_container.h" + namespace sqlite_orm { namespace internal { @@ -4557,6 +4570,7 @@ namespace sqlite_orm { // #include "column.h" + namespace sqlite_orm { namespace internal { @@ -4663,6 +4677,7 @@ namespace sqlite_orm { // #include "is_std_ptr.h" + namespace sqlite_orm { /** @@ -4690,6 +4705,7 @@ namespace sqlite_orm { }; } + namespace sqlite_orm { /** @@ -4900,6 +4916,7 @@ namespace sqlite_orm { // #include "journal_mode.h" + #include // std::string #include // std::unique_ptr #include // std::array @@ -4960,6 +4977,7 @@ namespace sqlite_orm { // #include "error_code.h" + namespace sqlite_orm { /** @@ -5336,6 +5354,7 @@ namespace sqlite_orm { // #include "alias.h" + namespace sqlite_orm { namespace internal { @@ -5582,6 +5601,7 @@ namespace sqlite_orm { } } + namespace sqlite_orm { namespace internal { @@ -5821,6 +5841,7 @@ namespace sqlite_orm { // #include "column.h" + namespace sqlite_orm { namespace internal { @@ -6120,10 +6141,12 @@ namespace sqlite_orm { // #include "field_value_holder.h" + #include // std::enable_if // #include "column.h" + namespace sqlite_orm { namespace internal { @@ -6146,6 +6169,7 @@ namespace sqlite_orm { } } + namespace sqlite_orm { namespace internal { @@ -6647,6 +6671,7 @@ namespace sqlite_orm { // #include "view.h" + #include // std::shared_ptr #include // std::string #include // std::forward, std::move @@ -6662,6 +6687,7 @@ namespace sqlite_orm { // #include "iterator.h" + #include // std::shared_ptr, std::unique_ptr, std::make_shared #include #include // std::decay @@ -6677,6 +6703,7 @@ namespace sqlite_orm { // #include "error_code.h" + namespace sqlite_orm { namespace internal { @@ -6805,6 +6832,7 @@ namespace sqlite_orm { // #include "ast_iterator.h" + #include // std::vector #include // std::reference_wrapper @@ -6820,6 +6848,7 @@ namespace sqlite_orm { // #include "prepared_statement.h" + #include #include // std::iterator_traits #include // std::string @@ -6828,12 +6857,14 @@ namespace sqlite_orm { // #include "connection_holder.h" + #include #include // std::string #include // std::system_error // #include "error_code.h" + namespace sqlite_orm { namespace internal { @@ -6908,6 +6939,7 @@ namespace sqlite_orm { // #include "select_constraints.h" + namespace sqlite_orm { namespace internal { @@ -7279,6 +7311,7 @@ namespace sqlite_orm { #endif // SQLITE_ORM_OPTIONAL_SUPPORTED } + namespace sqlite_orm { namespace internal { @@ -7756,6 +7789,7 @@ namespace sqlite_orm { // #include "connection_holder.h" + namespace sqlite_orm { namespace internal { @@ -7814,6 +7848,7 @@ namespace sqlite_orm { // #include "storage_base.h" + #include // std::function, std::bind #include #include // std::string @@ -7828,6 +7863,7 @@ namespace sqlite_orm { // #include "pragma.h" + #include // std::string #include #include // std::function @@ -7841,6 +7877,7 @@ namespace sqlite_orm { // #include "connection_holder.h" + namespace sqlite_orm { namespace internal { @@ -7961,6 +7998,7 @@ namespace sqlite_orm { // #include "limit_accesor.h" + #include #include // std::map #include // std::function @@ -7968,6 +8006,7 @@ namespace sqlite_orm { // #include "connection_holder.h" + namespace sqlite_orm { namespace internal { @@ -8101,10 +8140,12 @@ namespace sqlite_orm { // #include "transaction_guard.h" + #include // std::function // #include "connection_holder.h" + namespace sqlite_orm { namespace internal { @@ -8179,6 +8220,7 @@ namespace sqlite_orm { // #include "backup.h" + #include #include // std::string #include @@ -8187,6 +8229,7 @@ namespace sqlite_orm { // #include "connection_holder.h" + namespace sqlite_orm { namespace internal { @@ -8252,6 +8295,7 @@ namespace sqlite_orm { } } + namespace sqlite_orm { namespace internal { @@ -8787,11 +8831,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 { @@ -8911,6 +8957,7 @@ namespace sqlite_orm { // #include "statement_serializator.h" + #include // std::stringstream #include // std::string #include // std::is_arithmetic, std::enable_if @@ -8925,6 +8972,7 @@ namespace sqlite_orm { // #include "column.h" + namespace sqlite_orm { namespace internal { @@ -9214,6 +9262,7 @@ namespace sqlite_orm { // #include "table_name_collector.h" + #include // std::set #include // std::string #include // std::function @@ -9225,6 +9274,7 @@ namespace sqlite_orm { // #include "core_functions.h" + namespace sqlite_orm { namespace internal { @@ -9283,6 +9333,7 @@ namespace sqlite_orm { } + namespace sqlite_orm { namespace conditions { @@ -11866,19 +11917,20 @@ __pragma(pop_macro("min")) #include // std::pair #include // std::reference_wrapper - // #include "conditions.h" +// #include "conditions.h" - // #include "operators.h" +// #include "operators.h" - // #include "select_constraints.h" +// #include "select_constraints.h" - // #include "prepared_statement.h" +// #include "prepared_statement.h" - // #include "optional_container.h" +// #include "optional_container.h" - // #include "core_functions.h" +// #include "core_functions.h" - namespace sqlite_orm { + +namespace sqlite_orm { namespace internal { @@ -12160,6 +12212,7 @@ __pragma(pop_macro("min")) // #include "expression_object_type.h" + namespace sqlite_orm { template diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index f1aeca35c..0ff50e9a4 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -10,7 +10,7 @@ else() add_subdirectory(third_party/sqlite) endif() -add_executable(unit_tests tests.cpp tests2.cpp tests3.cpp tests4.cpp private_getters_tests.cpp pragma_tests.cpp explicit_columns.cpp core_functions_tests.cpp composite_key.cpp static_tests.cpp operators/arithmetic_operators.cpp operators/like.cpp operators/glob.cpp operators/in.cpp operators/cast.cpp operators/is_null.cpp operators/not_operator.cpp dynamic_order_by.cpp prepared_statement_tests/select.cpp prepared_statement_tests/get_all.cpp prepared_statement_tests/get_all_pointer.cpp prepared_statement_tests/get_all_optional.cpp prepared_statement_tests/update_all.cpp prepared_statement_tests/remove_all.cpp prepared_statement_tests/get.cpp prepared_statement_tests/get_pointer.cpp prepared_statement_tests/get_optional.cpp prepared_statement_tests/update.cpp prepared_statement_tests/remove.cpp prepared_statement_tests/insert.cpp prepared_statement_tests/replace.cpp prepared_statement_tests/insert_range.cpp prepared_statement_tests/replace_range.cpp prepared_statement_tests/insert_explicit.cpp pragma_tests.cpp simple_query.cpp static_tests/is_bindable.cpp static_tests/arithmetic_operators_result_type.cpp static_tests/tuple_conc.cpp static_tests/node_tuple.cpp static_tests/bindable_filter.cpp static_tests/count_tuple.cpp static_tests/member_traits_tests.cpp constraints/default.cpp constraints/foreign_key.cpp constraints/check.cpp table_tests.cpp statement_serializator_tests/primary_key.cpp statement_serializator_tests/column_names.cpp statement_serializator_tests/autoincrement.cpp statement_serializator_tests/arithmetic_operators.cpp statement_serializator_tests/core_functions.cpp statement_serializator_tests/comparison_operators.cpp statement_serializator_tests/unique.cpp statement_serializator_tests/foreign_key.cpp statement_serializator_tests/collate.cpp statement_serializator_tests/check.cpp unique_cases/get_all_with_two_tables.cpp) +add_executable(unit_tests tests.cpp tests2.cpp tests3.cpp tests4.cpp tests5.cpp private_getters_tests.cpp pragma_tests.cpp explicit_columns.cpp core_functions_tests.cpp composite_key.cpp static_tests.cpp operators/arithmetic_operators.cpp operators/like.cpp operators/glob.cpp operators/in.cpp operators/cast.cpp operators/is_null.cpp operators/not_operator.cpp dynamic_order_by.cpp prepared_statement_tests/select.cpp prepared_statement_tests/get_all.cpp prepared_statement_tests/get_all_pointer.cpp prepared_statement_tests/get_all_optional.cpp prepared_statement_tests/update_all.cpp prepared_statement_tests/remove_all.cpp prepared_statement_tests/get.cpp prepared_statement_tests/get_pointer.cpp prepared_statement_tests/get_optional.cpp prepared_statement_tests/update.cpp prepared_statement_tests/remove.cpp prepared_statement_tests/insert.cpp prepared_statement_tests/replace.cpp prepared_statement_tests/insert_range.cpp prepared_statement_tests/replace_range.cpp prepared_statement_tests/insert_explicit.cpp pragma_tests.cpp simple_query.cpp static_tests/is_bindable.cpp static_tests/arithmetic_operators_result_type.cpp static_tests/tuple_conc.cpp static_tests/node_tuple.cpp static_tests/bindable_filter.cpp static_tests/count_tuple.cpp static_tests/member_traits_tests.cpp constraints/default.cpp constraints/foreign_key.cpp constraints/check.cpp table_tests.cpp statement_serializator_tests/primary_key.cpp statement_serializator_tests/column_names.cpp statement_serializator_tests/autoincrement.cpp statement_serializator_tests/arithmetic_operators.cpp statement_serializator_tests/core_functions.cpp statement_serializator_tests/comparison_operators.cpp statement_serializator_tests/unique.cpp statement_serializator_tests/foreign_key.cpp statement_serializator_tests/collate.cpp statement_serializator_tests/check.cpp unique_cases/get_all_with_two_tables.cpp) if(SQLITE_ORM_OMITS_CODECVT) diff --git a/tests/tests4.cpp b/tests/tests4.cpp index d6f02d2d3..205e5cd9c 100644 --- a/tests/tests4.cpp +++ b/tests/tests4.cpp @@ -2,16 +2,12 @@ #include #include #include // std::count_if -#include #ifdef SQLITE_ORM_OPTIONAL_SUPPORTED #include // std::optional #endif // SQLITE_ORM_OPTIONAL_SUPPORTED using namespace sqlite_orm; -using std::cout; -using std::endl; - TEST_CASE("Case") { struct User { @@ -305,347 +301,3 @@ TEST_CASE("Set null") { REQUIRE(!rows.front().name); } } - -TEST_CASE("Composite key column names") { - - struct User { - int id = 0; - std::string name; - std::string info; - }; - - { - auto table = make_table("t", - make_column("id", &User::id), - make_column("name", &User::name), - make_column("info", &User::info), - primary_key(&User::id, &User::name)); - auto compositeKeyColumnsNames = table.composite_key_columns_names(); - std::vector expected = {"id", "name"}; - REQUIRE(std::equal(compositeKeyColumnsNames.begin(), compositeKeyColumnsNames.end(), expected.begin())); - } - { - auto table = make_table("t", - make_column("id", &User::id), - make_column("name", &User::name), - make_column("info", &User::info), - primary_key(&User::name, &User::id)); - auto compositeKeyColumnsNames = table.composite_key_columns_names(); - std::vector expected = {"name", "id"}; - REQUIRE(std::equal(compositeKeyColumnsNames.begin(), compositeKeyColumnsNames.end(), expected.begin())); - } - { - auto table = make_table("t", - make_column("id", &User::id), - make_column("name", &User::name), - make_column("info", &User::info), - primary_key(&User::name, &User::id, &User::info)); - auto compositeKeyColumnsNames = table.composite_key_columns_names(); - std::vector expected = {"name", "id", "info"}; - REQUIRE(std::equal(compositeKeyColumnsNames.begin(), compositeKeyColumnsNames.end(), expected.begin())); - } - { - auto table = make_table("t", - make_column("id", &User::id), - make_column("name", &User::name), - make_column("info", &User::info)); - auto compositeKeyColumnsNames = table.composite_key_columns_names(); - REQUIRE(compositeKeyColumnsNames.empty()); - } -} - -TEST_CASE("Exists") { - struct User { - int id = 0; - std::string name; - }; - - struct Visit { - int id = 0; - int userId = 0; - time_t time = 0; - }; - - auto storage = - make_storage("", - make_table("users", make_column("id", &User::id, primary_key()), make_column("name", &User::name)), - make_table("visits", - make_column("id", &Visit::id, primary_key()), - make_column("userId", &Visit::userId), - make_column("time", &Visit::time), - foreign_key(&Visit::userId).references(&User::id))); - storage.sync_schema(); - - storage.replace(User{1, "Daddy Yankee"}); - storage.replace(User{2, "Don Omar"}); - - storage.replace(Visit{1, 1, 100000}); - storage.replace(Visit{2, 1, 100001}); - storage.replace(Visit{3, 1, 100002}); - storage.replace(Visit{4, 1, 200000}); - - storage.replace(Visit{5, 2, 100000}); - - auto rows = storage.select( - &User::id, - where(exists(select(&Visit::id, where(c(&Visit::time) == 200000 and eq(&Visit::userId, &User::id)))))); - REQUIRE(!rows.empty() == 1); -} - -TEST_CASE("Iterate blob") { - struct Test { - int64_t id; - std::vector key; - }; - - struct TestComparator { - bool operator()(const Test &lhs, const Test &rhs) const { - return lhs.id == rhs.id && lhs.key == rhs.key; - } - }; - - auto db = - make_storage("", - make_table("Test", make_column("key", &Test::key), make_column("id", &Test::id, primary_key()))); - db.sync_schema(true); - - std::vector key(255); - iota(key.begin(), key.end(), 0); - - Test v{5, key}; - - db.replace(v); - - TestComparator testComparator; - for(auto &obj: db.iterate()) { - REQUIRE(testComparator(obj, v)); - } // test that view_t and iterator_t compile - - for(const auto &obj: db.iterate()) { - REQUIRE(testComparator(obj, v)); - } // test that view_t and iterator_t compile - - { - auto keysCount = db.count(where(c(&Test::key) == key)); - auto keysCountRows = db.select(count(), where(c(&Test::key) == key)); - REQUIRE(keysCountRows.size() == 1); - REQUIRE(keysCountRows.front() == 1); - REQUIRE(keysCount == keysCountRows.front()); - REQUIRE(db.get_all(where(c(&Test::key) == key)).size() == 1); - } - { - int iterationsCount = 0; - for(auto &w: db.iterate(where(c(&Test::key) == key))) { - REQUIRE(testComparator(w, v)); - ++iterationsCount; - } - REQUIRE(iterationsCount == 1); - } -} - -TEST_CASE("Threadsafe") { - // this code just shows this value on CI - cout << "threadsafe = " << threadsafe() << endl; -} - -TEST_CASE("Different getters and setters") { - struct User { - int id; - std::string name; - - int getIdByValConst() const { - return this->id; - } - - void setIdByVal(int id) { - this->id = id; - } - - std::string getNameByVal() { - return this->name; - } - - void setNameByConstRef(const std::string &name) { - this->name = name; - } - - const int &getConstIdByRefConst() const { - return this->id; - } - - void setIdByRef(int &id) { - this->id = id; - } - - const std::string &getConstNameByRefConst() const { - return this->name; - } - - void setNameByRef(std::string &name) { - this->name = std::move(name); - } - }; - - auto filename = "different.sqlite"; - auto storage0 = make_storage( - filename, - make_table("users", make_column("id", &User::id, primary_key()), make_column("name", &User::name))); - auto storage1 = make_storage(filename, - make_table("users", - make_column("id", &User::getIdByValConst, &User::setIdByVal, primary_key()), - make_column("name", &User::setNameByConstRef, &User::getNameByVal))); - auto storage2 = - make_storage(filename, - make_table("users", - make_column("id", &User::getConstIdByRefConst, &User::setIdByRef, primary_key()), - make_column("name", &User::getConstNameByRefConst, &User::setNameByRef))); - storage0.sync_schema(); - storage0.remove_all(); - - REQUIRE(storage0.count() == 0); - REQUIRE(storage1.count() == 0); - REQUIRE(storage2.count() == 0); - - storage0.replace(User{1, "Da buzz"}); - - REQUIRE(storage0.count() == 1); - REQUIRE(storage1.count() == 1); - REQUIRE(storage2.count() == 1); - - { - auto ids = storage0.select(&User::id); - REQUIRE(ids.size() == 1); - REQUIRE(ids.front() == 1); - auto ids2 = storage1.select(&User::getIdByValConst); - REQUIRE(ids == ids2); - auto ids3 = storage1.select(&User::setIdByVal); - REQUIRE(ids3 == ids2); - auto ids4 = storage2.select(&User::getConstIdByRefConst); - REQUIRE(ids4 == ids3); - auto ids5 = storage2.select(&User::setIdByRef); - REQUIRE(ids5 == ids4); - } - { - auto ids = storage0.select(&User::id, where(is_equal(&User::name, "Da buzz"))); - REQUIRE(ids.size() == 1); - REQUIRE(ids.front() == 1); - auto ids2 = storage1.select(&User::getIdByValConst, where(is_equal(&User::setNameByConstRef, "Da buzz"))); - REQUIRE(ids == ids2); - auto ids3 = storage1.select(&User::setIdByVal, where(is_equal(&User::getNameByVal, "Da buzz"))); - REQUIRE(ids3 == ids2); - auto ids4 = - storage2.select(&User::getConstIdByRefConst, where(is_equal(&User::getConstNameByRefConst, "Da buzz"))); - REQUIRE(ids4 == ids3); - auto ids5 = storage2.select(&User::setIdByRef, where(is_equal(&User::setNameByRef, "Da buzz"))); - REQUIRE(ids5 == ids4); - } - { - auto ids = storage0.select(columns(&User::id), where(is_equal(&User::name, "Da buzz"))); - REQUIRE(ids.size() == 1); - REQUIRE(std::get<0>(ids.front()) == 1); - auto ids2 = - storage1.select(columns(&User::getIdByValConst), where(is_equal(&User::setNameByConstRef, "Da buzz"))); - REQUIRE(ids == ids2); - auto ids3 = storage1.select(columns(&User::setIdByVal), where(is_equal(&User::getNameByVal, "Da buzz"))); - REQUIRE(ids3 == ids2); - auto ids4 = storage2.select(columns(&User::getConstIdByRefConst), - where(is_equal(&User::getConstNameByRefConst, "Da buzz"))); - REQUIRE(ids4 == ids3); - auto ids5 = storage2.select(columns(&User::setIdByRef), where(is_equal(&User::setNameByRef, "Da buzz"))); - REQUIRE(ids5 == ids4); - } - { - auto avgValue = storage0.avg(&User::id); - REQUIRE(avgValue == storage1.avg(&User::getIdByValConst)); - REQUIRE(avgValue == storage1.avg(&User::setIdByVal)); - REQUIRE(avgValue == storage2.avg(&User::getConstIdByRefConst)); - REQUIRE(avgValue == storage2.avg(&User::setIdByRef)); - } - { - auto count = storage0.count(&User::id); - REQUIRE(count == storage1.count(&User::getIdByValConst)); - REQUIRE(count == storage1.count(&User::setIdByVal)); - REQUIRE(count == storage2.count(&User::getConstIdByRefConst)); - REQUIRE(count == storage2.count(&User::setIdByRef)); - } - { - auto groupConcat = storage0.group_concat(&User::id); - REQUIRE(groupConcat == storage1.group_concat(&User::getIdByValConst)); - REQUIRE(groupConcat == storage1.group_concat(&User::setIdByVal)); - REQUIRE(groupConcat == storage2.group_concat(&User::getConstIdByRefConst)); - REQUIRE(groupConcat == storage2.group_concat(&User::setIdByRef)); - } - { - auto arg = "ototo"; - auto groupConcat = storage0.group_concat(&User::id, arg); - REQUIRE(groupConcat == storage1.group_concat(&User::getIdByValConst, arg)); - REQUIRE(groupConcat == storage1.group_concat(&User::setIdByVal, arg)); - REQUIRE(groupConcat == storage2.group_concat(&User::getConstIdByRefConst, arg)); - REQUIRE(groupConcat == storage2.group_concat(&User::setIdByRef, arg)); - } - { - auto max = storage0.max(&User::id); - REQUIRE(max); - REQUIRE(*max == *storage1.max(&User::getIdByValConst)); - REQUIRE(*max == *storage1.max(&User::setIdByVal)); - REQUIRE(*max == *storage2.max(&User::getConstIdByRefConst)); - REQUIRE(*max == *storage2.max(&User::setIdByRef)); - } - { - auto min = storage0.min(&User::id); - REQUIRE(min); - REQUIRE(*min == *storage1.min(&User::getIdByValConst)); - REQUIRE(*min == *storage1.min(&User::setIdByVal)); - REQUIRE(*min == *storage2.min(&User::getConstIdByRefConst)); - REQUIRE(*min == *storage2.min(&User::setIdByRef)); - } - { - auto sum = storage0.sum(&User::id); - REQUIRE(sum); - REQUIRE(*sum == *storage1.sum(&User::getIdByValConst)); - REQUIRE(*sum == *storage1.sum(&User::setIdByVal)); - REQUIRE(*sum == *storage2.sum(&User::getConstIdByRefConst)); - REQUIRE(*sum == *storage2.sum(&User::setIdByRef)); - } - { - auto total = storage0.total(&User::id); - REQUIRE(total == storage1.total(&User::getIdByValConst)); - REQUIRE(total == storage1.total(&User::setIdByVal)); - REQUIRE(total == storage2.total(&User::getConstIdByRefConst)); - REQUIRE(total == storage2.total(&User::setIdByRef)); - } -} - -#ifdef SQLITE_ORM_OPTIONAL_SUPPORTED -TEST_CASE("Dump") { - - struct User { - int id = 0; - std::optional carYear; // will be empty if user takes the bus. - }; - - auto storage = make_storage( - {}, - make_table("users", make_column("id", &User::id, primary_key()), make_column("car_year", &User::carYear))); - storage.sync_schema(); - - auto userId_1 = storage.insert(User{0, {}}); - auto userId_2 = storage.insert(User{0, 2006}); - std::ignore = userId_2; - - REQUIRE(storage.count(where(is_not_null(&User::carYear))) == 1); - - auto rows = storage.select(&User::carYear, where(is_equal(&User::id, userId_1))); - REQUIRE(rows.size() == 1); - REQUIRE(!rows.front().has_value()); - - auto allUsers = storage.get_all(); - REQUIRE(allUsers.size() == 2); - - const std::string dumpUser1 = storage.dump(allUsers[0]); - REQUIRE(dumpUser1 == std::string{"{ id : '1', car_year : 'null' }"}); - - const std::string dumpUser2 = storage.dump(allUsers[1]); - REQUIRE(dumpUser2 == std::string{"{ id : '2', car_year : '2006' }"}); -} -#endif // SQLITE_ORM_OPTIONAL_SUPPORTED diff --git a/tests/tests5.cpp b/tests/tests5.cpp new file mode 100644 index 000000000..981a15f95 --- /dev/null +++ b/tests/tests5.cpp @@ -0,0 +1,347 @@ +#include +#include + +using namespace sqlite_orm; + +TEST_CASE("Composite key column names") { + + struct User { + int id = 0; + std::string name; + std::string info; + }; + + { + auto table = make_table("t", + make_column("id", &User::id), + make_column("name", &User::name), + make_column("info", &User::info), + primary_key(&User::id, &User::name)); + auto compositeKeyColumnsNames = table.composite_key_columns_names(); + std::vector expected = {"id", "name"}; + REQUIRE(std::equal(compositeKeyColumnsNames.begin(), compositeKeyColumnsNames.end(), expected.begin())); + } + { + auto table = make_table("t", + make_column("id", &User::id), + make_column("name", &User::name), + make_column("info", &User::info), + primary_key(&User::name, &User::id)); + auto compositeKeyColumnsNames = table.composite_key_columns_names(); + std::vector expected = {"name", "id"}; + REQUIRE(std::equal(compositeKeyColumnsNames.begin(), compositeKeyColumnsNames.end(), expected.begin())); + } + { + auto table = make_table("t", + make_column("id", &User::id), + make_column("name", &User::name), + make_column("info", &User::info), + primary_key(&User::name, &User::id, &User::info)); + auto compositeKeyColumnsNames = table.composite_key_columns_names(); + std::vector expected = {"name", "id", "info"}; + REQUIRE(std::equal(compositeKeyColumnsNames.begin(), compositeKeyColumnsNames.end(), expected.begin())); + } + { + auto table = make_table("t", + make_column("id", &User::id), + make_column("name", &User::name), + make_column("info", &User::info)); + auto compositeKeyColumnsNames = table.composite_key_columns_names(); + REQUIRE(compositeKeyColumnsNames.empty()); + } +} + +TEST_CASE("Exists") { + struct User { + int id = 0; + std::string name; + }; + + struct Visit { + int id = 0; + int userId = 0; + time_t time = 0; + }; + + auto storage = + make_storage("", + make_table("users", make_column("id", &User::id, primary_key()), make_column("name", &User::name)), + make_table("visits", + make_column("id", &Visit::id, primary_key()), + make_column("userId", &Visit::userId), + make_column("time", &Visit::time), + foreign_key(&Visit::userId).references(&User::id))); + storage.sync_schema(); + + storage.replace(User{1, "Daddy Yankee"}); + storage.replace(User{2, "Don Omar"}); + + storage.replace(Visit{1, 1, 100000}); + storage.replace(Visit{2, 1, 100001}); + storage.replace(Visit{3, 1, 100002}); + storage.replace(Visit{4, 1, 200000}); + + storage.replace(Visit{5, 2, 100000}); + + auto rows = storage.select( + &User::id, + where(exists(select(&Visit::id, where(c(&Visit::time) == 200000 and eq(&Visit::userId, &User::id)))))); + REQUIRE(!rows.empty() == 1); +} + +TEST_CASE("Iterate blob") { + struct Test { + int64_t id; + std::vector key; + }; + + struct TestComparator { + bool operator()(const Test &lhs, const Test &rhs) const { + return lhs.id == rhs.id && lhs.key == rhs.key; + } + }; + + auto db = + make_storage("", + make_table("Test", make_column("key", &Test::key), make_column("id", &Test::id, primary_key()))); + db.sync_schema(true); + + std::vector key(255); + iota(key.begin(), key.end(), 0); + + Test v{5, key}; + + db.replace(v); + + TestComparator testComparator; + for(auto &obj: db.iterate()) { + REQUIRE(testComparator(obj, v)); + } // test that view_t and iterator_t compile + + for(const auto &obj: db.iterate()) { + REQUIRE(testComparator(obj, v)); + } // test that view_t and iterator_t compile + + { + auto keysCount = db.count(where(c(&Test::key) == key)); + auto keysCountRows = db.select(count(), where(c(&Test::key) == key)); + REQUIRE(keysCountRows.size() == 1); + REQUIRE(keysCountRows.front() == 1); + REQUIRE(keysCount == keysCountRows.front()); + REQUIRE(db.get_all(where(c(&Test::key) == key)).size() == 1); + } + { + int iterationsCount = 0; + for(auto &w: db.iterate(where(c(&Test::key) == key))) { + REQUIRE(testComparator(w, v)); + ++iterationsCount; + } + REQUIRE(iterationsCount == 1); + } +} + +TEST_CASE("Threadsafe") { + threadsafe(); +} + +TEST_CASE("Different getters and setters") { + struct User { + int id; + std::string name; + + int getIdByValConst() const { + return this->id; + } + + void setIdByVal(int id) { + this->id = id; + } + + std::string getNameByVal() { + return this->name; + } + + void setNameByConstRef(const std::string &name) { + this->name = name; + } + + const int &getConstIdByRefConst() const { + return this->id; + } + + void setIdByRef(int &id) { + this->id = id; + } + + const std::string &getConstNameByRefConst() const { + return this->name; + } + + void setNameByRef(std::string &name) { + this->name = std::move(name); + } + }; + + auto filename = "different.sqlite"; + auto storage0 = make_storage( + filename, + make_table("users", make_column("id", &User::id, primary_key()), make_column("name", &User::name))); + auto storage1 = make_storage(filename, + make_table("users", + make_column("id", &User::getIdByValConst, &User::setIdByVal, primary_key()), + make_column("name", &User::setNameByConstRef, &User::getNameByVal))); + auto storage2 = + make_storage(filename, + make_table("users", + make_column("id", &User::getConstIdByRefConst, &User::setIdByRef, primary_key()), + make_column("name", &User::getConstNameByRefConst, &User::setNameByRef))); + storage0.sync_schema(); + storage0.remove_all(); + + REQUIRE(storage0.count() == 0); + REQUIRE(storage1.count() == 0); + REQUIRE(storage2.count() == 0); + + storage0.replace(User{1, "Da buzz"}); + + REQUIRE(storage0.count() == 1); + REQUIRE(storage1.count() == 1); + REQUIRE(storage2.count() == 1); + + { + auto ids = storage0.select(&User::id); + REQUIRE(ids.size() == 1); + REQUIRE(ids.front() == 1); + auto ids2 = storage1.select(&User::getIdByValConst); + REQUIRE(ids == ids2); + auto ids3 = storage1.select(&User::setIdByVal); + REQUIRE(ids3 == ids2); + auto ids4 = storage2.select(&User::getConstIdByRefConst); + REQUIRE(ids4 == ids3); + auto ids5 = storage2.select(&User::setIdByRef); + REQUIRE(ids5 == ids4); + } + { + auto ids = storage0.select(&User::id, where(is_equal(&User::name, "Da buzz"))); + REQUIRE(ids.size() == 1); + REQUIRE(ids.front() == 1); + auto ids2 = storage1.select(&User::getIdByValConst, where(is_equal(&User::setNameByConstRef, "Da buzz"))); + REQUIRE(ids == ids2); + auto ids3 = storage1.select(&User::setIdByVal, where(is_equal(&User::getNameByVal, "Da buzz"))); + REQUIRE(ids3 == ids2); + auto ids4 = + storage2.select(&User::getConstIdByRefConst, where(is_equal(&User::getConstNameByRefConst, "Da buzz"))); + REQUIRE(ids4 == ids3); + auto ids5 = storage2.select(&User::setIdByRef, where(is_equal(&User::setNameByRef, "Da buzz"))); + REQUIRE(ids5 == ids4); + } + { + auto ids = storage0.select(columns(&User::id), where(is_equal(&User::name, "Da buzz"))); + REQUIRE(ids.size() == 1); + REQUIRE(std::get<0>(ids.front()) == 1); + auto ids2 = + storage1.select(columns(&User::getIdByValConst), where(is_equal(&User::setNameByConstRef, "Da buzz"))); + REQUIRE(ids == ids2); + auto ids3 = storage1.select(columns(&User::setIdByVal), where(is_equal(&User::getNameByVal, "Da buzz"))); + REQUIRE(ids3 == ids2); + auto ids4 = storage2.select(columns(&User::getConstIdByRefConst), + where(is_equal(&User::getConstNameByRefConst, "Da buzz"))); + REQUIRE(ids4 == ids3); + auto ids5 = storage2.select(columns(&User::setIdByRef), where(is_equal(&User::setNameByRef, "Da buzz"))); + REQUIRE(ids5 == ids4); + } + { + auto avgValue = storage0.avg(&User::id); + REQUIRE(avgValue == storage1.avg(&User::getIdByValConst)); + REQUIRE(avgValue == storage1.avg(&User::setIdByVal)); + REQUIRE(avgValue == storage2.avg(&User::getConstIdByRefConst)); + REQUIRE(avgValue == storage2.avg(&User::setIdByRef)); + } + { + auto count = storage0.count(&User::id); + REQUIRE(count == storage1.count(&User::getIdByValConst)); + REQUIRE(count == storage1.count(&User::setIdByVal)); + REQUIRE(count == storage2.count(&User::getConstIdByRefConst)); + REQUIRE(count == storage2.count(&User::setIdByRef)); + } + { + auto groupConcat = storage0.group_concat(&User::id); + REQUIRE(groupConcat == storage1.group_concat(&User::getIdByValConst)); + REQUIRE(groupConcat == storage1.group_concat(&User::setIdByVal)); + REQUIRE(groupConcat == storage2.group_concat(&User::getConstIdByRefConst)); + REQUIRE(groupConcat == storage2.group_concat(&User::setIdByRef)); + } + { + auto arg = "ototo"; + auto groupConcat = storage0.group_concat(&User::id, arg); + REQUIRE(groupConcat == storage1.group_concat(&User::getIdByValConst, arg)); + REQUIRE(groupConcat == storage1.group_concat(&User::setIdByVal, arg)); + REQUIRE(groupConcat == storage2.group_concat(&User::getConstIdByRefConst, arg)); + REQUIRE(groupConcat == storage2.group_concat(&User::setIdByRef, arg)); + } + { + auto max = storage0.max(&User::id); + REQUIRE(max); + REQUIRE(*max == *storage1.max(&User::getIdByValConst)); + REQUIRE(*max == *storage1.max(&User::setIdByVal)); + REQUIRE(*max == *storage2.max(&User::getConstIdByRefConst)); + REQUIRE(*max == *storage2.max(&User::setIdByRef)); + } + { + auto min = storage0.min(&User::id); + REQUIRE(min); + REQUIRE(*min == *storage1.min(&User::getIdByValConst)); + REQUIRE(*min == *storage1.min(&User::setIdByVal)); + REQUIRE(*min == *storage2.min(&User::getConstIdByRefConst)); + REQUIRE(*min == *storage2.min(&User::setIdByRef)); + } + { + auto sum = storage0.sum(&User::id); + REQUIRE(sum); + REQUIRE(*sum == *storage1.sum(&User::getIdByValConst)); + REQUIRE(*sum == *storage1.sum(&User::setIdByVal)); + REQUIRE(*sum == *storage2.sum(&User::getConstIdByRefConst)); + REQUIRE(*sum == *storage2.sum(&User::setIdByRef)); + } + { + auto total = storage0.total(&User::id); + REQUIRE(total == storage1.total(&User::getIdByValConst)); + REQUIRE(total == storage1.total(&User::setIdByVal)); + REQUIRE(total == storage2.total(&User::getConstIdByRefConst)); + REQUIRE(total == storage2.total(&User::setIdByRef)); + } +} + +#ifdef SQLITE_ORM_OPTIONAL_SUPPORTED +TEST_CASE("Dump") { + + struct User { + int id = 0; + std::optional carYear; // will be empty if user takes the bus. + }; + + auto storage = make_storage( + {}, + make_table("users", make_column("id", &User::id, primary_key()), make_column("car_year", &User::carYear))); + storage.sync_schema(); + + auto userId_1 = storage.insert(User{0, {}}); + auto userId_2 = storage.insert(User{0, 2006}); + std::ignore = userId_2; + + REQUIRE(storage.count(where(is_not_null(&User::carYear))) == 1); + + auto rows = storage.select(&User::carYear, where(is_equal(&User::id, userId_1))); + REQUIRE(rows.size() == 1); + REQUIRE(!rows.front().has_value()); + + auto allUsers = storage.get_all(); + REQUIRE(allUsers.size() == 2); + + const std::string dumpUser1 = storage.dump(allUsers[0]); + REQUIRE(dumpUser1 == std::string{"{ id : '1', car_year : 'null' }"}); + + const std::string dumpUser2 = storage.dump(allUsers[1]); + REQUIRE(dumpUser2 == std::string{"{ id : '2', car_year : '2006' }"}); +} +#endif // SQLITE_ORM_OPTIONAL_SUPPORTED From 7835e9508959af30544db3eca0ee06f324af85ce Mon Sep 17 00:00:00 2001 From: fnc12 Date: Fri, 21 Feb 2020 08:24:41 +0300 Subject: [PATCH 035/132] fixed tests5 compilation on windows --- include/sqlite_orm/sqlite_orm.h | 69 ++++----------------------------- tests/tests4.cpp | 1 - tests/tests5.cpp | 1 + 3 files changed, 9 insertions(+), 62 deletions(-) diff --git a/include/sqlite_orm/sqlite_orm.h b/include/sqlite_orm/sqlite_orm.h index 46c9ba4b0..fd118a38a 100644 --- a/include/sqlite_orm/sqlite_orm.h +++ b/include/sqlite_orm/sqlite_orm.h @@ -27,7 +27,7 @@ __pragma(push_macro("min")) #include #include // std::ostringstream -namespace sqlite_orm { + namespace sqlite_orm { enum class orm_error_code { not_found = 1, @@ -44,7 +44,6 @@ namespace sqlite_orm { failed_to_init_a_backup, unknown_member_value, }; - } namespace sqlite_orm { @@ -225,7 +224,6 @@ namespace sqlite_orm { // #include "static_magic.h" - #include // std::false_type, std::true_type, std::integral_constant namespace sqlite_orm { @@ -260,7 +258,6 @@ namespace sqlite_orm { } - namespace sqlite_orm { // got from here http://stackoverflow.com/questions/25958259/how-do-i-find-out-if-a-tuple-contains-a-type @@ -992,7 +989,6 @@ namespace sqlite_orm { // #include "serializator_context.h" - namespace sqlite_orm { namespace internal { @@ -1023,7 +1019,6 @@ namespace sqlite_orm { } - namespace sqlite_orm { namespace internal { @@ -1265,7 +1260,6 @@ namespace sqlite_orm { // #include "getter_traits.h" - namespace sqlite_orm { namespace internal { @@ -1449,7 +1443,6 @@ namespace sqlite_orm { } } - namespace sqlite_orm { namespace internal { @@ -1780,7 +1773,6 @@ namespace sqlite_orm { // #include "optional_container.h" - namespace sqlite_orm { namespace internal { @@ -1813,7 +1805,6 @@ namespace sqlite_orm { } } - namespace sqlite_orm { namespace internal { @@ -3302,7 +3293,6 @@ namespace sqlite_orm { // #include "conditions.h" - namespace sqlite_orm { namespace internal { @@ -3422,7 +3412,6 @@ namespace sqlite_orm { // #include "is_base_of_template.h" - #include // std::true_type, std::false_type, std::declval namespace sqlite_orm { @@ -3460,7 +3449,6 @@ namespace sqlite_orm { } } - namespace sqlite_orm { namespace internal { @@ -4213,7 +4201,6 @@ namespace sqlite_orm { // #include "optional_container.h" - namespace sqlite_orm { namespace internal { @@ -4570,7 +4557,6 @@ namespace sqlite_orm { // #include "column.h" - namespace sqlite_orm { namespace internal { @@ -4677,7 +4663,6 @@ namespace sqlite_orm { // #include "is_std_ptr.h" - namespace sqlite_orm { /** @@ -4705,7 +4690,6 @@ namespace sqlite_orm { }; } - namespace sqlite_orm { /** @@ -4916,7 +4900,6 @@ namespace sqlite_orm { // #include "journal_mode.h" - #include // std::string #include // std::unique_ptr #include // std::array @@ -4977,7 +4960,6 @@ namespace sqlite_orm { // #include "error_code.h" - namespace sqlite_orm { /** @@ -5354,7 +5336,6 @@ namespace sqlite_orm { // #include "alias.h" - namespace sqlite_orm { namespace internal { @@ -5601,7 +5582,6 @@ namespace sqlite_orm { } } - namespace sqlite_orm { namespace internal { @@ -5841,7 +5821,6 @@ namespace sqlite_orm { // #include "column.h" - namespace sqlite_orm { namespace internal { @@ -6141,12 +6120,10 @@ namespace sqlite_orm { // #include "field_value_holder.h" - #include // std::enable_if // #include "column.h" - namespace sqlite_orm { namespace internal { @@ -6169,7 +6146,6 @@ namespace sqlite_orm { } } - namespace sqlite_orm { namespace internal { @@ -6671,7 +6647,6 @@ namespace sqlite_orm { // #include "view.h" - #include // std::shared_ptr #include // std::string #include // std::forward, std::move @@ -6687,7 +6662,6 @@ namespace sqlite_orm { // #include "iterator.h" - #include // std::shared_ptr, std::unique_ptr, std::make_shared #include #include // std::decay @@ -6703,7 +6677,6 @@ namespace sqlite_orm { // #include "error_code.h" - namespace sqlite_orm { namespace internal { @@ -6832,7 +6805,6 @@ namespace sqlite_orm { // #include "ast_iterator.h" - #include // std::vector #include // std::reference_wrapper @@ -6848,7 +6820,6 @@ namespace sqlite_orm { // #include "prepared_statement.h" - #include #include // std::iterator_traits #include // std::string @@ -6857,14 +6828,12 @@ namespace sqlite_orm { // #include "connection_holder.h" - #include #include // std::string #include // std::system_error // #include "error_code.h" - namespace sqlite_orm { namespace internal { @@ -6939,7 +6908,6 @@ namespace sqlite_orm { // #include "select_constraints.h" - namespace sqlite_orm { namespace internal { @@ -7311,7 +7279,6 @@ namespace sqlite_orm { #endif // SQLITE_ORM_OPTIONAL_SUPPORTED } - namespace sqlite_orm { namespace internal { @@ -7789,7 +7756,6 @@ namespace sqlite_orm { // #include "connection_holder.h" - namespace sqlite_orm { namespace internal { @@ -7848,7 +7814,6 @@ namespace sqlite_orm { // #include "storage_base.h" - #include // std::function, std::bind #include #include // std::string @@ -7863,7 +7828,6 @@ namespace sqlite_orm { // #include "pragma.h" - #include // std::string #include #include // std::function @@ -7877,7 +7841,6 @@ namespace sqlite_orm { // #include "connection_holder.h" - namespace sqlite_orm { namespace internal { @@ -7998,7 +7961,6 @@ namespace sqlite_orm { // #include "limit_accesor.h" - #include #include // std::map #include // std::function @@ -8006,7 +7968,6 @@ namespace sqlite_orm { // #include "connection_holder.h" - namespace sqlite_orm { namespace internal { @@ -8140,12 +8101,10 @@ namespace sqlite_orm { // #include "transaction_guard.h" - #include // std::function // #include "connection_holder.h" - namespace sqlite_orm { namespace internal { @@ -8220,7 +8179,6 @@ namespace sqlite_orm { // #include "backup.h" - #include #include // std::string #include @@ -8229,7 +8187,6 @@ namespace sqlite_orm { // #include "connection_holder.h" - namespace sqlite_orm { namespace internal { @@ -8295,7 +8252,6 @@ namespace sqlite_orm { } } - namespace sqlite_orm { namespace internal { @@ -8831,13 +8787,11 @@ namespace sqlite_orm { // #include "expression_object_type.h" - #include // std::decay #include // std::reference_wrapper // #include "prepared_statement.h" - namespace sqlite_orm { namespace internal { @@ -8957,7 +8911,6 @@ namespace sqlite_orm { // #include "statement_serializator.h" - #include // std::stringstream #include // std::string #include // std::is_arithmetic, std::enable_if @@ -8972,7 +8925,6 @@ namespace sqlite_orm { // #include "column.h" - namespace sqlite_orm { namespace internal { @@ -9262,7 +9214,6 @@ namespace sqlite_orm { // #include "table_name_collector.h" - #include // std::set #include // std::string #include // std::function @@ -9274,7 +9225,6 @@ namespace sqlite_orm { // #include "core_functions.h" - namespace sqlite_orm { namespace internal { @@ -9333,7 +9283,6 @@ namespace sqlite_orm { } - namespace sqlite_orm { namespace conditions { @@ -11917,20 +11866,19 @@ __pragma(pop_macro("min")) #include // std::pair #include // std::reference_wrapper -// #include "conditions.h" + // #include "conditions.h" -// #include "operators.h" + // #include "operators.h" -// #include "select_constraints.h" + // #include "select_constraints.h" -// #include "prepared_statement.h" + // #include "prepared_statement.h" -// #include "optional_container.h" + // #include "optional_container.h" -// #include "core_functions.h" + // #include "core_functions.h" - -namespace sqlite_orm { + namespace sqlite_orm { namespace internal { @@ -12212,7 +12160,6 @@ namespace sqlite_orm { // #include "expression_object_type.h" - namespace sqlite_orm { template diff --git a/tests/tests4.cpp b/tests/tests4.cpp index 205e5cd9c..ea4136d8e 100644 --- a/tests/tests4.cpp +++ b/tests/tests4.cpp @@ -1,6 +1,5 @@ #include #include -#include #include // std::count_if #ifdef SQLITE_ORM_OPTIONAL_SUPPORTED #include // std::optional diff --git a/tests/tests5.cpp b/tests/tests5.cpp index 981a15f95..aac2f76bf 100644 --- a/tests/tests5.cpp +++ b/tests/tests5.cpp @@ -1,5 +1,6 @@ #include #include +#include // std::iota using namespace sqlite_orm; From 27d5dde00fd81cbe5e0c662baa54a690750c26ef Mon Sep 17 00:00:00 2001 From: fnc12 Date: Mon, 24 Feb 2020 10:22:12 +0300 Subject: [PATCH 036/132] started fix --- dev/prepared_statement.h | 4 +- dev/storage.h | 8 +- include/sqlite_orm/sqlite_orm.h | 81 ++++++++++++++--- tests/CMakeLists.txt | 2 +- tests/{ => constraints}/composite_key.cpp | 0 tests/tests2.cpp | 106 +++++++--------------- tests/type_parsing.cpp | 81 +++++++++++++++++ 7 files changed, 189 insertions(+), 93 deletions(-) rename tests/{ => constraints}/composite_key.cpp (100%) create mode 100644 tests/type_parsing.cpp diff --git a/dev/prepared_statement.h b/dev/prepared_statement.h index 28b4ded94..cf38c317b 100644 --- a/dev/prepared_statement.h +++ b/dev/prepared_statement.h @@ -335,8 +335,8 @@ namespace sqlite_orm { * T is an object type mapped to a storage. * Usage: storage.get_all(...); */ - template - internal::get_all_t get_all(Args... args) { + template, class... Args> + internal::get_all_t get_all(Args... args) { using args_tuple = std::tuple; internal::validate_conditions(); args_tuple conditions{std::forward(args)...}; diff --git a/dev/storage.h b/dev/storage.h index 8aefb3b74..dbff22076 100644 --- a/dev/storage.h +++ b/dev/storage.h @@ -1251,7 +1251,7 @@ namespace sqlite_orm { template, class... Args> C get_all(Args &&... args) { this->assert_mapped_type(); - auto statement = this->prepare(sqlite_orm::get_all(std::forward(args)...)); + auto statement = this->prepare(sqlite_orm::get_all(std::forward(args)...)); return this->execute(statement); } @@ -2451,8 +2451,8 @@ namespace sqlite_orm { return res; } - template - std::vector execute(const prepared_statement_t> &statement) { + template + C execute(const prepared_statement_t> &statement) { auto &impl = this->get_impl(); auto con = this->get_connection(); auto db = con.get(); @@ -2467,7 +2467,7 @@ namespace sqlite_orm { sqlite3_errmsg(db)); } }); - std::vector res; + C res; int stepRes; do { stepRes = sqlite3_step(stmt); diff --git a/include/sqlite_orm/sqlite_orm.h b/include/sqlite_orm/sqlite_orm.h index fd118a38a..6c52ad73f 100644 --- a/include/sqlite_orm/sqlite_orm.h +++ b/include/sqlite_orm/sqlite_orm.h @@ -27,7 +27,7 @@ __pragma(push_macro("min")) #include #include // std::ostringstream - namespace sqlite_orm { +namespace sqlite_orm { enum class orm_error_code { not_found = 1, @@ -44,6 +44,7 @@ __pragma(push_macro("min")) failed_to_init_a_backup, unknown_member_value, }; + } namespace sqlite_orm { @@ -224,6 +225,7 @@ namespace sqlite_orm { // #include "static_magic.h" + #include // std::false_type, std::true_type, std::integral_constant namespace sqlite_orm { @@ -258,6 +260,7 @@ namespace sqlite_orm { } + namespace sqlite_orm { // got from here http://stackoverflow.com/questions/25958259/how-do-i-find-out-if-a-tuple-contains-a-type @@ -989,6 +992,7 @@ namespace sqlite_orm { // #include "serializator_context.h" + namespace sqlite_orm { namespace internal { @@ -1019,6 +1023,7 @@ namespace sqlite_orm { } + namespace sqlite_orm { namespace internal { @@ -1260,6 +1265,7 @@ namespace sqlite_orm { // #include "getter_traits.h" + namespace sqlite_orm { namespace internal { @@ -1443,6 +1449,7 @@ namespace sqlite_orm { } } + namespace sqlite_orm { namespace internal { @@ -1773,6 +1780,7 @@ namespace sqlite_orm { // #include "optional_container.h" + namespace sqlite_orm { namespace internal { @@ -1805,6 +1813,7 @@ namespace sqlite_orm { } } + namespace sqlite_orm { namespace internal { @@ -3293,6 +3302,7 @@ namespace sqlite_orm { // #include "conditions.h" + namespace sqlite_orm { namespace internal { @@ -3412,6 +3422,7 @@ namespace sqlite_orm { // #include "is_base_of_template.h" + #include // std::true_type, std::false_type, std::declval namespace sqlite_orm { @@ -3449,6 +3460,7 @@ namespace sqlite_orm { } } + namespace sqlite_orm { namespace internal { @@ -4201,6 +4213,7 @@ namespace sqlite_orm { // #include "optional_container.h" + namespace sqlite_orm { namespace internal { @@ -4557,6 +4570,7 @@ namespace sqlite_orm { // #include "column.h" + namespace sqlite_orm { namespace internal { @@ -4663,6 +4677,7 @@ namespace sqlite_orm { // #include "is_std_ptr.h" + namespace sqlite_orm { /** @@ -4690,6 +4705,7 @@ namespace sqlite_orm { }; } + namespace sqlite_orm { /** @@ -4900,6 +4916,7 @@ namespace sqlite_orm { // #include "journal_mode.h" + #include // std::string #include // std::unique_ptr #include // std::array @@ -4960,6 +4977,7 @@ namespace sqlite_orm { // #include "error_code.h" + namespace sqlite_orm { /** @@ -5336,6 +5354,7 @@ namespace sqlite_orm { // #include "alias.h" + namespace sqlite_orm { namespace internal { @@ -5582,6 +5601,7 @@ namespace sqlite_orm { } } + namespace sqlite_orm { namespace internal { @@ -5821,6 +5841,7 @@ namespace sqlite_orm { // #include "column.h" + namespace sqlite_orm { namespace internal { @@ -6120,10 +6141,12 @@ namespace sqlite_orm { // #include "field_value_holder.h" + #include // std::enable_if // #include "column.h" + namespace sqlite_orm { namespace internal { @@ -6146,6 +6169,7 @@ namespace sqlite_orm { } } + namespace sqlite_orm { namespace internal { @@ -6647,6 +6671,7 @@ namespace sqlite_orm { // #include "view.h" + #include // std::shared_ptr #include // std::string #include // std::forward, std::move @@ -6662,6 +6687,7 @@ namespace sqlite_orm { // #include "iterator.h" + #include // std::shared_ptr, std::unique_ptr, std::make_shared #include #include // std::decay @@ -6677,6 +6703,7 @@ namespace sqlite_orm { // #include "error_code.h" + namespace sqlite_orm { namespace internal { @@ -6805,6 +6832,7 @@ namespace sqlite_orm { // #include "ast_iterator.h" + #include // std::vector #include // std::reference_wrapper @@ -6820,6 +6848,7 @@ namespace sqlite_orm { // #include "prepared_statement.h" + #include #include // std::iterator_traits #include // std::string @@ -6828,12 +6857,14 @@ namespace sqlite_orm { // #include "connection_holder.h" + #include #include // std::string #include // std::system_error // #include "error_code.h" + namespace sqlite_orm { namespace internal { @@ -6908,6 +6939,7 @@ namespace sqlite_orm { // #include "select_constraints.h" + namespace sqlite_orm { namespace internal { @@ -7234,8 +7266,8 @@ namespace sqlite_orm { * T is an object type mapped to a storage. * Usage: storage.get_all(...); */ - template - internal::get_all_t get_all(Args... args) { + template, class... Args> + internal::get_all_t get_all(Args... args) { using args_tuple = std::tuple; internal::validate_conditions(); args_tuple conditions{std::forward(args)...}; @@ -7279,6 +7311,7 @@ namespace sqlite_orm { #endif // SQLITE_ORM_OPTIONAL_SUPPORTED } + namespace sqlite_orm { namespace internal { @@ -7756,6 +7789,7 @@ namespace sqlite_orm { // #include "connection_holder.h" + namespace sqlite_orm { namespace internal { @@ -7814,6 +7848,7 @@ namespace sqlite_orm { // #include "storage_base.h" + #include // std::function, std::bind #include #include // std::string @@ -7828,6 +7863,7 @@ namespace sqlite_orm { // #include "pragma.h" + #include // std::string #include #include // std::function @@ -7841,6 +7877,7 @@ namespace sqlite_orm { // #include "connection_holder.h" + namespace sqlite_orm { namespace internal { @@ -7961,6 +7998,7 @@ namespace sqlite_orm { // #include "limit_accesor.h" + #include #include // std::map #include // std::function @@ -7968,6 +8006,7 @@ namespace sqlite_orm { // #include "connection_holder.h" + namespace sqlite_orm { namespace internal { @@ -8101,10 +8140,12 @@ namespace sqlite_orm { // #include "transaction_guard.h" + #include // std::function // #include "connection_holder.h" + namespace sqlite_orm { namespace internal { @@ -8179,6 +8220,7 @@ namespace sqlite_orm { // #include "backup.h" + #include #include // std::string #include @@ -8187,6 +8229,7 @@ namespace sqlite_orm { // #include "connection_holder.h" + namespace sqlite_orm { namespace internal { @@ -8252,6 +8295,7 @@ namespace sqlite_orm { } } + namespace sqlite_orm { namespace internal { @@ -8787,11 +8831,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 { @@ -8911,6 +8957,7 @@ namespace sqlite_orm { // #include "statement_serializator.h" + #include // std::stringstream #include // std::string #include // std::is_arithmetic, std::enable_if @@ -8925,6 +8972,7 @@ namespace sqlite_orm { // #include "column.h" + namespace sqlite_orm { namespace internal { @@ -9214,6 +9262,7 @@ namespace sqlite_orm { // #include "table_name_collector.h" + #include // std::set #include // std::string #include // std::function @@ -9225,6 +9274,7 @@ namespace sqlite_orm { // #include "core_functions.h" + namespace sqlite_orm { namespace internal { @@ -9283,6 +9333,7 @@ namespace sqlite_orm { } + namespace sqlite_orm { namespace conditions { @@ -10486,7 +10537,7 @@ namespace sqlite_orm { template, class... Args> C get_all(Args &&... args) { this->assert_mapped_type(); - auto statement = this->prepare(sqlite_orm::get_all(std::forward(args)...)); + auto statement = this->prepare(sqlite_orm::get_all(std::forward(args)...)); return this->execute(statement); } @@ -11686,8 +11737,8 @@ namespace sqlite_orm { return res; } - template - std::vector execute(const prepared_statement_t> &statement) { + template + C execute(const prepared_statement_t> &statement) { auto &impl = this->get_impl(); auto con = this->get_connection(); auto db = con.get(); @@ -11702,7 +11753,7 @@ namespace sqlite_orm { sqlite3_errmsg(db)); } }); - std::vector res; + C res; int stepRes; do { stepRes = sqlite3_step(stmt); @@ -11866,19 +11917,20 @@ __pragma(pop_macro("min")) #include // std::pair #include // std::reference_wrapper - // #include "conditions.h" +// #include "conditions.h" - // #include "operators.h" +// #include "operators.h" - // #include "select_constraints.h" +// #include "select_constraints.h" - // #include "prepared_statement.h" +// #include "prepared_statement.h" - // #include "optional_container.h" +// #include "optional_container.h" - // #include "core_functions.h" +// #include "core_functions.h" - namespace sqlite_orm { + +namespace sqlite_orm { namespace internal { @@ -12160,6 +12212,7 @@ __pragma(pop_macro("min")) // #include "expression_object_type.h" + namespace sqlite_orm { template diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 0ff50e9a4..464a48313 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -10,7 +10,7 @@ else() add_subdirectory(third_party/sqlite) endif() -add_executable(unit_tests tests.cpp tests2.cpp tests3.cpp tests4.cpp tests5.cpp private_getters_tests.cpp pragma_tests.cpp explicit_columns.cpp core_functions_tests.cpp composite_key.cpp static_tests.cpp operators/arithmetic_operators.cpp operators/like.cpp operators/glob.cpp operators/in.cpp operators/cast.cpp operators/is_null.cpp operators/not_operator.cpp dynamic_order_by.cpp prepared_statement_tests/select.cpp prepared_statement_tests/get_all.cpp prepared_statement_tests/get_all_pointer.cpp prepared_statement_tests/get_all_optional.cpp prepared_statement_tests/update_all.cpp prepared_statement_tests/remove_all.cpp prepared_statement_tests/get.cpp prepared_statement_tests/get_pointer.cpp prepared_statement_tests/get_optional.cpp prepared_statement_tests/update.cpp prepared_statement_tests/remove.cpp prepared_statement_tests/insert.cpp prepared_statement_tests/replace.cpp prepared_statement_tests/insert_range.cpp prepared_statement_tests/replace_range.cpp prepared_statement_tests/insert_explicit.cpp pragma_tests.cpp simple_query.cpp static_tests/is_bindable.cpp static_tests/arithmetic_operators_result_type.cpp static_tests/tuple_conc.cpp static_tests/node_tuple.cpp static_tests/bindable_filter.cpp static_tests/count_tuple.cpp static_tests/member_traits_tests.cpp constraints/default.cpp constraints/foreign_key.cpp constraints/check.cpp table_tests.cpp statement_serializator_tests/primary_key.cpp statement_serializator_tests/column_names.cpp statement_serializator_tests/autoincrement.cpp statement_serializator_tests/arithmetic_operators.cpp statement_serializator_tests/core_functions.cpp statement_serializator_tests/comparison_operators.cpp statement_serializator_tests/unique.cpp statement_serializator_tests/foreign_key.cpp statement_serializator_tests/collate.cpp statement_serializator_tests/check.cpp unique_cases/get_all_with_two_tables.cpp) +add_executable(unit_tests tests.cpp tests2.cpp tests3.cpp tests4.cpp tests5.cpp private_getters_tests.cpp pragma_tests.cpp explicit_columns.cpp core_functions_tests.cpp constraints/composite_key.cpp static_tests.cpp operators/arithmetic_operators.cpp operators/like.cpp operators/glob.cpp operators/in.cpp operators/cast.cpp operators/is_null.cpp operators/not_operator.cpp dynamic_order_by.cpp prepared_statement_tests/select.cpp prepared_statement_tests/get_all.cpp prepared_statement_tests/get_all_pointer.cpp prepared_statement_tests/get_all_optional.cpp prepared_statement_tests/update_all.cpp prepared_statement_tests/remove_all.cpp prepared_statement_tests/get.cpp prepared_statement_tests/get_pointer.cpp prepared_statement_tests/get_optional.cpp prepared_statement_tests/update.cpp prepared_statement_tests/remove.cpp prepared_statement_tests/insert.cpp prepared_statement_tests/replace.cpp prepared_statement_tests/insert_range.cpp prepared_statement_tests/replace_range.cpp prepared_statement_tests/insert_explicit.cpp pragma_tests.cpp simple_query.cpp static_tests/is_bindable.cpp static_tests/arithmetic_operators_result_type.cpp static_tests/tuple_conc.cpp static_tests/node_tuple.cpp static_tests/bindable_filter.cpp static_tests/count_tuple.cpp static_tests/member_traits_tests.cpp constraints/default.cpp constraints/foreign_key.cpp constraints/check.cpp table_tests.cpp statement_serializator_tests/primary_key.cpp statement_serializator_tests/column_names.cpp statement_serializator_tests/autoincrement.cpp statement_serializator_tests/arithmetic_operators.cpp statement_serializator_tests/core_functions.cpp statement_serializator_tests/comparison_operators.cpp statement_serializator_tests/unique.cpp statement_serializator_tests/foreign_key.cpp statement_serializator_tests/collate.cpp statement_serializator_tests/check.cpp unique_cases/get_all_with_two_tables.cpp) if(SQLITE_ORM_OMITS_CODECVT) diff --git a/tests/composite_key.cpp b/tests/constraints/composite_key.cpp similarity index 100% rename from tests/composite_key.cpp rename to tests/constraints/composite_key.cpp diff --git a/tests/tests2.cpp b/tests/tests2.cpp index d7aeb6e69..e2e000195 100644 --- a/tests/tests2.cpp +++ b/tests/tests2.cpp @@ -456,79 +456,41 @@ TEST_CASE("Insert") { REQUIRE(storage.get(20).name == "Death"); } -TEST_CASE("Type parsing") { - using namespace sqlite_orm::internal; - - // int - REQUIRE(*to_sqlite_type("INT") == sqlite_type::INTEGER); - REQUIRE(*to_sqlite_type("integeer") == sqlite_type::INTEGER); - REQUIRE(*to_sqlite_type("INTEGER") == sqlite_type::INTEGER); - REQUIRE(*to_sqlite_type("TINYINT") == sqlite_type::INTEGER); - REQUIRE(*to_sqlite_type("SMALLINT") == sqlite_type::INTEGER); - REQUIRE(*to_sqlite_type("MEDIUMINT") == sqlite_type::INTEGER); - REQUIRE(*to_sqlite_type("BIGINT") == sqlite_type::INTEGER); - REQUIRE(*to_sqlite_type("UNSIGNED BIG INT") == sqlite_type::INTEGER); - REQUIRE(*to_sqlite_type("INT2") == sqlite_type::INTEGER); - REQUIRE(*to_sqlite_type("INT8") == sqlite_type::INTEGER); - REQUIRE(*to_sqlite_type("UNSIGNED INT(6)") == sqlite_type::INTEGER); - REQUIRE(*to_sqlite_type("UNSIGNED INT(4)") == sqlite_type::INTEGER); - - // text - REQUIRE(*to_sqlite_type("TEXT") == sqlite_type::TEXT); - REQUIRE(*to_sqlite_type("CLOB") == sqlite_type::TEXT); - for(auto i = 0; i < 255; ++i) { - REQUIRE(*to_sqlite_type("CHARACTER(" + std::to_string(i) + ")") == sqlite_type::TEXT); - REQUIRE(*to_sqlite_type("VARCHAR(" + std::to_string(i) + ")") == sqlite_type::TEXT); - REQUIRE(*to_sqlite_type("VARYING CHARACTER(" + std::to_string(i) + ")") == sqlite_type::TEXT); - REQUIRE(*to_sqlite_type("NCHAR(" + std::to_string(i) + ")") == sqlite_type::TEXT); - REQUIRE(*to_sqlite_type("NATIVE CHARACTER(" + std::to_string(i) + ")") == sqlite_type::TEXT); - REQUIRE(*to_sqlite_type("NVARCHAR(" + std::to_string(i) + ")") == sqlite_type::TEXT); - } - - // blob.. - REQUIRE(*to_sqlite_type("BLOB") == sqlite_type::BLOB); - - // real - REQUIRE(*to_sqlite_type("REAL") == sqlite_type::REAL); - REQUIRE(*to_sqlite_type("DOUBLE") == sqlite_type::REAL); - REQUIRE(*to_sqlite_type("DOUBLE PRECISION") == sqlite_type::REAL); - REQUIRE(*to_sqlite_type("FLOAT") == sqlite_type::REAL); +namespace get_all_deque { + struct User { + int id = 0; + std::string name; + }; - REQUIRE(*to_sqlite_type("NUMERIC") == sqlite_type::REAL); - for(auto i = 0; i < 255; ++i) { - for(auto j = 0; j < 10; ++j) { - REQUIRE(*to_sqlite_type("DECIMAL(" + std::to_string(i) + "," + std::to_string(j) + ")") == - sqlite_type::REAL); - } + bool operator==(const User &lhs, const User &rhs) { + return lhs.id == rhs.id && lhs.name == rhs.name; } - REQUIRE(*to_sqlite_type("BOOLEAN") == sqlite_type::REAL); - REQUIRE(*to_sqlite_type("DATE") == sqlite_type::REAL); - REQUIRE(*to_sqlite_type("DATETIME") == sqlite_type::REAL); - - REQUIRE(type_is_nullable::value == false); - REQUIRE(type_is_nullable::value == false); - REQUIRE(type_is_nullable::value == false); - REQUIRE(type_is_nullable::value == false); - REQUIRE(type_is_nullable::value == false); - REQUIRE(type_is_nullable::value == false); - REQUIRE(type_is_nullable::value == false); - REQUIRE(type_is_nullable::value == false); - REQUIRE(type_is_nullable::value == false); - REQUIRE(type_is_nullable::value == false); - REQUIRE(type_is_nullable::value == false); - REQUIRE(type_is_nullable::value == false); - REQUIRE(type_is_nullable::value == false); - REQUIRE(type_is_nullable::value == false); - REQUIRE(type_is_nullable::value == false); - REQUIRE(type_is_nullable::value == false); - REQUIRE(type_is_nullable::value == false); - REQUIRE(type_is_nullable>::value == true); - REQUIRE(type_is_nullable>::value == true); - REQUIRE(type_is_nullable>::value == true); - REQUIRE(type_is_nullable>::value == true); +} -#ifdef SQLITE_ORM_OPTIONAL_SUPPORTED - REQUIRE(type_is_nullable>::value == true); - REQUIRE(type_is_nullable>::value == true); -#endif // SQLITE_ORM_OPTIONAL_SUPPORTED +TEST_CASE("get_all deque") { + using namespace get_all_deque; + using Catch::Matchers::UnorderedEquals; + + auto storage = make_storage({}, + make_table("users", + make_column("id", &User::id, primary_key()), + make_column("name", &User::name))); + storage.sync_schema(); + + User user1{1, "Nicki"}; + User user2{2, "Karol"}; + storage.replace(user1); + storage.replace(user2); + + std::vector expected; + expected.push_back(user1); + expected.push_back(user2); + { + auto users = storage.get_all(); + REQUIRE_THAT(users, UnorderedEquals(expected)); + } + { + auto users = storage.get_all>(); + REQUIRE_THAT(users, UnorderedEquals(expected)); + } } diff --git a/tests/type_parsing.cpp b/tests/type_parsing.cpp new file mode 100644 index 000000000..1490f3907 --- /dev/null +++ b/tests/type_parsing.cpp @@ -0,0 +1,81 @@ +#include +#include + +using namespace sqlite_orm; + +TEST_CASE("Type parsing") { + using namespace sqlite_orm::internal; + + // int + REQUIRE(*to_sqlite_type("INT") == sqlite_type::INTEGER); + REQUIRE(*to_sqlite_type("integeer") == sqlite_type::INTEGER); + REQUIRE(*to_sqlite_type("INTEGER") == sqlite_type::INTEGER); + REQUIRE(*to_sqlite_type("TINYINT") == sqlite_type::INTEGER); + REQUIRE(*to_sqlite_type("SMALLINT") == sqlite_type::INTEGER); + REQUIRE(*to_sqlite_type("MEDIUMINT") == sqlite_type::INTEGER); + REQUIRE(*to_sqlite_type("BIGINT") == sqlite_type::INTEGER); + REQUIRE(*to_sqlite_type("UNSIGNED BIG INT") == sqlite_type::INTEGER); + REQUIRE(*to_sqlite_type("INT2") == sqlite_type::INTEGER); + REQUIRE(*to_sqlite_type("INT8") == sqlite_type::INTEGER); + REQUIRE(*to_sqlite_type("UNSIGNED INT(6)") == sqlite_type::INTEGER); + REQUIRE(*to_sqlite_type("UNSIGNED INT(4)") == sqlite_type::INTEGER); + + // text + REQUIRE(*to_sqlite_type("TEXT") == sqlite_type::TEXT); + REQUIRE(*to_sqlite_type("CLOB") == sqlite_type::TEXT); + for(auto i = 0; i < 255; ++i) { + REQUIRE(*to_sqlite_type("CHARACTER(" + std::to_string(i) + ")") == sqlite_type::TEXT); + REQUIRE(*to_sqlite_type("VARCHAR(" + std::to_string(i) + ")") == sqlite_type::TEXT); + REQUIRE(*to_sqlite_type("VARYING CHARACTER(" + std::to_string(i) + ")") == sqlite_type::TEXT); + REQUIRE(*to_sqlite_type("NCHAR(" + std::to_string(i) + ")") == sqlite_type::TEXT); + REQUIRE(*to_sqlite_type("NATIVE CHARACTER(" + std::to_string(i) + ")") == sqlite_type::TEXT); + REQUIRE(*to_sqlite_type("NVARCHAR(" + std::to_string(i) + ")") == sqlite_type::TEXT); + } + + // blob.. + REQUIRE(*to_sqlite_type("BLOB") == sqlite_type::BLOB); + + // real + REQUIRE(*to_sqlite_type("REAL") == sqlite_type::REAL); + REQUIRE(*to_sqlite_type("DOUBLE") == sqlite_type::REAL); + REQUIRE(*to_sqlite_type("DOUBLE PRECISION") == sqlite_type::REAL); + REQUIRE(*to_sqlite_type("FLOAT") == sqlite_type::REAL); + + REQUIRE(*to_sqlite_type("NUMERIC") == sqlite_type::REAL); + for(auto i = 0; i < 255; ++i) { + for(auto j = 0; j < 10; ++j) { + REQUIRE(*to_sqlite_type("DECIMAL(" + std::to_string(i) + "," + std::to_string(j) + ")") == + sqlite_type::REAL); + } + } + REQUIRE(*to_sqlite_type("BOOLEAN") == sqlite_type::REAL); + REQUIRE(*to_sqlite_type("DATE") == sqlite_type::REAL); + REQUIRE(*to_sqlite_type("DATETIME") == sqlite_type::REAL); + + REQUIRE(type_is_nullable::value == false); + REQUIRE(type_is_nullable::value == false); + REQUIRE(type_is_nullable::value == false); + REQUIRE(type_is_nullable::value == false); + REQUIRE(type_is_nullable::value == false); + REQUIRE(type_is_nullable::value == false); + REQUIRE(type_is_nullable::value == false); + REQUIRE(type_is_nullable::value == false); + REQUIRE(type_is_nullable::value == false); + REQUIRE(type_is_nullable::value == false); + REQUIRE(type_is_nullable::value == false); + REQUIRE(type_is_nullable::value == false); + REQUIRE(type_is_nullable::value == false); + REQUIRE(type_is_nullable::value == false); + REQUIRE(type_is_nullable::value == false); + REQUIRE(type_is_nullable::value == false); + REQUIRE(type_is_nullable::value == false); + REQUIRE(type_is_nullable>::value == true); + REQUIRE(type_is_nullable>::value == true); + REQUIRE(type_is_nullable>::value == true); + REQUIRE(type_is_nullable>::value == true); + +#ifdef SQLITE_ORM_OPTIONAL_SUPPORTED + REQUIRE(type_is_nullable>::value == true); + REQUIRE(type_is_nullable>::value == true); +#endif // SQLITE_ORM_OPTIONAL_SUPPORTED +} From 64e848f62910dde0785a1392e36346b5d20d2ac0 Mon Sep 17 00:00:00 2001 From: fnc12 Date: Tue, 25 Feb 2020 16:24:40 +0300 Subject: [PATCH 037/132] added default ctor to core function --- dev/core_functions.h | 2 ++ include/sqlite_orm/sqlite_orm.h | 2 ++ tests/CMakeLists.txt | 2 +- .../unique_cases/get_all_with_two_tables.cpp | 26 ++++++++++++++++--- .../prepare_get_all_with_case.cpp | 23 ++++++++++++++++ 5 files changed, 50 insertions(+), 5 deletions(-) create mode 100644 tests/unique_cases/prepare_get_all_with_case.cpp diff --git a/dev/core_functions.h b/dev/core_functions.h index 6518e1652..7fbc03301 100644 --- a/dev/core_functions.h +++ b/dev/core_functions.h @@ -33,6 +33,8 @@ namespace sqlite_orm { args_type args; + core_function_t() = default; + core_function_t(args_type &&args_) : args(std::move(args_)) {} }; diff --git a/include/sqlite_orm/sqlite_orm.h b/include/sqlite_orm/sqlite_orm.h index fd118a38a..96e5373f2 100644 --- a/include/sqlite_orm/sqlite_orm.h +++ b/include/sqlite_orm/sqlite_orm.h @@ -3472,6 +3472,8 @@ namespace sqlite_orm { args_type args; + core_function_t() = default; + core_function_t(args_type &&args_) : args(std::move(args_)) {} }; diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 0ff50e9a4..48dd015eb 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -10,7 +10,7 @@ else() add_subdirectory(third_party/sqlite) endif() -add_executable(unit_tests tests.cpp tests2.cpp tests3.cpp tests4.cpp tests5.cpp private_getters_tests.cpp pragma_tests.cpp explicit_columns.cpp core_functions_tests.cpp composite_key.cpp static_tests.cpp operators/arithmetic_operators.cpp operators/like.cpp operators/glob.cpp operators/in.cpp operators/cast.cpp operators/is_null.cpp operators/not_operator.cpp dynamic_order_by.cpp prepared_statement_tests/select.cpp prepared_statement_tests/get_all.cpp prepared_statement_tests/get_all_pointer.cpp prepared_statement_tests/get_all_optional.cpp prepared_statement_tests/update_all.cpp prepared_statement_tests/remove_all.cpp prepared_statement_tests/get.cpp prepared_statement_tests/get_pointer.cpp prepared_statement_tests/get_optional.cpp prepared_statement_tests/update.cpp prepared_statement_tests/remove.cpp prepared_statement_tests/insert.cpp prepared_statement_tests/replace.cpp prepared_statement_tests/insert_range.cpp prepared_statement_tests/replace_range.cpp prepared_statement_tests/insert_explicit.cpp pragma_tests.cpp simple_query.cpp static_tests/is_bindable.cpp static_tests/arithmetic_operators_result_type.cpp static_tests/tuple_conc.cpp static_tests/node_tuple.cpp static_tests/bindable_filter.cpp static_tests/count_tuple.cpp static_tests/member_traits_tests.cpp constraints/default.cpp constraints/foreign_key.cpp constraints/check.cpp table_tests.cpp statement_serializator_tests/primary_key.cpp statement_serializator_tests/column_names.cpp statement_serializator_tests/autoincrement.cpp statement_serializator_tests/arithmetic_operators.cpp statement_serializator_tests/core_functions.cpp statement_serializator_tests/comparison_operators.cpp statement_serializator_tests/unique.cpp statement_serializator_tests/foreign_key.cpp statement_serializator_tests/collate.cpp statement_serializator_tests/check.cpp unique_cases/get_all_with_two_tables.cpp) +add_executable(unit_tests tests.cpp tests2.cpp tests3.cpp tests4.cpp tests5.cpp private_getters_tests.cpp pragma_tests.cpp explicit_columns.cpp core_functions_tests.cpp composite_key.cpp static_tests.cpp operators/arithmetic_operators.cpp operators/like.cpp operators/glob.cpp operators/in.cpp operators/cast.cpp operators/is_null.cpp operators/not_operator.cpp dynamic_order_by.cpp prepared_statement_tests/select.cpp prepared_statement_tests/get_all.cpp prepared_statement_tests/get_all_pointer.cpp prepared_statement_tests/get_all_optional.cpp prepared_statement_tests/update_all.cpp prepared_statement_tests/remove_all.cpp prepared_statement_tests/get.cpp prepared_statement_tests/get_pointer.cpp prepared_statement_tests/get_optional.cpp prepared_statement_tests/update.cpp prepared_statement_tests/remove.cpp prepared_statement_tests/insert.cpp prepared_statement_tests/replace.cpp prepared_statement_tests/insert_range.cpp prepared_statement_tests/replace_range.cpp prepared_statement_tests/insert_explicit.cpp pragma_tests.cpp simple_query.cpp static_tests/is_bindable.cpp static_tests/arithmetic_operators_result_type.cpp static_tests/tuple_conc.cpp static_tests/node_tuple.cpp static_tests/bindable_filter.cpp static_tests/count_tuple.cpp static_tests/member_traits_tests.cpp constraints/default.cpp constraints/foreign_key.cpp constraints/check.cpp table_tests.cpp statement_serializator_tests/primary_key.cpp statement_serializator_tests/column_names.cpp statement_serializator_tests/autoincrement.cpp statement_serializator_tests/arithmetic_operators.cpp statement_serializator_tests/core_functions.cpp statement_serializator_tests/comparison_operators.cpp statement_serializator_tests/unique.cpp statement_serializator_tests/foreign_key.cpp statement_serializator_tests/collate.cpp statement_serializator_tests/check.cpp unique_cases/get_all_with_two_tables.cpp unique_cases/prepare_get_all_with_case.cpp) if(SQLITE_ORM_OMITS_CODECVT) diff --git a/tests/unique_cases/get_all_with_two_tables.cpp b/tests/unique_cases/get_all_with_two_tables.cpp index cd15c9252..878904aaf 100644 --- a/tests/unique_cases/get_all_with_two_tables.cpp +++ b/tests/unique_cases/get_all_with_two_tables.cpp @@ -30,6 +30,8 @@ TEST_CASE("get_all with two tables") { const Item item1{1, "one"}; const Item item2{2, "two"}; const Item item3{3, "three"}; + const Item item4{4, "nwa"}; + storage.replace(item1); storage.replace(item2); storage.replace(item3); @@ -43,10 +45,26 @@ TEST_CASE("get_all with two tables") { { auto rows = storage.select(&Item::id, where(like(&Item::attributes, conc(conc("%", &Pattern::value), "%")))); REQUIRE_THAT(rows, UnorderedEquals({1, 2})); + + auto items = storage.get_all(where( + in(&Item::id, select(&Item::id, where(like(&Item::attributes, conc(conc("%", &Pattern::value), "%"))))))); + REQUIRE_THAT(items, UnorderedEquals({item1, item2})); } - auto items = storage.get_all( - where(in(&Item::id, select(&Item::id, where(like(&Item::attributes, conc(conc("%", &Pattern::value), "%"))))))); - storage.rollback(); + { + storage.replace(Item{4, "nwa"}); + auto rows = storage.select(&Item::id, + where(like(&Item::attributes, conc(conc("%", &Pattern::value), "%"))), + group_by(&Item::id), + having(is_equal(count(&Pattern::value), select(count())))); + REQUIRE_THAT(rows, UnorderedEquals({4})); - REQUIRE_THAT(items, UnorderedEquals({item1, item2})); + auto items = storage.get_all( + where(in(&Item::id, + select(&Item::id, + where(like(&Item::attributes, conc(conc("%", &Pattern::value), "%"))), + group_by(&Item::id), + having(is_equal(count(&Pattern::value), select(count()))))))); + REQUIRE_THAT(items, UnorderedEquals({item4})); + } + storage.rollback(); } diff --git a/tests/unique_cases/prepare_get_all_with_case.cpp b/tests/unique_cases/prepare_get_all_with_case.cpp new file mode 100644 index 000000000..23cbbe79b --- /dev/null +++ b/tests/unique_cases/prepare_get_all_with_case.cpp @@ -0,0 +1,23 @@ +#include +#include + +using namespace sqlite_orm; + +TEST_CASE("Prepare with case") { + struct UserProfile { + int id = 0; + std::string firstName; + }; + + auto storage = make_storage({}, + make_table("user_profiles", + make_column("id", &UserProfile::id, primary_key()), + make_column("first_name", &UserProfile::firstName))); + storage.sync_schema(); + + const std::string name = "Iggy"; + + auto statement = storage.prepare(get_all(where( + is_equal(&UserProfile::firstName, + case_(name).when((length(name) > 0), then(name)).else_(&UserProfile::firstName).end())))); +} From 6fc3c4f2fd57f12525bb0548827dbae985a395e0 Mon Sep 17 00:00:00 2001 From: fnc12 Date: Thu, 27 Feb 2020 11:57:21 +0300 Subject: [PATCH 038/132] reactored tuple creation --- dev/core_functions.h | 2 -- dev/select_constraints.h | 4 ++-- include/sqlite_orm/sqlite_orm.h | 6 ++---- tests/unique_cases/prepare_get_all_with_case.cpp | 14 +++++++++++--- 4 files changed, 15 insertions(+), 11 deletions(-) diff --git a/dev/core_functions.h b/dev/core_functions.h index 7fbc03301..6518e1652 100644 --- a/dev/core_functions.h +++ b/dev/core_functions.h @@ -33,8 +33,6 @@ namespace sqlite_orm { args_type args; - core_function_t() = default; - core_function_t(args_type &&args_) : args(std::move(args_)) {} }; diff --git a/dev/select_constraints.h b/dev/select_constraints.h index 0c2a2559c..6659b008c 100644 --- a/dev/select_constraints.h +++ b/dev/select_constraints.h @@ -217,9 +217,9 @@ namespace sqlite_orm { template simple_case_builder> when(W w, then_t t) { using result_args_type = std::tuple>; - result_args_type result_args; - move_tuple::value>(result_args, this->args); std::pair newPair{std::move(w), std::move(t.expression)}; + result_args_type result_args = + std::tuple_cat(std::move(this->args), std::move(std::make_tuple(newPair))); std::get::value - 1>(result_args) = std::move(newPair); return {std::move(this->case_expression), std::move(result_args), std::move(this->else_expression)}; } diff --git a/include/sqlite_orm/sqlite_orm.h b/include/sqlite_orm/sqlite_orm.h index 96e5373f2..7c90477c3 100644 --- a/include/sqlite_orm/sqlite_orm.h +++ b/include/sqlite_orm/sqlite_orm.h @@ -3472,8 +3472,6 @@ namespace sqlite_orm { args_type args; - core_function_t() = default; - core_function_t(args_type &&args_) : args(std::move(args_)) {} }; @@ -4412,9 +4410,9 @@ namespace sqlite_orm { template simple_case_builder> when(W w, then_t t) { using result_args_type = std::tuple>; - result_args_type result_args; - move_tuple::value>(result_args, this->args); std::pair newPair{std::move(w), std::move(t.expression)}; + result_args_type result_args = + std::tuple_cat(std::move(this->args), std::move(std::make_tuple(newPair))); std::get::value - 1>(result_args) = std::move(newPair); return {std::move(this->case_expression), std::move(result_args), std::move(this->else_expression)}; } diff --git a/tests/unique_cases/prepare_get_all_with_case.cpp b/tests/unique_cases/prepare_get_all_with_case.cpp index 23cbbe79b..a4e66cafe 100644 --- a/tests/unique_cases/prepare_get_all_with_case.cpp +++ b/tests/unique_cases/prepare_get_all_with_case.cpp @@ -17,7 +17,15 @@ TEST_CASE("Prepare with case") { const std::string name = "Iggy"; - auto statement = storage.prepare(get_all(where( - is_equal(&UserProfile::firstName, - case_(name).when((length(name) > 0), then(name)).else_(&UserProfile::firstName).end())))); + { + auto statement = storage.prepare(get_all(where(is_equal( + &UserProfile::firstName, + case_(name).when((length(name) > 0), then(name)).else_(&UserProfile::firstName).end())))); + std::ignore = statement; + } + { + auto statement = storage.prepare(get_all(where( + case_().when(length(name) > 0, then(like(&UserProfile::firstName, name))).else_(true).end()))); + std::ignore = statement; + } } From 50c5a7a560b12310884c228b3142770d6d054818 Mon Sep 17 00:00:00 2001 From: fnc12 Date: Tue, 3 Mar 2020 00:40:05 +0300 Subject: [PATCH 039/132] fixed get_all with custom containers --- dev/ast_iterator.h | 6 +- dev/node_tuple.h | 6 +- dev/prepared_statement.h | 18 +++- dev/storage.h | 19 ++-- dev/table_info.h | 6 +- dev/view.h | 2 +- include/sqlite_orm/sqlite_orm.h | 126 ++++++++-------------- tests/CMakeLists.txt | 2 +- tests/static_tests.cpp | 98 +---------------- tests/static_tests/select_return_type.cpp | 67 ++++++++++++ tests/static_tests/static_tests_common.h | 35 ++++++ tests/tests2.cpp | 38 +++++-- 12 files changed, 218 insertions(+), 205 deletions(-) create mode 100644 tests/static_tests/select_return_type.cpp create mode 100644 tests/static_tests/static_tests_common.h diff --git a/dev/ast_iterator.h b/dev/ast_iterator.h index 86f24773c..1c84341be 100644 --- a/dev/ast_iterator.h +++ b/dev/ast_iterator.h @@ -154,9 +154,9 @@ namespace sqlite_orm { } }; - template - struct ast_iterator, void> { - using node_type = get_all_t; + template + struct ast_iterator, void> { + using node_type = get_all_t; template void operator()(const node_type &get, const L &l) const { diff --git a/dev/node_tuple.h b/dev/node_tuple.h index 64291e135..18066bfc2 100644 --- a/dev/node_tuple.h +++ b/dev/node_tuple.h @@ -89,9 +89,9 @@ namespace sqlite_orm { using type = typename conc_tuple::type; }; - template - struct node_tuple, void> { - using node_type = get_all_t; + template + struct node_tuple, void> { + using node_type = get_all_t; using type = typename conc_tuple::type...>::type; }; diff --git a/dev/prepared_statement.h b/dev/prepared_statement.h index cf38c317b..ce5689586 100644 --- a/dev/prepared_statement.h +++ b/dev/prepared_statement.h @@ -76,9 +76,13 @@ namespace sqlite_orm { prepared_statement_base{stmt, std::move(con_)}, t(std::move(t_)) {} }; - template + /** + * T - type of object to obtain from a database + */ + template struct get_all_t { using type = T; + using return_type = R; using conditions_type = std::tuple; @@ -335,8 +339,16 @@ namespace sqlite_orm { * T is an object type mapped to a storage. * Usage: storage.get_all(...); */ - template, class... Args> - internal::get_all_t get_all(Args... args) { + template + internal::get_all_t, Args...> get_all(Args... args) { + using args_tuple = std::tuple; + internal::validate_conditions(); + args_tuple conditions{std::forward(args)...}; + return {move(conditions)}; + } + + template + internal::get_all_t get_all(Args... args) { using args_tuple = std::tuple; internal::validate_conditions(); args_tuple conditions{std::forward(args)...}; diff --git a/dev/storage.h b/dev/storage.h index dbff22076..3174eedfe 100644 --- a/dev/storage.h +++ b/dev/storage.h @@ -1248,10 +1248,17 @@ namespace sqlite_orm { * O is an object type to be extracted. Must be specified explicitly. * @return All objects of type O stored in database at the moment. */ - template, class... Args> - C get_all(Args &&... args) { + template + auto get_all(Args &&... args) { + this->assert_mapped_type(); + auto statement = this->prepare(sqlite_orm::get_all(std::forward(args)...)); + return this->execute(statement); + } + + template + auto get_all(Args &&... args) { this->assert_mapped_type(); - auto statement = this->prepare(sqlite_orm::get_all(std::forward(args)...)); + auto statement = this->prepare(sqlite_orm::get_all(std::forward(args)...)); return this->execute(statement); } @@ -2451,8 +2458,8 @@ namespace sqlite_orm { return res; } - template - C execute(const prepared_statement_t> &statement) { + template + R execute(const prepared_statement_t> &statement) { auto &impl = this->get_impl(); auto con = this->get_connection(); auto db = con.get(); @@ -2467,7 +2474,7 @@ namespace sqlite_orm { sqlite3_errmsg(db)); } }); - C res; + R res; int stepRes; do { stepRes = sqlite3_step(stmt); diff --git a/dev/table_info.h b/dev/table_info.h index 2b362d1b4..8beccaea1 100644 --- a/dev/table_info.h +++ b/dev/table_info.h @@ -5,12 +5,12 @@ namespace sqlite_orm { struct table_info { - int cid; + int cid = 0; std::string name; std::string type; - bool notnull; + bool notnull = false; std::string dflt_value; - int pk; + int pk = 0; }; } diff --git a/dev/view.h b/dev/view.h index afd868e79..571a9c116 100644 --- a/dev/view.h +++ b/dev/view.h @@ -27,7 +27,7 @@ namespace sqlite_orm { storage_type &storage; connection_ref connection; - get_all_t args; + get_all_t, Args...> args; view_t(storage_type &stor, decltype(connection) conn, Args &&... args_) : storage(stor), connection(std::move(conn)), args{std::make_tuple(std::forward(args_)...)} {} diff --git a/include/sqlite_orm/sqlite_orm.h b/include/sqlite_orm/sqlite_orm.h index afb8055fa..3cfe33f0c 100644 --- a/include/sqlite_orm/sqlite_orm.h +++ b/include/sqlite_orm/sqlite_orm.h @@ -27,7 +27,7 @@ __pragma(push_macro("min")) #include #include // std::ostringstream -namespace sqlite_orm { + namespace sqlite_orm { enum class orm_error_code { not_found = 1, @@ -44,7 +44,6 @@ namespace sqlite_orm { failed_to_init_a_backup, unknown_member_value, }; - } namespace sqlite_orm { @@ -225,7 +224,6 @@ namespace sqlite_orm { // #include "static_magic.h" - #include // std::false_type, std::true_type, std::integral_constant namespace sqlite_orm { @@ -260,7 +258,6 @@ namespace sqlite_orm { } - namespace sqlite_orm { // got from here http://stackoverflow.com/questions/25958259/how-do-i-find-out-if-a-tuple-contains-a-type @@ -992,7 +989,6 @@ namespace sqlite_orm { // #include "serializator_context.h" - namespace sqlite_orm { namespace internal { @@ -1023,7 +1019,6 @@ namespace sqlite_orm { } - namespace sqlite_orm { namespace internal { @@ -1265,7 +1260,6 @@ namespace sqlite_orm { // #include "getter_traits.h" - namespace sqlite_orm { namespace internal { @@ -1449,7 +1443,6 @@ namespace sqlite_orm { } } - namespace sqlite_orm { namespace internal { @@ -1780,7 +1773,6 @@ namespace sqlite_orm { // #include "optional_container.h" - namespace sqlite_orm { namespace internal { @@ -1813,7 +1805,6 @@ namespace sqlite_orm { } } - namespace sqlite_orm { namespace internal { @@ -3302,7 +3293,6 @@ namespace sqlite_orm { // #include "conditions.h" - namespace sqlite_orm { namespace internal { @@ -3422,7 +3412,6 @@ namespace sqlite_orm { // #include "is_base_of_template.h" - #include // std::true_type, std::false_type, std::declval namespace sqlite_orm { @@ -3460,7 +3449,6 @@ namespace sqlite_orm { } } - namespace sqlite_orm { namespace internal { @@ -4213,7 +4201,6 @@ namespace sqlite_orm { // #include "optional_container.h" - namespace sqlite_orm { namespace internal { @@ -4570,7 +4557,6 @@ namespace sqlite_orm { // #include "column.h" - namespace sqlite_orm { namespace internal { @@ -4612,12 +4598,12 @@ namespace sqlite_orm { namespace sqlite_orm { struct table_info { - int cid; + int cid = 0; std::string name; std::string type; - bool notnull; + bool notnull = false; std::string dflt_value; - int pk; + int pk = 0; }; } @@ -4677,7 +4663,6 @@ namespace sqlite_orm { // #include "is_std_ptr.h" - namespace sqlite_orm { /** @@ -4705,7 +4690,6 @@ namespace sqlite_orm { }; } - namespace sqlite_orm { /** @@ -4916,7 +4900,6 @@ namespace sqlite_orm { // #include "journal_mode.h" - #include // std::string #include // std::unique_ptr #include // std::array @@ -4977,7 +4960,6 @@ namespace sqlite_orm { // #include "error_code.h" - namespace sqlite_orm { /** @@ -5354,7 +5336,6 @@ namespace sqlite_orm { // #include "alias.h" - namespace sqlite_orm { namespace internal { @@ -5601,7 +5582,6 @@ namespace sqlite_orm { } } - namespace sqlite_orm { namespace internal { @@ -5841,7 +5821,6 @@ namespace sqlite_orm { // #include "column.h" - namespace sqlite_orm { namespace internal { @@ -6141,12 +6120,10 @@ namespace sqlite_orm { // #include "field_value_holder.h" - #include // std::enable_if // #include "column.h" - namespace sqlite_orm { namespace internal { @@ -6169,7 +6146,6 @@ namespace sqlite_orm { } } - namespace sqlite_orm { namespace internal { @@ -6671,7 +6647,6 @@ namespace sqlite_orm { // #include "view.h" - #include // std::shared_ptr #include // std::string #include // std::forward, std::move @@ -6687,7 +6662,6 @@ namespace sqlite_orm { // #include "iterator.h" - #include // std::shared_ptr, std::unique_ptr, std::make_shared #include #include // std::decay @@ -6703,7 +6677,6 @@ namespace sqlite_orm { // #include "error_code.h" - namespace sqlite_orm { namespace internal { @@ -6832,7 +6805,6 @@ namespace sqlite_orm { // #include "ast_iterator.h" - #include // std::vector #include // std::reference_wrapper @@ -6848,7 +6820,6 @@ namespace sqlite_orm { // #include "prepared_statement.h" - #include #include // std::iterator_traits #include // std::string @@ -6857,14 +6828,12 @@ namespace sqlite_orm { // #include "connection_holder.h" - #include #include // std::string #include // std::system_error // #include "error_code.h" - namespace sqlite_orm { namespace internal { @@ -6939,7 +6908,6 @@ namespace sqlite_orm { // #include "select_constraints.h" - namespace sqlite_orm { namespace internal { @@ -7007,9 +6975,13 @@ namespace sqlite_orm { prepared_statement_base{stmt, std::move(con_)}, t(std::move(t_)) {} }; - template + /** + * T - type of object to obtain from a database + */ + template struct get_all_t { using type = T; + using return_type = R; using conditions_type = std::tuple; @@ -7266,8 +7238,16 @@ namespace sqlite_orm { * T is an object type mapped to a storage. * Usage: storage.get_all(...); */ - template, class... Args> - internal::get_all_t get_all(Args... args) { + template + internal::get_all_t, Args...> get_all(Args... args) { + using args_tuple = std::tuple; + internal::validate_conditions(); + args_tuple conditions{std::forward(args)...}; + return {move(conditions)}; + } + + template + internal::get_all_t get_all(Args... args) { using args_tuple = std::tuple; internal::validate_conditions(); args_tuple conditions{std::forward(args)...}; @@ -7311,7 +7291,6 @@ namespace sqlite_orm { #endif // SQLITE_ORM_OPTIONAL_SUPPORTED } - namespace sqlite_orm { namespace internal { @@ -7456,9 +7435,9 @@ namespace sqlite_orm { } }; - template - struct ast_iterator, void> { - using node_type = get_all_t; + template + struct ast_iterator, void> { + using node_type = get_all_t; template void operator()(const node_type &get, const L &l) const { @@ -7789,7 +7768,6 @@ namespace sqlite_orm { // #include "connection_holder.h" - namespace sqlite_orm { namespace internal { @@ -7802,7 +7780,7 @@ namespace sqlite_orm { storage_type &storage; connection_ref connection; - get_all_t args; + get_all_t, Args...> args; view_t(storage_type &stor, decltype(connection) conn, Args &&... args_) : storage(stor), connection(std::move(conn)), args{std::make_tuple(std::forward(args_)...)} {} @@ -7848,7 +7826,6 @@ namespace sqlite_orm { // #include "storage_base.h" - #include // std::function, std::bind #include #include // std::string @@ -7863,7 +7840,6 @@ namespace sqlite_orm { // #include "pragma.h" - #include // std::string #include #include // std::function @@ -7877,7 +7853,6 @@ namespace sqlite_orm { // #include "connection_holder.h" - namespace sqlite_orm { namespace internal { @@ -7998,7 +7973,6 @@ namespace sqlite_orm { // #include "limit_accesor.h" - #include #include // std::map #include // std::function @@ -8006,7 +7980,6 @@ namespace sqlite_orm { // #include "connection_holder.h" - namespace sqlite_orm { namespace internal { @@ -8140,12 +8113,10 @@ namespace sqlite_orm { // #include "transaction_guard.h" - #include // std::function // #include "connection_holder.h" - namespace sqlite_orm { namespace internal { @@ -8220,7 +8191,6 @@ namespace sqlite_orm { // #include "backup.h" - #include #include // std::string #include @@ -8229,7 +8199,6 @@ namespace sqlite_orm { // #include "connection_holder.h" - namespace sqlite_orm { namespace internal { @@ -8295,7 +8264,6 @@ namespace sqlite_orm { } } - namespace sqlite_orm { namespace internal { @@ -8831,13 +8799,11 @@ namespace sqlite_orm { // #include "expression_object_type.h" - #include // std::decay #include // std::reference_wrapper // #include "prepared_statement.h" - namespace sqlite_orm { namespace internal { @@ -8957,7 +8923,6 @@ namespace sqlite_orm { // #include "statement_serializator.h" - #include // std::stringstream #include // std::string #include // std::is_arithmetic, std::enable_if @@ -8972,7 +8937,6 @@ namespace sqlite_orm { // #include "column.h" - namespace sqlite_orm { namespace internal { @@ -9262,7 +9226,6 @@ namespace sqlite_orm { // #include "table_name_collector.h" - #include // std::set #include // std::string #include // std::function @@ -9274,7 +9237,6 @@ namespace sqlite_orm { // #include "core_functions.h" - namespace sqlite_orm { namespace internal { @@ -9333,7 +9295,6 @@ namespace sqlite_orm { } - namespace sqlite_orm { namespace conditions { @@ -10534,10 +10495,17 @@ namespace sqlite_orm { * O is an object type to be extracted. Must be specified explicitly. * @return All objects of type O stored in database at the moment. */ - template, class... Args> - C get_all(Args &&... args) { + template + auto get_all(Args &&... args) { this->assert_mapped_type(); - auto statement = this->prepare(sqlite_orm::get_all(std::forward(args)...)); + auto statement = this->prepare(sqlite_orm::get_all(std::forward(args)...)); + return this->execute(statement); + } + + template + auto get_all(Args &&... args) { + this->assert_mapped_type(); + auto statement = this->prepare(sqlite_orm::get_all(std::forward(args)...)); return this->execute(statement); } @@ -11737,8 +11705,8 @@ namespace sqlite_orm { return res; } - template - C execute(const prepared_statement_t> &statement) { + template + R execute(const prepared_statement_t> &statement) { auto &impl = this->get_impl(); auto con = this->get_connection(); auto db = con.get(); @@ -11753,7 +11721,7 @@ namespace sqlite_orm { sqlite3_errmsg(db)); } }); - C res; + R res; int stepRes; do { stepRes = sqlite3_step(stmt); @@ -11917,20 +11885,19 @@ __pragma(pop_macro("min")) #include // std::pair #include // std::reference_wrapper -// #include "conditions.h" + // #include "conditions.h" -// #include "operators.h" + // #include "operators.h" -// #include "select_constraints.h" + // #include "select_constraints.h" -// #include "prepared_statement.h" + // #include "prepared_statement.h" -// #include "optional_container.h" + // #include "optional_container.h" -// #include "core_functions.h" + // #include "core_functions.h" - -namespace sqlite_orm { + namespace sqlite_orm { namespace internal { @@ -12008,9 +11975,9 @@ namespace sqlite_orm { using type = typename conc_tuple::type; }; - template - struct node_tuple, void> { - using node_type = get_all_t; + template + struct node_tuple, void> { + using node_type = get_all_t; using type = typename conc_tuple::type...>::type; }; @@ -12212,7 +12179,6 @@ namespace sqlite_orm { // #include "expression_object_type.h" - namespace sqlite_orm { template diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index cd022aeb2..0d3213113 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -10,7 +10,7 @@ else() add_subdirectory(third_party/sqlite) endif() -add_executable(unit_tests tests.cpp tests2.cpp tests3.cpp tests4.cpp tests5.cpp private_getters_tests.cpp pragma_tests.cpp explicit_columns.cpp core_functions_tests.cpp constraints/composite_key.cpp static_tests.cpp operators/arithmetic_operators.cpp operators/like.cpp operators/glob.cpp operators/in.cpp operators/cast.cpp operators/is_null.cpp operators/not_operator.cpp dynamic_order_by.cpp prepared_statement_tests/select.cpp prepared_statement_tests/get_all.cpp prepared_statement_tests/get_all_pointer.cpp prepared_statement_tests/get_all_optional.cpp prepared_statement_tests/update_all.cpp prepared_statement_tests/remove_all.cpp prepared_statement_tests/get.cpp prepared_statement_tests/get_pointer.cpp prepared_statement_tests/get_optional.cpp prepared_statement_tests/update.cpp prepared_statement_tests/remove.cpp prepared_statement_tests/insert.cpp prepared_statement_tests/replace.cpp prepared_statement_tests/insert_range.cpp prepared_statement_tests/replace_range.cpp prepared_statement_tests/insert_explicit.cpp pragma_tests.cpp simple_query.cpp static_tests/is_bindable.cpp static_tests/arithmetic_operators_result_type.cpp static_tests/tuple_conc.cpp static_tests/node_tuple.cpp static_tests/bindable_filter.cpp static_tests/count_tuple.cpp static_tests/member_traits_tests.cpp constraints/default.cpp constraints/foreign_key.cpp constraints/check.cpp table_tests.cpp statement_serializator_tests/primary_key.cpp statement_serializator_tests/column_names.cpp statement_serializator_tests/autoincrement.cpp statement_serializator_tests/arithmetic_operators.cpp statement_serializator_tests/core_functions.cpp statement_serializator_tests/comparison_operators.cpp statement_serializator_tests/unique.cpp statement_serializator_tests/foreign_key.cpp statement_serializator_tests/collate.cpp statement_serializator_tests/check.cpp unique_cases/get_all_with_two_tables.cpp unique_cases/prepare_get_all_with_case.cpp) +add_executable(unit_tests tests.cpp tests2.cpp tests3.cpp tests4.cpp tests5.cpp private_getters_tests.cpp pragma_tests.cpp explicit_columns.cpp core_functions_tests.cpp constraints/composite_key.cpp static_tests.cpp operators/arithmetic_operators.cpp operators/like.cpp operators/glob.cpp operators/in.cpp operators/cast.cpp operators/is_null.cpp operators/not_operator.cpp dynamic_order_by.cpp prepared_statement_tests/select.cpp prepared_statement_tests/get_all.cpp prepared_statement_tests/get_all_pointer.cpp prepared_statement_tests/get_all_optional.cpp prepared_statement_tests/update_all.cpp prepared_statement_tests/remove_all.cpp prepared_statement_tests/get.cpp prepared_statement_tests/get_pointer.cpp prepared_statement_tests/get_optional.cpp prepared_statement_tests/update.cpp prepared_statement_tests/remove.cpp prepared_statement_tests/insert.cpp prepared_statement_tests/replace.cpp prepared_statement_tests/insert_range.cpp prepared_statement_tests/replace_range.cpp prepared_statement_tests/insert_explicit.cpp pragma_tests.cpp simple_query.cpp static_tests/is_bindable.cpp static_tests/arithmetic_operators_result_type.cpp static_tests/tuple_conc.cpp static_tests/node_tuple.cpp static_tests/bindable_filter.cpp static_tests/count_tuple.cpp static_tests/member_traits_tests.cpp static_tests/select_return_type.cpp constraints/default.cpp constraints/foreign_key.cpp constraints/check.cpp table_tests.cpp statement_serializator_tests/primary_key.cpp statement_serializator_tests/column_names.cpp statement_serializator_tests/autoincrement.cpp statement_serializator_tests/arithmetic_operators.cpp statement_serializator_tests/core_functions.cpp statement_serializator_tests/comparison_operators.cpp statement_serializator_tests/unique.cpp statement_serializator_tests/foreign_key.cpp statement_serializator_tests/collate.cpp statement_serializator_tests/check.cpp unique_cases/get_all_with_two_tables.cpp unique_cases/prepare_get_all_with_case.cpp) if(SQLITE_ORM_OMITS_CODECVT) diff --git a/tests/static_tests.cpp b/tests/static_tests.cpp index fb91fec04..847e4db5e 100644 --- a/tests/static_tests.cpp +++ b/tests/static_tests.cpp @@ -1,44 +1,11 @@ - #include #include #include #include -using namespace sqlite_orm; - -struct User { - int id; - - const int &getIdByRefConst() const { - return this->id; - } - - const int &getIdByRef() { - return this->id; - } - - int getIdByValConst() const { - return this->id; - } - - void setIdByVal(int id) { - this->id = id; - } - - void setIdByConstRef(const int &id) { - this->id = id; - } - - void setIdByRef(int &id) { - this->id = id; - } -}; - -struct Object { - int id; -}; +#include "static_tests/static_tests_common.h" -struct Token : Object {}; +using namespace sqlite_orm; TEST_CASE("Column") { { @@ -271,64 +238,3 @@ TEST_CASE("Compound operators") { static_assert(internal::is_base_of_template::value, "except must be base of compound_operator"); } - -TEST_CASE("Select return types") { - auto storage = make_storage("", make_table("users", make_column("id", &User::id))); - // this call is important - it tests compilation in inner storage_t::serialize_column_schema function - storage.sync_schema(); - { - using SelectVectorInt = decltype(storage.select(&User::id)); - static_assert(std::is_same>::value, "Incorrect select id vector type"); - - using SelectVectorTuple = decltype(storage.select(columns(&User::id))); - auto ids = storage.select(columns(&User::id)); - static_assert(std::is_same::value, ""); - static_assert(std::is_same>>::value, - "Incorrect select id vector type"); - using IdsTuple = SelectVectorTuple::value_type; - static_assert(std::tuple_size::value == 1, "Incorrect tuple size"); - } - { - // test storage traits - struct Visit { - int id = 0; - std::string date; - }; - using namespace sqlite_orm::internal::storage_traits; - - // test type_is_mapped - static_assert(type_is_mapped::value, "User must be mapped to a storage"); - static_assert(!type_is_mapped::value, "User must be mapped to a storage"); - - // test is_storage - static_assert(internal::is_storage::value, "is_storage works incorrectly"); - static_assert(!internal::is_storage::value, "is_storage works incorrectly"); - static_assert(!internal::is_storage::value, "is_storage works incorrectly"); - static_assert(!internal::is_storage::value, "is_storage works incorrectly"); - - auto storage2 = make_storage( - "", - make_table("visits", make_column("id", &Visit::id, primary_key()), make_column("date", &Visit::date))); - - // test storage_columns_count - static_assert(storage_columns_count::value == 1, - "Incorrect storage columns count value"); - static_assert(storage_columns_count::value == 0, - "Incorrect storage columns count value"); - static_assert(storage_columns_count::value == 2, - "Incorrect storage columns count value"); - - // test storage mapped columns - using UserColumnsTuple = storage_mapped_columns::type; - static_assert(std::is_same>::value, - "Incorrect storage_mapped_columns result"); - - using VisitColumsEmptyType = storage_mapped_columns::type; - static_assert(std::is_same>::value, - "Incorrect storage_mapped_columns result"); - - using VisitColumnTypes = storage_mapped_columns::type; - static_assert(std::is_same>::value, - "Incorrect storage_mapped_columns result"); - } -} diff --git a/tests/static_tests/select_return_type.cpp b/tests/static_tests/select_return_type.cpp new file mode 100644 index 000000000..f94f64ef0 --- /dev/null +++ b/tests/static_tests/select_return_type.cpp @@ -0,0 +1,67 @@ +#include +#include + +#include "static_tests_common.h" + +using namespace sqlite_orm; + +TEST_CASE("Select return types") { + auto storage = make_storage("", make_table("users", make_column("id", &User::id))); + // this call is important - it tests compilation in inner storage_t::serialize_column_schema function + storage.sync_schema(); + { + using SelectVectorInt = decltype(storage.select(&User::id)); + static_assert(std::is_same>::value, "Incorrect select id vector type"); + + using SelectVectorTuple = decltype(storage.select(columns(&User::id))); + auto ids = storage.select(columns(&User::id)); + static_assert(std::is_same::value, ""); + static_assert(std::is_same>>::value, + "Incorrect select id vector type"); + using IdsTuple = SelectVectorTuple::value_type; + static_assert(std::tuple_size::value == 1, "Incorrect tuple size"); + } + { + // test storage traits + struct Visit { + int id = 0; + std::string date; + }; + using namespace sqlite_orm::internal::storage_traits; + + // test type_is_mapped + static_assert(type_is_mapped::value, "User must be mapped to a storage"); + static_assert(!type_is_mapped::value, "User must be mapped to a storage"); + + // test is_storage + static_assert(internal::is_storage::value, "is_storage works incorrectly"); + static_assert(!internal::is_storage::value, "is_storage works incorrectly"); + static_assert(!internal::is_storage::value, "is_storage works incorrectly"); + static_assert(!internal::is_storage::value, "is_storage works incorrectly"); + + auto storage2 = make_storage( + "", + make_table("visits", make_column("id", &Visit::id, primary_key()), make_column("date", &Visit::date))); + + // test storage_columns_count + static_assert(storage_columns_count::value == 1, + "Incorrect storage columns count value"); + static_assert(storage_columns_count::value == 0, + "Incorrect storage columns count value"); + static_assert(storage_columns_count::value == 2, + "Incorrect storage columns count value"); + + // test storage mapped columns + using UserColumnsTuple = storage_mapped_columns::type; + static_assert(std::is_same>::value, + "Incorrect storage_mapped_columns result"); + + using VisitColumsEmptyType = storage_mapped_columns::type; + static_assert(std::is_same>::value, + "Incorrect storage_mapped_columns result"); + + using VisitColumnTypes = storage_mapped_columns::type; + static_assert(std::is_same>::value, + "Incorrect storage_mapped_columns result"); + } +} diff --git a/tests/static_tests/static_tests_common.h b/tests/static_tests/static_tests_common.h new file mode 100644 index 000000000..80a67b4c9 --- /dev/null +++ b/tests/static_tests/static_tests_common.h @@ -0,0 +1,35 @@ +#pragma once + +struct User { + int id; + + const int &getIdByRefConst() const { + return this->id; + } + + const int &getIdByRef() { + return this->id; + } + + int getIdByValConst() const { + return this->id; + } + + void setIdByVal(int id) { + this->id = id; + } + + void setIdByConstRef(const int &id) { + this->id = id; + } + + void setIdByRef(int &id) { + this->id = id; + } +}; + +struct Object { + int id; +}; + +struct Token : Object {}; diff --git a/tests/tests2.cpp b/tests/tests2.cpp index e2e000195..8c8ad85a6 100644 --- a/tests/tests2.cpp +++ b/tests/tests2.cpp @@ -3,6 +3,8 @@ #ifdef SQLITE_ORM_OPTIONAL_SUPPORTED #include // std::optional #endif // SQLITE_ORM_OPTIONAL_SUPPORTED +#include +#include using namespace sqlite_orm; @@ -470,27 +472,45 @@ namespace get_all_deque { TEST_CASE("get_all deque") { using namespace get_all_deque; using Catch::Matchers::UnorderedEquals; - - auto storage = make_storage({}, - make_table("users", - make_column("id", &User::id, primary_key()), - make_column("name", &User::name))); + + auto storage = make_storage( + {}, + make_table("users", make_column("id", &User::id, primary_key()), make_column("name", &User::name))); storage.sync_schema(); - + User user1{1, "Nicki"}; User user2{2, "Karol"}; storage.replace(user1); storage.replace(user2); - + std::vector expected; expected.push_back(user1); expected.push_back(user2); { auto users = storage.get_all(); - REQUIRE_THAT(users, UnorderedEquals(expected)); + REQUIRE(std::equal(users.begin(), users.end(), expected.begin(), expected.end())); } { auto users = storage.get_all>(); - REQUIRE_THAT(users, UnorderedEquals(expected)); + REQUIRE(std::equal(users.begin(), users.end(), expected.begin(), expected.end())); + } + { + auto users = storage.get_all>(); + REQUIRE(std::equal(users.begin(), users.end(), expected.begin(), expected.end())); + } + { + auto statement = storage.prepare(get_all()); + auto users = storage.execute(statement); + REQUIRE(std::equal(users.begin(), users.end(), expected.begin(), expected.end())); + } + { + auto statement = storage.prepare(get_all>()); + auto users = storage.execute(statement); + REQUIRE(std::equal(users.begin(), users.end(), expected.begin(), expected.end())); + } + { + auto statement = storage.prepare(get_all>()); + auto users = storage.execute(statement); + REQUIRE(std::equal(users.begin(), users.end(), expected.begin(), expected.end())); } } From d4cb805764cc049bcd7e30582fceed5e14cf3be3 Mon Sep 17 00:00:00 2001 From: fnc12 Date: Tue, 3 Mar 2020 01:43:15 +0300 Subject: [PATCH 040/132] added static tests for return types in tests --- tests/tests2.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/tests/tests2.cpp b/tests/tests2.cpp index 8c8ad85a6..0112b93b9 100644 --- a/tests/tests2.cpp +++ b/tests/tests2.cpp @@ -489,28 +489,34 @@ TEST_CASE("get_all deque") { { auto users = storage.get_all(); REQUIRE(std::equal(users.begin(), users.end(), expected.begin(), expected.end())); + static_assert(std::is_same>::value, ""); } { auto users = storage.get_all>(); REQUIRE(std::equal(users.begin(), users.end(), expected.begin(), expected.end())); + static_assert(std::is_same>::value, ""); } { auto users = storage.get_all>(); REQUIRE(std::equal(users.begin(), users.end(), expected.begin(), expected.end())); + static_assert(std::is_same>::value, ""); } { auto statement = storage.prepare(get_all()); auto users = storage.execute(statement); REQUIRE(std::equal(users.begin(), users.end(), expected.begin(), expected.end())); + static_assert(std::is_same>::value, ""); } { auto statement = storage.prepare(get_all>()); auto users = storage.execute(statement); REQUIRE(std::equal(users.begin(), users.end(), expected.begin(), expected.end())); + static_assert(std::is_same>::value, ""); } { auto statement = storage.prepare(get_all>()); auto users = storage.execute(statement); REQUIRE(std::equal(users.begin(), users.end(), expected.begin(), expected.end())); + static_assert(std::is_same>::value, ""); } } From 971057e28d69fdaafb45359078b5170b190ef9f4 Mon Sep 17 00:00:00 2001 From: fnc12 Date: Tue, 3 Mar 2020 16:52:26 +0300 Subject: [PATCH 041/132] fixed shadowing local vars warnings in tests target --- dev/conditions.h | 4 +- dev/journal_mode.h | 4 +- dev/sqlite_type.h | 2 +- dev/storage.h | 199 ++++++++--------- include/sqlite_orm/sqlite_orm.h | 209 +++++++++--------- tests/operators/glob.cpp | 27 +-- tests/prepared_statement_tests/get_all.cpp | 46 ++-- tests/prepared_statement_tests/update_all.cpp | 38 ++-- tests/private_getters_tests.cpp | 4 +- tests/static_tests.cpp | 16 +- tests/static_tests/static_tests_common.h | 12 +- tests/tests2.cpp | 8 +- tests/tests4.cpp | 9 +- tests/tests5.cpp | 16 +- 14 files changed, 302 insertions(+), 292 deletions(-) diff --git a/dev/conditions.h b/dev/conditions.h index bf468caa4..774f11a88 100644 --- a/dev/conditions.h +++ b/dev/conditions.h @@ -651,8 +651,8 @@ namespace sqlite_orm { template like_t escape(C c) const { - sqlite_orm::internal::optional_container arg3{std::move(c)}; - return {std::move(this->arg), std::move(this->pattern), std::move(arg3)}; + sqlite_orm::internal::optional_container newArg3{std::move(c)}; + return {std::move(this->arg), std::move(this->pattern), std::move(newArg3)}; } negated_condition_t operator!() const { diff --git a/dev/journal_mode.h b/dev/journal_mode.h index dd6b3a032..c6079a2a3 100644 --- a/dev/journal_mode.h +++ b/dev/journal_mode.h @@ -39,7 +39,9 @@ namespace sqlite_orm { inline std::unique_ptr journal_mode_from_string(const std::string &str) { std::string upper_str; - std::transform(str.begin(), str.end(), std::back_inserter(upper_str), ::toupper); + std::transform(str.begin(), str.end(), std::back_inserter(upper_str), [](char c) { + return static_cast(std::toupper(static_cast(c))); + }); static std::array all = { journal_mode::DELETE, journal_mode::TRUNCATE, diff --git a/dev/sqlite_type.h b/dev/sqlite_type.h index a3b09535f..d2a1eece5 100644 --- a/dev/sqlite_type.h +++ b/dev/sqlite_type.h @@ -25,7 +25,7 @@ namespace sqlite_orm { inline std::unique_ptr to_sqlite_type(const std::string &str) { auto asciiStringToUpper = [](std::string &s) { std::transform(s.begin(), s.end(), s.begin(), [](char c) { - return std::toupper(c); + return static_cast(std::toupper(static_cast(c))); }); }; auto upperStr = str; diff --git a/dev/storage.h b/dev/storage.h index 3174eedfe..f13496c2c 100644 --- a/dev/storage.h +++ b/dev/storage.h @@ -89,14 +89,14 @@ namespace sqlite_orm { friend struct iterator_t; template - void create_table(sqlite3 *db, const std::string &tableName, I *impl) { + void create_table(sqlite3 *db, const std::string &tableName, I *tableImpl) { std::stringstream ss; ss << "CREATE TABLE '" << tableName << "' ( "; - auto columnsCount = impl->table.columns_count; + auto columnsCount = tableImpl->table.columns_count; auto index = 0; using context_t = serializator_context; context_t context{this->impl}; - iterate_tuple(impl->table.columns, [columnsCount, &index, &ss, &context](auto &c) { + iterate_tuple(tableImpl->table.columns, [columnsCount, &index, &ss, &context](auto &c) { ss << serialize(c, context); if(index < columnsCount - 1) { ss << ", "; @@ -104,7 +104,7 @@ namespace sqlite_orm { index++; }); ss << ") "; - if(impl->table._without_rowid) { + if(tableImpl->table._without_rowid) { ss << "WITHOUT ROWID "; } auto query = ss.str(); @@ -124,18 +124,18 @@ namespace sqlite_orm { } template - void backup_table(sqlite3 *db, I *impl) { + void backup_table(sqlite3 *db, I *tableImpl) { // here we copy source table to another with a name with '_backup' suffix, but in case table with such // a name already exists we append suffix 1, then 2, etc until we find a free name.. - auto backupTableName = impl->table.name + "_backup"; - if(impl->table_exists(backupTableName, db)) { + auto backupTableName = tableImpl->table.name + "_backup"; + if(tableImpl->table_exists(backupTableName, db)) { int suffix = 1; do { std::stringstream stream; stream << suffix; auto anotherBackupTableName = backupTableName + stream.str(); - if(!impl->table_exists(anotherBackupTableName, db)) { + if(!tableImpl->table_exists(anotherBackupTableName, db)) { backupTableName = anotherBackupTableName; break; } @@ -143,13 +143,13 @@ namespace sqlite_orm { } while(true); } - this->create_table(db, backupTableName, impl); + this->create_table(db, backupTableName, tableImpl); - impl->copy_table(db, backupTableName); + tableImpl->copy_table(db, backupTableName); - this->drop_table_internal(impl->table.name, db); + this->drop_table_internal(tableImpl->table.name, db); - impl->rename_table(db, backupTableName, impl->table.name); + tableImpl->rename_table(db, backupTableName, tableImpl->table.name); } template @@ -322,8 +322,8 @@ namespace sqlite_orm { if(!noTableName) { ss << "'" << this->impl.find_table_name(typeid(T)) << "'."; } - auto &impl = this->get_impl(); - ss << "\"" << impl.column_name_simple(c.field) << "\""; + auto &tImpl = this->get_impl(); + ss << "\"" << tImpl.column_name_simple(c.field) << "\""; return ss.str(); } @@ -440,10 +440,10 @@ namespace sqlite_orm { iterate_ast(get_query.conditions, collector); std::stringstream ss; ss << "SELECT "; - auto &impl = this->get_impl(); - auto columnNames = impl.table.column_names(); + auto &tImpl = this->get_impl(); + auto columnNames = tImpl.table.column_names(); for(size_t i = 0; i < columnNames.size(); ++i) { - ss << "\"" << impl.table.name << "\"." + ss << "\"" << tImpl.table.name << "\"." << "\"" << columnNames[i] << "\""; if(i < columnNames.size() - 1) { ss << ", "; @@ -531,9 +531,9 @@ namespace sqlite_orm { template std::string string_from_expression(const remove_all_t &rem, bool /*noTableName*/) const { - auto &impl = this->get_impl(); + auto &tImpl = this->get_impl(); std::stringstream ss; - ss << "DELETE FROM '" << impl.table.name << "' "; + ss << "DELETE FROM '" << tImpl.table.name << "' "; this->process_conditions(ss, rem.conditions); return ss.str(); } @@ -541,10 +541,10 @@ namespace sqlite_orm { // Common code for statements with conditions: get_t, get_pointer_t, get_optional_t. template std::string string_from_expression_impl_get(bool /*noTableName*/) const { - auto &impl = this->get_impl(); + auto &tImpl = this->get_impl(); std::stringstream ss; ss << "SELECT "; - auto columnNames = impl.table.column_names(); + auto columnNames = tImpl.table.column_names(); for(size_t i = 0; i < columnNames.size(); ++i) { ss << "\"" << columnNames[i] << "\""; if(i < columnNames.size() - 1) { @@ -552,8 +552,8 @@ namespace sqlite_orm { } ss << " "; } - ss << "FROM '" << impl.table.name << "' WHERE "; - auto primaryKeyColumnNames = impl.table.primary_key_column_names(); + ss << "FROM '" << tImpl.table.name << "' WHERE "; + auto primaryKeyColumnNames = tImpl.table.primary_key_column_names(); if(!primaryKeyColumnNames.empty()) { for(size_t i = 0; i < primaryKeyColumnNames.size(); ++i) { ss << "\"" << primaryKeyColumnNames[i] << "\"" @@ -590,12 +590,12 @@ namespace sqlite_orm { std::string string_from_expression(const update_t &upd, bool /*noTableName*/) const { using expression_type = typename std::decay::type; using object_type = typename expression_object_type::type; - auto &impl = this->get_impl(); + auto &tImpl = this->get_impl(); std::stringstream ss; - ss << "UPDATE '" << impl.table.name << "' SET "; + ss << "UPDATE '" << tImpl.table.name << "' SET "; std::vector setColumnNames; - impl.table.for_each_column([&setColumnNames](auto &c) { + tImpl.table.for_each_column([&setColumnNames](auto &c) { if(!c.template has>()) { setColumnNames.emplace_back(c.name); } @@ -609,7 +609,7 @@ namespace sqlite_orm { ss << " "; } ss << "WHERE "; - auto primaryKeyColumnNames = impl.table.primary_key_column_names(); + auto primaryKeyColumnNames = tImpl.table.primary_key_column_names(); for(size_t i = 0; i < primaryKeyColumnNames.size(); ++i) { ss << "\"" << primaryKeyColumnNames[i] << "\"" << " = ?"; @@ -623,11 +623,11 @@ namespace sqlite_orm { template std::string string_from_expression(const remove_t &, bool /*noTableName*/) const { - auto &impl = this->get_impl(); + auto &tImpl = this->get_impl(); std::stringstream ss; - ss << "DELETE FROM '" << impl.table.name << "' "; + ss << "DELETE FROM '" << tImpl.table.name << "' "; ss << "WHERE "; - auto primaryKeyColumnNames = impl.table.primary_key_column_names(); + auto primaryKeyColumnNames = tImpl.table.primary_key_column_names(); for(size_t i = 0; i < primaryKeyColumnNames.size(); ++i) { ss << "\"" << primaryKeyColumnNames[i] << "\"" << " = ? "; @@ -645,9 +645,9 @@ namespace sqlite_orm { using expression_type = typename std::decay::type; using object_type = typename expression_object_type::type; this->assert_mapped_type(); - auto &impl = this->get_impl(); + auto &tImpl = this->get_impl(); std::stringstream ss; - ss << "INSERT INTO '" << impl.table.name << "' "; + ss << "INSERT INTO '" << tImpl.table.name << "' "; std::vector columnNames; columnNames.reserve(colsCount); iterate_tuple(ins.columns.columns, [&columnNames, this](auto &m) { @@ -686,14 +686,14 @@ namespace sqlite_orm { using expression_type = typename std::decay::type; using object_type = typename expression_object_type::type; this->assert_mapped_type(); - auto &impl = this->get_impl(); + auto &tImpl = this->get_impl(); std::stringstream ss; - ss << "INSERT INTO '" << impl.table.name << "' "; + ss << "INSERT INTO '" << tImpl.table.name << "' "; std::vector columnNames; - auto compositeKeyColumnNames = impl.table.composite_key_columns_names(); + auto compositeKeyColumnNames = tImpl.table.composite_key_columns_names(); - impl.table.for_each_column([&impl, &columnNames, &compositeKeyColumnNames](auto &c) { - if(impl.table._without_rowid || !c.template has>()) { + tImpl.table.for_each_column([&tImpl, &columnNames, &compositeKeyColumnNames](auto &c) { + if(tImpl.table._without_rowid || !c.template has>()) { auto it = std::find(compositeKeyColumnNames.begin(), compositeKeyColumnNames.end(), c.name); if(it == compositeKeyColumnNames.end()) { columnNames.emplace_back(c.name); @@ -736,10 +736,10 @@ namespace sqlite_orm { using expression_type = typename std::decay::type; using object_type = typename expression_object_type::type; this->assert_mapped_type(); - auto &impl = this->get_impl(); + auto &tImpl = this->get_impl(); std::stringstream ss; - ss << "REPLACE INTO '" << impl.table.name << "' ("; - auto columnNames = impl.table.column_names(); + ss << "REPLACE INTO '" << tImpl.table.name << "' ("; + auto columnNames = tImpl.table.column_names(); auto columnNamesCount = columnNames.size(); for(size_t i = 0; i < columnNamesCount; ++i) { ss << "\"" << columnNames[i] << "\""; @@ -766,10 +766,10 @@ namespace sqlite_orm { std::string string_from_expression(const replace_range_t &rep, bool /*noTableName*/) const { using expression_type = typename std::decay::type; using object_type = typename expression_type::object_type; - auto &impl = this->get_impl(); + auto &tImpl = this->get_impl(); std::stringstream ss; - ss << "REPLACE INTO '" << impl.table.name << "' ("; - auto columnNames = impl.table.column_names(); + ss << "REPLACE INTO '" << tImpl.table.name << "' ("; + auto columnNames = tImpl.table.column_names(); auto columnNamesCount = columnNames.size(); for(size_t i = 0; i < columnNamesCount; ++i) { ss << "\"" << columnNames[i] << "\""; @@ -808,12 +808,12 @@ namespace sqlite_orm { std::string string_from_expression(const insert_range_t &ins, bool /*noTableName*/) const { using expression_type = typename std::decay::type; using object_type = typename expression_type::object_type; - auto &impl = this->get_impl(); + auto &tImpl = this->get_impl(); std::stringstream ss; - ss << "INSERT INTO '" << impl.table.name << "' ("; + ss << "INSERT INTO '" << tImpl.table.name << "' ("; std::vector columnNames; - impl.table.for_each_column([&columnNames](auto &c) { + tImpl.table.for_each_column([&columnNames](auto &c) { if(!c.template has>()) { columnNames.emplace_back(c.name); } @@ -1573,20 +1573,21 @@ namespace sqlite_orm { protected: template - sync_schema_result sync_table(storage_impl, Tss...> *impl, sqlite3 *db, bool) { + sync_schema_result + sync_table(storage_impl, Tss...> *tableImpl, sqlite3 *db, bool) { auto res = sync_schema_result::already_in_sync; std::stringstream ss; ss << "CREATE "; - if(impl->table.unique) { + if(tableImpl->table.unique) { ss << "UNIQUE "; } - using columns_type = typename decltype(impl->table)::columns_type; + using columns_type = typename decltype(tableImpl->table)::columns_type; using head_t = typename std::tuple_element<0, columns_type>::type; using indexed_type = typename internal::table_type::type; - ss << "INDEX IF NOT EXISTS '" << impl->table.name << "' ON '" + ss << "INDEX IF NOT EXISTS '" << tableImpl->table.name << "' ON '" << this->impl.find_table_name(typeid(indexed_type)) << "' ( "; std::vector columnNames; - iterate_tuple(impl->table.columns, [&columnNames, this](auto &v) { + iterate_tuple(tableImpl->table.columns, [&columnNames, this](auto &v) { columnNames.push_back(this->impl.column_name(v)); }); for(size_t i = 0; i < columnNames.size(); ++i) { @@ -1607,13 +1608,13 @@ namespace sqlite_orm { } template - sync_schema_result sync_table(storage_impl, Tss...> *impl, sqlite3 *db, bool preserve) { + sync_schema_result sync_table(storage_impl, Tss...> *tImpl, sqlite3 *db, bool preserve) { auto res = sync_schema_result::already_in_sync; - auto schema_stat = impl->schema_status(db, preserve); + auto schema_stat = tImpl->schema_status(db, preserve); if(schema_stat != decltype(schema_stat)::already_in_sync) { if(schema_stat == decltype(schema_stat)::new_table_created) { - this->create_table(db, impl->table.name, impl); + this->create_table(db, tImpl->table.name, tImpl); res = decltype(res)::new_table_created; } else { if(schema_stat == sync_schema_result::old_columns_removed || @@ -1621,26 +1622,26 @@ namespace sqlite_orm { schema_stat == sync_schema_result::new_columns_added_and_old_columns_removed) { // get table info provided in `make_table` call.. - auto storageTableInfo = impl->table.get_table_info(); + auto storageTableInfo = tImpl->table.get_table_info(); // now get current table info from db using `PRAGMA table_info` query.. - auto dbTableInfo = impl->get_table_info(impl->table.name, db); + auto dbTableInfo = tImpl->get_table_info(tImpl->table.name, db); // this vector will contain pointers to columns that gotta be added.. std::vector columnsToAdd; - impl->get_remove_add_columns(columnsToAdd, storageTableInfo, dbTableInfo); + tImpl->get_remove_add_columns(columnsToAdd, storageTableInfo, dbTableInfo); if(schema_stat == sync_schema_result::old_columns_removed) { // extra table columns than storage columns - this->backup_table(db, impl); + this->backup_table(db, tImpl); res = decltype(res)::old_columns_removed; } if(schema_stat == sync_schema_result::new_columns_added) { for(auto columnPointer: columnsToAdd) { - impl->add_column(*columnPointer, db); + tImpl->add_column(*columnPointer, db); } res = decltype(res)::new_columns_added; } @@ -1648,15 +1649,15 @@ namespace sqlite_orm { if(schema_stat == sync_schema_result::new_columns_added_and_old_columns_removed) { // remove extra columns - this->backup_table(db, impl); + this->backup_table(db, tImpl); for(auto columnPointer: columnsToAdd) { - impl->add_column(*columnPointer, db); + tImpl->add_column(*columnPointer, db); } res = decltype(res)::new_columns_added_and_old_columns_removed; } } else if(schema_stat == sync_schema_result::dropped_and_recreated) { - this->drop_table_internal(impl->table.name, db); - this->create_table(db, impl->table.name, impl); + this->drop_table_internal(tImpl->table.name, db); + this->create_table(db, tImpl->table.name, tImpl); res = decltype(res)::dropped_and_recreated; } } @@ -1696,9 +1697,9 @@ namespace sqlite_orm { auto con = this->get_connection(); std::map result; auto db = con.get(); - this->impl.for_each([&result, db, preserve, this](auto impl) { - auto res = this->sync_table(impl, db, preserve); - result.insert({impl->table.name, res}); + this->impl.for_each([&result, db, preserve, this](auto tableImpl) { + auto res = this->sync_table(tableImpl, db, preserve); + result.insert({tableImpl->table.name, res}); }); return result; } @@ -1712,8 +1713,8 @@ namespace sqlite_orm { auto con = this->get_connection(); std::map result; auto db = con.get(); - this->impl.for_each([&result, db, preserve](auto impl) { - result.insert({impl->table.name, impl->schema_status(db, preserve)}); + this->impl.for_each([&result, db, preserve](auto tableImpl) { + result.insert({tableImpl->table.name, tableImpl->schema_status(db, preserve)}); }); return result; } @@ -1967,13 +1968,13 @@ namespace sqlite_orm { auto con = this->get_connection(); auto db = con.get(); auto stmt = statement.stmt; - auto &impl = this->get_impl(); + auto &tImpl = this->get_impl(); auto &o = statement.t.obj; sqlite3_reset(stmt); - iterate_tuple(statement.t.columns.columns, [&o, &index, &stmt, &impl, db](auto &m) { + iterate_tuple(statement.t.columns.columns, [&o, &index, &stmt, &tImpl, db](auto &m) { using column_type = typename std::decay::type; using field_type = typename column_result_t::type; - const field_type *value = impl.table.template get_object_field_pointer(o, m); + const field_type *value = tImpl.table.template get_object_field_pointer(o, m); if(SQLITE_OK != statement_binder().bind(stmt, index++, *value)) { throw std::system_error(std::error_code(sqlite3_errcode(db), get_sqlite_error_category()), sqlite3_errmsg(db)); @@ -1992,7 +1993,7 @@ namespace sqlite_orm { using statement_type = typename std::decay::type; using expression_type = typename statement_type::expression_type; using object_type = typename expression_type::object_type; - auto &impl = this->get_impl(); + auto &tImpl = this->get_impl(); auto index = 1; auto con = this->get_connection(); auto db = con.get(); @@ -2000,7 +2001,7 @@ namespace sqlite_orm { sqlite3_reset(stmt); for(auto it = statement.t.range.first; it != statement.t.range.second; ++it) { auto &o = *it; - impl.table.for_each_column([&o, &index, &stmt, db](auto &c) { + tImpl.table.for_each_column([&o, &index, &stmt, db](auto &c) { using column_type = typename std::decay::type; using field_type = typename column_type::field_type; if(c.member_pointer) { @@ -2037,11 +2038,11 @@ namespace sqlite_orm { auto con = this->get_connection(); auto db = con.get(); auto stmt = statement.stmt; - auto &impl = this->get_impl(); + auto &tImpl = this->get_impl(); sqlite3_reset(stmt); for(auto it = statement.t.range.first; it != statement.t.range.second; ++it) { auto &o = *it; - impl.table.for_each_column([&o, &index, &stmt, db](auto &c) { + tImpl.table.for_each_column([&o, &index, &stmt, db](auto &c) { if(!c.template has>()) { using column_type = typename std::decay::type; using field_type = typename column_type::field_type; @@ -2082,9 +2083,9 @@ namespace sqlite_orm { auto stmt = statement.stmt; auto index = 1; auto &o = get_object(statement.t); - auto &impl = this->get_impl(); + auto &tImpl = this->get_impl(); sqlite3_reset(stmt); - impl.table.for_each_column([&o, &index, &stmt, db](auto &c) { + tImpl.table.for_each_column([&o, &index, &stmt, db](auto &c) { using column_type = typename std::decay::type; using field_type = typename column_type::field_type; if(c.member_pointer) { @@ -2119,12 +2120,12 @@ namespace sqlite_orm { auto db = con.get(); auto stmt = statement.stmt; auto index = 1; - auto &impl = this->get_impl(); + auto &tImpl = this->get_impl(); auto &o = get_object(statement.t); - auto compositeKeyColumnNames = impl.table.composite_key_columns_names(); + auto compositeKeyColumnNames = tImpl.table.composite_key_columns_names(); sqlite3_reset(stmt); - impl.table.for_each_column([&o, &index, &stmt, &impl, &compositeKeyColumnNames, db](auto &c) { - if(impl.table._without_rowid || !c.template has>()) { + tImpl.table.for_each_column([&o, &index, &stmt, &tImpl, &compositeKeyColumnNames, db](auto &c) { + if(tImpl.table._without_rowid || !c.template has>()) { auto it = std::find(compositeKeyColumnNames.begin(), compositeKeyColumnNames.end(), c.name); if(it == compositeKeyColumnNames.end()) { using column_type = typename std::decay::type; @@ -2186,12 +2187,12 @@ namespace sqlite_orm { using object_type = typename expression_object_type::type; auto con = this->get_connection(); auto db = con.get(); - auto &impl = this->get_impl(); + auto &tImpl = this->get_impl(); auto stmt = statement.stmt; auto index = 1; auto &o = get_object(statement.t); sqlite3_reset(stmt); - impl.table.for_each_column([&o, stmt, &index, db](auto &c) { + tImpl.table.for_each_column([&o, stmt, &index, db](auto &c) { if(!c.template has>()) { using column_type = typename std::decay::type; using field_type = typename column_type::field_type; @@ -2213,7 +2214,7 @@ namespace sqlite_orm { } } }); - impl.table.for_each_column([&o, stmt, &index, db](auto &c) { + tImpl.table.for_each_column([&o, stmt, &index, db](auto &c) { if(c.template has>()) { using column_type = typename std::decay::type; using field_type = typename column_type::field_type; @@ -2244,7 +2245,7 @@ namespace sqlite_orm { template std::unique_ptr execute(const prepared_statement_t> &statement) { - auto &impl = this->get_impl(); + auto &tImpl = this->get_impl(); auto con = this->get_connection(); auto db = con.get(); auto stmt = statement.stmt; @@ -2262,7 +2263,7 @@ namespace sqlite_orm { case SQLITE_ROW: { auto res = std::make_unique(); index = 0; - impl.table.for_each_column([&index, &res, stmt](auto &c) { + tImpl.table.for_each_column([&index, &res, stmt](auto &c) { using field_type = typename std::decay::type::field_type; auto value = row_extractor().extract(stmt, index++); if(c.member_pointer) { @@ -2286,7 +2287,7 @@ namespace sqlite_orm { #ifdef SQLITE_ORM_OPTIONAL_SUPPORTED template std::optional execute(const prepared_statement_t> &statement) { - auto &impl = this->get_impl(); + auto &tImpl = this->get_impl(); auto con = this->get_connection(); auto db = con.get(); auto stmt = statement.stmt; @@ -2304,7 +2305,7 @@ namespace sqlite_orm { case SQLITE_ROW: { auto res = std::make_optional(); index = 0; - impl.table.for_each_column([&index, &res, stmt](auto &c) { + tImpl.table.for_each_column([&index, &res, stmt](auto &c) { using field_type = typename std::decay::type::field_type; auto value = row_extractor().extract(stmt, index++); if(c.member_pointer) { @@ -2328,7 +2329,7 @@ namespace sqlite_orm { template T execute(const prepared_statement_t> &statement) { - auto &impl = this->get_impl(); + auto &tImpl = this->get_impl(); auto con = this->get_connection(); auto db = con.get(); auto stmt = statement.stmt; @@ -2346,7 +2347,7 @@ namespace sqlite_orm { case SQLITE_ROW: { T res; index = 0; - impl.table.for_each_column([&index, &res, stmt](auto &c) { + tImpl.table.for_each_column([&index, &res, stmt](auto &c) { using column_type = typename std::decay::type; using field_type = typename column_type::field_type; auto value = row_extractor().extract(stmt, index++); @@ -2460,7 +2461,7 @@ namespace sqlite_orm { template R execute(const prepared_statement_t> &statement) { - auto &impl = this->get_impl(); + auto &tImpl = this->get_impl(); auto con = this->get_connection(); auto db = con.get(); auto stmt = statement.stmt; @@ -2481,8 +2482,8 @@ namespace sqlite_orm { switch(stepRes) { case SQLITE_ROW: { T obj; - auto index = 0; - impl.table.for_each_column([&index, &obj, stmt](auto &c) { + index = 0; + tImpl.table.for_each_column([&index, &obj, stmt](auto &c) { using field_type = typename std::decay::type::field_type; auto value = row_extractor().extract(stmt, index++); if(c.member_pointer) { @@ -2507,7 +2508,7 @@ namespace sqlite_orm { template std::vector> execute(const prepared_statement_t> &statement) { - auto &impl = this->get_impl(); + auto &tImpl = this->get_impl(); auto con = this->get_connection(); auto db = con.get(); auto stmt = statement.stmt; @@ -2528,8 +2529,8 @@ namespace sqlite_orm { switch(stepRes) { case SQLITE_ROW: { auto obj = std::make_unique(); - auto index = 0; - impl.table.for_each_column([&index, &obj, stmt](auto &c) { + index = 0; + tImpl.table.for_each_column([&index, &obj, stmt](auto &c) { using field_type = typename std::decay::type::field_type; auto value = row_extractor().extract(stmt, index++); if(c.member_pointer) { @@ -2555,7 +2556,7 @@ namespace sqlite_orm { template std::vector> execute(const prepared_statement_t> &statement) { - auto &impl = this->get_impl(); + auto &tImpl = this->get_impl(); auto con = this->get_connection(); auto db = con.get(); auto stmt = statement.stmt; @@ -2576,8 +2577,8 @@ namespace sqlite_orm { switch(stepRes) { case SQLITE_ROW: { auto obj = std::make_optional(); - auto index = 0; - impl.table.for_each_column([&index, &obj, stmt](auto &c) { + index = 0; + tImpl.table.for_each_column([&index, &obj, stmt](auto &c) { using field_type = typename std::decay::type::field_type; auto value = row_extractor().extract(stmt, index++); if(c.member_pointer) { diff --git a/include/sqlite_orm/sqlite_orm.h b/include/sqlite_orm/sqlite_orm.h index 3cfe33f0c..13db2e954 100644 --- a/include/sqlite_orm/sqlite_orm.h +++ b/include/sqlite_orm/sqlite_orm.h @@ -158,7 +158,7 @@ namespace sqlite_orm { inline std::unique_ptr to_sqlite_type(const std::string &str) { auto asciiStringToUpper = [](std::string &s) { std::transform(s.begin(), s.end(), s.begin(), [](char c) { - return std::toupper(c); + return static_cast(std::toupper(static_cast(c))); }); }; auto upperStr = str; @@ -2447,8 +2447,8 @@ namespace sqlite_orm { template like_t escape(C c) const { - sqlite_orm::internal::optional_container arg3{std::move(c)}; - return {std::move(this->arg), std::move(this->pattern), std::move(arg3)}; + sqlite_orm::internal::optional_container newArg3{std::move(c)}; + return {std::move(this->arg), std::move(this->pattern), std::move(newArg3)}; } negated_condition_t operator!() const { @@ -4939,7 +4939,9 @@ namespace sqlite_orm { inline std::unique_ptr journal_mode_from_string(const std::string &str) { std::string upper_str; - std::transform(str.begin(), str.end(), std::back_inserter(upper_str), ::toupper); + std::transform(str.begin(), str.end(), std::back_inserter(upper_str), [](char c) { + return static_cast(std::toupper(static_cast(c))); + }); static std::array all = { journal_mode::DELETE, journal_mode::TRUNCATE, @@ -9336,14 +9338,14 @@ namespace sqlite_orm { friend struct iterator_t; template - void create_table(sqlite3 *db, const std::string &tableName, I *impl) { + void create_table(sqlite3 *db, const std::string &tableName, I *tableImpl) { std::stringstream ss; ss << "CREATE TABLE '" << tableName << "' ( "; - auto columnsCount = impl->table.columns_count; + auto columnsCount = tableImpl->table.columns_count; auto index = 0; using context_t = serializator_context; context_t context{this->impl}; - iterate_tuple(impl->table.columns, [columnsCount, &index, &ss, &context](auto &c) { + iterate_tuple(tableImpl->table.columns, [columnsCount, &index, &ss, &context](auto &c) { ss << serialize(c, context); if(index < columnsCount - 1) { ss << ", "; @@ -9351,7 +9353,7 @@ namespace sqlite_orm { index++; }); ss << ") "; - if(impl->table._without_rowid) { + if(tableImpl->table._without_rowid) { ss << "WITHOUT ROWID "; } auto query = ss.str(); @@ -9371,18 +9373,18 @@ namespace sqlite_orm { } template - void backup_table(sqlite3 *db, I *impl) { + void backup_table(sqlite3 *db, I *tableImpl) { // here we copy source table to another with a name with '_backup' suffix, but in case table with such // a name already exists we append suffix 1, then 2, etc until we find a free name.. - auto backupTableName = impl->table.name + "_backup"; - if(impl->table_exists(backupTableName, db)) { + auto backupTableName = tableImpl->table.name + "_backup"; + if(tableImpl->table_exists(backupTableName, db)) { int suffix = 1; do { std::stringstream stream; stream << suffix; auto anotherBackupTableName = backupTableName + stream.str(); - if(!impl->table_exists(anotherBackupTableName, db)) { + if(!tableImpl->table_exists(anotherBackupTableName, db)) { backupTableName = anotherBackupTableName; break; } @@ -9390,13 +9392,13 @@ namespace sqlite_orm { } while(true); } - this->create_table(db, backupTableName, impl); + this->create_table(db, backupTableName, tableImpl); - impl->copy_table(db, backupTableName); + tableImpl->copy_table(db, backupTableName); - this->drop_table_internal(impl->table.name, db); + this->drop_table_internal(tableImpl->table.name, db); - impl->rename_table(db, backupTableName, impl->table.name); + tableImpl->rename_table(db, backupTableName, tableImpl->table.name); } template @@ -9569,8 +9571,8 @@ namespace sqlite_orm { if(!noTableName) { ss << "'" << this->impl.find_table_name(typeid(T)) << "'."; } - auto &impl = this->get_impl(); - ss << "\"" << impl.column_name_simple(c.field) << "\""; + auto &tImpl = this->get_impl(); + ss << "\"" << tImpl.column_name_simple(c.field) << "\""; return ss.str(); } @@ -9687,10 +9689,10 @@ namespace sqlite_orm { iterate_ast(get_query.conditions, collector); std::stringstream ss; ss << "SELECT "; - auto &impl = this->get_impl(); - auto columnNames = impl.table.column_names(); + auto &tImpl = this->get_impl(); + auto columnNames = tImpl.table.column_names(); for(size_t i = 0; i < columnNames.size(); ++i) { - ss << "\"" << impl.table.name << "\"." + ss << "\"" << tImpl.table.name << "\"." << "\"" << columnNames[i] << "\""; if(i < columnNames.size() - 1) { ss << ", "; @@ -9778,9 +9780,9 @@ namespace sqlite_orm { template std::string string_from_expression(const remove_all_t &rem, bool /*noTableName*/) const { - auto &impl = this->get_impl(); + auto &tImpl = this->get_impl(); std::stringstream ss; - ss << "DELETE FROM '" << impl.table.name << "' "; + ss << "DELETE FROM '" << tImpl.table.name << "' "; this->process_conditions(ss, rem.conditions); return ss.str(); } @@ -9788,10 +9790,10 @@ namespace sqlite_orm { // Common code for statements with conditions: get_t, get_pointer_t, get_optional_t. template std::string string_from_expression_impl_get(bool /*noTableName*/) const { - auto &impl = this->get_impl(); + auto &tImpl = this->get_impl(); std::stringstream ss; ss << "SELECT "; - auto columnNames = impl.table.column_names(); + auto columnNames = tImpl.table.column_names(); for(size_t i = 0; i < columnNames.size(); ++i) { ss << "\"" << columnNames[i] << "\""; if(i < columnNames.size() - 1) { @@ -9799,8 +9801,8 @@ namespace sqlite_orm { } ss << " "; } - ss << "FROM '" << impl.table.name << "' WHERE "; - auto primaryKeyColumnNames = impl.table.primary_key_column_names(); + ss << "FROM '" << tImpl.table.name << "' WHERE "; + auto primaryKeyColumnNames = tImpl.table.primary_key_column_names(); if(!primaryKeyColumnNames.empty()) { for(size_t i = 0; i < primaryKeyColumnNames.size(); ++i) { ss << "\"" << primaryKeyColumnNames[i] << "\"" @@ -9837,12 +9839,12 @@ namespace sqlite_orm { std::string string_from_expression(const update_t &upd, bool /*noTableName*/) const { using expression_type = typename std::decay::type; using object_type = typename expression_object_type::type; - auto &impl = this->get_impl(); + auto &tImpl = this->get_impl(); std::stringstream ss; - ss << "UPDATE '" << impl.table.name << "' SET "; + ss << "UPDATE '" << tImpl.table.name << "' SET "; std::vector setColumnNames; - impl.table.for_each_column([&setColumnNames](auto &c) { + tImpl.table.for_each_column([&setColumnNames](auto &c) { if(!c.template has>()) { setColumnNames.emplace_back(c.name); } @@ -9856,7 +9858,7 @@ namespace sqlite_orm { ss << " "; } ss << "WHERE "; - auto primaryKeyColumnNames = impl.table.primary_key_column_names(); + auto primaryKeyColumnNames = tImpl.table.primary_key_column_names(); for(size_t i = 0; i < primaryKeyColumnNames.size(); ++i) { ss << "\"" << primaryKeyColumnNames[i] << "\"" << " = ?"; @@ -9870,11 +9872,11 @@ namespace sqlite_orm { template std::string string_from_expression(const remove_t &, bool /*noTableName*/) const { - auto &impl = this->get_impl(); + auto &tImpl = this->get_impl(); std::stringstream ss; - ss << "DELETE FROM '" << impl.table.name << "' "; + ss << "DELETE FROM '" << tImpl.table.name << "' "; ss << "WHERE "; - auto primaryKeyColumnNames = impl.table.primary_key_column_names(); + auto primaryKeyColumnNames = tImpl.table.primary_key_column_names(); for(size_t i = 0; i < primaryKeyColumnNames.size(); ++i) { ss << "\"" << primaryKeyColumnNames[i] << "\"" << " = ? "; @@ -9892,9 +9894,9 @@ namespace sqlite_orm { using expression_type = typename std::decay::type; using object_type = typename expression_object_type::type; this->assert_mapped_type(); - auto &impl = this->get_impl(); + auto &tImpl = this->get_impl(); std::stringstream ss; - ss << "INSERT INTO '" << impl.table.name << "' "; + ss << "INSERT INTO '" << tImpl.table.name << "' "; std::vector columnNames; columnNames.reserve(colsCount); iterate_tuple(ins.columns.columns, [&columnNames, this](auto &m) { @@ -9933,14 +9935,14 @@ namespace sqlite_orm { using expression_type = typename std::decay::type; using object_type = typename expression_object_type::type; this->assert_mapped_type(); - auto &impl = this->get_impl(); + auto &tImpl = this->get_impl(); std::stringstream ss; - ss << "INSERT INTO '" << impl.table.name << "' "; + ss << "INSERT INTO '" << tImpl.table.name << "' "; std::vector columnNames; - auto compositeKeyColumnNames = impl.table.composite_key_columns_names(); + auto compositeKeyColumnNames = tImpl.table.composite_key_columns_names(); - impl.table.for_each_column([&impl, &columnNames, &compositeKeyColumnNames](auto &c) { - if(impl.table._without_rowid || !c.template has>()) { + tImpl.table.for_each_column([&tImpl, &columnNames, &compositeKeyColumnNames](auto &c) { + if(tImpl.table._without_rowid || !c.template has>()) { auto it = std::find(compositeKeyColumnNames.begin(), compositeKeyColumnNames.end(), c.name); if(it == compositeKeyColumnNames.end()) { columnNames.emplace_back(c.name); @@ -9983,10 +9985,10 @@ namespace sqlite_orm { using expression_type = typename std::decay::type; using object_type = typename expression_object_type::type; this->assert_mapped_type(); - auto &impl = this->get_impl(); + auto &tImpl = this->get_impl(); std::stringstream ss; - ss << "REPLACE INTO '" << impl.table.name << "' ("; - auto columnNames = impl.table.column_names(); + ss << "REPLACE INTO '" << tImpl.table.name << "' ("; + auto columnNames = tImpl.table.column_names(); auto columnNamesCount = columnNames.size(); for(size_t i = 0; i < columnNamesCount; ++i) { ss << "\"" << columnNames[i] << "\""; @@ -10013,10 +10015,10 @@ namespace sqlite_orm { std::string string_from_expression(const replace_range_t &rep, bool /*noTableName*/) const { using expression_type = typename std::decay::type; using object_type = typename expression_type::object_type; - auto &impl = this->get_impl(); + auto &tImpl = this->get_impl(); std::stringstream ss; - ss << "REPLACE INTO '" << impl.table.name << "' ("; - auto columnNames = impl.table.column_names(); + ss << "REPLACE INTO '" << tImpl.table.name << "' ("; + auto columnNames = tImpl.table.column_names(); auto columnNamesCount = columnNames.size(); for(size_t i = 0; i < columnNamesCount; ++i) { ss << "\"" << columnNames[i] << "\""; @@ -10055,12 +10057,12 @@ namespace sqlite_orm { std::string string_from_expression(const insert_range_t &ins, bool /*noTableName*/) const { using expression_type = typename std::decay::type; using object_type = typename expression_type::object_type; - auto &impl = this->get_impl(); + auto &tImpl = this->get_impl(); std::stringstream ss; - ss << "INSERT INTO '" << impl.table.name << "' ("; + ss << "INSERT INTO '" << tImpl.table.name << "' ("; std::vector columnNames; - impl.table.for_each_column([&columnNames](auto &c) { + tImpl.table.for_each_column([&columnNames](auto &c) { if(!c.template has>()) { columnNames.emplace_back(c.name); } @@ -10820,20 +10822,21 @@ namespace sqlite_orm { protected: template - sync_schema_result sync_table(storage_impl, Tss...> *impl, sqlite3 *db, bool) { + sync_schema_result + sync_table(storage_impl, Tss...> *tableImpl, sqlite3 *db, bool) { auto res = sync_schema_result::already_in_sync; std::stringstream ss; ss << "CREATE "; - if(impl->table.unique) { + if(tableImpl->table.unique) { ss << "UNIQUE "; } - using columns_type = typename decltype(impl->table)::columns_type; + using columns_type = typename decltype(tableImpl->table)::columns_type; using head_t = typename std::tuple_element<0, columns_type>::type; using indexed_type = typename internal::table_type::type; - ss << "INDEX IF NOT EXISTS '" << impl->table.name << "' ON '" + ss << "INDEX IF NOT EXISTS '" << tableImpl->table.name << "' ON '" << this->impl.find_table_name(typeid(indexed_type)) << "' ( "; std::vector columnNames; - iterate_tuple(impl->table.columns, [&columnNames, this](auto &v) { + iterate_tuple(tableImpl->table.columns, [&columnNames, this](auto &v) { columnNames.push_back(this->impl.column_name(v)); }); for(size_t i = 0; i < columnNames.size(); ++i) { @@ -10854,13 +10857,13 @@ namespace sqlite_orm { } template - sync_schema_result sync_table(storage_impl, Tss...> *impl, sqlite3 *db, bool preserve) { + sync_schema_result sync_table(storage_impl, Tss...> *tImpl, sqlite3 *db, bool preserve) { auto res = sync_schema_result::already_in_sync; - auto schema_stat = impl->schema_status(db, preserve); + auto schema_stat = tImpl->schema_status(db, preserve); if(schema_stat != decltype(schema_stat)::already_in_sync) { if(schema_stat == decltype(schema_stat)::new_table_created) { - this->create_table(db, impl->table.name, impl); + this->create_table(db, tImpl->table.name, tImpl); res = decltype(res)::new_table_created; } else { if(schema_stat == sync_schema_result::old_columns_removed || @@ -10868,26 +10871,26 @@ namespace sqlite_orm { schema_stat == sync_schema_result::new_columns_added_and_old_columns_removed) { // get table info provided in `make_table` call.. - auto storageTableInfo = impl->table.get_table_info(); + auto storageTableInfo = tImpl->table.get_table_info(); // now get current table info from db using `PRAGMA table_info` query.. - auto dbTableInfo = impl->get_table_info(impl->table.name, db); + auto dbTableInfo = tImpl->get_table_info(tImpl->table.name, db); // this vector will contain pointers to columns that gotta be added.. std::vector columnsToAdd; - impl->get_remove_add_columns(columnsToAdd, storageTableInfo, dbTableInfo); + tImpl->get_remove_add_columns(columnsToAdd, storageTableInfo, dbTableInfo); if(schema_stat == sync_schema_result::old_columns_removed) { // extra table columns than storage columns - this->backup_table(db, impl); + this->backup_table(db, tImpl); res = decltype(res)::old_columns_removed; } if(schema_stat == sync_schema_result::new_columns_added) { for(auto columnPointer: columnsToAdd) { - impl->add_column(*columnPointer, db); + tImpl->add_column(*columnPointer, db); } res = decltype(res)::new_columns_added; } @@ -10895,15 +10898,15 @@ namespace sqlite_orm { if(schema_stat == sync_schema_result::new_columns_added_and_old_columns_removed) { // remove extra columns - this->backup_table(db, impl); + this->backup_table(db, tImpl); for(auto columnPointer: columnsToAdd) { - impl->add_column(*columnPointer, db); + tImpl->add_column(*columnPointer, db); } res = decltype(res)::new_columns_added_and_old_columns_removed; } } else if(schema_stat == sync_schema_result::dropped_and_recreated) { - this->drop_table_internal(impl->table.name, db); - this->create_table(db, impl->table.name, impl); + this->drop_table_internal(tImpl->table.name, db); + this->create_table(db, tImpl->table.name, tImpl); res = decltype(res)::dropped_and_recreated; } } @@ -10943,9 +10946,9 @@ namespace sqlite_orm { auto con = this->get_connection(); std::map result; auto db = con.get(); - this->impl.for_each([&result, db, preserve, this](auto impl) { - auto res = this->sync_table(impl, db, preserve); - result.insert({impl->table.name, res}); + this->impl.for_each([&result, db, preserve, this](auto tableImpl) { + auto res = this->sync_table(tableImpl, db, preserve); + result.insert({tableImpl->table.name, res}); }); return result; } @@ -10959,8 +10962,8 @@ namespace sqlite_orm { auto con = this->get_connection(); std::map result; auto db = con.get(); - this->impl.for_each([&result, db, preserve](auto impl) { - result.insert({impl->table.name, impl->schema_status(db, preserve)}); + this->impl.for_each([&result, db, preserve](auto tableImpl) { + result.insert({tableImpl->table.name, tableImpl->schema_status(db, preserve)}); }); return result; } @@ -11214,13 +11217,13 @@ namespace sqlite_orm { auto con = this->get_connection(); auto db = con.get(); auto stmt = statement.stmt; - auto &impl = this->get_impl(); + auto &tImpl = this->get_impl(); auto &o = statement.t.obj; sqlite3_reset(stmt); - iterate_tuple(statement.t.columns.columns, [&o, &index, &stmt, &impl, db](auto &m) { + iterate_tuple(statement.t.columns.columns, [&o, &index, &stmt, &tImpl, db](auto &m) { using column_type = typename std::decay::type; using field_type = typename column_result_t::type; - const field_type *value = impl.table.template get_object_field_pointer(o, m); + const field_type *value = tImpl.table.template get_object_field_pointer(o, m); if(SQLITE_OK != statement_binder().bind(stmt, index++, *value)) { throw std::system_error(std::error_code(sqlite3_errcode(db), get_sqlite_error_category()), sqlite3_errmsg(db)); @@ -11239,7 +11242,7 @@ namespace sqlite_orm { using statement_type = typename std::decay::type; using expression_type = typename statement_type::expression_type; using object_type = typename expression_type::object_type; - auto &impl = this->get_impl(); + auto &tImpl = this->get_impl(); auto index = 1; auto con = this->get_connection(); auto db = con.get(); @@ -11247,7 +11250,7 @@ namespace sqlite_orm { sqlite3_reset(stmt); for(auto it = statement.t.range.first; it != statement.t.range.second; ++it) { auto &o = *it; - impl.table.for_each_column([&o, &index, &stmt, db](auto &c) { + tImpl.table.for_each_column([&o, &index, &stmt, db](auto &c) { using column_type = typename std::decay::type; using field_type = typename column_type::field_type; if(c.member_pointer) { @@ -11284,11 +11287,11 @@ namespace sqlite_orm { auto con = this->get_connection(); auto db = con.get(); auto stmt = statement.stmt; - auto &impl = this->get_impl(); + auto &tImpl = this->get_impl(); sqlite3_reset(stmt); for(auto it = statement.t.range.first; it != statement.t.range.second; ++it) { auto &o = *it; - impl.table.for_each_column([&o, &index, &stmt, db](auto &c) { + tImpl.table.for_each_column([&o, &index, &stmt, db](auto &c) { if(!c.template has>()) { using column_type = typename std::decay::type; using field_type = typename column_type::field_type; @@ -11329,9 +11332,9 @@ namespace sqlite_orm { auto stmt = statement.stmt; auto index = 1; auto &o = get_object(statement.t); - auto &impl = this->get_impl(); + auto &tImpl = this->get_impl(); sqlite3_reset(stmt); - impl.table.for_each_column([&o, &index, &stmt, db](auto &c) { + tImpl.table.for_each_column([&o, &index, &stmt, db](auto &c) { using column_type = typename std::decay::type; using field_type = typename column_type::field_type; if(c.member_pointer) { @@ -11366,12 +11369,12 @@ namespace sqlite_orm { auto db = con.get(); auto stmt = statement.stmt; auto index = 1; - auto &impl = this->get_impl(); + auto &tImpl = this->get_impl(); auto &o = get_object(statement.t); - auto compositeKeyColumnNames = impl.table.composite_key_columns_names(); + auto compositeKeyColumnNames = tImpl.table.composite_key_columns_names(); sqlite3_reset(stmt); - impl.table.for_each_column([&o, &index, &stmt, &impl, &compositeKeyColumnNames, db](auto &c) { - if(impl.table._without_rowid || !c.template has>()) { + tImpl.table.for_each_column([&o, &index, &stmt, &tImpl, &compositeKeyColumnNames, db](auto &c) { + if(tImpl.table._without_rowid || !c.template has>()) { auto it = std::find(compositeKeyColumnNames.begin(), compositeKeyColumnNames.end(), c.name); if(it == compositeKeyColumnNames.end()) { using column_type = typename std::decay::type; @@ -11433,12 +11436,12 @@ namespace sqlite_orm { using object_type = typename expression_object_type::type; auto con = this->get_connection(); auto db = con.get(); - auto &impl = this->get_impl(); + auto &tImpl = this->get_impl(); auto stmt = statement.stmt; auto index = 1; auto &o = get_object(statement.t); sqlite3_reset(stmt); - impl.table.for_each_column([&o, stmt, &index, db](auto &c) { + tImpl.table.for_each_column([&o, stmt, &index, db](auto &c) { if(!c.template has>()) { using column_type = typename std::decay::type; using field_type = typename column_type::field_type; @@ -11460,7 +11463,7 @@ namespace sqlite_orm { } } }); - impl.table.for_each_column([&o, stmt, &index, db](auto &c) { + tImpl.table.for_each_column([&o, stmt, &index, db](auto &c) { if(c.template has>()) { using column_type = typename std::decay::type; using field_type = typename column_type::field_type; @@ -11491,7 +11494,7 @@ namespace sqlite_orm { template std::unique_ptr execute(const prepared_statement_t> &statement) { - auto &impl = this->get_impl(); + auto &tImpl = this->get_impl(); auto con = this->get_connection(); auto db = con.get(); auto stmt = statement.stmt; @@ -11509,7 +11512,7 @@ namespace sqlite_orm { case SQLITE_ROW: { auto res = std::make_unique(); index = 0; - impl.table.for_each_column([&index, &res, stmt](auto &c) { + tImpl.table.for_each_column([&index, &res, stmt](auto &c) { using field_type = typename std::decay::type::field_type; auto value = row_extractor().extract(stmt, index++); if(c.member_pointer) { @@ -11533,7 +11536,7 @@ namespace sqlite_orm { #ifdef SQLITE_ORM_OPTIONAL_SUPPORTED template std::optional execute(const prepared_statement_t> &statement) { - auto &impl = this->get_impl(); + auto &tImpl = this->get_impl(); auto con = this->get_connection(); auto db = con.get(); auto stmt = statement.stmt; @@ -11551,7 +11554,7 @@ namespace sqlite_orm { case SQLITE_ROW: { auto res = std::make_optional(); index = 0; - impl.table.for_each_column([&index, &res, stmt](auto &c) { + tImpl.table.for_each_column([&index, &res, stmt](auto &c) { using field_type = typename std::decay::type::field_type; auto value = row_extractor().extract(stmt, index++); if(c.member_pointer) { @@ -11575,7 +11578,7 @@ namespace sqlite_orm { template T execute(const prepared_statement_t> &statement) { - auto &impl = this->get_impl(); + auto &tImpl = this->get_impl(); auto con = this->get_connection(); auto db = con.get(); auto stmt = statement.stmt; @@ -11593,7 +11596,7 @@ namespace sqlite_orm { case SQLITE_ROW: { T res; index = 0; - impl.table.for_each_column([&index, &res, stmt](auto &c) { + tImpl.table.for_each_column([&index, &res, stmt](auto &c) { using column_type = typename std::decay::type; using field_type = typename column_type::field_type; auto value = row_extractor().extract(stmt, index++); @@ -11707,7 +11710,7 @@ namespace sqlite_orm { template R execute(const prepared_statement_t> &statement) { - auto &impl = this->get_impl(); + auto &tImpl = this->get_impl(); auto con = this->get_connection(); auto db = con.get(); auto stmt = statement.stmt; @@ -11728,8 +11731,8 @@ namespace sqlite_orm { switch(stepRes) { case SQLITE_ROW: { T obj; - auto index = 0; - impl.table.for_each_column([&index, &obj, stmt](auto &c) { + index = 0; + tImpl.table.for_each_column([&index, &obj, stmt](auto &c) { using field_type = typename std::decay::type::field_type; auto value = row_extractor().extract(stmt, index++); if(c.member_pointer) { @@ -11754,7 +11757,7 @@ namespace sqlite_orm { template std::vector> execute(const prepared_statement_t> &statement) { - auto &impl = this->get_impl(); + auto &tImpl = this->get_impl(); auto con = this->get_connection(); auto db = con.get(); auto stmt = statement.stmt; @@ -11775,8 +11778,8 @@ namespace sqlite_orm { switch(stepRes) { case SQLITE_ROW: { auto obj = std::make_unique(); - auto index = 0; - impl.table.for_each_column([&index, &obj, stmt](auto &c) { + index = 0; + tImpl.table.for_each_column([&index, &obj, stmt](auto &c) { using field_type = typename std::decay::type::field_type; auto value = row_extractor().extract(stmt, index++); if(c.member_pointer) { @@ -11802,7 +11805,7 @@ namespace sqlite_orm { template std::vector> execute(const prepared_statement_t> &statement) { - auto &impl = this->get_impl(); + auto &tImpl = this->get_impl(); auto con = this->get_connection(); auto db = con.get(); auto stmt = statement.stmt; @@ -11823,8 +11826,8 @@ namespace sqlite_orm { switch(stepRes) { case SQLITE_ROW: { auto obj = std::make_optional(); - auto index = 0; - impl.table.for_each_column([&index, &obj, stmt](auto &c) { + index = 0; + tImpl.table.for_each_column([&index, &obj, stmt](auto &c) { using field_type = typename std::decay::type::field_type; auto value = row_extractor().extract(stmt, index++); if(c.member_pointer) { diff --git a/tests/operators/glob.cpp b/tests/operators/glob.cpp index 8ad24bf0d..7b461b892 100644 --- a/tests/operators/glob.cpp +++ b/tests/operators/glob.cpp @@ -25,19 +25,20 @@ TEST_CASE("Glob") { make_column("salary", &Employee::salary), make_column("dept_id", &Employee::deptId))); storage.sync_schema(); - - std::vector employees = { - Employee{1, "Honey", "Patel", 10100, 1}, - Employee{2, "Shweta", "Jariwala", 19300, 2}, - Employee{3, "Vinay", "Jariwala", 35100, 3}, - Employee{4, "Jagruti", "Viras", 9500, 2}, - Employee{5, "Shweta", "Rana", 12000, 3}, - Employee{6, "sonal", "Menpara", 13000, 1}, - Employee{7, "Yamini", "Patel", 10000, 2}, - Employee{8, "Khyati", "Shah", 500000, 3}, - Employee{9, "Shwets", "Jariwala", 19400, 2}, - }; - storage.replace_range(employees.begin(), employees.end()); + { + std::vector employees = { + Employee{1, "Honey", "Patel", 10100, 1}, + Employee{2, "Shweta", "Jariwala", 19300, 2}, + Employee{3, "Vinay", "Jariwala", 35100, 3}, + Employee{4, "Jagruti", "Viras", 9500, 2}, + Employee{5, "Shweta", "Rana", 12000, 3}, + Employee{6, "sonal", "Menpara", 13000, 1}, + Employee{7, "Yamini", "Patel", 10000, 2}, + Employee{8, "Khyati", "Shah", 500000, 3}, + Employee{9, "Shwets", "Jariwala", 19400, 2}, + }; + storage.replace_range(employees.begin(), employees.end()); + } auto expectIds = [](const std::vector &employees, const std::vector ids) { for(auto expectedId: ids) { diff --git a/tests/prepared_statement_tests/get_all.cpp b/tests/prepared_statement_tests/get_all.cpp index 5093ee179..3dbfe76f4 100644 --- a/tests/prepared_statement_tests/get_all.cpp +++ b/tests/prepared_statement_tests/get_all.cpp @@ -150,30 +150,32 @@ TEST_CASE("Prepared get all") { REQUIRE(get<3>(statement) == 20.0f); } { - { // by val - auto statement = storage.prepare(get_all(where(lesser_than(&User::id, 2)))); - std::vector expected; - REQUIRE(get<0>(statement) == 2); - expected.push_back(User{1, "Team BS"}); - { - auto rows = storage.execute(statement); - REQUIRE_THAT(rows, UnorderedEquals(expected)); - } + { + { // by val + auto statement = storage.prepare(get_all(where(lesser_than(&User::id, 2)))); + std::vector expected; + REQUIRE(get<0>(statement) == 2); + expected.push_back(User{1, "Team BS"}); + { + auto rows = storage.execute(statement); + REQUIRE_THAT(rows, UnorderedEquals(expected)); + } - get<0>(statement) = 3; - REQUIRE(get<0>(statement) == 3); - expected.push_back(User{2, "Shy'm"}); - { - auto rows = storage.execute(statement); - REQUIRE_THAT(rows, UnorderedEquals(expected)); - } + get<0>(statement) = 3; + REQUIRE(get<0>(statement) == 3); + expected.push_back(User{2, "Shy'm"}); + { + auto rows = storage.execute(statement); + REQUIRE_THAT(rows, UnorderedEquals(expected)); + } - get<0>(statement) = 4; - REQUIRE(get<0>(statement) == 4); - expected.push_back(User{3, "Maรฎtre Gims"}); - { - auto rows = storage.execute(statement); - REQUIRE_THAT(rows, UnorderedEquals(expected)); + get<0>(statement) = 4; + REQUIRE(get<0>(statement) == 4); + expected.push_back(User{3, "Maรฎtre Gims"}); + { + auto rows = storage.execute(statement); + REQUIRE_THAT(rows, UnorderedEquals(expected)); + } } { // by ref auto id = 2; diff --git a/tests/prepared_statement_tests/update_all.cpp b/tests/prepared_statement_tests/update_all.cpp index aedb9608d..00efd6c32 100644 --- a/tests/prepared_statement_tests/update_all.cpp +++ b/tests/prepared_statement_tests/update_all.cpp @@ -74,11 +74,11 @@ TEST_CASE("Prepared update all") { expected.push_back("Maรฎtre Gims_123"); REQUIRE_THAT(names, UnorderedEquals(expected)); } - auto statement = storage.prepare( + auto statement2 = storage.prepare( update_all(set(c(&User::name) = c(&User::name) || "!"), where(like(&User::name, "T%")))); - REQUIRE(strcmp(get<0>(statement), "!") == 0); - REQUIRE(strcmp(get<1>(statement), "T%") == 0); - storage.execute(statement); + REQUIRE(strcmp(get<0>(statement2), "!") == 0); + REQUIRE(strcmp(get<1>(statement2), "T%") == 0); + storage.execute(statement2); { auto names = storage.select(&User::name); std::vector expected; @@ -87,11 +87,11 @@ TEST_CASE("Prepared update all") { expected.push_back("Maรฎtre Gims_123"); REQUIRE_THAT(names, UnorderedEquals(expected)); } - get<0>(statement) = "@"; - get<1>(statement) = "Sh%"; - REQUIRE(strcmp(get<0>(statement), "@") == 0); - REQUIRE(strcmp(get<1>(statement), "Sh%") == 0); - storage.execute(statement); + get<0>(statement2) = "@"; + get<1>(statement2) = "Sh%"; + REQUIRE(strcmp(get<0>(statement2), "@") == 0); + REQUIRE(strcmp(get<1>(statement2), "Sh%") == 0); + storage.execute(statement2); { auto names = storage.select(&User::name); std::vector expected; @@ -144,13 +144,13 @@ TEST_CASE("Prepared update all") { } std::string name = "!"; std::string pattern = "T%"; - auto statement = storage.prepare(update_all(set(c(&User::name) = c(&User::name) || std::ref(name)), - where(like(&User::name, std::ref(pattern))))); - REQUIRE(get<0>(statement) == "!"); - REQUIRE(&get<0>(statement) == &name); - REQUIRE(get<1>(statement) == "T%"); - REQUIRE(&get<1>(statement) == &pattern); - storage.execute(statement); + auto statement2 = storage.prepare(update_all(set(c(&User::name) = c(&User::name) || std::ref(name)), + where(like(&User::name, std::ref(pattern))))); + REQUIRE(get<0>(statement2) == "!"); + REQUIRE(&get<0>(statement2) == &name); + REQUIRE(get<1>(statement2) == "T%"); + REQUIRE(&get<1>(statement2) == &pattern); + storage.execute(statement2); { auto names = storage.select(&User::name); std::vector expected; @@ -161,9 +161,9 @@ TEST_CASE("Prepared update all") { } name = "@"; pattern = "Sh%"; - REQUIRE(get<0>(statement) == "@"); - REQUIRE(get<1>(statement) == "Sh%"); - storage.execute(statement); + REQUIRE(get<0>(statement2) == "@"); + REQUIRE(get<1>(statement2) == "Sh%"); + storage.execute(statement2); { auto names = storage.select(&User::name); std::vector expected; diff --git a/tests/private_getters_tests.cpp b/tests/private_getters_tests.cpp index 494b68837..846ef756a 100644 --- a/tests/private_getters_tests.cpp +++ b/tests/private_getters_tests.cpp @@ -16,8 +16,8 @@ TEST_CASE("Issue 343") { return this->id; } - void setId(int id) { - this->id = id; + void setId(int id_) { + this->id = id_; } std::string name; diff --git a/tests/static_tests.cpp b/tests/static_tests.cpp index 847e4db5e..6ae6bd1a9 100644 --- a/tests/static_tests.cpp +++ b/tests/static_tests.cpp @@ -98,32 +98,32 @@ TEST_CASE("Aggregate function return types") { return this->id; } - void setIdByVal(int id) { - this->id = id; + void setIdByVal(int id_) { + this->id = id_; } std::string getNameByVal() { return this->name; } - void setNameByConstRef(const std::string &name) { - this->name = name; + void setNameByConstRef(const std::string &name_) { + this->name = name_; } const int &getConstIdByRefConst() const { return this->id; } - void setIdByRef(int &id) { - this->id = id; + void setIdByRef(int &id_) { + this->id = id_; } const std::string &getConstNameByRefConst() const { return this->name; } - void setNameByRef(std::string &name) { - this->name = std::move(name); + void setNameByRef(std::string &name_) { + this->name = std::move(name_); } }; const std::string filename = "static_tests.sqlite"; diff --git a/tests/static_tests/static_tests_common.h b/tests/static_tests/static_tests_common.h index 80a67b4c9..b27ae1e26 100644 --- a/tests/static_tests/static_tests_common.h +++ b/tests/static_tests/static_tests_common.h @@ -15,16 +15,16 @@ struct User { return this->id; } - void setIdByVal(int id) { - this->id = id; + void setIdByVal(int id_) { + this->id = id_; } - void setIdByConstRef(const int &id) { - this->id = id; + void setIdByConstRef(const int &id_) { + this->id = id_; } - void setIdByRef(int &id) { - this->id = id; + void setIdByRef(int &id_) { + this->id = id_; } }; diff --git a/tests/tests2.cpp b/tests/tests2.cpp index 0112b93b9..e49b9437c 100644 --- a/tests/tests2.cpp +++ b/tests/tests2.cpp @@ -322,16 +322,16 @@ TEST_CASE("Replace query") { return this->id; } - void setId(int id) { - this->id = id; + void setId(int id_) { + this->id = id_; } std::string getName() const { return this->name; } - void setName(std::string name) { - this->name = move(name); + void setName(std::string name_) { + this->name = move(name_); } private: diff --git a/tests/tests4.cpp b/tests/tests4.cpp index ea4136d8e..885b8c7ba 100644 --- a/tests/tests4.cpp +++ b/tests/tests4.cpp @@ -273,10 +273,11 @@ TEST_CASE("Set null") { storage.replace(User{1, std::make_unique("Ototo")}); REQUIRE(storage.count() == 1); - - auto rows = storage.get_all(); - REQUIRE(rows.size() == 1); - REQUIRE(rows.front().name); + { + auto rows = storage.get_all(); + REQUIRE(rows.size() == 1); + REQUIRE(rows.front().name); + } storage.update_all(set(assign(&User::name, nullptr))); { diff --git a/tests/tests5.cpp b/tests/tests5.cpp index aac2f76bf..0277d9802 100644 --- a/tests/tests5.cpp +++ b/tests/tests5.cpp @@ -154,32 +154,32 @@ TEST_CASE("Different getters and setters") { return this->id; } - void setIdByVal(int id) { - this->id = id; + void setIdByVal(int id_) { + this->id = id_; } std::string getNameByVal() { return this->name; } - void setNameByConstRef(const std::string &name) { - this->name = name; + void setNameByConstRef(const std::string &name_) { + this->name = name_; } const int &getConstIdByRefConst() const { return this->id; } - void setIdByRef(int &id) { - this->id = id; + void setIdByRef(int &id_) { + this->id = id_; } const std::string &getConstNameByRefConst() const { return this->name; } - void setNameByRef(std::string &name) { - this->name = std::move(name); + void setNameByRef(std::string &name_) { + this->name = std::move(name_); } }; From 1116f699d6f3b58280a75a1a42a921b661dd05f5 Mon Sep 17 00:00:00 2001 From: fnc12 Date: Tue, 3 Mar 2020 23:14:23 +0300 Subject: [PATCH 042/132] fixed unused arguments warning --- dev/serializator_context.h | 2 +- dev/statement_serializator.h | 12 ++++++------ dev/storage_impl.h | 2 +- dev/table_name_collector.h | 2 +- include/sqlite_orm/sqlite_orm.h | 18 +++++++++--------- 5 files changed, 18 insertions(+), 18 deletions(-) diff --git a/dev/serializator_context.h b/dev/serializator_context.h index fa679eacd..4e6065725 100644 --- a/dev/serializator_context.h +++ b/dev/serializator_context.h @@ -7,7 +7,7 @@ namespace sqlite_orm { struct serializator_context_base { template - std::string column_name(F O::*m) const { + std::string column_name(F O::*) const { return {}; } }; diff --git a/dev/statement_serializator.h b/dev/statement_serializator.h index d8a35a8fd..be998d8ed 100644 --- a/dev/statement_serializator.h +++ b/dev/statement_serializator.h @@ -64,7 +64,7 @@ namespace sqlite_orm { using statement_type = constraints::autoincrement_t; template - std::string operator()(const statement_type &c, const C &context) const { + std::string operator()(const statement_type &c, const C &) const { return static_cast(c); } }; @@ -99,7 +99,7 @@ namespace sqlite_orm { using statement_type = constraints::unique_t; template - std::string operator()(const statement_type &c, const C &context) const { + std::string operator()(const statement_type &c, const C &) const { return static_cast(c); } }; @@ -109,7 +109,7 @@ namespace sqlite_orm { using statement_type = constraints::collate_t; template - std::string operator()(const statement_type &c, const C &context) const { + std::string operator()(const statement_type &c, const C &) const { return static_cast(c); } }; @@ -129,7 +129,7 @@ namespace sqlite_orm { using statement_type = std::string; template - std::string operator()(const statement_type &c, const C &context) const { + std::string operator()(const statement_type &c, const C &) const { return "\"" + c + "\""; } }; @@ -139,7 +139,7 @@ namespace sqlite_orm { using statement_type = const char *; template - std::string operator()(const char *c, const C &context) const { + std::string operator()(const char *c, const C &) const { return std::string("'") + c + "'"; } }; @@ -274,7 +274,7 @@ namespace sqlite_orm { using statement_type = T; template - std::string operator()(const statement_type &t, const C &context) const { + std::string operator()(const statement_type &t, const C &) const { std::stringstream ss; ss << t; return ss.str(); diff --git a/dev/storage_impl.h b/dev/storage_impl.h index 2cf029180..94cd0aead 100644 --- a/dev/storage_impl.h +++ b/dev/storage_impl.h @@ -434,7 +434,7 @@ namespace sqlite_orm { template<> struct storage_impl<> : storage_impl_base { - std::string find_table_name(std::type_index ti) const { + std::string find_table_name(std::type_index) const { return {}; } diff --git a/dev/table_name_collector.h b/dev/table_name_collector.h index d3106eb32..06298c66b 100644 --- a/dev/table_name_collector.h +++ b/dev/table_name_collector.h @@ -21,7 +21,7 @@ namespace sqlite_orm { mutable table_name_set table_names; template - table_name_set operator()(const T &t) const { + table_name_set operator()(const T &) const { return {}; } diff --git a/include/sqlite_orm/sqlite_orm.h b/include/sqlite_orm/sqlite_orm.h index 13db2e954..db5c51884 100644 --- a/include/sqlite_orm/sqlite_orm.h +++ b/include/sqlite_orm/sqlite_orm.h @@ -996,7 +996,7 @@ namespace sqlite_orm { struct serializator_context_base { template - std::string column_name(F O::*m) const { + std::string column_name(F O::*) const { return {}; } }; @@ -6559,7 +6559,7 @@ namespace sqlite_orm { template<> struct storage_impl<> : storage_impl_base { - std::string find_table_name(std::type_index ti) const { + std::string find_table_name(std::type_index) const { return {}; } @@ -8992,7 +8992,7 @@ namespace sqlite_orm { using statement_type = constraints::autoincrement_t; template - std::string operator()(const statement_type &c, const C &context) const { + std::string operator()(const statement_type &c, const C &) const { return static_cast(c); } }; @@ -9027,7 +9027,7 @@ namespace sqlite_orm { using statement_type = constraints::unique_t; template - std::string operator()(const statement_type &c, const C &context) const { + std::string operator()(const statement_type &c, const C &) const { return static_cast(c); } }; @@ -9037,7 +9037,7 @@ namespace sqlite_orm { using statement_type = constraints::collate_t; template - std::string operator()(const statement_type &c, const C &context) const { + std::string operator()(const statement_type &c, const C &) const { return static_cast(c); } }; @@ -9057,7 +9057,7 @@ namespace sqlite_orm { using statement_type = std::string; template - std::string operator()(const statement_type &c, const C &context) const { + std::string operator()(const statement_type &c, const C &) const { return "\"" + c + "\""; } }; @@ -9067,7 +9067,7 @@ namespace sqlite_orm { using statement_type = const char *; template - std::string operator()(const char *c, const C &context) const { + std::string operator()(const char *c, const C &) const { return std::string("'") + c + "'"; } }; @@ -9202,7 +9202,7 @@ namespace sqlite_orm { using statement_type = T; template - std::string operator()(const statement_type &t, const C &context) const { + std::string operator()(const statement_type &t, const C &) const { std::stringstream ss; ss << t; return ss.str(); @@ -9251,7 +9251,7 @@ namespace sqlite_orm { mutable table_name_set table_names; template - table_name_set operator()(const T &t) const { + table_name_set operator()(const T &) const { return {}; } From fc5e7018ed9eb6bdff029a39b2d7df1c24d08a2b Mon Sep 17 00:00:00 2001 From: fnc12 Date: Mon, 9 Mar 2020 19:17:10 +0300 Subject: [PATCH 043/132] added <<, >>, & and | bitwise operators --- dev/column_result.h | 20 ++++++++ dev/operators.h | 69 ++++++++++++++++++++++++- include/sqlite_orm/sqlite_orm.h | 89 ++++++++++++++++++++++++++++++++- tests/CMakeLists.txt | 2 +- tests/operators/bitwise.cpp | 50 ++++++++++++++++++ 5 files changed, 227 insertions(+), 3 deletions(-) create mode 100644 tests/operators/bitwise.cpp diff --git a/dev/column_result.h b/dev/column_result.h index 7f04c0213..3d5bac939 100644 --- a/dev/column_result.h +++ b/dev/column_result.h @@ -112,6 +112,26 @@ namespace sqlite_orm { using type = double; }; + template + struct column_result_t, void> { + using type = int; + }; + + template + struct column_result_t, void> { + using type = int; + }; + + template + struct column_result_t, void> { + using type = int; + }; + + template + struct column_result_t, void> { + using type = int; + }; + template struct column_result_t { using type = int64; diff --git a/dev/operators.h b/dev/operators.h index da06aa7e7..d68320581 100644 --- a/dev/operators.h +++ b/dev/operators.h @@ -94,12 +94,59 @@ namespace sqlite_orm { template using mod_t = binary_operator; + struct bitwise_shift_left_string { + operator std::string() const { + return "<<"; + } + }; + + /** + * Result of bitwise shift left << operator + */ + template + using bitwise_shift_left_t = binary_operator; + + struct bitwise_shift_right_string { + operator std::string() const { + return ">>"; + } + }; + + /** + * Result of bitwise shift right >> operator + */ + template + using bitwise_shift_right_t = binary_operator; + + struct bitwise_and_string { + operator std::string() const { + return "&"; + } + }; + + /** + * Result of bitwise and & operator + */ + template + using bitwise_and_t = binary_operator; + + struct bitwise_or_string { + operator std::string() const { + return "|"; + } + }; + + /** + * Result of bitwise or | operator + */ + template + using bitwise_or_t = binary_operator; + struct assign_string { operator std::string() const { return "="; } }; - /** * Result of assign = operator */ @@ -188,6 +235,26 @@ namespace sqlite_orm { return {std::move(l), std::move(r)}; } + template + internal::bitwise_shift_left_t bitwise_shift_left(L l, R r) { + return {std::move(l), std::move(r)}; + } + + template + internal::bitwise_shift_right_t bitwise_shift_right(L l, R r) { + return {std::move(l), std::move(r)}; + } + + template + internal::bitwise_and_t bitwise_and(L l, R r) { + return {std::move(l), std::move(r)}; + } + + template + internal::bitwise_or_t bitwise_or(L l, R r) { + return {std::move(l), std::move(r)}; + } + template internal::assign_t assign(L l, R r) { return {std::move(l), std::move(r)}; diff --git a/include/sqlite_orm/sqlite_orm.h b/include/sqlite_orm/sqlite_orm.h index db5c51884..26579928a 100644 --- a/include/sqlite_orm/sqlite_orm.h +++ b/include/sqlite_orm/sqlite_orm.h @@ -1143,12 +1143,59 @@ namespace sqlite_orm { template using mod_t = binary_operator; + struct bitwise_shift_left_string { + operator std::string() const { + return "<<"; + } + }; + + /** + * Result of bitwise shift left << operator + */ + template + using bitwise_shift_left_t = binary_operator; + + struct bitwise_shift_right_string { + operator std::string() const { + return ">>"; + } + }; + + /** + * Result of bitwise shift right >> operator + */ + template + using bitwise_shift_right_t = binary_operator; + + struct bitwise_and_string { + operator std::string() const { + return "&"; + } + }; + + /** + * Result of bitwise and & operator + */ + template + using bitwise_and_t = binary_operator; + + struct bitwise_or_string { + operator std::string() const { + return "|"; + } + }; + + /** + * Result of bitwise or | operator + */ + template + using bitwise_or_t = binary_operator; + struct assign_string { operator std::string() const { return "="; } }; - /** * Result of assign = operator */ @@ -1237,6 +1284,26 @@ namespace sqlite_orm { return {std::move(l), std::move(r)}; } + template + internal::bitwise_shift_left_t bitwise_shift_left(L l, R r) { + return {std::move(l), std::move(r)}; + } + + template + internal::bitwise_shift_right_t bitwise_shift_right(L l, R r) { + return {std::move(l), std::move(r)}; + } + + template + internal::bitwise_and_t bitwise_and(L l, R r) { + return {std::move(l), std::move(r)}; + } + + template + internal::bitwise_or_t bitwise_or(L l, R r) { + return {std::move(l), std::move(r)}; + } + template internal::assign_t assign(L l, R r) { return {std::move(l), std::move(r)}; @@ -5684,6 +5751,26 @@ namespace sqlite_orm { using type = double; }; + template + struct column_result_t, void> { + using type = int; + }; + + template + struct column_result_t, void> { + using type = int; + }; + + template + struct column_result_t, void> { + using type = int; + }; + + template + struct column_result_t, void> { + using type = int; + }; + template struct column_result_t { using type = int64; diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 0d3213113..2e3a193a0 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -10,7 +10,7 @@ else() add_subdirectory(third_party/sqlite) endif() -add_executable(unit_tests tests.cpp tests2.cpp tests3.cpp tests4.cpp tests5.cpp private_getters_tests.cpp pragma_tests.cpp explicit_columns.cpp core_functions_tests.cpp constraints/composite_key.cpp static_tests.cpp operators/arithmetic_operators.cpp operators/like.cpp operators/glob.cpp operators/in.cpp operators/cast.cpp operators/is_null.cpp operators/not_operator.cpp dynamic_order_by.cpp prepared_statement_tests/select.cpp prepared_statement_tests/get_all.cpp prepared_statement_tests/get_all_pointer.cpp prepared_statement_tests/get_all_optional.cpp prepared_statement_tests/update_all.cpp prepared_statement_tests/remove_all.cpp prepared_statement_tests/get.cpp prepared_statement_tests/get_pointer.cpp prepared_statement_tests/get_optional.cpp prepared_statement_tests/update.cpp prepared_statement_tests/remove.cpp prepared_statement_tests/insert.cpp prepared_statement_tests/replace.cpp prepared_statement_tests/insert_range.cpp prepared_statement_tests/replace_range.cpp prepared_statement_tests/insert_explicit.cpp pragma_tests.cpp simple_query.cpp static_tests/is_bindable.cpp static_tests/arithmetic_operators_result_type.cpp static_tests/tuple_conc.cpp static_tests/node_tuple.cpp static_tests/bindable_filter.cpp static_tests/count_tuple.cpp static_tests/member_traits_tests.cpp static_tests/select_return_type.cpp constraints/default.cpp constraints/foreign_key.cpp constraints/check.cpp table_tests.cpp statement_serializator_tests/primary_key.cpp statement_serializator_tests/column_names.cpp statement_serializator_tests/autoincrement.cpp statement_serializator_tests/arithmetic_operators.cpp statement_serializator_tests/core_functions.cpp statement_serializator_tests/comparison_operators.cpp statement_serializator_tests/unique.cpp statement_serializator_tests/foreign_key.cpp statement_serializator_tests/collate.cpp statement_serializator_tests/check.cpp unique_cases/get_all_with_two_tables.cpp unique_cases/prepare_get_all_with_case.cpp) +add_executable(unit_tests tests.cpp tests2.cpp tests3.cpp tests4.cpp tests5.cpp private_getters_tests.cpp pragma_tests.cpp explicit_columns.cpp core_functions_tests.cpp constraints/composite_key.cpp static_tests.cpp operators/arithmetic_operators.cpp operators/like.cpp operators/glob.cpp operators/in.cpp operators/cast.cpp operators/is_null.cpp operators/not_operator.cpp operators/bitwise.cpp dynamic_order_by.cpp prepared_statement_tests/select.cpp prepared_statement_tests/get_all.cpp prepared_statement_tests/get_all_pointer.cpp prepared_statement_tests/get_all_optional.cpp prepared_statement_tests/update_all.cpp prepared_statement_tests/remove_all.cpp prepared_statement_tests/get.cpp prepared_statement_tests/get_pointer.cpp prepared_statement_tests/get_optional.cpp prepared_statement_tests/update.cpp prepared_statement_tests/remove.cpp prepared_statement_tests/insert.cpp prepared_statement_tests/replace.cpp prepared_statement_tests/insert_range.cpp prepared_statement_tests/replace_range.cpp prepared_statement_tests/insert_explicit.cpp pragma_tests.cpp simple_query.cpp static_tests/is_bindable.cpp static_tests/arithmetic_operators_result_type.cpp static_tests/tuple_conc.cpp static_tests/node_tuple.cpp static_tests/bindable_filter.cpp static_tests/count_tuple.cpp static_tests/member_traits_tests.cpp static_tests/select_return_type.cpp constraints/default.cpp constraints/foreign_key.cpp constraints/check.cpp table_tests.cpp statement_serializator_tests/primary_key.cpp statement_serializator_tests/column_names.cpp statement_serializator_tests/autoincrement.cpp statement_serializator_tests/arithmetic_operators.cpp statement_serializator_tests/core_functions.cpp statement_serializator_tests/comparison_operators.cpp statement_serializator_tests/unique.cpp statement_serializator_tests/foreign_key.cpp statement_serializator_tests/collate.cpp statement_serializator_tests/check.cpp unique_cases/get_all_with_two_tables.cpp unique_cases/prepare_get_all_with_case.cpp) if(SQLITE_ORM_OMITS_CODECVT) diff --git a/tests/operators/bitwise.cpp b/tests/operators/bitwise.cpp new file mode 100644 index 000000000..8b1acf121 --- /dev/null +++ b/tests/operators/bitwise.cpp @@ -0,0 +1,50 @@ +#include +#include + +using namespace sqlite_orm; + +TEST_CASE("bitwise operators") { + struct Entry { + int lhs = 0; + int rhs = 0; + }; + auto storage = + make_storage({}, make_table("entries", make_column("lhs", &Entry::lhs), make_column("rhs", &Entry::rhs))); + storage.sync_schema(); + + { + auto rows = storage.select(bitwise_or(60, 13)); + REQUIRE(rows == std::vector{61}); + } + { + auto rows = storage.select(bitwise_and(60, 13)); + REQUIRE(rows == std::vector{12}); + } + { + auto rows = storage.select(bitwise_shift_left(60, 2)); + REQUIRE(rows == std::vector{240}); + } + { + auto rows = storage.select(bitwise_shift_right(60, 2)); + REQUIRE(rows == std::vector{15}); + } + storage.insert(Entry{60, 13}); + { + auto rows = storage.select(bitwise_or(&Entry::lhs, &Entry::rhs)); + REQUIRE(rows == std::vector{61}); + } + { + auto rows = storage.select(bitwise_and(&Entry::lhs, &Entry::rhs)); + REQUIRE(rows == std::vector{12}); + } + storage.remove_all(); + storage.insert(Entry{60, 2}); + { + auto rows = storage.select(bitwise_shift_left(&Entry::lhs, &Entry::rhs)); + REQUIRE(rows == std::vector{240}); + } + { + auto rows = storage.select(bitwise_shift_right(&Entry::lhs, &Entry::rhs)); + REQUIRE(rows == std::vector{15}); + } +} From e0bc852c6fe389cd52593c0b51b984b58013bbc3 Mon Sep 17 00:00:00 2001 From: fnc12 Date: Tue, 10 Mar 2020 00:28:36 +0300 Subject: [PATCH 044/132] refactored operator not and added bitwise_not function --- dev/ast_iterator.h | 10 ++ dev/column_result.h | 5 + dev/conditions.h | 78 ++++------------ dev/negatable.h | 7 ++ dev/operators.h | 43 +++++++-- dev/storage.h | 9 ++ include/sqlite_orm/sqlite_orm.h | 152 +++++++++++++++++-------------- tests/operators/bitwise.cpp | 8 ++ tests/operators/not_operator.cpp | 55 ++++++++++- 9 files changed, 226 insertions(+), 141 deletions(-) create mode 100644 dev/negatable.h diff --git a/dev/ast_iterator.h b/dev/ast_iterator.h index 1c84341be..5bdcb477c 100644 --- a/dev/ast_iterator.h +++ b/dev/ast_iterator.h @@ -480,5 +480,15 @@ namespace sqlite_orm { iterate_ast(a.t, l); } }; + + template + struct ast_iterator, void> { + using node_type = bitwise_not_t; + + template + void operator()(const node_type &a, const L &l) const { + iterate_ast(a.argument, l); + } + }; } } diff --git a/dev/column_result.h b/dev/column_result.h index 3d5bac939..09ad3e58c 100644 --- a/dev/column_result.h +++ b/dev/column_result.h @@ -132,6 +132,11 @@ namespace sqlite_orm { using type = int; }; + template + struct column_result_t, void> { + using type = int; + }; + template struct column_result_t { using type = int64; diff --git a/dev/conditions.h b/dev/conditions.h index 774f11a88..b2d0703be 100644 --- a/dev/conditions.h +++ b/dev/conditions.h @@ -8,6 +8,7 @@ #include "collate_argument.h" #include "constraints.h" #include "optional_container.h" +#include "negatable.h" namespace sqlite_orm { @@ -170,15 +171,11 @@ namespace sqlite_orm { * = and == operators object */ template - struct is_equal_t : binary_condition, is_equal_string { + struct is_equal_t : binary_condition, is_equal_string, internal::negatable_t { using self = is_equal_t; using binary_condition::binary_condition; - negated_condition_t operator!() const { - return {*this}; - } - collate_t collate_binary() const { return {*this, internal::collate_argument::binary}; } @@ -206,15 +203,11 @@ namespace sqlite_orm { * != operator object */ template - struct is_not_equal_t : binary_condition, is_not_equal_string { + struct is_not_equal_t : binary_condition, is_not_equal_string, internal::negatable_t { using self = is_not_equal_t; using binary_condition::binary_condition; - negated_condition_t operator!() const { - return {*this}; - } - collate_t collate_binary() const { return {*this, internal::collate_argument::binary}; } @@ -238,15 +231,11 @@ namespace sqlite_orm { * > operator object. */ template - struct greater_than_t : binary_condition, greater_than_string { + struct greater_than_t : binary_condition, greater_than_string, internal::negatable_t { using self = greater_than_t; using binary_condition::binary_condition; - negated_condition_t operator!() const { - return {*this}; - } - collate_t collate_binary() const { return {*this, internal::collate_argument::binary}; } @@ -270,15 +259,11 @@ namespace sqlite_orm { * >= operator object. */ template - struct greater_or_equal_t : binary_condition, greater_or_equal_string { + struct greater_or_equal_t : binary_condition, greater_or_equal_string, internal::negatable_t { using self = greater_or_equal_t; using binary_condition::binary_condition; - negated_condition_t operator!() const { - return {*this}; - } - collate_t collate_binary() const { return {*this, internal::collate_argument::binary}; } @@ -302,15 +287,11 @@ namespace sqlite_orm { * < operator object. */ template - struct lesser_than_t : binary_condition, lesser_than_string { + struct lesser_than_t : binary_condition, lesser_than_string, internal::negatable_t { using self = lesser_than_t; using binary_condition::binary_condition; - negated_condition_t operator!() const { - return {*this}; - } - collate_t collate_binary() const { return {*this, internal::collate_argument::binary}; } @@ -334,15 +315,11 @@ namespace sqlite_orm { * <= operator object. */ template - struct lesser_or_equal_t : binary_condition, lesser_or_equal_string { + struct lesser_or_equal_t : binary_condition, lesser_or_equal_string, internal::negatable_t { using self = lesser_or_equal_t; using binary_condition::binary_condition; - negated_condition_t> operator!() const { - return {*this}; - } - collate_t collate_binary() const { return {*this, internal::collate_argument::binary}; } @@ -372,17 +349,13 @@ namespace sqlite_orm { * IN operator object. */ template - struct in_t : condition_t, in_base { + struct in_t : condition_t, in_base, internal::negatable_t { using self = in_t; L l; // left expression A arg; // in arg in_t(L l_, A arg_, bool negative) : in_base{negative}, l(l_), arg(std::move(arg_)) {} - - negated_condition_t operator!() const { - return {*this}; - } }; struct is_null_string { @@ -395,16 +368,12 @@ namespace sqlite_orm { * IS NULL operator object. */ template - struct is_null_t : is_null_string { + struct is_null_t : is_null_string, internal::negatable_t { using self = is_null_t; T t; is_null_t(T t_) : t(std::move(t_)) {} - - negated_condition_t operator!() const { - return {*this}; - } }; struct is_not_null_string { @@ -417,16 +386,12 @@ namespace sqlite_orm { * IS NOT NULL operator object. */ template - struct is_not_null_t : is_not_null_string { + struct is_not_null_t : is_not_null_string, internal::negatable_t { using self = is_not_null_t; T t; is_not_null_t(T t_) : t(std::move(t_)) {} - - negated_condition_t operator!() const { - return {*this}; - } }; struct where_string { @@ -635,7 +600,7 @@ namespace sqlite_orm { * LIKE operator object. */ template - struct like_t : condition_t, like_string { + struct like_t : condition_t, like_string, internal::negatable_t { using self = like_t; using arg_t = A; using pattern_t = T; @@ -654,10 +619,6 @@ namespace sqlite_orm { sqlite_orm::internal::optional_container newArg3{std::move(c)}; return {std::move(this->arg), std::move(this->pattern), std::move(newArg3)}; } - - negated_condition_t operator!() const { - return {*this}; - } }; struct glob_string { @@ -667,7 +628,7 @@ namespace sqlite_orm { }; template - struct glob_t : condition_t, glob_string { + struct glob_t : condition_t, glob_string, internal::negatable_t { using self = glob_t; using arg_t = A; using pattern_t = T; @@ -676,10 +637,6 @@ namespace sqlite_orm { pattern_t pattern; glob_t(arg_t arg_, pattern_t pattern_) : arg(std::move(arg_)), pattern(std::move(pattern_)) {} - - negated_condition_t operator!() const { - return {*this}; - } }; struct cross_join_string { @@ -834,17 +791,13 @@ namespace sqlite_orm { }; template - struct exists_t : condition_t, exists_string { + struct exists_t : condition_t, exists_string, internal::negatable_t { using type = T; using self = exists_t; type t; exists_t(T t_) : t(std::move(t_)) {} - - negated_condition_t operator!() const { - return {*this}; - } }; struct having_string { @@ -896,6 +849,11 @@ namespace sqlite_orm { } + template::value>::type> + conditions::negated_condition_t operator!(T arg) { + return {std::move(arg)}; + } + /** * Cute operators for columns */ diff --git a/dev/negatable.h b/dev/negatable.h new file mode 100644 index 000000000..8bdb7de6b --- /dev/null +++ b/dev/negatable.h @@ -0,0 +1,7 @@ +#pragma once + +namespace sqlite_orm { + namespace internal { + struct negatable_t {}; + } +} diff --git a/dev/operators.h b/dev/operators.h index d68320581..9136e6a2c 100644 --- a/dev/operators.h +++ b/dev/operators.h @@ -2,6 +2,8 @@ #include // std::false_type, std::true_type +#include "negatable.h" + namespace sqlite_orm { namespace internal { @@ -44,7 +46,7 @@ namespace sqlite_orm { * Result of addition + operator */ template - using add_t = binary_operator; + using add_t = binary_operator; struct sub_string { operator std::string() const { @@ -56,7 +58,7 @@ namespace sqlite_orm { * Result of substitute - operator */ template - using sub_t = binary_operator; + using sub_t = binary_operator; struct mul_string { operator std::string() const { @@ -68,7 +70,7 @@ namespace sqlite_orm { * Result of multiply * operator */ template - using mul_t = binary_operator; + using mul_t = binary_operator; struct div_string { operator std::string() const { @@ -80,7 +82,7 @@ namespace sqlite_orm { * Result of divide / operator */ template - using div_t = binary_operator; + using div_t = binary_operator; struct mod_string { operator std::string() const { @@ -92,7 +94,7 @@ namespace sqlite_orm { * Result of mod % operator */ template - using mod_t = binary_operator; + using mod_t = binary_operator; struct bitwise_shift_left_string { operator std::string() const { @@ -104,7 +106,7 @@ namespace sqlite_orm { * Result of bitwise shift left << operator */ template - using bitwise_shift_left_t = binary_operator; + using bitwise_shift_left_t = binary_operator; struct bitwise_shift_right_string { operator std::string() const { @@ -116,7 +118,7 @@ namespace sqlite_orm { * Result of bitwise shift right >> operator */ template - using bitwise_shift_right_t = binary_operator; + using bitwise_shift_right_t = binary_operator; struct bitwise_and_string { operator std::string() const { @@ -128,7 +130,7 @@ namespace sqlite_orm { * Result of bitwise and & operator */ template - using bitwise_and_t = binary_operator; + using bitwise_and_t = binary_operator; struct bitwise_or_string { operator std::string() const { @@ -140,7 +142,25 @@ namespace sqlite_orm { * Result of bitwise or | operator */ template - using bitwise_or_t = binary_operator; + using bitwise_or_t = binary_operator; + + struct bitwise_not_string { + operator std::string() const { + return "~"; + } + }; + + /** + * Result of bitwise not ~ operator + */ + template + struct bitwise_not_t : bitwise_not_string, arithmetic_t, negatable_t { + using argument_type = T; + + argument_type argument; + + bitwise_not_t(argument_type argument_) : argument(std::move(argument_)) {} + }; struct assign_string { operator std::string() const { @@ -255,6 +275,11 @@ namespace sqlite_orm { return {std::move(l), std::move(r)}; } + template + internal::bitwise_not_t bitwise_not(T t) { + return {std::move(t)}; + } + template internal::assign_t assign(L l, R r) { return {std::move(l), std::move(r)}; diff --git a/dev/storage.h b/dev/storage.h index f13496c2c..0978b8ed4 100644 --- a/dev/storage.h +++ b/dev/storage.h @@ -906,6 +906,15 @@ namespace sqlite_orm { return ss.str(); } + template + std::string string_from_expression(const bitwise_not_t &arg, bool noTableName) const { + std::stringstream ss; + ss << static_cast(arg) << " "; + auto cString = this->string_from_expression(arg.argument, noTableName); + ss << " (" << cString << " ) "; + return ss.str(); + } + template std::string string_from_expression(const conditions::negated_condition_t &c, bool noTableName) const { std::stringstream ss; diff --git a/include/sqlite_orm/sqlite_orm.h b/include/sqlite_orm/sqlite_orm.h index 26579928a..28f43f3a5 100644 --- a/include/sqlite_orm/sqlite_orm.h +++ b/include/sqlite_orm/sqlite_orm.h @@ -1051,6 +1051,14 @@ namespace sqlite_orm { #include // std::false_type, std::true_type +// #include "negatable.h" + +namespace sqlite_orm { + namespace internal { + struct negatable_t {}; + } +} + namespace sqlite_orm { namespace internal { @@ -1093,7 +1101,7 @@ namespace sqlite_orm { * Result of addition + operator */ template - using add_t = binary_operator; + using add_t = binary_operator; struct sub_string { operator std::string() const { @@ -1105,7 +1113,7 @@ namespace sqlite_orm { * Result of substitute - operator */ template - using sub_t = binary_operator; + using sub_t = binary_operator; struct mul_string { operator std::string() const { @@ -1117,7 +1125,7 @@ namespace sqlite_orm { * Result of multiply * operator */ template - using mul_t = binary_operator; + using mul_t = binary_operator; struct div_string { operator std::string() const { @@ -1129,7 +1137,7 @@ namespace sqlite_orm { * Result of divide / operator */ template - using div_t = binary_operator; + using div_t = binary_operator; struct mod_string { operator std::string() const { @@ -1141,7 +1149,7 @@ namespace sqlite_orm { * Result of mod % operator */ template - using mod_t = binary_operator; + using mod_t = binary_operator; struct bitwise_shift_left_string { operator std::string() const { @@ -1153,7 +1161,7 @@ namespace sqlite_orm { * Result of bitwise shift left << operator */ template - using bitwise_shift_left_t = binary_operator; + using bitwise_shift_left_t = binary_operator; struct bitwise_shift_right_string { operator std::string() const { @@ -1165,7 +1173,7 @@ namespace sqlite_orm { * Result of bitwise shift right >> operator */ template - using bitwise_shift_right_t = binary_operator; + using bitwise_shift_right_t = binary_operator; struct bitwise_and_string { operator std::string() const { @@ -1177,7 +1185,7 @@ namespace sqlite_orm { * Result of bitwise and & operator */ template - using bitwise_and_t = binary_operator; + using bitwise_and_t = binary_operator; struct bitwise_or_string { operator std::string() const { @@ -1189,7 +1197,25 @@ namespace sqlite_orm { * Result of bitwise or | operator */ template - using bitwise_or_t = binary_operator; + using bitwise_or_t = binary_operator; + + struct bitwise_not_string { + operator std::string() const { + return "~"; + } + }; + + /** + * Result of bitwise not ~ operator + */ + template + struct bitwise_not_t : bitwise_not_string, arithmetic_t, negatable_t { + using argument_type = T; + + argument_type argument; + + bitwise_not_t(argument_type argument_) : argument(std::move(argument_)) {} + }; struct assign_string { operator std::string() const { @@ -1304,6 +1330,11 @@ namespace sqlite_orm { return {std::move(l), std::move(r)}; } + template + internal::bitwise_not_t bitwise_not(T t) { + return {std::move(t)}; + } + template internal::assign_t assign(L l, R r) { return {std::move(l), std::move(r)}; @@ -1872,6 +1903,8 @@ namespace sqlite_orm { } } +// #include "negatable.h" + namespace sqlite_orm { namespace internal { @@ -2033,15 +2066,11 @@ namespace sqlite_orm { * = and == operators object */ template - struct is_equal_t : binary_condition, is_equal_string { + struct is_equal_t : binary_condition, is_equal_string, internal::negatable_t { using self = is_equal_t; using binary_condition::binary_condition; - negated_condition_t operator!() const { - return {*this}; - } - collate_t collate_binary() const { return {*this, internal::collate_argument::binary}; } @@ -2069,15 +2098,11 @@ namespace sqlite_orm { * != operator object */ template - struct is_not_equal_t : binary_condition, is_not_equal_string { + struct is_not_equal_t : binary_condition, is_not_equal_string, internal::negatable_t { using self = is_not_equal_t; using binary_condition::binary_condition; - negated_condition_t operator!() const { - return {*this}; - } - collate_t collate_binary() const { return {*this, internal::collate_argument::binary}; } @@ -2101,15 +2126,11 @@ namespace sqlite_orm { * > operator object. */ template - struct greater_than_t : binary_condition, greater_than_string { + struct greater_than_t : binary_condition, greater_than_string, internal::negatable_t { using self = greater_than_t; using binary_condition::binary_condition; - negated_condition_t operator!() const { - return {*this}; - } - collate_t collate_binary() const { return {*this, internal::collate_argument::binary}; } @@ -2133,15 +2154,11 @@ namespace sqlite_orm { * >= operator object. */ template - struct greater_or_equal_t : binary_condition, greater_or_equal_string { + struct greater_or_equal_t : binary_condition, greater_or_equal_string, internal::negatable_t { using self = greater_or_equal_t; using binary_condition::binary_condition; - negated_condition_t operator!() const { - return {*this}; - } - collate_t collate_binary() const { return {*this, internal::collate_argument::binary}; } @@ -2165,15 +2182,11 @@ namespace sqlite_orm { * < operator object. */ template - struct lesser_than_t : binary_condition, lesser_than_string { + struct lesser_than_t : binary_condition, lesser_than_string, internal::negatable_t { using self = lesser_than_t; using binary_condition::binary_condition; - negated_condition_t operator!() const { - return {*this}; - } - collate_t collate_binary() const { return {*this, internal::collate_argument::binary}; } @@ -2197,15 +2210,11 @@ namespace sqlite_orm { * <= operator object. */ template - struct lesser_or_equal_t : binary_condition, lesser_or_equal_string { + struct lesser_or_equal_t : binary_condition, lesser_or_equal_string, internal::negatable_t { using self = lesser_or_equal_t; using binary_condition::binary_condition; - negated_condition_t> operator!() const { - return {*this}; - } - collate_t collate_binary() const { return {*this, internal::collate_argument::binary}; } @@ -2235,17 +2244,13 @@ namespace sqlite_orm { * IN operator object. */ template - struct in_t : condition_t, in_base { + struct in_t : condition_t, in_base, internal::negatable_t { using self = in_t; L l; // left expression A arg; // in arg in_t(L l_, A arg_, bool negative) : in_base{negative}, l(l_), arg(std::move(arg_)) {} - - negated_condition_t operator!() const { - return {*this}; - } }; struct is_null_string { @@ -2258,16 +2263,12 @@ namespace sqlite_orm { * IS NULL operator object. */ template - struct is_null_t : is_null_string { + struct is_null_t : is_null_string, internal::negatable_t { using self = is_null_t; T t; is_null_t(T t_) : t(std::move(t_)) {} - - negated_condition_t operator!() const { - return {*this}; - } }; struct is_not_null_string { @@ -2280,16 +2281,12 @@ namespace sqlite_orm { * IS NOT NULL operator object. */ template - struct is_not_null_t : is_not_null_string { + struct is_not_null_t : is_not_null_string, internal::negatable_t { using self = is_not_null_t; T t; is_not_null_t(T t_) : t(std::move(t_)) {} - - negated_condition_t operator!() const { - return {*this}; - } }; struct where_string { @@ -2498,7 +2495,7 @@ namespace sqlite_orm { * LIKE operator object. */ template - struct like_t : condition_t, like_string { + struct like_t : condition_t, like_string, internal::negatable_t { using self = like_t; using arg_t = A; using pattern_t = T; @@ -2517,10 +2514,6 @@ namespace sqlite_orm { sqlite_orm::internal::optional_container newArg3{std::move(c)}; return {std::move(this->arg), std::move(this->pattern), std::move(newArg3)}; } - - negated_condition_t operator!() const { - return {*this}; - } }; struct glob_string { @@ -2530,7 +2523,7 @@ namespace sqlite_orm { }; template - struct glob_t : condition_t, glob_string { + struct glob_t : condition_t, glob_string, internal::negatable_t { using self = glob_t; using arg_t = A; using pattern_t = T; @@ -2539,10 +2532,6 @@ namespace sqlite_orm { pattern_t pattern; glob_t(arg_t arg_, pattern_t pattern_) : arg(std::move(arg_)), pattern(std::move(pattern_)) {} - - negated_condition_t operator!() const { - return {*this}; - } }; struct cross_join_string { @@ -2697,17 +2686,13 @@ namespace sqlite_orm { }; template - struct exists_t : condition_t, exists_string { + struct exists_t : condition_t, exists_string, internal::negatable_t { using type = T; using self = exists_t; type t; exists_t(T t_) : t(std::move(t_)) {} - - negated_condition_t operator!() const { - return {*this}; - } }; struct having_string { @@ -2759,6 +2744,11 @@ namespace sqlite_orm { } + template::value>::type> + conditions::negated_condition_t operator!(T arg) { + return {std::move(arg)}; + } + /** * Cute operators for columns */ @@ -5771,6 +5761,11 @@ namespace sqlite_orm { using type = int; }; + template + struct column_result_t, void> { + using type = int; + }; + template struct column_result_t { using type = int64; @@ -7850,6 +7845,16 @@ namespace sqlite_orm { iterate_ast(a.t, l); } }; + + template + struct ast_iterator, void> { + using node_type = bitwise_not_t; + + template + void operator()(const node_type &a, const L &l) const { + iterate_ast(a.argument, l); + } + }; } } @@ -10242,6 +10247,15 @@ namespace sqlite_orm { return ss.str(); } + template + std::string string_from_expression(const bitwise_not_t &arg, bool noTableName) const { + std::stringstream ss; + ss << static_cast(arg) << " "; + auto cString = this->string_from_expression(arg.argument, noTableName); + ss << " (" << cString << " ) "; + return ss.str(); + } + template std::string string_from_expression(const conditions::negated_condition_t &c, bool noTableName) const { std::stringstream ss; diff --git a/tests/operators/bitwise.cpp b/tests/operators/bitwise.cpp index 8b1acf121..3d78fa647 100644 --- a/tests/operators/bitwise.cpp +++ b/tests/operators/bitwise.cpp @@ -28,6 +28,10 @@ TEST_CASE("bitwise operators") { auto rows = storage.select(bitwise_shift_right(60, 2)); REQUIRE(rows == std::vector{15}); } + { + auto rows = storage.select(bitwise_not(60)); + REQUIRE(rows == std::vector{-61}); + } storage.insert(Entry{60, 13}); { auto rows = storage.select(bitwise_or(&Entry::lhs, &Entry::rhs)); @@ -47,4 +51,8 @@ TEST_CASE("bitwise operators") { auto rows = storage.select(bitwise_shift_right(&Entry::lhs, &Entry::rhs)); REQUIRE(rows == std::vector{15}); } + { + auto rows = storage.select(bitwise_not(&Entry::lhs)); + REQUIRE(rows == std::vector{-61}); + } } diff --git a/tests/operators/not_operator.cpp b/tests/operators/not_operator.cpp index 889751812..367ae501d 100644 --- a/tests/operators/not_operator.cpp +++ b/tests/operators/not_operator.cpp @@ -12,8 +12,57 @@ TEST_CASE("Not operator") { storage.sync_schema(); storage.replace(Object{2}); + storage.replace(Object{3}); - auto rows = storage.select(&Object::id, where(not is_equal(&Object::id, 1))); - REQUIRE(rows.size() == 1); - REQUIRE(rows.front() == 2); + std::vector rows; + std::vector expected; + SECTION("is_equal") { + rows = storage.select(&Object::id, where(not is_equal(&Object::id, 1))); + expected.push_back(2); + expected.push_back(3); + } + SECTION("is_not_equal") { + rows = storage.select(&Object::id, where(not is_not_equal(&Object::id, 3))); + expected.push_back(3); + } + SECTION("greater_than") { + rows = storage.select(&Object::id, where(not greater_than(&Object::id, 2))); + expected.push_back(2); + } + SECTION("greater_or_equal") { + rows = storage.select(&Object::id, where(not greater_or_equal(&Object::id, 3))); + expected.push_back(2); + } + SECTION("lesser_than") { + rows = storage.select(&Object::id, where(not lesser_than(&Object::id, 3))); + expected.push_back(3); + } + SECTION("lesser_or_equal") { + rows = storage.select(&Object::id, where(not lesser_or_equal(&Object::id, 2))); + expected.push_back(3); + } + SECTION("in") { + rows = storage.select(&Object::id, where(not in(&Object::id, {1, 2}))); + expected.push_back(3); + } + SECTION("is_null") { + rows = storage.select(&Object::id, where(not is_null(&Object::id))); + expected.push_back(2); + expected.push_back(3); + } + SECTION("is_not_null") { + rows = storage.select(&Object::id, where(not is_not_null(&Object::id))); + } + SECTION("like") { + rows = storage.select(&Object::id, where(not like(cast(&Object::id), "2"))); + expected.push_back(3); + } + SECTION("glob") { + rows = storage.select(&Object::id, where(not like(cast(&Object::id), "3"))); + expected.push_back(2); + } + SECTION("exists") { + rows = storage.select(&Object::id, where(not exists(select(&Object::id, where(is_equal(&Object::id, 2)))))); + } + REQUIRE(rows == expected); } From 26f9138222124342a391a782d5d3f449268cabda Mon Sep 17 00:00:00 2001 From: fnc12 Date: Wed, 11 Mar 2020 21:26:32 +0300 Subject: [PATCH 045/132] added quotes in fk serizlization --- dev/statement_serializator.h | 2 +- include/sqlite_orm/sqlite_orm.h | 2 +- tests/CMakeLists.txt | 2 +- .../foreign_key.cpp | 26 +++--- .../index_named_table_with_fk.cpp | 79 +++++++++++++++++++ 5 files changed, 95 insertions(+), 16 deletions(-) create mode 100644 tests/unique_cases/index_named_table_with_fk.cpp diff --git a/dev/statement_serializator.h b/dev/statement_serializator.h index be998d8ed..681754fbe 100644 --- a/dev/statement_serializator.h +++ b/dev/statement_serializator.h @@ -174,7 +174,7 @@ namespace sqlite_orm { using first_reference_t = typename std::tuple_element<0, references_type_t>::type; using first_reference_mapped_type = typename internal::table_type::type; auto refTableName = context.impl.find_table_name(typeid(first_reference_mapped_type)); - ss << refTableName; + ss << '\'' << refTableName << '\''; } iterate_tuple(fk.references, [&referencesNames, &context](auto &v) { referencesNames.push_back(context.impl.column_name(v)); diff --git a/include/sqlite_orm/sqlite_orm.h b/include/sqlite_orm/sqlite_orm.h index 28f43f3a5..a6ae12883 100644 --- a/include/sqlite_orm/sqlite_orm.h +++ b/include/sqlite_orm/sqlite_orm.h @@ -9194,7 +9194,7 @@ namespace sqlite_orm { using first_reference_t = typename std::tuple_element<0, references_type_t>::type; using first_reference_mapped_type = typename internal::table_type::type; auto refTableName = context.impl.find_table_name(typeid(first_reference_mapped_type)); - ss << refTableName; + ss << '\'' << refTableName << '\''; } iterate_tuple(fk.references, [&referencesNames, &context](auto &v) { referencesNames.push_back(context.impl.column_name(v)); diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 2e3a193a0..a7c01fed4 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -10,7 +10,7 @@ else() add_subdirectory(third_party/sqlite) endif() -add_executable(unit_tests tests.cpp tests2.cpp tests3.cpp tests4.cpp tests5.cpp private_getters_tests.cpp pragma_tests.cpp explicit_columns.cpp core_functions_tests.cpp constraints/composite_key.cpp static_tests.cpp operators/arithmetic_operators.cpp operators/like.cpp operators/glob.cpp operators/in.cpp operators/cast.cpp operators/is_null.cpp operators/not_operator.cpp operators/bitwise.cpp dynamic_order_by.cpp prepared_statement_tests/select.cpp prepared_statement_tests/get_all.cpp prepared_statement_tests/get_all_pointer.cpp prepared_statement_tests/get_all_optional.cpp prepared_statement_tests/update_all.cpp prepared_statement_tests/remove_all.cpp prepared_statement_tests/get.cpp prepared_statement_tests/get_pointer.cpp prepared_statement_tests/get_optional.cpp prepared_statement_tests/update.cpp prepared_statement_tests/remove.cpp prepared_statement_tests/insert.cpp prepared_statement_tests/replace.cpp prepared_statement_tests/insert_range.cpp prepared_statement_tests/replace_range.cpp prepared_statement_tests/insert_explicit.cpp pragma_tests.cpp simple_query.cpp static_tests/is_bindable.cpp static_tests/arithmetic_operators_result_type.cpp static_tests/tuple_conc.cpp static_tests/node_tuple.cpp static_tests/bindable_filter.cpp static_tests/count_tuple.cpp static_tests/member_traits_tests.cpp static_tests/select_return_type.cpp constraints/default.cpp constraints/foreign_key.cpp constraints/check.cpp table_tests.cpp statement_serializator_tests/primary_key.cpp statement_serializator_tests/column_names.cpp statement_serializator_tests/autoincrement.cpp statement_serializator_tests/arithmetic_operators.cpp statement_serializator_tests/core_functions.cpp statement_serializator_tests/comparison_operators.cpp statement_serializator_tests/unique.cpp statement_serializator_tests/foreign_key.cpp statement_serializator_tests/collate.cpp statement_serializator_tests/check.cpp unique_cases/get_all_with_two_tables.cpp unique_cases/prepare_get_all_with_case.cpp) +add_executable(unit_tests tests.cpp tests2.cpp tests3.cpp tests4.cpp tests5.cpp private_getters_tests.cpp pragma_tests.cpp explicit_columns.cpp core_functions_tests.cpp constraints/composite_key.cpp static_tests.cpp operators/arithmetic_operators.cpp operators/like.cpp operators/glob.cpp operators/in.cpp operators/cast.cpp operators/is_null.cpp operators/not_operator.cpp operators/bitwise.cpp dynamic_order_by.cpp prepared_statement_tests/select.cpp prepared_statement_tests/get_all.cpp prepared_statement_tests/get_all_pointer.cpp prepared_statement_tests/get_all_optional.cpp prepared_statement_tests/update_all.cpp prepared_statement_tests/remove_all.cpp prepared_statement_tests/get.cpp prepared_statement_tests/get_pointer.cpp prepared_statement_tests/get_optional.cpp prepared_statement_tests/update.cpp prepared_statement_tests/remove.cpp prepared_statement_tests/insert.cpp prepared_statement_tests/replace.cpp prepared_statement_tests/insert_range.cpp prepared_statement_tests/replace_range.cpp prepared_statement_tests/insert_explicit.cpp pragma_tests.cpp simple_query.cpp static_tests/is_bindable.cpp static_tests/arithmetic_operators_result_type.cpp static_tests/tuple_conc.cpp static_tests/node_tuple.cpp static_tests/bindable_filter.cpp static_tests/count_tuple.cpp static_tests/member_traits_tests.cpp static_tests/select_return_type.cpp constraints/default.cpp constraints/foreign_key.cpp constraints/check.cpp table_tests.cpp statement_serializator_tests/primary_key.cpp statement_serializator_tests/column_names.cpp statement_serializator_tests/autoincrement.cpp statement_serializator_tests/arithmetic_operators.cpp statement_serializator_tests/core_functions.cpp statement_serializator_tests/comparison_operators.cpp statement_serializator_tests/unique.cpp statement_serializator_tests/foreign_key.cpp statement_serializator_tests/collate.cpp statement_serializator_tests/check.cpp unique_cases/get_all_with_two_tables.cpp unique_cases/prepare_get_all_with_case.cpp unique_cases/index_named_table_with_fk.cpp) if(SQLITE_ORM_OMITS_CODECVT) diff --git a/tests/statement_serializator_tests/foreign_key.cpp b/tests/statement_serializator_tests/foreign_key.cpp index b32a51ed5..564bcd9d1 100644 --- a/tests/statement_serializator_tests/foreign_key.cpp +++ b/tests/statement_serializator_tests/foreign_key.cpp @@ -39,7 +39,7 @@ TEST_CASE("statement_serializator foreign key") { context_t context{storageImpl}; auto value = serialize(fk, context); - REQUIRE(value == "FOREIGN KEY('user_id') REFERENCES users('id')"); + REQUIRE(value == "FOREIGN KEY('user_id') REFERENCES 'users'('id')"); } SECTION("on update") { SECTION("no_action") { @@ -59,7 +59,7 @@ TEST_CASE("statement_serializator foreign key") { context_t context{storageImpl}; auto value = serialize(fk, context); - REQUIRE(value == "FOREIGN KEY('user_id') REFERENCES users('id') ON UPDATE NO ACTION"); + REQUIRE(value == "FOREIGN KEY('user_id') REFERENCES 'users'('id') ON UPDATE NO ACTION"); } SECTION("restrict_") { auto fk = foreign_key(&Visit::userId).references(&User::id).on_update.restrict_(); @@ -78,7 +78,7 @@ TEST_CASE("statement_serializator foreign key") { context_t context{storageImpl}; auto value = serialize(fk, context); - REQUIRE(value == "FOREIGN KEY('user_id') REFERENCES users('id') ON UPDATE RESTRICT"); + REQUIRE(value == "FOREIGN KEY('user_id') REFERENCES 'users'('id') ON UPDATE RESTRICT"); } SECTION("set_null") { auto fk = foreign_key(&Visit::userId).references(&User::id).on_update.set_null(); @@ -97,7 +97,7 @@ TEST_CASE("statement_serializator foreign key") { context_t context{storageImpl}; auto value = serialize(fk, context); - REQUIRE(value == "FOREIGN KEY('user_id') REFERENCES users('id') ON UPDATE SET NULL"); + REQUIRE(value == "FOREIGN KEY('user_id') REFERENCES 'users'('id') ON UPDATE SET NULL"); } SECTION("set_default") { auto fk = foreign_key(&Visit::userId).references(&User::id).on_update.set_default(); @@ -116,7 +116,7 @@ TEST_CASE("statement_serializator foreign key") { context_t context{storageImpl}; auto value = serialize(fk, context); - REQUIRE(value == "FOREIGN KEY('user_id') REFERENCES users('id') ON UPDATE SET DEFAULT"); + REQUIRE(value == "FOREIGN KEY('user_id') REFERENCES 'users'('id') ON UPDATE SET DEFAULT"); } SECTION("cascade") { auto fk = foreign_key(&Visit::userId).references(&User::id).on_update.cascade(); @@ -135,7 +135,7 @@ TEST_CASE("statement_serializator foreign key") { context_t context{storageImpl}; auto value = serialize(fk, context); - REQUIRE(value == "FOREIGN KEY('user_id') REFERENCES users('id') ON UPDATE CASCADE"); + REQUIRE(value == "FOREIGN KEY('user_id') REFERENCES 'users'('id') ON UPDATE CASCADE"); } } SECTION("on delete") { @@ -156,7 +156,7 @@ TEST_CASE("statement_serializator foreign key") { context_t context{storageImpl}; auto value = serialize(fk, context); - REQUIRE(value == "FOREIGN KEY('user_id') REFERENCES users('id') ON DELETE NO ACTION"); + REQUIRE(value == "FOREIGN KEY('user_id') REFERENCES 'users'('id') ON DELETE NO ACTION"); } SECTION("restrict_") { auto fk = foreign_key(&Visit::userId).references(&User::id).on_delete.restrict_(); @@ -175,7 +175,7 @@ TEST_CASE("statement_serializator foreign key") { context_t context{storageImpl}; auto value = serialize(fk, context); - REQUIRE(value == "FOREIGN KEY('user_id') REFERENCES users('id') ON DELETE RESTRICT"); + REQUIRE(value == "FOREIGN KEY('user_id') REFERENCES 'users'('id') ON DELETE RESTRICT"); } SECTION("set_null") { auto fk = foreign_key(&Visit::userId).references(&User::id).on_delete.set_null(); @@ -194,7 +194,7 @@ TEST_CASE("statement_serializator foreign key") { context_t context{storageImpl}; auto value = serialize(fk, context); - REQUIRE(value == "FOREIGN KEY('user_id') REFERENCES users('id') ON DELETE SET NULL"); + REQUIRE(value == "FOREIGN KEY('user_id') REFERENCES 'users'('id') ON DELETE SET NULL"); } SECTION("set_default") { auto fk = foreign_key(&Visit::userId).references(&User::id).on_delete.set_default(); @@ -213,7 +213,7 @@ TEST_CASE("statement_serializator foreign key") { context_t context{storageImpl}; auto value = serialize(fk, context); - REQUIRE(value == "FOREIGN KEY('user_id') REFERENCES users('id') ON DELETE SET DEFAULT"); + REQUIRE(value == "FOREIGN KEY('user_id') REFERENCES 'users'('id') ON DELETE SET DEFAULT"); } SECTION("cascade") { auto fk = foreign_key(&Visit::userId).references(&User::id).on_delete.cascade(); @@ -232,7 +232,7 @@ TEST_CASE("statement_serializator foreign key") { context_t context{storageImpl}; auto value = serialize(fk, context); - REQUIRE(value == "FOREIGN KEY('user_id') REFERENCES users('id') ON DELETE CASCADE"); + REQUIRE(value == "FOREIGN KEY('user_id') REFERENCES 'users'('id') ON DELETE CASCADE"); } } } @@ -271,7 +271,7 @@ TEST_CASE("statement_serializator foreign key") { context_t context{storageImpl}; auto value = serialize(fk, context); - REQUIRE(value == "FOREIGN KEY('user_id') REFERENCES users('id')"); + REQUIRE(value == "FOREIGN KEY('user_id') REFERENCES 'users'('id')"); } SECTION("composite key") { struct User { @@ -306,7 +306,7 @@ TEST_CASE("statement_serializator foreign key") { context_t context{storageImpl}; auto value = serialize(fk, context); - REQUIRE(value == "FOREIGN KEY('user_id', 'user_first_name') REFERENCES users('id', 'first_name')"); + REQUIRE(value == "FOREIGN KEY('user_id', 'user_first_name') REFERENCES 'users'('id', 'first_name')"); } } diff --git a/tests/unique_cases/index_named_table_with_fk.cpp b/tests/unique_cases/index_named_table_with_fk.cpp new file mode 100644 index 000000000..3ebd8183e --- /dev/null +++ b/tests/unique_cases/index_named_table_with_fk.cpp @@ -0,0 +1,79 @@ +#include +#include + +using namespace sqlite_orm; + +TEST_CASE("index named table") { + using std::string; + struct OrderTable { + string order_number; + string start_time; + string end_time; + int type; + int renewal_times; + int status; + float amount; + string openid; + string nickname; + string parking_space_number; + string license_plate_number; + string parking_code; + string phone_number; + string appointment_time; + string arrival_time; + string leave_parking_lot_time; + string parking_time; + string leave_parking_space_time; + string in_barrier_gate_number; + string out_barrier_gate_number; + int parking_duration; + string create_time; + }; + + struct pay_info { + int id; + + int pay_type; + int payment; + float amount; + string pay_time; + std::unique_ptr order_number; + }; + + auto storage = + make_storage("mysqlite.sqlite", + make_table("order", + make_column("order_number", &OrderTable::order_number, primary_key()), + make_column("start_time", &OrderTable::start_time), + make_column("end_time", &OrderTable::end_time), + make_column("type", &OrderTable::type), + make_column("renewal_times", &OrderTable::renewal_times), + make_column("status", &OrderTable::status), + make_column("amount", &OrderTable::amount), + make_column("openid", &OrderTable::openid), + make_column("nickname", &OrderTable::nickname), + make_column("parking_space_number", &OrderTable::parking_space_number), + make_column("license_plate_number", &OrderTable::license_plate_number), + make_column("parking_code", &OrderTable::parking_code), + make_column("phone_number", &OrderTable::phone_number), + make_column("appointment_time", &OrderTable::appointment_time), + make_column("arrival_time", &OrderTable::arrival_time), + make_column("leave_parking_lot_time", &OrderTable::leave_parking_lot_time), + make_column("parking_time", &OrderTable::parking_time), + make_column("leave_parking_space_time", &OrderTable::leave_parking_space_time), + make_column("in_barrier_gate_number", &OrderTable::in_barrier_gate_number), + make_column("out_barrier_gate_number", &OrderTable::out_barrier_gate_number), + make_column("parking_duration", &OrderTable::parking_duration), + make_column("create_time", &OrderTable::create_time)), + + make_table("pay_info", + make_column("id", &pay_info::id, primary_key()), + + make_column("pay_type", &pay_info::pay_type), + make_column("payment", &pay_info::payment), + make_column("amount", &pay_info::amount), + make_column("pay_time", &pay_info::pay_time), + make_column("order_number", &pay_info::order_number), + foreign_key(&pay_info::order_number).references(&OrderTable::order_number))); + storage.sync_schema(); +} From 378fddb13d38137b01dbe2f8639c360a54550842 Mon Sep 17 00:00:00 2001 From: fnc12 Date: Wed, 18 Mar 2020 08:41:34 +0300 Subject: [PATCH 046/132] added more ztatement serializator specializations --- dev/statement_serializator.h | 24 ++++-- dev/storage.h | 45 +++++++---- include/sqlite_orm/sqlite_orm.h | 134 ++++++++++++++++++++++++++------ 3 files changed, 158 insertions(+), 45 deletions(-) diff --git a/dev/statement_serializator.h b/dev/statement_serializator.h index 29d6302d9..0dea42c3c 100644 --- a/dev/statement_serializator.h +++ b/dev/statement_serializator.h @@ -25,6 +25,16 @@ namespace sqlite_orm { statement_serializator serializator; return serializator(t, context); } + + template + struct statement_serializator::value>::type> { + using statement_type = T; + + template + std::string operator()(const statement_type &, const C &) { + return "?"; + } + }; template struct statement_serializator, void> { @@ -408,7 +418,7 @@ namespace sqlite_orm { } }; - template + /*template struct statement_serializator, void> { using statement_type = conditions::is_equal_t; @@ -420,7 +430,7 @@ namespace sqlite_orm { ss << leftString << " " << static_cast(c) << " " << rightString; return ss.str(); } - }; + };*/ template struct statement_serializator< @@ -550,7 +560,7 @@ namespace sqlite_orm { std::string operator()(const statement_type &c, const C &context) const { std::stringstream ss; ss << static_cast(c) << " "; - ss << serialize(c.t, noTableName); + ss << serialize(c.t, context); return ss.str(); } }; @@ -729,7 +739,7 @@ namespace sqlite_orm { } }; - template + /*template struct statement_serializator< T, typename std::enable_if::value>::type> { @@ -743,9 +753,9 @@ namespace sqlite_orm { ss << "(" << leftString << " " << static_cast(c) << " " << rightString << ")"; return ss.str(); } - }; + };*/ - template + /*template struct statement_serializator::value>::type> { using statement_type = T; @@ -755,7 +765,7 @@ namespace sqlite_orm { ss << t; return ss.str(); } - }; + };*/ } } diff --git a/dev/storage.h b/dev/storage.h index 905e39896..fb243989c 100644 --- a/dev/storage.h +++ b/dev/storage.h @@ -334,9 +334,12 @@ namespace sqlite_orm { template std::vector get_column_names(const T &t) const { - auto columnName = this->string_from_expression(t, false); + using context_t = serializator_context; + context_t context{this->impl}; + context.skip_table_name = false; + auto columnName = serialize(t, context); if(columnName.length()) { - return {columnName}; + return {move(columnName)}; } else { throw std::system_error(std::make_error_code(orm_error_code::column_not_found)); } @@ -348,18 +351,21 @@ namespace sqlite_orm { } template - std::vector get_column_names(const internal::asterisk_t &) const { + std::vector get_column_names(const asterisk_t &) const { std::vector res; res.push_back("*"); return res; } template - std::vector get_column_names(const internal::columns_t &cols) const { + std::vector get_column_names(const columns_t &cols) const { std::vector columnNames; columnNames.reserve(static_cast(cols.count)); - iterate_tuple(cols.columns, [&columnNames, this](auto &m) { - auto columnName = this->string_from_expression(m, false); + using context_t = serializator_context; + context_t context{this->impl}; + context.skip_table_name = false; + iterate_tuple(cols.columns, [&columnNames, &context](auto &m) { + auto columnName = serialize(m, context); if(columnName.length()) { columnNames.push_back(columnName); } else { @@ -373,7 +379,7 @@ namespace sqlite_orm { * Takes select_t object and returns SELECT query string */ template - std::string string_from_expression(const internal::select_t &sel, bool /*noTableName*/) const { + std::string string_from_expression(const select_t &sel, bool /*noTableName*/) const { std::stringstream ss; if(!is_base_of_template::value) { if(!sel.highest_level) { @@ -510,11 +516,15 @@ namespace sqlite_orm { ss << " '" << collector.table_names.begin()->first << "' "; ss << static_cast(upd.set) << " "; std::vector setPairs; - iterate_tuple(upd.set.assigns, [this, &setPairs](auto &asgn) { + using context_t = serializator_context; + context_t context{this->impl}; + iterate_tuple(upd.set.assigns, [&context, &setPairs](auto &asgn) { std::stringstream sss; - sss << this->string_from_expression(asgn.lhs, true); + context.skip_table_name = true; + sss << serialize(asgn.lhs, context); sss << " " << static_cast(asgn) << " "; - sss << this->string_from_expression(asgn.rhs, false) << " "; + context.skip_table_name = false; + sss << serialize(asgn.rhs, context) << " "; setPairs.push_back(sss.str()); }); auto setPairsCount = setPairs.size(); @@ -1029,7 +1039,10 @@ namespace sqlite_orm { template std::string process_order_by(const conditions::order_by_t &orderBy) const { std::stringstream ss; - auto columnName = this->string_from_expression(orderBy.o, false); + using context_t = serializator_context; + context_t context{this->impl}; + context.skip_table_name = false; + auto columnName = serialize(orderBy.o, context); ss << columnName << " "; if(orderBy._collate_argument.length()) { ss << "COLLATE " << orderBy._collate_argument << " "; @@ -1047,7 +1060,10 @@ namespace sqlite_orm { template void process_join_constraint(std::stringstream &ss, const conditions::on_t &t) const { - ss << static_cast(t) << " " << this->string_from_expression(t.arg, false); + using context_t = serializator_context; + context_t context{this->impl}; + context.skip_table_name = false; + ss << static_cast(t) << " " << serialize(t.arg, context); } template @@ -1127,7 +1143,10 @@ namespace sqlite_orm { template void process_single_condition(std::stringstream &ss, const conditions::where_t &w) const { ss << static_cast(w) << " "; - auto whereString = this->string_from_expression(w.c, false); +// auto whereString = this->string_from_expression(w.c, false); + using context_t = serializator_context; + context_t context{this->impl}; + auto whereString = serialize(w.c, context); ss << "( " << whereString << ") "; } diff --git a/include/sqlite_orm/sqlite_orm.h b/include/sqlite_orm/sqlite_orm.h index a46480886..0a8fdbb39 100644 --- a/include/sqlite_orm/sqlite_orm.h +++ b/include/sqlite_orm/sqlite_orm.h @@ -27,7 +27,7 @@ __pragma(push_macro("min")) #include #include // std::ostringstream - namespace sqlite_orm { +namespace sqlite_orm { enum class orm_error_code { not_found = 1, @@ -44,6 +44,7 @@ __pragma(push_macro("min")) failed_to_init_a_backup, unknown_member_value, }; + } namespace sqlite_orm { @@ -224,6 +225,7 @@ namespace sqlite_orm { // #include "static_magic.h" + #include // std::false_type, std::true_type, std::integral_constant namespace sqlite_orm { @@ -258,6 +260,7 @@ namespace sqlite_orm { } + namespace sqlite_orm { // got from here http://stackoverflow.com/questions/25958259/how-do-i-find-out-if-a-tuple-contains-a-type @@ -989,6 +992,7 @@ namespace sqlite_orm { // #include "serializator_context.h" + namespace sqlite_orm { namespace internal { @@ -1021,6 +1025,7 @@ namespace sqlite_orm { } + namespace sqlite_orm { namespace internal { @@ -1055,12 +1060,14 @@ namespace sqlite_orm { // #include "negatable.h" + namespace sqlite_orm { namespace internal { struct negatable_t {}; } } + namespace sqlite_orm { namespace internal { @@ -1360,6 +1367,7 @@ namespace sqlite_orm { // #include "getter_traits.h" + namespace sqlite_orm { namespace internal { @@ -1543,6 +1551,7 @@ namespace sqlite_orm { } } + namespace sqlite_orm { namespace internal { @@ -1873,6 +1882,7 @@ namespace sqlite_orm { // #include "optional_container.h" + namespace sqlite_orm { namespace internal { @@ -1907,6 +1917,7 @@ namespace sqlite_orm { // #include "negatable.h" + namespace sqlite_orm { namespace internal { @@ -3352,6 +3363,7 @@ namespace sqlite_orm { // #include "conditions.h" + namespace sqlite_orm { namespace internal { @@ -3471,6 +3483,7 @@ namespace sqlite_orm { // #include "is_base_of_template.h" + #include // std::true_type, std::false_type, std::declval namespace sqlite_orm { @@ -3508,6 +3521,7 @@ namespace sqlite_orm { } } + namespace sqlite_orm { namespace internal { @@ -4260,6 +4274,7 @@ namespace sqlite_orm { // #include "optional_container.h" + namespace sqlite_orm { namespace internal { @@ -4616,6 +4631,7 @@ namespace sqlite_orm { // #include "column.h" + namespace sqlite_orm { namespace internal { @@ -4722,6 +4738,7 @@ namespace sqlite_orm { // #include "is_std_ptr.h" + namespace sqlite_orm { /** @@ -4749,6 +4766,7 @@ namespace sqlite_orm { }; } + namespace sqlite_orm { /** @@ -4959,6 +4977,7 @@ namespace sqlite_orm { // #include "journal_mode.h" + #include // std::string #include // std::unique_ptr #include // std::array @@ -5021,6 +5040,7 @@ namespace sqlite_orm { // #include "error_code.h" + namespace sqlite_orm { /** @@ -5397,6 +5417,7 @@ namespace sqlite_orm { // #include "alias.h" + namespace sqlite_orm { namespace internal { @@ -5643,6 +5664,7 @@ namespace sqlite_orm { } } + namespace sqlite_orm { namespace internal { @@ -5907,6 +5929,7 @@ namespace sqlite_orm { // #include "column.h" + namespace sqlite_orm { namespace internal { @@ -6206,10 +6229,12 @@ namespace sqlite_orm { // #include "field_value_holder.h" + #include // std::enable_if // #include "column.h" + namespace sqlite_orm { namespace internal { @@ -6232,6 +6257,7 @@ namespace sqlite_orm { } } + namespace sqlite_orm { namespace internal { @@ -6733,6 +6759,7 @@ namespace sqlite_orm { // #include "view.h" + #include // std::shared_ptr #include // std::string #include // std::forward, std::move @@ -6748,6 +6775,7 @@ namespace sqlite_orm { // #include "iterator.h" + #include // std::shared_ptr, std::unique_ptr, std::make_shared #include #include // std::decay @@ -6763,6 +6791,7 @@ namespace sqlite_orm { // #include "error_code.h" + namespace sqlite_orm { namespace internal { @@ -6891,6 +6920,7 @@ namespace sqlite_orm { // #include "ast_iterator.h" + #include // std::vector #include // std::reference_wrapper @@ -6906,6 +6936,7 @@ namespace sqlite_orm { // #include "prepared_statement.h" + #include #include // std::iterator_traits #include // std::string @@ -6914,12 +6945,14 @@ namespace sqlite_orm { // #include "connection_holder.h" + #include #include // std::string #include // std::system_error // #include "error_code.h" + namespace sqlite_orm { namespace internal { @@ -6994,6 +7027,7 @@ namespace sqlite_orm { // #include "select_constraints.h" + namespace sqlite_orm { namespace internal { @@ -7377,6 +7411,7 @@ namespace sqlite_orm { #endif // SQLITE_ORM_OPTIONAL_SUPPORTED } + namespace sqlite_orm { namespace internal { @@ -7864,6 +7899,7 @@ namespace sqlite_orm { // #include "connection_holder.h" + namespace sqlite_orm { namespace internal { @@ -7922,6 +7958,7 @@ namespace sqlite_orm { // #include "storage_base.h" + #include // std::function, std::bind #include #include // std::string @@ -7936,6 +7973,7 @@ namespace sqlite_orm { // #include "pragma.h" + #include // std::string #include #include // std::function @@ -7949,6 +7987,7 @@ namespace sqlite_orm { // #include "connection_holder.h" + namespace sqlite_orm { namespace internal { @@ -8069,6 +8108,7 @@ namespace sqlite_orm { // #include "limit_accesor.h" + #include #include // std::map #include // std::function @@ -8076,6 +8116,7 @@ namespace sqlite_orm { // #include "connection_holder.h" + namespace sqlite_orm { namespace internal { @@ -8209,10 +8250,12 @@ namespace sqlite_orm { // #include "transaction_guard.h" + #include // std::function // #include "connection_holder.h" + namespace sqlite_orm { namespace internal { @@ -8287,6 +8330,7 @@ namespace sqlite_orm { // #include "backup.h" + #include #include // std::string #include @@ -8295,6 +8339,7 @@ namespace sqlite_orm { // #include "connection_holder.h" + namespace sqlite_orm { namespace internal { @@ -8360,6 +8405,7 @@ namespace sqlite_orm { } } + namespace sqlite_orm { namespace internal { @@ -8895,11 +8941,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 { @@ -9019,6 +9067,7 @@ namespace sqlite_orm { // #include "statement_serializator.h" + #include // std::stringstream #include // std::string #include // std::is_arithmetic, std::enable_if @@ -9037,6 +9086,7 @@ namespace sqlite_orm { // #include "type_printer.h" + namespace sqlite_orm { namespace internal { @@ -9049,6 +9099,16 @@ namespace sqlite_orm { statement_serializator serializator; return serializator(t, context); } + + template + struct statement_serializator::value>::type> { + using statement_type = T; + + template + std::string operator()(const statement_type &, const C &) { + return "?"; + } + }; template struct statement_serializator, void> { @@ -9432,7 +9492,7 @@ namespace sqlite_orm { } }; - template + /*template struct statement_serializator, void> { using statement_type = conditions::is_equal_t; @@ -9444,7 +9504,7 @@ namespace sqlite_orm { ss << leftString << " " << static_cast(c) << " " << rightString; return ss.str(); } - }; + };*/ template struct statement_serializator< @@ -9574,7 +9634,7 @@ namespace sqlite_orm { std::string operator()(const statement_type &c, const C &context) const { std::stringstream ss; ss << static_cast(c) << " "; - ss << serialize(c.t, noTableName); + ss << serialize(c.t, context); return ss.str(); } }; @@ -9753,7 +9813,7 @@ namespace sqlite_orm { } }; - template + /*template struct statement_serializator< T, typename std::enable_if::value>::type> { @@ -9767,9 +9827,9 @@ namespace sqlite_orm { ss << "(" << leftString << " " << static_cast(c) << " " << rightString << ")"; return ss.str(); } - }; + };*/ - template + /*template struct statement_serializator::value>::type> { using statement_type = T; @@ -9779,13 +9839,14 @@ namespace sqlite_orm { ss << t; return ss.str(); } - }; + };*/ } } // #include "table_name_collector.h" + #include // std::set #include // std::string #include // std::function @@ -9797,6 +9858,7 @@ namespace sqlite_orm { // #include "core_functions.h" + namespace sqlite_orm { namespace internal { @@ -9855,6 +9917,7 @@ namespace sqlite_orm { } + namespace sqlite_orm { namespace conditions { @@ -10141,9 +10204,12 @@ namespace sqlite_orm { template std::vector get_column_names(const T &t) const { - auto columnName = this->string_from_expression(t, false); + using context_t = serializator_context; + context_t context{this->impl}; + context.skip_table_name = false; + auto columnName = serialize(t, context); if(columnName.length()) { - return {columnName}; + return {move(columnName)}; } else { throw std::system_error(std::make_error_code(orm_error_code::column_not_found)); } @@ -10165,8 +10231,11 @@ namespace sqlite_orm { std::vector get_column_names(const internal::columns_t &cols) const { std::vector columnNames; columnNames.reserve(static_cast(cols.count)); - iterate_tuple(cols.columns, [&columnNames, this](auto &m) { - auto columnName = this->string_from_expression(m, false); + using context_t = serializator_context; + context_t context{this->impl}; + context.skip_table_name = false; + iterate_tuple(cols.columns, [&columnNames, &context](auto &m) { + auto columnName = serialize(m, context); if(columnName.length()) { columnNames.push_back(columnName); } else { @@ -10317,11 +10386,15 @@ namespace sqlite_orm { ss << " '" << collector.table_names.begin()->first << "' "; ss << static_cast(upd.set) << " "; std::vector setPairs; - iterate_tuple(upd.set.assigns, [this, &setPairs](auto &asgn) { + using context_t = serializator_context; + context_t context{this->impl}; + iterate_tuple(upd.set.assigns, [&context, &setPairs](auto &asgn) { std::stringstream sss; - sss << this->string_from_expression(asgn.lhs, true); + context.skip_table_name = true; + sss << serialize(asgn.lhs, context); sss << " " << static_cast(asgn) << " "; - sss << this->string_from_expression(asgn.rhs, false) << " "; + context.skip_table_name = false; + sss << serialize(asgn.rhs, context) << " "; setPairs.push_back(sss.str()); }); auto setPairsCount = setPairs.size(); @@ -10836,7 +10909,10 @@ namespace sqlite_orm { template std::string process_order_by(const conditions::order_by_t &orderBy) const { std::stringstream ss; - auto columnName = this->string_from_expression(orderBy.o, false); + using context_t = serializator_context; + context_t context{this->impl}; + context.skip_table_name = false; + auto columnName = serialize(orderBy.o, context); ss << columnName << " "; if(orderBy._collate_argument.length()) { ss << "COLLATE " << orderBy._collate_argument << " "; @@ -10854,7 +10930,10 @@ namespace sqlite_orm { template void process_join_constraint(std::stringstream &ss, const conditions::on_t &t) const { - ss << static_cast(t) << " " << this->string_from_expression(t.arg, false); + using context_t = serializator_context; + context_t context{this->impl}; + context.skip_table_name = false; + ss << static_cast(t) << " " << serialize(t.arg, context); } template @@ -10934,7 +11013,10 @@ namespace sqlite_orm { template void process_single_condition(std::stringstream &ss, const conditions::where_t &w) const { ss << static_cast(w) << " "; - auto whereString = this->string_from_expression(w.c, false); +// auto whereString = this->string_from_expression(w.c, false); + using context_t = serializator_context; + context_t context{this->impl}; + auto whereString = serialize(w.c, context); ss << "( " << whereString << ") "; } @@ -12460,19 +12542,20 @@ __pragma(pop_macro("min")) #include // std::pair #include // std::reference_wrapper - // #include "conditions.h" +// #include "conditions.h" - // #include "operators.h" +// #include "operators.h" + +// #include "select_constraints.h" - // #include "select_constraints.h" +// #include "prepared_statement.h" - // #include "prepared_statement.h" +// #include "optional_container.h" - // #include "optional_container.h" +// #include "core_functions.h" - // #include "core_functions.h" - namespace sqlite_orm { +namespace sqlite_orm { namespace internal { @@ -12754,6 +12837,7 @@ __pragma(pop_macro("min")) // #include "expression_object_type.h" + namespace sqlite_orm { template From 5442e4a3882c1a55fe78425a4e3d6c5dc26692e7 Mon Sep 17 00:00:00 2001 From: fnc12 Date: Sat, 21 Mar 2020 22:18:31 +0300 Subject: [PATCH 047/132] added column names getter --- dev/column_names_getter.h | 84 +++++++++++++++++++++++++++++++++ dev/statement_serializator.h | 80 +++++++++++++++++++++++++------ dev/storage.h | 25 +++++----- include/sqlite_orm/sqlite_orm.h | 6 +-- 4 files changed, 167 insertions(+), 28 deletions(-) create mode 100644 dev/column_names_getter.h diff --git a/dev/column_names_getter.h b/dev/column_names_getter.h new file mode 100644 index 000000000..1719752e1 --- /dev/null +++ b/dev/column_names_getter.h @@ -0,0 +1,84 @@ +#pragma once + +#include // std::string +#include // std::vector +#include // std::reference_wrapper + +#include "error_code.h" +#include "select_constraints.h" + +namespace sqlite_orm { + +namespace internal { + +template +std::string serialize(const T &t, const C &context); + +template +struct column_names_getter { + using expression_type = T; + + template + std::vector operator()(const expression_type &t, const C &context) { + auto newContext = context; + newContext.skip_table_name = false; + auto columnName = serialize(t, newContext); + if(columnName.length()) { + return {move(columnName)}; + } else { + throw std::system_error(std::make_error_code(orm_error_code::column_not_found)); + } + } +}; + + template + std::vector get_column_names(const T &t, const C &context) { + column_names_getter serializator; + return column_names_getter(t, context); + } + +template +struct column_names_getter, void> { + using expression_type = std::reference_wrapper; + + template + std::vector operator()(const expression_type &expression, const C &context) { + return get_column_names(expression.get(), context); + } +}; +template +struct column_names_getter, void> { + using expression_type = asterisk_t; + + template + std::vector operator()(const expression_type &, const C &) { + std::vector res; + res.push_back("*"); + return res; + } +}; + +template +struct column_names_getter, void> { + using expression_type = columns_t; + + template + std::vector operator()(const expression_type &expression, const C &context) { + std::vector columnNames; + columnNames.reserve(static_cast(cols.count)); + auto newContext = context; + newContext.skip_table_name = false; + iterate_tuple(cols.columns, [&columnNames, &newContext](auto &m) { + auto columnName = serialize(m, newContext); + if(columnName.length()) { + columnNames.push_back(columnName); + } else { + throw std::system_error(std::make_error_code(orm_error_code::column_not_found)); + } + }); + return columnNames; + } +}; + +} +} diff --git a/dev/statement_serializator.h b/dev/statement_serializator.h index 0dea42c3c..3fb52b276 100644 --- a/dev/statement_serializator.h +++ b/dev/statement_serializator.h @@ -418,20 +418,6 @@ namespace sqlite_orm { } }; - /*template - struct statement_serializator, void> { - using statement_type = conditions::is_equal_t; - - template - std::string operator()(const statement_type &c, const C &context) const { - auto leftString = serialize(c.l, context); - auto rightString = serialize(c.r, context); - std::stringstream ss; - ss << leftString << " " << static_cast(c) << " " << rightString; - return ss.str(); - } - };*/ - template struct statement_serializator< T, @@ -738,6 +724,72 @@ namespace sqlite_orm { return ss.str(); } }; + + template + struct statement_serializator, void> { + using statement_type = select_t; + + template + std::string operator()(const statement_type &sel, const C &context) const { + std::stringstream ss; + if(!is_base_of_template::value) { + if(!sel.highest_level) { + ss << "( "; + } + ss << "SELECT "; + } + if(get_distinct(sel.col)) { + ss << static_cast(distinct(0)) << " "; + } + auto columnNames = get_column_names(sel.col, context); + for(size_t i = 0; i < columnNames.size(); ++i) { + ss << columnNames[i]; + if(i < columnNames.size() - 1) { + ss << ","; + } + ss << " "; + } + table_name_collector collector{[&context](std::type_index ti) { + return context.impl.find_table_name(ti); + }}; + iterate_ast(sel.col, collector); + iterate_ast(sel.conditions, collector); + internal::join_iterator()([&collector, &](const auto &c) { + using original_join_type = typename std::decay::type::join_type::type; + using cross_join_type = typename internal::mapped_type_proxy::type; + auto crossJoinedTableName = context.impl.find_table_name(typeid(cross_join_type)); + auto tableAliasString = alias_extractor::get(); + std::pair tableNameWithAlias(std::move(crossJoinedTableName), + std::move(tableAliasString)); + collector.table_names.erase(tableNameWithAlias); + }); + if(!collector.table_names.empty()) { + ss << "FROM "; + std::vector> tableNames(collector.table_names.begin(), + collector.table_names.end()); + for(size_t i = 0; i < tableNames.size(); ++i) { + auto &tableNamePair = tableNames[i]; + ss << "'" << tableNamePair.first << "' "; + if(!tableNamePair.second.empty()) { + ss << tableNamePair.second << " "; + } + if(int(i) < int(tableNames.size()) - 1) { + ss << ","; + } + ss << " "; + } + } + iterate_tuple(sel.conditions, [&ss, this](auto &v) { + this->process_single_condition(ss, v); + }); + if(!is_base_of_template::value) { + if(!sel.highest_level) { + ss << ") "; + } + } + return ss.str(); + } + }; /*template struct statement_serializator< diff --git a/dev/storage.h b/dev/storage.h index fb243989c..5ef13a8d0 100644 --- a/dev/storage.h +++ b/dev/storage.h @@ -332,7 +332,7 @@ namespace sqlite_orm { return ss.str(); }*/ - template + /*template std::vector get_column_names(const T &t) const { using context_t = serializator_context; context_t context{this->impl}; @@ -343,21 +343,21 @@ namespace sqlite_orm { } else { throw std::system_error(std::make_error_code(orm_error_code::column_not_found)); } - } + }*/ - template + /*template std::vector get_column_names(std::reference_wrapper r) const { return this->get_column_names(r.get()); - } + }*/ - template + /*template std::vector get_column_names(const asterisk_t &) const { std::vector res; res.push_back("*"); return res; - } + }*/ - template + /*template std::vector get_column_names(const columns_t &cols) const { std::vector columnNames; columnNames.reserve(static_cast(cols.count)); @@ -373,14 +373,14 @@ namespace sqlite_orm { } }); return columnNames; - } + }*/ /** * Takes select_t object and returns SELECT query string */ template - std::string string_from_expression(const select_t &sel, bool /*noTableName*/) const { - std::stringstream ss; + std::string string_from_expression(const select_t &sel, bool) const { + /*std::stringstream ss; if(!is_base_of_template::value) { if(!sel.highest_level) { ss << "( "; @@ -436,7 +436,10 @@ namespace sqlite_orm { ss << ") "; } } - return ss.str(); + return ss.str();*/ + using context_t = serializator_context; + context_t context{this->impl}; + return serialize(sel, context); } // Common code for statements returning the whole content of a table: get_all_t, get_all_pointer_t, diff --git a/include/sqlite_orm/sqlite_orm.h b/include/sqlite_orm/sqlite_orm.h index 0a8fdbb39..c14a3c96e 100644 --- a/include/sqlite_orm/sqlite_orm.h +++ b/include/sqlite_orm/sqlite_orm.h @@ -10221,14 +10221,14 @@ namespace sqlite_orm { } template - std::vector get_column_names(const internal::asterisk_t &) const { + std::vector get_column_names(const asterisk_t &) const { std::vector res; res.push_back("*"); return res; } template - std::vector get_column_names(const internal::columns_t &cols) const { + std::vector get_column_names(const columns_t &cols) const { std::vector columnNames; columnNames.reserve(static_cast(cols.count)); using context_t = serializator_context; @@ -10249,7 +10249,7 @@ namespace sqlite_orm { * Takes select_t object and returns SELECT query string */ template - std::string string_from_expression(const internal::select_t &sel, bool /*noTableName*/) const { + std::string string_from_expression(const select_t &sel, bool /*noTableName*/) const { std::stringstream ss; if(!is_base_of_template::value) { if(!sel.highest_level) { From 48e68f3789eb2a8826d43539dddfc57703526e90 Mon Sep 17 00:00:00 2001 From: fnc12 Date: Sun, 22 Mar 2020 02:24:32 +0300 Subject: [PATCH 048/132] renamed process_single_condition to string_from_expression --- dev/storage.h | 58 +++++++++++++++++++++++---------- include/sqlite_orm/sqlite_orm.h | 58 +++++++++++++++++++++++---------- 2 files changed, 82 insertions(+), 34 deletions(-) diff --git a/dev/storage.h b/dev/storage.h index 0978b8ed4..e4adbd9a0 100644 --- a/dev/storage.h +++ b/dev/storage.h @@ -418,7 +418,7 @@ namespace sqlite_orm { } } iterate_tuple(sel.conditions, [&ss, this](auto &v) { - this->process_single_condition(ss, v); + ss << this->string_from_expression(v, false); }); if(!is_base_of_template::value) { if(!sel.highest_level) { @@ -1055,7 +1055,8 @@ namespace sqlite_orm { * OI - offset is implicit */ template - void process_single_condition(std::stringstream &ss, const conditions::limit_t &limt) const { + std::string string_from_expression(const conditions::limit_t &limt, bool) const { + std::stringstream ss; ss << static_cast(limt) << " "; if(HO) { if(OI) { @@ -1073,22 +1074,28 @@ namespace sqlite_orm { } else { ss << this->string_from_expression(limt.lim, false); } + return ss.str(); } template - void process_single_condition(std::stringstream &ss, const conditions::cross_join_t &c) const { + std::string string_from_expression(const conditions::cross_join_t &c, bool) const { + std::stringstream ss; ss << static_cast(c) << " "; ss << " '" << this->impl.find_table_name(typeid(O)) << "'"; + return ss.str(); } template - void process_single_condition(std::stringstream &ss, const conditions::natural_join_t &c) const { + std::string string_from_expression(const conditions::natural_join_t &c, bool) const { + std::stringstream ss; ss << static_cast(c) << " "; ss << " '" << this->impl.find_table_name(typeid(O)) << "'"; + return ss.str(); } template - void process_single_condition(std::stringstream &ss, const conditions::inner_join_t &l) const { + std::string string_from_expression(const conditions::inner_join_t &l, bool) const { + std::stringstream ss; ss << static_cast(l) << " "; auto aliasString = alias_extractor::get(); ss << " '" << this->impl.find_table_name(typeid(typename mapped_type_proxy::type)) << "' "; @@ -1096,46 +1103,57 @@ namespace sqlite_orm { ss << "'" << aliasString << "' "; } this->process_join_constraint(ss, l.constraint); + return ss.str(); } template - void process_single_condition(std::stringstream &ss, const conditions::left_outer_join_t &l) const { + std::string string_from_expression(const conditions::left_outer_join_t &l, bool) const { + std::stringstream ss; ss << static_cast(l) << " "; ss << " '" << this->impl.find_table_name(typeid(T)) << "' "; this->process_join_constraint(ss, l.constraint); + return ss.str(); } template - void process_single_condition(std::stringstream &ss, const conditions::left_join_t &l) const { + std::string string_from_expression(const conditions::left_join_t &l, bool) const { + std::stringstream ss; ss << static_cast(l) << " "; ss << " '" << this->impl.find_table_name(typeid(T)) << "' "; this->process_join_constraint(ss, l.constraint); + return ss.str(); } template - void process_single_condition(std::stringstream &ss, const conditions::join_t &l) const { + std::string string_from_expression(const conditions::join_t &l, bool) const { + std::stringstream ss; ss << static_cast(l) << " "; ss << " '" << this->impl.find_table_name(typeid(T)) << "' "; this->process_join_constraint(ss, l.constraint); + return ss.str(); } template - void process_single_condition(std::stringstream &ss, const conditions::where_t &w) const { + std::string string_from_expression(const conditions::where_t &w, bool) const { + std::stringstream ss; ss << static_cast(w) << " "; auto whereString = this->string_from_expression(w.c, false); ss << "( " << whereString << ") "; + return ss.str(); } template - void process_single_condition(std::stringstream &ss, const conditions::order_by_t &orderBy) const { + std::string string_from_expression(const conditions::order_by_t &orderBy, bool) const { + std::stringstream ss; ss << static_cast(orderBy) << " "; auto orderByString = this->process_order_by(orderBy); ss << orderByString << " "; + return ss.str(); } template - void process_single_condition(std::stringstream &ss, - const conditions::multi_order_by_t &orderBy) const { + std::string string_from_expression(const conditions::multi_order_by_t &orderBy, bool) const { + std::stringstream ss; std::vector expressions; iterate_tuple(orderBy.args, [&expressions, this](auto &v) { auto expression = this->process_order_by(v); @@ -1149,16 +1167,19 @@ namespace sqlite_orm { } } ss << " "; + return ss.str(); } template - void process_single_condition(std::stringstream &ss, - const conditions::dynamic_order_by_t &orderBy) const { + std::string string_from_expression(const conditions::dynamic_order_by_t &orderBy, bool) const { + std::stringstream ss; ss << this->storage_base::process_order_by(orderBy) << " "; + return ss.str(); } template - void process_single_condition(std::stringstream &ss, const conditions::group_by_t &groupBy) const { + std::string string_from_expression(const conditions::group_by_t &groupBy, bool) const { + std::stringstream ss; std::vector expressions; iterate_tuple(groupBy.args, [&expressions, this](auto &v) { auto expression = this->string_from_expression(v, false); @@ -1172,18 +1193,21 @@ namespace sqlite_orm { } } ss << " "; + return ss.str(); } template - void process_single_condition(std::stringstream &ss, const conditions::having_t &hav) const { + std::string string_from_expression(const conditions::having_t &hav, bool) const { + std::stringstream ss; ss << static_cast(hav) << " "; ss << this->string_from_expression(hav.t, false) << " "; + return ss.str(); } template void process_conditions(std::stringstream &ss, const std::tuple &args) const { iterate_tuple(args, [this, &ss](auto &v) { - this->process_single_condition(ss, v); + ss << this->string_from_expression(v, false); }); } diff --git a/include/sqlite_orm/sqlite_orm.h b/include/sqlite_orm/sqlite_orm.h index a6ae12883..53195cb3c 100644 --- a/include/sqlite_orm/sqlite_orm.h +++ b/include/sqlite_orm/sqlite_orm.h @@ -9759,7 +9759,7 @@ namespace sqlite_orm { } } iterate_tuple(sel.conditions, [&ss, this](auto &v) { - this->process_single_condition(ss, v); + ss << this->string_from_expression(v, false); }); if(!is_base_of_template::value) { if(!sel.highest_level) { @@ -10396,7 +10396,8 @@ namespace sqlite_orm { * OI - offset is implicit */ template - void process_single_condition(std::stringstream &ss, const conditions::limit_t &limt) const { + std::string string_from_expression(const conditions::limit_t &limt, bool) const { + std::stringstream ss; ss << static_cast(limt) << " "; if(HO) { if(OI) { @@ -10414,22 +10415,28 @@ namespace sqlite_orm { } else { ss << this->string_from_expression(limt.lim, false); } + return ss.str(); } template - void process_single_condition(std::stringstream &ss, const conditions::cross_join_t &c) const { + std::string string_from_expression(const conditions::cross_join_t &c, bool) const { + std::stringstream ss; ss << static_cast(c) << " "; ss << " '" << this->impl.find_table_name(typeid(O)) << "'"; + return ss.str(); } template - void process_single_condition(std::stringstream &ss, const conditions::natural_join_t &c) const { + std::string string_from_expression(const conditions::natural_join_t &c, bool) const { + std::stringstream ss; ss << static_cast(c) << " "; ss << " '" << this->impl.find_table_name(typeid(O)) << "'"; + return ss.str(); } template - void process_single_condition(std::stringstream &ss, const conditions::inner_join_t &l) const { + std::string string_from_expression(const conditions::inner_join_t &l, bool) const { + std::stringstream ss; ss << static_cast(l) << " "; auto aliasString = alias_extractor::get(); ss << " '" << this->impl.find_table_name(typeid(typename mapped_type_proxy::type)) << "' "; @@ -10437,46 +10444,57 @@ namespace sqlite_orm { ss << "'" << aliasString << "' "; } this->process_join_constraint(ss, l.constraint); + return ss.str(); } template - void process_single_condition(std::stringstream &ss, const conditions::left_outer_join_t &l) const { + std::string string_from_expression(const conditions::left_outer_join_t &l, bool) const { + std::stringstream ss; ss << static_cast(l) << " "; ss << " '" << this->impl.find_table_name(typeid(T)) << "' "; this->process_join_constraint(ss, l.constraint); + return ss.str(); } template - void process_single_condition(std::stringstream &ss, const conditions::left_join_t &l) const { + std::string string_from_expression(const conditions::left_join_t &l, bool) const { + std::stringstream ss; ss << static_cast(l) << " "; ss << " '" << this->impl.find_table_name(typeid(T)) << "' "; this->process_join_constraint(ss, l.constraint); + return ss.str(); } template - void process_single_condition(std::stringstream &ss, const conditions::join_t &l) const { + std::string string_from_expression(const conditions::join_t &l, bool) const { + std::stringstream ss; ss << static_cast(l) << " "; ss << " '" << this->impl.find_table_name(typeid(T)) << "' "; this->process_join_constraint(ss, l.constraint); + return ss.str(); } template - void process_single_condition(std::stringstream &ss, const conditions::where_t &w) const { + std::string string_from_expression(const conditions::where_t &w, bool) const { + std::stringstream ss; ss << static_cast(w) << " "; auto whereString = this->string_from_expression(w.c, false); ss << "( " << whereString << ") "; + return ss.str(); } template - void process_single_condition(std::stringstream &ss, const conditions::order_by_t &orderBy) const { + std::string string_from_expression(const conditions::order_by_t &orderBy, bool) const { + std::stringstream ss; ss << static_cast(orderBy) << " "; auto orderByString = this->process_order_by(orderBy); ss << orderByString << " "; + return ss.str(); } template - void process_single_condition(std::stringstream &ss, - const conditions::multi_order_by_t &orderBy) const { + std::string string_from_expression(const conditions::multi_order_by_t &orderBy, bool) const { + std::stringstream ss; std::vector expressions; iterate_tuple(orderBy.args, [&expressions, this](auto &v) { auto expression = this->process_order_by(v); @@ -10490,16 +10508,19 @@ namespace sqlite_orm { } } ss << " "; + return ss.str(); } template - void process_single_condition(std::stringstream &ss, - const conditions::dynamic_order_by_t &orderBy) const { + std::string string_from_expression(const conditions::dynamic_order_by_t &orderBy, bool) const { + std::stringstream ss; ss << this->storage_base::process_order_by(orderBy) << " "; + return ss.str(); } template - void process_single_condition(std::stringstream &ss, const conditions::group_by_t &groupBy) const { + std::string string_from_expression(const conditions::group_by_t &groupBy, bool) const { + std::stringstream ss; std::vector expressions; iterate_tuple(groupBy.args, [&expressions, this](auto &v) { auto expression = this->string_from_expression(v, false); @@ -10513,18 +10534,21 @@ namespace sqlite_orm { } } ss << " "; + return ss.str(); } template - void process_single_condition(std::stringstream &ss, const conditions::having_t &hav) const { + std::string string_from_expression(const conditions::having_t &hav, bool) const { + std::stringstream ss; ss << static_cast(hav) << " "; ss << this->string_from_expression(hav.t, false) << " "; + return ss.str(); } template void process_conditions(std::stringstream &ss, const std::tuple &args) const { iterate_tuple(args, [this, &ss](auto &v) { - this->process_single_condition(ss, v); + ss << this->string_from_expression(v, false); }); } From 7be2ca26eeda9afccad9b04701d0277c3aae9adb Mon Sep 17 00:00:00 2001 From: Yevgeniy Zakharov Date: Sun, 22 Mar 2020 15:22:17 +0300 Subject: [PATCH 049/132] Update TODO.md --- TODO.md | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/TODO.md b/TODO.md index b86065dc5..3596ff358 100644 --- a/TODO.md +++ b/TODO.md @@ -6,16 +6,14 @@ * rest of core functions(https://sqlite.org/lang_corefunc.html) * `ATTACH` * blob incremental I/O https://sqlite.org/c3ref/blob_open.html -* reusing of prepared statements - useful for query optimisation * explicit FROM for subqueries in FROM argument -* backup API https://www.sqlite.org/backup.html * busy handler https://sqlite.org/c3ref/busy_handler.html * CREATE VIEW and other view operations https://sqlite.org/lang_createview.html * triggers * query static check for correct order (e.g. `GROUP BY` after `WHERE`) * `WINDOW` * `UPSERT` https://www.sqlite.org/lang_UPSERT.html -* `CHECK` constraint * `SAVEPOINT` https://www.sqlite.org/lang_savepoint.html +* add `static_assert` in crud `get*` functions in case user passes `where_t` instead of id to make compilation error more clear (example https://github.com/fnc12/sqlite_orm/issues/485) Please feel free to add any feature that isn't listed here and not implemented yet. From 2242a3066473c098835be71b222477f63d325f2d Mon Sep 17 00:00:00 2001 From: Yevgeniy Zakharov Date: Mon, 23 Mar 2020 23:33:50 +0300 Subject: [PATCH 050/132] Update TODO.md --- TODO.md | 1 + 1 file changed, 1 insertion(+) diff --git a/TODO.md b/TODO.md index 3596ff358..511c79bcf 100644 --- a/TODO.md +++ b/TODO.md @@ -15,5 +15,6 @@ * `UPSERT` https://www.sqlite.org/lang_UPSERT.html * `SAVEPOINT` https://www.sqlite.org/lang_savepoint.html * add `static_assert` in crud `get*` functions in case user passes `where_t` instead of id to make compilation error more clear (example https://github.com/fnc12/sqlite_orm/issues/485) +* generated columns https://www.sqlite.org/gencol.html Please feel free to add any feature that isn't listed here and not implemented yet. From d12745813aba514dde7c436867cabca0be807400 Mon Sep 17 00:00:00 2001 From: fnc12 Date: Thu, 26 Mar 2020 18:30:37 +0300 Subject: [PATCH 051/132] added order by serializator --- dev/column_names_getter.h | 4 +- dev/conditions.h | 25 +- dev/order_by_serializator.h | 87 ++++ dev/statement_serializator.h | 240 +++++++++- dev/storage.h | 81 ++-- dev/storage_base.h | 4 +- include/sqlite_orm/sqlite_orm.h | 765 ++++++++++++++++++++++++++------ 7 files changed, 1012 insertions(+), 194 deletions(-) create mode 100644 dev/order_by_serializator.h diff --git a/dev/column_names_getter.h b/dev/column_names_getter.h index 1719752e1..587c83bec 100644 --- a/dev/column_names_getter.h +++ b/dev/column_names_getter.h @@ -34,7 +34,7 @@ struct column_names_getter { template std::vector get_column_names(const T &t, const C &context) { column_names_getter serializator; - return column_names_getter(t, context); + return serializator(t, context); } template @@ -63,7 +63,7 @@ struct column_names_getter, void> { using expression_type = columns_t; template - std::vector operator()(const expression_type &expression, const C &context) { + std::vector operator()(const expression_type &cols, const C &context) { std::vector columnNames; columnNames.reserve(static_cast(cols.count)); auto newContext = context; diff --git a/dev/conditions.h b/dev/conditions.h index b2d0703be..ad84ad078 100644 --- a/dev/conditions.h +++ b/dev/conditions.h @@ -492,11 +492,11 @@ namespace sqlite_orm { }; /** - * S - storage class + * C - serializator context class */ - template + template struct dynamic_order_by_t : order_by_string { - using storage_type = S; + using context_t = C; struct entry_t : order_by_base { std::string name; @@ -507,11 +507,13 @@ namespace sqlite_orm { using const_iterator = typename std::vector::const_iterator; - dynamic_order_by_t(const storage_type &storage_) : storage(storage_) {} + dynamic_order_by_t(const context_t &context_) : context(context_) {} template void push_back(order_by_t order_by) { - auto columnName = this->storage.string_from_expression(order_by.o, true); + auto newContext = this->context; + newContext.skip_table_name = true; + auto columnName = serialize(order_by.o, newContext); entries.emplace_back(move(columnName), order_by.asc_desc, move(order_by._collate_argument)); } @@ -529,7 +531,7 @@ namespace sqlite_orm { protected: std::vector entries; - const storage_type &storage; + const context_t &context; }; template @@ -541,8 +543,8 @@ namespace sqlite_orm { template struct is_order_by> : std::true_type {}; - template - struct is_order_by> : std::true_type {}; + template + struct is_order_by> : std::true_type {}; struct group_by_string { operator std::string() const { @@ -1220,8 +1222,11 @@ namespace sqlite_orm { * } */ template - conditions::dynamic_order_by_t dynamic_order_by(const S &storage) { - return {storage}; + conditions::dynamic_order_by_t> dynamic_order_by(const S &storage) { + using context_t = internal::serializator_context; + using return_type = conditions::dynamic_order_by_t; + context_t context{storage.impl}; + return return_type{std::move(context)}; } /** diff --git a/dev/order_by_serializator.h b/dev/order_by_serializator.h new file mode 100644 index 000000000..1d5df0854 --- /dev/null +++ b/dev/order_by_serializator.h @@ -0,0 +1,87 @@ +#pragma once + +#include // std::string +#include // std::vector +#include // std::stringstream + +namespace sqlite_orm { + +namespace internal { + +template +struct order_by_serializator; + +template +std::string serialize_order_by(const T &t, const C &context) { + order_by_serializator serializator; + return serializator(t, context); +} + +template +struct order_by_serializator, void> { + using statement_type = conditions::order_by_t; + + template + std::string operator()(const statement_type &orderBy, const C &context) const { + std::stringstream ss; + auto newContext = context; + newContext.skip_table_name = false; + auto columnName = serialize(orderBy.o, newContext); + ss << columnName << " "; + if(orderBy._collate_argument.length()) { + ss << "COLLATE " << orderBy._collate_argument << " "; + } + switch(orderBy.asc_desc) { + case 1: + ss << "ASC"; + break; + case -1: + ss << "DESC"; + break; + } + return ss.str(); + } +}; + +template +struct order_by_serializator, void> { + using statement_type = conditions::dynamic_order_by_t; + + template + std::string operator()(const statement_type &orderBy, const C &) const { + std::vector expressions; + for(auto &entry: orderBy) { + std::string entryString; + { + std::stringstream ss; + ss << entry.name << " "; + if(!entry._collate_argument.empty()) { + ss << "COLLATE " << entry._collate_argument << " "; + } + switch(entry.asc_desc) { + case 1: + ss << "ASC"; + break; + case -1: + ss << "DESC"; + break; + } + entryString = ss.str(); + } + expressions.push_back(move(entryString)); + }; + std::stringstream ss; + ss << static_cast(orderBy) << " "; + for(size_t i = 0; i < expressions.size(); ++i) { + ss << expressions[i]; + if(i < expressions.size() - 1) { + ss << ", "; + } + } + ss << " "; + return ss.str(); + } +}; + +} +} diff --git a/dev/statement_serializator.h b/dev/statement_serializator.h index 3fb52b276..c4d993021 100644 --- a/dev/statement_serializator.h +++ b/dev/statement_serializator.h @@ -12,6 +12,9 @@ #include "column.h" #include "rowid.h" #include "type_printer.h" +#include "table_name_collector.h" +#include "column_names_getter.h" +#include "order_by_serializator.h" namespace sqlite_orm { @@ -330,7 +333,7 @@ namespace sqlite_orm { template struct statement_serializator< T, - typename std::enable_if::value, std::string>::type> { + typename std::enable_if::value>::type> { using statement_type = T; template @@ -754,7 +757,7 @@ namespace sqlite_orm { }}; iterate_ast(sel.col, collector); iterate_ast(sel.conditions, collector); - internal::join_iterator()([&collector, &](const auto &c) { + internal::join_iterator()([&collector, &context](const auto &c) { using original_join_type = typename std::decay::type::join_type::type; using cross_join_type = typename internal::mapped_type_proxy::type; auto crossJoinedTableName = context.impl.find_table_name(typeid(cross_join_type)); @@ -779,8 +782,8 @@ namespace sqlite_orm { ss << " "; } } - iterate_tuple(sel.conditions, [&ss, this](auto &v) { - this->process_single_condition(ss, v); + iterate_tuple(sel.conditions, [&context](auto &v) { + serialize(v, context); }); if(!is_base_of_template::value) { if(!sel.highest_level) { @@ -790,7 +793,234 @@ namespace sqlite_orm { return ss.str(); } }; - + + template + struct statement_serializator, void> { + using statement_type = conditions::where_t; + + template + std::string operator()(const statement_type &w, const C &context) const { + std::stringstream ss; + ss << static_cast(w) << " "; + auto whereString = serialize(w.c, context); + ss << "( " << whereString << ") "; + return ss.str(); + } + }; + + template + struct statement_serializator, void> { + using statement_type = conditions::order_by_t; + + template + std::string operator()(const statement_type &orderBy, const C &context) const { + std::stringstream ss; + ss << static_cast(orderBy) << " "; + auto orderByString = serialize_order_by(orderBy, context); + ss << orderByString << " "; + return ss.str(); + } + }; + + template + struct statement_serializator, void> { + using statement_type = conditions::multi_order_by_t; + + template + std::string operator()(const statement_type &orderBy, const C &context) const { + std::stringstream ss; + std::vector expressions; + iterate_tuple(orderBy.args, [&expressions, &context](auto &v) { + auto expression = serialize_order_by(v, context); + expressions.push_back(move(expression)); + }); + ss << static_cast(orderBy) << " "; + for(size_t i = 0; i < expressions.size(); ++i) { + ss << expressions[i]; + if(i < expressions.size() - 1) { + ss << ", "; + } + } + ss << " "; + return ss.str(); + } + }; + + template + struct statement_serializator, void> { + using statement_type = conditions::cross_join_t; + + template + std::string operator()(const statement_type &c, const C &context) const { + std::stringstream ss; + ss << static_cast(c) << " "; + ss << " '" << context.impl.find_table_name(typeid(O)) << "'"; + return ss.str(); + } + }; + + template + struct statement_serializator, void> { + using statement_type = conditions::inner_join_t; + + template + std::string operator()(const statement_type &l, const C &context) const { + std::stringstream ss; + ss << static_cast(l) << " "; + auto aliasString = alias_extractor::get(); + ss << " '" << context.impl.find_table_name(typeid(typename mapped_type_proxy::type)) << "' "; + if(aliasString.length()) { + ss << "'" << aliasString << "' "; + } + ss << serialize(l.constraint, context); + return ss.str(); + } + }; + + template + struct statement_serializator, void> { + using statement_type = conditions::on_t; + + template + std::string operator()(const statement_type &t, const C &context) const { + std::stringstream ss; + auto newContext = context; + newContext.skip_table_name = false; + ss << static_cast(t) << " " << serialize(t.arg, newContext); + return ss.str(); + } + }; + + template + struct statement_serializator, void> { + using statement_type = conditions::join_t; + + template + std::string operator()(const statement_type &l, const C &context) const { + std::stringstream ss; + ss << static_cast(l) << " "; + ss << " '" << context.impl.find_table_name(typeid(T)) << "' "; + ss << serialize(l.constraint, context); + return ss.str(); + } + }; + + template + struct statement_serializator, void> { + using statement_type = conditions::left_join_t; + + template + std::string operator()(const statement_type &l, const C &context) const { + std::stringstream ss; + ss << static_cast(l) << " "; + ss << " '" << context.impl.find_table_name(typeid(T)) << "' "; + ss << serialize(l.constraint, context); + return ss.str(); + } + }; + + template + struct statement_serializator, void> { + using statement_type = conditions::left_outer_join_t; + + template + std::string operator()(const statement_type &l, const C &context) const { + std::stringstream ss; + ss << static_cast(l) << " "; + ss << " '" << context.impl.find_table_name(typeid(T)) << "' "; + ss << serialize(l.constraint, context); + return ss.str(); + } + }; + + template + struct statement_serializator, void> { + using statement_type = conditions::natural_join_t; + + template + std::string operator()(const statement_type &c, const C &context) const { + std::stringstream ss; + ss << static_cast(c) << " "; + ss << " '" << context.impl.find_table_name(typeid(O)) << "'"; + return ss.str(); + } + }; + + template + struct statement_serializator, void> { + using statement_type = conditions::group_by_t; + + template + std::string operator()(const statement_type &groupBy, const C &context) const { + std::stringstream ss; + std::vector expressions; + auto newContext = context; + newContext.skip_table_name = false; + iterate_tuple(groupBy.args, [&expressions, &newContext](auto &v) { + auto expression = serialize(v, newContext); + expressions.push_back(expression); + }); + ss << static_cast(groupBy) << " "; + for(size_t i = 0; i < expressions.size(); ++i) { + ss << expressions[i]; + if(i < expressions.size() - 1) { + ss << ", "; + } + } + ss << " "; + return ss.str(); + } + }; + + template + struct statement_serializator, void> { + using statement_type = conditions::having_t; + + template + std::string operator()(const statement_type &hav, const C &context) const { + std::stringstream ss; + auto newContext = context; + newContext.skip_table_name = false; + ss << static_cast(hav) << " "; + ss << serialize(hav.t, newContext) << " "; + return ss.str(); + } + }; + + /** + * HO - has offset + * OI - offset is implicit + */ + template + struct statement_serializator, void> { + using statement_type = conditions::limit_t; + + template + std::string operator()(const statement_type &limt, const C &context) const { + auto newContext = context; + newContext.skip_table_name = false; + std::stringstream ss; + ss << static_cast(limt) << " "; + if(HO) { + if(OI) { + limt.off.apply([&newContext, &ss](auto &value) { + ss << serialize(value, newContext); + }); + ss << ", "; + ss << serialize(limt.lim, newContext); + } else { + ss << serialize(limt.lim, newContext) << " OFFSET "; + limt.off.apply([&newContext, &ss](auto &value) { + ss << serialize(value, newContext); + }); + } + } else { + ss << serialize(limt.lim, newContext); + } + return ss.str(); + } + }; + /*template struct statement_serializator< T, diff --git a/dev/storage.h b/dev/storage.h index b3c6b1cc0..c3812d383 100644 --- a/dev/storage.h +++ b/dev/storage.h @@ -50,6 +50,9 @@ namespace sqlite_orm { +template +conditions::dynamic_order_by_t> dynamic_order_by(const S &storage); + namespace conditions { template @@ -668,8 +671,11 @@ namespace sqlite_orm { ss << "INSERT INTO '" << tImpl.table.name << "' "; std::vector columnNames; columnNames.reserve(colsCount); - iterate_tuple(ins.columns.columns, [&columnNames, this](auto &m) { - auto columnName = this->string_from_expression(m, true); + using context_t = serializator_context; + context_t context{this->impl}; + context.skip_table_name = true; + iterate_tuple(ins.columns.columns, [&columnNames, &context](auto &m) { + auto columnName = serialize(m, context); if(!columnName.empty()) { columnNames.push_back(columnName); } else { @@ -1039,7 +1045,7 @@ namespace sqlite_orm { return ss.str(); }*/ - template + /*template std::string process_order_by(const conditions::order_by_t &orderBy) const { std::stringstream ss; using context_t = serializator_context; @@ -1059,15 +1065,15 @@ namespace sqlite_orm { break; } return ss.str(); - } + }*/ - template + /*template void process_join_constraint(std::stringstream &ss, const conditions::on_t &t) const { using context_t = serializator_context; context_t context{this->impl}; context.skip_table_name = false; ss << static_cast(t) << " " << serialize(t.arg, context); - } + }*/ template void process_join_constraint(std::stringstream &ss, const conditions::using_t &u) const { @@ -1078,7 +1084,7 @@ namespace sqlite_orm { * HO - has offset * OI - offset is implicit */ - template + /*template std::string string_from_expression(const conditions::limit_t &limt, bool) const { std::stringstream ss; ss << static_cast(limt) << " "; @@ -1099,25 +1105,25 @@ namespace sqlite_orm { ss << this->string_from_expression(limt.lim, false); } return ss.str(); - } + }*/ - template + /*template std::string string_from_expression(const conditions::cross_join_t &c, bool) const { std::stringstream ss; ss << static_cast(c) << " "; ss << " '" << this->impl.find_table_name(typeid(O)) << "'"; return ss.str(); - } + }*/ - template + /*template std::string string_from_expression(const conditions::natural_join_t &c, bool) const { std::stringstream ss; ss << static_cast(c) << " "; ss << " '" << this->impl.find_table_name(typeid(O)) << "'"; return ss.str(); - } + }*/ - template + /*template std::string string_from_expression(const conditions::inner_join_t &l, bool) const { std::stringstream ss; ss << static_cast(l) << " "; @@ -1128,36 +1134,36 @@ namespace sqlite_orm { } this->process_join_constraint(ss, l.constraint); return ss.str(); - } + }*/ - template + /*template std::string string_from_expression(const conditions::left_outer_join_t &l, bool) const { std::stringstream ss; ss << static_cast(l) << " "; ss << " '" << this->impl.find_table_name(typeid(T)) << "' "; this->process_join_constraint(ss, l.constraint); return ss.str(); - } + }*/ - template + /*template std::string string_from_expression(const conditions::left_join_t &l, bool) const { std::stringstream ss; ss << static_cast(l) << " "; ss << " '" << this->impl.find_table_name(typeid(T)) << "' "; this->process_join_constraint(ss, l.constraint); return ss.str(); - } + }*/ - template + /*template std::string string_from_expression(const conditions::join_t &l, bool) const { std::stringstream ss; ss << static_cast(l) << " "; ss << " '" << this->impl.find_table_name(typeid(T)) << "' "; this->process_join_constraint(ss, l.constraint); return ss.str(); - } + }*/ - template + /*template std::string string_from_expression(const conditions::where_t &w, bool) const { std::stringstream ss; ss << static_cast(w) << " "; @@ -1167,18 +1173,18 @@ namespace sqlite_orm { auto whereString = serialize(w.c, context); ss << "( " << whereString << ") "; return ss.str(); - } + }*/ - template + /*template std::string string_from_expression(const conditions::order_by_t &orderBy, bool) const { std::stringstream ss; ss << static_cast(orderBy) << " "; auto orderByString = this->process_order_by(orderBy); ss << orderByString << " "; return ss.str(); - } + }*/ - template + /*template std::string string_from_expression(const conditions::multi_order_by_t &orderBy, bool) const { std::stringstream ss; std::vector expressions; @@ -1195,7 +1201,7 @@ namespace sqlite_orm { } ss << " "; return ss.str(); - } + }*/ template std::string string_from_expression(const conditions::dynamic_order_by_t &orderBy, bool) const { @@ -1204,7 +1210,7 @@ namespace sqlite_orm { return ss.str(); } - template + /*template std::string string_from_expression(const conditions::group_by_t &groupBy, bool) const { std::stringstream ss; std::vector expressions; @@ -1221,20 +1227,23 @@ namespace sqlite_orm { } ss << " "; return ss.str(); - } + }*/ - template + /*template std::string string_from_expression(const conditions::having_t &hav, bool) const { std::stringstream ss; ss << static_cast(hav) << " "; ss << this->string_from_expression(hav.t, false) << " "; return ss.str(); - } + }*/ template void process_conditions(std::stringstream &ss, const std::tuple &args) const { - iterate_tuple(args, [this, &ss](auto &v) { - ss << this->string_from_expression(v, false); + using context_t = serializator_context; + context_t context{this->impl}; + context.skip_table_name = false; + iterate_tuple(args, [&context, &ss](auto &v) { + ss << serialize(v, context); }); } @@ -1286,6 +1295,9 @@ namespace sqlite_orm { } protected: + template + friend conditions::dynamic_order_by_t> dynamic_order_by(const S &storage); + template std::string group_concat_internal(F O::*m, std::unique_ptr y, Args &&... args) { this->assert_mapped_type(); @@ -1795,7 +1807,10 @@ namespace sqlite_orm { auto con = this->get_connection(); sqlite3_stmt *stmt; auto db = con.get(); - auto query = this->string_from_expression(sel, false); + using context_t = serializator_context; + context_t context{this->impl}; + context.skip_table_name = false; + auto query = serialize(sel, context); if(sqlite3_prepare_v2(db, query.c_str(), -1, &stmt, nullptr) == SQLITE_OK) { return {std::move(sel), stmt, con}; } else { diff --git a/dev/storage_base.h b/dev/storage_base.h index 6fcacab58..39e810b80 100644 --- a/dev/storage_base.h +++ b/dev/storage_base.h @@ -500,7 +500,7 @@ namespace sqlite_orm { } } - template + /*template std::string process_order_by(const conditions::dynamic_order_by_t &orderBy) const { std::vector expressions; for(auto &entry: orderBy) { @@ -533,7 +533,7 @@ namespace sqlite_orm { } ss << " "; return ss.str(); - } + }*/ static int collate_callback(void *arg, int leftLen, const void *lhs, int rightLen, const void *rhs) { auto &f = *(collating_function *)arg; diff --git a/include/sqlite_orm/sqlite_orm.h b/include/sqlite_orm/sqlite_orm.h index afc80d662..9ed0ef743 100644 --- a/include/sqlite_orm/sqlite_orm.h +++ b/include/sqlite_orm/sqlite_orm.h @@ -2400,11 +2400,11 @@ namespace sqlite_orm { }; /** - * S - storage class + * C - serializator context class */ - template + template struct dynamic_order_by_t : order_by_string { - using storage_type = S; + using context_t = C; struct entry_t : order_by_base { std::string name; @@ -2415,11 +2415,13 @@ namespace sqlite_orm { using const_iterator = typename std::vector::const_iterator; - dynamic_order_by_t(const storage_type &storage_) : storage(storage_) {} + dynamic_order_by_t(const context_t &context_) : context(context_) {} template void push_back(order_by_t order_by) { - auto columnName = this->storage.string_from_expression(order_by.o, true); + auto newContext = this->context; + newContext.skip_table_name = true; + auto columnName = serialize(order_by.o, newContext); entries.emplace_back(move(columnName), order_by.asc_desc, move(order_by._collate_argument)); } @@ -2437,7 +2439,7 @@ namespace sqlite_orm { protected: std::vector entries; - const storage_type &storage; + const context_t &context; }; template @@ -2449,8 +2451,8 @@ namespace sqlite_orm { template struct is_order_by> : std::true_type {}; - template - struct is_order_by> : std::true_type {}; + template + struct is_order_by> : std::true_type {}; struct group_by_string { operator std::string() const { @@ -3128,8 +3130,11 @@ namespace sqlite_orm { * } */ template - conditions::dynamic_order_by_t dynamic_order_by(const S &storage) { - return {storage}; + conditions::dynamic_order_by_t> dynamic_order_by(const S &storage) { + using context_t = internal::serializator_context; + using return_type = conditions::dynamic_order_by_t; + context_t context{storage.impl}; + return return_type{std::move(context)}; } /** @@ -8884,7 +8889,7 @@ namespace sqlite_orm { } } - template + /*template std::string process_order_by(const conditions::dynamic_order_by_t &orderBy) const { std::vector expressions; for(auto &entry: orderBy) { @@ -8917,7 +8922,7 @@ namespace sqlite_orm { } ss << " "; return ss.str(); - } + }*/ static int collate_callback(void *arg, int leftLen, const void *lhs, int rightLen, const void *rhs) { auto &f = *(collating_function *)arg; @@ -9086,6 +9091,256 @@ namespace sqlite_orm { // #include "type_printer.h" +// #include "table_name_collector.h" + + +#include // std::set +#include // std::string +#include // std::function +#include // std::type_index + +// #include "select_constraints.h" + +// #include "alias.h" + +// #include "core_functions.h" + + +namespace sqlite_orm { + + namespace internal { + + struct table_name_collector { + using table_name_set = std::set>; + using find_table_name_t = std::function; + + find_table_name_t find_table_name; + mutable table_name_set table_names; + + template + table_name_set operator()(const T &) const { + return {}; + } + + template + void operator()(F O::*, std::string alias = {}) const { + if(this->find_table_name) { + table_names.insert(std::make_pair(this->find_table_name(typeid(O)), move(alias))); + } + } + + template + void operator()(const column_pointer &) const { + if(this->find_table_name) { + table_names.insert({this->find_table_name(typeid(T)), ""}); + } + } + + template + void operator()(const alias_column_t &a) const { + (*this)(a.column, alias_extractor::get()); + } + + template + void operator()(const count_asterisk_t &) const { + if(this->find_table_name) { + auto tableName = this->find_table_name(typeid(T)); + if(!tableName.empty()) { + table_names.insert(std::make_pair(move(tableName), "")); + } + } + } + + template + void operator()(const asterisk_t &) const { + if(this->find_table_name) { + auto tableName = this->find_table_name(typeid(T)); + table_names.insert(std::make_pair(move(tableName), "")); + } + } + }; + + } + +} + +// #include "column_names_getter.h" + + +#include // std::string +#include // std::vector +#include // std::reference_wrapper + +// #include "error_code.h" + +// #include "select_constraints.h" + + +namespace sqlite_orm { + +namespace internal { + +template +std::string serialize(const T &t, const C &context); + +template +struct column_names_getter { + using expression_type = T; + + template + std::vector operator()(const expression_type &t, const C &context) { + auto newContext = context; + newContext.skip_table_name = false; + auto columnName = serialize(t, newContext); + if(columnName.length()) { + return {move(columnName)}; + } else { + throw std::system_error(std::make_error_code(orm_error_code::column_not_found)); + } + } +}; + + template + std::vector get_column_names(const T &t, const C &context) { + column_names_getter serializator; + return serializator(t, context); + } + +template +struct column_names_getter, void> { + using expression_type = std::reference_wrapper; + + template + std::vector operator()(const expression_type &expression, const C &context) { + return get_column_names(expression.get(), context); + } +}; +template +struct column_names_getter, void> { + using expression_type = asterisk_t; + + template + std::vector operator()(const expression_type &, const C &) { + std::vector res; + res.push_back("*"); + return res; + } +}; + +template +struct column_names_getter, void> { + using expression_type = columns_t; + + template + std::vector operator()(const expression_type &cols, const C &context) { + std::vector columnNames; + columnNames.reserve(static_cast(cols.count)); + auto newContext = context; + newContext.skip_table_name = false; + iterate_tuple(cols.columns, [&columnNames, &newContext](auto &m) { + auto columnName = serialize(m, newContext); + if(columnName.length()) { + columnNames.push_back(columnName); + } else { + throw std::system_error(std::make_error_code(orm_error_code::column_not_found)); + } + }); + return columnNames; + } +}; + +} +} + +// #include "order_by_serializator.h" + + +#include // std::string +#include // std::vector +#include // std::stringstream + +namespace sqlite_orm { + +namespace internal { + +template +struct order_by_serializator; + +template +std::string serialize_order_by(const T &t, const C &context) { + order_by_serializator serializator; + return serializator(t, context); +} + +template +struct order_by_serializator, void> { + using statement_type = conditions::order_by_t; + + template + std::string operator()(const statement_type &orderBy, const C &context) const { + std::stringstream ss; + auto newContext = context; + newContext.skip_table_name = false; + auto columnName = serialize(orderBy.o, newContext); + ss << columnName << " "; + if(orderBy._collate_argument.length()) { + ss << "COLLATE " << orderBy._collate_argument << " "; + } + switch(orderBy.asc_desc) { + case 1: + ss << "ASC"; + break; + case -1: + ss << "DESC"; + break; + } + return ss.str(); + } +}; + +template +struct order_by_serializator, void> { + using statement_type = conditions::dynamic_order_by_t; + + template + std::string operator()(const statement_type &orderBy, const C &) const { + std::vector expressions; + for(auto &entry: orderBy) { + std::string entryString; + { + std::stringstream ss; + ss << entry.name << " "; + if(!entry._collate_argument.empty()) { + ss << "COLLATE " << entry._collate_argument << " "; + } + switch(entry.asc_desc) { + case 1: + ss << "ASC"; + break; + case -1: + ss << "DESC"; + break; + } + entryString = ss.str(); + } + expressions.push_back(move(entryString)); + }; + std::stringstream ss; + ss << static_cast(orderBy) << " "; + for(size_t i = 0; i < expressions.size(); ++i) { + ss << expressions[i]; + if(i < expressions.size() - 1) { + ss << ", "; + } + } + ss << " "; + return ss.str(); + } +}; + +} +} + namespace sqlite_orm { @@ -9404,7 +9659,7 @@ namespace sqlite_orm { template struct statement_serializator< T, - typename std::enable_if::value, std::string>::type> { + typename std::enable_if::value>::type> { using statement_type = T; template @@ -9492,20 +9747,6 @@ namespace sqlite_orm { } }; - /*template - struct statement_serializator, void> { - using statement_type = conditions::is_equal_t; - - template - std::string operator()(const statement_type &c, const C &context) const { - auto leftString = serialize(c.l, context); - auto rightString = serialize(c.r, context); - std::stringstream ss; - ss << leftString << " " << static_cast(c) << " " << rightString; - return ss.str(); - } - };*/ - template struct statement_serializator< T, @@ -9812,7 +10053,300 @@ namespace sqlite_orm { return ss.str(); } }; - + + template + struct statement_serializator, void> { + using statement_type = select_t; + + template + std::string operator()(const statement_type &sel, const C &context) const { + std::stringstream ss; + if(!is_base_of_template::value) { + if(!sel.highest_level) { + ss << "( "; + } + ss << "SELECT "; + } + if(get_distinct(sel.col)) { + ss << static_cast(distinct(0)) << " "; + } + auto columnNames = get_column_names(sel.col, context); + for(size_t i = 0; i < columnNames.size(); ++i) { + ss << columnNames[i]; + if(i < columnNames.size() - 1) { + ss << ","; + } + ss << " "; + } + table_name_collector collector{[&context](std::type_index ti) { + return context.impl.find_table_name(ti); + }}; + iterate_ast(sel.col, collector); + iterate_ast(sel.conditions, collector); + internal::join_iterator()([&collector, &context](const auto &c) { + using original_join_type = typename std::decay::type::join_type::type; + using cross_join_type = typename internal::mapped_type_proxy::type; + auto crossJoinedTableName = context.impl.find_table_name(typeid(cross_join_type)); + auto tableAliasString = alias_extractor::get(); + std::pair tableNameWithAlias(std::move(crossJoinedTableName), + std::move(tableAliasString)); + collector.table_names.erase(tableNameWithAlias); + }); + if(!collector.table_names.empty()) { + ss << "FROM "; + std::vector> tableNames(collector.table_names.begin(), + collector.table_names.end()); + for(size_t i = 0; i < tableNames.size(); ++i) { + auto &tableNamePair = tableNames[i]; + ss << "'" << tableNamePair.first << "' "; + if(!tableNamePair.second.empty()) { + ss << tableNamePair.second << " "; + } + if(int(i) < int(tableNames.size()) - 1) { + ss << ","; + } + ss << " "; + } + } + iterate_tuple(sel.conditions, [&context](auto &v) { + serialize(v, context); + }); + if(!is_base_of_template::value) { + if(!sel.highest_level) { + ss << ") "; + } + } + return ss.str(); + } + }; + + template + struct statement_serializator, void> { + using statement_type = conditions::where_t; + + template + std::string operator()(const statement_type &w, const C &context) const { + std::stringstream ss; + ss << static_cast(w) << " "; + auto whereString = serialize(w.c, context); + ss << "( " << whereString << ") "; + return ss.str(); + } + }; + + template + struct statement_serializator, void> { + using statement_type = conditions::order_by_t; + + template + std::string operator()(const statement_type &orderBy, const C &context) const { + std::stringstream ss; + ss << static_cast(orderBy) << " "; + auto orderByString = serialize_order_by(orderBy, context); + ss << orderByString << " "; + return ss.str(); + } + }; + + template + struct statement_serializator, void> { + using statement_type = conditions::multi_order_by_t; + + template + std::string operator()(const statement_type &orderBy, const C &context) const { + std::stringstream ss; + std::vector expressions; + iterate_tuple(orderBy.args, [&expressions, &context](auto &v) { + auto expression = serialize_order_by(v, context); + expressions.push_back(move(expression)); + }); + ss << static_cast(orderBy) << " "; + for(size_t i = 0; i < expressions.size(); ++i) { + ss << expressions[i]; + if(i < expressions.size() - 1) { + ss << ", "; + } + } + ss << " "; + return ss.str(); + } + }; + + template + struct statement_serializator, void> { + using statement_type = conditions::cross_join_t; + + template + std::string operator()(const statement_type &c, const C &context) const { + std::stringstream ss; + ss << static_cast(c) << " "; + ss << " '" << context.impl.find_table_name(typeid(O)) << "'"; + return ss.str(); + } + }; + + template + struct statement_serializator, void> { + using statement_type = conditions::inner_join_t; + + template + std::string operator()(const statement_type &l, const C &context) const { + std::stringstream ss; + ss << static_cast(l) << " "; + auto aliasString = alias_extractor::get(); + ss << " '" << context.impl.find_table_name(typeid(typename mapped_type_proxy::type)) << "' "; + if(aliasString.length()) { + ss << "'" << aliasString << "' "; + } + ss << serialize(l.constraint, context); + return ss.str(); + } + }; + + template + struct statement_serializator, void> { + using statement_type = conditions::on_t; + + template + std::string operator()(const statement_type &t, const C &context) const { + std::stringstream ss; + auto newContext = context; + newContext.skip_table_name = false; + ss << static_cast(t) << " " << serialize(t.arg, newContext); + return ss.str(); + } + }; + + template + struct statement_serializator, void> { + using statement_type = conditions::join_t; + + template + std::string operator()(const statement_type &l, const C &context) const { + std::stringstream ss; + ss << static_cast(l) << " "; + ss << " '" << context.impl.find_table_name(typeid(T)) << "' "; + ss << serialize(l.constraint, context); + return ss.str(); + } + }; + + template + struct statement_serializator, void> { + using statement_type = conditions::left_join_t; + + template + std::string operator()(const statement_type &l, const C &context) const { + std::stringstream ss; + ss << static_cast(l) << " "; + ss << " '" << context.impl.find_table_name(typeid(T)) << "' "; + ss << serialize(l.constraint, context); + return ss.str(); + } + }; + + template + struct statement_serializator, void> { + using statement_type = conditions::left_outer_join_t; + + template + std::string operator()(const statement_type &l, const C &context) const { + std::stringstream ss; + ss << static_cast(l) << " "; + ss << " '" << context.impl.find_table_name(typeid(T)) << "' "; + ss << serialize(l.constraint, context); + return ss.str(); + } + }; + + template + struct statement_serializator, void> { + using statement_type = conditions::natural_join_t; + + template + std::string operator()(const statement_type &c, const C &context) const { + std::stringstream ss; + ss << static_cast(c) << " "; + ss << " '" << context.impl.find_table_name(typeid(O)) << "'"; + return ss.str(); + } + }; + + template + struct statement_serializator, void> { + using statement_type = conditions::group_by_t; + + template + std::string operator()(const statement_type &groupBy, const C &context) const { + std::stringstream ss; + std::vector expressions; + auto newContext = context; + newContext.skip_table_name = false; + iterate_tuple(groupBy.args, [&expressions, &newContext](auto &v) { + auto expression = serialize(v, newContext); + expressions.push_back(expression); + }); + ss << static_cast(groupBy) << " "; + for(size_t i = 0; i < expressions.size(); ++i) { + ss << expressions[i]; + if(i < expressions.size() - 1) { + ss << ", "; + } + } + ss << " "; + return ss.str(); + } + }; + + template + struct statement_serializator, void> { + using statement_type = conditions::having_t; + + template + std::string operator()(const statement_type &hav, const C &context) const { + std::stringstream ss; + auto newContext = context; + newContext.skip_table_name = false; + ss << static_cast(hav) << " "; + ss << serialize(hav.t, newContext) << " "; + return ss.str(); + } + }; + + /** + * HO - has offset + * OI - offset is implicit + */ + template + struct statement_serializator, void> { + using statement_type = conditions::limit_t; + + template + std::string operator()(const statement_type &limt, const C &context) const { + auto newContext = context; + newContext.skip_table_name = false; + std::stringstream ss; + ss << static_cast(limt) << " "; + if(HO) { + if(OI) { + limt.off.apply([&newContext, &ss](auto &value) { + ss << serialize(value, newContext); + }); + ss << ", "; + ss << serialize(limt.lim, newContext); + } else { + ss << serialize(limt.lim, newContext) << " OFFSET "; + limt.off.apply([&newContext, &ss](auto &value) { + ss << serialize(value, newContext); + }); + } + } else { + ss << serialize(limt.lim, newContext); + } + return ss.str(); + } + }; + /*template struct statement_serializator< T, @@ -9847,78 +10381,10 @@ namespace sqlite_orm { // #include "table_name_collector.h" -#include // std::set -#include // std::string -#include // std::function -#include // std::type_index - -// #include "select_constraints.h" - -// #include "alias.h" - -// #include "core_functions.h" - - namespace sqlite_orm { - namespace internal { - - struct table_name_collector { - using table_name_set = std::set>; - using find_table_name_t = std::function; - - find_table_name_t find_table_name; - mutable table_name_set table_names; - - template - table_name_set operator()(const T &) const { - return {}; - } - - template - void operator()(F O::*, std::string alias = {}) const { - if(this->find_table_name) { - table_names.insert(std::make_pair(this->find_table_name(typeid(O)), move(alias))); - } - } - - template - void operator()(const column_pointer &) const { - if(this->find_table_name) { - table_names.insert({this->find_table_name(typeid(T)), ""}); - } - } - - template - void operator()(const alias_column_t &a) const { - (*this)(a.column, alias_extractor::get()); - } - - template - void operator()(const count_asterisk_t &) const { - if(this->find_table_name) { - auto tableName = this->find_table_name(typeid(T)); - if(!tableName.empty()) { - table_names.insert(std::make_pair(move(tableName), "")); - } - } - } - - template - void operator()(const asterisk_t &) const { - if(this->find_table_name) { - auto tableName = this->find_table_name(typeid(T)); - table_names.insert(std::make_pair(move(tableName), "")); - } - } - }; - - } - -} - - -namespace sqlite_orm { +template +conditions::dynamic_order_by_t> dynamic_order_by(const S &storage); namespace conditions { @@ -10202,7 +10668,7 @@ namespace sqlite_orm { return ss.str(); }*/ - template + /*template std::vector get_column_names(const T &t) const { using context_t = serializator_context; context_t context{this->impl}; @@ -10213,21 +10679,21 @@ namespace sqlite_orm { } else { throw std::system_error(std::make_error_code(orm_error_code::column_not_found)); } - } + }*/ - template + /*template std::vector get_column_names(std::reference_wrapper r) const { return this->get_column_names(r.get()); - } + }*/ - template + /*template std::vector get_column_names(const asterisk_t &) const { std::vector res; res.push_back("*"); return res; - } + }*/ - template + /*template std::vector get_column_names(const columns_t &cols) const { std::vector columnNames; columnNames.reserve(static_cast(cols.count)); @@ -10243,14 +10709,14 @@ namespace sqlite_orm { } }); return columnNames; - } + }*/ /** * Takes select_t object and returns SELECT query string */ template - std::string string_from_expression(const select_t &sel, bool /*noTableName*/) const { - std::stringstream ss; + std::string string_from_expression(const select_t &sel, bool) const { + /*std::stringstream ss; if(!is_base_of_template::value) { if(!sel.highest_level) { ss << "( "; @@ -10306,7 +10772,10 @@ namespace sqlite_orm { ss << ") "; } } - return ss.str(); + return ss.str();*/ + using context_t = serializator_context; + context_t context{this->impl}; + return serialize(sel, context); } // Common code for statements returning the whole content of a table: get_all_t, get_all_pointer_t, @@ -10535,8 +11004,11 @@ namespace sqlite_orm { ss << "INSERT INTO '" << tImpl.table.name << "' "; std::vector columnNames; columnNames.reserve(colsCount); - iterate_tuple(ins.columns.columns, [&columnNames, this](auto &m) { - auto columnName = this->string_from_expression(m, true); + using context_t = serializator_context; + context_t context{this->impl}; + context.skip_table_name = true; + iterate_tuple(ins.columns.columns, [&columnNames, &context](auto &m) { + auto columnName = serialize(m, context); if(!columnName.empty()) { columnNames.push_back(columnName); } else { @@ -10906,7 +11378,7 @@ namespace sqlite_orm { return ss.str(); }*/ - template + /*template std::string process_order_by(const conditions::order_by_t &orderBy) const { std::stringstream ss; using context_t = serializator_context; @@ -10926,15 +11398,15 @@ namespace sqlite_orm { break; } return ss.str(); - } + }*/ - template + /*template void process_join_constraint(std::stringstream &ss, const conditions::on_t &t) const { using context_t = serializator_context; context_t context{this->impl}; context.skip_table_name = false; ss << static_cast(t) << " " << serialize(t.arg, context); - } + }*/ template void process_join_constraint(std::stringstream &ss, const conditions::using_t &u) const { @@ -10945,7 +11417,7 @@ namespace sqlite_orm { * HO - has offset * OI - offset is implicit */ - template + /*template std::string string_from_expression(const conditions::limit_t &limt, bool) const { std::stringstream ss; ss << static_cast(limt) << " "; @@ -10966,25 +11438,25 @@ namespace sqlite_orm { ss << this->string_from_expression(limt.lim, false); } return ss.str(); - } + }*/ - template + /*template std::string string_from_expression(const conditions::cross_join_t &c, bool) const { std::stringstream ss; ss << static_cast(c) << " "; ss << " '" << this->impl.find_table_name(typeid(O)) << "'"; return ss.str(); - } + }*/ - template + /*template std::string string_from_expression(const conditions::natural_join_t &c, bool) const { std::stringstream ss; ss << static_cast(c) << " "; ss << " '" << this->impl.find_table_name(typeid(O)) << "'"; return ss.str(); - } + }*/ - template + /*template std::string string_from_expression(const conditions::inner_join_t &l, bool) const { std::stringstream ss; ss << static_cast(l) << " "; @@ -10995,36 +11467,36 @@ namespace sqlite_orm { } this->process_join_constraint(ss, l.constraint); return ss.str(); - } + }*/ - template + /*template std::string string_from_expression(const conditions::left_outer_join_t &l, bool) const { std::stringstream ss; ss << static_cast(l) << " "; ss << " '" << this->impl.find_table_name(typeid(T)) << "' "; this->process_join_constraint(ss, l.constraint); return ss.str(); - } + }*/ - template + /*template std::string string_from_expression(const conditions::left_join_t &l, bool) const { std::stringstream ss; ss << static_cast(l) << " "; ss << " '" << this->impl.find_table_name(typeid(T)) << "' "; this->process_join_constraint(ss, l.constraint); return ss.str(); - } + }*/ - template + /*template std::string string_from_expression(const conditions::join_t &l, bool) const { std::stringstream ss; ss << static_cast(l) << " "; ss << " '" << this->impl.find_table_name(typeid(T)) << "' "; this->process_join_constraint(ss, l.constraint); return ss.str(); - } + }*/ - template + /*template std::string string_from_expression(const conditions::where_t &w, bool) const { std::stringstream ss; ss << static_cast(w) << " "; @@ -11034,18 +11506,18 @@ namespace sqlite_orm { auto whereString = serialize(w.c, context); ss << "( " << whereString << ") "; return ss.str(); - } + }*/ - template + /*template std::string string_from_expression(const conditions::order_by_t &orderBy, bool) const { std::stringstream ss; ss << static_cast(orderBy) << " "; auto orderByString = this->process_order_by(orderBy); ss << orderByString << " "; return ss.str(); - } + }*/ - template + /*template std::string string_from_expression(const conditions::multi_order_by_t &orderBy, bool) const { std::stringstream ss; std::vector expressions; @@ -11062,7 +11534,7 @@ namespace sqlite_orm { } ss << " "; return ss.str(); - } + }*/ template std::string string_from_expression(const conditions::dynamic_order_by_t &orderBy, bool) const { @@ -11071,7 +11543,7 @@ namespace sqlite_orm { return ss.str(); } - template + /*template std::string string_from_expression(const conditions::group_by_t &groupBy, bool) const { std::stringstream ss; std::vector expressions; @@ -11088,20 +11560,23 @@ namespace sqlite_orm { } ss << " "; return ss.str(); - } + }*/ - template + /*template std::string string_from_expression(const conditions::having_t &hav, bool) const { std::stringstream ss; ss << static_cast(hav) << " "; ss << this->string_from_expression(hav.t, false) << " "; return ss.str(); - } + }*/ template void process_conditions(std::stringstream &ss, const std::tuple &args) const { - iterate_tuple(args, [this, &ss](auto &v) { - ss << this->string_from_expression(v, false); + using context_t = serializator_context; + context_t context{this->impl}; + context.skip_table_name = false; + iterate_tuple(args, [&context, &ss](auto &v) { + ss << serialize(v, context); }); } @@ -11153,6 +11628,9 @@ namespace sqlite_orm { } protected: + template + friend conditions::dynamic_order_by_t> dynamic_order_by(const S &storage); + template std::string group_concat_internal(F O::*m, std::unique_ptr y, Args &&... args) { this->assert_mapped_type(); @@ -11662,7 +12140,10 @@ namespace sqlite_orm { auto con = this->get_connection(); sqlite3_stmt *stmt; auto db = con.get(); - auto query = this->string_from_expression(sel, false); + using context_t = serializator_context; + context_t context{this->impl}; + context.skip_table_name = false; + auto query = serialize(sel, context); if(sqlite3_prepare_v2(db, query.c_str(), -1, &stmt, nullptr) == SQLITE_OK) { return {std::move(sel), stmt, con}; } else { From b37730ce9dab58d4892e2a1c50347d497a42d29e Mon Sep 17 00:00:00 2001 From: fnc12 Date: Thu, 26 Mar 2020 21:27:19 +0300 Subject: [PATCH 052/132] refactored dynamic order by with context --- dev/ast_iterator.h | 84 +++--- dev/column_result.h | 8 +- dev/conditions.h | 161 +++++----- dev/core_functions.h | 12 +- dev/join_iterator.h | 24 +- dev/node_tuple.h | 83 +++--- dev/select_constraints.h | 12 +- dev/statement_serializator.h | 5 +- dev/storage.h | 63 ++-- dev/storage_base.h | 2 +- include/sqlite_orm/sqlite_orm.h | 454 ++++++++++++++--------------- tests/static_tests/count_tuple.cpp | 40 +-- tests/static_tests/node_tuple.cpp | 2 +- 13 files changed, 471 insertions(+), 479 deletions(-) diff --git a/dev/ast_iterator.h b/dev/ast_iterator.h index 5bdcb477c..8c96203ee 100644 --- a/dev/ast_iterator.h +++ b/dev/ast_iterator.h @@ -56,8 +56,8 @@ namespace sqlite_orm { }; template - struct ast_iterator, void> { - using node_type = conditions::where_t; + struct ast_iterator, void> { + using node_type = where_t; template void operator()(const node_type &where, const L &l) const { @@ -66,9 +66,7 @@ namespace sqlite_orm { }; template - struct ast_iterator< - T, - typename std::enable_if::value>::type> { + struct ast_iterator::value>::type> { using node_type = T; template @@ -100,8 +98,8 @@ namespace sqlite_orm { }; template - struct ast_iterator, void> { - using node_type = conditions::in_t; + struct ast_iterator, void> { + using node_type = in_t; template void operator()(const node_type &in, const C &l) const { @@ -230,8 +228,8 @@ namespace sqlite_orm { }; template - struct ast_iterator, void> { - using node_type = conditions::having_t; + struct ast_iterator, void> { + using node_type = having_t; template void operator()(const node_type &hav, const L &l) const { @@ -240,8 +238,8 @@ namespace sqlite_orm { }; template - struct ast_iterator, void> { - using node_type = conditions::cast_t; + struct ast_iterator, void> { + using node_type = cast_t; template void operator()(const node_type &c, const L &l) const { @@ -250,8 +248,8 @@ namespace sqlite_orm { }; template - struct ast_iterator, void> { - using node_type = conditions::exists_t; + struct ast_iterator, void> { + using node_type = exists_t; template void operator()(const node_type &e, const L &l) const { @@ -260,8 +258,8 @@ namespace sqlite_orm { }; template - struct ast_iterator, void> { - using node_type = conditions::like_t; + struct ast_iterator, void> { + using node_type = like_t; template void operator()(const node_type &lk, const L &l) const { @@ -274,8 +272,8 @@ namespace sqlite_orm { }; template - struct ast_iterator, void> { - using node_type = conditions::glob_t; + struct ast_iterator, void> { + using node_type = glob_t; template void operator()(const node_type &lk, const L &l) const { @@ -285,8 +283,8 @@ namespace sqlite_orm { }; template - struct ast_iterator, void> { - using node_type = conditions::between_t; + struct ast_iterator, void> { + using node_type = between_t; template void operator()(const node_type &b, const L &l) const { @@ -297,8 +295,8 @@ namespace sqlite_orm { }; template - struct ast_iterator, void> { - using node_type = conditions::named_collate; + struct ast_iterator, void> { + using node_type = named_collate; template void operator()(const node_type &col, const L &l) const { @@ -307,8 +305,8 @@ namespace sqlite_orm { }; template - struct ast_iterator, void> { - using node_type = conditions::negated_condition_t; + struct ast_iterator, void> { + using node_type = negated_condition_t; template void operator()(const node_type &neg, const L &l) const { @@ -317,8 +315,8 @@ namespace sqlite_orm { }; template - struct ast_iterator, void> { - using node_type = conditions::is_null_t; + struct ast_iterator, void> { + using node_type = is_null_t; template void operator()(const node_type &i, const L &l) const { @@ -327,8 +325,8 @@ namespace sqlite_orm { }; template - struct ast_iterator, void> { - using node_type = conditions::is_not_null_t; + struct ast_iterator, void> { + using node_type = is_not_null_t; template void operator()(const node_type &i, const L &l) const { @@ -347,8 +345,8 @@ namespace sqlite_orm { }; template - struct ast_iterator, void> { - using node_type = conditions::left_join_t; + struct ast_iterator, void> { + using node_type = left_join_t; template void operator()(const node_type &j, const L &l) const { @@ -357,8 +355,8 @@ namespace sqlite_orm { }; template - struct ast_iterator, void> { - using node_type = conditions::on_t; + struct ast_iterator, void> { + using node_type = on_t; template void operator()(const node_type &o, const L &l) const { @@ -367,8 +365,8 @@ namespace sqlite_orm { }; template - struct ast_iterator, void> { - using node_type = conditions::join_t; + struct ast_iterator, void> { + using node_type = join_t; template void operator()(const node_type &j, const L &l) const { @@ -377,8 +375,8 @@ namespace sqlite_orm { }; template - struct ast_iterator, void> { - using node_type = conditions::left_outer_join_t; + struct ast_iterator, void> { + using node_type = left_outer_join_t; template void operator()(const node_type &j, const L &l) const { @@ -387,8 +385,8 @@ namespace sqlite_orm { }; template - struct ast_iterator, void> { - using node_type = conditions::inner_join_t; + struct ast_iterator, void> { + using node_type = inner_join_t; template void operator()(const node_type &j, const L &l) const { @@ -426,8 +424,8 @@ namespace sqlite_orm { }; template - struct ast_iterator, void> { - using node_type = conditions::limit_t; + struct ast_iterator, void> { + using node_type = limit_t; template void operator()(const node_type &a, const L &l) const { @@ -436,8 +434,8 @@ namespace sqlite_orm { }; template - struct ast_iterator, void> { - using node_type = conditions::limit_t; + struct ast_iterator, void> { + using node_type = limit_t; template void operator()(const node_type &a, const L &l) const { @@ -449,8 +447,8 @@ namespace sqlite_orm { }; template - struct ast_iterator, void> { - using node_type = conditions::limit_t; + struct ast_iterator, void> { + using node_type = limit_t; template void operator()(const node_type &a, const L &l) const { diff --git a/dev/column_result.h b/dev/column_result.h index 09ad3e58c..65f2086b6 100644 --- a/dev/column_result.h +++ b/dev/column_result.h @@ -224,7 +224,7 @@ namespace sqlite_orm { }; template - struct column_result_t, void> { + struct column_result_t, void> { using type = T; }; @@ -234,17 +234,17 @@ namespace sqlite_orm { }; template - struct column_result_t, void> { + struct column_result_t, void> { using type = bool; }; template - struct column_result_t, void> { + struct column_result_t, void> { using type = bool; }; template - struct column_result_t, void> { + struct column_result_t, void> { using type = bool; }; diff --git a/dev/conditions.h b/dev/conditions.h index b2d0703be..94977e10c 100644 --- a/dev/conditions.h +++ b/dev/conditions.h @@ -16,7 +16,7 @@ namespace sqlite_orm { struct arithmetic_t; } - namespace conditions { + namespace internal { struct limit_string { operator std::string() const { @@ -491,27 +491,31 @@ namespace sqlite_orm { multi_order_by_t(args_type &&args_) : args(std::move(args_)) {} }; + struct dynamic_order_by_entry_t : order_by_base { + std::string name; + + dynamic_order_by_entry_t(decltype(name) name_, int asc_desc, std::string collate_argument) : + order_by_base{asc_desc, move(collate_argument)}, name(move(name_)) {} + }; + /** - * S - storage class + * C - serializator context class */ - template + template struct dynamic_order_by_t : order_by_string { - using storage_type = S; - - struct entry_t : order_by_base { - std::string name; - - entry_t(decltype(name) name_, int asc_desc, std::string collate_argument) : - order_by_base{asc_desc, move(collate_argument)}, name(move(name_)) {} - }; + using context_type = C; + using entry_t = dynamic_order_by_entry_t; using const_iterator = typename std::vector::const_iterator; - dynamic_order_by_t(const storage_type &storage_) : storage(storage_) {} + template + dynamic_order_by_t(const S &storage_) : context(storage_.impl) { + // this->context.skip_table_name = true; + } template void push_back(order_by_t order_by) { - auto columnName = this->storage.string_from_expression(order_by.o, true); + auto columnName = serialize(order_by.o, this->context); entries.emplace_back(move(columnName), order_by.asc_desc, move(order_by._collate_argument)); } @@ -529,7 +533,7 @@ namespace sqlite_orm { protected: std::vector entries; - const storage_type &storage; + context_type context; }; template @@ -850,7 +854,7 @@ namespace sqlite_orm { } template::value>::type> - conditions::negated_condition_t operator!(T arg) { + internal::negated_condition_t operator!(T arg) { return {std::move(arg)}; } @@ -858,62 +862,62 @@ namespace sqlite_orm { * Cute operators for columns */ template - conditions::lesser_than_t operator<(internal::expression_t expr, R r) { + internal::lesser_than_t operator<(internal::expression_t expr, R r) { return {std::move(expr.t), std::move(r)}; } template - conditions::lesser_than_t operator<(L l, internal::expression_t expr) { + internal::lesser_than_t operator<(L l, internal::expression_t expr) { return {std::move(l), std::move(expr.t)}; } template - conditions::lesser_or_equal_t operator<=(internal::expression_t expr, R r) { + internal::lesser_or_equal_t operator<=(internal::expression_t expr, R r) { return {std::move(expr.t), std::move(r)}; } template - conditions::lesser_or_equal_t operator<=(L l, internal::expression_t expr) { + internal::lesser_or_equal_t operator<=(L l, internal::expression_t expr) { return {std::move(l), std::move(expr.t)}; } template - conditions::greater_than_t operator>(internal::expression_t expr, R r) { + internal::greater_than_t operator>(internal::expression_t expr, R r) { return {std::move(expr.t), std::move(r)}; } template - conditions::greater_than_t operator>(L l, internal::expression_t expr) { + internal::greater_than_t operator>(L l, internal::expression_t expr) { return {std::move(l), std::move(expr.t)}; } template - conditions::greater_or_equal_t operator>=(internal::expression_t expr, R r) { + internal::greater_or_equal_t operator>=(internal::expression_t expr, R r) { return {std::move(expr.t), std::move(r)}; } template - conditions::greater_or_equal_t operator>=(L l, internal::expression_t expr) { + internal::greater_or_equal_t operator>=(L l, internal::expression_t expr) { return {std::move(l), std::move(expr.t)}; } template - conditions::is_equal_t operator==(internal::expression_t expr, R r) { + internal::is_equal_t operator==(internal::expression_t expr, R r) { return {std::move(expr.t), std::move(r)}; } template - conditions::is_equal_t operator==(L l, internal::expression_t expr) { + internal::is_equal_t operator==(L l, internal::expression_t expr) { return {std::move(l), std::move(expr.t)}; } template - conditions::is_not_equal_t operator!=(internal::expression_t expr, R r) { + internal::is_not_equal_t operator!=(internal::expression_t expr, R r) { return {std::move(expr.t), std::move(r)}; } template - conditions::is_not_equal_t operator!=(L l, internal::expression_t expr) { + internal::is_not_equal_t operator!=(L l, internal::expression_t expr) { return {std::move(l), std::move(expr.t)}; } @@ -1008,184 +1012,184 @@ namespace sqlite_orm { } template - conditions::using_t using_(F O::*p) { + internal::using_t using_(F O::*p) { return {std::move(p)}; } template - conditions::on_t on(T t) { + internal::on_t on(T t) { return {std::move(t)}; } template - conditions::cross_join_t cross_join() { + internal::cross_join_t cross_join() { return {}; } template - conditions::natural_join_t natural_join() { + internal::natural_join_t natural_join() { return {}; } template - conditions::left_join_t left_join(O o) { + internal::left_join_t left_join(O o) { return {std::move(o)}; } template - conditions::join_t join(O o) { + internal::join_t join(O o) { return {std::move(o)}; } template - conditions::left_outer_join_t left_outer_join(O o) { + internal::left_outer_join_t left_outer_join(O o) { return {std::move(o)}; } template - conditions::inner_join_t inner_join(O o) { + internal::inner_join_t inner_join(O o) { return {std::move(o)}; } template - conditions::offset_t offset(T off) { + internal::offset_t offset(T off) { return {std::move(off)}; } template - conditions::limit_t limit(T lim) { + internal::limit_t limit(T lim) { return {std::move(lim)}; } template - typename std::enable_if::value, conditions::limit_t>::type - limit(O off, T lim) { + typename std::enable_if::value, internal::limit_t>::type limit(O off, + T lim) { return {std::move(lim), {std::move(off)}}; } template - conditions::limit_t limit(T lim, conditions::offset_t offt) { + internal::limit_t limit(T lim, internal::offset_t offt) { return {std::move(lim), {std::move(offt.off)}}; } template::value || - std::is_base_of::value>::type> - conditions::and_condition_t operator&&(L l, R r) { + typename = typename std::enable_if::value || + std::is_base_of::value>::type> + internal::and_condition_t operator&&(L l, R r) { return {std::move(l), std::move(r)}; } template::value || - std::is_base_of::value>::type> - conditions::or_condition_t operator||(L l, R r) { + typename = typename std::enable_if::value || + std::is_base_of::value>::type> + internal::or_condition_t operator||(L l, R r) { return {std::move(l), std::move(r)}; } template - conditions::is_not_null_t is_not_null(T t) { + internal::is_not_null_t is_not_null(T t) { return {std::move(t)}; } template - conditions::is_null_t is_null(T t) { + internal::is_null_t is_null(T t) { return {std::move(t)}; } template - conditions::in_t> in(L l, std::vector values) { + internal::in_t> in(L l, std::vector values) { return {std::move(l), std::move(values), false}; } template - conditions::in_t> in(L l, std::initializer_list values) { + internal::in_t> in(L l, std::initializer_list values) { return {std::move(l), std::move(values), false}; } template - conditions::in_t in(L l, A arg) { + internal::in_t in(L l, A arg) { return {std::move(l), std::move(arg), false}; } template - conditions::in_t> not_in(L l, std::vector values) { + internal::in_t> not_in(L l, std::vector values) { return {std::move(l), std::move(values), true}; } template - conditions::in_t> not_in(L l, std::initializer_list values) { + internal::in_t> not_in(L l, std::initializer_list values) { return {std::move(l), std::move(values), true}; } template - conditions::in_t not_in(L l, A arg) { + internal::in_t not_in(L l, A arg) { return {std::move(l), std::move(arg), true}; } template - conditions::is_equal_t is_equal(L l, R r) { + internal::is_equal_t is_equal(L l, R r) { return {std::move(l), std::move(r)}; } template - conditions::is_equal_t eq(L l, R r) { + internal::is_equal_t eq(L l, R r) { return {std::move(l), std::move(r)}; } template - conditions::is_not_equal_t is_not_equal(L l, R r) { + internal::is_not_equal_t is_not_equal(L l, R r) { return {std::move(l), std::move(r)}; } template - conditions::is_not_equal_t ne(L l, R r) { + internal::is_not_equal_t ne(L l, R r) { return {std::move(l), std::move(r)}; } template - conditions::greater_than_t greater_than(L l, R r) { + internal::greater_than_t greater_than(L l, R r) { return {std::move(l), std::move(r)}; } template - conditions::greater_than_t gt(L l, R r) { + internal::greater_than_t gt(L l, R r) { return {std::move(l), std::move(r)}; } template - conditions::greater_or_equal_t greater_or_equal(L l, R r) { + internal::greater_or_equal_t greater_or_equal(L l, R r) { return {std::move(l), std::move(r)}; } template - conditions::greater_or_equal_t ge(L l, R r) { + internal::greater_or_equal_t ge(L l, R r) { return {std::move(l), std::move(r)}; } template - conditions::lesser_than_t lesser_than(L l, R r) { + internal::lesser_than_t lesser_than(L l, R r) { return {std::move(l), std::move(r)}; } template - conditions::lesser_than_t lt(L l, R r) { + internal::lesser_than_t lt(L l, R r) { return {std::move(l), std::move(r)}; } template - conditions::lesser_or_equal_t lesser_or_equal(L l, R r) { + internal::lesser_or_equal_t lesser_or_equal(L l, R r) { return {std::move(l), std::move(r)}; } template - conditions::lesser_or_equal_t le(L l, R r) { + internal::lesser_or_equal_t le(L l, R r) { return {std::move(l), std::move(r)}; } template - conditions::where_t where(C c) { + internal::where_t where(C c) { return {std::move(c)}; } @@ -1194,7 +1198,7 @@ namespace sqlite_orm { * Example: storage.select(&User::name, order_by(&User::id)) */ template - conditions::order_by_t order_by(O o) { + internal::order_by_t order_by(O o) { return {std::move(o)}; } @@ -1203,7 +1207,7 @@ namespace sqlite_orm { * Example: storage.get_all(multi_order_by(order_by(&Singer::name).asc(), order_by(&Singer::gender).desc()) */ template - conditions::multi_order_by_t multi_order_by(Args &&... args) { + internal::multi_order_by_t multi_order_by(Args &&... args) { return {std::make_tuple(std::forward(args)...)}; } @@ -1220,7 +1224,8 @@ namespace sqlite_orm { * } */ template - conditions::dynamic_order_by_t dynamic_order_by(const S &storage) { + internal::dynamic_order_by_t> + dynamic_order_by(const S &storage) { return {storage}; } @@ -1229,7 +1234,7 @@ namespace sqlite_orm { * Example: storage.get_all(group_by(&Employee::name)) */ template - conditions::group_by_t group_by(Args &&... args) { + internal::group_by_t group_by(Args &&... args) { return {std::make_tuple(std::forward(args)...)}; } @@ -1238,7 +1243,7 @@ namespace sqlite_orm { * Example: storage.select(between(&User::id, 10, 20)) */ template - conditions::between_t between(A expr, T b1, T b2) { + internal::between_t between(A expr, T b1, T b2) { return {std::move(expr), std::move(b1), std::move(b2)}; } @@ -1247,7 +1252,7 @@ namespace sqlite_orm { * Example: storage.select(like(&User::name, "T%")) */ template - conditions::like_t like(A a, T t) { + internal::like_t like(A a, T t) { return {std::move(a), std::move(t), {}}; } @@ -1256,7 +1261,7 @@ namespace sqlite_orm { * Example: storage.select(glob(&User::name, "*S")) */ template - conditions::glob_t glob(A a, T t) { + internal::glob_t glob(A a, T t) { return {std::move(a), std::move(t)}; } @@ -1265,7 +1270,7 @@ namespace sqlite_orm { * Example: storage.select(like(&User::name, "T%", "%")) */ template - conditions::like_t like(A a, T t, E e) { + internal::like_t like(A a, T t, E e) { return {std::move(a), std::move(t), {std::move(e)}}; } @@ -1278,7 +1283,7 @@ namespace sqlite_orm { order_by(&Agent::comission)); */ template - conditions::exists_t exists(T t) { + internal::exists_t exists(T t) { return {std::move(t)}; } @@ -1287,7 +1292,7 @@ namespace sqlite_orm { * Example: storage.get_all(group_by(&Employee::name), having(greater_than(count(&Employee::name), 2))); */ template - conditions::having_t having(T t) { + internal::having_t having(T t) { return {std::move(t)}; } @@ -1296,7 +1301,7 @@ namespace sqlite_orm { * Example: cast(&User::id) */ template - conditions::cast_t cast(E e) { + internal::cast_t cast(E e) { return {std::move(e)}; } } diff --git a/dev/core_functions.h b/dev/core_functions.h index 6518e1652..27454be20 100644 --- a/dev/core_functions.h +++ b/dev/core_functions.h @@ -274,7 +274,7 @@ namespace sqlite_orm { class F, class R, typename = typename std::enable_if::value>::type> - conditions::lesser_than_t operator<(F f, R r) { + internal::lesser_than_t operator<(F f, R r) { return {std::move(f), std::move(r)}; } @@ -282,7 +282,7 @@ namespace sqlite_orm { class F, class R, typename = typename std::enable_if::value>::type> - conditions::lesser_or_equal_t operator<=(F f, R r) { + internal::lesser_or_equal_t operator<=(F f, R r) { return {std::move(f), std::move(r)}; } @@ -290,7 +290,7 @@ namespace sqlite_orm { class F, class R, typename = typename std::enable_if::value>::type> - conditions::greater_than_t operator>(F f, R r) { + internal::greater_than_t operator>(F f, R r) { return {std::move(f), std::move(r)}; } @@ -298,7 +298,7 @@ namespace sqlite_orm { class F, class R, typename = typename std::enable_if::value>::type> - conditions::greater_or_equal_t operator>=(F f, R r) { + internal::greater_or_equal_t operator>=(F f, R r) { return {std::move(f), std::move(r)}; } @@ -306,7 +306,7 @@ namespace sqlite_orm { class F, class R, typename = typename std::enable_if::value>::type> - conditions::is_equal_t operator==(F f, R r) { + internal::is_equal_t operator==(F f, R r) { return {std::move(f), std::move(r)}; } @@ -314,7 +314,7 @@ namespace sqlite_orm { class F, class R, typename = typename std::enable_if::value>::type> - conditions::is_not_equal_t operator!=(F f, R r) { + internal::is_not_equal_t operator!=(F f, R r) { return {std::move(f), std::move(r)}; } diff --git a/dev/join_iterator.h b/dev/join_iterator.h index 1e5fd7e00..4d9777d1a 100644 --- a/dev/join_iterator.h +++ b/dev/join_iterator.h @@ -35,9 +35,9 @@ namespace sqlite_orm { }; template - struct join_iterator, Tail...> : public join_iterator { + struct join_iterator, Tail...> : public join_iterator { using super = join_iterator; - using join_type = conditions::cross_join_t; + using join_type = cross_join_t; template void operator()(const L &l) { @@ -47,9 +47,9 @@ namespace sqlite_orm { }; template - struct join_iterator, Tail...> : public join_iterator { + struct join_iterator, Tail...> : public join_iterator { using super = join_iterator; - using join_type = conditions::natural_join_t; + using join_type = natural_join_t; template void operator()(const L &l) { @@ -59,9 +59,9 @@ namespace sqlite_orm { }; template - struct join_iterator, Tail...> : public join_iterator { + struct join_iterator, Tail...> : public join_iterator { using super = join_iterator; - using join_type = conditions::left_join_t; + using join_type = left_join_t; template void operator()(const L &l) { @@ -71,9 +71,9 @@ namespace sqlite_orm { }; template - struct join_iterator, Tail...> : public join_iterator { + struct join_iterator, Tail...> : public join_iterator { using super = join_iterator; - using join_type = conditions::join_t; + using join_type = join_t; template void operator()(const L &l) { @@ -83,9 +83,9 @@ namespace sqlite_orm { }; template - struct join_iterator, Tail...> : public join_iterator { + struct join_iterator, Tail...> : public join_iterator { using super = join_iterator; - using join_type = conditions::left_outer_join_t; + using join_type = left_outer_join_t; template void operator()(const L &l) { @@ -95,9 +95,9 @@ namespace sqlite_orm { }; template - struct join_iterator, Tail...> : public join_iterator { + struct join_iterator, Tail...> : public join_iterator { using super = join_iterator; - using join_type = conditions::inner_join_t; + using join_type = inner_join_t; template void operator()(const L &l) { diff --git a/dev/node_tuple.h b/dev/node_tuple.h index 18066bfc2..66e34d478 100644 --- a/dev/node_tuple.h +++ b/dev/node_tuple.h @@ -31,14 +31,13 @@ namespace sqlite_orm { }; template - struct node_tuple, void> { - using node_type = conditions::where_t; + struct node_tuple, void> { + using node_type = where_t; using type = typename node_tuple::type; }; template - struct node_tuple::value>::type> { + struct node_tuple::value>::type> { using node_type = T; using left_type = typename node_type::left_type; using right_type = typename node_type::right_type; @@ -64,8 +63,8 @@ namespace sqlite_orm { }; template - struct node_tuple, void> { - using node_type = conditions::in_t; + struct node_tuple, void> { + using node_type = in_t; using left_tuple = typename node_tuple::type; using right_tuple = typename node_tuple::type; using type = typename conc_tuple::type; @@ -124,20 +123,20 @@ namespace sqlite_orm { }; template - struct node_tuple, void> { - using node_type = conditions::having_t; + struct node_tuple, void> { + using node_type = having_t; using type = typename node_tuple::type; }; template - struct node_tuple, void> { - using node_type = conditions::cast_t; + struct node_tuple, void> { + using node_type = cast_t; using type = typename node_tuple::type; }; template - struct node_tuple, void> { - using node_type = conditions::exists_t; + struct node_tuple, void> { + using node_type = exists_t; using type = typename node_tuple::type; }; @@ -154,8 +153,8 @@ namespace sqlite_orm { }; template - struct node_tuple, void> { - using node_type = conditions::like_t; + struct node_tuple, void> { + using node_type = like_t; using arg_tuple = typename node_tuple::type; using pattern_tuple = typename node_tuple::type; using escape_tuple = typename node_tuple::type; @@ -163,16 +162,16 @@ namespace sqlite_orm { }; template - struct node_tuple, void> { - using node_type = conditions::glob_t; + struct node_tuple, void> { + using node_type = glob_t; using arg_tuple = typename node_tuple::type; using pattern_tuple = typename node_tuple::type; using type = typename conc_tuple::type; }; template - struct node_tuple, void> { - using node_type = conditions::between_t; + struct node_tuple, void> { + using node_type = between_t; using expression_tuple = typename node_tuple::type; using lower_tuple = typename node_tuple::type; using upper_tuple = typename node_tuple::type; @@ -180,26 +179,26 @@ namespace sqlite_orm { }; template - struct node_tuple, void> { - using node_type = conditions::named_collate; + struct node_tuple, void> { + using node_type = named_collate; using type = typename node_tuple::type; }; template - struct node_tuple, void> { - using node_type = conditions::is_null_t; + struct node_tuple, void> { + using node_type = is_null_t; using type = typename node_tuple::type; }; template - struct node_tuple, void> { - using node_type = conditions::is_not_null_t; + struct node_tuple, void> { + using node_type = is_not_null_t; using type = typename node_tuple::type; }; template - struct node_tuple, void> { - using node_type = conditions::negated_condition_t; + struct node_tuple, void> { + using node_type = negated_condition_t; using type = typename node_tuple::type; }; @@ -210,32 +209,32 @@ namespace sqlite_orm { }; template - struct node_tuple, void> { - using node_type = conditions::left_join_t; + struct node_tuple, void> { + using node_type = left_join_t; using type = typename node_tuple::type; }; template - struct node_tuple, void> { - using node_type = conditions::on_t; + struct node_tuple, void> { + using node_type = on_t; using type = typename node_tuple::type; }; template - struct node_tuple, void> { - using node_type = conditions::join_t; + struct node_tuple, void> { + using node_type = join_t; using type = typename node_tuple::type; }; template - struct node_tuple, void> { - using node_type = conditions::left_outer_join_t; + struct node_tuple, void> { + using node_type = left_outer_join_t; using type = typename node_tuple::type; }; template - struct node_tuple, void> { - using node_type = conditions::inner_join_t; + struct node_tuple, void> { + using node_type = inner_join_t; using type = typename node_tuple::type; }; @@ -263,20 +262,20 @@ namespace sqlite_orm { }; template - struct node_tuple, void> { - using node_type = conditions::limit_t; + struct node_tuple, void> { + using node_type = limit_t; using type = typename node_tuple::type; }; template - struct node_tuple, void> { - using node_type = conditions::limit_t; + struct node_tuple, void> { + using node_type = limit_t; using type = typename conc_tuple::type, typename node_tuple::type>::type; }; template - struct node_tuple, void> { - using node_type = conditions::limit_t; + struct node_tuple, void> { + using node_type = limit_t; using type = typename conc_tuple::type, typename node_tuple::type>::type; }; } diff --git a/dev/select_constraints.h b/dev/select_constraints.h index 6659b008c..bb3ad1900 100644 --- a/dev/select_constraints.h +++ b/dev/select_constraints.h @@ -236,14 +236,10 @@ namespace sqlite_orm { template void validate_conditions() { - static_assert(count_tuple::value <= 1, - "a single query cannot contain > 1 WHERE blocks"); - static_assert(count_tuple::value <= 1, - "a single query cannot contain > 1 GROUP BY blocks"); - static_assert(count_tuple::value <= 1, - "a single query cannot contain > 1 ORDER BY blocks"); - static_assert(count_tuple::value <= 1, - "a single query cannot contain > 1 LIMIT blocks"); + static_assert(count_tuple::value <= 1, "a single query cannot contain > 1 WHERE blocks"); + static_assert(count_tuple::value <= 1, "a single query cannot contain > 1 GROUP BY blocks"); + static_assert(count_tuple::value <= 1, "a single query cannot contain > 1 ORDER BY blocks"); + static_assert(count_tuple::value <= 1, "a single query cannot contain > 1 LIMIT blocks"); } } diff --git a/dev/statement_serializator.h b/dev/statement_serializator.h index 681754fbe..89a70ac18 100644 --- a/dev/statement_serializator.h +++ b/dev/statement_serializator.h @@ -254,9 +254,8 @@ namespace sqlite_orm { }; template - struct statement_serializator< - T, - typename std::enable_if::value>::type> { + struct statement_serializator::value>::type> { using statement_type = T; template diff --git a/dev/storage.h b/dev/storage.h index e4adbd9a0..375f8ca15 100644 --- a/dev/storage.h +++ b/dev/storage.h @@ -83,7 +83,7 @@ namespace sqlite_orm { friend struct view_t; template - friend struct conditions::dynamic_order_by_t; + friend struct dynamic_order_by_t; template friend struct iterator_t; @@ -855,7 +855,7 @@ namespace sqlite_orm { } template - std::string string_from_expression(const conditions::cast_t &c, bool noTableName) const { + std::string string_from_expression(const cast_t &c, bool noTableName) const { std::stringstream ss; ss << static_cast(c) << " ("; ss << this->string_from_expression(c.expression, noTableName) << " AS " << type_printer().print() @@ -893,14 +893,14 @@ namespace sqlite_orm { } template - std::string string_from_expression(const conditions::is_null_t &c, bool noTableName) const { + std::string string_from_expression(const is_null_t &c, bool noTableName) const { std::stringstream ss; ss << this->string_from_expression(c.t, noTableName) << " " << static_cast(c) << " "; return ss.str(); } template - std::string string_from_expression(const conditions::is_not_null_t &c, bool noTableName) const { + std::string string_from_expression(const is_not_null_t &c, bool noTableName) const { std::stringstream ss; ss << this->string_from_expression(c.t, noTableName) << " " << static_cast(c) << " "; return ss.str(); @@ -916,7 +916,7 @@ namespace sqlite_orm { } template - std::string string_from_expression(const conditions::negated_condition_t &c, bool noTableName) const { + std::string string_from_expression(const negated_condition_t &c, bool noTableName) const { std::stringstream ss; ss << static_cast(c) << " "; auto cString = this->string_from_expression(c.c, noTableName); @@ -925,7 +925,7 @@ namespace sqlite_orm { } template - std::string string_from_expression(const conditions::is_equal_t &c, bool noTableName) const { + std::string string_from_expression(const is_equal_t &c, bool noTableName) const { auto leftString = this->string_from_expression(c.l, noTableName); auto rightString = this->string_from_expression(c.r, noTableName); std::stringstream ss; @@ -934,7 +934,7 @@ namespace sqlite_orm { } template - typename std::enable_if::value, std::string>::type + typename std::enable_if::value, std::string>::type string_from_expression(const C &c, bool noTableName) const { auto leftString = this->string_from_expression(c.l, noTableName); auto rightString = this->string_from_expression(c.r, noTableName); @@ -944,19 +944,19 @@ namespace sqlite_orm { } template - std::string string_from_expression(const conditions::named_collate &col, bool noTableName) const { + std::string string_from_expression(const named_collate &col, bool noTableName) const { auto res = this->string_from_expression(col.expr, noTableName); return res + " " + static_cast(col); } template - std::string string_from_expression(const conditions::collate_t &col, bool noTableName) const { + std::string string_from_expression(const collate_t &col, bool noTableName) const { auto res = this->string_from_expression(col.expr, noTableName); return res + " " + static_cast(col); } template - std::string string_from_expression(const conditions::in_t &inCondition, bool noTableName) const { + std::string string_from_expression(const in_t &inCondition, bool noTableName) const { std::stringstream ss; auto leftString = this->string_from_expression(inCondition.l, noTableName); ss << leftString << " " << static_cast(inCondition) << " "; @@ -965,8 +965,7 @@ namespace sqlite_orm { } template - std::string string_from_expression(const conditions::in_t> &inCondition, - bool noTableName) const { + std::string string_from_expression(const in_t> &inCondition, bool noTableName) const { std::stringstream ss; auto leftString = this->string_from_expression(inCondition.l, noTableName); ss << leftString << " " << static_cast(inCondition) << " ( "; @@ -982,7 +981,7 @@ namespace sqlite_orm { } template - std::string string_from_expression(const conditions::like_t &l, bool noTableName) const { + std::string string_from_expression(const like_t &l, bool noTableName) const { std::stringstream ss; ss << this->string_from_expression(l.arg, noTableName) << " "; ss << static_cast(l) << " "; @@ -994,7 +993,7 @@ namespace sqlite_orm { } template - std::string string_from_expression(const conditions::glob_t &l, bool noTableName) const { + std::string string_from_expression(const glob_t &l, bool noTableName) const { std::stringstream ss; ss << this->string_from_expression(l.arg, noTableName) << " "; ss << static_cast(l) << " "; @@ -1003,7 +1002,7 @@ namespace sqlite_orm { } template - std::string string_from_expression(const conditions::between_t &bw, bool noTableName) const { + std::string string_from_expression(const between_t &bw, bool noTableName) const { std::stringstream ss; auto expr = this->string_from_expression(bw.expr, noTableName); ss << expr << " " << static_cast(bw) << " "; @@ -1014,7 +1013,7 @@ namespace sqlite_orm { } template - std::string string_from_expression(const conditions::exists_t &e, bool noTableName) const { + std::string string_from_expression(const exists_t &e, bool noTableName) const { std::stringstream ss; ss << static_cast(e) << " "; ss << this->string_from_expression(e.t, noTableName); @@ -1022,7 +1021,7 @@ namespace sqlite_orm { } template - std::string process_order_by(const conditions::order_by_t &orderBy) const { + std::string process_order_by(const order_by_t &orderBy) const { std::stringstream ss; auto columnName = this->string_from_expression(orderBy.o, false); ss << columnName << " "; @@ -1041,12 +1040,12 @@ namespace sqlite_orm { } template - void process_join_constraint(std::stringstream &ss, const conditions::on_t &t) const { + void process_join_constraint(std::stringstream &ss, const on_t &t) const { ss << static_cast(t) << " " << this->string_from_expression(t.arg, false); } template - void process_join_constraint(std::stringstream &ss, const conditions::using_t &u) const { + void process_join_constraint(std::stringstream &ss, const using_t &u) const { ss << static_cast(u) << " (" << this->string_from_expression(u.column, true) << " )"; } @@ -1055,7 +1054,7 @@ namespace sqlite_orm { * OI - offset is implicit */ template - std::string string_from_expression(const conditions::limit_t &limt, bool) const { + std::string string_from_expression(const limit_t &limt, bool) const { std::stringstream ss; ss << static_cast(limt) << " "; if(HO) { @@ -1078,7 +1077,7 @@ namespace sqlite_orm { } template - std::string string_from_expression(const conditions::cross_join_t &c, bool) const { + std::string string_from_expression(const cross_join_t &c, bool) const { std::stringstream ss; ss << static_cast(c) << " "; ss << " '" << this->impl.find_table_name(typeid(O)) << "'"; @@ -1086,7 +1085,7 @@ namespace sqlite_orm { } template - std::string string_from_expression(const conditions::natural_join_t &c, bool) const { + std::string string_from_expression(const natural_join_t &c, bool) const { std::stringstream ss; ss << static_cast(c) << " "; ss << " '" << this->impl.find_table_name(typeid(O)) << "'"; @@ -1094,7 +1093,7 @@ namespace sqlite_orm { } template - std::string string_from_expression(const conditions::inner_join_t &l, bool) const { + std::string string_from_expression(const inner_join_t &l, bool) const { std::stringstream ss; ss << static_cast(l) << " "; auto aliasString = alias_extractor::get(); @@ -1107,7 +1106,7 @@ namespace sqlite_orm { } template - std::string string_from_expression(const conditions::left_outer_join_t &l, bool) const { + std::string string_from_expression(const left_outer_join_t &l, bool) const { std::stringstream ss; ss << static_cast(l) << " "; ss << " '" << this->impl.find_table_name(typeid(T)) << "' "; @@ -1116,7 +1115,7 @@ namespace sqlite_orm { } template - std::string string_from_expression(const conditions::left_join_t &l, bool) const { + std::string string_from_expression(const left_join_t &l, bool) const { std::stringstream ss; ss << static_cast(l) << " "; ss << " '" << this->impl.find_table_name(typeid(T)) << "' "; @@ -1125,7 +1124,7 @@ namespace sqlite_orm { } template - std::string string_from_expression(const conditions::join_t &l, bool) const { + std::string string_from_expression(const join_t &l, bool) const { std::stringstream ss; ss << static_cast(l) << " "; ss << " '" << this->impl.find_table_name(typeid(T)) << "' "; @@ -1134,7 +1133,7 @@ namespace sqlite_orm { } template - std::string string_from_expression(const conditions::where_t &w, bool) const { + std::string string_from_expression(const where_t &w, bool) const { std::stringstream ss; ss << static_cast(w) << " "; auto whereString = this->string_from_expression(w.c, false); @@ -1143,7 +1142,7 @@ namespace sqlite_orm { } template - std::string string_from_expression(const conditions::order_by_t &orderBy, bool) const { + std::string string_from_expression(const order_by_t &orderBy, bool) const { std::stringstream ss; ss << static_cast(orderBy) << " "; auto orderByString = this->process_order_by(orderBy); @@ -1152,7 +1151,7 @@ namespace sqlite_orm { } template - std::string string_from_expression(const conditions::multi_order_by_t &orderBy, bool) const { + std::string string_from_expression(const multi_order_by_t &orderBy, bool) const { std::stringstream ss; std::vector expressions; iterate_tuple(orderBy.args, [&expressions, this](auto &v) { @@ -1171,14 +1170,14 @@ namespace sqlite_orm { } template - std::string string_from_expression(const conditions::dynamic_order_by_t &orderBy, bool) const { + std::string string_from_expression(const dynamic_order_by_t &orderBy, bool) const { std::stringstream ss; ss << this->storage_base::process_order_by(orderBy) << " "; return ss.str(); } template - std::string string_from_expression(const conditions::group_by_t &groupBy, bool) const { + std::string string_from_expression(const group_by_t &groupBy, bool) const { std::stringstream ss; std::vector expressions; iterate_tuple(groupBy.args, [&expressions, this](auto &v) { @@ -1197,7 +1196,7 @@ namespace sqlite_orm { } template - std::string string_from_expression(const conditions::having_t &hav, bool) const { + std::string string_from_expression(const having_t &hav, bool) const { std::stringstream ss; ss << static_cast(hav) << " "; ss << this->string_from_expression(hav.t, false) << " "; diff --git a/dev/storage_base.h b/dev/storage_base.h index 6fcacab58..843ec3aa3 100644 --- a/dev/storage_base.h +++ b/dev/storage_base.h @@ -501,7 +501,7 @@ namespace sqlite_orm { } template - std::string process_order_by(const conditions::dynamic_order_by_t &orderBy) const { + std::string process_order_by(const dynamic_order_by_t &orderBy) const { std::vector expressions; for(auto &entry: orderBy) { std::string entryString; diff --git a/include/sqlite_orm/sqlite_orm.h b/include/sqlite_orm/sqlite_orm.h index 53195cb3c..5c7cb682e 100644 --- a/include/sqlite_orm/sqlite_orm.h +++ b/include/sqlite_orm/sqlite_orm.h @@ -1911,7 +1911,7 @@ namespace sqlite_orm { struct arithmetic_t; } - namespace conditions { + namespace internal { struct limit_string { operator std::string() const { @@ -2386,27 +2386,31 @@ namespace sqlite_orm { multi_order_by_t(args_type &&args_) : args(std::move(args_)) {} }; + struct dynamic_order_by_entry_t : order_by_base { + std::string name; + + dynamic_order_by_entry_t(decltype(name) name_, int asc_desc, std::string collate_argument) : + order_by_base{asc_desc, move(collate_argument)}, name(move(name_)) {} + }; + /** - * S - storage class + * C - serializator context class */ - template + template struct dynamic_order_by_t : order_by_string { - using storage_type = S; - - struct entry_t : order_by_base { - std::string name; - - entry_t(decltype(name) name_, int asc_desc, std::string collate_argument) : - order_by_base{asc_desc, move(collate_argument)}, name(move(name_)) {} - }; + using context_type = C; + using entry_t = dynamic_order_by_entry_t; using const_iterator = typename std::vector::const_iterator; - dynamic_order_by_t(const storage_type &storage_) : storage(storage_) {} + template + dynamic_order_by_t(const S &storage_) : context(storage_.impl) { + // this->context.skip_table_name = true; + } template void push_back(order_by_t order_by) { - auto columnName = this->storage.string_from_expression(order_by.o, true); + auto columnName = serialize(order_by.o, this->context); entries.emplace_back(move(columnName), order_by.asc_desc, move(order_by._collate_argument)); } @@ -2424,7 +2428,7 @@ namespace sqlite_orm { protected: std::vector entries; - const storage_type &storage; + context_type context; }; template @@ -2745,7 +2749,7 @@ namespace sqlite_orm { } template::value>::type> - conditions::negated_condition_t operator!(T arg) { + internal::negated_condition_t operator!(T arg) { return {std::move(arg)}; } @@ -2753,62 +2757,62 @@ namespace sqlite_orm { * Cute operators for columns */ template - conditions::lesser_than_t operator<(internal::expression_t expr, R r) { + internal::lesser_than_t operator<(internal::expression_t expr, R r) { return {std::move(expr.t), std::move(r)}; } template - conditions::lesser_than_t operator<(L l, internal::expression_t expr) { + internal::lesser_than_t operator<(L l, internal::expression_t expr) { return {std::move(l), std::move(expr.t)}; } template - conditions::lesser_or_equal_t operator<=(internal::expression_t expr, R r) { + internal::lesser_or_equal_t operator<=(internal::expression_t expr, R r) { return {std::move(expr.t), std::move(r)}; } template - conditions::lesser_or_equal_t operator<=(L l, internal::expression_t expr) { + internal::lesser_or_equal_t operator<=(L l, internal::expression_t expr) { return {std::move(l), std::move(expr.t)}; } template - conditions::greater_than_t operator>(internal::expression_t expr, R r) { + internal::greater_than_t operator>(internal::expression_t expr, R r) { return {std::move(expr.t), std::move(r)}; } template - conditions::greater_than_t operator>(L l, internal::expression_t expr) { + internal::greater_than_t operator>(L l, internal::expression_t expr) { return {std::move(l), std::move(expr.t)}; } template - conditions::greater_or_equal_t operator>=(internal::expression_t expr, R r) { + internal::greater_or_equal_t operator>=(internal::expression_t expr, R r) { return {std::move(expr.t), std::move(r)}; } template - conditions::greater_or_equal_t operator>=(L l, internal::expression_t expr) { + internal::greater_or_equal_t operator>=(L l, internal::expression_t expr) { return {std::move(l), std::move(expr.t)}; } template - conditions::is_equal_t operator==(internal::expression_t expr, R r) { + internal::is_equal_t operator==(internal::expression_t expr, R r) { return {std::move(expr.t), std::move(r)}; } template - conditions::is_equal_t operator==(L l, internal::expression_t expr) { + internal::is_equal_t operator==(L l, internal::expression_t expr) { return {std::move(l), std::move(expr.t)}; } template - conditions::is_not_equal_t operator!=(internal::expression_t expr, R r) { + internal::is_not_equal_t operator!=(internal::expression_t expr, R r) { return {std::move(expr.t), std::move(r)}; } template - conditions::is_not_equal_t operator!=(L l, internal::expression_t expr) { + internal::is_not_equal_t operator!=(L l, internal::expression_t expr) { return {std::move(l), std::move(expr.t)}; } @@ -2903,184 +2907,184 @@ namespace sqlite_orm { } template - conditions::using_t using_(F O::*p) { + internal::using_t using_(F O::*p) { return {std::move(p)}; } template - conditions::on_t on(T t) { + internal::on_t on(T t) { return {std::move(t)}; } template - conditions::cross_join_t cross_join() { + internal::cross_join_t cross_join() { return {}; } template - conditions::natural_join_t natural_join() { + internal::natural_join_t natural_join() { return {}; } template - conditions::left_join_t left_join(O o) { + internal::left_join_t left_join(O o) { return {std::move(o)}; } template - conditions::join_t join(O o) { + internal::join_t join(O o) { return {std::move(o)}; } template - conditions::left_outer_join_t left_outer_join(O o) { + internal::left_outer_join_t left_outer_join(O o) { return {std::move(o)}; } template - conditions::inner_join_t inner_join(O o) { + internal::inner_join_t inner_join(O o) { return {std::move(o)}; } template - conditions::offset_t offset(T off) { + internal::offset_t offset(T off) { return {std::move(off)}; } template - conditions::limit_t limit(T lim) { + internal::limit_t limit(T lim) { return {std::move(lim)}; } template - typename std::enable_if::value, conditions::limit_t>::type - limit(O off, T lim) { + typename std::enable_if::value, internal::limit_t>::type limit(O off, + T lim) { return {std::move(lim), {std::move(off)}}; } template - conditions::limit_t limit(T lim, conditions::offset_t offt) { + internal::limit_t limit(T lim, internal::offset_t offt) { return {std::move(lim), {std::move(offt.off)}}; } template::value || - std::is_base_of::value>::type> - conditions::and_condition_t operator&&(L l, R r) { + typename = typename std::enable_if::value || + std::is_base_of::value>::type> + internal::and_condition_t operator&&(L l, R r) { return {std::move(l), std::move(r)}; } template::value || - std::is_base_of::value>::type> - conditions::or_condition_t operator||(L l, R r) { + typename = typename std::enable_if::value || + std::is_base_of::value>::type> + internal::or_condition_t operator||(L l, R r) { return {std::move(l), std::move(r)}; } template - conditions::is_not_null_t is_not_null(T t) { + internal::is_not_null_t is_not_null(T t) { return {std::move(t)}; } template - conditions::is_null_t is_null(T t) { + internal::is_null_t is_null(T t) { return {std::move(t)}; } template - conditions::in_t> in(L l, std::vector values) { + internal::in_t> in(L l, std::vector values) { return {std::move(l), std::move(values), false}; } template - conditions::in_t> in(L l, std::initializer_list values) { + internal::in_t> in(L l, std::initializer_list values) { return {std::move(l), std::move(values), false}; } template - conditions::in_t in(L l, A arg) { + internal::in_t in(L l, A arg) { return {std::move(l), std::move(arg), false}; } template - conditions::in_t> not_in(L l, std::vector values) { + internal::in_t> not_in(L l, std::vector values) { return {std::move(l), std::move(values), true}; } template - conditions::in_t> not_in(L l, std::initializer_list values) { + internal::in_t> not_in(L l, std::initializer_list values) { return {std::move(l), std::move(values), true}; } template - conditions::in_t not_in(L l, A arg) { + internal::in_t not_in(L l, A arg) { return {std::move(l), std::move(arg), true}; } template - conditions::is_equal_t is_equal(L l, R r) { + internal::is_equal_t is_equal(L l, R r) { return {std::move(l), std::move(r)}; } template - conditions::is_equal_t eq(L l, R r) { + internal::is_equal_t eq(L l, R r) { return {std::move(l), std::move(r)}; } template - conditions::is_not_equal_t is_not_equal(L l, R r) { + internal::is_not_equal_t is_not_equal(L l, R r) { return {std::move(l), std::move(r)}; } template - conditions::is_not_equal_t ne(L l, R r) { + internal::is_not_equal_t ne(L l, R r) { return {std::move(l), std::move(r)}; } template - conditions::greater_than_t greater_than(L l, R r) { + internal::greater_than_t greater_than(L l, R r) { return {std::move(l), std::move(r)}; } template - conditions::greater_than_t gt(L l, R r) { + internal::greater_than_t gt(L l, R r) { return {std::move(l), std::move(r)}; } template - conditions::greater_or_equal_t greater_or_equal(L l, R r) { + internal::greater_or_equal_t greater_or_equal(L l, R r) { return {std::move(l), std::move(r)}; } template - conditions::greater_or_equal_t ge(L l, R r) { + internal::greater_or_equal_t ge(L l, R r) { return {std::move(l), std::move(r)}; } template - conditions::lesser_than_t lesser_than(L l, R r) { + internal::lesser_than_t lesser_than(L l, R r) { return {std::move(l), std::move(r)}; } template - conditions::lesser_than_t lt(L l, R r) { + internal::lesser_than_t lt(L l, R r) { return {std::move(l), std::move(r)}; } template - conditions::lesser_or_equal_t lesser_or_equal(L l, R r) { + internal::lesser_or_equal_t lesser_or_equal(L l, R r) { return {std::move(l), std::move(r)}; } template - conditions::lesser_or_equal_t le(L l, R r) { + internal::lesser_or_equal_t le(L l, R r) { return {std::move(l), std::move(r)}; } template - conditions::where_t where(C c) { + internal::where_t where(C c) { return {std::move(c)}; } @@ -3089,7 +3093,7 @@ namespace sqlite_orm { * Example: storage.select(&User::name, order_by(&User::id)) */ template - conditions::order_by_t order_by(O o) { + internal::order_by_t order_by(O o) { return {std::move(o)}; } @@ -3098,7 +3102,7 @@ namespace sqlite_orm { * Example: storage.get_all(multi_order_by(order_by(&Singer::name).asc(), order_by(&Singer::gender).desc()) */ template - conditions::multi_order_by_t multi_order_by(Args &&... args) { + internal::multi_order_by_t multi_order_by(Args &&... args) { return {std::make_tuple(std::forward(args)...)}; } @@ -3115,7 +3119,8 @@ namespace sqlite_orm { * } */ template - conditions::dynamic_order_by_t dynamic_order_by(const S &storage) { + internal::dynamic_order_by_t> + dynamic_order_by(const S &storage) { return {storage}; } @@ -3124,7 +3129,7 @@ namespace sqlite_orm { * Example: storage.get_all(group_by(&Employee::name)) */ template - conditions::group_by_t group_by(Args &&... args) { + internal::group_by_t group_by(Args &&... args) { return {std::make_tuple(std::forward(args)...)}; } @@ -3133,7 +3138,7 @@ namespace sqlite_orm { * Example: storage.select(between(&User::id, 10, 20)) */ template - conditions::between_t between(A expr, T b1, T b2) { + internal::between_t between(A expr, T b1, T b2) { return {std::move(expr), std::move(b1), std::move(b2)}; } @@ -3142,7 +3147,7 @@ namespace sqlite_orm { * Example: storage.select(like(&User::name, "T%")) */ template - conditions::like_t like(A a, T t) { + internal::like_t like(A a, T t) { return {std::move(a), std::move(t), {}}; } @@ -3151,7 +3156,7 @@ namespace sqlite_orm { * Example: storage.select(glob(&User::name, "*S")) */ template - conditions::glob_t glob(A a, T t) { + internal::glob_t glob(A a, T t) { return {std::move(a), std::move(t)}; } @@ -3160,7 +3165,7 @@ namespace sqlite_orm { * Example: storage.select(like(&User::name, "T%", "%")) */ template - conditions::like_t like(A a, T t, E e) { + internal::like_t like(A a, T t, E e) { return {std::move(a), std::move(t), {std::move(e)}}; } @@ -3173,7 +3178,7 @@ namespace sqlite_orm { order_by(&Agent::comission)); */ template - conditions::exists_t exists(T t) { + internal::exists_t exists(T t) { return {std::move(t)}; } @@ -3182,7 +3187,7 @@ namespace sqlite_orm { * Example: storage.get_all(group_by(&Employee::name), having(greater_than(count(&Employee::name), 2))); */ template - conditions::having_t having(T t) { + internal::having_t having(T t) { return {std::move(t)}; } @@ -3191,7 +3196,7 @@ namespace sqlite_orm { * Example: cast(&User::id) */ template - conditions::cast_t cast(E e) { + internal::cast_t cast(E e) { return {std::move(e)}; } } @@ -3383,9 +3388,9 @@ namespace sqlite_orm { }; template - struct join_iterator, Tail...> : public join_iterator { + struct join_iterator, Tail...> : public join_iterator { using super = join_iterator; - using join_type = conditions::cross_join_t; + using join_type = cross_join_t; template void operator()(const L &l) { @@ -3395,9 +3400,9 @@ namespace sqlite_orm { }; template - struct join_iterator, Tail...> : public join_iterator { + struct join_iterator, Tail...> : public join_iterator { using super = join_iterator; - using join_type = conditions::natural_join_t; + using join_type = natural_join_t; template void operator()(const L &l) { @@ -3407,9 +3412,9 @@ namespace sqlite_orm { }; template - struct join_iterator, Tail...> : public join_iterator { + struct join_iterator, Tail...> : public join_iterator { using super = join_iterator; - using join_type = conditions::left_join_t; + using join_type = left_join_t; template void operator()(const L &l) { @@ -3419,9 +3424,9 @@ namespace sqlite_orm { }; template - struct join_iterator, Tail...> : public join_iterator { + struct join_iterator, Tail...> : public join_iterator { using super = join_iterator; - using join_type = conditions::join_t; + using join_type = join_t; template void operator()(const L &l) { @@ -3431,9 +3436,9 @@ namespace sqlite_orm { }; template - struct join_iterator, Tail...> : public join_iterator { + struct join_iterator, Tail...> : public join_iterator { using super = join_iterator; - using join_type = conditions::left_outer_join_t; + using join_type = left_outer_join_t; template void operator()(const L &l) { @@ -3443,9 +3448,9 @@ namespace sqlite_orm { }; template - struct join_iterator, Tail...> : public join_iterator { + struct join_iterator, Tail...> : public join_iterator { using super = join_iterator; - using join_type = conditions::inner_join_t; + using join_type = inner_join_t; template void operator()(const L &l) { @@ -3770,7 +3775,7 @@ namespace sqlite_orm { class F, class R, typename = typename std::enable_if::value>::type> - conditions::lesser_than_t operator<(F f, R r) { + internal::lesser_than_t operator<(F f, R r) { return {std::move(f), std::move(r)}; } @@ -3778,7 +3783,7 @@ namespace sqlite_orm { class F, class R, typename = typename std::enable_if::value>::type> - conditions::lesser_or_equal_t operator<=(F f, R r) { + internal::lesser_or_equal_t operator<=(F f, R r) { return {std::move(f), std::move(r)}; } @@ -3786,7 +3791,7 @@ namespace sqlite_orm { class F, class R, typename = typename std::enable_if::value>::type> - conditions::greater_than_t operator>(F f, R r) { + internal::greater_than_t operator>(F f, R r) { return {std::move(f), std::move(r)}; } @@ -3794,7 +3799,7 @@ namespace sqlite_orm { class F, class R, typename = typename std::enable_if::value>::type> - conditions::greater_or_equal_t operator>=(F f, R r) { + internal::greater_or_equal_t operator>=(F f, R r) { return {std::move(f), std::move(r)}; } @@ -3802,7 +3807,7 @@ namespace sqlite_orm { class F, class R, typename = typename std::enable_if::value>::type> - conditions::is_equal_t operator==(F f, R r) { + internal::is_equal_t operator==(F f, R r) { return {std::move(f), std::move(r)}; } @@ -3810,7 +3815,7 @@ namespace sqlite_orm { class F, class R, typename = typename std::enable_if::value>::type> - conditions::is_not_equal_t operator!=(F f, R r) { + internal::is_not_equal_t operator!=(F f, R r) { return {std::move(f), std::move(r)}; } @@ -4486,14 +4491,10 @@ namespace sqlite_orm { template void validate_conditions() { - static_assert(count_tuple::value <= 1, - "a single query cannot contain > 1 WHERE blocks"); - static_assert(count_tuple::value <= 1, - "a single query cannot contain > 1 GROUP BY blocks"); - static_assert(count_tuple::value <= 1, - "a single query cannot contain > 1 ORDER BY blocks"); - static_assert(count_tuple::value <= 1, - "a single query cannot contain > 1 LIMIT blocks"); + static_assert(count_tuple::value <= 1, "a single query cannot contain > 1 WHERE blocks"); + static_assert(count_tuple::value <= 1, "a single query cannot contain > 1 GROUP BY blocks"); + static_assert(count_tuple::value <= 1, "a single query cannot contain > 1 ORDER BY blocks"); + static_assert(count_tuple::value <= 1, "a single query cannot contain > 1 LIMIT blocks"); } } @@ -5853,7 +5854,7 @@ namespace sqlite_orm { }; template - struct column_result_t, void> { + struct column_result_t, void> { using type = T; }; @@ -5863,17 +5864,17 @@ namespace sqlite_orm { }; template - struct column_result_t, void> { + struct column_result_t, void> { using type = bool; }; template - struct column_result_t, void> { + struct column_result_t, void> { using type = bool; }; template - struct column_result_t, void> { + struct column_result_t, void> { using type = bool; }; @@ -7421,8 +7422,8 @@ namespace sqlite_orm { }; template - struct ast_iterator, void> { - using node_type = conditions::where_t; + struct ast_iterator, void> { + using node_type = where_t; template void operator()(const node_type &where, const L &l) const { @@ -7431,9 +7432,7 @@ namespace sqlite_orm { }; template - struct ast_iterator< - T, - typename std::enable_if::value>::type> { + struct ast_iterator::value>::type> { using node_type = T; template @@ -7465,8 +7464,8 @@ namespace sqlite_orm { }; template - struct ast_iterator, void> { - using node_type = conditions::in_t; + struct ast_iterator, void> { + using node_type = in_t; template void operator()(const node_type &in, const C &l) const { @@ -7595,8 +7594,8 @@ namespace sqlite_orm { }; template - struct ast_iterator, void> { - using node_type = conditions::having_t; + struct ast_iterator, void> { + using node_type = having_t; template void operator()(const node_type &hav, const L &l) const { @@ -7605,8 +7604,8 @@ namespace sqlite_orm { }; template - struct ast_iterator, void> { - using node_type = conditions::cast_t; + struct ast_iterator, void> { + using node_type = cast_t; template void operator()(const node_type &c, const L &l) const { @@ -7615,8 +7614,8 @@ namespace sqlite_orm { }; template - struct ast_iterator, void> { - using node_type = conditions::exists_t; + struct ast_iterator, void> { + using node_type = exists_t; template void operator()(const node_type &e, const L &l) const { @@ -7625,8 +7624,8 @@ namespace sqlite_orm { }; template - struct ast_iterator, void> { - using node_type = conditions::like_t; + struct ast_iterator, void> { + using node_type = like_t; template void operator()(const node_type &lk, const L &l) const { @@ -7639,8 +7638,8 @@ namespace sqlite_orm { }; template - struct ast_iterator, void> { - using node_type = conditions::glob_t; + struct ast_iterator, void> { + using node_type = glob_t; template void operator()(const node_type &lk, const L &l) const { @@ -7650,8 +7649,8 @@ namespace sqlite_orm { }; template - struct ast_iterator, void> { - using node_type = conditions::between_t; + struct ast_iterator, void> { + using node_type = between_t; template void operator()(const node_type &b, const L &l) const { @@ -7662,8 +7661,8 @@ namespace sqlite_orm { }; template - struct ast_iterator, void> { - using node_type = conditions::named_collate; + struct ast_iterator, void> { + using node_type = named_collate; template void operator()(const node_type &col, const L &l) const { @@ -7672,8 +7671,8 @@ namespace sqlite_orm { }; template - struct ast_iterator, void> { - using node_type = conditions::negated_condition_t; + struct ast_iterator, void> { + using node_type = negated_condition_t; template void operator()(const node_type &neg, const L &l) const { @@ -7682,8 +7681,8 @@ namespace sqlite_orm { }; template - struct ast_iterator, void> { - using node_type = conditions::is_null_t; + struct ast_iterator, void> { + using node_type = is_null_t; template void operator()(const node_type &i, const L &l) const { @@ -7692,8 +7691,8 @@ namespace sqlite_orm { }; template - struct ast_iterator, void> { - using node_type = conditions::is_not_null_t; + struct ast_iterator, void> { + using node_type = is_not_null_t; template void operator()(const node_type &i, const L &l) const { @@ -7712,8 +7711,8 @@ namespace sqlite_orm { }; template - struct ast_iterator, void> { - using node_type = conditions::left_join_t; + struct ast_iterator, void> { + using node_type = left_join_t; template void operator()(const node_type &j, const L &l) const { @@ -7722,8 +7721,8 @@ namespace sqlite_orm { }; template - struct ast_iterator, void> { - using node_type = conditions::on_t; + struct ast_iterator, void> { + using node_type = on_t; template void operator()(const node_type &o, const L &l) const { @@ -7732,8 +7731,8 @@ namespace sqlite_orm { }; template - struct ast_iterator, void> { - using node_type = conditions::join_t; + struct ast_iterator, void> { + using node_type = join_t; template void operator()(const node_type &j, const L &l) const { @@ -7742,8 +7741,8 @@ namespace sqlite_orm { }; template - struct ast_iterator, void> { - using node_type = conditions::left_outer_join_t; + struct ast_iterator, void> { + using node_type = left_outer_join_t; template void operator()(const node_type &j, const L &l) const { @@ -7752,8 +7751,8 @@ namespace sqlite_orm { }; template - struct ast_iterator, void> { - using node_type = conditions::inner_join_t; + struct ast_iterator, void> { + using node_type = inner_join_t; template void operator()(const node_type &j, const L &l) const { @@ -7791,8 +7790,8 @@ namespace sqlite_orm { }; template - struct ast_iterator, void> { - using node_type = conditions::limit_t; + struct ast_iterator, void> { + using node_type = limit_t; template void operator()(const node_type &a, const L &l) const { @@ -7801,8 +7800,8 @@ namespace sqlite_orm { }; template - struct ast_iterator, void> { - using node_type = conditions::limit_t; + struct ast_iterator, void> { + using node_type = limit_t; template void operator()(const node_type &a, const L &l) const { @@ -7814,8 +7813,8 @@ namespace sqlite_orm { }; template - struct ast_iterator, void> { - using node_type = conditions::limit_t; + struct ast_iterator, void> { + using node_type = limit_t; template void operator()(const node_type &a, const L &l) const { @@ -8837,7 +8836,7 @@ namespace sqlite_orm { } template - std::string process_order_by(const conditions::dynamic_order_by_t &orderBy) const { + std::string process_order_by(const dynamic_order_by_t &orderBy) const { std::vector expressions; for(auto &entry: orderBy) { std::string entryString; @@ -9274,9 +9273,8 @@ namespace sqlite_orm { }; template - struct statement_serializator< - T, - typename std::enable_if::value>::type> { + struct statement_serializator::value>::type> { using statement_type = T; template @@ -9424,7 +9422,7 @@ namespace sqlite_orm { friend struct view_t; template - friend struct conditions::dynamic_order_by_t; + friend struct dynamic_order_by_t; template friend struct iterator_t; @@ -10196,7 +10194,7 @@ namespace sqlite_orm { } template - std::string string_from_expression(const conditions::cast_t &c, bool noTableName) const { + std::string string_from_expression(const cast_t &c, bool noTableName) const { std::stringstream ss; ss << static_cast(c) << " ("; ss << this->string_from_expression(c.expression, noTableName) << " AS " << type_printer().print() @@ -10234,14 +10232,14 @@ namespace sqlite_orm { } template - std::string string_from_expression(const conditions::is_null_t &c, bool noTableName) const { + std::string string_from_expression(const is_null_t &c, bool noTableName) const { std::stringstream ss; ss << this->string_from_expression(c.t, noTableName) << " " << static_cast(c) << " "; return ss.str(); } template - std::string string_from_expression(const conditions::is_not_null_t &c, bool noTableName) const { + std::string string_from_expression(const is_not_null_t &c, bool noTableName) const { std::stringstream ss; ss << this->string_from_expression(c.t, noTableName) << " " << static_cast(c) << " "; return ss.str(); @@ -10257,7 +10255,7 @@ namespace sqlite_orm { } template - std::string string_from_expression(const conditions::negated_condition_t &c, bool noTableName) const { + std::string string_from_expression(const negated_condition_t &c, bool noTableName) const { std::stringstream ss; ss << static_cast(c) << " "; auto cString = this->string_from_expression(c.c, noTableName); @@ -10266,7 +10264,7 @@ namespace sqlite_orm { } template - std::string string_from_expression(const conditions::is_equal_t &c, bool noTableName) const { + std::string string_from_expression(const is_equal_t &c, bool noTableName) const { auto leftString = this->string_from_expression(c.l, noTableName); auto rightString = this->string_from_expression(c.r, noTableName); std::stringstream ss; @@ -10275,7 +10273,7 @@ namespace sqlite_orm { } template - typename std::enable_if::value, std::string>::type + typename std::enable_if::value, std::string>::type string_from_expression(const C &c, bool noTableName) const { auto leftString = this->string_from_expression(c.l, noTableName); auto rightString = this->string_from_expression(c.r, noTableName); @@ -10285,19 +10283,19 @@ namespace sqlite_orm { } template - std::string string_from_expression(const conditions::named_collate &col, bool noTableName) const { + std::string string_from_expression(const named_collate &col, bool noTableName) const { auto res = this->string_from_expression(col.expr, noTableName); return res + " " + static_cast(col); } template - std::string string_from_expression(const conditions::collate_t &col, bool noTableName) const { + std::string string_from_expression(const collate_t &col, bool noTableName) const { auto res = this->string_from_expression(col.expr, noTableName); return res + " " + static_cast(col); } template - std::string string_from_expression(const conditions::in_t &inCondition, bool noTableName) const { + std::string string_from_expression(const in_t &inCondition, bool noTableName) const { std::stringstream ss; auto leftString = this->string_from_expression(inCondition.l, noTableName); ss << leftString << " " << static_cast(inCondition) << " "; @@ -10306,8 +10304,7 @@ namespace sqlite_orm { } template - std::string string_from_expression(const conditions::in_t> &inCondition, - bool noTableName) const { + std::string string_from_expression(const in_t> &inCondition, bool noTableName) const { std::stringstream ss; auto leftString = this->string_from_expression(inCondition.l, noTableName); ss << leftString << " " << static_cast(inCondition) << " ( "; @@ -10323,7 +10320,7 @@ namespace sqlite_orm { } template - std::string string_from_expression(const conditions::like_t &l, bool noTableName) const { + std::string string_from_expression(const like_t &l, bool noTableName) const { std::stringstream ss; ss << this->string_from_expression(l.arg, noTableName) << " "; ss << static_cast(l) << " "; @@ -10335,7 +10332,7 @@ namespace sqlite_orm { } template - std::string string_from_expression(const conditions::glob_t &l, bool noTableName) const { + std::string string_from_expression(const glob_t &l, bool noTableName) const { std::stringstream ss; ss << this->string_from_expression(l.arg, noTableName) << " "; ss << static_cast(l) << " "; @@ -10344,7 +10341,7 @@ namespace sqlite_orm { } template - std::string string_from_expression(const conditions::between_t &bw, bool noTableName) const { + std::string string_from_expression(const between_t &bw, bool noTableName) const { std::stringstream ss; auto expr = this->string_from_expression(bw.expr, noTableName); ss << expr << " " << static_cast(bw) << " "; @@ -10355,7 +10352,7 @@ namespace sqlite_orm { } template - std::string string_from_expression(const conditions::exists_t &e, bool noTableName) const { + std::string string_from_expression(const exists_t &e, bool noTableName) const { std::stringstream ss; ss << static_cast(e) << " "; ss << this->string_from_expression(e.t, noTableName); @@ -10363,7 +10360,7 @@ namespace sqlite_orm { } template - std::string process_order_by(const conditions::order_by_t &orderBy) const { + std::string process_order_by(const order_by_t &orderBy) const { std::stringstream ss; auto columnName = this->string_from_expression(orderBy.o, false); ss << columnName << " "; @@ -10382,12 +10379,12 @@ namespace sqlite_orm { } template - void process_join_constraint(std::stringstream &ss, const conditions::on_t &t) const { + void process_join_constraint(std::stringstream &ss, const on_t &t) const { ss << static_cast(t) << " " << this->string_from_expression(t.arg, false); } template - void process_join_constraint(std::stringstream &ss, const conditions::using_t &u) const { + void process_join_constraint(std::stringstream &ss, const using_t &u) const { ss << static_cast(u) << " (" << this->string_from_expression(u.column, true) << " )"; } @@ -10396,7 +10393,7 @@ namespace sqlite_orm { * OI - offset is implicit */ template - std::string string_from_expression(const conditions::limit_t &limt, bool) const { + std::string string_from_expression(const limit_t &limt, bool) const { std::stringstream ss; ss << static_cast(limt) << " "; if(HO) { @@ -10419,7 +10416,7 @@ namespace sqlite_orm { } template - std::string string_from_expression(const conditions::cross_join_t &c, bool) const { + std::string string_from_expression(const cross_join_t &c, bool) const { std::stringstream ss; ss << static_cast(c) << " "; ss << " '" << this->impl.find_table_name(typeid(O)) << "'"; @@ -10427,7 +10424,7 @@ namespace sqlite_orm { } template - std::string string_from_expression(const conditions::natural_join_t &c, bool) const { + std::string string_from_expression(const natural_join_t &c, bool) const { std::stringstream ss; ss << static_cast(c) << " "; ss << " '" << this->impl.find_table_name(typeid(O)) << "'"; @@ -10435,7 +10432,7 @@ namespace sqlite_orm { } template - std::string string_from_expression(const conditions::inner_join_t &l, bool) const { + std::string string_from_expression(const inner_join_t &l, bool) const { std::stringstream ss; ss << static_cast(l) << " "; auto aliasString = alias_extractor::get(); @@ -10448,7 +10445,7 @@ namespace sqlite_orm { } template - std::string string_from_expression(const conditions::left_outer_join_t &l, bool) const { + std::string string_from_expression(const left_outer_join_t &l, bool) const { std::stringstream ss; ss << static_cast(l) << " "; ss << " '" << this->impl.find_table_name(typeid(T)) << "' "; @@ -10457,7 +10454,7 @@ namespace sqlite_orm { } template - std::string string_from_expression(const conditions::left_join_t &l, bool) const { + std::string string_from_expression(const left_join_t &l, bool) const { std::stringstream ss; ss << static_cast(l) << " "; ss << " '" << this->impl.find_table_name(typeid(T)) << "' "; @@ -10466,7 +10463,7 @@ namespace sqlite_orm { } template - std::string string_from_expression(const conditions::join_t &l, bool) const { + std::string string_from_expression(const join_t &l, bool) const { std::stringstream ss; ss << static_cast(l) << " "; ss << " '" << this->impl.find_table_name(typeid(T)) << "' "; @@ -10475,7 +10472,7 @@ namespace sqlite_orm { } template - std::string string_from_expression(const conditions::where_t &w, bool) const { + std::string string_from_expression(const where_t &w, bool) const { std::stringstream ss; ss << static_cast(w) << " "; auto whereString = this->string_from_expression(w.c, false); @@ -10484,7 +10481,7 @@ namespace sqlite_orm { } template - std::string string_from_expression(const conditions::order_by_t &orderBy, bool) const { + std::string string_from_expression(const order_by_t &orderBy, bool) const { std::stringstream ss; ss << static_cast(orderBy) << " "; auto orderByString = this->process_order_by(orderBy); @@ -10493,7 +10490,7 @@ namespace sqlite_orm { } template - std::string string_from_expression(const conditions::multi_order_by_t &orderBy, bool) const { + std::string string_from_expression(const multi_order_by_t &orderBy, bool) const { std::stringstream ss; std::vector expressions; iterate_tuple(orderBy.args, [&expressions, this](auto &v) { @@ -10512,14 +10509,14 @@ namespace sqlite_orm { } template - std::string string_from_expression(const conditions::dynamic_order_by_t &orderBy, bool) const { + std::string string_from_expression(const dynamic_order_by_t &orderBy, bool) const { std::stringstream ss; ss << this->storage_base::process_order_by(orderBy) << " "; return ss.str(); } template - std::string string_from_expression(const conditions::group_by_t &groupBy, bool) const { + std::string string_from_expression(const group_by_t &groupBy, bool) const { std::stringstream ss; std::vector expressions; iterate_tuple(groupBy.args, [&expressions, this](auto &v) { @@ -10538,7 +10535,7 @@ namespace sqlite_orm { } template - std::string string_from_expression(const conditions::having_t &hav, bool) const { + std::string string_from_expression(const having_t &hav, bool) const { std::stringstream ss; ss << static_cast(hav) << " "; ss << this->string_from_expression(hav.t, false) << " "; @@ -12045,14 +12042,13 @@ __pragma(pop_macro("min")) }; template - struct node_tuple, void> { - using node_type = conditions::where_t; + struct node_tuple, void> { + using node_type = where_t; using type = typename node_tuple::type; }; template - struct node_tuple::value>::type> { + struct node_tuple::value>::type> { using node_type = T; using left_type = typename node_type::left_type; using right_type = typename node_type::right_type; @@ -12078,8 +12074,8 @@ __pragma(pop_macro("min")) }; template - struct node_tuple, void> { - using node_type = conditions::in_t; + struct node_tuple, void> { + using node_type = in_t; using left_tuple = typename node_tuple::type; using right_tuple = typename node_tuple::type; using type = typename conc_tuple::type; @@ -12138,20 +12134,20 @@ __pragma(pop_macro("min")) }; template - struct node_tuple, void> { - using node_type = conditions::having_t; + struct node_tuple, void> { + using node_type = having_t; using type = typename node_tuple::type; }; template - struct node_tuple, void> { - using node_type = conditions::cast_t; + struct node_tuple, void> { + using node_type = cast_t; using type = typename node_tuple::type; }; template - struct node_tuple, void> { - using node_type = conditions::exists_t; + struct node_tuple, void> { + using node_type = exists_t; using type = typename node_tuple::type; }; @@ -12168,8 +12164,8 @@ __pragma(pop_macro("min")) }; template - struct node_tuple, void> { - using node_type = conditions::like_t; + struct node_tuple, void> { + using node_type = like_t; using arg_tuple = typename node_tuple::type; using pattern_tuple = typename node_tuple::type; using escape_tuple = typename node_tuple::type; @@ -12177,16 +12173,16 @@ __pragma(pop_macro("min")) }; template - struct node_tuple, void> { - using node_type = conditions::glob_t; + struct node_tuple, void> { + using node_type = glob_t; using arg_tuple = typename node_tuple::type; using pattern_tuple = typename node_tuple::type; using type = typename conc_tuple::type; }; template - struct node_tuple, void> { - using node_type = conditions::between_t; + struct node_tuple, void> { + using node_type = between_t; using expression_tuple = typename node_tuple::type; using lower_tuple = typename node_tuple::type; using upper_tuple = typename node_tuple::type; @@ -12194,26 +12190,26 @@ __pragma(pop_macro("min")) }; template - struct node_tuple, void> { - using node_type = conditions::named_collate; + struct node_tuple, void> { + using node_type = named_collate; using type = typename node_tuple::type; }; template - struct node_tuple, void> { - using node_type = conditions::is_null_t; + struct node_tuple, void> { + using node_type = is_null_t; using type = typename node_tuple::type; }; template - struct node_tuple, void> { - using node_type = conditions::is_not_null_t; + struct node_tuple, void> { + using node_type = is_not_null_t; using type = typename node_tuple::type; }; template - struct node_tuple, void> { - using node_type = conditions::negated_condition_t; + struct node_tuple, void> { + using node_type = negated_condition_t; using type = typename node_tuple::type; }; @@ -12224,32 +12220,32 @@ __pragma(pop_macro("min")) }; template - struct node_tuple, void> { - using node_type = conditions::left_join_t; + struct node_tuple, void> { + using node_type = left_join_t; using type = typename node_tuple::type; }; template - struct node_tuple, void> { - using node_type = conditions::on_t; + struct node_tuple, void> { + using node_type = on_t; using type = typename node_tuple::type; }; template - struct node_tuple, void> { - using node_type = conditions::join_t; + struct node_tuple, void> { + using node_type = join_t; using type = typename node_tuple::type; }; template - struct node_tuple, void> { - using node_type = conditions::left_outer_join_t; + struct node_tuple, void> { + using node_type = left_outer_join_t; using type = typename node_tuple::type; }; template - struct node_tuple, void> { - using node_type = conditions::inner_join_t; + struct node_tuple, void> { + using node_type = inner_join_t; using type = typename node_tuple::type; }; @@ -12277,20 +12273,20 @@ __pragma(pop_macro("min")) }; template - struct node_tuple, void> { - using node_type = conditions::limit_t; + struct node_tuple, void> { + using node_type = limit_t; using type = typename node_tuple::type; }; template - struct node_tuple, void> { - using node_type = conditions::limit_t; + struct node_tuple, void> { + using node_type = limit_t; using type = typename conc_tuple::type, typename node_tuple::type>::type; }; template - struct node_tuple, void> { - using node_type = conditions::limit_t; + struct node_tuple, void> { + using node_type = limit_t; using type = typename conc_tuple::type, typename node_tuple::type>::type; }; } diff --git a/tests/static_tests/count_tuple.cpp b/tests/static_tests/count_tuple.cpp index e61d5d690..046f80bdd 100644 --- a/tests/static_tests/count_tuple.cpp +++ b/tests/static_tests/count_tuple.cpp @@ -13,44 +13,44 @@ TEST_CASE("count_tuple") { { auto t = std::make_tuple(where(is_equal(&User::id, 5)), limit(5), order_by(&User::name)); using T = decltype(t); - static_assert(count_tuple::value == 1, ""); - static_assert(count_tuple::value == 0, ""); - static_assert(count_tuple::value == 1, ""); - static_assert(count_tuple::value == 1, ""); + static_assert(count_tuple::value == 1, ""); + static_assert(count_tuple::value == 0, ""); + static_assert(count_tuple::value == 1, ""); + static_assert(count_tuple::value == 1, ""); } { auto t = std::make_tuple(where(lesser_than(&User::id, 10)), where(greater_than(&User::id, 5)), group_by(&User::name)); using T = decltype(t); - static_assert(count_tuple::value == 2, ""); - static_assert(count_tuple::value == 1, ""); - static_assert(count_tuple::value == 0, ""); - static_assert(count_tuple::value == 0, ""); + static_assert(count_tuple::value == 2, ""); + static_assert(count_tuple::value == 1, ""); + static_assert(count_tuple::value == 0, ""); + static_assert(count_tuple::value == 0, ""); } { auto t = std::make_tuple(group_by(&User::name), limit(10, offset(5))); using T = decltype(t); - static_assert(count_tuple::value == 0, ""); - static_assert(count_tuple::value == 1, ""); - static_assert(count_tuple::value == 0, ""); - static_assert(count_tuple::value == 1, ""); + static_assert(count_tuple::value == 0, ""); + static_assert(count_tuple::value == 1, ""); + static_assert(count_tuple::value == 0, ""); + static_assert(count_tuple::value == 1, ""); } { auto t = std::make_tuple(where(is_null(&User::name)), order_by(&User::id), multi_order_by(order_by(&User::name))); using T = decltype(t); - static_assert(count_tuple::value == 1, ""); - static_assert(count_tuple::value == 0, ""); - static_assert(count_tuple::value == 2, ""); - static_assert(count_tuple::value == 0, ""); + static_assert(count_tuple::value == 1, ""); + static_assert(count_tuple::value == 0, ""); + static_assert(count_tuple::value == 2, ""); + static_assert(count_tuple::value == 0, ""); } { auto t = std::make_tuple(dynamic_order_by(make_storage(""))); using T = decltype(t); - static_assert(count_tuple::value == 0, ""); - static_assert(count_tuple::value == 0, ""); - static_assert(count_tuple::value == 1, ""); - static_assert(count_tuple::value == 0, ""); + static_assert(count_tuple::value == 0, ""); + static_assert(count_tuple::value == 0, ""); + static_assert(count_tuple::value == 1, ""); + static_assert(count_tuple::value == 0, ""); } } diff --git a/tests/static_tests/node_tuple.cpp b/tests/static_tests/node_tuple.cpp index abc4e53c3..affa81259 100644 --- a/tests/static_tests/node_tuple.cpp +++ b/tests/static_tests/node_tuple.cpp @@ -41,7 +41,7 @@ TEST_CASE("Node tuple") { } { // binary_condition - using namespace conditions; + using namespace internal; { // 5 < 6.0f auto c = lesser_than(5, 6.0f); using C = decltype(c); From 2f36dd912aac6932848b2a0b4458881ff1758e03 Mon Sep 17 00:00:00 2001 From: fnc12 Date: Thu, 26 Mar 2020 21:39:06 +0300 Subject: [PATCH 053/132] removed a comment --- dev/conditions.h | 4 +--- include/sqlite_orm/sqlite_orm.h | 4 +--- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/dev/conditions.h b/dev/conditions.h index 94977e10c..eca25f0d1 100644 --- a/dev/conditions.h +++ b/dev/conditions.h @@ -509,9 +509,7 @@ namespace sqlite_orm { using const_iterator = typename std::vector::const_iterator; template - dynamic_order_by_t(const S &storage_) : context(storage_.impl) { - // this->context.skip_table_name = true; - } + dynamic_order_by_t(const S &storage_) : context(storage_.impl) {} template void push_back(order_by_t order_by) { diff --git a/include/sqlite_orm/sqlite_orm.h b/include/sqlite_orm/sqlite_orm.h index 5c7cb682e..8002a0cec 100644 --- a/include/sqlite_orm/sqlite_orm.h +++ b/include/sqlite_orm/sqlite_orm.h @@ -2404,9 +2404,7 @@ namespace sqlite_orm { using const_iterator = typename std::vector::const_iterator; template - dynamic_order_by_t(const S &storage_) : context(storage_.impl) { - // this->context.skip_table_name = true; - } + dynamic_order_by_t(const S &storage_) : context(storage_.impl) {} template void push_back(order_by_t order_by) { From 44ab697676b9dfc1bec7753a3990c7a048920508 Mon Sep 17 00:00:00 2001 From: Yevgeniy Zakharov Date: Sun, 12 Apr 2020 22:12:06 +0300 Subject: [PATCH 054/132] Update TODO.md --- TODO.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/TODO.md b/TODO.md index 511c79bcf..000dbc2d7 100644 --- a/TODO.md +++ b/TODO.md @@ -2,7 +2,7 @@ `sqlite_orm` is a wonderful library but there are still features that are not implemented. Here you can find a list of them: -* `FOREIGN KEY` - sync_schema fk comparison and ability of two tables to have fk to each other +* `FOREIGN KEY` - sync_schema fk comparison and ability of two tables to have fk to each other (`PRAGMA foreign_key_list(%table_name%);` may be useful) * rest of core functions(https://sqlite.org/lang_corefunc.html) * `ATTACH` * blob incremental I/O https://sqlite.org/c3ref/blob_open.html From 55e64c2a22a008621c8e088b08eea6254dd0a059 Mon Sep 17 00:00:00 2001 From: Yevgeniy Zakharov Date: Tue, 14 Apr 2020 19:07:11 +0300 Subject: [PATCH 055/132] Update TODO.md --- TODO.md | 1 + 1 file changed, 1 insertion(+) diff --git a/TODO.md b/TODO.md index 000dbc2d7..df39bf71c 100644 --- a/TODO.md +++ b/TODO.md @@ -16,5 +16,6 @@ * `SAVEPOINT` https://www.sqlite.org/lang_savepoint.html * add `static_assert` in crud `get*` functions in case user passes `where_t` instead of id to make compilation error more clear (example https://github.com/fnc12/sqlite_orm/issues/485) * generated columns https://www.sqlite.org/gencol.html +* named constraints: constraint can have name `CREATE TABLE heroes(id INTEGER CONSTRAINT pk PRIMARY KEY)` Please feel free to add any feature that isn't listed here and not implemented yet. From bc1f6a279ebfbb2d6e81d034377d4a1fae052c7c Mon Sep 17 00:00:00 2001 From: fnc12 Date: Sun, 26 Apr 2020 20:36:16 +0300 Subject: [PATCH 056/132] added use_parentheses field --- dev/column_names_getter.h | 134 +-- dev/conditions.h | 7 +- dev/order_by_serializator.h | 126 +-- dev/serializator_context.h | 29 +- dev/statement_serializator.h | 626 +++++------ dev/storage.h | 20 +- include/sqlite_orm/sqlite_orm.h | 1014 +++++++++--------- tests/statement_serializator_tests/check.cpp | 32 +- 8 files changed, 985 insertions(+), 1003 deletions(-) diff --git a/dev/column_names_getter.h b/dev/column_names_getter.h index 587c83bec..72f4f4f76 100644 --- a/dev/column_names_getter.h +++ b/dev/column_names_getter.h @@ -1,84 +1,84 @@ #pragma once -#include // std::string -#include // std::vector -#include // std::reference_wrapper +#include // std::string +#include // std::vector +#include // std::reference_wrapper #include "error_code.h" #include "select_constraints.h" namespace sqlite_orm { -namespace internal { + namespace internal { -template -std::string serialize(const T &t, const C &context); + template + std::string serialize(const T &t, const C &context); -template -struct column_names_getter { - using expression_type = T; - - template - std::vector operator()(const expression_type &t, const C &context) { - auto newContext = context; - newContext.skip_table_name = false; - auto columnName = serialize(t, newContext); - if(columnName.length()) { - return {move(columnName)}; - } else { - throw std::system_error(std::make_error_code(orm_error_code::column_not_found)); + template + struct column_names_getter { + using expression_type = T; + + template + std::vector operator()(const expression_type &t, const C &context) { + auto newContext = context; + newContext.skip_table_name = false; + auto columnName = serialize(t, newContext); + if(columnName.length()) { + return {move(columnName)}; + } else { + throw std::system_error(std::make_error_code(orm_error_code::column_not_found)); + } + } + }; + + template + std::vector get_column_names(const T &t, const C &context) { + column_names_getter serializator; + return serializator(t, context); } - } -}; - template - std::vector get_column_names(const T &t, const C &context) { - column_names_getter serializator; - return serializator(t, context); - } + template + struct column_names_getter, void> { + using expression_type = std::reference_wrapper; -template -struct column_names_getter, void> { - using expression_type = std::reference_wrapper; - - template - std::vector operator()(const expression_type &expression, const C &context) { - return get_column_names(expression.get(), context); - } -}; -template -struct column_names_getter, void> { - using expression_type = asterisk_t; - - template - std::vector operator()(const expression_type &, const C &) { - std::vector res; - res.push_back("*"); - return res; - } -}; + template + std::vector operator()(const expression_type &expression, const C &context) { + return get_column_names(expression.get(), context); + } + }; + template + struct column_names_getter, void> { + using expression_type = asterisk_t; -template -struct column_names_getter, void> { - using expression_type = columns_t; - - template - std::vector operator()(const expression_type &cols, const C &context) { - std::vector columnNames; - columnNames.reserve(static_cast(cols.count)); - auto newContext = context; - newContext.skip_table_name = false; - iterate_tuple(cols.columns, [&columnNames, &newContext](auto &m) { - auto columnName = serialize(m, newContext); - if(columnName.length()) { - columnNames.push_back(columnName); - } else { - throw std::system_error(std::make_error_code(orm_error_code::column_not_found)); + template + std::vector operator()(const expression_type &, const C &) { + std::vector res; + res.push_back("*"); + return res; } - }); - return columnNames; - } -}; + }; -} + template + struct column_names_getter, void> { + using expression_type = columns_t; + + template + std::vector operator()(const expression_type &cols, const C &context) { + std::vector columnNames; + columnNames.reserve(static_cast(cols.count)); + auto newContext = context; + newContext.skip_table_name = false; + iterate_tuple(cols.columns, [&columnNames, &newContext](auto &m) { + auto columnName = serialize(m, newContext); + if(columnName.length()) { + columnNames.push_back(columnName); + } else { + throw std::system_error(std::make_error_code(orm_error_code::column_not_found)); + } + }); + return columnNames; + } + }; + + } } diff --git a/dev/conditions.h b/dev/conditions.h index b4d74947e..4a4fcf6a4 100644 --- a/dev/conditions.h +++ b/dev/conditions.h @@ -506,9 +506,9 @@ namespace sqlite_orm { using context_t = C; using entry_t = dynamic_order_by_entry_t; using const_iterator = typename std::vector::const_iterator; - + dynamic_order_by_t(const context_t &context_) : context(context_) {} - + template void push_back(order_by_t order_by) { auto newContext = this->context; @@ -1222,7 +1222,8 @@ namespace sqlite_orm { * } */ template - internal::dynamic_order_by_t> dynamic_order_by(const S &storage) { + internal::dynamic_order_by_t> + dynamic_order_by(const S &storage) { internal::serializator_context_builder builder(storage); return builder(); /*using context_t = internal::serializator_context; diff --git a/dev/order_by_serializator.h b/dev/order_by_serializator.h index b61c2836d..082b61647 100644 --- a/dev/order_by_serializator.h +++ b/dev/order_by_serializator.h @@ -1,64 +1,37 @@ #pragma once -#include // std::string -#include // std::vector +#include // std::string +#include // std::vector #include // std::stringstream namespace sqlite_orm { -namespace internal { + namespace internal { -template -struct order_by_serializator; + template + struct order_by_serializator; -template -std::string serialize_order_by(const T &t, const C &context) { - order_by_serializator serializator; - return serializator(t, context); -} - -template -struct order_by_serializator, void> { - using statement_type = order_by_t; - - template - std::string operator()(const statement_type &orderBy, const C &context) const { - std::stringstream ss; - auto newContext = context; - newContext.skip_table_name = false; - auto columnName = serialize(orderBy.o, newContext); - ss << columnName << " "; - if(orderBy._collate_argument.length()) { - ss << "COLLATE " << orderBy._collate_argument << " "; + template + std::string serialize_order_by(const T &t, const C &context) { + order_by_serializator serializator; + return serializator(t, context); } - switch(orderBy.asc_desc) { - case 1: - ss << "ASC"; - break; - case -1: - ss << "DESC"; - break; - } - return ss.str(); - } -}; -template -struct order_by_serializator, void> { - using statement_type = dynamic_order_by_t; - - template - std::string operator()(const statement_type &orderBy, const C &) const { - std::vector expressions; - for(auto &entry: orderBy) { - std::string entryString; - { + template + struct order_by_serializator, void> { + using statement_type = order_by_t; + + template + std::string operator()(const statement_type &orderBy, const C &context) const { std::stringstream ss; - ss << entry.name << " "; - if(!entry._collate_argument.empty()) { - ss << "COLLATE " << entry._collate_argument << " "; + auto newContext = context; + newContext.skip_table_name = false; + auto columnName = serialize(orderBy.o, newContext); + ss << columnName << " "; + if(orderBy._collate_argument.length()) { + ss << "COLLATE " << orderBy._collate_argument << " "; } - switch(entry.asc_desc) { + switch(orderBy.asc_desc) { case 1: ss << "ASC"; break; @@ -66,22 +39,49 @@ struct order_by_serializator, void> { ss << "DESC"; break; } - entryString = ss.str(); + return ss.str(); } - expressions.push_back(move(entryString)); }; - std::stringstream ss; - ss << static_cast(orderBy) << " "; - for(size_t i = 0; i < expressions.size(); ++i) { - ss << expressions[i]; - if(i < expressions.size() - 1) { - ss << ", "; + + template + struct order_by_serializator, void> { + using statement_type = dynamic_order_by_t; + + template + std::string operator()(const statement_type &orderBy, const C &) const { + std::vector expressions; + for(auto &entry: orderBy) { + std::string entryString; + { + std::stringstream ss; + ss << entry.name << " "; + if(!entry._collate_argument.empty()) { + ss << "COLLATE " << entry._collate_argument << " "; + } + switch(entry.asc_desc) { + case 1: + ss << "ASC"; + break; + case -1: + ss << "DESC"; + break; + } + entryString = ss.str(); + } + expressions.push_back(move(entryString)); + }; + std::stringstream ss; + ss << static_cast(orderBy) << " "; + for(size_t i = 0; i < expressions.size(); ++i) { + ss << expressions[i]; + if(i < expressions.size() - 1) { + ss << ", "; + } + } + ss << " "; + return ss.str(); } - } - ss << " "; - return ss.str(); - } -}; + }; -} + } } diff --git a/dev/serializator_context.h b/dev/serializator_context.h index b5bfeb274..e568eed75 100644 --- a/dev/serializator_context.h +++ b/dev/serializator_context.h @@ -7,6 +7,7 @@ namespace sqlite_orm { struct serializator_context_base { bool replace_bindable_with_question = false; bool skip_table_name = true; + bool use_parentheses = true; template std::string column_name(F O::*) const { @@ -27,20 +28,20 @@ namespace sqlite_orm { return this->impl.column_name(m); } }; - - template - struct serializator_context_builder { - using storage_type = S; - using impl_type = typename storage_type::impl_type; - - serializator_context_builder(const storage_type &storage_) : storage(storage_) {} - - serializator_context operator()() const { - return {this->storage.impl}; - } - - const storage_type &storage; - }; + + template + struct serializator_context_builder { + using storage_type = S; + using impl_type = typename storage_type::impl_type; + + serializator_context_builder(const storage_type &storage_) : storage(storage_) {} + + serializator_context operator()() const { + return {this->storage.impl}; + } + + const storage_type &storage; + }; } diff --git a/dev/statement_serializator.h b/dev/statement_serializator.h index 6e06183b7..2a4fb3d34 100644 --- a/dev/statement_serializator.h +++ b/dev/statement_serializator.h @@ -28,8 +28,8 @@ namespace sqlite_orm { statement_serializator serializator; return serializator(t, context); } - - /*template + + /*template struct statement_serializator::value>::type> { using statement_type = T; @@ -44,20 +44,20 @@ namespace sqlite_orm { } } };*/ - - template - struct statement_serializator::value>::type> { - using statement_type = T; - - template - std::string operator()(const statement_type &statement, const C &context) { - if(context.replace_bindable_with_question){ - return "?"; - }else{ - return field_printer{}(statement); + + template + struct statement_serializator::value>::type> { + using statement_type = T; + + template + std::string operator()(const statement_type &statement, const C &context) { + if(context.replace_bindable_with_question) { + return "?"; + } else { + return field_printer{}(statement); + } } - } - }; + }; template struct statement_serializator, void> { @@ -351,9 +351,8 @@ namespace sqlite_orm { }; template - struct statement_serializator< - T, - typename std::enable_if::value>::type> { + struct statement_serializator::value>::type> { using statement_type = T; template @@ -442,9 +441,8 @@ namespace sqlite_orm { }; template - struct statement_serializator< - T, - typename std::enable_if::value>::type> { + struct statement_serializator::value>::type> { using statement_type = T; template @@ -452,7 +450,13 @@ namespace sqlite_orm { auto leftString = serialize(c.l, context); auto rightString = serialize(c.r, context); std::stringstream ss; - ss << "(" << leftString << " " << static_cast(c) << " " << rightString << ")"; + if(context.use_parentheses) { + ss << "("; + } + ss << leftString << " " << static_cast(c) << " " << rightString; + if(context.use_parentheses) { + ss << ")"; + } return ss.str(); } }; @@ -463,7 +467,9 @@ namespace sqlite_orm { template std::string operator()(const statement_type &c, const C &context) const { - auto res = serialize(c.expr, context); + auto newContext = context; + newContext.use_parentheses = false; + auto res = serialize(c.expr, newContext); return res + " " + static_cast(c); } }; @@ -474,7 +480,9 @@ namespace sqlite_orm { template std::string operator()(const statement_type &c, const C &context) const { - auto res = serialize(c.expr, context); + auto newContext = context; + newContext.use_parentheses = false; + auto res = serialize(c.expr, newContext); return res + " " + static_cast(c); } }; @@ -747,310 +755,310 @@ namespace sqlite_orm { return ss.str(); } }; - - template - struct statement_serializator, void> { - using statement_type = select_t; - - template - std::string operator()(const statement_type &sel, const C &context) const { - std::stringstream ss; - if(!is_base_of_template::value) { - if(!sel.highest_level) { - ss << "( "; + + template + struct statement_serializator, void> { + using statement_type = select_t; + + template + std::string operator()(const statement_type &sel, const C &context) const { + std::stringstream ss; + if(!is_base_of_template::value) { + if(!sel.highest_level) { + ss << "( "; + } + ss << "SELECT "; } - ss << "SELECT "; - } - if(get_distinct(sel.col)) { - ss << static_cast(distinct(0)) << " "; - } - auto columnNames = get_column_names(sel.col, context); - for(size_t i = 0; i < columnNames.size(); ++i) { - ss << columnNames[i]; - if(i < columnNames.size() - 1) { - ss << ","; + if(get_distinct(sel.col)) { + ss << static_cast(distinct(0)) << " "; } - ss << " "; - } - table_name_collector collector{[&context](std::type_index ti) { - return context.impl.find_table_name(ti); - }}; - iterate_ast(sel.col, collector); - iterate_ast(sel.conditions, collector); - internal::join_iterator()([&collector, &context](const auto &c) { - using original_join_type = typename std::decay::type::join_type::type; - using cross_join_type = typename internal::mapped_type_proxy::type; - auto crossJoinedTableName = context.impl.find_table_name(typeid(cross_join_type)); - auto tableAliasString = alias_extractor::get(); - std::pair tableNameWithAlias(std::move(crossJoinedTableName), - std::move(tableAliasString)); - collector.table_names.erase(tableNameWithAlias); - }); - if(!collector.table_names.empty()) { - ss << "FROM "; - std::vector> tableNames(collector.table_names.begin(), - collector.table_names.end()); - for(size_t i = 0; i < tableNames.size(); ++i) { - auto &tableNamePair = tableNames[i]; - ss << "'" << tableNamePair.first << "' "; - if(!tableNamePair.second.empty()) { - ss << tableNamePair.second << " "; - } - if(int(i) < int(tableNames.size()) - 1) { + auto columnNames = get_column_names(sel.col, context); + for(size_t i = 0; i < columnNames.size(); ++i) { + ss << columnNames[i]; + if(i < columnNames.size() - 1) { ss << ","; } ss << " "; } - } - iterate_tuple(sel.conditions, [&context, &ss](auto &v) { - ss << serialize(v, context); - }); - if(!is_base_of_template::value) { - if(!sel.highest_level) { - ss << ") "; + table_name_collector collector{[&context](std::type_index ti) { + return context.impl.find_table_name(ti); + }}; + iterate_ast(sel.col, collector); + iterate_ast(sel.conditions, collector); + internal::join_iterator()([&collector, &context](const auto &c) { + using original_join_type = typename std::decay::type::join_type::type; + using cross_join_type = typename internal::mapped_type_proxy::type; + auto crossJoinedTableName = context.impl.find_table_name(typeid(cross_join_type)); + auto tableAliasString = alias_extractor::get(); + std::pair tableNameWithAlias(std::move(crossJoinedTableName), + std::move(tableAliasString)); + collector.table_names.erase(tableNameWithAlias); + }); + if(!collector.table_names.empty()) { + ss << "FROM "; + std::vector> tableNames(collector.table_names.begin(), + collector.table_names.end()); + for(size_t i = 0; i < tableNames.size(); ++i) { + auto &tableNamePair = tableNames[i]; + ss << "'" << tableNamePair.first << "' "; + if(!tableNamePair.second.empty()) { + ss << tableNamePair.second << " "; + } + if(int(i) < int(tableNames.size()) - 1) { + ss << ","; + } + ss << " "; + } } + iterate_tuple(sel.conditions, [&context, &ss](auto &v) { + ss << serialize(v, context); + }); + if(!is_base_of_template::value) { + if(!sel.highest_level) { + ss << ") "; + } + } + return ss.str(); } - return ss.str(); - } - }; - - template - struct statement_serializator, void> { - using statement_type = where_t; - - template - std::string operator()(const statement_type &w, const C &context) const { - std::stringstream ss; - ss << static_cast(w) << " "; - auto whereString = serialize(w.c, context); - ss << "( " << whereString << ") "; - return ss.str(); - } - }; - - template - struct statement_serializator, void> { - using statement_type = order_by_t; - - template - std::string operator()(const statement_type &orderBy, const C &context) const { - std::stringstream ss; - ss << static_cast(orderBy) << " "; - auto orderByString = serialize_order_by(orderBy, context); - ss << orderByString << " "; - return ss.str(); - } - }; - - template - struct statement_serializator, void> { - using statement_type = dynamic_order_by_t; - - template - std::string operator()(const statement_type &orderBy, const CC &context) const { - return serialize_order_by(orderBy, context); - } - }; - - template - struct statement_serializator, void> { - using statement_type = multi_order_by_t; - + }; + + template + struct statement_serializator, void> { + using statement_type = where_t; + + template + std::string operator()(const statement_type &w, const C &context) const { + std::stringstream ss; + ss << static_cast(w) << " "; + auto whereString = serialize(w.c, context); + ss << "( " << whereString << ") "; + return ss.str(); + } + }; + + template + struct statement_serializator, void> { + using statement_type = order_by_t; + + template + std::string operator()(const statement_type &orderBy, const C &context) const { + std::stringstream ss; + ss << static_cast(orderBy) << " "; + auto orderByString = serialize_order_by(orderBy, context); + ss << orderByString << " "; + return ss.str(); + } + }; + template - std::string operator()(const statement_type &orderBy, const C &context) const { - std::stringstream ss; - std::vector expressions; - iterate_tuple(orderBy.args, [&expressions, &context](auto &v) { - auto expression = serialize_order_by(v, context); - expressions.push_back(move(expression)); - }); - ss << static_cast(orderBy) << " "; - for(size_t i = 0; i < expressions.size(); ++i) { - ss << expressions[i]; - if(i < expressions.size() - 1) { - ss << ", "; + struct statement_serializator, void> { + using statement_type = dynamic_order_by_t; + + template + std::string operator()(const statement_type &orderBy, const CC &context) const { + return serialize_order_by(orderBy, context); + } + }; + + template + struct statement_serializator, void> { + using statement_type = multi_order_by_t; + + template + std::string operator()(const statement_type &orderBy, const C &context) const { + std::stringstream ss; + std::vector expressions; + iterate_tuple(orderBy.args, [&expressions, &context](auto &v) { + auto expression = serialize_order_by(v, context); + expressions.push_back(move(expression)); + }); + ss << static_cast(orderBy) << " "; + for(size_t i = 0; i < expressions.size(); ++i) { + ss << expressions[i]; + if(i < expressions.size() - 1) { + ss << ", "; + } } + ss << " "; + return ss.str(); } - ss << " "; - return ss.str(); - } - }; - - template - struct statement_serializator, void> { - using statement_type = cross_join_t; - - template - std::string operator()(const statement_type &c, const C &context) const { - std::stringstream ss; - ss << static_cast(c) << " "; - ss << " '" << context.impl.find_table_name(typeid(O)) << "'"; - return ss.str(); - } - }; - - template - struct statement_serializator, void> { - using statement_type = inner_join_t; - - template - std::string operator()(const statement_type &l, const C &context) const { - std::stringstream ss; - ss << static_cast(l) << " "; - auto aliasString = alias_extractor::get(); - ss << " '" << context.impl.find_table_name(typeid(typename mapped_type_proxy::type)) << "' "; - if(aliasString.length()) { - ss << "'" << aliasString << "' "; - } - ss << serialize(l.constraint, context); - return ss.str(); - } - }; - - template - struct statement_serializator, void> { - using statement_type = on_t; - - template - std::string operator()(const statement_type &t, const C &context) const { - std::stringstream ss; - auto newContext = context; - newContext.skip_table_name = false; - ss << static_cast(t) << " " << serialize(t.arg, newContext); - return ss.str(); - } - }; - - template - struct statement_serializator, void> { - using statement_type = join_t; - - template - std::string operator()(const statement_type &l, const C &context) const { - std::stringstream ss; - ss << static_cast(l) << " "; - ss << " '" << context.impl.find_table_name(typeid(T)) << "' "; - ss << serialize(l.constraint, context); - return ss.str(); - } - }; - - template - struct statement_serializator, void> { - using statement_type = left_join_t; - - template - std::string operator()(const statement_type &l, const C &context) const { - std::stringstream ss; - ss << static_cast(l) << " "; - ss << " '" << context.impl.find_table_name(typeid(T)) << "' "; - ss << serialize(l.constraint, context); - return ss.str(); - } - }; - - template - struct statement_serializator, void> { - using statement_type = left_outer_join_t; - - template - std::string operator()(const statement_type &l, const C &context) const { - std::stringstream ss; - ss << static_cast(l) << " "; - ss << " '" << context.impl.find_table_name(typeid(T)) << "' "; - ss << serialize(l.constraint, context); - return ss.str(); - } - }; - - template - struct statement_serializator, void> { - using statement_type = natural_join_t; - - template - std::string operator()(const statement_type &c, const C &context) const { - std::stringstream ss; - ss << static_cast(c) << " "; - ss << " '" << context.impl.find_table_name(typeid(O)) << "'"; - return ss.str(); - } - }; - - template - struct statement_serializator, void> { - using statement_type = group_by_t; - - template - std::string operator()(const statement_type &groupBy, const C &context) const { - std::stringstream ss; - std::vector expressions; - auto newContext = context; - newContext.skip_table_name = false; - iterate_tuple(groupBy.args, [&expressions, &newContext](auto &v) { - auto expression = serialize(v, newContext); - expressions.push_back(expression); - }); - ss << static_cast(groupBy) << " "; - for(size_t i = 0; i < expressions.size(); ++i) { - ss << expressions[i]; - if(i < expressions.size() - 1) { - ss << ", "; + }; + + template + struct statement_serializator, void> { + using statement_type = cross_join_t; + + template + std::string operator()(const statement_type &c, const C &context) const { + std::stringstream ss; + ss << static_cast(c) << " "; + ss << " '" << context.impl.find_table_name(typeid(O)) << "'"; + return ss.str(); + } + }; + + template + struct statement_serializator, void> { + using statement_type = inner_join_t; + + template + std::string operator()(const statement_type &l, const C &context) const { + std::stringstream ss; + ss << static_cast(l) << " "; + auto aliasString = alias_extractor::get(); + ss << " '" << context.impl.find_table_name(typeid(typename mapped_type_proxy::type)) << "' "; + if(aliasString.length()) { + ss << "'" << aliasString << "' "; } + ss << serialize(l.constraint, context); + return ss.str(); } - ss << " "; - return ss.str(); - } - }; - - template - struct statement_serializator, void> { - using statement_type = having_t; - - template - std::string operator()(const statement_type &hav, const C &context) const { - std::stringstream ss; - auto newContext = context; - newContext.skip_table_name = false; - ss << static_cast(hav) << " "; - ss << serialize(hav.t, newContext) << " "; - return ss.str(); - } - }; - - /** + }; + + template + struct statement_serializator, void> { + using statement_type = on_t; + + template + std::string operator()(const statement_type &t, const C &context) const { + std::stringstream ss; + auto newContext = context; + newContext.skip_table_name = false; + ss << static_cast(t) << " " << serialize(t.arg, newContext); + return ss.str(); + } + }; + + template + struct statement_serializator, void> { + using statement_type = join_t; + + template + std::string operator()(const statement_type &l, const C &context) const { + std::stringstream ss; + ss << static_cast(l) << " "; + ss << " '" << context.impl.find_table_name(typeid(T)) << "' "; + ss << serialize(l.constraint, context); + return ss.str(); + } + }; + + template + struct statement_serializator, void> { + using statement_type = left_join_t; + + template + std::string operator()(const statement_type &l, const C &context) const { + std::stringstream ss; + ss << static_cast(l) << " "; + ss << " '" << context.impl.find_table_name(typeid(T)) << "' "; + ss << serialize(l.constraint, context); + return ss.str(); + } + }; + + template + struct statement_serializator, void> { + using statement_type = left_outer_join_t; + + template + std::string operator()(const statement_type &l, const C &context) const { + std::stringstream ss; + ss << static_cast(l) << " "; + ss << " '" << context.impl.find_table_name(typeid(T)) << "' "; + ss << serialize(l.constraint, context); + return ss.str(); + } + }; + + template + struct statement_serializator, void> { + using statement_type = natural_join_t; + + template + std::string operator()(const statement_type &c, const C &context) const { + std::stringstream ss; + ss << static_cast(c) << " "; + ss << " '" << context.impl.find_table_name(typeid(O)) << "'"; + return ss.str(); + } + }; + + template + struct statement_serializator, void> { + using statement_type = group_by_t; + + template + std::string operator()(const statement_type &groupBy, const C &context) const { + std::stringstream ss; + std::vector expressions; + auto newContext = context; + newContext.skip_table_name = false; + iterate_tuple(groupBy.args, [&expressions, &newContext](auto &v) { + auto expression = serialize(v, newContext); + expressions.push_back(expression); + }); + ss << static_cast(groupBy) << " "; + for(size_t i = 0; i < expressions.size(); ++i) { + ss << expressions[i]; + if(i < expressions.size() - 1) { + ss << ", "; + } + } + ss << " "; + return ss.str(); + } + }; + + template + struct statement_serializator, void> { + using statement_type = having_t; + + template + std::string operator()(const statement_type &hav, const C &context) const { + std::stringstream ss; + auto newContext = context; + newContext.skip_table_name = false; + ss << static_cast(hav) << " "; + ss << serialize(hav.t, newContext) << " "; + return ss.str(); + } + }; + + /** * HO - has offset * OI - offset is implicit */ - template - struct statement_serializator, void> { - using statement_type = limit_t; - - template - std::string operator()(const statement_type &limt, const C &context) const { - auto newContext = context; - newContext.skip_table_name = false; - std::stringstream ss; - ss << static_cast(limt) << " "; - if(HO) { - if(OI) { - limt.off.apply([&newContext, &ss](auto &value) { - ss << serialize(value, newContext); - }); - ss << ", "; - ss << serialize(limt.lim, newContext); + template + struct statement_serializator, void> { + using statement_type = limit_t; + + template + std::string operator()(const statement_type &limt, const C &context) const { + auto newContext = context; + newContext.skip_table_name = false; + std::stringstream ss; + ss << static_cast(limt) << " "; + if(HO) { + if(OI) { + limt.off.apply([&newContext, &ss](auto &value) { + ss << serialize(value, newContext); + }); + ss << ", "; + ss << serialize(limt.lim, newContext); + } else { + ss << serialize(limt.lim, newContext) << " OFFSET "; + limt.off.apply([&newContext, &ss](auto &value) { + ss << serialize(value, newContext); + }); + } } else { - ss << serialize(limt.lim, newContext) << " OFFSET "; - limt.off.apply([&newContext, &ss](auto &value) { - ss << serialize(value, newContext); - }); + ss << serialize(limt.lim, newContext); } - } else { - ss << serialize(limt.lim, newContext); + return ss.str(); } - return ss.str(); - } - }; - + }; + /*template struct statement_serializator< T, diff --git a/dev/storage.h b/dev/storage.h index d05e8cfed..6794a2d5e 100644 --- a/dev/storage.h +++ b/dev/storage.h @@ -50,8 +50,8 @@ namespace sqlite_orm { -//template -//internal::dynamic_order_by_t> dynamic_order_by(const S &storage); + //template + //internal::dynamic_order_by_t> dynamic_order_by(const S &storage); /*namespace conditions { @@ -90,7 +90,7 @@ namespace sqlite_orm { template friend struct iterator_t; - + template friend struct serializator_context_builder; @@ -1232,13 +1232,13 @@ namespace sqlite_orm { } protected: -// template -// friend dynamic_order_by_t> dynamic_order_by(const S &storage); -// friend dynamic_order_by_t> dynamic_order_by(const S &storage) - -// template -// friend dynamic_order_by_t> dynamic_order_by(const S &storage); - + // template + // friend dynamic_order_by_t> dynamic_order_by(const S &storage); + // friend dynamic_order_by_t> dynamic_order_by(const S &storage) + + // template + // friend dynamic_order_by_t> dynamic_order_by(const S &storage); + template std::string group_concat_internal(F O::*m, std::unique_ptr y, Args &&... args) { this->assert_mapped_type(); diff --git a/include/sqlite_orm/sqlite_orm.h b/include/sqlite_orm/sqlite_orm.h index e2a95a79d..1f6d57e1d 100644 --- a/include/sqlite_orm/sqlite_orm.h +++ b/include/sqlite_orm/sqlite_orm.h @@ -27,7 +27,7 @@ __pragma(push_macro("min")) #include #include // std::ostringstream -namespace sqlite_orm { + namespace sqlite_orm { enum class orm_error_code { not_found = 1, @@ -44,7 +44,6 @@ namespace sqlite_orm { failed_to_init_a_backup, unknown_member_value, }; - } namespace sqlite_orm { @@ -225,7 +224,6 @@ namespace sqlite_orm { // #include "static_magic.h" - #include // std::false_type, std::true_type, std::integral_constant namespace sqlite_orm { @@ -260,7 +258,6 @@ namespace sqlite_orm { } - namespace sqlite_orm { // got from here http://stackoverflow.com/questions/25958259/how-do-i-find-out-if-a-tuple-contains-a-type @@ -992,7 +989,6 @@ namespace sqlite_orm { // #include "serializator_context.h" - namespace sqlite_orm { namespace internal { @@ -1000,6 +996,7 @@ namespace sqlite_orm { struct serializator_context_base { bool replace_bindable_with_question = false; bool skip_table_name = true; + bool use_parentheses = true; template std::string column_name(F O::*) const { @@ -1020,26 +1017,25 @@ namespace sqlite_orm { return this->impl.column_name(m); } }; - - template - struct serializator_context_builder { - using storage_type = S; - using impl_type = typename storage_type::impl_type; - - serializator_context_builder(const storage_type &storage_) : storage(storage_) {} - - serializator_context operator()() const { - return {this->storage.impl}; - } - - const storage_type &storage; - }; + + template + struct serializator_context_builder { + using storage_type = S; + using impl_type = typename storage_type::impl_type; + + serializator_context_builder(const storage_type &storage_) : storage(storage_) {} + + serializator_context operator()() const { + return {this->storage.impl}; + } + + const storage_type &storage; + }; } } - namespace sqlite_orm { namespace internal { @@ -1074,14 +1070,12 @@ namespace sqlite_orm { // #include "negatable.h" - namespace sqlite_orm { namespace internal { struct negatable_t {}; } } - namespace sqlite_orm { namespace internal { @@ -1381,7 +1375,6 @@ namespace sqlite_orm { // #include "getter_traits.h" - namespace sqlite_orm { namespace internal { @@ -1565,7 +1558,6 @@ namespace sqlite_orm { } } - namespace sqlite_orm { namespace internal { @@ -1896,7 +1888,6 @@ namespace sqlite_orm { // #include "optional_container.h" - namespace sqlite_orm { namespace internal { @@ -1931,7 +1922,6 @@ namespace sqlite_orm { // #include "negatable.h" - namespace sqlite_orm { namespace internal { @@ -2428,9 +2418,9 @@ namespace sqlite_orm { using context_t = C; using entry_t = dynamic_order_by_entry_t; using const_iterator = typename std::vector::const_iterator; - + dynamic_order_by_t(const context_t &context_) : context(context_) {} - + template void push_back(order_by_t order_by) { auto newContext = this->context; @@ -3144,7 +3134,8 @@ namespace sqlite_orm { * } */ template - internal::dynamic_order_by_t> dynamic_order_by(const S &storage) { + internal::dynamic_order_by_t> + dynamic_order_by(const S &storage) { internal::serializator_context_builder builder(storage); return builder(); /*using context_t = internal::serializator_context; @@ -3384,7 +3375,6 @@ namespace sqlite_orm { // #include "conditions.h" - namespace sqlite_orm { namespace internal { @@ -3504,7 +3494,6 @@ namespace sqlite_orm { // #include "is_base_of_template.h" - #include // std::true_type, std::false_type, std::declval namespace sqlite_orm { @@ -3542,7 +3531,6 @@ namespace sqlite_orm { } } - namespace sqlite_orm { namespace internal { @@ -4295,7 +4283,6 @@ namespace sqlite_orm { // #include "optional_container.h" - namespace sqlite_orm { namespace internal { @@ -4648,7 +4635,6 @@ namespace sqlite_orm { // #include "column.h" - namespace sqlite_orm { namespace internal { @@ -4755,7 +4741,6 @@ namespace sqlite_orm { // #include "is_std_ptr.h" - namespace sqlite_orm { /** @@ -4783,7 +4768,6 @@ namespace sqlite_orm { }; } - namespace sqlite_orm { /** @@ -4994,7 +4978,6 @@ namespace sqlite_orm { // #include "journal_mode.h" - #include // std::string #include // std::unique_ptr #include // std::array @@ -5057,7 +5040,6 @@ namespace sqlite_orm { // #include "error_code.h" - namespace sqlite_orm { /** @@ -5434,7 +5416,6 @@ namespace sqlite_orm { // #include "alias.h" - namespace sqlite_orm { namespace internal { @@ -5681,7 +5662,6 @@ namespace sqlite_orm { } } - namespace sqlite_orm { namespace internal { @@ -5946,7 +5926,6 @@ namespace sqlite_orm { // #include "column.h" - namespace sqlite_orm { namespace internal { @@ -6246,12 +6225,10 @@ namespace sqlite_orm { // #include "field_value_holder.h" - #include // std::enable_if // #include "column.h" - namespace sqlite_orm { namespace internal { @@ -6274,7 +6251,6 @@ namespace sqlite_orm { } } - namespace sqlite_orm { namespace internal { @@ -6776,7 +6752,6 @@ namespace sqlite_orm { // #include "view.h" - #include // std::shared_ptr #include // std::string #include // std::forward, std::move @@ -6792,7 +6767,6 @@ namespace sqlite_orm { // #include "iterator.h" - #include // std::shared_ptr, std::unique_ptr, std::make_shared #include #include // std::decay @@ -6808,7 +6782,6 @@ namespace sqlite_orm { // #include "error_code.h" - namespace sqlite_orm { namespace internal { @@ -6937,7 +6910,6 @@ namespace sqlite_orm { // #include "ast_iterator.h" - #include // std::vector #include // std::reference_wrapper @@ -6953,7 +6925,6 @@ namespace sqlite_orm { // #include "prepared_statement.h" - #include #include // std::iterator_traits #include // std::string @@ -6962,14 +6933,12 @@ namespace sqlite_orm { // #include "connection_holder.h" - #include #include // std::string #include // std::system_error // #include "error_code.h" - namespace sqlite_orm { namespace internal { @@ -7044,7 +7013,6 @@ namespace sqlite_orm { // #include "select_constraints.h" - namespace sqlite_orm { namespace internal { @@ -7428,7 +7396,6 @@ namespace sqlite_orm { #endif // SQLITE_ORM_OPTIONAL_SUPPORTED } - namespace sqlite_orm { namespace internal { @@ -7914,7 +7881,6 @@ namespace sqlite_orm { // #include "connection_holder.h" - namespace sqlite_orm { namespace internal { @@ -7973,7 +7939,6 @@ namespace sqlite_orm { // #include "storage_base.h" - #include // std::function, std::bind #include #include // std::string @@ -7988,7 +7953,6 @@ namespace sqlite_orm { // #include "pragma.h" - #include // std::string #include #include // std::function @@ -8002,7 +7966,6 @@ namespace sqlite_orm { // #include "connection_holder.h" - namespace sqlite_orm { namespace internal { @@ -8123,7 +8086,6 @@ namespace sqlite_orm { // #include "limit_accesor.h" - #include #include // std::map #include // std::function @@ -8131,7 +8093,6 @@ namespace sqlite_orm { // #include "connection_holder.h" - namespace sqlite_orm { namespace internal { @@ -8265,12 +8226,10 @@ namespace sqlite_orm { // #include "transaction_guard.h" - #include // std::function // #include "connection_holder.h" - namespace sqlite_orm { namespace internal { @@ -8345,7 +8304,6 @@ namespace sqlite_orm { // #include "backup.h" - #include #include // std::string #include @@ -8354,7 +8312,6 @@ namespace sqlite_orm { // #include "connection_holder.h" - namespace sqlite_orm { namespace internal { @@ -8420,7 +8377,6 @@ namespace sqlite_orm { } } - namespace sqlite_orm { namespace internal { @@ -8956,13 +8912,11 @@ namespace sqlite_orm { // #include "expression_object_type.h" - #include // std::decay #include // std::reference_wrapper // #include "prepared_statement.h" - namespace sqlite_orm { namespace internal { @@ -9082,7 +9036,6 @@ namespace sqlite_orm { // #include "statement_serializator.h" - #include // std::stringstream #include // std::string #include // std::is_arithmetic, std::enable_if @@ -9103,7 +9056,6 @@ namespace sqlite_orm { // #include "table_name_collector.h" - #include // std::set #include // std::string #include // std::function @@ -9115,7 +9067,6 @@ namespace sqlite_orm { // #include "core_functions.h" - namespace sqlite_orm { namespace internal { @@ -9176,154 +9127,124 @@ namespace sqlite_orm { // #include "column_names_getter.h" - -#include // std::string -#include // std::vector -#include // std::reference_wrapper +#include // std::string +#include // std::vector +#include // std::reference_wrapper // #include "error_code.h" // #include "select_constraints.h" - namespace sqlite_orm { -namespace internal { + namespace internal { -template -std::string serialize(const T &t, const C &context); + template + std::string serialize(const T &t, const C &context); -template -struct column_names_getter { - using expression_type = T; - - template - std::vector operator()(const expression_type &t, const C &context) { - auto newContext = context; - newContext.skip_table_name = false; - auto columnName = serialize(t, newContext); - if(columnName.length()) { - return {move(columnName)}; - } else { - throw std::system_error(std::make_error_code(orm_error_code::column_not_found)); + template + struct column_names_getter { + using expression_type = T; + + template + std::vector operator()(const expression_type &t, const C &context) { + auto newContext = context; + newContext.skip_table_name = false; + auto columnName = serialize(t, newContext); + if(columnName.length()) { + return {move(columnName)}; + } else { + throw std::system_error(std::make_error_code(orm_error_code::column_not_found)); + } + } + }; + + template + std::vector get_column_names(const T &t, const C &context) { + column_names_getter serializator; + return serializator(t, context); } - } -}; - template - std::vector get_column_names(const T &t, const C &context) { - column_names_getter serializator; - return serializator(t, context); - } + template + struct column_names_getter, void> { + using expression_type = std::reference_wrapper; -template -struct column_names_getter, void> { - using expression_type = std::reference_wrapper; - - template - std::vector operator()(const expression_type &expression, const C &context) { - return get_column_names(expression.get(), context); - } -}; -template -struct column_names_getter, void> { - using expression_type = asterisk_t; - - template - std::vector operator()(const expression_type &, const C &) { - std::vector res; - res.push_back("*"); - return res; - } -}; + template + std::vector operator()(const expression_type &expression, const C &context) { + return get_column_names(expression.get(), context); + } + }; + template + struct column_names_getter, void> { + using expression_type = asterisk_t; -template -struct column_names_getter, void> { - using expression_type = columns_t; - - template - std::vector operator()(const expression_type &cols, const C &context) { - std::vector columnNames; - columnNames.reserve(static_cast(cols.count)); - auto newContext = context; - newContext.skip_table_name = false; - iterate_tuple(cols.columns, [&columnNames, &newContext](auto &m) { - auto columnName = serialize(m, newContext); - if(columnName.length()) { - columnNames.push_back(columnName); - } else { - throw std::system_error(std::make_error_code(orm_error_code::column_not_found)); + template + std::vector operator()(const expression_type &, const C &) { + std::vector res; + res.push_back("*"); + return res; } - }); - return columnNames; - } -}; + }; -} + template + struct column_names_getter, void> { + using expression_type = columns_t; + + template + std::vector operator()(const expression_type &cols, const C &context) { + std::vector columnNames; + columnNames.reserve(static_cast(cols.count)); + auto newContext = context; + newContext.skip_table_name = false; + iterate_tuple(cols.columns, [&columnNames, &newContext](auto &m) { + auto columnName = serialize(m, newContext); + if(columnName.length()) { + columnNames.push_back(columnName); + } else { + throw std::system_error(std::make_error_code(orm_error_code::column_not_found)); + } + }); + return columnNames; + } + }; + + } } // #include "order_by_serializator.h" - -#include // std::string -#include // std::vector +#include // std::string +#include // std::vector #include // std::stringstream namespace sqlite_orm { -namespace internal { - -template -struct order_by_serializator; + namespace internal { -template -std::string serialize_order_by(const T &t, const C &context) { - order_by_serializator serializator; - return serializator(t, context); -} + template + struct order_by_serializator; -template -struct order_by_serializator, void> { - using statement_type = order_by_t; - - template - std::string operator()(const statement_type &orderBy, const C &context) const { - std::stringstream ss; - auto newContext = context; - newContext.skip_table_name = false; - auto columnName = serialize(orderBy.o, newContext); - ss << columnName << " "; - if(orderBy._collate_argument.length()) { - ss << "COLLATE " << orderBy._collate_argument << " "; - } - switch(orderBy.asc_desc) { - case 1: - ss << "ASC"; - break; - case -1: - ss << "DESC"; - break; + template + std::string serialize_order_by(const T &t, const C &context) { + order_by_serializator serializator; + return serializator(t, context); } - return ss.str(); - } -}; -template -struct order_by_serializator, void> { - using statement_type = dynamic_order_by_t; - - template - std::string operator()(const statement_type &orderBy, const C &) const { - std::vector expressions; - for(auto &entry: orderBy) { - std::string entryString; - { + template + struct order_by_serializator, void> { + using statement_type = order_by_t; + + template + std::string operator()(const statement_type &orderBy, const C &context) const { std::stringstream ss; - ss << entry.name << " "; - if(!entry._collate_argument.empty()) { - ss << "COLLATE " << entry._collate_argument << " "; + auto newContext = context; + newContext.skip_table_name = false; + auto columnName = serialize(orderBy.o, newContext); + ss << columnName << " "; + if(orderBy._collate_argument.length()) { + ss << "COLLATE " << orderBy._collate_argument << " "; } - switch(entry.asc_desc) { + switch(orderBy.asc_desc) { case 1: ss << "ASC"; break; @@ -9331,27 +9252,53 @@ struct order_by_serializator, void> { ss << "DESC"; break; } - entryString = ss.str(); + return ss.str(); } - expressions.push_back(move(entryString)); }; - std::stringstream ss; - ss << static_cast(orderBy) << " "; - for(size_t i = 0; i < expressions.size(); ++i) { - ss << expressions[i]; - if(i < expressions.size() - 1) { - ss << ", "; + + template + struct order_by_serializator, void> { + using statement_type = dynamic_order_by_t; + + template + std::string operator()(const statement_type &orderBy, const C &) const { + std::vector expressions; + for(auto &entry: orderBy) { + std::string entryString; + { + std::stringstream ss; + ss << entry.name << " "; + if(!entry._collate_argument.empty()) { + ss << "COLLATE " << entry._collate_argument << " "; + } + switch(entry.asc_desc) { + case 1: + ss << "ASC"; + break; + case -1: + ss << "DESC"; + break; + } + entryString = ss.str(); + } + expressions.push_back(move(entryString)); + }; + std::stringstream ss; + ss << static_cast(orderBy) << " "; + for(size_t i = 0; i < expressions.size(); ++i) { + ss << expressions[i]; + if(i < expressions.size() - 1) { + ss << ", "; + } + } + ss << " "; + return ss.str(); } - } - ss << " "; - return ss.str(); - } -}; + }; -} + } } - namespace sqlite_orm { namespace internal { @@ -9364,8 +9311,8 @@ namespace sqlite_orm { statement_serializator serializator; return serializator(t, context); } - - /*template + + /*template struct statement_serializator::value>::type> { using statement_type = T; @@ -9380,20 +9327,20 @@ namespace sqlite_orm { } } };*/ - - template - struct statement_serializator::value>::type> { - using statement_type = T; - - template - std::string operator()(const statement_type &statement, const C &context) { - if(context.replace_bindable_with_question){ - return "?"; - }else{ - return field_printer{}(statement); + + template + struct statement_serializator::value>::type> { + using statement_type = T; + + template + std::string operator()(const statement_type &statement, const C &context) { + if(context.replace_bindable_with_question) { + return "?"; + } else { + return field_printer{}(statement); + } } - } - }; + }; template struct statement_serializator, void> { @@ -9687,9 +9634,8 @@ namespace sqlite_orm { }; template - struct statement_serializator< - T, - typename std::enable_if::value>::type> { + struct statement_serializator::value>::type> { using statement_type = T; template @@ -9778,9 +9724,8 @@ namespace sqlite_orm { }; template - struct statement_serializator< - T, - typename std::enable_if::value>::type> { + struct statement_serializator::value>::type> { using statement_type = T; template @@ -9788,7 +9733,13 @@ namespace sqlite_orm { auto leftString = serialize(c.l, context); auto rightString = serialize(c.r, context); std::stringstream ss; - ss << "(" << leftString << " " << static_cast(c) << " " << rightString << ")"; + if(context.use_parentheses) { + ss << "("; + } + ss << leftString << " " << static_cast(c) << " " << rightString; + if(context.use_parentheses) { + ss << ")"; + } return ss.str(); } }; @@ -9799,7 +9750,9 @@ namespace sqlite_orm { template std::string operator()(const statement_type &c, const C &context) const { - auto res = serialize(c.expr, context); + auto newContext = context; + newContext.use_parentheses = false; + auto res = serialize(c.expr, newContext); return res + " " + static_cast(c); } }; @@ -9810,7 +9763,9 @@ namespace sqlite_orm { template std::string operator()(const statement_type &c, const C &context) const { - auto res = serialize(c.expr, context); + auto newContext = context; + newContext.use_parentheses = false; + auto res = serialize(c.expr, newContext); return res + " " + static_cast(c); } }; @@ -10083,310 +10038,310 @@ namespace sqlite_orm { return ss.str(); } }; - - template - struct statement_serializator, void> { - using statement_type = select_t; - - template - std::string operator()(const statement_type &sel, const C &context) const { - std::stringstream ss; - if(!is_base_of_template::value) { - if(!sel.highest_level) { - ss << "( "; + + template + struct statement_serializator, void> { + using statement_type = select_t; + + template + std::string operator()(const statement_type &sel, const C &context) const { + std::stringstream ss; + if(!is_base_of_template::value) { + if(!sel.highest_level) { + ss << "( "; + } + ss << "SELECT "; } - ss << "SELECT "; - } - if(get_distinct(sel.col)) { - ss << static_cast(distinct(0)) << " "; - } - auto columnNames = get_column_names(sel.col, context); - for(size_t i = 0; i < columnNames.size(); ++i) { - ss << columnNames[i]; - if(i < columnNames.size() - 1) { - ss << ","; + if(get_distinct(sel.col)) { + ss << static_cast(distinct(0)) << " "; } - ss << " "; - } - table_name_collector collector{[&context](std::type_index ti) { - return context.impl.find_table_name(ti); - }}; - iterate_ast(sel.col, collector); - iterate_ast(sel.conditions, collector); - internal::join_iterator()([&collector, &context](const auto &c) { - using original_join_type = typename std::decay::type::join_type::type; - using cross_join_type = typename internal::mapped_type_proxy::type; - auto crossJoinedTableName = context.impl.find_table_name(typeid(cross_join_type)); - auto tableAliasString = alias_extractor::get(); - std::pair tableNameWithAlias(std::move(crossJoinedTableName), - std::move(tableAliasString)); - collector.table_names.erase(tableNameWithAlias); - }); - if(!collector.table_names.empty()) { - ss << "FROM "; - std::vector> tableNames(collector.table_names.begin(), - collector.table_names.end()); - for(size_t i = 0; i < tableNames.size(); ++i) { - auto &tableNamePair = tableNames[i]; - ss << "'" << tableNamePair.first << "' "; - if(!tableNamePair.second.empty()) { - ss << tableNamePair.second << " "; - } - if(int(i) < int(tableNames.size()) - 1) { + auto columnNames = get_column_names(sel.col, context); + for(size_t i = 0; i < columnNames.size(); ++i) { + ss << columnNames[i]; + if(i < columnNames.size() - 1) { ss << ","; } ss << " "; } - } - iterate_tuple(sel.conditions, [&context, &ss](auto &v) { - ss << serialize(v, context); - }); - if(!is_base_of_template::value) { - if(!sel.highest_level) { - ss << ") "; + table_name_collector collector{[&context](std::type_index ti) { + return context.impl.find_table_name(ti); + }}; + iterate_ast(sel.col, collector); + iterate_ast(sel.conditions, collector); + internal::join_iterator()([&collector, &context](const auto &c) { + using original_join_type = typename std::decay::type::join_type::type; + using cross_join_type = typename internal::mapped_type_proxy::type; + auto crossJoinedTableName = context.impl.find_table_name(typeid(cross_join_type)); + auto tableAliasString = alias_extractor::get(); + std::pair tableNameWithAlias(std::move(crossJoinedTableName), + std::move(tableAliasString)); + collector.table_names.erase(tableNameWithAlias); + }); + if(!collector.table_names.empty()) { + ss << "FROM "; + std::vector> tableNames(collector.table_names.begin(), + collector.table_names.end()); + for(size_t i = 0; i < tableNames.size(); ++i) { + auto &tableNamePair = tableNames[i]; + ss << "'" << tableNamePair.first << "' "; + if(!tableNamePair.second.empty()) { + ss << tableNamePair.second << " "; + } + if(int(i) < int(tableNames.size()) - 1) { + ss << ","; + } + ss << " "; + } } + iterate_tuple(sel.conditions, [&context, &ss](auto &v) { + ss << serialize(v, context); + }); + if(!is_base_of_template::value) { + if(!sel.highest_level) { + ss << ") "; + } + } + return ss.str(); } - return ss.str(); - } - }; - - template - struct statement_serializator, void> { - using statement_type = where_t; - - template - std::string operator()(const statement_type &w, const C &context) const { - std::stringstream ss; - ss << static_cast(w) << " "; - auto whereString = serialize(w.c, context); - ss << "( " << whereString << ") "; - return ss.str(); - } - }; - - template - struct statement_serializator, void> { - using statement_type = order_by_t; - - template - std::string operator()(const statement_type &orderBy, const C &context) const { - std::stringstream ss; - ss << static_cast(orderBy) << " "; - auto orderByString = serialize_order_by(orderBy, context); - ss << orderByString << " "; - return ss.str(); - } - }; - - template - struct statement_serializator, void> { - using statement_type = dynamic_order_by_t; - - template - std::string operator()(const statement_type &orderBy, const CC &context) const { - return serialize_order_by(orderBy, context); - } - }; - - template - struct statement_serializator, void> { - using statement_type = multi_order_by_t; - + }; + + template + struct statement_serializator, void> { + using statement_type = where_t; + + template + std::string operator()(const statement_type &w, const C &context) const { + std::stringstream ss; + ss << static_cast(w) << " "; + auto whereString = serialize(w.c, context); + ss << "( " << whereString << ") "; + return ss.str(); + } + }; + + template + struct statement_serializator, void> { + using statement_type = order_by_t; + + template + std::string operator()(const statement_type &orderBy, const C &context) const { + std::stringstream ss; + ss << static_cast(orderBy) << " "; + auto orderByString = serialize_order_by(orderBy, context); + ss << orderByString << " "; + return ss.str(); + } + }; + template - std::string operator()(const statement_type &orderBy, const C &context) const { - std::stringstream ss; - std::vector expressions; - iterate_tuple(orderBy.args, [&expressions, &context](auto &v) { - auto expression = serialize_order_by(v, context); - expressions.push_back(move(expression)); - }); - ss << static_cast(orderBy) << " "; - for(size_t i = 0; i < expressions.size(); ++i) { - ss << expressions[i]; - if(i < expressions.size() - 1) { - ss << ", "; + struct statement_serializator, void> { + using statement_type = dynamic_order_by_t; + + template + std::string operator()(const statement_type &orderBy, const CC &context) const { + return serialize_order_by(orderBy, context); + } + }; + + template + struct statement_serializator, void> { + using statement_type = multi_order_by_t; + + template + std::string operator()(const statement_type &orderBy, const C &context) const { + std::stringstream ss; + std::vector expressions; + iterate_tuple(orderBy.args, [&expressions, &context](auto &v) { + auto expression = serialize_order_by(v, context); + expressions.push_back(move(expression)); + }); + ss << static_cast(orderBy) << " "; + for(size_t i = 0; i < expressions.size(); ++i) { + ss << expressions[i]; + if(i < expressions.size() - 1) { + ss << ", "; + } } + ss << " "; + return ss.str(); } - ss << " "; - return ss.str(); - } - }; - - template - struct statement_serializator, void> { - using statement_type = cross_join_t; - - template - std::string operator()(const statement_type &c, const C &context) const { - std::stringstream ss; - ss << static_cast(c) << " "; - ss << " '" << context.impl.find_table_name(typeid(O)) << "'"; - return ss.str(); - } - }; - - template - struct statement_serializator, void> { - using statement_type = inner_join_t; - - template - std::string operator()(const statement_type &l, const C &context) const { - std::stringstream ss; - ss << static_cast(l) << " "; - auto aliasString = alias_extractor::get(); - ss << " '" << context.impl.find_table_name(typeid(typename mapped_type_proxy::type)) << "' "; - if(aliasString.length()) { - ss << "'" << aliasString << "' "; + }; + + template + struct statement_serializator, void> { + using statement_type = cross_join_t; + + template + std::string operator()(const statement_type &c, const C &context) const { + std::stringstream ss; + ss << static_cast(c) << " "; + ss << " '" << context.impl.find_table_name(typeid(O)) << "'"; + return ss.str(); } - ss << serialize(l.constraint, context); - return ss.str(); - } - }; - - template - struct statement_serializator, void> { - using statement_type = on_t; - - template - std::string operator()(const statement_type &t, const C &context) const { - std::stringstream ss; - auto newContext = context; - newContext.skip_table_name = false; - ss << static_cast(t) << " " << serialize(t.arg, newContext); - return ss.str(); - } - }; - - template - struct statement_serializator, void> { - using statement_type = join_t; - - template - std::string operator()(const statement_type &l, const C &context) const { - std::stringstream ss; - ss << static_cast(l) << " "; - ss << " '" << context.impl.find_table_name(typeid(T)) << "' "; - ss << serialize(l.constraint, context); - return ss.str(); - } - }; - - template - struct statement_serializator, void> { - using statement_type = left_join_t; - - template - std::string operator()(const statement_type &l, const C &context) const { - std::stringstream ss; - ss << static_cast(l) << " "; - ss << " '" << context.impl.find_table_name(typeid(T)) << "' "; - ss << serialize(l.constraint, context); - return ss.str(); - } - }; - - template - struct statement_serializator, void> { - using statement_type = left_outer_join_t; - - template - std::string operator()(const statement_type &l, const C &context) const { - std::stringstream ss; - ss << static_cast(l) << " "; - ss << " '" << context.impl.find_table_name(typeid(T)) << "' "; - ss << serialize(l.constraint, context); - return ss.str(); - } - }; - - template - struct statement_serializator, void> { - using statement_type = natural_join_t; - - template - std::string operator()(const statement_type &c, const C &context) const { - std::stringstream ss; - ss << static_cast(c) << " "; - ss << " '" << context.impl.find_table_name(typeid(O)) << "'"; - return ss.str(); - } - }; - - template - struct statement_serializator, void> { - using statement_type = group_by_t; - - template - std::string operator()(const statement_type &groupBy, const C &context) const { - std::stringstream ss; - std::vector expressions; - auto newContext = context; - newContext.skip_table_name = false; - iterate_tuple(groupBy.args, [&expressions, &newContext](auto &v) { - auto expression = serialize(v, newContext); - expressions.push_back(expression); - }); - ss << static_cast(groupBy) << " "; - for(size_t i = 0; i < expressions.size(); ++i) { - ss << expressions[i]; - if(i < expressions.size() - 1) { - ss << ", "; + }; + + template + struct statement_serializator, void> { + using statement_type = inner_join_t; + + template + std::string operator()(const statement_type &l, const C &context) const { + std::stringstream ss; + ss << static_cast(l) << " "; + auto aliasString = alias_extractor::get(); + ss << " '" << context.impl.find_table_name(typeid(typename mapped_type_proxy::type)) << "' "; + if(aliasString.length()) { + ss << "'" << aliasString << "' "; } + ss << serialize(l.constraint, context); + return ss.str(); } - ss << " "; - return ss.str(); - } - }; - - template - struct statement_serializator, void> { - using statement_type = having_t; - - template - std::string operator()(const statement_type &hav, const C &context) const { - std::stringstream ss; - auto newContext = context; - newContext.skip_table_name = false; - ss << static_cast(hav) << " "; - ss << serialize(hav.t, newContext) << " "; - return ss.str(); - } - }; - - /** + }; + + template + struct statement_serializator, void> { + using statement_type = on_t; + + template + std::string operator()(const statement_type &t, const C &context) const { + std::stringstream ss; + auto newContext = context; + newContext.skip_table_name = false; + ss << static_cast(t) << " " << serialize(t.arg, newContext); + return ss.str(); + } + }; + + template + struct statement_serializator, void> { + using statement_type = join_t; + + template + std::string operator()(const statement_type &l, const C &context) const { + std::stringstream ss; + ss << static_cast(l) << " "; + ss << " '" << context.impl.find_table_name(typeid(T)) << "' "; + ss << serialize(l.constraint, context); + return ss.str(); + } + }; + + template + struct statement_serializator, void> { + using statement_type = left_join_t; + + template + std::string operator()(const statement_type &l, const C &context) const { + std::stringstream ss; + ss << static_cast(l) << " "; + ss << " '" << context.impl.find_table_name(typeid(T)) << "' "; + ss << serialize(l.constraint, context); + return ss.str(); + } + }; + + template + struct statement_serializator, void> { + using statement_type = left_outer_join_t; + + template + std::string operator()(const statement_type &l, const C &context) const { + std::stringstream ss; + ss << static_cast(l) << " "; + ss << " '" << context.impl.find_table_name(typeid(T)) << "' "; + ss << serialize(l.constraint, context); + return ss.str(); + } + }; + + template + struct statement_serializator, void> { + using statement_type = natural_join_t; + + template + std::string operator()(const statement_type &c, const C &context) const { + std::stringstream ss; + ss << static_cast(c) << " "; + ss << " '" << context.impl.find_table_name(typeid(O)) << "'"; + return ss.str(); + } + }; + + template + struct statement_serializator, void> { + using statement_type = group_by_t; + + template + std::string operator()(const statement_type &groupBy, const C &context) const { + std::stringstream ss; + std::vector expressions; + auto newContext = context; + newContext.skip_table_name = false; + iterate_tuple(groupBy.args, [&expressions, &newContext](auto &v) { + auto expression = serialize(v, newContext); + expressions.push_back(expression); + }); + ss << static_cast(groupBy) << " "; + for(size_t i = 0; i < expressions.size(); ++i) { + ss << expressions[i]; + if(i < expressions.size() - 1) { + ss << ", "; + } + } + ss << " "; + return ss.str(); + } + }; + + template + struct statement_serializator, void> { + using statement_type = having_t; + + template + std::string operator()(const statement_type &hav, const C &context) const { + std::stringstream ss; + auto newContext = context; + newContext.skip_table_name = false; + ss << static_cast(hav) << " "; + ss << serialize(hav.t, newContext) << " "; + return ss.str(); + } + }; + + /** * HO - has offset * OI - offset is implicit */ - template - struct statement_serializator, void> { - using statement_type = limit_t; - - template - std::string operator()(const statement_type &limt, const C &context) const { - auto newContext = context; - newContext.skip_table_name = false; - std::stringstream ss; - ss << static_cast(limt) << " "; - if(HO) { - if(OI) { - limt.off.apply([&newContext, &ss](auto &value) { - ss << serialize(value, newContext); - }); - ss << ", "; - ss << serialize(limt.lim, newContext); + template + struct statement_serializator, void> { + using statement_type = limit_t; + + template + std::string operator()(const statement_type &limt, const C &context) const { + auto newContext = context; + newContext.skip_table_name = false; + std::stringstream ss; + ss << static_cast(limt) << " "; + if(HO) { + if(OI) { + limt.off.apply([&newContext, &ss](auto &value) { + ss << serialize(value, newContext); + }); + ss << ", "; + ss << serialize(limt.lim, newContext); + } else { + ss << serialize(limt.lim, newContext) << " OFFSET "; + limt.off.apply([&newContext, &ss](auto &value) { + ss << serialize(value, newContext); + }); + } } else { - ss << serialize(limt.lim, newContext) << " OFFSET "; - limt.off.apply([&newContext, &ss](auto &value) { - ss << serialize(value, newContext); - }); + ss << serialize(limt.lim, newContext); } - } else { - ss << serialize(limt.lim, newContext); + return ss.str(); } - return ss.str(); - } - }; - + }; + /*template struct statement_serializator< T, @@ -10420,11 +10375,10 @@ namespace sqlite_orm { // #include "table_name_collector.h" - namespace sqlite_orm { -//template -//internal::dynamic_order_by_t> dynamic_order_by(const S &storage); + //template + //internal::dynamic_order_by_t> dynamic_order_by(const S &storage); /*namespace conditions { @@ -10463,7 +10417,7 @@ namespace sqlite_orm { template friend struct iterator_t; - + template friend struct serializator_context_builder; @@ -11605,13 +11559,13 @@ namespace sqlite_orm { } protected: -// template -// friend dynamic_order_by_t> dynamic_order_by(const S &storage); -// friend dynamic_order_by_t> dynamic_order_by(const S &storage) - -// template -// friend dynamic_order_by_t> dynamic_order_by(const S &storage); - + // template + // friend dynamic_order_by_t> dynamic_order_by(const S &storage); + // friend dynamic_order_by_t> dynamic_order_by(const S &storage) + + // template + // friend dynamic_order_by_t> dynamic_order_by(const S &storage); + template std::string group_concat_internal(F O::*m, std::unique_ptr y, Args &&... args) { this->assert_mapped_type(); @@ -13029,20 +12983,19 @@ __pragma(pop_macro("min")) #include // std::pair #include // std::reference_wrapper -// #include "conditions.h" + // #include "conditions.h" -// #include "operators.h" - -// #include "select_constraints.h" + // #include "operators.h" -// #include "prepared_statement.h" + // #include "select_constraints.h" -// #include "optional_container.h" + // #include "prepared_statement.h" -// #include "core_functions.h" + // #include "optional_container.h" + // #include "core_functions.h" -namespace sqlite_orm { + namespace sqlite_orm { namespace internal { @@ -13323,7 +13276,6 @@ namespace sqlite_orm { // #include "expression_object_type.h" - namespace sqlite_orm { template diff --git a/tests/statement_serializator_tests/check.cpp b/tests/statement_serializator_tests/check.cpp index 583ec17db..44482d6c9 100644 --- a/tests/statement_serializator_tests/check.cpp +++ b/tests/statement_serializator_tests/check.cpp @@ -4,7 +4,7 @@ using namespace sqlite_orm; TEST_CASE("statement_serializator check") { - { + SECTION("greater than") { struct Table { int col1 = 0; std::string col2; @@ -23,10 +23,20 @@ TEST_CASE("statement_serializator check") { using context_t = internal::serializator_context; context_t context{storageImpl}; - auto value = serialize(ch, context); - REQUIRE(value == "CHECK (\"col3\" > 0)"); + std::string value; + std::string expected; + SECTION("with parentheses") { + value = serialize(ch, context); + expected = "CHECK (\"col3\" > 0)"; + } + SECTION("without parentheses") { + context.use_parentheses = false; + value = serialize(ch, context); + expected = "CHECK \"col3\" > 0"; + } + REQUIRE(value == expected); } - { + SECTION("lesser than") { struct Book { int id = 0; std::string name; @@ -46,7 +56,17 @@ TEST_CASE("statement_serializator check") { using context_t = internal::serializator_context; context_t context{storageImpl}; - auto value = serialize(ch, context); - REQUIRE(value == "CHECK (0 < \"PRICE\")"); + std::string value; + std::string expected; + SECTION("with parentheses") { + value = serialize(ch, context); + expected = "CHECK (0 < \"PRICE\")"; + } + SECTION("without parentheses") { + context.use_parentheses = false; + value = serialize(ch, context); + expected = "CHECK 0 < \"PRICE\""; + } + REQUIRE(value == expected); } } From 9d28a50507a333612a83fcce49e9b13e5a83a258 Mon Sep 17 00:00:00 2001 From: fnc12 Date: Sun, 26 Apr 2020 20:57:56 +0300 Subject: [PATCH 057/132] removed commented code --- dev/conditions.h | 4 - dev/statement_serializator.h | 51 +-- dev/storage.h | 576 +-------------------------- dev/storage_base.h | 35 -- include/sqlite_orm/sqlite_orm.h | 666 +------------------------------- 5 files changed, 8 insertions(+), 1324 deletions(-) diff --git a/dev/conditions.h b/dev/conditions.h index 4a4fcf6a4..eb1bc8e37 100644 --- a/dev/conditions.h +++ b/dev/conditions.h @@ -1226,10 +1226,6 @@ namespace sqlite_orm { dynamic_order_by(const S &storage) { internal::serializator_context_builder builder(storage); return builder(); - /*using context_t = internal::serializator_context; - using return_type = internal::dynamic_order_by_t; - context_t context{storage.impl}; - return return_type{std::move(context)};*/ } /** diff --git a/dev/statement_serializator.h b/dev/statement_serializator.h index 2a4fb3d34..c63576b9f 100644 --- a/dev/statement_serializator.h +++ b/dev/statement_serializator.h @@ -29,22 +29,6 @@ namespace sqlite_orm { return serializator(t, context); } - /*template - struct statement_serializator::value>::type> { - using statement_type = T; - - template - std::string operator()(const statement_type &statement, const C &context) { - if(context.replace_bindable_with_question){ - return "?"; - }else{ - std::stringstream ss; - ss << statement; - return ss.str(); - } - } - };*/ - template struct statement_serializator::value>::type> { using statement_type = T; @@ -1026,9 +1010,9 @@ namespace sqlite_orm { }; /** - * HO - has offset - * OI - offset is implicit - */ + * HO - has offset + * OI - offset is implicit + */ template struct statement_serializator, void> { using statement_type = limit_t; @@ -1058,34 +1042,5 @@ namespace sqlite_orm { return ss.str(); } }; - - /*template - struct statement_serializator< - T, - typename std::enable_if::value>::type> { - using statement_type = T; - - template - std::string operator()(const statement_type &c, const C &context) const { - auto leftString = serialize(c.l, context); - auto rightString = serialize(c.r, context); - std::stringstream ss; - ss << "(" << leftString << " " << static_cast(c) << " " << rightString << ")"; - return ss.str(); - } - };*/ - - /*template - struct statement_serializator::value>::type> { - using statement_type = T; - - template - std::string operator()(const statement_type &t, const C &) const { - std::stringstream ss; - ss << t; - return ss.str(); - } - };*/ - } } diff --git a/dev/storage.h b/dev/storage.h index 6794a2d5e..442ab55ad 100644 --- a/dev/storage.h +++ b/dev/storage.h @@ -50,20 +50,11 @@ namespace sqlite_orm { - //template - //internal::dynamic_order_by_t> dynamic_order_by(const S &storage); - - /*namespace conditions { - - template - struct dynamic_order_by_t; - }*/ - namespace internal { /** * Storage class itself. Create an instanse to use it as an interfacto to sqlite db by calling `make_storage` - * function. + * function. */ template struct storage_t : storage_base { @@ -169,218 +160,6 @@ namespace sqlite_orm { return this->impl.template get_impl(); } - /*template - typename std::enable_if::value, std::string>::type - string_from_expression(const T &, bool) const { - return "?"; - }*/ - - /*template - std::string string_from_expression(std::reference_wrapper ref, bool noTableName) const { - return this->string_from_expression(ref.get(), noTableName); - }*/ - - /*std::string string_from_expression(std::nullptr_t, bool) const { - return "?"; - }*/ - - /*template - std::string string_from_expression(const alias_holder &, bool) const { - return T::get(); - }*/ - - /*template - std::string string_from_expression(const core_function_t &c, bool noTableName) const { - std::stringstream ss; - ss << static_cast(c) << "("; - std::vector args; - using args_type = typename std::decay::type::args_type; - args.reserve(std::tuple_size::value); - iterate_tuple(c.args, [&args, this, noTableName](auto &v) { - args.push_back(this->string_from_expression(v, noTableName)); - }); - for(size_t i = 0; i < args.size(); ++i) { - ss << args[i]; - if(i < args.size() - 1) { - ss << ", "; - } - } - ss << ")"; - return ss.str(); - }*/ - - /*template - std::string string_from_expression(const as_t &als, bool noTableName) const { - auto tableAliasString = alias_extractor::get(); - return this->string_from_expression(als.expression, noTableName) + " AS " + tableAliasString; - }*/ - - /*template - std::string string_from_expression(const alias_column_t &als, bool noTableName) const { - std::stringstream ss; - if(!noTableName) { - ss << "'" << T::get() << "'."; - } - ss << this->string_from_expression(als.column, true); - return ss.str(); - }*/ - - /*std::string string_from_expression(const std::string &s, bool) const { - serializator_context_base context; - context.replace_bindable_with_question = true; - return serialize(s, context); - }*/ - - /*std::string string_from_expression(const char *s, bool) const { - serializator_context_base context; - context.replace_bindable_with_question = true; - return serialize(s, context); - }*/ - - /*template - std::string string_from_expression(F O::*m, bool noTableName) const { - using context_t = serializator_context; - context_t context{this->impl}; - context.skip_table_name = noTableName; - return serialize(m, context); - }*/ - - /*std::string string_from_expression(const rowid_t &rid, bool) const { - serializator_context_base context; - return serialize(rid, context); - }*/ - - /*std::string string_from_expression(const oid_t &rid, bool) const { - serializator_context_base context; - return serialize(rid, context); - }*/ - - /*std::string string_from_expression(const _rowid_t &rid, bool) const { - serializator_context_base context; - return serialize(rid, context); - }*/ - - /*template - std::string string_from_expression(const table_rowid_t &rid, bool noTableName) const { - std::stringstream ss; - if(!noTableName) { - ss << "'" << this->impl.find_table_name(typeid(O)) << "'."; - } - ss << static_cast(rid); - return ss.str(); - }*/ - - /*template - std::string string_from_expression(const table_oid_t &rid, bool noTableName) const { - std::stringstream ss; - if(!noTableName) { - ss << "'" << this->impl.find_table_name(typeid(O)) << "'."; - } - ss << static_cast(rid); - return ss.str(); - }*/ - - /*template - std::string string_from_expression(const table__rowid_t &rid, bool noTableName) const { - std::stringstream ss; - if(!noTableName) { - ss << "'" << this->impl.find_table_name(typeid(O)) << "'."; - } - ss << static_cast(rid); - return ss.str(); - }*/ - - /*template - std::string string_from_expression(const binary_operator &f, bool noTableName) const { - std::stringstream ss; - auto lhs = this->string_from_expression(f.lhs, noTableName); - auto rhs = this->string_from_expression(f.rhs, noTableName); - ss << "(" << lhs << " " << static_cast(f) << " " << rhs << ")"; - return ss.str(); - }*/ - - /*template - std::string string_from_expression(const count_asterisk_t &, bool noTableName) const { - return this->string_from_expression(internal::count_asterisk_without_type{}, noTableName); - }*/ - - /*std::string string_from_expression(const count_asterisk_without_type &f, - bool) const { - std::stringstream ss; - ss << static_cast(f) << "(*)"; - return ss.str(); - }*/ - - /*template - std::string string_from_expression(const distinct_t &f, bool noTableName) const { - std::stringstream ss; - auto expr = this->string_from_expression(f.t, noTableName); - ss << static_cast(f) << "(" << expr << ") "; - return ss.str(); - }*/ - - /*template - std::string string_from_expression(const all_t &f, bool noTableName) const { - std::stringstream ss; - auto expr = this->string_from_expression(f.t, noTableName); - ss << static_cast(f) << "(" << expr << ") "; - return ss.str(); - }*/ - - /*template - std::string string_from_expression(const column_pointer &c, bool noTableName) const { - std::stringstream ss; - if(!noTableName) { - ss << "'" << this->impl.find_table_name(typeid(T)) << "'."; - } - auto &tImpl = this->get_impl(); - ss << "\"" << tImpl.column_name_simple(c.field) << "\""; - return ss.str(); - }*/ - - /*template - std::vector get_column_names(const T &t) const { - using context_t = serializator_context; - context_t context{this->impl}; - context.skip_table_name = false; - auto columnName = serialize(t, context); - if(columnName.length()) { - return {move(columnName)}; - } else { - throw std::system_error(std::make_error_code(orm_error_code::column_not_found)); - } - }*/ - - /*template - std::vector get_column_names(std::reference_wrapper r) const { - return this->get_column_names(r.get()); - }*/ - - /*template - std::vector get_column_names(const asterisk_t &) const { - std::vector res; - res.push_back("*"); - return res; - }*/ - - /*template - std::vector get_column_names(const columns_t &cols) const { - std::vector columnNames; - columnNames.reserve(static_cast(cols.count)); - using context_t = serializator_context; - context_t context{this->impl}; - context.skip_table_name = false; - iterate_tuple(cols.columns, [&columnNames, &context](auto &m) { - auto columnName = serialize(m, context); - if(columnName.length()) { - columnNames.push_back(columnName); - } else { - throw std::system_error(std::make_error_code(orm_error_code::column_not_found)); - } - }); - return columnNames; - }*/ - // Common code for statements returning the whole content of a table: get_all_t, get_all_pointer_t, // get_all_optional_t. template @@ -815,330 +594,11 @@ namespace sqlite_orm { return ss.str(); } - /*template - std::string string_from_expression(const cast_t &c, bool noTableName) const { - std::stringstream ss; - ss << static_cast(c) << " ("; - ss << this->string_from_expression(c.expression, noTableName) << " AS " << type_printer().print() - << ")"; - return ss.str(); - }*/ - - /*template - typename std::enable_if::value, std::string>::type - string_from_expression(const T &op, bool noTableName) const { - std::stringstream ss; - ss << this->string_from_expression(op.left, noTableName) << " "; - ss << static_cast(op) << " "; - ss << this->string_from_expression(op.right, noTableName); - return ss.str(); - }*/ - - /*template - std::string string_from_expression(const simple_case_t &c, - bool noTableName) const { - std::stringstream ss; - ss << "CASE "; - c.case_expression.apply([&ss, this, noTableName](auto &c) { - ss << this->string_from_expression(c, noTableName) << " "; - }); - iterate_tuple(c.args, [&ss, this, noTableName](auto &pair) { - ss << "WHEN " << this->string_from_expression(pair.first, noTableName) << " "; - ss << "THEN " << this->string_from_expression(pair.second, noTableName) << " "; - }); - c.else_expression.apply([&ss, this, noTableName](auto &el) { - ss << "ELSE " << this->string_from_expression(el, noTableName) << " "; - }); - ss << "END"; - return ss.str(); - }*/ - - /*template - std::string string_from_expression(const is_null_t &c, bool noTableName) const { - std::stringstream ss; - ss << this->string_from_expression(c.t, noTableName) << " " << static_cast(c) << " "; - return ss.str(); - }*/ - - /*template - std::string string_from_expression(const is_not_null_t &c, bool noTableName) const { - std::stringstream ss; - ss << this->string_from_expression(c.t, noTableName) << " " << static_cast(c) << " "; - return ss.str(); - }*/ - - /*template - std::string string_from_expression(const bitwise_not_t &arg, bool noTableName) const { - std::stringstream ss; - ss << static_cast(arg) << " "; - auto cString = this->string_from_expression(arg.argument, noTableName); - ss << " (" << cString << " ) "; - return ss.str(); - }*/ - - /*template - std::string string_from_expression(const negated_condition_t &c, bool noTableName) const { - std::stringstream ss; - ss << static_cast(c) << " "; - auto cString = this->string_from_expression(c.c, noTableName); - ss << " (" << cString << " ) "; - return ss.str(); - }*/ - - /*template - std::string string_from_expression(const is_equal_t &c, bool noTableName) const { - auto leftString = this->string_from_expression(c.l, noTableName); - auto rightString = this->string_from_expression(c.r, noTableName); - std::stringstream ss; - ss << leftString << " " << static_cast(c) << " " << rightString; - return ss.str(); - }*/ - - /*template - typename std::enable_if::value, std::string>::type - string_from_expression(const C &c, bool noTableName) const { - auto leftString = this->string_from_expression(c.l, noTableName); - auto rightString = this->string_from_expression(c.r, noTableName); - std::stringstream ss; - ss << "(" << leftString << " " << static_cast(c) << " " << rightString << ")"; - return ss.str(); - }*/ - - /*template - std::string string_from_expression(const named_collate &col, bool noTableName) const { - auto res = this->string_from_expression(col.expr, noTableName); - return res + " " + static_cast(col); - }*/ - - /*template - std::string string_from_expression(const collate_t &col, bool noTableName) const { - auto res = this->string_from_expression(col.expr, noTableName); - return res + " " + static_cast(col); - }*/ - - /*template - std::string string_from_expression(const in_t &inCondition, bool noTableName) const { - std::stringstream ss; - auto leftString = this->string_from_expression(inCondition.l, noTableName); - ss << leftString << " " << static_cast(inCondition) << " "; - ss << this->string_from_expression(inCondition.arg, noTableName); - return ss.str(); - }*/ - - /*template - std::string string_from_expression(const in_t> &inCondition, bool noTableName) const { - std::stringstream ss; - auto leftString = this->string_from_expression(inCondition.l, noTableName); - ss << leftString << " " << static_cast(inCondition) << " ( "; - for(size_t index = 0; index < inCondition.arg.size(); ++index) { - auto &value = inCondition.arg[index]; - ss << " " << this->string_from_expression(value, noTableName); - if(index < inCondition.arg.size() - 1) { - ss << ", "; - } - } - ss << " )"; - return ss.str(); - }*/ - - /*template - std::string string_from_expression(const like_t &l, bool noTableName) const { - std::stringstream ss; - ss << this->string_from_expression(l.arg, noTableName) << " "; - ss << static_cast(l) << " "; - ss << this->string_from_expression(l.pattern, noTableName); - l.arg3.apply([&ss, this, noTableName](auto &value) { - ss << " ESCAPE " << this->string_from_expression(value, noTableName); - }); - return ss.str(); - }*/ - - /*template - std::string string_from_expression(const glob_t &l, bool noTableName) const { - std::stringstream ss; - ss << this->string_from_expression(l.arg, noTableName) << " "; - ss << static_cast(l) << " "; - ss << this->string_from_expression(l.pattern, noTableName); - return ss.str(); - }*/ - - /*template - std::string string_from_expression(const between_t &bw, bool noTableName) const { - std::stringstream ss; - auto expr = this->string_from_expression(bw.expr, noTableName); - ss << expr << " " << static_cast(bw) << " "; - ss << this->string_from_expression(bw.b1, noTableName); - ss << " AND "; - ss << this->string_from_expression(bw.b2, noTableName); - return ss.str(); - }*/ - - /*template - std::string string_from_expression(const exists_t &e, bool noTableName) const { - std::stringstream ss; - ss << static_cast(e) << " "; - ss << this->string_from_expression(e.t, noTableName); - return ss.str(); - }*/ - - /*template - std::string process_order_by(const order_by_t &orderBy) const { - std::stringstream ss; - using context_t = serializator_context; - context_t context{this->impl}; - context.skip_table_name = false; - auto columnName = serialize(orderBy.o, context); - ss << columnName << " "; - if(orderBy._collate_argument.length()) { - ss << "COLLATE " << orderBy._collate_argument << " "; - } - switch(orderBy.asc_desc) { - case 1: - ss << "ASC"; - break; - case -1: - ss << "DESC"; - break; - } - return ss.str(); - }*/ - - /*template - void process_join_constraint(std::stringstream &ss, const on_t &t) const { - using context_t = serializator_context; - context_t context{this->impl}; - context.skip_table_name = false; - ss << static_cast(t) << " " << serialize(t.arg, context); - }*/ - template void process_join_constraint(std::stringstream &ss, const using_t &u) const { ss << static_cast(u) << " (" << this->string_from_expression(u.column, true) << " )"; } - /** - * HO - has offset - * OI - offset is implicit - */ - /*template - std::string string_from_expression(const limit_t &limt, bool) const { - std::stringstream ss; - ss << static_cast(limt) << " "; - if(HO) { - if(OI) { - limt.off.apply([this, &ss](auto &value) { - ss << this->string_from_expression(value, false); - }); - ss << ", "; - ss << this->string_from_expression(limt.lim, false); - } else { - ss << this->string_from_expression(limt.lim, false) << " OFFSET "; - limt.off.apply([this, &ss](auto &value) { - ss << this->string_from_expression(value, false); - }); - } - } else { - ss << this->string_from_expression(limt.lim, false); - } - return ss.str(); - }*/ - - /*template - std::string string_from_expression(const cross_join_t &c, bool) const { - std::stringstream ss; - ss << static_cast(c) << " "; - ss << " '" << this->impl.find_table_name(typeid(O)) << "'"; - return ss.str(); - }*/ - - /*template - std::string string_from_expression(const natural_join_t &c, bool) const { - std::stringstream ss; - ss << static_cast(c) << " "; - ss << " '" << this->impl.find_table_name(typeid(O)) << "'"; - return ss.str(); - }*/ - - /*template - std::string string_from_expression(const inner_join_t &l, bool) const { - std::stringstream ss; - ss << static_cast(l) << " "; - auto aliasString = alias_extractor::get(); - ss << " '" << this->impl.find_table_name(typeid(typename mapped_type_proxy::type)) << "' "; - if(aliasString.length()) { - ss << "'" << aliasString << "' "; - } - this->process_join_constraint(ss, l.constraint); - return ss.str(); - }*/ - - /*template - std::string string_from_expression(const left_outer_join_t &l, bool) const { - std::stringstream ss; - ss << static_cast(l) << " "; - ss << " '" << this->impl.find_table_name(typeid(T)) << "' "; - this->process_join_constraint(ss, l.constraint); - return ss.str(); - }*/ - - /*template - std::string string_from_expression(const left_join_t &l, bool) const { - std::stringstream ss; - ss << static_cast(l) << " "; - ss << " '" << this->impl.find_table_name(typeid(T)) << "' "; - this->process_join_constraint(ss, l.constraint); - return ss.str(); - }*/ - - /*template - std::string string_from_expression(const join_t &l, bool) const { - std::stringstream ss; - ss << static_cast(l) << " "; - ss << " '" << this->impl.find_table_name(typeid(T)) << "' "; - this->process_join_constraint(ss, l.constraint); - return ss.str(); - }*/ - - /*template - std::string string_from_expression(const where_t &w, bool) const { - std::stringstream ss; - ss << static_cast(w) << " "; -// auto whereString = this->string_from_expression(w.c, false); - using context_t = serializator_context; - context_t context{this->impl}; - auto whereString = serialize(w.c, context); - ss << "( " << whereString << ") "; - return ss.str(); - }*/ - - /*template - std::string string_from_expression(const order_by_t &orderBy, bool) const { - std::stringstream ss; - ss << static_cast(orderBy) << " "; - auto orderByString = this->process_order_by(orderBy); - ss << orderByString << " "; - return ss.str(); - }*/ - - /*template - std::string string_from_expression(const multi_order_by_t &orderBy, bool) const { - std::stringstream ss; - std::vector expressions; - iterate_tuple(orderBy.args, [&expressions, this](auto &v) { - auto expression = this->process_order_by(v); - expressions.push_back(std::move(expression)); - }); - ss << static_cast(orderBy) << " "; - for(size_t i = 0; i < expressions.size(); ++i) { - ss << expressions[i]; - if(i < expressions.size() - 1) { - ss << ", "; - } - } - ss << " "; - return ss.str(); - }*/ - template std::string string_from_expression(const dynamic_order_by_t &orderBy, bool) const { std::stringstream ss; @@ -1146,33 +606,6 @@ namespace sqlite_orm { return ss.str(); } - /*template - std::string string_from_expression(const group_by_t &groupBy, bool) const { - std::stringstream ss; - std::vector expressions; - iterate_tuple(groupBy.args, [&expressions, this](auto &v) { - auto expression = this->string_from_expression(v, false); - expressions.push_back(expression); - }); - ss << static_cast(groupBy) << " "; - for(size_t i = 0; i < expressions.size(); ++i) { - ss << expressions[i]; - if(i < expressions.size() - 1) { - ss << ", "; - } - } - ss << " "; - return ss.str(); - }*/ - - /*template - std::string string_from_expression(const having_t &hav, bool) const { - std::stringstream ss; - ss << static_cast(hav) << " "; - ss << this->string_from_expression(hav.t, false) << " "; - return ss.str(); - }*/ - template void process_conditions(std::stringstream &ss, const std::tuple &args) const { using context_t = serializator_context; @@ -1232,13 +665,6 @@ namespace sqlite_orm { } protected: - // template - // friend dynamic_order_by_t> dynamic_order_by(const S &storage); - // friend dynamic_order_by_t> dynamic_order_by(const S &storage) - - // template - // friend dynamic_order_by_t> dynamic_order_by(const S &storage); - template std::string group_concat_internal(F O::*m, std::unique_ptr y, Args &&... args) { this->assert_mapped_type(); diff --git a/dev/storage_base.h b/dev/storage_base.h index e98d0a0fa..db8467082 100644 --- a/dev/storage_base.h +++ b/dev/storage_base.h @@ -500,41 +500,6 @@ namespace sqlite_orm { } } - /*template - std::string process_order_by(const dynamic_order_by_t &orderBy) const { - std::vector expressions; - for(auto &entry: orderBy) { - std::string entryString; - { - std::stringstream ss; - ss << entry.name << " "; - if(!entry._collate_argument.empty()) { - ss << "COLLATE " << entry._collate_argument << " "; - } - switch(entry.asc_desc) { - case 1: - ss << "ASC"; - break; - case -1: - ss << "DESC"; - break; - } - entryString = ss.str(); - } - expressions.push_back(move(entryString)); - }; - std::stringstream ss; - ss << static_cast(orderBy) << " "; - for(size_t i = 0; i < expressions.size(); ++i) { - ss << expressions[i]; - if(i < expressions.size() - 1) { - ss << ", "; - } - } - ss << " "; - return ss.str(); - }*/ - static int collate_callback(void *arg, int leftLen, const void *lhs, int rightLen, const void *rhs) { auto &f = *(collating_function *)arg; return f(leftLen, lhs, rightLen, rhs); diff --git a/include/sqlite_orm/sqlite_orm.h b/include/sqlite_orm/sqlite_orm.h index 1f6d57e1d..a7babd8ad 100644 --- a/include/sqlite_orm/sqlite_orm.h +++ b/include/sqlite_orm/sqlite_orm.h @@ -3138,10 +3138,6 @@ namespace sqlite_orm { dynamic_order_by(const S &storage) { internal::serializator_context_builder builder(storage); return builder(); - /*using context_t = internal::serializator_context; - using return_type = internal::dynamic_order_by_t; - context_t context{storage.impl}; - return return_type{std::move(context)};*/ } /** @@ -8855,41 +8851,6 @@ namespace sqlite_orm { } } - /*template - std::string process_order_by(const dynamic_order_by_t &orderBy) const { - std::vector expressions; - for(auto &entry: orderBy) { - std::string entryString; - { - std::stringstream ss; - ss << entry.name << " "; - if(!entry._collate_argument.empty()) { - ss << "COLLATE " << entry._collate_argument << " "; - } - switch(entry.asc_desc) { - case 1: - ss << "ASC"; - break; - case -1: - ss << "DESC"; - break; - } - entryString = ss.str(); - } - expressions.push_back(move(entryString)); - }; - std::stringstream ss; - ss << static_cast(orderBy) << " "; - for(size_t i = 0; i < expressions.size(); ++i) { - ss << expressions[i]; - if(i < expressions.size() - 1) { - ss << ", "; - } - } - ss << " "; - return ss.str(); - }*/ - static int collate_callback(void *arg, int leftLen, const void *lhs, int rightLen, const void *rhs) { auto &f = *(collating_function *)arg; return f(leftLen, lhs, rightLen, rhs); @@ -9312,22 +9273,6 @@ namespace sqlite_orm { return serializator(t, context); } - /*template - struct statement_serializator::value>::type> { - using statement_type = T; - - template - std::string operator()(const statement_type &statement, const C &context) { - if(context.replace_bindable_with_question){ - return "?"; - }else{ - std::stringstream ss; - ss << statement; - return ss.str(); - } - } - };*/ - template struct statement_serializator::value>::type> { using statement_type = T; @@ -10309,9 +10254,9 @@ namespace sqlite_orm { }; /** - * HO - has offset - * OI - offset is implicit - */ + * HO - has offset + * OI - offset is implicit + */ template struct statement_serializator, void> { using statement_type = limit_t; @@ -10341,35 +10286,6 @@ namespace sqlite_orm { return ss.str(); } }; - - /*template - struct statement_serializator< - T, - typename std::enable_if::value>::type> { - using statement_type = T; - - template - std::string operator()(const statement_type &c, const C &context) const { - auto leftString = serialize(c.l, context); - auto rightString = serialize(c.r, context); - std::stringstream ss; - ss << "(" << leftString << " " << static_cast(c) << " " << rightString << ")"; - return ss.str(); - } - };*/ - - /*template - struct statement_serializator::value>::type> { - using statement_type = T; - - template - std::string operator()(const statement_type &t, const C &) const { - std::stringstream ss; - ss << t; - return ss.str(); - } - };*/ - } } @@ -10377,20 +10293,11 @@ namespace sqlite_orm { namespace sqlite_orm { - //template - //internal::dynamic_order_by_t> dynamic_order_by(const S &storage); - - /*namespace conditions { - - template - struct dynamic_order_by_t; - }*/ - namespace internal { /** * Storage class itself. Create an instanse to use it as an interfacto to sqlite db by calling `make_storage` - * function. + * function. */ template struct storage_t : storage_base { @@ -10496,218 +10403,6 @@ namespace sqlite_orm { return this->impl.template get_impl(); } - /*template - typename std::enable_if::value, std::string>::type - string_from_expression(const T &, bool) const { - return "?"; - }*/ - - /*template - std::string string_from_expression(std::reference_wrapper ref, bool noTableName) const { - return this->string_from_expression(ref.get(), noTableName); - }*/ - - /*std::string string_from_expression(std::nullptr_t, bool) const { - return "?"; - }*/ - - /*template - std::string string_from_expression(const alias_holder &, bool) const { - return T::get(); - }*/ - - /*template - std::string string_from_expression(const core_function_t &c, bool noTableName) const { - std::stringstream ss; - ss << static_cast(c) << "("; - std::vector args; - using args_type = typename std::decay::type::args_type; - args.reserve(std::tuple_size::value); - iterate_tuple(c.args, [&args, this, noTableName](auto &v) { - args.push_back(this->string_from_expression(v, noTableName)); - }); - for(size_t i = 0; i < args.size(); ++i) { - ss << args[i]; - if(i < args.size() - 1) { - ss << ", "; - } - } - ss << ")"; - return ss.str(); - }*/ - - /*template - std::string string_from_expression(const as_t &als, bool noTableName) const { - auto tableAliasString = alias_extractor::get(); - return this->string_from_expression(als.expression, noTableName) + " AS " + tableAliasString; - }*/ - - /*template - std::string string_from_expression(const alias_column_t &als, bool noTableName) const { - std::stringstream ss; - if(!noTableName) { - ss << "'" << T::get() << "'."; - } - ss << this->string_from_expression(als.column, true); - return ss.str(); - }*/ - - /*std::string string_from_expression(const std::string &s, bool) const { - serializator_context_base context; - context.replace_bindable_with_question = true; - return serialize(s, context); - }*/ - - /*std::string string_from_expression(const char *s, bool) const { - serializator_context_base context; - context.replace_bindable_with_question = true; - return serialize(s, context); - }*/ - - /*template - std::string string_from_expression(F O::*m, bool noTableName) const { - using context_t = serializator_context; - context_t context{this->impl}; - context.skip_table_name = noTableName; - return serialize(m, context); - }*/ - - /*std::string string_from_expression(const rowid_t &rid, bool) const { - serializator_context_base context; - return serialize(rid, context); - }*/ - - /*std::string string_from_expression(const oid_t &rid, bool) const { - serializator_context_base context; - return serialize(rid, context); - }*/ - - /*std::string string_from_expression(const _rowid_t &rid, bool) const { - serializator_context_base context; - return serialize(rid, context); - }*/ - - /*template - std::string string_from_expression(const table_rowid_t &rid, bool noTableName) const { - std::stringstream ss; - if(!noTableName) { - ss << "'" << this->impl.find_table_name(typeid(O)) << "'."; - } - ss << static_cast(rid); - return ss.str(); - }*/ - - /*template - std::string string_from_expression(const table_oid_t &rid, bool noTableName) const { - std::stringstream ss; - if(!noTableName) { - ss << "'" << this->impl.find_table_name(typeid(O)) << "'."; - } - ss << static_cast(rid); - return ss.str(); - }*/ - - /*template - std::string string_from_expression(const table__rowid_t &rid, bool noTableName) const { - std::stringstream ss; - if(!noTableName) { - ss << "'" << this->impl.find_table_name(typeid(O)) << "'."; - } - ss << static_cast(rid); - return ss.str(); - }*/ - - /*template - std::string string_from_expression(const binary_operator &f, bool noTableName) const { - std::stringstream ss; - auto lhs = this->string_from_expression(f.lhs, noTableName); - auto rhs = this->string_from_expression(f.rhs, noTableName); - ss << "(" << lhs << " " << static_cast(f) << " " << rhs << ")"; - return ss.str(); - }*/ - - /*template - std::string string_from_expression(const count_asterisk_t &, bool noTableName) const { - return this->string_from_expression(internal::count_asterisk_without_type{}, noTableName); - }*/ - - /*std::string string_from_expression(const count_asterisk_without_type &f, - bool) const { - std::stringstream ss; - ss << static_cast(f) << "(*)"; - return ss.str(); - }*/ - - /*template - std::string string_from_expression(const distinct_t &f, bool noTableName) const { - std::stringstream ss; - auto expr = this->string_from_expression(f.t, noTableName); - ss << static_cast(f) << "(" << expr << ") "; - return ss.str(); - }*/ - - /*template - std::string string_from_expression(const all_t &f, bool noTableName) const { - std::stringstream ss; - auto expr = this->string_from_expression(f.t, noTableName); - ss << static_cast(f) << "(" << expr << ") "; - return ss.str(); - }*/ - - /*template - std::string string_from_expression(const column_pointer &c, bool noTableName) const { - std::stringstream ss; - if(!noTableName) { - ss << "'" << this->impl.find_table_name(typeid(T)) << "'."; - } - auto &tImpl = this->get_impl(); - ss << "\"" << tImpl.column_name_simple(c.field) << "\""; - return ss.str(); - }*/ - - /*template - std::vector get_column_names(const T &t) const { - using context_t = serializator_context; - context_t context{this->impl}; - context.skip_table_name = false; - auto columnName = serialize(t, context); - if(columnName.length()) { - return {move(columnName)}; - } else { - throw std::system_error(std::make_error_code(orm_error_code::column_not_found)); - } - }*/ - - /*template - std::vector get_column_names(std::reference_wrapper r) const { - return this->get_column_names(r.get()); - }*/ - - /*template - std::vector get_column_names(const asterisk_t &) const { - std::vector res; - res.push_back("*"); - return res; - }*/ - - /*template - std::vector get_column_names(const columns_t &cols) const { - std::vector columnNames; - columnNames.reserve(static_cast(cols.count)); - using context_t = serializator_context; - context_t context{this->impl}; - context.skip_table_name = false; - iterate_tuple(cols.columns, [&columnNames, &context](auto &m) { - auto columnName = serialize(m, context); - if(columnName.length()) { - columnNames.push_back(columnName); - } else { - throw std::system_error(std::make_error_code(orm_error_code::column_not_found)); - } - }); - return columnNames; - }*/ - // Common code for statements returning the whole content of a table: get_all_t, get_all_pointer_t, // get_all_optional_t. template @@ -11142,330 +10837,11 @@ namespace sqlite_orm { return ss.str(); } - /*template - std::string string_from_expression(const cast_t &c, bool noTableName) const { - std::stringstream ss; - ss << static_cast(c) << " ("; - ss << this->string_from_expression(c.expression, noTableName) << " AS " << type_printer().print() - << ")"; - return ss.str(); - }*/ - - /*template - typename std::enable_if::value, std::string>::type - string_from_expression(const T &op, bool noTableName) const { - std::stringstream ss; - ss << this->string_from_expression(op.left, noTableName) << " "; - ss << static_cast(op) << " "; - ss << this->string_from_expression(op.right, noTableName); - return ss.str(); - }*/ - - /*template - std::string string_from_expression(const simple_case_t &c, - bool noTableName) const { - std::stringstream ss; - ss << "CASE "; - c.case_expression.apply([&ss, this, noTableName](auto &c) { - ss << this->string_from_expression(c, noTableName) << " "; - }); - iterate_tuple(c.args, [&ss, this, noTableName](auto &pair) { - ss << "WHEN " << this->string_from_expression(pair.first, noTableName) << " "; - ss << "THEN " << this->string_from_expression(pair.second, noTableName) << " "; - }); - c.else_expression.apply([&ss, this, noTableName](auto &el) { - ss << "ELSE " << this->string_from_expression(el, noTableName) << " "; - }); - ss << "END"; - return ss.str(); - }*/ - - /*template - std::string string_from_expression(const is_null_t &c, bool noTableName) const { - std::stringstream ss; - ss << this->string_from_expression(c.t, noTableName) << " " << static_cast(c) << " "; - return ss.str(); - }*/ - - /*template - std::string string_from_expression(const is_not_null_t &c, bool noTableName) const { - std::stringstream ss; - ss << this->string_from_expression(c.t, noTableName) << " " << static_cast(c) << " "; - return ss.str(); - }*/ - - /*template - std::string string_from_expression(const bitwise_not_t &arg, bool noTableName) const { - std::stringstream ss; - ss << static_cast(arg) << " "; - auto cString = this->string_from_expression(arg.argument, noTableName); - ss << " (" << cString << " ) "; - return ss.str(); - }*/ - - /*template - std::string string_from_expression(const negated_condition_t &c, bool noTableName) const { - std::stringstream ss; - ss << static_cast(c) << " "; - auto cString = this->string_from_expression(c.c, noTableName); - ss << " (" << cString << " ) "; - return ss.str(); - }*/ - - /*template - std::string string_from_expression(const is_equal_t &c, bool noTableName) const { - auto leftString = this->string_from_expression(c.l, noTableName); - auto rightString = this->string_from_expression(c.r, noTableName); - std::stringstream ss; - ss << leftString << " " << static_cast(c) << " " << rightString; - return ss.str(); - }*/ - - /*template - typename std::enable_if::value, std::string>::type - string_from_expression(const C &c, bool noTableName) const { - auto leftString = this->string_from_expression(c.l, noTableName); - auto rightString = this->string_from_expression(c.r, noTableName); - std::stringstream ss; - ss << "(" << leftString << " " << static_cast(c) << " " << rightString << ")"; - return ss.str(); - }*/ - - /*template - std::string string_from_expression(const named_collate &col, bool noTableName) const { - auto res = this->string_from_expression(col.expr, noTableName); - return res + " " + static_cast(col); - }*/ - - /*template - std::string string_from_expression(const collate_t &col, bool noTableName) const { - auto res = this->string_from_expression(col.expr, noTableName); - return res + " " + static_cast(col); - }*/ - - /*template - std::string string_from_expression(const in_t &inCondition, bool noTableName) const { - std::stringstream ss; - auto leftString = this->string_from_expression(inCondition.l, noTableName); - ss << leftString << " " << static_cast(inCondition) << " "; - ss << this->string_from_expression(inCondition.arg, noTableName); - return ss.str(); - }*/ - - /*template - std::string string_from_expression(const in_t> &inCondition, bool noTableName) const { - std::stringstream ss; - auto leftString = this->string_from_expression(inCondition.l, noTableName); - ss << leftString << " " << static_cast(inCondition) << " ( "; - for(size_t index = 0; index < inCondition.arg.size(); ++index) { - auto &value = inCondition.arg[index]; - ss << " " << this->string_from_expression(value, noTableName); - if(index < inCondition.arg.size() - 1) { - ss << ", "; - } - } - ss << " )"; - return ss.str(); - }*/ - - /*template - std::string string_from_expression(const like_t &l, bool noTableName) const { - std::stringstream ss; - ss << this->string_from_expression(l.arg, noTableName) << " "; - ss << static_cast(l) << " "; - ss << this->string_from_expression(l.pattern, noTableName); - l.arg3.apply([&ss, this, noTableName](auto &value) { - ss << " ESCAPE " << this->string_from_expression(value, noTableName); - }); - return ss.str(); - }*/ - - /*template - std::string string_from_expression(const glob_t &l, bool noTableName) const { - std::stringstream ss; - ss << this->string_from_expression(l.arg, noTableName) << " "; - ss << static_cast(l) << " "; - ss << this->string_from_expression(l.pattern, noTableName); - return ss.str(); - }*/ - - /*template - std::string string_from_expression(const between_t &bw, bool noTableName) const { - std::stringstream ss; - auto expr = this->string_from_expression(bw.expr, noTableName); - ss << expr << " " << static_cast(bw) << " "; - ss << this->string_from_expression(bw.b1, noTableName); - ss << " AND "; - ss << this->string_from_expression(bw.b2, noTableName); - return ss.str(); - }*/ - - /*template - std::string string_from_expression(const exists_t &e, bool noTableName) const { - std::stringstream ss; - ss << static_cast(e) << " "; - ss << this->string_from_expression(e.t, noTableName); - return ss.str(); - }*/ - - /*template - std::string process_order_by(const order_by_t &orderBy) const { - std::stringstream ss; - using context_t = serializator_context; - context_t context{this->impl}; - context.skip_table_name = false; - auto columnName = serialize(orderBy.o, context); - ss << columnName << " "; - if(orderBy._collate_argument.length()) { - ss << "COLLATE " << orderBy._collate_argument << " "; - } - switch(orderBy.asc_desc) { - case 1: - ss << "ASC"; - break; - case -1: - ss << "DESC"; - break; - } - return ss.str(); - }*/ - - /*template - void process_join_constraint(std::stringstream &ss, const on_t &t) const { - using context_t = serializator_context; - context_t context{this->impl}; - context.skip_table_name = false; - ss << static_cast(t) << " " << serialize(t.arg, context); - }*/ - template void process_join_constraint(std::stringstream &ss, const using_t &u) const { ss << static_cast(u) << " (" << this->string_from_expression(u.column, true) << " )"; } - /** - * HO - has offset - * OI - offset is implicit - */ - /*template - std::string string_from_expression(const limit_t &limt, bool) const { - std::stringstream ss; - ss << static_cast(limt) << " "; - if(HO) { - if(OI) { - limt.off.apply([this, &ss](auto &value) { - ss << this->string_from_expression(value, false); - }); - ss << ", "; - ss << this->string_from_expression(limt.lim, false); - } else { - ss << this->string_from_expression(limt.lim, false) << " OFFSET "; - limt.off.apply([this, &ss](auto &value) { - ss << this->string_from_expression(value, false); - }); - } - } else { - ss << this->string_from_expression(limt.lim, false); - } - return ss.str(); - }*/ - - /*template - std::string string_from_expression(const cross_join_t &c, bool) const { - std::stringstream ss; - ss << static_cast(c) << " "; - ss << " '" << this->impl.find_table_name(typeid(O)) << "'"; - return ss.str(); - }*/ - - /*template - std::string string_from_expression(const natural_join_t &c, bool) const { - std::stringstream ss; - ss << static_cast(c) << " "; - ss << " '" << this->impl.find_table_name(typeid(O)) << "'"; - return ss.str(); - }*/ - - /*template - std::string string_from_expression(const inner_join_t &l, bool) const { - std::stringstream ss; - ss << static_cast(l) << " "; - auto aliasString = alias_extractor::get(); - ss << " '" << this->impl.find_table_name(typeid(typename mapped_type_proxy::type)) << "' "; - if(aliasString.length()) { - ss << "'" << aliasString << "' "; - } - this->process_join_constraint(ss, l.constraint); - return ss.str(); - }*/ - - /*template - std::string string_from_expression(const left_outer_join_t &l, bool) const { - std::stringstream ss; - ss << static_cast(l) << " "; - ss << " '" << this->impl.find_table_name(typeid(T)) << "' "; - this->process_join_constraint(ss, l.constraint); - return ss.str(); - }*/ - - /*template - std::string string_from_expression(const left_join_t &l, bool) const { - std::stringstream ss; - ss << static_cast(l) << " "; - ss << " '" << this->impl.find_table_name(typeid(T)) << "' "; - this->process_join_constraint(ss, l.constraint); - return ss.str(); - }*/ - - /*template - std::string string_from_expression(const join_t &l, bool) const { - std::stringstream ss; - ss << static_cast(l) << " "; - ss << " '" << this->impl.find_table_name(typeid(T)) << "' "; - this->process_join_constraint(ss, l.constraint); - return ss.str(); - }*/ - - /*template - std::string string_from_expression(const where_t &w, bool) const { - std::stringstream ss; - ss << static_cast(w) << " "; -// auto whereString = this->string_from_expression(w.c, false); - using context_t = serializator_context; - context_t context{this->impl}; - auto whereString = serialize(w.c, context); - ss << "( " << whereString << ") "; - return ss.str(); - }*/ - - /*template - std::string string_from_expression(const order_by_t &orderBy, bool) const { - std::stringstream ss; - ss << static_cast(orderBy) << " "; - auto orderByString = this->process_order_by(orderBy); - ss << orderByString << " "; - return ss.str(); - }*/ - - /*template - std::string string_from_expression(const multi_order_by_t &orderBy, bool) const { - std::stringstream ss; - std::vector expressions; - iterate_tuple(orderBy.args, [&expressions, this](auto &v) { - auto expression = this->process_order_by(v); - expressions.push_back(std::move(expression)); - }); - ss << static_cast(orderBy) << " "; - for(size_t i = 0; i < expressions.size(); ++i) { - ss << expressions[i]; - if(i < expressions.size() - 1) { - ss << ", "; - } - } - ss << " "; - return ss.str(); - }*/ - template std::string string_from_expression(const dynamic_order_by_t &orderBy, bool) const { std::stringstream ss; @@ -11473,33 +10849,6 @@ namespace sqlite_orm { return ss.str(); } - /*template - std::string string_from_expression(const group_by_t &groupBy, bool) const { - std::stringstream ss; - std::vector expressions; - iterate_tuple(groupBy.args, [&expressions, this](auto &v) { - auto expression = this->string_from_expression(v, false); - expressions.push_back(expression); - }); - ss << static_cast(groupBy) << " "; - for(size_t i = 0; i < expressions.size(); ++i) { - ss << expressions[i]; - if(i < expressions.size() - 1) { - ss << ", "; - } - } - ss << " "; - return ss.str(); - }*/ - - /*template - std::string string_from_expression(const having_t &hav, bool) const { - std::stringstream ss; - ss << static_cast(hav) << " "; - ss << this->string_from_expression(hav.t, false) << " "; - return ss.str(); - }*/ - template void process_conditions(std::stringstream &ss, const std::tuple &args) const { using context_t = serializator_context; @@ -11559,13 +10908,6 @@ namespace sqlite_orm { } protected: - // template - // friend dynamic_order_by_t> dynamic_order_by(const S &storage); - // friend dynamic_order_by_t> dynamic_order_by(const S &storage) - - // template - // friend dynamic_order_by_t> dynamic_order_by(const S &storage); - template std::string group_concat_internal(F O::*m, std::unique_ptr y, Args &&... args) { this->assert_mapped_type(); From 0ffb85ddc7c692fc31e5631a321768bed55a840f Mon Sep 17 00:00:00 2001 From: fnc12 Date: Mon, 27 Apr 2020 10:35:51 +0300 Subject: [PATCH 058/132] added statement serializator for using --- dev/statement_serializator.h | 14 +++++- include/sqlite_orm/sqlite_orm.h | 88 +++++++++++++++++++++++++++++---- 2 files changed, 92 insertions(+), 10 deletions(-) diff --git a/dev/statement_serializator.h b/dev/statement_serializator.h index c63576b9f..51fc4eecb 100644 --- a/dev/statement_serializator.h +++ b/dev/statement_serializator.h @@ -908,7 +908,7 @@ namespace sqlite_orm { std::stringstream ss; auto newContext = context; newContext.skip_table_name = false; - ss << static_cast(t) << " " << serialize(t.arg, newContext); + ss << static_cast(t) << " " << serialize(t.arg, newContext) << " "; return ss.str(); } }; @@ -1042,5 +1042,17 @@ namespace sqlite_orm { return ss.str(); } }; + + template + struct statement_serializator, void> { + using statement_type = using_t; + + template + std::string operator()(const statement_type &statement, const C &context) const { + auto newContext = context; + newContext.skip_table_name = true; + return static_cast(statement) + " (" + serialize(statement.column, newContext) + " )"; + } + }; } } diff --git a/include/sqlite_orm/sqlite_orm.h b/include/sqlite_orm/sqlite_orm.h index a7babd8ad..e558a2337 100644 --- a/include/sqlite_orm/sqlite_orm.h +++ b/include/sqlite_orm/sqlite_orm.h @@ -27,7 +27,7 @@ __pragma(push_macro("min")) #include #include // std::ostringstream - namespace sqlite_orm { +namespace sqlite_orm { enum class orm_error_code { not_found = 1, @@ -44,6 +44,7 @@ __pragma(push_macro("min")) failed_to_init_a_backup, unknown_member_value, }; + } namespace sqlite_orm { @@ -224,6 +225,7 @@ namespace sqlite_orm { // #include "static_magic.h" + #include // std::false_type, std::true_type, std::integral_constant namespace sqlite_orm { @@ -258,6 +260,7 @@ namespace sqlite_orm { } + namespace sqlite_orm { // got from here http://stackoverflow.com/questions/25958259/how-do-i-find-out-if-a-tuple-contains-a-type @@ -989,6 +992,7 @@ namespace sqlite_orm { // #include "serializator_context.h" + namespace sqlite_orm { namespace internal { @@ -1036,6 +1040,7 @@ namespace sqlite_orm { } + namespace sqlite_orm { namespace internal { @@ -1070,12 +1075,14 @@ namespace sqlite_orm { // #include "negatable.h" + namespace sqlite_orm { namespace internal { struct negatable_t {}; } } + namespace sqlite_orm { namespace internal { @@ -1375,6 +1382,7 @@ namespace sqlite_orm { // #include "getter_traits.h" + namespace sqlite_orm { namespace internal { @@ -1558,6 +1566,7 @@ namespace sqlite_orm { } } + namespace sqlite_orm { namespace internal { @@ -1888,6 +1897,7 @@ namespace sqlite_orm { // #include "optional_container.h" + namespace sqlite_orm { namespace internal { @@ -1922,6 +1932,7 @@ namespace sqlite_orm { // #include "negatable.h" + namespace sqlite_orm { namespace internal { @@ -3371,6 +3382,7 @@ namespace sqlite_orm { // #include "conditions.h" + namespace sqlite_orm { namespace internal { @@ -3490,6 +3502,7 @@ namespace sqlite_orm { // #include "is_base_of_template.h" + #include // std::true_type, std::false_type, std::declval namespace sqlite_orm { @@ -3527,6 +3540,7 @@ namespace sqlite_orm { } } + namespace sqlite_orm { namespace internal { @@ -4279,6 +4293,7 @@ namespace sqlite_orm { // #include "optional_container.h" + namespace sqlite_orm { namespace internal { @@ -4631,6 +4646,7 @@ namespace sqlite_orm { // #include "column.h" + namespace sqlite_orm { namespace internal { @@ -4737,6 +4753,7 @@ namespace sqlite_orm { // #include "is_std_ptr.h" + namespace sqlite_orm { /** @@ -4764,6 +4781,7 @@ namespace sqlite_orm { }; } + namespace sqlite_orm { /** @@ -4974,6 +4992,7 @@ namespace sqlite_orm { // #include "journal_mode.h" + #include // std::string #include // std::unique_ptr #include // std::array @@ -5036,6 +5055,7 @@ namespace sqlite_orm { // #include "error_code.h" + namespace sqlite_orm { /** @@ -5412,6 +5432,7 @@ namespace sqlite_orm { // #include "alias.h" + namespace sqlite_orm { namespace internal { @@ -5658,6 +5679,7 @@ namespace sqlite_orm { } } + namespace sqlite_orm { namespace internal { @@ -5922,6 +5944,7 @@ namespace sqlite_orm { // #include "column.h" + namespace sqlite_orm { namespace internal { @@ -6221,10 +6244,12 @@ namespace sqlite_orm { // #include "field_value_holder.h" + #include // std::enable_if // #include "column.h" + namespace sqlite_orm { namespace internal { @@ -6247,6 +6272,7 @@ namespace sqlite_orm { } } + namespace sqlite_orm { namespace internal { @@ -6748,6 +6774,7 @@ namespace sqlite_orm { // #include "view.h" + #include // std::shared_ptr #include // std::string #include // std::forward, std::move @@ -6763,6 +6790,7 @@ namespace sqlite_orm { // #include "iterator.h" + #include // std::shared_ptr, std::unique_ptr, std::make_shared #include #include // std::decay @@ -6778,6 +6806,7 @@ namespace sqlite_orm { // #include "error_code.h" + namespace sqlite_orm { namespace internal { @@ -6906,6 +6935,7 @@ namespace sqlite_orm { // #include "ast_iterator.h" + #include // std::vector #include // std::reference_wrapper @@ -6921,6 +6951,7 @@ namespace sqlite_orm { // #include "prepared_statement.h" + #include #include // std::iterator_traits #include // std::string @@ -6929,12 +6960,14 @@ namespace sqlite_orm { // #include "connection_holder.h" + #include #include // std::string #include // std::system_error // #include "error_code.h" + namespace sqlite_orm { namespace internal { @@ -7009,6 +7042,7 @@ namespace sqlite_orm { // #include "select_constraints.h" + namespace sqlite_orm { namespace internal { @@ -7392,6 +7426,7 @@ namespace sqlite_orm { #endif // SQLITE_ORM_OPTIONAL_SUPPORTED } + namespace sqlite_orm { namespace internal { @@ -7877,6 +7912,7 @@ namespace sqlite_orm { // #include "connection_holder.h" + namespace sqlite_orm { namespace internal { @@ -7935,6 +7971,7 @@ namespace sqlite_orm { // #include "storage_base.h" + #include // std::function, std::bind #include #include // std::string @@ -7949,6 +7986,7 @@ namespace sqlite_orm { // #include "pragma.h" + #include // std::string #include #include // std::function @@ -7962,6 +8000,7 @@ namespace sqlite_orm { // #include "connection_holder.h" + namespace sqlite_orm { namespace internal { @@ -8082,6 +8121,7 @@ namespace sqlite_orm { // #include "limit_accesor.h" + #include #include // std::map #include // std::function @@ -8089,6 +8129,7 @@ namespace sqlite_orm { // #include "connection_holder.h" + namespace sqlite_orm { namespace internal { @@ -8222,10 +8263,12 @@ namespace sqlite_orm { // #include "transaction_guard.h" + #include // std::function // #include "connection_holder.h" + namespace sqlite_orm { namespace internal { @@ -8300,6 +8343,7 @@ namespace sqlite_orm { // #include "backup.h" + #include #include // std::string #include @@ -8308,6 +8352,7 @@ namespace sqlite_orm { // #include "connection_holder.h" + namespace sqlite_orm { namespace internal { @@ -8373,6 +8418,7 @@ namespace sqlite_orm { } } + namespace sqlite_orm { namespace internal { @@ -8873,11 +8919,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 { @@ -8997,6 +9045,7 @@ namespace sqlite_orm { // #include "statement_serializator.h" + #include // std::stringstream #include // std::string #include // std::is_arithmetic, std::enable_if @@ -9017,6 +9066,7 @@ namespace sqlite_orm { // #include "table_name_collector.h" + #include // std::set #include // std::string #include // std::function @@ -9028,6 +9078,7 @@ namespace sqlite_orm { // #include "core_functions.h" + namespace sqlite_orm { namespace internal { @@ -9088,6 +9139,7 @@ namespace sqlite_orm { // #include "column_names_getter.h" + #include // std::string #include // std::vector #include // std::reference_wrapper @@ -9096,6 +9148,7 @@ namespace sqlite_orm { // #include "select_constraints.h" + namespace sqlite_orm { namespace internal { @@ -9174,6 +9227,7 @@ namespace sqlite_orm { // #include "order_by_serializator.h" + #include // std::string #include // std::vector #include // std::stringstream @@ -9260,6 +9314,7 @@ namespace sqlite_orm { } } + namespace sqlite_orm { namespace internal { @@ -10152,7 +10207,7 @@ namespace sqlite_orm { std::stringstream ss; auto newContext = context; newContext.skip_table_name = false; - ss << static_cast(t) << " " << serialize(t.arg, newContext); + ss << static_cast(t) << " " << serialize(t.arg, newContext) << " "; return ss.str(); } }; @@ -10286,11 +10341,24 @@ namespace sqlite_orm { return ss.str(); } }; + + template + struct statement_serializator, void> { + using statement_type = using_t; + + template + std::string operator()(const statement_type &statement, const C &context) const { + auto newContext = context; + newContext.skip_table_name = true; + return static_cast(statement) + " (" + serialize(statement.column, newContext) + " )"; + } + }; } } // #include "table_name_collector.h" + namespace sqlite_orm { namespace internal { @@ -12325,19 +12393,20 @@ __pragma(pop_macro("min")) #include // std::pair #include // std::reference_wrapper - // #include "conditions.h" +// #include "conditions.h" - // #include "operators.h" +// #include "operators.h" + +// #include "select_constraints.h" - // #include "select_constraints.h" +// #include "prepared_statement.h" - // #include "prepared_statement.h" +// #include "optional_container.h" - // #include "optional_container.h" +// #include "core_functions.h" - // #include "core_functions.h" - namespace sqlite_orm { +namespace sqlite_orm { namespace internal { @@ -12618,6 +12687,7 @@ __pragma(pop_macro("min")) // #include "expression_object_type.h" + namespace sqlite_orm { template From 45a79483ace7320afb306dbf41d581e5dc043194 Mon Sep 17 00:00:00 2001 From: fnc12 Date: Mon, 27 Apr 2020 10:40:00 +0300 Subject: [PATCH 059/132] code format --- dev/statement_serializator.h | 24 ++++---- include/sqlite_orm/sqlite_orm.h | 98 +++++++-------------------------- 2 files changed, 32 insertions(+), 90 deletions(-) diff --git a/dev/statement_serializator.h b/dev/statement_serializator.h index 51fc4eecb..f13459716 100644 --- a/dev/statement_serializator.h +++ b/dev/statement_serializator.h @@ -1042,17 +1042,17 @@ namespace sqlite_orm { return ss.str(); } }; - - template - struct statement_serializator, void> { - using statement_type = using_t; - - template - std::string operator()(const statement_type &statement, const C &context) const { - auto newContext = context; - newContext.skip_table_name = true; - return static_cast(statement) + " (" + serialize(statement.column, newContext) + " )"; - } - }; + + template + struct statement_serializator, void> { + using statement_type = using_t; + + template + std::string operator()(const statement_type &statement, const C &context) const { + auto newContext = context; + newContext.skip_table_name = true; + return static_cast(statement) + " (" + serialize(statement.column, newContext) + " )"; + } + }; } } diff --git a/include/sqlite_orm/sqlite_orm.h b/include/sqlite_orm/sqlite_orm.h index e558a2337..af356f4a0 100644 --- a/include/sqlite_orm/sqlite_orm.h +++ b/include/sqlite_orm/sqlite_orm.h @@ -27,7 +27,7 @@ __pragma(push_macro("min")) #include #include // std::ostringstream -namespace sqlite_orm { + namespace sqlite_orm { enum class orm_error_code { not_found = 1, @@ -44,7 +44,6 @@ namespace sqlite_orm { failed_to_init_a_backup, unknown_member_value, }; - } namespace sqlite_orm { @@ -225,7 +224,6 @@ namespace sqlite_orm { // #include "static_magic.h" - #include // std::false_type, std::true_type, std::integral_constant namespace sqlite_orm { @@ -260,7 +258,6 @@ namespace sqlite_orm { } - namespace sqlite_orm { // got from here http://stackoverflow.com/questions/25958259/how-do-i-find-out-if-a-tuple-contains-a-type @@ -992,7 +989,6 @@ namespace sqlite_orm { // #include "serializator_context.h" - namespace sqlite_orm { namespace internal { @@ -1040,7 +1036,6 @@ namespace sqlite_orm { } - namespace sqlite_orm { namespace internal { @@ -1075,14 +1070,12 @@ namespace sqlite_orm { // #include "negatable.h" - namespace sqlite_orm { namespace internal { struct negatable_t {}; } } - namespace sqlite_orm { namespace internal { @@ -1382,7 +1375,6 @@ namespace sqlite_orm { // #include "getter_traits.h" - namespace sqlite_orm { namespace internal { @@ -1566,7 +1558,6 @@ namespace sqlite_orm { } } - namespace sqlite_orm { namespace internal { @@ -1897,7 +1888,6 @@ namespace sqlite_orm { // #include "optional_container.h" - namespace sqlite_orm { namespace internal { @@ -1932,7 +1922,6 @@ namespace sqlite_orm { // #include "negatable.h" - namespace sqlite_orm { namespace internal { @@ -3382,7 +3371,6 @@ namespace sqlite_orm { // #include "conditions.h" - namespace sqlite_orm { namespace internal { @@ -3502,7 +3490,6 @@ namespace sqlite_orm { // #include "is_base_of_template.h" - #include // std::true_type, std::false_type, std::declval namespace sqlite_orm { @@ -3540,7 +3527,6 @@ namespace sqlite_orm { } } - namespace sqlite_orm { namespace internal { @@ -4293,7 +4279,6 @@ namespace sqlite_orm { // #include "optional_container.h" - namespace sqlite_orm { namespace internal { @@ -4646,7 +4631,6 @@ namespace sqlite_orm { // #include "column.h" - namespace sqlite_orm { namespace internal { @@ -4753,7 +4737,6 @@ namespace sqlite_orm { // #include "is_std_ptr.h" - namespace sqlite_orm { /** @@ -4781,7 +4764,6 @@ namespace sqlite_orm { }; } - namespace sqlite_orm { /** @@ -4992,7 +4974,6 @@ namespace sqlite_orm { // #include "journal_mode.h" - #include // std::string #include // std::unique_ptr #include // std::array @@ -5055,7 +5036,6 @@ namespace sqlite_orm { // #include "error_code.h" - namespace sqlite_orm { /** @@ -5432,7 +5412,6 @@ namespace sqlite_orm { // #include "alias.h" - namespace sqlite_orm { namespace internal { @@ -5679,7 +5658,6 @@ namespace sqlite_orm { } } - namespace sqlite_orm { namespace internal { @@ -5944,7 +5922,6 @@ namespace sqlite_orm { // #include "column.h" - namespace sqlite_orm { namespace internal { @@ -6244,12 +6221,10 @@ namespace sqlite_orm { // #include "field_value_holder.h" - #include // std::enable_if // #include "column.h" - namespace sqlite_orm { namespace internal { @@ -6272,7 +6247,6 @@ namespace sqlite_orm { } } - namespace sqlite_orm { namespace internal { @@ -6774,7 +6748,6 @@ namespace sqlite_orm { // #include "view.h" - #include // std::shared_ptr #include // std::string #include // std::forward, std::move @@ -6790,7 +6763,6 @@ namespace sqlite_orm { // #include "iterator.h" - #include // std::shared_ptr, std::unique_ptr, std::make_shared #include #include // std::decay @@ -6806,7 +6778,6 @@ namespace sqlite_orm { // #include "error_code.h" - namespace sqlite_orm { namespace internal { @@ -6935,7 +6906,6 @@ namespace sqlite_orm { // #include "ast_iterator.h" - #include // std::vector #include // std::reference_wrapper @@ -6951,7 +6921,6 @@ namespace sqlite_orm { // #include "prepared_statement.h" - #include #include // std::iterator_traits #include // std::string @@ -6960,14 +6929,12 @@ namespace sqlite_orm { // #include "connection_holder.h" - #include #include // std::string #include // std::system_error // #include "error_code.h" - namespace sqlite_orm { namespace internal { @@ -7042,7 +7009,6 @@ namespace sqlite_orm { // #include "select_constraints.h" - namespace sqlite_orm { namespace internal { @@ -7426,7 +7392,6 @@ namespace sqlite_orm { #endif // SQLITE_ORM_OPTIONAL_SUPPORTED } - namespace sqlite_orm { namespace internal { @@ -7912,7 +7877,6 @@ namespace sqlite_orm { // #include "connection_holder.h" - namespace sqlite_orm { namespace internal { @@ -7971,7 +7935,6 @@ namespace sqlite_orm { // #include "storage_base.h" - #include // std::function, std::bind #include #include // std::string @@ -7986,7 +7949,6 @@ namespace sqlite_orm { // #include "pragma.h" - #include // std::string #include #include // std::function @@ -8000,7 +7962,6 @@ namespace sqlite_orm { // #include "connection_holder.h" - namespace sqlite_orm { namespace internal { @@ -8121,7 +8082,6 @@ namespace sqlite_orm { // #include "limit_accesor.h" - #include #include // std::map #include // std::function @@ -8129,7 +8089,6 @@ namespace sqlite_orm { // #include "connection_holder.h" - namespace sqlite_orm { namespace internal { @@ -8263,12 +8222,10 @@ namespace sqlite_orm { // #include "transaction_guard.h" - #include // std::function // #include "connection_holder.h" - namespace sqlite_orm { namespace internal { @@ -8343,7 +8300,6 @@ namespace sqlite_orm { // #include "backup.h" - #include #include // std::string #include @@ -8352,7 +8308,6 @@ namespace sqlite_orm { // #include "connection_holder.h" - namespace sqlite_orm { namespace internal { @@ -8418,7 +8373,6 @@ namespace sqlite_orm { } } - namespace sqlite_orm { namespace internal { @@ -8919,13 +8873,11 @@ namespace sqlite_orm { // #include "expression_object_type.h" - #include // std::decay #include // std::reference_wrapper // #include "prepared_statement.h" - namespace sqlite_orm { namespace internal { @@ -9045,7 +8997,6 @@ namespace sqlite_orm { // #include "statement_serializator.h" - #include // std::stringstream #include // std::string #include // std::is_arithmetic, std::enable_if @@ -9066,7 +9017,6 @@ namespace sqlite_orm { // #include "table_name_collector.h" - #include // std::set #include // std::string #include // std::function @@ -9078,7 +9028,6 @@ namespace sqlite_orm { // #include "core_functions.h" - namespace sqlite_orm { namespace internal { @@ -9139,7 +9088,6 @@ namespace sqlite_orm { // #include "column_names_getter.h" - #include // std::string #include // std::vector #include // std::reference_wrapper @@ -9148,7 +9096,6 @@ namespace sqlite_orm { // #include "select_constraints.h" - namespace sqlite_orm { namespace internal { @@ -9227,7 +9174,6 @@ namespace sqlite_orm { // #include "order_by_serializator.h" - #include // std::string #include // std::vector #include // std::stringstream @@ -9314,7 +9260,6 @@ namespace sqlite_orm { } } - namespace sqlite_orm { namespace internal { @@ -10341,24 +10286,23 @@ namespace sqlite_orm { return ss.str(); } }; - - template - struct statement_serializator, void> { - using statement_type = using_t; - - template - std::string operator()(const statement_type &statement, const C &context) const { - auto newContext = context; - newContext.skip_table_name = true; - return static_cast(statement) + " (" + serialize(statement.column, newContext) + " )"; - } - }; + + template + struct statement_serializator, void> { + using statement_type = using_t; + + template + std::string operator()(const statement_type &statement, const C &context) const { + auto newContext = context; + newContext.skip_table_name = true; + return static_cast(statement) + " (" + serialize(statement.column, newContext) + " )"; + } + }; } } // #include "table_name_collector.h" - namespace sqlite_orm { namespace internal { @@ -12393,20 +12337,19 @@ __pragma(pop_macro("min")) #include // std::pair #include // std::reference_wrapper -// #include "conditions.h" + // #include "conditions.h" -// #include "operators.h" + // #include "operators.h" -// #include "select_constraints.h" + // #include "select_constraints.h" -// #include "prepared_statement.h" + // #include "prepared_statement.h" -// #include "optional_container.h" - -// #include "core_functions.h" + // #include "optional_container.h" + // #include "core_functions.h" -namespace sqlite_orm { + namespace sqlite_orm { namespace internal { @@ -12687,7 +12630,6 @@ namespace sqlite_orm { // #include "expression_object_type.h" - namespace sqlite_orm { template From c46bcb7a7700916516d19908707bf1cbe12bf8e2 Mon Sep 17 00:00:00 2001 From: fnc12 Date: Mon, 27 Apr 2020 10:45:15 +0300 Subject: [PATCH 060/132] removed process join constraint func --- dev/storage.h | 5 ----- include/sqlite_orm/sqlite_orm.h | 5 ----- 2 files changed, 10 deletions(-) diff --git a/dev/storage.h b/dev/storage.h index 442ab55ad..dd4b012d8 100644 --- a/dev/storage.h +++ b/dev/storage.h @@ -594,11 +594,6 @@ namespace sqlite_orm { return ss.str(); } - template - void process_join_constraint(std::stringstream &ss, const using_t &u) const { - ss << static_cast(u) << " (" << this->string_from_expression(u.column, true) << " )"; - } - template std::string string_from_expression(const dynamic_order_by_t &orderBy, bool) const { std::stringstream ss; diff --git a/include/sqlite_orm/sqlite_orm.h b/include/sqlite_orm/sqlite_orm.h index af356f4a0..96253b0d6 100644 --- a/include/sqlite_orm/sqlite_orm.h +++ b/include/sqlite_orm/sqlite_orm.h @@ -10849,11 +10849,6 @@ namespace sqlite_orm { return ss.str(); } - template - void process_join_constraint(std::stringstream &ss, const using_t &u) const { - ss << static_cast(u) << " (" << this->string_from_expression(u.column, true) << " )"; - } - template std::string string_from_expression(const dynamic_order_by_t &orderBy, bool) const { std::stringstream ss; From 42dad5246d89a99fb58e52ce57f88d2e8eeb97ee Mon Sep 17 00:00:00 2001 From: fnc12 Date: Tue, 28 Apr 2020 02:25:44 +0300 Subject: [PATCH 061/132] added statement serializator for insert range --- dev/statement_serializator.h | 55 ++++++++++++++ dev/storage.h | 67 ++---------------- include/sqlite_orm/sqlite_orm.h | 122 ++++++++++++++++++-------------- 3 files changed, 130 insertions(+), 114 deletions(-) diff --git a/dev/statement_serializator.h b/dev/statement_serializator.h index f13459716..3bb8b5bd2 100644 --- a/dev/statement_serializator.h +++ b/dev/statement_serializator.h @@ -740,6 +740,61 @@ namespace sqlite_orm { } }; + template + struct statement_serializator, void> { + using statement_type = insert_range_t; + + template + std::string operator()(const statement_type &statement, const C &context) const { + using expression_type = typename std::decay::type; + using object_type = typename expression_type::object_type; + auto &tImpl = context.impl.template get_impl(); + + std::stringstream ss; + ss << "INSERT INTO '" << tImpl.table.name << "' ("; + std::vector columnNames; + tImpl.table.for_each_column([&columnNames](auto &c) { + if(!c.template has>()) { + columnNames.emplace_back(c.name); + } + }); + + auto columnNamesCount = columnNames.size(); + for(size_t i = 0; i < columnNamesCount; ++i) { + ss << "\"" << columnNames[i] << "\""; + if(i < columnNamesCount - 1) { + ss << ","; + } else { + ss << ")"; + } + ss << " "; + } + ss << "VALUES "; + auto valuesString = [columnNamesCount] { + std::stringstream ss; + ss << "("; + for(size_t i = 0; i < columnNamesCount; ++i) { + ss << "?"; + if(i < columnNamesCount - 1) { + ss << ", "; + } else { + ss << ")"; + } + } + return ss.str(); + }(); + auto valuesCount = static_cast(std::distance(statement.range.first, statement.range.second)); + for(auto i = 0; i < valuesCount; ++i) { + ss << valuesString; + if(i < valuesCount - 1) { + ss << ","; + } + ss << " "; + } + return ss.str(); + } + }; + template struct statement_serializator, void> { using statement_type = select_t; diff --git a/dev/storage.h b/dev/storage.h index dd4b012d8..ce1dc1100 100644 --- a/dev/storage.h +++ b/dev/storage.h @@ -544,63 +544,6 @@ namespace sqlite_orm { return ss.str(); } - template - std::string string_from_expression(const insert_range_t &ins, bool /*noTableName*/) const { - using expression_type = typename std::decay::type; - using object_type = typename expression_type::object_type; - auto &tImpl = this->get_impl(); - - std::stringstream ss; - ss << "INSERT INTO '" << tImpl.table.name << "' ("; - std::vector columnNames; - tImpl.table.for_each_column([&columnNames](auto &c) { - if(!c.template has>()) { - columnNames.emplace_back(c.name); - } - }); - - auto columnNamesCount = columnNames.size(); - for(size_t i = 0; i < columnNamesCount; ++i) { - ss << "\"" << columnNames[i] << "\""; - if(i < columnNamesCount - 1) { - ss << ","; - } else { - ss << ")"; - } - ss << " "; - } - ss << "VALUES "; - auto valuesString = [columnNamesCount] { - std::stringstream ss; - ss << "("; - for(size_t i = 0; i < columnNamesCount; ++i) { - ss << "?"; - if(i < columnNamesCount - 1) { - ss << ", "; - } else { - ss << ")"; - } - } - return ss.str(); - }(); - auto valuesCount = static_cast(std::distance(ins.range.first, ins.range.second)); - for(auto i = 0; i < valuesCount; ++i) { - ss << valuesString; - if(i < valuesCount - 1) { - ss << ","; - } - ss << " "; - } - return ss.str(); - } - - template - std::string string_from_expression(const dynamic_order_by_t &orderBy, bool) const { - std::stringstream ss; - ss << this->storage_base::process_order_by(orderBy) << " "; - return ss.str(); - } - template void process_conditions(std::stringstream &ss, const std::tuple &args) const { using context_t = serializator_context; @@ -1356,13 +1299,17 @@ namespace sqlite_orm { } template - prepared_statement_t> prepare(insert_range_t ins) { + prepared_statement_t> prepare(insert_range_t statement) { auto con = this->get_connection(); sqlite3_stmt *stmt; auto db = con.get(); - auto query = this->string_from_expression(ins, false); + using context_t = serializator_context; + context_t context{this->impl}; + context.skip_table_name = false; + context.replace_bindable_with_question = true; + auto query = serialize(statement, context); if(sqlite3_prepare_v2(db, query.c_str(), -1, &stmt, nullptr) == SQLITE_OK) { - return {std::move(ins), stmt, con}; + return {std::move(statement), stmt, con}; } else { throw std::system_error(std::error_code(sqlite3_errcode(db), get_sqlite_error_category()), sqlite3_errmsg(db)); diff --git a/include/sqlite_orm/sqlite_orm.h b/include/sqlite_orm/sqlite_orm.h index 96253b0d6..0f67f4370 100644 --- a/include/sqlite_orm/sqlite_orm.h +++ b/include/sqlite_orm/sqlite_orm.h @@ -9984,6 +9984,61 @@ namespace sqlite_orm { } }; + template + struct statement_serializator, void> { + using statement_type = insert_range_t; + + template + std::string operator()(const statement_type &statement, const C &context) const { + using expression_type = typename std::decay::type; + using object_type = typename expression_type::object_type; + auto &tImpl = context.impl.template get_impl(); + + std::stringstream ss; + ss << "INSERT INTO '" << tImpl.table.name << "' ("; + std::vector columnNames; + tImpl.table.for_each_column([&columnNames](auto &c) { + if(!c.template has>()) { + columnNames.emplace_back(c.name); + } + }); + + auto columnNamesCount = columnNames.size(); + for(size_t i = 0; i < columnNamesCount; ++i) { + ss << "\"" << columnNames[i] << "\""; + if(i < columnNamesCount - 1) { + ss << ","; + } else { + ss << ")"; + } + ss << " "; + } + ss << "VALUES "; + auto valuesString = [columnNamesCount] { + std::stringstream ss; + ss << "("; + for(size_t i = 0; i < columnNamesCount; ++i) { + ss << "?"; + if(i < columnNamesCount - 1) { + ss << ", "; + } else { + ss << ")"; + } + } + return ss.str(); + }(); + auto valuesCount = static_cast(std::distance(statement.range.first, statement.range.second)); + for(auto i = 0; i < valuesCount; ++i) { + ss << valuesString; + if(i < valuesCount - 1) { + ss << ","; + } + ss << " "; + } + return ss.str(); + } + }; + template struct statement_serializator, void> { using statement_type = select_t; @@ -10799,62 +10854,17 @@ namespace sqlite_orm { return ss.str(); } - template - std::string string_from_expression(const insert_range_t &ins, bool /*noTableName*/) const { - using expression_type = typename std::decay::type; - using object_type = typename expression_type::object_type; - auto &tImpl = this->get_impl(); - - std::stringstream ss; - ss << "INSERT INTO '" << tImpl.table.name << "' ("; - std::vector columnNames; - tImpl.table.for_each_column([&columnNames](auto &c) { - if(!c.template has>()) { - columnNames.emplace_back(c.name); - } - }); - - auto columnNamesCount = columnNames.size(); - for(size_t i = 0; i < columnNamesCount; ++i) { - ss << "\"" << columnNames[i] << "\""; - if(i < columnNamesCount - 1) { - ss << ","; - } else { - ss << ")"; - } - ss << " "; - } - ss << "VALUES "; - auto valuesString = [columnNamesCount] { - std::stringstream ss; - ss << "("; - for(size_t i = 0; i < columnNamesCount; ++i) { - ss << "?"; - if(i < columnNamesCount - 1) { - ss << ", "; - } else { - ss << ")"; - } - } - return ss.str(); - }(); - auto valuesCount = static_cast(std::distance(ins.range.first, ins.range.second)); - for(auto i = 0; i < valuesCount; ++i) { - ss << valuesString; - if(i < valuesCount - 1) { - ss << ","; - } - ss << " "; - } - return ss.str(); - } + /*template + std::string string_from_expression(const insert_range_t &ins, bool ) const { + ff + }*/ - template + /*template std::string string_from_expression(const dynamic_order_by_t &orderBy, bool) const { std::stringstream ss; ss << this->storage_base::process_order_by(orderBy) << " "; return ss.str(); - } + }*/ template void process_conditions(std::stringstream &ss, const std::tuple &args) const { @@ -11611,13 +11621,17 @@ namespace sqlite_orm { } template - prepared_statement_t> prepare(insert_range_t ins) { + prepared_statement_t> prepare(insert_range_t statement) { auto con = this->get_connection(); sqlite3_stmt *stmt; auto db = con.get(); - auto query = this->string_from_expression(ins, false); + using context_t = serializator_context; + context_t context{this->impl}; + context.skip_table_name = false; + context.replace_bindable_with_question = true; + auto query = serialize(statement, context); if(sqlite3_prepare_v2(db, query.c_str(), -1, &stmt, nullptr) == SQLITE_OK) { - return {std::move(ins), stmt, con}; + return {std::move(statement), stmt, con}; } else { throw std::system_error(std::error_code(sqlite3_errcode(db), get_sqlite_error_category()), sqlite3_errmsg(db)); From 7ad4dabf830b8aee206d957f2c44ed01bb2f819c Mon Sep 17 00:00:00 2001 From: fnc12 Date: Mon, 11 May 2020 19:41:37 +0300 Subject: [PATCH 062/132] removed string_from_expression for remote_v --- dev/statement_serializator.h | 22 +++++++ dev/storage.h | 71 ++++++++++----------- include/sqlite_orm/sqlite_orm.h | 105 ++++++++++++++++++-------------- 3 files changed, 118 insertions(+), 80 deletions(-) diff --git a/dev/statement_serializator.h b/dev/statement_serializator.h index 3bb8b5bd2..eaef933c8 100644 --- a/dev/statement_serializator.h +++ b/dev/statement_serializator.h @@ -740,6 +740,28 @@ namespace sqlite_orm { } }; + template + struct statement_serializator, void> { + using statement_type = remove_t; + + template + std::string operator()(const statement_type &, const C &context) const { + auto &tImpl = context.impl.template get_impl(); + std::stringstream ss; + ss << "DELETE FROM '" << tImpl.table.name << "' "; + ss << "WHERE "; + auto primaryKeyColumnNames = tImpl.table.primary_key_column_names(); + for(size_t i = 0; i < primaryKeyColumnNames.size(); ++i) { + ss << "\"" << primaryKeyColumnNames[i] << "\"" + << " = ? "; + if(i < primaryKeyColumnNames.size() - 1) { + ss << "AND "; + } + } + return ss.str(); + } + }; + template struct statement_serializator, void> { using statement_type = insert_range_t; diff --git a/dev/storage.h b/dev/storage.h index ce1dc1100..f6d557392 100644 --- a/dev/storage.h +++ b/dev/storage.h @@ -203,14 +203,26 @@ namespace sqlite_orm { template std::string string_from_expression(const get_all_t &get, bool noTableName) const { std::stringstream ss = this->string_from_expression_impl_get_all(get, noTableName); - this->process_conditions(ss, get.conditions); + using context_t = serializator_context; + context_t context{this->impl}; + context.skip_table_name = false; + context.replace_bindable_with_question = true; + iterate_tuple(get.conditions, [&context, &ss](auto &v) { + ss << serialize(v, context); + }); return ss.str(); } template std::string string_from_expression(const get_all_pointer_t &get, bool noTableName) const { std::stringstream ss = this->string_from_expression_impl_get_all(get, noTableName); - this->process_conditions(ss, get.conditions); + using context_t = serializator_context; + context_t context{this->impl}; + context.skip_table_name = false; + context.replace_bindable_with_question = true; + iterate_tuple(get.conditions, [&context, &ss](auto &v) { + ss << serialize(v, context); + }); return ss.str(); } @@ -218,7 +230,13 @@ namespace sqlite_orm { template std::string string_from_expression(const get_all_optional_t &get, bool noTableName) const { std::stringstream ss = this->string_from_expression_impl_get_all(get, noTableName); - this->process_conditions(ss, get.conditions); + using context_t = serializator_context; + context_t context{this->impl}; + context.skip_table_name = false; + context.replace_bindable_with_question = true; + iterate_tuple(get.conditions, [&context, &ss](auto &v) { + ss << serialize(v, context); + }); return ss.str(); } #endif // SQLITE_ORM_OPTIONAL_SUPPORTED @@ -256,7 +274,10 @@ namespace sqlite_orm { ss << ", "; } } - this->process_conditions(ss, upd.conditions); + context.skip_table_name = false; + iterate_tuple(upd.conditions, [&context, &ss](auto &v) { + ss << serialize(v, context); + }); return ss.str(); } else { throw std::system_error(std::make_error_code(orm_error_code::too_many_tables_specified)); @@ -271,7 +292,13 @@ namespace sqlite_orm { auto &tImpl = this->get_impl(); std::stringstream ss; ss << "DELETE FROM '" << tImpl.table.name << "' "; - this->process_conditions(ss, rem.conditions); + using context_t = serializator_context; + context_t context{this->impl}; + context.skip_table_name = false; + context.replace_bindable_with_question = true; + iterate_tuple(rem.conditions, [&context, &ss](auto &v) { + ss << serialize(v, context); + }); return ss.str(); } @@ -358,23 +385,6 @@ namespace sqlite_orm { return ss.str(); } - template - std::string string_from_expression(const remove_t &, bool /*noTableName*/) const { - auto &tImpl = this->get_impl(); - std::stringstream ss; - ss << "DELETE FROM '" << tImpl.table.name << "' "; - ss << "WHERE "; - auto primaryKeyColumnNames = tImpl.table.primary_key_column_names(); - for(size_t i = 0; i < primaryKeyColumnNames.size(); ++i) { - ss << "\"" << primaryKeyColumnNames[i] << "\"" - << " = ? "; - if(i < primaryKeyColumnNames.size() - 1) { - ss << "AND "; - } - } - return ss.str(); - } - template std::string string_from_expression(const insert_explicit &ins, bool /*noTableName*/) const { constexpr const size_t colsCount = std::tuple_size>::value; @@ -544,17 +554,6 @@ namespace sqlite_orm { return ss.str(); } - template - void process_conditions(std::stringstream &ss, const std::tuple &args) const { - using context_t = serializator_context; - context_t context{this->impl}; - context.skip_table_name = false; - context.replace_bindable_with_question = true; - iterate_tuple(args, [&context, &ss](auto &v) { - ss << serialize(v, context); - }); - } - public: template view_t iterate(Args &&... args) { @@ -1261,7 +1260,11 @@ namespace sqlite_orm { auto con = this->get_connection(); sqlite3_stmt *stmt; auto db = con.get(); - auto query = this->string_from_expression(rem, false); + using context_t = serializator_context; + context_t context{this->impl}; + context.skip_table_name = false; + context.replace_bindable_with_question = true; + auto query = serialize(rem, context); if(sqlite3_prepare_v2(db, query.c_str(), -1, &stmt, nullptr) == SQLITE_OK) { return {std::move(rem), stmt, con}; } else { diff --git a/include/sqlite_orm/sqlite_orm.h b/include/sqlite_orm/sqlite_orm.h index 0f67f4370..d9f5dde82 100644 --- a/include/sqlite_orm/sqlite_orm.h +++ b/include/sqlite_orm/sqlite_orm.h @@ -9984,6 +9984,28 @@ namespace sqlite_orm { } }; + template + struct statement_serializator, void> { + using statement_type = remove_t; + + template + std::string operator()(const statement_type &, const C &context) const { + auto &tImpl = context.impl.template get_impl(); + std::stringstream ss; + ss << "DELETE FROM '" << tImpl.table.name << "' "; + ss << "WHERE "; + auto primaryKeyColumnNames = tImpl.table.primary_key_column_names(); + for(size_t i = 0; i < primaryKeyColumnNames.size(); ++i) { + ss << "\"" << primaryKeyColumnNames[i] << "\"" + << " = ? "; + if(i < primaryKeyColumnNames.size() - 1) { + ss << "AND "; + } + } + return ss.str(); + } + }; + template struct statement_serializator, void> { using statement_type = insert_range_t; @@ -10513,14 +10535,26 @@ namespace sqlite_orm { template std::string string_from_expression(const get_all_t &get, bool noTableName) const { std::stringstream ss = this->string_from_expression_impl_get_all(get, noTableName); - this->process_conditions(ss, get.conditions); + using context_t = serializator_context; + context_t context{this->impl}; + context.skip_table_name = false; + context.replace_bindable_with_question = true; + iterate_tuple(get.conditions, [&context, &ss](auto &v) { + ss << serialize(v, context); + }); return ss.str(); } template std::string string_from_expression(const get_all_pointer_t &get, bool noTableName) const { std::stringstream ss = this->string_from_expression_impl_get_all(get, noTableName); - this->process_conditions(ss, get.conditions); + using context_t = serializator_context; + context_t context{this->impl}; + context.skip_table_name = false; + context.replace_bindable_with_question = true; + iterate_tuple(get.conditions, [&context, &ss](auto &v) { + ss << serialize(v, context); + }); return ss.str(); } @@ -10528,7 +10562,13 @@ namespace sqlite_orm { template std::string string_from_expression(const get_all_optional_t &get, bool noTableName) const { std::stringstream ss = this->string_from_expression_impl_get_all(get, noTableName); - this->process_conditions(ss, get.conditions); + using context_t = serializator_context; + context_t context{this->impl}; + context.skip_table_name = false; + context.replace_bindable_with_question = true; + iterate_tuple(get.conditions, [&context, &ss](auto &v) { + ss << serialize(v, context); + }); return ss.str(); } #endif // SQLITE_ORM_OPTIONAL_SUPPORTED @@ -10566,7 +10606,10 @@ namespace sqlite_orm { ss << ", "; } } - this->process_conditions(ss, upd.conditions); + context.skip_table_name = false; + iterate_tuple(upd.conditions, [&context, &ss](auto &v) { + ss << serialize(v, context); + }); return ss.str(); } else { throw std::system_error(std::make_error_code(orm_error_code::too_many_tables_specified)); @@ -10581,7 +10624,13 @@ namespace sqlite_orm { auto &tImpl = this->get_impl(); std::stringstream ss; ss << "DELETE FROM '" << tImpl.table.name << "' "; - this->process_conditions(ss, rem.conditions); + using context_t = serializator_context; + context_t context{this->impl}; + context.skip_table_name = false; + context.replace_bindable_with_question = true; + iterate_tuple(rem.conditions, [&context, &ss](auto &v) { + ss << serialize(v, context); + }); return ss.str(); } @@ -10668,23 +10717,6 @@ namespace sqlite_orm { return ss.str(); } - template - std::string string_from_expression(const remove_t &, bool /*noTableName*/) const { - auto &tImpl = this->get_impl(); - std::stringstream ss; - ss << "DELETE FROM '" << tImpl.table.name << "' "; - ss << "WHERE "; - auto primaryKeyColumnNames = tImpl.table.primary_key_column_names(); - for(size_t i = 0; i < primaryKeyColumnNames.size(); ++i) { - ss << "\"" << primaryKeyColumnNames[i] << "\"" - << " = ? "; - if(i < primaryKeyColumnNames.size() - 1) { - ss << "AND "; - } - } - return ss.str(); - } - template std::string string_from_expression(const insert_explicit &ins, bool /*noTableName*/) const { constexpr const size_t colsCount = std::tuple_size>::value; @@ -10854,29 +10886,6 @@ namespace sqlite_orm { return ss.str(); } - /*template - std::string string_from_expression(const insert_range_t &ins, bool ) const { - ff - }*/ - - /*template - std::string string_from_expression(const dynamic_order_by_t &orderBy, bool) const { - std::stringstream ss; - ss << this->storage_base::process_order_by(orderBy) << " "; - return ss.str(); - }*/ - - template - void process_conditions(std::stringstream &ss, const std::tuple &args) const { - using context_t = serializator_context; - context_t context{this->impl}; - context.skip_table_name = false; - context.replace_bindable_with_question = true; - iterate_tuple(args, [&context, &ss](auto &v) { - ss << serialize(v, context); - }); - } - public: template view_t iterate(Args &&... args) { @@ -11583,7 +11592,11 @@ namespace sqlite_orm { auto con = this->get_connection(); sqlite3_stmt *stmt; auto db = con.get(); - auto query = this->string_from_expression(rem, false); + using context_t = serializator_context; + context_t context{this->impl}; + context.skip_table_name = false; + context.replace_bindable_with_question = true; + auto query = serialize(rem, context); if(sqlite3_prepare_v2(db, query.c_str(), -1, &stmt, nullptr) == SQLITE_OK) { return {std::move(rem), stmt, con}; } else { From 83f816571afca3594a4ba5c952e5ae6ee3351cac Mon Sep 17 00:00:00 2001 From: fnc12 Date: Mon, 11 May 2020 19:56:36 +0300 Subject: [PATCH 063/132] removed string_from_expression for insert_t --- dev/statement_serializator.h | 53 +++++++++++++++ dev/storage.h | 58 ++--------------- include/sqlite_orm/sqlite_orm.h | 111 +++++++++++++++++--------------- 3 files changed, 120 insertions(+), 102 deletions(-) diff --git a/dev/statement_serializator.h b/dev/statement_serializator.h index eaef933c8..fec6afb94 100644 --- a/dev/statement_serializator.h +++ b/dev/statement_serializator.h @@ -740,6 +740,59 @@ namespace sqlite_orm { } }; + template + struct statement_serializator, void> { + using statement_type = insert_t; + + template + std::string operator()(const statement_type &, const C &context) const { + using object_type = typename expression_object_type::type; + auto &tImpl = context.impl.template get_impl(); + std::stringstream ss; + ss << "INSERT INTO '" << tImpl.table.name << "' "; + std::vector columnNames; + auto compositeKeyColumnNames = tImpl.table.composite_key_columns_names(); + + tImpl.table.for_each_column([&tImpl, &columnNames, &compositeKeyColumnNames](auto &c) { + if(tImpl.table._without_rowid || !c.template has>()) { + auto it = find(compositeKeyColumnNames.begin(), compositeKeyColumnNames.end(), c.name); + if(it == compositeKeyColumnNames.end()) { + columnNames.emplace_back(c.name); + } + } + }); + + auto columnNamesCount = columnNames.size(); + if(columnNamesCount) { + ss << "("; + for(size_t i = 0; i < columnNamesCount; ++i) { + ss << "\"" << columnNames[i] << "\""; + if(i < columnNamesCount - 1) { + ss << ","; + } else { + ss << ")"; + } + ss << " "; + } + } else { + ss << "DEFAULT "; + } + ss << "VALUES "; + if(columnNamesCount) { + ss << "("; + for(size_t i = 0; i < columnNamesCount; ++i) { + ss << "?"; + if(i < columnNamesCount - 1) { + ss << ", "; + } else { + ss << ")"; + } + } + } + return ss.str(); + } + }; + template struct statement_serializator, void> { using statement_type = remove_t; diff --git a/dev/storage.h b/dev/storage.h index f6d557392..34b379cd4 100644 --- a/dev/storage.h +++ b/dev/storage.h @@ -431,56 +431,6 @@ namespace sqlite_orm { return ss.str(); } - template - std::string string_from_expression(const insert_t &ins, bool /*noTableName*/) const { - using expression_type = typename std::decay::type; - using object_type = typename expression_object_type::type; - this->assert_mapped_type(); - auto &tImpl = this->get_impl(); - std::stringstream ss; - ss << "INSERT INTO '" << tImpl.table.name << "' "; - std::vector columnNames; - auto compositeKeyColumnNames = tImpl.table.composite_key_columns_names(); - - tImpl.table.for_each_column([&tImpl, &columnNames, &compositeKeyColumnNames](auto &c) { - if(tImpl.table._without_rowid || !c.template has>()) { - auto it = std::find(compositeKeyColumnNames.begin(), compositeKeyColumnNames.end(), c.name); - if(it == compositeKeyColumnNames.end()) { - columnNames.emplace_back(c.name); - } - } - }); - - auto columnNamesCount = columnNames.size(); - if(columnNamesCount) { - ss << "("; - for(size_t i = 0; i < columnNamesCount; ++i) { - ss << "\"" << columnNames[i] << "\""; - if(i < columnNamesCount - 1) { - ss << ","; - } else { - ss << ")"; - } - ss << " "; - } - } else { - ss << "DEFAULT "; - } - ss << "VALUES "; - if(columnNamesCount) { - ss << "("; - for(size_t i = 0; i < columnNamesCount; ++i) { - ss << "?"; - if(i < columnNamesCount - 1) { - ss << ", "; - } else { - ss << ")"; - } - } - } - return ss.str(); - } - template std::string string_from_expression(const replace_t &rep, bool /*noTableName*/) const { using expression_type = typename std::decay::type; @@ -1275,10 +1225,16 @@ namespace sqlite_orm { template prepared_statement_t> prepare(insert_t ins) { + using object_type = typename expression_object_type::type; + this->assert_mapped_type(); auto con = this->get_connection(); sqlite3_stmt *stmt; auto db = con.get(); - auto query = this->string_from_expression(ins, false); + using context_t = serializator_context; + context_t context{this->impl}; + context.skip_table_name = false; + context.replace_bindable_with_question = true; + auto query = serialize(ins, context); if(sqlite3_prepare_v2(db, query.c_str(), -1, &stmt, nullptr) == SQLITE_OK) { return {std::move(ins), stmt, con}; } else { diff --git a/include/sqlite_orm/sqlite_orm.h b/include/sqlite_orm/sqlite_orm.h index d9f5dde82..4b7810cea 100644 --- a/include/sqlite_orm/sqlite_orm.h +++ b/include/sqlite_orm/sqlite_orm.h @@ -9984,6 +9984,59 @@ namespace sqlite_orm { } }; + template + struct statement_serializator, void> { + using statement_type = insert_t; + + template + std::string operator()(const statement_type &, const C &context) const { + using object_type = typename expression_object_type::type; + auto &tImpl = context.impl.template get_impl(); + std::stringstream ss; + ss << "INSERT INTO '" << tImpl.table.name << "' "; + std::vector columnNames; + auto compositeKeyColumnNames = tImpl.table.composite_key_columns_names(); + + tImpl.table.for_each_column([&tImpl, &columnNames, &compositeKeyColumnNames](auto &c) { + if(tImpl.table._without_rowid || !c.template has>()) { + auto it = find(compositeKeyColumnNames.begin(), compositeKeyColumnNames.end(), c.name); + if(it == compositeKeyColumnNames.end()) { + columnNames.emplace_back(c.name); + } + } + }); + + auto columnNamesCount = columnNames.size(); + if(columnNamesCount) { + ss << "("; + for(size_t i = 0; i < columnNamesCount; ++i) { + ss << "\"" << columnNames[i] << "\""; + if(i < columnNamesCount - 1) { + ss << ","; + } else { + ss << ")"; + } + ss << " "; + } + } else { + ss << "DEFAULT "; + } + ss << "VALUES "; + if(columnNamesCount) { + ss << "("; + for(size_t i = 0; i < columnNamesCount; ++i) { + ss << "?"; + if(i < columnNamesCount - 1) { + ss << ", "; + } else { + ss << ")"; + } + } + } + return ss.str(); + } + }; + template struct statement_serializator, void> { using statement_type = remove_t; @@ -10763,56 +10816,6 @@ namespace sqlite_orm { return ss.str(); } - template - std::string string_from_expression(const insert_t &ins, bool /*noTableName*/) const { - using expression_type = typename std::decay::type; - using object_type = typename expression_object_type::type; - this->assert_mapped_type(); - auto &tImpl = this->get_impl(); - std::stringstream ss; - ss << "INSERT INTO '" << tImpl.table.name << "' "; - std::vector columnNames; - auto compositeKeyColumnNames = tImpl.table.composite_key_columns_names(); - - tImpl.table.for_each_column([&tImpl, &columnNames, &compositeKeyColumnNames](auto &c) { - if(tImpl.table._without_rowid || !c.template has>()) { - auto it = std::find(compositeKeyColumnNames.begin(), compositeKeyColumnNames.end(), c.name); - if(it == compositeKeyColumnNames.end()) { - columnNames.emplace_back(c.name); - } - } - }); - - auto columnNamesCount = columnNames.size(); - if(columnNamesCount) { - ss << "("; - for(size_t i = 0; i < columnNamesCount; ++i) { - ss << "\"" << columnNames[i] << "\""; - if(i < columnNamesCount - 1) { - ss << ","; - } else { - ss << ")"; - } - ss << " "; - } - } else { - ss << "DEFAULT "; - } - ss << "VALUES "; - if(columnNamesCount) { - ss << "("; - for(size_t i = 0; i < columnNamesCount; ++i) { - ss << "?"; - if(i < columnNamesCount - 1) { - ss << ", "; - } else { - ss << ")"; - } - } - } - return ss.str(); - } - template std::string string_from_expression(const replace_t &rep, bool /*noTableName*/) const { using expression_type = typename std::decay::type; @@ -11607,10 +11610,16 @@ namespace sqlite_orm { template prepared_statement_t> prepare(insert_t ins) { + using object_type = typename expression_object_type::type; + this->assert_mapped_type(); auto con = this->get_connection(); sqlite3_stmt *stmt; auto db = con.get(); - auto query = this->string_from_expression(ins, false); + using context_t = serializator_context; + context_t context{this->impl}; + context.skip_table_name = false; + context.replace_bindable_with_question = true; + auto query = serialize(ins, context); if(sqlite3_prepare_v2(db, query.c_str(), -1, &stmt, nullptr) == SQLITE_OK) { return {std::move(ins), stmt, con}; } else { From 25df9c63229ed2648d6d887af71b23992e2a869f Mon Sep 17 00:00:00 2001 From: fnc12 Date: Mon, 11 May 2020 20:05:03 +0300 Subject: [PATCH 064/132] removed string_from_expression for remove_all_t --- dev/statement_serializator.h | 16 +++++++++++++ dev/storage.h | 21 ++++------------- include/sqlite_orm/sqlite_orm.h | 41 ++++++++++++++++++++------------- 3 files changed, 46 insertions(+), 32 deletions(-) diff --git a/dev/statement_serializator.h b/dev/statement_serializator.h index fec6afb94..5baacbfc0 100644 --- a/dev/statement_serializator.h +++ b/dev/statement_serializator.h @@ -740,6 +740,22 @@ namespace sqlite_orm { } }; + template + struct statement_serializator, void> { + using statement_type = remove_all_t; + + template + std::string operator()(const statement_type &rem, const C &context) const { + auto &tImpl = context.impl.template get_impl(); + std::stringstream ss; + ss << "DELETE FROM '" << tImpl.table.name << "' "; + iterate_tuple(rem.conditions, [&context, &ss](auto &v) { + ss << serialize(v, context); + }); + return ss.str(); + } + }; + template struct statement_serializator, void> { using statement_type = insert_t; diff --git a/dev/storage.h b/dev/storage.h index 34b379cd4..b9eaf3451 100644 --- a/dev/storage.h +++ b/dev/storage.h @@ -287,21 +287,6 @@ namespace sqlite_orm { } } - template - std::string string_from_expression(const remove_all_t &rem, bool /*noTableName*/) const { - auto &tImpl = this->get_impl(); - std::stringstream ss; - ss << "DELETE FROM '" << tImpl.table.name << "' "; - using context_t = serializator_context; - context_t context{this->impl}; - context.skip_table_name = false; - context.replace_bindable_with_question = true; - iterate_tuple(rem.conditions, [&context, &ss](auto &v) { - ss << serialize(v, context); - }); - return ss.str(); - } - // Common code for statements with conditions: get_t, get_pointer_t, get_optional_t. template std::string string_from_expression_impl_get(bool /*noTableName*/) const { @@ -1138,7 +1123,11 @@ namespace sqlite_orm { auto con = this->get_connection(); sqlite3_stmt *stmt; auto db = con.get(); - auto query = this->string_from_expression(rem, false); + using context_t = serializator_context; + context_t context{this->impl}; + context.skip_table_name = false; + context.replace_bindable_with_question = true; + auto query = serialize(rem, context); if(sqlite3_prepare_v2(db, query.c_str(), -1, &stmt, nullptr) == SQLITE_OK) { return {std::move(rem), stmt, std::move(con)}; } else { diff --git a/include/sqlite_orm/sqlite_orm.h b/include/sqlite_orm/sqlite_orm.h index 4b7810cea..ec37acd58 100644 --- a/include/sqlite_orm/sqlite_orm.h +++ b/include/sqlite_orm/sqlite_orm.h @@ -9984,6 +9984,26 @@ namespace sqlite_orm { } }; + template + struct statement_serializator, void> { + using statement_type = remove_all_t; + + template + std::string operator()(const statement_type &rem, const C &context) const { + auto &tImpl = context.impl.template get_impl(); + std::stringstream ss; + ss << "DELETE FROM '" << tImpl.table.name << "' "; + // using context_t = serializator_context; + // context_t context{this->impl}; + // context.skip_table_name = false; + // context.replace_bindable_with_question = true; + iterate_tuple(rem.conditions, [&context, &ss](auto &v) { + ss << serialize(v, context); + }); + return ss.str(); + } + }; + template struct statement_serializator, void> { using statement_type = insert_t; @@ -10672,21 +10692,6 @@ namespace sqlite_orm { } } - template - std::string string_from_expression(const remove_all_t &rem, bool /*noTableName*/) const { - auto &tImpl = this->get_impl(); - std::stringstream ss; - ss << "DELETE FROM '" << tImpl.table.name << "' "; - using context_t = serializator_context; - context_t context{this->impl}; - context.skip_table_name = false; - context.replace_bindable_with_question = true; - iterate_tuple(rem.conditions, [&context, &ss](auto &v) { - ss << serialize(v, context); - }); - return ss.str(); - } - // Common code for statements with conditions: get_t, get_pointer_t, get_optional_t. template std::string string_from_expression_impl_get(bool /*noTableName*/) const { @@ -11523,7 +11528,11 @@ namespace sqlite_orm { auto con = this->get_connection(); sqlite3_stmt *stmt; auto db = con.get(); - auto query = this->string_from_expression(rem, false); + using context_t = serializator_context; + context_t context{this->impl}; + context.skip_table_name = false; + context.replace_bindable_with_question = true; + auto query = serialize(rem, context); if(sqlite3_prepare_v2(db, query.c_str(), -1, &stmt, nullptr) == SQLITE_OK) { return {std::move(rem), stmt, std::move(con)}; } else { From abf63c69dd79e0f57910f4e173f076252687a47a Mon Sep 17 00:00:00 2001 From: fnc12 Date: Tue, 12 May 2020 16:55:19 +0300 Subject: [PATCH 065/132] removed string_from_expression for update_all_t --- dev/statement_serializator.h | 46 ++++++++++++++ dev/storage.h | 52 ++-------------- include/sqlite_orm/sqlite_orm.h | 104 ++++++++++++++++---------------- 3 files changed, 104 insertions(+), 98 deletions(-) diff --git a/dev/statement_serializator.h b/dev/statement_serializator.h index 5baacbfc0..ddb266714 100644 --- a/dev/statement_serializator.h +++ b/dev/statement_serializator.h @@ -756,6 +756,52 @@ namespace sqlite_orm { } }; + template + struct statement_serializator, Wargs...>, void> { + using statement_type = update_all_t, Wargs...>; + + template + std::string operator()(const statement_type &upd, const C &context) const { + std::stringstream ss; + ss << "UPDATE "; + table_name_collector collector{[&context](std::type_index ti) { + return context.impl.find_table_name(ti); + }}; + iterate_ast(upd.set.assigns, collector); + if(!collector.table_names.empty()) { + if(collector.table_names.size() == 1) { + ss << " '" << collector.table_names.begin()->first << "' "; + ss << static_cast(upd.set) << " "; + std::vector setPairs; + auto leftContext = context; + leftContext.skip_table_name = true; + iterate_tuple(upd.set.assigns, [&context, &leftContext, &setPairs](auto &asgn) { + std::stringstream sss; + sss << serialize(asgn.lhs, leftContext); + sss << " " << static_cast(asgn) << " "; + sss << serialize(asgn.rhs, context) << " "; + setPairs.push_back(sss.str()); + }); + auto setPairsCount = setPairs.size(); + for(size_t i = 0; i < setPairsCount; ++i) { + ss << setPairs[i] << " "; + if(i < setPairsCount - 1) { + ss << ", "; + } + } + iterate_tuple(upd.conditions, [&context, &ss](auto &v) { + ss << serialize(v, context); + }); + return ss.str(); + } else { + throw std::system_error(std::make_error_code(orm_error_code::too_many_tables_specified)); + } + } else { + throw std::system_error(std::make_error_code(orm_error_code::incorrect_set_fields_specified)); + } + } + }; + template struct statement_serializator, void> { using statement_type = insert_t; diff --git a/dev/storage.h b/dev/storage.h index b9eaf3451..0d914f16d 100644 --- a/dev/storage.h +++ b/dev/storage.h @@ -241,52 +241,6 @@ namespace sqlite_orm { } #endif // SQLITE_ORM_OPTIONAL_SUPPORTED - template - std::string string_from_expression(const update_all_t, Wargs...> &upd, - bool /*noTableName*/) const { - std::stringstream ss; - ss << "UPDATE "; - table_name_collector collector{[this](std::type_index ti) { - return this->impl.find_table_name(ti); - }}; - iterate_ast(upd.set.assigns, collector); - if(!collector.table_names.empty()) { - if(collector.table_names.size() == 1) { - ss << " '" << collector.table_names.begin()->first << "' "; - ss << static_cast(upd.set) << " "; - std::vector setPairs; - using context_t = serializator_context; - context_t context{this->impl}; - context.replace_bindable_with_question = true; - iterate_tuple(upd.set.assigns, [&context, &setPairs](auto &asgn) { - std::stringstream sss; - context.skip_table_name = true; - sss << serialize(asgn.lhs, context); - sss << " " << static_cast(asgn) << " "; - context.skip_table_name = false; - sss << serialize(asgn.rhs, context) << " "; - setPairs.push_back(sss.str()); - }); - auto setPairsCount = setPairs.size(); - for(size_t i = 0; i < setPairsCount; ++i) { - ss << setPairs[i] << " "; - if(i < setPairsCount - 1) { - ss << ", "; - } - } - context.skip_table_name = false; - iterate_tuple(upd.conditions, [&context, &ss](auto &v) { - ss << serialize(v, context); - }); - return ss.str(); - } else { - throw std::system_error(std::make_error_code(orm_error_code::too_many_tables_specified)); - } - } else { - throw std::system_error(std::make_error_code(orm_error_code::incorrect_set_fields_specified)); - } - } - // Common code for statements with conditions: get_t, get_pointer_t, get_optional_t. template std::string string_from_expression_impl_get(bool /*noTableName*/) const { @@ -1109,7 +1063,11 @@ namespace sqlite_orm { auto con = this->get_connection(); sqlite3_stmt *stmt; auto db = con.get(); - auto query = this->string_from_expression(upd, false); + using context_t = serializator_context; + context_t context{this->impl}; + context.skip_table_name = false; + context.replace_bindable_with_question = true; + auto query = serialize(upd, context); if(sqlite3_prepare_v2(db, query.c_str(), -1, &stmt, nullptr) == SQLITE_OK) { return {std::move(upd), stmt, con}; } else { diff --git a/include/sqlite_orm/sqlite_orm.h b/include/sqlite_orm/sqlite_orm.h index ec37acd58..11fd1eb47 100644 --- a/include/sqlite_orm/sqlite_orm.h +++ b/include/sqlite_orm/sqlite_orm.h @@ -9993,10 +9993,6 @@ namespace sqlite_orm { auto &tImpl = context.impl.template get_impl(); std::stringstream ss; ss << "DELETE FROM '" << tImpl.table.name << "' "; - // using context_t = serializator_context; - // context_t context{this->impl}; - // context.skip_table_name = false; - // context.replace_bindable_with_question = true; iterate_tuple(rem.conditions, [&context, &ss](auto &v) { ss << serialize(v, context); }); @@ -10004,6 +10000,54 @@ namespace sqlite_orm { } }; + template + struct statement_serializator, Wargs...>, void> { + using statement_type = update_all_t, Wargs...>; + + template + std::string operator()(const statement_type &upd, const C &context) const { + std::stringstream ss; + ss << "UPDATE "; + table_name_collector collector{[&context](std::type_index ti) { + return context.impl.find_table_name(ti); + }}; + iterate_ast(upd.set.assigns, collector); + if(!collector.table_names.empty()) { + if(collector.table_names.size() == 1) { + ss << " '" << collector.table_names.begin()->first << "' "; + ss << static_cast(upd.set) << " "; + std::vector setPairs; + auto leftContext = context; + leftContext.skip_table_name = true; + iterate_tuple(upd.set.assigns, [&context, &leftContext, &setPairs](auto &asgn) { + std::stringstream sss; + sss << serialize(asgn.lhs, leftContext); + sss << " " << static_cast(asgn) << " "; + // context.skip_table_name = false; + sss << serialize(asgn.rhs, context) << " "; + setPairs.push_back(sss.str()); + }); + auto setPairsCount = setPairs.size(); + for(size_t i = 0; i < setPairsCount; ++i) { + ss << setPairs[i] << " "; + if(i < setPairsCount - 1) { + ss << ", "; + } + } + // context.skip_table_name = false; + iterate_tuple(upd.conditions, [&context, &ss](auto &v) { + ss << serialize(v, context); + }); + return ss.str(); + } else { + throw std::system_error(std::make_error_code(orm_error_code::too_many_tables_specified)); + } + } else { + throw std::system_error(std::make_error_code(orm_error_code::incorrect_set_fields_specified)); + } + } + }; + template struct statement_serializator, void> { using statement_type = insert_t; @@ -10646,52 +10690,6 @@ namespace sqlite_orm { } #endif // SQLITE_ORM_OPTIONAL_SUPPORTED - template - std::string string_from_expression(const update_all_t, Wargs...> &upd, - bool /*noTableName*/) const { - std::stringstream ss; - ss << "UPDATE "; - table_name_collector collector{[this](std::type_index ti) { - return this->impl.find_table_name(ti); - }}; - iterate_ast(upd.set.assigns, collector); - if(!collector.table_names.empty()) { - if(collector.table_names.size() == 1) { - ss << " '" << collector.table_names.begin()->first << "' "; - ss << static_cast(upd.set) << " "; - std::vector setPairs; - using context_t = serializator_context; - context_t context{this->impl}; - context.replace_bindable_with_question = true; - iterate_tuple(upd.set.assigns, [&context, &setPairs](auto &asgn) { - std::stringstream sss; - context.skip_table_name = true; - sss << serialize(asgn.lhs, context); - sss << " " << static_cast(asgn) << " "; - context.skip_table_name = false; - sss << serialize(asgn.rhs, context) << " "; - setPairs.push_back(sss.str()); - }); - auto setPairsCount = setPairs.size(); - for(size_t i = 0; i < setPairsCount; ++i) { - ss << setPairs[i] << " "; - if(i < setPairsCount - 1) { - ss << ", "; - } - } - context.skip_table_name = false; - iterate_tuple(upd.conditions, [&context, &ss](auto &v) { - ss << serialize(v, context); - }); - return ss.str(); - } else { - throw std::system_error(std::make_error_code(orm_error_code::too_many_tables_specified)); - } - } else { - throw std::system_error(std::make_error_code(orm_error_code::incorrect_set_fields_specified)); - } - } - // Common code for statements with conditions: get_t, get_pointer_t, get_optional_t. template std::string string_from_expression_impl_get(bool /*noTableName*/) const { @@ -11514,7 +11512,11 @@ namespace sqlite_orm { auto con = this->get_connection(); sqlite3_stmt *stmt; auto db = con.get(); - auto query = this->string_from_expression(upd, false); + using context_t = serializator_context; + context_t context{this->impl}; + context.skip_table_name = false; + context.replace_bindable_with_question = true; + auto query = serialize(upd, context); if(sqlite3_prepare_v2(db, query.c_str(), -1, &stmt, nullptr) == SQLITE_OK) { return {std::move(upd), stmt, con}; } else { From a908ac43aec8b6f3bd7baeb6fcfbf9bc132a80e0 Mon Sep 17 00:00:00 2001 From: fnc12 Date: Tue, 12 May 2020 17:16:13 +0300 Subject: [PATCH 066/132] removed string_from_expression for update_t --- dev/statement_serializator.h | 40 ++++++++++++++++ dev/storage.h | 41 ++-------------- include/sqlite_orm/sqlite_orm.h | 83 ++++++++++++++++++--------------- 3 files changed, 90 insertions(+), 74 deletions(-) diff --git a/dev/statement_serializator.h b/dev/statement_serializator.h index ddb266714..a27ccc040 100644 --- a/dev/statement_serializator.h +++ b/dev/statement_serializator.h @@ -756,6 +756,46 @@ namespace sqlite_orm { } }; + template + struct statement_serializator, void> { + using statement_type = update_t; + + template + std::string operator()(const statement_type &upd, const C &context) const { + using expression_type = typename std::decay::type; + using object_type = typename expression_object_type::type; + auto &tImpl = context.impl.template get_impl(); + + std::stringstream ss; + ss << "UPDATE '" << tImpl.table.name << "' SET "; + std::vector setColumnNames; + tImpl.table.for_each_column([&setColumnNames](auto &c) { + if(!c.template has>()) { + setColumnNames.emplace_back(c.name); + } + }); + for(size_t i = 0; i < setColumnNames.size(); ++i) { + ss << "\"" << setColumnNames[i] << "\"" + << " = ?"; + if(i < setColumnNames.size() - 1) { + ss << ","; + } + ss << " "; + } + ss << "WHERE "; + auto primaryKeyColumnNames = tImpl.table.primary_key_column_names(); + for(size_t i = 0; i < primaryKeyColumnNames.size(); ++i) { + ss << "\"" << primaryKeyColumnNames[i] << "\"" + << " = ?"; + if(i < primaryKeyColumnNames.size() - 1) { + ss << " AND"; + } + ss << " "; + } + return ss.str(); + } + }; + template struct statement_serializator, Wargs...>, void> { using statement_type = update_all_t, Wargs...>; diff --git a/dev/storage.h b/dev/storage.h index 0d914f16d..dc9935a8e 100644 --- a/dev/storage.h +++ b/dev/storage.h @@ -289,41 +289,6 @@ namespace sqlite_orm { } #endif // SQLITE_ORM_OPTIONAL_SUPPORTED - template - std::string string_from_expression(const update_t &upd, bool /*noTableName*/) const { - using expression_type = typename std::decay::type; - using object_type = typename expression_object_type::type; - auto &tImpl = this->get_impl(); - - std::stringstream ss; - ss << "UPDATE '" << tImpl.table.name << "' SET "; - std::vector setColumnNames; - tImpl.table.for_each_column([&setColumnNames](auto &c) { - if(!c.template has>()) { - setColumnNames.emplace_back(c.name); - } - }); - for(size_t i = 0; i < setColumnNames.size(); ++i) { - ss << "\"" << setColumnNames[i] << "\"" - << " = ?"; - if(i < setColumnNames.size() - 1) { - ss << ","; - } - ss << " "; - } - ss << "WHERE "; - auto primaryKeyColumnNames = tImpl.table.primary_key_column_names(); - for(size_t i = 0; i < primaryKeyColumnNames.size(); ++i) { - ss << "\"" << primaryKeyColumnNames[i] << "\"" - << " = ?"; - if(i < primaryKeyColumnNames.size() - 1) { - ss << " AND"; - } - ss << " "; - } - return ss.str(); - } - template std::string string_from_expression(const insert_explicit &ins, bool /*noTableName*/) const { constexpr const size_t colsCount = std::tuple_size>::value; @@ -1143,7 +1108,11 @@ namespace sqlite_orm { auto con = this->get_connection(); sqlite3_stmt *stmt; auto db = con.get(); - auto query = this->string_from_expression(upd, false); + using context_t = serializator_context; + context_t context{this->impl}; + context.skip_table_name = false; + context.replace_bindable_with_question = true; + auto query = serialize(upd, context); if(sqlite3_prepare_v2(db, query.c_str(), -1, &stmt, nullptr) == SQLITE_OK) { return {std::move(upd), stmt, con}; } else { diff --git a/include/sqlite_orm/sqlite_orm.h b/include/sqlite_orm/sqlite_orm.h index 11fd1eb47..2586f2650 100644 --- a/include/sqlite_orm/sqlite_orm.h +++ b/include/sqlite_orm/sqlite_orm.h @@ -10000,6 +10000,46 @@ namespace sqlite_orm { } }; + template + struct statement_serializator, void> { + using statement_type = update_t; + + template + std::string operator()(const statement_type &upd, const C &context) const { + using expression_type = typename std::decay::type; + using object_type = typename expression_object_type::type; + auto &tImpl = context.impl.template get_impl(); + + std::stringstream ss; + ss << "UPDATE '" << tImpl.table.name << "' SET "; + std::vector setColumnNames; + tImpl.table.for_each_column([&setColumnNames](auto &c) { + if(!c.template has>()) { + setColumnNames.emplace_back(c.name); + } + }); + for(size_t i = 0; i < setColumnNames.size(); ++i) { + ss << "\"" << setColumnNames[i] << "\"" + << " = ?"; + if(i < setColumnNames.size() - 1) { + ss << ","; + } + ss << " "; + } + ss << "WHERE "; + auto primaryKeyColumnNames = tImpl.table.primary_key_column_names(); + for(size_t i = 0; i < primaryKeyColumnNames.size(); ++i) { + ss << "\"" << primaryKeyColumnNames[i] << "\"" + << " = ?"; + if(i < primaryKeyColumnNames.size() - 1) { + ss << " AND"; + } + ss << " "; + } + return ss.str(); + } + }; + template struct statement_serializator, Wargs...>, void> { using statement_type = update_all_t, Wargs...>; @@ -10023,7 +10063,6 @@ namespace sqlite_orm { std::stringstream sss; sss << serialize(asgn.lhs, leftContext); sss << " " << static_cast(asgn) << " "; - // context.skip_table_name = false; sss << serialize(asgn.rhs, context) << " "; setPairs.push_back(sss.str()); }); @@ -10034,7 +10073,6 @@ namespace sqlite_orm { ss << ", "; } } - // context.skip_table_name = false; iterate_tuple(upd.conditions, [&context, &ss](auto &v) { ss << serialize(v, context); }); @@ -10738,41 +10776,6 @@ namespace sqlite_orm { } #endif // SQLITE_ORM_OPTIONAL_SUPPORTED - template - std::string string_from_expression(const update_t &upd, bool /*noTableName*/) const { - using expression_type = typename std::decay::type; - using object_type = typename expression_object_type::type; - auto &tImpl = this->get_impl(); - - std::stringstream ss; - ss << "UPDATE '" << tImpl.table.name << "' SET "; - std::vector setColumnNames; - tImpl.table.for_each_column([&setColumnNames](auto &c) { - if(!c.template has>()) { - setColumnNames.emplace_back(c.name); - } - }); - for(size_t i = 0; i < setColumnNames.size(); ++i) { - ss << "\"" << setColumnNames[i] << "\"" - << " = ?"; - if(i < setColumnNames.size() - 1) { - ss << ","; - } - ss << " "; - } - ss << "WHERE "; - auto primaryKeyColumnNames = tImpl.table.primary_key_column_names(); - for(size_t i = 0; i < primaryKeyColumnNames.size(); ++i) { - ss << "\"" << primaryKeyColumnNames[i] << "\"" - << " = ?"; - if(i < primaryKeyColumnNames.size() - 1) { - ss << " AND"; - } - ss << " "; - } - return ss.str(); - } - template std::string string_from_expression(const insert_explicit &ins, bool /*noTableName*/) const { constexpr const size_t colsCount = std::tuple_size>::value; @@ -11592,7 +11595,11 @@ namespace sqlite_orm { auto con = this->get_connection(); sqlite3_stmt *stmt; auto db = con.get(); - auto query = this->string_from_expression(upd, false); + using context_t = serializator_context; + context_t context{this->impl}; + context.skip_table_name = false; + context.replace_bindable_with_question = true; + auto query = serialize(upd, context); if(sqlite3_prepare_v2(db, query.c_str(), -1, &stmt, nullptr) == SQLITE_OK) { return {std::move(upd), stmt, con}; } else { From 2c85daec645c2fe7053d3d86be79d0a9996effa9 Mon Sep 17 00:00:00 2001 From: fnc12 Date: Tue, 12 May 2020 20:25:44 +0300 Subject: [PATCH 067/132] remove string_from_expression for insert_explicit_t --- dev/statement_serializator.h | 51 ++++++++++++++++ dev/storage.h | 54 +++------------- include/sqlite_orm/sqlite_orm.h | 105 ++++++++++++++++++-------------- 3 files changed, 116 insertions(+), 94 deletions(-) diff --git a/dev/statement_serializator.h b/dev/statement_serializator.h index a27ccc040..11f552dd1 100644 --- a/dev/statement_serializator.h +++ b/dev/statement_serializator.h @@ -756,6 +756,57 @@ namespace sqlite_orm { } }; + template + struct statement_serializator, void> { + using statement_type = insert_explicit; + + template + std::string operator()(const statement_type &ins, const C &context) const { + constexpr const size_t colsCount = std::tuple_size>::value; + static_assert(colsCount > 0, "Use insert or replace with 1 argument instead"); + using expression_type = typename std::decay::type; + using object_type = typename expression_object_type::type; + auto &tImpl = context.impl.template get_impl(); + std::stringstream ss; + ss << "INSERT INTO '" << tImpl.table.name << "' "; + std::vector columnNames; + columnNames.reserve(colsCount); + { + auto columnsContext = context; + columnsContext.skip_table_name = true; + iterate_tuple(ins.columns.columns, [&columnNames, &columnsContext](auto &m) { + auto columnName = serialize(m, columnsContext); + if(!columnName.empty()) { + columnNames.push_back(columnName); + } else { + throw std::system_error(std::make_error_code(orm_error_code::column_not_found)); + } + }); + } + ss << "("; + for(size_t i = 0; i < columnNames.size(); ++i) { + ss << columnNames[i]; + if(i < columnNames.size() - 1) { + ss << ","; + } else { + ss << ")"; + } + ss << " "; + } + ss << "VALUES ("; + for(size_t i = 0; i < columnNames.size(); ++i) { + ss << "?"; + if(i < columnNames.size() - 1) { + ss << ","; + } else { + ss << ")"; + } + ss << " "; + } + return ss.str(); + } + }; + template struct statement_serializator, void> { using statement_type = update_t; diff --git a/dev/storage.h b/dev/storage.h index dc9935a8e..d12b2b918 100644 --- a/dev/storage.h +++ b/dev/storage.h @@ -289,52 +289,6 @@ namespace sqlite_orm { } #endif // SQLITE_ORM_OPTIONAL_SUPPORTED - template - std::string string_from_expression(const insert_explicit &ins, bool /*noTableName*/) const { - constexpr const size_t colsCount = std::tuple_size>::value; - static_assert(colsCount > 0, "Use insert or replace with 1 argument instead"); - using expression_type = typename std::decay::type; - using object_type = typename expression_object_type::type; - this->assert_mapped_type(); - auto &tImpl = this->get_impl(); - std::stringstream ss; - ss << "INSERT INTO '" << tImpl.table.name << "' "; - std::vector columnNames; - columnNames.reserve(colsCount); - using context_t = serializator_context; - context_t context{this->impl}; - context.skip_table_name = true; - iterate_tuple(ins.columns.columns, [&columnNames, &context](auto &m) { - auto columnName = serialize(m, context); - if(!columnName.empty()) { - columnNames.push_back(columnName); - } else { - throw std::system_error(std::make_error_code(orm_error_code::column_not_found)); - } - }); - ss << "("; - for(size_t i = 0; i < columnNames.size(); ++i) { - ss << columnNames[i]; - if(i < columnNames.size() - 1) { - ss << ","; - } else { - ss << ")"; - } - ss << " "; - } - ss << "VALUES ("; - for(size_t i = 0; i < columnNames.size(); ++i) { - ss << "?"; - if(i < columnNames.size() - 1) { - ss << ","; - } else { - ss << ")"; - } - ss << " "; - } - return ss.str(); - } - template std::string string_from_expression(const replace_t &rep, bool /*noTableName*/) const { using expression_type = typename std::decay::type; @@ -1207,10 +1161,16 @@ namespace sqlite_orm { template prepared_statement_t> prepare(insert_explicit ins) { + using object_type = typename expression_object_type::type; + this->assert_mapped_type(); auto con = this->get_connection(); sqlite3_stmt *stmt; auto db = con.get(); - auto query = this->string_from_expression(ins, false); + using context_t = serializator_context; + context_t context{this->impl}; + context.skip_table_name = false; + context.replace_bindable_with_question = true; + auto query = serialize(ins, context); if(sqlite3_prepare_v2(db, query.c_str(), -1, &stmt, nullptr) == SQLITE_OK) { return {std::move(ins), stmt, con}; } else { diff --git a/include/sqlite_orm/sqlite_orm.h b/include/sqlite_orm/sqlite_orm.h index 2586f2650..ace97e17a 100644 --- a/include/sqlite_orm/sqlite_orm.h +++ b/include/sqlite_orm/sqlite_orm.h @@ -10000,6 +10000,57 @@ namespace sqlite_orm { } }; + template + struct statement_serializator, void> { + using statement_type = insert_explicit; + + template + std::string operator()(const statement_type &ins, const C &context) const { + constexpr const size_t colsCount = std::tuple_size>::value; + static_assert(colsCount > 0, "Use insert or replace with 1 argument instead"); + using expression_type = typename std::decay::type; + using object_type = typename expression_object_type::type; + auto &tImpl = context.impl.template get_impl(); + std::stringstream ss; + ss << "INSERT INTO '" << tImpl.table.name << "' "; + std::vector columnNames; + columnNames.reserve(colsCount); + { + auto columnsContext = context; + columnsContext.skip_table_name = true; + iterate_tuple(ins.columns.columns, [&columnNames, &columnsContext](auto &m) { + auto columnName = serialize(m, columnsContext); + if(!columnName.empty()) { + columnNames.push_back(columnName); + } else { + throw std::system_error(std::make_error_code(orm_error_code::column_not_found)); + } + }); + } + ss << "("; + for(size_t i = 0; i < columnNames.size(); ++i) { + ss << columnNames[i]; + if(i < columnNames.size() - 1) { + ss << ","; + } else { + ss << ")"; + } + ss << " "; + } + ss << "VALUES ("; + for(size_t i = 0; i < columnNames.size(); ++i) { + ss << "?"; + if(i < columnNames.size() - 1) { + ss << ","; + } else { + ss << ")"; + } + ss << " "; + } + return ss.str(); + } + }; + template struct statement_serializator, void> { using statement_type = update_t; @@ -10776,52 +10827,6 @@ namespace sqlite_orm { } #endif // SQLITE_ORM_OPTIONAL_SUPPORTED - template - std::string string_from_expression(const insert_explicit &ins, bool /*noTableName*/) const { - constexpr const size_t colsCount = std::tuple_size>::value; - static_assert(colsCount > 0, "Use insert or replace with 1 argument instead"); - using expression_type = typename std::decay::type; - using object_type = typename expression_object_type::type; - this->assert_mapped_type(); - auto &tImpl = this->get_impl(); - std::stringstream ss; - ss << "INSERT INTO '" << tImpl.table.name << "' "; - std::vector columnNames; - columnNames.reserve(colsCount); - using context_t = serializator_context; - context_t context{this->impl}; - context.skip_table_name = true; - iterate_tuple(ins.columns.columns, [&columnNames, &context](auto &m) { - auto columnName = serialize(m, context); - if(!columnName.empty()) { - columnNames.push_back(columnName); - } else { - throw std::system_error(std::make_error_code(orm_error_code::column_not_found)); - } - }); - ss << "("; - for(size_t i = 0; i < columnNames.size(); ++i) { - ss << columnNames[i]; - if(i < columnNames.size() - 1) { - ss << ","; - } else { - ss << ")"; - } - ss << " "; - } - ss << "VALUES ("; - for(size_t i = 0; i < columnNames.size(); ++i) { - ss << "?"; - if(i < columnNames.size() - 1) { - ss << ","; - } else { - ss << ")"; - } - ss << " "; - } - return ss.str(); - } - template std::string string_from_expression(const replace_t &rep, bool /*noTableName*/) const { using expression_type = typename std::decay::type; @@ -11694,10 +11699,16 @@ namespace sqlite_orm { template prepared_statement_t> prepare(insert_explicit ins) { + using object_type = typename expression_object_type::type; + this->assert_mapped_type(); auto con = this->get_connection(); sqlite3_stmt *stmt; auto db = con.get(); - auto query = this->string_from_expression(ins, false); + using context_t = serializator_context; + context_t context{this->impl}; + context.skip_table_name = false; + context.replace_bindable_with_question = true; + auto query = serialize(ins, context); if(sqlite3_prepare_v2(db, query.c_str(), -1, &stmt, nullptr) == SQLITE_OK) { return {std::move(ins), stmt, con}; } else { From 8b8a544ea4c757383ac1fe4448ed2d4d26f42866 Mon Sep 17 00:00:00 2001 From: fnc12 Date: Tue, 12 May 2020 20:33:00 +0300 Subject: [PATCH 068/132] removed string_from_expression for replace_t --- dev/statement_serializator.h | 35 ++++++++++++++++ dev/storage.h | 39 ++++------------- include/sqlite_orm/sqlite_orm.h | 74 +++++++++++++++++++-------------- 3 files changed, 84 insertions(+), 64 deletions(-) diff --git a/dev/statement_serializator.h b/dev/statement_serializator.h index 11f552dd1..61c6807b9 100644 --- a/dev/statement_serializator.h +++ b/dev/statement_serializator.h @@ -756,6 +756,41 @@ namespace sqlite_orm { } }; + template + struct statement_serializator, void> { + using statement_type = replace_t; + + template + std::string operator()(const statement_type &rep, const C &context) const { + using expression_type = typename std::decay::type; + using object_type = typename expression_object_type::type; + auto &tImpl = context.impl.template get_impl(); + std::stringstream ss; + ss << "REPLACE INTO '" << tImpl.table.name << "' ("; + auto columnNames = tImpl.table.column_names(); + auto columnNamesCount = columnNames.size(); + for(size_t i = 0; i < columnNamesCount; ++i) { + ss << "\"" << columnNames[i] << "\""; + if(i < columnNamesCount - 1) { + ss << ","; + } else { + ss << ")"; + } + ss << " "; + } + ss << "VALUES("; + for(size_t i = 0; i < columnNamesCount; ++i) { + ss << "?"; + if(i < columnNamesCount - 1) { + ss << ", "; + } else { + ss << ")"; + } + } + return ss.str(); + } + }; + template struct statement_serializator, void> { using statement_type = insert_explicit; diff --git a/dev/storage.h b/dev/storage.h index d12b2b918..921a0ebc5 100644 --- a/dev/storage.h +++ b/dev/storage.h @@ -289,37 +289,6 @@ namespace sqlite_orm { } #endif // SQLITE_ORM_OPTIONAL_SUPPORTED - template - std::string string_from_expression(const replace_t &rep, bool /*noTableName*/) const { - using expression_type = typename std::decay::type; - using object_type = typename expression_object_type::type; - this->assert_mapped_type(); - auto &tImpl = this->get_impl(); - std::stringstream ss; - ss << "REPLACE INTO '" << tImpl.table.name << "' ("; - auto columnNames = tImpl.table.column_names(); - auto columnNamesCount = columnNames.size(); - for(size_t i = 0; i < columnNamesCount; ++i) { - ss << "\"" << columnNames[i] << "\""; - if(i < columnNamesCount - 1) { - ss << ","; - } else { - ss << ")"; - } - ss << " "; - } - ss << "VALUES("; - for(size_t i = 0; i < columnNamesCount; ++i) { - ss << "?"; - if(i < columnNamesCount - 1) { - ss << ", "; - } else { - ss << ")"; - } - } - return ss.str(); - } - template std::string string_from_expression(const replace_range_t &rep, bool /*noTableName*/) const { using expression_type = typename std::decay::type; @@ -1117,8 +1086,14 @@ namespace sqlite_orm { prepared_statement_t> prepare(replace_t rep) { auto con = this->get_connection(); sqlite3_stmt *stmt; + using object_type = typename expression_object_type::type; + this->assert_mapped_type(); auto db = con.get(); - auto query = this->string_from_expression(rep, false); + using context_t = serializator_context; + context_t context{this->impl}; + context.skip_table_name = false; + context.replace_bindable_with_question = true; + auto query = serialize(rep, context); if(sqlite3_prepare_v2(db, query.c_str(), -1, &stmt, nullptr) == SQLITE_OK) { return {std::move(rep), stmt, con}; } else { diff --git a/include/sqlite_orm/sqlite_orm.h b/include/sqlite_orm/sqlite_orm.h index ace97e17a..87edfabd0 100644 --- a/include/sqlite_orm/sqlite_orm.h +++ b/include/sqlite_orm/sqlite_orm.h @@ -10000,6 +10000,41 @@ namespace sqlite_orm { } }; + template + struct statement_serializator, void> { + using statement_type = replace_t; + + template + std::string operator()(const statement_type &rep, const C &context) const { + using expression_type = typename std::decay::type; + using object_type = typename expression_object_type::type; + auto &tImpl = context.impl.template get_impl(); + std::stringstream ss; + ss << "REPLACE INTO '" << tImpl.table.name << "' ("; + auto columnNames = tImpl.table.column_names(); + auto columnNamesCount = columnNames.size(); + for(size_t i = 0; i < columnNamesCount; ++i) { + ss << "\"" << columnNames[i] << "\""; + if(i < columnNamesCount - 1) { + ss << ","; + } else { + ss << ")"; + } + ss << " "; + } + ss << "VALUES("; + for(size_t i = 0; i < columnNamesCount; ++i) { + ss << "?"; + if(i < columnNamesCount - 1) { + ss << ", "; + } else { + ss << ")"; + } + } + return ss.str(); + } + }; + template struct statement_serializator, void> { using statement_type = insert_explicit; @@ -10827,37 +10862,6 @@ namespace sqlite_orm { } #endif // SQLITE_ORM_OPTIONAL_SUPPORTED - template - std::string string_from_expression(const replace_t &rep, bool /*noTableName*/) const { - using expression_type = typename std::decay::type; - using object_type = typename expression_object_type::type; - this->assert_mapped_type(); - auto &tImpl = this->get_impl(); - std::stringstream ss; - ss << "REPLACE INTO '" << tImpl.table.name << "' ("; - auto columnNames = tImpl.table.column_names(); - auto columnNamesCount = columnNames.size(); - for(size_t i = 0; i < columnNamesCount; ++i) { - ss << "\"" << columnNames[i] << "\""; - if(i < columnNamesCount - 1) { - ss << ","; - } else { - ss << ")"; - } - ss << " "; - } - ss << "VALUES("; - for(size_t i = 0; i < columnNamesCount; ++i) { - ss << "?"; - if(i < columnNamesCount - 1) { - ss << ", "; - } else { - ss << ")"; - } - } - return ss.str(); - } - template std::string string_from_expression(const replace_range_t &rep, bool /*noTableName*/) const { using expression_type = typename std::decay::type; @@ -11655,8 +11659,14 @@ namespace sqlite_orm { prepared_statement_t> prepare(replace_t rep) { auto con = this->get_connection(); sqlite3_stmt *stmt; + using object_type = typename expression_object_type::type; + this->assert_mapped_type(); auto db = con.get(); - auto query = this->string_from_expression(rep, false); + using context_t = serializator_context; + context_t context{this->impl}; + context.skip_table_name = false; + context.replace_bindable_with_question = true; + auto query = serialize(rep, context); if(sqlite3_prepare_v2(db, query.c_str(), -1, &stmt, nullptr) == SQLITE_OK) { return {std::move(rep), stmt, con}; } else { From 25a5df54d2082ed8a180712d17be90da969c848b Mon Sep 17 00:00:00 2001 From: fnc12 Date: Tue, 12 May 2020 20:42:02 +0300 Subject: [PATCH 069/132] remove string_from_expression for replace_range_t --- dev/statement_serializator.h | 47 ++++++++++++++++ dev/storage.h | 48 ++--------------- include/sqlite_orm/sqlite_orm.h | 95 ++++++++++++++++++--------------- 3 files changed, 104 insertions(+), 86 deletions(-) diff --git a/dev/statement_serializator.h b/dev/statement_serializator.h index 61c6807b9..c86771bbf 100644 --- a/dev/statement_serializator.h +++ b/dev/statement_serializator.h @@ -1003,6 +1003,53 @@ namespace sqlite_orm { } }; + template + struct statement_serializator, void> { + using statement_type = replace_range_t; + + template + std::string operator()(const statement_type &rep, const C &context) const { + using expression_type = typename std::decay::type; + using object_type = typename expression_type::object_type; + auto &tImpl = context.impl.template get_impl(); + std::stringstream ss; + ss << "REPLACE INTO '" << tImpl.table.name << "' ("; + auto columnNames = tImpl.table.column_names(); + auto columnNamesCount = columnNames.size(); + for(size_t i = 0; i < columnNamesCount; ++i) { + ss << "\"" << columnNames[i] << "\""; + if(i < columnNamesCount - 1) { + ss << ", "; + } else { + ss << ") "; + } + } + ss << "VALUES "; + auto valuesString = [columnNamesCount] { + std::stringstream ss; + ss << "("; + for(size_t i = 0; i < columnNamesCount; ++i) { + ss << "?"; + if(i < columnNamesCount - 1) { + ss << ", "; + } else { + ss << ")"; + } + } + return ss.str(); + }(); + auto valuesCount = static_cast(std::distance(rep.range.first, rep.range.second)); + for(auto i = 0; i < valuesCount; ++i) { + ss << valuesString; + if(i < valuesCount - 1) { + ss << ","; + } + ss << " "; + } + return ss.str(); + } + }; + template struct statement_serializator, void> { using statement_type = insert_range_t; diff --git a/dev/storage.h b/dev/storage.h index 921a0ebc5..0585c3d3f 100644 --- a/dev/storage.h +++ b/dev/storage.h @@ -289,48 +289,6 @@ namespace sqlite_orm { } #endif // SQLITE_ORM_OPTIONAL_SUPPORTED - template - std::string string_from_expression(const replace_range_t &rep, bool /*noTableName*/) const { - using expression_type = typename std::decay::type; - using object_type = typename expression_type::object_type; - auto &tImpl = this->get_impl(); - std::stringstream ss; - ss << "REPLACE INTO '" << tImpl.table.name << "' ("; - auto columnNames = tImpl.table.column_names(); - auto columnNamesCount = columnNames.size(); - for(size_t i = 0; i < columnNamesCount; ++i) { - ss << "\"" << columnNames[i] << "\""; - if(i < columnNamesCount - 1) { - ss << ", "; - } else { - ss << ") "; - } - } - ss << "VALUES "; - auto valuesString = [columnNamesCount] { - std::stringstream ss; - ss << "("; - for(size_t i = 0; i < columnNamesCount; ++i) { - ss << "?"; - if(i < columnNamesCount - 1) { - ss << ", "; - } else { - ss << ")"; - } - } - return ss.str(); - }(); - auto valuesCount = static_cast(std::distance(rep.range.first, rep.range.second)); - for(auto i = 0; i < valuesCount; ++i) { - ss << valuesString; - if(i < valuesCount - 1) { - ss << ","; - } - ss << " "; - } - return ss.str(); - } - public: template view_t iterate(Args &&... args) { @@ -1125,7 +1083,11 @@ namespace sqlite_orm { auto con = this->get_connection(); sqlite3_stmt *stmt; auto db = con.get(); - auto query = this->string_from_expression(rep, false); + using context_t = serializator_context; + context_t context{this->impl}; + context.skip_table_name = false; + context.replace_bindable_with_question = true; + auto query = serialize(rep, context); if(sqlite3_prepare_v2(db, query.c_str(), -1, &stmt, nullptr) == SQLITE_OK) { return {std::move(rep), stmt, con}; } else { diff --git a/include/sqlite_orm/sqlite_orm.h b/include/sqlite_orm/sqlite_orm.h index 87edfabd0..f97c50a43 100644 --- a/include/sqlite_orm/sqlite_orm.h +++ b/include/sqlite_orm/sqlite_orm.h @@ -10247,6 +10247,53 @@ namespace sqlite_orm { } }; + template + struct statement_serializator, void> { + using statement_type = replace_range_t; + + template + std::string operator()(const statement_type &rep, const C &context) const { + using expression_type = typename std::decay::type; + using object_type = typename expression_type::object_type; + auto &tImpl = context.impl.template get_impl(); + std::stringstream ss; + ss << "REPLACE INTO '" << tImpl.table.name << "' ("; + auto columnNames = tImpl.table.column_names(); + auto columnNamesCount = columnNames.size(); + for(size_t i = 0; i < columnNamesCount; ++i) { + ss << "\"" << columnNames[i] << "\""; + if(i < columnNamesCount - 1) { + ss << ", "; + } else { + ss << ") "; + } + } + ss << "VALUES "; + auto valuesString = [columnNamesCount] { + std::stringstream ss; + ss << "("; + for(size_t i = 0; i < columnNamesCount; ++i) { + ss << "?"; + if(i < columnNamesCount - 1) { + ss << ", "; + } else { + ss << ")"; + } + } + return ss.str(); + }(); + auto valuesCount = static_cast(std::distance(rep.range.first, rep.range.second)); + for(auto i = 0; i < valuesCount; ++i) { + ss << valuesString; + if(i < valuesCount - 1) { + ss << ","; + } + ss << " "; + } + return ss.str(); + } + }; + template struct statement_serializator, void> { using statement_type = insert_range_t; @@ -10862,48 +10909,6 @@ namespace sqlite_orm { } #endif // SQLITE_ORM_OPTIONAL_SUPPORTED - template - std::string string_from_expression(const replace_range_t &rep, bool /*noTableName*/) const { - using expression_type = typename std::decay::type; - using object_type = typename expression_type::object_type; - auto &tImpl = this->get_impl(); - std::stringstream ss; - ss << "REPLACE INTO '" << tImpl.table.name << "' ("; - auto columnNames = tImpl.table.column_names(); - auto columnNamesCount = columnNames.size(); - for(size_t i = 0; i < columnNamesCount; ++i) { - ss << "\"" << columnNames[i] << "\""; - if(i < columnNamesCount - 1) { - ss << ", "; - } else { - ss << ") "; - } - } - ss << "VALUES "; - auto valuesString = [columnNamesCount] { - std::stringstream ss; - ss << "("; - for(size_t i = 0; i < columnNamesCount; ++i) { - ss << "?"; - if(i < columnNamesCount - 1) { - ss << ", "; - } else { - ss << ")"; - } - } - return ss.str(); - }(); - auto valuesCount = static_cast(std::distance(rep.range.first, rep.range.second)); - for(auto i = 0; i < valuesCount; ++i) { - ss << valuesString; - if(i < valuesCount - 1) { - ss << ","; - } - ss << " "; - } - return ss.str(); - } - public: template view_t iterate(Args &&... args) { @@ -11698,7 +11703,11 @@ namespace sqlite_orm { auto con = this->get_connection(); sqlite3_stmt *stmt; auto db = con.get(); - auto query = this->string_from_expression(rep, false); + using context_t = serializator_context; + context_t context{this->impl}; + context.skip_table_name = false; + context.replace_bindable_with_question = true; + auto query = serialize(rep, context); if(sqlite3_prepare_v2(db, query.c_str(), -1, &stmt, nullptr) == SQLITE_OK) { return {std::move(rep), stmt, con}; } else { From 77752cdc40259fd70bb3127e8429e522d4277246 Mon Sep 17 00:00:00 2001 From: fnc12 Date: Wed, 13 May 2020 01:16:40 +0300 Subject: [PATCH 070/132] removved string_from_expression for get_all_t --- dev/statement_serializator.h | 43 ++++++++++++++++++ dev/storage.h | 30 ++++--------- dev/view.h | 6 ++- include/sqlite_orm/sqlite_orm.h | 79 +++++++++++++++++++++++---------- 4 files changed, 112 insertions(+), 46 deletions(-) diff --git a/dev/statement_serializator.h b/dev/statement_serializator.h index c86771bbf..9c906f5c5 100644 --- a/dev/statement_serializator.h +++ b/dev/statement_serializator.h @@ -1105,6 +1105,49 @@ namespace sqlite_orm { } }; + template + struct statement_serializator, void> { + using statement_type = get_all_t; + + template + std::string operator()(const statement_type &get, const C &context) const { + table_name_collector collector; + collector.table_names.insert(std::make_pair(context.impl.find_table_name(typeid(T)), std::string{})); + iterate_ast(get.conditions, collector); + std::stringstream ss; + ss << "SELECT "; + auto &tImpl = context.impl.template get_impl(); + auto columnNames = tImpl.table.column_names(); + for(size_t i = 0; i < columnNames.size(); ++i) { + ss << "\"" << tImpl.table.name << "\"." + << "\"" << columnNames[i] << "\""; + if(i < columnNames.size() - 1) { + ss << ", "; + } else { + ss << " "; + } + } + ss << "FROM "; + std::vector> tableNames(collector.table_names.begin(), + collector.table_names.end()); + for(size_t i = 0; i < tableNames.size(); ++i) { + auto &tableNamePair = tableNames[i]; + ss << "'" << tableNamePair.first << "' "; + if(!tableNamePair.second.empty()) { + ss << tableNamePair.second << " "; + } + if(int(i) < int(tableNames.size()) - 1) { + ss << ","; + } + ss << " "; + } + iterate_tuple(get.conditions, [&context, &ss](auto &v) { + ss << serialize(v, context); + }); + return ss.str(); + } + }; + template struct statement_serializator, void> { using statement_type = select_t; diff --git a/dev/storage.h b/dev/storage.h index 0585c3d3f..29342d1dc 100644 --- a/dev/storage.h +++ b/dev/storage.h @@ -197,32 +197,21 @@ namespace sqlite_orm { } ss << " "; } - return ss; - } - template - std::string string_from_expression(const get_all_t &get, bool noTableName) const { - std::stringstream ss = this->string_from_expression_impl_get_all(get, noTableName); using context_t = serializator_context; context_t context{this->impl}; context.skip_table_name = false; context.replace_bindable_with_question = true; - iterate_tuple(get.conditions, [&context, &ss](auto &v) { + iterate_tuple(get_query.conditions, [&context, &ss](auto &v) { ss << serialize(v, context); }); - return ss.str(); + + return ss; } template std::string string_from_expression(const get_all_pointer_t &get, bool noTableName) const { std::stringstream ss = this->string_from_expression_impl_get_all(get, noTableName); - using context_t = serializator_context; - context_t context{this->impl}; - context.skip_table_name = false; - context.replace_bindable_with_question = true; - iterate_tuple(get.conditions, [&context, &ss](auto &v) { - ss << serialize(v, context); - }); return ss.str(); } @@ -230,13 +219,6 @@ namespace sqlite_orm { template std::string string_from_expression(const get_all_optional_t &get, bool noTableName) const { std::stringstream ss = this->string_from_expression_impl_get_all(get, noTableName); - using context_t = serializator_context; - context_t context{this->impl}; - context.skip_table_name = false; - context.replace_bindable_with_question = true; - iterate_tuple(get.conditions, [&context, &ss](auto &v) { - ss << serialize(v, context); - }); return ss.str(); } #endif // SQLITE_ORM_OPTIONAL_SUPPORTED @@ -864,7 +846,11 @@ namespace sqlite_orm { auto con = this->get_connection(); sqlite3_stmt *stmt; auto db = con.get(); - auto query = this->string_from_expression(get, false); + using context_t = serializator_context; + context_t context{this->impl}; + context.skip_table_name = false; + context.replace_bindable_with_question = true; + auto query = serialize(get, context); if(sqlite3_prepare_v2(db, query.c_str(), -1, &stmt, nullptr) == SQLITE_OK) { return {std::move(get), stmt, con}; } else { diff --git a/dev/view.h b/dev/view.h index 571a9c116..5abddd4e5 100644 --- a/dev/view.h +++ b/dev/view.h @@ -47,7 +47,11 @@ namespace sqlite_orm { iterator_t begin() { sqlite3_stmt *stmt = nullptr; auto db = this->connection.get(); - auto query = this->storage.string_from_expression(this->args, false); + using context_t = serializator_context; + context_t context{this->storage.impl}; + context.skip_table_name = false; + context.replace_bindable_with_question = true; + auto query = serialize(this->args, context); auto ret = sqlite3_prepare_v2(db, query.c_str(), -1, &stmt, nullptr); if(ret == SQLITE_OK) { auto index = 1; diff --git a/include/sqlite_orm/sqlite_orm.h b/include/sqlite_orm/sqlite_orm.h index f97c50a43..3a7b55534 100644 --- a/include/sqlite_orm/sqlite_orm.h +++ b/include/sqlite_orm/sqlite_orm.h @@ -7909,7 +7909,11 @@ namespace sqlite_orm { iterator_t begin() { sqlite3_stmt *stmt = nullptr; auto db = this->connection.get(); - auto query = this->storage.string_from_expression(this->args, false); + using context_t = serializator_context; + context_t context{this->storage.impl}; + context.skip_table_name = false; + context.replace_bindable_with_question = true; + auto query = serialize(this->args, context); auto ret = sqlite3_prepare_v2(db, query.c_str(), -1, &stmt, nullptr); if(ret == SQLITE_OK) { auto index = 1; @@ -10349,6 +10353,49 @@ namespace sqlite_orm { } }; + template + struct statement_serializator, void> { + using statement_type = get_all_t; + + template + std::string operator()(const statement_type &get, const C &context) const { + table_name_collector collector; + collector.table_names.insert(std::make_pair(context.impl.find_table_name(typeid(T)), std::string{})); + iterate_ast(get.conditions, collector); + std::stringstream ss; + ss << "SELECT "; + auto &tImpl = context.impl.template get_impl(); + auto columnNames = tImpl.table.column_names(); + for(size_t i = 0; i < columnNames.size(); ++i) { + ss << "\"" << tImpl.table.name << "\"." + << "\"" << columnNames[i] << "\""; + if(i < columnNames.size() - 1) { + ss << ", "; + } else { + ss << " "; + } + } + ss << "FROM "; + std::vector> tableNames(collector.table_names.begin(), + collector.table_names.end()); + for(size_t i = 0; i < tableNames.size(); ++i) { + auto &tableNamePair = tableNames[i]; + ss << "'" << tableNamePair.first << "' "; + if(!tableNamePair.second.empty()) { + ss << tableNamePair.second << " "; + } + if(int(i) < int(tableNames.size()) - 1) { + ss << ","; + } + ss << " "; + } + iterate_tuple(get.conditions, [&context, &ss](auto &v) { + ss << serialize(v, context); + }); + return ss.str(); + } + }; + template struct statement_serializator, void> { using statement_type = select_t; @@ -10817,32 +10864,21 @@ namespace sqlite_orm { } ss << " "; } - return ss; - } - template - std::string string_from_expression(const get_all_t &get, bool noTableName) const { - std::stringstream ss = this->string_from_expression_impl_get_all(get, noTableName); using context_t = serializator_context; context_t context{this->impl}; context.skip_table_name = false; context.replace_bindable_with_question = true; - iterate_tuple(get.conditions, [&context, &ss](auto &v) { + iterate_tuple(get_query.conditions, [&context, &ss](auto &v) { ss << serialize(v, context); }); - return ss.str(); + + return ss; } template std::string string_from_expression(const get_all_pointer_t &get, bool noTableName) const { std::stringstream ss = this->string_from_expression_impl_get_all(get, noTableName); - using context_t = serializator_context; - context_t context{this->impl}; - context.skip_table_name = false; - context.replace_bindable_with_question = true; - iterate_tuple(get.conditions, [&context, &ss](auto &v) { - ss << serialize(v, context); - }); return ss.str(); } @@ -10850,13 +10886,6 @@ namespace sqlite_orm { template std::string string_from_expression(const get_all_optional_t &get, bool noTableName) const { std::stringstream ss = this->string_from_expression_impl_get_all(get, noTableName); - using context_t = serializator_context; - context_t context{this->impl}; - context.skip_table_name = false; - context.replace_bindable_with_question = true; - iterate_tuple(get.conditions, [&context, &ss](auto &v) { - ss << serialize(v, context); - }); return ss.str(); } #endif // SQLITE_ORM_OPTIONAL_SUPPORTED @@ -11484,7 +11513,11 @@ namespace sqlite_orm { auto con = this->get_connection(); sqlite3_stmt *stmt; auto db = con.get(); - auto query = this->string_from_expression(get, false); + using context_t = serializator_context; + context_t context{this->impl}; + context.skip_table_name = false; + context.replace_bindable_with_question = true; + auto query = serialize(get, context); if(sqlite3_prepare_v2(db, query.c_str(), -1, &stmt, nullptr) == SQLITE_OK) { return {std::move(get), stmt, con}; } else { From d421526bea4c362595edfdab9c52494a64585a96 Mon Sep 17 00:00:00 2001 From: fnc12 Date: Wed, 13 May 2020 01:33:51 +0300 Subject: [PATCH 071/132] added the second template arg to get_all_t --- dev/statement_serializator.h | 6 +++--- include/sqlite_orm/sqlite_orm.h | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/dev/statement_serializator.h b/dev/statement_serializator.h index 9c906f5c5..23c26ca3e 100644 --- a/dev/statement_serializator.h +++ b/dev/statement_serializator.h @@ -1105,9 +1105,9 @@ namespace sqlite_orm { } }; - template - struct statement_serializator, void> { - using statement_type = get_all_t; + template + struct statement_serializator, void> { + using statement_type = get_all_t; template std::string operator()(const statement_type &get, const C &context) const { diff --git a/include/sqlite_orm/sqlite_orm.h b/include/sqlite_orm/sqlite_orm.h index 3a7b55534..fa51e917b 100644 --- a/include/sqlite_orm/sqlite_orm.h +++ b/include/sqlite_orm/sqlite_orm.h @@ -10353,9 +10353,9 @@ namespace sqlite_orm { } }; - template - struct statement_serializator, void> { - using statement_type = get_all_t; + template + struct statement_serializator, void> { + using statement_type = get_all_t; template std::string operator()(const statement_type &get, const C &context) const { From 06158ff487291cdf84eca687370ac5c28221778a Mon Sep 17 00:00:00 2001 From: fnc12 Date: Wed, 13 May 2020 22:54:55 +0300 Subject: [PATCH 072/132] added custom container support for get_all_pointer --- dev/prepared_statement.h | 22 +++- dev/storage.h | 24 +++- include/sqlite_orm/sqlite_orm.h | 114 +++++++++++++++--- tests/CMakeLists.txt | 2 +- tests/get_all_custom_containers.cpp | 82 +++++++++++++ .../get_all_pointer.cpp | 25 +--- tests/tests2.cpp | 65 ---------- 7 files changed, 218 insertions(+), 116 deletions(-) create mode 100644 tests/get_all_custom_containers.cpp diff --git a/dev/prepared_statement.h b/dev/prepared_statement.h index ce5689586..55a47024e 100644 --- a/dev/prepared_statement.h +++ b/dev/prepared_statement.h @@ -89,10 +89,11 @@ namespace sqlite_orm { conditions_type conditions; }; - template + template struct get_all_pointer_t { using type = T; - + using return_type = R; + using conditions_type = std::tuple; conditions_type conditions; @@ -373,10 +374,25 @@ namespace sqlite_orm { * Usage: storage.get_all_pointer(...); */ template - internal::get_all_pointer_t get_all_pointer(Args... args) { + internal::get_all_pointer_t>, Args...> get_all_pointer(Args... args) { + using args_tuple = std::tuple; + internal::validate_conditions(); std::tuple conditions{std::forward(args)...}; return {move(conditions)}; } + /** + * Create a get all pointer statement. + * T is an object type mapped to a storage. + * R is a container return type. std::vector> is default + * Usage: storage.get_all_pointer(...); + */ +template +internal::get_all_pointer_t get_all_pointer(Args... args) { + using args_tuple = std::tuple; + internal::validate_conditions(); + std::tuple conditions{std::forward(args)...}; + return {move(conditions)}; +} #ifdef SQLITE_ORM_OPTIONAL_SUPPORTED /** diff --git a/dev/storage.h b/dev/storage.h index 29342d1dc..88b15637a 100644 --- a/dev/storage.h +++ b/dev/storage.h @@ -360,12 +360,25 @@ namespace sqlite_orm { * O is an object type to be extracted. Must be specified explicitly. * @return All objects of type O as std::unique_ptr stored in database at the moment. */ - template>, class... Args> - C get_all_pointer(Args &&... args) { + template + auto get_all_pointer(Args &&... args) { this->assert_mapped_type(); auto statement = this->prepare(sqlite_orm::get_all_pointer(std::forward(args)...)); return this->execute(statement); } + + /** + * Select * with no conditions routine. + * O is an object type to be extracted. Must be specified explicitly. + * R is a container type. std::vector> is default + * @return All objects of type O as std::unique_ptr stored in database at the moment. + */ + template + auto get_all_pointer(Args &&... args) { + this->assert_mapped_type(); + auto statement = this->prepare(sqlite_orm::get_all_pointer(std::forward(args)...)); + return this->execute(statement); + } /** * Select * by id routine. @@ -1648,9 +1661,8 @@ namespace sqlite_orm { return res; } - template - std::vector> - execute(const prepared_statement_t> &statement) { + template + R execute(const prepared_statement_t> &statement) { auto &tImpl = this->get_impl(); auto con = this->get_connection(); auto db = con.get(); @@ -1665,7 +1677,7 @@ namespace sqlite_orm { sqlite3_errmsg(db)); } }); - std::vector> res; + R res; int stepRes; do { stepRes = sqlite3_step(stmt); diff --git a/include/sqlite_orm/sqlite_orm.h b/include/sqlite_orm/sqlite_orm.h index fa51e917b..cb4fd1155 100644 --- a/include/sqlite_orm/sqlite_orm.h +++ b/include/sqlite_orm/sqlite_orm.h @@ -27,7 +27,7 @@ __pragma(push_macro("min")) #include #include // std::ostringstream - namespace sqlite_orm { +namespace sqlite_orm { enum class orm_error_code { not_found = 1, @@ -44,6 +44,7 @@ __pragma(push_macro("min")) failed_to_init_a_backup, unknown_member_value, }; + } namespace sqlite_orm { @@ -224,6 +225,7 @@ namespace sqlite_orm { // #include "static_magic.h" + #include // std::false_type, std::true_type, std::integral_constant namespace sqlite_orm { @@ -258,6 +260,7 @@ namespace sqlite_orm { } + namespace sqlite_orm { // got from here http://stackoverflow.com/questions/25958259/how-do-i-find-out-if-a-tuple-contains-a-type @@ -989,6 +992,7 @@ namespace sqlite_orm { // #include "serializator_context.h" + namespace sqlite_orm { namespace internal { @@ -1036,6 +1040,7 @@ namespace sqlite_orm { } + namespace sqlite_orm { namespace internal { @@ -1070,12 +1075,14 @@ namespace sqlite_orm { // #include "negatable.h" + namespace sqlite_orm { namespace internal { struct negatable_t {}; } } + namespace sqlite_orm { namespace internal { @@ -1375,6 +1382,7 @@ namespace sqlite_orm { // #include "getter_traits.h" + namespace sqlite_orm { namespace internal { @@ -1558,6 +1566,7 @@ namespace sqlite_orm { } } + namespace sqlite_orm { namespace internal { @@ -1888,6 +1897,7 @@ namespace sqlite_orm { // #include "optional_container.h" + namespace sqlite_orm { namespace internal { @@ -1922,6 +1932,7 @@ namespace sqlite_orm { // #include "negatable.h" + namespace sqlite_orm { namespace internal { @@ -3371,6 +3382,7 @@ namespace sqlite_orm { // #include "conditions.h" + namespace sqlite_orm { namespace internal { @@ -3490,6 +3502,7 @@ namespace sqlite_orm { // #include "is_base_of_template.h" + #include // std::true_type, std::false_type, std::declval namespace sqlite_orm { @@ -3527,6 +3540,7 @@ namespace sqlite_orm { } } + namespace sqlite_orm { namespace internal { @@ -4279,6 +4293,7 @@ namespace sqlite_orm { // #include "optional_container.h" + namespace sqlite_orm { namespace internal { @@ -4631,6 +4646,7 @@ namespace sqlite_orm { // #include "column.h" + namespace sqlite_orm { namespace internal { @@ -4737,6 +4753,7 @@ namespace sqlite_orm { // #include "is_std_ptr.h" + namespace sqlite_orm { /** @@ -4764,6 +4781,7 @@ namespace sqlite_orm { }; } + namespace sqlite_orm { /** @@ -4974,6 +4992,7 @@ namespace sqlite_orm { // #include "journal_mode.h" + #include // std::string #include // std::unique_ptr #include // std::array @@ -5036,6 +5055,7 @@ namespace sqlite_orm { // #include "error_code.h" + namespace sqlite_orm { /** @@ -5412,6 +5432,7 @@ namespace sqlite_orm { // #include "alias.h" + namespace sqlite_orm { namespace internal { @@ -5658,6 +5679,7 @@ namespace sqlite_orm { } } + namespace sqlite_orm { namespace internal { @@ -5922,6 +5944,7 @@ namespace sqlite_orm { // #include "column.h" + namespace sqlite_orm { namespace internal { @@ -6221,10 +6244,12 @@ namespace sqlite_orm { // #include "field_value_holder.h" + #include // std::enable_if // #include "column.h" + namespace sqlite_orm { namespace internal { @@ -6247,6 +6272,7 @@ namespace sqlite_orm { } } + namespace sqlite_orm { namespace internal { @@ -6748,6 +6774,7 @@ namespace sqlite_orm { // #include "view.h" + #include // std::shared_ptr #include // std::string #include // std::forward, std::move @@ -6763,6 +6790,7 @@ namespace sqlite_orm { // #include "iterator.h" + #include // std::shared_ptr, std::unique_ptr, std::make_shared #include #include // std::decay @@ -6778,6 +6806,7 @@ namespace sqlite_orm { // #include "error_code.h" + namespace sqlite_orm { namespace internal { @@ -6906,6 +6935,7 @@ namespace sqlite_orm { // #include "ast_iterator.h" + #include // std::vector #include // std::reference_wrapper @@ -6921,6 +6951,7 @@ namespace sqlite_orm { // #include "prepared_statement.h" + #include #include // std::iterator_traits #include // std::string @@ -6929,12 +6960,14 @@ namespace sqlite_orm { // #include "connection_holder.h" + #include #include // std::string #include // std::system_error // #include "error_code.h" + namespace sqlite_orm { namespace internal { @@ -7009,6 +7042,7 @@ namespace sqlite_orm { // #include "select_constraints.h" + namespace sqlite_orm { namespace internal { @@ -7089,10 +7123,11 @@ namespace sqlite_orm { conditions_type conditions; }; - template + template struct get_all_pointer_t { using type = T; - + using return_type = R; + using conditions_type = std::tuple; conditions_type conditions; @@ -7373,10 +7408,25 @@ namespace sqlite_orm { * Usage: storage.get_all_pointer(...); */ template - internal::get_all_pointer_t get_all_pointer(Args... args) { + internal::get_all_pointer_t>, Args...> get_all_pointer(Args... args) { + using args_tuple = std::tuple; + internal::validate_conditions(); std::tuple conditions{std::forward(args)...}; return {move(conditions)}; } + /** + * Create a get all pointer statement. + * T is an object type mapped to a storage. + * R is a container return type + * Usage: storage.get_all_pointer(...); + */ +template +internal::get_all_pointer_t get_all_pointer(Args... args) { + using args_tuple = std::tuple; + internal::validate_conditions(); + std::tuple conditions{std::forward(args)...}; + return {move(conditions)}; +} #ifdef SQLITE_ORM_OPTIONAL_SUPPORTED /** @@ -7392,6 +7442,7 @@ namespace sqlite_orm { #endif // SQLITE_ORM_OPTIONAL_SUPPORTED } + namespace sqlite_orm { namespace internal { @@ -7877,6 +7928,7 @@ namespace sqlite_orm { // #include "connection_holder.h" + namespace sqlite_orm { namespace internal { @@ -7939,6 +7991,7 @@ namespace sqlite_orm { // #include "storage_base.h" + #include // std::function, std::bind #include #include // std::string @@ -7953,6 +8006,7 @@ namespace sqlite_orm { // #include "pragma.h" + #include // std::string #include #include // std::function @@ -7966,6 +8020,7 @@ namespace sqlite_orm { // #include "connection_holder.h" + namespace sqlite_orm { namespace internal { @@ -8086,6 +8141,7 @@ namespace sqlite_orm { // #include "limit_accesor.h" + #include #include // std::map #include // std::function @@ -8093,6 +8149,7 @@ namespace sqlite_orm { // #include "connection_holder.h" + namespace sqlite_orm { namespace internal { @@ -8226,10 +8283,12 @@ namespace sqlite_orm { // #include "transaction_guard.h" + #include // std::function // #include "connection_holder.h" + namespace sqlite_orm { namespace internal { @@ -8304,6 +8363,7 @@ namespace sqlite_orm { // #include "backup.h" + #include #include // std::string #include @@ -8312,6 +8372,7 @@ namespace sqlite_orm { // #include "connection_holder.h" + namespace sqlite_orm { namespace internal { @@ -8377,6 +8438,7 @@ namespace sqlite_orm { } } + namespace sqlite_orm { namespace internal { @@ -8877,11 +8939,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 { @@ -9001,6 +9065,7 @@ namespace sqlite_orm { // #include "statement_serializator.h" + #include // std::stringstream #include // std::string #include // std::is_arithmetic, std::enable_if @@ -9021,6 +9086,7 @@ namespace sqlite_orm { // #include "table_name_collector.h" + #include // std::set #include // std::string #include // std::function @@ -9032,6 +9098,7 @@ namespace sqlite_orm { // #include "core_functions.h" + namespace sqlite_orm { namespace internal { @@ -9092,6 +9159,7 @@ namespace sqlite_orm { // #include "column_names_getter.h" + #include // std::string #include // std::vector #include // std::reference_wrapper @@ -9100,6 +9168,7 @@ namespace sqlite_orm { // #include "select_constraints.h" + namespace sqlite_orm { namespace internal { @@ -9178,6 +9247,7 @@ namespace sqlite_orm { // #include "order_by_serializator.h" + #include // std::string #include // std::vector #include // std::stringstream @@ -9264,6 +9334,7 @@ namespace sqlite_orm { } } + namespace sqlite_orm { namespace internal { @@ -10715,6 +10786,7 @@ namespace sqlite_orm { // #include "table_name_collector.h" + namespace sqlite_orm { namespace internal { @@ -11027,12 +11099,19 @@ namespace sqlite_orm { * O is an object type to be extracted. Must be specified explicitly. * @return All objects of type O as std::unique_ptr stored in database at the moment. */ - template>, class... Args> - C get_all_pointer(Args &&... args) { + template + auto get_all_pointer(Args &&... args) { this->assert_mapped_type(); auto statement = this->prepare(sqlite_orm::get_all_pointer(std::forward(args)...)); return this->execute(statement); } + + template + auto get_all_pointer(Args &&... args) { + this->assert_mapped_type(); + auto statement = this->prepare(sqlite_orm::get_all_pointer(std::forward(args)...)); + return this->execute(statement); + } /** * Select * by id routine. @@ -12315,9 +12394,8 @@ namespace sqlite_orm { return res; } - template - std::vector> - execute(const prepared_statement_t> &statement) { + template + R execute(const prepared_statement_t> &statement) { auto &tImpl = this->get_impl(); auto con = this->get_connection(); auto db = con.get(); @@ -12332,7 +12410,7 @@ namespace sqlite_orm { sqlite3_errmsg(db)); } }); - std::vector> res; + R res; int stepRes; do { stepRes = sqlite3_step(stmt); @@ -12449,19 +12527,20 @@ __pragma(pop_macro("min")) #include // std::pair #include // std::reference_wrapper - // #include "conditions.h" +// #include "conditions.h" - // #include "operators.h" +// #include "operators.h" + +// #include "select_constraints.h" - // #include "select_constraints.h" +// #include "prepared_statement.h" - // #include "prepared_statement.h" +// #include "optional_container.h" - // #include "optional_container.h" +// #include "core_functions.h" - // #include "core_functions.h" - namespace sqlite_orm { +namespace sqlite_orm { namespace internal { @@ -12742,6 +12821,7 @@ __pragma(pop_macro("min")) // #include "expression_object_type.h" + namespace sqlite_orm { template diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index a7c01fed4..67f7030fc 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -10,7 +10,7 @@ else() add_subdirectory(third_party/sqlite) endif() -add_executable(unit_tests tests.cpp tests2.cpp tests3.cpp tests4.cpp tests5.cpp private_getters_tests.cpp pragma_tests.cpp explicit_columns.cpp core_functions_tests.cpp constraints/composite_key.cpp static_tests.cpp operators/arithmetic_operators.cpp operators/like.cpp operators/glob.cpp operators/in.cpp operators/cast.cpp operators/is_null.cpp operators/not_operator.cpp operators/bitwise.cpp dynamic_order_by.cpp prepared_statement_tests/select.cpp prepared_statement_tests/get_all.cpp prepared_statement_tests/get_all_pointer.cpp prepared_statement_tests/get_all_optional.cpp prepared_statement_tests/update_all.cpp prepared_statement_tests/remove_all.cpp prepared_statement_tests/get.cpp prepared_statement_tests/get_pointer.cpp prepared_statement_tests/get_optional.cpp prepared_statement_tests/update.cpp prepared_statement_tests/remove.cpp prepared_statement_tests/insert.cpp prepared_statement_tests/replace.cpp prepared_statement_tests/insert_range.cpp prepared_statement_tests/replace_range.cpp prepared_statement_tests/insert_explicit.cpp pragma_tests.cpp simple_query.cpp static_tests/is_bindable.cpp static_tests/arithmetic_operators_result_type.cpp static_tests/tuple_conc.cpp static_tests/node_tuple.cpp static_tests/bindable_filter.cpp static_tests/count_tuple.cpp static_tests/member_traits_tests.cpp static_tests/select_return_type.cpp constraints/default.cpp constraints/foreign_key.cpp constraints/check.cpp table_tests.cpp statement_serializator_tests/primary_key.cpp statement_serializator_tests/column_names.cpp statement_serializator_tests/autoincrement.cpp statement_serializator_tests/arithmetic_operators.cpp statement_serializator_tests/core_functions.cpp statement_serializator_tests/comparison_operators.cpp statement_serializator_tests/unique.cpp statement_serializator_tests/foreign_key.cpp statement_serializator_tests/collate.cpp statement_serializator_tests/check.cpp unique_cases/get_all_with_two_tables.cpp unique_cases/prepare_get_all_with_case.cpp unique_cases/index_named_table_with_fk.cpp) +add_executable(unit_tests tests.cpp tests2.cpp tests3.cpp tests4.cpp tests5.cpp private_getters_tests.cpp pragma_tests.cpp explicit_columns.cpp core_functions_tests.cpp constraints/composite_key.cpp static_tests.cpp operators/arithmetic_operators.cpp operators/like.cpp operators/glob.cpp operators/in.cpp operators/cast.cpp operators/is_null.cpp operators/not_operator.cpp operators/bitwise.cpp dynamic_order_by.cpp prepared_statement_tests/select.cpp prepared_statement_tests/get_all.cpp prepared_statement_tests/get_all_pointer.cpp prepared_statement_tests/get_all_optional.cpp prepared_statement_tests/update_all.cpp prepared_statement_tests/remove_all.cpp prepared_statement_tests/get.cpp prepared_statement_tests/get_pointer.cpp prepared_statement_tests/get_optional.cpp prepared_statement_tests/update.cpp prepared_statement_tests/remove.cpp prepared_statement_tests/insert.cpp prepared_statement_tests/replace.cpp prepared_statement_tests/insert_range.cpp prepared_statement_tests/replace_range.cpp prepared_statement_tests/insert_explicit.cpp pragma_tests.cpp simple_query.cpp static_tests/is_bindable.cpp static_tests/arithmetic_operators_result_type.cpp static_tests/tuple_conc.cpp static_tests/node_tuple.cpp static_tests/bindable_filter.cpp static_tests/count_tuple.cpp static_tests/member_traits_tests.cpp static_tests/select_return_type.cpp constraints/default.cpp constraints/foreign_key.cpp constraints/check.cpp table_tests.cpp statement_serializator_tests/primary_key.cpp statement_serializator_tests/column_names.cpp statement_serializator_tests/autoincrement.cpp statement_serializator_tests/arithmetic_operators.cpp statement_serializator_tests/core_functions.cpp statement_serializator_tests/comparison_operators.cpp statement_serializator_tests/unique.cpp statement_serializator_tests/foreign_key.cpp statement_serializator_tests/collate.cpp statement_serializator_tests/check.cpp unique_cases/get_all_with_two_tables.cpp unique_cases/prepare_get_all_with_case.cpp unique_cases/index_named_table_with_fk.cpp get_all_custom_containers.cpp) if(SQLITE_ORM_OMITS_CODECVT) diff --git a/tests/get_all_custom_containers.cpp b/tests/get_all_custom_containers.cpp new file mode 100644 index 000000000..a297554a8 --- /dev/null +++ b/tests/get_all_custom_containers.cpp @@ -0,0 +1,82 @@ +#include +#include + +#include +#include + +using namespace sqlite_orm; + +struct User { + int id = 0; + std::string name; +}; + +struct Comparator { + + bool operator()(const User &lhs, const User &rhs) const { + return lhs.id == rhs.id && lhs.name == rhs.name; + } + + bool operator()(const std::unique_ptr &lhs, const User &rhs) const { + if(lhs){ + return this->operator()(*lhs, rhs); + }else{ + return false; + } + } +}; + +struct Tester { + const std::vector &expected; + + template + void testContainer(const T &users) const { + REQUIRE(std::equal(users.begin(), users.end(), this->expected.begin(), this->expected.end(), Comparator{})); + static_assert(std::is_same::value, ""); + } + + template + void testPreparedStatement(S &storage, const T &statement) const { + this->testContainer(storage.execute(statement)); + } +}; + +TEST_CASE("get_all deque") { + using Catch::Matchers::UnorderedEquals; + + auto storage = make_storage( + {}, + make_table("users", make_column("id", &User::id, primary_key()), make_column("name", &User::name))); + storage.sync_schema(); + + User user1{1, "Nicki"}; + User user2{2, "Karol"}; + storage.replace(user1); + storage.replace(user2); + + std::vector expected; + expected.push_back(user1); + expected.push_back(user2); + + Tester tester{expected}; + + // get_all + tester.testContainer>(storage.get_all()); + tester.testContainer>(storage.get_all>()); + tester.testContainer>(storage.get_all>()); + tester.testContainer>(storage.get_all>()); + tester.testPreparedStatement>(storage, storage.prepare(get_all())); + tester.testPreparedStatement>(storage, storage.prepare(get_all>())); + tester.testPreparedStatement>(storage, storage.prepare(get_all>())); + tester.testPreparedStatement>(storage, storage.prepare(get_all>())); + + // get_all_pointer + tester.testContainer>>(storage.get_all_pointer()); + tester.testContainer>>(storage.get_all_pointer>>()); + tester.testContainer>>(storage.get_all_pointer>>()); + tester.testContainer>>(storage.get_all_pointer>>()); + tester.testPreparedStatement>>(storage, storage.prepare(get_all_pointer())); + tester.testPreparedStatement>>(storage, storage.prepare(get_all_pointer>>())); + tester.testPreparedStatement>>(storage, storage.prepare(get_all_pointer>>())); + tester.testPreparedStatement>>(storage, storage.prepare(get_all_pointer>>())); +} diff --git a/tests/prepared_statement_tests/get_all_pointer.cpp b/tests/prepared_statement_tests/get_all_pointer.cpp index c3ea39199..ab06fd1e9 100644 --- a/tests/prepared_statement_tests/get_all_pointer.cpp +++ b/tests/prepared_statement_tests/get_all_pointer.cpp @@ -60,18 +60,6 @@ TEST_CASE("Prepared get all pointer") { using Statement = decltype(statement); using Expression = Statement::expression_type; using NodeTuple = internal::node_tuple::type; - { - static_assert(std::tuple_size::value == 2, ""); - { - using Arg0 = std::tuple_element<0, NodeTuple>::type; - static_assert(std::is_same::value, ""); - } - { - using Arg1 = std::tuple_element<1, NodeTuple>::type; - static_assert(std::is_same::value, ""); - } - } - using BindTuple = typename internal::bindable_filter::type; { static_assert(std::tuple_size::value == 1, ""); @@ -109,21 +97,10 @@ TEST_CASE("Prepared get all pointer") { { // by ref auto id = 3; auto statement = storage.prepare(get_all_pointer(where(lesser_than(&User::id, std::ref(id))))); + using Statement = decltype(statement); using Expression = Statement::expression_type; using NodeTuple = internal::node_tuple::type; - { - static_assert(std::tuple_size::value == 2, ""); - { - using Arg0 = std::tuple_element<0, NodeTuple>::type; - static_assert(std::is_same::value, ""); - } - { - using Arg1 = std::tuple_element<1, NodeTuple>::type; - static_assert(std::is_same::value, ""); - } - } - using BindTuple = typename internal::bindable_filter::type; { static_assert(std::tuple_size::value == 1, ""); diff --git a/tests/tests2.cpp b/tests/tests2.cpp index e49b9437c..d89c7e436 100644 --- a/tests/tests2.cpp +++ b/tests/tests2.cpp @@ -3,8 +3,6 @@ #ifdef SQLITE_ORM_OPTIONAL_SUPPORTED #include // std::optional #endif // SQLITE_ORM_OPTIONAL_SUPPORTED -#include -#include using namespace sqlite_orm; @@ -457,66 +455,3 @@ TEST_CASE("Insert") { storage.insert(ObjectWithoutRowid{20, "Death"}); REQUIRE(storage.get(20).name == "Death"); } - -namespace get_all_deque { - struct User { - int id = 0; - std::string name; - }; - - bool operator==(const User &lhs, const User &rhs) { - return lhs.id == rhs.id && lhs.name == rhs.name; - } -} - -TEST_CASE("get_all deque") { - using namespace get_all_deque; - using Catch::Matchers::UnorderedEquals; - - auto storage = make_storage( - {}, - make_table("users", make_column("id", &User::id, primary_key()), make_column("name", &User::name))); - storage.sync_schema(); - - User user1{1, "Nicki"}; - User user2{2, "Karol"}; - storage.replace(user1); - storage.replace(user2); - - std::vector expected; - expected.push_back(user1); - expected.push_back(user2); - { - auto users = storage.get_all(); - REQUIRE(std::equal(users.begin(), users.end(), expected.begin(), expected.end())); - static_assert(std::is_same>::value, ""); - } - { - auto users = storage.get_all>(); - REQUIRE(std::equal(users.begin(), users.end(), expected.begin(), expected.end())); - static_assert(std::is_same>::value, ""); - } - { - auto users = storage.get_all>(); - REQUIRE(std::equal(users.begin(), users.end(), expected.begin(), expected.end())); - static_assert(std::is_same>::value, ""); - } - { - auto statement = storage.prepare(get_all()); - auto users = storage.execute(statement); - REQUIRE(std::equal(users.begin(), users.end(), expected.begin(), expected.end())); - static_assert(std::is_same>::value, ""); - } - { - auto statement = storage.prepare(get_all>()); - auto users = storage.execute(statement); - REQUIRE(std::equal(users.begin(), users.end(), expected.begin(), expected.end())); - static_assert(std::is_same>::value, ""); - } - { - auto statement = storage.prepare(get_all>()); - auto users = storage.execute(statement); - REQUIRE(std::equal(users.begin(), users.end(), expected.begin(), expected.end())); - static_assert(std::is_same>::value, ""); - } -} From 9d7787acdefcb23a81c22a8512655a45eeeb8ef1 Mon Sep 17 00:00:00 2001 From: fnc12 Date: Wed, 13 May 2020 22:55:56 +0300 Subject: [PATCH 073/132] code format --- dev/prepared_statement.h | 16 ++-- dev/storage.h | 2 +- include/sqlite_orm/sqlite_orm.h | 92 ++++--------------- tests/get_all_custom_containers.cpp | 39 +++++--- .../get_all_pointer.cpp | 2 +- 5 files changed, 51 insertions(+), 100 deletions(-) diff --git a/dev/prepared_statement.h b/dev/prepared_statement.h index 55a47024e..bed4cc8c1 100644 --- a/dev/prepared_statement.h +++ b/dev/prepared_statement.h @@ -93,7 +93,7 @@ namespace sqlite_orm { struct get_all_pointer_t { using type = T; using return_type = R; - + using conditions_type = std::tuple; conditions_type conditions; @@ -386,13 +386,13 @@ namespace sqlite_orm { * R is a container return type. std::vector> is default * Usage: storage.get_all_pointer(...); */ -template -internal::get_all_pointer_t get_all_pointer(Args... args) { - using args_tuple = std::tuple; - internal::validate_conditions(); - std::tuple conditions{std::forward(args)...}; - return {move(conditions)}; -} + template + internal::get_all_pointer_t get_all_pointer(Args... args) { + using args_tuple = std::tuple; + internal::validate_conditions(); + std::tuple conditions{std::forward(args)...}; + return {move(conditions)}; + } #ifdef SQLITE_ORM_OPTIONAL_SUPPORTED /** diff --git a/dev/storage.h b/dev/storage.h index 88b15637a..75584fc1a 100644 --- a/dev/storage.h +++ b/dev/storage.h @@ -366,7 +366,7 @@ namespace sqlite_orm { auto statement = this->prepare(sqlite_orm::get_all_pointer(std::forward(args)...)); return this->execute(statement); } - + /** * Select * with no conditions routine. * O is an object type to be extracted. Must be specified explicitly. diff --git a/include/sqlite_orm/sqlite_orm.h b/include/sqlite_orm/sqlite_orm.h index cb4fd1155..df74a30dc 100644 --- a/include/sqlite_orm/sqlite_orm.h +++ b/include/sqlite_orm/sqlite_orm.h @@ -27,7 +27,7 @@ __pragma(push_macro("min")) #include #include // std::ostringstream -namespace sqlite_orm { + namespace sqlite_orm { enum class orm_error_code { not_found = 1, @@ -44,7 +44,6 @@ namespace sqlite_orm { failed_to_init_a_backup, unknown_member_value, }; - } namespace sqlite_orm { @@ -225,7 +224,6 @@ namespace sqlite_orm { // #include "static_magic.h" - #include // std::false_type, std::true_type, std::integral_constant namespace sqlite_orm { @@ -260,7 +258,6 @@ namespace sqlite_orm { } - namespace sqlite_orm { // got from here http://stackoverflow.com/questions/25958259/how-do-i-find-out-if-a-tuple-contains-a-type @@ -992,7 +989,6 @@ namespace sqlite_orm { // #include "serializator_context.h" - namespace sqlite_orm { namespace internal { @@ -1040,7 +1036,6 @@ namespace sqlite_orm { } - namespace sqlite_orm { namespace internal { @@ -1075,14 +1070,12 @@ namespace sqlite_orm { // #include "negatable.h" - namespace sqlite_orm { namespace internal { struct negatable_t {}; } } - namespace sqlite_orm { namespace internal { @@ -1382,7 +1375,6 @@ namespace sqlite_orm { // #include "getter_traits.h" - namespace sqlite_orm { namespace internal { @@ -1566,7 +1558,6 @@ namespace sqlite_orm { } } - namespace sqlite_orm { namespace internal { @@ -1897,7 +1888,6 @@ namespace sqlite_orm { // #include "optional_container.h" - namespace sqlite_orm { namespace internal { @@ -1932,7 +1922,6 @@ namespace sqlite_orm { // #include "negatable.h" - namespace sqlite_orm { namespace internal { @@ -3382,7 +3371,6 @@ namespace sqlite_orm { // #include "conditions.h" - namespace sqlite_orm { namespace internal { @@ -3502,7 +3490,6 @@ namespace sqlite_orm { // #include "is_base_of_template.h" - #include // std::true_type, std::false_type, std::declval namespace sqlite_orm { @@ -3540,7 +3527,6 @@ namespace sqlite_orm { } } - namespace sqlite_orm { namespace internal { @@ -4293,7 +4279,6 @@ namespace sqlite_orm { // #include "optional_container.h" - namespace sqlite_orm { namespace internal { @@ -4646,7 +4631,6 @@ namespace sqlite_orm { // #include "column.h" - namespace sqlite_orm { namespace internal { @@ -4753,7 +4737,6 @@ namespace sqlite_orm { // #include "is_std_ptr.h" - namespace sqlite_orm { /** @@ -4781,7 +4764,6 @@ namespace sqlite_orm { }; } - namespace sqlite_orm { /** @@ -4992,7 +4974,6 @@ namespace sqlite_orm { // #include "journal_mode.h" - #include // std::string #include // std::unique_ptr #include // std::array @@ -5055,7 +5036,6 @@ namespace sqlite_orm { // #include "error_code.h" - namespace sqlite_orm { /** @@ -5432,7 +5412,6 @@ namespace sqlite_orm { // #include "alias.h" - namespace sqlite_orm { namespace internal { @@ -5679,7 +5658,6 @@ namespace sqlite_orm { } } - namespace sqlite_orm { namespace internal { @@ -5944,7 +5922,6 @@ namespace sqlite_orm { // #include "column.h" - namespace sqlite_orm { namespace internal { @@ -6244,12 +6221,10 @@ namespace sqlite_orm { // #include "field_value_holder.h" - #include // std::enable_if // #include "column.h" - namespace sqlite_orm { namespace internal { @@ -6272,7 +6247,6 @@ namespace sqlite_orm { } } - namespace sqlite_orm { namespace internal { @@ -6774,7 +6748,6 @@ namespace sqlite_orm { // #include "view.h" - #include // std::shared_ptr #include // std::string #include // std::forward, std::move @@ -6790,7 +6763,6 @@ namespace sqlite_orm { // #include "iterator.h" - #include // std::shared_ptr, std::unique_ptr, std::make_shared #include #include // std::decay @@ -6806,7 +6778,6 @@ namespace sqlite_orm { // #include "error_code.h" - namespace sqlite_orm { namespace internal { @@ -6935,7 +6906,6 @@ namespace sqlite_orm { // #include "ast_iterator.h" - #include // std::vector #include // std::reference_wrapper @@ -6951,7 +6921,6 @@ namespace sqlite_orm { // #include "prepared_statement.h" - #include #include // std::iterator_traits #include // std::string @@ -6960,14 +6929,12 @@ namespace sqlite_orm { // #include "connection_holder.h" - #include #include // std::string #include // std::system_error // #include "error_code.h" - namespace sqlite_orm { namespace internal { @@ -7042,7 +7009,6 @@ namespace sqlite_orm { // #include "select_constraints.h" - namespace sqlite_orm { namespace internal { @@ -7127,7 +7093,7 @@ namespace sqlite_orm { struct get_all_pointer_t { using type = T; using return_type = R; - + using conditions_type = std::tuple; conditions_type conditions; @@ -7420,13 +7386,13 @@ namespace sqlite_orm { * R is a container return type * Usage: storage.get_all_pointer(...); */ -template -internal::get_all_pointer_t get_all_pointer(Args... args) { - using args_tuple = std::tuple; - internal::validate_conditions(); - std::tuple conditions{std::forward(args)...}; - return {move(conditions)}; -} + template + internal::get_all_pointer_t get_all_pointer(Args... args) { + using args_tuple = std::tuple; + internal::validate_conditions(); + std::tuple conditions{std::forward(args)...}; + return {move(conditions)}; + } #ifdef SQLITE_ORM_OPTIONAL_SUPPORTED /** @@ -7442,7 +7408,6 @@ internal::get_all_pointer_t get_all_pointer(Args... args) { #endif // SQLITE_ORM_OPTIONAL_SUPPORTED } - namespace sqlite_orm { namespace internal { @@ -7928,7 +7893,6 @@ namespace sqlite_orm { // #include "connection_holder.h" - namespace sqlite_orm { namespace internal { @@ -7991,7 +7955,6 @@ namespace sqlite_orm { // #include "storage_base.h" - #include // std::function, std::bind #include #include // std::string @@ -8006,7 +7969,6 @@ namespace sqlite_orm { // #include "pragma.h" - #include // std::string #include #include // std::function @@ -8020,7 +7982,6 @@ namespace sqlite_orm { // #include "connection_holder.h" - namespace sqlite_orm { namespace internal { @@ -8141,7 +8102,6 @@ namespace sqlite_orm { // #include "limit_accesor.h" - #include #include // std::map #include // std::function @@ -8149,7 +8109,6 @@ namespace sqlite_orm { // #include "connection_holder.h" - namespace sqlite_orm { namespace internal { @@ -8283,12 +8242,10 @@ namespace sqlite_orm { // #include "transaction_guard.h" - #include // std::function // #include "connection_holder.h" - namespace sqlite_orm { namespace internal { @@ -8363,7 +8320,6 @@ namespace sqlite_orm { // #include "backup.h" - #include #include // std::string #include @@ -8372,7 +8328,6 @@ namespace sqlite_orm { // #include "connection_holder.h" - namespace sqlite_orm { namespace internal { @@ -8438,7 +8393,6 @@ namespace sqlite_orm { } } - namespace sqlite_orm { namespace internal { @@ -8939,13 +8893,11 @@ namespace sqlite_orm { // #include "expression_object_type.h" - #include // std::decay #include // std::reference_wrapper // #include "prepared_statement.h" - namespace sqlite_orm { namespace internal { @@ -9065,7 +9017,6 @@ namespace sqlite_orm { // #include "statement_serializator.h" - #include // std::stringstream #include // std::string #include // std::is_arithmetic, std::enable_if @@ -9086,7 +9037,6 @@ namespace sqlite_orm { // #include "table_name_collector.h" - #include // std::set #include // std::string #include // std::function @@ -9098,7 +9048,6 @@ namespace sqlite_orm { // #include "core_functions.h" - namespace sqlite_orm { namespace internal { @@ -9159,7 +9108,6 @@ namespace sqlite_orm { // #include "column_names_getter.h" - #include // std::string #include // std::vector #include // std::reference_wrapper @@ -9168,7 +9116,6 @@ namespace sqlite_orm { // #include "select_constraints.h" - namespace sqlite_orm { namespace internal { @@ -9247,7 +9194,6 @@ namespace sqlite_orm { // #include "order_by_serializator.h" - #include // std::string #include // std::vector #include // std::stringstream @@ -9334,7 +9280,6 @@ namespace sqlite_orm { } } - namespace sqlite_orm { namespace internal { @@ -10786,7 +10731,6 @@ namespace sqlite_orm { // #include "table_name_collector.h" - namespace sqlite_orm { namespace internal { @@ -11105,7 +11049,7 @@ namespace sqlite_orm { auto statement = this->prepare(sqlite_orm::get_all_pointer(std::forward(args)...)); return this->execute(statement); } - + template auto get_all_pointer(Args &&... args) { this->assert_mapped_type(); @@ -12527,20 +12471,19 @@ __pragma(pop_macro("min")) #include // std::pair #include // std::reference_wrapper -// #include "conditions.h" + // #include "conditions.h" -// #include "operators.h" + // #include "operators.h" -// #include "select_constraints.h" + // #include "select_constraints.h" -// #include "prepared_statement.h" + // #include "prepared_statement.h" -// #include "optional_container.h" - -// #include "core_functions.h" + // #include "optional_container.h" + // #include "core_functions.h" -namespace sqlite_orm { + namespace sqlite_orm { namespace internal { @@ -12821,7 +12764,6 @@ namespace sqlite_orm { // #include "expression_object_type.h" - namespace sqlite_orm { template diff --git a/tests/get_all_custom_containers.cpp b/tests/get_all_custom_containers.cpp index a297554a8..174f57d1d 100644 --- a/tests/get_all_custom_containers.cpp +++ b/tests/get_all_custom_containers.cpp @@ -12,15 +12,15 @@ struct User { }; struct Comparator { - + bool operator()(const User &lhs, const User &rhs) const { return lhs.id == rhs.id && lhs.name == rhs.name; } - + bool operator()(const std::unique_ptr &lhs, const User &rhs) const { - if(lhs){ + if(lhs) { return this->operator()(*lhs, rhs); - }else{ + } else { return false; } } @@ -28,13 +28,13 @@ struct Comparator { struct Tester { const std::vector &expected; - + template void testContainer(const T &users) const { REQUIRE(std::equal(users.begin(), users.end(), this->expected.begin(), this->expected.end(), Comparator{})); static_assert(std::is_same::value, ""); } - + template void testPreparedStatement(S &storage, const T &statement) const { this->testContainer(storage.execute(statement)); @@ -57,9 +57,9 @@ TEST_CASE("get_all deque") { std::vector expected; expected.push_back(user1); expected.push_back(user2); - + Tester tester{expected}; - + // get_all tester.testContainer>(storage.get_all()); tester.testContainer>(storage.get_all>()); @@ -69,14 +69,23 @@ TEST_CASE("get_all deque") { tester.testPreparedStatement>(storage, storage.prepare(get_all>())); tester.testPreparedStatement>(storage, storage.prepare(get_all>())); tester.testPreparedStatement>(storage, storage.prepare(get_all>())); - + // get_all_pointer tester.testContainer>>(storage.get_all_pointer()); - tester.testContainer>>(storage.get_all_pointer>>()); - tester.testContainer>>(storage.get_all_pointer>>()); - tester.testContainer>>(storage.get_all_pointer>>()); + tester.testContainer>>( + storage.get_all_pointer>>()); + tester.testContainer>>( + storage.get_all_pointer>>()); + tester.testContainer>>( + storage.get_all_pointer>>()); tester.testPreparedStatement>>(storage, storage.prepare(get_all_pointer())); - tester.testPreparedStatement>>(storage, storage.prepare(get_all_pointer>>())); - tester.testPreparedStatement>>(storage, storage.prepare(get_all_pointer>>())); - tester.testPreparedStatement>>(storage, storage.prepare(get_all_pointer>>())); + tester.testPreparedStatement>>( + storage, + storage.prepare(get_all_pointer>>())); + tester.testPreparedStatement>>( + storage, + storage.prepare(get_all_pointer>>())); + tester.testPreparedStatement>>( + storage, + storage.prepare(get_all_pointer>>())); } diff --git a/tests/prepared_statement_tests/get_all_pointer.cpp b/tests/prepared_statement_tests/get_all_pointer.cpp index ab06fd1e9..8f0ca3098 100644 --- a/tests/prepared_statement_tests/get_all_pointer.cpp +++ b/tests/prepared_statement_tests/get_all_pointer.cpp @@ -97,7 +97,7 @@ TEST_CASE("Prepared get all pointer") { { // by ref auto id = 3; auto statement = storage.prepare(get_all_pointer(where(lesser_than(&User::id, std::ref(id))))); - + using Statement = decltype(statement); using Expression = Statement::expression_type; using NodeTuple = internal::node_tuple::type; From 6aaa595dc9aa2b266ad9219f820c9082e816855b Mon Sep 17 00:00:00 2001 From: fnc12 Date: Thu, 14 May 2020 23:05:06 +0300 Subject: [PATCH 074/132] fixed comments --- dev/prepared_statement.h | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/dev/prepared_statement.h b/dev/prepared_statement.h index bed4cc8c1..0c7d24065 100644 --- a/dev/prepared_statement.h +++ b/dev/prepared_statement.h @@ -231,8 +231,8 @@ namespace sqlite_orm { * Create a replace statement. * T is an object type mapped to a storage. * Usage: storage.replace(myUserInstance); - * Parameter obj is accepted by value. Is you want to accept it by ref - * the use std::ref function: storage.replace(std::ref(myUserInstance)); + * Parameter obj is accepted by value. If you want to accept it by ref + * please use std::ref function: storage.replace(std::ref(myUserInstance)); */ template internal::replace_t replace(T obj) { @@ -243,8 +243,8 @@ namespace sqlite_orm { * Create an insert statement. * T is an object type mapped to a storage. * Usage: storage.insert(myUserInstance); - * Parameter obj is accepted by value. Is you want to accept it by ref - * the use std::ref function: storage.insert(std::ref(myUserInstance)); + * Parameter obj is accepted by value. If you want to accept it by ref + * please use std::ref function: storage.insert(std::ref(myUserInstance)); */ template internal::insert_t insert(T obj) { @@ -256,8 +256,8 @@ namespace sqlite_orm { * T is an object type mapped to a storage. * Cols is columns types aparameter pack. Must contain member pointers * Usage: storage.insert(myUserInstance, columns(&User::id, &User::name)); - * Parameter obj is accepted by value. Is you want to accept it by ref - * the use std::ref function: storage.insert(std::ref(myUserInstance), columns(&User::id, &User::name)); + * Parameter obj is accepted by value. If you want to accept it by ref + * please use std::ref function: storage.insert(std::ref(myUserInstance), columns(&User::id, &User::name)); */ template internal::insert_explicit insert(T obj, internal::columns_t cols) { @@ -279,8 +279,8 @@ namespace sqlite_orm { * Create an update statement. * T is an object type mapped to a storage. * Usage: storage.update(myUserInstance); - * Parameter obj is accepted by value. Is you want to accept it by ref - * the use std::ref function: storage.update(std::ref(myUserInstance)); + * Parameter obj is accepted by value. If you want to accept it by ref + * please use std::ref function: storage.update(std::ref(myUserInstance)); */ template internal::update_t update(T obj) { @@ -348,6 +348,12 @@ namespace sqlite_orm { return {move(conditions)}; } + /** + * Create a get all statement. + * T is an object type mapped to a storage. + * R is a container type. std::vector is default + * Usage: storage.get_all(...); + */ template internal::get_all_t get_all(Args... args) { using args_tuple = std::tuple; From 627eacfd7eac2e1f0e9a33c672ddc889e08a7731 Mon Sep 17 00:00:00 2001 From: fnc12 Date: Thu, 14 May 2020 23:49:51 +0300 Subject: [PATCH 075/132] added custom container support for get_all_optional --- dev/prepared_statement.h | 33 ++++++++++--- dev/storage.h | 15 +++--- include/sqlite_orm/sqlite_orm.h | 76 ++++++++++++++++++++--------- tests/get_all_custom_containers.cpp | 74 +++++++++++++++++++++------- 4 files changed, 141 insertions(+), 57 deletions(-) diff --git a/dev/prepared_statement.h b/dev/prepared_statement.h index 0c7d24065..3287a67dc 100644 --- a/dev/prepared_statement.h +++ b/dev/prepared_statement.h @@ -77,8 +77,8 @@ namespace sqlite_orm { }; /** - * T - type of object to obtain from a database - */ + * T - type of object to obtain from a database + */ template struct get_all_t { using type = T; @@ -100,9 +100,10 @@ namespace sqlite_orm { }; #ifdef SQLITE_ORM_OPTIONAL_SUPPORTED - template + template struct get_all_optional_t { using type = T; + using return_type = R; using conditions_type = std::tuple; @@ -383,20 +384,20 @@ namespace sqlite_orm { internal::get_all_pointer_t>, Args...> get_all_pointer(Args... args) { using args_tuple = std::tuple; internal::validate_conditions(); - std::tuple conditions{std::forward(args)...}; + args_tuple conditions{std::forward(args)...}; return {move(conditions)}; } /** * Create a get all pointer statement. * T is an object type mapped to a storage. - * R is a container return type. std::vector> is default + * R is a container return type. std::vector> is default * Usage: storage.get_all_pointer(...); */ template internal::get_all_pointer_t get_all_pointer(Args... args) { using args_tuple = std::tuple; internal::validate_conditions(); - std::tuple conditions{std::forward(args)...}; + args_tuple conditions{std::forward(args)...}; return {move(conditions)}; } @@ -407,8 +408,24 @@ namespace sqlite_orm { * Usage: storage.get_all_optional(...); */ template - internal::get_all_optional_t get_all_optional(Args... args) { - std::tuple conditions{std::forward(args)...}; + internal::get_all_optional_t>, Args...> get_all_optional(Args... args) { + using args_tuple = std::tuple; + internal::validate_conditions(); + args_tuple conditions{std::forward(args)...}; + return {move(conditions)}; + } + + /** + * Create a get all optional statement. + * T is an object type mapped to a storage. + * R is a container return type. std::vector> is default + * Usage: storage.get_all_optional(...); + */ + template + internal::get_all_optional_t get_all_optional(Args... args) { + using args_tuple = std::tuple; + internal::validate_conditions(); + args_tuple conditions{std::forward(args)...}; return {move(conditions)}; } #endif // SQLITE_ORM_OPTIONAL_SUPPORTED diff --git a/dev/storage.h b/dev/storage.h index 75584fc1a..d338c1db4 100644 --- a/dev/storage.h +++ b/dev/storage.h @@ -216,8 +216,8 @@ namespace sqlite_orm { } #ifdef SQLITE_ORM_OPTIONAL_SUPPORTED - template - std::string string_from_expression(const get_all_optional_t &get, bool noTableName) const { + template + std::string string_from_expression(const get_all_optional_t &get, bool noTableName) const { std::stringstream ss = this->string_from_expression_impl_get_all(get, noTableName); return ss.str(); } @@ -887,8 +887,8 @@ namespace sqlite_orm { } #ifdef SQLITE_ORM_OPTIONAL_SUPPORTED - template - prepared_statement_t> prepare(get_all_optional_t get) { + template + prepared_statement_t> prepare(get_all_optional_t get) { auto con = this->get_connection(); sqlite3_stmt *stmt; auto db = con.get(); @@ -1708,9 +1708,8 @@ namespace sqlite_orm { } #ifdef SQLITE_ORM_OPTIONAL_SUPPORTED - template - std::vector> - execute(const prepared_statement_t> &statement) { + template + R execute(const prepared_statement_t> &statement) { auto &tImpl = this->get_impl(); auto con = this->get_connection(); auto db = con.get(); @@ -1725,7 +1724,7 @@ namespace sqlite_orm { sqlite3_errmsg(db)); } }); - std::vector> res; + R res; int stepRes; do { stepRes = sqlite3_step(stmt); diff --git a/include/sqlite_orm/sqlite_orm.h b/include/sqlite_orm/sqlite_orm.h index df74a30dc..e556c22c2 100644 --- a/include/sqlite_orm/sqlite_orm.h +++ b/include/sqlite_orm/sqlite_orm.h @@ -7077,8 +7077,8 @@ namespace sqlite_orm { }; /** - * T - type of object to obtain from a database - */ + * T - type of object to obtain from a database + */ template struct get_all_t { using type = T; @@ -7100,9 +7100,10 @@ namespace sqlite_orm { }; #ifdef SQLITE_ORM_OPTIONAL_SUPPORTED - template + template struct get_all_optional_t { using type = T; + using return_type = R; using conditions_type = std::tuple; @@ -7231,8 +7232,8 @@ namespace sqlite_orm { * Create a replace statement. * T is an object type mapped to a storage. * Usage: storage.replace(myUserInstance); - * Parameter obj is accepted by value. Is you want to accept it by ref - * the use std::ref function: storage.replace(std::ref(myUserInstance)); + * Parameter obj is accepted by value. If you want to accept it by ref + * please use std::ref function: storage.replace(std::ref(myUserInstance)); */ template internal::replace_t replace(T obj) { @@ -7243,8 +7244,8 @@ namespace sqlite_orm { * Create an insert statement. * T is an object type mapped to a storage. * Usage: storage.insert(myUserInstance); - * Parameter obj is accepted by value. Is you want to accept it by ref - * the use std::ref function: storage.insert(std::ref(myUserInstance)); + * Parameter obj is accepted by value. If you want to accept it by ref + * please use std::ref function: storage.insert(std::ref(myUserInstance)); */ template internal::insert_t insert(T obj) { @@ -7256,8 +7257,8 @@ namespace sqlite_orm { * T is an object type mapped to a storage. * Cols is columns types aparameter pack. Must contain member pointers * Usage: storage.insert(myUserInstance, columns(&User::id, &User::name)); - * Parameter obj is accepted by value. Is you want to accept it by ref - * the use std::ref function: storage.insert(std::ref(myUserInstance), columns(&User::id, &User::name)); + * Parameter obj is accepted by value. If you want to accept it by ref + * please use std::ref function: storage.insert(std::ref(myUserInstance), columns(&User::id, &User::name)); */ template internal::insert_explicit insert(T obj, internal::columns_t cols) { @@ -7279,8 +7280,8 @@ namespace sqlite_orm { * Create an update statement. * T is an object type mapped to a storage. * Usage: storage.update(myUserInstance); - * Parameter obj is accepted by value. Is you want to accept it by ref - * the use std::ref function: storage.update(std::ref(myUserInstance)); + * Parameter obj is accepted by value. If you want to accept it by ref + * please use std::ref function: storage.update(std::ref(myUserInstance)); */ template internal::update_t update(T obj) { @@ -7348,6 +7349,12 @@ namespace sqlite_orm { return {move(conditions)}; } + /** + * Create a get all statement. + * T is an object type mapped to a storage. + * R is a container type. std::vector is default + * Usage: storage.get_all(...); + */ template internal::get_all_t get_all(Args... args) { using args_tuple = std::tuple; @@ -7377,20 +7384,20 @@ namespace sqlite_orm { internal::get_all_pointer_t>, Args...> get_all_pointer(Args... args) { using args_tuple = std::tuple; internal::validate_conditions(); - std::tuple conditions{std::forward(args)...}; + args_tuple conditions{std::forward(args)...}; return {move(conditions)}; } /** * Create a get all pointer statement. * T is an object type mapped to a storage. - * R is a container return type + * R is a container return type. std::vector> is default * Usage: storage.get_all_pointer(...); */ template internal::get_all_pointer_t get_all_pointer(Args... args) { using args_tuple = std::tuple; internal::validate_conditions(); - std::tuple conditions{std::forward(args)...}; + args_tuple conditions{std::forward(args)...}; return {move(conditions)}; } @@ -7401,8 +7408,24 @@ namespace sqlite_orm { * Usage: storage.get_all_optional(...); */ template - internal::get_all_optional_t get_all_optional(Args... args) { - std::tuple conditions{std::forward(args)...}; + internal::get_all_optional_t>, Args...> get_all_optional(Args... args) { + using args_tuple = std::tuple; + internal::validate_conditions(); + args_tuple conditions{std::forward(args)...}; + return {move(conditions)}; + } + + /** + * Create a get all optional statement. + * T is an object type mapped to a storage. + * R is a container return type. std::vector> is default + * Usage: storage.get_all_optional(...); + */ + template + internal::get_all_optional_t get_all_optional(Args... args) { + using args_tuple = std::tuple; + internal::validate_conditions(); + args_tuple conditions{std::forward(args)...}; return {move(conditions)}; } #endif // SQLITE_ORM_OPTIONAL_SUPPORTED @@ -10899,8 +10922,8 @@ namespace sqlite_orm { } #ifdef SQLITE_ORM_OPTIONAL_SUPPORTED - template - std::string string_from_expression(const get_all_optional_t &get, bool noTableName) const { + template + std::string string_from_expression(const get_all_optional_t &get, bool noTableName) const { std::stringstream ss = this->string_from_expression_impl_get_all(get, noTableName); return ss.str(); } @@ -11050,6 +11073,12 @@ namespace sqlite_orm { return this->execute(statement); } + /** + * Select * with no conditions routine. + * O is an object type to be extracted. Must be specified explicitly. + * R is a container type. std::vector> is default + * @return All objects of type O as std::unique_ptr stored in database at the moment. + */ template auto get_all_pointer(Args &&... args) { this->assert_mapped_type(); @@ -11564,8 +11593,8 @@ namespace sqlite_orm { } #ifdef SQLITE_ORM_OPTIONAL_SUPPORTED - template - prepared_statement_t> prepare(get_all_optional_t get) { + template + prepared_statement_t> prepare(get_all_optional_t get) { auto con = this->get_connection(); sqlite3_stmt *stmt; auto db = con.get(); @@ -12385,9 +12414,8 @@ namespace sqlite_orm { } #ifdef SQLITE_ORM_OPTIONAL_SUPPORTED - template - std::vector> - execute(const prepared_statement_t> &statement) { + template + R execute(const prepared_statement_t> &statement) { auto &tImpl = this->get_impl(); auto con = this->get_connection(); auto db = con.get(); @@ -12402,7 +12430,7 @@ namespace sqlite_orm { sqlite3_errmsg(db)); } }); - std::vector> res; + R res; int stepRes; do { stepRes = sqlite3_step(stmt); diff --git a/tests/get_all_custom_containers.cpp b/tests/get_all_custom_containers.cpp index 174f57d1d..592be9028 100644 --- a/tests/get_all_custom_containers.cpp +++ b/tests/get_all_custom_containers.cpp @@ -24,6 +24,15 @@ struct Comparator { return false; } } +#ifdef SQLITE_ORM_OPTIONAL_SUPPORTED + bool operator()(const std::optional &lhs, const User &rhs) const { + if(lhs.has_value()) { + return this->operator()(*lhs, rhs); + } else { + return false; + } + } +#endif // SQLITE_ORM_OPTIONAL_SUPPORTED }; struct Tester { @@ -71,21 +80,52 @@ TEST_CASE("get_all deque") { tester.testPreparedStatement>(storage, storage.prepare(get_all>())); // get_all_pointer - tester.testContainer>>(storage.get_all_pointer()); - tester.testContainer>>( - storage.get_all_pointer>>()); - tester.testContainer>>( - storage.get_all_pointer>>()); - tester.testContainer>>( - storage.get_all_pointer>>()); - tester.testPreparedStatement>>(storage, storage.prepare(get_all_pointer())); - tester.testPreparedStatement>>( - storage, - storage.prepare(get_all_pointer>>())); - tester.testPreparedStatement>>( - storage, - storage.prepare(get_all_pointer>>())); - tester.testPreparedStatement>>( - storage, - storage.prepare(get_all_pointer>>())); + { + using UserP = std::unique_ptr; + tester.testContainer>(storage.get_all_pointer()); + { + using Container = std::vector; + tester.testContainer(storage.get_all_pointer()); + } + { + using Container = std::deque; + tester.testContainer(storage.get_all_pointer()); + } + { + using Container = std::list; + tester.testContainer(storage.get_all_pointer()); + } + tester.testPreparedStatement>(storage, storage.prepare(get_all_pointer())); + { + using Container = std::vector; + tester.testPreparedStatement(storage, storage.prepare(get_all_pointer())); + } + { + using Container = std::deque; + tester.testPreparedStatement(storage, storage.prepare(get_all_pointer())); + } + { + using Container = std::list; + tester.testPreparedStatement(storage, storage.prepare(get_all_pointer())); + } + } +#ifdef SQLITE_ORM_OPTIONAL_SUPPORTED + // get_all_optional + { + using UserP = std::optional; + tester.testPreparedStatement>(storage, storage.prepare(get_all_optional())); + { + using Container = std::vector; + tester.testPreparedStatement(storage, storage.prepare(get_all_optional())); + } + { + using Container = std::deque; + tester.testPreparedStatement(storage, storage.prepare(get_all_optional())); + } + { + using Container = std::list; + tester.testPreparedStatement(storage, storage.prepare(get_all_optional())); + } + } +#endif // SQLITE_ORM_OPTIONAL_SUPPORTED } From 93c5ee42ff5be11305d900df6eaeef4be2e19d15 Mon Sep 17 00:00:00 2001 From: fnc12 Date: Fri, 15 May 2020 00:29:23 +0300 Subject: [PATCH 076/132] fixed get all optional unit tests --- .../get_all_optional.cpp | 24 ------------------- 1 file changed, 24 deletions(-) diff --git a/tests/prepared_statement_tests/get_all_optional.cpp b/tests/prepared_statement_tests/get_all_optional.cpp index e123f79f2..954e49fcc 100644 --- a/tests/prepared_statement_tests/get_all_optional.cpp +++ b/tests/prepared_statement_tests/get_all_optional.cpp @@ -58,18 +58,6 @@ TEST_CASE("Prepared get all optional") { using Statement = decltype(statement); using Expression = Statement::expression_type; using NodeTuple = internal::node_tuple::type; - { - static_assert(std::tuple_size::value == 2, ""); - { - using Arg0 = std::tuple_element<0, NodeTuple>::type; - static_assert(std::is_same::value, ""); - } - { - using Arg1 = std::tuple_element<1, NodeTuple>::type; - static_assert(std::is_same::value, ""); - } - } - using BindTuple = typename internal::bindable_filter::type; { static_assert(std::tuple_size::value == 1, ""); @@ -110,18 +98,6 @@ TEST_CASE("Prepared get all optional") { using Statement = decltype(statement); using Expression = Statement::expression_type; using NodeTuple = internal::node_tuple::type; - { - static_assert(std::tuple_size::value == 2, ""); - { - using Arg0 = std::tuple_element<0, NodeTuple>::type; - static_assert(std::is_same::value, ""); - } - { - using Arg1 = std::tuple_element<1, NodeTuple>::type; - static_assert(std::is_same::value, ""); - } - } - using BindTuple = typename internal::bindable_filter::type; { static_assert(std::tuple_size::value == 1, ""); From 265bd41177b72f194b7b3314fa2c8c2330fa398f Mon Sep 17 00:00:00 2001 From: fnc12 Date: Fri, 15 May 2020 23:28:10 +0300 Subject: [PATCH 077/132] removed string_from_expression for get_all* --- dev/statement_serializator.h | 98 +++++++++++------- dev/storage.h | 75 ++------------ include/sqlite_orm/sqlite_orm.h | 173 ++++++++++++++------------------ 3 files changed, 148 insertions(+), 198 deletions(-) diff --git a/dev/statement_serializator.h b/dev/statement_serializator.h index 23c26ca3e..7c3806d4d 100644 --- a/dev/statement_serializator.h +++ b/dev/statement_serializator.h @@ -1105,46 +1105,76 @@ namespace sqlite_orm { } }; + template + std::string serialize_get_all_impl(const T &getQuery, const C &context) { + using primary_type = typename T::type; + + table_name_collector collector; + collector.table_names.insert( + std::make_pair(context.impl.find_table_name(typeid(primary_type)), std::string{})); + iterate_ast(getQuery.conditions, collector); + std::stringstream ss; + ss << "SELECT "; + auto &tImpl = context.impl.template get_impl(); + auto columnNames = tImpl.table.column_names(); + for(size_t i = 0; i < columnNames.size(); ++i) { + ss << "\"" << tImpl.table.name << "\"." + << "\"" << columnNames[i] << "\""; + if(i < columnNames.size() - 1) { + ss << ", "; + } else { + ss << " "; + } + } + ss << "FROM "; + std::vector> tableNames(collector.table_names.begin(), + collector.table_names.end()); + for(size_t i = 0; i < tableNames.size(); ++i) { + auto &tableNamePair = tableNames[i]; + ss << "'" << tableNamePair.first << "' "; + if(!tableNamePair.second.empty()) { + ss << tableNamePair.second << " "; + } + if(int(i) < int(tableNames.size()) - 1) { + ss << ","; + } + ss << " "; + } + iterate_tuple(getQuery.conditions, [&context, &ss](auto &v) { + ss << serialize(v, context); + }); + return ss.str(); + } + +#ifdef SQLITE_ORM_OPTIONAL_SUPPORTED + template + struct statement_serializator, void> { + using statement_type = get_all_optional_t; + + template + std::string operator()(const statement_type &get, const C &context) const { + return serialize_get_all_impl(get, context); + } + }; +#endif // SQLITE_ORM_OPTIONAL_SUPPORTED + + template + struct statement_serializator, void> { + using statement_type = get_all_pointer_t; + + template + std::string operator()(const statement_type &get, const C &context) const { + return serialize_get_all_impl(get, context); + } + }; + template struct statement_serializator, void> { using statement_type = get_all_t; template std::string operator()(const statement_type &get, const C &context) const { - table_name_collector collector; - collector.table_names.insert(std::make_pair(context.impl.find_table_name(typeid(T)), std::string{})); - iterate_ast(get.conditions, collector); - std::stringstream ss; - ss << "SELECT "; - auto &tImpl = context.impl.template get_impl(); - auto columnNames = tImpl.table.column_names(); - for(size_t i = 0; i < columnNames.size(); ++i) { - ss << "\"" << tImpl.table.name << "\"." - << "\"" << columnNames[i] << "\""; - if(i < columnNames.size() - 1) { - ss << ", "; - } else { - ss << " "; - } - } - ss << "FROM "; - std::vector> tableNames(collector.table_names.begin(), - collector.table_names.end()); - for(size_t i = 0; i < tableNames.size(); ++i) { - auto &tableNamePair = tableNames[i]; - ss << "'" << tableNamePair.first << "' "; - if(!tableNamePair.second.empty()) { - ss << tableNamePair.second << " "; - } - if(int(i) < int(tableNames.size()) - 1) { - ss << ","; - } - ss << " "; - } - iterate_tuple(get.conditions, [&context, &ss](auto &v) { - ss << serialize(v, context); - }); - return ss.str(); + return serialize_get_all_impl(get, context); } }; diff --git a/dev/storage.h b/dev/storage.h index d338c1db4..b4060d73e 100644 --- a/dev/storage.h +++ b/dev/storage.h @@ -160,69 +160,6 @@ namespace sqlite_orm { return this->impl.template get_impl(); } - // Common code for statements returning the whole content of a table: get_all_t, get_all_pointer_t, - // get_all_optional_t. - template - std::stringstream string_from_expression_impl_get_all(const T &get_query, bool /*noTableName*/) const { - using primary_type = typename T::type; - - table_name_collector collector; - collector.table_names.insert( - std::make_pair(this->impl.find_table_name(typeid(primary_type)), std::string{})); - iterate_ast(get_query.conditions, collector); - std::stringstream ss; - ss << "SELECT "; - auto &tImpl = this->get_impl(); - auto columnNames = tImpl.table.column_names(); - for(size_t i = 0; i < columnNames.size(); ++i) { - ss << "\"" << tImpl.table.name << "\"." - << "\"" << columnNames[i] << "\""; - if(i < columnNames.size() - 1) { - ss << ", "; - } else { - ss << " "; - } - } - ss << "FROM "; - std::vector> tableNames(collector.table_names.begin(), - collector.table_names.end()); - for(size_t i = 0; i < tableNames.size(); ++i) { - auto &tableNamePair = tableNames[i]; - ss << "'" << tableNamePair.first << "' "; - if(!tableNamePair.second.empty()) { - ss << tableNamePair.second << " "; - } - if(int(i) < int(tableNames.size()) - 1) { - ss << ","; - } - ss << " "; - } - - using context_t = serializator_context; - context_t context{this->impl}; - context.skip_table_name = false; - context.replace_bindable_with_question = true; - iterate_tuple(get_query.conditions, [&context, &ss](auto &v) { - ss << serialize(v, context); - }); - - return ss; - } - - template - std::string string_from_expression(const get_all_pointer_t &get, bool noTableName) const { - std::stringstream ss = this->string_from_expression_impl_get_all(get, noTableName); - return ss.str(); - } - -#ifdef SQLITE_ORM_OPTIONAL_SUPPORTED - template - std::string string_from_expression(const get_all_optional_t &get, bool noTableName) const { - std::stringstream ss = this->string_from_expression_impl_get_all(get, noTableName); - return ss.str(); - } -#endif // SQLITE_ORM_OPTIONAL_SUPPORTED - // Common code for statements with conditions: get_t, get_pointer_t, get_optional_t. template std::string string_from_expression_impl_get(bool /*noTableName*/) const { @@ -877,7 +814,11 @@ namespace sqlite_orm { auto con = this->get_connection(); sqlite3_stmt *stmt; auto db = con.get(); - auto query = this->string_from_expression(get, false); + using context_t = serializator_context; + context_t context{this->impl}; + context.skip_table_name = false; + context.replace_bindable_with_question = true; + auto query = serialize(get, context); if(sqlite3_prepare_v2(db, query.c_str(), -1, &stmt, nullptr) == SQLITE_OK) { return {std::move(get), stmt, con}; } else { @@ -892,7 +833,11 @@ namespace sqlite_orm { auto con = this->get_connection(); sqlite3_stmt *stmt; auto db = con.get(); - auto query = this->string_from_expression(get, false); + using context_t = serializator_context; + context_t context{this->impl}; + context.skip_table_name = false; + context.replace_bindable_with_question = true; + auto query = serialize(get, context); if(sqlite3_prepare_v2(db, query.c_str(), -1, &stmt, nullptr) == SQLITE_OK) { return {std::move(get), stmt, con}; } else { diff --git a/include/sqlite_orm/sqlite_orm.h b/include/sqlite_orm/sqlite_orm.h index e556c22c2..eea07cf38 100644 --- a/include/sqlite_orm/sqlite_orm.h +++ b/include/sqlite_orm/sqlite_orm.h @@ -10392,46 +10392,76 @@ namespace sqlite_orm { } }; + template + std::string serialize_get_all_impl(const T &getQuery, const C &context) { + using primary_type = typename T::type; + + table_name_collector collector; + collector.table_names.insert( + std::make_pair(context.impl.find_table_name(typeid(primary_type)), std::string{})); + iterate_ast(getQuery.conditions, collector); + std::stringstream ss; + ss << "SELECT "; + auto &tImpl = context.impl.template get_impl(); + auto columnNames = tImpl.table.column_names(); + for(size_t i = 0; i < columnNames.size(); ++i) { + ss << "\"" << tImpl.table.name << "\"." + << "\"" << columnNames[i] << "\""; + if(i < columnNames.size() - 1) { + ss << ", "; + } else { + ss << " "; + } + } + ss << "FROM "; + std::vector> tableNames(collector.table_names.begin(), + collector.table_names.end()); + for(size_t i = 0; i < tableNames.size(); ++i) { + auto &tableNamePair = tableNames[i]; + ss << "'" << tableNamePair.first << "' "; + if(!tableNamePair.second.empty()) { + ss << tableNamePair.second << " "; + } + if(int(i) < int(tableNames.size()) - 1) { + ss << ","; + } + ss << " "; + } + iterate_tuple(getQuery.conditions, [&context, &ss](auto &v) { + ss << serialize(v, context); + }); + return ss.str(); + } + +#ifdef SQLITE_ORM_OPTIONAL_SUPPORTED + template + struct statement_serializator, void> { + using statement_type = get_all_optional_t; + + template + std::string operator()(const statement_type &get, const C &context) const { + return serialize_get_all_impl(get, context); + } + }; +#endif // SQLITE_ORM_OPTIONAL_SUPPORTED + + template + struct statement_serializator, void> { + using statement_type = get_all_pointer_t; + + template + std::string operator()(const statement_type &get, const C &context) const { + return serialize_get_all_impl(get, context); + } + }; + template struct statement_serializator, void> { using statement_type = get_all_t; template std::string operator()(const statement_type &get, const C &context) const { - table_name_collector collector; - collector.table_names.insert(std::make_pair(context.impl.find_table_name(typeid(T)), std::string{})); - iterate_ast(get.conditions, collector); - std::stringstream ss; - ss << "SELECT "; - auto &tImpl = context.impl.template get_impl(); - auto columnNames = tImpl.table.column_names(); - for(size_t i = 0; i < columnNames.size(); ++i) { - ss << "\"" << tImpl.table.name << "\"." - << "\"" << columnNames[i] << "\""; - if(i < columnNames.size() - 1) { - ss << ", "; - } else { - ss << " "; - } - } - ss << "FROM "; - std::vector> tableNames(collector.table_names.begin(), - collector.table_names.end()); - for(size_t i = 0; i < tableNames.size(); ++i) { - auto &tableNamePair = tableNames[i]; - ss << "'" << tableNamePair.first << "' "; - if(!tableNamePair.second.empty()) { - ss << tableNamePair.second << " "; - } - if(int(i) < int(tableNames.size()) - 1) { - ss << ","; - } - ss << " "; - } - iterate_tuple(get.conditions, [&context, &ss](auto &v) { - ss << serialize(v, context); - }); - return ss.str(); + return serialize_get_all_impl(get, context); } }; @@ -10866,69 +10896,6 @@ namespace sqlite_orm { return this->impl.template get_impl(); } - // Common code for statements returning the whole content of a table: get_all_t, get_all_pointer_t, - // get_all_optional_t. - template - std::stringstream string_from_expression_impl_get_all(const T &get_query, bool /*noTableName*/) const { - using primary_type = typename T::type; - - table_name_collector collector; - collector.table_names.insert( - std::make_pair(this->impl.find_table_name(typeid(primary_type)), std::string{})); - iterate_ast(get_query.conditions, collector); - std::stringstream ss; - ss << "SELECT "; - auto &tImpl = this->get_impl(); - auto columnNames = tImpl.table.column_names(); - for(size_t i = 0; i < columnNames.size(); ++i) { - ss << "\"" << tImpl.table.name << "\"." - << "\"" << columnNames[i] << "\""; - if(i < columnNames.size() - 1) { - ss << ", "; - } else { - ss << " "; - } - } - ss << "FROM "; - std::vector> tableNames(collector.table_names.begin(), - collector.table_names.end()); - for(size_t i = 0; i < tableNames.size(); ++i) { - auto &tableNamePair = tableNames[i]; - ss << "'" << tableNamePair.first << "' "; - if(!tableNamePair.second.empty()) { - ss << tableNamePair.second << " "; - } - if(int(i) < int(tableNames.size()) - 1) { - ss << ","; - } - ss << " "; - } - - using context_t = serializator_context; - context_t context{this->impl}; - context.skip_table_name = false; - context.replace_bindable_with_question = true; - iterate_tuple(get_query.conditions, [&context, &ss](auto &v) { - ss << serialize(v, context); - }); - - return ss; - } - - template - std::string string_from_expression(const get_all_pointer_t &get, bool noTableName) const { - std::stringstream ss = this->string_from_expression_impl_get_all(get, noTableName); - return ss.str(); - } - -#ifdef SQLITE_ORM_OPTIONAL_SUPPORTED - template - std::string string_from_expression(const get_all_optional_t &get, bool noTableName) const { - std::stringstream ss = this->string_from_expression_impl_get_all(get, noTableName); - return ss.str(); - } -#endif // SQLITE_ORM_OPTIONAL_SUPPORTED - // Common code for statements with conditions: get_t, get_pointer_t, get_optional_t. template std::string string_from_expression_impl_get(bool /*noTableName*/) const { @@ -11583,7 +11550,11 @@ namespace sqlite_orm { auto con = this->get_connection(); sqlite3_stmt *stmt; auto db = con.get(); - auto query = this->string_from_expression(get, false); + using context_t = serializator_context; + context_t context{this->impl}; + context.skip_table_name = false; + context.replace_bindable_with_question = true; + auto query = serialize(get, context); if(sqlite3_prepare_v2(db, query.c_str(), -1, &stmt, nullptr) == SQLITE_OK) { return {std::move(get), stmt, con}; } else { @@ -11598,7 +11569,11 @@ namespace sqlite_orm { auto con = this->get_connection(); sqlite3_stmt *stmt; auto db = con.get(); - auto query = this->string_from_expression(get, false); + using context_t = serializator_context; + context_t context{this->impl}; + context.skip_table_name = false; + context.replace_bindable_with_question = true; + auto query = serialize(get, context); if(sqlite3_prepare_v2(db, query.c_str(), -1, &stmt, nullptr) == SQLITE_OK) { return {std::move(get), stmt, con}; } else { From 94a36b4be33df8ac2f5775692cb0db9f6e11aeec Mon Sep 17 00:00:00 2001 From: fnc12 Date: Sat, 16 May 2020 00:52:23 +0300 Subject: [PATCH 078/132] removed string_from_expression for get* --- dev/statement_serializator.h | 68 ++++++++++++++- dev/storage.h | 78 +++++------------ include/sqlite_orm/sqlite_orm.h | 146 +++++++++++++++++++------------- 3 files changed, 172 insertions(+), 120 deletions(-) diff --git a/dev/statement_serializator.h b/dev/statement_serializator.h index 7c3806d4d..af700bd2e 100644 --- a/dev/statement_serializator.h +++ b/dev/statement_serializator.h @@ -1106,13 +1106,13 @@ namespace sqlite_orm { }; template - std::string serialize_get_all_impl(const T &getQuery, const C &context) { + std::string serialize_get_all_impl(const T &get, const C &context) { using primary_type = typename T::type; table_name_collector collector; collector.table_names.insert( std::make_pair(context.impl.find_table_name(typeid(primary_type)), std::string{})); - iterate_ast(getQuery.conditions, collector); + iterate_ast(get.conditions, collector); std::stringstream ss; ss << "SELECT "; auto &tImpl = context.impl.template get_impl(); @@ -1140,7 +1140,7 @@ namespace sqlite_orm { } ss << " "; } - iterate_tuple(getQuery.conditions, [&context, &ss](auto &v) { + iterate_tuple(get.conditions, [&context, &ss](auto &v) { ss << serialize(v, context); }); return ss.str(); @@ -1178,6 +1178,68 @@ namespace sqlite_orm { } }; + template + std::string serialize_get_impl(const T &, const C &context) { + using primary_type = typename T::type; + auto &tImpl = context.impl.template get_impl(); + std::stringstream ss; + ss << "SELECT "; + auto columnNames = tImpl.table.column_names(); + for(size_t i = 0; i < columnNames.size(); ++i) { + ss << "\"" << columnNames[i] << "\""; + if(i < columnNames.size() - 1) { + ss << ","; + } + ss << " "; + } + ss << "FROM '" << tImpl.table.name << "' WHERE "; + auto primaryKeyColumnNames = tImpl.table.primary_key_column_names(); + if(!primaryKeyColumnNames.empty()) { + for(size_t i = 0; i < primaryKeyColumnNames.size(); ++i) { + ss << "\"" << primaryKeyColumnNames[i] << "\"" + << " = ? "; + if(i < primaryKeyColumnNames.size() - 1) { + ss << "AND"; + } + ss << ' '; + } + return ss.str(); + } else { + throw std::system_error(std::make_error_code(orm_error_code::table_has_no_primary_key_column)); + } + } + + template + struct statement_serializator, void> { + using statement_type = get_t; + + template + std::string operator()(const statement_type &get, const C &context) const { + return serialize_get_impl(get, context); + } + }; + + template + struct statement_serializator, void> { + using statement_type = get_pointer_t; + + template + std::string operator()(const statement_type &get, const C &context) const { + return serialize_get_impl(get, context); + } + }; + +#ifdef SQLITE_ORM_OPTIONAL_SUPPORTED + template + struct statement_serializator, void> { + using statement_type = get_optional_t; + + template + std::string operator()(const statement_type &get, const C &context) const { + return serialize_get_impl(get, context); + } + }; +#endif // SQLITE_ORM_OPTIONAL_SUPPORTED template struct statement_serializator, void> { using statement_type = select_t; diff --git a/dev/storage.h b/dev/storage.h index b4060d73e..d1ab194d7 100644 --- a/dev/storage.h +++ b/dev/storage.h @@ -160,54 +160,6 @@ namespace sqlite_orm { return this->impl.template get_impl(); } - // Common code for statements with conditions: get_t, get_pointer_t, get_optional_t. - template - std::string string_from_expression_impl_get(bool /*noTableName*/) const { - auto &tImpl = this->get_impl(); - std::stringstream ss; - ss << "SELECT "; - auto columnNames = tImpl.table.column_names(); - for(size_t i = 0; i < columnNames.size(); ++i) { - ss << "\"" << columnNames[i] << "\""; - if(i < columnNames.size() - 1) { - ss << ","; - } - ss << " "; - } - ss << "FROM '" << tImpl.table.name << "' WHERE "; - auto primaryKeyColumnNames = tImpl.table.primary_key_column_names(); - if(!primaryKeyColumnNames.empty()) { - for(size_t i = 0; i < primaryKeyColumnNames.size(); ++i) { - ss << "\"" << primaryKeyColumnNames[i] << "\"" - << " = ? "; - if(i < primaryKeyColumnNames.size() - 1) { - ss << "AND "; - } - ss << ' '; - } - return ss.str(); - } else { - throw std::system_error(std::make_error_code(orm_error_code::table_has_no_primary_key_column)); - } - } - - template - std::string string_from_expression(const get_t &, bool noTableName) const { - return this->string_from_expression_impl_get(noTableName); - } - - template - std::string string_from_expression(const get_pointer_t &, bool noTableName) const { - return this->string_from_expression_impl_get(noTableName); - } - -#ifdef SQLITE_ORM_OPTIONAL_SUPPORTED - template - std::string string_from_expression(const get_optional_t &, bool noTableName) const { - return this->string_from_expression_impl_get(noTableName); - } -#endif // SQLITE_ORM_OPTIONAL_SUPPORTED - public: template view_t iterate(Args &&... args) { @@ -885,13 +837,17 @@ namespace sqlite_orm { } template - prepared_statement_t> prepare(get_t g) { + prepared_statement_t> prepare(get_t get) { auto con = this->get_connection(); sqlite3_stmt *stmt; auto db = con.get(); - auto query = this->string_from_expression(g, false); + using context_t = serializator_context; + context_t context{this->impl}; + context.skip_table_name = false; + context.replace_bindable_with_question = true; + auto query = serialize(get, context); if(sqlite3_prepare_v2(db, query.c_str(), -1, &stmt, nullptr) == SQLITE_OK) { - return {std::move(g), stmt, con}; + return {std::move(get), stmt, con}; } else { throw std::system_error(std::error_code(sqlite3_errcode(db), get_sqlite_error_category()), sqlite3_errmsg(db)); @@ -899,13 +855,17 @@ namespace sqlite_orm { } template - prepared_statement_t> prepare(get_pointer_t g) { + prepared_statement_t> prepare(get_pointer_t get) { auto con = this->get_connection(); sqlite3_stmt *stmt; auto db = con.get(); - auto query = this->string_from_expression(g, false); + using context_t = serializator_context; + context_t context{this->impl}; + context.skip_table_name = false; + context.replace_bindable_with_question = true; + auto query = serialize(get, context); if(sqlite3_prepare_v2(db, query.c_str(), -1, &stmt, nullptr) == SQLITE_OK) { - return {std::move(g), stmt, con}; + return {std::move(get), stmt, con}; } else { throw std::system_error(std::error_code(sqlite3_errcode(db), get_sqlite_error_category()), sqlite3_errmsg(db)); @@ -914,13 +874,17 @@ namespace sqlite_orm { #ifdef SQLITE_ORM_OPTIONAL_SUPPORTED template - prepared_statement_t> prepare(get_optional_t g) { + prepared_statement_t> prepare(get_optional_t get) { auto con = this->get_connection(); sqlite3_stmt *stmt; auto db = con.get(); - auto query = this->string_from_expression(g, false); + using context_t = serializator_context; + context_t context{this->impl}; + context.skip_table_name = false; + context.replace_bindable_with_question = true; + auto query = serialize(get, context); if(sqlite3_prepare_v2(db, query.c_str(), -1, &stmt, nullptr) == SQLITE_OK) { - return {std::move(g), stmt, con}; + return {std::move(get), stmt, con}; } else { throw std::system_error(std::error_code(sqlite3_errcode(db), get_sqlite_error_category()), sqlite3_errmsg(db)); diff --git a/include/sqlite_orm/sqlite_orm.h b/include/sqlite_orm/sqlite_orm.h index eea07cf38..9c75e6c5a 100644 --- a/include/sqlite_orm/sqlite_orm.h +++ b/include/sqlite_orm/sqlite_orm.h @@ -10393,13 +10393,13 @@ namespace sqlite_orm { }; template - std::string serialize_get_all_impl(const T &getQuery, const C &context) { + std::string serialize_get_all_impl(const T &get, const C &context) { using primary_type = typename T::type; table_name_collector collector; collector.table_names.insert( std::make_pair(context.impl.find_table_name(typeid(primary_type)), std::string{})); - iterate_ast(getQuery.conditions, collector); + iterate_ast(get.conditions, collector); std::stringstream ss; ss << "SELECT "; auto &tImpl = context.impl.template get_impl(); @@ -10427,7 +10427,7 @@ namespace sqlite_orm { } ss << " "; } - iterate_tuple(getQuery.conditions, [&context, &ss](auto &v) { + iterate_tuple(get.conditions, [&context, &ss](auto &v) { ss << serialize(v, context); }); return ss.str(); @@ -10465,6 +10465,68 @@ namespace sqlite_orm { } }; + template + std::string serialize_get_impl(const T &, const C &context) { + using primary_type = typename T::type; + auto &tImpl = context.impl.template get_impl(); + std::stringstream ss; + ss << "SELECT "; + auto columnNames = tImpl.table.column_names(); + for(size_t i = 0; i < columnNames.size(); ++i) { + ss << "\"" << columnNames[i] << "\""; + if(i < columnNames.size() - 1) { + ss << ","; + } + ss << " "; + } + ss << "FROM '" << tImpl.table.name << "' WHERE "; + auto primaryKeyColumnNames = tImpl.table.primary_key_column_names(); + if(!primaryKeyColumnNames.empty()) { + for(size_t i = 0; i < primaryKeyColumnNames.size(); ++i) { + ss << "\"" << primaryKeyColumnNames[i] << "\"" + << " = ? "; + if(i < primaryKeyColumnNames.size() - 1) { + ss << "AND"; + } + ss << ' '; + } + return ss.str(); + } else { + throw std::system_error(std::make_error_code(orm_error_code::table_has_no_primary_key_column)); + } + } + + template + struct statement_serializator, void> { + using statement_type = get_t; + + template + std::string operator()(const statement_type &get, const C &context) const { + return serialize_get_impl(get, context); + } + }; + + template + struct statement_serializator, void> { + using statement_type = get_pointer_t; + + template + std::string operator()(const statement_type &get, const C &context) const { + return serialize_get_impl(get, context); + } + }; + +#ifdef SQLITE_ORM_OPTIONAL_SUPPORTED + template + struct statement_serializator, void> { + using statement_type = get_optional_t; + + template + std::string operator()(const statement_type &get, const C &context) const { + return serialize_get_impl(get, context); + } + }; +#endif // SQLITE_ORM_OPTIONAL_SUPPORTED template struct statement_serializator, void> { using statement_type = select_t; @@ -10896,54 +10958,6 @@ namespace sqlite_orm { return this->impl.template get_impl(); } - // Common code for statements with conditions: get_t, get_pointer_t, get_optional_t. - template - std::string string_from_expression_impl_get(bool /*noTableName*/) const { - auto &tImpl = this->get_impl(); - std::stringstream ss; - ss << "SELECT "; - auto columnNames = tImpl.table.column_names(); - for(size_t i = 0; i < columnNames.size(); ++i) { - ss << "\"" << columnNames[i] << "\""; - if(i < columnNames.size() - 1) { - ss << ","; - } - ss << " "; - } - ss << "FROM '" << tImpl.table.name << "' WHERE "; - auto primaryKeyColumnNames = tImpl.table.primary_key_column_names(); - if(!primaryKeyColumnNames.empty()) { - for(size_t i = 0; i < primaryKeyColumnNames.size(); ++i) { - ss << "\"" << primaryKeyColumnNames[i] << "\"" - << " = ? "; - if(i < primaryKeyColumnNames.size() - 1) { - ss << "AND "; - } - ss << ' '; - } - return ss.str(); - } else { - throw std::system_error(std::make_error_code(orm_error_code::table_has_no_primary_key_column)); - } - } - - template - std::string string_from_expression(const get_t &, bool noTableName) const { - return this->string_from_expression_impl_get(noTableName); - } - - template - std::string string_from_expression(const get_pointer_t &, bool noTableName) const { - return this->string_from_expression_impl_get(noTableName); - } - -#ifdef SQLITE_ORM_OPTIONAL_SUPPORTED - template - std::string string_from_expression(const get_optional_t &, bool noTableName) const { - return this->string_from_expression_impl_get(noTableName); - } -#endif // SQLITE_ORM_OPTIONAL_SUPPORTED - public: template view_t iterate(Args &&... args) { @@ -11621,13 +11635,17 @@ namespace sqlite_orm { } template - prepared_statement_t> prepare(get_t g) { + prepared_statement_t> prepare(get_t get) { auto con = this->get_connection(); sqlite3_stmt *stmt; auto db = con.get(); - auto query = this->string_from_expression(g, false); + using context_t = serializator_context; + context_t context{this->impl}; + context.skip_table_name = false; + context.replace_bindable_with_question = true; + auto query = serialize(get, context); if(sqlite3_prepare_v2(db, query.c_str(), -1, &stmt, nullptr) == SQLITE_OK) { - return {std::move(g), stmt, con}; + return {std::move(get), stmt, con}; } else { throw std::system_error(std::error_code(sqlite3_errcode(db), get_sqlite_error_category()), sqlite3_errmsg(db)); @@ -11635,13 +11653,17 @@ namespace sqlite_orm { } template - prepared_statement_t> prepare(get_pointer_t g) { + prepared_statement_t> prepare(get_pointer_t get) { auto con = this->get_connection(); sqlite3_stmt *stmt; auto db = con.get(); - auto query = this->string_from_expression(g, false); + using context_t = serializator_context; + context_t context{this->impl}; + context.skip_table_name = false; + context.replace_bindable_with_question = true; + auto query = serialize(get, context); if(sqlite3_prepare_v2(db, query.c_str(), -1, &stmt, nullptr) == SQLITE_OK) { - return {std::move(g), stmt, con}; + return {std::move(get), stmt, con}; } else { throw std::system_error(std::error_code(sqlite3_errcode(db), get_sqlite_error_category()), sqlite3_errmsg(db)); @@ -11650,13 +11672,17 @@ namespace sqlite_orm { #ifdef SQLITE_ORM_OPTIONAL_SUPPORTED template - prepared_statement_t> prepare(get_optional_t g) { + prepared_statement_t> prepare(get_optional_t get) { auto con = this->get_connection(); sqlite3_stmt *stmt; auto db = con.get(); - auto query = this->string_from_expression(g, false); + using context_t = serializator_context; + context_t context{this->impl}; + context.skip_table_name = false; + context.replace_bindable_with_question = true; + auto query = serialize(get, context); if(sqlite3_prepare_v2(db, query.c_str(), -1, &stmt, nullptr) == SQLITE_OK) { - return {std::move(g), stmt, con}; + return {std::move(get), stmt, con}; } else { throw std::system_error(std::error_code(sqlite3_errcode(db), get_sqlite_error_category()), sqlite3_errmsg(db)); From a791d7d0df0a02a9d44ed05f197f586762b15641 Mon Sep 17 00:00:00 2001 From: fnc12 Date: Sun, 24 May 2020 14:13:05 +0300 Subject: [PATCH 079/132] added object_t, refactored extract lambda and created mapped row extractor --- dev/column_names_getter.h | 13 + dev/column_result.h | 5 + dev/iterator.h | 14 +- dev/mapped_row_extractor.h | 37 ++ dev/object_from_column_builder.h | 41 +++ dev/row_extractor.h | 44 +-- dev/row_extractor_builder.h | 43 +++ dev/select_constraints.h | 24 ++ dev/static_magic.h | 14 +- dev/storage.h | 88 ++--- dev/storage_impl.h | 15 + dev/table_name_collector.h | 8 + include/sqlite_orm/sqlite_orm.h | 344 ++++++++++++------ tests/CMakeLists.txt | 2 +- .../get_all_pointer.cpp | 6 +- .../prepared_common.h | 5 + tests/select_asterisk.cpp | 75 ++++ tests/tests2.cpp | 52 --- 18 files changed, 533 insertions(+), 297 deletions(-) create mode 100644 dev/mapped_row_extractor.h create mode 100644 dev/object_from_column_builder.h create mode 100644 dev/row_extractor_builder.h create mode 100644 tests/select_asterisk.cpp diff --git a/dev/column_names_getter.h b/dev/column_names_getter.h index 72f4f4f76..26e43481c 100644 --- a/dev/column_names_getter.h +++ b/dev/column_names_getter.h @@ -46,6 +46,7 @@ namespace sqlite_orm { return get_column_names(expression.get(), context); } }; + template struct column_names_getter, void> { using expression_type = asterisk_t; @@ -58,6 +59,18 @@ namespace sqlite_orm { } }; + template + struct column_names_getter, void> { + using expression_type = object_t; + + template + std::vector operator()(const expression_type &, const C &) { + std::vector res; + res.push_back("*"); + return res; + } + }; + template struct column_names_getter, void> { using expression_type = columns_t; diff --git a/dev/column_result.h b/dev/column_result.h index 65f2086b6..37f4930c3 100644 --- a/dev/column_result.h +++ b/dev/column_result.h @@ -223,6 +223,11 @@ namespace sqlite_orm { using type = typename storage_traits::storage_mapped_columns::type; }; + template + struct column_result_t, void> { + using type = T; + }; + template struct column_result_t, void> { using type = T; diff --git a/dev/iterator.h b/dev/iterator.h index 8451d1697..187d082e9 100644 --- a/dev/iterator.h +++ b/dev/iterator.h @@ -12,6 +12,7 @@ #include "row_extractor.h" #include "statement_finalizer.h" #include "error_code.h" +#include "object_from_column_builder.h" namespace sqlite_orm { @@ -42,17 +43,8 @@ namespace sqlite_orm { temp = std::make_unique(); auto &storage = this->view.storage; auto &impl = storage.template get_impl(); - auto index = 0; - impl.table.for_each_column([&index, &temp, this](auto &c) { - using field_type = typename std::decay::type::field_type; - auto value = row_extractor().extract(*this->stmt, index++); - if(c.member_pointer) { - auto member_pointer = c.member_pointer; - (*temp).*member_pointer = std::move(value); - } else { - ((*temp).*(c.setter))(std::move(value)); - } - }); + object_from_column_builder builder{*temp, *this->stmt}; + impl.table.for_each_column(builder); } public: diff --git a/dev/mapped_row_extractor.h b/dev/mapped_row_extractor.h new file mode 100644 index 000000000..5a50e7d14 --- /dev/null +++ b/dev/mapped_row_extractor.h @@ -0,0 +1,37 @@ +#pragma once + +#include + +#include "object_from_column_builder.h" + +namespace sqlite_orm { + + namespace internal { + + /** + * This is a private row extractor class. It is used for extracting rows as objects instead of tuple. + * Main difference from regular `row_extractor` is that this class takes table info which is required + * for constructing objects by member pointers. To construct please use `row_extractor_builder` class + * Type arguments: + * V is value type just like regular `row_extractor` has + * T is table info class `table_t` + */ + template + struct mapped_row_extractor { + using table_info_t = T; + + mapped_row_extractor(const table_info_t &tableInfo_) : tableInfo(tableInfo_) {} + + V extract(sqlite3_stmt *stmt, int /*columnIndex*/) { + V res; + object_from_column_builder builder{res, stmt}; + this->tableInfo.for_each_column(builder); + return res; + } + + const table_info_t &tableInfo; + }; + + } + +} diff --git a/dev/object_from_column_builder.h b/dev/object_from_column_builder.h new file mode 100644 index 000000000..27cc5e9c9 --- /dev/null +++ b/dev/object_from_column_builder.h @@ -0,0 +1,41 @@ +#pragma once + +#include + +#include "row_extractor.h" + +namespace sqlite_orm { + + namespace internal { + + struct object_from_column_builder_base { + sqlite3_stmt *stmt = nullptr; + mutable int index = 0; + }; + + /** + * This is a cute lambda replacement which is used in several places. + */ + template + struct object_from_column_builder : object_from_column_builder_base { + using object_type = O; + + object_type &object; + + object_from_column_builder(object_type &object_, sqlite3_stmt *stmt_) : + object_from_column_builder_base{stmt_}, object(object_) {} + + template + void operator()(const C &c) const { + using field_type = typename C::field_type; + auto value = row_extractor().extract(this->stmt, this->index++); + if(c.member_pointer) { + this->object.*c.member_pointer = std::move(value); + } else { + ((this->object).*(c.setter))(std::move(value)); + } + } + }; + + } +} diff --git a/dev/row_extractor.h b/dev/row_extractor.h index 2108415e3..41027d0ee 100644 --- a/dev/row_extractor.h +++ b/dev/row_extractor.h @@ -77,8 +77,8 @@ namespace sqlite_orm { /** * Specialization for std::string. */ - template - struct row_extractor::value>> { + template<> + struct row_extractor { std::string extract(const char *row_value) { if(row_value) { return row_value; @@ -100,8 +100,8 @@ namespace sqlite_orm { /** * Specialization for std::wstring. */ - template - struct row_extractor::value>> { + template<> + struct row_extractor { std::wstring extract(const char *row_value) { if(row_value) { std::wstring_convert> converter; @@ -122,38 +122,6 @@ namespace sqlite_orm { } }; #endif // SQLITE_ORM_OMITS_CODECVT - /** - * Specialization for std::vector. - */ - template - struct row_extractor>::value>> { - std::vector extract(const char *row_value) { - if(row_value) { - auto len = ::strlen(row_value); - return this->go(row_value, len); - } else { - return {}; - } - } - - std::vector extract(sqlite3_stmt *stmt, int columnIndex) { - auto bytes = static_cast(sqlite3_column_blob(stmt, columnIndex)); - auto len = sqlite3_column_bytes(stmt, columnIndex); - return this->go(bytes, len); - } - - protected: - std::vector go(const char *bytes, size_t len) { - if(len) { - std::vector res; - res.reserve(len); - std::copy(bytes, bytes + len, std::back_inserter(res)); - return res; - } else { - return {}; - } - } - }; template struct row_extractor::value>> { @@ -277,8 +245,8 @@ namespace sqlite_orm { /** * Specialization for journal_mode. */ - template - struct row_extractor::value>> { + template<> + struct row_extractor { journal_mode extract(const char *row_value) { if(row_value) { if(auto res = internal::journal_mode_from_string(row_value)) { diff --git a/dev/row_extractor_builder.h b/dev/row_extractor_builder.h new file mode 100644 index 000000000..20c20b764 --- /dev/null +++ b/dev/row_extractor_builder.h @@ -0,0 +1,43 @@ +#pragma once + +#include "row_extractor.h" +#include "mapped_row_extractor.h" + +namespace sqlite_orm { + + namespace internal { + + /** + * This builder is used to construct different row extractors depending on type. + * It has two specializations: for mapped to storage types (e.g. User, Visit etc) and + * for non-mapped (e.g. std::string, QString, int etc). For non mapped its operator() returns + * generic `row_extractor`, for mapped it returns `mapped_row_extractor` instance. + */ + template + struct row_extractor_builder; + + template + struct row_extractor_builder { + + row_extractor operator()(const I * /*tableInfo*/) const { + return {}; + } + }; + + template + struct row_extractor_builder { + + mapped_row_extractor operator()(const I *tableInfo) const { + return {*tableInfo}; + } + }; + + template + auto make_row_extractor(const I *tableInfo) { + using builder_t = row_extractor_builder; + return builder_t{}(tableInfo); + } + + } + +} diff --git a/dev/select_constraints.h b/dev/select_constraints.h index bb3ad1900..12c18792c 100644 --- a/dev/select_constraints.h +++ b/dev/select_constraints.h @@ -179,6 +179,11 @@ namespace sqlite_orm { using type = T; }; + template + struct object_t { + using type = T; + }; + template struct then_t { using expression_type = T; @@ -347,8 +352,27 @@ namespace sqlite_orm { return {std::move(lhs), std::move(rhs), true}; } + /** + * SELECT * FROM T function. + * T is typed mapped to a storage. + * Example: auto rows = storage.select(asterisk()); + * // decltype(rows) is std::vector> + * If you need to fetch result as objects not tuple please use `object` instead. + */ template internal::asterisk_t asterisk() { return {}; } + + /** + * SELECT * FROM T function. + * T is typed mapped to a storage. + * Example: auto rows = storage.select(object()); + * // decltype(rows) is std::vector + * If you need to fetch result as tuples not objects please use `asterisk` instead. + */ + template + internal::object_t object() { + return {}; + } } diff --git a/dev/static_magic.h b/dev/static_magic.h index 96187120e..8aad18bfb 100644 --- a/dev/static_magic.h +++ b/dev/static_magic.h @@ -9,22 +9,22 @@ namespace sqlite_orm { namespace internal { template - auto static_if(std::true_type, T t, F) { - return std::move(t); + decltype(auto) static_if(std::true_type, const T &t, const F &) { + return (t); } template - auto static_if(std::false_type, T, F f) { - return std::move(f); + decltype(auto) static_if(std::false_type, const T &, const F &f) { + return (f); } template - auto static_if(T t, F f) { - return static_if(std::integral_constant{}, std::move(t), std::move(f)); + decltype(auto) static_if(const T &t, const F &f) { + return static_if(std::integral_constant{}, t, f); } template - auto static_if(T t) { + decltype(auto) static_if(const T &t) { return static_if(std::integral_constant{}, t, [](auto &&...) {}); } diff --git a/dev/storage.h b/dev/storage.h index d1ab194d7..e24348abe 100644 --- a/dev/storage.h +++ b/dev/storage.h @@ -19,7 +19,7 @@ #endif // SQLITE_ORM_OPTIONAL_SUPPORTED #include "alias.h" -#include "row_extractor.h" +#include "row_extractor_builder.h" #include "error_code.h" #include "type_printer.h" #include "tuple_helper.h" @@ -47,6 +47,7 @@ #include "expression_object_type.h" #include "statement_serializator.h" #include "table_name_collector.h" +#include "object_from_column_builder.h" namespace sqlite_orm { @@ -1327,16 +1328,8 @@ namespace sqlite_orm { switch(stepRes) { case SQLITE_ROW: { auto res = std::make_unique(); - index = 0; - tImpl.table.for_each_column([&index, &res, stmt](auto &c) { - using field_type = typename std::decay::type::field_type; - auto value = row_extractor().extract(stmt, index++); - if(c.member_pointer) { - (*res).*c.member_pointer = std::move(value); - } else { - ((*res).*(c.setter))(std::move(value)); - } - }); + object_from_column_builder builder{*res, stmt}; + tImpl.table.for_each_column(builder); return res; } break; case SQLITE_DONE: { @@ -1369,16 +1362,8 @@ namespace sqlite_orm { switch(stepRes) { case SQLITE_ROW: { auto res = std::make_optional(); - index = 0; - tImpl.table.for_each_column([&index, &res, stmt](auto &c) { - using field_type = typename std::decay::type::field_type; - auto value = row_extractor().extract(stmt, index++); - if(c.member_pointer) { - (*res).*c.member_pointer = std::move(value); - } else { - ((*res).*(c.setter))(std::move(value)); - } - }); + object_from_column_builder builder{res.value(), stmt}; + tImpl.table.for_each_column(builder); return res; } break; case SQLITE_DONE: { @@ -1411,17 +1396,8 @@ namespace sqlite_orm { switch(stepRes) { case SQLITE_ROW: { T res; - index = 0; - tImpl.table.for_each_column([&index, &res, stmt](auto &c) { - using column_type = typename std::decay::type; - using field_type = typename column_type::field_type; - auto value = row_extractor().extract(stmt, index++); - if(c.member_pointer) { - res.*c.member_pointer = std::move(value); - } else { - ((res).*(c.setter))(std::move(value)); - } - }); + object_from_column_builder builder{res, stmt}; + tImpl.table.for_each_column(builder); return res; } break; case SQLITE_DONE: { @@ -1506,12 +1482,18 @@ namespace sqlite_orm { } }); std::vector res; + auto tableInfoPointer = this->impl.template find_table(); int stepRes; do { stepRes = sqlite3_step(stmt); switch(stepRes) { case SQLITE_ROW: { - res.push_back(row_extractor().extract(stmt, 0)); + using table_info_pointer_t = typename std::remove_pointer::type; + using table_info_t = typename std::decay::type; + row_extractor_builder::value, table_info_t> + builder; + auto rowExtractor = builder(tableInfoPointer); + res.push_back(rowExtractor.extract(stmt, 0)); } break; case SQLITE_DONE: break; @@ -1547,16 +1529,8 @@ namespace sqlite_orm { switch(stepRes) { case SQLITE_ROW: { T obj; - index = 0; - tImpl.table.for_each_column([&index, &obj, stmt](auto &c) { - using field_type = typename std::decay::type::field_type; - auto value = row_extractor().extract(stmt, index++); - if(c.member_pointer) { - obj.*c.member_pointer = std::move(value); - } else { - ((obj).*(c.setter))(std::move(value)); - } - }); + object_from_column_builder builder{obj, stmt}; + tImpl.table.for_each_column(builder); res.push_back(std::move(obj)); } break; case SQLITE_DONE: @@ -1593,17 +1567,9 @@ namespace sqlite_orm { switch(stepRes) { case SQLITE_ROW: { auto obj = std::make_unique(); - index = 0; - tImpl.table.for_each_column([&index, &obj, stmt](auto &c) { - using field_type = typename std::decay::type::field_type; - auto value = row_extractor().extract(stmt, index++); - if(c.member_pointer) { - (*obj).*c.member_pointer = std::move(value); - } else { - ((*obj).*(c.setter))(std::move(value)); - } - }); - res.push_back(std::move(obj)); + object_from_column_builder builder{*obj, stmt}; + tImpl.table.for_each_column(builder); + res.push_back(move(obj)); } break; case SQLITE_DONE: break; @@ -1640,17 +1606,9 @@ namespace sqlite_orm { switch(stepRes) { case SQLITE_ROW: { auto obj = std::make_optional(); - index = 0; - tImpl.table.for_each_column([&index, &obj, stmt](auto &c) { - using field_type = typename std::decay::type::field_type; - auto value = row_extractor().extract(stmt, index++); - if(c.member_pointer) { - (*obj).*c.member_pointer = std::move(value); - } else { - ((*obj).*(c.setter))(std::move(value)); - } - }); - res.push_back(std::move(obj)); + object_from_column_builder builder{*obj, stmt}; + tImpl.table.for_each_column(builder); + res.push_back(move(obj)); } break; case SQLITE_DONE: break; diff --git a/dev/storage_impl.h b/dev/storage_impl.h index 94cd0aead..91130b7e3 100644 --- a/dev/storage_impl.h +++ b/dev/storage_impl.h @@ -243,6 +243,16 @@ namespace sqlite_orm { return this->super::template get_impl(); } + template + auto *find_table(typename std::enable_if::value>::type * = nullptr) const { + return &this->table; + } + + template + auto *find_table(typename std::enable_if::value>::type * = nullptr) const { + return this->super::template find_table(); + } + std::string find_table_name(std::type_index ti) const { std::type_index thisTypeIndex{typeid(typename H::object_type)}; if(thisTypeIndex == ti) { @@ -449,6 +459,11 @@ namespace sqlite_orm { std::string dump(const O &, sqlite3 *, std::nullptr_t) { throw std::system_error(std::make_error_code(orm_error_code::type_is_not_mapped_to_storage)); } + + template + const void *find_table() const { + return nullptr; + } }; template diff --git a/dev/table_name_collector.h b/dev/table_name_collector.h index 06298c66b..20cf1a857 100644 --- a/dev/table_name_collector.h +++ b/dev/table_name_collector.h @@ -61,6 +61,14 @@ namespace sqlite_orm { table_names.insert(std::make_pair(move(tableName), "")); } } + + template + void operator()(const object_t &) const { + if(this->find_table_name) { + auto tableName = this->find_table_name(typeid(T)); + table_names.insert(std::make_pair(move(tableName), "")); + } + } }; } diff --git a/include/sqlite_orm/sqlite_orm.h b/include/sqlite_orm/sqlite_orm.h index 9c75e6c5a..5a3801018 100644 --- a/include/sqlite_orm/sqlite_orm.h +++ b/include/sqlite_orm/sqlite_orm.h @@ -233,22 +233,22 @@ namespace sqlite_orm { namespace internal { template - auto static_if(std::true_type, T t, F) { - return std::move(t); + decltype(auto) static_if(std::true_type, const T &t, const F &) { + return (t); } template - auto static_if(std::false_type, T, F f) { - return std::move(f); + decltype(auto) static_if(std::false_type, const T &, const F &f) { + return (f); } template - auto static_if(T t, F f) { - return static_if(std::integral_constant{}, std::move(t), std::move(f)); + decltype(auto) static_if(const T &t, const F &f) { + return static_if(std::integral_constant{}, t, f); } template - auto static_if(T t) { + decltype(auto) static_if(const T &t) { return static_if(std::integral_constant{}, t, [](auto &&...) {}); } @@ -4450,6 +4450,11 @@ namespace sqlite_orm { using type = T; }; + template + struct object_t { + using type = T; + }; + template struct then_t { using expression_type = T; @@ -4618,10 +4623,29 @@ namespace sqlite_orm { return {std::move(lhs), std::move(rhs), true}; } + /** + * SELECT * FROM T function. + * T is typed mapped to a storage. + * Example: auto rows = storage.select(asterisk()); + * // decltype(rows) is std::vector> + * If you need to fetch result as objects not tuple please use `object` instead. + */ template internal::asterisk_t asterisk() { return {}; } + + /** + * SELECT * FROM T function. + * T is typed mapped to a storage. + * Example: auto rows = storage.select(object()); + * // decltype(rows) is std::vector + * If you need to fetch result as tuples not objects please use `asterisk` instead. + */ + template + internal::object_t object() { + return {}; + } } #pragma once @@ -5096,8 +5120,8 @@ namespace sqlite_orm { /** * Specialization for std::string. */ - template - struct row_extractor::value>> { + template<> + struct row_extractor { std::string extract(const char *row_value) { if(row_value) { return row_value; @@ -5119,8 +5143,8 @@ namespace sqlite_orm { /** * Specialization for std::wstring. */ - template - struct row_extractor::value>> { + template<> + struct row_extractor { std::wstring extract(const char *row_value) { if(row_value) { std::wstring_convert> converter; @@ -5141,38 +5165,6 @@ namespace sqlite_orm { } }; #endif // SQLITE_ORM_OMITS_CODECVT - /** - * Specialization for std::vector. - */ - template - struct row_extractor>::value>> { - std::vector extract(const char *row_value) { - if(row_value) { - auto len = ::strlen(row_value); - return this->go(row_value, len); - } else { - return {}; - } - } - - std::vector extract(sqlite3_stmt *stmt, int columnIndex) { - auto bytes = static_cast(sqlite3_column_blob(stmt, columnIndex)); - auto len = sqlite3_column_bytes(stmt, columnIndex); - return this->go(bytes, len); - } - - protected: - std::vector go(const char *bytes, size_t len) { - if(len) { - std::vector res; - res.reserve(len); - std::copy(bytes, bytes + len, std::back_inserter(res)); - return res; - } else { - return {}; - } - } - }; template struct row_extractor::value>> { @@ -5296,8 +5288,8 @@ namespace sqlite_orm { /** * Specialization for journal_mode. */ - template - struct row_extractor::value>> { + template<> + struct row_extractor { journal_mode extract(const char *row_value) { if(row_value) { if(auto res = internal::journal_mode_from_string(row_value)) { @@ -5869,6 +5861,11 @@ namespace sqlite_orm { using type = typename storage_traits::storage_mapped_columns::type; }; + template + struct column_result_t, void> { + using type = T; + }; + template struct column_result_t, void> { using type = T; @@ -6467,6 +6464,16 @@ namespace sqlite_orm { return this->super::template get_impl(); } + template + auto *find_table(typename std::enable_if::value>::type * = nullptr) const { + return &this->table; + } + + template + auto *find_table(typename std::enable_if::value>::type * = nullptr) const { + return this->super::template find_table(); + } + std::string find_table_name(std::type_index ti) const { std::type_index thisTypeIndex{typeid(typename H::object_type)}; if(thisTypeIndex == ti) { @@ -6673,6 +6680,11 @@ namespace sqlite_orm { std::string dump(const O &, sqlite3 *, std::nullptr_t) { throw std::system_error(std::make_error_code(orm_error_code::type_is_not_mapped_to_storage)); } + + template + const void *find_table() const { + return nullptr; + } }; template @@ -6704,8 +6716,127 @@ namespace sqlite_orm { // #include "alias.h" +// #include "row_extractor_builder.h" + // #include "row_extractor.h" +// #include "mapped_row_extractor.h" + +#include + +// #include "object_from_column_builder.h" + +#include + +// #include "row_extractor.h" + +namespace sqlite_orm { + + namespace internal { + + struct object_from_column_builder_base { + sqlite3_stmt *stmt = nullptr; + mutable int index = 0; + }; + + /** + * This is a cute lambda replacement which is used in several places. + */ + template + struct object_from_column_builder : object_from_column_builder_base { + using object_type = O; + + object_type &object; + + object_from_column_builder(object_type &object_, sqlite3_stmt *stmt_) : + object_from_column_builder_base{stmt_}, object(object_) {} + + template + void operator()(const C &c) const { + using field_type = typename C::field_type; + auto value = row_extractor().extract(this->stmt, this->index++); + if(c.member_pointer) { + this->object.*c.member_pointer = std::move(value); + } else { + ((this->object).*(c.setter))(std::move(value)); + } + } + }; + + } +} + +namespace sqlite_orm { + + namespace internal { + + /** + * This is a private row extractor class. It is used for extracting rows as objects instead of tuple. + * Main difference from regular `row_extractor` is that this class takes table info which is required + * for constructing objects by member pointers. To construct please use `row_extractor_builder` class + * Type arguments: + * V is value type just like regular `row_extractor` has + * T is table info class `table_t` + */ + template + struct mapped_row_extractor { + using table_info_t = T; + + mapped_row_extractor(const table_info_t &tableInfo_) : tableInfo(tableInfo_) {} + + V extract(sqlite3_stmt *stmt, int /*columnIndex*/) { + V res; + object_from_column_builder builder{res, stmt}; + this->tableInfo.for_each_column(builder); + return res; + } + + const table_info_t &tableInfo; + }; + + } + +} + +namespace sqlite_orm { + + namespace internal { + + /** + * This builder is used to construct different row extractors depending on type. + * It has two specializations: for mapped to storage types (e.g. User, Visit etc) and + * for non-mapped (e.g. std::string, QString, int etc). For non mapped its operator() returns + * generic `row_extractor`, for mapped it returns `mapped_row_extractor` instance. + */ + template + struct row_extractor_builder; + + template + struct row_extractor_builder { + + row_extractor operator()(const I * /*tableInfo*/) const { + return {}; + } + }; + + template + struct row_extractor_builder { + + mapped_row_extractor operator()(const I *tableInfo) const { + return {*tableInfo}; + } + }; + + template + auto make_row_extractor(const I *tableInfo) { + using builder_t = row_extractor_builder; + return builder_t{}(tableInfo); + } + + } + +} + // #include "error_code.h" // #include "type_printer.h" @@ -6778,6 +6909,8 @@ namespace sqlite_orm { // #include "error_code.h" +// #include "object_from_column_builder.h" + namespace sqlite_orm { namespace internal { @@ -6807,17 +6940,8 @@ namespace sqlite_orm { temp = std::make_unique(); auto &storage = this->view.storage; auto &impl = storage.template get_impl(); - auto index = 0; - impl.table.for_each_column([&index, &temp, this](auto &c) { - using field_type = typename std::decay::type::field_type; - auto value = row_extractor().extract(*this->stmt, index++); - if(c.member_pointer) { - auto member_pointer = c.member_pointer; - (*temp).*member_pointer = std::move(value); - } else { - ((*temp).*(c.setter))(std::move(value)); - } - }); + object_from_column_builder builder{*temp, *this->stmt}; + impl.table.for_each_column(builder); } public: @@ -9123,6 +9247,14 @@ namespace sqlite_orm { table_names.insert(std::make_pair(move(tableName), "")); } } + + template + void operator()(const object_t &) const { + if(this->find_table_name) { + auto tableName = this->find_table_name(typeid(T)); + table_names.insert(std::make_pair(move(tableName), "")); + } + } }; } @@ -9178,6 +9310,7 @@ namespace sqlite_orm { return get_column_names(expression.get(), context); } }; + template struct column_names_getter, void> { using expression_type = asterisk_t; @@ -9190,6 +9323,18 @@ namespace sqlite_orm { } }; + template + struct column_names_getter, void> { + using expression_type = object_t; + + template + std::vector operator()(const expression_type &, const C &) { + std::vector res; + res.push_back("*"); + return res; + } + }; + template struct column_names_getter, void> { using expression_type = columns_t; @@ -10846,6 +10991,8 @@ namespace sqlite_orm { // #include "table_name_collector.h" +// #include "object_from_column_builder.h" + namespace sqlite_orm { namespace internal { @@ -12125,16 +12272,8 @@ namespace sqlite_orm { switch(stepRes) { case SQLITE_ROW: { auto res = std::make_unique(); - index = 0; - tImpl.table.for_each_column([&index, &res, stmt](auto &c) { - using field_type = typename std::decay::type::field_type; - auto value = row_extractor().extract(stmt, index++); - if(c.member_pointer) { - (*res).*c.member_pointer = std::move(value); - } else { - ((*res).*(c.setter))(std::move(value)); - } - }); + object_from_column_builder builder{*res, stmt}; + tImpl.table.for_each_column(builder); return res; } break; case SQLITE_DONE: { @@ -12167,16 +12306,8 @@ namespace sqlite_orm { switch(stepRes) { case SQLITE_ROW: { auto res = std::make_optional(); - index = 0; - tImpl.table.for_each_column([&index, &res, stmt](auto &c) { - using field_type = typename std::decay::type::field_type; - auto value = row_extractor().extract(stmt, index++); - if(c.member_pointer) { - (*res).*c.member_pointer = std::move(value); - } else { - ((*res).*(c.setter))(std::move(value)); - } - }); + object_from_column_builder builder{res.value(), stmt}; + tImpl.table.for_each_column(builder); return res; } break; case SQLITE_DONE: { @@ -12209,17 +12340,8 @@ namespace sqlite_orm { switch(stepRes) { case SQLITE_ROW: { T res; - index = 0; - tImpl.table.for_each_column([&index, &res, stmt](auto &c) { - using column_type = typename std::decay::type; - using field_type = typename column_type::field_type; - auto value = row_extractor().extract(stmt, index++); - if(c.member_pointer) { - res.*c.member_pointer = std::move(value); - } else { - ((res).*(c.setter))(std::move(value)); - } - }); + object_from_column_builder builder{res, stmt}; + tImpl.table.for_each_column(builder); return res; } break; case SQLITE_DONE: { @@ -12304,12 +12426,18 @@ namespace sqlite_orm { } }); std::vector res; + auto tableInfoPointer = this->impl.template find_table(); int stepRes; do { stepRes = sqlite3_step(stmt); switch(stepRes) { case SQLITE_ROW: { - res.push_back(row_extractor().extract(stmt, 0)); + using table_info_pointer_t = typename std::remove_pointer::type; + using table_info_t = typename std::decay::type; + row_extractor_builder::value, table_info_t> + builder; + auto rowExtractor = builder(tableInfoPointer); + res.push_back(rowExtractor.extract(stmt, 0)); } break; case SQLITE_DONE: break; @@ -12345,16 +12473,8 @@ namespace sqlite_orm { switch(stepRes) { case SQLITE_ROW: { T obj; - index = 0; - tImpl.table.for_each_column([&index, &obj, stmt](auto &c) { - using field_type = typename std::decay::type::field_type; - auto value = row_extractor().extract(stmt, index++); - if(c.member_pointer) { - obj.*c.member_pointer = std::move(value); - } else { - ((obj).*(c.setter))(std::move(value)); - } - }); + object_from_column_builder builder{obj, stmt}; + tImpl.table.for_each_column(builder); res.push_back(std::move(obj)); } break; case SQLITE_DONE: @@ -12391,17 +12511,9 @@ namespace sqlite_orm { switch(stepRes) { case SQLITE_ROW: { auto obj = std::make_unique(); - index = 0; - tImpl.table.for_each_column([&index, &obj, stmt](auto &c) { - using field_type = typename std::decay::type::field_type; - auto value = row_extractor().extract(stmt, index++); - if(c.member_pointer) { - (*obj).*c.member_pointer = std::move(value); - } else { - ((*obj).*(c.setter))(std::move(value)); - } - }); - res.push_back(std::move(obj)); + object_from_column_builder builder{*obj, stmt}; + tImpl.table.for_each_column(builder); + res.push_back(move(obj)); } break; case SQLITE_DONE: break; @@ -12438,17 +12550,9 @@ namespace sqlite_orm { switch(stepRes) { case SQLITE_ROW: { auto obj = std::make_optional(); - index = 0; - tImpl.table.for_each_column([&index, &obj, stmt](auto &c) { - using field_type = typename std::decay::type::field_type; - auto value = row_extractor().extract(stmt, index++); - if(c.member_pointer) { - (*obj).*c.member_pointer = std::move(value); - } else { - ((*obj).*(c.setter))(std::move(value)); - } - }); - res.push_back(std::move(obj)); + object_from_column_builder builder{*obj, stmt}; + tImpl.table.for_each_column(builder); + res.push_back(move(obj)); } break; case SQLITE_DONE: break; diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 67f7030fc..28e700753 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -10,7 +10,7 @@ else() add_subdirectory(third_party/sqlite) endif() -add_executable(unit_tests tests.cpp tests2.cpp tests3.cpp tests4.cpp tests5.cpp private_getters_tests.cpp pragma_tests.cpp explicit_columns.cpp core_functions_tests.cpp constraints/composite_key.cpp static_tests.cpp operators/arithmetic_operators.cpp operators/like.cpp operators/glob.cpp operators/in.cpp operators/cast.cpp operators/is_null.cpp operators/not_operator.cpp operators/bitwise.cpp dynamic_order_by.cpp prepared_statement_tests/select.cpp prepared_statement_tests/get_all.cpp prepared_statement_tests/get_all_pointer.cpp prepared_statement_tests/get_all_optional.cpp prepared_statement_tests/update_all.cpp prepared_statement_tests/remove_all.cpp prepared_statement_tests/get.cpp prepared_statement_tests/get_pointer.cpp prepared_statement_tests/get_optional.cpp prepared_statement_tests/update.cpp prepared_statement_tests/remove.cpp prepared_statement_tests/insert.cpp prepared_statement_tests/replace.cpp prepared_statement_tests/insert_range.cpp prepared_statement_tests/replace_range.cpp prepared_statement_tests/insert_explicit.cpp pragma_tests.cpp simple_query.cpp static_tests/is_bindable.cpp static_tests/arithmetic_operators_result_type.cpp static_tests/tuple_conc.cpp static_tests/node_tuple.cpp static_tests/bindable_filter.cpp static_tests/count_tuple.cpp static_tests/member_traits_tests.cpp static_tests/select_return_type.cpp constraints/default.cpp constraints/foreign_key.cpp constraints/check.cpp table_tests.cpp statement_serializator_tests/primary_key.cpp statement_serializator_tests/column_names.cpp statement_serializator_tests/autoincrement.cpp statement_serializator_tests/arithmetic_operators.cpp statement_serializator_tests/core_functions.cpp statement_serializator_tests/comparison_operators.cpp statement_serializator_tests/unique.cpp statement_serializator_tests/foreign_key.cpp statement_serializator_tests/collate.cpp statement_serializator_tests/check.cpp unique_cases/get_all_with_two_tables.cpp unique_cases/prepare_get_all_with_case.cpp unique_cases/index_named_table_with_fk.cpp get_all_custom_containers.cpp) +add_executable(unit_tests tests.cpp tests2.cpp tests3.cpp tests4.cpp tests5.cpp private_getters_tests.cpp pragma_tests.cpp explicit_columns.cpp core_functions_tests.cpp constraints/composite_key.cpp static_tests.cpp operators/arithmetic_operators.cpp operators/like.cpp operators/glob.cpp operators/in.cpp operators/cast.cpp operators/is_null.cpp operators/not_operator.cpp operators/bitwise.cpp dynamic_order_by.cpp prepared_statement_tests/select.cpp prepared_statement_tests/get_all.cpp prepared_statement_tests/get_all_pointer.cpp prepared_statement_tests/get_all_optional.cpp prepared_statement_tests/update_all.cpp prepared_statement_tests/remove_all.cpp prepared_statement_tests/get.cpp prepared_statement_tests/get_pointer.cpp prepared_statement_tests/get_optional.cpp prepared_statement_tests/update.cpp prepared_statement_tests/remove.cpp prepared_statement_tests/insert.cpp prepared_statement_tests/replace.cpp prepared_statement_tests/insert_range.cpp prepared_statement_tests/replace_range.cpp prepared_statement_tests/insert_explicit.cpp pragma_tests.cpp simple_query.cpp static_tests/is_bindable.cpp static_tests/arithmetic_operators_result_type.cpp static_tests/tuple_conc.cpp static_tests/node_tuple.cpp static_tests/bindable_filter.cpp static_tests/count_tuple.cpp static_tests/member_traits_tests.cpp static_tests/select_return_type.cpp constraints/default.cpp constraints/foreign_key.cpp constraints/check.cpp table_tests.cpp statement_serializator_tests/primary_key.cpp statement_serializator_tests/column_names.cpp statement_serializator_tests/autoincrement.cpp statement_serializator_tests/arithmetic_operators.cpp statement_serializator_tests/core_functions.cpp statement_serializator_tests/comparison_operators.cpp statement_serializator_tests/unique.cpp statement_serializator_tests/foreign_key.cpp statement_serializator_tests/collate.cpp statement_serializator_tests/check.cpp unique_cases/get_all_with_two_tables.cpp unique_cases/prepare_get_all_with_case.cpp unique_cases/index_named_table_with_fk.cpp get_all_custom_containers.cpp select_asterisk.cpp) if(SQLITE_ORM_OMITS_CODECVT) diff --git a/tests/prepared_statement_tests/get_all_pointer.cpp b/tests/prepared_statement_tests/get_all_pointer.cpp index 8f0ca3098..0a588f947 100644 --- a/tests/prepared_statement_tests/get_all_pointer.cpp +++ b/tests/prepared_statement_tests/get_all_pointer.cpp @@ -37,7 +37,7 @@ TEST_CASE("Prepared get all pointer") { storage.replace(UserAndVisit{2, 1, "Glad you came"}); storage.replace(UserAndVisit{3, 1, "Shine on"}); - { + SECTION("no conditions") { auto statement = storage.prepare(get_all_pointer()); testSerializing(statement); SECTION("nothing") { @@ -55,7 +55,7 @@ TEST_CASE("Prepared get all pointer") { REQUIRE(*rows[2].get() == expected[2]); } } - { // by val + SECTION("with conditions by val") { auto statement = storage.prepare(get_all_pointer(where(lesser_than(&User::id, 3)))); using Statement = decltype(statement); using Expression = Statement::expression_type; @@ -94,7 +94,7 @@ TEST_CASE("Prepared get all pointer") { } } } - { // by ref + SECTION("with conditions by ref") { auto id = 3; auto statement = storage.prepare(get_all_pointer(where(lesser_than(&User::id, std::ref(id))))); diff --git a/tests/prepared_statement_tests/prepared_common.h b/tests/prepared_statement_tests/prepared_common.h index c56980923..cbcfd0e00 100644 --- a/tests/prepared_statement_tests/prepared_common.h +++ b/tests/prepared_statement_tests/prepared_common.h @@ -3,6 +3,7 @@ #include // std::string #include // std::ignore #include +#include // std::ostream namespace PreparedStatementTests { struct User { @@ -42,4 +43,8 @@ namespace PreparedStatementTests { std::ignore = normalized; #endif } + + inline std::ostream &operator<<(std::ostream &os, const User &user) { + return os << "{" << user.id << ", " << user.name << "}"; + } } diff --git a/tests/select_asterisk.cpp b/tests/select_asterisk.cpp new file mode 100644 index 000000000..aa973d466 --- /dev/null +++ b/tests/select_asterisk.cpp @@ -0,0 +1,75 @@ +#include +#include + +using namespace sqlite_orm; + +TEST_CASE("select asterisk") { + using Catch::Matchers::UnorderedEquals; + + struct Employee { + int id; + std::string name; + int age; + std::string address; // optional + double salary; // optional + + bool operator==(const Employee &other) const { + return this->id == other.id && this->name == other.name && this->age == other.age && + this->address == other.address && this->salary == other.salary; + } + }; + + auto storage = make_storage({}, + make_table("COMPANY", + make_column("ID", &Employee::id, primary_key()), + make_column("NAME", &Employee::name), + make_column("AGE", &Employee::age), + make_column("ADDRESS", &Employee::address), + make_column("SALARY", &Employee::salary))); + storage.sync_schema(); + + // create employees.. + Employee paul{-1, "Paul", 32, "California", 20000.0}; + Employee allen{-1, "Allen", 25, "Texas", 15000.0}; + Employee teddy{-1, "Teddy", 23, "Norway", 20000.0}; + Employee mark{-1, "Mark", 25, "Rich-Mond", 65000.0}; + Employee david{-1, "David", 27, "Texas", 85000.0}; + Employee kim{-1, "Kim", 22, "South-Hall", 45000.0}; + Employee james{-1, "James", 24, "Houston", 10000.0}; + + // insert employees. `insert` function returns id of inserted object.. + paul.id = storage.insert(paul); + allen.id = storage.insert(allen); + teddy.id = storage.insert(teddy); + mark.id = storage.insert(mark); + david.id = storage.insert(david); + kim.id = storage.insert(kim); + james.id = storage.insert(james); + + SECTION("asterisk") { + auto allEmployeesTuples = storage.select(asterisk()); + + std::vector> expected; + + expected.push_back(std::make_tuple(paul.id, "Paul", 32, "California", 20000.0)); + expected.push_back(std::make_tuple(allen.id, "Allen", 25, "Texas", 15000.0)); + expected.push_back(std::make_tuple(teddy.id, "Teddy", 23, "Norway", 20000.0)); + expected.push_back(std::make_tuple(mark.id, "Mark", 25, "Rich-Mond", 65000.0)); + expected.push_back(std::make_tuple(david.id, "David", 27, "Texas", 85000.0)); + expected.push_back(std::make_tuple(kim.id, "Kim", 22, "South-Hall", 45000.0)); + expected.push_back(std::make_tuple(james.id, "James", 24, "Houston", 10000.0)); + REQUIRE_THAT(allEmployeesTuples, UnorderedEquals(expected)); + } + SECTION("object") { + auto allEmployees = storage.select(object()); + std::vector expected; + expected.push_back(paul); + expected.push_back(allen); + expected.push_back(teddy); + expected.push_back(mark); + expected.push_back(david); + expected.push_back(kim); + expected.push_back(james); + REQUIRE_THAT(allEmployees, UnorderedEquals(expected)); + } +} diff --git a/tests/tests2.cpp b/tests/tests2.cpp index d89c7e436..6483895ff 100644 --- a/tests/tests2.cpp +++ b/tests/tests2.cpp @@ -254,58 +254,6 @@ TEST_CASE("Select") { REQUIRE(storage.get(firstId).currentWord == "ototo"); } -TEST_CASE("select asterisk") { - using Catch::Matchers::UnorderedEquals; - - struct Employee { - int id; - std::string name; - int age; - std::string address; // optional - double salary; // optional - }; - - auto storage = make_storage({}, - make_table("COMPANY", - make_column("ID", &Employee::id, primary_key()), - make_column("NAME", &Employee::name), - make_column("AGE", &Employee::age), - make_column("ADDRESS", &Employee::address), - make_column("SALARY", &Employee::salary))); - storage.sync_schema(); - - // create employees.. - Employee paul{-1, "Paul", 32, "California", 20000.0}; - Employee allen{-1, "Allen", 25, "Texas", 15000.0}; - Employee teddy{-1, "Teddy", 23, "Norway", 20000.0}; - Employee mark{-1, "Mark", 25, "Rich-Mond", 65000.0}; - Employee david{-1, "David", 27, "Texas", 85000.0}; - Employee kim{-1, "Kim", 22, "South-Hall", 45000.0}; - Employee james{-1, "James", 24, "Houston", 10000.0}; - - // insert employees. `insert` function returns id of inserted object.. - paul.id = storage.insert(paul); - allen.id = storage.insert(allen); - teddy.id = storage.insert(teddy); - mark.id = storage.insert(mark); - david.id = storage.insert(david); - kim.id = storage.insert(kim); - james.id = storage.insert(james); - - auto allEmployeesTuples = storage.select(asterisk()); - - std::vector> expected; - - expected.push_back(std::make_tuple(paul.id, "Paul", 32, "California", 20000.0)); - expected.push_back(std::make_tuple(allen.id, "Allen", 25, "Texas", 15000.0)); - expected.push_back(std::make_tuple(teddy.id, "Teddy", 23, "Norway", 20000.0)); - expected.push_back(std::make_tuple(mark.id, "Mark", 25, "Rich-Mond", 65000.0)); - expected.push_back(std::make_tuple(david.id, "David", 27, "Texas", 85000.0)); - expected.push_back(std::make_tuple(kim.id, "Kim", 22, "South-Hall", 45000.0)); - expected.push_back(std::make_tuple(james.id, "James", 24, "Houston", 10000.0)); - REQUIRE_THAT(allEmployeesTuples, UnorderedEquals(expected)); -} - TEST_CASE("Replace query") { struct Object { int id; From 10e3c9440182535e152e21affbc31b0fb5218413 Mon Sep 17 00:00:00 2001 From: fnc12 Date: Tue, 26 May 2020 22:48:09 +0300 Subject: [PATCH 080/132] added unique for several columns --- dev/constraints.h | 38 +++++++++++++------ dev/statement_serializator.h | 25 ++++++++++--- include/sqlite_orm/sqlite_orm.h | 63 ++++++++++++++++++++++++-------- tests/CMakeLists.txt | 2 +- tests/constraints/unique.cpp | 65 +++++++++++++++++++++++++++++++++ 5 files changed, 160 insertions(+), 33 deletions(-) create mode 100644 tests/constraints/unique.cpp diff --git a/dev/constraints.h b/dev/constraints.h index ea9b6c0d2..932d7a492 100644 --- a/dev/constraints.h +++ b/dev/constraints.h @@ -72,14 +72,22 @@ namespace sqlite_orm { } }; + struct unique_base { + operator std::string() const { + return "UNIQUE"; + } + }; + /** * UNIQUE constraint class. */ - struct unique_t { + template + struct unique_t : unique_base { + using columns_tuple = std::tuple; - operator std::string() const { - return "UNIQUE"; - } + columns_tuple columns; + + unique_t(columns_tuple columns_) : columns(move(columns_)) {} }; /** @@ -329,8 +337,8 @@ namespace sqlite_orm { template struct is_constraint> : std::true_type {}; - template<> - struct is_constraint : std::true_type {}; + template + struct is_constraint> : std::true_type {}; template struct is_constraint> : std::true_type {}; @@ -373,8 +381,13 @@ namespace sqlite_orm { /** * UNIQUE constraint builder function. */ - inline constraints::unique_t unique() { - return {}; + template + constraints::unique_t unique(Args... args) { + return {std::make_tuple(std::forward(args)...)}; + } + + inline constraints::unique_t<> unique() { + return {{}}; } inline constraints::autoincrement_t autoincrement() { @@ -382,9 +395,12 @@ namespace sqlite_orm { } template - inline constraints::primary_key_t primary_key(Cs... cs) { - using ret_type = constraints::primary_key_t; - return ret_type(std::make_tuple(cs...)); + constraints::primary_key_t primary_key(Cs... cs) { + return {std::make_tuple(std::forward(cs)...)}; + } + + inline constraints::primary_key_t<> primary_key() { + return {{}}; } template diff --git a/dev/statement_serializator.h b/dev/statement_serializator.h index af700bd2e..e84d21de4 100644 --- a/dev/statement_serializator.h +++ b/dev/statement_serializator.h @@ -601,13 +601,28 @@ namespace sqlite_orm { } }; - template<> - struct statement_serializator { - using statement_type = constraints::unique_t; + template + struct statement_serializator, void> { + using statement_type = constraints::unique_t; template - std::string operator()(const statement_type &c, const C &) const { - return static_cast(c); + std::string operator()(const statement_type &c, const C &context) const { + auto res = static_cast(c); + using columns_tuple = typename statement_type::columns_tuple; + auto columnsCount = std::tuple_size::value; + if(columnsCount) { + res += "("; + decltype(columnsCount) columnIndex = 0; + iterate_tuple(c.columns, [&context, &res, &columnIndex, columnsCount](auto &column) { + res += context.column_name(column); + if(columnIndex < columnsCount - 1) { + res += ", "; + } + ++columnIndex; + }); + res += ")"; + } + return res; } }; diff --git a/include/sqlite_orm/sqlite_orm.h b/include/sqlite_orm/sqlite_orm.h index 5a3801018..3dbd649ac 100644 --- a/include/sqlite_orm/sqlite_orm.h +++ b/include/sqlite_orm/sqlite_orm.h @@ -557,14 +557,22 @@ namespace sqlite_orm { } }; + struct unique_base { + operator std::string() const { + return "UNIQUE"; + } + }; + /** * UNIQUE constraint class. */ - struct unique_t { + template + struct unique_t : unique_base { + using columns_tuple = std::tuple; - operator std::string() const { - return "UNIQUE"; - } + columns_tuple columns; + + unique_t(columns_tuple columns_) : columns(move(columns_)) {} }; /** @@ -814,8 +822,8 @@ namespace sqlite_orm { template struct is_constraint> : std::true_type {}; - template<> - struct is_constraint : std::true_type {}; + template + struct is_constraint> : std::true_type {}; template struct is_constraint> : std::true_type {}; @@ -858,8 +866,13 @@ namespace sqlite_orm { /** * UNIQUE constraint builder function. */ - inline constraints::unique_t unique() { - return {}; + template + constraints::unique_t unique(Args... args) { + return {std::make_tuple(std::forward(args)...)}; + } + + inline constraints::unique_t<> unique() { + return {{}}; } inline constraints::autoincrement_t autoincrement() { @@ -867,9 +880,12 @@ namespace sqlite_orm { } template - inline constraints::primary_key_t primary_key(Cs... cs) { - using ret_type = constraints::primary_key_t; - return ret_type(std::make_tuple(cs...)); + constraints::primary_key_t primary_key(Cs... cs) { + return {std::make_tuple(std::forward(cs)...)}; + } + + inline constraints::primary_key_t<> primary_key() { + return {{}}; } template @@ -10033,13 +10049,28 @@ namespace sqlite_orm { } }; - template<> - struct statement_serializator { - using statement_type = constraints::unique_t; + template + struct statement_serializator, void> { + using statement_type = constraints::unique_t; template - std::string operator()(const statement_type &c, const C &) const { - return static_cast(c); + std::string operator()(const statement_type &c, const C &context) const { + auto res = static_cast(c); + using columns_tuple = typename statement_type::columns_tuple; + auto columnsCount = std::tuple_size::value; + if(columnsCount) { + res += "("; + decltype(columnsCount) columnIndex = 0; + iterate_tuple(c.columns, [&context, &res, &columnIndex, columnsCount](auto &column) { + res += context.column_name(column); + if(columnIndex < columnsCount - 1) { + res += ", "; + } + ++columnIndex; + }); + res += ")"; + } + return res; } }; diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 28e700753..e65f9667a 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -10,7 +10,7 @@ else() add_subdirectory(third_party/sqlite) endif() -add_executable(unit_tests tests.cpp tests2.cpp tests3.cpp tests4.cpp tests5.cpp private_getters_tests.cpp pragma_tests.cpp explicit_columns.cpp core_functions_tests.cpp constraints/composite_key.cpp static_tests.cpp operators/arithmetic_operators.cpp operators/like.cpp operators/glob.cpp operators/in.cpp operators/cast.cpp operators/is_null.cpp operators/not_operator.cpp operators/bitwise.cpp dynamic_order_by.cpp prepared_statement_tests/select.cpp prepared_statement_tests/get_all.cpp prepared_statement_tests/get_all_pointer.cpp prepared_statement_tests/get_all_optional.cpp prepared_statement_tests/update_all.cpp prepared_statement_tests/remove_all.cpp prepared_statement_tests/get.cpp prepared_statement_tests/get_pointer.cpp prepared_statement_tests/get_optional.cpp prepared_statement_tests/update.cpp prepared_statement_tests/remove.cpp prepared_statement_tests/insert.cpp prepared_statement_tests/replace.cpp prepared_statement_tests/insert_range.cpp prepared_statement_tests/replace_range.cpp prepared_statement_tests/insert_explicit.cpp pragma_tests.cpp simple_query.cpp static_tests/is_bindable.cpp static_tests/arithmetic_operators_result_type.cpp static_tests/tuple_conc.cpp static_tests/node_tuple.cpp static_tests/bindable_filter.cpp static_tests/count_tuple.cpp static_tests/member_traits_tests.cpp static_tests/select_return_type.cpp constraints/default.cpp constraints/foreign_key.cpp constraints/check.cpp table_tests.cpp statement_serializator_tests/primary_key.cpp statement_serializator_tests/column_names.cpp statement_serializator_tests/autoincrement.cpp statement_serializator_tests/arithmetic_operators.cpp statement_serializator_tests/core_functions.cpp statement_serializator_tests/comparison_operators.cpp statement_serializator_tests/unique.cpp statement_serializator_tests/foreign_key.cpp statement_serializator_tests/collate.cpp statement_serializator_tests/check.cpp unique_cases/get_all_with_two_tables.cpp unique_cases/prepare_get_all_with_case.cpp unique_cases/index_named_table_with_fk.cpp get_all_custom_containers.cpp select_asterisk.cpp) +add_executable(unit_tests tests.cpp tests2.cpp tests3.cpp tests4.cpp tests5.cpp private_getters_tests.cpp pragma_tests.cpp explicit_columns.cpp core_functions_tests.cpp constraints/composite_key.cpp static_tests.cpp operators/arithmetic_operators.cpp operators/like.cpp operators/glob.cpp operators/in.cpp operators/cast.cpp operators/is_null.cpp operators/not_operator.cpp operators/bitwise.cpp dynamic_order_by.cpp prepared_statement_tests/select.cpp prepared_statement_tests/get_all.cpp prepared_statement_tests/get_all_pointer.cpp prepared_statement_tests/get_all_optional.cpp prepared_statement_tests/update_all.cpp prepared_statement_tests/remove_all.cpp prepared_statement_tests/get.cpp prepared_statement_tests/get_pointer.cpp prepared_statement_tests/get_optional.cpp prepared_statement_tests/update.cpp prepared_statement_tests/remove.cpp prepared_statement_tests/insert.cpp prepared_statement_tests/replace.cpp prepared_statement_tests/insert_range.cpp prepared_statement_tests/replace_range.cpp prepared_statement_tests/insert_explicit.cpp pragma_tests.cpp simple_query.cpp static_tests/is_bindable.cpp static_tests/arithmetic_operators_result_type.cpp static_tests/tuple_conc.cpp static_tests/node_tuple.cpp static_tests/bindable_filter.cpp static_tests/count_tuple.cpp static_tests/member_traits_tests.cpp static_tests/select_return_type.cpp constraints/default.cpp constraints/unique.cpp constraints/foreign_key.cpp constraints/check.cpp table_tests.cpp statement_serializator_tests/primary_key.cpp statement_serializator_tests/column_names.cpp statement_serializator_tests/autoincrement.cpp statement_serializator_tests/arithmetic_operators.cpp statement_serializator_tests/core_functions.cpp statement_serializator_tests/comparison_operators.cpp statement_serializator_tests/unique.cpp statement_serializator_tests/foreign_key.cpp statement_serializator_tests/collate.cpp statement_serializator_tests/check.cpp unique_cases/get_all_with_two_tables.cpp unique_cases/prepare_get_all_with_case.cpp unique_cases/index_named_table_with_fk.cpp get_all_custom_containers.cpp select_asterisk.cpp) if(SQLITE_ORM_OMITS_CODECVT) diff --git a/tests/constraints/unique.cpp b/tests/constraints/unique.cpp new file mode 100644 index 000000000..f207d70c0 --- /dev/null +++ b/tests/constraints/unique.cpp @@ -0,0 +1,65 @@ +#include +#include + +using namespace sqlite_orm; + +TEST_CASE("Unique") { + + struct Contact { + int id = 0; + std::string firstName; + std::string lastName; + std::string email; + }; + struct Shape { + int id = 0; + std::string backgroundColor; + std::string foregroundColor; + }; + struct List { + int id = 0; + std::unique_ptr email; + }; + + auto storage = make_storage( + {}, + make_table("contacts", + make_column("contact_id", &Contact::id, primary_key()), + make_column("first_name", &Contact::firstName), + make_column("last_name", &Contact::lastName), + make_column("email", &Contact::email, unique())), + make_table("shapes", + make_column("shape_id", &Shape::id, primary_key()), + make_column("background_color", &Shape::backgroundColor), + make_column("foreground_color", &Shape::foregroundColor), + sqlite_orm::unique(&Shape::backgroundColor, &Shape::foregroundColor)), + make_table("lists", make_column("list_id", &List::id, primary_key()), make_column("email", &List::email))); + storage.sync_schema(); + + storage.insert(Contact{0, "John", "Doe", "john.doe@gmail.com"}); + + try { + storage.insert(Contact{0, "Johnny", "Doe", "john.doe@gmail.com"}); + REQUIRE(false); + } catch(const std::system_error &e) { + //.. + } catch(...) { + REQUIRE(false); + } + + storage.insert(Shape{0, "red", "green"}); + storage.insert(Shape{0, "red", "blue"}); + try { + storage.insert(Shape{0, "red", "green"}); + REQUIRE(false); + } catch(const std::system_error &e) { + //.. + } catch(...) { + REQUIRE(false); + } + + std::vector lists; + lists.push_back(List{0, nullptr}); + lists.push_back(List{0, nullptr}); + storage.insert_range(lists.begin(), lists.end()); +} From 87f54848664d9f43056c0e8898c6dd7000a4c95b Mon Sep 17 00:00:00 2001 From: fnc12 Date: Sat, 30 May 2020 18:41:57 +0300 Subject: [PATCH 081/132] fixed sync_schema --- dev/storage.h | 11 +- dev/storage_impl.h | 16 +- include/sqlite_orm/sqlite_orm.h | 27 +-- tests/sync_schema_tests.cpp | 306 ++++++++++++++++++++++++++++++++ 4 files changed, 340 insertions(+), 20 deletions(-) diff --git a/dev/storage.h b/dev/storage.h index e24348abe..55cef1aa8 100644 --- a/dev/storage.h +++ b/dev/storage.h @@ -122,7 +122,7 @@ namespace sqlite_orm { } template - void backup_table(sqlite3 *db, I *tableImpl) { + void backup_table(sqlite3 *db, I *tableImpl, const std::vector &columnsToIgnore) { // here we copy source table to another with a name with '_backup' suffix, but in case table with such // a name already exists we append suffix 1, then 2, etc until we find a free name.. @@ -143,7 +143,7 @@ namespace sqlite_orm { this->create_table(db, backupTableName, tableImpl); - tableImpl->copy_table(db, backupTableName); + tableImpl->copy_table(db, backupTableName, columnsToIgnore); this->drop_table_internal(tableImpl->table.name, db); @@ -631,7 +631,7 @@ namespace sqlite_orm { if(schema_stat == sync_schema_result::old_columns_removed) { // extra table columns than storage columns - this->backup_table(db, tImpl); + this->backup_table(db, tImpl, {}); res = decltype(res)::old_columns_removed; } @@ -645,10 +645,7 @@ namespace sqlite_orm { if(schema_stat == sync_schema_result::new_columns_added_and_old_columns_removed) { // remove extra columns - this->backup_table(db, tImpl); - for(auto columnPointer: columnsToAdd) { - tImpl->add_column(*columnPointer, db); - } + this->backup_table(db, tImpl, columnsToAdd); res = decltype(res)::new_columns_added_and_old_columns_removed; } } else if(schema_stat == sync_schema_result::dropped_and_recreated) { diff --git a/dev/storage_impl.h b/dev/storage_impl.h index 91130b7e3..c6ac4cf01 100644 --- a/dev/storage_impl.h +++ b/dev/storage_impl.h @@ -332,11 +332,21 @@ namespace sqlite_orm { * Copies current table to another table with a given **name**. * Performs CREATE TABLE %name% AS SELECT %this->table.columns_names()% FROM &this->table.name%; */ - void copy_table(sqlite3 *db, const std::string &name) { + void copy_table(sqlite3 *db, const std::string &name, const std::vector &columnsToIgnore) { + std::ignore = columnsToIgnore; + std::stringstream ss; std::vector columnNames; - this->table.for_each_column([&columnNames](auto &c) { - columnNames.emplace_back(c.name); + this->table.for_each_column([&columnNames, &columnsToIgnore](auto &c) { + auto &columnName = c.name; + auto columnToIgnoreIt = std::find_if(columnsToIgnore.begin(), + columnsToIgnore.end(), + [&columnName](auto tableInfoPointer) { + return columnName == tableInfoPointer->name; + }); + if(columnToIgnoreIt == columnsToIgnore.end()) { + columnNames.emplace_back(columnName); + } }); auto columnNamesCount = columnNames.size(); ss << "INSERT INTO " << name << " ("; diff --git a/include/sqlite_orm/sqlite_orm.h b/include/sqlite_orm/sqlite_orm.h index 3dbd649ac..cb4d21673 100644 --- a/include/sqlite_orm/sqlite_orm.h +++ b/include/sqlite_orm/sqlite_orm.h @@ -6569,11 +6569,21 @@ namespace sqlite_orm { * Copies current table to another table with a given **name**. * Performs CREATE TABLE %name% AS SELECT %this->table.columns_names()% FROM &this->table.name%; */ - void copy_table(sqlite3 *db, const std::string &name) { + void copy_table(sqlite3 *db, const std::string &name, const std::vector &columnsToIgnore) { + std::ignore = columnsToIgnore; + std::stringstream ss; std::vector columnNames; - this->table.for_each_column([&columnNames](auto &c) { - columnNames.emplace_back(c.name); + this->table.for_each_column([&columnNames, &columnsToIgnore](auto &c) { + auto &columnName = c.name; + auto columnToIgnoreIt = std::find_if(columnsToIgnore.begin(), + columnsToIgnore.end(), + [&columnName](auto tableInfoPointer) { + return columnName == tableInfoPointer->name; + }); + if(columnToIgnoreIt == columnsToIgnore.end()) { + columnNames.emplace_back(columnName); + } }); auto columnNamesCount = columnNames.size(); ss << "INSERT INTO " << name << " ("; @@ -11097,7 +11107,7 @@ namespace sqlite_orm { } template - void backup_table(sqlite3 *db, I *tableImpl) { + void backup_table(sqlite3 *db, I *tableImpl, const std::vector &columnsToIgnore) { // here we copy source table to another with a name with '_backup' suffix, but in case table with such // a name already exists we append suffix 1, then 2, etc until we find a free name.. @@ -11118,7 +11128,7 @@ namespace sqlite_orm { this->create_table(db, backupTableName, tableImpl); - tableImpl->copy_table(db, backupTableName); + tableImpl->copy_table(db, backupTableName, columnsToIgnore); this->drop_table_internal(tableImpl->table.name, db); @@ -11606,7 +11616,7 @@ namespace sqlite_orm { if(schema_stat == sync_schema_result::old_columns_removed) { // extra table columns than storage columns - this->backup_table(db, tImpl); + this->backup_table(db, tImpl, {}); res = decltype(res)::old_columns_removed; } @@ -11620,10 +11630,7 @@ namespace sqlite_orm { if(schema_stat == sync_schema_result::new_columns_added_and_old_columns_removed) { // remove extra columns - this->backup_table(db, tImpl); - for(auto columnPointer: columnsToAdd) { - tImpl->add_column(*columnPointer, db); - } + this->backup_table(db, tImpl, columnsToAdd); res = decltype(res)::new_columns_added_and_old_columns_removed; } } else if(schema_stat == sync_schema_result::dropped_and_recreated) { diff --git a/tests/sync_schema_tests.cpp b/tests/sync_schema_tests.cpp index 54c86d4c4..19c02056c 100644 --- a/tests/sync_schema_tests.cpp +++ b/tests/sync_schema_tests.cpp @@ -109,3 +109,309 @@ TEST_CASE("Sync schema") { }); REQUIRE(std::equal(ids.begin(), ids.end(), idsFromGetAll.begin(), idsFromGetAll.end())); } + +TEST_CASE("issue521") { + auto storagePath = "issue521.sqlite"; + + struct MockDatabasePoco { + int id{-1}; + std::string name{""}; + uint32_t alpha{0}; + float beta{0.0}; + }; + std::vector pocosToInsert; + + // constexpr size_t zeroSize{ 0 }; + + ::remove(storagePath); + { + // --- Create the initial database + auto storage = sqlite_orm::make_storage( + storagePath, + sqlite_orm::make_table("pocos", + sqlite_orm::make_column("id", &MockDatabasePoco::id, sqlite_orm::primary_key()), + sqlite_orm::make_column("name", &MockDatabasePoco::name))); + + // --- We simulate the synchronization first, then do it for real and compare + auto simulated = storage.sync_schema_simulate(true); + auto ssr = storage.sync_schema(true); + REQUIRE(ssr == simulated); + REQUIRE(ssr.at("pocos") == sqlite_orm::sync_schema_result::new_table_created); + + // --- Insert two rows + pocosToInsert.clear(); + pocosToInsert.push_back({-1, "Michael", 10, 10.10}); + pocosToInsert.push_back({-1, "Joyce", 20, 20.20}); + + for(auto &poco: pocosToInsert) { + auto insertedId = storage.insert(poco); + poco.id = insertedId; + } + + // --- Retrieve the pocos and verify + REQUIRE(static_cast(storage.count()) == pocosToInsert.size()); + + using namespace sqlite_orm; + auto pocosFromDb = storage.get_all(order_by(&MockDatabasePoco::id)); + for(size_t i = 0; i < pocosFromDb.size(); ++i) { + auto &pocoFromDb = pocosFromDb[i]; + auto &oldPoco = pocosToInsert[i]; + + REQUIRE(pocoFromDb.id == oldPoco.id); + REQUIRE(pocoFromDb.name == oldPoco.name); + } + } + { + // --- Read the database and create the storage + auto storage = sqlite_orm::make_storage( + storagePath, + sqlite_orm::make_table("pocos", + sqlite_orm::make_column("id", &MockDatabasePoco::id, sqlite_orm::primary_key()), + sqlite_orm::make_column("name", &MockDatabasePoco::name))); + // --- We simulate the synchronization first, then do it for real and compare + auto simulated = storage.sync_schema_simulate(true); + auto ssr = storage.sync_schema(true); + REQUIRE(ssr == simulated); + REQUIRE(ssr["pocos"] == sqlite_orm::sync_schema_result::already_in_sync); + + REQUIRE(static_cast(storage.count()) == pocosToInsert.size()); + + auto pocosFromDb = storage.get_all(order_by(&MockDatabasePoco::id)); + for(size_t i = 0; i < pocosFromDb.size(); ++i) { + auto &pocoFromDb = pocosFromDb[i]; + auto &oldPoco = pocosToInsert[i]; + REQUIRE(pocoFromDb.id == oldPoco.id); + REQUIRE(pocoFromDb.name == oldPoco.name); + } + } + // --- Add a new column + { + // --- Read the database and create the storage + auto storage = sqlite_orm::make_storage( + storagePath, + sqlite_orm::make_table( + "pocos", + sqlite_orm::make_column("id", &MockDatabasePoco::id, sqlite_orm::primary_key()), + sqlite_orm::make_column("name", &MockDatabasePoco::name), + sqlite_orm::make_column("alpha", &MockDatabasePoco::alpha, sqlite_orm::default_value(1)))); + // --- We simulate the synchronization first, then do it for real and compare + auto simulated = storage.sync_schema_simulate(true); + auto ssr = storage.sync_schema(true); + REQUIRE(ssr == simulated); + REQUIRE(ssr["pocos"] == sqlite_orm::sync_schema_result::new_columns_added); + REQUIRE(static_cast(storage.count()) == pocosToInsert.size()); + + auto pocosFromDb = storage.get_all(order_by(&MockDatabasePoco::id)); + for(size_t i = 0; i < pocosFromDb.size(); ++i) { + auto &pocoFromDb = pocosFromDb[i]; + auto &oldPoco = pocosToInsert[i]; + REQUIRE(pocoFromDb.id == oldPoco.id); + REQUIRE(pocoFromDb.name == oldPoco.name); + REQUIRE(pocoFromDb.alpha == 1); + } + } + // --- Add a new column and delete an old one + { + // --- Read the database and create the storage + auto storage = sqlite_orm::make_storage( + storagePath, + sqlite_orm::make_table( + "pocos", + sqlite_orm::make_column("id", &MockDatabasePoco::id, sqlite_orm::primary_key()), + sqlite_orm::make_column("name", &MockDatabasePoco::name), + sqlite_orm::make_column("beta", &MockDatabasePoco::beta, sqlite_orm::default_value(1.1)))); + + // --- We simulate the synchronization first, then do it for real and compare + auto simulated = storage.sync_schema_simulate(true); + auto ssr = storage.sync_schema(true); + REQUIRE(ssr == simulated); + REQUIRE(ssr["pocos"] == sqlite_orm::sync_schema_result::new_columns_added_and_old_columns_removed); + REQUIRE(static_cast(storage.count()) == pocosToInsert.size()); + + auto pocosFromDb = storage.get_all(order_by(&MockDatabasePoco::id)); + for(size_t i = 0; i < pocosFromDb.size(); ++i) { + auto &pocoFromDb = pocosFromDb[i]; + auto &oldPoco = pocosToInsert[i]; + + REQUIRE(pocoFromDb.id == oldPoco.id); + REQUIRE(pocoFromDb.name == oldPoco.name); + REQUIRE(!(pocoFromDb.beta < 1)); + } + } +} + +bool compareUniquePointers(const std::unique_ptr &lhs, const std::unique_ptr &rhs) { + if(!lhs && !rhs) { + return true; + } else { + if(lhs && rhs) { + return *lhs == *rhs; + } else { + return false; + } + } +} + +TEST_CASE("sync_schema") { + using Catch::Matchers::UnorderedEquals; + struct User { + int id = 0; + std::string name; + int age = 0; + std::unique_ptr ageNullable; + + User() = default; + + User(int id_) : id(id_) {} + + User(int id_, std::string name_) : id(id_), name(move(name_)) {} + + User(int id_, int age_) : id(id_), age(age_) {} + + User(const User &other) : + id(other.id), name(other.name), age(other.age), + ageNullable(other.ageNullable ? std::make_unique(*other.ageNullable) : nullptr) {} + + bool operator==(const User &other) const { + return this->id == other.id && this->name == other.name && this->age == other.age; + } + }; + auto storagePath = "sync_schema.sqlite"; + std::string tableName = "users"; + struct { + const std::string id = "id"; + const std::string name = "name"; + const std::string age = "age"; + } columnNames; + ::remove(storagePath); + { + auto storage = make_storage(storagePath, + make_table(tableName, + make_column(columnNames.id, &User::id, primary_key()), + make_column(columnNames.name, &User::name))); + auto syncSchemaSimulateRes = storage.sync_schema_simulate(true); + auto syncSchemaRes = storage.sync_schema(true); + REQUIRE(syncSchemaSimulateRes == syncSchemaRes); + decltype(syncSchemaRes) expected{ + {tableName, sync_schema_result::new_table_created}, + }; + REQUIRE(syncSchemaRes == expected); + + storage.replace(User{1, "Alex"}); + storage.replace(User{2, "Michael"}); + } + SECTION("remove name column") { + auto storage = + make_storage(storagePath, make_table(tableName, make_column(columnNames.id, &User::id, primary_key()))); + SECTION("preserve = true") { + auto syncSchemaSimulateRes = storage.sync_schema_simulate(true); + auto syncSchemaRes = storage.sync_schema(true); + REQUIRE(syncSchemaSimulateRes == syncSchemaRes); + decltype(syncSchemaRes) expected{ + {tableName, sync_schema_result::old_columns_removed}, + }; + REQUIRE(syncSchemaRes == expected); + auto users = storage.get_all(); + REQUIRE_THAT(users, UnorderedEquals(std::vector{User{1}, User{2}})); + } + SECTION("preserve = false") { + auto syncSchemaSimulateRes = storage.sync_schema_simulate(); + auto syncSchemaRes = storage.sync_schema(); + REQUIRE(syncSchemaSimulateRes == syncSchemaRes); + decltype(syncSchemaRes) expected{ + {tableName, sync_schema_result::dropped_and_recreated}, + }; + REQUIRE(syncSchemaRes == expected); + auto users = storage.get_all(); + REQUIRE(users.empty()); + } + } + SECTION("replace a column with no default value") { + auto storage = make_storage(storagePath, + make_table(tableName, + make_column(columnNames.id, &User::id, primary_key()), + make_column(columnNames.age, &User::age))); + std::map syncSchemaSimulateRes; + std::map syncSchemaRes; + SECTION("preserve = true") { + syncSchemaSimulateRes = storage.sync_schema_simulate(true); + syncSchemaRes = storage.sync_schema(true); + } + SECTION("preserve = false") { + syncSchemaSimulateRes = storage.sync_schema_simulate(); + syncSchemaRes = storage.sync_schema(); + } + REQUIRE(syncSchemaSimulateRes == syncSchemaRes); + decltype(syncSchemaRes) expected{ + {tableName, sync_schema_result::dropped_and_recreated}, + }; + REQUIRE(syncSchemaRes == expected); + auto users = storage.get_all(); + REQUIRE(users.empty()); + } + SECTION("replace a column with default value") { + auto storage = make_storage(storagePath, + make_table(tableName, + make_column(columnNames.id, &User::id, primary_key()), + make_column(columnNames.age, &User::age, default_value(-1)))); + SECTION("preserve = true") { + auto syncSchemaSimulateRes = storage.sync_schema_simulate(true); + auto syncSchemaRes = storage.sync_schema(true); + REQUIRE(syncSchemaSimulateRes == syncSchemaRes); + decltype(syncSchemaRes) expected{ + {tableName, sync_schema_result::new_columns_added_and_old_columns_removed}, + }; + REQUIRE(syncSchemaRes == expected); + auto users = storage.get_all(); + REQUIRE_THAT(users, UnorderedEquals(std::vector{User{1, -1}, User{2, -1}})); + } + SECTION("preserve = false") { + auto syncSchemaSimulateRes = storage.sync_schema_simulate(); + auto syncSchemaRes = storage.sync_schema(); + REQUIRE(syncSchemaSimulateRes == syncSchemaRes); + decltype(syncSchemaRes) expected{ + {tableName, sync_schema_result::dropped_and_recreated}, + }; + REQUIRE(syncSchemaRes == expected); + auto users = storage.get_all(); + REQUIRE(users.empty()); + } + } + SECTION("replace a column with null") { + auto storage = make_storage(storagePath, + make_table(tableName, + make_column(columnNames.id, &User::id, primary_key()), + make_column(columnNames.age, &User::ageNullable))); + SECTION("preserve = true") { + auto syncSchemaSimulateRes = storage.sync_schema_simulate(true); + auto syncSchemaRes = storage.sync_schema(true); + REQUIRE(syncSchemaSimulateRes == syncSchemaRes); + { + decltype(syncSchemaRes) expected{ + {tableName, sync_schema_result::new_columns_added_and_old_columns_removed}, + }; + REQUIRE(syncSchemaRes == expected); + } + auto users = storage.get_all(); + REQUIRE_THAT(users, UnorderedEquals(std::vector{User{1}, User{2}})); + { + auto rows = storage.select(asterisk()); + decltype(rows) expected; + expected.push_back({1, std::unique_ptr()}); + expected.push_back({2, std::unique_ptr()}); + REQUIRE_THAT(rows, UnorderedEquals(expected)); + } + } + SECTION("preserve = false") { + auto syncSchemaSimulateRes = storage.sync_schema_simulate(); + auto syncSchemaRes = storage.sync_schema(); + REQUIRE(syncSchemaSimulateRes == syncSchemaRes); + decltype(syncSchemaRes) expected{ + {tableName, sync_schema_result::dropped_and_recreated}, + }; + REQUIRE(syncSchemaRes == expected); + auto users = storage.get_all(); + REQUIRE(users.empty()); + } + } +} From 7895f1004bf3afa767118bd6a8f44acacba6e0f4 Mon Sep 17 00:00:00 2001 From: fnc12 Date: Sat, 30 May 2020 18:44:09 +0300 Subject: [PATCH 082/132] removed a comment --- tests/sync_schema_tests.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/tests/sync_schema_tests.cpp b/tests/sync_schema_tests.cpp index 19c02056c..1169ef7c0 100644 --- a/tests/sync_schema_tests.cpp +++ b/tests/sync_schema_tests.cpp @@ -121,8 +121,6 @@ TEST_CASE("issue521") { }; std::vector pocosToInsert; - // constexpr size_t zeroSize{ 0 }; - ::remove(storagePath); { // --- Create the initial database From 888695db3ce3b5cb2df0b54506cb65d69bf011b0 Mon Sep 17 00:00:00 2001 From: fnc12 Date: Fri, 5 Jun 2020 00:43:20 +0300 Subject: [PATCH 083/132] added new unique case --- tests/CMakeLists.txt | 2 +- tests/table_tests.cpp | 48 +++++++++++++++++++++++++++++++++ tests/tests5.cpp | 48 --------------------------------- tests/unique_cases/issue525.cpp | 35 ++++++++++++++++++++++++ 4 files changed, 84 insertions(+), 49 deletions(-) create mode 100644 tests/unique_cases/issue525.cpp diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index e65f9667a..cd3364951 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -10,7 +10,7 @@ else() add_subdirectory(third_party/sqlite) endif() -add_executable(unit_tests tests.cpp tests2.cpp tests3.cpp tests4.cpp tests5.cpp private_getters_tests.cpp pragma_tests.cpp explicit_columns.cpp core_functions_tests.cpp constraints/composite_key.cpp static_tests.cpp operators/arithmetic_operators.cpp operators/like.cpp operators/glob.cpp operators/in.cpp operators/cast.cpp operators/is_null.cpp operators/not_operator.cpp operators/bitwise.cpp dynamic_order_by.cpp prepared_statement_tests/select.cpp prepared_statement_tests/get_all.cpp prepared_statement_tests/get_all_pointer.cpp prepared_statement_tests/get_all_optional.cpp prepared_statement_tests/update_all.cpp prepared_statement_tests/remove_all.cpp prepared_statement_tests/get.cpp prepared_statement_tests/get_pointer.cpp prepared_statement_tests/get_optional.cpp prepared_statement_tests/update.cpp prepared_statement_tests/remove.cpp prepared_statement_tests/insert.cpp prepared_statement_tests/replace.cpp prepared_statement_tests/insert_range.cpp prepared_statement_tests/replace_range.cpp prepared_statement_tests/insert_explicit.cpp pragma_tests.cpp simple_query.cpp static_tests/is_bindable.cpp static_tests/arithmetic_operators_result_type.cpp static_tests/tuple_conc.cpp static_tests/node_tuple.cpp static_tests/bindable_filter.cpp static_tests/count_tuple.cpp static_tests/member_traits_tests.cpp static_tests/select_return_type.cpp constraints/default.cpp constraints/unique.cpp constraints/foreign_key.cpp constraints/check.cpp table_tests.cpp statement_serializator_tests/primary_key.cpp statement_serializator_tests/column_names.cpp statement_serializator_tests/autoincrement.cpp statement_serializator_tests/arithmetic_operators.cpp statement_serializator_tests/core_functions.cpp statement_serializator_tests/comparison_operators.cpp statement_serializator_tests/unique.cpp statement_serializator_tests/foreign_key.cpp statement_serializator_tests/collate.cpp statement_serializator_tests/check.cpp unique_cases/get_all_with_two_tables.cpp unique_cases/prepare_get_all_with_case.cpp unique_cases/index_named_table_with_fk.cpp get_all_custom_containers.cpp select_asterisk.cpp) +add_executable(unit_tests tests.cpp tests2.cpp tests3.cpp tests4.cpp tests5.cpp private_getters_tests.cpp pragma_tests.cpp explicit_columns.cpp core_functions_tests.cpp constraints/composite_key.cpp static_tests.cpp operators/arithmetic_operators.cpp operators/like.cpp operators/glob.cpp operators/in.cpp operators/cast.cpp operators/is_null.cpp operators/not_operator.cpp operators/bitwise.cpp dynamic_order_by.cpp prepared_statement_tests/select.cpp prepared_statement_tests/get_all.cpp prepared_statement_tests/get_all_pointer.cpp prepared_statement_tests/get_all_optional.cpp prepared_statement_tests/update_all.cpp prepared_statement_tests/remove_all.cpp prepared_statement_tests/get.cpp prepared_statement_tests/get_pointer.cpp prepared_statement_tests/get_optional.cpp prepared_statement_tests/update.cpp prepared_statement_tests/remove.cpp prepared_statement_tests/insert.cpp prepared_statement_tests/replace.cpp prepared_statement_tests/insert_range.cpp prepared_statement_tests/replace_range.cpp prepared_statement_tests/insert_explicit.cpp pragma_tests.cpp simple_query.cpp static_tests/is_bindable.cpp static_tests/arithmetic_operators_result_type.cpp static_tests/tuple_conc.cpp static_tests/node_tuple.cpp static_tests/bindable_filter.cpp static_tests/count_tuple.cpp static_tests/member_traits_tests.cpp static_tests/select_return_type.cpp constraints/default.cpp constraints/unique.cpp constraints/foreign_key.cpp constraints/check.cpp table_tests.cpp statement_serializator_tests/primary_key.cpp statement_serializator_tests/column_names.cpp statement_serializator_tests/autoincrement.cpp statement_serializator_tests/arithmetic_operators.cpp statement_serializator_tests/core_functions.cpp statement_serializator_tests/comparison_operators.cpp statement_serializator_tests/unique.cpp statement_serializator_tests/foreign_key.cpp statement_serializator_tests/collate.cpp statement_serializator_tests/check.cpp unique_cases/get_all_with_two_tables.cpp unique_cases/prepare_get_all_with_case.cpp unique_cases/index_named_table_with_fk.cpp unique_cases/issue525.cpp get_all_custom_containers.cpp select_asterisk.cpp) if(SQLITE_ORM_OMITS_CODECVT) diff --git a/tests/table_tests.cpp b/tests/table_tests.cpp index 21aa89b69..b96bb796a 100644 --- a/tests/table_tests.cpp +++ b/tests/table_tests.cpp @@ -123,3 +123,51 @@ TEST_CASE("table") { REQUIRE(table.find_column_name(&Contact::setVisitsCount) == "visits_count"); } } + +TEST_CASE("Composite key column names") { + + struct User { + int id = 0; + std::string name; + std::string info; + }; + + { + auto table = make_table("t", + make_column("id", &User::id), + make_column("name", &User::name), + make_column("info", &User::info), + primary_key(&User::id, &User::name)); + auto compositeKeyColumnsNames = table.composite_key_columns_names(); + std::vector expected = {"id", "name"}; + REQUIRE(std::equal(compositeKeyColumnsNames.begin(), compositeKeyColumnsNames.end(), expected.begin())); + } + { + auto table = make_table("t", + make_column("id", &User::id), + make_column("name", &User::name), + make_column("info", &User::info), + primary_key(&User::name, &User::id)); + auto compositeKeyColumnsNames = table.composite_key_columns_names(); + std::vector expected = {"name", "id"}; + REQUIRE(std::equal(compositeKeyColumnsNames.begin(), compositeKeyColumnsNames.end(), expected.begin())); + } + { + auto table = make_table("t", + make_column("id", &User::id), + make_column("name", &User::name), + make_column("info", &User::info), + primary_key(&User::name, &User::id, &User::info)); + auto compositeKeyColumnsNames = table.composite_key_columns_names(); + std::vector expected = {"name", "id", "info"}; + REQUIRE(std::equal(compositeKeyColumnsNames.begin(), compositeKeyColumnsNames.end(), expected.begin())); + } + { + auto table = make_table("t", + make_column("id", &User::id), + make_column("name", &User::name), + make_column("info", &User::info)); + auto compositeKeyColumnsNames = table.composite_key_columns_names(); + REQUIRE(compositeKeyColumnsNames.empty()); + } +} diff --git a/tests/tests5.cpp b/tests/tests5.cpp index 0277d9802..866c17be4 100644 --- a/tests/tests5.cpp +++ b/tests/tests5.cpp @@ -4,54 +4,6 @@ using namespace sqlite_orm; -TEST_CASE("Composite key column names") { - - struct User { - int id = 0; - std::string name; - std::string info; - }; - - { - auto table = make_table("t", - make_column("id", &User::id), - make_column("name", &User::name), - make_column("info", &User::info), - primary_key(&User::id, &User::name)); - auto compositeKeyColumnsNames = table.composite_key_columns_names(); - std::vector expected = {"id", "name"}; - REQUIRE(std::equal(compositeKeyColumnsNames.begin(), compositeKeyColumnsNames.end(), expected.begin())); - } - { - auto table = make_table("t", - make_column("id", &User::id), - make_column("name", &User::name), - make_column("info", &User::info), - primary_key(&User::name, &User::id)); - auto compositeKeyColumnsNames = table.composite_key_columns_names(); - std::vector expected = {"name", "id"}; - REQUIRE(std::equal(compositeKeyColumnsNames.begin(), compositeKeyColumnsNames.end(), expected.begin())); - } - { - auto table = make_table("t", - make_column("id", &User::id), - make_column("name", &User::name), - make_column("info", &User::info), - primary_key(&User::name, &User::id, &User::info)); - auto compositeKeyColumnsNames = table.composite_key_columns_names(); - std::vector expected = {"name", "id", "info"}; - REQUIRE(std::equal(compositeKeyColumnsNames.begin(), compositeKeyColumnsNames.end(), expected.begin())); - } - { - auto table = make_table("t", - make_column("id", &User::id), - make_column("name", &User::name), - make_column("info", &User::info)); - auto compositeKeyColumnsNames = table.composite_key_columns_names(); - REQUIRE(compositeKeyColumnsNames.empty()); - } -} - TEST_CASE("Exists") { struct User { int id = 0; diff --git a/tests/unique_cases/issue525.cpp b/tests/unique_cases/issue525.cpp new file mode 100644 index 000000000..fd9c0b6a1 --- /dev/null +++ b/tests/unique_cases/issue525.cpp @@ -0,0 +1,35 @@ +#include +#include + +using namespace sqlite_orm; + +TEST_CASE("issue525") { + struct User { + int id; + std::string firstName; + std::string lastName; + int birthDate; + std::unique_ptr imageUrl; + int typeId; + }; + + struct UserType { + int id; + std::string name; + }; + + auto filename = "db1.sqlite"; + auto storage = make_storage(filename, + make_table("users", + make_column("id", &User::id, autoincrement(), primary_key()), + make_column("first_name", &User::firstName), + make_column("last_name", &User::lastName), + make_column("birth_date", &User::birthDate), + make_column("image_url", &User::imageUrl), + make_column("type_id", &User::typeId)), + make_table("user_types", + make_column("id", &UserType::id, autoincrement(), primary_key()), + make_column("name", &UserType::name, default_value("name_placeholder")))); + + storage.sync_schema(); +} From c2bf0c8e140915dea36b0953f17ccec3e14295a4 Mon Sep 17 00:00:00 2001 From: fnc12 Date: Tue, 9 Jun 2020 23:53:22 +0300 Subject: [PATCH 084/132] adde rename_table with unit tests --- dev/storage_base.h | 15 ++++++- include/sqlite_orm/sqlite_orm.h | 15 ++++++- tests/storage_tests.cpp | 76 +++++++++++++++++++++++++++++++++ 3 files changed, 104 insertions(+), 2 deletions(-) create mode 100644 tests/storage_tests.cpp diff --git a/dev/storage_base.h b/dev/storage_base.h index db8467082..9fbd6c78c 100644 --- a/dev/storage_base.h +++ b/dev/storage_base.h @@ -88,6 +88,16 @@ namespace sqlite_orm { this->drop_table_internal(tableName, con.get()); } + /** + * Rename table named `from` to `to`. + */ + void rename_table(const std::string &from, const std::string &to) { + auto con = this->get_connection(); + std::stringstream ss; + ss << "ALTER TABLE '" << from << "' RENAME TO '" << to << "'"; + this->perform_query_without_result(ss.str(), con.get()); + } + /** * sqlite3_changes function. */ @@ -484,7 +494,10 @@ namespace sqlite_orm { void drop_table_internal(const std::string &tableName, sqlite3 *db) { std::stringstream ss; ss << "DROP TABLE '" << tableName + "'"; - auto query = ss.str(); + this->perform_query_without_result(ss.str(), db); + } + + void perform_query_without_result(const std::string &query, sqlite3 *db) { sqlite3_stmt *stmt; if(sqlite3_prepare_v2(db, query.c_str(), -1, &stmt, nullptr) == SQLITE_OK) { statement_finalizer finalizer{stmt}; diff --git a/include/sqlite_orm/sqlite_orm.h b/include/sqlite_orm/sqlite_orm.h index cb4d21673..46a2fbcdb 100644 --- a/include/sqlite_orm/sqlite_orm.h +++ b/include/sqlite_orm/sqlite_orm.h @@ -8632,6 +8632,16 @@ namespace sqlite_orm { this->drop_table_internal(tableName, con.get()); } + /** + * Rename table named `from` to `to`. + */ + void rename_table(const std::string &from, const std::string &to) { + auto con = this->get_connection(); + std::stringstream ss; + ss << "ALTER TABLE '" << from << "' RENAME TO '" << to << "'"; + this->perform_query_without_result(ss.str(), con.get()); + } + /** * sqlite3_changes function. */ @@ -9028,7 +9038,10 @@ namespace sqlite_orm { void drop_table_internal(const std::string &tableName, sqlite3 *db) { std::stringstream ss; ss << "DROP TABLE '" << tableName + "'"; - auto query = ss.str(); + this->perform_query_without_result(ss.str(), db); + } + + void perform_query_without_result(const std::string &query, sqlite3 *db) { sqlite3_stmt *stmt; if(sqlite3_prepare_v2(db, query.c_str(), -1, &stmt, nullptr) == SQLITE_OK) { statement_finalizer finalizer{stmt}; diff --git a/tests/storage_tests.cpp b/tests/storage_tests.cpp new file mode 100644 index 000000000..6a399f528 --- /dev/null +++ b/tests/storage_tests.cpp @@ -0,0 +1,76 @@ +#include +#include + +using namespace sqlite_orm; + +TEST_CASE("drop table") { + struct User { + int id = 0; + std::string name; + }; + struct Visit { + int id = 0; + std::string date; + }; + const std::string usersTableName = "users"; + const std::string visitsTableName = "visits"; + auto storage = make_storage( + {}, + make_table(usersTableName, make_column("id", &User::id, primary_key()), make_column("name", &User::name)), + make_table(visitsTableName, make_column("id", &Visit::id, primary_key()), make_column("date", &Visit::date))); + REQUIRE(!storage.table_exists(usersTableName)); + REQUIRE(!storage.table_exists(visitsTableName)); + + storage.sync_schema(); + REQUIRE(storage.table_exists(usersTableName)); + REQUIRE(storage.table_exists(visitsTableName)); + + storage.drop_table(usersTableName); + REQUIRE(!storage.table_exists(usersTableName)); + REQUIRE(storage.table_exists(visitsTableName)); + + storage.drop_table(visitsTableName); + REQUIRE(!storage.table_exists(usersTableName)); + REQUIRE(!storage.table_exists(visitsTableName)); +} + +TEST_CASE("rename table") { + struct User { + int id = 0; + std::string name; + }; + struct Visit { + int id = 0; + std::string date; + }; + const std::string usersTableName = "users"; + const std::string userNewTableName = "users_new"; + const std::string visitsTableName = "visits"; + const std::string visitsNewTableName = "visits_new"; + auto storage = make_storage( + {}, + make_table(usersTableName, make_column("id", &User::id, primary_key()), make_column("name", &User::name)), + make_table(visitsTableName, make_column("id", &Visit::id, primary_key()), make_column("date", &Visit::date))); + REQUIRE(!storage.table_exists(usersTableName)); + REQUIRE(!storage.table_exists(userNewTableName)); + REQUIRE(!storage.table_exists(visitsTableName)); + REQUIRE(!storage.table_exists(visitsNewTableName)); + + storage.sync_schema(); + REQUIRE(storage.table_exists(usersTableName)); + REQUIRE(!storage.table_exists(userNewTableName)); + REQUIRE(storage.table_exists(visitsTableName)); + REQUIRE(!storage.table_exists(visitsNewTableName)); + + storage.rename_table(usersTableName, userNewTableName); + REQUIRE(!storage.table_exists(usersTableName)); + REQUIRE(storage.table_exists(userNewTableName)); + REQUIRE(storage.table_exists(visitsTableName)); + REQUIRE(!storage.table_exists(visitsNewTableName)); + + storage.rename_table(visitsTableName, visitsNewTableName); + REQUIRE(!storage.table_exists(usersTableName)); + REQUIRE(storage.table_exists(userNewTableName)); + REQUIRE(!storage.table_exists(visitsTableName)); + REQUIRE(storage.table_exists(visitsNewTableName)); +} From a69a163244201f746a1e85ec1394bd191a19e4a6 Mon Sep 17 00:00:00 2001 From: fnc12 Date: Sun, 14 Jun 2020 12:45:23 +0300 Subject: [PATCH 085/132] added rename_table with a template parameter --- dev/storage.h | 62 ++++++++++++++++++++++-- dev/storage_base.h | 2 +- dev/storage_impl.h | 18 +++++-- dev/table.h | 2 +- include/sqlite_orm/sqlite_orm.h | 84 ++++++++++++++++++++++++++++----- tests/storage_tests.cpp | 61 ++++++++++++++++++++---- 6 files changed, 197 insertions(+), 32 deletions(-) diff --git a/dev/storage.h b/dev/storage.h index 55cef1aa8..017628b65 100644 --- a/dev/storage.h +++ b/dev/storage.h @@ -161,6 +161,11 @@ namespace sqlite_orm { return this->impl.template get_impl(); } + template + auto &get_impl() { + return this->impl.template get_impl(); + } + public: template view_t iterate(Args &&... args) { @@ -170,6 +175,13 @@ namespace sqlite_orm { return {*this, std::move(con), std::forward(args)...}; } + /** + * Delete from routine. + * O is an object's type. Must be specified explicitly. + * @param args optional conditions: `where`, `join` etc + * @example: storage.remove_all(); - DELETE FROM users + * @example: storage.remove_all(where(in(&User::id, {5, 6, 7}))); - DELETE FROM users WHERE id IN (5, 6, 7) + */ template void remove_all(Args &&... args) { this->assert_mapped_type(); @@ -227,9 +239,12 @@ namespace sqlite_orm { public: /** - * Select * with no conditions routine. + * SELECT * routine. * O is an object type to be extracted. Must be specified explicitly. - * @return All objects of type O stored in database at the moment. + * @return All objects of type O stored in database at the moment in `std::vector`. + * @note If you need to return the result in a different container type then use a different `get_all` function overload `get_all>` + * @example: storage.get_all() - SELECT * FROM users + * @example: storage.get_all(where(like(&User::name, "N%")), order_by(&User::id)); - SELECT * FROM users WHERE name LIKE 'N%' ORDER BY id */ template auto get_all(Args &&... args) { @@ -238,6 +253,14 @@ namespace sqlite_orm { return this->execute(statement); } + /** + * SELECT * routine. + * O is an object type to be extracted. Must be specified explicitly. + * R is an explicit return type. This type must have `push_back(O &&)` function. + * @return All objects of type O stored in database at the moment in `R`. + * @example: storage.get_all>(); - SELECT * FROM users + * @example: storage.get_all>(where(like(&User::name, "N%")), order_by(&User::id)); - SELECT * FROM users WHERE name LIKE 'N%' ORDER BY id + */ template auto get_all(Args &&... args) { this->assert_mapped_type(); @@ -246,9 +269,12 @@ namespace sqlite_orm { } /** - * Select * with no conditions routine. + * SELECT * routine. * O is an object type to be extracted. Must be specified explicitly. - * @return All objects of type O as std::unique_ptr stored in database at the moment. + * @return All objects of type O as `std::unique_ptr` inside a `std::vector` stored in database at the moment. + * @note If you need to return the result in a different container type then use a different `get_all_pointer` function overload `get_all_pointer>` + * @example: storage.get_all_pointer(); - SELECT * FROM users + * @example: storage.get_all_pointer(where(length(&User::name) > 6)); - SELECT * FROM users WHERE LENGTH(name) > 6 */ template auto get_all_pointer(Args &&... args) { @@ -258,10 +284,12 @@ namespace sqlite_orm { } /** - * Select * with no conditions routine. + * SELECT * routine. * O is an object type to be extracted. Must be specified explicitly. * R is a container type. std::vector> is default * @return All objects of type O as std::unique_ptr stored in database at the moment. + * @example: storage.get_all_pointer>(); - SELECT * FROM users + * @example: storage.get_all_pointer>(where(length(&User::name) > 6)); - SELECT * FROM users WHERE LENGTH(name) > 6 */ template auto get_all_pointer(Args &&... args) { @@ -567,6 +595,30 @@ namespace sqlite_orm { this->execute(statement); } + /** + * Change table name inside storage's schema info. This function does not + * affect database + */ + template + void rename_table(std::string name) { + this->assert_mapped_type(); + auto &tImpl = this->get_impl(); + tImpl.table.name = move(name); + } + + using storage_base::rename_table; + + /** + * Get table's name stored in storage's schema info. This function does not call + * any SQLite queries + */ + template + const std::string &tablename() const { + this->assert_mapped_type(); + auto &tImpl = this->get_impl(); + return tImpl.table.name; + } + protected: template sync_schema_result diff --git a/dev/storage_base.h b/dev/storage_base.h index 9fbd6c78c..8a0db2266 100644 --- a/dev/storage_base.h +++ b/dev/storage_base.h @@ -131,7 +131,7 @@ namespace sqlite_orm { return sqlite3_libversion(); } - bool transaction(std::function f) { + bool transaction(const std::function &f) { this->begin_transaction(); auto con = this->get_connection(); auto db = con.get(); diff --git a/dev/storage_impl.h b/dev/storage_impl.h index c6ac4cf01..6a2224a5c 100644 --- a/dev/storage_impl.h +++ b/dev/storage_impl.h @@ -234,22 +234,32 @@ namespace sqlite_orm { } template - auto &get_impl(typename std::enable_if::value>::type * = nullptr) const { + const auto &get_impl(typename std::enable_if::value>::type * = nullptr) const { return *this; } template - auto &get_impl(typename std::enable_if::value>::type * = nullptr) const { + const auto &get_impl(typename std::enable_if::value>::type * = nullptr) const { return this->super::template get_impl(); } template - auto *find_table(typename std::enable_if::value>::type * = nullptr) const { + auto &get_impl(typename std::enable_if::value>::type * = nullptr) { + return *this; + } + + template + auto &get_impl(typename std::enable_if::value>::type * = nullptr) { + return this->super::template get_impl(); + } + + template + const auto *find_table(typename std::enable_if::value>::type * = nullptr) const { return &this->table; } template - auto *find_table(typename std::enable_if::value>::type * = nullptr) const { + const auto *find_table(typename std::enable_if::value>::type * = nullptr) const { return this->super::template find_table(); } diff --git a/dev/table.h b/dev/table.h index a82c5cb81..fb90dfaab 100644 --- a/dev/table.h +++ b/dev/table.h @@ -24,7 +24,7 @@ namespace sqlite_orm { /** * Table name. */ - const std::string name; + std::string name; bool _without_rowid = false; }; diff --git a/include/sqlite_orm/sqlite_orm.h b/include/sqlite_orm/sqlite_orm.h index 46a2fbcdb..216beaaa7 100644 --- a/include/sqlite_orm/sqlite_orm.h +++ b/include/sqlite_orm/sqlite_orm.h @@ -5944,7 +5944,7 @@ namespace sqlite_orm { /** * Table name. */ - const std::string name; + std::string name; bool _without_rowid = false; }; @@ -6471,22 +6471,32 @@ namespace sqlite_orm { } template - auto &get_impl(typename std::enable_if::value>::type * = nullptr) const { + const auto &get_impl(typename std::enable_if::value>::type * = nullptr) const { return *this; } template - auto &get_impl(typename std::enable_if::value>::type * = nullptr) const { + const auto &get_impl(typename std::enable_if::value>::type * = nullptr) const { return this->super::template get_impl(); } template - auto *find_table(typename std::enable_if::value>::type * = nullptr) const { + auto &get_impl(typename std::enable_if::value>::type * = nullptr) { + return *this; + } + + template + auto &get_impl(typename std::enable_if::value>::type * = nullptr) { + return this->super::template get_impl(); + } + + template + const auto *find_table(typename std::enable_if::value>::type * = nullptr) const { return &this->table; } template - auto *find_table(typename std::enable_if::value>::type * = nullptr) const { + const auto *find_table(typename std::enable_if::value>::type * = nullptr) const { return this->super::template find_table(); } @@ -8675,7 +8685,7 @@ namespace sqlite_orm { return sqlite3_libversion(); } - bool transaction(std::function f) { + bool transaction(const std::function &f) { this->begin_transaction(); auto con = this->get_connection(); auto db = con.get(); @@ -11159,6 +11169,11 @@ namespace sqlite_orm { return this->impl.template get_impl(); } + template + auto &get_impl() { + return this->impl.template get_impl(); + } + public: template view_t iterate(Args &&... args) { @@ -11168,6 +11183,13 @@ namespace sqlite_orm { return {*this, std::move(con), std::forward(args)...}; } + /** + * Delete from routine. + * O is an object's type. Must be specified explicitly. + * @param args optional conditions: `where`, `join` etc + * @example: storage.remove_all(); - DELETE FROM users + * @example: storage.remove_all(where(in(&User::id, {5, 6, 7}))); - DELETE FROM users WHERE id IN (5, 6, 7) + */ template void remove_all(Args &&... args) { this->assert_mapped_type(); @@ -11225,9 +11247,12 @@ namespace sqlite_orm { public: /** - * Select * with no conditions routine. + * SELECT * routine. * O is an object type to be extracted. Must be specified explicitly. - * @return All objects of type O stored in database at the moment. + * @return All objects of type O stored in database at the moment in `std::vector`. + * @note If you need to return the result in a different container type then use a different `get_all` function overload `get_all>` + * @example: storage.get_all() - SELECT * FROM users + * @example: storage.get_all(where(like(&User::name, "N%")), order_by(&User::id)); - SELECT * FROM users WHERE name LIKE 'N%' ORDER BY id */ template auto get_all(Args &&... args) { @@ -11236,6 +11261,14 @@ namespace sqlite_orm { return this->execute(statement); } + /** + * SELECT * routine. + * O is an object type to be extracted. Must be specified explicitly. + * R is an explicit return type. This type must have `push_back(O &&)` function. + * @return All objects of type O stored in database at the moment in `R`. + * @example: storage.get_all>(); - SELECT * FROM users + * @example: storage.get_all>(where(like(&User::name, "N%")), order_by(&User::id)); - SELECT * FROM users WHERE name LIKE 'N%' ORDER BY id + */ template auto get_all(Args &&... args) { this->assert_mapped_type(); @@ -11244,9 +11277,12 @@ namespace sqlite_orm { } /** - * Select * with no conditions routine. + * SELECT * routine. * O is an object type to be extracted. Must be specified explicitly. - * @return All objects of type O as std::unique_ptr stored in database at the moment. + * @return All objects of type O as `std::unique_ptr` inside a `std::vector` stored in database at the moment. + * @note If you need to return the result in a different container type then use a different `get_all_pointer` function overload `get_all_pointer>` + * @example: storage.get_all_pointer(); - SELECT * FROM users + * @example: storage.get_all_pointer(where(length(&User::name) > 6)); - SELECT * FROM users WHERE LENGTH(name) > 6 */ template auto get_all_pointer(Args &&... args) { @@ -11256,10 +11292,12 @@ namespace sqlite_orm { } /** - * Select * with no conditions routine. + * SELECT * routine. * O is an object type to be extracted. Must be specified explicitly. * R is a container type. std::vector> is default * @return All objects of type O as std::unique_ptr stored in database at the moment. + * @example: storage.get_all_pointer>(); - SELECT * FROM users + * @example: storage.get_all_pointer>(where(length(&User::name) > 6)); - SELECT * FROM users WHERE LENGTH(name) > 6 */ template auto get_all_pointer(Args &&... args) { @@ -11565,6 +11603,30 @@ namespace sqlite_orm { this->execute(statement); } + /** + * Change table name inside storage's schema info. This function does not + * affect database + */ + template + void rename_table(std::string name) { + this->assert_mapped_type(); + auto &tImpl = this->get_impl(); + tImpl.table.name = move(name); + } + + using storage_base::rename_table; + + /** + * Get table's name stored in storage's schema info. This function does not call + * any SQLite queries + */ + template + const std::string &tablename() const { + this->assert_mapped_type(); + auto &tImpl = this->get_impl(); + return tImpl.table.name; + } + protected: template sync_schema_result diff --git a/tests/storage_tests.cpp b/tests/storage_tests.cpp index 6a399f528..7998e36cb 100644 --- a/tests/storage_tests.cpp +++ b/tests/storage_tests.cpp @@ -51,26 +51,67 @@ TEST_CASE("rename table") { {}, make_table(usersTableName, make_column("id", &User::id, primary_key()), make_column("name", &User::name)), make_table(visitsTableName, make_column("id", &Visit::id, primary_key()), make_column("date", &Visit::date))); + REQUIRE(!storage.table_exists(usersTableName)); REQUIRE(!storage.table_exists(userNewTableName)); REQUIRE(!storage.table_exists(visitsTableName)); REQUIRE(!storage.table_exists(visitsNewTableName)); + REQUIRE(storage.tablename() == usersTableName); + REQUIRE(storage.tablename() != userNewTableName); + REQUIRE(storage.tablename() == visitsTableName); + REQUIRE(storage.tablename() != visitsNewTableName); storage.sync_schema(); REQUIRE(storage.table_exists(usersTableName)); REQUIRE(!storage.table_exists(userNewTableName)); REQUIRE(storage.table_exists(visitsTableName)); REQUIRE(!storage.table_exists(visitsNewTableName)); + REQUIRE(storage.tablename() == usersTableName); + REQUIRE(storage.tablename() != userNewTableName); + REQUIRE(storage.tablename() == visitsTableName); + REQUIRE(storage.tablename() != visitsNewTableName); - storage.rename_table(usersTableName, userNewTableName); - REQUIRE(!storage.table_exists(usersTableName)); - REQUIRE(storage.table_exists(userNewTableName)); - REQUIRE(storage.table_exists(visitsTableName)); - REQUIRE(!storage.table_exists(visitsNewTableName)); + SECTION("with 1 argument") { + storage.rename_table(userNewTableName); + REQUIRE(storage.table_exists(usersTableName)); + REQUIRE(!storage.table_exists(userNewTableName)); + REQUIRE(storage.table_exists(visitsTableName)); + REQUIRE(!storage.table_exists(visitsNewTableName)); + REQUIRE(storage.tablename() != usersTableName); + REQUIRE(storage.tablename() == userNewTableName); + REQUIRE(storage.tablename() == visitsTableName); + REQUIRE(storage.tablename() != visitsNewTableName); - storage.rename_table(visitsTableName, visitsNewTableName); - REQUIRE(!storage.table_exists(usersTableName)); - REQUIRE(storage.table_exists(userNewTableName)); - REQUIRE(!storage.table_exists(visitsTableName)); - REQUIRE(storage.table_exists(visitsNewTableName)); + storage.rename_table(visitsNewTableName); + REQUIRE(storage.table_exists(usersTableName)); + REQUIRE(!storage.table_exists(userNewTableName)); + REQUIRE(storage.table_exists(visitsTableName)); + REQUIRE(!storage.table_exists(visitsNewTableName)); + REQUIRE(storage.tablename() != usersTableName); + REQUIRE(storage.tablename() == userNewTableName); + REQUIRE(storage.tablename() != visitsTableName); + REQUIRE(storage.tablename() == visitsNewTableName); + } + SECTION("with 2 arguments") { + + storage.rename_table(usersTableName, userNewTableName); + REQUIRE(!storage.table_exists(usersTableName)); + REQUIRE(storage.table_exists(userNewTableName)); + REQUIRE(storage.table_exists(visitsTableName)); + REQUIRE(!storage.table_exists(visitsNewTableName)); + REQUIRE(storage.tablename() == usersTableName); + REQUIRE(storage.tablename() != userNewTableName); + REQUIRE(storage.tablename() == visitsTableName); + REQUIRE(storage.tablename() != visitsNewTableName); + + storage.rename_table(visitsTableName, visitsNewTableName); + REQUIRE(!storage.table_exists(usersTableName)); + REQUIRE(storage.table_exists(userNewTableName)); + REQUIRE(!storage.table_exists(visitsTableName)); + REQUIRE(storage.table_exists(visitsNewTableName)); + REQUIRE(storage.tablename() == usersTableName); + REQUIRE(storage.tablename() != userNewTableName); + REQUIRE(storage.tablename() == visitsTableName); + REQUIRE(storage.tablename() != visitsNewTableName); + } } From 636d706e3fa2320e7044b2801d64e92a183e8247 Mon Sep 17 00:00:00 2001 From: fnc12 Date: Sat, 27 Jun 2020 14:55:09 +0300 Subject: [PATCH 086/132] added values and unit tests --- dev/object_from_column_builder.h | 4 +- dev/statement_serializator.h | 59 ++++++++++++- dev/values.h | 22 +++++ include/sqlite_orm/sqlite_orm.h | 85 ++++++++++++++++++- tests/unique_cases/delete_with_two_fields.cpp | 18 ++++ 5 files changed, 182 insertions(+), 6 deletions(-) create mode 100644 dev/values.h create mode 100644 tests/unique_cases/delete_with_two_fields.cpp diff --git a/dev/object_from_column_builder.h b/dev/object_from_column_builder.h index 27cc5e9c9..6c45e2739 100644 --- a/dev/object_from_column_builder.h +++ b/dev/object_from_column_builder.h @@ -14,8 +14,8 @@ namespace sqlite_orm { }; /** - * This is a cute lambda replacement which is used in several places. - */ + * This is a cute lambda replacement which is used in several places. + */ template struct object_from_column_builder : object_from_column_builder_base { using object_type = O; diff --git a/dev/statement_serializator.h b/dev/statement_serializator.h index e84d21de4..940e47fef 100644 --- a/dev/statement_serializator.h +++ b/dev/statement_serializator.h @@ -15,6 +15,7 @@ #include "table_name_collector.h" #include "column_names_getter.h" #include "order_by_serializator.h" +#include "values.h" namespace sqlite_orm { @@ -480,7 +481,9 @@ namespace sqlite_orm { std::stringstream ss; auto leftString = serialize(c.l, context); ss << leftString << " " << static_cast(c) << " "; - ss << serialize(c.arg, context); + auto newContext = context; + newContext.use_parentheses = true; + ss << serialize(c.arg, newContext); return ss.str(); } }; @@ -1569,5 +1572,59 @@ namespace sqlite_orm { return static_cast(statement) + " (" + serialize(statement.column, newContext) + " )"; } }; + + template + struct statement_serializator, void> { + using statement_type = std::tuple; + + template + std::string operator()(const statement_type &statement, const C &context) const { + std::stringstream ss; + ss << '('; + auto index = 0; + const auto tupleSize = int(std::tuple_size::value); + iterate_tuple(statement, [&context, &index, &ss](auto &value) { + ss << serialize(value, context); + if(index < tupleSize - 1) { + ss << ", "; + } + ++index; + }); + ss << ')'; + return ss.str(); + } + }; + + template + struct statement_serializator, void> { + using statement_type = values_t; + + template + std::string operator()(const statement_type &statement, const C &context) const { + std::stringstream ss; + if(context.use_parentheses) { + ss << '('; + } + ss << "VALUES "; + { + auto index = 0; + auto &tuple = statement.tuple; + using tuple_type = typename std::decay::type; + const auto tupleSize = int(std::tuple_size::value); + iterate_tuple(tuple, [&context, &index, &ss](auto &value) { + ss << serialize(value, context); + if(index < tupleSize - 1) { + ss << ", "; + } + ++index; + }); + } + if(context.use_parentheses) { + ss << ')'; + } + return ss.str(); + } + }; + } } diff --git a/dev/values.h b/dev/values.h new file mode 100644 index 000000000..82ff7d0a5 --- /dev/null +++ b/dev/values.h @@ -0,0 +1,22 @@ +#pragma once + +#include +#include + +namespace sqlite_orm { + + namespace internal { + + template + struct values_t { + std::tuple tuple; + }; + + } + + template + internal::values_t values(Args... args) { + return {{std::forward(args)...}}; + } + +} diff --git a/include/sqlite_orm/sqlite_orm.h b/include/sqlite_orm/sqlite_orm.h index 216beaaa7..59a73c9e6 100644 --- a/include/sqlite_orm/sqlite_orm.h +++ b/include/sqlite_orm/sqlite_orm.h @@ -6776,8 +6776,8 @@ namespace sqlite_orm { }; /** - * This is a cute lambda replacement which is used in several places. - */ + * This is a cute lambda replacement which is used in several places. + */ template struct object_from_column_builder : object_from_column_builder_base { using object_type = O; @@ -9497,6 +9497,29 @@ namespace sqlite_orm { } } +// #include "values.h" + +#include +#include + +namespace sqlite_orm { + + namespace internal { + + template + struct values_t { + std::tuple tuple; + }; + + } + + template + internal::values_t values(Args... args) { + return {{std::forward(args)...}}; + } + +} + namespace sqlite_orm { namespace internal { @@ -9961,7 +9984,9 @@ namespace sqlite_orm { std::stringstream ss; auto leftString = serialize(c.l, context); ss << leftString << " " << static_cast(c) << " "; - ss << serialize(c.arg, context); + auto newContext = context; + newContext.use_parentheses = true; + ss << serialize(c.arg, newContext); return ss.str(); } }; @@ -11050,6 +11075,60 @@ namespace sqlite_orm { return static_cast(statement) + " (" + serialize(statement.column, newContext) + " )"; } }; + + template + struct statement_serializator, void> { + using statement_type = std::tuple; + + template + std::string operator()(const statement_type &statement, const C &context) const { + std::stringstream ss; + ss << '('; + auto index = 0; + const auto tupleSize = int(std::tuple_size::value); + iterate_tuple(statement, [&context, &index, &ss](auto &value) { + ss << serialize(value, context); + if(index < tupleSize - 1) { + ss << ", "; + } + ++index; + }); + ss << ')'; + return ss.str(); + } + }; + + template + struct statement_serializator, void> { + using statement_type = values_t; + + template + std::string operator()(const statement_type &statement, const C &context) const { + std::stringstream ss; + if(context.use_parentheses) { + ss << '('; + } + ss << "VALUES "; + { + auto index = 0; + auto &tuple = statement.tuple; + using tuple_type = typename std::decay::type; + const auto tupleSize = int(std::tuple_size::value); + iterate_tuple(tuple, [&context, &index, &ss](auto &value) { + ss << serialize(value, context); + if(index < tupleSize - 1) { + ss << ", "; + } + ++index; + }); + } + if(context.use_parentheses) { + ss << ')'; + } + return ss.str(); + } + }; + } } diff --git a/tests/unique_cases/delete_with_two_fields.cpp b/tests/unique_cases/delete_with_two_fields.cpp new file mode 100644 index 000000000..b0b670eac --- /dev/null +++ b/tests/unique_cases/delete_with_two_fields.cpp @@ -0,0 +1,18 @@ +#include +#include + +using namespace sqlite_orm; + +TEST_CASE("delete with two fields") { + struct Device { + std::string serialNumber; + std::string deviceId; + }; + auto storage = make_storage({}, + make_table("devices", + make_column("serial_number", &Device::serialNumber), + make_column("device_id", &Device::deviceId))); + storage.sync_schema(); + storage.remove_all(where(in(std::make_tuple(&Device::serialNumber, &Device::deviceId), + values(std::make_tuple("abc", "123"), std::make_tuple("def", "456"))))); +} From 559cfdbb29b7bd3d2b26f5b9c57dc2295c013503 Mon Sep 17 00:00:00 2001 From: fnc12 Date: Fri, 3 Jul 2020 21:25:04 +0300 Subject: [PATCH 087/132] fixed backup bug --- dev/storage_base.h | 3 ++- include/sqlite_orm/sqlite_orm.h | 3 ++- tests/CMakeLists.txt | 2 +- tests/statement_serializator_tests/base_types.cpp | 2 +- 4 files changed, 6 insertions(+), 4 deletions(-) diff --git a/dev/storage_base.h b/dev/storage_base.h index 8a0db2266..9c1862a11 100644 --- a/dev/storage_base.h +++ b/dev/storage_base.h @@ -274,7 +274,8 @@ namespace sqlite_orm { backup_t make_backup_to(const std::string &filename) { auto holder = std::make_unique(filename); - return {connection_ref{*holder}, "main", this->get_connection(), "main", move(holder)}; + connection_ref conRef{*holder}; + return {conRef, "main", this->get_connection(), "main", move(holder)}; } backup_t make_backup_to(storage_base &other) { diff --git a/include/sqlite_orm/sqlite_orm.h b/include/sqlite_orm/sqlite_orm.h index 59a73c9e6..e13087568 100644 --- a/include/sqlite_orm/sqlite_orm.h +++ b/include/sqlite_orm/sqlite_orm.h @@ -8828,7 +8828,8 @@ namespace sqlite_orm { backup_t make_backup_to(const std::string &filename) { auto holder = std::make_unique(filename); - return {connection_ref{*holder}, "main", this->get_connection(), "main", move(holder)}; + connection_ref conRef{*holder}; + return {conRef, "main", this->get_connection(), "main", move(holder)}; } backup_t make_backup_to(storage_base &other) { diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index cd3364951..3f8638626 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -10,7 +10,7 @@ else() add_subdirectory(third_party/sqlite) endif() -add_executable(unit_tests tests.cpp tests2.cpp tests3.cpp tests4.cpp tests5.cpp private_getters_tests.cpp pragma_tests.cpp explicit_columns.cpp core_functions_tests.cpp constraints/composite_key.cpp static_tests.cpp operators/arithmetic_operators.cpp operators/like.cpp operators/glob.cpp operators/in.cpp operators/cast.cpp operators/is_null.cpp operators/not_operator.cpp operators/bitwise.cpp dynamic_order_by.cpp prepared_statement_tests/select.cpp prepared_statement_tests/get_all.cpp prepared_statement_tests/get_all_pointer.cpp prepared_statement_tests/get_all_optional.cpp prepared_statement_tests/update_all.cpp prepared_statement_tests/remove_all.cpp prepared_statement_tests/get.cpp prepared_statement_tests/get_pointer.cpp prepared_statement_tests/get_optional.cpp prepared_statement_tests/update.cpp prepared_statement_tests/remove.cpp prepared_statement_tests/insert.cpp prepared_statement_tests/replace.cpp prepared_statement_tests/insert_range.cpp prepared_statement_tests/replace_range.cpp prepared_statement_tests/insert_explicit.cpp pragma_tests.cpp simple_query.cpp static_tests/is_bindable.cpp static_tests/arithmetic_operators_result_type.cpp static_tests/tuple_conc.cpp static_tests/node_tuple.cpp static_tests/bindable_filter.cpp static_tests/count_tuple.cpp static_tests/member_traits_tests.cpp static_tests/select_return_type.cpp constraints/default.cpp constraints/unique.cpp constraints/foreign_key.cpp constraints/check.cpp table_tests.cpp statement_serializator_tests/primary_key.cpp statement_serializator_tests/column_names.cpp statement_serializator_tests/autoincrement.cpp statement_serializator_tests/arithmetic_operators.cpp statement_serializator_tests/core_functions.cpp statement_serializator_tests/comparison_operators.cpp statement_serializator_tests/unique.cpp statement_serializator_tests/foreign_key.cpp statement_serializator_tests/collate.cpp statement_serializator_tests/check.cpp unique_cases/get_all_with_two_tables.cpp unique_cases/prepare_get_all_with_case.cpp unique_cases/index_named_table_with_fk.cpp unique_cases/issue525.cpp get_all_custom_containers.cpp select_asterisk.cpp) +add_executable(unit_tests tests.cpp tests2.cpp tests3.cpp tests4.cpp tests5.cpp private_getters_tests.cpp pragma_tests.cpp explicit_columns.cpp core_functions_tests.cpp constraints/composite_key.cpp static_tests.cpp operators/arithmetic_operators.cpp operators/like.cpp operators/glob.cpp operators/in.cpp operators/cast.cpp operators/is_null.cpp operators/not_operator.cpp operators/bitwise.cpp dynamic_order_by.cpp prepared_statement_tests/select.cpp prepared_statement_tests/get_all.cpp prepared_statement_tests/get_all_pointer.cpp prepared_statement_tests/get_all_optional.cpp prepared_statement_tests/update_all.cpp prepared_statement_tests/remove_all.cpp prepared_statement_tests/get.cpp prepared_statement_tests/get_pointer.cpp prepared_statement_tests/get_optional.cpp prepared_statement_tests/update.cpp prepared_statement_tests/remove.cpp prepared_statement_tests/insert.cpp prepared_statement_tests/replace.cpp prepared_statement_tests/insert_range.cpp prepared_statement_tests/replace_range.cpp prepared_statement_tests/insert_explicit.cpp pragma_tests.cpp simple_query.cpp static_tests/is_bindable.cpp static_tests/arithmetic_operators_result_type.cpp static_tests/tuple_conc.cpp static_tests/node_tuple.cpp static_tests/bindable_filter.cpp static_tests/count_tuple.cpp static_tests/member_traits_tests.cpp static_tests/select_return_type.cpp constraints/default.cpp constraints/unique.cpp constraints/foreign_key.cpp constraints/check.cpp table_tests.cpp statement_serializator_tests/primary_key.cpp statement_serializator_tests/column_names.cpp statement_serializator_tests/autoincrement.cpp statement_serializator_tests/arithmetic_operators.cpp statement_serializator_tests/core_functions.cpp statement_serializator_tests/comparison_operators.cpp statement_serializator_tests/unique.cpp statement_serializator_tests/foreign_key.cpp statement_serializator_tests/collate.cpp statement_serializator_tests/check.cpp unique_cases/get_all_with_two_tables.cpp unique_cases/prepare_get_all_with_case.cpp unique_cases/index_named_table_with_fk.cpp unique_cases/issue525.cpp get_all_custom_containers.cpp select_asterisk.cpp backup_tests.cpp) if(SQLITE_ORM_OMITS_CODECVT) diff --git a/tests/statement_serializator_tests/base_types.cpp b/tests/statement_serializator_tests/base_types.cpp index 910fd35ab..dbf9ff1db 100644 --- a/tests/statement_serializator_tests/base_types.cpp +++ b/tests/statement_serializator_tests/base_types.cpp @@ -9,7 +9,7 @@ TEST_CASE("statement_serializator base types") { std::string str("calma"); SECTION("no question") { auto value = serialize(str, context); - REQUIRE(value == "\'calma\'"); + REQUIRE(value == "\"calma\""); } SECTION("question") { context.replace_bindable_with_question = true; From 3be483118089e9f5b55beacccadbb55f6e4c6bd4 Mon Sep 17 00:00:00 2001 From: fnc12 Date: Sat, 4 Jul 2020 17:13:25 +0300 Subject: [PATCH 088/132] changed order of non-static members in backup_t --- dev/backup.h | 6 +++--- include/sqlite_orm/sqlite_orm.h | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/dev/backup.h b/dev/backup.h index 51c1f3196..0459b0a4c 100644 --- a/dev/backup.h +++ b/dev/backup.h @@ -24,14 +24,14 @@ namespace sqlite_orm { const std::string &zSourceName, std::unique_ptr holder_) : handle(sqlite3_backup_init(to_.get(), zDestName.c_str(), from_.get(), zSourceName.c_str())), - holder(move(holder_)), to(to_), from(from_) { + to(to_), from(from_), holder(move(holder_)) { if(!this->handle) { throw std::system_error(std::make_error_code(orm_error_code::failed_to_init_a_backup)); } } backup_t(backup_t &&other) : - handle(other.handle), holder(move(other.holder)), to(other.to), from(other.from) { + handle(other.handle), to(other.to), from(other.from), holder(move(other.holder)) { other.handle = nullptr; } @@ -65,9 +65,9 @@ namespace sqlite_orm { protected: sqlite3_backup *handle = nullptr; - std::unique_ptr holder; connection_ref to; connection_ref from; + std::unique_ptr holder; }; } } diff --git a/include/sqlite_orm/sqlite_orm.h b/include/sqlite_orm/sqlite_orm.h index e13087568..9bcb8f408 100644 --- a/include/sqlite_orm/sqlite_orm.h +++ b/include/sqlite_orm/sqlite_orm.h @@ -8528,14 +8528,14 @@ namespace sqlite_orm { const std::string &zSourceName, std::unique_ptr holder_) : handle(sqlite3_backup_init(to_.get(), zDestName.c_str(), from_.get(), zSourceName.c_str())), - holder(move(holder_)), to(to_), from(from_) { + to(to_), from(from_), holder(move(holder_)) { if(!this->handle) { throw std::system_error(std::make_error_code(orm_error_code::failed_to_init_a_backup)); } } backup_t(backup_t &&other) : - handle(other.handle), holder(move(other.holder)), to(other.to), from(other.from) { + handle(other.handle), to(other.to), from(other.from), holder(move(other.holder)) { other.handle = nullptr; } @@ -8569,9 +8569,9 @@ namespace sqlite_orm { protected: sqlite3_backup *handle = nullptr; - std::unique_ptr holder; connection_ref to; connection_ref from; + std::unique_ptr holder; }; } } From 6e477cf681b918c1311b98d05f52393dd3f4e58a Mon Sep 17 00:00:00 2001 From: fnc12 Date: Sun, 5 Jul 2020 02:58:35 +0300 Subject: [PATCH 089/132] refactored make_backup_from --- dev/storage_base.h | 3 ++- include/sqlite_orm/sqlite_orm.h | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/dev/storage_base.h b/dev/storage_base.h index 9c1862a11..d0d83e5e1 100644 --- a/dev/storage_base.h +++ b/dev/storage_base.h @@ -284,7 +284,8 @@ namespace sqlite_orm { backup_t make_backup_from(const std::string &filename) { auto holder = std::make_unique(filename); - return {this->get_connection(), "main", connection_ref{*holder}, "main", move(holder)}; + connection_ref conRef{*holder}; + return {this->get_connection(), "main", conRef, "main", move(holder)}; } backup_t make_backup_from(storage_base &other) { diff --git a/include/sqlite_orm/sqlite_orm.h b/include/sqlite_orm/sqlite_orm.h index 9bcb8f408..fd4ae897a 100644 --- a/include/sqlite_orm/sqlite_orm.h +++ b/include/sqlite_orm/sqlite_orm.h @@ -8838,7 +8838,8 @@ namespace sqlite_orm { backup_t make_backup_from(const std::string &filename) { auto holder = std::make_unique(filename); - return {this->get_connection(), "main", connection_ref{*holder}, "main", move(holder)}; + connection_ref conRef{*holder}; + return {this->get_connection(), "main", conRef, "main", move(holder)}; } backup_t make_backup_from(storage_base &other) { From 57c3b2105e8e4a74d6fd3ada25b6736a6856def3 Mon Sep 17 00:00:00 2001 From: fnc12 Date: Sun, 5 Jul 2020 14:53:36 +0300 Subject: [PATCH 090/132] added unique filename --- tests/backup_tests.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/backup_tests.cpp b/tests/backup_tests.cpp index 990692682..e20c68b38 100644 --- a/tests/backup_tests.cpp +++ b/tests/backup_tests.cpp @@ -40,7 +40,8 @@ TEST_CASE("backup") { filename, make_table(usersTableName, make_column("id", &User::id, primary_key()), make_column("name", &User::name))); }; - const std::string backupFilename = "backup.sqlite"; + static int filenameSuffix = 0; // to make an unique filename for every test + const std::string backupFilename = "backup" + std::to_string(filenameSuffix++) + ".sqlite"; SECTION("to") { ::remove(backupFilename.c_str()); auto storage2 = makeStorage(backupFilename); From ff9a8c8edff439269c71bd8d17e1d3c6f4296ca8 Mon Sep 17 00:00:00 2001 From: fnc12 Date: Thu, 9 Jul 2020 00:57:17 +0300 Subject: [PATCH 091/132] updated sqlite source link --- tests/third_party/sqlite/CMakeLists.txt | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/tests/third_party/sqlite/CMakeLists.txt b/tests/third_party/sqlite/CMakeLists.txt index d990826b8..6b583e2f9 100644 --- a/tests/third_party/sqlite/CMakeLists.txt +++ b/tests/third_party/sqlite/CMakeLists.txt @@ -1,8 +1,8 @@ cmake_minimum_required (VERSION 3.2) set(SQLITE3_ARCH_NAME "${CMAKE_CURRENT_BINARY_DIR}/sqlite.zip") -set(SQLITE3_LINK "https://www.sqlite.org/2017/sqlite-amalgamation-3210000.zip") -set(SQLITE3_ARCH_SHA1 "ebe33c20d37a715db95288010c1009cd560f2452") +set(SQLITE3_LINK "https://www.sqlite.org/2020/sqlite-amalgamation-3320300.zip") +set(SQLITE3_ARCH_SHA1 "0949c0a18d750df869003f3b2793a66012584f87") add_custom_command( OUTPUT ${SQLITE3_ARCH_NAME} @@ -10,15 +10,15 @@ add_custom_command( ${CMAKE_COMMAND} -DSQLITE3_ARCH_NAME=${SQLITE3_ARCH_NAME} -DSQLITE3_LINK=${SQLITE3_LINK} -DSQLITE3_ARCH_SHA1=${SQLITE3_ARCH_SHA1} -P "${CMAKE_CURRENT_SOURCE_DIR}/DownloadSqlite3.cmake") add_custom_command( - OUTPUT sqlite-amalgamation-3210000 sqlite-amalgamation-3210000/sqlite3.c sqlite-amalgamation-3210000/sqlite3.h + OUTPUT sqlite-amalgamation-3320300 sqlite-amalgamation-3320300/sqlite3.c sqlite-amalgamation-3320300/sqlite3.h DEPENDS ${SQLITE3_ARCH_NAME} COMMAND ${CMAKE_COMMAND} -E tar xfz ${SQLITE3_ARCH_NAME}) -add_library(sqlite3 sqlite-amalgamation-3210000/sqlite3.c) +add_library(sqlite3 sqlite-amalgamation-3320300/sqlite3.c) set(THREADS_PREFER_PTHREAD_FLAG ON) find_package(Threads REQUIRED) -target_include_directories(sqlite3 INTERFACE "${CMAKE_CURRENT_BINARY_DIR}/sqlite-amalgamation-3210000") +target_include_directories(sqlite3 INTERFACE "${CMAKE_CURRENT_BINARY_DIR}/sqlite-amalgamation-3320300") target_link_libraries(sqlite3 PRIVATE ${CMAKE_DL_LIBS} Threads::Threads) From e8a0abfe8c297732a2dea7c357db6a3843744a1a Mon Sep 17 00:00:00 2001 From: fnc12 Date: Thu, 9 Jul 2020 01:01:05 +0300 Subject: [PATCH 092/132] fixed hash --- tests/third_party/sqlite/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/third_party/sqlite/CMakeLists.txt b/tests/third_party/sqlite/CMakeLists.txt index 6b583e2f9..c792b188d 100644 --- a/tests/third_party/sqlite/CMakeLists.txt +++ b/tests/third_party/sqlite/CMakeLists.txt @@ -2,7 +2,7 @@ cmake_minimum_required (VERSION 3.2) set(SQLITE3_ARCH_NAME "${CMAKE_CURRENT_BINARY_DIR}/sqlite.zip") set(SQLITE3_LINK "https://www.sqlite.org/2020/sqlite-amalgamation-3320300.zip") -set(SQLITE3_ARCH_SHA1 "0949c0a18d750df869003f3b2793a66012584f87") +set(SQLITE3_ARCH_SHA1 "0c805bea134712a903290a26b2a61c3a8a3bd8cc") add_custom_command( OUTPUT ${SQLITE3_ARCH_NAME} From f26fe5bf9a797445b7ba0f18fdd02b0becc09c23 Mon Sep 17 00:00:00 2001 From: fnc12 Date: Thu, 9 Jul 2020 01:42:30 +0300 Subject: [PATCH 093/132] commented out hash check --- tests/operators/like.cpp | 10 ---------- tests/third_party/sqlite/DownloadSqlite3.cmake | 8 ++++---- 2 files changed, 4 insertions(+), 14 deletions(-) diff --git a/tests/operators/like.cpp b/tests/operators/like.cpp index 32a23f2a6..4d9d4c308 100644 --- a/tests/operators/like.cpp +++ b/tests/operators/like.cpp @@ -61,14 +61,4 @@ TEST_CASE("Like operator") { REQUIRE(rows.size() == 1); REQUIRE(rows.front() == false); } - { - auto rows = storage.select(like("ototo", "ototo%").escape("%")); - REQUIRE(rows.size() == 1); - REQUIRE(rows.front() == true); - } - { - auto rows = storage.select(like("ototo", "ototo%", "%")); - REQUIRE(rows.size() == 1); - REQUIRE(rows.front() == true); - } } diff --git a/tests/third_party/sqlite/DownloadSqlite3.cmake b/tests/third_party/sqlite/DownloadSqlite3.cmake index 06ebb028c..16d1f6f79 100644 --- a/tests/third_party/sqlite/DownloadSqlite3.cmake +++ b/tests/third_party/sqlite/DownloadSqlite3.cmake @@ -10,7 +10,7 @@ if(NOT SQLITE3_DOWNLOADED) endif() file(SHA1 ${SQLITE3_ARCH_NAME} SQLITE3_SHA1) -if(${SQLITE3_SHA1} STREQUAL ${SQLITE3_ARCH_SHA1}) -else() - message(FATAL_ERROR "Invalid hash: ${SQLITE3_SHA1} != ${SQLITE3_ARCH_SHA1}") -endif() +#if(${SQLITE3_SHA1} STREQUAL ${SQLITE3_ARCH_SHA1}) +#else() + #message(FATAL_ERROR "Invalid hash: ${SQLITE3_SHA1} != ${SQLITE3_ARCH_SHA1}") +#endif() From c3f6798bba0cf4507908446c177ba78625ddc306 Mon Sep 17 00:00:00 2001 From: fnc12 Date: Thu, 9 Jul 2020 23:55:16 +0300 Subject: [PATCH 094/132] commented out osx in travis config --- .travis.yml | 76 ++++++++++++++++++++++++++--------------------------- 1 file changed, 38 insertions(+), 38 deletions(-) diff --git a/.travis.yml b/.travis.yml index b5faca2d7..0d07b844a 100644 --- a/.travis.yml +++ b/.travis.yml @@ -38,18 +38,18 @@ matrix: env: - SQLITE_ORM_OMITS_CODECVT: ON - - name: "[C++14] AppleClang-10.0.1" - os: osx - osx_image: xcode10.2 - language: cpp - env: - - SQLITE_ORM_OMITS_CODECVT: ON - addons: - homebrew: - packages: - - catch2 - - ninja - update: true +# - name: "[C++14] AppleClang-10.0.1" +# os: osx +# osx_image: xcode10.2 +# language: cpp +# env: +# - SQLITE_ORM_OMITS_CODECVT: ON +# addons: +# homebrew: +# packages: +# - catch2 +# - ninja +# update: true # - name: "[C++14] LLVM/Clang (latest)" # os: osx @@ -71,19 +71,19 @@ matrix: # - CXX: /usr/local/opt/llvm/bin/clang++ # - SQLITE_ORM_OMITS_CODECVT: ON - - name: "[C++14] GCC-6" - os: osx - osx_image: xcode10.2 - addons: - homebrew: - packages: - - gcc@6 - - catch2 - - ninja - update: true - env: - - CC: gcc-6 - - CXX: g++-6 +# - name: "[C++14] GCC-6" +# os: osx +# osx_image: xcode10.2 +# addons: +# homebrew: +# packages: +# - gcc@6 +# - catch2 +# - ninja +# update: true +# env: +# - CC: gcc-6 +# - CXX: g++-6 - name: "[C++17] GCC-9" addons: @@ -111,19 +111,19 @@ matrix: - CXX: g++-7 - SQLITE_ORM_CXX_STANDARD: "-DSQLITE_ORM_ENABLE_CXX_17=ON" - - name: "[C++17] AppleClang-10.0.1" - os: osx - osx_image: xcode10.2 - language: cpp - env: - - SQLITE_ORM_OMITS_CODECVT: ON - - SQLITE_ORM_CXX_STANDARD: "-DSQLITE_ORM_ENABLE_CXX_17=ON" - addons: - homebrew: - packages: - - catch2 - - ninja - update: true +# - name: "[C++17] AppleClang-10.0.1" +# os: osx +# osx_image: xcode10.2 +# language: cpp +# env: +# - SQLITE_ORM_OMITS_CODECVT: ON +# - SQLITE_ORM_CXX_STANDARD: "-DSQLITE_ORM_ENABLE_CXX_17=ON" +# addons: +# homebrew: +# packages: +# - catch2 +# - ninja +# update: true # - name: "[C++17] LLVM/Clang (latest)" # os: osx From 6e795808b73f1a58bcfe40628484cc4600d2bc17 Mon Sep 17 00:00:00 2001 From: fnc12 Date: Thu, 9 Jul 2020 23:56:32 +0300 Subject: [PATCH 095/132] removed comments --- tests/third_party/sqlite/DownloadSqlite3.cmake | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/third_party/sqlite/DownloadSqlite3.cmake b/tests/third_party/sqlite/DownloadSqlite3.cmake index 16d1f6f79..06ebb028c 100644 --- a/tests/third_party/sqlite/DownloadSqlite3.cmake +++ b/tests/third_party/sqlite/DownloadSqlite3.cmake @@ -10,7 +10,7 @@ if(NOT SQLITE3_DOWNLOADED) endif() file(SHA1 ${SQLITE3_ARCH_NAME} SQLITE3_SHA1) -#if(${SQLITE3_SHA1} STREQUAL ${SQLITE3_ARCH_SHA1}) -#else() - #message(FATAL_ERROR "Invalid hash: ${SQLITE3_SHA1} != ${SQLITE3_ARCH_SHA1}") -#endif() +if(${SQLITE3_SHA1} STREQUAL ${SQLITE3_ARCH_SHA1}) +else() + message(FATAL_ERROR "Invalid hash: ${SQLITE3_SHA1} != ${SQLITE3_ARCH_SHA1}") +endif() From c9eb9115dd66cd5e311811901e43d33b39b27a49 Mon Sep 17 00:00:00 2001 From: fnc12 Date: Fri, 10 Jul 2020 02:53:37 +0300 Subject: [PATCH 096/132] added empty callable static function --- dev/static_magic.h | 7 ++++++- include/sqlite_orm/sqlite_orm.h | 7 ++++++- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/dev/static_magic.h b/dev/static_magic.h index 8aad18bfb..23fe1b84d 100644 --- a/dev/static_magic.h +++ b/dev/static_magic.h @@ -8,6 +8,11 @@ namespace sqlite_orm { // https://stackoverflow.com/questions/37617677/implementing-a-compile-time-static-if-logic-for-different-string-types-in-a-co namespace internal { + static inline decltype(auto) empty_callable() { + static auto res = [](auto &&...) {}; + return (res); + } + template decltype(auto) static_if(std::true_type, const T &t, const F &) { return (t); @@ -25,7 +30,7 @@ namespace sqlite_orm { template decltype(auto) static_if(const T &t) { - return static_if(std::integral_constant{}, t, [](auto &&...) {}); + return static_if(std::integral_constant{}, t, empty_callable()); } template diff --git a/include/sqlite_orm/sqlite_orm.h b/include/sqlite_orm/sqlite_orm.h index fd4ae897a..4dde78c5a 100644 --- a/include/sqlite_orm/sqlite_orm.h +++ b/include/sqlite_orm/sqlite_orm.h @@ -232,6 +232,11 @@ namespace sqlite_orm { // https://stackoverflow.com/questions/37617677/implementing-a-compile-time-static-if-logic-for-different-string-types-in-a-co namespace internal { + static inline decltype(auto) empty_callable() { + static auto res = [](auto &&...) {}; + return (res); + } + template decltype(auto) static_if(std::true_type, const T &t, const F &) { return (t); @@ -249,7 +254,7 @@ namespace sqlite_orm { template decltype(auto) static_if(const T &t) { - return static_if(std::integral_constant{}, t, [](auto &&...) {}); + return static_if(std::integral_constant{}, t, empty_callable()); } template From ecc625c3bfeee83635eed190daf7ee7ee09ea6b0 Mon Sep 17 00:00:00 2001 From: fnc12 Date: Sat, 11 Jul 2020 00:53:20 +0300 Subject: [PATCH 097/132] added dynamic_values_t --- dev/statement_serializator.h | 28 +++++++++++++ dev/values.h | 13 +++++- include/sqlite_orm/sqlite_orm.h | 41 ++++++++++++++++++- tests/unique_cases/delete_with_two_fields.cpp | 5 +++ 4 files changed, 85 insertions(+), 2 deletions(-) diff --git a/dev/statement_serializator.h b/dev/statement_serializator.h index 940e47fef..8de75baab 100644 --- a/dev/statement_serializator.h +++ b/dev/statement_serializator.h @@ -1626,5 +1626,33 @@ namespace sqlite_orm { } }; + template + struct statement_serializator, void> { + using statement_type = dynamic_values_t; + + template + std::string operator()(const statement_type &statement, const C &context) const { + std::stringstream ss; + if(context.use_parentheses) { + ss << '('; + } + ss << "VALUES "; + { + auto vectorSize = statement.vector.size(); + for(decltype(vectorSize) index = 0; index < vectorSize; ++index) { + auto &value = statement.vector[index]; + ss << serialize(value, context); + if(index < vectorSize - 1) { + ss << ", "; + } + } + } + if(context.use_parentheses) { + ss << ')'; + } + return ss.str(); + } + }; + } } diff --git a/dev/values.h b/dev/values.h index 82ff7d0a5..ed608738f 100644 --- a/dev/values.h +++ b/dev/values.h @@ -1,7 +1,8 @@ #pragma once -#include +#include // std::vector #include +#include // std::tuple namespace sqlite_orm { @@ -12,6 +13,11 @@ namespace sqlite_orm { std::tuple tuple; }; + template + struct dynamic_values_t { + std::vector vector; + }; + } template @@ -19,4 +25,9 @@ namespace sqlite_orm { return {{std::forward(args)...}}; } + template + internal::dynamic_values_t values(std::vector vector) { + return {{move(vector)}}; + } + } diff --git a/include/sqlite_orm/sqlite_orm.h b/include/sqlite_orm/sqlite_orm.h index 4dde78c5a..b8dad7a8d 100644 --- a/include/sqlite_orm/sqlite_orm.h +++ b/include/sqlite_orm/sqlite_orm.h @@ -9506,8 +9506,9 @@ namespace sqlite_orm { // #include "values.h" -#include +#include // std::vector #include +#include // std::tuple namespace sqlite_orm { @@ -9518,6 +9519,11 @@ namespace sqlite_orm { std::tuple tuple; }; + template + struct dynamic_values_t { + std::vector vector; + }; + } template @@ -9525,6 +9531,11 @@ namespace sqlite_orm { return {{std::forward(args)...}}; } + template + internal::dynamic_values_t values(std::vector vector) { + return {{move(vector)}}; + } + } namespace sqlite_orm { @@ -11136,6 +11147,34 @@ namespace sqlite_orm { } }; + template + struct statement_serializator, void> { + using statement_type = dynamic_values_t; + + template + std::string operator()(const statement_type &statement, const C &context) const { + std::stringstream ss; + if(context.use_parentheses) { + ss << '('; + } + ss << "VALUES "; + { + auto vectorSize = statement.vector.size(); + for(decltype(vectorSize) index = 0; index < vectorSize; ++index) { + auto &value = statement.vector[index]; + ss << serialize(value, context); + if(index < vectorSize - 1) { + ss << ", "; + } + } + } + if(context.use_parentheses) { + ss << ')'; + } + return ss.str(); + } + }; + } } diff --git a/tests/unique_cases/delete_with_two_fields.cpp b/tests/unique_cases/delete_with_two_fields.cpp index b0b670eac..b67142a8a 100644 --- a/tests/unique_cases/delete_with_two_fields.cpp +++ b/tests/unique_cases/delete_with_two_fields.cpp @@ -15,4 +15,9 @@ TEST_CASE("delete with two fields") { storage.sync_schema(); storage.remove_all(where(in(std::make_tuple(&Device::serialNumber, &Device::deviceId), values(std::make_tuple("abc", "123"), std::make_tuple("def", "456"))))); + + storage.remove_all( + where(in(std::make_tuple(&Device::serialNumber, &Device::deviceId), + values(std::vector>{std::make_tuple("abc", "123"), + std::make_tuple("def", "456")})))); } From 258ae5e477f6b1c0b2262b22c476cd34d3a2b1ff Mon Sep 17 00:00:00 2001 From: fnc12 Date: Tue, 21 Jul 2020 00:21:30 +0300 Subject: [PATCH 098/132] added dump for prepared statements --- dev/prepared_statement.h | 6 ++ dev/storage.h | 43 ++++++++++- dev/storage_impl.h | 41 ---------- include/sqlite_orm/sqlite_orm.h | 90 +++++++++++----------- tests/prepared_statement_tests/get_all.cpp | 8 ++ tests/prepared_statement_tests/select.cpp | 18 +++++ 6 files changed, 118 insertions(+), 88 deletions(-) diff --git a/dev/prepared_statement.h b/dev/prepared_statement.h index 3287a67dc..308c5599a 100644 --- a/dev/prepared_statement.h +++ b/dev/prepared_statement.h @@ -76,6 +76,12 @@ namespace sqlite_orm { prepared_statement_base{stmt, std::move(con_)}, t(std::move(t_)) {} }; + template + struct is_prepared_statement : std::false_type {}; + + template + struct is_prepared_statement> : std::true_type {}; + /** * T - type of object to obtain from a database */ diff --git a/dev/storage.h b/dev/storage.h index 017628b65..feff8fa79 100644 --- a/dev/storage.h +++ b/dev/storage.h @@ -527,14 +527,51 @@ namespace sqlite_orm { return this->execute(statement); } + template + typename std::enable_if::value, std::string>::type + dump(const T &preparedStatement) const { + using context_t = serializator_context; + context_t context{this->impl}; + // context.skip_table_name = false; + // context.replace_bindable_with_question = true; + return serialize(preparedStatement.t, context); + } + /** * Returns a string representation of object of a class mapped to the storage. * Type of string has json-like style. */ template - std::string dump(const O &o) { - this->assert_mapped_type(); - return this->impl.dump(o); + typename std::enable_if::value, std::string>::type + dump(const O &o) { + auto &tImpl = this->get_impl(); + std::stringstream ss; + ss << "{ "; + using pair = std::pair; + std::vector pairs; + tImpl.table.for_each_column([&pairs, &o](auto &c) { + using column_type = typename std::decay::type; + using field_type = typename column_type::field_type; + pair p{c.name, std::string()}; + if(c.member_pointer) { + p.second = field_printer()(o.*c.member_pointer); + } else { + using getter_type = typename column_type::getter_type; + field_value_holder valueHolder{((o).*(c.getter))()}; + p.second = field_printer()(valueHolder.value); + } + pairs.push_back(move(p)); + }); + for(size_t i = 0; i < pairs.size(); ++i) { + auto &p = pairs[i]; + ss << p.first << " : '" << p.second << "'"; + if(i < pairs.size() - 1) { + ss << ", "; + } else { + ss << " }"; + } + } + return ss.str(); } /** diff --git a/dev/storage_impl.h b/dev/storage_impl.h index 6a2224a5c..66e6e8430 100644 --- a/dev/storage_impl.h +++ b/dev/storage_impl.h @@ -272,42 +272,6 @@ namespace sqlite_orm { } } - template - std::string dump(const O &o, typename std::enable_if::value>::type * = nullptr) { - return this->super::dump(o, nullptr); - } - - template - std::string dump(const O &o, typename std::enable_if::value>::type * = nullptr) { - std::stringstream ss; - ss << "{ "; - using pair = std::pair; - std::vector pairs; - this->table.for_each_column([&pairs, &o](auto &c) { - using column_type = typename std::decay::type; - using field_type = typename column_type::field_type; - pair p{c.name, ""}; - if(c.member_pointer) { - p.second = field_printer()(o.*c.member_pointer); - } else { - using getter_type = typename column_type::getter_type; - field_value_holder valueHolder{((o).*(c.getter))()}; - p.second = field_printer()(valueHolder.value); - } - pairs.push_back(std::move(p)); - }); - for(size_t i = 0; i < pairs.size(); ++i) { - auto &p = pairs[i]; - ss << p.first << " : '" << p.second << "'"; - if(i < pairs.size() - 1) { - ss << ", "; - } else { - ss << " }"; - } - } - return ss.str(); - } - void add_column(const table_info &ti, sqlite3 *db) { std::stringstream ss; ss << "ALTER TABLE " << this->table.name << " ADD COLUMN " << ti.name << " "; @@ -475,11 +439,6 @@ namespace sqlite_orm { return 0; } - template - std::string dump(const O &, sqlite3 *, std::nullptr_t) { - throw std::system_error(std::make_error_code(orm_error_code::type_is_not_mapped_to_storage)); - } - template const void *find_table() const { return nullptr; diff --git a/include/sqlite_orm/sqlite_orm.h b/include/sqlite_orm/sqlite_orm.h index b8dad7a8d..014711444 100644 --- a/include/sqlite_orm/sqlite_orm.h +++ b/include/sqlite_orm/sqlite_orm.h @@ -6514,42 +6514,6 @@ namespace sqlite_orm { } } - template - std::string dump(const O &o, typename std::enable_if::value>::type * = nullptr) { - return this->super::dump(o, nullptr); - } - - template - std::string dump(const O &o, typename std::enable_if::value>::type * = nullptr) { - std::stringstream ss; - ss << "{ "; - using pair = std::pair; - std::vector pairs; - this->table.for_each_column([&pairs, &o](auto &c) { - using column_type = typename std::decay::type; - using field_type = typename column_type::field_type; - pair p{c.name, ""}; - if(c.member_pointer) { - p.second = field_printer()(o.*c.member_pointer); - } else { - using getter_type = typename column_type::getter_type; - field_value_holder valueHolder{((o).*(c.getter))()}; - p.second = field_printer()(valueHolder.value); - } - pairs.push_back(std::move(p)); - }); - for(size_t i = 0; i < pairs.size(); ++i) { - auto &p = pairs[i]; - ss << p.first << " : '" << p.second << "'"; - if(i < pairs.size() - 1) { - ss << ", "; - } else { - ss << " }"; - } - } - return ss.str(); - } - void add_column(const table_info &ti, sqlite3 *db) { std::stringstream ss; ss << "ALTER TABLE " << this->table.name << " ADD COLUMN " << ti.name << " "; @@ -6717,11 +6681,6 @@ namespace sqlite_orm { return 0; } - template - std::string dump(const O &, sqlite3 *, std::nullptr_t) { - throw std::system_error(std::make_error_code(orm_error_code::type_is_not_mapped_to_storage)); - } - template const void *find_table() const { return nullptr; @@ -7241,6 +7200,12 @@ namespace sqlite_orm { prepared_statement_base{stmt, std::move(con_)}, t(std::move(t_)) {} }; + template + struct is_prepared_statement : std::false_type {}; + + template + struct is_prepared_statement> : std::true_type {}; + /** * T - type of object to obtain from a database */ @@ -11660,14 +11625,51 @@ namespace sqlite_orm { return this->execute(statement); } + template + typename std::enable_if::value, std::string>::type + dump(const T &preparedStatement) const { + using context_t = serializator_context; + context_t context{this->impl}; + // context.skip_table_name = false; + // context.replace_bindable_with_question = true; + return serialize(preparedStatement.t, context); + } + /** * Returns a string representation of object of a class mapped to the storage. * Type of string has json-like style. */ template - std::string dump(const O &o) { - this->assert_mapped_type(); - return this->impl.dump(o); + typename std::enable_if::value, std::string>::type + dump(const O &o) { + auto &tImpl = this->get_impl(); + std::stringstream ss; + ss << "{ "; + using pair = std::pair; + std::vector pairs; + tImpl.table.for_each_column([&pairs, &o](auto &c) { + using column_type = typename std::decay::type; + using field_type = typename column_type::field_type; + pair p{c.name, std::string()}; + if(c.member_pointer) { + p.second = field_printer()(o.*c.member_pointer); + } else { + using getter_type = typename column_type::getter_type; + field_value_holder valueHolder{((o).*(c.getter))()}; + p.second = field_printer()(valueHolder.value); + } + pairs.push_back(move(p)); + }); + for(size_t i = 0; i < pairs.size(); ++i) { + auto &p = pairs[i]; + ss << p.first << " : '" << p.second << "'"; + if(i < pairs.size() - 1) { + ss << ", "; + } else { + ss << " }"; + } + } + return ss.str(); } /** diff --git a/tests/prepared_statement_tests/get_all.cpp b/tests/prepared_statement_tests/get_all.cpp index 3dbfe76f4..5f6a05614 100644 --- a/tests/prepared_statement_tests/get_all.cpp +++ b/tests/prepared_statement_tests/get_all.cpp @@ -39,6 +39,7 @@ TEST_CASE("Prepared get all") { { auto statement = storage.prepare(get_all()); + auto str = storage.dump(statement); testSerializing(statement); SECTION("nothing") { //.. @@ -54,6 +55,7 @@ TEST_CASE("Prepared get all") { } { // by var auto statement = storage.prepare(get_all(where(lesser_than(&User::id, 3)))); + auto str = storage.dump(statement); { using Statement = decltype(statement); using ExpressionType = Statement::expression_type; @@ -84,6 +86,7 @@ TEST_CASE("Prepared get all") { { // by ref auto id = 3; auto statement = storage.prepare(get_all(where(lesser_than(&User::id, std::ref(id))))); + auto str = storage.dump(statement); { using Statement = decltype(statement); using ExpressionType = Statement::expression_type; @@ -126,6 +129,7 @@ TEST_CASE("Prepared get all") { { // by val auto statement = storage.prepare( get_all(where(lesser_or_equal(&User::id, 1) and is_equal(&User::name, "Team BS")), limit(10))); + auto str = storage.dump(statement); REQUIRE(get<0>(statement) == 1); REQUIRE(strcmp(get<1>(statement), "Team BS") == 0); REQUIRE(get<2>(statement) == 10); @@ -135,6 +139,7 @@ TEST_CASE("Prepared get all") { std::string name = "Team BS"; auto statement = storage.prepare( get_all(where(lesser_or_equal(&User::id, std::ref(id)) and is_equal(&User::name, std::ref(name))))); + auto str = storage.dump(statement); REQUIRE(get<0>(statement) == 1); REQUIRE(&get<0>(statement) == &id); REQUIRE(get<1>(statement) == "Team BS"); @@ -144,6 +149,7 @@ TEST_CASE("Prepared get all") { auto statement = storage.prepare( get_all(where(lesser_or_equal(&User::id, 2) and (like(&User::name, "T%") or glob(&User::name, "*S"))), limit(20.0f))); + auto str = storage.dump(statement); REQUIRE(get<0>(statement) == 2); REQUIRE(strcmp(get<1>(statement), "T%") == 0); REQUIRE(strcmp(get<2>(statement), "*S") == 0); @@ -153,6 +159,7 @@ TEST_CASE("Prepared get all") { { { // by val auto statement = storage.prepare(get_all(where(lesser_than(&User::id, 2)))); + auto str = storage.dump(statement); std::vector expected; REQUIRE(get<0>(statement) == 2); expected.push_back(User{1, "Team BS"}); @@ -180,6 +187,7 @@ TEST_CASE("Prepared get all") { { // by ref auto id = 2; auto statement = storage.prepare(get_all(where(lesser_than(&User::id, std::ref(id))))); + auto str = storage.dump(statement); std::vector expected; REQUIRE(get<0>(statement) == 2); REQUIRE(&get<0>(statement) == &id); diff --git a/tests/prepared_statement_tests/select.cpp b/tests/prepared_statement_tests/select.cpp index 1b31c7692..97b98e1bf 100644 --- a/tests/prepared_statement_tests/select.cpp +++ b/tests/prepared_statement_tests/select.cpp @@ -40,6 +40,7 @@ TEST_CASE("Prepared select") { {// one simple argument {// by val auto statement = storage.prepare(select(10)); + auto str = storage.dump(statement); REQUIRE(get<0>(statement) == 10); { auto rows = storage.execute(statement); @@ -55,6 +56,7 @@ TEST_CASE("Prepared select") { { // by ref auto id = 10; auto statement = storage.prepare(select(std::ref(id))); + auto str = storage.dump(statement); REQUIRE(get<0>(statement) == 10); REQUIRE(&get<0>(statement) == &id); { @@ -63,6 +65,7 @@ TEST_CASE("Prepared select") { } id = 20; REQUIRE(get<0>(statement) == 20); + str = storage.dump(statement); REQUIRE(&get<0>(statement) == &id); { auto rows = storage.execute(statement); @@ -73,6 +76,7 @@ TEST_CASE("Prepared select") { {// two simple arguments {// by val auto statement = storage.prepare(select(columns("ototo", 25))); +auto str = storage.dump(statement); REQUIRE(strcmp(get<0>(statement), "ototo") == 0); REQUIRE(get<1>(statement) == 25); { @@ -84,6 +88,7 @@ REQUIRE(get<1>(statement) == 25); } get<0>(statement) = "Rock"; get<1>(statement) = -15; +str = storage.dump(statement); { auto rows = storage.execute(statement); REQUIRE(rows.size() == 1); @@ -96,6 +101,7 @@ get<1>(statement) = -15; std::string ototo = "ototo"; auto id = 25; auto statement = storage.prepare(select(columns(std::ref(ototo), std::ref(id)))); + auto str = storage.dump(statement); REQUIRE(get<0>(statement) == "ototo"); REQUIRE(&get<0>(statement) == &ototo); REQUIRE(get<1>(statement) == 25); @@ -126,6 +132,7 @@ get<1>(statement) = -15; {// by val auto statement = storage.prepare(select(columns(5.0, &User::id, count(&User::name)), where(lesser_than(&User::id, 10)))); +auto str = storage.dump(statement); REQUIRE(get<0>(statement) == 5.0); REQUIRE(get<1>(statement) == 10); { @@ -137,6 +144,7 @@ REQUIRE(get<1>(statement) == 10); } get<0>(statement) = 4; get<1>(statement) = 2; +str = storage.dump(statement); { auto rows = storage.execute(statement); REQUIRE(rows.size() == 1); @@ -150,6 +158,7 @@ get<1>(statement) = 2; auto id = 10; auto statement = storage.prepare( select(columns(std::ref(first), &User::id, count(&User::name)), where(lesser_than(&User::id, std::ref(id))))); + auto str = storage.dump(statement); REQUIRE(get<0>(statement) == 5.0); REQUIRE(&get<0>(statement) == &first); REQUIRE(get<1>(statement) == 10); @@ -164,6 +173,7 @@ get<1>(statement) = 2; first = 4; REQUIRE(&get<0>(statement) == &first); id = 2; + str = storage.dump(statement); { auto rows = storage.execute(statement); REQUIRE(rows.size() == 1); @@ -189,6 +199,7 @@ get<1>(statement) = 2; { for(auto i = 0; i < 2; ++i) { auto statement = storage.prepare(select(&User::name, order_by(&User::id))); + auto str = storage.dump(statement); testSerializing(statement); SECTION("nothing") { //.. @@ -201,6 +212,7 @@ get<1>(statement) = 2; } {{// by val auto statement = storage.prepare(select(&User::id, where(length(&User::name) > 5))); +auto str = storage.dump(statement); REQUIRE(get<0>(statement) == 5); testSerializing(statement); SECTION("nothing") { @@ -214,6 +226,7 @@ SECTION("execute") { { // by ref auto len = 5; auto statement = storage.prepare(select(&User::id, where(length(&User::name) > std::ref(len)))); + auto str = storage.dump(statement); REQUIRE(get<0>(statement) == len); REQUIRE(&get<0>(statement) == &len); testSerializing(statement); @@ -228,6 +241,7 @@ SECTION("execute") { } {{// by val auto statement = storage.prepare(select(&User::id, where(length(&User::name) > 5 and like(&User::name, "T%")))); +auto str = storage.dump(statement); REQUIRE(get<0>(statement) == 5); REQUIRE(strcmp(get<1>(statement), "T%") == 0); testSerializing(statement); @@ -244,6 +258,7 @@ SECTION("execute") { std::string pattern = "T%"; auto statement = storage.prepare( select(&User::id, where(length(&User::name) > std::ref(len) and like(&User::name, std::ref(pattern))))); + auto str = storage.dump(statement); REQUIRE(get<0>(statement) == len); REQUIRE(&get<0>(statement) == &len); REQUIRE(get<1>(statement) == pattern); @@ -260,6 +275,7 @@ SECTION("execute") { } { auto statement = storage.prepare(select(columns(&User::id, &User::name))); + auto str = storage.dump(statement); testSerializing(statement); SECTION("nothing") { //.. @@ -277,6 +293,7 @@ SECTION("execute") { { // by val auto statement = storage.prepare( select(columns(&User::name, &User::id), where(is_equal(mod(&User::id, 2), 0)), order_by(&User::name))); + auto str = storage.dump(statement); testSerializing(statement); SECTION("nothing") { //.. @@ -294,6 +311,7 @@ SECTION("execute") { auto statement = storage.prepare(select(columns(&User::name, &User::id), where(is_equal(mod(&User::id, std::ref(m)), std::ref(v))), order_by(&User::name))); + auto str = storage.dump(statement); testSerializing(statement); REQUIRE(get<0>(statement) == m); REQUIRE(&get<0>(statement) == &m); From df3622209d50ed818f33a04ac791bcce94a63df9 Mon Sep 17 00:00:00 2001 From: fnc12 Date: Tue, 21 Jul 2020 00:25:36 +0300 Subject: [PATCH 099/132] removed commented lines --- dev/storage.h | 2 -- include/sqlite_orm/sqlite_orm.h | 2 -- 2 files changed, 4 deletions(-) diff --git a/dev/storage.h b/dev/storage.h index feff8fa79..5012c998a 100644 --- a/dev/storage.h +++ b/dev/storage.h @@ -532,8 +532,6 @@ namespace sqlite_orm { dump(const T &preparedStatement) const { using context_t = serializator_context; context_t context{this->impl}; - // context.skip_table_name = false; - // context.replace_bindable_with_question = true; return serialize(preparedStatement.t, context); } diff --git a/include/sqlite_orm/sqlite_orm.h b/include/sqlite_orm/sqlite_orm.h index 014711444..3ac2a6661 100644 --- a/include/sqlite_orm/sqlite_orm.h +++ b/include/sqlite_orm/sqlite_orm.h @@ -11630,8 +11630,6 @@ namespace sqlite_orm { dump(const T &preparedStatement) const { using context_t = serializator_context; context_t context{this->impl}; - // context.skip_table_name = false; - // context.replace_bindable_with_question = true; return serialize(preparedStatement.t, context); } From 41cedd17dc40b8fd675abcb920e87926927c4276 Mon Sep 17 00:00:00 2001 From: fnc12 Date: Sat, 25 Jul 2020 17:14:50 +0300 Subject: [PATCH 100/132] added template keyword --- dev/column.h | 6 +++--- include/sqlite_orm/sqlite_orm.h | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/dev/column.h b/dev/column.h index b42ce4a0a..1b397fce0 100644 --- a/dev/column.h +++ b/dev/column.h @@ -152,7 +152,7 @@ namespace sqlite_orm { class... Op> internal::column_t make_column(const std::string &name, T O::*m, Op... constraints) { - static_assert(constraints::constraints_size::value == std::tuple_size>::value, + static_assert(constraints::template constraints_size::value == std::tuple_size>::value, "Incorrect constraints pack"); static_assert(internal::is_field_member_pointer::value, "second argument expected as a member field pointer, not member function pointer"); @@ -176,7 +176,7 @@ namespace sqlite_orm { static_assert(std::is_same::field_type, typename internal::getter_traits::field_type>::value, "Getter and setter must get and set same data type"); - static_assert(constraints::constraints_size::value == std::tuple_size>::value, + static_assert(constraints::template constraints_size::value == std::tuple_size>::value, "Incorrect constraints pack"); return {name, nullptr, getter, setter, std::make_tuple(constraints...)}; } @@ -199,7 +199,7 @@ namespace sqlite_orm { static_assert(std::is_same::field_type, typename internal::getter_traits::field_type>::value, "Getter and setter must get and set same data type"); - static_assert(constraints::constraints_size::value == std::tuple_size>::value, + static_assert(constraints::template constraints_size::value == std::tuple_size>::value, "Incorrect constraints pack"); return {name, nullptr, getter, setter, std::make_tuple(constraints...)}; } diff --git a/include/sqlite_orm/sqlite_orm.h b/include/sqlite_orm/sqlite_orm.h index 3ac2a6661..564c56ab8 100644 --- a/include/sqlite_orm/sqlite_orm.h +++ b/include/sqlite_orm/sqlite_orm.h @@ -1720,7 +1720,7 @@ namespace sqlite_orm { class... Op> internal::column_t make_column(const std::string &name, T O::*m, Op... constraints) { - static_assert(constraints::constraints_size::value == std::tuple_size>::value, + static_assert(constraints::template constraints_size::value == std::tuple_size>::value, "Incorrect constraints pack"); static_assert(internal::is_field_member_pointer::value, "second argument expected as a member field pointer, not member function pointer"); @@ -1744,7 +1744,7 @@ namespace sqlite_orm { static_assert(std::is_same::field_type, typename internal::getter_traits::field_type>::value, "Getter and setter must get and set same data type"); - static_assert(constraints::constraints_size::value == std::tuple_size>::value, + static_assert(constraints::template constraints_size::value == std::tuple_size>::value, "Incorrect constraints pack"); return {name, nullptr, getter, setter, std::make_tuple(constraints...)}; } @@ -1767,7 +1767,7 @@ namespace sqlite_orm { static_assert(std::is_same::field_type, typename internal::getter_traits::field_type>::value, "Getter and setter must get and set same data type"); - static_assert(constraints::constraints_size::value == std::tuple_size>::value, + static_assert(constraints::template constraints_size::value == std::tuple_size>::value, "Incorrect constraints pack"); return {name, nullptr, getter, setter, std::make_tuple(constraints...)}; } From ffda7dcea6f0d6d2d3b4b78d3c8f1f326ebca43f Mon Sep 17 00:00:00 2001 From: air-h-128k-il Date: Sun, 26 Jul 2020 04:35:40 +0900 Subject: [PATCH 101/132] rm compile folder --- .gitignore | 2 ++ README.md | 3 ++- prepare-osx-with-clang.sh | 2 +- 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/.gitignore b/.gitignore index a2c5a7b71..f5cff1a34 100644 --- a/.gitignore +++ b/.gitignore @@ -4,3 +4,5 @@ examples/simple_neural_network.cpp cmake-build-debug/ .idea/ + +/compile diff --git a/README.md b/README.md index f6803016b..d7a374ef3 100644 --- a/README.md +++ b/README.md @@ -758,7 +758,8 @@ For more details please check the project [wiki](https://github.com/fnc12/sqlite Use popular package manager like [vcpkg](https://github.com/Microsoft/vcpkg) and just install it with `vcpkg install sqlite-orm` command. -Or you can use below instructions +Or you can use below instructions +Note: If you build on Mac OSX, you need to install Catch2 project prior to the following installation ```bash git clone https://github.com/fnc12/sqlite_orm.git sqlite_orm diff --git a/prepare-osx-with-clang.sh b/prepare-osx-with-clang.sh index 267cc3253..c824f65d2 100755 --- a/prepare-osx-with-clang.sh +++ b/prepare-osx-with-clang.sh @@ -6,4 +6,4 @@ set -e brew install llvm brew info llvm export PATH="/usr/local/opt/llvm/bin:$PATH" -echo 'export PATH="/usr/local/opt/llvm/bin:$PATH"' >> ~/.bash_profile +echo 'export PATH="/usr/local/opt/llvm/bin:$PATH"' >> ~/.zshenv From 3a543f000f2c8a87620242e03c4866608aa5ad9a Mon Sep 17 00:00:00 2001 From: fnc12 Date: Sat, 1 Aug 2020 01:53:45 +0300 Subject: [PATCH 102/132] removed sqlite type and its comparison --- dev/column_result.h | 3 + dev/sqlite_type.h | 86 -------------------- dev/storage_impl.h | 31 +++----- include/sqlite_orm/sqlite_orm.h | 121 ++++------------------------- tests/type_parsing.cpp | 81 ------------------- third_party/amalgamate/config.json | 1 - 6 files changed, 26 insertions(+), 297 deletions(-) delete mode 100644 dev/sqlite_type.h delete mode 100644 tests/type_parsing.cpp diff --git a/dev/column_result.h b/dev/column_result.h index 37f4930c3..a6af11a1f 100644 --- a/dev/column_result.h +++ b/dev/column_result.h @@ -14,6 +14,9 @@ namespace sqlite_orm { + using int64 = sqlite_int64; + using uint64 = sqlite_uint64; + namespace internal { /** diff --git a/dev/sqlite_type.h b/dev/sqlite_type.h deleted file mode 100644 index d2a1eece5..000000000 --- a/dev/sqlite_type.h +++ /dev/null @@ -1,86 +0,0 @@ -#pragma once - -#include // std::map -#include // std::string -#include // std::regex, std::regex_match -#include // std::make_unique, std::unique_ptr -#include // std::vector -#include // std::toupper - -namespace sqlite_orm { - using int64 = sqlite_int64; - using uint64 = sqlite_uint64; - - // numeric and real are the same for c++ - enum class sqlite_type { - INTEGER, - TEXT, - BLOB, - REAL, - }; - - /** - * @param str case doesn't matter - it is uppercased before comparing. - */ - inline std::unique_ptr to_sqlite_type(const std::string &str) { - auto asciiStringToUpper = [](std::string &s) { - std::transform(s.begin(), s.end(), s.begin(), [](char c) { - return static_cast(std::toupper(static_cast(c))); - }); - }; - auto upperStr = str; - asciiStringToUpper(upperStr); - - static std::map> typeMap = { - {sqlite_type::INTEGER, - { - std::regex("INT"), - std::regex("INT.*"), - std::regex("TINYINT"), - std::regex("SMALLINT"), - std::regex("MEDIUMINT"), - std::regex("BIGINT"), - std::regex("UNSIGNED BIG INT"), - std::regex("INT2"), - std::regex("INT8"), - std::regex("UNSIGNED\\s+INT\\([[:digit:]]+\\)"), - }}, - {sqlite_type::TEXT, - { - std::regex("CHARACTER\\([[:digit:]]+\\)"), - std::regex("VARCHAR\\([[:digit:]]+\\)"), - std::regex("VARYING CHARACTER\\([[:digit:]]+\\)"), - std::regex("NCHAR\\([[:digit:]]+\\)"), - std::regex("NATIVE CHARACTER\\([[:digit:]]+\\)"), - std::regex("NVARCHAR\\([[:digit:]]+\\)"), - std::regex("CLOB"), - std::regex("TEXT"), - }}, - {sqlite_type::BLOB, - { - std::regex("BLOB"), - }}, - {sqlite_type::REAL, - { - std::regex("REAL"), - std::regex("DOUBLE"), - std::regex("DOUBLE PRECISION"), - std::regex("FLOAT"), - std::regex("NUMERIC"), - std::regex("DECIMAL\\([[:digit:]]+,[[:digit:]]+\\)"), - std::regex("BOOLEAN"), - std::regex("DATE"), - std::regex("DATETIME"), - }}, - }; - for(auto &p: typeMap) { - for(auto &r: p.second) { - if(std::regex_match(upperStr, r)) { - return std::make_unique(p.first); - } - } - } - - return {}; - } -} diff --git a/dev/storage_impl.h b/dev/storage_impl.h index 66e6e8430..8af7a9efd 100644 --- a/dev/storage_impl.h +++ b/dev/storage_impl.h @@ -20,7 +20,6 @@ #include "field_printer.h" #include "table_info.h" #include "sync_schema_result.h" -#include "sqlite_type.h" #include "field_value_holder.h" namespace sqlite_orm { @@ -93,29 +92,19 @@ namespace sqlite_orm { }); if(dbColumnInfoIt != dbTableInfo.end()) { auto &dbColumnInfo = *dbColumnInfoIt; - auto dbColumnInfoType = to_sqlite_type(dbColumnInfo.type); - auto storageColumnInfoType = to_sqlite_type(storageColumnInfo.type); - if(dbColumnInfoType && storageColumnInfoType) { - auto columnsAreEqual = - dbColumnInfo.name == storageColumnInfo.name && - *dbColumnInfoType == *storageColumnInfoType && - dbColumnInfo.notnull == storageColumnInfo.notnull && - (dbColumnInfo.dflt_value.length() > 0) == (storageColumnInfo.dflt_value.length() > 0) && - dbColumnInfo.pk == storageColumnInfo.pk; - if(!columnsAreEqual) { - notEqual = true; - break; - } - dbTableInfo.erase(dbColumnInfoIt); - storageTableInfo.erase(storageTableInfo.begin() + - static_cast(storageColumnInfoIndex)); - --storageColumnInfoIndex; - } else { - - // undefined type/types + auto columnsAreEqual = + dbColumnInfo.name == storageColumnInfo.name && + dbColumnInfo.notnull == storageColumnInfo.notnull && + (dbColumnInfo.dflt_value.length() > 0) == (storageColumnInfo.dflt_value.length() > 0) && + dbColumnInfo.pk == storageColumnInfo.pk; + if(!columnsAreEqual) { notEqual = true; break; } + dbTableInfo.erase(dbColumnInfoIt); + storageTableInfo.erase(storageTableInfo.begin() + + static_cast(storageColumnInfoIndex)); + --storageColumnInfoIndex; } else { columnsToAdd.push_back(&storageColumnInfo); } diff --git a/include/sqlite_orm/sqlite_orm.h b/include/sqlite_orm/sqlite_orm.h index 564c56ab8..f29a87448 100644 --- a/include/sqlite_orm/sqlite_orm.h +++ b/include/sqlite_orm/sqlite_orm.h @@ -133,92 +133,6 @@ namespace std { } #pragma once -#include // std::map -#include // std::string -#include // std::regex, std::regex_match -#include // std::make_unique, std::unique_ptr -#include // std::vector -#include // std::toupper - -namespace sqlite_orm { - using int64 = sqlite_int64; - using uint64 = sqlite_uint64; - - // numeric and real are the same for c++ - enum class sqlite_type { - INTEGER, - TEXT, - BLOB, - REAL, - }; - - /** - * @param str case doesn't matter - it is uppercased before comparing. - */ - inline std::unique_ptr to_sqlite_type(const std::string &str) { - auto asciiStringToUpper = [](std::string &s) { - std::transform(s.begin(), s.end(), s.begin(), [](char c) { - return static_cast(std::toupper(static_cast(c))); - }); - }; - auto upperStr = str; - asciiStringToUpper(upperStr); - - static std::map> typeMap = { - {sqlite_type::INTEGER, - { - std::regex("INT"), - std::regex("INT.*"), - std::regex("TINYINT"), - std::regex("SMALLINT"), - std::regex("MEDIUMINT"), - std::regex("BIGINT"), - std::regex("UNSIGNED BIG INT"), - std::regex("INT2"), - std::regex("INT8"), - std::regex("UNSIGNED\\s+INT\\([[:digit:]]+\\)"), - }}, - {sqlite_type::TEXT, - { - std::regex("CHARACTER\\([[:digit:]]+\\)"), - std::regex("VARCHAR\\([[:digit:]]+\\)"), - std::regex("VARYING CHARACTER\\([[:digit:]]+\\)"), - std::regex("NCHAR\\([[:digit:]]+\\)"), - std::regex("NATIVE CHARACTER\\([[:digit:]]+\\)"), - std::regex("NVARCHAR\\([[:digit:]]+\\)"), - std::regex("CLOB"), - std::regex("TEXT"), - }}, - {sqlite_type::BLOB, - { - std::regex("BLOB"), - }}, - {sqlite_type::REAL, - { - std::regex("REAL"), - std::regex("DOUBLE"), - std::regex("DOUBLE PRECISION"), - std::regex("FLOAT"), - std::regex("NUMERIC"), - std::regex("DECIMAL\\([[:digit:]]+,[[:digit:]]+\\)"), - std::regex("BOOLEAN"), - std::regex("DATE"), - std::regex("DATETIME"), - }}, - }; - for(auto &p: typeMap) { - for(auto &r: p.second) { - if(std::regex_match(upperStr, r)) { - return std::make_unique(p.first); - } - } - } - - return {}; - } -} -#pragma once - #include // std::tuple, std::get #include // std::false_type, std::true_type @@ -5673,6 +5587,9 @@ namespace sqlite_orm { namespace sqlite_orm { + using int64 = sqlite_int64; + using uint64 = sqlite_uint64; + namespace internal { /** @@ -6235,8 +6152,6 @@ namespace sqlite_orm { // #include "sync_schema_result.h" -// #include "sqlite_type.h" - // #include "field_value_holder.h" #include // std::enable_if @@ -6335,29 +6250,19 @@ namespace sqlite_orm { }); if(dbColumnInfoIt != dbTableInfo.end()) { auto &dbColumnInfo = *dbColumnInfoIt; - auto dbColumnInfoType = to_sqlite_type(dbColumnInfo.type); - auto storageColumnInfoType = to_sqlite_type(storageColumnInfo.type); - if(dbColumnInfoType && storageColumnInfoType) { - auto columnsAreEqual = - dbColumnInfo.name == storageColumnInfo.name && - *dbColumnInfoType == *storageColumnInfoType && - dbColumnInfo.notnull == storageColumnInfo.notnull && - (dbColumnInfo.dflt_value.length() > 0) == (storageColumnInfo.dflt_value.length() > 0) && - dbColumnInfo.pk == storageColumnInfo.pk; - if(!columnsAreEqual) { - notEqual = true; - break; - } - dbTableInfo.erase(dbColumnInfoIt); - storageTableInfo.erase(storageTableInfo.begin() + - static_cast(storageColumnInfoIndex)); - --storageColumnInfoIndex; - } else { - - // undefined type/types + auto columnsAreEqual = + dbColumnInfo.name == storageColumnInfo.name && + dbColumnInfo.notnull == storageColumnInfo.notnull && + (dbColumnInfo.dflt_value.length() > 0) == (storageColumnInfo.dflt_value.length() > 0) && + dbColumnInfo.pk == storageColumnInfo.pk; + if(!columnsAreEqual) { notEqual = true; break; } + dbTableInfo.erase(dbColumnInfoIt); + storageTableInfo.erase(storageTableInfo.begin() + + static_cast(storageColumnInfoIndex)); + --storageColumnInfoIndex; } else { columnsToAdd.push_back(&storageColumnInfo); } diff --git a/tests/type_parsing.cpp b/tests/type_parsing.cpp deleted file mode 100644 index 1490f3907..000000000 --- a/tests/type_parsing.cpp +++ /dev/null @@ -1,81 +0,0 @@ -#include -#include - -using namespace sqlite_orm; - -TEST_CASE("Type parsing") { - using namespace sqlite_orm::internal; - - // int - REQUIRE(*to_sqlite_type("INT") == sqlite_type::INTEGER); - REQUIRE(*to_sqlite_type("integeer") == sqlite_type::INTEGER); - REQUIRE(*to_sqlite_type("INTEGER") == sqlite_type::INTEGER); - REQUIRE(*to_sqlite_type("TINYINT") == sqlite_type::INTEGER); - REQUIRE(*to_sqlite_type("SMALLINT") == sqlite_type::INTEGER); - REQUIRE(*to_sqlite_type("MEDIUMINT") == sqlite_type::INTEGER); - REQUIRE(*to_sqlite_type("BIGINT") == sqlite_type::INTEGER); - REQUIRE(*to_sqlite_type("UNSIGNED BIG INT") == sqlite_type::INTEGER); - REQUIRE(*to_sqlite_type("INT2") == sqlite_type::INTEGER); - REQUIRE(*to_sqlite_type("INT8") == sqlite_type::INTEGER); - REQUIRE(*to_sqlite_type("UNSIGNED INT(6)") == sqlite_type::INTEGER); - REQUIRE(*to_sqlite_type("UNSIGNED INT(4)") == sqlite_type::INTEGER); - - // text - REQUIRE(*to_sqlite_type("TEXT") == sqlite_type::TEXT); - REQUIRE(*to_sqlite_type("CLOB") == sqlite_type::TEXT); - for(auto i = 0; i < 255; ++i) { - REQUIRE(*to_sqlite_type("CHARACTER(" + std::to_string(i) + ")") == sqlite_type::TEXT); - REQUIRE(*to_sqlite_type("VARCHAR(" + std::to_string(i) + ")") == sqlite_type::TEXT); - REQUIRE(*to_sqlite_type("VARYING CHARACTER(" + std::to_string(i) + ")") == sqlite_type::TEXT); - REQUIRE(*to_sqlite_type("NCHAR(" + std::to_string(i) + ")") == sqlite_type::TEXT); - REQUIRE(*to_sqlite_type("NATIVE CHARACTER(" + std::to_string(i) + ")") == sqlite_type::TEXT); - REQUIRE(*to_sqlite_type("NVARCHAR(" + std::to_string(i) + ")") == sqlite_type::TEXT); - } - - // blob.. - REQUIRE(*to_sqlite_type("BLOB") == sqlite_type::BLOB); - - // real - REQUIRE(*to_sqlite_type("REAL") == sqlite_type::REAL); - REQUIRE(*to_sqlite_type("DOUBLE") == sqlite_type::REAL); - REQUIRE(*to_sqlite_type("DOUBLE PRECISION") == sqlite_type::REAL); - REQUIRE(*to_sqlite_type("FLOAT") == sqlite_type::REAL); - - REQUIRE(*to_sqlite_type("NUMERIC") == sqlite_type::REAL); - for(auto i = 0; i < 255; ++i) { - for(auto j = 0; j < 10; ++j) { - REQUIRE(*to_sqlite_type("DECIMAL(" + std::to_string(i) + "," + std::to_string(j) + ")") == - sqlite_type::REAL); - } - } - REQUIRE(*to_sqlite_type("BOOLEAN") == sqlite_type::REAL); - REQUIRE(*to_sqlite_type("DATE") == sqlite_type::REAL); - REQUIRE(*to_sqlite_type("DATETIME") == sqlite_type::REAL); - - REQUIRE(type_is_nullable::value == false); - REQUIRE(type_is_nullable::value == false); - REQUIRE(type_is_nullable::value == false); - REQUIRE(type_is_nullable::value == false); - REQUIRE(type_is_nullable::value == false); - REQUIRE(type_is_nullable::value == false); - REQUIRE(type_is_nullable::value == false); - REQUIRE(type_is_nullable::value == false); - REQUIRE(type_is_nullable::value == false); - REQUIRE(type_is_nullable::value == false); - REQUIRE(type_is_nullable::value == false); - REQUIRE(type_is_nullable::value == false); - REQUIRE(type_is_nullable::value == false); - REQUIRE(type_is_nullable::value == false); - REQUIRE(type_is_nullable::value == false); - REQUIRE(type_is_nullable::value == false); - REQUIRE(type_is_nullable::value == false); - REQUIRE(type_is_nullable>::value == true); - REQUIRE(type_is_nullable>::value == true); - REQUIRE(type_is_nullable>::value == true); - REQUIRE(type_is_nullable>::value == true); - -#ifdef SQLITE_ORM_OPTIONAL_SUPPORTED - REQUIRE(type_is_nullable>::value == true); - REQUIRE(type_is_nullable>::value == true); -#endif // SQLITE_ORM_OPTIONAL_SUPPORTED -} diff --git a/third_party/amalgamate/config.json b/third_party/amalgamate/config.json index 65093054e..d9dfc9c54 100755 --- a/third_party/amalgamate/config.json +++ b/third_party/amalgamate/config.json @@ -4,7 +4,6 @@ "sources": [ "dev/start_macros.h", "dev/error_code.h", - "dev/sqlite_type.h", "dev/tuple_helper.h", "dev/type_printer.h", "dev/collate_argument.h", From 7ead019840cb2c0c12efbadbe0ee288953d54271 Mon Sep 17 00:00:00 2001 From: fnc12 Date: Sat, 1 Aug 2020 13:05:06 +0300 Subject: [PATCH 103/132] fixed include --- dev/journal_mode.h | 2 +- include/sqlite_orm/sqlite_orm.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/dev/journal_mode.h b/dev/journal_mode.h index c6079a2a3..06811e8e2 100644 --- a/dev/journal_mode.h +++ b/dev/journal_mode.h @@ -4,7 +4,7 @@ #include // std::unique_ptr #include // std::array #include // std::transform -#include // std::toupper +#include // std::toupper namespace sqlite_orm { diff --git a/include/sqlite_orm/sqlite_orm.h b/include/sqlite_orm/sqlite_orm.h index f29a87448..45922cfd8 100644 --- a/include/sqlite_orm/sqlite_orm.h +++ b/include/sqlite_orm/sqlite_orm.h @@ -4937,7 +4937,7 @@ namespace sqlite_orm { #include // std::unique_ptr #include // std::array #include // std::transform -#include // std::toupper +#include // std::toupper namespace sqlite_orm { From 1699a0b6c5efaf7aeace0f6bbfc6609244ce03be Mon Sep 17 00:00:00 2001 From: fnc12 Date: Sat, 1 Aug 2020 13:34:57 +0300 Subject: [PATCH 104/132] fixed headers again --- dev/statement_binder.h | 3 ++- include/sqlite_orm/sqlite_orm.h | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/dev/statement_binder.h b/dev/statement_binder.h index 4ca80ca95..b9895702e 100644 --- a/dev/statement_binder.h +++ b/dev/statement_binder.h @@ -4,11 +4,12 @@ #include // std::enable_if_t, std::is_arithmetic, std::is_same, std::true_type, std::false_type #include // std::string, std::wstring #ifndef SQLITE_ORM_OMITS_CODECVT -#include // std::wstring_convert, std::codecvt_utf8_utf16 +#include // std::codecvt_utf8_utf16 #endif // SQLITE_ORM_OMITS_CODECVT #include // std::vector #include // std::nullptr_t #include // std::declval +#include // std::wstring_convert #include "is_std_ptr.h" diff --git a/include/sqlite_orm/sqlite_orm.h b/include/sqlite_orm/sqlite_orm.h index 45922cfd8..06eefe369 100644 --- a/include/sqlite_orm/sqlite_orm.h +++ b/include/sqlite_orm/sqlite_orm.h @@ -4688,11 +4688,12 @@ namespace sqlite_orm { #include // std::enable_if_t, std::is_arithmetic, std::is_same, std::true_type, std::false_type #include // std::string, std::wstring #ifndef SQLITE_ORM_OMITS_CODECVT -#include // std::wstring_convert, std::codecvt_utf8_utf16 +#include // std::codecvt_utf8_utf16 #endif // SQLITE_ORM_OMITS_CODECVT #include // std::vector #include // std::nullptr_t #include // std::declval +#include // std::wstring_convert // #include "is_std_ptr.h" From 95617442b0c5bcc561b6cbbec35946f62d0b554b Mon Sep 17 00:00:00 2001 From: Leon De Andrade Date: Sat, 1 Aug 2020 15:23:11 +0200 Subject: [PATCH 105/132] Add sqlite3 and catch2 dependencies --- CMakeLists.txt | 15 +++++++++++---- build/cmake/SqliteOrmConfig.cmake.in | 3 +++ dependencies/CMakeLists.txt | 13 +++++++++++++ dependencies/catch2/CMakeLists.txt | 1 + dependencies/sqlite3/CMakeLists.txt | 2 ++ tests/CMakeLists.txt | 5 +---- 6 files changed, 31 insertions(+), 8 deletions(-) create mode 100644 dependencies/CMakeLists.txt create mode 100644 dependencies/catch2/CMakeLists.txt create mode 100644 dependencies/sqlite3/CMakeLists.txt diff --git a/CMakeLists.txt b/CMakeLists.txt index 5ffbdf3d3..252275d27 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -23,12 +23,15 @@ set(PACKAGE_VERSION ${sqlite_orm_VERSION}) project("sqlite_orm" VERSION ${PACKAGE_VERSION}) + set(CMAKE_VERBOSE_MAKEFILE ON) message(STATUS "Configuring ${CMAKE_PROJECT_NAME} ${sqlite_orm_VERSION}") set(CMAKE_MODULE_PATH "${CMAKE_MODULE_PATH}" "${CMAKE_CURRENT_SOURCE_DIR}/build/cmake") +include(CTest) + # Build time options are defined here include(DefineInstallationPaths) @@ -37,10 +40,16 @@ include(GenerateConfigModule) set(ProjectName "SqliteOrm") -option(SqliteOrm_BuildTests "Build sqlite_orm unit tests" ON) +### Dependencies +add_subdirectory(dependencies) +### Main Build Targets set(SqliteOrm_INCLUDE "${CMAKE_CURRENT_SOURCE_DIR}/include") add_library(sqlite_orm INTERFACE) +add_library(sqlite_orm::sqlite_orm ALIAS sqlite_orm) + +find_package(SQLite3 REQUIRED) +target_link_libraries(sqlite_orm INTERFACE SQLite::SQLite3) target_sources(sqlite_orm INTERFACE $ @@ -69,9 +78,7 @@ ucm_print_flags() message(STATUS "CMAKE_BUILD_TYPE: ${CMAKE_BUILD_TYPE}") # Tests -include(CTest) -if(SqliteOrm_BuildTests AND BUILD_TESTING) - enable_testing() +if(CMAKE_PROJECT_NAME STREQUAL PROJECT_NAME AND BUILD_TESTING) add_subdirectory(tests) endif() diff --git a/build/cmake/SqliteOrmConfig.cmake.in b/build/cmake/SqliteOrmConfig.cmake.in index a6b6f20b9..bf0253798 100644 --- a/build/cmake/SqliteOrmConfig.cmake.in +++ b/build/cmake/SqliteOrmConfig.cmake.in @@ -1,5 +1,8 @@ set(SQLITE_ORM_VERSION ${sqlite_orm_VERSION}) +include(CMakeFindDependencyMacro) +find_dependency(SQLite3) + @PACKAGE_INIT@ set_and_check(SQLITE_ORM_INCLUDE_DIR "@PACKAGE_INCLUDE_INSTALL_DIR@") diff --git a/dependencies/CMakeLists.txt b/dependencies/CMakeLists.txt new file mode 100644 index 000000000..376ede119 --- /dev/null +++ b/dependencies/CMakeLists.txt @@ -0,0 +1,13 @@ +include(FetchContent) + +if(CMAKE_PROJECT_NAME STREQUAL PROJECT_NAME AND BUILD_TESTING) + FetchContent_Declare( + catch2 + GIT_REPOSITORY https://github.com/catchorg/Catch2.git + ) +endif() + +if(CMAKE_PROJECT_NAME STREQUAL PROJECT_NAME AND BUILD_TESTING) + add_subdirectory(catch2) +endif() +add_subdirectory(sqlite3) \ No newline at end of file diff --git a/dependencies/catch2/CMakeLists.txt b/dependencies/catch2/CMakeLists.txt new file mode 100644 index 000000000..e5b14fd79 --- /dev/null +++ b/dependencies/catch2/CMakeLists.txt @@ -0,0 +1 @@ +FetchContent_MakeAvailable(catch2) \ No newline at end of file diff --git a/dependencies/sqlite3/CMakeLists.txt b/dependencies/sqlite3/CMakeLists.txt new file mode 100644 index 000000000..028c757ed --- /dev/null +++ b/dependencies/sqlite3/CMakeLists.txt @@ -0,0 +1,2 @@ +# find_package exposes targets only globally, but caches them. So call find_package again in the directory of usage +find_package(SQLite3 REQUIRED) \ No newline at end of file diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 3f8638626..a813d1816 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -18,10 +18,7 @@ if(SQLITE_ORM_OMITS_CODECVT) target_compile_definitions(unit_tests PRIVATE SQLITE_ORM_OMITS_CODECVT=1) endif() -find_package(Catch2 REQUIRED) -target_link_libraries(unit_tests PRIVATE sqlite_orm sqlite3 Catch2::Catch2) - -enable_testing() +target_link_libraries(unit_tests PRIVATE sqlite_orm Catch2::Catch2) add_test(NAME "All_in_one_unit_test" COMMAND unit_tests From 57e0f6a15c46fe74e6a14eeb02c8f8a7c17e7a74 Mon Sep 17 00:00:00 2001 From: Leon De Andrade Date: Sat, 1 Aug 2020 15:27:28 +0200 Subject: [PATCH 106/132] Add example --- CMakeLists.txt | 5 +- examples/fetch_content/CMakeLists.txt | 14 ++++++ .../fetch_content/dependencies/CMakeLists.txt | 8 ++++ .../dependencies/sqlite_orm/CMakeLists.txt | 1 + examples/fetch_content/src/CMakeLists.txt | 7 +++ examples/fetch_content/src/main.cpp | 46 +++++++++++++++++++ 6 files changed, 80 insertions(+), 1 deletion(-) create mode 100644 examples/fetch_content/CMakeLists.txt create mode 100644 examples/fetch_content/dependencies/CMakeLists.txt create mode 100644 examples/fetch_content/dependencies/sqlite_orm/CMakeLists.txt create mode 100644 examples/fetch_content/src/CMakeLists.txt create mode 100644 examples/fetch_content/src/main.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 252275d27..12fae5c11 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -82,7 +82,10 @@ if(CMAKE_PROJECT_NAME STREQUAL PROJECT_NAME AND BUILD_TESTING) add_subdirectory(tests) endif() -add_subdirectory(examples) +option(BUILD_EXAMPLES ON) +if(CMAKE_PROJECT_NAME STREQUAL PROJECT_NAME AND BUILD_EXAMPLES) + add_subdirectory(examples) +endif() install(TARGETS sqlite_orm EXPORT "${ProjectName}Targets" INCLUDES DESTINATION "${INCLUDE_INSTALL_DIR}" COMPONENT Development diff --git a/examples/fetch_content/CMakeLists.txt b/examples/fetch_content/CMakeLists.txt new file mode 100644 index 000000000..17419748a --- /dev/null +++ b/examples/fetch_content/CMakeLists.txt @@ -0,0 +1,14 @@ +### Preamble ### +cmake_minimum_required(VERSION 3.15) +project(Test VERSION 0.1 LANGUAGES CXX) + +##### Project wide setup #### +set(CMAKE_CXX_STANDARD 17) +set(CMAKE_CXX_STANDARD_REQUIRED ON) +set(CMAKE_CXX_EXTENSIONS OFF) + +### Dependencies ### +add_subdirectory(dependencies) + +### Main Targets ### +add_subdirectory(src) diff --git a/examples/fetch_content/dependencies/CMakeLists.txt b/examples/fetch_content/dependencies/CMakeLists.txt new file mode 100644 index 000000000..bb951d1b8 --- /dev/null +++ b/examples/fetch_content/dependencies/CMakeLists.txt @@ -0,0 +1,8 @@ +include(FetchContent) + +FetchContent_Declare(sqliteOrm + GIT_REPOSITORY https://github.com/Leon0402/sqlite_orm.git + GIT_TAG origin/feature/dependencyManagment +) + +add_subdirectory(sqlite_orm) diff --git a/examples/fetch_content/dependencies/sqlite_orm/CMakeLists.txt b/examples/fetch_content/dependencies/sqlite_orm/CMakeLists.txt new file mode 100644 index 000000000..4a0567de7 --- /dev/null +++ b/examples/fetch_content/dependencies/sqlite_orm/CMakeLists.txt @@ -0,0 +1 @@ +FetchContent_MakeAvailable(sqliteOrm) \ No newline at end of file diff --git a/examples/fetch_content/src/CMakeLists.txt b/examples/fetch_content/src/CMakeLists.txt new file mode 100644 index 000000000..95a90f48f --- /dev/null +++ b/examples/fetch_content/src/CMakeLists.txt @@ -0,0 +1,7 @@ +add_executable(Test) +target_link_libraries(Test PRIVATE sqlite_orm::sqlite_orm) + +target_sources(Test + PRIVATE + main.cpp +) \ No newline at end of file diff --git a/examples/fetch_content/src/main.cpp b/examples/fetch_content/src/main.cpp new file mode 100644 index 000000000..e39a410d3 --- /dev/null +++ b/examples/fetch_content/src/main.cpp @@ -0,0 +1,46 @@ +#include + +#include +#include +#include + +using namespace sqlite_orm; + +using std::cout; +using std::endl; + +struct RapArtist { + int id; + std::string name; +}; + +int main(int, char **) { + + auto storage = make_storage(":memory:", + make_table("rap_artists", + make_column("id", &RapArtist::id, primary_key()), + make_column("name", &RapArtist::name))); + cout << "in memory db opened" << endl; + storage.sync_schema(); + + assert(!storage.count()); + + storage.insert(RapArtist{-1, "The Weeknd"}); + + storage.transaction([&] { + storage.insert(RapArtist{-1, "Drake"}); + return true; + }); + + cout << "rap artists count = " << storage.count() << endl; + + // transaction also work in memory.. + storage.transaction([&] { + storage.insert(RapArtist{-1, "Kanye West"}); + return false; + }); + + cout << "rap artists count = " << storage.count() << " (no Kanye)" << endl; + + return 0; +} \ No newline at end of file From 2e0e142606a07daf55292afeb8d35752f15ebc30 Mon Sep 17 00:00:00 2001 From: Leon De Andrade Date: Sat, 1 Aug 2020 16:48:02 +0200 Subject: [PATCH 107/132] find_package support --- CMakeLists.txt | 39 ++++--------------- build/cmake/DefineInstallationPaths.cmake | 12 ------ build/cmake/GenerateConfigModule.cmake | 24 ------------ build/cmake/SqliteOrmConfig.cmake.in | 25 ------------ cmake/SqliteOrmConfig.cmake.in | 4 ++ {build/cmake => cmake}/ucm.cmake | 0 examples/find_package/CMakeLists.txt | 14 +++++++ examples/find_package/src/CMakeLists.txt | 7 ++++ examples/find_package/src/main.cpp | 46 +++++++++++++++++++++++ packaging/CMakeLists.txt | 35 +++++++++++++++++ 10 files changed, 113 insertions(+), 93 deletions(-) delete mode 100644 build/cmake/DefineInstallationPaths.cmake delete mode 100644 build/cmake/GenerateConfigModule.cmake delete mode 100644 build/cmake/SqliteOrmConfig.cmake.in create mode 100644 cmake/SqliteOrmConfig.cmake.in rename {build/cmake => cmake}/ucm.cmake (100%) create mode 100644 examples/find_package/CMakeLists.txt create mode 100644 examples/find_package/src/CMakeLists.txt create mode 100644 examples/find_package/src/main.cpp create mode 100644 packaging/CMakeLists.txt diff --git a/CMakeLists.txt b/CMakeLists.txt index 12fae5c11..a20a76ab2 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,5 +1,5 @@ -cmake_minimum_required (VERSION 3.2) -cmake_policy(SET CMP0057 NEW) +cmake_minimum_required (VERSION 3.17) +#cmake_policy(SET CMP0057 NEW) # Handling C++ standard version to use option(SQLITE_ORM_ENABLE_CXX_17 "Enable C++ 17" OFF) @@ -28,18 +28,10 @@ set(CMAKE_VERBOSE_MAKEFILE ON) message(STATUS "Configuring ${CMAKE_PROJECT_NAME} ${sqlite_orm_VERSION}") -set(CMAKE_MODULE_PATH "${CMAKE_MODULE_PATH}" "${CMAKE_CURRENT_SOURCE_DIR}/build/cmake") +list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/cmake") include(CTest) -# Build time options are defined here -include(DefineInstallationPaths) - -# Generate the SqliteOrmConfig.cmake module -include(GenerateConfigModule) - -set(ProjectName "SqliteOrm") - ### Dependencies add_subdirectory(dependencies) @@ -51,13 +43,9 @@ add_library(sqlite_orm::sqlite_orm ALIAS sqlite_orm) find_package(SQLite3 REQUIRED) target_link_libraries(sqlite_orm INTERFACE SQLite::SQLite3) -target_sources(sqlite_orm INTERFACE - $ - $) +target_sources(sqlite_orm INTERFACE $) -target_include_directories(sqlite_orm INTERFACE - $ - $) +target_include_directories(sqlite_orm INTERFACE $) include(ucm) @@ -87,18 +75,5 @@ if(CMAKE_PROJECT_NAME STREQUAL PROJECT_NAME AND BUILD_EXAMPLES) add_subdirectory(examples) endif() -install(TARGETS sqlite_orm EXPORT "${ProjectName}Targets" - INCLUDES DESTINATION "${INCLUDE_INSTALL_DIR}" COMPONENT Development - PUBLIC_HEADER DESTINATION "${INCLUDE_INSTALL_DIR}" COMPONENT Development) - -install(FILES "include/sqlite_orm/sqlite_orm.h" - DESTINATION "${INCLUDE_INSTALL_DIR}" COMPONENT Development) - -export(EXPORT "${ProjectName}Targets" - FILE "${CMAKE_CURRENT_BINARY_DIR}/${ProjectName}/${ProjectName}Targets.cmake" - NAMESPACE "sqlite_orm::") - -install(EXPORT "${ProjectName}Targets" - FILE "${ProjectName}Targets.cmake" - NAMESPACE "sqlite_orm::" - DESTINATION "${CMAKE_INSTALL_DIR}/sqlite_orm") +### Packaging +add_subdirectory(packaging) diff --git a/build/cmake/DefineInstallationPaths.cmake b/build/cmake/DefineInstallationPaths.cmake deleted file mode 100644 index 3406e68e4..000000000 --- a/build/cmake/DefineInstallationPaths.cmake +++ /dev/null @@ -1,12 +0,0 @@ -# Define the default install paths -set(BIN_INSTALL_DIR "bin" CACHE PATH "The binary install dir (default: bin)") -set(LIB_INSTALL_DIR "lib${LIB_SUFFIX}" CACHE PATH "The library install dir (default: lib${LIB_SUFFIX})") -set(INCLUDE_INSTALL_DIR "include" CACHE PATH "The library install dir (default: include)") -set(CMAKE_INSTALL_DIR "lib/cmake" CACHE PATH "The subdirectory to install cmake config files (default: cmake)") -set(PKGCONFIG_INSTALL_DIR "lib/pkgconfig" CACHE PATH "The subdirectory to install pkgconfig config files (default: lib/pkgconfig)") -set(DOC_INSTALL_DIR "share/doc" CACHE PATH "The subdirectory to install documentation files (default: share/doc)") -set(prefix "${CMAKE_INSTALL_PREFIX}") -set(exec_prefix "${CMAKE_INSTALL_PREFIX}/bin") -set(libdir "${CMAKE_INSTALL_PREFIX}/lib") -set(includedir "${CMAKE_INSTALL_PREFIX}/include") -set(cmakedir "${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_DIR}") diff --git a/build/cmake/GenerateConfigModule.cmake b/build/cmake/GenerateConfigModule.cmake deleted file mode 100644 index 3c5143d3e..000000000 --- a/build/cmake/GenerateConfigModule.cmake +++ /dev/null @@ -1,24 +0,0 @@ -include(CMakePackageConfigHelpers) - -set(PACKAGE_INCLUDE_INSTALL_DIR "${includedir}/sqlite_orm") -set(PACKAGE_CMAKE_INSTALL_DIR "${cmakedir}/sqlite_orm") - -# In CYGWIN enviroment below commands does not work properly -if (NOT CYGWIN) - configure_package_config_file("${CMAKE_CURRENT_SOURCE_DIR}/build/cmake/SqliteOrmConfig.cmake.in" - "${CMAKE_CURRENT_BINARY_DIR}/SqliteOrmConfig.cmake" - INSTALL_DESTINATION "${CMAKE_INSTALL_DIR}/sqlite_orm" - PATH_VARS - PACKAGE_INCLUDE_INSTALL_DIR - PACKAGE_CMAKE_INSTALL_DIR - ) - - write_basic_package_version_file("${CMAKE_CURRENT_BINARY_DIR}/SqliteOrmConfigVersion.cmake" - VERSION ${sqlite_orm_VERSION} - COMPATIBILITY SameMajorVersion - ) - - install(FILES "${CMAKE_CURRENT_BINARY_DIR}/SqliteOrmConfig.cmake" - "${CMAKE_CURRENT_BINARY_DIR}/SqliteOrmConfigVersion.cmake" - DESTINATION "${CMAKE_INSTALL_DIR}/sqlite_orm") -endif() \ No newline at end of file diff --git a/build/cmake/SqliteOrmConfig.cmake.in b/build/cmake/SqliteOrmConfig.cmake.in deleted file mode 100644 index bf0253798..000000000 --- a/build/cmake/SqliteOrmConfig.cmake.in +++ /dev/null @@ -1,25 +0,0 @@ -set(SQLITE_ORM_VERSION ${sqlite_orm_VERSION}) - -include(CMakeFindDependencyMacro) -find_dependency(SQLite3) - -@PACKAGE_INIT@ - -set_and_check(SQLITE_ORM_INCLUDE_DIR "@PACKAGE_INCLUDE_INSTALL_DIR@") -set_and_check(SQLITE_ORM_CMAKE_DIR "@PACKAGE_CMAKE_INSTALL_DIR@") - -if (NOT TARGET sqlite_orm::sqlite_orm) - include("${SQLITE_ORM_CMAKE_DIR}/SqliteOrmTargets.cmake") -endif() - -set(SQLITE_ORM_LIBRARIES sqlite_orm::sqlite_orm) - -if ("${SQLITE_ORM_LIBRARIES}" STREQUAL "") - message(FATAL_ERROR "sqlite_orm libraries were not found") -endif() - -if (NOT SqliteOrm_FIND_QUIETLY) - message(STATUS "Found sqlite_orm: ${PACKAGE_PREFIX_DIR}") -endif() - -check_required_components(SqliteOrm) diff --git a/cmake/SqliteOrmConfig.cmake.in b/cmake/SqliteOrmConfig.cmake.in new file mode 100644 index 000000000..e0635d28a --- /dev/null +++ b/cmake/SqliteOrmConfig.cmake.in @@ -0,0 +1,4 @@ +include(CMakeFindDependencyMacro) +find_dependency(SQLite3) + +include(${CMAKE_CURRENT_LIST_DIR}/SqliteOrmTargets.cmake) diff --git a/build/cmake/ucm.cmake b/cmake/ucm.cmake similarity index 100% rename from build/cmake/ucm.cmake rename to cmake/ucm.cmake diff --git a/examples/find_package/CMakeLists.txt b/examples/find_package/CMakeLists.txt new file mode 100644 index 000000000..6c6e0182b --- /dev/null +++ b/examples/find_package/CMakeLists.txt @@ -0,0 +1,14 @@ +### Preamble ### +cmake_minimum_required(VERSION 3.15) +project(Test VERSION 0.1 LANGUAGES CXX) + +##### Project wide setup #### +set(CMAKE_CXX_STANDARD 17) +set(CMAKE_CXX_STANDARD_REQUIRED ON) +set(CMAKE_CXX_EXTENSIONS OFF) + +### Dependencies ### +find_package(SqliteOrm REQUIRED) + +### Main Targets ### +add_subdirectory(src) diff --git a/examples/find_package/src/CMakeLists.txt b/examples/find_package/src/CMakeLists.txt new file mode 100644 index 000000000..95a90f48f --- /dev/null +++ b/examples/find_package/src/CMakeLists.txt @@ -0,0 +1,7 @@ +add_executable(Test) +target_link_libraries(Test PRIVATE sqlite_orm::sqlite_orm) + +target_sources(Test + PRIVATE + main.cpp +) \ No newline at end of file diff --git a/examples/find_package/src/main.cpp b/examples/find_package/src/main.cpp new file mode 100644 index 000000000..e39a410d3 --- /dev/null +++ b/examples/find_package/src/main.cpp @@ -0,0 +1,46 @@ +#include + +#include +#include +#include + +using namespace sqlite_orm; + +using std::cout; +using std::endl; + +struct RapArtist { + int id; + std::string name; +}; + +int main(int, char **) { + + auto storage = make_storage(":memory:", + make_table("rap_artists", + make_column("id", &RapArtist::id, primary_key()), + make_column("name", &RapArtist::name))); + cout << "in memory db opened" << endl; + storage.sync_schema(); + + assert(!storage.count()); + + storage.insert(RapArtist{-1, "The Weeknd"}); + + storage.transaction([&] { + storage.insert(RapArtist{-1, "Drake"}); + return true; + }); + + cout << "rap artists count = " << storage.count() << endl; + + // transaction also work in memory.. + storage.transaction([&] { + storage.insert(RapArtist{-1, "Kanye West"}); + return false; + }); + + cout << "rap artists count = " << storage.count() << " (no Kanye)" << endl; + + return 0; +} \ No newline at end of file diff --git a/packaging/CMakeLists.txt b/packaging/CMakeLists.txt new file mode 100644 index 000000000..045194261 --- /dev/null +++ b/packaging/CMakeLists.txt @@ -0,0 +1,35 @@ +include(GNUInstallDirs) +include(CMakePackageConfigHelpers) + +set(SQLITE_ORM_INSTALL_CMAKEDIR ${CMAKE_INSTALL_LIBDIR}/cmake/SqliteOrm CACHE STRING "Path to SqliteOrm cmake files") + +configure_file(${PROJECT_SOURCE_DIR}/cmake/SqliteOrmConfig.cmake.in SqliteOrmConfig.cmake @ONLY) + +write_basic_package_version_file(${CMAKE_CURRENT_BINARY_DIR}/SqliteOrmConfigVersion.cmake + VERSION ${sqlite_orm_VERSION} + COMPATIBILITY SameMajorVersion + ) + +install(FILES ${CMAKE_CURRENT_BINARY_DIR}/SqliteOrmConfig.cmake + ${CMAKE_CURRENT_BINARY_DIR}/SqliteOrmConfigVersion.cmake + DESTINATION ${SQLITE_ORM_INSTALL_CMAKEDIR}) + +install(TARGETS sqlite_orm + EXPORT SqliteOrmTargets + RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} + COMPONENT sqlite_orm_runtime + LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} + COMPONENT sqlite_orm_runtime + NAMELINK_COMPONENT sqlite_orm_development + ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} + COMPONENT sqlite_orm_development + INCLUDES DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} +) + +INSTALL(DIRECTORY ${PROJECT_SOURCE_DIR}/include/sqlite_orm DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}) + +install(EXPORT SqliteOrmTargets + DESTINATION ${SQLITE_ORM_INSTALL_CMAKEDIR} + NAMESPACE sqlite_orm:: + COMPONENT sqlite_orm_development +) \ No newline at end of file From 7bf19a0a99e82ea64f2145f2773a2401d04a4eca Mon Sep 17 00:00:00 2001 From: Leon De Andrade Date: Sat, 1 Aug 2020 17:21:20 +0200 Subject: [PATCH 108/132] Undo version bump --- CMakeLists.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index a20a76ab2..fa0398d64 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,5 +1,5 @@ -cmake_minimum_required (VERSION 3.17) -#cmake_policy(SET CMP0057 NEW) +cmake_minimum_required (VERSION 3.2) +cmake_policy(SET CMP0057 NEW) # Handling C++ standard version to use option(SQLITE_ORM_ENABLE_CXX_17 "Enable C++ 17" OFF) From a5103049bed2645676065ec582fedb38c394219b Mon Sep 17 00:00:00 2001 From: Leon De Andrade Date: Sat, 1 Aug 2020 17:26:02 +0200 Subject: [PATCH 109/132] Fix pipeline --- .travis.yml | 10 ---------- appveyor.yml | 2 +- 2 files changed, 1 insertion(+), 11 deletions(-) diff --git a/.travis.yml b/.travis.yml index 0d07b844a..80bcb5857 100644 --- a/.travis.yml +++ b/.travis.yml @@ -152,16 +152,6 @@ before_install: export PATH="/usr/local/opt/coreutils/libexec/gnubin:$PATH" # Use coreutils from homebrew. fi -install: - - | - # Catch2 test framework - if [[ ${TRAVIS_OS_NAME} == "linux" ]]; then - git clone --depth=1 --quiet https://github.com/catchorg/Catch2.git - cd Catch2 - cmake -Bbuild -H. -DBUILD_TESTING=OFF - sudo env "PATH=$PATH" cmake --build ./build --target install - fi - # scripts to run before build before_script: - if [[ "$CXX" == *"clang"* ]]; then clang --version ; fi diff --git a/appveyor.yml b/appveyor.yml index 866a6c507..7b097a7b1 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -44,7 +44,7 @@ init: install: - C:\Tools\vcpkg\vcpkg integrate install - - vcpkg install catch2:%PLATFORM%-windows + - vcpkg install sqlite3:%PLATFORM%-windows # scripts to run before build before_build: From 9082ad10f704a9f1068b702787aa0b5e96bd8290 Mon Sep 17 00:00:00 2001 From: Yevgeniy Zakharov Date: Sun, 2 Aug 2020 03:23:14 +0300 Subject: [PATCH 110/132] Update README.md --- README.md | 5 ----- 1 file changed, 5 deletions(-) diff --git a/README.md b/README.md index d7a374ef3..581b79997 100644 --- a/README.md +++ b/README.md @@ -785,8 +785,3 @@ Or just put `include/sqlite_orm/sqlite_orm.h` into you folder with headers. Also * C++14 compatible compiler (not C++11 cause of templated lambdas in the lib). * libsqlite3 linked to your binary - -## Support on Beerpay -Hey dude! Help me out for a couple of :beers:! - -[![Beerpay](https://beerpay.io/fnc12/sqlite_orm/badge.svg?style=beer-square)](https://beerpay.io/fnc12/sqlite_orm) [![Beerpay](https://beerpay.io/fnc12/sqlite_orm/make-wish.svg?style=flat-square)](https://beerpay.io/fnc12/sqlite_orm?focus=wish) From 662151196eb58bb7604cdb45214eb0558036b3d9 Mon Sep 17 00:00:00 2001 From: Leon De Andrade Date: Mon, 3 Aug 2020 09:02:49 +0200 Subject: [PATCH 111/132] Update docs, bump cmake version --- CMakeLists.txt | 3 +- README.md | 47 ++++++++++++------- .../fetch_content/dependencies/CMakeLists.txt | 5 +- .../dependencies/sqlite_orm/CMakeLists.txt | 2 + 4 files changed, 37 insertions(+), 20 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index fa0398d64..057dff072 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,5 +1,4 @@ -cmake_minimum_required (VERSION 3.2) -cmake_policy(SET CMP0057 NEW) +cmake_minimum_required (VERSION 3.13) # Handling C++ standard version to use option(SQLITE_ORM_ENABLE_CXX_17 "Enable C++ 17" OFF) diff --git a/README.md b/README.md index 581b79997..c2983a3e2 100644 --- a/README.md +++ b/README.md @@ -756,32 +756,47 @@ For more details please check the project [wiki](https://github.com/fnc12/sqlite # Installation -Use popular package manager like [vcpkg](https://github.com/Microsoft/vcpkg) and just install it with `vcpkg install sqlite-orm` command. +**Note**: Installation is not necessary if you plan to use the fetchContent method, see below in Usage. -Or you can use below instructions -Note: If you build on Mac OSX, you need to install Catch2 project prior to the following installation +Use a popular package manager like [vcpkg](https://github.com/Microsoft/vcpkg) and just install it with the `vcpkg install sqlite-orm` command. + +Or you build it from source: ```bash git clone https://github.com/fnc12/sqlite_orm.git sqlite_orm cd sqlite_orm -mkdir compile -cd compile -cmake .. -cmake --build . -sudo make install +cmake -B build +cmake --build build --target install ``` +You might need admin rights for the last command. -then you can just include `sqlite_orm.h` that is installed in system-wide header files location or in case you use cmake build system you can just add below commands in CMakeLists.txt +# Usage -```cmake -find_package(sqlite_orm CONFIG REQUIRED) -target_link_libraries(main PRIVATE sqlite_orm::sqlite_orm) -target_include_directories(main PRIVATE ${SQLITE_ORM_INCLUDE_DIR}) -``` +## Cmake + +If you use cmake, there are two supported ways how to use it with cmake (if another works as well or should be supported, open an issue). + +Either way you choose, the include path as well as the dependency sqlite3 will be set automatically on your target. So usage is straight forward, but you need to have installed sqlite3 on your system (see Requirements below) + +## Find Package + +If you have installed the lib system wide and it's in your PATH, you can use find_package to include it in cmake. It will make a target `sqlite_orm::sqlite_orm` available which you can link against. Have a look at examples/find_package for a full example. -Or just put `include/sqlite_orm/sqlite_orm.h` into you folder with headers. Also it is recommended to keep project libraries' sources in separate folders cause there is no dominant normal dependency manager for C++ yet. +## Fetch Content (Recommended) + +Alternatively, cmake can download the project directly from github during configure stage and therefore you don't need to install the lib before. +Againt a target `sqlite_orm::sqlite_orm` will be available which you can link against. Have a look at examples/fetch_content for a full example. + +## None cmake + +If you want to use the lib directly with Make or something else, just set the inlcude path correctly (should be correct on Linux already), so `sqlite_orm/sqlite_orm.h` is found. As this is a header only lib, there is nothing more you have to do. # Requirements * C++14 compatible compiler (not C++11 cause of templated lambdas in the lib). -* libsqlite3 linked to your binary +* Sqlite3 installed on your system and in the path, so cmake can find it (or linked to you project if you don't use cmake) + +## Support on Beerpay +Hey dude! Help me out for a couple of :beers:! + +[![Beerpay](https://beerpay.io/fnc12/sqlite_orm/badge.svg?style=beer-square)](https://beerpay.io/fnc12/sqlite_orm) [![Beerpay](https://beerpay.io/fnc12/sqlite_orm/make-wish.svg?style=flat-square)](https://beerpay.io/fnc12/sqlite_orm?focus=wish) diff --git a/examples/fetch_content/dependencies/CMakeLists.txt b/examples/fetch_content/dependencies/CMakeLists.txt index bb951d1b8..da0ecd397 100644 --- a/examples/fetch_content/dependencies/CMakeLists.txt +++ b/examples/fetch_content/dependencies/CMakeLists.txt @@ -1,8 +1,9 @@ include(FetchContent) +# You can configure this for your need, presumbably you want speificy a git tag here instead of a branch FetchContent_Declare(sqliteOrm - GIT_REPOSITORY https://github.com/Leon0402/sqlite_orm.git - GIT_TAG origin/feature/dependencyManagment + GIT_REPOSITORY https://github.com/fnc12/sqlite_orm + GIT_TAG origin/dev ) add_subdirectory(sqlite_orm) diff --git a/examples/fetch_content/dependencies/sqlite_orm/CMakeLists.txt b/examples/fetch_content/dependencies/sqlite_orm/CMakeLists.txt index 4a0567de7..705383adb 100644 --- a/examples/fetch_content/dependencies/sqlite_orm/CMakeLists.txt +++ b/examples/fetch_content/dependencies/sqlite_orm/CMakeLists.txt @@ -1 +1,3 @@ +# Set here options for sliteOrm +# for example set(BUILD_TESTING ON) if you want to have tests included of sqliteOrm FetchContent_MakeAvailable(sqliteOrm) \ No newline at end of file From 7e0d2f334552819a9ecbf3ed1fad86924489f1e1 Mon Sep 17 00:00:00 2001 From: Leon De Andrade Date: Mon, 3 Aug 2020 12:51:45 +0200 Subject: [PATCH 112/132] Address issue --- README.md | 5 ----- 1 file changed, 5 deletions(-) diff --git a/README.md b/README.md index c2983a3e2..0d6df4f1d 100644 --- a/README.md +++ b/README.md @@ -795,8 +795,3 @@ If you want to use the lib directly with Make or something else, just set the in * C++14 compatible compiler (not C++11 cause of templated lambdas in the lib). * Sqlite3 installed on your system and in the path, so cmake can find it (or linked to you project if you don't use cmake) - -## Support on Beerpay -Hey dude! Help me out for a couple of :beers:! - -[![Beerpay](https://beerpay.io/fnc12/sqlite_orm/badge.svg?style=beer-square)](https://beerpay.io/fnc12/sqlite_orm) [![Beerpay](https://beerpay.io/fnc12/sqlite_orm/make-wish.svg?style=flat-square)](https://beerpay.io/fnc12/sqlite_orm?focus=wish) From 344fd88d8cb082d1afe9afa9d62c88d7dcbb4c87 Mon Sep 17 00:00:00 2001 From: Leon De Andrade Date: Mon, 3 Aug 2020 12:55:29 +0200 Subject: [PATCH 113/132] Change to Cmake 3.12.4, the lastest one supported by travis --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 057dff072..1099643cd 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required (VERSION 3.13) +cmake_minimum_required (VERSION 3.12.4) # Handling C++ standard version to use option(SQLITE_ORM_ENABLE_CXX_17 "Enable C++ 17" OFF) From fc0310b30ef349a32f1daaae6539c58475940af4 Mon Sep 17 00:00:00 2001 From: Leon De Andrade Date: Mon, 3 Aug 2020 13:00:12 +0200 Subject: [PATCH 114/132] Use old fetch method --- dependencies/catch2/CMakeLists.txt | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/dependencies/catch2/CMakeLists.txt b/dependencies/catch2/CMakeLists.txt index e5b14fd79..c320febdc 100644 --- a/dependencies/catch2/CMakeLists.txt +++ b/dependencies/catch2/CMakeLists.txt @@ -1 +1,8 @@ -FetchContent_MakeAvailable(catch2) \ No newline at end of file +# TO DO: Switch to cmake 3.14 when travis does support it and use the newer command below instead +#FetchContent_MakeAvailable(catch2) + +FetchContent_GetProperties(catch2) +if(NOT catch2_POPULATED) + FetchContent_Populate(catch2) + add_subdirectory(${catch2_SOURCE_DIR} ${catch2_BINARY_DIR}) +endif() From 2d0268c2672914c8c01b519e50c2548273e054a0 Mon Sep 17 00:00:00 2001 From: Leon De Andrade Date: Mon, 3 Aug 2020 13:13:24 +0200 Subject: [PATCH 115/132] Quick test, if ubuntu 20.04 is available --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 80bcb5857..bcd7b43d3 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,6 +1,6 @@ # Defaults os: linux -dist: xenial +dist: focal matrix: include: From e51561fb8b2fb14df71cd1b8e4ad1c882655a54d Mon Sep 17 00:00:00 2001 From: Leon De Andrade Date: Mon, 3 Aug 2020 13:19:00 +0200 Subject: [PATCH 116/132] Test --- CMakeLists.txt | 2 +- dependencies/catch2/CMakeLists.txt | 9 +-------- 2 files changed, 2 insertions(+), 9 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 1099643cd..dd86d2f1f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required (VERSION 3.12.4) +cmake_minimum_required (VERSION 3.16.0) # Handling C++ standard version to use option(SQLITE_ORM_ENABLE_CXX_17 "Enable C++ 17" OFF) diff --git a/dependencies/catch2/CMakeLists.txt b/dependencies/catch2/CMakeLists.txt index c320febdc..efbcfd8af 100644 --- a/dependencies/catch2/CMakeLists.txt +++ b/dependencies/catch2/CMakeLists.txt @@ -1,8 +1 @@ -# TO DO: Switch to cmake 3.14 when travis does support it and use the newer command below instead -#FetchContent_MakeAvailable(catch2) - -FetchContent_GetProperties(catch2) -if(NOT catch2_POPULATED) - FetchContent_Populate(catch2) - add_subdirectory(${catch2_SOURCE_DIR} ${catch2_BINARY_DIR}) -endif() +FetchContent_MakeAvailable(catch2) From 179e91f2667ed5a35bab0ef8c417fc28b9ba3f60 Mon Sep 17 00:00:00 2001 From: Leon De Andrade Date: Mon, 3 Aug 2020 13:57:12 +0200 Subject: [PATCH 117/132] Add cmake ppa --- .travis.yml | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index bcd7b43d3..7811f8aa8 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,6 +1,6 @@ # Defaults os: linux -dist: focal +dist: bionic matrix: include: @@ -151,6 +151,12 @@ before_install: if [[ ${TRAVIS_OS_NAME} == "osx" ]]; then export PATH="/usr/local/opt/coreutils/libexec/gnubin:$PATH" # Use coreutils from homebrew. fi + # Add ppa repo for cmake and delete cmake 3.12.4 folder of travis + - wget -O - https://apt.kitware.com/keys/kitware-archive-latest.asc 2>/dev/null | gpg --dearmor - | sudo tee /etc/apt/trusted.gpg.d/kitware.gpg >/dev/null + - sudo apt-add-repository -y 'deb https://apt.kitware.com/ubuntu/ bionic main' + - sudo apt-get update -qq -y + - sudo apt-get install -y cmake + - sudo rm -r /usr/local/cmake-3.12.4/ # scripts to run before build before_script: From 2fabcc8b3f63aaa12dc5b8e3fc99bd665938e29d Mon Sep 17 00:00:00 2001 From: fnc12 Date: Thu, 6 Aug 2020 21:12:41 +0300 Subject: [PATCH 118/132] added indexed_column function --- dev/column_result.h | 2 +- dev/error_code.h | 3 + dev/index.h | 24 +- dev/indexed_column.h | 67 +++++ dev/statement_serializator.h | 62 ++++- dev/storage.h | 77 ++---- dev/storage_base.h | 4 +- dev/storage_impl.h | 15 +- dev/table.h | 2 +- examples/index.cpp | 15 +- include/sqlite_orm/sqlite_orm.h | 258 +++++++++++++----- tests/CMakeLists.txt | 2 +- tests/index_tests.cpp | 47 ++++ tests/statement_serializator_tests/index.cpp | 19 ++ .../indexed_column.cpp | 46 ++++ 15 files changed, 498 insertions(+), 145 deletions(-) create mode 100644 dev/indexed_column.h create mode 100644 tests/index_tests.cpp create mode 100644 tests/statement_serializator_tests/index.cpp create mode 100644 tests/statement_serializator_tests/indexed_column.cpp diff --git a/dev/column_result.h b/dev/column_result.h index a6af11a1f..a32771be2 100644 --- a/dev/column_result.h +++ b/dev/column_result.h @@ -1,6 +1,6 @@ #pragma once -#include // std::enable_if, std::is_same, std::decay +#include // std::enable_if, std::is_same, std::decay, std::is_arithmetic #include // std::tuple #include // std::reference_wrapper diff --git a/dev/error_code.h b/dev/error_code.h index 0dd1f1b25..706bc4d26 100644 --- a/dev/error_code.h +++ b/dev/error_code.h @@ -22,6 +22,7 @@ namespace sqlite_orm { invalid_collate_argument_enum, failed_to_init_a_backup, unknown_member_value, + incorrect_order, }; } @@ -60,6 +61,8 @@ namespace sqlite_orm { return "Failed to init a backup"; case orm_error_code::unknown_member_value: return "Unknown member value"; + case orm_error_code::incorrect_order: + return "Incorrect order"; default: return "unknown error"; } diff --git a/dev/index.h b/dev/index.h index 2b68750f1..35de1669e 100644 --- a/dev/index.h +++ b/dev/index.h @@ -4,28 +4,38 @@ #include // std::string #include // std::forward +#include "indexed_column.h" + namespace sqlite_orm { namespace internal { + struct index_base { + std::string name; + bool unique = false; + }; + template - struct index_t { + struct index_t : index_base { using columns_type = std::tuple; using object_type = void; - std::string name; - bool unique; + index_t(std::string name, bool unique, columns_type columns_) : + index_base{move(name), unique}, columns(move(columns_)) {} + columns_type columns; }; } template - internal::index_t make_index(const std::string &name, Cols... cols) { - return {name, false, std::make_tuple(std::forward(cols)...)}; + internal::index_t::type...> make_index(const std::string &name, + Cols... cols) { + return {name, false, std::make_tuple(internal::make_indexed_column(cols)...)}; } template - internal::index_t make_unique_index(const std::string &name, Cols... cols) { - return {name, true, std::make_tuple(std::forward(cols)...)}; + internal::index_t::type...> make_unique_index(const std::string &name, + Cols... cols) { + return {name, true, std::make_tuple(internal::make_indexed_column(cols)...)}; } } diff --git a/dev/indexed_column.h b/dev/indexed_column.h new file mode 100644 index 000000000..9b2e710a2 --- /dev/null +++ b/dev/indexed_column.h @@ -0,0 +1,67 @@ +#pragma once + +#include // std::string + +namespace sqlite_orm { + + namespace internal { + + template + struct indexed_column_t { + using column_type = C; + + column_type column_or_expression; + std::string _collation_name; + int _order = 0; // -1 = desc, 1 = asc, 0 = not specified + + indexed_column_t collate(std::string name) { + auto res = std::move(*this); + res._collation_name = move(name); + return res; + } + + indexed_column_t asc() { + auto res = std::move(*this); + res._order = 1; + return res; + } + + indexed_column_t desc() { + auto res = std::move(*this); + res._order = -1; + return res; + } + }; + + template + struct indexed_column_maker { + using type = indexed_column_t; + + indexed_column_t operator()(C col) const { + return {std::move(col)}; + } + }; + + template + struct indexed_column_maker> { + using type = indexed_column_t; + + indexed_column_t operator()(indexed_column_t col) const { + return std::move(col); + } + }; + + template + auto make_indexed_column(C col) { + indexed_column_maker maker; + return maker(std::move(col)); + } + + } + + template + internal::indexed_column_t indexed_column(C column_or_expression) { + return {std::move(column_or_expression)}; + } + +} diff --git a/dev/statement_serializator.h b/dev/statement_serializator.h index 8de75baab..aaf193944 100644 --- a/dev/statement_serializator.h +++ b/dev/statement_serializator.h @@ -2,7 +2,7 @@ #include // std::stringstream #include // std::string -#include // std::is_arithmetic, std::enable_if +#include // std::enable_if #include // std::vector #include // std::iter_swap @@ -16,6 +16,8 @@ #include "column_names_getter.h" #include "order_by_serializator.h" #include "values.h" +#include "table_type.h" +#include "indexed_column.h" namespace sqlite_orm { @@ -1324,6 +1326,64 @@ namespace sqlite_orm { } }; + template + struct statement_serializator, void> { + using statement_type = indexed_column_t; + + template + std::string operator()(const statement_type &statement, const C &context) const { + std::stringstream ss; + ss << serialize(statement.column_or_expression, context); + if(!statement._collation_name.empty()) { + ss << " COLLATE " << statement._collation_name; + } + if(statement._order) { + switch(statement._order) { + case -1: + ss << " DESC"; + break; + case 1: + ss << " ASC"; + break; + default: + throw std::system_error(std::make_error_code(orm_error_code::column_not_found)); + } + } + return ss.str(); + } + }; + + template + struct statement_serializator, void> { + using statement_type = index_t; + + template + std::string operator()(const statement_type &statement, const C &context) const { + std::stringstream ss; + ss << "CREATE "; + if(statement.unique) { + ss << "UNIQUE "; + } + using columns_type = typename std::decay::type::columns_type; + using head_t = typename std::tuple_element<0, columns_type>::type::column_type; + using indexed_type = typename table_type::type; + ss << "INDEX IF NOT EXISTS '" << statement.name << "' ON '" + << context.impl.find_table_name(typeid(indexed_type)) << "' ("; + std::vector columnNames; + iterate_tuple(statement.columns, [&columnNames, &context](auto &v) { + columnNames.push_back(context.column_name(v.column_or_expression)); + }); + for(size_t i = 0; i < columnNames.size(); ++i) { + ss << "'" << columnNames[i] << "'"; + if(i < columnNames.size() - 1) { + ss << ", "; + } + } + ss << ")"; + return ss.str(); + } + }; + template struct statement_serializator, void> { using statement_type = where_t; diff --git a/dev/storage.h b/dev/storage.h index 5012c998a..73f8f5ef2 100644 --- a/dev/storage.h +++ b/dev/storage.h @@ -24,7 +24,6 @@ #include "type_printer.h" #include "tuple_helper.h" #include "constraints.h" -#include "table_type.h" #include "type_is_nullable.h" #include "field_printer.h" #include "rowid.h" @@ -87,14 +86,14 @@ namespace sqlite_orm { friend struct serializator_context_builder; template - void create_table(sqlite3 *db, const std::string &tableName, I *tableImpl) { + void create_table(sqlite3 *db, const std::string &tableName, const I &tableImpl) { std::stringstream ss; ss << "CREATE TABLE '" << tableName << "' ( "; - auto columnsCount = tableImpl->table.columns_count; + auto columnsCount = tableImpl.table.columns_count; auto index = 0; using context_t = serializator_context; context_t context{this->impl}; - iterate_tuple(tableImpl->table.columns, [columnsCount, &index, &ss, &context](auto &c) { + iterate_tuple(tableImpl.table.columns, [columnsCount, &index, &ss, &context](auto &c) { ss << serialize(c, context); if(index < columnsCount - 1) { ss << ", "; @@ -102,7 +101,7 @@ namespace sqlite_orm { index++; }); ss << ") "; - if(tableImpl->table._without_rowid) { + if(tableImpl.table._without_rowid) { ss << "WITHOUT ROWID "; } auto query = ss.str(); @@ -122,18 +121,18 @@ namespace sqlite_orm { } template - void backup_table(sqlite3 *db, I *tableImpl, const std::vector &columnsToIgnore) { + void backup_table(sqlite3 *db, const I &tableImpl, const std::vector &columnsToIgnore) { // here we copy source table to another with a name with '_backup' suffix, but in case table with such // a name already exists we append suffix 1, then 2, etc until we find a free name.. - auto backupTableName = tableImpl->table.name + "_backup"; - if(tableImpl->table_exists(backupTableName, db)) { + auto backupTableName = tableImpl.table.name + "_backup"; + if(tableImpl.table_exists(backupTableName, db)) { int suffix = 1; do { std::stringstream stream; stream << suffix; auto anotherBackupTableName = backupTableName + stream.str(); - if(!tableImpl->table_exists(anotherBackupTableName, db)) { + if(!tableImpl.table_exists(anotherBackupTableName, db)) { backupTableName = anotherBackupTableName; break; } @@ -143,11 +142,11 @@ namespace sqlite_orm { this->create_table(db, backupTableName, tableImpl); - tableImpl->copy_table(db, backupTableName, columnsToIgnore); + tableImpl.copy_table(db, backupTableName, columnsToIgnore); - this->drop_table_internal(tableImpl->table.name, db); + this->drop_table_internal(tableImpl.table.name, db); - tableImpl->rename_table(db, backupTableName, tableImpl->table.name); + tableImpl.rename_table(db, backupTableName, tableImpl.table.name); } template @@ -656,32 +655,11 @@ namespace sqlite_orm { protected: template - sync_schema_result - sync_table(storage_impl, Tss...> *tableImpl, sqlite3 *db, bool) { + sync_schema_result sync_table(const storage_impl, Tss...> &tableImpl, sqlite3 *db, bool) { auto res = sync_schema_result::already_in_sync; - std::stringstream ss; - ss << "CREATE "; - if(tableImpl->table.unique) { - ss << "UNIQUE "; - } - using columns_type = typename decltype(tableImpl->table)::columns_type; - using head_t = typename std::tuple_element<0, columns_type>::type; - using indexed_type = typename internal::table_type::type; - ss << "INDEX IF NOT EXISTS '" << tableImpl->table.name << "' ON '" - << this->impl.find_table_name(typeid(indexed_type)) << "' ( "; - std::vector columnNames; - iterate_tuple(tableImpl->table.columns, [&columnNames, this](auto &v) { - columnNames.push_back(this->impl.column_name(v)); - }); - for(size_t i = 0; i < columnNames.size(); ++i) { - ss << "'" << columnNames[i] << "'"; - if(i < columnNames.size() - 1) { - ss << ","; - } - ss << " "; - } - ss << ") "; - auto query = ss.str(); + using context_t = serializator_context; + context_t context{this->impl}; + auto query = serialize(tableImpl.table, context); auto rc = sqlite3_exec(db, query.c_str(), nullptr, nullptr, nullptr); if(rc != SQLITE_OK) { throw std::system_error(std::error_code(sqlite3_errcode(db), get_sqlite_error_category()), @@ -691,13 +669,14 @@ namespace sqlite_orm { } template - sync_schema_result sync_table(storage_impl, Tss...> *tImpl, sqlite3 *db, bool preserve) { + sync_schema_result + sync_table(const storage_impl, Tss...> &tImpl, sqlite3 *db, bool preserve) { auto res = sync_schema_result::already_in_sync; - auto schema_stat = tImpl->schema_status(db, preserve); + auto schema_stat = tImpl.schema_status(db, preserve); if(schema_stat != decltype(schema_stat)::already_in_sync) { if(schema_stat == decltype(schema_stat)::new_table_created) { - this->create_table(db, tImpl->table.name, tImpl); + this->create_table(db, tImpl.table.name, tImpl); res = decltype(res)::new_table_created; } else { if(schema_stat == sync_schema_result::old_columns_removed || @@ -705,15 +684,15 @@ namespace sqlite_orm { schema_stat == sync_schema_result::new_columns_added_and_old_columns_removed) { // get table info provided in `make_table` call.. - auto storageTableInfo = tImpl->table.get_table_info(); + auto storageTableInfo = tImpl.table.get_table_info(); // now get current table info from db using `PRAGMA table_info` query.. - auto dbTableInfo = tImpl->get_table_info(tImpl->table.name, db); + auto dbTableInfo = tImpl.get_table_info(tImpl.table.name, db); // this vector will contain pointers to columns that gotta be added.. std::vector columnsToAdd; - tImpl->get_remove_add_columns(columnsToAdd, storageTableInfo, dbTableInfo); + tImpl.get_remove_add_columns(columnsToAdd, storageTableInfo, dbTableInfo); if(schema_stat == sync_schema_result::old_columns_removed) { @@ -724,7 +703,7 @@ namespace sqlite_orm { if(schema_stat == sync_schema_result::new_columns_added) { for(auto columnPointer: columnsToAdd) { - tImpl->add_column(*columnPointer, db); + tImpl.add_column(*columnPointer, db); } res = decltype(res)::new_columns_added; } @@ -736,8 +715,8 @@ namespace sqlite_orm { res = decltype(res)::new_columns_added_and_old_columns_removed; } } else if(schema_stat == sync_schema_result::dropped_and_recreated) { - this->drop_table_internal(tImpl->table.name, db); - this->create_table(db, tImpl->table.name, tImpl); + this->drop_table_internal(tImpl.table.name, db); + this->create_table(db, tImpl.table.name, tImpl); res = decltype(res)::dropped_and_recreated; } } @@ -777,9 +756,9 @@ namespace sqlite_orm { auto con = this->get_connection(); std::map result; auto db = con.get(); - this->impl.for_each([&result, db, preserve, this](auto tableImpl) { + this->impl.for_each([&result, db, preserve, this](auto &tableImpl) { auto res = this->sync_table(tableImpl, db, preserve); - result.insert({tableImpl->table.name, res}); + result.insert({tableImpl.table.name, res}); }); return result; } @@ -794,7 +773,7 @@ namespace sqlite_orm { std::map result; auto db = con.get(); this->impl.for_each([&result, db, preserve](auto tableImpl) { - result.insert({tableImpl->table.name, tableImpl->schema_status(db, preserve)}); + result.insert({tableImpl.table.name, tableImpl.schema_status(db, preserve)}); }); return result; } diff --git a/dev/storage_base.h b/dev/storage_base.h index d0d83e5e1..20f535064 100644 --- a/dev/storage_base.h +++ b/dev/storage_base.h @@ -524,8 +524,8 @@ namespace sqlite_orm { template static int foreign_keys_count(T &storageImpl) { auto res = 0; - storageImpl.for_each([&res](auto impl) { - res += impl->foreign_keys_count(); + storageImpl.for_each([&res](auto &impl) { + res += impl.foreign_keys_count(); }); return res; } diff --git a/dev/storage_impl.h b/dev/storage_impl.h index 8af7a9efd..617f55ef0 100644 --- a/dev/storage_impl.h +++ b/dev/storage_impl.h @@ -28,7 +28,7 @@ namespace sqlite_orm { struct storage_impl_base { - bool table_exists(const std::string &tableName, sqlite3 *db) { + bool table_exists(const std::string &tableName, sqlite3 *db) const { auto res = false; std::stringstream ss; ss << "SELECT COUNT(*) FROM sqlite_master WHERE type = '" @@ -54,7 +54,7 @@ namespace sqlite_orm { return res; } - void rename_table(sqlite3 *db, const std::string &oldName, const std::string &newName) { + void rename_table(sqlite3 *db, const std::string &oldName, const std::string &newName) const { std::stringstream ss; ss << "ALTER TABLE " << oldName << " RENAME TO " << newName; auto query = ss.str(); @@ -112,7 +112,7 @@ namespace sqlite_orm { return notEqual; } - std::vector get_table_info(const std::string &tableName, sqlite3 *db) { + std::vector get_table_info(const std::string &tableName, sqlite3 *db) const { std::vector res; auto query = "PRAGMA table_info('" + tableName + "')"; auto rc = sqlite3_exec( @@ -161,7 +161,7 @@ namespace sqlite_orm { template void for_each(const L &l) { this->super::for_each(l); - l(this); + l(*this); } #if SQLITE_VERSION_NUMBER >= 3006019 @@ -261,7 +261,7 @@ namespace sqlite_orm { } } - void add_column(const table_info &ti, sqlite3 *db) { + void add_column(const table_info &ti, sqlite3 *db) const { std::stringstream ss; ss << "ALTER TABLE " << this->table.name << " ADD COLUMN " << ti.name << " "; ss << ti.type << " "; @@ -295,7 +295,8 @@ namespace sqlite_orm { * Copies current table to another table with a given **name**. * Performs CREATE TABLE %name% AS SELECT %this->table.columns_names()% FROM &this->table.name%; */ - void copy_table(sqlite3 *db, const std::string &name, const std::vector &columnsToIgnore) { + void + copy_table(sqlite3 *db, const std::string &name, const std::vector &columnsToIgnore) const { std::ignore = columnsToIgnore; std::stringstream ss; @@ -346,7 +347,7 @@ namespace sqlite_orm { } } - sync_schema_result schema_status(sqlite3 *db, bool preserve) { + sync_schema_result schema_status(sqlite3 *db, bool preserve) const { auto res = sync_schema_result::already_in_sync; diff --git a/dev/table.h b/dev/table.h index fb90dfaab..7fc86810a 100644 --- a/dev/table.h +++ b/dev/table.h @@ -232,7 +232,7 @@ namespace sqlite_orm { }); } - std::vector get_table_info() { + std::vector get_table_info() const { std::vector res; res.reserve(size_t(this->columns_count)); this->for_each_column([&res](auto &col) { diff --git a/examples/index.cpp b/examples/index.cpp index 71b541768..fd45ec6a1 100644 --- a/examples/index.cpp +++ b/examples/index.cpp @@ -17,13 +17,14 @@ using namespace sqlite_orm; // beware - put `make_index` before `make_table` cause `sync_schema` is called in reverse order // otherwise you'll receive an exception -auto storage = make_storage("index.sqlite", - make_index("idx_contacts_name", &Contract::firstName, &Contract::lastName), - make_unique_index("idx_contacts_email", &Contract::email), - make_table("contacts", - make_column("first_name", &Contract::firstName), - make_column("last_name", &Contract::lastName), - make_column("email", &Contract::email))); +auto storage = + make_storage("index.sqlite", + make_index("idx_contacts_name", &Contract::firstName, &Contract::lastName), + make_unique_index("idx_contacts_email", indexed_column(&Contract::email).collate("BINARY").desc()), + make_table("contacts", + make_column("first_name", &Contract::firstName), + make_column("last_name", &Contract::lastName), + make_column("email", &Contract::email))); int main(int, char **) { diff --git a/include/sqlite_orm/sqlite_orm.h b/include/sqlite_orm/sqlite_orm.h index 06eefe369..e602779c4 100644 --- a/include/sqlite_orm/sqlite_orm.h +++ b/include/sqlite_orm/sqlite_orm.h @@ -43,6 +43,7 @@ __pragma(push_macro("min")) invalid_collate_argument_enum, failed_to_init_a_backup, unknown_member_value, + incorrect_order, }; } @@ -80,6 +81,8 @@ namespace sqlite_orm { return "Failed to init a backup"; case orm_error_code::unknown_member_value: return "Unknown member value"; + case orm_error_code::incorrect_order: + return "Incorrect order"; default: return "unknown error"; } @@ -5311,29 +5314,105 @@ namespace sqlite_orm { #include // std::string #include // std::forward +// #include "indexed_column.h" + +#include // std::string + +namespace sqlite_orm { + + namespace internal { + + template + struct indexed_column_t { + using column_type = C; + + column_type column_or_expression; + std::string _collation_name; + int _order = 0; // -1 = desc, 1 = asc, 0 = not specified + + indexed_column_t collate(std::string name) { + auto res = std::move(*this); + res._collation_name = move(name); + return res; + } + + indexed_column_t asc() { + auto res = std::move(*this); + res._order = 1; + return res; + } + + indexed_column_t desc() { + auto res = std::move(*this); + res._order = -1; + return res; + } + }; + + template + struct indexed_column_maker { + using type = indexed_column_t; + + indexed_column_t operator()(C col) const { + return {std::move(col)}; + } + }; + + template + struct indexed_column_maker> { + using type = indexed_column_t; + + indexed_column_t operator()(indexed_column_t col) const { + return std::move(col); + } + }; + + template + auto make_indexed_column(C col) { + indexed_column_maker maker; + return maker(std::move(col)); + } + + } + + template + internal::indexed_column_t indexed_column(C column_or_expression) { + return {std::move(column_or_expression)}; + } + +} + namespace sqlite_orm { namespace internal { + struct index_base { + std::string name; + bool unique = false; + }; + template - struct index_t { + struct index_t : index_base { using columns_type = std::tuple; using object_type = void; - std::string name; - bool unique; + index_t(std::string name, bool unique, columns_type columns_) : + index_base{move(name), unique}, columns(move(columns_)) {} + columns_type columns; }; } template - internal::index_t make_index(const std::string &name, Cols... cols) { - return {name, false, std::make_tuple(std::forward(cols)...)}; + internal::index_t::type...> make_index(const std::string &name, + Cols... cols) { + return {name, false, std::make_tuple(internal::make_indexed_column(cols)...)}; } template - internal::index_t make_unique_index(const std::string &name, Cols... cols) { - return {name, true, std::make_tuple(std::forward(cols)...)}; + internal::index_t::type...> make_unique_index(const std::string &name, + Cols... cols) { + return {name, true, std::make_tuple(internal::make_indexed_column(cols)...)}; } } #pragma once @@ -5430,7 +5509,7 @@ namespace sqlite_orm { } #pragma once -#include // std::enable_if, std::is_same, std::decay +#include // std::enable_if, std::is_same, std::decay, std::is_arithmetic #include // std::tuple #include // std::reference_wrapper @@ -6075,7 +6154,7 @@ namespace sqlite_orm { }); } - std::vector get_table_info() { + std::vector get_table_info() const { std::vector res; res.reserve(size_t(this->columns_count)); this->for_each_column([&res](auto &col) { @@ -6187,7 +6266,7 @@ namespace sqlite_orm { struct storage_impl_base { - bool table_exists(const std::string &tableName, sqlite3 *db) { + bool table_exists(const std::string &tableName, sqlite3 *db) const { auto res = false; std::stringstream ss; ss << "SELECT COUNT(*) FROM sqlite_master WHERE type = '" @@ -6213,7 +6292,7 @@ namespace sqlite_orm { return res; } - void rename_table(sqlite3 *db, const std::string &oldName, const std::string &newName) { + void rename_table(sqlite3 *db, const std::string &oldName, const std::string &newName) const { std::stringstream ss; ss << "ALTER TABLE " << oldName << " RENAME TO " << newName; auto query = ss.str(); @@ -6271,7 +6350,7 @@ namespace sqlite_orm { return notEqual; } - std::vector get_table_info(const std::string &tableName, sqlite3 *db) { + std::vector get_table_info(const std::string &tableName, sqlite3 *db) const { std::vector res; auto query = "PRAGMA table_info('" + tableName + "')"; auto rc = sqlite3_exec( @@ -6320,7 +6399,7 @@ namespace sqlite_orm { template void for_each(const L &l) { this->super::for_each(l); - l(this); + l(*this); } #if SQLITE_VERSION_NUMBER >= 3006019 @@ -6420,7 +6499,7 @@ namespace sqlite_orm { } } - void add_column(const table_info &ti, sqlite3 *db) { + void add_column(const table_info &ti, sqlite3 *db) const { std::stringstream ss; ss << "ALTER TABLE " << this->table.name << " ADD COLUMN " << ti.name << " "; ss << ti.type << " "; @@ -6454,7 +6533,8 @@ namespace sqlite_orm { * Copies current table to another table with a given **name**. * Performs CREATE TABLE %name% AS SELECT %this->table.columns_names()% FROM &this->table.name%; */ - void copy_table(sqlite3 *db, const std::string &name, const std::vector &columnsToIgnore) { + void + copy_table(sqlite3 *db, const std::string &name, const std::vector &columnsToIgnore) const { std::ignore = columnsToIgnore; std::stringstream ss; @@ -6505,7 +6585,7 @@ namespace sqlite_orm { } } - sync_schema_result schema_status(sqlite3 *db, bool preserve) { + sync_schema_result schema_status(sqlite3 *db, bool preserve) const { auto res = sync_schema_result::already_in_sync; @@ -6751,8 +6831,6 @@ namespace sqlite_orm { // #include "constraints.h" -// #include "table_type.h" - // #include "type_is_nullable.h" // #include "field_printer.h" @@ -8954,8 +9032,8 @@ namespace sqlite_orm { template static int foreign_keys_count(T &storageImpl) { auto res = 0; - storageImpl.for_each([&res](auto impl) { - res += impl->foreign_keys_count(); + storageImpl.for_each([&res](auto &impl) { + res += impl.foreign_keys_count(); }); return res; } @@ -9093,7 +9171,7 @@ namespace sqlite_orm { #include // std::stringstream #include // std::string -#include // std::is_arithmetic, std::enable_if +#include // std::enable_if #include // std::vector #include // std::iter_swap @@ -9409,6 +9487,10 @@ namespace sqlite_orm { } +// #include "table_type.h" + +// #include "indexed_column.h" + namespace sqlite_orm { namespace internal { @@ -10716,6 +10798,64 @@ namespace sqlite_orm { } }; + template + struct statement_serializator, void> { + using statement_type = indexed_column_t; + + template + std::string operator()(const statement_type &statement, const C &context) const { + std::stringstream ss; + ss << serialize(statement.column_or_expression, context); + if(!statement._collation_name.empty()) { + ss << " COLLATE " << statement._collation_name; + } + if(statement._order) { + switch(statement._order) { + case -1: + ss << " DESC"; + break; + case 1: + ss << " ASC"; + break; + default: + throw std::system_error(std::make_error_code(orm_error_code::column_not_found)); + } + } + return ss.str(); + } + }; + + template + struct statement_serializator, void> { + using statement_type = index_t; + + template + std::string operator()(const statement_type &statement, const C &context) const { + std::stringstream ss; + ss << "CREATE "; + if(statement.unique) { + ss << "UNIQUE "; + } + using columns_type = typename std::decay::type::columns_type; + using head_t = typename std::tuple_element<0, columns_type>::type::column_type; + using indexed_type = typename table_type::type; + ss << "INDEX IF NOT EXISTS '" << statement.name << "' ON '" + << context.impl.find_table_name(typeid(indexed_type)) << "' ("; + std::vector columnNames; + iterate_tuple(statement.columns, [&columnNames, &context](auto &v) { + columnNames.push_back(context.column_name(v.column_or_expression)); + }); + for(size_t i = 0; i < columnNames.size(); ++i) { + ss << "'" << columnNames[i] << "'"; + if(i < columnNames.size() - 1) { + ss << ", "; + } + } + ss << ")"; + return ss.str(); + } + }; + template struct statement_serializator, void> { using statement_type = where_t; @@ -11091,14 +11231,14 @@ namespace sqlite_orm { friend struct serializator_context_builder; template - void create_table(sqlite3 *db, const std::string &tableName, I *tableImpl) { + void create_table(sqlite3 *db, const std::string &tableName, const I &tableImpl) { std::stringstream ss; ss << "CREATE TABLE '" << tableName << "' ( "; - auto columnsCount = tableImpl->table.columns_count; + auto columnsCount = tableImpl.table.columns_count; auto index = 0; using context_t = serializator_context; context_t context{this->impl}; - iterate_tuple(tableImpl->table.columns, [columnsCount, &index, &ss, &context](auto &c) { + iterate_tuple(tableImpl.table.columns, [columnsCount, &index, &ss, &context](auto &c) { ss << serialize(c, context); if(index < columnsCount - 1) { ss << ", "; @@ -11106,7 +11246,7 @@ namespace sqlite_orm { index++; }); ss << ") "; - if(tableImpl->table._without_rowid) { + if(tableImpl.table._without_rowid) { ss << "WITHOUT ROWID "; } auto query = ss.str(); @@ -11126,18 +11266,18 @@ namespace sqlite_orm { } template - void backup_table(sqlite3 *db, I *tableImpl, const std::vector &columnsToIgnore) { + void backup_table(sqlite3 *db, const I &tableImpl, const std::vector &columnsToIgnore) { // here we copy source table to another with a name with '_backup' suffix, but in case table with such // a name already exists we append suffix 1, then 2, etc until we find a free name.. - auto backupTableName = tableImpl->table.name + "_backup"; - if(tableImpl->table_exists(backupTableName, db)) { + auto backupTableName = tableImpl.table.name + "_backup"; + if(tableImpl.table_exists(backupTableName, db)) { int suffix = 1; do { std::stringstream stream; stream << suffix; auto anotherBackupTableName = backupTableName + stream.str(); - if(!tableImpl->table_exists(anotherBackupTableName, db)) { + if(!tableImpl.table_exists(anotherBackupTableName, db)) { backupTableName = anotherBackupTableName; break; } @@ -11147,11 +11287,11 @@ namespace sqlite_orm { this->create_table(db, backupTableName, tableImpl); - tableImpl->copy_table(db, backupTableName, columnsToIgnore); + tableImpl.copy_table(db, backupTableName, columnsToIgnore); - this->drop_table_internal(tableImpl->table.name, db); + this->drop_table_internal(tableImpl.table.name, db); - tableImpl->rename_table(db, backupTableName, tableImpl->table.name); + tableImpl.rename_table(db, backupTableName, tableImpl.table.name); } template @@ -11660,32 +11800,11 @@ namespace sqlite_orm { protected: template - sync_schema_result - sync_table(storage_impl, Tss...> *tableImpl, sqlite3 *db, bool) { + sync_schema_result sync_table(const storage_impl, Tss...> &tableImpl, sqlite3 *db, bool) { auto res = sync_schema_result::already_in_sync; - std::stringstream ss; - ss << "CREATE "; - if(tableImpl->table.unique) { - ss << "UNIQUE "; - } - using columns_type = typename decltype(tableImpl->table)::columns_type; - using head_t = typename std::tuple_element<0, columns_type>::type; - using indexed_type = typename internal::table_type::type; - ss << "INDEX IF NOT EXISTS '" << tableImpl->table.name << "' ON '" - << this->impl.find_table_name(typeid(indexed_type)) << "' ( "; - std::vector columnNames; - iterate_tuple(tableImpl->table.columns, [&columnNames, this](auto &v) { - columnNames.push_back(this->impl.column_name(v)); - }); - for(size_t i = 0; i < columnNames.size(); ++i) { - ss << "'" << columnNames[i] << "'"; - if(i < columnNames.size() - 1) { - ss << ","; - } - ss << " "; - } - ss << ") "; - auto query = ss.str(); + using context_t = serializator_context; + context_t context{this->impl}; + auto query = serialize(tableImpl.table, context); auto rc = sqlite3_exec(db, query.c_str(), nullptr, nullptr, nullptr); if(rc != SQLITE_OK) { throw std::system_error(std::error_code(sqlite3_errcode(db), get_sqlite_error_category()), @@ -11695,13 +11814,14 @@ namespace sqlite_orm { } template - sync_schema_result sync_table(storage_impl, Tss...> *tImpl, sqlite3 *db, bool preserve) { + sync_schema_result + sync_table(const storage_impl, Tss...> &tImpl, sqlite3 *db, bool preserve) { auto res = sync_schema_result::already_in_sync; - auto schema_stat = tImpl->schema_status(db, preserve); + auto schema_stat = tImpl.schema_status(db, preserve); if(schema_stat != decltype(schema_stat)::already_in_sync) { if(schema_stat == decltype(schema_stat)::new_table_created) { - this->create_table(db, tImpl->table.name, tImpl); + this->create_table(db, tImpl.table.name, tImpl); res = decltype(res)::new_table_created; } else { if(schema_stat == sync_schema_result::old_columns_removed || @@ -11709,15 +11829,15 @@ namespace sqlite_orm { schema_stat == sync_schema_result::new_columns_added_and_old_columns_removed) { // get table info provided in `make_table` call.. - auto storageTableInfo = tImpl->table.get_table_info(); + auto storageTableInfo = tImpl.table.get_table_info(); // now get current table info from db using `PRAGMA table_info` query.. - auto dbTableInfo = tImpl->get_table_info(tImpl->table.name, db); + auto dbTableInfo = tImpl.get_table_info(tImpl.table.name, db); // this vector will contain pointers to columns that gotta be added.. std::vector columnsToAdd; - tImpl->get_remove_add_columns(columnsToAdd, storageTableInfo, dbTableInfo); + tImpl.get_remove_add_columns(columnsToAdd, storageTableInfo, dbTableInfo); if(schema_stat == sync_schema_result::old_columns_removed) { @@ -11728,7 +11848,7 @@ namespace sqlite_orm { if(schema_stat == sync_schema_result::new_columns_added) { for(auto columnPointer: columnsToAdd) { - tImpl->add_column(*columnPointer, db); + tImpl.add_column(*columnPointer, db); } res = decltype(res)::new_columns_added; } @@ -11740,8 +11860,8 @@ namespace sqlite_orm { res = decltype(res)::new_columns_added_and_old_columns_removed; } } else if(schema_stat == sync_schema_result::dropped_and_recreated) { - this->drop_table_internal(tImpl->table.name, db); - this->create_table(db, tImpl->table.name, tImpl); + this->drop_table_internal(tImpl.table.name, db); + this->create_table(db, tImpl.table.name, tImpl); res = decltype(res)::dropped_and_recreated; } } @@ -11781,9 +11901,9 @@ namespace sqlite_orm { auto con = this->get_connection(); std::map result; auto db = con.get(); - this->impl.for_each([&result, db, preserve, this](auto tableImpl) { + this->impl.for_each([&result, db, preserve, this](auto &tableImpl) { auto res = this->sync_table(tableImpl, db, preserve); - result.insert({tableImpl->table.name, res}); + result.insert({tableImpl.table.name, res}); }); return result; } @@ -11798,7 +11918,7 @@ namespace sqlite_orm { std::map result; auto db = con.get(); this->impl.for_each([&result, db, preserve](auto tableImpl) { - result.insert({tableImpl->table.name, tableImpl->schema_status(db, preserve)}); + result.insert({tableImpl.table.name, tableImpl.schema_status(db, preserve)}); }); return result; } diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index a813d1816..9a3d22120 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -10,7 +10,7 @@ else() add_subdirectory(third_party/sqlite) endif() -add_executable(unit_tests tests.cpp tests2.cpp tests3.cpp tests4.cpp tests5.cpp private_getters_tests.cpp pragma_tests.cpp explicit_columns.cpp core_functions_tests.cpp constraints/composite_key.cpp static_tests.cpp operators/arithmetic_operators.cpp operators/like.cpp operators/glob.cpp operators/in.cpp operators/cast.cpp operators/is_null.cpp operators/not_operator.cpp operators/bitwise.cpp dynamic_order_by.cpp prepared_statement_tests/select.cpp prepared_statement_tests/get_all.cpp prepared_statement_tests/get_all_pointer.cpp prepared_statement_tests/get_all_optional.cpp prepared_statement_tests/update_all.cpp prepared_statement_tests/remove_all.cpp prepared_statement_tests/get.cpp prepared_statement_tests/get_pointer.cpp prepared_statement_tests/get_optional.cpp prepared_statement_tests/update.cpp prepared_statement_tests/remove.cpp prepared_statement_tests/insert.cpp prepared_statement_tests/replace.cpp prepared_statement_tests/insert_range.cpp prepared_statement_tests/replace_range.cpp prepared_statement_tests/insert_explicit.cpp pragma_tests.cpp simple_query.cpp static_tests/is_bindable.cpp static_tests/arithmetic_operators_result_type.cpp static_tests/tuple_conc.cpp static_tests/node_tuple.cpp static_tests/bindable_filter.cpp static_tests/count_tuple.cpp static_tests/member_traits_tests.cpp static_tests/select_return_type.cpp constraints/default.cpp constraints/unique.cpp constraints/foreign_key.cpp constraints/check.cpp table_tests.cpp statement_serializator_tests/primary_key.cpp statement_serializator_tests/column_names.cpp statement_serializator_tests/autoincrement.cpp statement_serializator_tests/arithmetic_operators.cpp statement_serializator_tests/core_functions.cpp statement_serializator_tests/comparison_operators.cpp statement_serializator_tests/unique.cpp statement_serializator_tests/foreign_key.cpp statement_serializator_tests/collate.cpp statement_serializator_tests/check.cpp unique_cases/get_all_with_two_tables.cpp unique_cases/prepare_get_all_with_case.cpp unique_cases/index_named_table_with_fk.cpp unique_cases/issue525.cpp get_all_custom_containers.cpp select_asterisk.cpp backup_tests.cpp) +add_executable(unit_tests tests.cpp tests2.cpp tests3.cpp tests4.cpp tests5.cpp private_getters_tests.cpp pragma_tests.cpp explicit_columns.cpp core_functions_tests.cpp index_tests.cpp constraints/composite_key.cpp static_tests.cpp operators/arithmetic_operators.cpp operators/like.cpp operators/glob.cpp operators/in.cpp operators/cast.cpp operators/is_null.cpp operators/not_operator.cpp operators/bitwise.cpp dynamic_order_by.cpp prepared_statement_tests/select.cpp prepared_statement_tests/get_all.cpp prepared_statement_tests/get_all_pointer.cpp prepared_statement_tests/get_all_optional.cpp prepared_statement_tests/update_all.cpp prepared_statement_tests/remove_all.cpp prepared_statement_tests/get.cpp prepared_statement_tests/get_pointer.cpp prepared_statement_tests/get_optional.cpp prepared_statement_tests/update.cpp prepared_statement_tests/remove.cpp prepared_statement_tests/insert.cpp prepared_statement_tests/replace.cpp prepared_statement_tests/insert_range.cpp prepared_statement_tests/replace_range.cpp prepared_statement_tests/insert_explicit.cpp pragma_tests.cpp simple_query.cpp static_tests/is_bindable.cpp static_tests/arithmetic_operators_result_type.cpp static_tests/tuple_conc.cpp static_tests/node_tuple.cpp static_tests/bindable_filter.cpp static_tests/count_tuple.cpp static_tests/member_traits_tests.cpp static_tests/select_return_type.cpp constraints/default.cpp constraints/unique.cpp constraints/foreign_key.cpp constraints/check.cpp table_tests.cpp statement_serializator_tests/primary_key.cpp statement_serializator_tests/column_names.cpp statement_serializator_tests/autoincrement.cpp statement_serializator_tests/arithmetic_operators.cpp statement_serializator_tests/core_functions.cpp statement_serializator_tests/comparison_operators.cpp statement_serializator_tests/unique.cpp statement_serializator_tests/foreign_key.cpp statement_serializator_tests/collate.cpp statement_serializator_tests/check.cpp statement_serializator_tests/index.cpp statement_serializator_tests/indexed_column.cpp unique_cases/get_all_with_two_tables.cpp unique_cases/prepare_get_all_with_case.cpp unique_cases/index_named_table_with_fk.cpp unique_cases/issue525.cpp get_all_custom_containers.cpp select_asterisk.cpp backup_tests.cpp) if(SQLITE_ORM_OMITS_CODECVT) diff --git a/tests/index_tests.cpp b/tests/index_tests.cpp new file mode 100644 index 000000000..ccb64f6ad --- /dev/null +++ b/tests/index_tests.cpp @@ -0,0 +1,47 @@ +#include +#include + +using namespace sqlite_orm; + +TEST_CASE("index") { + struct User { + int id = 0; + std::string name; + }; + + auto table = make_table("users", make_column("id", &User::id), make_column("name", &User::name)); + { + auto storage = make_storage({}, make_index("id_index", &User::id), table); + storage.sync_schema(); + } + { + auto storage = make_storage({}, make_index("id_index", indexed_column(&User::id).asc()), table); + storage.sync_schema(); + } + { + auto storage = make_storage({}, make_index("id_index", indexed_column(&User::id).desc()), table); + storage.sync_schema(); + } + { + auto storage = make_storage({}, make_index("name_index", &User::name), table); + storage.sync_schema(); + } + { + auto storage = make_storage({}, make_index("name_index", indexed_column(&User::name)), table); + storage.sync_schema(); + } + { + auto storage = make_storage({}, make_index("name_index", indexed_column(&User::name).collate("binary")), table); + storage.sync_schema(); + } + { + auto storage = + make_storage({}, make_index("name_index", indexed_column(&User::name).collate("binary").asc()), table); + storage.sync_schema(); + } + { + auto storage = + make_storage({}, make_index("name_index", indexed_column(&User::name).collate("binary").desc()), table); + storage.sync_schema(); + } +} diff --git a/tests/statement_serializator_tests/index.cpp b/tests/statement_serializator_tests/index.cpp new file mode 100644 index 000000000..64e247a9a --- /dev/null +++ b/tests/statement_serializator_tests/index.cpp @@ -0,0 +1,19 @@ +#include +#include + +using namespace sqlite_orm; + +TEST_CASE("statement_serializator index") { + struct User { + int id = 0; + std::string name; + }; + auto table = make_table("users", make_column("id", &User::id), make_column("name", &User::name)); + using storage_impl_t = internal::storage_impl; + auto storageImpl = storage_impl_t{table}; + using context_t = internal::serializator_context; + context_t context{storageImpl}; + auto index = make_index("id_index", &User::id); + auto value = internal::serialize(index, context); + REQUIRE(value == "CREATE INDEX IF NOT EXISTS 'id_index' ON 'users' ('id')"); +} diff --git a/tests/statement_serializator_tests/indexed_column.cpp b/tests/statement_serializator_tests/indexed_column.cpp new file mode 100644 index 000000000..3736056ac --- /dev/null +++ b/tests/statement_serializator_tests/indexed_column.cpp @@ -0,0 +1,46 @@ +#include +#include + +using namespace sqlite_orm; + +TEST_CASE("statement_serializator indexed_column") { + struct User { + int id = 0; + std::string name; + }; + auto table = make_table("users", make_column("id", &User::id), make_column("name", &User::name)); + using storage_impl_t = internal::storage_impl; + auto storageImpl = storage_impl_t{table}; + using context_t = internal::serializator_context; + context_t context{storageImpl}; + { + auto column = indexed_column(&User::id); + auto value = internal::serialize(column, context); + REQUIRE(value == "\"id\""); + } + { + auto column = indexed_column(&User::id).asc(); + auto value = internal::serialize(column, context); + REQUIRE(value == "\"id\" ASC"); + } + { + auto column = indexed_column(&User::id).desc(); + auto value = internal::serialize(column, context); + REQUIRE(value == "\"id\" DESC"); + } + { + auto column = indexed_column(&User::id).collate("BINARY"); + auto value = internal::serialize(column, context); + REQUIRE(value == "\"id\" COLLATE BINARY"); + } + { + auto column = indexed_column(&User::name).collate("BINARY").asc(); + auto value = internal::serialize(column, context); + REQUIRE(value == "\"name\" COLLATE BINARY ASC"); + } + { + auto column = indexed_column(&User::name).collate("OTHER").desc(); + auto value = internal::serialize(column, context); + REQUIRE(value == "\"name\" COLLATE OTHER DESC"); + } +} From 65bd71dc6f3601766b23f56eb4444ca05570e5fa Mon Sep 17 00:00:00 2001 From: fnc12 Date: Thu, 6 Aug 2020 21:19:09 +0300 Subject: [PATCH 119/132] added a comment --- dev/indexed_column.h | 4 ++++ dev/statement_serializator.h | 2 +- include/sqlite_orm/sqlite_orm.h | 2 +- 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/dev/indexed_column.h b/dev/indexed_column.h index 9b2e710a2..7b19e3b43 100644 --- a/dev/indexed_column.h +++ b/dev/indexed_column.h @@ -59,6 +59,10 @@ namespace sqlite_orm { } + /** + * Use this function to specify indexed column inside `make_index` function call. + * Example: make_index("index_name", indexed_column(&User::id).asc()) + */ template internal::indexed_column_t indexed_column(C column_or_expression) { return {std::move(column_or_expression)}; diff --git a/dev/statement_serializator.h b/dev/statement_serializator.h index aaf193944..651ba07e5 100644 --- a/dev/statement_serializator.h +++ b/dev/statement_serializator.h @@ -1346,7 +1346,7 @@ namespace sqlite_orm { ss << " ASC"; break; default: - throw std::system_error(std::make_error_code(orm_error_code::column_not_found)); + throw std::system_error(std::make_error_code(orm_error_code::incorrect_order)); } } return ss.str(); diff --git a/include/sqlite_orm/sqlite_orm.h b/include/sqlite_orm/sqlite_orm.h index e602779c4..2047bc048 100644 --- a/include/sqlite_orm/sqlite_orm.h +++ b/include/sqlite_orm/sqlite_orm.h @@ -10818,7 +10818,7 @@ namespace sqlite_orm { ss << " ASC"; break; default: - throw std::system_error(std::make_error_code(orm_error_code::column_not_found)); + throw std::system_error(std::make_error_code(orm_error_code::incorrect_order)); } } return ss.str(); From 5ba0dab8e2153186517fa5444245bceb8e363a57 Mon Sep 17 00:00:00 2001 From: fnc12 Date: Sun, 16 Aug 2020 14:55:19 +0300 Subject: [PATCH 120/132] added delete_with_two_fields to cmake --- tests/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 9a3d22120..b0f83ee25 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -10,7 +10,7 @@ else() add_subdirectory(third_party/sqlite) endif() -add_executable(unit_tests tests.cpp tests2.cpp tests3.cpp tests4.cpp tests5.cpp private_getters_tests.cpp pragma_tests.cpp explicit_columns.cpp core_functions_tests.cpp index_tests.cpp constraints/composite_key.cpp static_tests.cpp operators/arithmetic_operators.cpp operators/like.cpp operators/glob.cpp operators/in.cpp operators/cast.cpp operators/is_null.cpp operators/not_operator.cpp operators/bitwise.cpp dynamic_order_by.cpp prepared_statement_tests/select.cpp prepared_statement_tests/get_all.cpp prepared_statement_tests/get_all_pointer.cpp prepared_statement_tests/get_all_optional.cpp prepared_statement_tests/update_all.cpp prepared_statement_tests/remove_all.cpp prepared_statement_tests/get.cpp prepared_statement_tests/get_pointer.cpp prepared_statement_tests/get_optional.cpp prepared_statement_tests/update.cpp prepared_statement_tests/remove.cpp prepared_statement_tests/insert.cpp prepared_statement_tests/replace.cpp prepared_statement_tests/insert_range.cpp prepared_statement_tests/replace_range.cpp prepared_statement_tests/insert_explicit.cpp pragma_tests.cpp simple_query.cpp static_tests/is_bindable.cpp static_tests/arithmetic_operators_result_type.cpp static_tests/tuple_conc.cpp static_tests/node_tuple.cpp static_tests/bindable_filter.cpp static_tests/count_tuple.cpp static_tests/member_traits_tests.cpp static_tests/select_return_type.cpp constraints/default.cpp constraints/unique.cpp constraints/foreign_key.cpp constraints/check.cpp table_tests.cpp statement_serializator_tests/primary_key.cpp statement_serializator_tests/column_names.cpp statement_serializator_tests/autoincrement.cpp statement_serializator_tests/arithmetic_operators.cpp statement_serializator_tests/core_functions.cpp statement_serializator_tests/comparison_operators.cpp statement_serializator_tests/unique.cpp statement_serializator_tests/foreign_key.cpp statement_serializator_tests/collate.cpp statement_serializator_tests/check.cpp statement_serializator_tests/index.cpp statement_serializator_tests/indexed_column.cpp unique_cases/get_all_with_two_tables.cpp unique_cases/prepare_get_all_with_case.cpp unique_cases/index_named_table_with_fk.cpp unique_cases/issue525.cpp get_all_custom_containers.cpp select_asterisk.cpp backup_tests.cpp) +add_executable(unit_tests tests.cpp tests2.cpp tests3.cpp tests4.cpp tests5.cpp private_getters_tests.cpp pragma_tests.cpp explicit_columns.cpp core_functions_tests.cpp index_tests.cpp constraints/composite_key.cpp static_tests.cpp operators/arithmetic_operators.cpp operators/like.cpp operators/glob.cpp operators/in.cpp operators/cast.cpp operators/is_null.cpp operators/not_operator.cpp operators/bitwise.cpp dynamic_order_by.cpp prepared_statement_tests/select.cpp prepared_statement_tests/get_all.cpp prepared_statement_tests/get_all_pointer.cpp prepared_statement_tests/get_all_optional.cpp prepared_statement_tests/update_all.cpp prepared_statement_tests/remove_all.cpp prepared_statement_tests/get.cpp prepared_statement_tests/get_pointer.cpp prepared_statement_tests/get_optional.cpp prepared_statement_tests/update.cpp prepared_statement_tests/remove.cpp prepared_statement_tests/insert.cpp prepared_statement_tests/replace.cpp prepared_statement_tests/insert_range.cpp prepared_statement_tests/replace_range.cpp prepared_statement_tests/insert_explicit.cpp pragma_tests.cpp simple_query.cpp static_tests/is_bindable.cpp static_tests/arithmetic_operators_result_type.cpp static_tests/tuple_conc.cpp static_tests/node_tuple.cpp static_tests/bindable_filter.cpp static_tests/count_tuple.cpp static_tests/member_traits_tests.cpp static_tests/select_return_type.cpp constraints/default.cpp constraints/unique.cpp constraints/foreign_key.cpp constraints/check.cpp table_tests.cpp statement_serializator_tests/primary_key.cpp statement_serializator_tests/column_names.cpp statement_serializator_tests/autoincrement.cpp statement_serializator_tests/arithmetic_operators.cpp statement_serializator_tests/core_functions.cpp statement_serializator_tests/comparison_operators.cpp statement_serializator_tests/unique.cpp statement_serializator_tests/foreign_key.cpp statement_serializator_tests/collate.cpp statement_serializator_tests/check.cpp statement_serializator_tests/index.cpp statement_serializator_tests/indexed_column.cpp unique_cases/get_all_with_two_tables.cpp unique_cases/prepare_get_all_with_case.cpp unique_cases/index_named_table_with_fk.cpp unique_cases/issue525.cpp unique_cases/delete_with_two_fields.cpp get_all_custom_containers.cpp select_asterisk.cpp backup_tests.cpp) if(SQLITE_ORM_OMITS_CODECVT) From 9d94ea22d217d05d2a4aa09ee164195f0ea60d73 Mon Sep 17 00:00:00 2001 From: fnc12 Date: Sun, 16 Aug 2020 21:11:50 +0300 Subject: [PATCH 121/132] changed scope value to type --- dev/statement_serializator.h | 8 ++++---- include/sqlite_orm/sqlite_orm.h | 12 ++++++++---- 2 files changed, 12 insertions(+), 8 deletions(-) diff --git a/dev/statement_serializator.h b/dev/statement_serializator.h index 651ba07e5..f91933c35 100644 --- a/dev/statement_serializator.h +++ b/dev/statement_serializator.h @@ -1642,10 +1642,10 @@ namespace sqlite_orm { std::stringstream ss; ss << '('; auto index = 0; - const auto tupleSize = int(std::tuple_size::value); + using TupleSize = std::tuple_size; iterate_tuple(statement, [&context, &index, &ss](auto &value) { ss << serialize(value, context); - if(index < tupleSize - 1) { + if(index < TupleSize::value - 1) { ss << ", "; } ++index; @@ -1670,10 +1670,10 @@ namespace sqlite_orm { auto index = 0; auto &tuple = statement.tuple; using tuple_type = typename std::decay::type; - const auto tupleSize = int(std::tuple_size::value); + using TupleSize = std::tuple_size; iterate_tuple(tuple, [&context, &index, &ss](auto &value) { ss << serialize(value, context); - if(index < tupleSize - 1) { + if(index < TupleSize::value - 1) { ss << ", "; } ++index; diff --git a/include/sqlite_orm/sqlite_orm.h b/include/sqlite_orm/sqlite_orm.h index 2047bc048..80991c873 100644 --- a/include/sqlite_orm/sqlite_orm.h +++ b/include/sqlite_orm/sqlite_orm.h @@ -5375,6 +5375,10 @@ namespace sqlite_orm { } + /** + * Use this function to specify indexed column inside `make_index` function call. + * Example: make_index("index_name", indexed_column(&User::id).asc()) + */ template internal::indexed_column_t indexed_column(C column_or_expression) { return {std::move(column_or_expression)}; @@ -11114,10 +11118,10 @@ namespace sqlite_orm { std::stringstream ss; ss << '('; auto index = 0; - const auto tupleSize = int(std::tuple_size::value); + using TupleSize = std::tuple_size; iterate_tuple(statement, [&context, &index, &ss](auto &value) { ss << serialize(value, context); - if(index < tupleSize - 1) { + if(index < TupleSize::value - 1) { ss << ", "; } ++index; @@ -11142,10 +11146,10 @@ namespace sqlite_orm { auto index = 0; auto &tuple = statement.tuple; using tuple_type = typename std::decay::type; - const auto tupleSize = int(std::tuple_size::value); + using TupleSize = std::tuple_size; iterate_tuple(tuple, [&context, &index, &ss](auto &value) { ss << serialize(value, context); - if(index < tupleSize - 1) { + if(index < TupleSize::value - 1) { ss << ", "; } ++index; From 96c70b01261a7da1e2ad54b011a27202ce19ef30 Mon Sep 17 00:00:00 2001 From: fnc12 Date: Tue, 18 Aug 2020 01:14:57 +0300 Subject: [PATCH 122/132] added ast iterator for values and dynamic values --- dev/ast_iterator.h | 22 +++++ include/sqlite_orm/sqlite_orm.h | 87 ++++++++++++------- tests/unique_cases/delete_with_two_fields.cpp | 37 ++++++-- 3 files changed, 108 insertions(+), 38 deletions(-) diff --git a/dev/ast_iterator.h b/dev/ast_iterator.h index 8c96203ee..12fe84f66 100644 --- a/dev/ast_iterator.h +++ b/dev/ast_iterator.h @@ -9,6 +9,7 @@ #include "tuple_helper.h" #include "core_functions.h" #include "prepared_statement.h" +#include "values.h" namespace sqlite_orm { @@ -488,5 +489,26 @@ namespace sqlite_orm { iterate_ast(a.argument, l); } }; + + template + struct ast_iterator, void> { + using node_type = values_t; + + template + void operator()(const node_type &node, const L &l) const { + iterate_ast(node.tuple, l); + } + }; + + template + struct ast_iterator, void> { + using node_type = dynamic_values_t; + + template + void operator()(const node_type &node, const L &l) const { + iterate_ast(node.vector, l); + } + }; + } } diff --git a/include/sqlite_orm/sqlite_orm.h b/include/sqlite_orm/sqlite_orm.h index 80991c873..e5312cc66 100644 --- a/include/sqlite_orm/sqlite_orm.h +++ b/include/sqlite_orm/sqlite_orm.h @@ -7549,6 +7549,40 @@ namespace sqlite_orm { #endif // SQLITE_ORM_OPTIONAL_SUPPORTED } +// #include "values.h" + +#include // std::vector +#include +#include // std::tuple + +namespace sqlite_orm { + + namespace internal { + + template + struct values_t { + std::tuple tuple; + }; + + template + struct dynamic_values_t { + std::vector vector; + }; + + } + + template + internal::values_t values(Args... args) { + return {{std::forward(args)...}}; + } + + template + internal::dynamic_values_t values(std::vector vector) { + return {{move(vector)}}; + } + +} + namespace sqlite_orm { namespace internal { @@ -8027,6 +8061,27 @@ namespace sqlite_orm { iterate_ast(a.argument, l); } }; + + template + struct ast_iterator, void> { + using node_type = values_t; + + template + void operator()(const node_type &node, const L &l) const { + iterate_ast(node.tuple, l); + } + }; + + template + struct ast_iterator, void> { + using node_type = dynamic_values_t; + + template + void operator()(const node_type &node, const L &l) const { + iterate_ast(node.vector, l); + } + }; + } } @@ -9459,38 +9514,6 @@ namespace sqlite_orm { // #include "values.h" -#include // std::vector -#include -#include // std::tuple - -namespace sqlite_orm { - - namespace internal { - - template - struct values_t { - std::tuple tuple; - }; - - template - struct dynamic_values_t { - std::vector vector; - }; - - } - - template - internal::values_t values(Args... args) { - return {{std::forward(args)...}}; - } - - template - internal::dynamic_values_t values(std::vector vector) { - return {{move(vector)}}; - } - -} - // #include "table_type.h" // #include "indexed_column.h" diff --git a/tests/unique_cases/delete_with_two_fields.cpp b/tests/unique_cases/delete_with_two_fields.cpp index b67142a8a..0d91fc9ce 100644 --- a/tests/unique_cases/delete_with_two_fields.cpp +++ b/tests/unique_cases/delete_with_two_fields.cpp @@ -13,11 +13,36 @@ TEST_CASE("delete with two fields") { make_column("serial_number", &Device::serialNumber), make_column("device_id", &Device::deviceId))); storage.sync_schema(); - storage.remove_all(where(in(std::make_tuple(&Device::serialNumber, &Device::deviceId), - values(std::make_tuple("abc", "123"), std::make_tuple("def", "456"))))); - storage.remove_all( - where(in(std::make_tuple(&Device::serialNumber, &Device::deviceId), - values(std::vector>{std::make_tuple("abc", "123"), - std::make_tuple("def", "456")})))); + SECTION("none") { + storage.remove_all(where(in(std::make_tuple(&Device::serialNumber, &Device::deviceId), + values(std::make_tuple("abc", "123"), std::make_tuple("def", "456"))))); + + storage.remove_all( + where(in(std::make_tuple(&Device::serialNumber, &Device::deviceId), + values(std::vector>{std::make_tuple("abc", "123"), + std::make_tuple("def", "456")})))); + REQUIRE(storage.count() == 0); + } + SECTION("two devices") { + Device device_abc{"abc", "123"}; + Device device_def{"def", "456"}; + + storage.replace(device_abc); + REQUIRE(storage.count() == 1); + storage.replace(device_def); + REQUIRE(storage.count() == 2); + + SECTION("static condition") { + storage.remove_all(where(in(std::make_tuple(&Device::serialNumber, &Device::deviceId), + values(std::make_tuple("abc", "123"), std::make_tuple("def", "456"))))); + } + SECTION("dynamic condition") { + storage.remove_all( + where(in(std::make_tuple(&Device::serialNumber, &Device::deviceId), + values(std::vector>{std::make_tuple("abc", "123"), + std::make_tuple("def", "456")})))); + } + REQUIRE(storage.count() == 0); + } } From 4a4a5e0f6257bb6c179981c4fb69011be7bbe53d Mon Sep 17 00:00:00 2001 From: Yevgeniy Zakharov Date: Tue, 25 Aug 2020 10:05:42 +0300 Subject: [PATCH 123/132] Update README.md --- README.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 0d6df4f1d..a1d0ee5f0 100644 --- a/README.md +++ b/README.md @@ -16,8 +16,6 @@ SQLite ORM light header only library for modern C++ | [`master`](https://github.com/fnc12/sqlite_orm/tree/master) | [![Build Status](https://travis-ci.org/fnc12/sqlite_orm.svg?branch=master)](https://travis-ci.org/fnc12/sqlite_orm) | [![Build status](https://ci.appveyor.com/api/projects/status/github/fnc12/sqlite_orm?branch=master&svg=true)](https://ci.appveyor.com/project/fnc12/sqlite-orm/history) | | | [![Website](https://img.shields.io/badge/official-website-brightgreen.svg)](https://github.com/fnc12/sqlite_orm/) | | [`dev`](https://github.com/fnc12/sqlite_orm/tree/dev) | [![Build Status](https://travis-ci.org/fnc12/sqlite_orm.svg?branch=dev)](https://travis-ci.org/fnc12/sqlite_orm) | [![Build status](https://ci.appveyor.com/api/projects/status/github/fnc12/sqlite_orm?branch=dev&svg=true)](https://ci.appveyor.com/project/fnc12/sqlite-orm/history) | | | [![Website](https://img.shields.io/badge/official-website-brightgreen.svg)](https://github.com/fnc12/sqlite_orm/tree/dev) | -GitAds - # Advantages * **No raw string queries** @@ -795,3 +793,7 @@ If you want to use the lib directly with Make or something else, just set the in * C++14 compatible compiler (not C++11 cause of templated lambdas in the lib). * Sqlite3 installed on your system and in the path, so cmake can find it (or linked to you project if you don't use cmake) + +# SqliteMan + +In case you need a native SQLite client for macOS or Windows 10 you can use SqliteMan https://sqliteman.dev. It is not a commercial. It is a free native client being developed by the maintainer of this repo. From 250ce1cd7b0b6ec415898e0a26cda49a2d326bd3 Mon Sep 17 00:00:00 2001 From: fnc12 Date: Sun, 6 Sep 2020 11:42:59 +0300 Subject: [PATCH 124/132] added ast_iterator specialization for collate_t --- dev/ast_iterator.h | 10 +++ dev/conditions.h | 2 +- include/sqlite_orm/sqlite_orm.h | 12 +++- tests/CMakeLists.txt | 2 +- tests/tests.cpp | 62 ++++++++----------- .../join_iterator_ctor_compilation_error.cpp | 39 ++++++++++++ 6 files changed, 88 insertions(+), 39 deletions(-) create mode 100644 tests/unique_cases/join_iterator_ctor_compilation_error.cpp diff --git a/dev/ast_iterator.h b/dev/ast_iterator.h index 12fe84f66..e23329525 100644 --- a/dev/ast_iterator.h +++ b/dev/ast_iterator.h @@ -510,5 +510,15 @@ namespace sqlite_orm { } }; + template + struct ast_iterator, void> { + using node_type = collate_t; + + template + void operator()(const node_type &node, const L &l) const { + iterate_ast(node.expr, l); + } + }; + } } diff --git a/dev/conditions.h b/dev/conditions.h index eb1bc8e37..386bb2f15 100644 --- a/dev/conditions.h +++ b/dev/conditions.h @@ -72,7 +72,7 @@ namespace sqlite_orm { T expr; internal::collate_argument argument; - collate_t(T expr_, internal::collate_argument argument_) : expr(expr_), argument(argument_) {} + collate_t(T expr_, internal::collate_argument argument_) : expr(std::move(expr_)), argument(argument_) {} operator std::string() const { return constraints::collate_t{this->argument}; diff --git a/include/sqlite_orm/sqlite_orm.h b/include/sqlite_orm/sqlite_orm.h index e5312cc66..429094d67 100644 --- a/include/sqlite_orm/sqlite_orm.h +++ b/include/sqlite_orm/sqlite_orm.h @@ -1922,7 +1922,7 @@ namespace sqlite_orm { T expr; internal::collate_argument argument; - collate_t(T expr_, internal::collate_argument argument_) : expr(expr_), argument(argument_) {} + collate_t(T expr_, internal::collate_argument argument_) : expr(std::move(expr_)), argument(argument_) {} operator std::string() const { return constraints::collate_t{this->argument}; @@ -8082,6 +8082,16 @@ namespace sqlite_orm { } }; + template + struct ast_iterator, void> { + using node_type = collate_t; + + template + void operator()(const node_type &node, const L &l) const { + iterate_ast(node.expr, l); + } + }; + } } diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index b0f83ee25..6abacb16a 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -10,7 +10,7 @@ else() add_subdirectory(third_party/sqlite) endif() -add_executable(unit_tests tests.cpp tests2.cpp tests3.cpp tests4.cpp tests5.cpp private_getters_tests.cpp pragma_tests.cpp explicit_columns.cpp core_functions_tests.cpp index_tests.cpp constraints/composite_key.cpp static_tests.cpp operators/arithmetic_operators.cpp operators/like.cpp operators/glob.cpp operators/in.cpp operators/cast.cpp operators/is_null.cpp operators/not_operator.cpp operators/bitwise.cpp dynamic_order_by.cpp prepared_statement_tests/select.cpp prepared_statement_tests/get_all.cpp prepared_statement_tests/get_all_pointer.cpp prepared_statement_tests/get_all_optional.cpp prepared_statement_tests/update_all.cpp prepared_statement_tests/remove_all.cpp prepared_statement_tests/get.cpp prepared_statement_tests/get_pointer.cpp prepared_statement_tests/get_optional.cpp prepared_statement_tests/update.cpp prepared_statement_tests/remove.cpp prepared_statement_tests/insert.cpp prepared_statement_tests/replace.cpp prepared_statement_tests/insert_range.cpp prepared_statement_tests/replace_range.cpp prepared_statement_tests/insert_explicit.cpp pragma_tests.cpp simple_query.cpp static_tests/is_bindable.cpp static_tests/arithmetic_operators_result_type.cpp static_tests/tuple_conc.cpp static_tests/node_tuple.cpp static_tests/bindable_filter.cpp static_tests/count_tuple.cpp static_tests/member_traits_tests.cpp static_tests/select_return_type.cpp constraints/default.cpp constraints/unique.cpp constraints/foreign_key.cpp constraints/check.cpp table_tests.cpp statement_serializator_tests/primary_key.cpp statement_serializator_tests/column_names.cpp statement_serializator_tests/autoincrement.cpp statement_serializator_tests/arithmetic_operators.cpp statement_serializator_tests/core_functions.cpp statement_serializator_tests/comparison_operators.cpp statement_serializator_tests/unique.cpp statement_serializator_tests/foreign_key.cpp statement_serializator_tests/collate.cpp statement_serializator_tests/check.cpp statement_serializator_tests/index.cpp statement_serializator_tests/indexed_column.cpp unique_cases/get_all_with_two_tables.cpp unique_cases/prepare_get_all_with_case.cpp unique_cases/index_named_table_with_fk.cpp unique_cases/issue525.cpp unique_cases/delete_with_two_fields.cpp get_all_custom_containers.cpp select_asterisk.cpp backup_tests.cpp) +add_executable(unit_tests tests.cpp tests2.cpp tests3.cpp tests4.cpp tests5.cpp private_getters_tests.cpp pragma_tests.cpp explicit_columns.cpp core_functions_tests.cpp index_tests.cpp constraints/composite_key.cpp static_tests.cpp operators/arithmetic_operators.cpp operators/like.cpp operators/glob.cpp operators/in.cpp operators/cast.cpp operators/is_null.cpp operators/not_operator.cpp operators/bitwise.cpp dynamic_order_by.cpp prepared_statement_tests/select.cpp prepared_statement_tests/get_all.cpp prepared_statement_tests/get_all_pointer.cpp prepared_statement_tests/get_all_optional.cpp prepared_statement_tests/update_all.cpp prepared_statement_tests/remove_all.cpp prepared_statement_tests/get.cpp prepared_statement_tests/get_pointer.cpp prepared_statement_tests/get_optional.cpp prepared_statement_tests/update.cpp prepared_statement_tests/remove.cpp prepared_statement_tests/insert.cpp prepared_statement_tests/replace.cpp prepared_statement_tests/insert_range.cpp prepared_statement_tests/replace_range.cpp prepared_statement_tests/insert_explicit.cpp pragma_tests.cpp simple_query.cpp static_tests/is_bindable.cpp static_tests/arithmetic_operators_result_type.cpp static_tests/tuple_conc.cpp static_tests/node_tuple.cpp static_tests/bindable_filter.cpp static_tests/count_tuple.cpp static_tests/member_traits_tests.cpp static_tests/select_return_type.cpp constraints/default.cpp constraints/unique.cpp constraints/foreign_key.cpp constraints/check.cpp table_tests.cpp statement_serializator_tests/primary_key.cpp statement_serializator_tests/column_names.cpp statement_serializator_tests/autoincrement.cpp statement_serializator_tests/arithmetic_operators.cpp statement_serializator_tests/core_functions.cpp statement_serializator_tests/comparison_operators.cpp statement_serializator_tests/unique.cpp statement_serializator_tests/foreign_key.cpp statement_serializator_tests/collate.cpp statement_serializator_tests/check.cpp statement_serializator_tests/index.cpp statement_serializator_tests/indexed_column.cpp unique_cases/get_all_with_two_tables.cpp unique_cases/prepare_get_all_with_case.cpp unique_cases/index_named_table_with_fk.cpp unique_cases/issue525.cpp unique_cases/delete_with_two_fields.cpp unique_cases/join_iterator_ctor_compilation_error.cpp get_all_custom_containers.cpp select_asterisk.cpp backup_tests.cpp) if(SQLITE_ORM_OMITS_CODECVT) diff --git a/tests/tests.cpp b/tests/tests.cpp index e295662ac..adbe80e96 100644 --- a/tests/tests.cpp +++ b/tests/tests.cpp @@ -14,42 +14,6 @@ using namespace sqlite_orm; -TEST_CASE("Join iterator ctor compilation error") { - // TODO: move to static tests - struct Tag { - int objectId; - std::string text; - }; - - auto storage = - make_storage("join_error.sqlite", - make_table("tags", make_column("object_id", &Tag::objectId), make_column("text", &Tag::text))); - storage.sync_schema(); - - auto offs = 0; - auto lim = 5; - storage.select(columns(&Tag::text, count(&Tag::text)), - group_by(&Tag::text), - order_by(count(&Tag::text)).desc(), - limit(offs, lim)); - { - auto statement = storage.prepare(select(columns(&Tag::text, count(&Tag::text)), - group_by(&Tag::text), - order_by(count(&Tag::text)).desc(), - limit(offs, lim))); - REQUIRE(get<0>(statement) == offs); - REQUIRE(get<1>(statement) == lim); - } - { - auto statement = storage.prepare(select(columns(&Tag::text, count(&Tag::text)), - group_by(&Tag::text), - order_by(count(&Tag::text)).desc(), - limit(lim, offset(offs)))); - REQUIRE(get<0>(statement) == lim); - REQUIRE(get<1>(statement) == offs); - } -} - TEST_CASE("Limits") { auto storage2 = make_storage("limits.sqlite"); auto storage = storage2; @@ -358,6 +322,32 @@ TEST_CASE("Custom collate") { REQUIRE(rows.size() == static_cast(storage.count())); } +TEST_CASE("collate") { + struct User { + int id = 0; + std::string firstName; + + bool operator==(const User &user) const { + return this->id == user.id && this->firstName == user.firstName; + } + }; + auto storage = make_storage( + {}, + make_table("users", make_column("id", &User::id, primary_key()), make_column("first_name", &User::firstName))); + storage.sync_schema(); + User user1{1, "HELLO"}; + User user2{2, "Hello"}; + User user3{3, "HEllo"}; + + storage.replace(user1); + storage.replace(user2); + storage.replace(user3); + + auto rows = storage.get_all(where(is_equal(&User::firstName, "hello").collate_nocase())); + std::vector expected = {user1, user2, user3}; + REQUIRE(rows == expected); +} + TEST_CASE("Vacuum") { struct Item { int id; diff --git a/tests/unique_cases/join_iterator_ctor_compilation_error.cpp b/tests/unique_cases/join_iterator_ctor_compilation_error.cpp new file mode 100644 index 000000000..cbbb947e0 --- /dev/null +++ b/tests/unique_cases/join_iterator_ctor_compilation_error.cpp @@ -0,0 +1,39 @@ +#include +#include + +using namespace sqlite_orm; + +TEST_CASE("Join iterator ctor compilation error") { + struct Tag { + int objectId; + std::string text; + }; + + auto storage = + make_storage("join_error.sqlite", + make_table("tags", make_column("object_id", &Tag::objectId), make_column("text", &Tag::text))); + storage.sync_schema(); + + auto offs = 0; + auto lim = 5; + storage.select(columns(&Tag::text, count(&Tag::text)), + group_by(&Tag::text), + order_by(count(&Tag::text)).desc(), + limit(offs, lim)); + { + auto statement = storage.prepare(select(columns(&Tag::text, count(&Tag::text)), + group_by(&Tag::text), + order_by(count(&Tag::text)).desc(), + limit(offs, lim))); + REQUIRE(get<0>(statement) == offs); + REQUIRE(get<1>(statement) == lim); + } + { + auto statement = storage.prepare(select(columns(&Tag::text, count(&Tag::text)), + group_by(&Tag::text), + order_by(count(&Tag::text)).desc(), + limit(lim, offset(offs)))); + REQUIRE(get<0>(statement) == lim); + REQUIRE(get<1>(statement) == offs); + } +} From 5e4fe2033549b89ef86834e2fcba350fa5099443 Mon Sep 17 00:00:00 2001 From: null Date: Sat, 12 Sep 2020 19:19:52 +0900 Subject: [PATCH 125/132] Fix GCC compile error regarding insufficient braces --- dev/journal_mode.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dev/journal_mode.h b/dev/journal_mode.h index 06811e8e2..6226a7d81 100644 --- a/dev/journal_mode.h +++ b/dev/journal_mode.h @@ -42,14 +42,14 @@ namespace sqlite_orm { std::transform(str.begin(), str.end(), std::back_inserter(upper_str), [](char c) { return static_cast(std::toupper(static_cast(c))); }); - static std::array all = { + static std::array all = {{ journal_mode::DELETE, journal_mode::TRUNCATE, journal_mode::PERSIST, journal_mode::MEMORY, journal_mode::WAL, journal_mode::OFF, - }; + }}; for(auto j: all) { if(to_string(j) == upper_str) { return std::make_unique(j); From 0fef00c89e8d60e41a452ffc31a8300b551116be Mon Sep 17 00:00:00 2001 From: Tan Li Boon Date: Mon, 14 Sep 2020 11:25:23 +0900 Subject: [PATCH 126/132] Silence shadowed variable warnings and re-run amalgamation scripts. --- dev/ast_iterator.h | 4 +- dev/column.h | 4 +- dev/conditions.h | 10 +- dev/constraints.h | 8 +- dev/get_prepared_statement.h | 8 +- dev/index.h | 4 +- dev/pragma.h | 6 +- dev/prepared_statement.h | 4 +- dev/select_constraints.h | 4 +- dev/statement_serializator.h | 28 +++--- dev/storage.h | 36 +++---- dev/storage_base.h | 16 +-- dev/storage_impl.h | 12 +-- dev/table.h | 12 +-- dev/tuple_helper.h | 8 +- include/sqlite_orm/sqlite_orm.h | 168 ++++++++++++++++---------------- 16 files changed, 166 insertions(+), 166 deletions(-) diff --git a/dev/ast_iterator.h b/dev/ast_iterator.h index e23329525..30c35020f 100644 --- a/dev/ast_iterator.h +++ b/dev/ast_iterator.h @@ -401,8 +401,8 @@ namespace sqlite_orm { template void operator()(const node_type &c, const L &l) const { - c.case_expression.apply([&l](auto &c) { - iterate_ast(c, l); + c.case_expression.apply([&l](auto &c_) { + iterate_ast(c_, l); }); iterate_tuple(c.args, [&l](auto &pair) { iterate_ast(pair.first, l); diff --git a/dev/column.h b/dev/column.h index 1b397fce0..2293ede03 100644 --- a/dev/column.h +++ b/dev/column.h @@ -59,12 +59,12 @@ namespace sqlite_orm { */ constraints_type constraints; - column_t(std::string name, + column_t(std::string name_, member_pointer_t member_pointer_, getter_type getter_, setter_type setter_, constraints_type constraints_) : - column_base{std::move(name)}, + column_base{std::move(name_)}, member_pointer(member_pointer_), getter(getter_), setter(setter_), constraints(move(constraints_)) {} /** diff --git a/dev/conditions.h b/dev/conditions.h index 386bb2f15..cf09c3e08 100644 --- a/dev/conditions.h +++ b/dev/conditions.h @@ -355,7 +355,7 @@ namespace sqlite_orm { L l; // left expression A arg; // in arg - in_t(L l_, A arg_, bool negative) : in_base{negative}, l(l_), arg(std::move(arg_)) {} + in_t(L l_, A arg_, bool negative_) : in_base{negative_}, l(l_), arg(std::move(arg_)) {} }; struct is_null_string { @@ -494,8 +494,8 @@ namespace sqlite_orm { struct dynamic_order_by_entry_t : order_by_base { std::string name; - dynamic_order_by_entry_t(decltype(name) name_, int asc_desc, std::string collate_argument) : - order_by_base{asc_desc, move(collate_argument)}, name(move(name_)) {} + dynamic_order_by_entry_t(decltype(name) name_, int asc_desc_, std::string collate_argument_) : + order_by_base{asc_desc_, move(collate_argument_)}, name(move(name_)) {} }; /** @@ -613,8 +613,8 @@ namespace sqlite_orm { sqlite_orm::internal::optional_container arg3; // not escape cause escape exists as a function here - like_t(arg_t arg_, pattern_t pattern_, sqlite_orm::internal::optional_container escape) : - arg(std::move(arg_)), pattern(std::move(pattern_)), arg3(std::move(escape)) {} + like_t(arg_t arg_, pattern_t pattern_, sqlite_orm::internal::optional_container escape_) : + arg(std::move(arg_)), pattern(std::move(pattern_)), arg3(std::move(escape_)) {} template like_t escape(C c) const { diff --git a/dev/constraints.h b/dev/constraints.h index 932d7a492..1b21964a1 100644 --- a/dev/constraints.h +++ b/dev/constraints.h @@ -170,8 +170,8 @@ namespace sqlite_orm { const foreign_key_type &fk; - on_update_delete_t(decltype(fk) fk_, decltype(update) update, foreign_key_action action_) : - on_update_delete_base{update}, fk(fk_), _action(action_) {} + on_update_delete_t(decltype(fk) fk_, decltype(update) update_, foreign_key_action action_) : + on_update_delete_base{update_}, fk(fk_), _action(action_) {} foreign_key_action _action = foreign_key_action::none; @@ -284,8 +284,8 @@ namespace sqlite_orm { foreign_key_intermediate_t(tuple_type columns_) : columns(std::move(columns_)) {} template - foreign_key_t, std::tuple> references(Rs... references) { - return {std::move(this->columns), std::make_tuple(std::forward(references)...)}; + foreign_key_t, std::tuple> references(Rs... refs) { + return {std::move(this->columns), std::make_tuple(std::forward(refs)...)}; } }; #endif diff --git a/dev/get_prepared_statement.h b/dev/get_prepared_statement.h index d4c9dc442..1b2ee1e08 100644 --- a/dev/get_prepared_statement.h +++ b/dev/get_prepared_statement.h @@ -134,8 +134,8 @@ namespace sqlite_orm { ++index; } if(index == N) { - internal::static_if{}>([](auto &result, auto &node) { - result = const_cast::type>(&node); + internal::static_if{}>([](auto &r, auto &n) { + r = const_cast::type>(&n); })(result, node); } }); @@ -157,8 +157,8 @@ namespace sqlite_orm { ++index; } if(index == N) { - internal::static_if{}>([](auto &result, auto &node) { - result = const_cast::type>(&node); + internal::static_if{}>([](auto &r, auto &n) { + r = const_cast::type>(&n); })(result, node); } }); diff --git a/dev/index.h b/dev/index.h index 35de1669e..b509ede47 100644 --- a/dev/index.h +++ b/dev/index.h @@ -20,8 +20,8 @@ namespace sqlite_orm { using columns_type = std::tuple; using object_type = void; - index_t(std::string name, bool unique, columns_type columns_) : - index_base{move(name), unique}, columns(move(columns_)) {} + index_t(std::string name_, bool unique_, columns_type columns_) : + index_base{move(name_), unique_}, columns(move(columns_)) {} columns_type columns; }; diff --git a/dev/pragma.h b/dev/pragma.h index 059fbe45e..9c51dff35 100644 --- a/dev/pragma.h +++ b/dev/pragma.h @@ -69,7 +69,7 @@ namespace sqlite_orm { T get_pragma(const std::string &name) { auto connection = this->get_connection(); auto query = "PRAGMA " + name; - T res; + T result; auto db = connection.get(); auto rc = sqlite3_exec( db, @@ -81,10 +81,10 @@ namespace sqlite_orm { } return 0; }, - &res, + &result, nullptr); if(rc == SQLITE_OK) { - return res; + return result; } else { throw std::system_error(std::error_code(sqlite3_errcode(db), get_sqlite_error_category()), sqlite3_errmsg(db)); diff --git a/dev/prepared_statement.h b/dev/prepared_statement.h index 308c5599a..630a1d27b 100644 --- a/dev/prepared_statement.h +++ b/dev/prepared_statement.h @@ -72,8 +72,8 @@ namespace sqlite_orm { expression_type t; - prepared_statement_t(T t_, sqlite3_stmt *stmt, connection_ref con_) : - prepared_statement_base{stmt, std::move(con_)}, t(std::move(t_)) {} + prepared_statement_t(T t_, sqlite3_stmt *stmt_, connection_ref con_) : + prepared_statement_base{stmt_, std::move(con_)}, t(std::move(t_)) {} }; template diff --git a/dev/select_constraints.h b/dev/select_constraints.h index 12c18792c..406ded4b1 100644 --- a/dev/select_constraints.h +++ b/dev/select_constraints.h @@ -123,8 +123,8 @@ namespace sqlite_orm { using left_type = typename compound_operator::left_type; using right_type = typename compound_operator::right_type; - union_t(left_type l, right_type r, decltype(all) all) : - compound_operator(std::move(l), std::move(r)), union_base{all} {} + union_t(left_type l, right_type r, decltype(all) all_) : + compound_operator(std::move(l), std::move(r)), union_base{all_} {} union_t(left_type l, right_type r) : union_t(std::move(l), std::move(r), false) {} }; diff --git a/dev/statement_serializator.h b/dev/statement_serializator.h index f91933c35..e43801bac 100644 --- a/dev/statement_serializator.h +++ b/dev/statement_serializator.h @@ -360,8 +360,8 @@ namespace sqlite_orm { std::string operator()(const statement_type &c, const C &context) const { std::stringstream ss; ss << "CASE "; - c.case_expression.apply([&ss, context](auto &c) { - ss << serialize(c, context) << " "; + c.case_expression.apply([&ss, context](auto &c_) { + ss << serialize(c_, context) << " "; }); iterate_tuple(c.args, [&ss, context](auto &pair) { ss << "WHEN " << serialize(pair.first, context) << " "; @@ -1046,17 +1046,17 @@ namespace sqlite_orm { } ss << "VALUES "; auto valuesString = [columnNamesCount] { - std::stringstream ss; - ss << "("; + std::stringstream ss_; + ss_ << "("; for(size_t i = 0; i < columnNamesCount; ++i) { - ss << "?"; + ss_ << "?"; if(i < columnNamesCount - 1) { - ss << ", "; + ss_ << ", "; } else { - ss << ")"; + ss_ << ")"; } } - return ss.str(); + return ss_.str(); }(); auto valuesCount = static_cast(std::distance(rep.range.first, rep.range.second)); for(auto i = 0; i < valuesCount; ++i) { @@ -1101,17 +1101,17 @@ namespace sqlite_orm { } ss << "VALUES "; auto valuesString = [columnNamesCount] { - std::stringstream ss; - ss << "("; + std::stringstream ss_; + ss_ << "("; for(size_t i = 0; i < columnNamesCount; ++i) { - ss << "?"; + ss_ << "?"; if(i < columnNamesCount - 1) { - ss << ", "; + ss_ << ", "; } else { - ss << ")"; + ss_ << ")"; } } - return ss.str(); + return ss_.str(); }(); auto valuesCount = static_cast(std::distance(statement.range.first, statement.range.second)); for(auto i = 0; i < valuesCount; ++i) { diff --git a/dev/storage.h b/dev/storage.h index 73f8f5ef2..e85255df1 100644 --- a/dev/storage.h +++ b/dev/storage.h @@ -808,7 +808,7 @@ namespace sqlite_orm { } template - prepared_statement_t> prepare(get_all_t get) { + prepared_statement_t> prepare(get_all_t get_) { auto con = this->get_connection(); sqlite3_stmt *stmt; auto db = con.get(); @@ -816,9 +816,9 @@ namespace sqlite_orm { context_t context{this->impl}; context.skip_table_name = false; context.replace_bindable_with_question = true; - auto query = serialize(get, context); + auto query = serialize(get_, context); if(sqlite3_prepare_v2(db, query.c_str(), -1, &stmt, nullptr) == SQLITE_OK) { - return {std::move(get), stmt, con}; + return {std::move(get_), stmt, con}; } else { throw std::system_error(std::error_code(sqlite3_errcode(db), get_sqlite_error_category()), sqlite3_errmsg(db)); @@ -826,7 +826,7 @@ namespace sqlite_orm { } template - prepared_statement_t> prepare(get_all_pointer_t get) { + prepared_statement_t> prepare(get_all_pointer_t get_) { auto con = this->get_connection(); sqlite3_stmt *stmt; auto db = con.get(); @@ -834,9 +834,9 @@ namespace sqlite_orm { context_t context{this->impl}; context.skip_table_name = false; context.replace_bindable_with_question = true; - auto query = serialize(get, context); + auto query = serialize(get_, context); if(sqlite3_prepare_v2(db, query.c_str(), -1, &stmt, nullptr) == SQLITE_OK) { - return {std::move(get), stmt, con}; + return {std::move(get_), stmt, con}; } else { throw std::system_error(std::error_code(sqlite3_errcode(db), get_sqlite_error_category()), sqlite3_errmsg(db)); @@ -845,7 +845,7 @@ namespace sqlite_orm { #ifdef SQLITE_ORM_OPTIONAL_SUPPORTED template - prepared_statement_t> prepare(get_all_optional_t get) { + prepared_statement_t> prepare(get_all_optional_t get_) { auto con = this->get_connection(); sqlite3_stmt *stmt; auto db = con.get(); @@ -853,9 +853,9 @@ namespace sqlite_orm { context_t context{this->impl}; context.skip_table_name = false; context.replace_bindable_with_question = true; - auto query = serialize(get, context); + auto query = serialize(get_, context); if(sqlite3_prepare_v2(db, query.c_str(), -1, &stmt, nullptr) == SQLITE_OK) { - return {std::move(get), stmt, con}; + return {std::move(get_), stmt, con}; } else { throw std::system_error(std::error_code(sqlite3_errcode(db), get_sqlite_error_category()), sqlite3_errmsg(db)); @@ -901,7 +901,7 @@ namespace sqlite_orm { } template - prepared_statement_t> prepare(get_t get) { + prepared_statement_t> prepare(get_t get_) { auto con = this->get_connection(); sqlite3_stmt *stmt; auto db = con.get(); @@ -909,9 +909,9 @@ namespace sqlite_orm { context_t context{this->impl}; context.skip_table_name = false; context.replace_bindable_with_question = true; - auto query = serialize(get, context); + auto query = serialize(get_, context); if(sqlite3_prepare_v2(db, query.c_str(), -1, &stmt, nullptr) == SQLITE_OK) { - return {std::move(get), stmt, con}; + return {std::move(get_), stmt, con}; } else { throw std::system_error(std::error_code(sqlite3_errcode(db), get_sqlite_error_category()), sqlite3_errmsg(db)); @@ -919,7 +919,7 @@ namespace sqlite_orm { } template - prepared_statement_t> prepare(get_pointer_t get) { + prepared_statement_t> prepare(get_pointer_t get_) { auto con = this->get_connection(); sqlite3_stmt *stmt; auto db = con.get(); @@ -927,9 +927,9 @@ namespace sqlite_orm { context_t context{this->impl}; context.skip_table_name = false; context.replace_bindable_with_question = true; - auto query = serialize(get, context); + auto query = serialize(get_, context); if(sqlite3_prepare_v2(db, query.c_str(), -1, &stmt, nullptr) == SQLITE_OK) { - return {std::move(get), stmt, con}; + return {std::move(get_), stmt, con}; } else { throw std::system_error(std::error_code(sqlite3_errcode(db), get_sqlite_error_category()), sqlite3_errmsg(db)); @@ -938,7 +938,7 @@ namespace sqlite_orm { #ifdef SQLITE_ORM_OPTIONAL_SUPPORTED template - prepared_statement_t> prepare(get_optional_t get) { + prepared_statement_t> prepare(get_optional_t get_) { auto con = this->get_connection(); sqlite3_stmt *stmt; auto db = con.get(); @@ -946,9 +946,9 @@ namespace sqlite_orm { context_t context{this->impl}; context.skip_table_name = false; context.replace_bindable_with_question = true; - auto query = serialize(get, context); + auto query = serialize(get_, context); if(sqlite3_prepare_v2(db, query.c_str(), -1, &stmt, nullptr) == SQLITE_OK) { - return {std::move(get), stmt, con}; + return {std::move(get_), stmt, con}; } else { throw std::system_error(std::error_code(sqlite3_errcode(db), get_sqlite_error_category()), sqlite3_errmsg(db)); diff --git a/dev/storage_base.h b/dev/storage_base.h index 20f535064..77767956e 100644 --- a/dev/storage_base.h +++ b/dev/storage_base.h @@ -177,10 +177,10 @@ namespace sqlite_orm { db, sql.c_str(), [](void *data, int argc, char **argv, char * * /*columnName*/) -> int { - auto &tableNames = *(data_t *)data; + auto &tableNames_ = *(data_t *)data; for(int i = 0; i < argc; i++) { if(argv[i]) { - tableNames.push_back(argv[i]); + tableNames_.push_back(argv[i]); } } return 0; @@ -357,7 +357,7 @@ namespace sqlite_orm { bool foreign_keys(sqlite3 *db) { std::string query = "PRAGMA foreign_keys"; - auto res = false; + auto result = false; auto rc = sqlite3_exec( db, query.c_str(), @@ -368,13 +368,13 @@ namespace sqlite_orm { } return 0; }, - &res, + &result, nullptr); if(rc != SQLITE_OK) { throw std::system_error(std::error_code(sqlite3_errcode(db), get_sqlite_error_category()), sqlite3_errmsg(db)); } - return res; + return result; } #endif @@ -468,7 +468,7 @@ namespace sqlite_orm { } std::string current_timestamp(sqlite3 *db) { - std::string res; + std::string result; std::stringstream ss; ss << "SELECT CURRENT_TIMESTAMP"; auto query = ss.str(); @@ -484,13 +484,13 @@ namespace sqlite_orm { } return 0; }, - &res, + &result, nullptr); if(rc != SQLITE_OK) { throw std::system_error(std::error_code(sqlite3_errcode(db), get_sqlite_error_category()), sqlite3_errmsg(db)); } - return res; + return result; } void drop_table_internal(const std::string &tableName, sqlite3 *db) { diff --git a/dev/storage_impl.h b/dev/storage_impl.h index 617f55ef0..37aca6e25 100644 --- a/dev/storage_impl.h +++ b/dev/storage_impl.h @@ -29,7 +29,7 @@ namespace sqlite_orm { struct storage_impl_base { bool table_exists(const std::string &tableName, sqlite3 *db) const { - auto res = false; + auto result = false; std::stringstream ss; ss << "SELECT COUNT(*) FROM sqlite_master WHERE type = '" << "table" @@ -45,13 +45,13 @@ namespace sqlite_orm { } return 0; }, - &res, + &result, nullptr); if(rc != SQLITE_OK) { throw std::system_error(std::error_code(sqlite3_errcode(db), get_sqlite_error_category()), sqlite3_errmsg(db)); } - return res; + return result; } void rename_table(sqlite3 *db, const std::string &oldName, const std::string &newName) const { @@ -113,7 +113,7 @@ namespace sqlite_orm { } std::vector get_table_info(const std::string &tableName, sqlite3 *db) const { - std::vector res; + std::vector result; auto query = "PRAGMA table_info('" + tableName + "')"; auto rc = sqlite3_exec( db, @@ -133,13 +133,13 @@ namespace sqlite_orm { } return 0; }, - &res, + &result, nullptr); if(rc != SQLITE_OK) { throw std::system_error(std::error_code(sqlite3_errcode(db), get_sqlite_error_category()), sqlite3_errmsg(db)); } - return res; + return result; } }; diff --git a/dev/table.h b/dev/table.h index 7fc86810a..151238127 100644 --- a/dev/table.h +++ b/dev/table.h @@ -64,22 +64,22 @@ namespace sqlite_orm { // Make static_if have at least one input as a workaround for GCC bug: // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=64095 if(!res) { - static_if{}>([&res, &obj, &col](const C &c) { - if(compare_any(col.member_pointer, c)) { + static_if{}>([&res, &obj, &col](const C &c_) { + if(compare_any(col.member_pointer, c_)) { res = &(obj.*col.member_pointer); } })(c); } if(!res) { - static_if{}>([&res, &obj, &col](const C &c) { - if(compare_any(col.getter, c)) { + static_if{}>([&res, &obj, &col](const C &c_) { + if(compare_any(col.getter, c_)) { res = &((obj).*(col.getter))(); } })(c); } if(!res) { - static_if{}>([&res, &obj, &col](const C &c) { - if(compare_any(col.setter, c)) { + static_if{}>([&res, &obj, &col](const C &c_) { + if(compare_any(col.setter, c_)) { res = &((obj).*(col.getter))(); } })(c); diff --git a/dev/tuple_helper.h b/dev/tuple_helper.h index eb67655cf..b1535521d 100644 --- a/dev/tuple_helper.h +++ b/dev/tuple_helper.h @@ -61,8 +61,8 @@ namespace sqlite_orm { template void move_tuple_impl(L &lhs, R &rhs) { std::get(lhs) = std::move(std::get(rhs)); - internal::static_if{}>([](auto &lhs, auto &rhs) { - move_tuple_impl(lhs, rhs); + internal::static_if{}>([](auto &l, auto &r) { + move_tuple_impl(l, r); })(lhs, rhs); } } @@ -72,8 +72,8 @@ namespace sqlite_orm { template void move_tuple(L &lhs, R &rhs) { using bool_type = std::integral_constant; - static_if([](auto &lhs, auto &rhs) { - tuple_helper::move_tuple_impl(lhs, rhs); + static_if([](auto &l, auto &r) { + tuple_helper::move_tuple_impl(l, r); })(lhs, rhs); } diff --git a/include/sqlite_orm/sqlite_orm.h b/include/sqlite_orm/sqlite_orm.h index 429094d67..5836add2b 100644 --- a/include/sqlite_orm/sqlite_orm.h +++ b/include/sqlite_orm/sqlite_orm.h @@ -236,8 +236,8 @@ namespace sqlite_orm { template void move_tuple_impl(L &lhs, R &rhs) { std::get(lhs) = std::move(std::get(rhs)); - internal::static_if{}>([](auto &lhs, auto &rhs) { - move_tuple_impl(lhs, rhs); + internal::static_if{}>([](auto &l, auto &r) { + move_tuple_impl(l, r); })(lhs, rhs); } } @@ -247,8 +247,8 @@ namespace sqlite_orm { template void move_tuple(L &lhs, R &rhs) { using bool_type = std::integral_constant; - static_if([](auto &lhs, auto &rhs) { - tuple_helper::move_tuple_impl(lhs, rhs); + static_if([](auto &l, auto &r) { + tuple_helper::move_tuple_impl(l, r); })(lhs, rhs); } @@ -577,8 +577,8 @@ namespace sqlite_orm { const foreign_key_type &fk; - on_update_delete_t(decltype(fk) fk_, decltype(update) update, foreign_key_action action_) : - on_update_delete_base{update}, fk(fk_), _action(action_) {} + on_update_delete_t(decltype(fk) fk_, decltype(update) update_, foreign_key_action action_) : + on_update_delete_base{update_}, fk(fk_), _action(action_) {} foreign_key_action _action = foreign_key_action::none; @@ -691,8 +691,8 @@ namespace sqlite_orm { foreign_key_intermediate_t(tuple_type columns_) : columns(std::move(columns_)) {} template - foreign_key_t, std::tuple> references(Rs... references) { - return {std::move(this->columns), std::make_tuple(std::forward(references)...)}; + foreign_key_t, std::tuple> references(Rs... refs) { + return {std::move(this->columns), std::make_tuple(std::forward(refs)...)}; } }; #endif @@ -1544,12 +1544,12 @@ namespace sqlite_orm { */ constraints_type constraints; - column_t(std::string name, + column_t(std::string name_, member_pointer_t member_pointer_, getter_type getter_, setter_type setter_, constraints_type constraints_) : - column_base{std::move(name)}, + column_base{std::move(name_)}, member_pointer(member_pointer_), getter(getter_), setter(setter_), constraints(move(constraints_)) {} /** @@ -2205,7 +2205,7 @@ namespace sqlite_orm { L l; // left expression A arg; // in arg - in_t(L l_, A arg_, bool negative) : in_base{negative}, l(l_), arg(std::move(arg_)) {} + in_t(L l_, A arg_, bool negative_) : in_base{negative_}, l(l_), arg(std::move(arg_)) {} }; struct is_null_string { @@ -2344,8 +2344,8 @@ namespace sqlite_orm { struct dynamic_order_by_entry_t : order_by_base { std::string name; - dynamic_order_by_entry_t(decltype(name) name_, int asc_desc, std::string collate_argument) : - order_by_base{asc_desc, move(collate_argument)}, name(move(name_)) {} + dynamic_order_by_entry_t(decltype(name) name_, int asc_desc_, std::string collate_argument_) : + order_by_base{asc_desc_, move(collate_argument_)}, name(move(name_)) {} }; /** @@ -2463,8 +2463,8 @@ namespace sqlite_orm { sqlite_orm::internal::optional_container arg3; // not escape cause escape exists as a function here - like_t(arg_t arg_, pattern_t pattern_, sqlite_orm::internal::optional_container escape) : - arg(std::move(arg_)), pattern(std::move(pattern_)), arg3(std::move(escape)) {} + like_t(arg_t arg_, pattern_t pattern_, sqlite_orm::internal::optional_container escape_) : + arg(std::move(arg_)), pattern(std::move(pattern_)), arg3(std::move(escape_)) {} template like_t escape(C c) const { @@ -4332,8 +4332,8 @@ namespace sqlite_orm { using left_type = typename compound_operator::left_type; using right_type = typename compound_operator::right_type; - union_t(left_type l, right_type r, decltype(all) all) : - compound_operator(std::move(l), std::move(r)), union_base{all} {} + union_t(left_type l, right_type r, decltype(all) all_) : + compound_operator(std::move(l), std::move(r)), union_base{all_} {} union_t(left_type l, right_type r) : union_t(std::move(l), std::move(r), false) {} }; @@ -4979,14 +4979,14 @@ namespace sqlite_orm { std::transform(str.begin(), str.end(), std::back_inserter(upper_str), [](char c) { return static_cast(std::toupper(static_cast(c))); }); - static std::array all = { + static std::array all = {{ journal_mode::DELETE, journal_mode::TRUNCATE, journal_mode::PERSIST, journal_mode::MEMORY, journal_mode::WAL, journal_mode::OFF, - }; + }}; for(auto j: all) { if(to_string(j) == upper_str) { return std::make_unique(j); @@ -5400,8 +5400,8 @@ namespace sqlite_orm { using columns_type = std::tuple; using object_type = void; - index_t(std::string name, bool unique, columns_type columns_) : - index_base{move(name), unique}, columns(move(columns_)) {} + index_t(std::string name_, bool unique_, columns_type columns_) : + index_base{move(name_), unique_}, columns(move(columns_)) {} columns_type columns; }; @@ -5990,22 +5990,22 @@ namespace sqlite_orm { // Make static_if have at least one input as a workaround for GCC bug: // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=64095 if(!res) { - static_if{}>([&res, &obj, &col](const C &c) { - if(compare_any(col.member_pointer, c)) { + static_if{}>([&res, &obj, &col](const C &c_) { + if(compare_any(col.member_pointer, c_)) { res = &(obj.*col.member_pointer); } })(c); } if(!res) { - static_if{}>([&res, &obj, &col](const C &c) { - if(compare_any(col.getter, c)) { + static_if{}>([&res, &obj, &col](const C &c_) { + if(compare_any(col.getter, c_)) { res = &((obj).*(col.getter))(); } })(c); } if(!res) { - static_if{}>([&res, &obj, &col](const C &c) { - if(compare_any(col.setter, c)) { + static_if{}>([&res, &obj, &col](const C &c_) { + if(compare_any(col.setter, c_)) { res = &((obj).*(col.getter))(); } })(c); @@ -6271,7 +6271,7 @@ namespace sqlite_orm { struct storage_impl_base { bool table_exists(const std::string &tableName, sqlite3 *db) const { - auto res = false; + auto result = false; std::stringstream ss; ss << "SELECT COUNT(*) FROM sqlite_master WHERE type = '" << "table" @@ -6287,13 +6287,13 @@ namespace sqlite_orm { } return 0; }, - &res, + &result, nullptr); if(rc != SQLITE_OK) { throw std::system_error(std::error_code(sqlite3_errcode(db), get_sqlite_error_category()), sqlite3_errmsg(db)); } - return res; + return result; } void rename_table(sqlite3 *db, const std::string &oldName, const std::string &newName) const { @@ -6355,7 +6355,7 @@ namespace sqlite_orm { } std::vector get_table_info(const std::string &tableName, sqlite3 *db) const { - std::vector res; + std::vector result; auto query = "PRAGMA table_info('" + tableName + "')"; auto rc = sqlite3_exec( db, @@ -6375,13 +6375,13 @@ namespace sqlite_orm { } return 0; }, - &res, + &result, nullptr); if(rc != SQLITE_OK) { throw std::system_error(std::error_code(sqlite3_errcode(db), get_sqlite_error_category()), sqlite3_errmsg(db)); } - return res; + return result; } }; @@ -7184,8 +7184,8 @@ namespace sqlite_orm { expression_type t; - prepared_statement_t(T t_, sqlite3_stmt *stmt, connection_ref con_) : - prepared_statement_base{stmt, std::move(con_)}, t(std::move(t_)) {} + prepared_statement_t(T t_, sqlite3_stmt *stmt_, connection_ref con_) : + prepared_statement_base{stmt_, std::move(con_)}, t(std::move(t_)) {} }; template @@ -7973,8 +7973,8 @@ namespace sqlite_orm { template void operator()(const node_type &c, const L &l) const { - c.case_expression.apply([&l](auto &c) { - iterate_ast(c, l); + c.case_expression.apply([&l](auto &c_) { + iterate_ast(c_, l); }); iterate_tuple(c.args, [&l](auto &pair) { iterate_ast(pair.first, l); @@ -8247,7 +8247,7 @@ namespace sqlite_orm { T get_pragma(const std::string &name) { auto connection = this->get_connection(); auto query = "PRAGMA " + name; - T res; + T result; auto db = connection.get(); auto rc = sqlite3_exec( db, @@ -8259,10 +8259,10 @@ namespace sqlite_orm { } return 0; }, - &res, + &result, nullptr); if(rc == SQLITE_OK) { - return res; + return result; } else { throw std::system_error(std::error_code(sqlite3_errcode(db), get_sqlite_error_category()), sqlite3_errmsg(db)); @@ -8754,10 +8754,10 @@ namespace sqlite_orm { db, sql.c_str(), [](void *data, int argc, char **argv, char * * /*columnName*/) -> int { - auto &tableNames = *(data_t *)data; + auto &tableNames_ = *(data_t *)data; for(int i = 0; i < argc; i++) { if(argv[i]) { - tableNames.push_back(argv[i]); + tableNames_.push_back(argv[i]); } } return 0; @@ -8934,7 +8934,7 @@ namespace sqlite_orm { bool foreign_keys(sqlite3 *db) { std::string query = "PRAGMA foreign_keys"; - auto res = false; + auto result = false; auto rc = sqlite3_exec( db, query.c_str(), @@ -8945,13 +8945,13 @@ namespace sqlite_orm { } return 0; }, - &res, + &result, nullptr); if(rc != SQLITE_OK) { throw std::system_error(std::error_code(sqlite3_errcode(db), get_sqlite_error_category()), sqlite3_errmsg(db)); } - return res; + return result; } #endif @@ -9045,7 +9045,7 @@ namespace sqlite_orm { } std::string current_timestamp(sqlite3 *db) { - std::string res; + std::string result; std::stringstream ss; ss << "SELECT CURRENT_TIMESTAMP"; auto query = ss.str(); @@ -9061,13 +9061,13 @@ namespace sqlite_orm { } return 0; }, - &res, + &result, nullptr); if(rc != SQLITE_OK) { throw std::system_error(std::error_code(sqlite3_errcode(db), get_sqlite_error_category()), sqlite3_errmsg(db)); } - return res; + return result; } void drop_table_internal(const std::string &tableName, sqlite3 *db) { @@ -9869,8 +9869,8 @@ namespace sqlite_orm { std::string operator()(const statement_type &c, const C &context) const { std::stringstream ss; ss << "CASE "; - c.case_expression.apply([&ss, context](auto &c) { - ss << serialize(c, context) << " "; + c.case_expression.apply([&ss, context](auto &c_) { + ss << serialize(c_, context) << " "; }); iterate_tuple(c.args, [&ss, context](auto &pair) { ss << "WHEN " << serialize(pair.first, context) << " "; @@ -10555,17 +10555,17 @@ namespace sqlite_orm { } ss << "VALUES "; auto valuesString = [columnNamesCount] { - std::stringstream ss; - ss << "("; + std::stringstream ss_; + ss_ << "("; for(size_t i = 0; i < columnNamesCount; ++i) { - ss << "?"; + ss_ << "?"; if(i < columnNamesCount - 1) { - ss << ", "; + ss_ << ", "; } else { - ss << ")"; + ss_ << ")"; } } - return ss.str(); + return ss_.str(); }(); auto valuesCount = static_cast(std::distance(rep.range.first, rep.range.second)); for(auto i = 0; i < valuesCount; ++i) { @@ -10610,17 +10610,17 @@ namespace sqlite_orm { } ss << "VALUES "; auto valuesString = [columnNamesCount] { - std::stringstream ss; - ss << "("; + std::stringstream ss_; + ss_ << "("; for(size_t i = 0; i < columnNamesCount; ++i) { - ss << "?"; + ss_ << "?"; if(i < columnNamesCount - 1) { - ss << ", "; + ss_ << ", "; } else { - ss << ")"; + ss_ << ")"; } } - return ss.str(); + return ss_.str(); }(); auto valuesCount = static_cast(std::distance(statement.range.first, statement.range.second)); for(auto i = 0; i < valuesCount; ++i) { @@ -11990,7 +11990,7 @@ namespace sqlite_orm { } template - prepared_statement_t> prepare(get_all_t get) { + prepared_statement_t> prepare(get_all_t get_) { auto con = this->get_connection(); sqlite3_stmt *stmt; auto db = con.get(); @@ -11998,9 +11998,9 @@ namespace sqlite_orm { context_t context{this->impl}; context.skip_table_name = false; context.replace_bindable_with_question = true; - auto query = serialize(get, context); + auto query = serialize(get_, context); if(sqlite3_prepare_v2(db, query.c_str(), -1, &stmt, nullptr) == SQLITE_OK) { - return {std::move(get), stmt, con}; + return {std::move(get_), stmt, con}; } else { throw std::system_error(std::error_code(sqlite3_errcode(db), get_sqlite_error_category()), sqlite3_errmsg(db)); @@ -12008,7 +12008,7 @@ namespace sqlite_orm { } template - prepared_statement_t> prepare(get_all_pointer_t get) { + prepared_statement_t> prepare(get_all_pointer_t get_) { auto con = this->get_connection(); sqlite3_stmt *stmt; auto db = con.get(); @@ -12016,9 +12016,9 @@ namespace sqlite_orm { context_t context{this->impl}; context.skip_table_name = false; context.replace_bindable_with_question = true; - auto query = serialize(get, context); + auto query = serialize(get_, context); if(sqlite3_prepare_v2(db, query.c_str(), -1, &stmt, nullptr) == SQLITE_OK) { - return {std::move(get), stmt, con}; + return {std::move(get_), stmt, con}; } else { throw std::system_error(std::error_code(sqlite3_errcode(db), get_sqlite_error_category()), sqlite3_errmsg(db)); @@ -12027,7 +12027,7 @@ namespace sqlite_orm { #ifdef SQLITE_ORM_OPTIONAL_SUPPORTED template - prepared_statement_t> prepare(get_all_optional_t get) { + prepared_statement_t> prepare(get_all_optional_t get_) { auto con = this->get_connection(); sqlite3_stmt *stmt; auto db = con.get(); @@ -12035,9 +12035,9 @@ namespace sqlite_orm { context_t context{this->impl}; context.skip_table_name = false; context.replace_bindable_with_question = true; - auto query = serialize(get, context); + auto query = serialize(get_, context); if(sqlite3_prepare_v2(db, query.c_str(), -1, &stmt, nullptr) == SQLITE_OK) { - return {std::move(get), stmt, con}; + return {std::move(get_), stmt, con}; } else { throw std::system_error(std::error_code(sqlite3_errcode(db), get_sqlite_error_category()), sqlite3_errmsg(db)); @@ -12083,7 +12083,7 @@ namespace sqlite_orm { } template - prepared_statement_t> prepare(get_t get) { + prepared_statement_t> prepare(get_t get_) { auto con = this->get_connection(); sqlite3_stmt *stmt; auto db = con.get(); @@ -12091,9 +12091,9 @@ namespace sqlite_orm { context_t context{this->impl}; context.skip_table_name = false; context.replace_bindable_with_question = true; - auto query = serialize(get, context); + auto query = serialize(get_, context); if(sqlite3_prepare_v2(db, query.c_str(), -1, &stmt, nullptr) == SQLITE_OK) { - return {std::move(get), stmt, con}; + return {std::move(get_), stmt, con}; } else { throw std::system_error(std::error_code(sqlite3_errcode(db), get_sqlite_error_category()), sqlite3_errmsg(db)); @@ -12101,7 +12101,7 @@ namespace sqlite_orm { } template - prepared_statement_t> prepare(get_pointer_t get) { + prepared_statement_t> prepare(get_pointer_t get_) { auto con = this->get_connection(); sqlite3_stmt *stmt; auto db = con.get(); @@ -12109,9 +12109,9 @@ namespace sqlite_orm { context_t context{this->impl}; context.skip_table_name = false; context.replace_bindable_with_question = true; - auto query = serialize(get, context); + auto query = serialize(get_, context); if(sqlite3_prepare_v2(db, query.c_str(), -1, &stmt, nullptr) == SQLITE_OK) { - return {std::move(get), stmt, con}; + return {std::move(get_), stmt, con}; } else { throw std::system_error(std::error_code(sqlite3_errcode(db), get_sqlite_error_category()), sqlite3_errmsg(db)); @@ -12120,7 +12120,7 @@ namespace sqlite_orm { #ifdef SQLITE_ORM_OPTIONAL_SUPPORTED template - prepared_statement_t> prepare(get_optional_t get) { + prepared_statement_t> prepare(get_optional_t get_) { auto con = this->get_connection(); sqlite3_stmt *stmt; auto db = con.get(); @@ -12128,9 +12128,9 @@ namespace sqlite_orm { context_t context{this->impl}; context.skip_table_name = false; context.replace_bindable_with_question = true; - auto query = serialize(get, context); + auto query = serialize(get_, context); if(sqlite3_prepare_v2(db, query.c_str(), -1, &stmt, nullptr) == SQLITE_OK) { - return {std::move(get), stmt, con}; + return {std::move(get_), stmt, con}; } else { throw std::system_error(std::error_code(sqlite3_errcode(db), get_sqlite_error_category()), sqlite3_errmsg(db)); @@ -13325,8 +13325,8 @@ namespace sqlite_orm { ++index; } if(index == N) { - internal::static_if{}>([](auto &result, auto &node) { - result = const_cast::type>(&node); + internal::static_if{}>([](auto &r, auto &n) { + r = const_cast::type>(&n); })(result, node); } }); @@ -13348,8 +13348,8 @@ namespace sqlite_orm { ++index; } if(index == N) { - internal::static_if{}>([](auto &result, auto &node) { - result = const_cast::type>(&node); + internal::static_if{}>([](auto &r, auto &n) { + r = const_cast::type>(&n); })(result, node); } }); From cffcf32979526f2e2d26c06fe0b73666a7ca0e87 Mon Sep 17 00:00:00 2001 From: fnc12 Date: Thu, 24 Sep 2020 12:34:17 +0300 Subject: [PATCH 127/132] added is_opened function and fixed transaction connection --- dev/storage_base.h | 16 +++-- include/sqlite_orm/sqlite_orm.h | 16 +++-- tests/CMakeLists.txt | 2 +- tests/tests3.cpp | 90 ------------------------- tests/transaction_tests.cpp | 114 ++++++++++++++++++++++++++++++++ 5 files changed, 139 insertions(+), 99 deletions(-) create mode 100644 tests/transaction_tests.cpp diff --git a/dev/storage_base.h b/dev/storage_base.h index 77767956e..9d5499670 100644 --- a/dev/storage_base.h +++ b/dev/storage_base.h @@ -133,13 +133,13 @@ namespace sqlite_orm { bool transaction(const std::function &f) { this->begin_transaction(); - auto con = this->get_connection(); - auto db = con.get(); + // auto con = this->get_connection(); + // auto db = con.get(); auto shouldCommit = f(); if(shouldCommit) { - this->commit(db); + this->commit(); } else { - this->rollback(db); + this->rollback(); } return shouldCommit; } @@ -296,6 +296,14 @@ namespace sqlite_orm { return this->connection->filename; } + /** + * Checks whether connection to database is opened right now. + * Returns always `true` for in memory databases. + */ + bool is_opened() const { + return this->connection->retain_count() > 0; + } + protected: storage_base(const std::string &filename_, int foreignKeysCount) : pragma(std::bind(&storage_base::get_connection, this)), diff --git a/include/sqlite_orm/sqlite_orm.h b/include/sqlite_orm/sqlite_orm.h index 5836add2b..b7c32cb47 100644 --- a/include/sqlite_orm/sqlite_orm.h +++ b/include/sqlite_orm/sqlite_orm.h @@ -8710,13 +8710,13 @@ namespace sqlite_orm { bool transaction(const std::function &f) { this->begin_transaction(); - auto con = this->get_connection(); - auto db = con.get(); + // auto con = this->get_connection(); + // auto db = con.get(); auto shouldCommit = f(); if(shouldCommit) { - this->commit(db); + this->commit(); } else { - this->rollback(db); + this->rollback(); } return shouldCommit; } @@ -8873,6 +8873,14 @@ namespace sqlite_orm { return this->connection->filename; } + /** + * Checks whether connection to database is opened right now. + * Returns always `true` for in memory databases. + */ + bool is_opened() const { + return this->connection->retain_count() > 0; + } + protected: storage_base(const std::string &filename_, int foreignKeysCount) : pragma(std::bind(&storage_base::get_connection, this)), diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 6abacb16a..fd41e703e 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -10,7 +10,7 @@ else() add_subdirectory(third_party/sqlite) endif() -add_executable(unit_tests tests.cpp tests2.cpp tests3.cpp tests4.cpp tests5.cpp private_getters_tests.cpp pragma_tests.cpp explicit_columns.cpp core_functions_tests.cpp index_tests.cpp constraints/composite_key.cpp static_tests.cpp operators/arithmetic_operators.cpp operators/like.cpp operators/glob.cpp operators/in.cpp operators/cast.cpp operators/is_null.cpp operators/not_operator.cpp operators/bitwise.cpp dynamic_order_by.cpp prepared_statement_tests/select.cpp prepared_statement_tests/get_all.cpp prepared_statement_tests/get_all_pointer.cpp prepared_statement_tests/get_all_optional.cpp prepared_statement_tests/update_all.cpp prepared_statement_tests/remove_all.cpp prepared_statement_tests/get.cpp prepared_statement_tests/get_pointer.cpp prepared_statement_tests/get_optional.cpp prepared_statement_tests/update.cpp prepared_statement_tests/remove.cpp prepared_statement_tests/insert.cpp prepared_statement_tests/replace.cpp prepared_statement_tests/insert_range.cpp prepared_statement_tests/replace_range.cpp prepared_statement_tests/insert_explicit.cpp pragma_tests.cpp simple_query.cpp static_tests/is_bindable.cpp static_tests/arithmetic_operators_result_type.cpp static_tests/tuple_conc.cpp static_tests/node_tuple.cpp static_tests/bindable_filter.cpp static_tests/count_tuple.cpp static_tests/member_traits_tests.cpp static_tests/select_return_type.cpp constraints/default.cpp constraints/unique.cpp constraints/foreign_key.cpp constraints/check.cpp table_tests.cpp statement_serializator_tests/primary_key.cpp statement_serializator_tests/column_names.cpp statement_serializator_tests/autoincrement.cpp statement_serializator_tests/arithmetic_operators.cpp statement_serializator_tests/core_functions.cpp statement_serializator_tests/comparison_operators.cpp statement_serializator_tests/unique.cpp statement_serializator_tests/foreign_key.cpp statement_serializator_tests/collate.cpp statement_serializator_tests/check.cpp statement_serializator_tests/index.cpp statement_serializator_tests/indexed_column.cpp unique_cases/get_all_with_two_tables.cpp unique_cases/prepare_get_all_with_case.cpp unique_cases/index_named_table_with_fk.cpp unique_cases/issue525.cpp unique_cases/delete_with_two_fields.cpp unique_cases/join_iterator_ctor_compilation_error.cpp get_all_custom_containers.cpp select_asterisk.cpp backup_tests.cpp) +add_executable(unit_tests tests.cpp tests2.cpp tests3.cpp tests4.cpp tests5.cpp private_getters_tests.cpp pragma_tests.cpp explicit_columns.cpp core_functions_tests.cpp index_tests.cpp constraints/composite_key.cpp static_tests.cpp operators/arithmetic_operators.cpp operators/like.cpp operators/glob.cpp operators/in.cpp operators/cast.cpp operators/is_null.cpp operators/not_operator.cpp operators/bitwise.cpp dynamic_order_by.cpp prepared_statement_tests/select.cpp prepared_statement_tests/get_all.cpp prepared_statement_tests/get_all_pointer.cpp prepared_statement_tests/get_all_optional.cpp prepared_statement_tests/update_all.cpp prepared_statement_tests/remove_all.cpp prepared_statement_tests/get.cpp prepared_statement_tests/get_pointer.cpp prepared_statement_tests/get_optional.cpp prepared_statement_tests/update.cpp prepared_statement_tests/remove.cpp prepared_statement_tests/insert.cpp prepared_statement_tests/replace.cpp prepared_statement_tests/insert_range.cpp prepared_statement_tests/replace_range.cpp prepared_statement_tests/insert_explicit.cpp pragma_tests.cpp simple_query.cpp static_tests/is_bindable.cpp static_tests/arithmetic_operators_result_type.cpp static_tests/tuple_conc.cpp static_tests/node_tuple.cpp static_tests/bindable_filter.cpp static_tests/count_tuple.cpp static_tests/member_traits_tests.cpp static_tests/select_return_type.cpp constraints/default.cpp constraints/unique.cpp constraints/foreign_key.cpp constraints/check.cpp table_tests.cpp statement_serializator_tests/primary_key.cpp statement_serializator_tests/column_names.cpp statement_serializator_tests/autoincrement.cpp statement_serializator_tests/arithmetic_operators.cpp statement_serializator_tests/core_functions.cpp statement_serializator_tests/comparison_operators.cpp statement_serializator_tests/unique.cpp statement_serializator_tests/foreign_key.cpp statement_serializator_tests/collate.cpp statement_serializator_tests/check.cpp statement_serializator_tests/index.cpp statement_serializator_tests/indexed_column.cpp unique_cases/get_all_with_two_tables.cpp unique_cases/prepare_get_all_with_case.cpp unique_cases/index_named_table_with_fk.cpp unique_cases/issue525.cpp unique_cases/delete_with_two_fields.cpp unique_cases/join_iterator_ctor_compilation_error.cpp get_all_custom_containers.cpp select_asterisk.cpp backup_tests.cpp transaction_tests.cpp) if(SQLITE_ORM_OMITS_CODECVT) diff --git a/tests/tests3.cpp b/tests/tests3.cpp index 1cd65daa7..2a2418aae 100644 --- a/tests/tests3.cpp +++ b/tests/tests3.cpp @@ -450,93 +450,3 @@ TEST_CASE("Escape chars") { storage.update(selena); storage.remove(10); } - -TEST_CASE("Transaction guard") { - struct Object { - int id; - std::string name; - }; - - auto storage = make_storage( - "test_transaction_guard.sqlite", - make_table("objects", make_column("id", &Object::id, primary_key()), make_column("name", &Object::name))); - - storage.sync_schema(); - storage.remove_all(); - - storage.insert(Object{0, "Jack"}); - - // insert, call make a storage to cakk an exception and check that rollback was fired - auto countBefore = storage.count(); - try { - auto guard = storage.transaction_guard(); - - storage.insert(Object{0, "John"}); - - storage.get(-1); - - REQUIRE(false); - } catch(...) { - auto countNow = storage.count(); - - REQUIRE(countBefore == countNow); - } - - // check that one can call other transaction functions without exceptions - storage.transaction([&] { - return false; - }); - - // commit explicitly and check that after exception data was saved - countBefore = storage.count(); - try { - auto guard = storage.transaction_guard(); - storage.insert(Object{0, "John"}); - guard.commit(); - storage.get(-1); - REQUIRE(false); - } catch(...) { - auto countNow = storage.count(); - - REQUIRE(countNow == countBefore + 1); - } - - // rollback explicitly - countBefore = storage.count(); - try { - auto guard = storage.transaction_guard(); - storage.insert(Object{0, "Michael"}); - guard.rollback(); - storage.get(-1); - REQUIRE(false); - } catch(...) { - auto countNow = storage.count(); - REQUIRE(countNow == countBefore); - } - - // commit on exception - countBefore = storage.count(); - try { - auto guard = storage.transaction_guard(); - guard.commit_on_destroy = true; - storage.insert(Object{0, "Michael"}); - storage.get(-1); - REQUIRE(false); - } catch(...) { - auto countNow = storage.count(); - REQUIRE(countNow == countBefore + 1); - } - - // work witout exception - countBefore = storage.count(); - try { - auto guard = storage.transaction_guard(); - guard.commit_on_destroy = true; - storage.insert(Object{0, "Lincoln"}); - - } catch(...) { - throw std::runtime_error("Must not fire"); - } - auto countNow = storage.count(); - REQUIRE(countNow == countBefore + 1); -} diff --git a/tests/transaction_tests.cpp b/tests/transaction_tests.cpp new file mode 100644 index 000000000..301fe1f0f --- /dev/null +++ b/tests/transaction_tests.cpp @@ -0,0 +1,114 @@ +#include +#include + +using namespace sqlite_orm; + +TEST_CASE("transaction") { + struct Object { + int id = 0; + std::string name; + }; + auto filename = "transaction_test.sqlite"; + ::remove(filename); + auto storage = make_storage( + "test_transaction_guard.sqlite", + make_table("objects", make_column("id", &Object::id, primary_key()), make_column("name", &Object::name))); + REQUIRE(!storage.is_opened()); + storage.sync_schema(); + REQUIRE(!storage.is_opened()); + storage.transaction([&] { + storage.insert(Object{0, "Jack"}); + return true; + }); + REQUIRE(!storage.is_opened()); +} + +TEST_CASE("Transaction guard") { + struct Object { + int id = 0; + std::string name; + }; + + auto storage = make_storage( + "test_transaction_guard.sqlite", + make_table("objects", make_column("id", &Object::id, primary_key()), make_column("name", &Object::name))); + + storage.sync_schema(); + storage.remove_all(); + + storage.insert(Object{0, "Jack"}); + + SECTION("insert, call make a storage to call an exception and check that rollback was fired") { + auto countBefore = storage.count(); + try { + auto guard = storage.transaction_guard(); + + storage.insert(Object{0, "John"}); + + storage.get(-1); + + REQUIRE(false); + } catch(...) { + auto countNow = storage.count(); + + REQUIRE(countBefore == countNow); + } + } + SECTION("check that one can call other transaction functions without exceptions") { + storage.transaction([&] { + return false; + }); + } + SECTION("commit explicitly and check that after exception data was saved") { + auto countBefore = storage.count(); + try { + auto guard = storage.transaction_guard(); + storage.insert(Object{0, "John"}); + guard.commit(); + storage.get(-1); + REQUIRE(false); + } catch(...) { + auto countNow = storage.count(); + + REQUIRE(countNow == countBefore + 1); + } + } + SECTION("rollback explicitly") { + auto countBefore = storage.count(); + try { + auto guard = storage.transaction_guard(); + storage.insert(Object{0, "Michael"}); + guard.rollback(); + storage.get(-1); + REQUIRE(false); + } catch(...) { + auto countNow = storage.count(); + REQUIRE(countNow == countBefore); + } + } + SECTION("commit on exception") { + auto countBefore = storage.count(); + try { + auto guard = storage.transaction_guard(); + guard.commit_on_destroy = true; + storage.insert(Object{0, "Michael"}); + storage.get(-1); + REQUIRE(false); + } catch(...) { + auto countNow = storage.count(); + REQUIRE(countNow == countBefore + 1); + } + } + SECTION("work witout exception") { + auto countBefore = storage.count(); + try { + auto guard = storage.transaction_guard(); + guard.commit_on_destroy = true; + storage.insert(Object{0, "Lincoln"}); + } catch(...) { + throw std::runtime_error("Must not fire"); + } + auto countNow = storage.count(); + REQUIRE(countNow == countBefore + 1); + } +} From d8def5c1b13a83a1df8797fab3d34760596df692 Mon Sep 17 00:00:00 2001 From: fnc12 Date: Thu, 24 Sep 2020 12:37:39 +0300 Subject: [PATCH 128/132] removed comments --- dev/storage_base.h | 2 -- include/sqlite_orm/sqlite_orm.h | 2 -- 2 files changed, 4 deletions(-) diff --git a/dev/storage_base.h b/dev/storage_base.h index 9d5499670..fce551a0c 100644 --- a/dev/storage_base.h +++ b/dev/storage_base.h @@ -133,8 +133,6 @@ namespace sqlite_orm { bool transaction(const std::function &f) { this->begin_transaction(); - // auto con = this->get_connection(); - // auto db = con.get(); auto shouldCommit = f(); if(shouldCommit) { this->commit(); diff --git a/include/sqlite_orm/sqlite_orm.h b/include/sqlite_orm/sqlite_orm.h index b7c32cb47..c4b1c5f3d 100644 --- a/include/sqlite_orm/sqlite_orm.h +++ b/include/sqlite_orm/sqlite_orm.h @@ -8710,8 +8710,6 @@ namespace sqlite_orm { bool transaction(const std::function &f) { this->begin_transaction(); - // auto con = this->get_connection(); - // auto db = con.get(); auto shouldCommit = f(); if(shouldCommit) { this->commit(); From 0e22589763657896ff9742ab8f6ef3ba6edf046f Mon Sep 17 00:00:00 2001 From: fnc12 Date: Mon, 28 Sep 2020 19:53:42 +0300 Subject: [PATCH 129/132] added busy handler function --- dev/pragma.h | 8 ++++++++ dev/storage_base.h | 27 +++++++++++++++++++++++++ include/sqlite_orm/sqlite_orm.h | 35 +++++++++++++++++++++++++++++++++ tests/pragma_tests.cpp | 19 ++++++++++++++++++ tests/storage_tests.cpp | 7 +++++++ 5 files changed, 96 insertions(+) diff --git a/dev/pragma.h b/dev/pragma.h index 9c51dff35..8e456c581 100644 --- a/dev/pragma.h +++ b/dev/pragma.h @@ -21,6 +21,14 @@ namespace sqlite_orm { pragma_t(get_connection_t get_connection_) : get_connection(std::move(get_connection_)) {} + void busy_timeout(int value) { + this->set_pragma("busy_timeout", value); + } + + int busy_timeout() { + return this->get_pragma("busy_timeout"); + } + sqlite_orm::journal_mode journal_mode() { return this->get_pragma("journal_mode"); } diff --git a/dev/storage_base.h b/dev/storage_base.h index fce551a0c..21dee1d52 100644 --- a/dev/storage_base.h +++ b/dev/storage_base.h @@ -302,6 +302,19 @@ namespace sqlite_orm { return this->connection->retain_count() > 0; } + int busy_handler(std::function handler) { + _busy_handler = move(handler); + if(this->is_opened()) { + if(_busy_handler) { + return sqlite3_busy_handler(this->connection->get(), busy_handler_callback, this); + } else { + return sqlite3_busy_handler(this->connection->get(), nullptr, nullptr); + } + } else { + return SQLITE_OK; + } + } + protected: storage_base(const std::string &filename_, int foreignKeysCount) : pragma(std::bind(&storage_base::get_connection, this)), @@ -339,6 +352,7 @@ namespace sqlite_orm { std::unique_ptr connection; std::map collatingFunctions; const int cachedForeignKeysCount; + std::function _busy_handler; connection_ref get_connection() { connection_ref res{*this->connection}; @@ -411,6 +425,10 @@ namespace sqlite_orm { sqlite3_limit(db, p.first, p.second); } + if(_busy_handler) { + sqlite3_busy_handler(this->connection->get(), busy_handler_callback, this); + } + if(this->on_open) { this->on_open(db); } @@ -526,6 +544,15 @@ namespace sqlite_orm { return f(leftLen, lhs, rightLen, rhs); } + static int busy_handler_callback(void *selfPointer, int triesCount) { + auto &storage = *static_cast(selfPointer); + if(storage._busy_handler) { + return storage._busy_handler(triesCount); + } else { + return 0; + } + } + // returns foreign keys count in storage definition template static int foreign_keys_count(T &storageImpl) { diff --git a/include/sqlite_orm/sqlite_orm.h b/include/sqlite_orm/sqlite_orm.h index c4b1c5f3d..2567a34f8 100644 --- a/include/sqlite_orm/sqlite_orm.h +++ b/include/sqlite_orm/sqlite_orm.h @@ -8199,6 +8199,14 @@ namespace sqlite_orm { pragma_t(get_connection_t get_connection_) : get_connection(std::move(get_connection_)) {} + void busy_timeout(int value) { + this->set_pragma("busy_timeout", value); + } + + int busy_timeout() { + return this->get_pragma("busy_timeout"); + } + sqlite_orm::journal_mode journal_mode() { return this->get_pragma("journal_mode"); } @@ -8879,6 +8887,19 @@ namespace sqlite_orm { return this->connection->retain_count() > 0; } + int busy_handler(std::function handler) { + _busy_handler = move(handler); + if(this->is_opened()) { + if(_busy_handler) { + return sqlite3_busy_handler(this->connection->get(), busy_handler_callback, this); + } else { + return sqlite3_busy_handler(this->connection->get(), nullptr, nullptr); + } + } else { + return SQLITE_OK; + } + } + protected: storage_base(const std::string &filename_, int foreignKeysCount) : pragma(std::bind(&storage_base::get_connection, this)), @@ -8916,6 +8937,7 @@ namespace sqlite_orm { std::unique_ptr connection; std::map collatingFunctions; const int cachedForeignKeysCount; + std::function _busy_handler; connection_ref get_connection() { connection_ref res{*this->connection}; @@ -8988,6 +9010,10 @@ namespace sqlite_orm { sqlite3_limit(db, p.first, p.second); } + if(_busy_handler) { + sqlite3_busy_handler(this->connection->get(), busy_handler_callback, this); + } + if(this->on_open) { this->on_open(db); } @@ -9103,6 +9129,15 @@ namespace sqlite_orm { return f(leftLen, lhs, rightLen, rhs); } + static int busy_handler_callback(void *selfPointer, int triesCount) { + auto &storage = *static_cast(selfPointer); + if(storage._busy_handler) { + return storage._busy_handler(triesCount); + } else { + return 0; + } + } + // returns foreign keys count in storage definition template static int foreign_keys_count(T &storageImpl) { diff --git a/tests/pragma_tests.cpp b/tests/pragma_tests.cpp index 564e68b8b..acec737ad 100644 --- a/tests/pragma_tests.cpp +++ b/tests/pragma_tests.cpp @@ -99,3 +99,22 @@ TEST_CASE("Auto vacuum") { storage.pragma.auto_vacuum(2); REQUIRE(storage.pragma.auto_vacuum() == 2); } + +TEST_CASE("busy_timeout") { + auto storage = make_storage({}); + + auto value = storage.pragma.busy_timeout(); + REQUIRE(value == 0); + + storage.pragma.busy_timeout(10); + value = storage.pragma.busy_timeout(); + REQUIRE(value == 10); + + storage.pragma.busy_timeout(20); + value = storage.pragma.busy_timeout(); + REQUIRE(value == 20); + + storage.pragma.busy_timeout(-1); + value = storage.pragma.busy_timeout(); + REQUIRE(value == 0); +} diff --git a/tests/storage_tests.cpp b/tests/storage_tests.cpp index 7998e36cb..3f9e1376c 100644 --- a/tests/storage_tests.cpp +++ b/tests/storage_tests.cpp @@ -3,6 +3,13 @@ using namespace sqlite_orm; +TEST_CASE("busy handler") { + auto storage = make_storage({}); + storage.busy_handler([](int /*timesCount*/) { + return 0; + }); +} + TEST_CASE("drop table") { struct User { int id = 0; From 2ce815ff3be62988956fd25cd6e3caa44830329c Mon Sep 17 00:00:00 2001 From: Yevgeniy Zakharov Date: Tue, 29 Sep 2020 19:49:19 +0300 Subject: [PATCH 130/132] Update README.md --- README.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index a1d0ee5f0..f507fd216 100644 --- a/README.md +++ b/README.md @@ -42,7 +42,6 @@ SQLite ORM light header only library for modern C++ * **Easy integration** - single header only lib. * **The only dependency** - libsqlite3 * **C++ standard code style** -* **No undefined behaviour** - if something goes wrong lib throws an exception * **In memory database support** - provide `:memory:` or empty filename * **COLLATE support** * **Limits setting/getting support** @@ -794,6 +793,10 @@ If you want to use the lib directly with Make or something else, just set the in * C++14 compatible compiler (not C++11 cause of templated lambdas in the lib). * Sqlite3 installed on your system and in the path, so cmake can find it (or linked to you project if you don't use cmake) +# Video from conference + +[![Video from conference](https://img.youtube.com/vi/ngsilquWgpo/0.jpg)](https://www.youtube.com/watch?v=ngsilquWgpo) + # SqliteMan In case you need a native SQLite client for macOS or Windows 10 you can use SqliteMan https://sqliteman.dev. It is not a commercial. It is a free native client being developed by the maintainer of this repo. From 54439332343b7dad55b65a867eb63d7adb4057f9 Mon Sep 17 00:00:00 2001 From: Yevgeniy Zakharov Date: Sun, 4 Oct 2020 19:48:29 +0300 Subject: [PATCH 131/132] Update TODO.md --- TODO.md | 1 - 1 file changed, 1 deletion(-) diff --git a/TODO.md b/TODO.md index df39bf71c..315e99e47 100644 --- a/TODO.md +++ b/TODO.md @@ -7,7 +7,6 @@ * `ATTACH` * blob incremental I/O https://sqlite.org/c3ref/blob_open.html * explicit FROM for subqueries in FROM argument -* busy handler https://sqlite.org/c3ref/busy_handler.html * CREATE VIEW and other view operations https://sqlite.org/lang_createview.html * triggers * query static check for correct order (e.g. `GROUP BY` after `WHERE`) From a4ae9f1fa9e349151696e3ca1c91f6b51179c561 Mon Sep 17 00:00:00 2001 From: Tan Li Boon Date: Tue, 6 Oct 2020 20:06:44 +0900 Subject: [PATCH 132/132] Update documentation on CMake --- README.md | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index f507fd216..968133108 100644 --- a/README.md +++ b/README.md @@ -769,7 +769,7 @@ You might need admin rights for the last command. # Usage -## Cmake +## CMake If you use cmake, there are two supported ways how to use it with cmake (if another works as well or should be supported, open an issue). @@ -779,12 +779,18 @@ Either way you choose, the include path as well as the dependency sqlite3 will b If you have installed the lib system wide and it's in your PATH, you can use find_package to include it in cmake. It will make a target `sqlite_orm::sqlite_orm` available which you can link against. Have a look at examples/find_package for a full example. +```cmake +find_package(SqliteOrm REQUIRED) + +target_link_libraries(main PRIVATE sqlite_orm::sqlite_orm) +``` + ## Fetch Content (Recommended) Alternatively, cmake can download the project directly from github during configure stage and therefore you don't need to install the lib before. Againt a target `sqlite_orm::sqlite_orm` will be available which you can link against. Have a look at examples/fetch_content for a full example. -## None cmake +## No CMake If you want to use the lib directly with Make or something else, just set the inlcude path correctly (should be correct on Linux already), so `sqlite_orm/sqlite_orm.h` is found. As this is a header only lib, there is nothing more you have to do.