mirror of
https://github.com/MariaDB/server.git
synced 2025-07-29 05:21:33 +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 */
|
||||||
|
@ -2130,10 +2130,23 @@ 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
|
||||||
@ -2146,25 +2159,36 @@ mysql_stmt_param_metadata(MYSQL_STMT *stmt)
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
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)
|
||||||
@ -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,7 +2365,7 @@ 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;
|
||||||
@ -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)
|
int cli_stmt_execute(MYSQL_STMT *stmt)
|
||||||
{
|
{
|
||||||
DBUG_ENTER("cli_stmt_execute");
|
DBUG_ENTER("cli_stmt_execute");
|
||||||
@ -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))
|
||||||
@ -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;
|
||||||
@ -3041,8 +3124,8 @@ 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;
|
||||||
@ -3214,16 +3297,16 @@ static void send_data_time(MYSQL_BIND *param, MYSQL_TIME ltime,
|
|||||||
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;
|
||||||
@ -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
|
||||||
*/
|
*/
|
||||||
@ -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
|
||||||
*********************************************************************/
|
*********************************************************************/
|
||||||
|
Reference in New Issue
Block a user