Files
MaxScale/maxscale-system-test/bug694.cpp
Markus Mäkelä d11c78ad80 Format all sources with Uncrustify
Formatted all sources and manually tuned some files to make the code look
neater.
2018-09-10 13:22:49 +03:00

102 lines
4.0 KiB
C++

/**
* @file bug694.cpp - regression test for bug694 ("RWSplit: SELECT @a:=@a+1 as a, test.b FROM test breaks
* client session")
*
* - set use_sql_variables_in=all in MaxScale.cnf
* - connect to readwritesplit router and execute:
* @verbatim
* CREATE TABLE test (b integer);
* SELECT @a:=@a+1 as a, test.b FROM test;
* USE test
* @endverbatim
* - check if MaxScale alive
*/
/*
*
* Description Vilho Raatikka 2015-01-14 08:09:45 UTC
* Reproduce:
* - set use_sql_variables_in=all in MaxScale.cnf
* - connect to readwritesplit router and execute:
* CREATE TABLE test (b integer);
* SELECT @a:=@a+1 as a, test.b FROM test;
* USE test
*
* You'll get:
* ERROR 2006 (HY000): MySQL server has gone away
*
* It is a known limitation that SELÈCTs with SQL variable modifications are not supported. The issue is that
* they aren't detected and as a consequence hte client session is disconnected.
*
* It is possible to detect this kind of query in query classifier, but set_query_type loses part of the
* information. If both SELECT and SQL variable update are detected they can be stored in query type and
* rwsplit could, for example, prevent from executing the query, execute it in master only (and log), force
* all SQL variable modifications from that point to master (and log), etc.
* Comment 1 Vilho Raatikka 2015-01-15 13:19:18 UTC
* query_classifier.cc: set_query_type lost previous query type if the new was more restrictive. Problem was
* that if query is both READ and SESSION_WRITE and configuration parameter use_sql_variables_in=all was set,
* routing target became ambiguous. Replaced call to set_query_type with simply adding new type to type (=bit
* field) and checking unsupported combinations in readwritesplit.c:get_route_target. If such a case is met, a
* detailed error is written to error log in readwritesplit.c. mysql_client.c sees the error code and sends an
* error to client. Then mysql_client.c calls router's handleError which ensures that there are enough backend
* servers so that the session can continue.
*/
#include <iostream>
#include "testconnections.h"
#include "mariadb_func.h"
int main(int argc, char* argv[])
{
TestConnections* Test = new TestConnections(argc, argv);
Test->set_timeout(120);
Test->maxscales->connect_maxscale(0);
Test->try_query(Test->maxscales->conn_rwsplit[0], "USE test");
Test->try_query(Test->maxscales->conn_rwsplit[0], "DROP TABLE IF EXISTS test");
Test->try_query(Test->maxscales->conn_rwsplit[0], "CREATE TABLE test (b integer)");
const int iter = Test->smoke ? 10 : 100;
Test->tprintf("Creating and inserting %d rows into a table\n", iter);
for (int i = 0; i < iter; i++)
{
Test->set_timeout(30);
execute_query(Test->maxscales->conn_rwsplit[0], "insert into test value(2);");
Test->stop_timeout();
}
Test->set_timeout(200);
Test->tprintf("Trying SELECT @a:=@a+1 as a, test.b FROM test\n");
if (execute_query(Test->maxscales->conn_rwsplit[0], "SELECT @a:=@a+1 as a, test.b FROM test;") == 0)
{
Test->add_result(1, "Query succeded, but expected to fail.\n");
}
Test->tprintf("Trying USE test\n");
Test->try_query(Test->maxscales->conn_rwsplit[0], "USE test");
Test->try_query(Test->maxscales->conn_rwsplit[0], "DROP TABLE IF EXISTS test");
Test->tprintf("Checking if MaxScale alive\n");
Test->maxscales->close_maxscale_connections(0);
Test->tprintf("Checking logs\n");
Test->check_log_err(0,
(char*)
"The query can't be routed to all backend servers because it includes SELECT and SQL variable modifications which is not supported",
true);
Test->check_log_err(0,
(char*)
"SELECT with session data modification is not supported if configuration parameter use_sql_variables_in=all",
true);
Test->check_maxscale_alive(0);
int rval = Test->global_result;
delete Test;
return rval;
}