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.
This commit is contained in:
parent
cfb7d5d78a
commit
c233d6e120
@ -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())
|
||||
|
18
sql/table.h
18
sql/table.h
@ -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()
|
||||
|
Loading…
x
Reference in New Issue
Block a user