Skip to content
Permalink
Browse files

MDEV-7260: Crash in get_best_combination when executing multi-table U…

…PDATE 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.
  • Loading branch information...
sanja-byelkin committed Feb 11, 2015
1 parent cfb7d5d commit c233d6e120e20ea39dc7b9eac4cef264befc3cd0
Showing with 62 additions and 2 deletions.
  1. +13 −0 mysql-test/r/view.result
  2. +22 −0 mysql-test/t/view.test
  3. +3 −0 sql/sql_base.cc
  4. +3 −2 sql/sql_delete.cc
  5. +3 −0 sql/sql_derived.cc
  6. +18 −0 sql/table.h
@@ -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()

0 comments on commit c233d6e

Please sign in to comment.
You can’t perform that action at this time.