mirror of
https://github.com/MariaDB/server.git
synced 2025-07-27 18:02:13 +03:00
Comments and cleanups in client library.
This commit is contained in:
@ -558,7 +558,7 @@ typedef struct st_mysql_bind
|
|||||||
enum enum_field_types buffer_type; /* buffer type */
|
enum enum_field_types buffer_type; /* buffer type */
|
||||||
unsigned long buffer_length; /* buffer length, must be set for str/binary */
|
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 char *inter_buffer; /* for the current data position */
|
||||||
unsigned long offset; /* offset position for char/binary fetch */
|
unsigned long offset; /* offset position for char/binary fetch */
|
||||||
unsigned long internal_length; /* Used if length is 0 */
|
unsigned long internal_length; /* Used if length is 0 */
|
||||||
|
@ -1945,7 +1945,7 @@ mysql_stmt_prepare(MYSQL_STMT *stmt, const char *query, ulong length)
|
|||||||
|
|
||||||
mysql_stmt_free_result(stmt);
|
mysql_stmt_free_result(stmt);
|
||||||
/*
|
/*
|
||||||
These members must be reset for API to
|
These members must be reset for API to
|
||||||
function in case of error or misuse.
|
function in case of error or misuse.
|
||||||
*/
|
*/
|
||||||
stmt->bind_param_done= stmt->bind_result_done= FALSE;
|
stmt->bind_param_done= stmt->bind_result_done= FALSE;
|
||||||
@ -1984,14 +1984,14 @@ mysql_stmt_prepare(MYSQL_STMT *stmt, const char *query, ulong length)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
alloc_root will return valid address even in case param_count
|
alloc_root will return valid address even in case param_count
|
||||||
and field_count are zero. Thus we should never rely on stmt->bind
|
and field_count are zero. Thus we should never rely on stmt->bind
|
||||||
or stmt->params when checking for existence of placeholders or
|
or stmt->params when checking for existence of placeholders or
|
||||||
result set.
|
result set.
|
||||||
*/
|
*/
|
||||||
if (!(stmt->params= (MYSQL_BIND *) alloc_root(&stmt->mem_root,
|
if (!(stmt->params= (MYSQL_BIND *) alloc_root(&stmt->mem_root,
|
||||||
sizeof(MYSQL_BIND)*
|
sizeof(MYSQL_BIND)*
|
||||||
(stmt->param_count +
|
(stmt->param_count +
|
||||||
stmt->field_count))))
|
stmt->field_count))))
|
||||||
{
|
{
|
||||||
set_stmt_error(stmt, CR_OUT_OF_MEMORY, unknown_sqlstate);
|
set_stmt_error(stmt, CR_OUT_OF_MEMORY, unknown_sqlstate);
|
||||||
@ -2015,22 +2015,22 @@ static unsigned int alloc_stmt_fields(MYSQL_STMT *stmt)
|
|||||||
MYSQL_FIELD *fields, *field, *end;
|
MYSQL_FIELD *fields, *field, *end;
|
||||||
MEM_ROOT *alloc= &stmt->mem_root;
|
MEM_ROOT *alloc= &stmt->mem_root;
|
||||||
MYSQL *mysql= stmt->mysql->last_used_con;
|
MYSQL *mysql= stmt->mysql->last_used_con;
|
||||||
|
|
||||||
stmt->field_count= mysql->field_count;
|
stmt->field_count= mysql->field_count;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Get the field information for non-select statements
|
Get the field information for non-select statements
|
||||||
like SHOW and DESCRIBE commands
|
like SHOW and DESCRIBE commands
|
||||||
*/
|
*/
|
||||||
if (!(stmt->fields= (MYSQL_FIELD *) alloc_root(alloc,
|
if (!(stmt->fields= (MYSQL_FIELD *) alloc_root(alloc,
|
||||||
sizeof(MYSQL_FIELD) *
|
sizeof(MYSQL_FIELD) *
|
||||||
stmt->field_count)) ||
|
stmt->field_count)) ||
|
||||||
!(stmt->bind= (MYSQL_BIND *) alloc_root(alloc,
|
!(stmt->bind= (MYSQL_BIND *) alloc_root(alloc,
|
||||||
sizeof(MYSQL_BIND) *
|
sizeof(MYSQL_BIND) *
|
||||||
stmt->field_count)))
|
stmt->field_count)))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
for (fields= mysql->fields, end= fields+stmt->field_count,
|
for (fields= mysql->fields, end= fields+stmt->field_count,
|
||||||
field= stmt->fields;
|
field= stmt->fields;
|
||||||
field && fields < end; fields++, field++)
|
field && fields < end; fields++, field++)
|
||||||
{
|
{
|
||||||
@ -2107,7 +2107,7 @@ mysql_stmt_result_metadata(MYSQL_STMT *stmt)
|
|||||||
{
|
{
|
||||||
MYSQL_RES *result;
|
MYSQL_RES *result;
|
||||||
DBUG_ENTER("mysql_stmt_result_metadata");
|
DBUG_ENTER("mysql_stmt_result_metadata");
|
||||||
|
|
||||||
/*
|
/*
|
||||||
stmt->fields is only defined if stmt->field_count is not null;
|
stmt->fields is only defined if stmt->field_count is not null;
|
||||||
stmt->field_count is initialized in prepare.
|
stmt->field_count is initialized in prepare.
|
||||||
@ -2130,41 +2130,65 @@ mysql_stmt_result_metadata(MYSQL_STMT *stmt)
|
|||||||
DBUG_RETURN(result);
|
DBUG_RETURN(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Returns parameter columns meta information in the form of
|
Returns parameter columns meta information in the form of
|
||||||
result set.
|
result set.
|
||||||
XXX: not implemented yet.
|
|
||||||
|
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
|
MYSQL_RES * STDCALL
|
||||||
mysql_stmt_param_metadata(MYSQL_STMT *stmt)
|
mysql_stmt_param_metadata(MYSQL_STMT *stmt)
|
||||||
{
|
{
|
||||||
DBUG_ENTER("mysql_stmt_param_metadata");
|
DBUG_ENTER("mysql_stmt_param_metadata");
|
||||||
|
|
||||||
if (!stmt->param_count)
|
if (!stmt->param_count)
|
||||||
DBUG_RETURN(0);
|
DBUG_RETURN(0);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
TODO: Fix this when server sends the information.
|
TODO: Fix this when server sends the information.
|
||||||
Till then keep a dummy prototype
|
Till then keep a dummy prototype.
|
||||||
*/
|
*/
|
||||||
DBUG_RETURN(0);
|
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.
|
Functions to store parameter data in network packet.
|
||||||
|
|
||||||
All functions have the following characteristics:
|
|
||||||
|
|
||||||
SYNOPSIS
|
SYNOPSIS
|
||||||
store_param_xxx()
|
store_param_xxx()
|
||||||
net MySQL NET connection
|
net MySQL NET connection
|
||||||
param MySQL bind param
|
param MySQL bind param
|
||||||
|
|
||||||
RETURN VALUES
|
DESCRIPTION
|
||||||
0 ok
|
These funtions are invoked from mysql_stmt_execute by
|
||||||
1 Error (Can't alloc net->buffer)
|
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)
|
static void store_param_tinyint(NET *net, MYSQL_BIND *param)
|
||||||
@ -2253,7 +2277,7 @@ static void net_store_datetime(NET *net, MYSQL_TIME *tm)
|
|||||||
length= 4;
|
length= 4;
|
||||||
else
|
else
|
||||||
length= 0;
|
length= 0;
|
||||||
buff[0]= (char) length++;
|
buff[0]= (char) length++;
|
||||||
memcpy((char *)net->write_pos, buff, length);
|
memcpy((char *)net->write_pos, buff, length);
|
||||||
net->write_pos+= length;
|
net->write_pos+= length;
|
||||||
}
|
}
|
||||||
@ -2271,7 +2295,7 @@ static void store_param_datetime(NET *net, MYSQL_BIND *param)
|
|||||||
MYSQL_TIME *tm= (MYSQL_TIME *) param->buffer;
|
MYSQL_TIME *tm= (MYSQL_TIME *) param->buffer;
|
||||||
net_store_datetime(net, tm);
|
net_store_datetime(net, tm);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void store_param_str(NET *net, MYSQL_BIND *param)
|
static void store_param_str(NET *net, MYSQL_BIND *param)
|
||||||
{
|
{
|
||||||
/* param->length is always set in mysql_stmt_bind_param */
|
/* param->length is always set in mysql_stmt_bind_param */
|
||||||
@ -2292,7 +2316,8 @@ static void store_param_str(NET *net, MYSQL_BIND *param)
|
|||||||
|
|
||||||
DESCRIPTION
|
DESCRIPTION
|
||||||
A data package starts with a string of bits where we set a bit
|
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)
|
static void store_param_null(NET *net, MYSQL_BIND *param)
|
||||||
@ -2303,8 +2328,9 @@ static void store_param_null(NET *net, MYSQL_BIND *param)
|
|||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Set parameter data by reading from input buffers from the
|
Store one parameter in network packet: data is read from
|
||||||
client application
|
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)
|
static my_bool store_param(MYSQL_STMT *stmt, MYSQL_BIND *param)
|
||||||
@ -2339,11 +2365,11 @@ static my_bool store_param(MYSQL_STMT *stmt, MYSQL_BIND *param)
|
|||||||
Send the prepared query to server for execution
|
Send the prepared query to server for execution
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static my_bool execute(MYSQL_STMT * stmt, char *packet, ulong length)
|
static my_bool execute(MYSQL_STMT *stmt, char *packet, ulong length)
|
||||||
{
|
{
|
||||||
MYSQL *mysql= stmt->mysql;
|
MYSQL *mysql= stmt->mysql;
|
||||||
NET *net= &mysql->net;
|
NET *net= &mysql->net;
|
||||||
char buff[4 /* size of stmt id */ +
|
char buff[4 /* size of stmt id */ +
|
||||||
5 /* execution flags */];
|
5 /* execution flags */];
|
||||||
DBUG_ENTER("execute");
|
DBUG_ENTER("execute");
|
||||||
DBUG_PRINT("enter",("packet: %s, length :%d",packet ? packet :" ", length));
|
DBUG_PRINT("enter",("packet: %s, length :%d",packet ? packet :" ", length));
|
||||||
@ -2363,14 +2389,6 @@ static my_bool execute(MYSQL_STMT * stmt, char *packet, ulong length)
|
|||||||
stmt->insert_id= mysql->insert_id;
|
stmt->insert_id= mysql->insert_id;
|
||||||
DBUG_RETURN(0);
|
DBUG_RETURN(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
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)
|
int cli_stmt_execute(MYSQL_STMT *stmt)
|
||||||
@ -2413,7 +2431,7 @@ int cli_stmt_execute(MYSQL_STMT *stmt)
|
|||||||
|
|
||||||
for (param= stmt->params; param < param_end; param++)
|
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)
|
if (param->long_data_used)
|
||||||
param->long_data_used= 0; /* Clear for next execute call */
|
param->long_data_used= 0; /* Clear for next execute call */
|
||||||
else if (store_param(stmt, param))
|
else if (store_param(stmt, param))
|
||||||
@ -2472,16 +2490,16 @@ static int stmt_read_row_buffered(MYSQL_STMT *stmt, unsigned char **row)
|
|||||||
0 - success; *row contains valid address of a row;
|
0 - success; *row contains valid address of a row;
|
||||||
row data is stored in network buffer
|
row data is stored in network buffer
|
||||||
1 - error; error code is written to
|
1 - error; error code is written to
|
||||||
stmt->last_{errno,error}; *row is not changed
|
stmt->last_{errno,error}; *row is not changed
|
||||||
MYSQL_NO_DATA - end of file was read from network;
|
MYSQL_NO_DATA - end of file was read from network;
|
||||||
*row is to NULL
|
*row is to NULL
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static int stmt_read_row_unbuffered(MYSQL_STMT *stmt, unsigned char **row)
|
static int stmt_read_row_unbuffered(MYSQL_STMT *stmt, unsigned char **row)
|
||||||
{
|
{
|
||||||
int rc= 1;
|
int rc= 1;
|
||||||
MYSQL *mysql= stmt->mysql;
|
MYSQL *mysql= stmt->mysql;
|
||||||
/*
|
/*
|
||||||
This function won't be called if stmt->field_count is zero
|
This function won't be called if stmt->field_count is zero
|
||||||
or execution wasn't done: this is ensured by mysql_stmt_execute.
|
or execution wasn't done: this is ensured by mysql_stmt_execute.
|
||||||
*/
|
*/
|
||||||
@ -2555,7 +2573,7 @@ stmt_read_row_no_data(MYSQL_STMT *stmt __attribute__((unused)),
|
|||||||
0 success
|
0 success
|
||||||
!0 wrong attribute type
|
!0 wrong attribute type
|
||||||
*/
|
*/
|
||||||
|
|
||||||
my_bool STDCALL mysql_stmt_attr_set(MYSQL_STMT *stmt,
|
my_bool STDCALL mysql_stmt_attr_set(MYSQL_STMT *stmt,
|
||||||
enum enum_stmt_attr_type attr_type,
|
enum enum_stmt_attr_type attr_type,
|
||||||
const void *value)
|
const void *value)
|
||||||
@ -2564,14 +2582,14 @@ my_bool STDCALL mysql_stmt_attr_set(MYSQL_STMT *stmt,
|
|||||||
case STMT_ATTR_UPDATE_MAX_LENGTH:
|
case STMT_ATTR_UPDATE_MAX_LENGTH:
|
||||||
stmt->update_max_length= value ? *(const my_bool*) value : 0;
|
stmt->update_max_length= value ? *(const my_bool*) value : 0;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
my_bool STDCALL mysql_stmt_attr_get(MYSQL_STMT *stmt,
|
my_bool STDCALL mysql_stmt_attr_get(MYSQL_STMT *stmt,
|
||||||
enum enum_stmt_attr_type attr_type,
|
enum enum_stmt_attr_type attr_type,
|
||||||
void *value)
|
void *value)
|
||||||
{
|
{
|
||||||
@ -2579,7 +2597,7 @@ my_bool STDCALL mysql_stmt_attr_get(MYSQL_STMT *stmt,
|
|||||||
case STMT_ATTR_UPDATE_MAX_LENGTH:
|
case STMT_ATTR_UPDATE_MAX_LENGTH:
|
||||||
*(unsigned long *) value= stmt->update_max_length;
|
*(unsigned long *) value= stmt->update_max_length;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
return FALSE;
|
return FALSE;
|
||||||
@ -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)
|
int STDCALL mysql_stmt_execute(MYSQL_STMT *stmt)
|
||||||
@ -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)
|
my_ulonglong STDCALL mysql_stmt_insert_id(MYSQL_STMT *stmt)
|
||||||
@ -2693,11 +2763,24 @@ 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_true= 1; /* Used for MYSQL_TYPE_NULL */
|
||||||
static my_bool int_is_null_false= 0;
|
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)
|
my_bool STDCALL mysql_stmt_bind_param(MYSQL_STMT *stmt, MYSQL_BIND *bind)
|
||||||
{
|
{
|
||||||
uint count=0;
|
uint count=0;
|
||||||
MYSQL_BIND *param, *end;
|
MYSQL_BIND *param, *end;
|
||||||
@ -2839,7 +2922,7 @@ mysql_stmt_send_long_data(MYSQL_STMT *stmt, uint param_number,
|
|||||||
DBUG_ASSERT(stmt != 0);
|
DBUG_ASSERT(stmt != 0);
|
||||||
DBUG_PRINT("enter",("param no : %d, data : %lx, length : %ld",
|
DBUG_PRINT("enter",("param no : %d, data : %lx, length : %ld",
|
||||||
param_number, data, length));
|
param_number, data, length));
|
||||||
|
|
||||||
/*
|
/*
|
||||||
We only need to check for stmt->param_count, if it's not null
|
We only need to check for stmt->param_count, if it's not null
|
||||||
prepare was done.
|
prepare was done.
|
||||||
@ -2864,7 +2947,7 @@ mysql_stmt_send_long_data(MYSQL_STMT *stmt, uint param_number,
|
|||||||
DBUG_RETURN(1);
|
DBUG_RETURN(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Send long data packet if there is data or we're sending long data
|
Send long data packet if there is data or we're sending long data
|
||||||
for the first time.
|
for the first time.
|
||||||
*/
|
*/
|
||||||
@ -2872,8 +2955,8 @@ mysql_stmt_send_long_data(MYSQL_STMT *stmt, uint param_number,
|
|||||||
{
|
{
|
||||||
MYSQL *mysql= stmt->mysql;
|
MYSQL *mysql= stmt->mysql;
|
||||||
/* Packet header: stmt id (4 bytes), param no (2 bytes) */
|
/* Packet header: stmt id (4 bytes), param no (2 bytes) */
|
||||||
char buff[MYSQL_LONG_DATA_HEADER];
|
char buff[MYSQL_LONG_DATA_HEADER];
|
||||||
|
|
||||||
int4store(buff, stmt->stmt_id);
|
int4store(buff, stmt->stmt_id);
|
||||||
int2store(buff + 4, param_number);
|
int2store(buff + 4, param_number);
|
||||||
param->long_data_used= 1;
|
param->long_data_used= 1;
|
||||||
@ -2926,7 +3009,7 @@ static uint read_binary_time(MYSQL_TIME *tm, uchar **pos)
|
|||||||
{
|
{
|
||||||
uchar *to;
|
uchar *to;
|
||||||
uint length;
|
uint length;
|
||||||
|
|
||||||
/* net_field_length will set pos to the first byte of data */
|
/* net_field_length will set pos to the first byte of data */
|
||||||
if (!(length= net_field_length(pos)))
|
if (!(length= net_field_length(pos)))
|
||||||
{
|
{
|
||||||
@ -2983,14 +3066,14 @@ static uint read_binary_date(MYSQL_TIME *tm, uchar **pos)
|
|||||||
{
|
{
|
||||||
uchar *to;
|
uchar *to;
|
||||||
uint length;
|
uint length;
|
||||||
|
|
||||||
if (!(length= net_field_length(pos)))
|
if (!(length= net_field_length(pos)))
|
||||||
{
|
{
|
||||||
set_zero_time(tm);
|
set_zero_time(tm);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
to= *pos;
|
to= *pos;
|
||||||
tm->year = (uint) sint2korr(to);
|
tm->year = (uint) sint2korr(to);
|
||||||
tm->month= (uint) to[2];
|
tm->month= (uint) to[2];
|
||||||
tm->day= (uint) to[3];
|
tm->day= (uint) to[3];
|
||||||
@ -3004,7 +3087,7 @@ static uint read_binary_date(MYSQL_TIME *tm, uchar **pos)
|
|||||||
/* Convert Numeric to buffer types */
|
/* Convert Numeric to buffer types */
|
||||||
static void send_data_long(MYSQL_BIND *param, MYSQL_FIELD *field,
|
static void send_data_long(MYSQL_BIND *param, MYSQL_FIELD *field,
|
||||||
longlong value)
|
longlong value)
|
||||||
{
|
{
|
||||||
char *buffer= param->buffer;
|
char *buffer= param->buffer;
|
||||||
uint field_is_unsigned= (field->flags & UNSIGNED_FLAG);
|
uint field_is_unsigned= (field->flags & UNSIGNED_FLAG);
|
||||||
|
|
||||||
@ -3041,26 +3124,26 @@ static void send_data_long(MYSQL_BIND *param, MYSQL_FIELD *field,
|
|||||||
{
|
{
|
||||||
char tmp[22]; /* Enough for longlong */
|
char tmp[22]; /* Enough for longlong */
|
||||||
uint length= (uint)(longlong10_to_str(value,(char *)tmp,
|
uint length= (uint)(longlong10_to_str(value,(char *)tmp,
|
||||||
field_is_unsigned ? 10: -10) -
|
field_is_unsigned ? 10: -10) -
|
||||||
tmp);
|
tmp);
|
||||||
ulong copy_length= min((ulong)length-param->offset, param->buffer_length);
|
ulong copy_length= min((ulong)length-param->offset, param->buffer_length);
|
||||||
if ((long) copy_length < 0)
|
if ((long) copy_length < 0)
|
||||||
copy_length=0;
|
copy_length=0;
|
||||||
else
|
else
|
||||||
memcpy(buffer, (char *)tmp+param->offset, copy_length);
|
memcpy(buffer, (char *)tmp+param->offset, copy_length);
|
||||||
*param->length= length;
|
*param->length= length;
|
||||||
|
|
||||||
if (copy_length != param->buffer_length)
|
if (copy_length != param->buffer_length)
|
||||||
*(buffer+copy_length)= '\0';
|
*(buffer+copy_length)= '\0';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Convert Double to buffer types */
|
/* Convert Double to buffer types */
|
||||||
|
|
||||||
static void send_data_double(MYSQL_BIND *param, double value)
|
static void send_data_double(MYSQL_BIND *param, double value)
|
||||||
{
|
{
|
||||||
char *buffer= param->buffer;
|
char *buffer= param->buffer;
|
||||||
|
|
||||||
switch(param->buffer_type) {
|
switch(param->buffer_type) {
|
||||||
@ -3099,19 +3182,19 @@ static void send_data_double(MYSQL_BIND *param, double value)
|
|||||||
copy_length=0;
|
copy_length=0;
|
||||||
else
|
else
|
||||||
memcpy(buffer, (char *)tmp+param->offset, copy_length);
|
memcpy(buffer, (char *)tmp+param->offset, copy_length);
|
||||||
*param->length= length;
|
*param->length= length;
|
||||||
|
|
||||||
if (copy_length != param->buffer_length)
|
if (copy_length != param->buffer_length)
|
||||||
*(buffer+copy_length)= '\0';
|
*(buffer+copy_length)= '\0';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Convert string to buffer types */
|
/* Convert string to buffer types */
|
||||||
|
|
||||||
static void send_data_str(MYSQL_BIND *param, char *value, uint length)
|
static void send_data_str(MYSQL_BIND *param, char *value, uint length)
|
||||||
{
|
{
|
||||||
char *buffer= param->buffer;
|
char *buffer= param->buffer;
|
||||||
int err=0;
|
int err=0;
|
||||||
|
|
||||||
@ -3136,7 +3219,7 @@ static void send_data_str(MYSQL_BIND *param, char *value, uint length)
|
|||||||
{
|
{
|
||||||
int32 data= (int32)my_strntol(&my_charset_latin1,value,length,10,NULL,
|
int32 data= (int32)my_strntol(&my_charset_latin1,value,length,10,NULL,
|
||||||
&err);
|
&err);
|
||||||
int4store(buffer, data);
|
int4store(buffer, data);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case MYSQL_TYPE_LONGLONG:
|
case MYSQL_TYPE_LONGLONG:
|
||||||
@ -3179,7 +3262,7 @@ static void send_data_str(MYSQL_BIND *param, char *value, uint length)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void send_data_time(MYSQL_BIND *param, MYSQL_TIME ltime,
|
static void send_data_time(MYSQL_BIND *param, MYSQL_TIME ltime,
|
||||||
uint length)
|
uint length)
|
||||||
{
|
{
|
||||||
switch (param->buffer_type) {
|
switch (param->buffer_type) {
|
||||||
@ -3192,7 +3275,7 @@ static void send_data_time(MYSQL_BIND *param, MYSQL_TIME ltime,
|
|||||||
case MYSQL_TYPE_TIMESTAMP:
|
case MYSQL_TYPE_TIMESTAMP:
|
||||||
{
|
{
|
||||||
MYSQL_TIME *tm= (MYSQL_TIME *)param->buffer;
|
MYSQL_TIME *tm= (MYSQL_TIME *)param->buffer;
|
||||||
|
|
||||||
tm->year= ltime.year;
|
tm->year= ltime.year;
|
||||||
tm->month= ltime.month;
|
tm->month= ltime.month;
|
||||||
tm->day= ltime.day;
|
tm->day= ltime.day;
|
||||||
@ -3203,33 +3286,33 @@ static void send_data_time(MYSQL_BIND *param, MYSQL_TIME ltime,
|
|||||||
|
|
||||||
tm->second_part= ltime.second_part;
|
tm->second_part= ltime.second_part;
|
||||||
tm->neg= ltime.neg;
|
tm->neg= ltime.neg;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
{
|
{
|
||||||
char buff[25];
|
char buff[25];
|
||||||
|
|
||||||
if (!length)
|
if (!length)
|
||||||
ltime.time_type= MYSQL_TIMESTAMP_NONE;
|
ltime.time_type= MYSQL_TIMESTAMP_NONE;
|
||||||
switch (ltime.time_type) {
|
switch (ltime.time_type) {
|
||||||
case MYSQL_TIMESTAMP_DATE:
|
case MYSQL_TIMESTAMP_DATE:
|
||||||
length= my_sprintf(buff,(buff, "%04d-%02d-%02d", ltime.year,
|
length= my_sprintf(buff,(buff, "%04d-%02d-%02d", ltime.year,
|
||||||
ltime.month,ltime.day));
|
ltime.month,ltime.day));
|
||||||
break;
|
break;
|
||||||
case MYSQL_TIMESTAMP_FULL:
|
case MYSQL_TIMESTAMP_FULL:
|
||||||
length= my_sprintf(buff,(buff, "%04d-%02d-%02d %02d:%02d:%02d",
|
length= my_sprintf(buff,(buff, "%04d-%02d-%02d %02d:%02d:%02d",
|
||||||
ltime.year,ltime.month,ltime.day,
|
ltime.year,ltime.month,ltime.day,
|
||||||
ltime.hour,ltime.minute,ltime.second));
|
ltime.hour,ltime.minute,ltime.second));
|
||||||
break;
|
break;
|
||||||
case MYSQL_TIMESTAMP_TIME:
|
case MYSQL_TIMESTAMP_TIME:
|
||||||
length= my_sprintf(buff, (buff, "%02d:%02d:%02d",
|
length= my_sprintf(buff, (buff, "%02d:%02d:%02d",
|
||||||
ltime.hour,ltime.minute,ltime.second));
|
ltime.hour,ltime.minute,ltime.second));
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
length= 0;
|
length= 0;
|
||||||
buff[0]='\0';
|
buff[0]='\0';
|
||||||
}
|
}
|
||||||
send_data_str(param, (char *)buff, length);
|
send_data_str(param, (char *)buff, length);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -3261,7 +3344,7 @@ static void fetch_results(MYSQL_BIND *param, MYSQL_FIELD *field, uchar **row)
|
|||||||
longlong data= ((field_is_unsigned) ? (longlong) (unsigned short) value:
|
longlong data= ((field_is_unsigned) ? (longlong) (unsigned short) value:
|
||||||
(longlong) value);
|
(longlong) value);
|
||||||
send_data_long(param, field, data);
|
send_data_long(param, field, data);
|
||||||
length= 2;
|
length= 2;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case MYSQL_TYPE_LONG:
|
case MYSQL_TYPE_LONG:
|
||||||
@ -3300,7 +3383,7 @@ static void fetch_results(MYSQL_BIND *param, MYSQL_FIELD *field, uchar **row)
|
|||||||
case MYSQL_TYPE_DATE:
|
case MYSQL_TYPE_DATE:
|
||||||
{
|
{
|
||||||
MYSQL_TIME tm;
|
MYSQL_TIME tm;
|
||||||
|
|
||||||
length= read_binary_date(&tm, row);
|
length= read_binary_date(&tm, row);
|
||||||
tm.time_type= MYSQL_TIMESTAMP_DATE;
|
tm.time_type= MYSQL_TIMESTAMP_DATE;
|
||||||
send_data_time(param, tm, length);
|
send_data_time(param, tm, length);
|
||||||
@ -3309,7 +3392,7 @@ static void fetch_results(MYSQL_BIND *param, MYSQL_FIELD *field, uchar **row)
|
|||||||
case MYSQL_TYPE_TIME:
|
case MYSQL_TYPE_TIME:
|
||||||
{
|
{
|
||||||
MYSQL_TIME tm;
|
MYSQL_TIME tm;
|
||||||
|
|
||||||
length= read_binary_time(&tm, row);
|
length= read_binary_time(&tm, row);
|
||||||
tm.time_type= MYSQL_TIMESTAMP_TIME;
|
tm.time_type= MYSQL_TIMESTAMP_TIME;
|
||||||
send_data_time(param, tm, length);
|
send_data_time(param, tm, length);
|
||||||
@ -3319,14 +3402,14 @@ static void fetch_results(MYSQL_BIND *param, MYSQL_FIELD *field, uchar **row)
|
|||||||
case MYSQL_TYPE_TIMESTAMP:
|
case MYSQL_TYPE_TIMESTAMP:
|
||||||
{
|
{
|
||||||
MYSQL_TIME tm;
|
MYSQL_TIME tm;
|
||||||
|
|
||||||
length= read_binary_datetime(&tm, row);
|
length= read_binary_datetime(&tm, row);
|
||||||
tm.time_type= MYSQL_TIMESTAMP_FULL;
|
tm.time_type= MYSQL_TIMESTAMP_FULL;
|
||||||
send_data_time(param, tm, length);
|
send_data_time(param, tm, length);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
length= net_field_length(row);
|
length= net_field_length(row);
|
||||||
send_data_str(param,(char*) *row,length);
|
send_data_str(param,(char*) *row,length);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -3355,7 +3438,7 @@ static void fetch_result_int32(MYSQL_BIND *param, uchar **row)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void fetch_result_int64(MYSQL_BIND *param, uchar **row)
|
static void fetch_result_int64(MYSQL_BIND *param, uchar **row)
|
||||||
{
|
{
|
||||||
longlong value= (longlong)sint8korr(*row);
|
longlong value= (longlong)sint8korr(*row);
|
||||||
longlongstore(param->buffer, value);
|
longlongstore(param->buffer, value);
|
||||||
*row+= 8;
|
*row+= 8;
|
||||||
@ -3396,11 +3479,11 @@ static void fetch_result_datetime(MYSQL_BIND *param, uchar **row)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void fetch_result_bin(MYSQL_BIND *param, uchar **row)
|
static void fetch_result_bin(MYSQL_BIND *param, uchar **row)
|
||||||
{
|
{
|
||||||
ulong length= net_field_length(row);
|
ulong length= net_field_length(row);
|
||||||
ulong copy_length= min(length, param->buffer_length);
|
ulong copy_length= min(length, param->buffer_length);
|
||||||
memcpy(param->buffer, (char *)*row, copy_length);
|
memcpy(param->buffer, (char *)*row, copy_length);
|
||||||
*param->length= length;
|
*param->length= length;
|
||||||
*row+= length;
|
*row+= length;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3481,7 +3564,7 @@ my_bool STDCALL mysql_stmt_bind_result(MYSQL_STMT *stmt, MYSQL_BIND *bind)
|
|||||||
We only need to check that stmt->field_count - if it is not null
|
We only need to check that stmt->field_count - if it is not null
|
||||||
stmt->bind was initialized in mysql_stmt_prepare
|
stmt->bind was initialized in mysql_stmt_prepare
|
||||||
*/
|
*/
|
||||||
|
|
||||||
memcpy((char*) stmt->bind, (char*) bind, sizeof(MYSQL_BIND) * bind_count);
|
memcpy((char*) stmt->bind, (char*) bind, sizeof(MYSQL_BIND) * bind_count);
|
||||||
|
|
||||||
for (param= stmt->bind, end= param + bind_count, field= stmt->fields ;
|
for (param= stmt->bind, end= param + bind_count, field= stmt->fields ;
|
||||||
@ -3643,16 +3726,16 @@ static int stmt_fetch_row(MYSQL_STMT *stmt, uchar *row)
|
|||||||
/* If output parameters were not bound we should just return success */
|
/* If output parameters were not bound we should just return success */
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
null_ptr= row;
|
null_ptr= row;
|
||||||
row+= (stmt->field_count+9)/8; /* skip null bits */
|
row+= (stmt->field_count+9)/8; /* skip null bits */
|
||||||
bit= 4; /* first 2 bits are reserved */
|
bit= 4; /* first 2 bits are reserved */
|
||||||
|
|
||||||
/* Copy complete row to application buffers */
|
/* Copy complete row to application buffers */
|
||||||
for (bind= stmt->bind, end= bind + stmt->field_count, field= stmt->fields ;
|
for (bind= stmt->bind, end= bind + stmt->field_count, field= stmt->fields ;
|
||||||
bind < end ;
|
bind < end ;
|
||||||
bind++, field++)
|
bind++, field++)
|
||||||
{
|
{
|
||||||
if (*null_ptr & bit)
|
if (*null_ptr & bit)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
@ -3666,12 +3749,12 @@ static int stmt_fetch_row(MYSQL_STMT *stmt, uchar *row)
|
|||||||
*bind->is_null= 1;
|
*bind->is_null= 1;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
*bind->is_null= 0;
|
*bind->is_null= 0;
|
||||||
bind->inter_buffer= row;
|
bind->inter_buffer= row;
|
||||||
if (field->type == bind->buffer_type)
|
if (field->type == bind->buffer_type)
|
||||||
(*bind->fetch_result)(bind, &row);
|
(*bind->fetch_result)(bind, &row);
|
||||||
else
|
else
|
||||||
fetch_results(bind, field, &row);
|
fetch_results(bind, field, &row);
|
||||||
}
|
}
|
||||||
if (!((bit<<=1) & 255))
|
if (!((bit<<=1) & 255))
|
||||||
@ -3731,15 +3814,15 @@ int STDCALL mysql_stmt_fetch(MYSQL_STMT *stmt)
|
|||||||
column Column to fetch (first column is 0)
|
column Column to fetch (first column is 0)
|
||||||
ulong offset Offset in result data (to fetch blob in pieces)
|
ulong offset Offset in result data (to fetch blob in pieces)
|
||||||
This is normally 0
|
This is normally 0
|
||||||
RETURN
|
RETURN
|
||||||
0 ok
|
0 ok
|
||||||
1 error
|
1 error
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int STDCALL mysql_stmt_fetch_column(MYSQL_STMT *stmt, MYSQL_BIND *bind,
|
int STDCALL mysql_stmt_fetch_column(MYSQL_STMT *stmt, MYSQL_BIND *bind,
|
||||||
uint column, ulong offset)
|
uint column, ulong offset)
|
||||||
{
|
{
|
||||||
MYSQL_BIND *param= stmt->bind+column;
|
MYSQL_BIND *param= stmt->bind+column;
|
||||||
DBUG_ENTER("mysql_stmt_fetch_column");
|
DBUG_ENTER("mysql_stmt_fetch_column");
|
||||||
|
|
||||||
if ((int) stmt->state < (int) MYSQL_STMT_FETCH_DONE)
|
if ((int) stmt->state < (int) MYSQL_STMT_FETCH_DONE)
|
||||||
@ -3755,7 +3838,7 @@ int STDCALL mysql_stmt_fetch_column(MYSQL_STMT *stmt, MYSQL_BIND *bind,
|
|||||||
|
|
||||||
if (param->inter_buffer)
|
if (param->inter_buffer)
|
||||||
{
|
{
|
||||||
MYSQL_FIELD *field= stmt->fields+column;
|
MYSQL_FIELD *field= stmt->fields+column;
|
||||||
uchar *row= param->inter_buffer;
|
uchar *row= param->inter_buffer;
|
||||||
bind->offset= offset;
|
bind->offset= offset;
|
||||||
if (bind->is_null)
|
if (bind->is_null)
|
||||||
@ -3825,6 +3908,49 @@ err:
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
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
|
Store or buffer the binary results to stmt
|
||||||
*/
|
*/
|
||||||
@ -3909,7 +4035,7 @@ mysql_stmt_row_seek(MYSQL_STMT *stmt, MYSQL_ROW_OFFSET row)
|
|||||||
{
|
{
|
||||||
MYSQL_ROW_OFFSET offset= stmt->data_cursor;
|
MYSQL_ROW_OFFSET offset= stmt->data_cursor;
|
||||||
DBUG_ENTER("mysql_stmt_row_seek");
|
DBUG_ENTER("mysql_stmt_row_seek");
|
||||||
|
|
||||||
stmt->data_cursor= row;
|
stmt->data_cursor= row;
|
||||||
DBUG_RETURN(offset);
|
DBUG_RETURN(offset);
|
||||||
}
|
}
|
||||||
@ -3919,11 +4045,11 @@ mysql_stmt_row_seek(MYSQL_STMT *stmt, MYSQL_ROW_OFFSET row)
|
|||||||
Return the current statement row cursor position
|
Return the current statement row cursor position
|
||||||
*/
|
*/
|
||||||
|
|
||||||
MYSQL_ROW_OFFSET STDCALL
|
MYSQL_ROW_OFFSET STDCALL
|
||||||
mysql_stmt_row_tell(MYSQL_STMT *stmt)
|
mysql_stmt_row_tell(MYSQL_STMT *stmt)
|
||||||
{
|
{
|
||||||
DBUG_ENTER("mysql_stmt_row_tell");
|
DBUG_ENTER("mysql_stmt_row_tell");
|
||||||
|
|
||||||
DBUG_RETURN(stmt->data_cursor);
|
DBUG_RETURN(stmt->data_cursor);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3938,7 +4064,7 @@ mysql_stmt_data_seek(MYSQL_STMT *stmt, my_ulonglong row)
|
|||||||
MYSQL_ROWS *tmp= stmt->result.data;
|
MYSQL_ROWS *tmp= stmt->result.data;
|
||||||
DBUG_ENTER("mysql_stmt_data_seek");
|
DBUG_ENTER("mysql_stmt_data_seek");
|
||||||
DBUG_PRINT("enter",("row id to seek: %ld",(long) row));
|
DBUG_PRINT("enter",("row id to seek: %ld",(long) row));
|
||||||
|
|
||||||
for (; tmp && row; --row, tmp= tmp->next)
|
for (; tmp && row; --row, tmp= tmp->next)
|
||||||
;
|
;
|
||||||
stmt->data_cursor= tmp;
|
stmt->data_cursor= tmp;
|
||||||
@ -3953,7 +4079,7 @@ mysql_stmt_data_seek(MYSQL_STMT *stmt, my_ulonglong row)
|
|||||||
my_ulonglong STDCALL mysql_stmt_num_rows(MYSQL_STMT *stmt)
|
my_ulonglong STDCALL mysql_stmt_num_rows(MYSQL_STMT *stmt)
|
||||||
{
|
{
|
||||||
DBUG_ENTER("mysql_stmt_num_rows");
|
DBUG_ENTER("mysql_stmt_num_rows");
|
||||||
|
|
||||||
DBUG_RETURN(stmt->result.rows);
|
DBUG_RETURN(stmt->result.rows);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3963,7 +4089,7 @@ my_bool STDCALL mysql_stmt_free_result(MYSQL_STMT *stmt)
|
|||||||
DBUG_ENTER("mysql_stmt_free_result");
|
DBUG_ENTER("mysql_stmt_free_result");
|
||||||
|
|
||||||
DBUG_ASSERT(stmt != 0);
|
DBUG_ASSERT(stmt != 0);
|
||||||
|
|
||||||
if ((int) stmt->state > (int) MYSQL_STMT_INIT_DONE)
|
if ((int) stmt->state > (int) MYSQL_STMT_INIT_DONE)
|
||||||
{
|
{
|
||||||
MYSQL *mysql= stmt->mysql;
|
MYSQL *mysql= stmt->mysql;
|
||||||
@ -4031,7 +4157,7 @@ my_bool STDCALL mysql_stmt_close(MYSQL_STMT *stmt)
|
|||||||
mysql->unbuffered_fetch_owner= 0;
|
mysql->unbuffered_fetch_owner= 0;
|
||||||
if (mysql->status != MYSQL_STATUS_READY)
|
if (mysql->status != MYSQL_STATUS_READY)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
Flush result set of the connection. If it does not belong
|
Flush result set of the connection. If it does not belong
|
||||||
to this statement, set a warning.
|
to this statement, set a warning.
|
||||||
*/
|
*/
|
||||||
@ -4069,13 +4195,13 @@ my_bool STDCALL mysql_stmt_reset(MYSQL_STMT *stmt)
|
|||||||
/* If statement hasnt been prepared there is nothing to reset */
|
/* If statement hasnt been prepared there is nothing to reset */
|
||||||
if ((int) stmt->state < (int) MYSQL_STMT_PREPARE_DONE)
|
if ((int) stmt->state < (int) MYSQL_STMT_PREPARE_DONE)
|
||||||
DBUG_RETURN(0);
|
DBUG_RETURN(0);
|
||||||
|
|
||||||
mysql= stmt->mysql->last_used_con;
|
mysql= stmt->mysql->last_used_con;
|
||||||
int4store(buff, stmt->stmt_id); /* Send stmt id to server */
|
int4store(buff, stmt->stmt_id); /* Send stmt id to server */
|
||||||
if ((*mysql->methods->advanced_command)(mysql, COM_RESET_STMT, buff,
|
if ((*mysql->methods->advanced_command)(mysql, COM_RESET_STMT, buff,
|
||||||
sizeof(buff), 0, 0, 0))
|
sizeof(buff), 0, 0, 0))
|
||||||
{
|
{
|
||||||
set_stmt_errmsg(stmt, mysql->net.last_error, mysql->net.last_errno,
|
set_stmt_errmsg(stmt, mysql->net.last_error, mysql->net.last_errno,
|
||||||
mysql->net.sqlstate);
|
mysql->net.sqlstate);
|
||||||
DBUG_RETURN(1);
|
DBUG_RETURN(1);
|
||||||
}
|
}
|
||||||
@ -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
|
Transactional APIs
|
||||||
*********************************************************************/
|
*********************************************************************/
|
||||||
@ -4213,10 +4295,10 @@ my_bool STDCALL mysql_more_results(MYSQL *mysql)
|
|||||||
{
|
{
|
||||||
my_bool res;
|
my_bool res;
|
||||||
DBUG_ENTER("mysql_more_results");
|
DBUG_ENTER("mysql_more_results");
|
||||||
|
|
||||||
res= ((mysql->last_used_con->server_status & SERVER_MORE_RESULTS_EXISTS) ?
|
res= ((mysql->last_used_con->server_status & SERVER_MORE_RESULTS_EXISTS) ?
|
||||||
1: 0);
|
1: 0);
|
||||||
DBUG_PRINT("exit",("More results exists ? %d", res));
|
DBUG_PRINT("exit",("More results exists ? %d", res));
|
||||||
DBUG_RETURN(res);
|
DBUG_RETURN(res);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -4227,7 +4309,7 @@ my_bool STDCALL mysql_more_results(MYSQL *mysql)
|
|||||||
int STDCALL mysql_next_result(MYSQL *mysql)
|
int STDCALL mysql_next_result(MYSQL *mysql)
|
||||||
{
|
{
|
||||||
DBUG_ENTER("mysql_next_result");
|
DBUG_ENTER("mysql_next_result");
|
||||||
|
|
||||||
if (mysql->status != MYSQL_STATUS_READY)
|
if (mysql->status != MYSQL_STATUS_READY)
|
||||||
{
|
{
|
||||||
strmov(mysql->net.sqlstate, unknown_sqlstate);
|
strmov(mysql->net.sqlstate, unknown_sqlstate);
|
||||||
|
Reference in New Issue
Block a user