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;
|
DROP TABLE t1, t2;
|
||||||
create view v1 as select 1;
|
create view v1 as select 1;
|
||||||
drop view v1;
|
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.
|
# -- End of 5.5 tests.
|
||||||
# -----------------------------------------------------------------
|
# -----------------------------------------------------------------
|
||||||
|
@ -5345,6 +5345,28 @@ create view v1 as select 1;
|
|||||||
|
|
||||||
drop view v1;
|
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 # -----------------------------------------------------------------
|
||||||
--echo # -- End of 5.5 tests.
|
--echo # -- End of 5.5 tests.
|
||||||
--echo # -----------------------------------------------------------------
|
--echo # -----------------------------------------------------------------
|
||||||
|
@ -2028,6 +2028,9 @@ unique_table(THD *thd, TABLE_LIST *table, TABLE_LIST *table_list,
|
|||||||
bool check_alias)
|
bool check_alias)
|
||||||
{
|
{
|
||||||
TABLE_LIST *dup;
|
TABLE_LIST *dup;
|
||||||
|
|
||||||
|
table= table->find_table_for_update();
|
||||||
|
|
||||||
if (table->table && table->table->file->ht->db_type == DB_TYPE_MRG_MYISAM)
|
if (table->table && table->table->file->ht->db_type == DB_TYPE_MRG_MYISAM)
|
||||||
{
|
{
|
||||||
TABLE_LIST *child;
|
TABLE_LIST *child;
|
||||||
|
@ -657,9 +657,10 @@ multi_delete::initialize_tables(JOIN *join)
|
|||||||
delete_while_scanning= 1;
|
delete_while_scanning= 1;
|
||||||
for (walk= delete_tables; walk; walk= walk->next_local)
|
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 &&
|
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
|
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);
|
DBUG_RETURN(FALSE);
|
||||||
if (derived->is_materialized_derived())
|
if (derived->is_materialized_derived())
|
||||||
DBUG_RETURN(mysql_derived_prepare(thd, lex, 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->is_multitable())
|
||||||
{
|
{
|
||||||
if (!derived->single_table_updatable())
|
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 *find_underlying_table(TABLE *table);
|
||||||
TABLE_LIST *first_leaf_for_name_resolution();
|
TABLE_LIST *first_leaf_for_name_resolution();
|
||||||
TABLE_LIST *last_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();
|
TABLE *get_real_join_table();
|
||||||
bool is_leaf_for_name_resolution();
|
bool is_leaf_for_name_resolution();
|
||||||
inline TABLE_LIST *top_table()
|
inline TABLE_LIST *top_table()
|
||||||
|
Loading…
x
Reference in New Issue
Block a user