You've already forked mariadb-connector-c
mirror of
https://github.com/mariadb-corporation/mariadb-connector-c.git
synced 2025-08-08 14:02:17 +03:00
First implementation of mariadb_stmt_execute_direct
This commit is contained in:
@@ -253,3 +253,4 @@ my_ulonglong STDCALL mysql_stmt_insert_id(MYSQL_STMT *stmt);
|
||||
unsigned int STDCALL mysql_stmt_field_count(MYSQL_STMT *stmt);
|
||||
int STDCALL mysql_stmt_next_result(MYSQL_STMT *stmt);
|
||||
my_bool STDCALL mysql_stmt_more_results(MYSQL_STMT *stmt);
|
||||
int STDCALL mariadb_stmt_execute_direct(MYSQL_STMT *stmt, const char *stmt_str, size_t length);
|
||||
|
@@ -165,6 +165,12 @@ extern unsigned int mariadb_deinitialize_ssl;
|
||||
MEM_ROOT alloc;
|
||||
} MYSQL_DATA;
|
||||
|
||||
enum mariadb_com_multi {
|
||||
MARIADB_COM_MULTI_END,
|
||||
MARIADB_COM_MULTI_BEGIN,
|
||||
MARIADB_COM_MULTI_CANCEL
|
||||
};
|
||||
|
||||
enum mysql_option
|
||||
{
|
||||
MYSQL_OPT_CONNECT_TIMEOUT,
|
||||
@@ -752,6 +758,7 @@ struct st_mariadb_api {
|
||||
unsigned int (STDCALL *mysql_stmt_field_count)(MYSQL_STMT *stmt);
|
||||
int (STDCALL *mysql_stmt_next_result)(MYSQL_STMT *stmt);
|
||||
my_bool (STDCALL *mysql_stmt_more_results)(MYSQL_STMT *stmt);
|
||||
int (STDCALL *mariadb_stmt_execute_direct)(MYSQL_STMT *stmt, const char *stmtstr, size_t length);
|
||||
};
|
||||
|
||||
/* these methods can be overwritten by db plugins */
|
||||
|
@@ -129,7 +129,7 @@ enum enum_server_command
|
||||
#define REFRESH_READ_LOCK 16384 /* Lock tables for read */
|
||||
#define REFRESH_FAST 32768 /* Intern flag */
|
||||
|
||||
#define CLIENT_LONG_PASSWORD 1 /* new more secure passwords */
|
||||
#define CLIENT_MYSQL 1
|
||||
#define CLIENT_FOUND_ROWS 2 /* Found instead of affected rows */
|
||||
#define CLIENT_LONG_FLAG 4 /* Get all column flags */
|
||||
#define CLIENT_CONNECT_WITH_DB 8 /* One can specify db on connect */
|
||||
@@ -157,14 +157,14 @@ enum enum_server_command
|
||||
|
||||
/* MariaDB specific capabilities */
|
||||
#define MARIADB_CLIENT_FLAGS 0xFFFFFFFF00000000ULL
|
||||
#define MARIADB_CLIENT_COM_MULTI 1
|
||||
#define MARIADB_CLIENT_PROGRESS (1ULL << 32)
|
||||
#define MARIADB_CLIENT_EXTENDED_FLAGS (1ULL << 63)
|
||||
#define MARIADB_CLIENT_COM_MULTI (1ULL << 33)
|
||||
//#define MARIADB_CLIENT_EXTENDED_FLAGS (1ULL << 63)
|
||||
|
||||
#define MARIADB_CLIENT_SUPPORTED_FLAGS (MARIADB_CLIENT_PROGRESS |\
|
||||
MARIADB_CLIENT_EXTENDED_FLAGS)
|
||||
MARIADB_CLIENT_COM_MULTI)
|
||||
|
||||
#define CLIENT_SUPPORTED_FLAGS (CLIENT_LONG_PASSWORD |\
|
||||
#define CLIENT_SUPPORTED_FLAGS (CLIENT_MYSQL |\
|
||||
CLIENT_FOUND_ROWS |\
|
||||
CLIENT_LONG_FLAG |\
|
||||
CLIENT_CONNECT_WITH_DB |\
|
||||
@@ -188,7 +188,7 @@ enum enum_server_command
|
||||
CLIENT_PLUGIN_AUTH |\
|
||||
CLIENT_CONNECT_ATTRS)
|
||||
|
||||
#define CLIENT_CAPABILITIES (CLIENT_LONG_PASSWORD | \
|
||||
#define CLIENT_CAPABILITIES (CLIENT_MYSQL | \
|
||||
CLIENT_LONG_FLAG |\
|
||||
CLIENT_TRANSACTIONS |\
|
||||
CLIENT_SECURE_CONNECTION |\
|
||||
|
@@ -35,6 +35,7 @@ SET(EXPORT_SYMBOLS
|
||||
mariadb_dyncol_val_long
|
||||
mariadb_dyncol_val_str
|
||||
mariadb_get_charset_by_name
|
||||
mariadb_stmt_execute_direct
|
||||
mariadb_get_charset_by_nr
|
||||
mariadb_get_info
|
||||
mariadb_get_infov
|
||||
|
@@ -361,16 +361,16 @@ mthd_my_send_cmd(MYSQL *mysql,enum enum_server_command command, const char *arg,
|
||||
{
|
||||
NET *net= &mysql->net;
|
||||
int result= -1;
|
||||
my_bool is_multi= 0;
|
||||
enum mariadb_com_multi multi= MARIADB_COM_MULTI_END;
|
||||
|
||||
if (OPT_HAS_EXT_VAL(mysql, multi_command))
|
||||
is_multi= mysql->options.extension->multi_command;
|
||||
multi= mysql->options.extension->multi_command;
|
||||
|
||||
DBUG_ENTER("mthd_my_send_cmd");
|
||||
|
||||
DBUG_PRINT("info", ("server_command: %d packet_size: %u", command, length));
|
||||
|
||||
if (is_multi)
|
||||
if (multi == MARIADB_COM_MULTI_BEGIN)
|
||||
{
|
||||
/* todo: error handling */
|
||||
DBUG_RETURN(net_add_multi_command(&mysql->net, command, arg, length));
|
||||
@@ -1546,7 +1546,7 @@ MYSQL *mthd_my_real_connect(MYSQL *mysql, const char *host, const char *user,
|
||||
|
||||
if (strncmp(end, MA_RPL_VERSION_HACK, sizeof(MA_RPL_VERSION_HACK) - 1) == 0)
|
||||
{
|
||||
if (!(mysql->server_version= my_strdup(end + sizeof(MA_RPL_VERSION_HACK), 0)))
|
||||
if (!(mysql->server_version= my_strdup(end + sizeof(MA_RPL_VERSION_HACK) - 1, 0)))
|
||||
{
|
||||
SET_CLIENT_ERROR(mysql, CR_OUT_OF_MEMORY, SQLSTATE_UNKNOWN, 0);
|
||||
goto error;
|
||||
@@ -1586,11 +1586,11 @@ MYSQL *mthd_my_real_connect(MYSQL *mysql, const char *host, const char *user,
|
||||
{
|
||||
mysql->server_language= uint1korr(end + 2);
|
||||
mysql->server_status= uint2korr(end + 3);
|
||||
mysql->server_capabilities|= uint2korr(end + 5) << 16;
|
||||
mysql->server_capabilities|= (unsigned int)(uint2korr(end + 5) << 16);
|
||||
pkt_scramble_len= uint1korr(end + 7);
|
||||
|
||||
/* check if MariaD2B specific capabilities are available */
|
||||
if (is_maria && !(mysql->server_capabilities & CLIENT_LONG_PASSWORD))
|
||||
if (is_maria && !(mysql->server_capabilities & CLIENT_MYSQL))
|
||||
{
|
||||
mysql->server_capabilities|= (ulonglong) uint4korr(end + 14) << 32;
|
||||
}
|
||||
@@ -2630,6 +2630,24 @@ void ma_hash_free(void *p)
|
||||
my_free(p);
|
||||
}
|
||||
|
||||
int mariadb_flush_multi_command(MYSQL *mysql)
|
||||
{
|
||||
int rc;
|
||||
size_t length= mysql->net.mbuff_pos - mysql->net.mbuff;
|
||||
|
||||
rc= simple_command(mysql, COM_MULTI, mysql->net.mbuff,
|
||||
length, 1, 0);
|
||||
/* reset multi_buff */
|
||||
mysql->net.mbuff_pos= mysql->net.mbuff;
|
||||
|
||||
if (!rc)
|
||||
if (mysql->net.mbuff && length > 3 &&
|
||||
(mysql->net.mbuff[3] == COM_STMT_PREPARE || mysql->net.mbuff[3] == COM_STMT_EXECUTE))
|
||||
return rc;
|
||||
else
|
||||
return mysql->methods->db_read_query_result(mysql);
|
||||
return rc;
|
||||
}
|
||||
|
||||
int STDCALL
|
||||
mysql_optionsv(MYSQL *mysql,enum mysql_option option, ...)
|
||||
@@ -2975,8 +2993,33 @@ mysql_optionsv(MYSQL *mysql,enum mysql_option option, ...)
|
||||
break;
|
||||
case MARIADB_OPT_COM_MULTI:
|
||||
if (&mysql->net.pvio &&
|
||||
(mysql->server_capabilities & MARIADB_CLIENT_EXTENDED_FLAGS))
|
||||
!(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)
|
||||
DBUG_RETURN(-1);
|
||||
/* reset multi_buff */
|
||||
mysql->net.mbuff_pos= mysql->net.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)
|
||||
DBUG_RETURN(-1);
|
||||
OPT_SET_EXTENDED_VALUE_INT(&mysql->options, multi_command, MARIADB_COM_MULTI_END);
|
||||
if (mariadb_flush_multi_command(mysql))
|
||||
DBUG_RETURN(-1);
|
||||
break;
|
||||
default:
|
||||
DBUG_RETURN(-1);
|
||||
}
|
||||
OPT_SET_EXTENDED_VALUE_INT(&mysql->options, multi_command, *(my_bool *)arg1);
|
||||
}
|
||||
else
|
||||
@@ -3071,6 +3114,15 @@ 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
|
||||
DBUG_RETURN(-1);
|
||||
break;
|
||||
case MYSQL_OPT_SSL_VERIFY_SERVER_CERT:
|
||||
*((my_bool *)arg)= test(mysql->options.client_flag & CLIENT_SSL_VERIFY_SERVER_CERT);
|
||||
break;
|
||||
@@ -3575,28 +3627,6 @@ static my_socket mariadb_get_socket(MYSQL *mysql)
|
||||
return sock;
|
||||
}
|
||||
|
||||
int mariadb_flush_multi_command(MYSQL *mysql)
|
||||
{
|
||||
int is_multi= 0;
|
||||
int rc;
|
||||
|
||||
/* turn off multi_command option, so simple_command will
|
||||
* stop to add commands to the queue and send packet
|
||||
* to the server */
|
||||
mysql_options(mysql, MARIADB_OPT_COM_MULTI, &is_multi);
|
||||
|
||||
rc= simple_command(mysql, COM_MULTI, mysql->net.mbuff,
|
||||
mysql->net.mbuff_pos - mysql->net.mbuff,
|
||||
1, 0);
|
||||
/* reset multi_buff */
|
||||
mysql->net.mbuff_pos= mysql->net.mbuff;
|
||||
|
||||
if (!rc)
|
||||
rc= mysql->methods->db_read_query_result(mysql);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
my_socket STDCALL
|
||||
mysql_get_socket(MYSQL *mysql)
|
||||
{
|
||||
@@ -3951,7 +3981,8 @@ struct st_mariadb_api MARIADB_API=
|
||||
mysql_stmt_insert_id,
|
||||
mysql_stmt_field_count,
|
||||
mysql_stmt_next_result,
|
||||
mysql_stmt_more_results
|
||||
mysql_stmt_more_results,
|
||||
mariadb_stmt_execute_direct
|
||||
};
|
||||
|
||||
/*
|
||||
|
@@ -113,7 +113,7 @@ my_bool mthd_supported_buffer_type(enum enum_field_types type)
|
||||
}
|
||||
|
||||
static my_bool madb_reset_stmt(MYSQL_STMT *stmt, unsigned int flags);
|
||||
|
||||
static my_bool mysql_stmt_internal_reset(MYSQL_STMT *stmt, my_bool is_close);
|
||||
static int stmt_unbuffered_eof(MYSQL_STMT *stmt, uchar **row)
|
||||
{
|
||||
return MYSQL_NO_DATA;
|
||||
@@ -281,7 +281,7 @@ static int stmt_cursor_fetch(MYSQL_STMT *stmt, uchar **row)
|
||||
int4store(buf, stmt->stmt_id);
|
||||
int4store(buf + STMT_ID_LENGTH, stmt->prefetch_rows);
|
||||
|
||||
if (simple_command(stmt->mysql, COM_STMT_FETCH, (char *)buf, sizeof(buf), 1, stmt))
|
||||
if (stmt->mysql->methods->db_command(stmt->mysql, COM_STMT_FETCH, (char *)buf, sizeof(buf), 1, stmt))
|
||||
DBUG_RETURN(1);
|
||||
|
||||
/* free previously allocated buffer */
|
||||
@@ -774,9 +774,40 @@ my_bool STDCALL mysql_stmt_attr_set(MYSQL_STMT *stmt, enum enum_stmt_attr_type a
|
||||
|
||||
my_bool STDCALL mysql_stmt_bind_param(MYSQL_STMT *stmt, MYSQL_BIND *bind)
|
||||
{
|
||||
MYSQL *mysql= stmt->mysql;
|
||||
DBUG_ENTER("mysql_stmt_bind_param");
|
||||
|
||||
if (stmt->state < MYSQL_STMT_PREPARED) {
|
||||
if (!mysql)
|
||||
{
|
||||
SET_CLIENT_STMT_ERROR(stmt, CR_SERVER_LOST, SQLSTATE_UNKNOWN, 0);
|
||||
DBUG_RETURN(1);
|
||||
}
|
||||
|
||||
/* for mariadb_stmt_execute_direct we need to bind parameters in advance:
|
||||
client has to pass a bind array, where last parameter needs to be set
|
||||
to buffer type MAX_NO_FIELD_TYPES */
|
||||
if (stmt->state < MYSQL_STMT_PREPARED &&
|
||||
!(mysql->server_capabilities & CLIENT_MYSQL))
|
||||
{
|
||||
if (!stmt->params)
|
||||
{
|
||||
int param_count;
|
||||
for(param_count= 0;
|
||||
bind[param_count].buffer_type != MAX_NO_FIELD_TYPES;
|
||||
param_count++);
|
||||
stmt->param_count= param_count;
|
||||
if (stmt->param_count)
|
||||
{
|
||||
if (!(stmt->params= (MYSQL_BIND *)alloc_root(&stmt->mem_root, stmt->param_count * sizeof(MYSQL_BIND))))
|
||||
{
|
||||
SET_CLIENT_STMT_ERROR(stmt, CR_OUT_OF_MEMORY, SQLSTATE_UNKNOWN, 0);
|
||||
DBUG_RETURN(1);
|
||||
}
|
||||
}
|
||||
memset(stmt->params, '\0', stmt->param_count * sizeof(MYSQL_BIND));
|
||||
}
|
||||
}
|
||||
else if (stmt->state < MYSQL_STMT_PREPARED) {
|
||||
SET_CLIENT_STMT_ERROR(stmt, CR_NO_PREPARE_STMT, SQLSTATE_UNKNOWN, 0);
|
||||
DBUG_RETURN(1);
|
||||
}
|
||||
@@ -947,7 +978,7 @@ my_bool STDCALL mysql_stmt_bind_result(MYSQL_STMT *stmt, MYSQL_BIND *bind)
|
||||
DBUG_RETURN(0);
|
||||
}
|
||||
|
||||
my_bool net_stmt_close(MYSQL_STMT *stmt, my_bool remove)
|
||||
static my_bool net_stmt_close(MYSQL_STMT *stmt, my_bool remove)
|
||||
{
|
||||
char stmt_id[STMT_ID_LENGTH];
|
||||
MEM_ROOT *fields_alloc_root= &((MADB_STMT_EXTENSION *)stmt->extension)->fields_alloc_root;
|
||||
@@ -974,7 +1005,8 @@ my_bool net_stmt_close(MYSQL_STMT *stmt, my_bool remove)
|
||||
if (stmt->state > MYSQL_STMT_INITTED)
|
||||
{
|
||||
int4store(stmt_id, stmt->stmt_id);
|
||||
if (simple_command(stmt->mysql,COM_STMT_CLOSE, stmt_id, sizeof(stmt_id), 1, stmt))
|
||||
if (stmt->mysql->methods->db_command(stmt->mysql,COM_STMT_CLOSE, stmt_id,
|
||||
sizeof(stmt_id), 1, stmt))
|
||||
{
|
||||
SET_CLIENT_STMT_ERROR(stmt, stmt->mysql->net.last_errno, stmt->mysql->net.sqlstate, stmt->mysql->net.last_error);
|
||||
return 1;
|
||||
@@ -989,7 +1021,8 @@ my_bool STDCALL mysql_stmt_close(MYSQL_STMT *stmt)
|
||||
DBUG_ENTER("mysql_stmt_close");
|
||||
|
||||
if (stmt && stmt->mysql && stmt->mysql->net.pvio)
|
||||
mysql_stmt_reset(stmt);
|
||||
mysql_stmt_internal_reset(stmt, 1);
|
||||
|
||||
net_stmt_close(stmt, 1);
|
||||
|
||||
my_free(stmt->extension);
|
||||
@@ -1142,6 +1175,7 @@ MYSQL_STMT * STDCALL mysql_stmt_init(MYSQL *mysql)
|
||||
/* fill mysql's stmt list */
|
||||
stmt->list.data= stmt;
|
||||
stmt->mysql= mysql;
|
||||
stmt->stmt_id= -1;
|
||||
mysql->stmts= list_add(mysql->stmts, &stmt->list);
|
||||
|
||||
|
||||
@@ -1226,9 +1260,7 @@ int STDCALL mysql_stmt_prepare(MYSQL_STMT *stmt, const char *query, size_t lengt
|
||||
MYSQL *mysql= stmt->mysql;
|
||||
int rc= 1;
|
||||
DBUG_ENTER("mysql_stmt_prepare");
|
||||
|
||||
if (length == -1)
|
||||
length= strlen(query);
|
||||
enum mariadb_com_multi multi= MARIADB_COM_MULTI_END;
|
||||
|
||||
if (!stmt->mysql)
|
||||
{
|
||||
@@ -1236,6 +1268,11 @@ int STDCALL mysql_stmt_prepare(MYSQL_STMT *stmt, const char *query, size_t lengt
|
||||
DBUG_RETURN(1);
|
||||
}
|
||||
|
||||
if (length == -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);
|
||||
@@ -1259,14 +1296,18 @@ int STDCALL mysql_stmt_prepare(MYSQL_STMT *stmt, const char *query, size_t lengt
|
||||
stmt->field_count= 0;
|
||||
|
||||
int4store(stmt_id, stmt->stmt_id);
|
||||
if (simple_command(mysql, COM_STMT_CLOSE, stmt_id, sizeof(stmt_id), 1, stmt))
|
||||
if (mysql->methods->db_command(mysql, COM_STMT_CLOSE, stmt_id,
|
||||
sizeof(stmt_id), 1, stmt))
|
||||
goto fail;
|
||||
}
|
||||
if (simple_command(mysql, COM_STMT_PREPARE, query, length, 1, stmt))
|
||||
if (mysql->methods->db_command(mysql, COM_STMT_PREPARE, query, length, 1, stmt))
|
||||
goto fail;
|
||||
|
||||
if (stmt->mysql->methods->db_read_prepare_response &&
|
||||
stmt->mysql->methods->db_read_prepare_response(stmt))
|
||||
if (multi == MARIADB_COM_MULTI_BEGIN)
|
||||
return 0;
|
||||
|
||||
if (mysql->methods->db_read_prepare_response &&
|
||||
mysql->methods->db_read_prepare_response(stmt))
|
||||
goto fail;
|
||||
|
||||
/* metadata not supported yet */
|
||||
@@ -1346,7 +1387,8 @@ int STDCALL mysql_stmt_store_result(MYSQL_STMT *stmt)
|
||||
int4store(buff, stmt->stmt_id);
|
||||
int4store(buff + STMT_ID_LENGTH, (int)~0);
|
||||
|
||||
if (simple_command(stmt->mysql, COM_STMT_FETCH, buff, sizeof(buff), 1, stmt))
|
||||
if (stmt->mysql->methods->db_command(stmt->mysql, COM_STMT_FETCH,
|
||||
buff, sizeof(buff), 1, stmt))
|
||||
DBUG_RETURN(1);
|
||||
/* todo: cursor */
|
||||
}
|
||||
@@ -1442,63 +1484,17 @@ static int madb_alloc_stmt_fields(MYSQL_STMT *stmt)
|
||||
DBUG_RETURN(0);
|
||||
}
|
||||
|
||||
|
||||
int STDCALL mysql_stmt_execute(MYSQL_STMT *stmt)
|
||||
int stmt_read_execute_response(MYSQL_STMT *stmt)
|
||||
{
|
||||
MYSQL *mysql= stmt->mysql;
|
||||
char *request;
|
||||
int ret;
|
||||
size_t request_len= 0;
|
||||
|
||||
DBUG_ENTER("stmt_read_execute_response");
|
||||
|
||||
DBUG_ENTER("mysql_stmt_execute");
|
||||
|
||||
if (!stmt->mysql)
|
||||
{
|
||||
SET_CLIENT_STMT_ERROR(stmt, CR_SERVER_LOST, SQLSTATE_UNKNOWN, 0);
|
||||
if (!mysql)
|
||||
DBUG_RETURN(1);
|
||||
}
|
||||
|
||||
if (stmt->state < MYSQL_STMT_PREPARED)
|
||||
{
|
||||
SET_CLIENT_ERROR(mysql, CR_COMMANDS_OUT_OF_SYNC, SQLSTATE_UNKNOWN, 0);
|
||||
SET_CLIENT_STMT_ERROR(stmt, CR_COMMANDS_OUT_OF_SYNC, SQLSTATE_UNKNOWN, 0);
|
||||
DBUG_RETURN(1);
|
||||
}
|
||||
|
||||
if (stmt->param_count && !stmt->bind_param_done)
|
||||
{
|
||||
SET_CLIENT_STMT_ERROR(stmt, CR_PARAMS_NOT_BOUND, SQLSTATE_UNKNOWN, 0);
|
||||
DBUG_RETURN(1);
|
||||
}
|
||||
|
||||
if (stmt->state == MYSQL_STMT_WAITING_USE_OR_STORE)
|
||||
{
|
||||
stmt->default_rset_handler = _mysql_stmt_use_result;
|
||||
stmt->default_rset_handler(stmt);
|
||||
}
|
||||
if (stmt->state > MYSQL_STMT_WAITING_USE_OR_STORE && stmt->state < MYSQL_STMT_FETCH_DONE && !stmt->result.data)
|
||||
{
|
||||
mysql->methods->db_stmt_flush_unbuffered(stmt);
|
||||
stmt->state= MYSQL_STMT_PREPARED;
|
||||
stmt->mysql->status= MYSQL_STATUS_READY;
|
||||
}
|
||||
|
||||
/* clear data, in case mysql_stmt_store_result was called */
|
||||
if (stmt->result.data)
|
||||
{
|
||||
free_root(&stmt->result.alloc, MYF(MY_KEEP_PREALLOC));
|
||||
stmt->result_cursor= stmt->result.data= 0;
|
||||
stmt->result.rows= 0;
|
||||
}
|
||||
request= (char *)mysql_stmt_execute_generate_request(stmt, &request_len);
|
||||
DBUG_PRINT("info",("request_len=%ld", request_len));
|
||||
|
||||
ret= test(simple_command(mysql, COM_STMT_EXECUTE, request, request_len, 1, stmt) ||
|
||||
(mysql && mysql->methods->db_read_stmt_result && mysql->methods->db_read_stmt_result(mysql)));
|
||||
if (request)
|
||||
my_free(request);
|
||||
|
||||
int ret= test((mysql->methods->db_read_stmt_result &&
|
||||
mysql->methods->db_read_stmt_result(mysql)));
|
||||
/* if a reconnect occured, our connection handle is invalid */
|
||||
if (!stmt->mysql)
|
||||
DBUG_RETURN(1);
|
||||
@@ -1615,6 +1611,78 @@ int STDCALL mysql_stmt_execute(MYSQL_STMT *stmt)
|
||||
DBUG_RETURN(0);
|
||||
}
|
||||
|
||||
int STDCALL mysql_stmt_execute(MYSQL_STMT *stmt)
|
||||
{
|
||||
MYSQL *mysql= stmt->mysql;
|
||||
char *request;
|
||||
int ret;
|
||||
size_t request_len= 0;
|
||||
enum mariadb_com_multi multi= MARIADB_COM_MULTI_END;
|
||||
|
||||
DBUG_ENTER("mysql_stmt_execute");
|
||||
|
||||
if (!stmt->mysql)
|
||||
{
|
||||
SET_CLIENT_STMT_ERROR(stmt, CR_SERVER_LOST, SQLSTATE_UNKNOWN, 0);
|
||||
DBUG_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);
|
||||
SET_CLIENT_STMT_ERROR(stmt, CR_COMMANDS_OUT_OF_SYNC, SQLSTATE_UNKNOWN, 0);
|
||||
DBUG_RETURN(1);
|
||||
}
|
||||
|
||||
if (stmt->param_count && !stmt->bind_param_done)
|
||||
{
|
||||
SET_CLIENT_STMT_ERROR(stmt, CR_PARAMS_NOT_BOUND, SQLSTATE_UNKNOWN, 0);
|
||||
DBUG_RETURN(1);
|
||||
}
|
||||
|
||||
if (stmt->state == MYSQL_STMT_WAITING_USE_OR_STORE)
|
||||
{
|
||||
stmt->default_rset_handler = _mysql_stmt_use_result;
|
||||
stmt->default_rset_handler(stmt);
|
||||
}
|
||||
if (stmt->state > MYSQL_STMT_WAITING_USE_OR_STORE && stmt->state < MYSQL_STMT_FETCH_DONE && !stmt->result.data)
|
||||
{
|
||||
mysql->methods->db_stmt_flush_unbuffered(stmt);
|
||||
stmt->state= MYSQL_STMT_PREPARED;
|
||||
stmt->mysql->status= MYSQL_STATUS_READY;
|
||||
}
|
||||
|
||||
/* clear data, in case mysql_stmt_store_result was called */
|
||||
if (stmt->result.data)
|
||||
{
|
||||
free_root(&stmt->result.alloc, MYF(MY_KEEP_PREALLOC));
|
||||
stmt->result_cursor= stmt->result.data= 0;
|
||||
stmt->result.rows= 0;
|
||||
}
|
||||
request= (char *)mysql_stmt_execute_generate_request(stmt, &request_len);
|
||||
DBUG_PRINT("info",("request_len=%ld", request_len));
|
||||
|
||||
ret= stmt->mysql->methods->db_command(mysql, COM_STMT_EXECUTE, request,
|
||||
request_len, 1, stmt);
|
||||
|
||||
if (request)
|
||||
my_free(request);
|
||||
|
||||
if (ret)
|
||||
{
|
||||
SET_CLIENT_STMT_ERROR(stmt, mysql->net.last_errno, mysql->net.sqlstate,
|
||||
mysql->net.last_error);
|
||||
DBUG_RETURN(1);
|
||||
}
|
||||
|
||||
if (multi == MARIADB_COM_MULTI_BEGIN)
|
||||
DBUG_RETURN(0);
|
||||
|
||||
DBUG_RETURN(stmt_read_execute_response(stmt));
|
||||
}
|
||||
|
||||
static my_bool madb_reset_stmt(MYSQL_STMT *stmt, unsigned int flags)
|
||||
{
|
||||
MYSQL *mysql= stmt->mysql;
|
||||
@@ -1670,11 +1738,13 @@ static my_bool madb_reset_stmt(MYSQL_STMT *stmt, unsigned int flags)
|
||||
if (flags & MADB_RESET_SERVER)
|
||||
{
|
||||
/* reset statement on server side */
|
||||
if (stmt->mysql && stmt->mysql->status == MYSQL_STATUS_READY)
|
||||
if (stmt->mysql && stmt->mysql->status == MYSQL_STATUS_READY &&
|
||||
stmt->mysql->net.pvio)
|
||||
{
|
||||
unsigned char cmd_buf[STMT_ID_LENGTH];
|
||||
int4store(cmd_buf, stmt->stmt_id);
|
||||
if ((ret= simple_command(mysql,COM_STMT_RESET, (char *)cmd_buf, sizeof(cmd_buf), 0, stmt)))
|
||||
if ((ret= stmt->mysql->methods->db_command(mysql,COM_STMT_RESET, (char *)cmd_buf,
|
||||
sizeof(cmd_buf), 0, stmt)))
|
||||
{
|
||||
SET_CLIENT_STMT_ERROR(stmt, mysql->net.last_errno, mysql->net.sqlstate,
|
||||
mysql->net.last_error);
|
||||
@@ -1698,13 +1768,13 @@ static my_bool madb_reset_stmt(MYSQL_STMT *stmt, unsigned int flags)
|
||||
DBUG_RETURN(ret);
|
||||
}
|
||||
|
||||
my_bool STDCALL mysql_stmt_reset(MYSQL_STMT *stmt)
|
||||
static my_bool mysql_stmt_internal_reset(MYSQL_STMT *stmt, my_bool is_close)
|
||||
{
|
||||
MYSQL *mysql= stmt->mysql;
|
||||
my_bool ret= 1;
|
||||
unsigned int flags= MADB_RESET_LONGDATA | MADB_RESET_BUFFER | MADB_RESET_ERROR;
|
||||
|
||||
DBUG_ENTER("mysql_stmt_reset");
|
||||
DBUG_ENTER("mysql_stmt_internal_reset");
|
||||
|
||||
if (!mysql)
|
||||
{
|
||||
@@ -1739,6 +1809,8 @@ my_bool STDCALL mysql_stmt_reset(MYSQL_STMT *stmt)
|
||||
stmt->mysql->status= MYSQL_STATUS_READY;
|
||||
}
|
||||
}
|
||||
if (!stmt->execute_count)
|
||||
if (!is_close)
|
||||
ret= madb_reset_stmt(stmt, MADB_RESET_SERVER);
|
||||
}
|
||||
stmt->state= MYSQL_STMT_PREPARED;
|
||||
@@ -1770,7 +1842,13 @@ MYSQL_RES * STDCALL mysql_stmt_result_metadata(MYSQL_STMT *stmt)
|
||||
res->eof= 1;
|
||||
res->fields= stmt->fields;
|
||||
res->field_count= stmt->field_count;
|
||||
DBUG_RETURN(res);}
|
||||
DBUG_RETURN(res);
|
||||
}
|
||||
|
||||
my_bool STDCALL mysql_stmt_reset(MYSQL_STMT *stmt)
|
||||
{
|
||||
return mysql_stmt_internal_reset(stmt, 0);
|
||||
}
|
||||
|
||||
const char * STDCALL mysql_stmt_sqlstate(MYSQL_STMT *stmt)
|
||||
{
|
||||
@@ -1828,7 +1906,8 @@ my_bool STDCALL mysql_stmt_send_long_data(MYSQL_STMT *stmt, uint param_number,
|
||||
int2store(cmd_buff + STMT_ID_LENGTH, param_number);
|
||||
memcpy(cmd_buff + STMT_ID_LENGTH + 2, data, length);
|
||||
stmt->params[param_number].long_data_used= 1;
|
||||
ret= simple_command(stmt->mysql, COM_STMT_SEND_LONG_DATA, (char *)cmd_buff, packet_len, 1, stmt);
|
||||
ret= stmt->mysql->methods->db_command(stmt->mysql, COM_STMT_SEND_LONG_DATA,
|
||||
(char *)cmd_buff, packet_len, 1, stmt);
|
||||
my_free(cmd_buff);
|
||||
DBUG_RETURN(ret);
|
||||
}
|
||||
@@ -1915,3 +1994,75 @@ int STDCALL mysql_stmt_next_result(MYSQL_STMT *stmt)
|
||||
|
||||
DBUG_RETURN(rc);
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
SET_CLIENT_STMT_ERROR(stmt, CR_SERVER_LOST, SQLSTATE_UNKNOWN, 0);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (mysql_optionsv(mysql, MARIADB_OPT_COM_MULTI, &multi))
|
||||
goto fail;
|
||||
|
||||
if (length == -1)
|
||||
length= strlen(stmt_str);
|
||||
|
||||
if (mysql_stmt_prepare(stmt, stmt_str, length))
|
||||
goto fail;
|
||||
|
||||
stmt->state= MYSQL_STMT_PREPARED;
|
||||
|
||||
if (mysql_stmt_execute(stmt))
|
||||
goto fail;
|
||||
|
||||
multi= MARIADB_COM_MULTI_END;
|
||||
if (mysql_optionsv(mysql, MARIADB_OPT_COM_MULTI, &multi))
|
||||
goto fail;
|
||||
|
||||
/* read prepare response */
|
||||
if (mysql->methods->db_read_prepare_response &&
|
||||
mysql->methods->db_read_prepare_response(stmt))
|
||||
goto fail;
|
||||
|
||||
/* metadata not supported yet */
|
||||
|
||||
if (stmt->param_count &&
|
||||
stmt->mysql->methods->db_stmt_get_param_metadata(stmt))
|
||||
{
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* allocated bind buffer for parameters */
|
||||
if (stmt->field_count &&
|
||||
stmt->mysql->methods->db_stmt_get_result_metadata(stmt))
|
||||
{
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* allocated bind buffer for result */
|
||||
if (stmt->field_count)
|
||||
{
|
||||
MEM_ROOT *fields_alloc_root= &((MADB_STMT_EXTENSION *)stmt->extension)->fields_alloc_root;
|
||||
if (!(stmt->bind= (MYSQL_BIND *)alloc_root(fields_alloc_root, stmt->field_count * sizeof(MYSQL_BIND))))
|
||||
{
|
||||
SET_CLIENT_STMT_ERROR(stmt, CR_OUT_OF_MEMORY, SQLSTATE_UNKNOWN, 0);
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
stmt->state = MYSQL_STMT_PREPARED;
|
||||
|
||||
/* read execute response packet */
|
||||
return stmt_read_execute_response(stmt);
|
||||
fail:
|
||||
stmt->state= MYSQL_STMT_INITTED;
|
||||
SET_CLIENT_STMT_ERROR(stmt, mysql->net.last_errno, mysql->net.sqlstate,
|
||||
mysql->net.last_error);
|
||||
return 1;
|
||||
}
|
||||
|
@@ -169,12 +169,6 @@ static int send_client_reply_packet(MCPVIO_EXT *mpvio,
|
||||
if (mysql->client_flag & CLIENT_MULTI_STATEMENTS)
|
||||
mysql->client_flag|= CLIENT_MULTI_RESULTS;
|
||||
|
||||
/* if server supports extended MariaDB extended protocol, we will unset
|
||||
CLIENT_LONG_PASSWORD and send extended client capabilities in last
|
||||
four of 23 unused bytes */
|
||||
if (mysql->server_capabilities & MARIADB_CLIENT_EXTENDED_FLAGS)
|
||||
mysql->client_flag &= ~CLIENT_LONG_PASSWORD;
|
||||
|
||||
#if defined(HAVE_SSL) && !defined(EMBEDDED_LIBRARY)
|
||||
if (mysql->options.ssl_key || mysql->options.ssl_cert ||
|
||||
mysql->options.ssl_ca || mysql->options.ssl_capath ||
|
||||
@@ -218,7 +212,7 @@ static int send_client_reply_packet(MCPVIO_EXT *mpvio,
|
||||
int4store(buff+4, net->max_packet_size);
|
||||
buff[8]= (char) mysql->charset->nr;
|
||||
bzero(buff + 9, 32-9);
|
||||
if (mysql->server_capabilities & MARIADB_CLIENT_EXTENDED_FLAGS)
|
||||
if (!(mysql->server_capabilities & CLIENT_MYSQL))
|
||||
{
|
||||
mysql->client_flag |= MARIADB_CLIENT_SUPPORTED_FLAGS;
|
||||
int4store(buff + 28, mysql->client_flag >> 32);
|
||||
|
@@ -3,26 +3,30 @@
|
||||
|
||||
#include "my_test.h"
|
||||
|
||||
my_bool have_com_multi= 1;
|
||||
|
||||
static int com_multi_1(MYSQL *mysql)
|
||||
{
|
||||
int rc;
|
||||
MYSQL_RES *res;
|
||||
my_bool is_multi= 1;
|
||||
enum mariadb_com_multi status;
|
||||
|
||||
/* TEST a simple query before COM_MULTI */
|
||||
|
||||
rc= mysql_query(mysql, "select 1");
|
||||
check_mysql_rc(rc, mysql);
|
||||
FAIL_UNLESS(res, "1 simple query no result");
|
||||
res= mysql_store_result(mysql);
|
||||
FAIL_UNLESS(res, "1 simple query no result");
|
||||
|
||||
mysql_free_result(res);
|
||||
|
||||
/* TEST COM_MULTI */
|
||||
|
||||
if (mysql_options(mysql, MARIADB_OPT_COM_MULTI, &is_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;
|
||||
}
|
||||
|
||||
@@ -30,7 +34,8 @@ static int com_multi_1(MYSQL *mysql)
|
||||
|
||||
rc= mysql_query(mysql, "select 2");
|
||||
|
||||
rc= mariadb_flush_multi_command(mysql);
|
||||
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);
|
||||
@@ -48,10 +53,6 @@ static int com_multi_1(MYSQL *mysql)
|
||||
strcmp(res->fields[0].name, "2") == 0,
|
||||
"1 of 2 simple query in batch wrong result");
|
||||
mysql_free_result(res);
|
||||
/* WHOLE batch result (OK) */
|
||||
rc= mysql_next_result(mysql);
|
||||
res= mysql_store_result(mysql);
|
||||
FAIL_UNLESS(res == NULL, "rows instead of batch OK");
|
||||
rc= mysql_next_result(mysql);
|
||||
FAIL_UNLESS(rc == -1, "more then 2 results");
|
||||
|
||||
@@ -69,8 +70,86 @@ static int com_multi_1(MYSQL *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: %d", mysql_stmt_affected_rows(stmt));
|
||||
diag("stmt_id: %d", 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[3];
|
||||
int intval= 3, rc;
|
||||
int i;
|
||||
char *varval= "com_multi_ps2";
|
||||
|
||||
|
||||
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) * 3);
|
||||
bind[0].buffer_type= MYSQL_TYPE_SHORT;
|
||||
bind[0].buffer= &intval;
|
||||
bind[1].buffer_type= MYSQL_TYPE_STRING;
|
||||
bind[1].buffer= varval;
|
||||
bind[1].buffer_length= strlen(varval);
|
||||
bind[2].buffer_type= MAX_NO_FIELD_TYPES;
|
||||
|
||||
for (i=0; i < 2; i++)
|
||||
{
|
||||
stmt= mysql_stmt_init(mysql);
|
||||
rc= mysql_stmt_bind_param(stmt, bind);
|
||||
check_stmt_rc(rc, stmt);
|
||||
|
||||
rc= mariadb_stmt_execute_direct(stmt, "INSERT INTO t1 VALUES (1,'foo')", -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;
|
||||
}
|
||||
|
||||
struct my_tests_st my_tests[] = {
|
||||
{"com_multi_1", com_multi_1, 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},
|
||||
{NULL, NULL, 0, 0, NULL, NULL}
|
||||
};
|
||||
|
||||
|
@@ -189,6 +189,8 @@ int do_verify_prepare_field(MYSQL_RES *result,
|
||||
FAIL_UNLESS(strcmp(field->table, table) == 0, "field->table differs");
|
||||
if (org_table)
|
||||
FAIL_UNLESS(strcmp(field->org_table, org_table) == 0, "field->org_table differs");
|
||||
if (strcmp(field->db,db))
|
||||
diag("%s / %s", field->db, db);
|
||||
FAIL_UNLESS(strcmp(field->db, db) == 0, "field->db differs");
|
||||
/*
|
||||
Character set should be taken into account for multibyte encodings, such
|
||||
|
@@ -830,6 +830,7 @@ static int test_prepare_alter(MYSQL *mysql)
|
||||
FAIL_IF(!(mysql_real_connect(mysql_new, hostname, username, password,
|
||||
schema, port, socketname, 0)), "mysql_real_connect failed");
|
||||
rc= mysql_query(mysql_new, "ALTER TABLE test_prep_alter change id id_new varchar(20)");
|
||||
diag("Error: %d %s", mysql_errno(mysql_new), mysql_error(mysql_new));
|
||||
check_mysql_rc(rc, mysql_new);
|
||||
mysql_close(mysql_new);
|
||||
|
||||
|
Reference in New Issue
Block a user