diff options
author | unknown <konstantin@mysql.com> | 2005-07-01 15:47:45 +0400 |
---|---|---|
committer | unknown <konstantin@mysql.com> | 2005-07-01 15:47:45 +0400 |
commit | d36c14f7488af415258b03b61e1e7dad74e1cdcb (patch) | |
tree | e1393e450cf0ca1709997362f5ef64d6b49532d2 /sql/sql_prepare.cc | |
parent | 77532a6f578fb5fd3e48ded3ac0e05e2f8c7c44d (diff) | |
download | mariadb-git-d36c14f7488af415258b03b61e1e7dad74e1cdcb.tar.gz |
A fix and a test case for Bug#11172 "mysql_stmt_attr_set
CURSOR_TYPE_READ_ONLY date/datetime filter server crash".
The fix adds support for Item_change_list in cursors (proper rollback
of the modified item tree).
sql/sql_class.cc:
No need to call fatal_error() twice.
sql/sql_prepare.cc:
- implement proper cleanup of the prepared statement in mysql_stmt_reset
if there is a cursor.
- take into account thd->change_list when fetching data through a
cursor.
sql/sql_select.cc:
- take into account thd->change_list when fetching data from a cursor:
grab it when we open a cursor, and rollback the changes to the parsed
tree when we close it.
sql/sql_select.h:
- Cursor::change_list added
tests/mysql_client_test.c:
- a test case for Bug#11172 "mysql_stmt_attr_set CURSOR_TYPE_READ_ONLY date/datetime
filter server crash"
Diffstat (limited to 'sql/sql_prepare.cc')
-rw-r--r-- | sql/sql_prepare.cc | 30 |
1 files changed, 22 insertions, 8 deletions
diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc index c97cb037f15..7c9e0bc8a08 100644 --- a/sql/sql_prepare.cc +++ b/sql/sql_prepare.cc @@ -2203,13 +2203,15 @@ void mysql_stmt_fetch(THD *thd, char *packet, uint packet_length) ulong num_rows= uint4korr(packet+4); Prepared_statement *stmt; Statement stmt_backup; + Cursor *cursor; DBUG_ENTER("mysql_stmt_fetch"); statistic_increment(thd->status_var.com_stmt_fetch, &LOCK_status); if (!(stmt= find_prepared_statement(thd, stmt_id, "mysql_stmt_fetch"))) DBUG_VOID_RETURN; - if (!stmt->cursor || !stmt->cursor->is_open()) + cursor= stmt->cursor; + if (!cursor || !cursor->is_open()) { my_error(ER_STMT_HAS_NO_OPEN_CURSOR, MYF(0), stmt_id); DBUG_VOID_RETURN; @@ -2222,22 +2224,27 @@ void mysql_stmt_fetch(THD *thd, char *packet, uint packet_length) my_pthread_setprio(pthread_self(), QUERY_PRIOR); thd->protocol= &thd->protocol_prep; // Switch to binary protocol - stmt->cursor->fetch(num_rows); + cursor->fetch(num_rows); thd->protocol= &thd->protocol_simple; // Use normal protocol if (!(specialflag & SPECIAL_NO_PRIOR)) my_pthread_setprio(pthread_self(), WAIT_PRIOR); - thd->restore_backup_statement(stmt, &stmt_backup); - thd->current_arena= thd; - - if (!stmt->cursor->is_open()) + if (!cursor->is_open()) { /* We're done with the fetch: reset PS for next execution */ cleanup_stmt_and_thd_after_use(stmt, thd); reset_stmt_params(stmt); + /* + Must be the last, as some momory is still needed for + the previous calls. + */ + free_root(cursor->mem_root, MYF(0)); } + thd->restore_backup_statement(stmt, &stmt_backup); + thd->current_arena= thd; + DBUG_VOID_RETURN; } @@ -2264,14 +2271,21 @@ void mysql_stmt_reset(THD *thd, char *packet) /* There is always space for 4 bytes in buffer */ ulong stmt_id= uint4korr(packet); Prepared_statement *stmt; + Cursor *cursor; DBUG_ENTER("mysql_stmt_reset"); statistic_increment(thd->status_var.com_stmt_reset, &LOCK_status); if (!(stmt= find_prepared_statement(thd, stmt_id, "mysql_stmt_reset"))) DBUG_VOID_RETURN; - if (stmt->cursor && stmt->cursor->is_open()) - stmt->cursor->close(); + cursor= stmt->cursor; + if (cursor && cursor->is_open()) + { + thd->change_list= cursor->change_list; + cursor->close(FALSE); + cleanup_stmt_and_thd_after_use(stmt, thd); + free_root(cursor->mem_root, MYF(0)); + } stmt->state= Query_arena::PREPARED; |