diff options
author | unknown <sanja@montyprogram.com> | 2012-02-14 16:52:56 +0200 |
---|---|---|
committer | unknown <sanja@montyprogram.com> | 2012-02-14 16:52:56 +0200 |
commit | 764eeeee74f999fe2107fc362236563be0025093 (patch) | |
tree | 8af3359111969a90c2670d887c5ef79262aab74f /sql | |
parent | 7ab53e80627e54c6dece486bf0b059436b7e5777 (diff) | |
download | mariadb-git-764eeeee74f999fe2107fc362236563be0025093.tar.gz |
Fix for LP BUG#910123 MariaDB 5.3.3 causes 1093 error on Drupal
Problem was that now we can merge derived table (subquery in the FROM clause).
Fix: in case of detected conflict and presence of derived table "over" the table which cased the conflict - try materialization strategy.
Diffstat (limited to 'sql')
-rw-r--r-- | sql/sql_base.cc | 22 | ||||
-rw-r--r-- | sql/sql_lex.cc | 1 | ||||
-rw-r--r-- | sql/sql_union.cc | 1 | ||||
-rw-r--r-- | sql/table.cc | 33 | ||||
-rw-r--r-- | sql/table.h | 14 |
5 files changed, 63 insertions, 8 deletions
diff --git a/sql/sql_base.cc b/sql/sql_base.cc index 9c5d251c728..11fd5db2020 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -1707,11 +1707,12 @@ TABLE_LIST* unique_table(THD *thd, TABLE_LIST *table, TABLE_LIST *table_list, t_name= table->table_name; t_alias= table->alias; +retry: DBUG_PRINT("info", ("real table: %s.%s", d_name, t_name)); - for (;;) + for (TABLE_LIST *tl= table_list;;) { - if (((! (res= find_table_in_global_list(table_list, d_name, t_name))) && - (! (res= mysql_lock_have_duplicate(thd, table, table_list)))) || + 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) && (!check_alias || !(lower_case_table_names ? my_strcasecmp(files_charset_info, t_alias, res->alias) : @@ -1724,10 +1725,23 @@ TABLE_LIST* unique_table(THD *thd, TABLE_LIST *table, TABLE_LIST *table_list, processed in derived table or top select of multi-update/multi-delete (exclude_from_table_unique_test) or prelocking placeholder. */ - table_list= res->next_global; + tl= res->next_global; DBUG_PRINT("info", ("found same copy of table or table which we should skip")); } + if (res && res->belong_to_derived) + { + /* Try to fix */ + TABLE_LIST *derived= res->belong_to_derived; + if (derived->is_merged_derived()) + { + DBUG_PRINT("info", + ("convert merged to materialization to resolve the conflict")); + derived->change_refs_to_fields(); + derived->set_materialized_derived(); + } + goto retry; + } DBUG_RETURN(res); } diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc index f29f51325a9..4a69cd3b1fa 100644 --- a/sql/sql_lex.cc +++ b/sql/sql_lex.cc @@ -2885,6 +2885,7 @@ void st_lex::cleanup_after_one_table_open() if (all_selects_list != &select_lex) { derived_tables= 0; + select_lex.exclude_from_table_unique_test= false; /* cleunup underlying units (units of VIEW) */ for (SELECT_LEX_UNIT *un= select_lex.first_inner_unit(); un; diff --git a/sql/sql_union.cc b/sql/sql_union.cc index 90d9405ebe5..599dc993483 100644 --- a/sql/sql_union.cc +++ b/sql/sql_union.cc @@ -961,6 +961,7 @@ bool st_select_lex::cleanup() } non_agg_fields.empty(); inner_refs_list.empty(); + exclude_from_table_unique_test= FALSE; DBUG_RETURN(error); } diff --git a/sql/table.cc b/sql/table.cc index f1ff353a8c4..13e643f015b 100644 --- a/sql/table.cc +++ b/sql/table.cc @@ -4378,6 +4378,36 @@ bool TABLE_LIST::prepare_security(THD *thd) DBUG_RETURN(FALSE); } +#ifndef DBUG_OFF +void TABLE_LIST::set_check_merged() +{ + DBUG_ASSERT(derived); + /* + It is not simple to check all, but at least this should be checked: + this select is not excluded or the exclusion came from above. + */ + DBUG_ASSERT(!derived->first_select()->exclude_from_table_unique_test || + derived->outer_select()-> + exclude_from_table_unique_test); +} +#endif + +void TABLE_LIST::set_check_materialized() +{ + DBUG_ASSERT(derived); + if (!derived->first_select()->exclude_from_table_unique_test) + derived->set_unique_exclude(); + else + { + /* + The subtree should be already excluded + */ + DBUG_ASSERT(!derived->first_select()->first_inner_unit() || + derived->first_select()->first_inner_unit()->first_select()-> + exclude_from_table_unique_test); + } +} + Natural_join_column::Natural_join_column(Field_translator *field_param, TABLE_LIST *tab) @@ -5919,8 +5949,9 @@ bool TABLE_LIST::init_derived(THD *thd, bool init_view) */ if (is_materialized_derived()) { - unit->master_unit()->set_unique_exclude(); + set_check_materialized(); } + /* Create field translation for mergeable derived tables/views. For derived tables field translation can be created only after diff --git a/sql/table.h b/sql/table.h index 8d91804eb06..8de71658493 100644 --- a/sql/table.h +++ b/sql/table.h @@ -1747,16 +1747,18 @@ struct TABLE_LIST inline void set_merged_derived() { derived_type= ((derived_type & DTYPE_MASK) | - DTYPE_TABLE | DTYPE_MERGE); + DTYPE_TABLE | DTYPE_MERGE); + set_check_merged(); } inline bool is_materialized_derived() { return (derived_type & DTYPE_MATERIALIZE); } - inline void set_materialized_derived() + void set_materialized_derived() { derived_type= ((derived_type & DTYPE_MASK) | - DTYPE_TABLE | DTYPE_MATERIALIZE); + DTYPE_TABLE | DTYPE_MATERIALIZE); + set_check_materialized(); } inline bool is_multitable() { @@ -1802,6 +1804,12 @@ struct TABLE_LIST private: bool prep_check_option(THD *thd, uint8 check_opt_type); bool prep_where(THD *thd, Item **conds, bool no_where_clause); + void set_check_materialized(); +#ifndef DBUG_OFF + void set_check_merged(); +#else + inline void set_check_merged() {} +#endif /* Cleanup for re-execution in a prepared statement or a stored procedure. |