Files
MaxScale/maxscale-system-test/mxs1787_slave_reconnection.cpp
Markus Mäkelä 7a354bb28e Add slave reconnection regression test
After a session command fails on all connected slaves but succeeds on the
master, the servers that failed are discarded from the pool of valid
servers. If there are available servers, they will be taken into use when
the next read query is performed.

When a query is routed to an unconnected slave, it is taken into use and
the session command history is replayed. If the execution of the history
failed and there were more session commands to be executed, any queued
queries would get lost. This is due to a missing check that would detect
the fact that the server has been discarded.
2018-06-18 14:25:05 +03:00

82 lines
2.6 KiB
C++

/**
* MXS-1787: Crash with PS: CALL p1((SELECT f1()), ?)
*
* This is a modified version of the original test that revealed secondary problems in
* readwritesplit slave reconnection and execution of session commands.
*/
#include "testconnections.h"
using namespace std;
struct Bind
{
Bind()
{
bind.buffer = &data;
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;
uint32_t data = 1234;
unsigned long length = sizeof(data);
};
int main(int argc, char* argv[])
{
TestConnections test(argc, argv);
test.maxscales->ssh_node_f(0, true, "maxadmin enable log-priority info");
test.maxscales->connect();
execute_query(test.maxscales->conn_rwsplit[0], "USE test");
// Make sure the slaves don't have the procedure
execute_query(test.maxscales->conn_rwsplit[0], "DROP TABLE IF EXISTS t1");
execute_query(test.maxscales->conn_rwsplit[0], "DROP FUNCTION IF EXISTS f1");
execute_query(test.maxscales->conn_rwsplit[0], "DROP PROCEDURE IF EXISTS p1");
// Disable binary log and create the tables
execute_query(test.maxscales->conn_rwsplit[0], "SET sql_log_bin = 0");
execute_query(test.maxscales->conn_rwsplit[0], "CREATE OR REPLACE TABLE t1 AS SELECT 1 AS id");
execute_query(test.maxscales->conn_rwsplit[0],
"CREATE OR REPLACE FUNCTION f1() RETURNS INT DETERMINISTIC BEGIN RETURN 1; END");
execute_query(test.maxscales->conn_rwsplit[0],
"CREATE OR REPLACE PROCEDURE p1(IN i INT, IN j INT) BEGIN SELECT i + j; END");
execute_query(test.maxscales->conn_rwsplit[0], "SET sql_log_bin = 1");
test.maxscales->disconnect();
for (int i = 0; i < 10; i++)
{
test.maxscales->connect();
MYSQL_STMT* stmt = mysql_stmt_init(test.maxscales->conn_rwsplit[0]);
std::string query = "CALL p1((SELECT f1()), ?)";
Bind bind;
test.set_timeout(30);
test.assert(mysql_stmt_prepare(stmt, query.c_str(), query.size()) == 0,
"Prepared statement failure: %s", mysql_stmt_error(stmt));
test.assert(mysql_stmt_bind_param(stmt, &bind.bind) == 0,
"Bind failure: %s", mysql_stmt_error(stmt));
test.assert(mysql_stmt_execute(stmt) == 0,
"Execute failure: %s", mysql_stmt_error(stmt));
mysql_stmt_close(stmt);
test.assert(mysql_query(test.maxscales->conn_rwsplit[0], "SELECT 1") == 0, "Normal queries should work");
test.maxscales->disconnect();
}
return test.global_result;
}