diff options
-rw-r--r-- | mysql-test/r/derived_view.result | 40 | ||||
-rw-r--r-- | mysql-test/t/derived_view.test | 27 | ||||
-rw-r--r-- | sql/sql_base.cc | 11 | ||||
-rw-r--r-- | sql/sql_derived.cc | 50 | ||||
-rw-r--r-- | sql/table.h | 4 |
5 files changed, 112 insertions, 20 deletions
diff --git a/mysql-test/r/derived_view.result b/mysql-test/r/derived_view.result index acce2afb124..e958bfbdca4 100644 --- a/mysql-test/r/derived_view.result +++ b/mysql-test/r/derived_view.result @@ -2356,6 +2356,46 @@ id select_type table type possible_keys key key_len ref rows Extra 3 DEPENDENT SUBQUERY pi ref gallery_id gallery_id 4 test.gal.id 4 Using temporary; Using filesort drop table galleries, pictures; # +# MDEV-5740: Assertion +#`!derived->first_select()->exclude_from_table_unique_test || +#derived->outer_select()-> exclude_from_table_unique_test' +#failed on 2nd execution of PS with derived_merge +# +set @save_optimizer_switch5740=@@optimizer_switch; +SET optimizer_switch = 'derived_merge=on'; +CREATE TABLE t1 (a INT); +INSERT INTO t1 VALUES (1),(2); +CREATE TABLE t2 (b INT); +INSERT INTO t2 VALUES (3),(4); +PREPARE stmt FROM ' + INSERT INTO t1 SELECT * FROM t2 UNION SELECT * FROM (SELECT * FROM t1) AS sq +'; +EXECUTE stmt; +select * from t1; +a +1 +2 +3 +4 +1 +2 +EXECUTE stmt; +select * from t1; +a +1 +2 +3 +4 +1 +2 +3 +4 +1 +2 +deallocate prepare stmt; +drop table t1,t2; +set optimizer_switch=@save_optimizer_switch5740; +# # end of 5.3 tests # set optimizer_switch=@exit_optimizer_switch; diff --git a/mysql-test/t/derived_view.test b/mysql-test/t/derived_view.test index 61e11cebad4..de08b1c4d0d 100644 --- a/mysql-test/t/derived_view.test +++ b/mysql-test/t/derived_view.test @@ -1704,6 +1704,33 @@ ORDER BY gallery_name ASC drop table galleries, pictures; --echo # +--echo # MDEV-5740: Assertion +--echo #`!derived->first_select()->exclude_from_table_unique_test || +--echo #derived->outer_select()-> exclude_from_table_unique_test' +--echo #failed on 2nd execution of PS with derived_merge +--echo # + +set @save_optimizer_switch5740=@@optimizer_switch; +SET optimizer_switch = 'derived_merge=on'; + +CREATE TABLE t1 (a INT); +INSERT INTO t1 VALUES (1),(2); +CREATE TABLE t2 (b INT); +INSERT INTO t2 VALUES (3),(4); + +PREPARE stmt FROM ' + INSERT INTO t1 SELECT * FROM t2 UNION SELECT * FROM (SELECT * FROM t1) AS sq +'; +EXECUTE stmt; +select * from t1; +EXECUTE stmt; +select * from t1; +deallocate prepare stmt; + +drop table t1,t2; +set optimizer_switch=@save_optimizer_switch5740; + +--echo # --echo # end of 5.3 tests --echo # diff --git a/sql/sql_base.cc b/sql/sql_base.cc index 4e8847d1fe0..9d3a59afa0b 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -1735,6 +1735,17 @@ retry: DBUG_PRINT("info", ("real table: %s.%s", d_name, t_name)); for (TABLE_LIST *tl= table_list;;) { + if (tl && + tl->select_lex && tl->select_lex->master_unit() && + tl->select_lex->master_unit()->executed) + { + /* + There is no sense to check tables of already executed parts + of the query + */ + tl= tl->next_global; + continue; + } if (((! (res= find_table_in_global_list(tl, d_name, t_name))) && (! (res= mysql_lock_have_duplicate(thd, table, tl)))) || ((!res->table || res->table != table->table) && diff --git a/sql/sql_derived.cc b/sql/sql_derived.cc index 3243f0a0eff..83df1ddf59d 100644 --- a/sql/sql_derived.cc +++ b/sql/sql_derived.cc @@ -64,8 +64,10 @@ mysql_handle_derived(LEX *lex, uint phases) { bool res= FALSE; THD *thd= lex->thd; + DBUG_ENTER("mysql_handle_derived"); + DBUG_PRINT("enter", ("phases: 0x%x", phases)); if (!lex->derived_tables) - return FALSE; + DBUG_RETURN(FALSE); lex->thd->derived_tables_processing= TRUE; @@ -123,7 +125,7 @@ mysql_handle_derived(LEX *lex, uint phases) } } lex->thd->derived_tables_processing= FALSE; - return res; + DBUG_RETURN(res); } /* @@ -163,8 +165,10 @@ mysql_handle_single_derived(LEX *lex, TABLE_LIST *derived, uint phases) THD *thd= lex->thd; uint8 allowed_phases= (derived->is_merged_derived() ? DT_PHASES_MERGE : DT_PHASES_MATERIALIZE); + DBUG_ENTER("mysql_handle_single_derived"); + DBUG_PRINT("enter", ("phases: 0x%x allowed: 0x%x", phases, allowed_phases)); if (!lex->derived_tables) - return FALSE; + DBUG_RETURN(FALSE); lex->thd->derived_tables_processing= TRUE; @@ -186,7 +190,7 @@ mysql_handle_single_derived(LEX *lex, TABLE_LIST *derived, uint phases) break; } lex->thd->derived_tables_processing= FALSE; - return res; + DBUG_RETURN(res); } @@ -353,16 +357,17 @@ bool mysql_derived_merge(THD *thd, LEX *lex, TABLE_LIST *derived) uint tablenr; SELECT_LEX *parent_lex= derived->select_lex; Query_arena *arena, backup; + DBUG_ENTER("mysql_derived_merge"); if (derived->merged) - return FALSE; + DBUG_RETURN(FALSE); if (dt_select->uncacheable & UNCACHEABLE_RAND) { /* There is random function => fall back to materialization. */ derived->change_refs_to_fields(); derived->set_materialized_derived(); - return FALSE; + DBUG_RETURN(FALSE); } if (thd->lex->sql_command == SQLCOM_UPDATE_MULTI || @@ -466,7 +471,7 @@ bool mysql_derived_merge(THD *thd, LEX *lex, TABLE_LIST *derived) exit_merge: if (arena) thd->restore_active_arena(arena, &backup); - return res; + DBUG_RETURN(res); } @@ -492,14 +497,15 @@ exit_merge: bool mysql_derived_merge_for_insert(THD *thd, LEX *lex, TABLE_LIST *derived) { + DBUG_ENTER("mysql_derived_merge_for_insert"); if (derived->merged_for_insert) - return FALSE; + DBUG_RETURN(FALSE); if (derived->is_materialized_derived()) - return mysql_derived_prepare(thd, lex, derived); + DBUG_RETURN(mysql_derived_prepare(thd, lex, derived)); if (!derived->is_multitable()) { if (!derived->single_table_updatable()) - return derived->create_field_translation(thd); + DBUG_RETURN(derived->create_field_translation(thd)); if (derived->merge_underlying_list) { derived->table= derived->merge_underlying_list->table; @@ -507,7 +513,7 @@ bool mysql_derived_merge_for_insert(THD *thd, LEX *lex, TABLE_LIST *derived) derived->merged_for_insert= TRUE; } } - return FALSE; + DBUG_RETURN(FALSE); } @@ -764,9 +770,10 @@ bool mysql_derived_optimize(THD *thd, LEX *lex, TABLE_LIST *derived) SELECT_LEX *save_current_select= lex->current_select; bool res= FALSE; + DBUG_ENTER("mysql_derived_optimize"); if (unit->optimized) - return FALSE; + DBUG_RETURN(FALSE); lex->current_select= first_select; if (unit->is_union()) @@ -806,7 +813,7 @@ bool mysql_derived_optimize(THD *thd, LEX *lex, TABLE_LIST *derived) } err: lex->current_select= save_current_select; - return res; + DBUG_RETURN(res); } @@ -829,11 +836,12 @@ err: bool mysql_derived_create(THD *thd, LEX *lex, TABLE_LIST *derived) { + DBUG_ENTER("mysql_derived_create"); TABLE *table= derived->table; SELECT_LEX_UNIT *unit= derived->get_unit(); if (table->created) - return FALSE; + DBUG_RETURN(FALSE); select_union *result= (select_union*)unit->result; if (table->s->db_type() == TMP_ENGINE_HTON) { @@ -843,13 +851,13 @@ bool mysql_derived_create(THD *thd, LEX *lex, TABLE_LIST *derived) &result->tmp_table_param.recinfo, (unit->first_select()->options | thd->options | TMP_TABLE_ALL_COLUMNS))) - return(TRUE); + DBUG_RETURN(TRUE); } if (open_tmp_table(table)) - return TRUE; + DBUG_RETURN(TRUE); table->file->extra(HA_EXTRA_WRITE_CACHE); table->file->extra(HA_EXTRA_IGNORE_DUP_KEY); - return FALSE; + DBUG_RETURN(FALSE); } @@ -879,11 +887,12 @@ bool mysql_derived_create(THD *thd, LEX *lex, TABLE_LIST *derived) bool mysql_derived_fill(THD *thd, LEX *lex, TABLE_LIST *derived) { + DBUG_ENTER("mysql_derived_fill"); SELECT_LEX_UNIT *unit= derived->get_unit(); bool res= FALSE; if (unit->executed && !unit->uncacheable && !unit->describe) - return FALSE; + DBUG_RETURN(FALSE); /*check that table creation passed without problems. */ DBUG_ASSERT(derived->table && derived->table->created); SELECT_LEX *first_select= unit->first_select(); @@ -925,7 +934,7 @@ bool mysql_derived_fill(THD *thd, LEX *lex, TABLE_LIST *derived) unit->cleanup(); lex->current_select= save_current_select; - return res; + DBUG_RETURN(res); } @@ -949,6 +958,7 @@ bool mysql_derived_fill(THD *thd, LEX *lex, TABLE_LIST *derived) bool mysql_derived_reinit(THD *thd, LEX *lex, TABLE_LIST *derived) { + DBUG_ENTER("mysql_derived_reinit"); st_select_lex_unit *unit= derived->get_unit(); if (derived->table) @@ -958,5 +968,5 @@ bool mysql_derived_reinit(THD *thd, LEX *lex, TABLE_LIST *derived) /* for derived tables & PS (which can't be reset by Item_subquery) */ unit->reinit_exec_mechanism(); unit->set_thd(thd); - return FALSE; + DBUG_RETURN(FALSE); } diff --git a/sql/table.h b/sql/table.h index c3524ad3adf..30495e4d76f 100644 --- a/sql/table.h +++ b/sql/table.h @@ -1791,9 +1791,11 @@ struct TABLE_LIST } inline void set_merged_derived() { + DBUG_ENTER("set_merged_derived"); derived_type= ((derived_type & DTYPE_MASK) | DTYPE_TABLE | DTYPE_MERGE); set_check_merged(); + DBUG_VOID_RETURN; } inline bool is_materialized_derived() { @@ -1801,9 +1803,11 @@ struct TABLE_LIST } void set_materialized_derived() { + DBUG_ENTER("set_materialized_derived"); derived_type= ((derived_type & DTYPE_MASK) | DTYPE_TABLE | DTYPE_MATERIALIZE); set_check_materialized(); + DBUG_VOID_RETURN; } inline bool is_multitable() { |