/** * @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 #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->maxscales->connect_maxscale(0); 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->maxscales->conn_rwsplit[0], (char *) "DROP TABLE IF EXISTS t2;"); Test->try_query(Test->maxscales->conn_rwsplit[0], (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->maxscales->conn_rwsplit[0], (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->maxscales->conn_rwsplit[0], sel1, "last_insert_id()", &last_insert_id1[0]) != 0 ) || ( find_field( Test->maxscales->conn_rwsplit[0], 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->maxscales->conn_rwsplit[0], "insert into t2 (x) values (%d);", i), "Query failed"); sprintf(str1, "select * from t2 where x=%d;", i); find_field(Test->maxscales->conn_rwsplit[0], sel1, "last_insert_id()", &last_insert_id1[0]); find_field(Test->maxscales->conn_rwsplit[0], 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->maxscales->conn_rwsplit[0], 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(0); int rval = Test->global_result; delete Test; return rval; }