From 64862325a5514e742b399c7a367f9a9ffa6f2a78 Mon Sep 17 00:00:00 2001 From: Georg Richter Date: Thu, 10 Nov 2016 05:49:11 +0100 Subject: [PATCH] Removed com_multi for mariadb_stmt_execute_direct added support for pre 10.2-servers in mariadb_stmt_execute_direct --- libmariadb/ma_net.c | 31 ++-------------------- libmariadb/mariadb_lib.c | 11 +++----- libmariadb/mariadb_stmt.c | 19 ++++++++++++-- unittest/libmariadb/bulk1.c | 2 +- unittest/libmariadb/features-10_2.c | 40 +++++++++++++++++------------ unittest/libmariadb/ps_bugs.c | 1 - 6 files changed, 47 insertions(+), 57 deletions(-) diff --git a/libmariadb/ma_net.c b/libmariadb/ma_net.c index 068354e3..576561b5 100644 --- a/libmariadb/ma_net.c +++ b/libmariadb/ma_net.c @@ -90,8 +90,6 @@ int ma_net_init(NET *net, MARIADB_PVIO* pvio) printf("Fatal\n"); exit(-1); } - /* We don't allocate memory for multi buffer, since we don't know in advance if the server - * supports COM_MULTI comand. It will be allocated on demand in net_add_multi_command */ max_allowed_packet= net->max_packet_size= MAX(net_buffer_length, max_allowed_packet); net->buff_end=net->buff+(net->max_packet=net_buffer_length); net->pvio = pvio; @@ -583,36 +581,11 @@ ulong ma_net_read(NET *net) int net_add_multi_command(NET *net, uchar command, const uchar *packet, size_t length) { - size_t left_length; - size_t required_length, current_length; - /* 9 - maximum possible length of data stored in net length format */ - required_length= length + 1 + COMP_HEADER_SIZE + NET_HEADER_SIZE + 9; - - /* We didn't allocate memory in ma_net_init since it was too early to - * detect if the server supports COM_MULTI command */ if (net->extension->multi_status == COM_MULTI_OFF) { return(1); } - - left_length= net->buff_end - net->write_pos; - - /* check if our buffer is large enough */ - if (left_length < required_length) - { - current_length= net->write_pos - net->buff; - if (net_realloc(net, current_length + required_length)) - goto error; - net->write_pos = net->buff + current_length; - } - net->write_pos= mysql_net_store_length(net->write_pos, length + 1); - *net->write_pos= command; - net->write_pos++; - memcpy(net->write_pos, packet, length); - net->write_pos+= length; - return 0; - -error: - return 1; + net->compress_pkt_nr= net->pkt_nr= 0; + return ma_net_write_command(net, command, (const char *)packet, length, 1); } diff --git a/libmariadb/mariadb_lib.c b/libmariadb/mariadb_lib.c index f7da9162..4b920525 100644 --- a/libmariadb/mariadb_lib.c +++ b/libmariadb/mariadb_lib.c @@ -407,7 +407,7 @@ mthd_my_send_cmd(MYSQL *mysql,enum enum_server_command command, const char *arg, } result=0; - if (net->extension->multi_status == COM_MULTI_OFF) + if (net->extension->multi_status > COM_MULTI_OFF) skipp_check= 1; if (!skipp_check) @@ -440,19 +440,16 @@ int ma_multi_command(MYSQL *mysql, enum enum_multi_status status) return 1; ma_net_clear(net); net->extension->multi_status= status; - int3store(net->buff, 0); - net->buff[3]= (net->compress) ? 0 : (uchar) (net->pkt_nr++); - net->buff[4]= COM_MULTI; - net->write_pos= net->buff + 5; return 0; case COM_MULTI_END: { size_t len= net->write_pos - net->buff - NET_HEADER_SIZE; if (len < NET_HEADER_SIZE) /* don't send empty COM_MULTI */ + { + ma_net_clear(net); return 1; - /* store length after com_multi */ - int3store(net->buff, len); + } net->extension->multi_status= COM_MULTI_OFF; return ma_net_flush(net); } diff --git a/libmariadb/mariadb_stmt.c b/libmariadb/mariadb_stmt.c index c401b641..28a39dac 100644 --- a/libmariadb/mariadb_stmt.c +++ b/libmariadb/mariadb_stmt.c @@ -466,7 +466,6 @@ int store_param(MYSQL_STMT *stmt, int column, unsigned char **p, unsigned long r case MYSQL_TYPE_LONG: case MYSQL_TYPE_INT24: int4store(*p, (*(int32 *)buf)); - //stmt->params[column].buffer)[row_nr]); (*p)+= 4; break; case MYSQL_TYPE_TIME: @@ -560,7 +559,7 @@ int store_param(MYSQL_STMT *stmt, int column, unsigned char **p, unsigned long r /* to is after p. The latter hasn't been moved */ uchar *to; void *buf= ma_get_buffer_offset(stmt, stmt->params[column].buffer_type, - stmt->params[column].buffer, row_nr); + stmt->params[column].buffer, row_nr); if (stmt->row_size) len= *stmt->params[column].length; @@ -1382,6 +1381,7 @@ int STDCALL mysql_stmt_prepare(MYSQL_STMT *stmt, const char *query, size_t lengt stmt->param_count= 0; stmt->field_count= 0; + stmt->params= 0; int4store(stmt_id, stmt->stmt_id); if (mysql->methods->db_command(mysql, COM_STMT_CLOSE, stmt_id, @@ -2072,6 +2072,8 @@ int STDCALL mariadb_stmt_execute_direct(MYSQL_STMT *stmt, size_t length) { MYSQL *mysql= stmt->mysql; + my_bool emulate_cmd= !(!(stmt->mysql->server_capabilities & CLIENT_MYSQL) && + (stmt->mysql->extension->mariadb_server_capabilities & MARIADB_CLIENT_STMT_BULK_OPERATIONS >> 32)); if (!mysql) { @@ -2079,6 +2081,17 @@ int STDCALL mariadb_stmt_execute_direct(MYSQL_STMT *stmt, goto fail; } + /* Server versions < 10.2 don't support execute_direct, so we need to + emulate it */ + if (emulate_cmd) + { + int rc; + + if ((rc= mysql_stmt_prepare(stmt, stmt_str, length))) + return rc; + return mysql_stmt_execute(stmt); + } + if (ma_multi_command(mysql, COM_MULTI_PROGRESS)) { SET_CLIENT_STMT_ERROR(stmt, CR_COMMANDS_OUT_OF_SYNC, SQLSTATE_UNKNOWN, 0); @@ -2113,6 +2126,8 @@ int STDCALL mariadb_stmt_execute_direct(MYSQL_STMT *stmt, ma_free_root(&stmt->mem_root, MYF(MY_KEEP_PREALLOC)); ma_free_root(&((MADB_STMT_EXTENSION *)stmt->extension)->fields_ma_alloc_root, MYF(0)); stmt->field_count= 0; + stmt->param_count= 0; + stmt->params= 0; int4store(stmt_id, stmt->stmt_id); if (mysql->methods->db_command(mysql, COM_STMT_CLOSE, stmt_id, diff --git a/unittest/libmariadb/bulk1.c b/unittest/libmariadb/bulk1.c index 05191df0..33437ed0 100644 --- a/unittest/libmariadb/bulk1.c +++ b/unittest/libmariadb/bulk1.c @@ -136,7 +136,7 @@ static int bulk2(MYSQL *mysql) rc= mysql_query(mysql, "DROP TABLE IF EXISTS bulk2"); check_mysql_rc(rc, mysql); - rc= mysql_query(mysql, "CREATE TABLE bulk2 (a int default 4, b default 2)"); + rc= mysql_query(mysql, "CREATE TABLE bulk2 (a int default 4, b int default 2)"); check_mysql_rc(rc, mysql); rc= mysql_stmt_prepare(stmt, "INSERT INTO bulk2 VALUES (?,1)", -1); diff --git a/unittest/libmariadb/features-10_2.c b/unittest/libmariadb/features-10_2.c index 59e12356..699330f4 100644 --- a/unittest/libmariadb/features-10_2.c +++ b/unittest/libmariadb/features-10_2.c @@ -17,6 +17,14 @@ static int execute_direct(MYSQL *mysql) rc= mariadb_stmt_execute_direct(stmt, "DROP TABLE IF EXISTS t1", -1); check_stmt_rc(rc, stmt); + rc= mariadb_stmt_execute_direct(stmt, "SELECT 1", -1); + check_stmt_rc(rc, stmt); + + while (!mysql_stmt_fetch(stmt)); + + rc= mariadb_stmt_execute_direct(stmt, "SELECT 1", -1); + check_stmt_rc(rc, stmt); + rc= mariadb_stmt_execute_direct(stmt, "CREATE TABLE t1 (a int)", -1); check_stmt_rc(rc, stmt); @@ -60,38 +68,36 @@ static int execute_direct_example(MYSQL *mysql) MYSQL_BIND bind[2]; int intval= 1; int param_count= 2; - const char *strval= "execute_direct_example"; + int rc; + const char *strval= "execute_direct_example1"; /* Direct execution without parameters */ - if (mariadb_stmt_execute_direct(stmt, "DROP TABLE IF EXISTS execute_direct", -1)) - goto error; - if (mariadb_stmt_execute_direct(stmt, "CREATE TABLE execute_direct (a int, b varchar(20))", -1)) - goto error; - + rc= mariadb_stmt_execute_direct(stmt, "DROP TABLE IF EXISTS execute_direct", -1); + check_stmt_rc(rc, stmt); + rc= mariadb_stmt_execute_direct(stmt, "CREATE TABLE execute_direct (a int, b varchar(20))", -1); + rc= mysql_stmt_close(stmt); + stmt= mysql_stmt_init(mysql); + check_stmt_rc(rc, stmt); memset(bind, 0, sizeof(MYSQL_BIND) * 2); bind[0].buffer_type= MYSQL_TYPE_SHORT; bind[0].buffer= &intval; bind[1].buffer_type= MYSQL_TYPE_STRING; bind[1].buffer= (char *)strval; - bind[1].buffer_length= (ulong)strlen(strval); + bind[1].buffer_length= strlen(strval); /* set number of parameters */ - if (mysql_stmt_attr_set(stmt, STMT_ATTR_PREBIND_PARAMS, ¶m_count)) - goto error; + rc= mysql_stmt_attr_set(stmt, STMT_ATTR_PREBIND_PARAMS, ¶m_count); + check_stmt_rc(rc, stmt); /* bind parameters */ - if (mysql_stmt_bind_param(stmt, bind)) - goto error; + rc= mysql_stmt_bind_param(stmt, bind); + check_stmt_rc(rc, stmt); - if (mariadb_stmt_execute_direct(stmt, "INSERT INTO execute_direct VALUES (?,?)", -1)) - goto error; + rc= mariadb_stmt_execute_direct(stmt, "INSERT INTO execute_direct VALUES (?,?)", -1); + check_stmt_rc(rc, stmt); mysql_stmt_close(stmt); return OK; -error: - printf("Error: %s\n", mysql_stmt_error(stmt)); - mysql_stmt_close(stmt); - return FAIL; } struct my_tests_st my_tests[] = { diff --git a/unittest/libmariadb/ps_bugs.c b/unittest/libmariadb/ps_bugs.c index 25d93b8b..99f8b074 100644 --- a/unittest/libmariadb/ps_bugs.c +++ b/unittest/libmariadb/ps_bugs.c @@ -4487,7 +4487,6 @@ static int test_conc205(MYSQL *mysql) return OK; } - struct my_tests_st my_tests[] = { {"test_conc205", test_conc205, TEST_CONNECTION_DEFAULT, 0, NULL, NULL}, {"test_conc198", test_conc198, TEST_CONNECTION_DEFAULT, 0, NULL, NULL},