Commit 370b88f9 authored by venu@myvenu.com's avatar venu@myvenu.com

Implement store_result (read_binary_rows & mysql_stmt_store_result)

parent c2ddffb4
...@@ -476,6 +476,7 @@ typedef struct st_mysql_stmt ...@@ -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, ...@@ -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); ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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() */
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment