From ef295c31e3d50a99a90beccfb4deb9d9d36ac1e3 Mon Sep 17 00:00:00 2001 From: Monty Date: Wed, 16 May 2018 21:51:46 +0300 Subject: MDEV-11129 CREATE OR REPLACE TABLE t1 AS SELECT spfunc() crashes if spfunc() references t1 Fixed by extending unique_table() with a flag to not allow usage of the replaced table. I also cleaned up find_dup_table() to not use goto next. I also added more comments to the code in find_dup_table() --- sql/sql_base.cc | 46 ++++++++++++++++++++++++++++------------------ 1 file changed, 28 insertions(+), 18 deletions(-) (limited to 'sql/sql_base.cc') diff --git a/sql/sql_base.cc b/sql/sql_base.cc index 554c8cffeaf..bdde123f18c 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -1278,7 +1278,8 @@ TABLE_LIST *find_table_in_list(TABLE_LIST *table, @param thd thread handle @param table table which should be checked @param table_list list of tables - @param check_alias whether to check tables' aliases + @param check_flag whether to check tables' aliases + Currently this is only used by INSERT NOTE: to exclude derived tables from check we use following mechanism: a) during derived table processing set THD::derived_tables_processing @@ -1307,9 +1308,9 @@ TABLE_LIST *find_table_in_list(TABLE_LIST *table, static TABLE_LIST* find_dup_table(THD *thd, TABLE_LIST *table, TABLE_LIST *table_list, - bool check_alias) + uint check_flag) { - TABLE_LIST *res; + TABLE_LIST *res= 0; const char *d_name, *t_name, *t_alias; DBUG_ENTER("find_dup_table"); DBUG_PRINT("enter", ("table alias: %s", table->alias)); @@ -1345,17 +1346,15 @@ TABLE_LIST* find_dup_table(THD *thd, TABLE_LIST *table, TABLE_LIST *table_list, retry: DBUG_PRINT("info", ("real table: %s.%s", d_name, t_name)); - for (TABLE_LIST *tl= table_list;;) + for (TABLE_LIST *tl= table_list; tl ; tl= tl->next_global, res= 0) { - if (tl && - tl->select_lex && tl->select_lex->master_unit() && + if (tl->select_lex && tl->select_lex->master_unit() && tl->select_lex->master_unit()->executed) { /* There is no sense to check tables of already executed parts of the query */ - tl= tl->next_global; continue; } /* @@ -1364,21 +1363,29 @@ retry: */ if (! (res= find_table_in_global_list(tl, d_name, t_name))) break; + tl= res; // We can continue search after this table /* Skip if same underlying table. */ if (res->table && (res->table == table->table)) - goto next; + continue; + + if (check_flag & CHECK_DUP_FOR_CREATE) + DBUG_RETURN(res); /* Skip if table alias does not match. */ - if (check_alias) + if (check_flag & CHECK_DUP_FOR_CREATE) { if (my_strcasecmp(table_alias_charset, t_alias, res->alias)) - goto next; + continue; } /* - Skip if marked to be excluded (could be a derived table) or if - entry is a prelocking placeholder. + If table is not excluded (could be a derived table) and table is not + a prelocking placeholder then we found either a duplicate entry + or a table that is part of a derived table (handled below). + Examples are: + INSERT INTO t1 SELECT * FROM t1; + INSERT INTO t1 SELECT * FROM view_containing_t1; */ if (res->select_lex && !res->select_lex->exclude_from_table_unique_test && @@ -1390,14 +1397,17 @@ retry: processed in derived table or top select of multi-update/multi-delete (exclude_from_table_unique_test) or prelocking placeholder. */ -next: - 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 */ + /* + We come here for queries of type: + INSERT INTO t1 (SELECT tmp.a FROM (select * FROM t1) as tmp); + + Try to fix by materializing the derived table + */ TABLE_LIST *derived= res->belong_to_derived; if (derived->is_merged_derived()) { @@ -1429,7 +1439,7 @@ next: TABLE_LIST* unique_table(THD *thd, TABLE_LIST *table, TABLE_LIST *table_list, - bool check_alias) + uint check_flag) { TABLE_LIST *dup; @@ -1443,12 +1453,12 @@ unique_table(THD *thd, TABLE_LIST *table, TABLE_LIST *table_list, for (child= table->next_global; child && child->parent_l == table; child= child->next_global) { - if ((dup= find_dup_table(thd, child, child->next_global, check_alias))) + if ((dup= find_dup_table(thd, child, child->next_global, check_flag))) break; } } else - dup= find_dup_table(thd, table, table_list, check_alias); + dup= find_dup_table(thd, table, table_list, check_flag); return dup; } /* -- cgit v1.2.1 From cf5226174bcb41611e9650ac04104a9b16f368be Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Sat, 19 May 2018 15:34:17 +0200 Subject: MDEV-11129 CREATE OR REPLACE TABLE t1 AS SELECT spfunc() crashes if spfunc() references t1 fix a typo that broke the main.view test followup for ef295c31e3d --- sql/sql_base.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'sql/sql_base.cc') diff --git a/sql/sql_base.cc b/sql/sql_base.cc index bdde123f18c..dc61f396605 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -1373,7 +1373,7 @@ retry: DBUG_RETURN(res); /* Skip if table alias does not match. */ - if (check_flag & CHECK_DUP_FOR_CREATE) + if (check_flag & CHECK_DUP_ALLOW_DIFFERENT_ALIAS) { if (my_strcasecmp(table_alias_charset, t_alias, res->alias)) continue; -- cgit v1.2.1