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
Merge remote-tracking branch 'origin/master' into 10.2-server
This commit is contained in:
@@ -95,5 +95,6 @@ extern const char *mariadb_client_errors[]; /* Error messages */
|
|||||||
#define CR_FUNCTION_NOT_SUPPORTED 5003
|
#define CR_FUNCTION_NOT_SUPPORTED 5003
|
||||||
#define CR_FILE_NOT_FOUND 5004
|
#define CR_FILE_NOT_FOUND 5004
|
||||||
#define CR_FILE_READ 5005
|
#define CR_FILE_READ 5005
|
||||||
|
#define CR_BULK_WITHOUT_PARAMETERS 5006
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@@ -69,6 +69,8 @@ struct st_mysql_options_extension {
|
|||||||
my_bool (*set_option)(MYSQL *mysql, const char *config_option, const char *config_value);
|
my_bool (*set_option)(MYSQL *mysql, const char *config_option, const char *config_value);
|
||||||
HASH userdata;
|
HASH userdata;
|
||||||
char *server_public_key;
|
char *server_public_key;
|
||||||
|
char *proxy_header;
|
||||||
|
size_t proxy_header_len;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct st_connection_handler
|
typedef struct st_connection_handler
|
||||||
|
@@ -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,10 +29,10 @@
|
|||||||
#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))))
|
||||||
|
|
||||||
#define SET_CLIENT_STMT_ERROR(a, b, c, d) \
|
#define SET_CLIENT_STMT_ERROR(a, b, c, d) \
|
||||||
{ \
|
{ \
|
||||||
@@ -84,6 +84,12 @@ enum enum_indicator_type
|
|||||||
STMT_INDICATOR_IGNORE=3
|
STMT_INDICATOR_IGNORE=3
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
bulk PS flags
|
||||||
|
*/
|
||||||
|
#define STMT_BULK_FLAG_CLIENT_SEND_TYPES 128
|
||||||
|
#define STMT_BULK_FLAG_INSERT_ID_REQUEST 64
|
||||||
|
|
||||||
typedef enum mysql_stmt_state
|
typedef enum mysql_stmt_state
|
||||||
{
|
{
|
||||||
MYSQL_STMT_INITTED = 0,
|
MYSQL_STMT_INITTED = 0,
|
||||||
|
@@ -231,7 +231,8 @@ extern const char *SQLSTATE_UNKNOWN;
|
|||||||
MARIADB_OPT_FOUND_ROWS,
|
MARIADB_OPT_FOUND_ROWS,
|
||||||
MARIADB_OPT_MULTI_RESULTS,
|
MARIADB_OPT_MULTI_RESULTS,
|
||||||
MARIADB_OPT_MULTI_STATEMENTS,
|
MARIADB_OPT_MULTI_STATEMENTS,
|
||||||
MARIADB_OPT_INTERACTIVE
|
MARIADB_OPT_INTERACTIVE,
|
||||||
|
MARIADB_OPT_PROXY_HEADER
|
||||||
};
|
};
|
||||||
|
|
||||||
enum mariadb_value {
|
enum mariadb_value {
|
||||||
|
@@ -332,7 +332,7 @@ CREATE_EXPORT_FILE(mariadbclient
|
|||||||
"${MARIADB_LIB_SYMBOLS}")
|
"${MARIADB_LIB_SYMBOLS}")
|
||||||
|
|
||||||
|
|
||||||
IF(CMAKE_VERSION VERSION_GREATER 2.8.7)
|
IF((NOT WIN32) AND (CMAKE_VERSION VERSION_GREATER 2.8.7))
|
||||||
# CREATE OBJECT LIBRARY
|
# CREATE OBJECT LIBRARY
|
||||||
ADD_LIBRARY(mariadb_obj OBJECT ${LIBMARIADB_SOURCES})
|
ADD_LIBRARY(mariadb_obj OBJECT ${LIBMARIADB_SOURCES})
|
||||||
IF(UNIX)
|
IF(UNIX)
|
||||||
@@ -346,8 +346,8 @@ ENDIF()
|
|||||||
# Xcode doesn't support targets that have only object files,
|
# Xcode doesn't support targets that have only object files,
|
||||||
# so let's add an empty file to keep Xcode happy
|
# so let's add an empty file to keep Xcode happy
|
||||||
IF(CMAKE_GENERATOR MATCHES Xcode)
|
IF(CMAKE_GENERATOR MATCHES Xcode)
|
||||||
FILE(WRITE ${CC_SOURCE_DIR}/libmariadb/empty.c "")
|
FILE(WRITE ${CC_BINARY_DIR}/libmariadb/empty.c "")
|
||||||
SET(EMPTY_FILE ${CC_SOURCE_DIR}/libmariadb/empty.c)
|
SET(EMPTY_FILE ${CC_BINARY_DIR}/libmariadb/empty.c)
|
||||||
ENDIF()
|
ENDIF()
|
||||||
|
|
||||||
IF(WIN32)
|
IF(WIN32)
|
||||||
@@ -358,14 +358,20 @@ IF(WIN32)
|
|||||||
"FILE_DESCRIPTION:Dynamic lib for client/server communication")
|
"FILE_DESCRIPTION:Dynamic lib for client/server communication")
|
||||||
ENDIF()
|
ENDIF()
|
||||||
|
|
||||||
ADD_LIBRARY(mariadbclient STATIC ${mariadbclient_RC} ${MARIADB_OBJECTS} ${EMPTY_FILE} mariadbclient.def)
|
ADD_LIBRARY(mariadbclient STATIC ${MARIADB_OBJECTS} ${EMPTY_FILE})
|
||||||
TARGET_LINK_LIBRARIES(mariadbclient ${SYSTEM_LIBS})
|
TARGET_LINK_LIBRARIES(mariadbclient ${SYSTEM_LIBS})
|
||||||
ADD_LIBRARY(libmariadb SHARED ${libmariadb_RC} ${MARIADB_OBJECTS} ${EMPTY_FILE} mariadbclient.def)
|
|
||||||
TARGET_LINK_LIBRARIES(libmariadb ${SYSTEM_LIBS})
|
|
||||||
|
|
||||||
IF(UNIX)
|
IF(UNIX)
|
||||||
|
ADD_LIBRARY(libmariadb SHARED ${libmariadb_RC} ${MARIADB_OBJECTS} ${EMPTY_FILE} mariadbclient.def)
|
||||||
SET_TARGET_PROPERTIES(libmariadb PROPERTIES COMPILE_FLAGS "${CMAKE_SHARED_LIBRARY_C_FLAGS}")
|
SET_TARGET_PROPERTIES(libmariadb PROPERTIES COMPILE_FLAGS "${CMAKE_SHARED_LIBRARY_C_FLAGS}")
|
||||||
|
ELSE()
|
||||||
|
ADD_LIBRARY(libmariadb SHARED ${libmariadb_RC} mariadbclient.def)
|
||||||
|
TARGET_LINK_LIBRARIES(libmariadb mariadbclient)
|
||||||
|
SET_TARGET_PROPERTIES(libmariadb PROPERTIES LINKER_LANGUAGE C)
|
||||||
ENDIF()
|
ENDIF()
|
||||||
|
|
||||||
|
TARGET_LINK_LIBRARIES(libmariadb ${SYSTEM_LIBS})
|
||||||
|
|
||||||
SIGN_TARGET(libmariadb)
|
SIGN_TARGET(libmariadb)
|
||||||
|
|
||||||
IF(CMAKE_SIZEOF_VOID_P EQUAL 8 AND MSVC)
|
IF(CMAKE_SIZEOF_VOID_P EQUAL 8 AND MSVC)
|
||||||
|
@@ -156,6 +156,7 @@ const char *mariadb_client_errors[] =
|
|||||||
/* 5003 */ "Server doesn't support function '%s'",
|
/* 5003 */ "Server doesn't support function '%s'",
|
||||||
/* 5004 */ "File '%s' not found (Errcode: %d)",
|
/* 5004 */ "File '%s' not found (Errcode: %d)",
|
||||||
/* 5005 */ "Error reading file '%s' (Errcode: %d)",
|
/* 5005 */ "Error reading file '%s' (Errcode: %d)",
|
||||||
|
/* 5006 */ "Bulk operation without parameters is not supported",
|
||||||
""
|
""
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@@ -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)))
|
||||||
{
|
{
|
||||||
@@ -657,10 +657,12 @@ struct st_default_options mariadb_defaults[] =
|
|||||||
else \
|
else \
|
||||||
(OPTS)->extension->KEY= NULL
|
(OPTS)->extension->KEY= NULL
|
||||||
|
|
||||||
#define OPT_SET_EXTENDED_VALUE_INT(OPTS, KEY, VAL) \
|
#define OPT_SET_EXTENDED_VALUE(OPTS, KEY, VAL) \
|
||||||
CHECK_OPT_EXTENSION_SET(OPTS) \
|
CHECK_OPT_EXTENSION_SET(OPTS) \
|
||||||
(OPTS)->extension->KEY= (VAL)
|
(OPTS)->extension->KEY= (VAL)
|
||||||
|
|
||||||
|
#define OPT_SET_EXTENDED_VALUE_INT(A,B,C) OPT_SET_EXTENDED_VALUE(A,B,C)
|
||||||
|
|
||||||
#define OPT_SET_VALUE_STR(OPTS, KEY, VAL) \
|
#define OPT_SET_VALUE_STR(OPTS, KEY, VAL) \
|
||||||
free((OPTS)->KEY); \
|
free((OPTS)->KEY); \
|
||||||
if((VAL)) \
|
if((VAL)) \
|
||||||
@@ -1303,6 +1305,17 @@ MYSQL *mthd_my_real_connect(MYSQL *mysql, const char *host, const char *user,
|
|||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (mysql->options.extension && mysql->options.extension->proxy_header)
|
||||||
|
{
|
||||||
|
char *hdr = mysql->options.extension->proxy_header;
|
||||||
|
size_t len = mysql->options.extension->proxy_header_len;
|
||||||
|
if (ma_pvio_write(pvio, hdr, len) <= 0)
|
||||||
|
{
|
||||||
|
ma_pvio_close(pvio);
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (ma_net_init(net, pvio))
|
if (ma_net_init(net, pvio))
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
@@ -1483,7 +1496,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))
|
||||||
{
|
{
|
||||||
@@ -2955,6 +2969,13 @@ mysql_optionsv(MYSQL *mysql,enum mysql_option option, ...)
|
|||||||
case MARIADB_OPT_CONNECTION_READ_ONLY:
|
case MARIADB_OPT_CONNECTION_READ_ONLY:
|
||||||
OPT_SET_EXTENDED_VALUE_INT(&mysql->options, read_only, *(my_bool *)arg1);
|
OPT_SET_EXTENDED_VALUE_INT(&mysql->options, read_only, *(my_bool *)arg1);
|
||||||
break;
|
break;
|
||||||
|
case MARIADB_OPT_PROXY_HEADER:
|
||||||
|
{
|
||||||
|
size_t arg2 = va_arg(ap, size_t);
|
||||||
|
OPT_SET_EXTENDED_VALUE(&mysql->options, proxy_header, (char *)arg1);
|
||||||
|
OPT_SET_EXTENDED_VALUE(&mysql->options, proxy_header_len, arg2);
|
||||||
|
}
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
va_end(ap);
|
va_end(ap);
|
||||||
return(-1);
|
return(-1);
|
||||||
|
@@ -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,50 +715,202 @@ 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_FLAG_CLIENT_SEND_TYPES = 128
|
||||||
|
STMT_BULK_FLAG_INSERT_ID_REQUEST = 64
|
||||||
|
-----------------------------------------
|
||||||
|
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, "IM001",
|
||||||
|
CER(CR_FUNCTION_NOT_SUPPORTED), "Bulk operation");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!stmt->param_count)
|
||||||
|
{
|
||||||
|
stmt_set_error(stmt, CR_BULK_WITHOUT_PARAMETERS, "IM001",
|
||||||
|
CER(CR_BULK_WITHOUT_PARAMETERS), "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|= STMT_BULK_FLAG_CLIENT_SEND_TYPES;
|
||||||
|
int2store(p, flags);
|
||||||
|
p+=2;
|
||||||
|
|
||||||
|
/* 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)
|
||||||
|
{
|
||||||
|
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;
|
||||||
|
indicator= STMT_INDICATOR_NULL;
|
||||||
break;
|
break;
|
||||||
case MYSQL_TYPE_TINY_BLOB:
|
case MYSQL_TYPE_TINY_BLOB:
|
||||||
case MYSQL_TYPE_MEDIUM_BLOB:
|
case MYSQL_TYPE_MEDIUM_BLOB:
|
||||||
@@ -795,9 +928,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 +951,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 +969,6 @@ mem_error:
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
/* }}} */
|
/* }}} */
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
*******************************************************************************
|
*******************************************************************************
|
||||||
|
|
||||||
@@ -1820,13 +1935,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);
|
||||||
|
|
||||||
@@ -2151,7 +2270,8 @@ int STDCALL mariadb_stmt_execute_direct(MYSQL_STMT *stmt,
|
|||||||
{
|
{
|
||||||
MYSQL *mysql= stmt->mysql;
|
MYSQL *mysql= stmt->mysql;
|
||||||
my_bool emulate_cmd= !(!(stmt->mysql->server_capabilities & CLIENT_MYSQL) &&
|
my_bool emulate_cmd= !(!(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)));
|
||||||
|
|
||||||
if (!mysql)
|
if (!mysql)
|
||||||
{
|
{
|
||||||
|
@@ -451,7 +451,7 @@ int ma_tls_verify_server_cert(MARIADB_TLS *ctls)
|
|||||||
if (pszServerName && (sctx->mysql->client_flag & CLIENT_SSL_VERIFY_SERVER_CERT))
|
if (pszServerName && (sctx->mysql->client_flag & CLIENT_SSL_VERIFY_SERVER_CERT))
|
||||||
{
|
{
|
||||||
DWORD NameSize= 0;
|
DWORD NameSize= 0;
|
||||||
char *p1, *p2;
|
char *p1;
|
||||||
SECURITY_STATUS sRet;
|
SECURITY_STATUS sRet;
|
||||||
|
|
||||||
if ((sRet= QueryContextAttributes(&sctx->ctxt, SECPKG_ATTR_REMOTE_CERT_CONTEXT, (PVOID)&pServerCert)) != SEC_E_OK)
|
if ((sRet= QueryContextAttributes(&sctx->ctxt, SECPKG_ATTR_REMOTE_CERT_CONTEXT, (PVOID)&pServerCert)) != SEC_E_OK)
|
||||||
|
@@ -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;
|
||||||
|
@@ -37,7 +37,8 @@ char *rand_str(size_t length) {
|
|||||||
static int check_bulk(MYSQL *mysql)
|
static int check_bulk(MYSQL *mysql)
|
||||||
{
|
{
|
||||||
bulk_enabled= (!(mysql->server_capabilities & CLIENT_MYSQL) &&
|
bulk_enabled= (!(mysql->server_capabilities & CLIENT_MYSQL) &&
|
||||||
(mysql->extension->mariadb_server_capabilities & MARIADB_CLIENT_STMT_BULK_OPERATIONS >> 32));
|
(mysql->extension->mariadb_server_capabilities &
|
||||||
|
(MARIADB_CLIENT_STMT_BULK_OPERATIONS >> 32)));
|
||||||
diag("bulk %ssupported", bulk_enabled ? "" : "not ");
|
diag("bulk %ssupported", bulk_enabled ? "" : "not ");
|
||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
@@ -512,8 +513,266 @@ 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;
|
||||||
|
}
|
||||||
|
static int bulk7(MYSQL *mysql)
|
||||||
|
{
|
||||||
|
MYSQL_STMT *stmt= mysql_stmt_init(mysql);
|
||||||
|
int rc;
|
||||||
|
int array_size= 5;
|
||||||
|
|
||||||
|
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)");
|
||||||
|
check_mysql_rc(rc, mysql);
|
||||||
|
|
||||||
|
rc= mysql_stmt_prepare(stmt, "UPDATE t1 SET a=a+1", -1);
|
||||||
|
check_stmt_rc(rc, stmt);
|
||||||
|
|
||||||
|
rc= mysql_stmt_attr_set(stmt, STMT_ATTR_ARRAY_SIZE, &array_size);
|
||||||
|
check_stmt_rc(rc, stmt);
|
||||||
|
rc= mysql_stmt_execute(stmt);
|
||||||
|
|
||||||
|
FAIL_IF(!rc, "Error expected: Bulk operation without parameters is not supported");
|
||||||
|
diag("%s", mysql_stmt_error(stmt));
|
||||||
|
|
||||||
|
mysql_stmt_close(stmt);
|
||||||
|
rc= mysql_query(mysql, "DROP TABLE t1");
|
||||||
|
check_mysql_rc(rc, mysql);
|
||||||
|
|
||||||
|
return OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int test_char_conv1(MYSQL *mysql)
|
||||||
|
{
|
||||||
|
MYSQL_STMT *stmt= mysql_stmt_init(mysql);
|
||||||
|
int rc;
|
||||||
|
MYSQL_BIND bind_in, bind_out;
|
||||||
|
char buffer[100];
|
||||||
|
char outbuffer[100];
|
||||||
|
|
||||||
|
strcpy (buffer, "\xC3\x82\xC3\x83\xC3\x84\x00");
|
||||||
|
|
||||||
|
rc= mysql_query(mysql, "SET NAMES UTF8");
|
||||||
|
check_mysql_rc(rc, mysql);
|
||||||
|
rc= mysql_query(mysql, "DROP TABLE IF EXISTS char_conv");
|
||||||
|
check_mysql_rc(rc, mysql);
|
||||||
|
rc= mysql_query(mysql, "CREATE TABLE char_conv (a varchar(20)) CHARSET=latin1");
|
||||||
|
check_mysql_rc(rc, mysql);
|
||||||
|
|
||||||
|
rc= mysql_stmt_prepare(stmt, "INSERT INTO char_conv VALUES (?)", -1);
|
||||||
|
check_stmt_rc(rc, stmt);
|
||||||
|
|
||||||
|
memset(&bind_in, 0, sizeof(MYSQL_BIND));
|
||||||
|
bind_in.buffer_type= MYSQL_TYPE_STRING;
|
||||||
|
bind_in.buffer_length= -1;
|
||||||
|
bind_in.buffer= &buffer;
|
||||||
|
|
||||||
|
rc= mysql_stmt_bind_param(stmt, &bind_in);
|
||||||
|
check_stmt_rc(rc, stmt);
|
||||||
|
|
||||||
|
rc= mysql_stmt_execute(stmt);
|
||||||
|
check_stmt_rc(rc, stmt);
|
||||||
|
|
||||||
|
mysql_stmt_close(stmt);
|
||||||
|
|
||||||
|
stmt= mysql_stmt_init(mysql);
|
||||||
|
|
||||||
|
rc= mysql_stmt_prepare(stmt, "SELECT a from char_conv", -1);
|
||||||
|
check_stmt_rc(rc, stmt);
|
||||||
|
|
||||||
|
memset(&bind_out, 0, sizeof(MYSQL_BIND));
|
||||||
|
bind_out.buffer_type= MYSQL_TYPE_STRING;
|
||||||
|
bind_out.buffer_length= 100;
|
||||||
|
bind_out.buffer= outbuffer;
|
||||||
|
|
||||||
|
rc= mysql_stmt_bind_result(stmt, &bind_out);
|
||||||
|
check_stmt_rc(rc, stmt);
|
||||||
|
|
||||||
|
rc= mysql_stmt_execute(stmt);
|
||||||
|
check_stmt_rc(rc, stmt);
|
||||||
|
|
||||||
|
rc= mysql_stmt_fetch(stmt);
|
||||||
|
FAIL_IF(rc == MYSQL_NO_DATA, "Error");
|
||||||
|
|
||||||
|
mysql_stmt_close(stmt);
|
||||||
|
|
||||||
|
|
||||||
|
if (strcmp(buffer, outbuffer))
|
||||||
|
{
|
||||||
|
diag("Error: Expected '%s' instead of '%s'", buffer, outbuffer);
|
||||||
|
return FAIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
rc= mysql_query(mysql, "DROP TABLE char_conv");
|
||||||
|
check_mysql_rc(rc, mysql);
|
||||||
|
|
||||||
|
return OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int test_char_conv2(MYSQL *mysql)
|
||||||
|
{
|
||||||
|
MYSQL_STMT *stmt= mysql_stmt_init(mysql);
|
||||||
|
int rc;
|
||||||
|
int array_size= 1;
|
||||||
|
MYSQL_BIND bind_in, bind_out;
|
||||||
|
char *buffer[1];
|
||||||
|
char outbuffer[100];
|
||||||
|
|
||||||
|
buffer[0]= calloc(1, 7);
|
||||||
|
strcpy (buffer[0], "\xC3\x82\xC3\x83\xC3\x84\x00");
|
||||||
|
|
||||||
|
rc= mysql_query(mysql, "SET NAMES UTF8");
|
||||||
|
check_mysql_rc(rc, mysql);
|
||||||
|
rc= mysql_query(mysql, "DROP TABLE IF EXISTS char_conv");
|
||||||
|
check_mysql_rc(rc, mysql);
|
||||||
|
rc= mysql_query(mysql, "CREATE TABLE char_conv (a varchar(20)) CHARSET=latin1");
|
||||||
|
check_mysql_rc(rc, mysql);
|
||||||
|
|
||||||
|
rc= mysql_stmt_prepare(stmt, "INSERT INTO char_conv VALUES (?)", -1);
|
||||||
|
check_stmt_rc(rc, stmt);
|
||||||
|
|
||||||
|
rc= mysql_stmt_attr_set(stmt, STMT_ATTR_ARRAY_SIZE, &array_size);
|
||||||
|
check_stmt_rc(rc, stmt);
|
||||||
|
|
||||||
|
memset(&bind_in, 0, sizeof(MYSQL_BIND));
|
||||||
|
bind_in.buffer_type= MYSQL_TYPE_STRING;
|
||||||
|
bind_in.buffer_length= -1;
|
||||||
|
bind_in.buffer= &buffer;
|
||||||
|
|
||||||
|
rc= mysql_stmt_bind_param(stmt, &bind_in);
|
||||||
|
check_stmt_rc(rc, stmt);
|
||||||
|
|
||||||
|
rc= mysql_stmt_execute(stmt);
|
||||||
|
check_stmt_rc(rc, stmt);
|
||||||
|
|
||||||
|
mysql_stmt_close(stmt);
|
||||||
|
|
||||||
|
stmt= mysql_stmt_init(mysql);
|
||||||
|
|
||||||
|
rc= mysql_stmt_prepare(stmt, "SELECT a from char_conv", -1);
|
||||||
|
check_stmt_rc(rc, stmt);
|
||||||
|
|
||||||
|
memset(&bind_out, 0, sizeof(MYSQL_BIND));
|
||||||
|
bind_out.buffer_type= MYSQL_TYPE_STRING;
|
||||||
|
bind_out.buffer_length= 100;
|
||||||
|
bind_out.buffer= outbuffer;
|
||||||
|
|
||||||
|
rc= mysql_stmt_bind_result(stmt, &bind_out);
|
||||||
|
check_stmt_rc(rc, stmt);
|
||||||
|
|
||||||
|
rc= mysql_stmt_execute(stmt);
|
||||||
|
check_stmt_rc(rc, stmt);
|
||||||
|
|
||||||
|
rc= mysql_stmt_fetch(stmt);
|
||||||
|
FAIL_IF(rc == MYSQL_NO_DATA, "Error");
|
||||||
|
|
||||||
|
mysql_stmt_close(stmt);
|
||||||
|
|
||||||
|
|
||||||
|
if (strcmp(buffer[0], outbuffer))
|
||||||
|
{
|
||||||
|
diag("Error: Expected '%s' instead of '%s'", buffer[0], outbuffer);
|
||||||
|
return FAIL;
|
||||||
|
}
|
||||||
|
free(buffer[0]);
|
||||||
|
|
||||||
|
rc= mysql_query(mysql, "DROP TABLE char_conv");
|
||||||
|
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_char_conv1", test_char_conv1, TEST_CONNECTION_NEW, 0, NULL, NULL},
|
||||||
|
{"test_char_conv2", test_char_conv2, TEST_CONNECTION_NEW, 0, NULL, NULL},
|
||||||
|
{"test_conc243", test_conc243, TEST_CONNECTION_DEFAULT, 0, NULL, NULL},
|
||||||
|
{"update_no_param", bulk7, 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