mirror of
https://github.com/MariaDB/server.git
synced 2025-01-19 05:22:25 +01:00
Merge bk-internal.mysql.com:/home/bk/mysql-4.1
into mysql.com:/home/kostja/mysql/mysql-4.1-4030
This commit is contained in:
commit
834e9f870e
2 changed files with 237 additions and 155 deletions
|
@ -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 */
|
||||
|
|
|
@ -1945,7 +1945,7 @@ mysql_stmt_prepare(MYSQL_STMT *stmt, const char *query, ulong length)
|
|||
|
||||
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.
|
||||
*/
|
||||
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
|
||||
or stmt->params when checking for existence of placeholders or
|
||||
result set.
|
||||
*/
|
||||
if (!(stmt->params= (MYSQL_BIND *) alloc_root(&stmt->mem_root,
|
||||
sizeof(MYSQL_BIND)*
|
||||
(stmt->param_count +
|
||||
(stmt->param_count +
|
||||
stmt->field_count))))
|
||||
{
|
||||
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;
|
||||
MEM_ROOT *alloc= &stmt->mem_root;
|
||||
MYSQL *mysql= stmt->mysql->last_used_con;
|
||||
|
||||
|
||||
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
|
||||
*/
|
||||
if (!(stmt->fields= (MYSQL_FIELD *) alloc_root(alloc,
|
||||
if (!(stmt->fields= (MYSQL_FIELD *) alloc_root(alloc,
|
||||
sizeof(MYSQL_FIELD) *
|
||||
stmt->field_count)) ||
|
||||
!(stmt->bind= (MYSQL_BIND *) alloc_root(alloc,
|
||||
stmt->field_count)) ||
|
||||
!(stmt->bind= (MYSQL_BIND *) alloc_root(alloc,
|
||||
sizeof(MYSQL_BIND) *
|
||||
stmt->field_count)))
|
||||
return 0;
|
||||
|
||||
for (fields= mysql->fields, end= fields+stmt->field_count,
|
||||
|
||||
for (fields= mysql->fields, end= fields+stmt->field_count,
|
||||
field= stmt->fields;
|
||||
field && fields < end; fields++, field++)
|
||||
{
|
||||
|
@ -2107,7 +2107,7 @@ mysql_stmt_result_metadata(MYSQL_STMT *stmt)
|
|||
{
|
||||
MYSQL_RES *result;
|
||||
DBUG_ENTER("mysql_stmt_result_metadata");
|
||||
|
||||
|
||||
/*
|
||||
stmt->fields is only defined if stmt->field_count is not null;
|
||||
stmt->field_count is initialized in prepare.
|
||||
|
@ -2130,41 +2130,65 @@ mysql_stmt_result_metadata(MYSQL_STMT *stmt)
|
|||
DBUG_RETURN(result);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Returns parameter columns meta information in the form of
|
||||
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_stmt_param_metadata(MYSQL_STMT *stmt)
|
||||
{
|
||||
DBUG_ENTER("mysql_stmt_param_metadata");
|
||||
|
||||
|
||||
if (!stmt->param_count)
|
||||
DBUG_RETURN(0);
|
||||
|
||||
/*
|
||||
TODO: Fix this when server sends the information.
|
||||
Till then keep a dummy prototype
|
||||
TODO: Fix this when server sends the information.
|
||||
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)
|
||||
|
@ -2253,7 +2277,7 @@ static void net_store_datetime(NET *net, MYSQL_TIME *tm)
|
|||
length= 4;
|
||||
else
|
||||
length= 0;
|
||||
buff[0]= (char) length++;
|
||||
buff[0]= (char) length++;
|
||||
memcpy((char *)net->write_pos, buff, 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;
|
||||
net_store_datetime(net, tm);
|
||||
}
|
||||
|
||||
|
||||
static void store_param_str(NET *net, MYSQL_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
|
||||
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)
|
||||
|
@ -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)
|
||||
|
@ -2339,11 +2365,11 @@ static my_bool store_param(MYSQL_STMT *stmt, MYSQL_BIND *param)
|
|||
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;
|
||||
NET *net= &mysql->net;
|
||||
char buff[4 /* size of stmt id */ +
|
||||
char buff[4 /* size of stmt id */ +
|
||||
5 /* execution flags */];
|
||||
DBUG_ENTER("execute");
|
||||
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;
|
||||
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)
|
||||
|
@ -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))
|
||||
|
@ -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;
|
||||
row data is stored in network buffer
|
||||
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;
|
||||
*row is to NULL
|
||||
*row is to NULL
|
||||
*/
|
||||
|
||||
static int stmt_read_row_unbuffered(MYSQL_STMT *stmt, unsigned char **row)
|
||||
{
|
||||
int rc= 1;
|
||||
MYSQL *mysql= stmt->mysql;
|
||||
/*
|
||||
/*
|
||||
This function won't be called if stmt->field_count is zero
|
||||
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 wrong attribute type
|
||||
*/
|
||||
|
||||
|
||||
my_bool STDCALL mysql_stmt_attr_set(MYSQL_STMT *stmt,
|
||||
enum enum_stmt_attr_type attr_type,
|
||||
const void *value)
|
||||
|
@ -2564,14 +2582,14 @@ my_bool STDCALL mysql_stmt_attr_set(MYSQL_STMT *stmt,
|
|||
case STMT_ATTR_UPDATE_MAX_LENGTH:
|
||||
stmt->update_max_length= value ? *(const my_bool*) value : 0;
|
||||
break;
|
||||
default:
|
||||
default:
|
||||
return TRUE;
|
||||
}
|
||||
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,
|
||||
void *value)
|
||||
{
|
||||
|
@ -2579,7 +2597,7 @@ my_bool STDCALL mysql_stmt_attr_get(MYSQL_STMT *stmt,
|
|||
case STMT_ATTR_UPDATE_MAX_LENGTH:
|
||||
*(unsigned long *) value= stmt->update_max_length;
|
||||
break;
|
||||
default:
|
||||
default:
|
||||
return TRUE;
|
||||
}
|
||||
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)
|
||||
|
@ -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)
|
||||
|
@ -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_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;
|
||||
MYSQL_BIND *param, *end;
|
||||
|
@ -2839,7 +2922,7 @@ mysql_stmt_send_long_data(MYSQL_STMT *stmt, uint param_number,
|
|||
DBUG_ASSERT(stmt != 0);
|
||||
DBUG_PRINT("enter",("param no : %d, data : %lx, length : %ld",
|
||||
param_number, data, length));
|
||||
|
||||
|
||||
/*
|
||||
We only need to check for stmt->param_count, if it's not null
|
||||
prepare was done.
|
||||
|
@ -2864,7 +2947,7 @@ mysql_stmt_send_long_data(MYSQL_STMT *stmt, uint param_number,
|
|||
DBUG_RETURN(1);
|
||||
}
|
||||
|
||||
/*
|
||||
/*
|
||||
Send long data packet if there is data or we're sending long data
|
||||
for the first time.
|
||||
*/
|
||||
|
@ -2872,8 +2955,8 @@ mysql_stmt_send_long_data(MYSQL_STMT *stmt, uint param_number,
|
|||
{
|
||||
MYSQL *mysql= stmt->mysql;
|
||||
/* 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);
|
||||
int2store(buff + 4, param_number);
|
||||
param->long_data_used= 1;
|
||||
|
@ -2926,7 +3009,7 @@ static uint read_binary_time(MYSQL_TIME *tm, uchar **pos)
|
|||
{
|
||||
uchar *to;
|
||||
uint length;
|
||||
|
||||
|
||||
/* net_field_length will set pos to the first byte of data */
|
||||
if (!(length= net_field_length(pos)))
|
||||
{
|
||||
|
@ -2983,14 +3066,14 @@ static uint read_binary_date(MYSQL_TIME *tm, uchar **pos)
|
|||
{
|
||||
uchar *to;
|
||||
uint length;
|
||||
|
||||
|
||||
if (!(length= net_field_length(pos)))
|
||||
{
|
||||
set_zero_time(tm);
|
||||
return 0;
|
||||
}
|
||||
|
||||
to= *pos;
|
||||
|
||||
to= *pos;
|
||||
tm->year = (uint) sint2korr(to);
|
||||
tm->month= (uint) to[2];
|
||||
tm->day= (uint) to[3];
|
||||
|
@ -3004,7 +3087,7 @@ static uint read_binary_date(MYSQL_TIME *tm, uchar **pos)
|
|||
/* Convert Numeric to buffer types */
|
||||
static void send_data_long(MYSQL_BIND *param, MYSQL_FIELD *field,
|
||||
longlong value)
|
||||
{
|
||||
{
|
||||
char *buffer= param->buffer;
|
||||
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 */
|
||||
uint length= (uint)(longlong10_to_str(value,(char *)tmp,
|
||||
field_is_unsigned ? 10: -10) -
|
||||
tmp);
|
||||
field_is_unsigned ? 10: -10) -
|
||||
tmp);
|
||||
ulong copy_length= min((ulong)length-param->offset, param->buffer_length);
|
||||
if ((long) copy_length < 0)
|
||||
copy_length=0;
|
||||
else
|
||||
memcpy(buffer, (char *)tmp+param->offset, copy_length);
|
||||
*param->length= length;
|
||||
|
||||
*param->length= length;
|
||||
|
||||
if (copy_length != param->buffer_length)
|
||||
*(buffer+copy_length)= '\0';
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Convert Double to buffer types */
|
||||
|
||||
static void send_data_double(MYSQL_BIND *param, double value)
|
||||
{
|
||||
{
|
||||
char *buffer= param->buffer;
|
||||
|
||||
switch(param->buffer_type) {
|
||||
|
@ -3099,19 +3182,19 @@ static void send_data_double(MYSQL_BIND *param, double value)
|
|||
copy_length=0;
|
||||
else
|
||||
memcpy(buffer, (char *)tmp+param->offset, copy_length);
|
||||
*param->length= length;
|
||||
|
||||
*param->length= length;
|
||||
|
||||
if (copy_length != param->buffer_length)
|
||||
*(buffer+copy_length)= '\0';
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Convert string to buffer types */
|
||||
|
||||
static void send_data_str(MYSQL_BIND *param, char *value, uint length)
|
||||
{
|
||||
{
|
||||
char *buffer= param->buffer;
|
||||
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,
|
||||
&err);
|
||||
int4store(buffer, data);
|
||||
int4store(buffer, data);
|
||||
break;
|
||||
}
|
||||
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)
|
||||
{
|
||||
switch (param->buffer_type) {
|
||||
|
@ -3192,7 +3275,7 @@ static void send_data_time(MYSQL_BIND *param, MYSQL_TIME ltime,
|
|||
case MYSQL_TYPE_TIMESTAMP:
|
||||
{
|
||||
MYSQL_TIME *tm= (MYSQL_TIME *)param->buffer;
|
||||
|
||||
|
||||
tm->year= ltime.year;
|
||||
tm->month= ltime.month;
|
||||
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->neg= ltime.neg;
|
||||
break;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
char buff[25];
|
||||
|
||||
|
||||
if (!length)
|
||||
ltime.time_type= MYSQL_TIMESTAMP_NONE;
|
||||
switch (ltime.time_type) {
|
||||
case MYSQL_TIMESTAMP_DATE:
|
||||
length= my_sprintf(buff,(buff, "%04d-%02d-%02d", ltime.year,
|
||||
ltime.month,ltime.day));
|
||||
ltime.month,ltime.day));
|
||||
break;
|
||||
case MYSQL_TIMESTAMP_FULL:
|
||||
length= my_sprintf(buff,(buff, "%04d-%02d-%02d %02d:%02d:%02d",
|
||||
ltime.year,ltime.month,ltime.day,
|
||||
ltime.hour,ltime.minute,ltime.second));
|
||||
ltime.year,ltime.month,ltime.day,
|
||||
ltime.hour,ltime.minute,ltime.second));
|
||||
break;
|
||||
case MYSQL_TIMESTAMP_TIME:
|
||||
length= my_sprintf(buff, (buff, "%02d:%02d:%02d",
|
||||
ltime.hour,ltime.minute,ltime.second));
|
||||
ltime.hour,ltime.minute,ltime.second));
|
||||
break;
|
||||
default:
|
||||
length= 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) value);
|
||||
send_data_long(param, field, data);
|
||||
length= 2;
|
||||
length= 2;
|
||||
break;
|
||||
}
|
||||
case MYSQL_TYPE_LONG:
|
||||
|
@ -3300,7 +3383,7 @@ static void fetch_results(MYSQL_BIND *param, MYSQL_FIELD *field, uchar **row)
|
|||
case MYSQL_TYPE_DATE:
|
||||
{
|
||||
MYSQL_TIME tm;
|
||||
|
||||
|
||||
length= read_binary_date(&tm, row);
|
||||
tm.time_type= MYSQL_TIMESTAMP_DATE;
|
||||
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:
|
||||
{
|
||||
MYSQL_TIME tm;
|
||||
|
||||
|
||||
length= read_binary_time(&tm, row);
|
||||
tm.time_type= MYSQL_TIMESTAMP_TIME;
|
||||
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:
|
||||
{
|
||||
MYSQL_TIME tm;
|
||||
|
||||
|
||||
length= read_binary_datetime(&tm, row);
|
||||
tm.time_type= MYSQL_TIMESTAMP_FULL;
|
||||
send_data_time(param, tm, length);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
length= net_field_length(row);
|
||||
default:
|
||||
length= net_field_length(row);
|
||||
send_data_str(param,(char*) *row,length);
|
||||
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)
|
||||
{
|
||||
{
|
||||
longlong value= (longlong)sint8korr(*row);
|
||||
longlongstore(param->buffer, value);
|
||||
*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)
|
||||
{
|
||||
{
|
||||
ulong length= net_field_length(row);
|
||||
ulong copy_length= min(length, param->buffer_length);
|
||||
memcpy(param->buffer, (char *)*row, copy_length);
|
||||
*param->length= length;
|
||||
*param->length= 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
|
||||
stmt->bind was initialized in mysql_stmt_prepare
|
||||
*/
|
||||
|
||||
|
||||
memcpy((char*) stmt->bind, (char*) bind, sizeof(MYSQL_BIND) * bind_count);
|
||||
|
||||
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 */
|
||||
return 0;
|
||||
}
|
||||
|
||||
null_ptr= row;
|
||||
|
||||
null_ptr= row;
|
||||
row+= (stmt->field_count+9)/8; /* skip null bits */
|
||||
bit= 4; /* first 2 bits are reserved */
|
||||
|
||||
|
||||
/* Copy complete row to application buffers */
|
||||
for (bind= stmt->bind, end= bind + stmt->field_count, field= stmt->fields ;
|
||||
bind < end ;
|
||||
bind++, field++)
|
||||
{
|
||||
{
|
||||
if (*null_ptr & bit)
|
||||
{
|
||||
/*
|
||||
|
@ -3666,12 +3749,12 @@ static int stmt_fetch_row(MYSQL_STMT *stmt, uchar *row)
|
|||
*bind->is_null= 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
{
|
||||
*bind->is_null= 0;
|
||||
bind->inter_buffer= row;
|
||||
if (field->type == bind->buffer_type)
|
||||
(*bind->fetch_result)(bind, &row);
|
||||
else
|
||||
else
|
||||
fetch_results(bind, field, &row);
|
||||
}
|
||||
if (!((bit<<=1) & 255))
|
||||
|
@ -3731,15 +3814,15 @@ int STDCALL mysql_stmt_fetch(MYSQL_STMT *stmt)
|
|||
column Column to fetch (first column is 0)
|
||||
ulong offset Offset in result data (to fetch blob in pieces)
|
||||
This is normally 0
|
||||
RETURN
|
||||
RETURN
|
||||
0 ok
|
||||
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)
|
||||
{
|
||||
MYSQL_BIND *param= stmt->bind+column;
|
||||
MYSQL_BIND *param= stmt->bind+column;
|
||||
DBUG_ENTER("mysql_stmt_fetch_column");
|
||||
|
||||
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)
|
||||
{
|
||||
MYSQL_FIELD *field= stmt->fields+column;
|
||||
MYSQL_FIELD *field= stmt->fields+column;
|
||||
uchar *row= param->inter_buffer;
|
||||
bind->offset= offset;
|
||||
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
|
||||
*/
|
||||
|
@ -3909,7 +4035,7 @@ mysql_stmt_row_seek(MYSQL_STMT *stmt, MYSQL_ROW_OFFSET row)
|
|||
{
|
||||
MYSQL_ROW_OFFSET offset= stmt->data_cursor;
|
||||
DBUG_ENTER("mysql_stmt_row_seek");
|
||||
|
||||
|
||||
stmt->data_cursor= row;
|
||||
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
|
||||
*/
|
||||
|
||||
MYSQL_ROW_OFFSET STDCALL
|
||||
MYSQL_ROW_OFFSET STDCALL
|
||||
mysql_stmt_row_tell(MYSQL_STMT *stmt)
|
||||
{
|
||||
DBUG_ENTER("mysql_stmt_row_tell");
|
||||
|
||||
|
||||
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;
|
||||
DBUG_ENTER("mysql_stmt_data_seek");
|
||||
DBUG_PRINT("enter",("row id to seek: %ld",(long) row));
|
||||
|
||||
|
||||
for (; tmp && row; --row, tmp= tmp->next)
|
||||
;
|
||||
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)
|
||||
{
|
||||
DBUG_ENTER("mysql_stmt_num_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_ASSERT(stmt != 0);
|
||||
|
||||
|
||||
if ((int) stmt->state > (int) MYSQL_STMT_INIT_DONE)
|
||||
{
|
||||
MYSQL *mysql= stmt->mysql;
|
||||
|
@ -4031,7 +4157,7 @@ my_bool STDCALL mysql_stmt_close(MYSQL_STMT *stmt)
|
|||
mysql->unbuffered_fetch_owner= 0;
|
||||
if (mysql->status != MYSQL_STATUS_READY)
|
||||
{
|
||||
/*
|
||||
/*
|
||||
Flush result set of the connection. If it does not belong
|
||||
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 ((int) stmt->state < (int) MYSQL_STMT_PREPARE_DONE)
|
||||
DBUG_RETURN(0);
|
||||
|
||||
|
||||
mysql= stmt->mysql->last_used_con;
|
||||
int4store(buff, stmt->stmt_id); /* Send stmt id to server */
|
||||
if ((*mysql->methods->advanced_command)(mysql, COM_RESET_STMT, buff,
|
||||
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);
|
||||
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
|
||||
*********************************************************************/
|
||||
|
@ -4213,10 +4295,10 @@ my_bool STDCALL mysql_more_results(MYSQL *mysql)
|
|||
{
|
||||
my_bool res;
|
||||
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);
|
||||
DBUG_PRINT("exit",("More results exists ? %d", res));
|
||||
DBUG_PRINT("exit",("More results exists ? %d", res));
|
||||
DBUG_RETURN(res);
|
||||
}
|
||||
|
||||
|
@ -4227,7 +4309,7 @@ my_bool STDCALL mysql_more_results(MYSQL *mysql)
|
|||
int STDCALL mysql_next_result(MYSQL *mysql)
|
||||
{
|
||||
DBUG_ENTER("mysql_next_result");
|
||||
|
||||
|
||||
if (mysql->status != MYSQL_STATUS_READY)
|
||||
{
|
||||
strmov(mysql->net.sqlstate, unknown_sqlstate);
|
||||
|
|
Loading…
Reference in a new issue