1
0
mirror of https://github.com/mariadb-corporation/mariadb-connector-c.git synced 2025-08-07 02:42:49 +03:00

- removed COM_MULTI from options

COM_MULTI is now available for internal use only, e.g. in
  mariadb_stmt_execute_direct
This commit is contained in:
Georg Richter
2016-10-20 08:47:51 +02:00
parent 468cda3cfb
commit 6306c9f46b
8 changed files with 132 additions and 405 deletions

View File

@@ -23,6 +23,12 @@
#include <mysql.h>
#include <ma_hash.h>
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

View File

@@ -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);

View File

@@ -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 {

View File

@@ -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,
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);
}
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;
@@ -254,8 +246,9 @@ ma_net_write_command(NET *net, uchar command,
int3store(buff,length);
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;
}

View File

@@ -354,24 +354,12 @@ 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 */
if (mariadb_reconnect(mysql))
{
/* 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;

View File

@@ -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 */

View File

@@ -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)
{

View File

@@ -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, &param_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}