You've already forked mariadb-connector-c
mirror of
https://github.com/mariadb-corporation/mariadb-connector-c.git
synced 2025-08-07 02:42:49 +03:00
initial implementation for MDEV-12471
This commit is contained in:
@@ -93,6 +93,7 @@ enum enum_server_command
|
|||||||
COM_DAEMON= 29,
|
COM_DAEMON= 29,
|
||||||
COM_UNSUPPORTED= 30,
|
COM_UNSUPPORTED= 30,
|
||||||
COM_RESET_CONNECTION = 31,
|
COM_RESET_CONNECTION = 31,
|
||||||
|
COM_STMT_BULK_EXECUTE = 250,
|
||||||
COM_MULTI = 254,
|
COM_MULTI = 254,
|
||||||
COM_END
|
COM_END
|
||||||
};
|
};
|
||||||
@@ -135,7 +136,7 @@ enum enum_server_command
|
|||||||
#define REFRESH_READ_LOCK 16384 /* Lock tables for read */
|
#define REFRESH_READ_LOCK 16384 /* Lock tables for read */
|
||||||
#define REFRESH_FAST 32768 /* Intern flag */
|
#define REFRESH_FAST 32768 /* Intern flag */
|
||||||
|
|
||||||
#define CLIENT_MYSQL 1
|
#define CLIENT_MYSQL 1
|
||||||
#define CLIENT_FOUND_ROWS 2 /* Found instead of affected rows */
|
#define CLIENT_FOUND_ROWS 2 /* Found instead of affected rows */
|
||||||
#define CLIENT_LONG_FLAG 4 /* Get all column flags */
|
#define CLIENT_LONG_FLAG 4 /* Get all column flags */
|
||||||
#define CLIENT_CONNECT_WITH_DB 8 /* One can specify db on connect */
|
#define CLIENT_CONNECT_WITH_DB 8 /* One can specify db on connect */
|
||||||
|
@@ -29,8 +29,7 @@
|
|||||||
#define MADB_BIND_DUMMY 1
|
#define MADB_BIND_DUMMY 1
|
||||||
|
|
||||||
#define MARIADB_STMT_BULK_SUPPORTED(stmt)\
|
#define MARIADB_STMT_BULK_SUPPORTED(stmt)\
|
||||||
((stmt)->array_size > 0 && \
|
((stmt)->mysql && \
|
||||||
(stmt)->mysql && \
|
|
||||||
(!((stmt)->mysql->server_capabilities & CLIENT_MYSQL) &&\
|
(!((stmt)->mysql->server_capabilities & CLIENT_MYSQL) &&\
|
||||||
((stmt)->mysql->extension->mariadb_server_capabilities & MARIADB_CLIENT_STMT_BULK_OPERATIONS >> 32)))
|
((stmt)->mysql->extension->mariadb_server_capabilities & MARIADB_CLIENT_STMT_BULK_OPERATIONS >> 32)))
|
||||||
|
|
||||||
|
@@ -207,7 +207,7 @@ restart:
|
|||||||
|
|
||||||
if (last_errno== 65535 &&
|
if (last_errno== 65535 &&
|
||||||
((mariadb_connection(mysql) && (mysql->server_capabilities & CLIENT_PROGRESS)) ||
|
((mariadb_connection(mysql) && (mysql->server_capabilities & CLIENT_PROGRESS)) ||
|
||||||
(!(mysql->extension->mariadb_server_capabilities & MARIADB_CLIENT_PROGRESS >> 32))))
|
(!(mysql->extension->mariadb_server_capabilities & MARIADB_CLIENT_PROGRESS << 32))))
|
||||||
{
|
{
|
||||||
if (cli_report_progress(mysql, (uchar *)pos, (uint) (len-1)))
|
if (cli_report_progress(mysql, (uchar *)pos, (uint) (len-1)))
|
||||||
{
|
{
|
||||||
@@ -1483,7 +1483,8 @@ MYSQL *mthd_my_real_connect(MYSQL *mysql, const char *host, const char *user,
|
|||||||
net->compress= 1;
|
net->compress= 1;
|
||||||
|
|
||||||
/* last part: select default db */
|
/* last part: select default db */
|
||||||
if (db && !mysql->db)
|
if (!(mysql->server_capabilities & CLIENT_CONNECT_WITH_DB) &&
|
||||||
|
(db && !mysql->db))
|
||||||
{
|
{
|
||||||
if (mysql_select_db(mysql, db))
|
if (mysql_select_db(mysql, db))
|
||||||
{
|
{
|
||||||
|
@@ -628,8 +628,8 @@ int store_param(MYSQL_STMT *stmt, int column, unsigned char **p, unsigned long r
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* {{{ mysqlnd_stmt_execute_generate_request */
|
/* {{{ mysqlnd_stmt_execute_generate_simple_request */
|
||||||
unsigned char* mysql_stmt_execute_generate_request(MYSQL_STMT *stmt, size_t *request_len)
|
unsigned char* mysql_stmt_execute_generate_simple_request(MYSQL_STMT *stmt, size_t *request_len)
|
||||||
{
|
{
|
||||||
/* execute packet has the following format:
|
/* execute packet has the following format:
|
||||||
Offset Length Description
|
Offset Length Description
|
||||||
@@ -648,30 +648,17 @@ unsigned char* mysql_stmt_execute_generate_request(MYSQL_STMT *stmt, size_t *req
|
|||||||
unsigned flag (32768)
|
unsigned flag (32768)
|
||||||
indicator variable exists (16384)
|
indicator variable exists (16384)
|
||||||
------------------------------------------
|
------------------------------------------
|
||||||
Pre 10.2 protocol
|
|
||||||
n data from bind_buffer
|
n data from bind_buffer
|
||||||
10.2 protocol
|
|
||||||
if indicator variable exists
|
|
||||||
1st byte: indicator variable
|
|
||||||
2nd-n: data
|
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
size_t length= 1024;
|
size_t length= 1024;
|
||||||
size_t free_bytes= 0;
|
size_t free_bytes= 0;
|
||||||
size_t null_byte_offset= 0;
|
size_t null_byte_offset= 0;
|
||||||
uint i, j, num_rows= 1;
|
uint i;
|
||||||
|
|
||||||
uchar *start= NULL, *p;
|
uchar *start= NULL, *p;
|
||||||
|
|
||||||
if (!MARIADB_STMT_BULK_SUPPORTED(stmt) && stmt->array_size > 0)
|
|
||||||
{
|
|
||||||
stmt_set_error(stmt, CR_FUNCTION_NOT_SUPPORTED, SQLSTATE_UNKNOWN,
|
|
||||||
CER(CR_FUNCTION_NOT_SUPPORTED), "Bulk operation");
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* preallocate length bytes */
|
/* preallocate length bytes */
|
||||||
/* check: gr */
|
/* check: gr */
|
||||||
if (!(start= p= (uchar *)malloc(length)))
|
if (!(start= p= (uchar *)malloc(length)))
|
||||||
@@ -683,34 +670,28 @@ unsigned char* mysql_stmt_execute_generate_request(MYSQL_STMT *stmt, size_t *req
|
|||||||
/* flags is 4 bytes, we store just 1 */
|
/* flags is 4 bytes, we store just 1 */
|
||||||
int1store(p, (unsigned char) stmt->flags);
|
int1store(p, (unsigned char) stmt->flags);
|
||||||
p++;
|
p++;
|
||||||
if (MARIADB_STMT_BULK_SUPPORTED(stmt) && stmt->array_size)
|
|
||||||
num_rows= stmt->array_size;
|
|
||||||
int4store(p, num_rows);
|
|
||||||
p+= 4;
|
|
||||||
|
|
||||||
if (!stmt->param_count && stmt->prebind_params)
|
int4store(p, 1);
|
||||||
stmt->param_count= stmt->prebind_params;
|
p+= 4;
|
||||||
|
|
||||||
if (stmt->param_count)
|
if (stmt->param_count)
|
||||||
{
|
{
|
||||||
if (!stmt->array_size)
|
size_t null_count= (stmt->param_count + 7) / 8;
|
||||||
|
|
||||||
|
free_bytes= length - (p - start);
|
||||||
|
if (null_count + 20 > free_bytes)
|
||||||
{
|
{
|
||||||
size_t null_count= (stmt->param_count + 7) / 8;
|
size_t offset= p - start;
|
||||||
|
length+= offset + null_count + 20;
|
||||||
free_bytes= length - (p - start);
|
if (!(start= (uchar *)realloc(start, length)))
|
||||||
if (null_count + 20 > free_bytes)
|
goto mem_error;
|
||||||
{
|
p= start + offset;
|
||||||
size_t offset= p - start;
|
|
||||||
length+= offset + null_count + 20;
|
|
||||||
if (!(start= (uchar *)realloc(start, length)))
|
|
||||||
goto mem_error;
|
|
||||||
p= start + offset;
|
|
||||||
}
|
|
||||||
|
|
||||||
null_byte_offset= p - start;
|
|
||||||
memset(p, 0, null_count);
|
|
||||||
p += null_count;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
null_byte_offset= p - start;
|
||||||
|
memset(p, 0, null_count);
|
||||||
|
p += null_count;
|
||||||
|
|
||||||
int1store(p, stmt->send_types_to_server);
|
int1store(p, stmt->send_types_to_server);
|
||||||
p++;
|
p++;
|
||||||
|
|
||||||
@@ -734,49 +715,200 @@ unsigned char* mysql_stmt_execute_generate_request(MYSQL_STMT *stmt, size_t *req
|
|||||||
/* this differs from mysqlnd, c api supports unsinged !! */
|
/* this differs from mysqlnd, c api supports unsinged !! */
|
||||||
uint buffer_type= stmt->params[i].buffer_type | (stmt->params[i].is_unsigned ? 32768 : 0);
|
uint buffer_type= stmt->params[i].buffer_type | (stmt->params[i].is_unsigned ? 32768 : 0);
|
||||||
/* check if parameter requires indicator variable */
|
/* check if parameter requires indicator variable */
|
||||||
if (MARIADB_STMT_BULK_SUPPORTED(stmt) &&
|
|
||||||
(stmt->params[i].u.indicator || stmt->params[i].buffer_type == MYSQL_TYPE_NULL))
|
|
||||||
buffer_type|= 16384;
|
|
||||||
int2store(p, buffer_type);
|
int2store(p, buffer_type);
|
||||||
p+= 2;
|
p+= 2;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* calculate data size */
|
/* calculate data size */
|
||||||
for (j=0; j < num_rows; j++)
|
for (i=0; i < stmt->param_count; i++)
|
||||||
|
{
|
||||||
|
size_t size= 0;
|
||||||
|
my_bool has_data= TRUE;
|
||||||
|
|
||||||
|
if (stmt->params[i].long_data_used)
|
||||||
|
{
|
||||||
|
has_data= FALSE;
|
||||||
|
stmt->params[i].long_data_used= 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (has_data)
|
||||||
|
{
|
||||||
|
switch (stmt->params[i].buffer_type) {
|
||||||
|
case MYSQL_TYPE_NULL:
|
||||||
|
has_data= FALSE;
|
||||||
|
break;
|
||||||
|
case MYSQL_TYPE_TINY_BLOB:
|
||||||
|
case MYSQL_TYPE_MEDIUM_BLOB:
|
||||||
|
case MYSQL_TYPE_LONG_BLOB:
|
||||||
|
case MYSQL_TYPE_BLOB:
|
||||||
|
case MYSQL_TYPE_VARCHAR:
|
||||||
|
case MYSQL_TYPE_VAR_STRING:
|
||||||
|
case MYSQL_TYPE_STRING:
|
||||||
|
case MYSQL_TYPE_JSON:
|
||||||
|
case MYSQL_TYPE_DECIMAL:
|
||||||
|
case MYSQL_TYPE_NEWDECIMAL:
|
||||||
|
case MYSQL_TYPE_GEOMETRY:
|
||||||
|
case MYSQL_TYPE_NEWDATE:
|
||||||
|
case MYSQL_TYPE_ENUM:
|
||||||
|
case MYSQL_TYPE_BIT:
|
||||||
|
case MYSQL_TYPE_SET:
|
||||||
|
size+= 5; /* max 8 bytes for size */
|
||||||
|
size+= (size_t)ma_get_length(stmt, i, 0);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
size+= mysql_ps_fetch_functions[stmt->params[i].buffer_type].pack_len;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
free_bytes= length - (p - start);
|
||||||
|
if (free_bytes < size + 20)
|
||||||
|
{
|
||||||
|
size_t offset= p - start;
|
||||||
|
length= MAX(2 * length, offset + size + 20);
|
||||||
|
if (!(start= (uchar *)realloc(start, length)))
|
||||||
|
goto mem_error;
|
||||||
|
p= start + offset;
|
||||||
|
}
|
||||||
|
if (((stmt->params[i].is_null && *stmt->params[i].is_null) ||
|
||||||
|
stmt->params[i].buffer_type == MYSQL_TYPE_NULL ||
|
||||||
|
!stmt->params[i].buffer))
|
||||||
|
{
|
||||||
|
has_data= FALSE;
|
||||||
|
(start + null_byte_offset)[i/8] |= (unsigned char) (1 << (i & 7));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (has_data)
|
||||||
|
{
|
||||||
|
store_param(stmt, i, &p, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
stmt->send_types_to_server= 0;
|
||||||
|
*request_len = (size_t)(p - start);
|
||||||
|
return start;
|
||||||
|
mem_error:
|
||||||
|
SET_CLIENT_STMT_ERROR(stmt, CR_OUT_OF_MEMORY, SQLSTATE_UNKNOWN, 0);
|
||||||
|
free(start);
|
||||||
|
*request_len= 0;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
/* }}} */
|
||||||
|
|
||||||
|
/* {{{ mysqlnd_stmt_execute_generate_bulk_request */
|
||||||
|
unsigned char* mysql_stmt_execute_generate_bulk_request(MYSQL_STMT *stmt, size_t *request_len)
|
||||||
|
{
|
||||||
|
/* execute packet has the following format:
|
||||||
|
Offset Length Description
|
||||||
|
-----------------------------------------
|
||||||
|
0 4 Statement id
|
||||||
|
4 2 Flags (cursor type):
|
||||||
|
STMT_BULK_SEND_TYPES = 64
|
||||||
|
STMT_BULK_RETURN_AUTO_ID = 128
|
||||||
|
6 4 array size
|
||||||
|
-----------------------------------------
|
||||||
|
if (stmt->send_types_to_server):
|
||||||
|
for (i=0; i < param_count; i++)
|
||||||
|
1st byte: parameter type
|
||||||
|
2nd byte flag:
|
||||||
|
unsigned flag (32768)
|
||||||
|
------------------------------------------
|
||||||
|
for (i=0; i < param_count; i++)
|
||||||
|
1 indicator variable
|
||||||
|
STMT_INDICATOR_NONE 0
|
||||||
|
STMT_INDICATOR_NULL 1
|
||||||
|
STMT_INDICATOR_DEFAULT 2
|
||||||
|
STMT_INDICATOR_IGNORE 3
|
||||||
|
n data from bind buffer
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
size_t length= 1024;
|
||||||
|
size_t free_bytes= 0;
|
||||||
|
ushort flags= 0;
|
||||||
|
uint i, j;
|
||||||
|
|
||||||
|
uchar *start= NULL, *p;
|
||||||
|
|
||||||
|
if (!MARIADB_STMT_BULK_SUPPORTED(stmt))
|
||||||
|
{
|
||||||
|
stmt_set_error(stmt, CR_FUNCTION_NOT_SUPPORTED, SQLSTATE_UNKNOWN,
|
||||||
|
CER(CR_FUNCTION_NOT_SUPPORTED), "Bulk operation");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* preallocate length bytes */
|
||||||
|
if (!(start= p= (uchar *)malloc(length)))
|
||||||
|
goto mem_error;
|
||||||
|
|
||||||
|
int4store(p, stmt->stmt_id);
|
||||||
|
p += STMT_ID_LENGTH;
|
||||||
|
|
||||||
|
/* todo: request to return auto generated ids */
|
||||||
|
if (stmt->send_types_to_server)
|
||||||
|
flags|= 0x40;
|
||||||
|
int2store(p, flags);
|
||||||
|
p++;
|
||||||
|
|
||||||
|
int4store(p, stmt->array_size);
|
||||||
|
p+= 4;
|
||||||
|
|
||||||
|
/* When using mariadb_stmt_execute_direct stmt->paran_count is
|
||||||
|
not knowm, so we need to assign prebind_params, which was previously
|
||||||
|
set by mysql_stmt_attr_set
|
||||||
|
*/
|
||||||
|
if (!stmt->param_count && stmt->prebind_params)
|
||||||
|
stmt->param_count= stmt->prebind_params;
|
||||||
|
|
||||||
|
if (stmt->param_count)
|
||||||
|
{
|
||||||
|
int1store(p, stmt->send_types_to_server);
|
||||||
|
p++;
|
||||||
|
|
||||||
|
free_bytes= length - (p - start);
|
||||||
|
|
||||||
|
/* Store type information:
|
||||||
|
2 bytes per type
|
||||||
|
*/
|
||||||
|
if (stmt->send_types_to_server)
|
||||||
|
{
|
||||||
|
if (free_bytes < stmt->param_count * 2 + 20)
|
||||||
|
{
|
||||||
|
size_t offset= p - start;
|
||||||
|
length= offset + stmt->param_count * 2 + 20;
|
||||||
|
if (!(start= (uchar *)realloc(start, length)))
|
||||||
|
goto mem_error;
|
||||||
|
p= start + offset;
|
||||||
|
}
|
||||||
|
for (i = 0; i < stmt->param_count; i++)
|
||||||
|
{
|
||||||
|
/* this differs from mysqlnd, c api supports unsinged !! */
|
||||||
|
uint buffer_type= stmt->params[i].buffer_type | (stmt->params[i].is_unsigned ? 32768 : 0);
|
||||||
|
int2store(p, buffer_type);
|
||||||
|
p+= 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* calculate data size */
|
||||||
|
for (j=0; j < stmt->array_size; j++)
|
||||||
{
|
{
|
||||||
for (i=0; i < stmt->param_count; i++)
|
for (i=0; i < stmt->param_count; i++)
|
||||||
{
|
{
|
||||||
size_t size= 0;
|
size_t size= 0;
|
||||||
my_bool has_data= TRUE;
|
my_bool has_data= TRUE;
|
||||||
char indicator= 0;
|
char indicator= ma_get_indicator(stmt, i, j);
|
||||||
|
/* check if we need to send data */
|
||||||
if (MARIADB_STMT_BULK_SUPPORTED(stmt) &&
|
if (indicator > 0)
|
||||||
(stmt->params[i].u.indicator || stmt->params[i].buffer_type == MYSQL_TYPE_NULL))
|
|
||||||
{
|
|
||||||
if (stmt->params[i].buffer_type == MYSQL_TYPE_NULL)
|
|
||||||
{
|
|
||||||
indicator= STMT_INDICATOR_NULL;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
indicator= ma_get_indicator(stmt, i, j);
|
|
||||||
/* check if we need to send data */
|
|
||||||
if (indicator > 0)
|
|
||||||
has_data= FALSE;
|
|
||||||
size= 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (stmt->params[i].long_data_used)
|
|
||||||
{
|
|
||||||
has_data= FALSE;
|
has_data= FALSE;
|
||||||
stmt->params[i].long_data_used= 0;
|
size= 1;
|
||||||
}
|
|
||||||
|
/* Please note that mysql_stmt_send_long_data is not supported
|
||||||
|
current when performing bulk execute */
|
||||||
|
|
||||||
if (has_data)
|
if (has_data)
|
||||||
{
|
{
|
||||||
switch (stmt->params[i].buffer_type) {
|
switch (stmt->params[i].buffer_type) {
|
||||||
case MYSQL_TYPE_NULL:
|
case MYSQL_TYPE_NULL:
|
||||||
if (MARIADB_STMT_BULK_SUPPORTED(stmt))
|
|
||||||
indicator= STMT_INDICATOR_NULL;
|
|
||||||
has_data= FALSE;
|
has_data= FALSE;
|
||||||
break;
|
break;
|
||||||
case MYSQL_TYPE_TINY_BLOB:
|
case MYSQL_TYPE_TINY_BLOB:
|
||||||
@@ -795,9 +927,9 @@ unsigned char* mysql_stmt_execute_generate_request(MYSQL_STMT *stmt, size_t *req
|
|||||||
case MYSQL_TYPE_BIT:
|
case MYSQL_TYPE_BIT:
|
||||||
case MYSQL_TYPE_SET:
|
case MYSQL_TYPE_SET:
|
||||||
size+= 5; /* max 8 bytes for size */
|
size+= 5; /* max 8 bytes for size */
|
||||||
if (indicator == STMT_INDICATOR_NTS ||
|
if (indicator == STMT_INDICATOR_NTS ||
|
||||||
(!stmt->row_size && ma_get_length(stmt,i,j) == -1))
|
(!stmt->row_size && ma_get_length(stmt,i,j) == -1))
|
||||||
size+= strlen(ma_get_buffer_offset(stmt,
|
size+= strlen(ma_get_buffer_offset(stmt,
|
||||||
stmt->params[i].buffer_type,
|
stmt->params[i].buffer_type,
|
||||||
stmt->params[i].buffer,j));
|
stmt->params[i].buffer,j));
|
||||||
else
|
else
|
||||||
@@ -818,27 +950,10 @@ unsigned char* mysql_stmt_execute_generate_request(MYSQL_STMT *stmt, size_t *req
|
|||||||
p= start + offset;
|
p= start + offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((indicator != STMT_INDICATOR_DEFAULT && indicator != STMT_INDICATOR_IGNORE) &&
|
int1store(p, indicator > 0 ? indicator : 0);
|
||||||
((stmt->params[i].is_null && *stmt->params[i].is_null) ||
|
p++;
|
||||||
stmt->params[i].buffer_type == MYSQL_TYPE_NULL ||
|
|
||||||
!stmt->params[i].buffer))
|
|
||||||
{
|
|
||||||
has_data= FALSE;
|
|
||||||
if (!stmt->array_size)
|
|
||||||
(start + null_byte_offset)[i/8] |= (unsigned char) (1 << (i & 7));
|
|
||||||
else
|
|
||||||
indicator= STMT_INDICATOR_NULL;
|
|
||||||
}
|
|
||||||
if (MARIADB_STMT_BULK_SUPPORTED(stmt) &&
|
|
||||||
(indicator || stmt->params[i].u.indicator))
|
|
||||||
{
|
|
||||||
int1store(p, indicator > 0 ? indicator : 0);
|
|
||||||
p++;
|
|
||||||
}
|
|
||||||
if (has_data)
|
if (has_data)
|
||||||
{
|
|
||||||
store_param(stmt, i, &p, j);
|
store_param(stmt, i, &p, j);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -853,7 +968,6 @@ mem_error:
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
/* }}} */
|
/* }}} */
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
*******************************************************************************
|
*******************************************************************************
|
||||||
|
|
||||||
@@ -1820,13 +1934,17 @@ int STDCALL mysql_stmt_execute(MYSQL_STMT *stmt)
|
|||||||
stmt->result_cursor= stmt->result.data= 0;
|
stmt->result_cursor= stmt->result.data= 0;
|
||||||
stmt->result.rows= 0;
|
stmt->result.rows= 0;
|
||||||
}
|
}
|
||||||
request= (char *)mysql_stmt_execute_generate_request(stmt, &request_len);
|
if (stmt->array_size > 0)
|
||||||
|
request= (char *)mysql_stmt_execute_generate_bulk_request(stmt, &request_len);
|
||||||
|
else
|
||||||
|
request= (char *)mysql_stmt_execute_generate_simple_request(stmt, &request_len);
|
||||||
|
|
||||||
if (!request)
|
if (!request)
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
ret= stmt->mysql->methods->db_command(mysql, COM_STMT_EXECUTE, request,
|
ret= stmt->mysql->methods->db_command(mysql,
|
||||||
request_len, 1, stmt);
|
stmt->array_size > 0 ? COM_STMT_BULK_EXECUTE : COM_STMT_EXECUTE,
|
||||||
|
request, request_len, 1, stmt);
|
||||||
if (request)
|
if (request)
|
||||||
free(request);
|
free(request);
|
||||||
|
|
||||||
|
@@ -165,7 +165,7 @@ static int send_client_reply_packet(MCPVIO_EXT *mpvio,
|
|||||||
/* see end= buff+32 below, fixed size of the packet is 32 bytes */
|
/* see end= buff+32 below, fixed size of the packet is 32 bytes */
|
||||||
buff= malloc(33 + USERNAME_LENGTH + data_len + NAME_LEN + NAME_LEN + conn_attr_len + 9);
|
buff= malloc(33 + USERNAME_LENGTH + data_len + NAME_LEN + NAME_LEN + conn_attr_len + 9);
|
||||||
end= buff;
|
end= buff;
|
||||||
|
|
||||||
mysql->client_flag|= mysql->options.client_flag;
|
mysql->client_flag|= mysql->options.client_flag;
|
||||||
mysql->client_flag|= CLIENT_CAPABILITIES;
|
mysql->client_flag|= CLIENT_CAPABILITIES;
|
||||||
|
|
||||||
@@ -212,6 +212,8 @@ static int send_client_reply_packet(MCPVIO_EXT *mpvio,
|
|||||||
if (mysql->client_flag & CLIENT_PROTOCOL_41)
|
if (mysql->client_flag & CLIENT_PROTOCOL_41)
|
||||||
{
|
{
|
||||||
/* 4.1 server and 4.1 client has a 32 byte option flag */
|
/* 4.1 server and 4.1 client has a 32 byte option flag */
|
||||||
|
if (!(mysql->server_capabilities & CLIENT_MYSQL))
|
||||||
|
mysql->client_flag&= ~CLIENT_MYSQL;
|
||||||
int4store(buff,mysql->client_flag);
|
int4store(buff,mysql->client_flag);
|
||||||
int4store(buff+4, net->max_packet_size);
|
int4store(buff+4, net->max_packet_size);
|
||||||
buff[8]= (char) mysql->charset->nr;
|
buff[8]= (char) mysql->charset->nr;
|
||||||
|
@@ -512,8 +512,93 @@ static int bulk6(MYSQL *mysql)
|
|||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int test_conc243(MYSQL *mysql)
|
||||||
|
{
|
||||||
|
MYSQL_STMT *stmt;
|
||||||
|
MYSQL_BIND bind[3];
|
||||||
|
MYSQL_RES *result;
|
||||||
|
MYSQL_ROW row;
|
||||||
|
|
||||||
|
struct st_data {
|
||||||
|
unsigned long id;
|
||||||
|
char id_ind;
|
||||||
|
char forename[30];
|
||||||
|
char forename_ind;
|
||||||
|
char surname[30];
|
||||||
|
char surname_ind;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct st_data data[]= {
|
||||||
|
{0, STMT_INDICATOR_NULL, "Monty", STMT_INDICATOR_NTS, "Widenius", STMT_INDICATOR_NTS},
|
||||||
|
{0, STMT_INDICATOR_NULL, "David", STMT_INDICATOR_NTS, "Axmark", STMT_INDICATOR_NTS},
|
||||||
|
{0, STMT_INDICATOR_NULL, "default", STMT_INDICATOR_DEFAULT, "N.N.", STMT_INDICATOR_NTS},
|
||||||
|
};
|
||||||
|
|
||||||
|
unsigned int array_size= 1;
|
||||||
|
size_t row_size= sizeof(struct st_data);
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
rc= mysql_query(mysql, "DROP TABLE IF EXISTS bulk_example2");
|
||||||
|
check_mysql_rc(rc, mysql);
|
||||||
|
|
||||||
|
rc= mysql_query(mysql, "CREATE TABLE bulk_example2 (id INT NOT NULL AUTO_INCREMENT PRIMARY KEY,"\
|
||||||
|
"forename CHAR(30) NOT NULL DEFAULT 'unknown', surname CHAR(30))");
|
||||||
|
check_mysql_rc(rc, mysql);
|
||||||
|
|
||||||
|
stmt= mysql_stmt_init(mysql);
|
||||||
|
rc= mysql_stmt_prepare(stmt, "INSERT INTO bulk_example2 VALUES (?,?,?)", -1);
|
||||||
|
check_stmt_rc(rc, stmt);
|
||||||
|
|
||||||
|
memset(bind, 0, sizeof(MYSQL_BIND) * 3);
|
||||||
|
|
||||||
|
/* We autogenerate id's, so all indicators are STMT_INDICATOR_NULL */
|
||||||
|
bind[0].u.indicator= &data[0].id_ind;
|
||||||
|
bind[0].buffer_type= MYSQL_TYPE_LONG;
|
||||||
|
|
||||||
|
bind[1].buffer= &data[0].forename;
|
||||||
|
bind[1].buffer_type= MYSQL_TYPE_STRING;
|
||||||
|
bind[1].u.indicator= &data[0].forename_ind;
|
||||||
|
|
||||||
|
bind[2].buffer_type= MYSQL_TYPE_STRING;
|
||||||
|
bind[2].buffer= &data[0].surname;
|
||||||
|
bind[2].u.indicator= &data[0].surname_ind;
|
||||||
|
|
||||||
|
/* set array size */
|
||||||
|
mysql_stmt_attr_set(stmt, STMT_ATTR_ARRAY_SIZE, &array_size);
|
||||||
|
|
||||||
|
/* set row size */
|
||||||
|
mysql_stmt_attr_set(stmt, STMT_ATTR_ROW_SIZE, &row_size);
|
||||||
|
|
||||||
|
/* bind parameter */
|
||||||
|
mysql_stmt_bind_param(stmt, bind);
|
||||||
|
|
||||||
|
/* execute */
|
||||||
|
rc= mysql_stmt_execute(stmt);
|
||||||
|
check_stmt_rc(rc, stmt);
|
||||||
|
|
||||||
|
mysql_stmt_close(stmt);
|
||||||
|
|
||||||
|
rc= mysql_query(mysql, "SELECT forename, surname FROM bulk_example2");
|
||||||
|
check_mysql_rc(rc, mysql);
|
||||||
|
|
||||||
|
result= mysql_store_result(mysql);
|
||||||
|
FAIL_IF(!result || !mysql_num_rows(result), "Invalid resultset");
|
||||||
|
row = mysql_fetch_row(result);
|
||||||
|
if (strcmp(row[0], "Monty") || strcmp(row[1], "Widenius"))
|
||||||
|
{
|
||||||
|
mysql_free_result(result);
|
||||||
|
diag("Wrong walues");
|
||||||
|
return FAIL;
|
||||||
|
}
|
||||||
|
mysql_free_result(result);
|
||||||
|
rc= mysql_query(mysql, "DROP TABLE bulk_example2");
|
||||||
|
check_mysql_rc(rc, mysql);
|
||||||
|
return OK;
|
||||||
|
}
|
||||||
|
|
||||||
struct my_tests_st my_tests[] = {
|
struct my_tests_st my_tests[] = {
|
||||||
{"check_bulk", check_bulk, TEST_CONNECTION_DEFAULT, 0, NULL, NULL},
|
{"check_bulk", check_bulk, TEST_CONNECTION_DEFAULT, 0, NULL, NULL},
|
||||||
|
{"test_conc243", test_conc243, TEST_CONNECTION_DEFAULT, 0, NULL, NULL},
|
||||||
{"bulk5", bulk5, TEST_CONNECTION_DEFAULT, 0, NULL, NULL},
|
{"bulk5", bulk5, TEST_CONNECTION_DEFAULT, 0, NULL, NULL},
|
||||||
{"bulk6", bulk6, TEST_CONNECTION_DEFAULT, 0, NULL, NULL},
|
{"bulk6", bulk6, TEST_CONNECTION_DEFAULT, 0, NULL, NULL},
|
||||||
{"bulk1", bulk1, TEST_CONNECTION_DEFAULT, 0, NULL, NULL},
|
{"bulk1", bulk1, TEST_CONNECTION_DEFAULT, 0, NULL, NULL},
|
||||||
|
@@ -832,7 +832,6 @@ static int test_prepare_alter(MYSQL *mysql)
|
|||||||
rc= mysql_stmt_execute(stmt);
|
rc= mysql_stmt_execute(stmt);
|
||||||
check_stmt_rc(rc, stmt);
|
check_stmt_rc(rc, stmt);
|
||||||
|
|
||||||
|
|
||||||
mysql_new= mysql_init(NULL);
|
mysql_new= mysql_init(NULL);
|
||||||
FAIL_IF(!mysql_new, "mysql_init failed");
|
FAIL_IF(!mysql_new, "mysql_init failed");
|
||||||
FAIL_IF(!(my_test_connect(mysql_new, hostname, username, password,
|
FAIL_IF(!(my_test_connect(mysql_new, hostname, username, password,
|
||||||
|
Reference in New Issue
Block a user