summaryrefslogtreecommitdiff
path: root/sql/sql_prepare.cc
diff options
context:
space:
mode:
authorunknown <konstantin@mysql.com>2005-07-01 15:47:45 +0400
committerunknown <konstantin@mysql.com>2005-07-01 15:47:45 +0400
commitd36c14f7488af415258b03b61e1e7dad74e1cdcb (patch)
treee1393e450cf0ca1709997362f5ef64d6b49532d2 /sql/sql_prepare.cc
parent77532a6f578fb5fd3e48ded3ac0e05e2f8c7c44d (diff)
downloadmariadb-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.cc30
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;