diff --git a/mysql-test/r/derived.result b/mysql-test/r/derived.result index 3ad9d99651a..dcf54d55886 100644 --- a/mysql-test/r/derived.result +++ b/mysql-test/r/derived.result @@ -479,5 +479,27 @@ SELECT * FROM WHERE tmp.a; a b 100 200 +# +# MDEV-5356: Server crashes in Item_equal::contains on 2nd +# execution of a PS +# +CREATE TABLE t1 (a INT, b INT); +INSERT INTO t1 VALUES (1,2),(3,4); +CREATE TABLE t2 (c INT); +INSERT INTO t2 VALUES (5),(6); +CREATE TABLE t3 (d INT); +INSERT INTO t3 VALUES (7),(8); +CREATE PROCEDURE pr() +UPDATE t3, +(SELECT c FROM +(SELECT 1 FROM t1 WHERE a=72 AND NOT b) sq, +t2 +) sq2 +SET d=sq2.c; +CALL pr(); +CALL pr(); +CALL pr(); +drop procedure pr; +drop table t1,t2,t3; # End of 5.3 tests set optimizer_switch=@save_derived_optimizer_switch; diff --git a/mysql-test/t/derived.test b/mysql-test/t/derived.test index 4f6b8443055..c2921cd6b03 100644 --- a/mysql-test/t/derived.test +++ b/mysql-test/t/derived.test @@ -394,6 +394,35 @@ WHERE tmp.b; SELECT * FROM ( SELECT 100 a, subsel.b FROM ( SELECT 200 b ) subsel ) tmp WHERE tmp.a; + +--echo # +--echo # MDEV-5356: Server crashes in Item_equal::contains on 2nd +--echo # execution of a PS +--echo # +CREATE TABLE t1 (a INT, b INT); +INSERT INTO t1 VALUES (1,2),(3,4); + +CREATE TABLE t2 (c INT); +INSERT INTO t2 VALUES (5),(6); + +CREATE TABLE t3 (d INT); +INSERT INTO t3 VALUES (7),(8); + +CREATE PROCEDURE pr() + UPDATE t3, + (SELECT c FROM + (SELECT 1 FROM t1 WHERE a=72 AND NOT b) sq, + t2 + ) sq2 + SET d=sq2.c; + +CALL pr(); +CALL pr(); +CALL pr(); + +drop procedure pr; +drop table t1,t2,t3; + --echo # End of 5.3 tests set optimizer_switch=@save_derived_optimizer_switch; diff --git a/sql/sql_base.cc b/sql/sql_base.cc index 3eeb8afef6b..4e8847d1fe0 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -8050,12 +8050,9 @@ bool setup_tables(THD *thd, Name_resolution_context *context, if (table_list->merge_underlying_list) { DBUG_ASSERT(table_list->is_merged_derived()); - Query_arena *arena= thd->stmt_arena, backup; + Query_arena *arena, backup; + arena= thd->activate_stmt_arena_if_needed(&backup); bool res; - if (arena->is_conventional()) - arena= 0; // For easier test - else - thd->set_n_backup_active_arena(arena, &backup); res= table_list->setup_underlying(thd); if (arena) thd->restore_active_arena(arena, &backup); @@ -8434,11 +8431,8 @@ void wrap_ident(THD *thd, Item **conds) { Item_direct_ref_to_ident *wrapper; DBUG_ASSERT((*conds)->type() == Item::FIELD_ITEM || (*conds)->type() == Item::REF_ITEM); - Query_arena *arena= thd->stmt_arena, backup; - if (arena->is_conventional()) - arena= 0; - else - thd->set_n_backup_active_arena(arena, &backup); + Query_arena *arena, backup; + arena= thd->activate_stmt_arena_if_needed(&backup); if ((wrapper= new Item_direct_ref_to_ident((Item_ident *)(*conds)))) (*conds)= (Item*) wrapper; if (arena) diff --git a/sql/sql_derived.cc b/sql/sql_derived.cc index 5227ec2d958..f336d8f6b62 100644 --- a/sql/sql_derived.cc +++ b/sql/sql_derived.cc @@ -614,11 +614,8 @@ bool mysql_derived_prepare(THD *thd, LEX *lex, TABLE_LIST *derived) thd->lex->sql_command == SQLCOM_DELETE_MULTI)))) DBUG_RETURN(FALSE); - Query_arena *arena= thd->stmt_arena, backup; - if (arena->is_conventional()) - arena= 0; // For easier test - else - thd->set_n_backup_active_arena(arena, &backup); + Query_arena *arena, backup; + arena= thd->activate_stmt_arena_if_needed(&backup); SELECT_LEX *first_select= unit->first_select(); diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc index ccc51e39785..48d1254b418 100644 --- a/sql/sql_lex.cc +++ b/sql/sql_lex.cc @@ -3679,11 +3679,8 @@ void SELECT_LEX::mark_const_derived(bool empty) bool st_select_lex::save_leaf_tables(THD *thd) { - Query_arena *arena= thd->stmt_arena, backup; - if (arena->is_conventional()) - arena= 0; - else - thd->set_n_backup_active_arena(arena, &backup); + Query_arena *arena, backup; + arena= thd->activate_stmt_arena_if_needed(&backup); List_iterator_fast li(leaf_tables); TABLE_LIST *table; @@ -3711,10 +3708,7 @@ bool st_select_lex::save_prep_leaf_tables(THD *thd) return 0; Query_arena *arena= thd->stmt_arena, backup; - if (arena->is_conventional()) - arena= 0; - else - thd->set_n_backup_active_arena(arena, &backup); + arena= thd->activate_stmt_arena_if_needed(&backup); List_iterator_fast li(leaf_tables); TABLE_LIST *table; diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 28c2b86ffdf..289b75b5804 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -1000,11 +1000,8 @@ JOIN::optimize() MEMROOT for prepared statements and stored procedures. */ - Query_arena *arena= thd->stmt_arena, backup; - if (arena->is_conventional()) - arena= 0; // For easier test - else - thd->set_n_backup_active_arena(arena, &backup); + Query_arena *arena, backup; + arena= thd->activate_stmt_arena_if_needed(&backup); sel->first_cond_optimization= 0; diff --git a/sql/sql_view.cc b/sql/sql_view.cc index 2c9227b46f7..22c1ddb326d 100644 --- a/sql/sql_view.cc +++ b/sql/sql_view.cc @@ -1121,11 +1121,7 @@ bool mysql_make_view(THD *thd, File_parser *parser, TABLE_LIST *table, will be TRUE as far as we make new table cache). */ old_lex= thd->lex; - arena= thd->stmt_arena; - if (arena->is_conventional()) - arena= 0; - else - thd->set_n_backup_active_arena(arena, &backup); + arena= thd->activate_stmt_arena_if_needed(&backup); /* init timestamp */ if (!table->timestamp.str) diff --git a/sql/table.cc b/sql/table.cc index 066eb506835..aa5f11bbe30 100644 --- a/sql/table.cc +++ b/sql/table.cc @@ -3560,7 +3560,7 @@ bool TABLE_LIST::create_field_translation(THD *thd) SELECT_LEX *select= get_single_select(); List_iterator_fast it(select->item_list); uint field_count= 0; - Query_arena *arena= thd->stmt_arena, backup; + Query_arena *arena, backup; bool res= FALSE; if (thd->stmt_arena->is_conventional() || @@ -3598,10 +3598,7 @@ bool TABLE_LIST::create_field_translation(THD *thd) return FALSE; } - if (arena->is_conventional()) - arena= 0; // For easier test - else - thd->set_n_backup_active_arena(arena, &backup); + arena= thd->activate_stmt_arena_if_needed(&backup); /* Create view fields translation table */