From 14692cd70cca9f7db2ed2c0fd71bcaac1f78c46d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Markus=20M=C3=A4kel=C3=A4?= Date: Mon, 26 Jun 2017 21:51:41 +0300 Subject: [PATCH] MXS-852: Expand binary PS cursor test The test now tests that read-write splitting works both inside and outside transactions. --- maxscale-system-test/binary_ps_cursor.cpp | 118 +++++++++++++++++----- 1 file changed, 94 insertions(+), 24 deletions(-) diff --git a/maxscale-system-test/binary_ps_cursor.cpp b/maxscale-system-test/binary_ps_cursor.cpp index 4e6a41ba3..b7eadd753 100644 --- a/maxscale-system-test/binary_ps_cursor.cpp +++ b/maxscale-system-test/binary_ps_cursor.cpp @@ -27,8 +27,8 @@ void test1(TestConnections& test) cout << "Prepare" << endl; test.add_result(mysql_stmt_prepare(stmt, query, strlen(query)), "Failed to prepare"); - unsigned long cursor_type= CURSOR_TYPE_READ_ONLY; - unsigned long rows=0; + unsigned long cursor_type = CURSOR_TYPE_READ_ONLY; + unsigned long rows = 0; test.add_result(mysql_stmt_attr_set(stmt, STMT_ATTR_CURSOR_TYPE, &cursor_type), "Failed to set attributes"); test.add_result(mysql_stmt_attr_set(stmt, STMT_ATTR_PREFETCH_ROWS, &rows), "Failed to set attributes"); @@ -56,13 +56,15 @@ void test2(TestConnections& test) MYSQL_STMT* stmt1 = mysql_stmt_init(conn); MYSQL_STMT* stmt2 = mysql_stmt_init(conn); - const char* query = "SELECT @@server_id"; + const char* query1 = "SELECT @@server_id"; + const char* query2 = "SELECT @@server_id, @@last_insert_id"; char buffer1[100] = ""; char buffer2[100] = ""; + char buffer2_2[100] = ""; my_bool err = false; my_bool isnull = false; MYSQL_BIND bind1[1] = {}; - MYSQL_BIND bind2[1] = {}; + MYSQL_BIND bind2[2] = {}; bind1[0].buffer_length = sizeof(buffer1); bind1[0].buffer = buffer1; @@ -73,49 +75,117 @@ void test2(TestConnections& test) bind2[0].buffer = buffer2; bind2[0].error = &err; bind2[0].is_null = &isnull; + bind2[1].buffer_length = sizeof(buffer2); + bind2[1].buffer = buffer2_2; + bind2[1].error = &err; + bind2[1].is_null = &isnull; - cout << "Prepare" << endl; - test.add_result(mysql_stmt_prepare(stmt1, query, strlen(query)), "Failed to prepare"); - test.add_result(mysql_stmt_prepare(stmt2, query, strlen(query)), "Failed to prepare"); + cout << "First prepare, should go to slave" << endl; + test.add_result(mysql_stmt_prepare(stmt1, query1, strlen(query1)), "Failed to prepare"); - unsigned long cursor_type= CURSOR_TYPE_READ_ONLY; - unsigned long rows=0; + unsigned long cursor_type = CURSOR_TYPE_READ_ONLY; + unsigned long rows = 0; test.add_result(mysql_stmt_attr_set(stmt1, STMT_ATTR_CURSOR_TYPE, &cursor_type), "Failed to set attributes"); test.add_result(mysql_stmt_attr_set(stmt1, STMT_ATTR_PREFETCH_ROWS, &rows), "Failed to set attributes"); + + test.add_result(mysql_stmt_execute(stmt1), "Failed to execute"); + test.add_result(mysql_stmt_bind_result(stmt1, bind1), "Failed to bind result"); + + int rc1 = mysql_stmt_fetch(stmt1); + test.add_result(rc1, "Failed to fetch result: %d %s %s", rc1, mysql_stmt_error(stmt1), mysql_error(conn)); + mysql_stmt_close(stmt1); + + cout << "Second prepare, should go to master" << endl; + test.add_result(mysql_stmt_prepare(stmt2, query2, strlen(query2)), "Failed to prepare"); test.add_result(mysql_stmt_attr_set(stmt2, STMT_ATTR_CURSOR_TYPE, &cursor_type), "Failed to set attributes"); test.add_result(mysql_stmt_attr_set(stmt2, STMT_ATTR_PREFETCH_ROWS, &rows), "Failed to set attributes"); - cout << "Execute" << endl; - test.add_result(mysql_stmt_execute(stmt1), "Failed to execute"); test.add_result(mysql_stmt_execute(stmt2), "Failed to execute"); - cout << "Bind result" << endl; - test.add_result(mysql_stmt_bind_result(stmt1, bind1), "Failed to bind result"); test.add_result(mysql_stmt_bind_result(stmt2, bind2), "Failed to bind result"); - cout << "Fetch row" << endl; - int rc1 = mysql_stmt_fetch(stmt1); + int rc2 = mysql_stmt_fetch(stmt2); - test.add_result(rc1, "Failed to fetch result: %d %s %s", rc1, mysql_stmt_error(stmt1), mysql_error(conn)); test.add_result(rc2, "Failed to fetch result: %d %s %s", rc2, mysql_stmt_error(stmt2), mysql_error(conn)); - - test.add_result(strlen(buffer1) == 0, "Expected result buffer 1 to not be empty"); - test.add_result(strlen(buffer2) == 0, "Expected result buffer 2 to not be empty"); - - cout << "Close statement" << endl; - mysql_stmt_close(stmt1); mysql_stmt_close(stmt2); + + /** Get the master's server_id */ + char server_id[1024]; + test.repl->connect(); + sprintf(server_id, "%d", test.repl->get_server_id(0)); + + test.add_result(strcmp(buffer1, buffer2) == 0, "Expected results to differ"); + test.add_result(strcmp(buffer2, server_id) != 0, + "Expected prepare 2 to go to the master (%s) but it's %s", + server_id[0], buffer2); +} + +void test3(TestConnections& test) +{ + test.connect_maxscale(); + test.set_timeout(20); + + MYSQL_STMT* stmt = mysql_stmt_init(test.conn_rwsplit); + const char* query = "SELECT @@server_id"; + char buffer[100] = ""; + my_bool err = false; + my_bool isnull = false; + MYSQL_BIND bind[1] = {}; + + bind[0].buffer_length = sizeof(buffer); + bind[0].buffer = buffer; + bind[0].error = &err; + bind[0].is_null = &isnull; + + test.add_result(mysql_stmt_prepare(stmt, query, strlen(query)), "Failed to prepare"); + + cout << "Start transaction" << endl; + test.add_result(mysql_query(test.conn_rwsplit, "START TRANSACTION"), + "START TRANSACTION should succeed: %s", + mysql_error(test.conn_rwsplit)); + + + unsigned long cursor_type = CURSOR_TYPE_READ_ONLY; + unsigned long rows = 0; + test.add_result(mysql_stmt_attr_set(stmt, STMT_ATTR_CURSOR_TYPE, &cursor_type), "Failed to set attributes"); + test.add_result(mysql_stmt_attr_set(stmt, STMT_ATTR_PREFETCH_ROWS, &rows), "Failed to set attributes"); + + cout << "Execute" << endl; + test.add_result(mysql_stmt_execute(stmt), "Failed to execute"); + test.add_result(mysql_stmt_bind_result(stmt, bind), "Failed to bind result"); + test.add_result(mysql_stmt_fetch(stmt), "Failed to fetch result"); + + test.add_result(strlen(buffer) == 0, "Expected result buffer to not be empty"); + + cout << "Commit" << endl; + test.add_result(mysql_query(test.conn_rwsplit, "COMMIT"), + "COMMIT should succeed: %s", + mysql_error(test.conn_rwsplit)); + + mysql_stmt_close(stmt); + test.close_maxscale_connections(); + + char server_id[1024]; + test.repl->connect(); + sprintf(server_id, "%d", test.repl->get_server_id(0)); + test.add_result(strcmp(buffer, server_id) != 0, + "Expected the execute inside a transaction to go to the master (%s) but it's %s", + server_id[0], buffer); } int main(int argc, char** argv) { TestConnections test(argc, argv); - cout << "Test 1" << endl; + cout << "Test 1: Testing simple cursor usage" << endl; test1(test); cout << "Done" << endl << endl; - cout << "Test 2" << endl; + cout << "Test 2: Testing read-write splitting with cursors" << endl; test2(test); cout << "Done" << endl << endl; + cout << "Test 3: Testing transactions with cursors" << endl; + test3(test); + cout << "Done" << endl << endl; + return test.global_result; }