mirror of
https://github.com/MariaDB/server.git
synced 2025-07-27 18:02:13 +03:00
Implement store_result (read_binary_rows & mysql_stmt_store_result)
This commit is contained in:
@ -476,6 +476,7 @@ typedef struct st_mysql_stmt
|
|||||||
my_bool send_types_to_server; /* to indicate types supply to server */
|
my_bool send_types_to_server; /* to indicate types supply to server */
|
||||||
my_bool param_buffers; /* to indicate the param bound buffers */
|
my_bool param_buffers; /* to indicate the param bound buffers */
|
||||||
my_bool res_buffers; /* to indicate the output bound buffers */
|
my_bool res_buffers; /* to indicate the output bound buffers */
|
||||||
|
my_bool result_buffered; /* to indicate the results buffered */
|
||||||
} MYSQL_STMT;
|
} MYSQL_STMT;
|
||||||
|
|
||||||
|
|
||||||
@ -502,6 +503,7 @@ int STDCALL mysql_multi_query(MYSQL *mysql,const char *query,
|
|||||||
MYSQL_RES *STDCALL mysql_next_result(MYSQL *mysql);
|
MYSQL_RES *STDCALL mysql_next_result(MYSQL *mysql);
|
||||||
MYSQL_RES *STDCALL mysql_prepare_result(MYSQL_STMT *stmt);
|
MYSQL_RES *STDCALL mysql_prepare_result(MYSQL_STMT *stmt);
|
||||||
my_ulonglong STDCALL mysql_stmt_affected_rows(MYSQL_STMT *stmt);
|
my_ulonglong STDCALL mysql_stmt_affected_rows(MYSQL_STMT *stmt);
|
||||||
|
int STDCALL mysql_stmt_store_result(MYSQL_STMT *stmt);
|
||||||
|
|
||||||
|
|
||||||
/* new status messages */
|
/* new status messages */
|
||||||
|
@ -115,6 +115,7 @@ static sig_handler pipe_sig_handler(int sig);
|
|||||||
static ulong mysql_sub_escape_string(CHARSET_INFO *charset_info, char *to,
|
static ulong mysql_sub_escape_string(CHARSET_INFO *charset_info, char *to,
|
||||||
const char *from, ulong length);
|
const char *from, ulong length);
|
||||||
static my_bool stmt_close(MYSQL_STMT *stmt, my_bool skip_list);
|
static my_bool stmt_close(MYSQL_STMT *stmt, my_bool skip_list);
|
||||||
|
static unsigned int get_binary_length(uint type);
|
||||||
|
|
||||||
static my_bool org_my_init_done=0;
|
static my_bool org_my_init_done=0;
|
||||||
|
|
||||||
@ -3839,7 +3840,7 @@ static my_bool read_prepare_result(MYSQL_STMT *stmt)
|
|||||||
if ((length= net_safe_read(mysql)) == packet_error)
|
if ((length= net_safe_read(mysql)) == packet_error)
|
||||||
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;
|
||||||
param_count= uint2korr(pos); pos+=2;
|
param_count= uint2korr(pos); pos+=2;
|
||||||
@ -3865,10 +3866,10 @@ static my_bool read_prepare_result(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 + param_count);
|
||||||
stmt->field_count= (uint) field_count;
|
stmt->field_count= (uint) field_count;
|
||||||
stmt->param_count= (ulong) param_count;
|
stmt->param_count= (ulong) param_count;
|
||||||
stmt->mysql->status= MYSQL_STATUS_READY;
|
mysql->status= MYSQL_STATUS_READY;
|
||||||
DBUG_RETURN(0);
|
DBUG_RETURN(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -4102,8 +4103,18 @@ static my_bool store_param(MYSQL_STMT *stmt, MYSQL_BIND *param)
|
|||||||
store_param_null(net, param);
|
store_param_null(net, param);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* Allocate for worst case (long string) */
|
unsigned int length;
|
||||||
if ((my_realloc_str(net, 9 + *param->length)))
|
|
||||||
|
/*
|
||||||
|
Allocate for worst case (long string), ignore the length
|
||||||
|
buffer for numeric/double types by assigning the default
|
||||||
|
length using get_binary_length
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (!(length= get_binary_length(param->buffer_type)))
|
||||||
|
length= *param->length;
|
||||||
|
|
||||||
|
if ((my_realloc_str(net, 9 + length)))
|
||||||
DBUG_RETURN(1);
|
DBUG_RETURN(1);
|
||||||
(*param->store_param_func)(net, param);
|
(*param->store_param_func)(net, param);
|
||||||
}
|
}
|
||||||
@ -4133,6 +4144,8 @@ 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);
|
||||||
|
stmt->result= (MYSQL_RES *)0;
|
||||||
|
stmt->result_buffered= 0;
|
||||||
DBUG_RETURN(0);
|
DBUG_RETURN(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -4859,12 +4872,14 @@ 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 void
|
static int stmt_fetch_row(MYSQL_STMT *stmt, uchar *row)
|
||||||
stmt_fetch_row(MYSQL_STMT *stmt, uchar *row)
|
|
||||||
{
|
{
|
||||||
MYSQL_BIND *bind, *end;
|
MYSQL_BIND *bind, *end;
|
||||||
MYSQL_FIELD *field, *field_end;
|
MYSQL_FIELD *field, *field_end;
|
||||||
uchar *null_ptr, bit;
|
uchar *null_ptr, bit;
|
||||||
|
|
||||||
|
if (!row || !stmt->res_buffers)
|
||||||
|
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 */
|
||||||
@ -4884,7 +4899,7 @@ stmt_fetch_row(MYSQL_STMT *stmt, uchar *row)
|
|||||||
if (field->type == bind->buffer_type)
|
if (field->type == bind->buffer_type)
|
||||||
(*bind->fetch_result)(bind, &row);
|
(*bind->fetch_result)(bind, &row);
|
||||||
else if (fetch_results(stmt, bind, field->type, &row))
|
else if (fetch_results(stmt, bind, field->type, &row))
|
||||||
break;
|
return 1;
|
||||||
}
|
}
|
||||||
if (! (bit<<=1) & 255)
|
if (! (bit<<=1) & 255)
|
||||||
{
|
{
|
||||||
@ -4892,23 +4907,9 @@ stmt_fetch_row(MYSQL_STMT *stmt, uchar *row)
|
|||||||
null_ptr++;
|
null_ptr++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
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))
|
|
||||||
return -1;
|
|
||||||
if (mysql->net.read_pos[0] == 254)
|
|
||||||
return 1; /* End of data */
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Fetch and return row data to bound buffers, if any
|
Fetch and return row data to bound buffers, if any
|
||||||
*/
|
*/
|
||||||
@ -4916,24 +4917,153 @@ 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;
|
uchar *row;
|
||||||
DBUG_ENTER("mysql_fetch");
|
DBUG_ENTER("mysql_fetch");
|
||||||
|
|
||||||
if (!(res= read_binary_data(mysql)))
|
row= (uchar *)0;
|
||||||
|
if (stmt->result_buffered) /* buffered */
|
||||||
{
|
{
|
||||||
if (stmt->res_buffers)
|
MYSQL_RES *res;
|
||||||
stmt_fetch_row(stmt, mysql->net.read_pos+1);
|
|
||||||
DBUG_RETURN(0);
|
if (!(res= stmt->result) || !res->data_cursor)
|
||||||
|
goto no_data;
|
||||||
|
|
||||||
|
row= (uchar *)res->data_cursor->data;
|
||||||
|
res->data_cursor= res->data_cursor->next;
|
||||||
|
res->current_row= (MYSQL_ROW)row;
|
||||||
}
|
}
|
||||||
mysql->status= MYSQL_STATUS_READY;
|
else /* un-buffered */
|
||||||
if (res < 0) /* Network error */
|
{
|
||||||
|
if (packet_error == net_safe_read(mysql))
|
||||||
|
{
|
||||||
|
set_stmt_errmsg(stmt,(char *)mysql->net.last_error,
|
||||||
|
mysql->net.last_errno);
|
||||||
|
DBUG_RETURN(1);
|
||||||
|
}
|
||||||
|
if (mysql->net.read_pos[0] == 254)
|
||||||
|
{
|
||||||
|
mysql->status= MYSQL_STATUS_READY;
|
||||||
|
goto no_data;
|
||||||
|
}
|
||||||
|
row= mysql->net.read_pos+1;
|
||||||
|
}
|
||||||
|
DBUG_RETURN(stmt_fetch_row(stmt, row));
|
||||||
|
|
||||||
|
no_data:
|
||||||
|
DBUG_PRINT("info", ("end of data"));
|
||||||
|
DBUG_RETURN(MYSQL_NO_DATA); /* no more data */
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Read all rows of data from server (binary format)
|
||||||
|
*/
|
||||||
|
|
||||||
|
static MYSQL_DATA *read_binary_rows(MYSQL_STMT *stmt)
|
||||||
|
{
|
||||||
|
ulong pkt_len;
|
||||||
|
uchar *cp;
|
||||||
|
MYSQL *mysql= stmt->mysql;
|
||||||
|
MYSQL_DATA *result;
|
||||||
|
MYSQL_ROWS *cur, **prev_ptr;
|
||||||
|
NET *net = &mysql->net;
|
||||||
|
DBUG_ENTER("read_binary_rows");
|
||||||
|
|
||||||
|
mysql= mysql->last_used_con;
|
||||||
|
if ((pkt_len= net_safe_read(mysql)) == packet_error)
|
||||||
{
|
{
|
||||||
set_stmt_errmsg(stmt,(char *)mysql->net.last_error,
|
set_stmt_errmsg(stmt,(char *)mysql->net.last_error,
|
||||||
mysql->net.last_errno);
|
mysql->net.last_errno);
|
||||||
|
DBUG_RETURN(0);
|
||||||
|
}
|
||||||
|
if (mysql->net.read_pos[0] == 254) /* end of data */
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (!(result=(MYSQL_DATA*) my_malloc(sizeof(MYSQL_DATA),
|
||||||
|
MYF(MY_WME | MY_ZEROFILL))))
|
||||||
|
{
|
||||||
|
net->last_errno=CR_OUT_OF_MEMORY;
|
||||||
|
strmov(net->last_error,ER(net->last_errno));
|
||||||
|
DBUG_RETURN(0);
|
||||||
|
}
|
||||||
|
init_alloc_root(&result->alloc,8192,0); /* Assume rowlength < 8192 */
|
||||||
|
result->alloc.min_malloc= sizeof(MYSQL_ROWS);
|
||||||
|
prev_ptr= &result->data;
|
||||||
|
result->rows= 0;
|
||||||
|
|
||||||
|
while (*(cp=net->read_pos) != 254 || pkt_len >= 8)
|
||||||
|
{
|
||||||
|
result->rows++;
|
||||||
|
|
||||||
|
if (!(cur= (MYSQL_ROWS*) alloc_root(&result->alloc,sizeof(MYSQL_ROWS))) ||
|
||||||
|
!(cur->data= ((MYSQL_ROW) alloc_root(&result->alloc, pkt_len))))
|
||||||
|
{
|
||||||
|
free_rows(result);
|
||||||
|
net->last_errno=CR_OUT_OF_MEMORY;
|
||||||
|
strmov(net->last_error,ER(net->last_errno));
|
||||||
|
DBUG_RETURN(0);
|
||||||
|
}
|
||||||
|
*prev_ptr= cur;
|
||||||
|
prev_ptr= &cur->next;
|
||||||
|
memcpy(cur->data, (char*)cp+1, pkt_len-1);
|
||||||
|
|
||||||
|
if ((pkt_len=net_safe_read(mysql)) == packet_error)
|
||||||
|
{
|
||||||
|
free_rows(result);
|
||||||
|
DBUG_RETURN(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*prev_ptr= 0;
|
||||||
|
if (pkt_len > 1)
|
||||||
|
{
|
||||||
|
mysql->warning_count= uint2korr(cp+1);
|
||||||
|
DBUG_PRINT("info",("warning_count: %ld", mysql->warning_count));
|
||||||
|
}
|
||||||
|
DBUG_PRINT("exit",("Got %d rows",result->rows));
|
||||||
|
DBUG_RETURN(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Store or buffer the binary results to stmt
|
||||||
|
*/
|
||||||
|
|
||||||
|
int STDCALL mysql_stmt_store_result(MYSQL_STMT *stmt)
|
||||||
|
{
|
||||||
|
MYSQL *mysql= stmt->mysql;
|
||||||
|
MYSQL_RES *result;
|
||||||
|
DBUG_ENTER("mysql_stmt_tore_result");
|
||||||
|
|
||||||
|
mysql= mysql->last_used_con;
|
||||||
|
|
||||||
|
if (!stmt->field_count)
|
||||||
|
DBUG_RETURN(0);
|
||||||
|
if (mysql->status != MYSQL_STATUS_GET_RESULT)
|
||||||
|
{
|
||||||
|
strmov(mysql->net.last_error,
|
||||||
|
ER(mysql->net.last_errno= CR_COMMANDS_OUT_OF_SYNC));
|
||||||
|
DBUG_RETURN(0);
|
||||||
|
}
|
||||||
|
mysql->status= MYSQL_STATUS_READY; /* server is ready */
|
||||||
|
if (!(result= (MYSQL_RES*) my_malloc((uint) (sizeof(MYSQL_RES)+
|
||||||
|
sizeof(ulong) *
|
||||||
|
stmt->field_count),
|
||||||
|
MYF(MY_WME | MY_ZEROFILL))))
|
||||||
|
{
|
||||||
|
mysql->net.last_errno= CR_OUT_OF_MEMORY;
|
||||||
|
strmov(mysql->net.last_error, ER(mysql->net.last_errno));
|
||||||
DBUG_RETURN(1);
|
DBUG_RETURN(1);
|
||||||
}
|
}
|
||||||
DBUG_PRINT("info", ("end of data"));
|
stmt->result_buffered= 1;
|
||||||
DBUG_RETURN(MYSQL_NO_DATA); /* no more data */
|
if (!(result->data= read_binary_rows(stmt)))
|
||||||
|
{
|
||||||
|
my_free((gptr) result,MYF(0));
|
||||||
|
DBUG_RETURN(0);
|
||||||
|
}
|
||||||
|
mysql->affected_rows= result->row_count= result->data->rows;
|
||||||
|
result->data_cursor= result->data->data;
|
||||||
|
result->fields= stmt->fields;
|
||||||
|
result->field_count= stmt->field_count;
|
||||||
|
stmt->result= result;
|
||||||
|
DBUG_RETURN(0); /* Data buffered, must be fetched with mysql_fetch() */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user