1
0
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:
Georg Richter
2017-06-14 14:55:05 +02:00
13 changed files with 528 additions and 109 deletions

View File

@@ -95,5 +95,6 @@ extern const char *mariadb_client_errors[]; /* Error messages */
#define CR_FUNCTION_NOT_SUPPORTED 5003
#define CR_FILE_NOT_FOUND 5004
#define CR_FILE_READ 5005
#define CR_BULK_WITHOUT_PARAMETERS 5006
#endif

View File

@@ -69,6 +69,8 @@ struct st_mysql_options_extension {
my_bool (*set_option)(MYSQL *mysql, const char *config_option, const char *config_value);
HASH userdata;
char *server_public_key;
char *proxy_header;
size_t proxy_header_len;
};
typedef struct st_connection_handler

View File

@@ -93,6 +93,7 @@ enum enum_server_command
COM_DAEMON= 29,
COM_UNSUPPORTED= 30,
COM_RESET_CONNECTION = 31,
COM_STMT_BULK_EXECUTE = 250,
COM_MULTI = 254,
COM_END
};

View File

@@ -29,10 +29,10 @@
#define MADB_BIND_DUMMY 1
#define MARIADB_STMT_BULK_SUPPORTED(stmt)\
((stmt)->array_size > 0 && \
(stmt)->mysql && \
((stmt)->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) \
{ \
@@ -84,6 +84,12 @@ enum enum_indicator_type
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
{
MYSQL_STMT_INITTED = 0,

View File

@@ -231,7 +231,8 @@ extern const char *SQLSTATE_UNKNOWN;
MARIADB_OPT_FOUND_ROWS,
MARIADB_OPT_MULTI_RESULTS,
MARIADB_OPT_MULTI_STATEMENTS,
MARIADB_OPT_INTERACTIVE
MARIADB_OPT_INTERACTIVE,
MARIADB_OPT_PROXY_HEADER
};
enum mariadb_value {

View File

@@ -332,7 +332,7 @@ CREATE_EXPORT_FILE(mariadbclient
"${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
ADD_LIBRARY(mariadb_obj OBJECT ${LIBMARIADB_SOURCES})
IF(UNIX)
@@ -346,8 +346,8 @@ ENDIF()
# Xcode doesn't support targets that have only object files,
# so let's add an empty file to keep Xcode happy
IF(CMAKE_GENERATOR MATCHES Xcode)
FILE(WRITE ${CC_SOURCE_DIR}/libmariadb/empty.c "")
SET(EMPTY_FILE ${CC_SOURCE_DIR}/libmariadb/empty.c)
FILE(WRITE ${CC_BINARY_DIR}/libmariadb/empty.c "")
SET(EMPTY_FILE ${CC_BINARY_DIR}/libmariadb/empty.c)
ENDIF()
IF(WIN32)
@@ -358,14 +358,20 @@ IF(WIN32)
"FILE_DESCRIPTION:Dynamic lib for client/server communication")
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})
ADD_LIBRARY(libmariadb SHARED ${libmariadb_RC} ${MARIADB_OBJECTS} ${EMPTY_FILE} mariadbclient.def)
TARGET_LINK_LIBRARIES(libmariadb ${SYSTEM_LIBS})
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}")
ELSE()
ADD_LIBRARY(libmariadb SHARED ${libmariadb_RC} mariadbclient.def)
TARGET_LINK_LIBRARIES(libmariadb mariadbclient)
SET_TARGET_PROPERTIES(libmariadb PROPERTIES LINKER_LANGUAGE C)
ENDIF()
TARGET_LINK_LIBRARIES(libmariadb ${SYSTEM_LIBS})
SIGN_TARGET(libmariadb)
IF(CMAKE_SIZEOF_VOID_P EQUAL 8 AND MSVC)

View File

@@ -156,6 +156,7 @@ const char *mariadb_client_errors[] =
/* 5003 */ "Server doesn't support function '%s'",
/* 5004 */ "File '%s' not found (Errcode: %d)",
/* 5005 */ "Error reading file '%s' (Errcode: %d)",
/* 5006 */ "Bulk operation without parameters is not supported",
""
};

View File

@@ -207,7 +207,7 @@ restart:
if (last_errno== 65535 &&
((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)))
{
@@ -657,10 +657,12 @@ struct st_default_options mariadb_defaults[] =
else \
(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) \
(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) \
free((OPTS)->KEY); \
if((VAL)) \
@@ -1303,6 +1305,17 @@ MYSQL *mthd_my_real_connect(MYSQL *mysql, const char *host, const char *user,
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))
goto error;
@@ -1483,7 +1496,8 @@ MYSQL *mthd_my_real_connect(MYSQL *mysql, const char *host, const char *user,
net->compress= 1;
/* 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))
{
@@ -2955,6 +2969,13 @@ mysql_optionsv(MYSQL *mysql,enum mysql_option option, ...)
case MARIADB_OPT_CONNECTION_READ_ONLY:
OPT_SET_EXTENDED_VALUE_INT(&mysql->options, read_only, *(my_bool *)arg1);
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:
va_end(ap);
return(-1);

View File

@@ -628,8 +628,8 @@ int store_param(MYSQL_STMT *stmt, int column, unsigned char **p, unsigned long r
return 0;
}
/* {{{ mysqlnd_stmt_execute_generate_request */
unsigned char* mysql_stmt_execute_generate_request(MYSQL_STMT *stmt, size_t *request_len)
/* {{{ mysqlnd_stmt_execute_generate_simple_request */
unsigned char* mysql_stmt_execute_generate_simple_request(MYSQL_STMT *stmt, size_t *request_len)
{
/* execute packet has the following format:
Offset Length Description
@@ -648,30 +648,17 @@ unsigned char* mysql_stmt_execute_generate_request(MYSQL_STMT *stmt, size_t *req
unsigned flag (32768)
indicator variable exists (16384)
------------------------------------------
Pre 10.2 protocol
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 free_bytes= 0;
size_t null_byte_offset= 0;
uint i, j, num_rows= 1;
uint i;
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 */
/* check: gr */
if (!(start= p= (uchar *)malloc(length)))
@@ -683,17 +670,11 @@ unsigned char* mysql_stmt_execute_generate_request(MYSQL_STMT *stmt, size_t *req
/* flags is 4 bytes, we store just 1 */
int1store(p, (unsigned char) stmt->flags);
p++;
if (MARIADB_STMT_BULK_SUPPORTED(stmt) && stmt->array_size)
num_rows= stmt->array_size;
int4store(p, num_rows);
int4store(p, 1);
p+= 4;
if (!stmt->param_count && stmt->prebind_params)
stmt->param_count= stmt->prebind_params;
if (stmt->param_count)
{
if (!stmt->array_size)
{
size_t null_count= (stmt->param_count + 7) / 8;
@@ -710,7 +691,7 @@ unsigned char* mysql_stmt_execute_generate_request(MYSQL_STMT *stmt, size_t *req
null_byte_offset= p - start;
memset(p, 0, null_count);
p += null_count;
}
int1store(p, stmt->send_types_to_server);
p++;
@@ -734,49 +715,27 @@ unsigned char* mysql_stmt_execute_generate_request(MYSQL_STMT *stmt, size_t *req
/* this differs from mysqlnd, c api supports unsinged !! */
uint buffer_type= stmt->params[i].buffer_type | (stmt->params[i].is_unsigned ? 32768 : 0);
/* 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);
p+= 2;
}
}
/* 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;
char indicator= 0;
if (MARIADB_STMT_BULK_SUPPORTED(stmt) &&
(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;
stmt->params[i].long_data_used= 0;
}
if (has_data)
{
switch (stmt->params[i].buffer_type) {
case MYSQL_TYPE_NULL:
if (MARIADB_STMT_BULK_SUPPORTED(stmt))
indicator= STMT_INDICATOR_NULL;
has_data= FALSE;
break;
case MYSQL_TYPE_TINY_BLOB:
@@ -793,6 +752,180 @@ unsigned char* mysql_stmt_execute_generate_request(MYSQL_STMT *stmt, size_t *req
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++)
{
size_t size= 0;
my_bool has_data= TRUE;
char indicator= ma_get_indicator(stmt, i, j);
/* check if we need to send data */
if (indicator > 0)
has_data= FALSE;
size= 1;
/* Please note that mysql_stmt_send_long_data is not supported
current when performing bulk execute */
if (has_data)
{
switch (stmt->params[i].buffer_type) {
case MYSQL_TYPE_NULL:
has_data= FALSE;
indicator= STMT_INDICATOR_NULL;
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 */
if (indicator == STMT_INDICATOR_NTS ||
@@ -818,29 +951,12 @@ unsigned char* mysql_stmt_execute_generate_request(MYSQL_STMT *stmt, size_t *req
p= start + offset;
}
if ((indicator != STMT_INDICATOR_DEFAULT && indicator != STMT_INDICATOR_IGNORE) &&
((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;
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)
{
store_param(stmt, i, &p, j);
}
}
}
}
stmt->send_types_to_server= 0;
@@ -853,7 +969,6 @@ mem_error:
return NULL;
}
/* }}} */
/*!
*******************************************************************************
@@ -1820,13 +1935,17 @@ int STDCALL mysql_stmt_execute(MYSQL_STMT *stmt)
stmt->result_cursor= stmt->result.data= 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)
return 1;
ret= stmt->mysql->methods->db_command(mysql, COM_STMT_EXECUTE, request,
request_len, 1, stmt);
ret= stmt->mysql->methods->db_command(mysql,
stmt->array_size > 0 ? COM_STMT_BULK_EXECUTE : COM_STMT_EXECUTE,
request, request_len, 1, stmt);
if (request)
free(request);
@@ -2151,7 +2270,8 @@ int STDCALL mariadb_stmt_execute_direct(MYSQL_STMT *stmt,
{
MYSQL *mysql= stmt->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)
{

View File

@@ -451,7 +451,7 @@ int ma_tls_verify_server_cert(MARIADB_TLS *ctls)
if (pszServerName && (sctx->mysql->client_flag & CLIENT_SSL_VERIFY_SERVER_CERT))
{
DWORD NameSize= 0;
char *p1, *p2;
char *p1;
SECURITY_STATUS sRet;
if ((sRet= QueryContextAttributes(&sctx->ctxt, SECPKG_ATTR_REMOTE_CERT_CONTEXT, (PVOID)&pServerCert)) != SEC_E_OK)

View File

@@ -212,6 +212,8 @@ static int send_client_reply_packet(MCPVIO_EXT *mpvio,
if (mysql->client_flag & CLIENT_PROTOCOL_41)
{
/* 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+4, net->max_packet_size);
buff[8]= (char) mysql->charset->nr;

View File

@@ -37,7 +37,8 @@ char *rand_str(size_t length) {
static int check_bulk(MYSQL *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 ");
return OK;
}
@@ -512,8 +513,266 @@ static int bulk6(MYSQL *mysql)
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[] = {
{"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},
{"bulk6", bulk6, TEST_CONNECTION_DEFAULT, 0, NULL, NULL},
{"bulk1", bulk1, TEST_CONNECTION_DEFAULT, 0, NULL, NULL},

View File

@@ -832,7 +832,6 @@ static int test_prepare_alter(MYSQL *mysql)
rc= mysql_stmt_execute(stmt);
check_stmt_rc(rc, stmt);
mysql_new= mysql_init(NULL);
FAIL_IF(!mysql_new, "mysql_init failed");
FAIL_IF(!(my_test_connect(mysql_new, hostname, username, password,