diff --git a/include/ma_common.h b/include/ma_common.h index 6b170e9e..4c4e76a2 100644 --- a/include/ma_common.h +++ b/include/ma_common.h @@ -23,6 +23,12 @@ #include #include +enum enum_multi_status { + COM_MULTI_OFF= 0, + COM_MULTI_CANCEL, + COM_MULTI_PROGRESS, + COM_MULTI_END +}; typedef struct st_mariadb_db_driver { @@ -72,7 +78,7 @@ typedef struct st_connection_handler } MA_CONNECTION_HANDLER; struct st_mariadb_net_extension { - unsigned char *mbuff, *mbuff_end, *mbuff_pos; + enum enum_multi_status multi_status; }; struct st_mariadb_session_state @@ -88,7 +94,8 @@ struct st_mariadb_extension { unsigned long mariadb_server_capabilities; /* MariaDB specific server capabilities */ }; -#define OPT_HAS_EXT_VAL(a,key) \ - ((a)->options.extension && (a)->options.extension->key) +#define OPT_EXT_VAL(a,key) \ + ((a)->options.extension && (a)->options.extension->key) ?\ + (a)->options.extension->key : 0 #endif diff --git a/include/mariadb_com.h b/include/mariadb_com.h index 29b5de57..6e532a17 100644 --- a/include/mariadb_com.h +++ b/include/mariadb_com.h @@ -378,7 +378,7 @@ void ma_net_clear(NET *net); int ma_net_flush(NET *net); int ma_net_write(NET *net,const unsigned char *packet, size_t len); int ma_net_write_command(NET *net,unsigned char command,const char *packet, - size_t len); + size_t len, my_bool disable_flush); int ma_net_real_write(NET *net,const char *packet, size_t len); extern unsigned long ma_net_read(NET *net); diff --git a/include/mysql.h b/include/mysql.h index ca1b8d22..49d8488f 100644 --- a/include/mysql.h +++ b/include/mysql.h @@ -236,8 +236,7 @@ extern unsigned int mariadb_deinitialize_ssl; MARIADB_OPT_FOUND_ROWS, MARIADB_OPT_MULTI_RESULTS, MARIADB_OPT_MULTI_STATEMENTS, - MARIADB_OPT_INTERACTIVE, - MARIADB_OPT_COM_MULTI, + MARIADB_OPT_INTERACTIVE }; enum mariadb_value { diff --git a/libmariadb/ma_net.c b/libmariadb/ma_net.c index c6d5604f..068354e3 100644 --- a/libmariadb/ma_net.c +++ b/libmariadb/ma_net.c @@ -117,14 +117,12 @@ int ma_net_init(NET *net, MARIADB_PVIO* pvio) void ma_net_end(NET *net) { free(net->buff); - free(net->extension->mbuff); net->buff=0; - net->extension->mbuff= 0; } /* Realloc the packet buffer */ -static my_bool net_realloc(NET *net, my_bool is_multi, size_t length) +static my_bool net_realloc(NET *net, size_t length) { uchar *buff; size_t pkt_length; @@ -138,35 +136,24 @@ static my_bool net_realloc(NET *net, my_bool is_multi, size_t length) pkt_length = (length+IO_SIZE-1) & ~(IO_SIZE-1); /* reallocate buffer: size= pkt_length + NET_HEADER_SIZE + COMP_HEADER_SIZE */ - if (!(buff=(uchar*) realloc(is_multi ? net->extension->mbuff : net->buff, - pkt_length + NET_HEADER_SIZE + COMP_HEADER_SIZE))) + if (!(buff=(uchar*) realloc(net->buff, + pkt_length + NET_HEADER_SIZE + COMP_HEADER_SIZE))) { net->error=1; return(1); } - if (!is_multi) - { - net->buff=net->write_pos=buff; - net->buff_end=buff+(net->max_packet=(unsigned long)pkt_length); - } - else - { - net->extension->mbuff= buff; - net->extension->mbuff_end= buff + (net->max_packet= (unsigned long)pkt_length); - } + net->buff=net->write_pos=buff; + net->buff_end=buff+(net->max_packet=(unsigned long)pkt_length); return(0); } /* Remove unwanted characters from connection */ void ma_net_clear(NET *net) { -// size_t len; -/* if (net->pvio) - ma_pvio_has_data(net->pvio, &len); */ + if (net->extension->multi_status > COM_MULTI_OFF) + return; net->compress_pkt_nr= net->pkt_nr=0; /* Ready for new command */ net->write_pos=net->buff; - if (net->extension->mbuff) - net->extension->mbuff_pos= net->extension->mbuff; return; } @@ -175,6 +162,10 @@ int ma_net_flush(NET *net) { int error=0; + /* don't flush if com_multi is in progress */ + if (net->extension->multi_status > COM_MULTI_OFF) + return 0; + if (net->buff != net->write_pos) { error=ma_net_real_write(net,(char*) net->buff, @@ -223,7 +214,8 @@ ma_net_write(NET *net, const uchar *packet, size_t len) int ma_net_write_command(NET *net, uchar command, - const char *packet, size_t len) + const char *packet, size_t len, + my_bool disable_flush) { uchar buff[NET_HEADER_SIZE+1]; size_t buff_size= NET_HEADER_SIZE + 1; @@ -252,10 +244,11 @@ ma_net_write_command(NET *net, uchar command, len= length; } int3store(buff,length); - buff[3]= (net->compress) ? 0 : (uchar) (net->pkt_nr++); + buff[3]= (net->compress) ? 0 :(uchar) (net->pkt_nr++); rc= test (ma_net_write_buff(net,(char *)buff, buff_size) || - ma_net_write_buff(net,packet,len) || - ma_net_flush(net)); + ma_net_write_buff(net,packet,len)); + if (!rc && !disable_flush) + return test(ma_net_flush(net)); return rc; } @@ -306,57 +299,6 @@ ma_net_write_buff(NET *net,const char *packet, size_t len) unsigned char *mysql_net_store_length(unsigned char *packet, size_t length); -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->mbuff) - { - size_t alloc_size= (required_length + IO_SIZE - 1) & ~(IO_SIZE - 1); - if (!(net->extension->mbuff= (unsigned char *)malloc(alloc_size))) - { - net->last_errno=ER_OUT_OF_RESOURCES; - net->error=2; - net->reading_or_writing=0; - return(1); - } - net->extension->mbuff_pos= net->extension->mbuff; - net->extension->mbuff_end= net->extension->mbuff + alloc_size; - } - - left_length= net->extension->mbuff_end - net->extension->mbuff_pos; - - /* check if our buffer is large enough */ - if (left_length < required_length) - { - current_length= net->extension->mbuff_pos - net->extension->mbuff; - if (net_realloc(net, 1, current_length + required_length)) - goto error; - net->extension->mbuff_pos = net->extension->mbuff + current_length; - } - net->extension->mbuff_pos= mysql_net_store_length(net->extension->mbuff_pos, - length + 1); - *net->extension->mbuff_pos= command; - net->extension->mbuff_pos++; - memcpy(net->extension->mbuff_pos, packet, length); - net->extension->mbuff_pos+= length; - return 0; - -error: - if (net->extension->mbuff) - { - free(net->extension->mbuff); - net->extension->mbuff= net->extension->mbuff_pos= net->extension->mbuff_end= 0; - } - return 1; -} - /* Read and write using timeouts */ int @@ -467,7 +409,7 @@ ma_real_read(NET *net, size_t *complen) /* The necessary size of net->buff */ if (helping >= net->max_packet) { - if (net_realloc(net, 0, helping)) + if (net_realloc(net, helping)) { len= packet_error; /* Return error */ goto end; @@ -637,3 +579,40 @@ ulong ma_net_read(NET *net) #endif return (ulong)len; } + +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; +} + diff --git a/libmariadb/mariadb_lib.c b/libmariadb/mariadb_lib.c index 6780949a..06f157eb 100644 --- a/libmariadb/mariadb_lib.c +++ b/libmariadb/mariadb_lib.c @@ -354,23 +354,11 @@ mthd_my_send_cmd(MYSQL *mysql,enum enum_server_command command, const char *arg, { NET *net= &mysql->net; int result= -1; - enum mariadb_com_multi multi= MARIADB_COM_MULTI_END; - - if (OPT_HAS_EXT_VAL(mysql, multi_command)) - multi= mysql->options.extension->multi_command; - - if (multi == MARIADB_COM_MULTI_BEGIN) - { - /* todo: error handling */ - return(net_add_multi_command(&mysql->net, command, (uchar *)arg, length)); - } - if (mysql->net.pvio == 0) - { /* Do reconnect if possible */ + { + /* Do reconnect if possible */ if (mariadb_reconnect(mysql)) - { return(1); - } } if (mysql->status != MYSQL_STATUS_READY || mysql->server_status & SERVER_MORE_RESULTS_EXIST) @@ -394,8 +382,13 @@ mthd_my_send_cmd(MYSQL *mysql,enum enum_server_command command, const char *arg, if (!arg) arg=""; + if (net->extension->multi_status== COM_MULTI_PROGRESS) + { + return net_add_multi_command(net, command, (const uchar *)arg, length); + } + if (ma_net_write_command(net,(uchar) command,arg, - length ? length : (ulong) strlen(arg))) + length ? length : (ulong) strlen(arg), 0)) { if (net->last_errno == ER_NET_PACKET_TOO_LARGE) { @@ -406,14 +399,19 @@ mthd_my_send_cmd(MYSQL *mysql,enum enum_server_command command, const char *arg, if (mariadb_reconnect(mysql)) goto end; if (ma_net_write_command(net,(uchar) command,arg, - length ? length : (ulong) strlen(arg))) + length ? length : (ulong) strlen(arg), 0)) { my_set_error(mysql, CR_SERVER_GONE_ERROR, SQLSTATE_UNKNOWN, 0); goto end; } } result=0; - if (!skipp_check) { + + if (net->extension->multi_status == COM_MULTI_OFF) + skipp_check= 1; + + if (!skipp_check) + { result= ((mysql->packet_length=ma_net_safe_read(mysql)) == packet_error ? 1 : 0); } @@ -428,6 +426,45 @@ ma_simple_command(MYSQL *mysql,enum enum_server_command command, const char *arg return mysql->methods->db_command(mysql, command, arg, length, skipp_check, opt_arg); } +int ma_multi_command(MYSQL *mysql, enum enum_multi_status status) +{ + NET *net= &mysql->net; + + switch (status) { + case COM_MULTI_OFF: + ma_net_clear(net); + net->extension->multi_status= status; + return 0; + case COM_MULTI_PROGRESS: + if (net->extension->multi_status > COM_MULTI_OFF) + 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 */ + return 1; + /* store length after com_multi */ + int3store(net->buff, len); + net->extension->multi_status= COM_MULTI_OFF; + return ma_net_flush(net); + } + case COM_MULTI_CANCEL: + ma_net_clear(net); + net->extension->multi_status= COM_MULTI_OFF; + return 0; + default: + return 1; + } +} + static void free_old_query(MYSQL *mysql) { if (mysql->fields) @@ -2100,10 +2137,8 @@ mysql_read_query_result(MYSQL *mysql) int STDCALL mysql_real_query(MYSQL *mysql, const char *query, size_t length) { - my_bool is_multi= 0; + my_bool skip_result= OPT_EXT_VAL(mysql, multi_command); - if (OPT_HAS_EXT_VAL(mysql, multi_command)) - is_multi= mysql->options.extension->multi_command; if (length == (size_t)-1) length= strlen(query); @@ -2111,7 +2146,7 @@ mysql_real_query(MYSQL *mysql, const char *query, size_t length) if (ma_simple_command(mysql, COM_QUERY,query,length,1,0)) return(-1); - if (!is_multi) + if (!skip_result) return(mysql->methods->db_read_query_result(mysql)); return(0); } @@ -2560,31 +2595,6 @@ void ma_hash_free(void *p) free(p); } -int mariadb_flush_multi_command(MYSQL *mysql) -{ - int rc; - size_t length= mysql->net.extension->mbuff_pos - mysql->net.extension->mbuff; - - rc= ma_simple_command(mysql, COM_MULTI, (char *)mysql->net.extension->mbuff, - length, 1, 0); - /* reset multi_buff */ - mysql->net.extension->mbuff_pos= mysql->net.extension->mbuff; - - /* don't read result for mysql_stmt_execute_direct() */ - if (!rc) - { - uchar *p= (uchar *)mysql->net.extension->mbuff; - unsigned long len= net_field_length(&p); - if (len && (*p == COM_STMT_PREPARE || - *p == COM_STMT_EXECUTE || - *p == COM_STMT_CLOSE)) - return rc; - else - return mysql->methods->db_read_query_result(mysql); - } - return rc; -} - int STDCALL mysql_optionsv(MYSQL *mysql,enum mysql_option option, ...) { @@ -2698,8 +2708,6 @@ mysql_optionsv(MYSQL *mysql,enum mysql_option option, ...) goto end; } mysql->options.extension->async_context= ctxt; -// if (mysql->net.pvio) -// mysql->net.pvio->async_context= ctxt; break; case MYSQL_OPT_MAX_ALLOWED_PACKET: if (mysql) @@ -2931,40 +2939,6 @@ mysql_optionsv(MYSQL *mysql,enum mysql_option option, ...) case MARIADB_OPT_TLS_PASSPHRASE: OPT_SET_EXTENDED_VALUE_STR(&mysql->options, tls_pw, (char *)arg1); break; - case MARIADB_OPT_COM_MULTI: - if (&mysql->net.pvio && - !(mysql->server_capabilities & CLIENT_MYSQL)) - { - enum mariadb_com_multi type= *(enum mariadb_com_multi *)arg1; - switch (type) - { - case MARIADB_COM_MULTI_BEGIN: - OPT_SET_EXTENDED_VALUE_INT(&mysql->options, multi_command, type); - break; - case MARIADB_COM_MULTI_CANCEL: - if (!mysql->options.extension || - mysql->options.extension->multi_command != MARIADB_COM_MULTI_BEGIN) - return(-1); - /* reset multi_buff */ - mysql->net.extension->mbuff_pos= mysql->net.extension->mbuff; - OPT_SET_EXTENDED_VALUE_INT(&mysql->options, multi_command, MARIADB_COM_MULTI_END); - break; - case MARIADB_COM_MULTI_END: - if (!mysql->options.extension || - mysql->options.extension->multi_command != MARIADB_COM_MULTI_BEGIN) - return(-1); - OPT_SET_EXTENDED_VALUE_INT(&mysql->options, multi_command, MARIADB_COM_MULTI_END); - if (mariadb_flush_multi_command(mysql)) - return(-1); - break; - default: - return(-1); - } - OPT_SET_EXTENDED_VALUE_INT(&mysql->options, multi_command, *(my_bool *)arg1); - } - else - return(-1); - break; case MARIADB_OPT_CONNECTION_READ_ONLY: OPT_SET_EXTENDED_VALUE_INT(&mysql->options, read_only, *(my_bool *)arg1); break; @@ -3054,15 +3028,6 @@ mysql_get_optionv(MYSQL *mysql, enum mysql_option option, void *arg, ...) case MYSQL_OPT_NONBLOCK: *((my_bool *)arg)= test(mysql->options.extension && mysql->options.extension->async_context); break; - case MARIADB_OPT_COM_MULTI: - if (!(mysql->server_capabilities & CLIENT_MYSQL)) - { - *((enum mariadb_com_multi *)arg)= mysql->options.extension ? - mysql->options.extension->multi_command : 0; - } - else - return(-1); - break; case MYSQL_OPT_SSL_ENFORCE: *((my_bool *)arg)= mysql->options.use_ssl; break; diff --git a/libmariadb/mariadb_stmt.c b/libmariadb/mariadb_stmt.c index 4f407235..22085359 100644 --- a/libmariadb/mariadb_stmt.c +++ b/libmariadb/mariadb_stmt.c @@ -74,6 +74,7 @@ typedef struct MYSQL_DATA *read_rows(MYSQL *mysql,MYSQL_FIELD *mysql_fields, uint fields); void free_rows(MYSQL_DATA *cur); +int ma_multi_command(MYSQL *mysql, enum enum_multi_status status); MYSQL_FIELD * unpack_fields(MYSQL_DATA *data,MA_MEM_ROOT *alloc,uint fields, my_bool default_value, my_bool long_flag_protocol); static my_bool is_not_null= 0; @@ -1346,8 +1347,6 @@ int STDCALL mysql_stmt_prepare(MYSQL_STMT *stmt, const char *query, size_t lengt { MYSQL *mysql= stmt->mysql; int rc= 1; - enum mariadb_com_multi multi= MARIADB_COM_MULTI_END; - if (!stmt->mysql) { @@ -1358,8 +1357,6 @@ int STDCALL mysql_stmt_prepare(MYSQL_STMT *stmt, const char *query, size_t lengt if (length == (size_t) -1) length= strlen(query); - mysql_get_optionv(mysql, MARIADB_OPT_COM_MULTI, &multi); - /* clear flags */ CLEAR_CLIENT_STMT_ERROR(stmt); CLEAR_CLIENT_ERROR(stmt->mysql); @@ -1390,7 +1387,7 @@ int STDCALL mysql_stmt_prepare(MYSQL_STMT *stmt, const char *query, size_t lengt if (mysql->methods->db_command(mysql, COM_STMT_PREPARE, query, length, 1, stmt)) goto fail; - if (multi == MARIADB_COM_MULTI_BEGIN) + if (mysql->net.extension->multi_status > COM_MULTI_OFF) return 0; if (mysql->methods->db_read_prepare_response && @@ -1702,7 +1699,6 @@ int STDCALL mysql_stmt_execute(MYSQL_STMT *stmt) char *request; int ret; size_t request_len= 0; - enum mariadb_com_multi multi= MARIADB_COM_MULTI_END; if (!stmt->mysql) { @@ -1710,8 +1706,6 @@ int STDCALL mysql_stmt_execute(MYSQL_STMT *stmt) return(1); } - mysql_get_optionv(mysql, MARIADB_OPT_COM_MULTI, &multi); - if (stmt->state < MYSQL_STMT_PREPARED) { SET_CLIENT_ERROR(mysql, CR_COMMANDS_OUT_OF_SYNC, SQLSTATE_UNKNOWN, 0); @@ -1751,7 +1745,6 @@ int STDCALL mysql_stmt_execute(MYSQL_STMT *stmt) ret= stmt->mysql->methods->db_command(mysql, COM_STMT_EXECUTE, request, request_len, 1, stmt); - if (request) free(request); @@ -1762,7 +1755,7 @@ int STDCALL mysql_stmt_execute(MYSQL_STMT *stmt) return(1); } - if (multi == MARIADB_COM_MULTI_BEGIN) + if (mysql->net.extension->multi_status > COM_MULTI_OFF) return(0); return(stmt_read_execute_response(stmt)); @@ -2074,7 +2067,6 @@ int STDCALL mariadb_stmt_execute_direct(MYSQL_STMT *stmt, const char *stmt_str, size_t length) { - enum mariadb_com_multi multi= MARIADB_COM_MULTI_BEGIN; MYSQL *mysql= stmt->mysql; if (!mysql) @@ -2083,8 +2075,11 @@ int STDCALL mariadb_stmt_execute_direct(MYSQL_STMT *stmt, goto fail; } - if (mysql_optionsv(mysql, MARIADB_OPT_COM_MULTI, &multi)) + if (ma_multi_command(mysql, COM_MULTI_PROGRESS)) + { + SET_CLIENT_STMT_ERROR(stmt, CR_COMMANDS_OUT_OF_SYNC, SQLSTATE_UNKNOWN, 0); goto fail; + } if (!stmt->mysql) { @@ -2095,8 +2090,6 @@ int STDCALL mariadb_stmt_execute_direct(MYSQL_STMT *stmt, if (length == (size_t) -1) length= strlen(stmt_str); - mysql_get_optionv(mysql, MARIADB_OPT_COM_MULTI, &multi); - /* clear flags */ CLEAR_CLIENT_STMT_ERROR(stmt); CLEAR_CLIENT_ERROR(stmt->mysql); @@ -2133,8 +2126,7 @@ int STDCALL mariadb_stmt_execute_direct(MYSQL_STMT *stmt, goto fail; /* flush multi buffer */ - multi= MARIADB_COM_MULTI_END; - if (mysql_optionsv(mysql, MARIADB_OPT_COM_MULTI, &multi)) + if (ma_multi_command(mysql, COM_MULTI_END)) goto fail; /* read prepare response */ diff --git a/plugins/connection/aurora.c b/plugins/connection/aurora.c index 1bcc09d3..8fa42bc8 100644 --- a/plugins/connection/aurora.c +++ b/plugins/connection/aurora.c @@ -724,7 +724,7 @@ int aurora_command(MYSQL *mysql,enum enum_server_command command, const char *ar AURORA *aurora= (AURORA *)save_hdlr->data; /* if we don't have slave or slave became unavailable root traffic to master */ - if (!aurora->mysql[AURORA_REPLICA] || !OPT_HAS_EXT_VAL(mysql, read_only)) + if (!aurora->mysql[AURORA_REPLICA] || !OPT_EXT_VAL(mysql, read_only)) { if (command != COM_INIT_DB) { diff --git a/unittest/libmariadb/features-10_2.c b/unittest/libmariadb/features-10_2.c index 3ae63f92..59e12356 100644 --- a/unittest/libmariadb/features-10_2.c +++ b/unittest/libmariadb/features-10_2.c @@ -3,217 +3,6 @@ #include "my_test.h" -my_bool have_com_multi= 1; - -static int com_multi_1(MYSQL *mysql) -{ - int rc; - MYSQL_RES *res; - enum mariadb_com_multi status; - - /* TEST a simple query before COM_MULTI */ - - rc= mysql_query(mysql, "select 1"); - check_mysql_rc(rc, mysql); - res= mysql_store_result(mysql); - FAIL_UNLESS(res, "1 simple query no result"); - - mysql_free_result(res); - - /* TEST COM_MULTI */ - - status= MARIADB_COM_MULTI_BEGIN; - if (mysql_options(mysql, MARIADB_OPT_COM_MULTI, &status)) - { - diag("COM_MULT not supported"); - have_com_multi= 0; - return SKIP; - } - - rc= mysql_query(mysql, "select 1"); - - rc= mysql_query(mysql, "select 2"); - - status= MARIADB_COM_MULTI_END; - rc= mysql_options(mysql, MARIADB_OPT_COM_MULTI, &status); - check_mysql_rc(rc, mysql); - /* 1 SELECT result */ - res= mysql_store_result(mysql); - FAIL_UNLESS(res, "1 of 2 simple query in batch no result"); - FAIL_UNLESS(res->field_count == 1 && res->row_count == 1 && - strcmp(res->fields[0].name, "1") == 0, - "1 of 2 simple query in batch wrong result"); - mysql_free_result(res); - /* 2 SELECT result */ - rc= mysql_next_result(mysql); - FAIL_UNLESS(rc == 0, "no second result in the batch"); - res= mysql_store_result(mysql); - FAIL_UNLESS(res, "2 of 2 simple query in batch no result"); - FAIL_UNLESS(res->field_count == 1 && res->row_count == 1 && - strcmp(res->fields[0].name, "2") == 0, - "1 of 2 simple query in batch wrong result"); - mysql_free_result(res); - rc= mysql_next_result(mysql); - FAIL_UNLESS(rc == -1, "more then 2 results"); - - /* TEST a simple query after COM_MULTI */ - - rc= mysql_query(mysql, "select 1"); - check_mysql_rc(rc, mysql); - res= mysql_store_result(mysql); - FAIL_UNLESS(res != NULL, "2 simple query no result"); - mysql_free_result(res); - - /* question: how will result sets look like ? */ - diag("error: %s", mysql_error(mysql)); - - return OK; -} - - -#define repeat1 100 -#define repeat2 1 - -static int com_multi_2(MYSQL *mysql) -{ - int rc; - unsigned int i, j; - enum mariadb_com_multi status; - - - rc= mysql_query(mysql, "DROP TABLE IF EXISTS t1"); - check_mysql_rc(rc, mysql); - rc= mysql_query(mysql, "create table t1 (a int)"); - check_mysql_rc(rc, mysql); - - /* TEST COM_MULTI */ - - for (i= 0; i < repeat2; i++) - { - status= MARIADB_COM_MULTI_BEGIN; - if (mysql_options(mysql, MARIADB_OPT_COM_MULTI, &status)) - { - diag("COM_MULT not supported"); - have_com_multi= 0; - return SKIP; - } - - for (j= 0; j < repeat1; j++) - { - rc= mysql_query(mysql, "insert into t1 values (1)"); - rc= mysql_query(mysql, "insert into t1 values (2)"); - rc= mysql_query(mysql, "delete from t1;"); - } - - status= MARIADB_COM_MULTI_END; - rc= mysql_options(mysql, MARIADB_OPT_COM_MULTI, &status); - - for (j= 0; j < repeat1; j++) - { - /* 1 INSERT */ - check_mysql_rc(rc, mysql); - /* 2 INSERT */ - rc= mysql_next_result(mysql); - check_mysql_rc(rc, mysql); - /* 3 DELETE */ - rc= mysql_next_result(mysql); - check_mysql_rc(rc, mysql); - - rc= mysql_next_result(mysql); - } - - rc= mysql_next_result(mysql); - FAIL_UNLESS(rc == -1, "more then 3*repeat1 results"); - } - - /* TEST a simple query after COM_MULTI */ - rc= mysql_query(mysql, "drop table t1"); - - diag("error: %s", mysql_error(mysql)); - - return OK; -} - - -static int com_multi_ps1(MYSQL *mysql) -{ - MYSQL_STMT *stmt= mysql_stmt_init(mysql); - int rc; - - if (!have_com_multi) - return SKIP; - - rc= mysql_query(mysql, "DROP TABLE IF EXISTS t1"); - check_mysql_rc(rc, mysql); - rc= mysql_query(mysql, "CREATE TABLE t1 (a int, b varchar(20))"); - - rc= mysql_stmt_prepare(stmt, "INSERT INTO t1 values (2, 'execute_direct')", -1); - check_stmt_rc(rc, stmt); - - rc= mysql_stmt_execute(stmt); - check_stmt_rc(rc, stmt); - diag("affected_rows: %llu", mysql_stmt_affected_rows(stmt)); - diag("stmt_id: %lu", stmt->stmt_id); - mysql_stmt_close(stmt); - - stmt= mysql_stmt_init(mysql); - rc= mariadb_stmt_execute_direct(stmt, "INSERT INTO t1 values (2, 'execute_direct')", -1); - check_stmt_rc(rc, stmt); - - FAIL_IF(mysql_stmt_affected_rows(stmt) != 1, "expected affected_rows= 1"); - FAIL_IF(stmt->stmt_id < 1, "expected statement id > 0"); - - rc= mysql_stmt_close(stmt); - check_mysql_rc(rc, mysql); - - return OK; -} - -static int com_multi_ps2(MYSQL *mysql) -{ - MYSQL_STMT *stmt; - MYSQL_BIND bind[2]; - int intval= 3, rc; - int i; - const char *varval= "com_multi_ps2"; - unsigned int param_count= 2; - - if (!have_com_multi) - return SKIP; - - rc= mysql_query(mysql, "DROP TABLE IF EXISTS t1"); - check_mysql_rc(rc, mysql); - rc= mysql_query(mysql, "CREATE TABLE t1 (a int, b varchar(20))"); - - 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 *)varval; - bind[1].buffer_length= (ulong)strlen(varval); - - stmt= mysql_stmt_init(mysql); - mysql_stmt_attr_set(stmt, STMT_ATTR_PREBIND_PARAMS, ¶m_count); - rc= mysql_stmt_bind_param(stmt, bind); - check_stmt_rc(rc, stmt); - rc= mariadb_stmt_execute_direct(stmt, "INSERT INTO t1 VALUES (?,?)", -1); - check_stmt_rc(rc, stmt); - - for (i=0; i < 2; i++) - { - mysql_stmt_execute(stmt); - check_stmt_rc(rc, stmt); - FAIL_IF(mysql_stmt_affected_rows(stmt) != 1, "expected affected_rows= 1"); - FAIL_IF(stmt->stmt_id < 1, "expected statement id > 0"); - } - rc= mysql_stmt_close(stmt); - check_mysql_rc(rc, mysql); - - return OK; -} - - - static int execute_direct(MYSQL *mysql) { int rc= 0; @@ -306,10 +95,6 @@ error: } struct my_tests_st my_tests[] = { - {"com_multi_1", com_multi_1, TEST_CONNECTION_NEW, 0, NULL, NULL}, - {"com_multi_2", com_multi_2, TEST_CONNECTION_NEW, 0, NULL, NULL}, - {"com_multi_ps1", com_multi_ps1, TEST_CONNECTION_NEW, 0, NULL, NULL}, - {"com_multi_ps2", com_multi_ps2, TEST_CONNECTION_NEW, 0, NULL, NULL}, {"execute_direct", execute_direct, TEST_CONNECTION_DEFAULT, 0, NULL, NULL}, {"execute_direct_example", execute_direct_example, TEST_CONNECTION_DEFAULT, 0, NULL, NULL}, {NULL, NULL, 0, 0, NULL, NULL}