133 lines
		
	
	
		
			3.9 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			133 lines
		
	
	
		
			3.9 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
/**
 | 
						|
 * @file bug507.cpp regression case for bug 507 ( "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 INSERT using RWsplit
 | 
						|
 * - do "select last_insert_id(), @@server_id" using RWSplit and directly to Master, compare @@server_id
 | 
						|
 *
 | 
						|
 */
 | 
						|
 | 
						|
/*
 | 
						|
 *  Kolbe Kegel 2014-09-01 14:45:56 UTC
 | 
						|
 *  After inserting a row via the rw-split router, a call to last_insert_id() can go to a slave, producing bad
 | 
						|
 * results.
 | 
						|
 *
 | 
						|
 *  mariadb> select * from t1;
 | 
						|
 +----+
 | 
						|
 | id |
 | 
						|
 +----+
 | 
						|
 |  1 |
 | 
						|
 |  4 |
 | 
						|
 +----+
 | 
						|
 |  2 rows in set (0.00 sec)
 | 
						|
 |
 | 
						|
 |  mariadb> insert into t1 values ();
 | 
						|
 |  Query OK, 1 row affected (0.00 sec)
 | 
						|
 |
 | 
						|
 |  mariadb> select * from t1;
 | 
						|
 +----+
 | 
						|
 | id |
 | 
						|
 +----+
 | 
						|
 |  1 |
 | 
						|
 |  4 |
 | 
						|
 |  7 |
 | 
						|
 +----+
 | 
						|
 |  3 rows in set (0.00 sec)
 | 
						|
 |
 | 
						|
 |  mariadb> select last_insert_id();
 | 
						|
 +------------------+
 | 
						|
 | last_insert_id() |
 | 
						|
 +------------------+
 | 
						|
 |                0 |
 | 
						|
 +------------------+
 | 
						|
 |  1 row in set (0.00 sec)
 | 
						|
 |
 | 
						|
 |  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)
 | 
						|
 |  Comment 1 Vilho Raatikka 2014-09-01 17:51:45 UTC
 | 
						|
 |  last_inserted_id() belongs to UNKNOWN_FUNC class to which many read-only system functions belong too. Thus
 | 
						|
 |last_inserted_id() was routed to any slave.
 | 
						|
 |
 | 
						|
 |  Unfortunately I can't confirm wrong behavior since running the same sequence generates same output when
 | 
						|
 |connected directly to MariaDB backend. Perhaps there is something required for the table t1 which is not
 | 
						|
 |included here?
 | 
						|
 |  Comment 2 Vilho Raatikka 2014-09-01 20:01:35 UTC
 | 
						|
 |  An autoincrement attribute was missing.
 | 
						|
 */
 | 
						|
 | 
						|
 | 
						|
#include <iostream>
 | 
						|
#include "testconnections.h"
 | 
						|
 | 
						|
const char* sel1 = "select last_insert_id(), @@server_id";
 | 
						|
 | 
						|
int main(int argc, char* argv[])
 | 
						|
{
 | 
						|
    TestConnections* Test = new TestConnections(argc, argv);
 | 
						|
    Test->set_timeout(60);
 | 
						|
 | 
						|
    Test->repl->connect();
 | 
						|
    Test->maxscales->connect_maxscale(0);
 | 
						|
 | 
						|
    if (Test->repl->N < 3)
 | 
						|
    {
 | 
						|
        Test->tprintf("There is not enoght nodes for test\n");
 | 
						|
        delete Test;
 | 
						|
        exit(1);
 | 
						|
    }
 | 
						|
 | 
						|
    Test->tprintf("Creating table\n");
 | 
						|
    fflush(stdout);
 | 
						|
    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");
 | 
						|
    fflush(stdout);
 | 
						|
    Test->try_query(Test->maxscales->conn_rwsplit[0], (char*) "insert into t2 (x) values (1);");
 | 
						|
 | 
						|
    Test->stop_timeout();
 | 
						|
    Test->repl->sync_slaves();
 | 
						|
 | 
						|
    Test->set_timeout(20);
 | 
						|
    Test->tprintf("Trying \n");
 | 
						|
    char last_insert_id1[1024];
 | 
						|
    char last_insert_id2[1024];
 | 
						|
    if ((
 | 
						|
            find_field(Test->maxscales->conn_rwsplit[0],
 | 
						|
                       sel1,
 | 
						|
                       "@@server_id",
 | 
						|
                       &last_insert_id1[0])
 | 
						|
            != 0 ) || (
 | 
						|
            find_field(Test->repl->nodes[0],
 | 
						|
                       sel1,
 | 
						|
                       "@@server_id",
 | 
						|
                       &last_insert_id2[0])
 | 
						|
            != 0 ))
 | 
						|
    {
 | 
						|
        Test->tprintf("@@server_id fied not found!!\n");
 | 
						|
        delete Test;
 | 
						|
        exit(1);
 | 
						|
    }
 | 
						|
    else
 | 
						|
    {
 | 
						|
        Test->tprintf("'%s' to RWSplit gave @@server_id %s\n", sel1, last_insert_id1);
 | 
						|
        Test->tprintf("'%s' directly to master gave @@server_id %s\n", sel1, 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");
 | 
						|
    }
 | 
						|
 | 
						|
    Test->maxscales->close_maxscale_connections(0);
 | 
						|
    Test->repl->close_connections();
 | 
						|
 | 
						|
    Test->check_maxscale_alive(0);
 | 
						|
 | 
						|
    int rval = Test->global_result;
 | 
						|
    delete Test;
 | 
						|
    return rval;
 | 
						|
}
 |