From fb84f9b4a9ccff2665b9ddd748cb3eb6d3694bd3 Mon Sep 17 00:00:00 2001 From: Aaron Bishop Date: Sat, 21 Oct 2017 16:09:30 -0400 Subject: [PATCH 1/4] Allow result_t to have a size() function if DbResult has a size() function. size() must be const, but can be arbitrary type. size() may be wrong after first next has been called --- include/sqlpp11/result.h | 32 ++++++++++++++++++++++++++++++++ test_types/result_row.cpp | 6 ++++-- tests/MockDb.h | 2 ++ 3 files changed, 38 insertions(+), 2 deletions(-) diff --git a/include/sqlpp11/result.h b/include/sqlpp11/result.h index 109cdfed..b38cf86b 100644 --- a/include/sqlpp11/result.h +++ b/include/sqlpp11/result.h @@ -38,6 +38,31 @@ namespace sqlpp using type = std::input_iterator_tag; }; + namespace detail + { + template + struct result_has_size : std::false_type {}; + + template + struct result_has_size().size())>> + : std::true_type {}; + + template + constexpr bool result_has_size_v = result_has_size::value; + + template + struct result_size_type { using type = void; }; + + template + struct result_size_type().size())>> + { + using type = decltype(std::declval().size()); + }; + + template + using result_size_type_t = typename result_size_type::type; + } + template class result_t { @@ -139,6 +164,13 @@ namespace sqlpp { _result.next(_result_row); } + + template> + Size size() const + { + static_assert(detail::result_has_size_v, "Underlying connector does not support size()"); + return _result.size(); + } }; } // namespace sqlpp diff --git a/test_types/result_row.cpp b/test_types/result_row.cpp index 31858a91..b17140d2 100644 --- a/test_types/result_row.cpp +++ b/test_types/result_row.cpp @@ -65,9 +65,11 @@ namespace static_assert(not sqlpp::can_be_null_t::value, "constant non-null value can not be null"); } { - const auto& x = db(select(bar.alpha, foo.delta, bar.gamma, seven) + auto&& result = db(select(bar.alpha, foo.delta, bar.gamma, seven) .from(bar.join(foo).on(foo.omega > bar.alpha)) - .unconditionally()).front(); + .unconditionally()); + const auto& x = result.front(); + static_assert(std::is_same::value, "db doesn't have size_t result_t.size() "); static_assert(sqlpp::can_be_null_t::value, "nullable value can always be null"); static_assert(not sqlpp::can_be_null_t::value, "left side of (inner) join cannot be null"); static_assert(not sqlpp::can_be_null_t::value, "right side of (inner) join cannot be null"); diff --git a/tests/MockDb.h b/tests/MockDb.h index 8e5d5308..5c9bb432 100644 --- a/tests/MockDb.h +++ b/tests/MockDb.h @@ -114,6 +114,8 @@ struct MockDbT : public sqlpp::connection { result_row._invalidate(); } + + size_t size() const { return 0; } }; // Directly executed statements start here From d207a266380c5feba29c98ab9e79fd5167d651fd Mon Sep 17 00:00:00 2001 From: Aaron Bishop Date: Mon, 23 Oct 2017 09:10:10 -0400 Subject: [PATCH 2/4] Removed templated variables Also fixed tabs to spaces. Used github editor, can update later if there was a syntax error. --- include/sqlpp11/result.h | 44 +++++++++++++++++----------------------- 1 file changed, 19 insertions(+), 25 deletions(-) diff --git a/include/sqlpp11/result.h b/include/sqlpp11/result.h index b38cf86b..024dfc85 100644 --- a/include/sqlpp11/result.h +++ b/include/sqlpp11/result.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2015, Roland Bock + * Copyright (c) 2013-2017, Roland Bock, Aaron Bishop * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, @@ -40,27 +40,21 @@ namespace sqlpp namespace detail { - template - struct result_has_size : std::false_type {}; + template + struct result_has_size : std::false_type {}; - template - struct result_has_size().size())>> - : std::true_type {}; + template + struct result_has_size().size())>> + : std::true_type {}; - template - constexpr bool result_has_size_v = result_has_size::value; + template + struct result_size_type { using type = void; }; - template - struct result_size_type { using type = void; }; - - template - struct result_size_type().size())>> - { - using type = decltype(std::declval().size()); - }; - - template - using result_size_type_t = typename result_size_type::type; + template + struct result_size_type().size())>> + { + using type = decltype(std::declval().size()); + }; } template @@ -165,12 +159,12 @@ namespace sqlpp _result.next(_result_row); } - template> - Size size() const - { - static_assert(detail::result_has_size_v, "Underlying connector does not support size()"); - return _result.size(); - } + template::type> + Size size() const + { + static_assert(detail::result_has_size::value, "Underlying connector does not support size()"); + return _result.size(); + } }; } // namespace sqlpp From 1db9ccfd7cdb6ef90e5adcbe89fd1068d61f4d72 Mon Sep 17 00:00:00 2001 From: Aaron Bishop Date: Mon, 23 Oct 2017 20:03:37 -0400 Subject: [PATCH 3/4] Created separate MockSizeDb Removed size() from MockDb --- test_types/result_row.cpp | 14 ++++++++++---- tests/MockDb.h | 2 -- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/test_types/result_row.cpp b/test_types/result_row.cpp index b17140d2..294dff10 100644 --- a/test_types/result_row.cpp +++ b/test_types/result_row.cpp @@ -65,16 +65,22 @@ namespace static_assert(not sqlpp::can_be_null_t::value, "constant non-null value can not be null"); } { - auto&& result = db(select(bar.alpha, foo.delta, bar.gamma, seven) + const auto& x = db(select(bar.alpha, foo.delta, bar.gamma, seven) .from(bar.join(foo).on(foo.omega > bar.alpha)) - .unconditionally()); - const auto& x = result.front(); - static_assert(std::is_same::value, "db doesn't have size_t result_t.size() "); + .unconditionally()).front(); static_assert(sqlpp::can_be_null_t::value, "nullable value can always be null"); static_assert(not sqlpp::can_be_null_t::value, "left side of (inner) join cannot be null"); static_assert(not sqlpp::can_be_null_t::value, "right side of (inner) join cannot be null"); static_assert(not sqlpp::can_be_null_t::value, "constant non-null value can not be null"); } + { + MockSizeDB db2; + auto&& result = db2(select(bar.alpha, foo.delta, bar.gamma, seven) + .from(bar.join(foo).on(foo.omega > bar.alpha)) + .unconditionally()); + result.size(); + static_assert(std::is_same::value, "MockSizeDb size() isn't size_t"); + } // Inner join { diff --git a/tests/MockDb.h b/tests/MockDb.h index 5c9bb432..8e5d5308 100644 --- a/tests/MockDb.h +++ b/tests/MockDb.h @@ -114,8 +114,6 @@ struct MockDbT : public sqlpp::connection { result_row._invalidate(); } - - size_t size() const { return 0; } }; // Directly executed statements start here From d724909864a55654dd19b7478fd1514f4a86dd63 Mon Sep 17 00:00:00 2001 From: Aaron Bishop Date: Wed, 25 Oct 2017 11:47:57 -0400 Subject: [PATCH 4/4] fixed issues with test_types/result_row.cpp --- test_types/result_row.cpp | 12 +-- tests/MockDb.h | 202 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 208 insertions(+), 6 deletions(-) diff --git a/test_types/result_row.cpp b/test_types/result_row.cpp index 294dff10..9bfae81a 100644 --- a/test_types/result_row.cpp +++ b/test_types/result_row.cpp @@ -73,14 +73,14 @@ namespace static_assert(not sqlpp::can_be_null_t::value, "right side of (inner) join cannot be null"); static_assert(not sqlpp::can_be_null_t::value, "constant non-null value can not be null"); } - { - MockSizeDB db2; - auto&& result = db2(select(bar.alpha, foo.delta, bar.gamma, seven) + { + MockSizeDb db2; + auto&& result = db2(select(bar.alpha, foo.delta, bar.gamma, seven) .from(bar.join(foo).on(foo.omega > bar.alpha)) .unconditionally()); - result.size(); - static_assert(std::is_same::value, "MockSizeDb size() isn't size_t"); - } + result.size(); + static_assert(std::is_same::value, "MockSizeDb size() isn't size_t"); + } // Inner join { diff --git a/tests/MockDb.h b/tests/MockDb.h index 8e5d5308..05271893 100644 --- a/tests/MockDb.h +++ b/tests/MockDb.h @@ -288,4 +288,206 @@ struct MockDbT : public sqlpp::connection using MockDb = MockDbT; using EnforceDb = MockDbT; + +struct MockSizeDb : public sqlpp::connection +{ + using _traits = MockDb::_traits; + + using _serializer_context_t = MockDb::_serializer_context_t; + + using _interpreter_context_t = _serializer_context_t; + + _serializer_context_t get_serializer_context() + { + return {}; + } + + template + static _serializer_context_t& _serialize_interpretable(const T& t, _serializer_context_t& context) + { + sqlpp::serialize(t, context); + return context; + } + + template + static _serializer_context_t& _interpret_interpretable(const T& t, _interpreter_context_t& context) + { + sqlpp::serialize(t, context); + return context; + } + + class result_t : public MockDb::result_t + { + public: + size_t size() const { return 0; } + }; + + // Directly executed statements start here + template + auto _run(const T& t, ::sqlpp::consistent_t) -> decltype(t._run(*this)) + { + return t._run(*this); + } + + template + auto _run(const T& t, Check) -> Check; + + template + auto operator()(const T& t) -> decltype(this->_run(t, sqlpp::run_check_t<_serializer_context_t, T>{})) + { + return _run(t, sqlpp::run_check_t<_serializer_context_t, T>{}); + } + + size_t execute(const std::string&) + { + return 0; + } + + template < + typename Statement, + typename Enable = typename std::enable_if::value, void>::type> + size_t execute(const Statement& x) + { + _serializer_context_t context; + ::sqlpp::serialize(x, context); + std::cout << "Running execute call with\n" << context.str() << std::endl; + return execute(context.str()); + } + + template + size_t insert(const Insert& x) + { + _serializer_context_t context; + ::sqlpp::serialize(x, context); + std::cout << "Running insert call with\n" << context.str() << std::endl; + return 0; + } + + template + size_t update(const Update& x) + { + _serializer_context_t context; + ::sqlpp::serialize(x, context); + std::cout << "Running update call with\n" << context.str() << std::endl; + return 0; + } + + template + size_t remove(const Remove& x) + { + _serializer_context_t context; + ::sqlpp::serialize(x, context); + std::cout << "Running remove call with\n" << context.str() << std::endl; + return 0; + } + + template + result_t select(const Select& x) + { + _serializer_context_t context; + ::sqlpp::serialize(x, context); + std::cout << "Running select call with\n" << context.str() << std::endl; + return {}; + } + + // Prepared statements start here + using _prepared_statement_t = std::nullptr_t; + + template + auto _prepare(const T& t, ::sqlpp::consistent_t) -> decltype(t._prepare(*this)) + { + return t._prepare(*this); + } + + template + auto _prepare(const T& t, Check) -> Check; + + template + auto prepare(const T& t) -> decltype(this->_prepare(t, sqlpp::prepare_check_t<_serializer_context_t, T>{})) + { + return _prepare(t, sqlpp::prepare_check_t<_serializer_context_t, T>{}); + } + + template + _prepared_statement_t prepare_execute(Statement& x) + { + _serializer_context_t context; + ::sqlpp::serialize(x, context); + std::cout << "Running prepare execute call with\n" << context.str() << std::endl; + return nullptr; + } + + template + _prepared_statement_t prepare_insert(Insert& x) + { + _serializer_context_t context; + ::sqlpp::serialize(x, context); + std::cout << "Running prepare insert call with\n" << context.str() << std::endl; + return nullptr; + } + + template + size_t run_prepared_execute(const PreparedExecute&) + { + return 0; + } + + template + size_t run_prepared_insert(const PreparedInsert&) + { + return 0; + } + + template + _prepared_statement_t prepare_select(Select& x) + { + _serializer_context_t context; + ::sqlpp::serialize(x, context); + std::cout << "Running prepare select call with\n" << context.str() << std::endl; + return nullptr; + } + + template + result_t run_prepared_select(PreparedSelect&) + { + return {}; + } + + auto attach(std::string name) -> ::sqlpp::schema_t + { + return {name}; + } + + void start_transaction() + { + _mock_data._last_isolation_level = _mock_data._default_isolation_level; + } + + void start_transaction(sqlpp::isolation_level level) + { + _mock_data._last_isolation_level = level; + } + + void set_default_isolation_level(sqlpp::isolation_level level) + { + _mock_data._default_isolation_level = level; + } + + sqlpp::isolation_level get_default_isolation_level() + { + return _mock_data._default_isolation_level; + } + + void rollback_transaction(bool) + {} + + void commit_transaction() + {} + + void report_rollback_failure(std::string) + {} + + // temporary data store to verify the expected results were produced + InternalMockData _mock_data; +}; #endif