Commit 764eeeee authored by unknown's avatar unknown

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.
parent 7ab53e80
......@@ -273,4 +273,13 @@ ON alias3.f4 != 0
) ON alias3.f4 != 0;
f4 f4 f2 f4
drop table t1,t2,t3,t4;
#
# LP BUG#910123 MariaDB 5.3.3 causes 1093 error on Drupal
# Fix: force materialization in case of conflict
#
SET optimizer_switch='derived_merge=on';
CREATE TABLE t1 ( i INT );
INSERT INTO t1 VALUES ( (SELECT 1 FROM ( SELECT * FROM t1 ) as a) );
drop table t1;
set optimizer_switch=@save_optimizer_switch;
set optimizer_switch=@exit_optimizer_switch;
......@@ -202,5 +202,15 @@ RIGHT JOIN (
drop table t1,t2,t3,t4;
--echo #
--echo # LP BUG#910123 MariaDB 5.3.3 causes 1093 error on Drupal
--echo # Fix: force materialization in case of conflict
--echo #
SET optimizer_switch='derived_merge=on';
CREATE TABLE t1 ( i INT );
INSERT INTO t1 VALUES ( (SELECT 1 FROM ( SELECT * FROM t1 ) as a) );
drop table t1;
set optimizer_switch=@save_optimizer_switch;
# The following command must be the last one the file
set optimizer_switch=@exit_optimizer_switch;
......@@ -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);
}
......
......@@ -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;
......
......@@ -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);
}
......
......@@ -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
......
......@@ -1748,15 +1748,17 @@ struct TABLE_LIST
{
derived_type= ((derived_type & DTYPE_MASK) |
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);
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.
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment