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
- Fixed crash in prepared statement: Indicator variable should be checked only if we are in bulk operation mode (=stmt->array_size > 0 and bulk is supported by server
- Added new api function mysql_get_server_status, so client applications no longer need to access members of the mysql structure
This commit is contained in:
@@ -28,6 +28,11 @@
|
|||||||
/* Bind flags */
|
/* Bind flags */
|
||||||
#define MADB_BIND_DUMMY 1
|
#define MADB_BIND_DUMMY 1
|
||||||
|
|
||||||
|
#define MARIADB_STMT_BULK_SUPPORTED(stmt)\
|
||||||
|
((stmt)->array_size > 0 && \
|
||||||
|
(stmt)->mysql && \
|
||||||
|
(!((stmt)->mysql->server_capabilities & CLIENT_MYSQL) &&\
|
||||||
|
((stmt)->mysql->extension->mariadb_server_capabilities & MARIADB_CLIENT_STMT_BULK_OPERATIONS >> 32)))
|
||||||
|
|
||||||
#define SET_CLIENT_STMT_ERROR(a, b, c, d) \
|
#define SET_CLIENT_STMT_ERROR(a, b, c, d) \
|
||||||
{ \
|
{ \
|
||||||
|
@@ -519,6 +519,7 @@ int STDCALL mysql_kill(MYSQL *mysql,unsigned long pid);
|
|||||||
int STDCALL mysql_ping(MYSQL *mysql);
|
int STDCALL mysql_ping(MYSQL *mysql);
|
||||||
char * STDCALL mysql_stat(MYSQL *mysql);
|
char * STDCALL mysql_stat(MYSQL *mysql);
|
||||||
char * STDCALL mysql_get_server_info(MYSQL *mysql);
|
char * STDCALL mysql_get_server_info(MYSQL *mysql);
|
||||||
|
unsigned int STDCALL mysql_get_server_status(MYSQL *mysql);
|
||||||
unsigned long STDCALL mysql_get_server_version(MYSQL *mysql);
|
unsigned long STDCALL mysql_get_server_version(MYSQL *mysql);
|
||||||
char * STDCALL mysql_get_host_info(MYSQL *mysql);
|
char * STDCALL mysql_get_host_info(MYSQL *mysql);
|
||||||
unsigned int STDCALL mysql_get_proto_info(MYSQL *mysql);
|
unsigned int STDCALL mysql_get_proto_info(MYSQL *mysql);
|
||||||
@@ -737,6 +738,7 @@ struct st_mariadb_api {
|
|||||||
int (STDCALL *mysql_ping)(MYSQL *mysql);
|
int (STDCALL *mysql_ping)(MYSQL *mysql);
|
||||||
char * (STDCALL *mysql_stat)(MYSQL *mysql);
|
char * (STDCALL *mysql_stat)(MYSQL *mysql);
|
||||||
char * (STDCALL *mysql_get_server_info)(MYSQL *mysql);
|
char * (STDCALL *mysql_get_server_info)(MYSQL *mysql);
|
||||||
|
unsigned int (STDCALL *mysql_get_server_status)(MYSQL *mysql);
|
||||||
unsigned long (STDCALL *mysql_get_server_version)(MYSQL *mysql);
|
unsigned long (STDCALL *mysql_get_server_version)(MYSQL *mysql);
|
||||||
char * (STDCALL *mysql_get_host_info)(MYSQL *mysql);
|
char * (STDCALL *mysql_get_host_info)(MYSQL *mysql);
|
||||||
unsigned int (STDCALL *mysql_get_proto_info)(MYSQL *mysql);
|
unsigned int (STDCALL *mysql_get_proto_info)(MYSQL *mysql);
|
||||||
|
@@ -55,6 +55,7 @@ SET(MARIADB_LIB_SYMBOLS
|
|||||||
mysql_get_parameters
|
mysql_get_parameters
|
||||||
mysql_get_proto_info
|
mysql_get_proto_info
|
||||||
mysql_get_server_info
|
mysql_get_server_info
|
||||||
|
mysql_get_server_status
|
||||||
mysql_get_server_name
|
mysql_get_server_name
|
||||||
mysql_get_server_version
|
mysql_get_server_version
|
||||||
mysql_get_socket
|
mysql_get_socket
|
||||||
|
@@ -2523,6 +2523,12 @@ mysql_get_server_info(MYSQL *mysql)
|
|||||||
return((char*) mysql->server_version);
|
return((char*) mysql->server_version);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unsigned int STDCALL
|
||||||
|
mysql_get_server_status(MYSQL *mysql)
|
||||||
|
{
|
||||||
|
return mysql->server_status;
|
||||||
|
}
|
||||||
|
|
||||||
static size_t mariadb_server_version_id(MYSQL *mysql)
|
static size_t mariadb_server_version_id(MYSQL *mysql)
|
||||||
{
|
{
|
||||||
size_t major, minor, patch;
|
size_t major, minor, patch;
|
||||||
@@ -2546,15 +2552,12 @@ unsigned long STDCALL mysql_get_server_version(MYSQL *mysql)
|
|||||||
return (unsigned long)mariadb_server_version_id(mysql);
|
return (unsigned long)mariadb_server_version_id(mysql);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
char * STDCALL
|
char * STDCALL
|
||||||
mysql_get_host_info(MYSQL *mysql)
|
mysql_get_host_info(MYSQL *mysql)
|
||||||
{
|
{
|
||||||
return(mysql->host_info);
|
return(mysql->host_info);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
uint STDCALL
|
uint STDCALL
|
||||||
mysql_get_proto_info(MYSQL *mysql)
|
mysql_get_proto_info(MYSQL *mysql)
|
||||||
{
|
{
|
||||||
@@ -3899,6 +3902,7 @@ struct st_mariadb_api MARIADB_API=
|
|||||||
mysql_ping,
|
mysql_ping,
|
||||||
mysql_stat,
|
mysql_stat,
|
||||||
mysql_get_server_info,
|
mysql_get_server_info,
|
||||||
|
mysql_get_server_status,
|
||||||
mysql_get_server_version,
|
mysql_get_server_version,
|
||||||
mysql_get_host_info,
|
mysql_get_host_info,
|
||||||
mysql_get_proto_info,
|
mysql_get_proto_info,
|
||||||
|
@@ -434,7 +434,9 @@ static long ma_get_length(MYSQL_STMT *stmt, unsigned int param_nr, unsigned long
|
|||||||
|
|
||||||
static char ma_get_indicator(MYSQL_STMT *stmt, unsigned int param_nr, unsigned long row_nr)
|
static char ma_get_indicator(MYSQL_STMT *stmt, unsigned int param_nr, unsigned long row_nr)
|
||||||
{
|
{
|
||||||
if (!stmt->params[param_nr].u.indicator)
|
if (!MARIADB_STMT_BULK_SUPPORTED(stmt) ||
|
||||||
|
!stmt->array_size ||
|
||||||
|
!stmt->params[param_nr].u.indicator)
|
||||||
return 0;
|
return 0;
|
||||||
if (stmt->row_size)
|
if (stmt->row_size)
|
||||||
return *((char *)stmt->params[param_nr].u.indicator + (row_nr * stmt->row_size));
|
return *((char *)stmt->params[param_nr].u.indicator + (row_nr * stmt->row_size));
|
||||||
@@ -638,13 +640,10 @@ unsigned char* mysql_stmt_execute_generate_request(MYSQL_STMT *stmt, size_t *req
|
|||||||
size_t free_bytes= 0;
|
size_t free_bytes= 0;
|
||||||
size_t null_byte_offset;
|
size_t null_byte_offset;
|
||||||
uint i, j, num_rows= 1;
|
uint i, j, num_rows= 1;
|
||||||
my_bool bulk_supported= stmt->array_size > 0 &&
|
|
||||||
(!(stmt->mysql->server_capabilities & CLIENT_MYSQL) &&
|
|
||||||
(stmt->mysql->extension->mariadb_server_capabilities & MARIADB_CLIENT_STMT_BULK_OPERATIONS >> 32));
|
|
||||||
|
|
||||||
uchar *start= NULL, *p;
|
uchar *start= NULL, *p;
|
||||||
|
|
||||||
if (!bulk_supported && stmt->array_size > 0)
|
if (!MARIADB_STMT_BULK_SUPPORTED(stmt) && stmt->array_size > 0)
|
||||||
{
|
{
|
||||||
stmt_set_error(stmt, CR_FUNCTION_NOT_SUPPORTED, SQLSTATE_UNKNOWN,
|
stmt_set_error(stmt, CR_FUNCTION_NOT_SUPPORTED, SQLSTATE_UNKNOWN,
|
||||||
CER(CR_FUNCTION_NOT_SUPPORTED), "Bulk operation");
|
CER(CR_FUNCTION_NOT_SUPPORTED), "Bulk operation");
|
||||||
@@ -663,7 +662,7 @@ 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 (bulk_supported && stmt->array_size)
|
if (MARIADB_STMT_BULK_SUPPORTED(stmt) && stmt->array_size)
|
||||||
num_rows= stmt->array_size;
|
num_rows= stmt->array_size;
|
||||||
int4store(p, num_rows);
|
int4store(p, num_rows);
|
||||||
p+= 4;
|
p+= 4;
|
||||||
@@ -714,7 +713,7 @@ 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 (bulk_supported &&
|
if (MARIADB_STMT_BULK_SUPPORTED(stmt) &&
|
||||||
(stmt->params[i].u.indicator || stmt->params[i].buffer_type == MYSQL_TYPE_NULL))
|
(stmt->params[i].u.indicator || stmt->params[i].buffer_type == MYSQL_TYPE_NULL))
|
||||||
buffer_type|= 16384;
|
buffer_type|= 16384;
|
||||||
int2store(p, buffer_type);
|
int2store(p, buffer_type);
|
||||||
@@ -731,7 +730,7 @@ unsigned char* mysql_stmt_execute_generate_request(MYSQL_STMT *stmt, size_t *req
|
|||||||
my_bool has_data= TRUE;
|
my_bool has_data= TRUE;
|
||||||
char indicator= 0;
|
char indicator= 0;
|
||||||
|
|
||||||
if (bulk_supported &&
|
if (MARIADB_STMT_BULK_SUPPORTED(stmt) &&
|
||||||
(stmt->params[i].u.indicator || stmt->params[i].buffer_type == MYSQL_TYPE_NULL))
|
(stmt->params[i].u.indicator || stmt->params[i].buffer_type == MYSQL_TYPE_NULL))
|
||||||
{
|
{
|
||||||
if (stmt->params[i].buffer_type == MYSQL_TYPE_NULL)
|
if (stmt->params[i].buffer_type == MYSQL_TYPE_NULL)
|
||||||
@@ -755,7 +754,7 @@ unsigned char* mysql_stmt_execute_generate_request(MYSQL_STMT *stmt, size_t *req
|
|||||||
{
|
{
|
||||||
switch (stmt->params[i].buffer_type) {
|
switch (stmt->params[i].buffer_type) {
|
||||||
case MYSQL_TYPE_NULL:
|
case MYSQL_TYPE_NULL:
|
||||||
if (bulk_supported)
|
if (MARIADB_STMT_BULK_SUPPORTED(stmt))
|
||||||
indicator= STMT_INDICATOR_NULL;
|
indicator= STMT_INDICATOR_NULL;
|
||||||
has_data= FALSE;
|
has_data= FALSE;
|
||||||
break;
|
break;
|
||||||
@@ -809,7 +808,8 @@ unsigned char* mysql_stmt_execute_generate_request(MYSQL_STMT *stmt, size_t *req
|
|||||||
else
|
else
|
||||||
indicator= STMT_INDICATOR_NULL;
|
indicator= STMT_INDICATOR_NULL;
|
||||||
}
|
}
|
||||||
if (bulk_supported && (indicator || stmt->params[i].u.indicator))
|
if (MARIADB_STMT_BULK_SUPPORTED(stmt) &&
|
||||||
|
(indicator || stmt->params[i].u.indicator))
|
||||||
{
|
{
|
||||||
int1store(p, indicator > 0 ? indicator : 0);
|
int1store(p, indicator > 0 ? indicator : 0);
|
||||||
p++;
|
p++;
|
||||||
|
@@ -86,24 +86,6 @@ static void ma_tls_set_error(MYSQL *mysql)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void ma_tls_get_error(char *errmsg, size_t length)
|
|
||||||
{
|
|
||||||
ulong ssl_errno= ERR_get_error();
|
|
||||||
const char *ssl_error_reason;
|
|
||||||
|
|
||||||
if (!ssl_errno)
|
|
||||||
{
|
|
||||||
strncpy(errmsg, "Unknown SSL error", length);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if ((ssl_error_reason= ERR_reason_error_string(ssl_errno)))
|
|
||||||
{
|
|
||||||
strncpy(errmsg, ssl_error_reason, length);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
snprintf(errmsg, length, "SSL errno=%lu", ssl_errno);
|
|
||||||
}
|
|
||||||
|
|
||||||
#if OPENSSL_VERSION_NUMBER < 0x10100000L
|
#if OPENSSL_VERSION_NUMBER < 0x10100000L
|
||||||
/*
|
/*
|
||||||
thread safe callbacks for OpenSSL
|
thread safe callbacks for OpenSSL
|
||||||
@@ -296,7 +278,7 @@ static void disable_sigpipe()
|
|||||||
0 success
|
0 success
|
||||||
1 error
|
1 error
|
||||||
*/
|
*/
|
||||||
int ma_tls_start(char *errmsg, size_t errmsg_len)
|
int ma_tls_start(char *errmsg __attribute__((unused)), size_t errmsg_len __attribute__((unused)))
|
||||||
{
|
{
|
||||||
int rc= 1;
|
int rc= 1;
|
||||||
if (ma_tls_initialized)
|
if (ma_tls_initialized)
|
||||||
@@ -332,7 +314,6 @@ int ma_tls_start(char *errmsg, size_t errmsg_len)
|
|||||||
#endif
|
#endif
|
||||||
rc= 0;
|
rc= 0;
|
||||||
ma_tls_initialized= TRUE;
|
ma_tls_initialized= TRUE;
|
||||||
end:
|
|
||||||
pthread_mutex_unlock(&LOCK_openssl_config);
|
pthread_mutex_unlock(&LOCK_openssl_config);
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
@@ -1130,7 +1130,34 @@ static int test_zerofill(MYSQL *mysql)
|
|||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int test_server_status(MYSQL *mysql)
|
||||||
|
{
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
rc= mysql_autocommit(mysql, 1);
|
||||||
|
FAIL_IF(!(mysql_get_server_status(mysql) & SERVER_STATUS_AUTOCOMMIT),
|
||||||
|
"autocommit flag not set");
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
rc= mysql_query(mysql, "INSERT INTO t1 VALUES (1),(2),(3),(4),(5)");
|
||||||
|
check_mysql_rc(rc, mysql);
|
||||||
|
|
||||||
|
rc= mysql_query(mysql, "UPDATE t1 SET a=9 WHERE a=8");
|
||||||
|
check_mysql_rc(rc, mysql);
|
||||||
|
|
||||||
|
FAIL_IF(!(mysql_get_server_status(mysql) & SERVER_QUERY_NO_INDEX_USED), "autocommit flag not set");
|
||||||
|
|
||||||
|
return OK;
|
||||||
|
}
|
||||||
|
|
||||||
struct my_tests_st my_tests[] = {
|
struct my_tests_st my_tests[] = {
|
||||||
|
|
||||||
|
{"test_server_status", test_server_status, TEST_CONNECTION_DEFAULT, 0, NULL, NULL},
|
||||||
{"test_read_timeout", test_read_timeout, TEST_CONNECTION_DEFAULT, 0, NULL, NULL},
|
{"test_read_timeout", test_read_timeout, TEST_CONNECTION_DEFAULT, 0, NULL, NULL},
|
||||||
{"test_zerofill", test_zerofill, TEST_CONNECTION_DEFAULT, 0, NULL, NULL},
|
{"test_zerofill", test_zerofill, TEST_CONNECTION_DEFAULT, 0, NULL, NULL},
|
||||||
#ifdef HAVE_REMOTEIO
|
#ifdef HAVE_REMOTEIO
|
||||||
|
Reference in New Issue
Block a user