Loading include/mysql.h +1 −1 Original line number Diff line number Diff line Loading @@ -558,7 +558,7 @@ typedef struct st_mysql_bind enum enum_field_types buffer_type; /* buffer type */ unsigned long buffer_length; /* buffer length, must be set for str/binary */ /* Following are for internal use. Set by mysql_bind_param */ /* Following are for internal use. Set by mysql_stmt_bind_param */ unsigned char *inter_buffer; /* for the current data position */ unsigned long offset; /* offset position for char/binary fetch */ unsigned long internal_length; /* Used if length is 0 */ Loading libmysql/libmysql.c +236 −154 Original line number Diff line number Diff line Loading @@ -2130,10 +2130,23 @@ mysql_stmt_result_metadata(MYSQL_STMT *stmt) DBUG_RETURN(result); } /* Returns parameter columns meta information in the form of result set. SYNOPSYS mysql_stmt_param_metadata() stmt statement handle DESCRIPTION This function can be called after you prepared the statement handle with mysql_stmt_prepare(). XXX: not implemented yet. RETURN MYSQL_RES on success, 0 if there is no metadata. Currently this function always returns 0. */ MYSQL_RES * STDCALL Loading @@ -2146,25 +2159,36 @@ mysql_stmt_param_metadata(MYSQL_STMT *stmt) /* TODO: Fix this when server sends the information. Till then keep a dummy prototype Till then keep a dummy prototype. */ DBUG_RETURN(0); } /* Store type of parameter in network buffer. */ static void store_param_type(char **pos, MYSQL_BIND *param) { uint typecode= param->buffer_type | (param->is_unsigned ? 32768 : 0); int2store(*pos, typecode); *pos+= 2; } /* Functions to store parameter data in network packet. All functions have the following characteristics: SYNOPSIS store_param_xxx() net MySQL NET connection param MySQL bind param RETURN VALUES 0 ok 1 Error (Can't alloc net->buffer) DESCRIPTION These funtions are invoked from mysql_stmt_execute by MYSQL_BIND::store_param_func pointer. This pointer is set once per many executions in mysql_stmt_bind_param. The caller must ensure that network buffer have enough capacity to store parameter (MYSQL_BIND::buffer_length contains needed number of bytes). */ static void store_param_tinyint(NET *net, MYSQL_BIND *param) Loading Loading @@ -2292,7 +2316,8 @@ static void store_param_str(NET *net, MYSQL_BIND *param) DESCRIPTION A data package starts with a string of bits where we set a bit if a parameter is NULL if a parameter is NULL. Unlike bit string in result set row, here we don't have reserved bits for OK/error packet. */ static void store_param_null(NET *net, MYSQL_BIND *param) Loading @@ -2303,8 +2328,9 @@ static void store_param_null(NET *net, MYSQL_BIND *param) /* Set parameter data by reading from input buffers from the client application Store one parameter in network packet: data is read from client buffer and saved in network packet by means of one of store_param_xxxx functions. */ static my_bool store_param(MYSQL_STMT *stmt, MYSQL_BIND *param) Loading Loading @@ -2365,14 +2391,6 @@ static my_bool execute(MYSQL_STMT * stmt, char *packet, ulong length) } static void store_param_type(char **pos, MYSQL_BIND *param) { uint typecode= param->buffer_type | (param->is_unsigned ? 32768 : 0); int2store(*pos, typecode); *pos+= 2; } int cli_stmt_execute(MYSQL_STMT *stmt) { DBUG_ENTER("cli_stmt_execute"); Loading Loading @@ -2413,7 +2431,7 @@ int cli_stmt_execute(MYSQL_STMT *stmt) for (param= stmt->params; param < param_end; param++) { /* check if mysql_long_data() was used */ /* check if mysql_stmt_send_long_data() was used */ if (param->long_data_used) param->long_data_used= 0; /* Clear for next execute call */ else if (store_param(stmt, param)) Loading Loading @@ -2587,7 +2605,47 @@ my_bool STDCALL mysql_stmt_attr_get(MYSQL_STMT *stmt, /* Execute the prepared query Send placeholders data to server (if there are placeholders) and execute prepared statement. SYNOPSIS mysql_stmt_execute() stmt statement handle. The handle must be created with mysql_stmt_init() and prepared with mysql_stmt_prepare(). If there are placeholders in the statement they must be bound to local variables with mysql_stmt_bind_param(). DESCRIPTION This function will automatically flush pending result set (if there is one), send parameters data to the server and read result of statement execution. If previous result set was cached with mysql_stmt_store_result() it will also be freed in the beginning of this call. The server can return 3 types of responses to this command: - error, can be retrieved with mysql_stmt_error() - ok, no result set pending. In this case we just update stmt->insert_id and stmt->affected_rows. - the query returns a result set: there could be 0 .. N rows in it. In this case the server can also send updated result set metadata. Next steps you may want to make: - find out if there is result set with mysql_stmt_field_count(). If there is one: - optionally, cache entire result set on client to unblock connection with mysql_stmt_store_result() - bind client variables to result set columns and start read rows with mysql_stmt_fetch(). - reset statement with mysql_stmt_reset() or close it with mysql_stmt_close() Otherwise: - find out last insert id and number of affected rows with mysql_stmt_insert_id(), mysql_stmt_affected_rows() RETURN 0 success 1 error, message can be retrieved with mysql_stmt_error(). */ int STDCALL mysql_stmt_execute(MYSQL_STMT *stmt) Loading Loading @@ -2681,7 +2739,19 @@ unsigned int STDCALL mysql_stmt_field_count(MYSQL_STMT *stmt) } /* Return last inserted id for auto_increment columns Return last inserted id for auto_increment columns. SYNOPSIS mysql_stmt_insert_id() stmt statement handle DESCRIPTION Current implementation of this call has a caveat: stmt->insert_id is unconditionally updated from mysql->insert_id in the end of each mysql_stmt_execute(). This works OK if mysql->insert_id contains new value (sent in reply to mysql_stmt_execute()), otherwise stmt->insert_id value gets undefined, as it's updated from some arbitrary value saved in connection structure during some other call. */ my_ulonglong STDCALL mysql_stmt_insert_id(MYSQL_STMT *stmt) Loading @@ -2693,8 +2763,21 @@ my_ulonglong STDCALL mysql_stmt_insert_id(MYSQL_STMT *stmt) static my_bool int_is_null_true= 1; /* Used for MYSQL_TYPE_NULL */ static my_bool int_is_null_false= 0; /* Setup the parameter data buffers from application Setup the input parameter data buffers from application SYNOPSIS mysql_stmt_bind_param() stmt statement handle The statement must be prepared with mysql_stmt_prepare(). bind Array of mysql_stmt_param_count() bind parameters. RETURN 0 success 1 error, can be retrieved with mysql_stmt_error. Note, that this function doesn't check that size of MYSQL_BIND array is >= mysql_stmt_field_count(), */ my_bool STDCALL mysql_stmt_bind_param(MYSQL_STMT *stmt, MYSQL_BIND *bind) Loading Loading @@ -3825,6 +3908,49 @@ int cli_read_binary_rows(MYSQL_STMT *stmt) } /* Update meta data for statement SYNOPSIS stmt_update_metadata() stmt Statement handler row Binary data NOTES Only updates MYSQL_FIELD->max_length for strings */ static void stmt_update_metadata(MYSQL_STMT *stmt, MYSQL_ROWS *data) { MYSQL_BIND *bind, *end; MYSQL_FIELD *field; uchar *null_ptr, bit; uchar *row= (uchar*) data->data; #ifndef DBUG_OFF uchar *row_end= row + data->length; #endif null_ptr= row; row+= (stmt->field_count+9)/8; /* skip null bits */ bit= 4; /* first 2 bits are reserved */ /* Go throw all fields and calculate metadata */ for (bind= stmt->bind, end= bind + stmt->field_count, field= stmt->fields ; bind < end ; bind++, field++) { if (!(*null_ptr & bit)) (*bind->skip_result)(bind, field, &row); DBUG_ASSERT(row <= row_end); if (!((bit<<=1) & 255)) { bit= 1; /* To next byte */ null_ptr++; } } } /* Store or buffer the binary results to stmt */ Loading Loading @@ -4116,50 +4242,6 @@ const char *STDCALL mysql_stmt_error(MYSQL_STMT * stmt) } /* Update meta data for statement SYNOPSIS stmt_update_metadata() stmt Statement handler row Binary data NOTES Only updates MYSQL_FIELD->max_length for strings */ static void stmt_update_metadata(MYSQL_STMT *stmt, MYSQL_ROWS *data) { MYSQL_BIND *bind, *end; MYSQL_FIELD *field; uchar *null_ptr, bit; uchar *row= (uchar*) data->data; #ifndef DBUG_OFF uchar *row_end= row + data->length; #endif null_ptr= row; row+= (stmt->field_count+9)/8; /* skip null bits */ bit= 4; /* first 2 bits are reserved */ /* Go throw all fields and calculate metadata */ for (bind= stmt->bind, end= bind + stmt->field_count, field= stmt->fields ; bind < end ; bind++, field++) { if (!(*null_ptr & bit)) (*bind->skip_result)(bind, field, &row); DBUG_ASSERT(row <= row_end); if (!((bit<<=1) & 255)) { bit= 1; /* To next byte */ null_ptr++; } } } /******************************************************************** Transactional APIs *********************************************************************/ Loading Loading
include/mysql.h +1 −1 Original line number Diff line number Diff line Loading @@ -558,7 +558,7 @@ typedef struct st_mysql_bind enum enum_field_types buffer_type; /* buffer type */ unsigned long buffer_length; /* buffer length, must be set for str/binary */ /* Following are for internal use. Set by mysql_bind_param */ /* Following are for internal use. Set by mysql_stmt_bind_param */ unsigned char *inter_buffer; /* for the current data position */ unsigned long offset; /* offset position for char/binary fetch */ unsigned long internal_length; /* Used if length is 0 */ Loading
libmysql/libmysql.c +236 −154 Original line number Diff line number Diff line Loading @@ -2130,10 +2130,23 @@ mysql_stmt_result_metadata(MYSQL_STMT *stmt) DBUG_RETURN(result); } /* Returns parameter columns meta information in the form of result set. SYNOPSYS mysql_stmt_param_metadata() stmt statement handle DESCRIPTION This function can be called after you prepared the statement handle with mysql_stmt_prepare(). XXX: not implemented yet. RETURN MYSQL_RES on success, 0 if there is no metadata. Currently this function always returns 0. */ MYSQL_RES * STDCALL Loading @@ -2146,25 +2159,36 @@ mysql_stmt_param_metadata(MYSQL_STMT *stmt) /* TODO: Fix this when server sends the information. Till then keep a dummy prototype Till then keep a dummy prototype. */ DBUG_RETURN(0); } /* Store type of parameter in network buffer. */ static void store_param_type(char **pos, MYSQL_BIND *param) { uint typecode= param->buffer_type | (param->is_unsigned ? 32768 : 0); int2store(*pos, typecode); *pos+= 2; } /* Functions to store parameter data in network packet. All functions have the following characteristics: SYNOPSIS store_param_xxx() net MySQL NET connection param MySQL bind param RETURN VALUES 0 ok 1 Error (Can't alloc net->buffer) DESCRIPTION These funtions are invoked from mysql_stmt_execute by MYSQL_BIND::store_param_func pointer. This pointer is set once per many executions in mysql_stmt_bind_param. The caller must ensure that network buffer have enough capacity to store parameter (MYSQL_BIND::buffer_length contains needed number of bytes). */ static void store_param_tinyint(NET *net, MYSQL_BIND *param) Loading Loading @@ -2292,7 +2316,8 @@ static void store_param_str(NET *net, MYSQL_BIND *param) DESCRIPTION A data package starts with a string of bits where we set a bit if a parameter is NULL if a parameter is NULL. Unlike bit string in result set row, here we don't have reserved bits for OK/error packet. */ static void store_param_null(NET *net, MYSQL_BIND *param) Loading @@ -2303,8 +2328,9 @@ static void store_param_null(NET *net, MYSQL_BIND *param) /* Set parameter data by reading from input buffers from the client application Store one parameter in network packet: data is read from client buffer and saved in network packet by means of one of store_param_xxxx functions. */ static my_bool store_param(MYSQL_STMT *stmt, MYSQL_BIND *param) Loading Loading @@ -2365,14 +2391,6 @@ static my_bool execute(MYSQL_STMT * stmt, char *packet, ulong length) } static void store_param_type(char **pos, MYSQL_BIND *param) { uint typecode= param->buffer_type | (param->is_unsigned ? 32768 : 0); int2store(*pos, typecode); *pos+= 2; } int cli_stmt_execute(MYSQL_STMT *stmt) { DBUG_ENTER("cli_stmt_execute"); Loading Loading @@ -2413,7 +2431,7 @@ int cli_stmt_execute(MYSQL_STMT *stmt) for (param= stmt->params; param < param_end; param++) { /* check if mysql_long_data() was used */ /* check if mysql_stmt_send_long_data() was used */ if (param->long_data_used) param->long_data_used= 0; /* Clear for next execute call */ else if (store_param(stmt, param)) Loading Loading @@ -2587,7 +2605,47 @@ my_bool STDCALL mysql_stmt_attr_get(MYSQL_STMT *stmt, /* Execute the prepared query Send placeholders data to server (if there are placeholders) and execute prepared statement. SYNOPSIS mysql_stmt_execute() stmt statement handle. The handle must be created with mysql_stmt_init() and prepared with mysql_stmt_prepare(). If there are placeholders in the statement they must be bound to local variables with mysql_stmt_bind_param(). DESCRIPTION This function will automatically flush pending result set (if there is one), send parameters data to the server and read result of statement execution. If previous result set was cached with mysql_stmt_store_result() it will also be freed in the beginning of this call. The server can return 3 types of responses to this command: - error, can be retrieved with mysql_stmt_error() - ok, no result set pending. In this case we just update stmt->insert_id and stmt->affected_rows. - the query returns a result set: there could be 0 .. N rows in it. In this case the server can also send updated result set metadata. Next steps you may want to make: - find out if there is result set with mysql_stmt_field_count(). If there is one: - optionally, cache entire result set on client to unblock connection with mysql_stmt_store_result() - bind client variables to result set columns and start read rows with mysql_stmt_fetch(). - reset statement with mysql_stmt_reset() or close it with mysql_stmt_close() Otherwise: - find out last insert id and number of affected rows with mysql_stmt_insert_id(), mysql_stmt_affected_rows() RETURN 0 success 1 error, message can be retrieved with mysql_stmt_error(). */ int STDCALL mysql_stmt_execute(MYSQL_STMT *stmt) Loading Loading @@ -2681,7 +2739,19 @@ unsigned int STDCALL mysql_stmt_field_count(MYSQL_STMT *stmt) } /* Return last inserted id for auto_increment columns Return last inserted id for auto_increment columns. SYNOPSIS mysql_stmt_insert_id() stmt statement handle DESCRIPTION Current implementation of this call has a caveat: stmt->insert_id is unconditionally updated from mysql->insert_id in the end of each mysql_stmt_execute(). This works OK if mysql->insert_id contains new value (sent in reply to mysql_stmt_execute()), otherwise stmt->insert_id value gets undefined, as it's updated from some arbitrary value saved in connection structure during some other call. */ my_ulonglong STDCALL mysql_stmt_insert_id(MYSQL_STMT *stmt) Loading @@ -2693,8 +2763,21 @@ my_ulonglong STDCALL mysql_stmt_insert_id(MYSQL_STMT *stmt) static my_bool int_is_null_true= 1; /* Used for MYSQL_TYPE_NULL */ static my_bool int_is_null_false= 0; /* Setup the parameter data buffers from application Setup the input parameter data buffers from application SYNOPSIS mysql_stmt_bind_param() stmt statement handle The statement must be prepared with mysql_stmt_prepare(). bind Array of mysql_stmt_param_count() bind parameters. RETURN 0 success 1 error, can be retrieved with mysql_stmt_error. Note, that this function doesn't check that size of MYSQL_BIND array is >= mysql_stmt_field_count(), */ my_bool STDCALL mysql_stmt_bind_param(MYSQL_STMT *stmt, MYSQL_BIND *bind) Loading Loading @@ -3825,6 +3908,49 @@ int cli_read_binary_rows(MYSQL_STMT *stmt) } /* Update meta data for statement SYNOPSIS stmt_update_metadata() stmt Statement handler row Binary data NOTES Only updates MYSQL_FIELD->max_length for strings */ static void stmt_update_metadata(MYSQL_STMT *stmt, MYSQL_ROWS *data) { MYSQL_BIND *bind, *end; MYSQL_FIELD *field; uchar *null_ptr, bit; uchar *row= (uchar*) data->data; #ifndef DBUG_OFF uchar *row_end= row + data->length; #endif null_ptr= row; row+= (stmt->field_count+9)/8; /* skip null bits */ bit= 4; /* first 2 bits are reserved */ /* Go throw all fields and calculate metadata */ for (bind= stmt->bind, end= bind + stmt->field_count, field= stmt->fields ; bind < end ; bind++, field++) { if (!(*null_ptr & bit)) (*bind->skip_result)(bind, field, &row); DBUG_ASSERT(row <= row_end); if (!((bit<<=1) & 255)) { bit= 1; /* To next byte */ null_ptr++; } } } /* Store or buffer the binary results to stmt */ Loading Loading @@ -4116,50 +4242,6 @@ const char *STDCALL mysql_stmt_error(MYSQL_STMT * stmt) } /* Update meta data for statement SYNOPSIS stmt_update_metadata() stmt Statement handler row Binary data NOTES Only updates MYSQL_FIELD->max_length for strings */ static void stmt_update_metadata(MYSQL_STMT *stmt, MYSQL_ROWS *data) { MYSQL_BIND *bind, *end; MYSQL_FIELD *field; uchar *null_ptr, bit; uchar *row= (uchar*) data->data; #ifndef DBUG_OFF uchar *row_end= row + data->length; #endif null_ptr= row; row+= (stmt->field_count+9)/8; /* skip null bits */ bit= 4; /* first 2 bits are reserved */ /* Go throw all fields and calculate metadata */ for (bind= stmt->bind, end= bind + stmt->field_count, field= stmt->fields ; bind < end ; bind++, field++) { if (!(*null_ptr & bit)) (*bind->skip_result)(bind, field, &row); DBUG_ASSERT(row <= row_end); if (!((bit<<=1) & 255)) { bit= 1; /* To next byte */ null_ptr++; } } } /******************************************************************** Transactional APIs *********************************************************************/ Loading