mirror of
https://github.com/MariaDB/server.git
synced 2025-07-29 05:21:33 +03:00
Binary protocol changes (to monty)
This commit is contained in:
@ -1739,6 +1739,7 @@ static void mysql_once_init()
|
|||||||
|
|
||||||
#define strdup_if_not_null(A) (A) == 0 ? 0 : my_strdup((A),MYF(MY_WME))
|
#define strdup_if_not_null(A) (A) == 0 ? 0 : my_strdup((A),MYF(MY_WME))
|
||||||
|
|
||||||
|
#ifdef HAVE_OPENSSL
|
||||||
my_bool STDCALL
|
my_bool STDCALL
|
||||||
mysql_ssl_set(MYSQL *mysql __attribute__((unused)) ,
|
mysql_ssl_set(MYSQL *mysql __attribute__((unused)) ,
|
||||||
const char *key __attribute__((unused)),
|
const char *key __attribute__((unused)),
|
||||||
@ -1747,15 +1748,14 @@ mysql_ssl_set(MYSQL *mysql __attribute__((unused)) ,
|
|||||||
const char *capath __attribute__((unused)),
|
const char *capath __attribute__((unused)),
|
||||||
const char *cipher __attribute__((unused)))
|
const char *cipher __attribute__((unused)))
|
||||||
{
|
{
|
||||||
#ifdef HAVE_OPENSSL
|
|
||||||
mysql->options.ssl_key= strdup_if_not_null(key);
|
mysql->options.ssl_key= strdup_if_not_null(key);
|
||||||
mysql->options.ssl_cert= strdup_if_not_null(cert);
|
mysql->options.ssl_cert= strdup_if_not_null(cert);
|
||||||
mysql->options.ssl_ca= strdup_if_not_null(ca);
|
mysql->options.ssl_ca= strdup_if_not_null(ca);
|
||||||
mysql->options.ssl_capath= strdup_if_not_null(capath);
|
mysql->options.ssl_capath= strdup_if_not_null(capath);
|
||||||
mysql->options.ssl_cipher= strdup_if_not_null(cipher);
|
mysql->options.ssl_cipher= strdup_if_not_null(cipher);
|
||||||
#endif
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
/**************************************************************************
|
/**************************************************************************
|
||||||
@ -1763,10 +1763,10 @@ mysql_ssl_set(MYSQL *mysql __attribute__((unused)) ,
|
|||||||
NB! Errors are not reported until you do mysql_real_connect.
|
NB! Errors are not reported until you do mysql_real_connect.
|
||||||
**************************************************************************/
|
**************************************************************************/
|
||||||
|
|
||||||
|
#ifdef HAVE_OPENSLL
|
||||||
static void
|
static void
|
||||||
mysql_ssl_free(MYSQL *mysql __attribute__((unused)))
|
mysql_ssl_free(MYSQL *mysql __attribute__((unused)))
|
||||||
{
|
{
|
||||||
#ifdef HAVE_OPENSLL
|
|
||||||
my_free(mysql->options.ssl_key, MYF(MY_ALLOW_ZERO_PTR));
|
my_free(mysql->options.ssl_key, MYF(MY_ALLOW_ZERO_PTR));
|
||||||
my_free(mysql->options.ssl_cert, MYF(MY_ALLOW_ZERO_PTR));
|
my_free(mysql->options.ssl_cert, MYF(MY_ALLOW_ZERO_PTR));
|
||||||
my_free(mysql->options.ssl_ca, MYF(MY_ALLOW_ZERO_PTR));
|
my_free(mysql->options.ssl_ca, MYF(MY_ALLOW_ZERO_PTR));
|
||||||
@ -1780,8 +1780,8 @@ mysql_ssl_free(MYSQL *mysql __attribute__((unused)))
|
|||||||
mysql->options.ssl_cipher= 0;
|
mysql->options.ssl_cipher= 0;
|
||||||
mysql->options.use_ssl = FALSE;
|
mysql->options.use_ssl = FALSE;
|
||||||
mysql->connector_fd = 0;
|
mysql->connector_fd = 0;
|
||||||
#endif /* HAVE_OPENSLL */
|
|
||||||
}
|
}
|
||||||
|
#endif /* HAVE_OPENSLL */
|
||||||
|
|
||||||
/**************************************************************************
|
/**************************************************************************
|
||||||
Connect to sql server
|
Connect to sql server
|
||||||
@ -3824,12 +3824,13 @@ static my_bool my_realloc_str(NET *net, ulong length)
|
|||||||
1 error
|
1 error
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static my_bool read_prepare_result(MYSQL *mysql, MYSQL_STMT *stmt)
|
static my_bool read_prepare_result(MYSQL_STMT *stmt)
|
||||||
{
|
{
|
||||||
uchar *pos;
|
uchar *pos;
|
||||||
uint field_count;
|
uint field_count;
|
||||||
|
ulong length, param_count;
|
||||||
MYSQL_DATA *fields_data;
|
MYSQL_DATA *fields_data;
|
||||||
ulong length;
|
MYSQL *mysql= stmt->mysql;
|
||||||
DBUG_ENTER("read_prepare_result");
|
DBUG_ENTER("read_prepare_result");
|
||||||
|
|
||||||
mysql= mysql->last_used_con;
|
mysql= mysql->last_used_con;
|
||||||
@ -3837,9 +3838,9 @@ static my_bool read_prepare_result(MYSQL *mysql, MYSQL_STMT *stmt)
|
|||||||
DBUG_RETURN(1);
|
DBUG_RETURN(1);
|
||||||
|
|
||||||
pos=(uchar*) mysql->net.read_pos;
|
pos=(uchar*) mysql->net.read_pos;
|
||||||
stmt->stmt_id= uint4korr(pos); pos+=4;
|
stmt->stmt_id= uint4korr(pos); pos+=4;
|
||||||
field_count= uint2korr(pos); pos+=2;
|
field_count= uint2korr(pos); pos+=2;
|
||||||
stmt->param_count=uint2korr(pos); pos+=2;
|
param_count= uint2korr(pos); pos+=2;
|
||||||
|
|
||||||
if (field_count != 0)
|
if (field_count != 0)
|
||||||
{
|
{
|
||||||
@ -3862,9 +3863,10 @@ static my_bool read_prepare_result(MYSQL *mysql, MYSQL_STMT *stmt)
|
|||||||
set_stmt_error(stmt, CR_OUT_OF_MEMORY);
|
set_stmt_error(stmt, CR_OUT_OF_MEMORY);
|
||||||
DBUG_RETURN(0);
|
DBUG_RETURN(0);
|
||||||
}
|
}
|
||||||
stmt->bind= (stmt->params + stmt->param_count);
|
stmt->bind= (stmt->params + stmt->param_count);
|
||||||
stmt->field_count= (uint) field_count;
|
stmt->field_count= (uint) field_count;
|
||||||
mysql->status= MYSQL_STATUS_READY;
|
stmt->param_count= (ulong) param_count;
|
||||||
|
stmt->mysql->status= MYSQL_STATUS_READY;
|
||||||
DBUG_RETURN(0);
|
DBUG_RETURN(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3908,13 +3910,13 @@ mysql_prepare(MYSQL *mysql, const char *query, ulong length)
|
|||||||
}
|
}
|
||||||
|
|
||||||
init_alloc_root(&stmt->mem_root,8192,0);
|
init_alloc_root(&stmt->mem_root,8192,0);
|
||||||
if (read_prepare_result(mysql, stmt))
|
stmt->mysql= mysql;
|
||||||
|
if (read_prepare_result(stmt))
|
||||||
{
|
{
|
||||||
stmt_close(stmt, 1);
|
stmt_close(stmt, 1);
|
||||||
DBUG_RETURN(0);
|
DBUG_RETURN(0);
|
||||||
}
|
}
|
||||||
stmt->state= MY_ST_PREPARE;
|
stmt->state= MY_ST_PREPARE;
|
||||||
stmt->mysql= mysql;
|
|
||||||
mysql->stmts= list_add(mysql->stmts, &stmt->list);
|
mysql->stmts= list_add(mysql->stmts, &stmt->list);
|
||||||
stmt->list.data= stmt;
|
stmt->list.data= stmt;
|
||||||
DBUG_PRINT("info", ("Parameter count: %ld", stmt->param_count));
|
DBUG_PRINT("info", ("Parameter count: %ld", stmt->param_count));
|
||||||
@ -3925,18 +3927,41 @@ mysql_prepare(MYSQL *mysql, const char *query, ulong length)
|
|||||||
/*
|
/*
|
||||||
Returns prepared meta information in the form of resultset
|
Returns prepared meta information in the form of resultset
|
||||||
to client.
|
to client.
|
||||||
|
TODO : Return param information also
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
MYSQL_RES *prepare_result(MYSQL_FIELD *fields, unsigned long count)
|
||||||
|
{
|
||||||
|
MYSQL_RES *result;
|
||||||
|
|
||||||
|
if (!count || !fields)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (!(result=(MYSQL_RES*) my_malloc(sizeof(*result)+
|
||||||
|
sizeof(ulong)*count,
|
||||||
|
MYF(MY_WME | MY_ZEROFILL))))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
result->eof=1; /* Marker for buffered */
|
||||||
|
result->fields= fields;
|
||||||
|
result->field_count= count;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
MYSQL_RES * STDCALL
|
MYSQL_RES * STDCALL
|
||||||
mysql_prepare_result(MYSQL_STMT *stmt)
|
mysql_prepare_result(MYSQL_STMT *stmt)
|
||||||
{
|
{
|
||||||
MYSQL_RES *result;
|
MYSQL_RES *result;
|
||||||
DBUG_ENTER("mysql_prepare_result");
|
DBUG_ENTER("mysql_prepare_result");
|
||||||
|
|
||||||
if (!stmt->fields)
|
if (!stmt->field_count || !stmt->fields)
|
||||||
DBUG_RETURN(0);
|
DBUG_RETURN(0);
|
||||||
result= &stmt->tmp_result;
|
|
||||||
bzero((char*) result, sizeof(MYSQL_RES));
|
if (!(result=(MYSQL_RES*) my_malloc(sizeof(*result)+
|
||||||
|
sizeof(ulong)*stmt->field_count,
|
||||||
|
MYF(MY_WME | MY_ZEROFILL))))
|
||||||
|
return 0;
|
||||||
|
|
||||||
result->eof=1; /* Marker for buffered */
|
result->eof=1; /* Marker for buffered */
|
||||||
result->fields= stmt->fields;
|
result->fields= stmt->fields;
|
||||||
result->field_count= stmt->field_count;
|
result->field_count= stmt->field_count;
|
||||||
@ -4088,12 +4113,13 @@ static my_bool store_param(MYSQL_STMT *stmt, MYSQL_BIND *param)
|
|||||||
DBUG_ENTER("store_param");
|
DBUG_ENTER("store_param");
|
||||||
DBUG_PRINT("enter",("type: %d, buffer:%lx, length: %d", param->buffer_type,
|
DBUG_PRINT("enter",("type: %d, buffer:%lx, length: %d", param->buffer_type,
|
||||||
param->buffer ? param->buffer : "0", *param->length));
|
param->buffer ? param->buffer : "0", *param->length));
|
||||||
|
|
||||||
if (param->is_null || param->buffer_type == MYSQL_TYPE_NULL)
|
if (param->is_null || param->buffer_type == MYSQL_TYPE_NULL ||
|
||||||
|
*param->length == MYSQL_NULL_DATA)
|
||||||
store_param_null(net, param);
|
store_param_null(net, param);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* Allocate for worst case (long string) */
|
/* Allocate for worst case (long string) */
|
||||||
if ((my_realloc_str(net, 9 + *param->length)))
|
if ((my_realloc_str(net, 9 + *param->length)))
|
||||||
DBUG_RETURN(1);
|
DBUG_RETURN(1);
|
||||||
(*param->store_param_func)(net, param);
|
(*param->store_param_func)(net, param);
|
||||||
@ -4101,7 +4127,6 @@ static my_bool store_param(MYSQL_STMT *stmt, MYSQL_BIND *param)
|
|||||||
DBUG_RETURN(0);
|
DBUG_RETURN(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Send the prepare query to server for execution
|
Send the prepare query to server for execution
|
||||||
*/
|
*/
|
||||||
@ -4125,13 +4150,6 @@ static my_bool execute(MYSQL_STMT * stmt, char *packet, ulong length)
|
|||||||
}
|
}
|
||||||
stmt->state= MY_ST_EXECUTE;
|
stmt->state= MY_ST_EXECUTE;
|
||||||
mysql_free_result(stmt->result);
|
mysql_free_result(stmt->result);
|
||||||
#if USED_IN_FETCH
|
|
||||||
if (stmt->res_buffers) /* Result buffers exists, cache results */
|
|
||||||
{
|
|
||||||
mysql_free_result(stmt->result);
|
|
||||||
stmt->result= mysql_store_result(mysql);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
DBUG_RETURN(0);
|
DBUG_RETURN(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -4420,21 +4438,21 @@ static void fetch_result_tinyint(MYSQL_BIND *param, uchar **row)
|
|||||||
|
|
||||||
static void fetch_result_short(MYSQL_BIND *param, uchar **row)
|
static void fetch_result_short(MYSQL_BIND *param, uchar **row)
|
||||||
{
|
{
|
||||||
short value= *(short *)row;
|
short value= (short)**row;
|
||||||
int2store(param->buffer, value);
|
int2store(param->buffer, value);
|
||||||
*row+=2;
|
*row+=2;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void fetch_result_int32(MYSQL_BIND *param, uchar **row)
|
static void fetch_result_int32(MYSQL_BIND *param, uchar **row)
|
||||||
{
|
{
|
||||||
int32 value= *(int32 *)row;
|
int32 value= (int32)**row;
|
||||||
int4store(param->buffer, value);
|
int4store(param->buffer, value);
|
||||||
*row+=4;
|
*row+=4;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void fetch_result_int64(MYSQL_BIND *param, uchar **row)
|
static void fetch_result_int64(MYSQL_BIND *param, uchar **row)
|
||||||
{
|
{
|
||||||
longlong value= *(longlong *)row;
|
longlong value= (longlong)**row;
|
||||||
int8store(param->buffer, value);
|
int8store(param->buffer, value);
|
||||||
*row+=8;
|
*row+=8;
|
||||||
}
|
}
|
||||||
@ -4443,7 +4461,7 @@ static void fetch_result_float(MYSQL_BIND *param, uchar **row)
|
|||||||
{
|
{
|
||||||
float value;
|
float value;
|
||||||
float4get(value,*row);
|
float4get(value,*row);
|
||||||
float4store(param->buffer, *row);
|
float4store(param->buffer, value);
|
||||||
*row+=4;
|
*row+=4;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -4459,6 +4477,7 @@ static void fetch_result_str(MYSQL_BIND *param, uchar **row)
|
|||||||
{
|
{
|
||||||
ulong length= net_field_length(row);
|
ulong length= net_field_length(row);
|
||||||
memcpy(param->buffer, (char *)*row, length);
|
memcpy(param->buffer, (char *)*row, length);
|
||||||
|
*(param->buffer+length)= '\0'; /* do we need this for all cases.. I doubt */
|
||||||
*param->length= length;
|
*param->length= length;
|
||||||
*row+=length;
|
*row+=length;
|
||||||
}
|
}
|
||||||
@ -4537,41 +4556,46 @@ my_bool STDCALL mysql_bind_result(MYSQL_STMT *stmt, MYSQL_BIND *bind)
|
|||||||
Fetch row data to bind buffers
|
Fetch row data to bind buffers
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static my_bool
|
static void
|
||||||
stmt_fetch_row(MYSQL_STMT *stmt, uchar **row)
|
stmt_fetch_row(MYSQL_STMT *stmt, uchar *row)
|
||||||
{
|
{
|
||||||
MYSQL_BIND *bind, *end;
|
MYSQL_BIND *bind, *end;
|
||||||
uchar *null_ptr= (uchar*) *row, bit;
|
MYSQL_FIELD *field;
|
||||||
|
uchar *null_ptr, bit;
|
||||||
row+= (stmt->field_count+9)/8;
|
|
||||||
bit= 4; /* First 2 bits are reserved */
|
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 */
|
/* Copy complete row to application buffers */
|
||||||
for (bind= stmt->bind, end= (MYSQL_BIND *) bind + stmt->field_count;
|
for (bind= stmt->bind, end= (MYSQL_BIND *) bind + stmt->field_count,
|
||||||
bind < end;
|
field= stmt->fields;
|
||||||
bind++)
|
bind < end && field;
|
||||||
{
|
bind++, field++)
|
||||||
|
{
|
||||||
if (*null_ptr & bit)
|
if (*null_ptr & bit)
|
||||||
bind->is_null= 1;
|
*bind->length= MYSQL_NULL_DATA;
|
||||||
else
|
else
|
||||||
{
|
/* TODO: Add conversion routines code here */
|
||||||
bind->is_null= 0;
|
(*bind->fetch_result)(bind, &row);
|
||||||
(*bind->fetch_result)(bind, row);
|
|
||||||
}
|
|
||||||
if (! (bit<<=1) & 255)
|
if (! (bit<<=1) & 255)
|
||||||
{
|
{
|
||||||
bit=1; /* To next byte */
|
bit= 1; /* To next byte */
|
||||||
null_ptr++;
|
null_ptr++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int read_binary_data(MYSQL *mysql)
|
static int read_binary_data(MYSQL *mysql)
|
||||||
{
|
{
|
||||||
|
/* TODO : Changes needed based on logic of use_result/store_result
|
||||||
|
Currently by default it is use_result. In case of
|
||||||
|
store_result, the data packet must point to already
|
||||||
|
read data.
|
||||||
|
*/
|
||||||
if (packet_error == net_safe_read(mysql))
|
if (packet_error == net_safe_read(mysql))
|
||||||
return -1;
|
return -1;
|
||||||
if (mysql->net.read_pos[0])
|
if (mysql->net.read_pos[0] == 254)
|
||||||
return 1; /* End of data */
|
return 1; /* End of data */
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -4584,29 +4608,24 @@ static int read_binary_data(MYSQL *mysql)
|
|||||||
int STDCALL mysql_fetch(MYSQL_STMT *stmt)
|
int STDCALL mysql_fetch(MYSQL_STMT *stmt)
|
||||||
{
|
{
|
||||||
MYSQL *mysql= stmt->mysql;
|
MYSQL *mysql= stmt->mysql;
|
||||||
|
int res;
|
||||||
DBUG_ENTER("mysql_fetch");
|
DBUG_ENTER("mysql_fetch");
|
||||||
|
|
||||||
if (stmt->res_buffers)
|
if (!(res= read_binary_data(mysql)))
|
||||||
{
|
{
|
||||||
int res;
|
if (stmt->res_buffers)
|
||||||
if (!(res= read_binary_data(mysql)))
|
stmt_fetch_row(stmt, mysql->net.read_pos+1);
|
||||||
{
|
DBUG_RETURN(0);
|
||||||
if (stmt->res_buffers)
|
|
||||||
DBUG_RETURN((int) stmt_fetch_row(stmt,(uchar **) &mysql->net.read_pos+1));
|
|
||||||
DBUG_RETURN(0);
|
|
||||||
}
|
|
||||||
DBUG_PRINT("info", ("end of data"));
|
|
||||||
mysql->status= MYSQL_STATUS_READY;
|
|
||||||
|
|
||||||
if (res < 0) /* Network error */
|
|
||||||
{
|
|
||||||
set_stmt_errmsg(stmt,(char *)mysql->net.last_error,
|
|
||||||
mysql->net.last_errno);
|
|
||||||
DBUG_RETURN(MYSQL_STATUS_ERROR);
|
|
||||||
}
|
|
||||||
DBUG_RETURN(MYSQL_NO_DATA); /* no more data */
|
|
||||||
}
|
}
|
||||||
DBUG_RETURN(0); //?? do we need to set MYSQL_STATUS_READY ?
|
mysql->status= MYSQL_STATUS_READY;
|
||||||
|
if (res < 0) /* Network error */
|
||||||
|
{
|
||||||
|
set_stmt_errmsg(stmt,(char *)mysql->net.last_error,
|
||||||
|
mysql->net.last_errno);
|
||||||
|
DBUG_RETURN(MYSQL_STATUS_ERROR);
|
||||||
|
}
|
||||||
|
DBUG_PRINT("info", ("end of data"));
|
||||||
|
DBUG_RETURN(MYSQL_NO_DATA); /* no more data */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
35
sql/field.cc
35
sql/field.cc
@ -2599,7 +2599,7 @@ String *Field_double::val_str(String *val_buffer,
|
|||||||
|
|
||||||
bool Field_double::send_binary(Protocol *protocol)
|
bool Field_double::send_binary(Protocol *protocol)
|
||||||
{
|
{
|
||||||
return protocol->store((float) Field_double::val_real(), dec, (String*) 0);
|
return protocol->store((double) Field_double::val_real(), dec, (String*) 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -3169,7 +3169,7 @@ bool Field_time::send_binary(Protocol *protocol)
|
|||||||
Field_time::get_time(&tm);
|
Field_time::get_time(&tm);
|
||||||
tm.day= tm.hour/3600; // Move hours to days
|
tm.day= tm.hour/3600; // Move hours to days
|
||||||
tm.hour-= tm.day*3600;
|
tm.hour-= tm.day*3600;
|
||||||
return protocol->store(&tm);
|
return protocol->store_time(&tm);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -3254,6 +3254,13 @@ int Field_year::store(longlong nr)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Field_year::send_binary(Protocol *protocol)
|
||||||
|
{
|
||||||
|
ulonglong tmp= Field_year::val_int();
|
||||||
|
TIME tm;
|
||||||
|
tm.year= (uint32) tmp;
|
||||||
|
return protocol->store_date(&tm);
|
||||||
|
}
|
||||||
|
|
||||||
double Field_year::val_real(void)
|
double Field_year::val_real(void)
|
||||||
{
|
{
|
||||||
@ -3371,6 +3378,16 @@ int Field_date::store(longlong nr)
|
|||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Field_date::send_binary(Protocol *protocol)
|
||||||
|
{
|
||||||
|
longlong tmp= Field_date::val_int();
|
||||||
|
TIME tm;
|
||||||
|
tm.year= (uint32) tmp/10000L % 10000;
|
||||||
|
tm.month= (uint32) tmp/100 % 100;
|
||||||
|
tm.day= (uint32) tmp % 100;
|
||||||
|
return protocol->store_date(&tm);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
double Field_date::val_real(void)
|
double Field_date::val_real(void)
|
||||||
{
|
{
|
||||||
@ -3544,7 +3561,12 @@ void Field_newdate::store_time(TIME *ltime,timestamp_type type)
|
|||||||
int3store(ptr,tmp);
|
int3store(ptr,tmp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Field_newdate::send_binary(Protocol *protocol)
|
||||||
|
{
|
||||||
|
TIME tm;
|
||||||
|
Field_newdate::get_date(&tm,0);
|
||||||
|
return protocol->store_date(&tm);
|
||||||
|
}
|
||||||
|
|
||||||
double Field_newdate::val_real(void)
|
double Field_newdate::val_real(void)
|
||||||
{
|
{
|
||||||
@ -3705,6 +3727,13 @@ void Field_datetime::store_time(TIME *ltime,timestamp_type type)
|
|||||||
longlongstore(ptr,tmp);
|
longlongstore(ptr,tmp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Field_datetime::send_binary(Protocol *protocol)
|
||||||
|
{
|
||||||
|
TIME tm;
|
||||||
|
Field_datetime::get_date(&tm, 1);
|
||||||
|
return protocol->store(&tm);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
double Field_datetime::val_real(void)
|
double Field_datetime::val_real(void)
|
||||||
{
|
{
|
||||||
|
@ -166,7 +166,7 @@ public:
|
|||||||
ptr-=row_offset;
|
ptr-=row_offset;
|
||||||
return tmp;
|
return tmp;
|
||||||
}
|
}
|
||||||
bool send_binary(Protocol *protocol);
|
virtual bool send_binary(Protocol *protocol);
|
||||||
virtual char *pack(char* to, const char *from, uint max_length=~(uint) 0)
|
virtual char *pack(char* to, const char *from, uint max_length=~(uint) 0)
|
||||||
{
|
{
|
||||||
uint32 length=pack_length();
|
uint32 length=pack_length();
|
||||||
@ -792,7 +792,6 @@ public:
|
|||||||
double val_real(void);
|
double val_real(void);
|
||||||
longlong val_int(void);
|
longlong val_int(void);
|
||||||
String *val_str(String*,String *);
|
String *val_str(String*,String *);
|
||||||
bool send_binary(Protocol *protocol);
|
|
||||||
int cmp(const char *,const char*);
|
int cmp(const char *,const char*);
|
||||||
void sort_string(char *buff,uint length);
|
void sort_string(char *buff,uint length);
|
||||||
void sql_type(String &str) const;
|
void sql_type(String &str) const;
|
||||||
@ -833,7 +832,6 @@ public:
|
|||||||
double val_real(void);
|
double val_real(void);
|
||||||
longlong val_int(void);
|
longlong val_int(void);
|
||||||
String *val_str(String*,String *);
|
String *val_str(String*,String *);
|
||||||
bool send_binary(Protocol *protocol);
|
|
||||||
int cmp(const char *,const char*);
|
int cmp(const char *,const char*);
|
||||||
void sort_string(char *buff,uint length);
|
void sort_string(char *buff,uint length);
|
||||||
void get_key_image(char *buff,uint length, CHARSET_INFO *cs, imagetype type);
|
void get_key_image(char *buff,uint length, CHARSET_INFO *cs, imagetype type);
|
||||||
@ -876,7 +874,6 @@ public:
|
|||||||
double val_real(void);
|
double val_real(void);
|
||||||
longlong val_int(void);
|
longlong val_int(void);
|
||||||
String *val_str(String*,String *);
|
String *val_str(String*,String *);
|
||||||
bool send_binary(Protocol *protocol);
|
|
||||||
int cmp(const char *,const char*);
|
int cmp(const char *,const char*);
|
||||||
int cmp(const char *a, uint32 a_length, const char *b, uint32 b_length);
|
int cmp(const char *a, uint32 a_length, const char *b, uint32 b_length);
|
||||||
int cmp_offset(uint offset);
|
int cmp_offset(uint offset);
|
||||||
@ -982,7 +979,6 @@ public:
|
|||||||
double val_real(void);
|
double val_real(void);
|
||||||
longlong val_int(void);
|
longlong val_int(void);
|
||||||
String *val_str(String*,String *);
|
String *val_str(String*,String *);
|
||||||
bool send_binary(Protocol *protocol);
|
|
||||||
int cmp(const char *,const char*);
|
int cmp(const char *,const char*);
|
||||||
void sort_string(char *buff,uint length);
|
void sort_string(char *buff,uint length);
|
||||||
uint32 pack_length() const { return (uint32) packlength; }
|
uint32 pack_length() const { return (uint32) packlength; }
|
||||||
|
@ -616,7 +616,7 @@ bool Protocol_simple::store_null()
|
|||||||
field_pos++;
|
field_pos++;
|
||||||
#endif
|
#endif
|
||||||
char buff[1];
|
char buff[1];
|
||||||
buff[0]= 251;
|
buff[0]= (char)251;
|
||||||
return packet->append(buff, sizeof(buff), PACKET_BUFFET_EXTRA_ALLOC);
|
return packet->append(buff, sizeof(buff), PACKET_BUFFET_EXTRA_ALLOC);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -774,13 +774,27 @@ bool Protocol_simple::store_time(TIME *tm)
|
|||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
Functions to handle the binary protocol used with prepared statements
|
Functions to handle the binary protocol used with prepared statements
|
||||||
|
|
||||||
|
Data format:
|
||||||
|
|
||||||
|
[ok:1] <-- reserved ok packet
|
||||||
|
[null_field:(field_count+7+2)/8] <-- reserved to send null data. The size is
|
||||||
|
calculated using:
|
||||||
|
bit_fields= (field_count+7+2)/8;
|
||||||
|
2 bits are reserved
|
||||||
|
[[length]data] <-- data field (the length applies only for
|
||||||
|
string/binary/time/timestamp fields and
|
||||||
|
rest of them are not sent as they have
|
||||||
|
the default length that client understands
|
||||||
|
based on the field type
|
||||||
|
[..]..[[length]data] <-- data
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
bool Protocol_prep::prepare_for_send(List<Item> *item_list)
|
bool Protocol_prep::prepare_for_send(List<Item> *item_list)
|
||||||
{
|
{
|
||||||
field_count=item_list->elements;
|
field_count= item_list->elements;
|
||||||
bit_fields= (field_count+3)/8;
|
bit_fields= (field_count+9)/8;
|
||||||
if (packet->alloc(bit_fields))
|
if (packet->alloc(bit_fields+1))
|
||||||
return 1;
|
return 1;
|
||||||
/* prepare_for_resend will be called after this one */
|
/* prepare_for_resend will be called after this one */
|
||||||
return 0;
|
return 0;
|
||||||
@ -789,9 +803,8 @@ bool Protocol_prep::prepare_for_send(List<Item> *item_list)
|
|||||||
|
|
||||||
void Protocol_prep::prepare_for_resend()
|
void Protocol_prep::prepare_for_resend()
|
||||||
{
|
{
|
||||||
packet->length(bit_fields);
|
packet->length(bit_fields+1);
|
||||||
bzero((char*) packet->ptr()+1, bit_fields-1);
|
bzero((char*) packet->ptr(), 1+bit_fields);
|
||||||
packet[0]=1; // Marker for ok packet
|
|
||||||
field_pos=0;
|
field_pos=0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -813,7 +826,7 @@ bool Protocol_prep::store(const char *from,uint length)
|
|||||||
|
|
||||||
bool Protocol_prep::store_null()
|
bool Protocol_prep::store_null()
|
||||||
{
|
{
|
||||||
uint offset=(field_pos+2)/8, bit= (1 << ((field_pos+2) & 7));
|
uint offset= (field_pos+2)/8+1, bit= (1 << ((field_pos+2) & 7));
|
||||||
/* Room for this as it's allocated in prepare_for_send */
|
/* Room for this as it's allocated in prepare_for_send */
|
||||||
char *to= (char*) packet->ptr()+offset;
|
char *to= (char*) packet->ptr()+offset;
|
||||||
*to= (char) ((uchar) *to | (uchar) bit);
|
*to= (char) ((uchar) *to | (uchar) bit);
|
||||||
@ -926,6 +939,7 @@ bool Protocol_prep::store(TIME *tm)
|
|||||||
{
|
{
|
||||||
#ifndef DEBUG_OFF
|
#ifndef DEBUG_OFF
|
||||||
DBUG_ASSERT(field_types == 0 ||
|
DBUG_ASSERT(field_types == 0 ||
|
||||||
|
field_types[field_pos] == MYSQL_TYPE_YEAR ||
|
||||||
field_types[field_pos] == MYSQL_TYPE_DATETIME ||
|
field_types[field_pos] == MYSQL_TYPE_DATETIME ||
|
||||||
field_types[field_pos] == MYSQL_TYPE_DATE ||
|
field_types[field_pos] == MYSQL_TYPE_DATE ||
|
||||||
field_types[field_pos] == MYSQL_TYPE_TIMESTAMP);
|
field_types[field_pos] == MYSQL_TYPE_TIMESTAMP);
|
||||||
@ -987,3 +1001,10 @@ bool Protocol_prep::store_time(TIME *tm)
|
|||||||
buff[0]=(char) length; // Length is stored first
|
buff[0]=(char) length; // Length is stored first
|
||||||
return packet->append(buff, length+1, PACKET_BUFFET_EXTRA_ALLOC);
|
return packet->append(buff, length+1, PACKET_BUFFET_EXTRA_ALLOC);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
bool Protocol_prep::send_fields(List<Item> *list, uint flag)
|
||||||
|
{
|
||||||
|
return prepare_for_send(list);
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
@ -440,10 +440,9 @@ static bool mysql_test_upd_fields(PREP_STMT *stmt, TABLE_LIST *table_list,
|
|||||||
COND *conds)
|
COND *conds)
|
||||||
{
|
{
|
||||||
THD *thd= stmt->thd;
|
THD *thd= stmt->thd;
|
||||||
TABLE *table;
|
|
||||||
DBUG_ENTER("mysql_test_upd_fields");
|
DBUG_ENTER("mysql_test_upd_fields");
|
||||||
|
|
||||||
if (!(table = open_ltable(thd,table_list,table_list->lock_type)))
|
if (open_and_lock_tables(thd, table_list))
|
||||||
DBUG_RETURN(1);
|
DBUG_RETURN(1);
|
||||||
|
|
||||||
if (setup_tables(table_list) || setup_fields(thd,table_list,fields,1,0,0) ||
|
if (setup_tables(table_list) || setup_fields(thd,table_list,fields,1,0,0) ||
|
||||||
@ -477,13 +476,12 @@ static bool mysql_test_select_fields(PREP_STMT *stmt, TABLE_LIST *tables,
|
|||||||
COND *conds, ORDER *order, ORDER *group,
|
COND *conds, ORDER *order, ORDER *group,
|
||||||
Item *having)
|
Item *having)
|
||||||
{
|
{
|
||||||
TABLE *table;
|
|
||||||
bool hidden_group_fields;
|
bool hidden_group_fields;
|
||||||
THD *thd= stmt->thd;
|
THD *thd= stmt->thd;
|
||||||
List<Item> all_fields(fields);
|
List<Item> all_fields(fields);
|
||||||
DBUG_ENTER("mysql_test_select_fields");
|
DBUG_ENTER("mysql_test_select_fields");
|
||||||
|
|
||||||
if (!(table = open_ltable(thd,tables,TL_READ)))
|
if (open_and_lock_tables(thd, tables))
|
||||||
DBUG_RETURN(1);
|
DBUG_RETURN(1);
|
||||||
|
|
||||||
thd->used_tables=0; // Updated by setup_fields
|
thd->used_tables=0; // Updated by setup_fields
|
||||||
@ -512,7 +510,7 @@ static bool mysql_test_select_fields(PREP_STMT *stmt, TABLE_LIST *tables,
|
|||||||
sending any info on where clause.
|
sending any info on where clause.
|
||||||
*/
|
*/
|
||||||
if (send_prep_stmt(stmt, fields.elements) ||
|
if (send_prep_stmt(stmt, fields.elements) ||
|
||||||
thd->protocol_prep.send_fields(&fields,0) ||
|
thd->protocol_simple.send_fields(&fields,0) ||
|
||||||
send_item_params(stmt))
|
send_item_params(stmt))
|
||||||
DBUG_RETURN(1);
|
DBUG_RETURN(1);
|
||||||
DBUG_RETURN(0);
|
DBUG_RETURN(0);
|
||||||
@ -626,14 +624,17 @@ static bool parse_prepare_query(PREP_STMT *stmt,
|
|||||||
/*
|
/*
|
||||||
Initialize parameter items in statement
|
Initialize parameter items in statement
|
||||||
*/
|
*/
|
||||||
static bool init_param_items(THD *thd, PREP_STMT *stmt)
|
|
||||||
|
static bool init_param_items( PREP_STMT *stmt)
|
||||||
{
|
{
|
||||||
|
List<Item> ¶ms= stmt->thd->lex.param_list;
|
||||||
Item_param **to;
|
Item_param **to;
|
||||||
|
|
||||||
if (!(stmt->param= to= (Item_param **)
|
if (!(stmt->param= to= (Item_param **)
|
||||||
my_malloc(sizeof(Item_param *)*(stmt->param_count+1),
|
my_malloc(sizeof(Item_param *)*(stmt->param_count+1),
|
||||||
MYF(MY_WME))))
|
MYF(MY_WME))))
|
||||||
return 1;
|
return 1;
|
||||||
List_iterator<Item> param_iterator(thd->lex.param_list);
|
List_iterator<Item> param_iterator(params);
|
||||||
while ((*(to++) = (Item_param *)param_iterator++));
|
while ((*(to++) = (Item_param *)param_iterator++));
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -659,29 +660,32 @@ bool mysql_stmt_prepare(THD *thd, char *packet, uint packet_length)
|
|||||||
DBUG_ENTER("mysql_stmt_prepare");
|
DBUG_ENTER("mysql_stmt_prepare");
|
||||||
|
|
||||||
bzero((char*) &stmt, sizeof(stmt));
|
bzero((char*) &stmt, sizeof(stmt));
|
||||||
stmt.thd= thd;
|
|
||||||
stmt.stmt_id= ++thd->current_stmt_id;
|
stmt.stmt_id= ++thd->current_stmt_id;
|
||||||
init_sql_alloc(&stmt.mem_root, 8192, 8192);
|
init_sql_alloc(&stmt.mem_root, 8192, 8192);
|
||||||
|
|
||||||
|
stmt.thd= thd;
|
||||||
|
stmt.thd->mem_root= stmt.mem_root;
|
||||||
|
|
||||||
thd->mem_root= stmt.mem_root;
|
if (alloc_query(stmt.thd, packet, packet_length))
|
||||||
if (alloc_query(thd, packet, packet_length))
|
|
||||||
goto err;
|
goto err;
|
||||||
|
|
||||||
if (parse_prepare_query(&stmt, thd->query, thd->query_length))
|
if (parse_prepare_query(&stmt, thd->query, thd->query_length))
|
||||||
goto err;
|
goto err;
|
||||||
|
|
||||||
if (!(specialflag & SPECIAL_NO_PRIOR))
|
if (!(specialflag & SPECIAL_NO_PRIOR))
|
||||||
my_pthread_setprio(pthread_self(),WAIT_PRIOR);
|
my_pthread_setprio(pthread_self(),WAIT_PRIOR);
|
||||||
|
|
||||||
if (init_param_items(thd, &stmt))
|
if (init_param_items(&stmt))
|
||||||
goto err;
|
goto err;
|
||||||
|
|
||||||
stmt.mem_root= thd->mem_root;
|
stmt.mem_root= stmt.thd->mem_root;
|
||||||
tree_insert(&thd->prepared_statements, (void *)&stmt, 0, (void *)0);
|
tree_insert(&thd->prepared_statements, (void *)&stmt, 0, (void *)0);
|
||||||
thd->mem_root= thd_root; // restore main mem_root
|
thd->mem_root= thd_root; // restore main mem_root
|
||||||
DBUG_RETURN(0);
|
DBUG_RETURN(0);
|
||||||
|
|
||||||
err:
|
err:
|
||||||
stmt.mem_root= thd->mem_root;
|
stmt.mem_root= stmt.thd->mem_root;
|
||||||
free_prep_stmt(&stmt, free_free, (void*) 0);
|
free_prep_stmt(&stmt, free_free, (void*) 0);
|
||||||
thd->mem_root = thd_root; // restore main mem_root
|
thd->mem_root = thd_root; // restore main mem_root
|
||||||
DBUG_RETURN(1);
|
DBUG_RETURN(1);
|
||||||
@ -727,9 +731,9 @@ void mysql_stmt_execute(THD *thd, char *packet)
|
|||||||
mysql_delete(), mysql_update() and mysql_select() to not to
|
mysql_delete(), mysql_update() and mysql_select() to not to
|
||||||
have re-check on setup_* and other things ..
|
have re-check on setup_* and other things ..
|
||||||
*/
|
*/
|
||||||
thd->protocol= &thd->protocol_prep; // Switch to binary protocol
|
stmt->thd->protocol= &thd->protocol_prep; // Switch to binary protocol
|
||||||
mysql_execute_command(stmt->thd);
|
mysql_execute_command(stmt->thd);
|
||||||
thd->protocol= &thd->protocol_simple; // Use normal protocol
|
stmt->thd->protocol= &thd->protocol_simple; // Use normal protocol
|
||||||
|
|
||||||
if (!(specialflag & SPECIAL_NO_PRIOR))
|
if (!(specialflag & SPECIAL_NO_PRIOR))
|
||||||
my_pthread_setprio(pthread_self(), WAIT_PRIOR);
|
my_pthread_setprio(pthread_self(), WAIT_PRIOR);
|
||||||
|
Reference in New Issue
Block a user