diff options
Diffstat (limited to 'sql/sql_base.cc')
-rw-r--r-- | sql/sql_base.cc | 46 |
1 files changed, 28 insertions, 18 deletions
diff --git a/sql/sql_base.cc b/sql/sql_base.cc index 8472117510b..d671bb4ccc0 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -1322,7 +1322,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 @@ -1351,9 +1352,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)); @@ -1389,17 +1390,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; } /* @@ -1408,21 +1407,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_ALLOW_DIFFERENT_ALIAS) { 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 && @@ -1434,14 +1441,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()) { @@ -1473,7 +1483,7 @@ next: TABLE_LIST* unique_table(THD *thd, TABLE_LIST *table, TABLE_LIST *table_list, - bool check_alias) + uint check_flag) { TABLE_LIST *dup; @@ -1487,12 +1497,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; } /* |