summaryrefslogtreecommitdiff
path: root/sql
diff options
context:
space:
mode:
authorunknown <sanja@montyprogram.com>2012-02-14 16:52:56 +0200
committerunknown <sanja@montyprogram.com>2012-02-14 16:52:56 +0200
commit764eeeee74f999fe2107fc362236563be0025093 (patch)
tree8af3359111969a90c2670d887c5ef79262aab74f /sql
parent7ab53e80627e54c6dece486bf0b059436b7e5777 (diff)
downloadmariadb-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.cc22
-rw-r--r--sql/sql_lex.cc1
-rw-r--r--sql/sql_union.cc1
-rw-r--r--sql/table.cc33
-rw-r--r--sql/table.h14
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.