MXS-1808: Only store SQL statements for retrying
Only commands that can contain an SQL statements should be stored for retrying (COM_QUERY and COM_EXECUTE). Other commands are either session commands or do not work with query retrying.
This commit is contained in:
		@ -648,6 +648,10 @@ add_test_executable(mxs1786_statistics.cpp mxs1786_statistics replication LABELS
 | 
			
		||||
# https://jira.mariadb.org/browse/MXS-1787
 | 
			
		||||
add_test_executable(mxs1787_call_ps.cpp mxs1787_call_ps replication LABELS readwritesplit REPL_BACKEND)
 | 
			
		||||
 | 
			
		||||
# MXS-1808: Crash with mysql_stmt_send_long_data
 | 
			
		||||
# https://jira.mariadb.org/browse/MXS-1808
 | 
			
		||||
add_test_executable(mxs1808_long_data.cpp mxs1808_long_data replication LABELS readwritesplit REPL_BACKEND)
 | 
			
		||||
 | 
			
		||||
# 'namedserverfilter' test
 | 
			
		||||
add_test_executable(namedserverfilter.cpp namedserverfilter namedserverfilter LABELS namedserverfilter LIGHT REPL_BACKEND)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										86
									
								
								maxscale-system-test/mxs1808_long_data.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										86
									
								
								maxscale-system-test/mxs1808_long_data.cpp
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,86 @@
 | 
			
		||||
#include "testconnections.h"
 | 
			
		||||
#include <iostream>
 | 
			
		||||
 | 
			
		||||
using namespace std;
 | 
			
		||||
 | 
			
		||||
void print_stmt_error(MYSQL_STMT *stmt, const char* msg)
 | 
			
		||||
{
 | 
			
		||||
    cout << "Error: " << msg << ": " << mysql_stmt_error(stmt) << endl;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int test_long_data(MYSQL *conn, int sqlsize)
 | 
			
		||||
{
 | 
			
		||||
    int data1size = sqlsize / 2;
 | 
			
		||||
 | 
			
		||||
    char * data1 = (char*) malloc(data1size);
 | 
			
		||||
    memset(data1, 97, data1size);
 | 
			
		||||
    char * data3 = (char*) malloc(sqlsize);
 | 
			
		||||
    memset(data3, 99, sqlsize);
 | 
			
		||||
 | 
			
		||||
    MYSQL_STMT *stmt;
 | 
			
		||||
    stmt = mysql_stmt_init(conn);
 | 
			
		||||
    int        rc, int_data;
 | 
			
		||||
    MYSQL_RES  *result;
 | 
			
		||||
    MYSQL_BIND my_bind[1];
 | 
			
		||||
 | 
			
		||||
    rc = mysql_autocommit(conn, 1);
 | 
			
		||||
 | 
			
		||||
    if (NULL == stmt)
 | 
			
		||||
    {
 | 
			
		||||
        fprintf(stderr, "%s", mysql_error(conn));
 | 
			
		||||
        return 0;
 | 
			
		||||
    }
 | 
			
		||||
    if (mysql_stmt_prepare(stmt, "select ?", strlen("select ?")) != 0)
 | 
			
		||||
    {
 | 
			
		||||
        print_stmt_error(stmt, "stmt prepare fail");
 | 
			
		||||
        return 0;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    memset((char*) my_bind, 0, sizeof(my_bind));
 | 
			
		||||
 | 
			
		||||
    my_bind[0].buffer = (void *)&int_data;
 | 
			
		||||
    my_bind[0].buffer_type = MYSQL_TYPE_STRING;
 | 
			
		||||
 | 
			
		||||
    if (mysql_stmt_bind_param(stmt, my_bind) != 0)
 | 
			
		||||
    {
 | 
			
		||||
        print_stmt_error(stmt, "bind param error");
 | 
			
		||||
        return 0;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* supply data in pieces */
 | 
			
		||||
    if (mysql_stmt_send_long_data(stmt, 0, data1, data1size) != 0)
 | 
			
		||||
    {
 | 
			
		||||
        print_stmt_error(stmt, "send long data1 failed");
 | 
			
		||||
        return 0;
 | 
			
		||||
    }
 | 
			
		||||
    if (mysql_stmt_send_long_data(stmt, 0, data3, sqlsize) != 0)
 | 
			
		||||
    {
 | 
			
		||||
        print_stmt_error(stmt, "send long data3 failed");
 | 
			
		||||
        return 0;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* execute */
 | 
			
		||||
    if (mysql_stmt_execute(stmt) != 0)
 | 
			
		||||
    {
 | 
			
		||||
        print_stmt_error(stmt, "execute prepare stmt failed");
 | 
			
		||||
        return 0;
 | 
			
		||||
    }
 | 
			
		||||
    /* get the result */
 | 
			
		||||
    result = mysql_store_result(conn);
 | 
			
		||||
    mysql_free_result(result);
 | 
			
		||||
    mysql_stmt_close(stmt);
 | 
			
		||||
    free(data1);
 | 
			
		||||
    free(data3);
 | 
			
		||||
    return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int main(int argc, char** argv)
 | 
			
		||||
{
 | 
			
		||||
    TestConnections test(argc, argv);
 | 
			
		||||
 | 
			
		||||
    test.maxscales->connect();
 | 
			
		||||
    test.assert(test_long_data(test.maxscales->conn_rwsplit[0], 123456), "Test should work");
 | 
			
		||||
    test.maxscales->disconnect();
 | 
			
		||||
 | 
			
		||||
    return test.global_result;
 | 
			
		||||
}
 | 
			
		||||
@ -242,7 +242,13 @@ bool route_single_stmt(RWSplit *inst, RWSplitSession *rses, GWBUF *querybuf, con
 | 
			
		||||
            if ((target = handle_slave_is_target(inst, rses, command, stmt_id)))
 | 
			
		||||
            {
 | 
			
		||||
                succp = true;
 | 
			
		||||
                store_stmt = rses->rses_config.retry_failed_reads;
 | 
			
		||||
 | 
			
		||||
                if (rses->rses_config.retry_failed_reads &&
 | 
			
		||||
                    (command == MXS_COM_QUERY || command == MXS_COM_STMT_EXECUTE))
 | 
			
		||||
                {
 | 
			
		||||
                    // Only commands that can contain an SQL statement should be stored
 | 
			
		||||
                    store_stmt = true;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        else if (TARGET_IS_MASTER(route_target))
 | 
			
		||||
 | 
			
		||||
		Reference in New Issue
	
	Block a user