From 8b4408c95f5aae3420ff03919b424606c9fe7fc4 Mon Sep 17 00:00:00 2001 From: Alex Choi Date: Sat, 14 Oct 2017 13:34:07 +0800 Subject: [PATCH 1/5] fixed compile error when include connection_pool.h using c++11 --- include/sqlpp11/connection_pool.h | 339 ++++++++++++++++-------------- include/sqlpp11/pool_connection.h | 124 ++++++----- 2 files changed, 244 insertions(+), 219 deletions(-) diff --git a/include/sqlpp11/connection_pool.h b/include/sqlpp11/connection_pool.h index 67ce9ea9..c63141ba 100644 --- a/include/sqlpp11/connection_pool.h +++ b/include/sqlpp11/connection_pool.h @@ -1,28 +1,28 @@ /* -* Copyright (c) 2013 - 2017, Roland Bock, Frank Park -* All rights reserved. -* -* Redistribution and use in source and binary forms, with or without modification, -* are permitted provided that the following conditions are met: -* -* Redistributions of source code must retain the above copyright notice, this -* list of conditions and the following disclaimer. -* -* Redistributions in binary form must reproduce the above copyright notice, this -* list of conditions and the following disclaimer in the documentation and/or -* other materials provided with the distribution. -* -* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR -* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ + * Copyright (c) 2013 - 2017, Roland Bock, Frank Park + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, this + * list of conditions and the following disclaimer in the documentation and/or + * other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ #ifndef SQLPP_CONNECTION_POOL_H #define SQLPP_CONNECTION_POOL_H @@ -39,154 +39,171 @@ namespace sqlpp { - namespace reconnect_policy - { - struct auto_reconnect { - template - void operator()(Connection* connection) - { - if(!connection->is_valid()) - connection->reconnect() - } - template - void clean(Connection* connection) {} - }; + namespace reconnect_policy + { + struct auto_reconnect + { + template + void operator()(Connection* connection) + { + if (!connection->is_valid()) + connection->reconnect(); + } + template + void clean(Connection* connection) + { + } + }; - using namespace std::chrono_literals; - class periodic_reconnect - { - private: - std::chrono::seconds revalidate_after; - std::unordered_map > last_checked; + class periodic_reconnect + { + private: + std::chrono::seconds revalidate_after; + std::unordered_map> last_checked; - public: - periodic_reconnect(const std::chrono::seconds r = 28800s) //default wait_timeout in MySQL - : revalidate_after(r), last_checked() {} + public: + periodic_reconnect(const std::chrono::seconds r = std::chrono::seconds(28800)) // default wait_timeout in MySQL + : revalidate_after(r), last_checked() + { + } - template - void operator()(Connection* con) - { - auto last = last_checked.find(con); - auto now = std::chrono::system_clock::now(); - if(last == last_checked.end()) - { - if (!con->is_valid()) - { - con->reconnect(); - } - last_checked.emplace_hint(last, con, now); - } - else if(now - last->second > revalidate_after) - { - if (!con->is_valid()) - { - con->reconnect(); - } - last = now; - } - } - template - void clean(Connection* con) { - auto itr = last_checked.find(con); - if(itr != last_checked.end()) - { - last_checked.erase(itr); - } - } - }; + template + void operator()(Connection* con) + { + auto last = last_checked.find(con); + auto now = std::chrono::system_clock::now(); + if (last == last_checked.end()) + { + if (!con->is_valid()) + { + con->reconnect(); + } + last_checked.emplace_hint(last, con, now); + } + else if (now - last->second > revalidate_after) + { + if (!con->is_valid()) + { + con->reconnect(); + } + last = now; + } + } + template + void clean(Connection* con) + { + auto itr = last_checked.find(con); + if (itr != last_checked.end()) + { + last_checked.erase(itr); + } + } + }; - struct never_reconnect { - template - void operator()(Connection*) {} - template - void clean(Connection*) {} - }; - } + struct never_reconnect + { + template + void operator()(Connection*) + { + } + template + void clean(Connection*) + { + } + }; + } - template ::value, Connection_config::connection>::type> - class connection_pool - { - friend pool_connection; + template ::value, + typename Connection_config::connection>::type> + class connection_pool + { + friend pool_connection; - private: - std::mutex connection_pool_mutex; - const std::shared_ptr config; - size_t maximum_pool_size = 0; - std::stack> free_connections; - Reconnect_policy reconnect_policy; + private: + std::mutex connection_pool_mutex; + const std::shared_ptr config; + size_t maximum_pool_size = 0; + std::stack> free_connections; + Reconnect_policy reconnect_policy; - void free_connection(std::unique_ptr& connection) - { - std::lock_guard lock(connection_pool_mutex); - if (free_connections.size() >= maximum_pool_size) - { - // Exceeds default size, do nothign and let connection self destroy. - } - else - { - if (connection.get()) - { - if (connection->is_valid()) - { - free_connections.push(std::move(connection)); - } - else - { - throw sqlpp::exception("Trying to free a connection with incompatible config."); - } - } - else - { - throw sqlpp::exception("Trying to free an empty connection."); - } - } - } + void free_connection(std::unique_ptr& connection) + { + std::lock_guard lock(connection_pool_mutex); + if (free_connections.size() >= maximum_pool_size) + { + // Exceeds default size, do nothign and let connection self destroy. + } + else + { + if (connection.get()) + { + if (connection->is_valid()) + { + free_connections.push(std::move(connection)); + } + else + { + throw sqlpp::exception("Trying to free a connection with incompatible config."); + } + } + else + { + throw sqlpp::exception("Trying to free an empty connection."); + } + } + } - public: - connection_pool(const std::shared_ptr& config, size_t pool_size) - : config(config), maximum_pool_size(pool_size), reconnect_policy(Reconnect_policy()) {} - ~connection_pool() = default; - connection_pool(const connection_pool&) = delete; - connection_pool(connection_pool&& other) - : config(std::move(other.config)), maximum_pool_size(std::move(other.maximum_pool_size)), - reconnect_policy(std::move(other.reconnect_policy)) {} - connection_pool& operator=(const connection_pool&) = delete; - connection_pool& operator=(connection_pool&&) = delete; + public: + connection_pool(const std::shared_ptr& config, size_t pool_size) + : config(config), maximum_pool_size(pool_size), reconnect_policy(Reconnect_policy()) + { + } + ~connection_pool() = default; + connection_pool(const connection_pool&) = delete; + connection_pool(connection_pool&& other) + : config(std::move(other.config)), + maximum_pool_size(std::move(other.maximum_pool_size)), + reconnect_policy(std::move(other.reconnect_policy)) + { + } + connection_pool& operator=(const connection_pool&) = delete; + connection_pool& operator=(connection_pool&&) = delete; - pool_connection get_connection() - { - std::lock_guard lock(connection_pool_mutex); - if (!free_connections.empty()) - { - auto connection = std::move(free_connections.top()); - free_connections.pop(); - return pool_connection(connection, this); - } + pool_connection get_connection() + { + std::lock_guard lock(connection_pool_mutex); + if (!free_connections.empty()) + { + auto connection = std::move(free_connections.top()); + free_connections.pop(); + return pool_connection(connection, this); + } - try - { - return pool_connection(std::move(std::make_unique(config)), this); - } - catch (const sqlpp::exception& e) - { - std::cerr << "Failed to spawn a new connection." << std::endl; - std::cerr << e.what() << std::endl; - throw; - } - } - }; + try + { + auto c = std::unique_ptr(new Connection(*(config.get()))); + return pool_connection(c, this); + } + catch (const sqlpp::exception& e) + { + std::cerr << "Failed to spawn a new connection." << std::endl; + std::cerr << e.what() << std::endl; + throw; + } + } + }; - template::value,Connection_config::connection>::type> - connection_pool make_connection_pool( - const std::shared_ptr& config, - size_t max_pool_size) - { - return connection_pool(config, max_pool_size); - } + template ::value, + typename Connection_config::connection>::type> + connection_pool make_connection_pool( + const std::shared_ptr& config, size_t max_pool_size) + { + return connection_pool(config, max_pool_size); + } } #endif diff --git a/include/sqlpp11/pool_connection.h b/include/sqlpp11/pool_connection.h index 12ba5bce..58d4ab6f 100644 --- a/include/sqlpp11/pool_connection.h +++ b/include/sqlpp11/pool_connection.h @@ -1,28 +1,28 @@ /* -* Copyright (c) 2013 - 2017, Roland Bock, Frank Park -* All rights reserved. -* -* Redistribution and use in source and binary forms, with or without modification, -* are permitted provided that the following conditions are met: -* -* Redistributions of source code must retain the above copyright notice, this -* list of conditions and the following disclaimer. -* -* Redistributions in binary form must reproduce the above copyright notice, this -* list of conditions and the following disclaimer in the documentation and/or -* other materials provided with the distribution. -* -* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR -* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ + * Copyright (c) 2013 - 2017, Roland Bock, Frank Park + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, this + * list of conditions and the following disclaimer in the documentation and/or + * other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ #ifndef SQLPP_POOL_CONNECTION_H #define SQLPP_POOL_CONNECTION_H @@ -31,46 +31,54 @@ namespace sqlpp { - template > - struct pool_connection - { - private: - std::unique_ptr _impl; - Connection_pool* origin; + template + class connection_pool; - public: - pool_connection(std::unique_ptr& connection, Connection_pool* origin) - : _impl(std::move(connection)), origin(origin) {} + template > + struct pool_connection + { + private: + std::unique_ptr _impl; + Connection_pool* origin; - ~pool_connection() - { - origin->free_connection(_impl); - } + public: + pool_connection(std::unique_ptr& connection, Connection_pool* origin) + : _impl(std::move(connection)), origin(origin) + { + } - template - auto operator()(Args&&... args) -> decltype(_impl->args(std::forward(args)...)) - { - return _impl->args(std::forward(args)...); - } + ~pool_connection() + { + origin->free_connection(_impl); + } - template - auto operator()(const T& t) -> decltype(_impl->run(t)) - { - return _impl->run(t); - } + template + auto operator()(Args&&... args) -> decltype((*_impl)(std::forward(args)...)) + { + return (*_impl)(std::forward(args)...); + } - Connection* operator->() - { - return &_impl; - } + template + auto operator()(const T& t) -> decltype((*_impl)(t)) + { + return (*_impl)(t); + } - pool_connection(const pool_connection&) = delete; - pool_connection(pool_connection&& other) - : _impl(std::move(other._impl)), origin(other.origin) {} - pool_connection& operator=(const pool_connection&) = delete; - pool_connection& operator=(pool_connection&&) = delete; - }; + Connection* operator->() + { + return _impl.get(); + } + + pool_connection(const pool_connection&) = delete; + pool_connection(pool_connection&& other) : _impl(std::move(other._impl)), origin(other.origin) + { + } + pool_connection& operator=(const pool_connection&) = delete; + pool_connection& operator=(pool_connection&&) = delete; + }; } #endif From fb84f9b4a9ccff2665b9ddd748cb3eb6d3694bd3 Mon Sep 17 00:00:00 2001 From: Aaron Bishop Date: Sat, 21 Oct 2017 16:09:30 -0400 Subject: [PATCH 2/5] 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 3/5] 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 4/5] 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 5/5] 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