Commit c233d6e1 authored by unknown's avatar unknown

MDEV-7260: Crash in get_best_combination when executing multi-table UPDATE with nested views

Do not use merge_for_insert for commands which use SELECT because optimizer can't work with such tables.

Fixes which makes multi-delete working with normally merged views.
parent cfb7d5d7
......@@ -5398,6 +5398,19 @@ DROP VIEW v1;
DROP TABLE t1, t2;
create view v1 as select 1;
drop view v1;
#
# MDEV-7260: Crash in get_best_combination when executing multi-table
# UPDATE with nested views
#
CREATE TABLE `t1` (`id` bigint(20));
INSERT INTO `t1` VALUES (1),(2);
CREATE TABLE `t2` (`id` bigint(20));
CREATE TABLE `t3` (`id` bigint(20), `flag` tinyint(4));
create view v1 as select id from t1;
create view v2 as select t2.* from (t2 left join v1 using (id));
update t3 left join v2 using (id) set flag=flag+1;
drop view v2, v1;
drop table t1, t2, t3;
# -----------------------------------------------------------------
# -- End of 5.5 tests.
# -----------------------------------------------------------------
......
......@@ -5345,6 +5345,28 @@ create view v1 as select 1;
drop view v1;
--echo #
--echo # MDEV-7260: Crash in get_best_combination when executing multi-table
--echo # UPDATE with nested views
--echo #
CREATE TABLE `t1` (`id` bigint(20));
INSERT INTO `t1` VALUES (1),(2);
CREATE TABLE `t2` (`id` bigint(20));
CREATE TABLE `t3` (`id` bigint(20), `flag` tinyint(4));
create view v1 as select id from t1;
create view v2 as select t2.* from (t2 left join v1 using (id));
update t3 left join v2 using (id) set flag=flag+1;
drop view v2, v1;
drop table t1, t2, t3;
--echo # -----------------------------------------------------------------
--echo # -- End of 5.5 tests.
--echo # -----------------------------------------------------------------
......
......@@ -2028,6 +2028,9 @@ unique_table(THD *thd, TABLE_LIST *table, TABLE_LIST *table_list,
bool check_alias)
{
TABLE_LIST *dup;
table= table->find_table_for_update();
if (table->table && table->table->file->ht->db_type == DB_TYPE_MRG_MYISAM)
{
TABLE_LIST *child;
......
......@@ -657,9 +657,10 @@ multi_delete::initialize_tables(JOIN *join)
delete_while_scanning= 1;
for (walk= delete_tables; walk; walk= walk->next_local)
{
tables_to_delete_from|= walk->table->map;
TABLE_LIST *tbl= walk->correspondent_table->find_table_for_update();
tables_to_delete_from|= tbl->table->map;
if (delete_while_scanning &&
unique_table(thd, walk, join->tables_list, false))
unique_table(thd, tbl, join->tables_list, false))
{
/*
If the table we are going to delete from appears
......
......@@ -507,6 +507,9 @@ bool mysql_derived_merge_for_insert(THD *thd, LEX *lex, TABLE_LIST *derived)
DBUG_RETURN(FALSE);
if (derived->is_materialized_derived())
DBUG_RETURN(mysql_derived_prepare(thd, lex, derived));
if ((thd->lex->sql_command == SQLCOM_UPDATE_MULTI ||
thd->lex->sql_command == SQLCOM_DELETE_MULTI))
DBUG_RETURN(FALSE);
if (!derived->is_multitable())
{
if (!derived->single_table_updatable())
......
......@@ -1984,6 +1984,24 @@ struct TABLE_LIST
TABLE_LIST *find_underlying_table(TABLE *table);
TABLE_LIST *first_leaf_for_name_resolution();
TABLE_LIST *last_leaf_for_name_resolution();
/**
@brief
Find the bottom in the chain of embedded table VIEWs.
@detail
This is used for single-table UPDATE/DELETE when they are modifying a
single-table VIEW.
*/
TABLE_LIST *find_table_for_update()
{
TABLE_LIST *tbl= this;
while(!tbl->is_multitable() && tbl->single_table_updatable() &&
tbl->merge_underlying_list)
{
tbl= tbl->merge_underlying_list;
}
return tbl;
}
TABLE *get_real_join_table();
bool is_leaf_for_name_resolution();
inline TABLE_LIST *top_table()
......
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