145 lines
		
	
	
		
			5.4 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			145 lines
		
	
	
		
			5.4 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| /**
 | |
|  * @file bug509.cpp regression case for bug 509 and 507 ( "Referring to a nonexisting server in servers=... doesn't even raise a warning"
 | |
|  * and "rw-split router does not send last_insert_id() to master" )
 | |
|  *
 | |
|  * - "CREATE TABLE t2 (id INT(10) NOT NULL AUTO_INCREMENT, x int,  PRIMARY KEY (id));",
 | |
|  * - do a number of INSERTs first using RWsplit, then directly Galera nodes.
 | |
|  * - do "select @@wsrep_node_address, last_insert_id();" and "select last_insert_id(), @@wsrep_node_address;" and compares results.
 | |
|  * - do "insert into t2 (x) values (i);" 1000 times and compares results of
 | |
|  * "select @@wsrep_node_address, last_insert_id();" and "select last_insert_id(), @@wsrep_node_address;"
 | |
|  *
 | |
|  * Test fails if results are different (after 5 seconds of waiting after last INSERT)
 | |
|  */
 | |
| 
 | |
| /*
 | |
| Kolbe Kegel 2014-09-01 14:48:12 UTC
 | |
| For some reason, the order of terms in the field list of a SELECT statement influences how the rw-split router decides where to send a statement.
 | |
| 
 | |
| mariadb> select @@wsrep_node_address, last_insert_id();
 | |
| +----------------------+------------------+
 | |
| | @@wsrep_node_address | last_insert_id() |
 | |
| +----------------------+------------------+
 | |
| | 192.168.30.31        |                7 |
 | |
| +----------------------+------------------+
 | |
| 1 row in set (0.00 sec)
 | |
| 
 | |
| mariadb> select last_insert_id(), @@wsrep_node_address;
 | |
| +------------------+----------------------+
 | |
| | last_insert_id() | @@wsrep_node_address |
 | |
| +------------------+----------------------+
 | |
| |                0 | 192.168.30.33        |
 | |
| +------------------+----------------------+
 | |
| 1 row in set (0.00 sec)
 | |
| Comment 1 Vilho Raatikka 2014-09-03 20:44:17 UTC
 | |
| Added code to detect last_insert_id() function and now both types of elements are routed to master and their order of appearance doesn't matter.
 | |
| */
 | |
| 
 | |
| 
 | |
| #include <iostream>
 | |
| #include "testconnections.h"
 | |
| 
 | |
| const char * sel1 = "select @@wsrep_node_address, last_insert_id();";
 | |
| const char * sel2 = "select last_insert_id(), @@wsrep_node_address;";
 | |
| 
 | |
| int main(int argc, char *argv[])
 | |
| {
 | |
|     TestConnections * Test = new TestConnections(argc, argv);
 | |
|     Test->set_timeout(60);
 | |
| 
 | |
|     Test->galera->connect();
 | |
|     Test->connect_maxscale();
 | |
| 
 | |
|     if (Test->galera->N < 3)
 | |
|     {
 | |
|         Test->tprintf("There is not enoght nodes for test\n");
 | |
|         delete Test;
 | |
|         exit(1);
 | |
|     }
 | |
| 
 | |
|     Test->tprintf("Creating table\n");
 | |
|     Test->try_query(Test->conn_rwsplit, (char *) "DROP TABLE IF EXISTS t2;");
 | |
|     Test->try_query(Test->conn_rwsplit,
 | |
|                     (char *) "CREATE TABLE t2 (id INT(10) NOT NULL AUTO_INCREMENT, x int,  PRIMARY KEY (id));");
 | |
|     Test->tprintf("Doing INSERTs\n");
 | |
|     Test->try_query(Test->conn_rwsplit, (char *) "insert into t2 (x) values (1);");
 | |
| 
 | |
|     Test->try_query(Test->galera->nodes[0], (char *) "insert into t2 (x) values (2);");
 | |
|     Test->try_query(Test->galera->nodes[0], (char *) "insert into t2 (x) values (3);");
 | |
| 
 | |
|     Test->try_query(Test->galera->nodes[1], (char *) "insert into t2 (x) values (4);");
 | |
|     Test->try_query(Test->galera->nodes[1], (char *) "insert into t2 (x) values (5);");
 | |
|     Test->try_query(Test->galera->nodes[1], (char *) "insert into t2 (x) values (6);");
 | |
| 
 | |
|     Test->try_query(Test->galera->nodes[2], (char *) "insert into t2 (x) values (7);");
 | |
|     Test->try_query(Test->galera->nodes[2], (char *) "insert into t2 (x) values (8);");
 | |
|     Test->try_query(Test->galera->nodes[2], (char *) "insert into t2 (x) values (9);");
 | |
|     Test->try_query(Test->galera->nodes[2], (char *) "insert into t2 (x) values (10);");
 | |
| 
 | |
|     Test->stop_timeout();
 | |
|     Test->repl->sync_slaves();
 | |
| 
 | |
|     Test->tprintf("Trying \n");
 | |
|     char last_insert_id1[1024];
 | |
|     char last_insert_id2[1024];
 | |
|     if ( (
 | |
|                 find_field(
 | |
|                     Test->conn_rwsplit, sel1,
 | |
|                     "last_insert_id()", &last_insert_id1[0])
 | |
|                 != 0 ) || (
 | |
|                 find_field(
 | |
|                     Test->conn_rwsplit, sel2,
 | |
|                     "last_insert_id()", &last_insert_id2[0])
 | |
|                 != 0 ))
 | |
|     {
 | |
|         Test->tprintf("last_insert_id() fied not found!!\n");
 | |
|         delete Test;
 | |
|         exit(1);
 | |
|     }
 | |
|     else
 | |
|     {
 | |
|         Test->tprintf("'%s' gave last_insert_id() %s\n", sel1, last_insert_id1);
 | |
|         Test->tprintf("'%s' gave last_insert_id() %s\n", sel2, last_insert_id2);
 | |
|         Test->add_result(strcmp(last_insert_id1, last_insert_id2),
 | |
|                          "last_insert_id() are different depending in which order terms are in SELECT\n");
 | |
|     }
 | |
| 
 | |
|     char id_str[1024];
 | |
|     char str1[1024];
 | |
|     int iterations = 150;
 | |
| 
 | |
|     for (int i = 100; i < iterations; i++)
 | |
|     {
 | |
|         Test->set_timeout(50);
 | |
|         Test->add_result(execute_query(Test->conn_rwsplit, "insert into t2 (x) values (%d);", i), "Query failed");
 | |
| 
 | |
|         sprintf(str1, "select * from t2 where x=%d;", i);
 | |
| 
 | |
|         find_field(Test->conn_rwsplit, sel1, "last_insert_id()", &last_insert_id1[0]);
 | |
|         find_field(Test->conn_rwsplit, str1, "id", &id_str[0]);
 | |
| 
 | |
|         int n = 0;
 | |
| 
 | |
|         while (strcmp(last_insert_id1, id_str) != 0 && n < 5)
 | |
|         {
 | |
|             Test->tprintf("Replication is lagging");
 | |
|             sleep(1);
 | |
|             find_field(Test->conn_rwsplit, str1, "id", &id_str[0]);
 | |
|             n++;
 | |
|         }
 | |
| 
 | |
|         Test->add_result(strcmp(last_insert_id1, id_str),
 | |
|                          "last_insert_id is not equal to id even after waiting 5 seconds");
 | |
| 
 | |
|         if (i % 10 == 0)
 | |
|         {
 | |
|             Test->tprintf("last_insert_id is %s, id is %s", last_insert_id1, id_str);
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     Test->check_maxscale_alive();
 | |
| 
 | |
|     int rval = Test->global_result;
 | |
|     delete Test;
 | |
|     return rval;
 | |
| }
 | 
