diff options
-rw-r--r-- | include/mysql.h | 7 | ||||
-rw-r--r-- | libmysql/client_settings.h | 2 | ||||
-rw-r--r-- | libmysql/libmysql.c | 179 | ||||
-rw-r--r-- | libmysql/libmysql.def | 3 | ||||
-rw-r--r-- | libmysqld/lib_sql.cc | 9 |
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) |