summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/mysql.h7
-rw-r--r--libmysql/client_settings.h2
-rw-r--r--libmysql/libmysql.c179
-rw-r--r--libmysql/libmysql.def3
-rw-r--r--libmysqld/lib_sql.cc9
5 files changed, 88 insertions, 112 deletions
diff --git a/include/mysql.h b/include/mysql.h
index dcdbe3a07a4..43ca7fdba12 100644
--- a/include/mysql.h
+++ b/include/mysql.h
@@ -563,9 +563,11 @@ typedef struct st_mysql_stmt
MYSQL_BIND *params; /* input parameters */
MYSQL_BIND *bind; /* output parameters */
MYSQL_FIELD *fields; /* result set metadata */
- MYSQL_RES *result; /* cached result set */
+ MYSQL_DATA result; /* cached result set */
+ MYSQL_ROWS *data_cursor; /* current row in cached result */
/* copy of mysql->affected_rows after statement execution */
my_ulonglong affected_rows;
+ my_ulonglong insert_id; /* copy of mysql->insert_id */
/*
mysql_stmt_fetch() calls this function to fetch one row (it's different
for buffered, unbuffered and cursor fetch).
@@ -607,7 +609,7 @@ typedef struct st_mysql_methods
MYSQL_FIELD * (*list_fields)(MYSQL *mysql);
my_bool (*read_prepare_result)(MYSQL *mysql, MYSQL_STMT *stmt);
int (*stmt_execute)(MYSQL_STMT *stmt);
- MYSQL_DATA *(*read_binary_rows)(MYSQL_STMT *stmt);
+ int (*read_binary_rows)(MYSQL_STMT *stmt);
int (*unbuffered_fetch)(MYSQL *mysql, char **row);
void (*free_embedded_thd)(MYSQL *mysql);
const char *(*read_statistics)(MYSQL *mysql);
@@ -664,6 +666,7 @@ MYSQL_ROW_OFFSET STDCALL mysql_stmt_row_tell(MYSQL_STMT *stmt);
void STDCALL mysql_stmt_data_seek(MYSQL_STMT *stmt, my_ulonglong offset);
my_ulonglong STDCALL mysql_stmt_num_rows(MYSQL_STMT *stmt);
my_ulonglong STDCALL mysql_stmt_affected_rows(MYSQL_STMT *stmt);
+my_ulonglong STDCALL mysql_stmt_insert_id(MYSQL_STMT *stmt);
my_bool STDCALL mysql_commit(MYSQL * mysql);
my_bool STDCALL mysql_rollback(MYSQL * mysql);
diff --git a/libmysql/client_settings.h b/libmysql/client_settings.h
index 3fdadf29dea..a9695801e65 100644
--- a/libmysql/client_settings.h
+++ b/libmysql/client_settings.h
@@ -54,7 +54,7 @@ my_bool cli_read_prepare_result(MYSQL *mysql, MYSQL_STMT *stmt);
MYSQL_DATA * cli_read_rows(MYSQL *mysql,MYSQL_FIELD *mysql_fields,
uint fields);
int cli_stmt_execute(MYSQL_STMT *stmt);
-MYSQL_DATA * cli_read_binary_rows(MYSQL_STMT *stmt);
+int cli_read_binary_rows(MYSQL_STMT *stmt);
int cli_unbuffered_fetch(MYSQL *mysql, char **row);
const char * cli_read_statistics(MYSQL *mysql);
int cli_read_change_user_result(MYSQL *mysql, char *buff, const char *passwd);
diff --git a/libmysql/libmysql.c b/libmysql/libmysql.c
index 0043cdf3542..51d6d669d36 100644
--- a/libmysql/libmysql.c
+++ b/libmysql/libmysql.c
@@ -1907,6 +1907,8 @@ mysql_stmt_init(MYSQL *mysql)
}
init_alloc_root(&stmt->mem_root, 2048, 2048);
+ init_alloc_root(&stmt->result.alloc, 4096, 4096);
+ stmt->result.alloc.min_malloc= sizeof(MYSQL_ROWS);
mysql->stmts= list_add(mysql->stmts, &stmt->list);
stmt->list.data= stmt;
stmt->state= MYSQL_STMT_INIT_DONE;
@@ -2335,6 +2337,7 @@ static my_bool execute(MYSQL_STMT * stmt, char *packet, ulong length)
DBUG_RETURN(1);
}
stmt->affected_rows= mysql->affected_rows;
+ stmt->insert_id= mysql->insert_id;
DBUG_RETURN(0);
}
@@ -2414,12 +2417,10 @@ int cli_stmt_execute(MYSQL_STMT *stmt)
static int stmt_read_row_buffered(MYSQL_STMT *stmt, unsigned char **row)
{
- MYSQL_RES *result= stmt->result;
-
- if (result && result->data_cursor)
+ if (stmt->data_cursor)
{
- *row= (uchar *) result->data_cursor->data;
- result->data_cursor= result->data_cursor->next;
+ *row= (uchar *) stmt->data_cursor->data;
+ stmt->data_cursor= stmt->data_cursor->next;
return 0;
}
*row= 0;
@@ -2564,6 +2565,15 @@ my_ulonglong STDCALL mysql_stmt_affected_rows(MYSQL_STMT *stmt)
}
+/*
+ Return last inserted id for auto_increment columns
+*/
+
+my_ulonglong STDCALL mysql_stmt_insert_id(MYSQL_STMT *stmt)
+{
+ return stmt->insert_id;
+}
+
static my_bool int_is_null_true= 1; /* Used for MYSQL_TYPE_NULL */
static my_bool int_is_null_false= 0;
@@ -3534,67 +3544,46 @@ int STDCALL mysql_stmt_fetch_column(MYSQL_STMT *stmt, MYSQL_BIND *bind,
Read all rows of data from server (binary format)
*/
-MYSQL_DATA *cli_read_binary_rows(MYSQL_STMT *stmt)
+int cli_read_binary_rows(MYSQL_STMT *stmt)
{
ulong pkt_len;
uchar *cp;
MYSQL *mysql= stmt->mysql;
- MYSQL_DATA *result;
- MYSQL_ROWS *cur, **prev_ptr;
+ MYSQL_DATA *result= &stmt->result;
+ MYSQL_ROWS *cur, **prev_ptr= &result->data;
NET *net = &mysql->net;
DBUG_ENTER("cli_read_binary_rows");
-
- mysql= mysql->last_used_con;
- if ((pkt_len= net_safe_read(mysql)) == packet_error)
- {
- set_stmt_errmsg(stmt, mysql->net.last_error, mysql->net.last_errno,
- mysql->net.sqlstate);
-
- 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))))
- {
- set_stmt_error(stmt, CR_OUT_OF_MEMORY, unknown_sqlstate);
- 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;
+ mysql= mysql->last_used_con;
- while (*(cp=net->read_pos) != 254 || pkt_len >= 8)
+ while ((pkt_len= net_safe_read(mysql)) != packet_error)
{
- result->rows++;
-
- if (!(cur= (MYSQL_ROWS*) alloc_root(&result->alloc,sizeof(MYSQL_ROWS))) ||
- !(cur->data= ((MYSQL_ROW) alloc_root(&result->alloc, pkt_len))))
+ cp= net->read_pos;
+ if (cp[0] != 254 || pkt_len >= 8)
{
- free_rows(result);
- set_stmt_error(stmt, CR_OUT_OF_MEMORY, unknown_sqlstate);
- DBUG_RETURN(0);
+ if (!(cur= (MYSQL_ROWS*) alloc_root(&result->alloc,
+ sizeof(MYSQL_ROWS) + pkt_len - 1)))
+ {
+ set_stmt_error(stmt, CR_OUT_OF_MEMORY, unknown_sqlstate);
+ DBUG_RETURN(1);
+ }
+ cur->data= (MYSQL_ROW) (cur+1);
+ *prev_ptr= cur;
+ prev_ptr= &cur->next;
+ memcpy((char *) cur->data, (char *) cp+1, pkt_len-1);
+ ++result->rows;
}
- *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)
+ else
{
- free_rows(result);
+ /* end of data */
+ *prev_ptr= 0;
+ mysql->warning_count= uint2korr(cp+1);
+ mysql->server_status= uint2korr(cp+3);
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);
+ set_stmt_errmsg(stmt, net->last_error, net->last_errno, net->sqlstate);
+ DBUG_RETURN(1);
}
@@ -3605,7 +3594,7 @@ MYSQL_DATA *cli_read_binary_rows(MYSQL_STMT *stmt)
int STDCALL mysql_stmt_store_result(MYSQL_STMT *stmt)
{
MYSQL *mysql= stmt->mysql;
- MYSQL_RES *result;
+ MYSQL_DATA *result= &stmt->result;
DBUG_ENTER("mysql_stmt_store_result");
mysql= mysql->last_used_con;
@@ -3618,28 +3607,23 @@ int STDCALL mysql_stmt_store_result(MYSQL_STMT *stmt)
set_stmt_error(stmt, CR_COMMANDS_OUT_OF_SYNC, unknown_sqlstate);
DBUG_RETURN(1);
}
- if (!(result= (MYSQL_RES*) my_malloc(sizeof(MYSQL_RES),
- MYF(MY_WME | MY_ZEROFILL))))
- {
- set_stmt_error(stmt, CR_OUT_OF_MEMORY, unknown_sqlstate);
- DBUG_RETURN(1);
- }
- result->methods= mysql->methods;
- if ((result->data= (*mysql->methods->read_binary_rows)(stmt)))
+ if (result->data)
{
- result->row_count= result->data->rows;
- result->data_cursor= result->data->data;
+ free_root(&result->alloc, MYF(MY_KEEP_PREALLOC));
+ result->data= NULL;
+ result->rows= 0;
+ stmt->data_cursor= NULL;
}
- else if (stmt->last_errno)
+ if ((*mysql->methods->read_binary_rows)(stmt))
{
- my_free((gptr) result,MYF(0));
+ free_root(&result->alloc, MYF(MY_KEEP_PREALLOC));
+ result->data= NULL;
+ result->rows= 0;
DBUG_RETURN(1);
}
- mysql->affected_rows= stmt->affected_rows= result->row_count;
- result->fields= stmt->fields;
- result->field_count= stmt->field_count;
- /* The rest of MYSQL_RES members were bzeroed inside my_malloc */
- stmt->result= result;
+
+ stmt->data_cursor= result->data;
+ mysql->affected_rows= stmt->affected_rows= result->rows;
stmt->read_row_func= stmt_read_row_buffered;
mysql->unbuffered_fetch_owner= 0; /* set in stmt_execute */
mysql->status= MYSQL_STATUS_READY; /* server is ready */
@@ -3654,19 +3638,11 @@ int STDCALL mysql_stmt_store_result(MYSQL_STMT *stmt)
MYSQL_ROW_OFFSET STDCALL
mysql_stmt_row_seek(MYSQL_STMT *stmt, MYSQL_ROW_OFFSET row)
{
- MYSQL_RES *result;
+ MYSQL_ROW_OFFSET offset= stmt->data_cursor;
DBUG_ENTER("mysql_stmt_row_seek");
- if ((result= stmt->result))
- {
- MYSQL_ROW_OFFSET return_value= result->data_cursor;
- result->current_row= 0;
- result->data_cursor= row;
- DBUG_RETURN(return_value);
- }
-
- DBUG_PRINT("exit", ("stmt doesn't contain any resultset"));
- DBUG_RETURN(0);
+ stmt->data_cursor= row;
+ DBUG_RETURN(offset);
}
@@ -3679,11 +3655,7 @@ mysql_stmt_row_tell(MYSQL_STMT *stmt)
{
DBUG_ENTER("mysql_stmt_row_tell");
- if (stmt->result)
- DBUG_RETURN(stmt->result->data_cursor);
-
- DBUG_PRINT("exit", ("stmt doesn't contain any resultset"));
- DBUG_RETURN(0);
+ DBUG_RETURN(stmt->data_cursor);
}
@@ -3694,20 +3666,13 @@ mysql_stmt_row_tell(MYSQL_STMT *stmt)
void STDCALL
mysql_stmt_data_seek(MYSQL_STMT *stmt, my_ulonglong row)
{
- MYSQL_RES *result;
+ MYSQL_ROWS *tmp= stmt->result.data;
DBUG_ENTER("mysql_stmt_data_seek");
DBUG_PRINT("enter",("row id to seek: %ld",(long) row));
- if ((result= stmt->result))
- {
- MYSQL_ROWS *tmp= 0;
- if (result->data)
- for (tmp=result->data->data; row-- && tmp ; tmp = tmp->next) ;
- result->current_row= 0;
- result->data_cursor= tmp;
- }
- else
- DBUG_PRINT("exit", ("stmt doesn't contain any resultset"));
+ for (; tmp && row; --row, tmp= tmp->next)
+ ;
+ stmt->data_cursor= tmp;
DBUG_VOID_RETURN;
}
@@ -3720,15 +3685,12 @@ my_ulonglong STDCALL mysql_stmt_num_rows(MYSQL_STMT *stmt)
{
DBUG_ENTER("mysql_stmt_num_rows");
- if (stmt->result)
- DBUG_RETURN(stmt->result->row_count);
-
- DBUG_PRINT("exit", ("stmt doesn't contain any resultset"));
- DBUG_RETURN(0);
+ DBUG_RETURN(stmt->result.rows);
}
my_bool STDCALL mysql_stmt_free_result(MYSQL_STMT *stmt)
{
+ MYSQL_DATA *result= &stmt->result;
DBUG_ENTER("mysql_stmt_free_result");
DBUG_ASSERT(stmt != 0);
@@ -3737,14 +3699,17 @@ my_bool STDCALL mysql_stmt_free_result(MYSQL_STMT *stmt)
{
MYSQL *mysql= stmt->mysql;
- if (stmt->result)
+ if (result->data)
{
/* Result buffered */
- mysql_free_result(stmt->result);
- stmt->result= 0;
+ free_root(&result->alloc, MYF(MY_KEEP_PREALLOC));
+ result->data= NULL;
+ result->rows= 0;
+ stmt->data_cursor= NULL;
}
- else if (mysql && stmt->field_count
- && (int) stmt->state > (int) MYSQL_STMT_PREPARE_DONE)
+
+ if (mysql && stmt->field_count &&
+ (int) stmt->state > (int) MYSQL_STMT_PREPARE_DONE)
{
if (mysql->unbuffered_fetch_owner == &stmt->unbuffered_fetch_cancelled)
mysql->unbuffered_fetch_owner= 0;
@@ -3783,7 +3748,7 @@ my_bool STDCALL mysql_stmt_close(MYSQL_STMT *stmt)
int rc= 0;
DBUG_ENTER("mysql_stmt_close");
- mysql_free_result(stmt->result); /* if result is buffered */
+ free_root(&stmt->result.alloc, MYF(0));
free_root(&stmt->mem_root, MYF(0));
if (mysql)
diff --git a/libmysql/libmysql.def b/libmysql/libmysql.def
index 00d0fca119e..4f6347776e0 100644
--- a/libmysql/libmysql.def
+++ b/libmysql/libmysql.def
@@ -124,3 +124,6 @@ EXPORTS
strmake
strmov
strxmov
+ mysql_stmt_prepare
+ mysql_stmt_init
+ mysql_stmt_insert_id
diff --git a/libmysqld/lib_sql.cc b/libmysqld/lib_sql.cc
index aa29f630b0d..6fb23f8f00d 100644
--- a/libmysqld/lib_sql.cc
+++ b/libmysqld/lib_sql.cc
@@ -200,9 +200,14 @@ static int emb_stmt_execute(MYSQL_STMT *stmt)
DBUG_RETURN(0);
}
-MYSQL_DATA *emb_read_binary_rows(MYSQL_STMT *stmt)
+int emb_read_binary_rows(MYSQL_STMT *stmt)
{
- return emb_read_rows(stmt->mysql, 0, 0);
+ MYSQL_DATA *data;
+ if (!(data= emb_read_rows(stmt->mysql, 0, 0)))
+ return 1;
+ stmt->result= *data;
+ my_free((char *) data, MYF(0));
+ return 0;
}
int emb_unbuffered_fetch(MYSQL *mysql, char **row)