diff options
author | Oleksandr Byelkin <sanja@mariadb.com> | 2022-07-27 11:02:57 +0200 |
---|---|---|
committer | Oleksandr Byelkin <sanja@mariadb.com> | 2022-07-27 11:02:57 +0200 |
commit | 3bb36e949534fc4a24d68d4297663ae8b80ba336 (patch) | |
tree | 09907f6c2e82d718f261323075ffb33cb350fef7 /sql/sql_base.cc | |
parent | 9a897335eb4387980aed7698b832a893dbaa3d81 (diff) | |
parent | bd935a41060199a17019453d6e187e8edd7929ba (diff) | |
download | mariadb-git-3bb36e949534fc4a24d68d4297663ae8b80ba336.tar.gz |
Merge branch '10.3' into 10.4
Diffstat (limited to 'sql/sql_base.cc')
-rw-r--r-- | sql/sql_base.cc | 178 |
1 files changed, 125 insertions, 53 deletions
diff --git a/sql/sql_base.cc b/sql/sql_base.cc index 42285e9b3a4..9942552e80b 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -7749,46 +7749,118 @@ bool setup_fields(THD *thd, Ref_ptr_array ref_pointer_array, DBUG_RETURN(MY_TEST(thd->is_error())); } +/* + make list of leaves for a single TABLE_LIST + + SYNOPSIS + make_leaves_for_single_table() + thd Thread handler + leaves List of leaf tables to be filled + table TABLE_LIST object to process + full_table_list Whether to include tables from mergeable derived table/view +*/ +void make_leaves_for_single_table(THD *thd, List<TABLE_LIST> &leaves, + TABLE_LIST *table, bool& full_table_list, + TABLE_LIST *boundary) +{ + if (table == boundary) + full_table_list= !full_table_list; + if (full_table_list && table->is_merged_derived()) + { + SELECT_LEX *select_lex= table->get_single_select(); + /* + It's safe to use select_lex->leaf_tables because all derived + tables/views were already prepared and has their leaf_tables + set properly. + */ + make_leaves_list(thd, leaves, select_lex->get_table_list(), + full_table_list, boundary); + } + else + { + leaves.push_back(table, thd->mem_root); + } +} + /* make list of leaves of join table tree SYNOPSIS make_leaves_list() - list pointer to pointer on list first element - tables table list - full_table_list whether to include tables from mergeable derived table/view. - we need them for checks for INSERT/UPDATE statements only. - - RETURN pointer on pointer to next_leaf of last element + leaves List of leaf tables to be filled + tables Table list + full_table_list Whether to include tables from mergeable derived table/view. + We need them for checks for INSERT/UPDATE statements only. */ -void make_leaves_list(THD *thd, List<TABLE_LIST> &list, TABLE_LIST *tables, +void make_leaves_list(THD *thd, List<TABLE_LIST> &leaves, TABLE_LIST *tables, bool full_table_list, TABLE_LIST *boundary) { for (TABLE_LIST *table= tables; table; table= table->next_local) { - if (table == boundary) - full_table_list= !full_table_list; - if (full_table_list && table->is_merged_derived()) - { - SELECT_LEX *select_lex= table->get_single_select(); - /* - It's safe to use select_lex->leaf_tables because all derived - tables/views were already prepared and has their leaf_tables - set properly. - */ - make_leaves_list(thd, list, select_lex->get_table_list(), - full_table_list, boundary); - } - else - { - list.push_back(table, thd->mem_root); - } + make_leaves_for_single_table(thd, leaves, table, full_table_list, + boundary); + } +} + + +/* + Setup the map and other attributes for a single TABLE_LIST object + + SYNOPSIS + setup_table_attributes() + thd Thread handler + table_list TABLE_LIST object to process + first_select_table First table participating in SELECT for INSERT..SELECT + statements, NULL for other cases + tablenr Serial number of the table in the SQL statement + + RETURN + false Success + true Failure +*/ +bool setup_table_attributes(THD *thd, TABLE_LIST *table_list, + TABLE_LIST *first_select_table, + uint &tablenr) +{ + TABLE *table= table_list->table; + if (table) + table->pos_in_table_list= table_list; + if (first_select_table && table_list->top_table() == first_select_table) + { + /* new counting for SELECT of INSERT ... SELECT command */ + first_select_table= 0; + thd->lex->first_select_lex()->insert_tables= tablenr; + tablenr= 0; + } + if (table_list->jtbm_subselect) + { + table_list->jtbm_table_no= tablenr; + } + else if (table) + { + table->pos_in_table_list= table_list; + setup_table_map(table, table_list, tablenr); + + if (table_list->process_index_hints(table)) + return true; } + tablenr++; + /* + We test the max tables here as we setup_table_map() should not be called + with tablenr >= 64 + */ + if (tablenr > MAX_TABLES) + { + my_error(ER_TOO_MANY_TABLES, MYF(0), static_cast<int>(MAX_TABLES)); + return true; + } + return false; } + /* prepare tables @@ -7845,7 +7917,14 @@ bool setup_tables(THD *thd, Name_resolution_context *context, leaves.empty(); if (select_lex->prep_leaf_list_state != SELECT_LEX::SAVED) { - make_leaves_list(thd, leaves, tables, full_table_list, first_select_table); + /* + For INSERT ... SELECT statements we must not include the first table + (where the data is being inserted into) in the list of leaves + */ + TABLE_LIST *tables_for_leaves= + select_insert ? first_select_table : tables; + make_leaves_list(thd, leaves, tables_for_leaves, full_table_list, + first_select_table); select_lex->prep_leaf_list_state= SELECT_LEX::READY; select_lex->leaf_tables_exec.empty(); } @@ -7856,40 +7935,33 @@ bool setup_tables(THD *thd, Name_resolution_context *context, leaves.push_back(table_list, thd->mem_root); } + List_iterator<TABLE_LIST> ti(leaves); while ((table_list= ti++)) { - TABLE *table= table_list->table; - if (table) - table->pos_in_table_list= table_list; - if (first_select_table && - table_list->top_table() == first_select_table) - { - /* new counting for SELECT of INSERT ... SELECT command */ - first_select_table= 0; - thd->lex->first_select_lex()->insert_tables= tablenr; - tablenr= 0; - } - if(table_list->jtbm_subselect) - { - table_list->jtbm_table_no= tablenr; - } - else if (table) - { - table->pos_in_table_list= table_list; - setup_table_map(table, table_list, tablenr); + if (setup_table_attributes(thd, table_list, first_select_table, tablenr)) + DBUG_RETURN(1); + } - if (table_list->process_index_hints(table)) - DBUG_RETURN(1); - } - tablenr++; + if (select_insert) + { /* - We test the max tables here as we setup_table_map() should not be called - with tablenr >= 64 + The table/view in which the data is inserted must not be included into + the leaf_tables list. But we need this table/view to setup attributes + for it. So build a temporary list of leaves and setup attributes for + the tables included */ - if (tablenr > MAX_TABLES) + List<TABLE_LIST> leaves; + TABLE_LIST *table= tables; + + make_leaves_for_single_table(thd, leaves, table, full_table_list, + first_select_table); + + List_iterator<TABLE_LIST> ti(leaves); + while ((table_list= ti++)) { - my_error(ER_TOO_MANY_TABLES,MYF(0), static_cast<int>(MAX_TABLES)); - DBUG_RETURN(1); + if (setup_table_attributes(thd, table_list, first_select_table, + tablenr)) + DBUG_RETURN(1); } } } |