diff --git a/include/boost/mysql/detail/network_algorithms/impl/prepare_statement.hpp b/include/boost/mysql/detail/network_algorithms/impl/prepare_statement.hpp index ce010ebd..6ca44b10 100644 --- a/include/boost/mysql/detail/network_algorithms/impl/prepare_statement.hpp +++ b/include/boost/mysql/detail/network_algorithms/impl/prepare_statement.hpp @@ -188,15 +188,21 @@ void boost::mysql::detail::prepare_statement( // We ignore these for now. while (processor.has_remaining_meta()) { + // Read from the stream if necessary if (!channel.has_read_messages()) { channel.read_some(err); if (err) return; } + + // Discard the message channel.next_read_message(channel.shared_sequence_number(), err); if (err) return; + + // Update the processor state + processor.on_meta_received(); } } diff --git a/test/integration/execute_statement.cpp b/test/integration/execute_statement.cpp index 4f766c67..4ddfbe59 100644 --- a/test/integration/execute_statement.cpp +++ b/test/integration/execute_statement.cpp @@ -6,143 +6,151 @@ // #include -#include "er_network_variant.hpp" -#include "integration_test_common.hpp" -#include "tcp_network_fixture.hpp" -#include "streams.hpp" +#include +#include + #include +#include "er_network_variant.hpp" +#include "integration_test_common.hpp" +#include "streams.hpp" +#include "tcp_network_fixture.hpp" +#include "test_common.hpp" + using namespace boost::mysql::test; -using boost::mysql::field_view; -using boost::mysql::error_code; -using boost::mysql::make_execute_params; using boost::mysql::errc; +using boost::mysql::error_code; +using boost::mysql::field_view; +using boost::mysql::make_execute_params; + +namespace { BOOST_AUTO_TEST_SUITE(test_execute_statement) -// Iterator version -BOOST_MYSQL_NETWORK_TEST(iterator_ok_no_params, network_fixture) +BOOST_AUTO_TEST_SUITE(iterator) +BOOST_MYSQL_NETWORK_TEST(ok_no_params, network_fixture) { setup_and_connect(sample.net); // Prepare - auto stmt = conn->prepare_statement("SELECT * FROM empty_table").get(); + conn->prepare_statement("SELECT * FROM empty_table", *stmt).validate_no_error(); // Execute std::forward_list params; - auto result = stmt->execute_params(make_execute_params(params)).get(); - BOOST_TEST(result->valid()); + stmt->execute_params(make_execute_params(params), *result).validate_no_error(); + BOOST_TEST(result->base().valid()); } -BOOST_MYSQL_NETWORK_TEST(iterator_ok_with_params, network_fixture) +BOOST_MYSQL_NETWORK_TEST(ok_with_params, network_fixture) { setup_and_connect(sample.net); // Prepare - auto stmt = conn->prepare_statement("SELECT * FROM empty_table WHERE id IN (?, ?)").get(); + conn->prepare_statement("SELECT * FROM empty_table WHERE id IN (?, ?)", *stmt) + .validate_no_error(); // Execute - std::forward_list params { field_view("item"), field_view(42) }; - auto result = stmt->execute_params(make_execute_params(params)).get(); - BOOST_TEST(result->valid()); + std::forward_list params{field_view("item"), field_view(42)}; + stmt->execute_params(make_execute_params(params), *result).validate_no_error(); + BOOST_TEST(result->base().valid()); } -BOOST_MYSQL_NETWORK_TEST(iterator_mismatched_num_params, network_fixture) +BOOST_MYSQL_NETWORK_TEST(mismatched_num_params, network_fixture) { setup_and_connect(sample.net); // Prepare - auto stmt = conn->prepare_statement("SELECT * FROM empty_table WHERE id IN (?, ?)").get(); - + conn->prepare_statement("SELECT * FROM empty_table WHERE id IN (?, ?)", *stmt) + .validate_no_error(); + // Execute - std::forward_list params { field_view("item") }; - auto result = stmt->execute_params(make_execute_params(params)); - result.validate_error(errc::wrong_num_params, - {"param", "2", "1", "statement", "execute"}); + std::forward_list params{field_view("item")}; + stmt->execute_params(make_execute_params(params), *result) + .validate_error(errc::wrong_num_params, {"param", "2", "1", "statement", "execute"}); } -BOOST_MYSQL_NETWORK_TEST(iterator_server_error, network_fixture) +BOOST_MYSQL_NETWORK_TEST(server_error, network_fixture) { setup_and_connect(sample.net); start_transaction(); // Prepare - auto stmt = conn->prepare_statement("INSERT INTO inserts_table (field_varchar, field_date) VALUES (?, ?)").get(); + conn->prepare_statement( + "INSERT INTO inserts_table (field_varchar, field_date) VALUES (?, ?)", + *stmt + ) + .validate_no_error(); // Execute - std::forward_list params { field_view("f0"), field_view("bad_date") }; - auto result = stmt->execute_params(make_execute_params(params)); - result.validate_error(errc::truncated_wrong_value, - {"field_date", "bad_date", "incorrect date value"}); + std::forward_list params{field_view("f0"), field_view("bad_date")}; + stmt->execute_params(make_execute_params(params), *result) + .validate_error( + errc::truncated_wrong_value, + {"field_date", "bad_date", "incorrect date value"} + ); } +BOOST_AUTO_TEST_SUITE_END() -// Container version -BOOST_MYSQL_NETWORK_TEST(container_ok_no_params, network_fixture) +// collection is a wrapper around execute_params, so only +// a subset of tests are run here +BOOST_AUTO_TEST_SUITE(collection) +BOOST_MYSQL_NETWORK_TEST(ok, network_fixture) { setup_and_connect(sample.net); // Prepare - auto stmt = conn->prepare_statement("SELECT * FROM empty_table").get(); + conn->prepare_statement("SELECT * FROM empty_table WHERE id IN (?, ?)", *stmt) + .validate_no_error(); // Execute - auto result = stmt->execute_container(std::vector()).get(); - BOOST_TEST(result->valid()); + stmt->execute_collection(make_fv_vector("item", 42), *result).validate_no_error(); + BOOST_TEST(result->base().valid()); } -BOOST_MYSQL_NETWORK_TEST(container_ok_with_params, network_fixture) -{ - setup_and_connect(sample.net); - - // Prepare - auto stmt = conn->prepare_statement("SELECT * FROM empty_table WHERE id IN (?, ?)").get(); - auto result = stmt->execute_container(make_value_vector("item", 42)).get(); - BOOST_TEST(result->valid()); -} - -BOOST_MYSQL_NETWORK_TEST(container_mismatched_num_params, network_fixture) -{ - setup_and_connect(sample.net); - - // Prepare - auto stmt = conn->prepare_statement("SELECT * FROM empty_table WHERE id IN (?, ?)").get(); - - // Execute - auto result = stmt->execute_container(make_value_vector("item")); - result.validate_error(errc::wrong_num_params, - {"param", "2", "1", "statement", "execute"}); -} - -BOOST_MYSQL_NETWORK_TEST(container_server_error, network_fixture) +BOOST_MYSQL_NETWORK_TEST(error, network_fixture) { setup_and_connect(sample.net); start_transaction(); // Prepare - auto stmt = conn->prepare_statement("INSERT INTO inserts_table (field_varchar, field_date) VALUES (?, ?)").get(); + conn->prepare_statement( + "INSERT INTO inserts_table (field_varchar, field_date) VALUES (?, ?)", + *stmt + ) + .validate_no_error(); // Execute - auto result = stmt->execute_container(make_value_vector("f0", "bad_date")); - result.validate_error(errc::truncated_wrong_value, - {"field_date", "bad_date", "incorrect date value"}); + stmt->execute_collection(make_fv_vector("f0", "bad_date"), *result) + .validate_error( + errc::truncated_wrong_value, + {"field_date", "bad_date", "incorrect date value"} + ); } // Other containers. We can't use the type-erased functions here BOOST_FIXTURE_TEST_CASE(no_statement_params_variable, tcp_network_fixture) { + boost::mysql::tcp_statement stmt; + boost::mysql::tcp_resultset result; + connect(); - auto stmt = conn.prepare_statement("SELECT * FROM empty_table"); - auto result = stmt.execute(boost::mysql::no_statement_params); + conn.prepare_statement("SELECT * FROM empty_table", stmt); + stmt.execute(boost::mysql::no_statement_params, result); BOOST_TEST(result.valid()); } -BOOST_FIXTURE_TEST_CASE(c_array, tcp_network_fixture) +BOOST_FIXTURE_TEST_CASE(array, tcp_network_fixture) { + boost::mysql::tcp_statement stmt; + boost::mysql::tcp_resultset result; + connect(); - auto stmt = conn.prepare_statement("SELECT * FROM empty_table WHERE id IN (?, ?)"); - field_view arr [] = { field_view("hola"), field_view(10) }; - auto result = stmt.execute(arr); + conn.prepare_statement("SELECT * FROM empty_table WHERE id IN (?, ?)", stmt); + stmt.execute(boost::mysql::make_field_views("hola", 10), result); BOOST_TEST(result.valid()); } +BOOST_AUTO_TEST_SUITE_END() +BOOST_AUTO_TEST_SUITE_END() // test_execute_statement -BOOST_AUTO_TEST_SUITE_END() // test_execute_statement +} // namespace diff --git a/test/integration/prepare_statement.cpp b/test/integration/prepare_statement.cpp index 0f711466..e86dd935 100644 --- a/test/integration/prepare_statement.cpp +++ b/test/integration/prepare_statement.cpp @@ -6,101 +6,88 @@ // #include -#include "integration_test_common.hpp" -#include "tcp_network_fixture.hpp" -#include "streams.hpp" -#include #include +#include +#include + +#include "integration_test_common.hpp" +#include "streams.hpp" +#include "tcp_network_fixture.hpp" + using namespace boost::mysql::test; -using boost::mysql::error_code; using boost::mysql::errc; -using boost::mysql::tcp_prepared_statement; +using boost::mysql::error_code; using boost::mysql::no_statement_params; +using boost::mysql::tcp_resultset; +using boost::mysql::tcp_statement; + +namespace { BOOST_AUTO_TEST_SUITE(test_prepare_statement) BOOST_MYSQL_NETWORK_TEST(ok_no_params, network_fixture) { setup_and_connect(sample.net); - auto stmt = conn->prepare_statement("SELECT * FROM empty_table").get(); - BOOST_TEST_REQUIRE(stmt->valid()); - BOOST_TEST(stmt->id() > 0u); - BOOST_TEST(stmt->num_params() == 0u); + conn->prepare_statement("SELECT * FROM empty_table", *stmt).validate_no_error(); + BOOST_TEST_REQUIRE(stmt->base().valid()); + BOOST_TEST(stmt->base().id() > 0u); + BOOST_TEST(stmt->base().num_params() == 0u); } BOOST_MYSQL_NETWORK_TEST(ok_with_params, network_fixture) { setup_and_connect(sample.net); - auto stmt = conn->prepare_statement("SELECT * FROM empty_table WHERE id IN (?, ?)").get(); - BOOST_TEST_REQUIRE(stmt->valid()); - BOOST_TEST(stmt->id() > 0u); - BOOST_TEST(stmt->num_params() == 2u); + conn->prepare_statement("SELECT * FROM empty_table WHERE id IN (?, ?)", *stmt) + .validate_no_error(); + BOOST_TEST_REQUIRE(stmt->base().valid()); + BOOST_TEST(stmt->base().id() > 0u); + BOOST_TEST(stmt->base().num_params() == 2u); } BOOST_MYSQL_NETWORK_TEST(invalid_statement, network_fixture) { setup_and_connect(sample.net); - auto stmt = conn->prepare_statement("SELECT * FROM bad_table WHERE id IN (?, ?)"); - stmt.validate_error(errc::no_such_table, {"table", "doesn't exist", "bad_table"}); + conn->prepare_statement("SELECT * FROM bad_table WHERE id IN (?, ?)", *stmt) + .validate_error(errc::no_such_table, {"table", "doesn't exist", "bad_table"}); } -// Move operations -BOOST_AUTO_TEST_SUITE(move_operations) - BOOST_FIXTURE_TEST_CASE(move_ctor, tcp_network_fixture) { connect(); // Get a valid prepared statement and perform a move construction - tcp_prepared_statement s1 = conn.prepare_statement("SELECT * FROM empty_table"); - tcp_prepared_statement s2 (std::move(s1)); + tcp_statement s1; + conn.prepare_statement("SELECT * FROM empty_table", s1); - // Validate valid() - BOOST_TEST(!s1.valid()); - BOOST_TEST(s2.valid()); + // Move construct + tcp_statement s2(std::move(s1)); + BOOST_TEST_REQUIRE(s2.valid()); // We can use the 2nd stmt - auto rows = s2.execute(no_statement_params).read_all(); - BOOST_TEST(rows.empty()); + tcp_resultset result; + s2.execute(no_statement_params, result); + BOOST_TEST(result.read_all().empty()); } -BOOST_FIXTURE_TEST_CASE(move_assignment_to_invalid, tcp_network_fixture) +BOOST_FIXTURE_TEST_CASE(move_assignment, tcp_network_fixture) { connect(); // Get a valid resultset_base and perform a move assignment - tcp_prepared_statement s1 = conn.prepare_statement("SELECT * FROM empty_table"); - tcp_prepared_statement s2; - s2 = std::move(s1); + tcp_statement s1, s2; + conn.prepare_statement("SELECT * FROM empty_table", s1); + conn.prepare_statement("SELECT 1", s2); - // Validate valid() - BOOST_TEST(!s1.valid()); - BOOST_TEST(s2.valid()); + s2 = std::move(s1); + BOOST_TEST_REQUIRE(s2.valid()); // We can use the 2nd stmt - auto rows = s2.execute(no_statement_params).read_all(); - BOOST_TEST(rows.empty()); + tcp_resultset result; + s2.execute(no_statement_params, result); + BOOST_TEST(result.read_all().empty()); } -BOOST_FIXTURE_TEST_CASE(move_assignment_to_valid, tcp_network_fixture) -{ - connect(); - - // Get a valid resultset_base and perform a move assignment - tcp_prepared_statement s1 = conn.prepare_statement("SELECT * FROM empty_table"); - tcp_prepared_statement s2 = conn.prepare_statement("SELECT * FROM empty_table WHERE id IN (?, ?)"); - s2 = std::move(s1); +BOOST_AUTO_TEST_SUITE_END() // test_prepare_statement - // Validate valid() - BOOST_TEST(!s1.valid()); - BOOST_TEST(s2.valid()); - - // We can use the 2nd resultset_base - auto rows = s2.execute(no_statement_params).read_all(); - BOOST_TEST(rows.empty()); -} - -BOOST_AUTO_TEST_SUITE_END() // move_operations - -BOOST_AUTO_TEST_SUITE_END() // test_prepare_statement +} // namespace diff --git a/test/integration/query.cpp b/test/integration/query.cpp index bbeb21e4..a3b3401c 100644 --- a/test/integration/query.cpp +++ b/test/integration/query.cpp @@ -22,7 +22,6 @@ BOOST_MYSQL_NETWORK_TEST(insert_ok, network_fixture) start_transaction(); // Issue query - auto result = create_resultset(); conn->query( "INSERT INTO inserts_table (field_varchar, field_date) VALUES ('v0', '2010-10-11')", *result @@ -46,7 +45,6 @@ BOOST_MYSQL_NETWORK_TEST(insert_error, network_fixture) { setup_and_connect(sample.net); start_transaction(); - auto result = create_resultset(); auto netresult = conn->query( "INSERT INTO bad_table (field_varchar, field_date) VALUES ('v0', '2010-10-11')", *result @@ -60,7 +58,6 @@ BOOST_MYSQL_NETWORK_TEST(update_ok, network_fixture) start_transaction(); // Issue the query - auto result = create_resultset(); conn->query("UPDATE updates_table SET field_int = field_int+10", *result).get(); // Validate resultset_base @@ -82,7 +79,6 @@ BOOST_MYSQL_NETWORK_TEST(select_ok, network_fixture) { setup_and_connect(sample.net); - auto result = create_resultset(); conn->query("SELECT * FROM empty_table", *result).get(); BOOST_TEST(result->base().valid()); @@ -93,7 +89,6 @@ BOOST_MYSQL_NETWORK_TEST(select_ok, network_fixture) BOOST_MYSQL_NETWORK_TEST(select_error, network_fixture) { setup_and_connect(sample.net); - auto result = create_resultset(); auto netresult = conn->query("SELECT field_varchar, field_bad FROM one_row_table", *result); netresult.validate_error(errc::bad_field_error, {"unknown column", "field_bad"}); } diff --git a/test/integration/utils/include/integration_test_common.hpp b/test/integration/utils/include/integration_test_common.hpp index f211ad30..10c3cb10 100644 --- a/test/integration/utils/include/integration_test_common.hpp +++ b/test/integration/utils/include/integration_test_common.hpp @@ -41,6 +41,8 @@ struct network_fixture : network_fixture_base { er_network_variant* var{}; er_connection_ptr conn; + er_statement_ptr stmt; + er_resultset_ptr result; boost::asio::executor_work_guard guard; std::thread runner; @@ -56,14 +58,12 @@ struct network_fixture : network_fixture_base runner.join(); } - er_resultset_ptr create_resultset() { return var->create_resultset(); } - - er_statement_ptr create_statement() { return var->create_statement(); } - void setup(er_network_variant* variant) { var = variant; conn = var->create_connection(ctx.get_executor(), ssl_ctx); + stmt = var->create_statement(); + result = var->create_resultset(); } void setup_and_connect(er_network_variant* variant, ssl_mode m = ssl_mode::require) @@ -121,14 +121,12 @@ struct network_fixture : network_fixture_base // make the testing environment more stable and speed up the tests void start_transaction() { - auto result = create_resultset(); conn->query("START TRANSACTION", *result).get(); result->read_all().get(); } std::int64_t get_table_size(const std::string& table) { - auto result = create_resultset(); conn->query("SELECT COUNT(*) FROM " + table, *result).get(); return result->read_all().get().at(0).at(0).as_int64(); }