summaryrefslogtreecommitdiff
path: root/sql/item_subselect.cc
diff options
context:
space:
mode:
authorunknown <konstantin@mysql.com>2004-08-21 02:02:46 +0400
committerunknown <konstantin@mysql.com>2004-08-21 02:02:46 +0400
commit095b686c09f5c143abbfb99839c1d1e2810a5a35 (patch)
tree687b98d21d388c1958d7cabd22c8c450eecca73e /sql/item_subselect.cc
parentb368cb3f6e57f7cba609088ca3ff2376bbe1b56a (diff)
downloadmariadb-git-095b686c09f5c143abbfb99839c1d1e2810a5a35.tar.gz
Fix for bug#4912 "mysqld crashs in case a statement is executed
a second time". The bug was caused by incompatibility of negations elimination algorithm and PS: during first statement execute a subtree with negation was replaced with equivalent subtree without NOTs. The problem was that although this transformation was permanent, items of the new subtree were created in execute-local memory. The patch adds means to check if it is the first execute of a prepared statement, and if this is the case, to allocate items in memory of the prepared statement. The implementation: - backports Item_arena from 5.0 - adds Item_arena::is_stmt_prepare(), Item_arena::is_first_stmt_execute(). - deletes THD::allocate_temporary_pool_for_ps_preparing(), THD::free_temporary_pool_for_ps_preparing(); they were redundant. and adds a few invariants: - thd->free_list never contains junk (= freed items) - thd->current_arena is never null. If there is no prepared statement, it points at the thd. The rest of the patch contains mainly mechanical changes and cleanups. mysql-test/r/ps.result: Test results updated (test case for Bug#4912) mysql-test/t/ps.test: A test case for Bug#4912 "mysqld crashs in case a statement is executed a second time" sql/item_cmpfunc.cc: current_statement -> current_arena sql/item_subselect.cc: Statement -> Item_arena, current_statement -> current_arena sql/item_subselect.h: Item_subselect does not need to save thd->current_statement. sql/item_sum.cc: Statement -> Item_arena sql/item_sum.h: Statement -> Item_arena sql/mysql_priv.h: Statement -> Item_arena sql/sql_base.cc: current_statement -> current_arena sql/sql_class.cc: - Item_arena - convenient set_n_backup_statement, restore_backup_statement (nice idea, Sanja) sql/sql_class.h: - Item_arena: backport from 5.0 - allocate_temporary_pool_for_ps_preparing, free_temporary_pool_for_ps_preparing removed. sql/sql_derived.cc: current_statement -> current_arena sql/sql_lex.cc: current_statement -> current_arena sql/sql_parse.cc: Deploy invariant that thd->free_list never contains junk items (backport from 5.0). sql/sql_prepare.cc: - backporting Item_arena - no need to allocate_temporary_pool_for_ps_preparing(). sql/sql_select.cc: Fix for bug#4912 "mysqld crashs in case a statement is executed a second time": if this is the first execute of a prepared statement, negation elimination is done in memory of the prepared statement. sql/sql_union.cc: Backporting Item_arena from 5.0.
Diffstat (limited to 'sql/item_subselect.cc')
-rw-r--r--sql/item_subselect.cc50
1 files changed, 26 insertions, 24 deletions
diff --git a/sql/item_subselect.cc b/sql/item_subselect.cc
index 8c4dae92ddc..68bc144d518 100644
--- a/sql/item_subselect.cc
+++ b/sql/item_subselect.cc
@@ -125,7 +125,6 @@ bool Item_subselect::fix_fields(THD *thd_param, TABLE_LIST *tables, Item **ref)
{
DBUG_ASSERT(fixed == 0);
engine->set_thd((thd= thd_param));
- stmt= thd->current_statement;
char const *save_where= thd->where;
int res;
@@ -306,7 +305,10 @@ Item_singlerow_subselect::select_transformer(JOIN *join)
return RES_OK;
SELECT_LEX *select_lex= join->select_lex;
- Statement backup;
+
+ /* Juggle with current arena only if we're in prepared statement prepare */
+ Item_arena *arena= join->thd->current_arena;
+ Item_arena backup;
if (!select_lex->master_unit()->first_select()->next_select() &&
!select_lex->table_list.elements &&
@@ -341,8 +343,8 @@ Item_singlerow_subselect::select_transformer(JOIN *join)
if (join->conds || join->having)
{
Item *cond;
- if (stmt)
- thd->set_n_backup_item_arena(stmt, &backup);
+ if (arena->is_stmt_prepare())
+ thd->set_n_backup_item_arena(arena, &backup);
if (!join->having)
cond= join->conds;
@@ -355,15 +357,15 @@ Item_singlerow_subselect::select_transformer(JOIN *join)
new Item_null())))
goto err;
}
- if (stmt)
- thd->restore_backup_item_arena(stmt, &backup);
+ if (arena->is_stmt_prepare())
+ thd->restore_backup_item_arena(arena, &backup);
return RES_REDUCE;
}
return RES_OK;
err:
- if (stmt)
- thd->restore_backup_item_arena(stmt, &backup);
+ if (arena->is_stmt_prepare())
+ thd->restore_backup_item_arena(arena, &backup);
return RES_ERROR;
}
@@ -640,11 +642,11 @@ Item_in_subselect::single_value_transformer(JOIN *join,
}
SELECT_LEX *select_lex= join->select_lex;
- Statement backup;
+ Item_arena *arena= join->thd->current_arena, backup;
thd->where= "scalar IN/ALL/ANY subquery";
- if (stmt)
- thd->set_n_backup_item_arena(stmt, &backup);
+ if (arena->is_stmt_prepare())
+ thd->set_n_backup_item_arena(arena, &backup);
if (select_lex->item_list.elements > 1)
{
@@ -857,21 +859,21 @@ Item_in_subselect::single_value_transformer(JOIN *join,
push_warning(thd, MYSQL_ERROR::WARN_LEVEL_NOTE,
ER_SELECT_REDUCED, warn_buff);
}
- if (stmt)
- thd->restore_backup_item_arena(stmt, &backup);
+ if (arena->is_stmt_prepare())
+ thd->restore_backup_item_arena(arena, &backup);
DBUG_RETURN(RES_REDUCE);
}
}
}
ok:
- if (stmt)
- thd->restore_backup_item_arena(stmt, &backup);
+ if (arena->is_stmt_prepare())
+ thd->restore_backup_item_arena(arena, &backup);
DBUG_RETURN(RES_OK);
err:
- if (stmt)
- thd->restore_backup_item_arena(stmt, &backup);
+ if (arena->is_stmt_prepare())
+ thd->restore_backup_item_arena(arena, &backup);
DBUG_RETURN(RES_ERROR);
}
@@ -885,12 +887,12 @@ Item_in_subselect::row_value_transformer(JOIN *join)
{
DBUG_RETURN(RES_OK);
}
- Statement backup;
+ Item_arena *arena= join->thd->current_arena, backup;
Item *item= 0;
thd->where= "row IN/ALL/ANY subquery";
- if (stmt)
- thd->set_n_backup_item_arena(stmt, &backup);
+ if (arena->is_stmt_prepare())
+ thd->set_n_backup_item_arena(arena, &backup);
SELECT_LEX *select_lex= join->select_lex;
@@ -974,13 +976,13 @@ Item_in_subselect::row_value_transformer(JOIN *join)
if (join->conds->fix_fields(thd, join->tables_list, 0))
goto err;
}
- if (stmt)
- thd->restore_backup_item_arena(stmt, &backup);
+ if (arena->is_stmt_prepare())
+ thd->restore_backup_item_arena(arena, &backup);
DBUG_RETURN(RES_OK);
err:
- if (stmt)
- thd->restore_backup_item_arena(stmt, &backup);
+ if (arena->is_stmt_prepare())
+ thd->restore_backup_item_arena(arena, &backup);
DBUG_RETURN(RES_ERROR);
}