#include "testconnections.h" #include #include #include using namespace std; struct Bind { Bind() { bind.buffer = buffer; bind.buffer_type = MYSQL_TYPE_LONG; bind.error = &err; bind.is_null = &is_null; bind.length = &length; } MYSQL_BIND bind; char err = 0; char is_null = 0; char is_unsigned = 0; uint8_t buffer[1024]; unsigned long length = 0; }; struct TestCase { std::string name; std::function func; }; void run_test(TestConnections& test, TestCase test_case) { test.maxscales->connect(); MYSQL_STMT* stmt = mysql_stmt_init(test.maxscales->conn_rwsplit[0]); std::string query = "SELECT * FROM test.t1"; unsigned long cursor_type = CURSOR_TYPE_READ_ONLY; mysql_stmt_attr_set(stmt, STMT_ATTR_CURSOR_TYPE, &cursor_type); Bind bind; test.set_timeout(30); if (mysql_stmt_prepare(stmt, query.c_str(), query.size())) { test.assert(false, "Prepared statement failure: %s", mysql_stmt_error(stmt)); } cout << test_case.name << endl; test.assert(test_case.func(test.maxscales->conn_rwsplit[0], stmt, bind), "Test '%s' failed", test_case.name.c_str()); mysql_stmt_close(stmt); test.assert(mysql_query(test.maxscales->conn_rwsplit[0], "SELECT 1") == 0, "Normal queries should work"); test.maxscales->disconnect(); } int main(int argc, char* argv[]) { TestConnections test(argc, argv); test.maxscales->connect(); test.try_query(test.maxscales->conn_rwsplit[0], "CREATE OR REPLACE TABLE test.t1(id INT)"); test.try_query(test.maxscales->conn_rwsplit[0], "BEGIN"); for (int i = 0; i < 100; i++) { execute_query(test.maxscales->conn_rwsplit[0], "INSERT INTO test.t1 VALUES (%d)", i); } test.try_query(test.maxscales->conn_rwsplit[0], "COMMIT"); test.maxscales->disconnect(); vector tests = { { "Simple execute and fetch", [](MYSQL * conn, MYSQL_STMT * stmt, Bind & bind) { bool rval = true; if (mysql_stmt_execute(stmt) || mysql_stmt_bind_result(stmt, &bind.bind)) { rval = false; } while (mysql_stmt_fetch(stmt) == 0) { ; } return rval; } }, { "Multiple overlapping executions without fetch", [](MYSQL * conn, MYSQL_STMT * stmt, Bind & bind) { bool rval = true; if (mysql_stmt_execute(stmt) || mysql_stmt_execute(stmt) || mysql_stmt_execute(stmt) || mysql_stmt_execute(stmt) || mysql_stmt_execute(stmt)) { rval = false; } return rval; } }, { "Multiple overlapping executions with fetch", [](MYSQL * conn, MYSQL_STMT * stmt, Bind & bind) { bool rval = true; if (mysql_stmt_execute(stmt) || mysql_stmt_execute(stmt) || mysql_stmt_execute(stmt) || mysql_stmt_execute(stmt) || mysql_stmt_bind_result(stmt, &bind.bind)) { rval = false; } while (mysql_stmt_fetch(stmt) == 0) { ; } return rval; } }, { "Execution of queries while fetching", [](MYSQL * conn, MYSQL_STMT * stmt, Bind & bind) { bool rval = true; if (mysql_stmt_execute(stmt) || mysql_stmt_execute(stmt) || mysql_stmt_execute(stmt) || mysql_stmt_execute(stmt) || mysql_stmt_bind_result(stmt, &bind.bind)) { rval = false; } while (mysql_stmt_fetch(stmt) == 0) { mysql_query(conn, "SELECT 1"); } return rval; } }, { "Multiple overlapping executions and a query", [](MYSQL * conn, MYSQL_STMT * stmt, Bind & bind) { bool rval = true; if (mysql_stmt_execute(stmt) || mysql_stmt_execute(stmt) || mysql_stmt_execute(stmt) || mysql_stmt_execute(stmt) || mysql_stmt_execute(stmt) || mysql_query(conn, "SET @a = 1")) { rval = false; } return rval; } } }; for (auto a : tests) { run_test(test, a); } return test.global_result; }