diff --git a/example/query_sync.cpp b/example/query_sync.cpp index b91d20ac..9af95aca 100644 --- a/example/query_sync.cpp +++ b/example/query_sync.cpp @@ -104,9 +104,9 @@ void main_impl(int argc, char** argv) * MySQL fields. Indexing a rows object returns a row_view, which represents * an individual row. */ - boost::mysql::rows employees; - result.read_all(employees); - for (boost::mysql::row_view employee : employees) + boost::mysql::rows all_rows; + result.read_all(all_rows); + for (boost::mysql::row_view employee : all_rows) { print_employee(employee); } @@ -121,9 +121,9 @@ void main_impl(int argc, char** argv) // Check we have updated our poor intern salary conn.query("SELECT salary FROM employee WHERE first_name = 'Underpaid'", result); - auto rows = result.read_all(); - ASSERT(rows.size() == 1); - double salary = rows[0][0].as_double(); + result.read_all(all_rows); + ASSERT(all_rows.size() == 1); + double salary = all_rows[0][0].as_double(); ASSERT(salary == 10000); // Close the connection. This notifies the MySQL we want to log out diff --git a/include/boost/mysql/impl/resultset.hpp b/include/boost/mysql/impl/resultset.hpp index 1bfdfcc2..73830c00 100644 --- a/include/boost/mysql/impl/resultset.hpp +++ b/include/boost/mysql/impl/resultset.hpp @@ -17,14 +17,18 @@ // Read one row template -boost::mysql::row_view boost::mysql::resultset::read_one(error_code& err, error_info& info) +boost::mysql::row_view boost::mysql::resultset::read_one( + use_views_t, + error_code& err, + error_info& info +) { detail::clear_errors(err, info); return detail::read_one_row(get_channel(), *this, err, info); } template -boost::mysql::row_view boost::mysql::resultset::read_one() +boost::mysql::row_view boost::mysql::resultset::read_one(use_views_t) { detail::error_block blk; row_view res = detail::read_one_row(get_channel(), *this, blk.err, blk.info); @@ -39,7 +43,11 @@ BOOST_ASIO_INITFN_AUTO_RESULT_TYPE( CompletionToken, void(boost::mysql::error_code, boost::mysql::row_view) ) -boost::mysql::resultset::async_read_one(error_info& output_info, CompletionToken&& token) +boost::mysql::resultset::async_read_one( + use_views_t, + error_info& output_info, + CompletionToken&& token +) { return detail::async_read_one_row( get_channel(), @@ -86,6 +94,7 @@ boost::mysql::resultset::async_read_one( // Read some rows template boost::mysql::rows_view boost::mysql::resultset::read_some( + use_views_t, error_code& err, error_info& info ) @@ -95,7 +104,7 @@ boost::mysql::rows_view boost::mysql::resultset::read_some( } template -boost::mysql::rows_view boost::mysql::resultset::read_some() +boost::mysql::rows_view boost::mysql::resultset::read_some(use_views_t) { detail::error_block blk; rows_view res = detail::read_some_rows(get_channel(), *this, blk.err, blk.info); @@ -111,7 +120,11 @@ BOOST_ASIO_INITFN_AUTO_RESULT_TYPE( CompletionToken, void(boost::mysql::error_code, boost::mysql::rows_view) ) -boost::mysql::resultset::async_read_some(error_info& output_info, CompletionToken&& token) +boost::mysql::resultset::async_read_some( + use_views_t, + error_info& output_info, + CompletionToken&& token +) { return detail::async_read_some_rows( get_channel(), @@ -156,14 +169,18 @@ boost::mysql::resultset::async_read_some( // Read all rows template -boost::mysql::rows_view boost::mysql::resultset::read_all(error_code& err, error_info& info) +boost::mysql::rows_view boost::mysql::resultset::read_all( + use_views_t, + error_code& err, + error_info& info +) { detail::clear_errors(err, info); return detail::read_all_rows(get_channel(), *this, err, info); } template -boost::mysql::rows_view boost::mysql::resultset::read_all() +boost::mysql::rows_view boost::mysql::resultset::read_all(use_views_t) { detail::error_block blk; rows_view res = detail::read_all_rows(get_channel(), *this, blk.err, blk.info); @@ -179,7 +196,11 @@ BOOST_ASIO_INITFN_AUTO_RESULT_TYPE( CompletionToken, void(boost::mysql::error_code, boost::mysql::rows_view) ) -boost::mysql::resultset::async_read_all(error_info& output_info, CompletionToken&& token) +boost::mysql::resultset::async_read_all( + use_views_t, + error_info& output_info, + CompletionToken&& token +) { return detail::async_read_all_rows( get_channel(), diff --git a/include/boost/mysql/resultset.hpp b/include/boost/mysql/resultset.hpp index 28f22a6c..9de1673d 100644 --- a/include/boost/mysql/resultset.hpp +++ b/include/boost/mysql/resultset.hpp @@ -13,6 +13,7 @@ #include #include #include +#include #include @@ -54,7 +55,7 @@ public: * (TODO). If the operation fails, * `output` is left in a valid but undetrmined state. */ - row_view read_one(error_code& err, error_info& info); + row_view read_one(use_views_t, error_code& err, error_info& info); /** * \brief Reads a single row (sync with exceptions version). @@ -68,7 +69,7 @@ public: * (as if TODO was called). If the operation fails, * `output` is left in a valid but undetrmined state. */ - row_view read_one(); + row_view read_one(use_views_t); /** * \brief Reads a single row (async without [reflink error_info] version). @@ -89,9 +90,16 @@ public: BOOST_ASIO_COMPLETION_TOKEN_FOR(void(::boost::mysql::error_code, ::boost::mysql::row_view)) CompletionToken BOOST_ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)> BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, void(error_code, row_view)) - async_read_one(CompletionToken&& token BOOST_ASIO_DEFAULT_COMPLETION_TOKEN(executor_type)) + async_read_one( + use_views_t, + CompletionToken&& token BOOST_ASIO_DEFAULT_COMPLETION_TOKEN(executor_type) + ) { - return async_read_one(get_channel().shared_info(), std::forward(token)); + return async_read_one( + use_views, + get_channel().shared_info(), + std::forward(token) + ); } /** @@ -114,6 +122,7 @@ public: CompletionToken BOOST_ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)> BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, void(error_code, row_view)) async_read_one( + use_views_t, error_info& output_info, CompletionToken&& token BOOST_ASIO_DEFAULT_COMPLETION_TOKEN(executor_type) ); @@ -200,8 +209,8 @@ public: CompletionToken&& token BOOST_ASIO_DEFAULT_COMPLETION_TOKEN(executor_type) ); - rows_view read_some(error_code& err, error_info& info); - rows_view read_some(); + rows_view read_some(use_views_t, error_code& err, error_info& info); + rows_view read_some(use_views_t); /** * \brief Reads several rows, up to a maximum @@ -214,9 +223,16 @@ public: BOOST_ASIO_COMPLETION_TOKEN_FOR(void(::boost::mysql::error_code, ::boost::mysql::rows_view)) CompletionToken BOOST_ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)> BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, void(error_code, rows_view)) - async_read_some(CompletionToken&& token BOOST_ASIO_DEFAULT_COMPLETION_TOKEN(executor_type)) + async_read_some( + use_views_t, + CompletionToken&& token BOOST_ASIO_DEFAULT_COMPLETION_TOKEN(executor_type) + ) { - return async_read_some(get_channel().shared_info(), std::forward(token)); + return async_read_some( + use_views, + get_channel().shared_info(), + std::forward(token) + ); } /** @@ -231,6 +247,7 @@ public: CompletionToken BOOST_ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)> BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, void(error_code, rows_view)) async_read_some( + use_views_t, error_info& output_info, CompletionToken&& token BOOST_ASIO_DEFAULT_COMPLETION_TOKEN(executor_type) ); @@ -277,10 +294,10 @@ public: ); /// Reads all available rows (sync with error code version). - rows_view read_all(error_code& err, error_info& info); + rows_view read_all(use_views_t, error_code& err, error_info& info); /// Reads all available rows (sync with exceptions version). - rows_view read_all(); + rows_view read_all(use_views_t); /** * \brief Reads all available rows (async without [reflink error_info] version). @@ -292,9 +309,16 @@ public: BOOST_ASIO_COMPLETION_TOKEN_FOR(void(::boost::mysql::error_code, ::boost::mysql::rows_view)) CompletionToken BOOST_ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)> BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, void(error_code, rows_view)) - async_read_all(CompletionToken&& token BOOST_ASIO_DEFAULT_COMPLETION_TOKEN(executor_type)) + async_read_all( + use_views_t, + CompletionToken&& token BOOST_ASIO_DEFAULT_COMPLETION_TOKEN(executor_type) + ) { - return async_read_all(get_channel().shared_info(), std::forward(token)); + return async_read_all( + use_views, + get_channel().shared_info(), + std::forward(token) + ); } /** @@ -308,6 +332,7 @@ public: CompletionToken BOOST_ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)> BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, void(error_code, rows_view)) async_read_all( + use_views_t, error_info& output_info, CompletionToken&& token BOOST_ASIO_DEFAULT_COMPLETION_TOKEN(executor_type) ); diff --git a/include/boost/mysql/use_views.hpp b/include/boost/mysql/use_views.hpp new file mode 100644 index 00000000..386d35b5 --- /dev/null +++ b/include/boost/mysql/use_views.hpp @@ -0,0 +1,27 @@ +// +// Copyright (c) 2019-2022 Ruben Perez Hidalgo (rubenperez038 at gmail dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_MYSQL_USE_VIEWS_HPP +#define BOOST_MYSQL_USE_VIEWS_HPP + +namespace boost { +namespace mysql { + +/** + * \brief Placeholder type to indicate that a function should return non-owning views. + */ +struct use_views_t +{ +}; + +/// Placeholder to indicate that a function should return non-owning views. +constexpr use_views_t use_views{}; + +} // namespace mysql +} // namespace boost + +#endif diff --git a/test/integration/connection.cpp b/test/integration/connection.cpp index a9659134..1ea22c0c 100644 --- a/test/integration/connection.cpp +++ b/test/integration/connection.cpp @@ -7,6 +7,7 @@ #include #include +#include #include "get_endpoint.hpp" #include "integration_test_common.hpp" @@ -15,6 +16,7 @@ using namespace boost::mysql::test; using boost::asio::ip::tcp; using boost::mysql::tcp_connection; using boost::mysql::tcp_resultset; +using boost::mysql::use_views; namespace { @@ -30,13 +32,13 @@ BOOST_FIXTURE_TEST_CASE(move_constructor_connected_connection, network_fixture) tcp_resultset result; first.connect(get_endpoint(er_endpoint::valid), params); first.query("SELECT 1", result); - result.read_all(); + result.read_all(use_views); // Construct second connection tcp_connection second(std::move(first)); BOOST_TEST_REQUIRE(second.valid()); second.query("SELECT 1", result); - BOOST_TEST(result.read_all().at(0).at(0).as_int64() == 1); + BOOST_TEST(result.read_all(use_views).at(0).at(0).as_int64() == 1); } BOOST_FIXTURE_TEST_CASE(move_assignment_from_connected_connection, network_fixture) @@ -50,15 +52,15 @@ BOOST_FIXTURE_TEST_CASE(move_assignment_from_connected_connection, network_fixtu first.connect(get_endpoint(er_endpoint::valid), params); second.connect(get_endpoint(er_endpoint::valid), params); first.query("SELECT 1", result); - result.read_all(); + result.read_all(use_views); second.query("SELECT 2", result); - result.read_all(); + result.read_all(use_views); // Move second = std::move(first); BOOST_TEST(second.valid()); second.query("SELECT 4", result); - BOOST_TEST(result.read_all().at(0).at(0).as_int64() == 4); + BOOST_TEST(result.read_all(use_views).at(0).at(0).as_int64() == 4); } BOOST_AUTO_TEST_SUITE_END() // test_connection diff --git a/test/integration/database_types.cpp b/test/integration/database_types.cpp index 5e1a1524..28d95164 100644 --- a/test/integration/database_types.cpp +++ b/test/integration/database_types.cpp @@ -8,6 +8,7 @@ #include #include #include +#include #include #include @@ -28,6 +29,7 @@ using boost::mysql::datetime; using boost::mysql::field_view; using boost::mysql::make_field_views; using boost::mysql::metadata; +using boost::mysql::use_views; using boost::mysql::detail::stringize; BOOST_AUTO_TEST_SUITE(test_database_types) @@ -629,7 +631,7 @@ BOOST_FIXTURE_TEST_CASE(query, tcp_network_fixture) // Execute it boost::mysql::tcp_resultset result; conn.query(query, result); - auto rows = result.read_all(); + auto rows = result.read_all(use_views); // Validate the received metadata validate_meta(result.meta(), {sample.mvalid}); @@ -664,7 +666,7 @@ BOOST_FIXTURE_TEST_CASE(statement, tcp_network_fixture) // Execute it with the provided parameters boost::mysql::tcp_resultset result; stmt.execute(std::make_tuple(sample.row_id), result); - auto rows = result.read_all(); + auto rows = result.read_all(use_views); // Validate the received metadata validate_meta(result.meta(), {sample.mvalid}); @@ -720,7 +722,7 @@ BOOST_FIXTURE_TEST_CASE(prepared_statement_execute_param, tcp_network_fixture) // Execute it with the provided parameters boost::mysql::tcp_resultset result; stmt.execute(std::make_tuple(sample.row_id, sample.expected_value), result); - auto rows = result.read_all(); + auto rows = result.read_all(use_views); // Validate the returned value BOOST_TEST_REQUIRE(rows.size() == 1u); diff --git a/test/integration/utils/src/async_callback.cpp b/test/integration/utils/src/async_callback.cpp index 89217ff2..b3997e6a 100644 --- a/test/integration/utils/src/async_callback.cpp +++ b/test/integration/utils/src/async_callback.cpp @@ -15,6 +15,7 @@ #include #include #include +#include #include #include @@ -37,6 +38,7 @@ using boost::mysql::field_view; using boost::mysql::handshake_params; using boost::mysql::row_view; using boost::mysql::rows_view; +using boost::mysql::use_views; namespace { @@ -78,19 +80,19 @@ public: network_result read_one() override { return impl([&](handler h, error_info& info) { - return this->obj().async_read_one(info, std::move(h)); + return this->obj().async_read_one(use_views, info, std::move(h)); }); } network_result read_some() override { return impl([&](handler h, error_info& info) { - return this->obj().async_read_some(info, std::move(h)); + return this->obj().async_read_some(use_views, info, std::move(h)); }); } network_result read_all() override { return impl([&](handler h, error_info& info) { - return this->obj().async_read_all(info, std::move(h)); + return this->obj().async_read_all(use_views, info, std::move(h)); }); } }; diff --git a/test/integration/utils/src/async_callback_noerrinfo.cpp b/test/integration/utils/src/async_callback_noerrinfo.cpp index 66b884c3..4071b14f 100644 --- a/test/integration/utils/src/async_callback_noerrinfo.cpp +++ b/test/integration/utils/src/async_callback_noerrinfo.cpp @@ -15,6 +15,7 @@ #include #include #include +#include #include @@ -35,6 +36,7 @@ using boost::mysql::field_view; using boost::mysql::handshake_params; using boost::mysql::row_view; using boost::mysql::rows_view; +using boost::mysql::use_views; namespace { @@ -75,19 +77,19 @@ public: network_result read_one() override { return impl([&](handler h) { - return this->obj().async_read_one(std::move(h)); + return this->obj().async_read_one(use_views, std::move(h)); }); } network_result read_some() override { return impl([&](handler h) { - return this->obj().async_read_some(std::move(h)); + return this->obj().async_read_some(use_views, std::move(h)); }); } network_result read_all() override { return impl([&](handler h) { - return this->obj().async_read_all(std::move(h)); + return this->obj().async_read_all(use_views, std::move(h)); }); } }; diff --git a/test/integration/utils/src/async_coroutine.cpp b/test/integration/utils/src/async_coroutine.cpp index 09e343f6..da779331 100644 --- a/test/integration/utils/src/async_coroutine.cpp +++ b/test/integration/utils/src/async_coroutine.cpp @@ -38,6 +38,7 @@ using boost::mysql::field_view; using boost::mysql::handshake_params; using boost::mysql::row_view; using boost::mysql::rows_view; +using boost::mysql::use_views; namespace { @@ -69,19 +70,19 @@ public: network_result read_one() override { return impl(this->obj(), [&](boost::asio::yield_context yield, error_info& info) { - return this->obj().async_read_one(info, yield); + return this->obj().async_read_one(use_views, info, yield); }); } network_result read_some() override { return impl(this->obj(), [&](boost::asio::yield_context yield, error_info& info) { - return this->obj().async_read_some(info, yield); + return this->obj().async_read_some(use_views, info, yield); }); } network_result read_all() override { return impl(this->obj(), [&](boost::asio::yield_context yield, error_info& info) { - return this->obj().async_read_all(info, yield); + return this->obj().async_read_all(use_views, info, yield); }); } }; diff --git a/test/integration/utils/src/async_coroutinecpp20.cpp b/test/integration/utils/src/async_coroutinecpp20.cpp index 7398909d..225073b2 100644 --- a/test/integration/utils/src/async_coroutinecpp20.cpp +++ b/test/integration/utils/src/async_coroutinecpp20.cpp @@ -16,6 +16,7 @@ #include #include #include +#include #include #include @@ -41,6 +42,7 @@ using boost::mysql::field_view; using boost::mysql::handshake_params; using boost::mysql::row_view; using boost::mysql::rows_view; +using boost::mysql::use_views; #ifdef BOOST_ASIO_HAS_CO_AWAIT @@ -108,19 +110,19 @@ public: network_result read_one() override { return impl(this->obj(), [&](error_info& info) { - return this->obj().async_read_one(info, boost::asio::use_awaitable); + return this->obj().async_read_one(use_views, info, boost::asio::use_awaitable); }); } network_result read_some() override { return impl(this->obj(), [&](error_info& info) { - return this->obj().async_read_some(info, boost::asio::use_awaitable); + return this->obj().async_read_some(use_views, info, boost::asio::use_awaitable); }); } network_result read_all() override { return impl(this->obj(), [&](error_info& info) { - return this->obj().async_read_all(info, boost::asio::use_awaitable); + return this->obj().async_read_all(use_views, info, boost::asio::use_awaitable); }); } }; diff --git a/test/integration/utils/src/async_future.cpp b/test/integration/utils/src/async_future.cpp index eea62bed..b227faab 100644 --- a/test/integration/utils/src/async_future.cpp +++ b/test/integration/utils/src/async_future.cpp @@ -15,6 +15,7 @@ #include #include #include +#include #include @@ -36,6 +37,7 @@ using boost::mysql::field_view; using boost::mysql::handshake_params; using boost::mysql::row_view; using boost::mysql::rows_view; +using boost::mysql::use_views; namespace { @@ -79,19 +81,19 @@ public: network_result read_one() override { return impl([&](error_info& output_info) { - return this->obj().async_read_one(output_info, boost::asio::use_future); + return this->obj().async_read_one(use_views, output_info, boost::asio::use_future); }); } network_result read_some() override { return impl([&](error_info& output_info) { - return this->obj().async_read_some(output_info, boost::asio::use_future); + return this->obj().async_read_some(use_views, output_info, boost::asio::use_future); }); } network_result read_all() override { return impl([&](error_info& output_info) { - return this->obj().async_read_all(output_info, boost::asio::use_future); + return this->obj().async_read_all(use_views, output_info, boost::asio::use_future); }); } }; diff --git a/test/integration/utils/src/default_completion_tokens.cpp b/test/integration/utils/src/default_completion_tokens.cpp index c206bbcc..80c1ba28 100644 --- a/test/integration/utils/src/default_completion_tokens.cpp +++ b/test/integration/utils/src/default_completion_tokens.cpp @@ -36,6 +36,7 @@ using boost::mysql::field_view; using boost::mysql::handshake_params; using boost::mysql::row_view; using boost::mysql::rows_view; +using boost::mysql::use_views; namespace { @@ -75,15 +76,15 @@ class default_completion_tokens_resultset : public er_resultset_base public: network_result read_one() override { - return impl([&] { return this->obj().async_read_one(); }); + return impl([&] { return this->obj().async_read_one(use_views); }); } network_result read_some() override { - return impl([&] { return this->obj().async_read_some(); }); + return impl([&] { return this->obj().async_read_some(use_views); }); } network_result read_all() override { - return impl([&] { return this->obj().async_read_all(); }); + return impl([&] { return this->obj().async_read_all(use_views); }); } }; diff --git a/test/integration/utils/src/sync_errc.cpp b/test/integration/utils/src/sync_errc.cpp index 4e4fc8c2..9ae77b3e 100644 --- a/test/integration/utils/src/sync_errc.cpp +++ b/test/integration/utils/src/sync_errc.cpp @@ -17,6 +17,7 @@ #include #include #include +#include #include @@ -38,6 +39,7 @@ using boost::mysql::field_view; using boost::mysql::handshake_params; using boost::mysql::row_view; using boost::mysql::rows_view; +using boost::mysql::use_views; namespace { @@ -63,19 +65,19 @@ public: network_result read_one() override { return impl([&](error_code& code, error_info& info) { - return this->obj().read_one(code, info); + return this->obj().read_one(use_views, code, info); }); } network_result read_some() override { return impl([&](error_code& code, error_info& info) { - return this->obj().read_some(code, info); + return this->obj().read_some(use_views, code, info); }); } network_result read_all() override { return impl([&](error_code& code, error_info& info) { - return this->obj().read_all(code, info); + return this->obj().read_all(use_views, code, info); }); } }; diff --git a/test/integration/utils/src/sync_exc.cpp b/test/integration/utils/src/sync_exc.cpp index ab9cba9d..1811136c 100644 --- a/test/integration/utils/src/sync_exc.cpp +++ b/test/integration/utils/src/sync_exc.cpp @@ -15,6 +15,7 @@ #include #include #include +#include #include @@ -35,6 +36,7 @@ using boost::mysql::field_view; using boost::mysql::handshake_params; using boost::mysql::row_view; using boost::mysql::rows_view; +using boost::mysql::use_views; namespace { @@ -63,15 +65,15 @@ class sync_exc_resultset : public er_resultset_base public: network_result read_one() override { - return impl([&] { return this->obj().read_one(); }); + return impl([&] { return this->obj().read_one(use_views); }); } network_result read_some() override { - return impl([&] { return this->obj().read_some(); }); + return impl([&] { return this->obj().read_some(use_views); }); } network_result read_all() override { - return impl([&] { return this->obj().read_all(); }); + return impl([&] { return this->obj().read_all(use_views); }); } };