Skip to content

Commit 10008b3

Browse files
MDEV-31466 Add optional correlation column list for derived tables
Extend derived table syntax to support column name assignment. (subquery expression) [as|=] ident [comma separated column name list]. Prior to this patch, the optional comma separated column name list is not supported. Processing within the unit of the subquery expression will use original column names, outside the unit will use the new names. For example, in the query select a1, a2 from (select c1, c2, c3 from t1 where c2 > 0) as dt (a1, a2, a3) where a2 > 10; we see the second column of the derived table dt being used both within, (where c2 > 0), and outside, (where a2 > 10), the specification. Both conditions apply to t1.c2. When multiple unit preparations are required, such as when being used within a prepared statement or procedure, original column names are needed for correct resolution. Original names are reset within mysql_derived_reinit(). Item_holder items, used for result tables in both TVC and union preparations are renamed before use within st_select_lex_unit::prepare(). During wildcard expansion, if column names are present, items names are set directly after creation. Reviewed by Igor Babaev (igor@mariadb.com)
1 parent 4016c90 commit 10008b3

File tree

14 files changed

+4062
-23
lines changed

14 files changed

+4062
-23
lines changed

mysql-test/main/derived.result

Lines changed: 3298 additions & 0 deletions
Large diffs are not rendered by default.

mysql-test/main/derived.test

Lines changed: 572 additions & 0 deletions
Large diffs are not rendered by default.

sql/share/errmsg-utf8.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12280,3 +12280,6 @@ ER_SEQUENCE_TABLE_ORDER_BY
1228012280
eng "ORDER BY"
1228112281
ER_VARIABLE_IGNORED
1228212282
eng "The variable '%s' is ignored. It only exists for compatibility with old installations and will be removed in a future release"
12283+
ER_INCORRECT_COLUMN_NAME_COUNT
12284+
eng "Incorrect column name count for derived table"
12285+
chi "派生表的列名计数不正确"

sql/sql_base.cc

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8635,6 +8635,10 @@ insert_fields(THD *thd, Name_resolution_context *context,
86358635
*/
86368636
field_iterator.set(tables);
86378637

8638+
List_iterator_fast<Lex_ident_sys> ni;
8639+
if (tables->column_names)
8640+
ni.init(*tables->column_names);
8641+
86388642
for (; !field_iterator.end_of_fields(); field_iterator.next())
86398643
{
86408644
/*
@@ -8650,6 +8654,9 @@ insert_fields(THD *thd, Name_resolution_context *context,
86508654
if (!(item= field_iterator.create_item(thd)))
86518655
DBUG_RETURN(TRUE);
86528656

8657+
if (tables->column_names)
8658+
lex_string_set(&item->name, (ni++)->str);
8659+
86538660
/* cache the table for the Item_fields inserted by expanding stars */
86548661
if (item->type() == Item::FIELD_ITEM && tables->cacheable_table)
86558662
((Item_field *)item)->cached_table= tables;

sql/sql_cte.cc

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1652,10 +1652,14 @@ void With_clause::print(THD *thd, String *str, enum_query_type query_type)
16521652
}
16531653

16541654

1655-
static void list_strlex_print(THD *thd, String *str, List<Lex_ident_sys> *list)
1655+
void list_strlex_print(THD *thd, String *str, List<Lex_ident_sys> *list,
1656+
bool bracketed)
16561657
{
16571658
List_iterator_fast<Lex_ident_sys> li(*list);
16581659
bool first= TRUE;
1660+
1661+
if (bracketed)
1662+
str->append('(');
16591663
while(Lex_ident_sys *col_name= li++)
16601664
{
16611665
if (first)
@@ -1664,6 +1668,8 @@ static void list_strlex_print(THD *thd, String *str, List<Lex_ident_sys> *list)
16641668
str->append(',');
16651669
append_identifier(thd, str, col_name);
16661670
}
1671+
if (bracketed)
1672+
str->append(')');
16671673
}
16681674

16691675

@@ -1684,12 +1690,7 @@ void With_element::print(THD *thd, String *str, enum_query_type query_type)
16841690
{
16851691
str->append(get_name());
16861692
if (column_list.elements)
1687-
{
1688-
List_iterator_fast<Lex_ident_sys> li(column_list);
1689-
str->append('(');
1690-
list_strlex_print(thd, str, &column_list);
1691-
str->append(')');
1692-
}
1693+
list_strlex_print(thd, str, &column_list, true);
16931694
str->append(STRING_WITH_LEN(" as ("));
16941695
spec->print(str, query_type);
16951696
str->append(')');

sql/sql_cte.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -550,4 +550,7 @@ void st_select_lex::set_with_clause(With_clause *with_clause)
550550
with_clause->set_owner(master_unit());
551551
}
552552

553+
void list_strlex_print(THD *thd, String *str, List<Lex_ident_sys> *list,
554+
bool bracketed= false);
555+
553556
#endif /* SQL_CTE_INCLUDED */

sql/sql_derived.cc

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1354,6 +1354,9 @@ bool mysql_derived_reinit(THD *thd, LEX *lex, TABLE_LIST *derived)
13541354
derived->get_unit()));
13551355
st_select_lex_unit *unit= derived->get_unit();
13561356

1357+
if (derived->original_names_are_saved)
1358+
unit->first_select()->set_item_list_names(derived->original_names);
1359+
13571360
// reset item names to that saved after wildcard expansion in JOIN::prepare
13581361
for(st_select_lex *sl= unit->first_select(); sl; sl= sl->next_select())
13591362
sl->restore_item_list_names();

sql/sql_lex.cc

Lines changed: 47 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3606,6 +3606,42 @@ List<Item>* st_select_lex::get_item_list()
36063606
}
36073607

36083608

3609+
/**
3610+
@brief
3611+
Replace the name of each item in the item_list with a new name.
3612+
3613+
@param
3614+
new_names pointer to a List of Lex_ident_sys from which replacement
3615+
names are taken.
3616+
3617+
@details
3618+
This is used in derived tables to optionally set the names in the item_list.
3619+
Usually called in unit::prepare().
3620+
3621+
@retval
3622+
true: an error occurred
3623+
false: success
3624+
*/
3625+
3626+
bool st_select_lex::set_item_list_names(List<Lex_ident_sys> *new_names)
3627+
{
3628+
if (item_list.elements != new_names->elements)
3629+
{
3630+
my_error(ER_INCORRECT_COLUMN_NAME_COUNT, MYF(0));
3631+
return true;
3632+
}
3633+
3634+
List_iterator<Lex_ident_sys> it(*new_names);
3635+
List_iterator_fast<Item> li(item_list);
3636+
Item *item;
3637+
3638+
while ((item= li++))
3639+
lex_string_set( &item->name, (it++)->str);
3640+
3641+
return false;
3642+
}
3643+
3644+
36093645
uint st_select_lex::get_cardinality_of_ref_ptrs_slice(uint order_group_num_arg)
36103646
{
36113647
if (!((options & SELECT_DISTINCT) && !group_list.elements))
@@ -10705,7 +10741,8 @@ SELECT_LEX *LEX::parsed_TVC_end()
1070510741

1070610742
TABLE_LIST *LEX::parsed_derived_table(SELECT_LEX_UNIT *unit,
1070710743
int for_system_time,
10708-
LEX_CSTRING *alias)
10744+
LEX_CSTRING *alias,
10745+
List<Lex_ident_sys> *column_names)
1070910746
{
1071010747
TABLE_LIST *res;
1071110748
derived_tables|= DERIVED_SUBQUERY;
@@ -10726,6 +10763,15 @@ TABLE_LIST *LEX::parsed_derived_table(SELECT_LEX_UNIT *unit,
1072610763
{
1072710764
res->vers_conditions= vers_conditions;
1072810765
}
10766+
10767+
if (column_names && column_names->elements > 0)
10768+
{
10769+
res->column_names= column_names;
10770+
// pre-allocate space to save item_list names
10771+
res->original_names= new (thd->mem_root) List<Lex_ident_sys>;
10772+
for (uint i= 0; i < column_names->elements; i++)
10773+
res->original_names->push_back( new Lex_ident_sys );
10774+
}
1072910775
return res;
1073010776
}
1073110777

sql/sql_lex.h

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -803,6 +803,8 @@ class st_select_lex_unit: public st_select_lex_node {
803803
bool is_view:1;
804804
bool describe:1; /* union exec() called for EXPLAIN */
805805
bool columns_are_renamed:1;
806+
inline bool rename_item_list(TABLE_LIST *derived_arg);
807+
inline void rename_types_list(List<Lex_ident_sys> *new_names);
806808

807809
protected:
808810
/* This is bool, not bit, as it's used and set in many places */
@@ -1322,7 +1324,7 @@ class st_select_lex: public st_select_lex_node
13221324
List<Item>* get_item_list();
13231325
bool save_item_list_names(THD *thd);
13241326
void restore_item_list_names();
1325-
1327+
bool set_item_list_names( List<Lex_ident_sys> *overwrite );
13261328
ulong get_table_join_options();
13271329
void set_lock_for_tables(thr_lock_type lock_type, bool for_update,
13281330
bool skip_locks);
@@ -4728,7 +4730,8 @@ struct LEX: public Query_tables_list
47284730
SELECT_LEX *parsed_TVC_end();
47294731
TABLE_LIST *parsed_derived_table(SELECT_LEX_UNIT *unit,
47304732
int for_system_time,
4731-
LEX_CSTRING *alias);
4733+
LEX_CSTRING *alias,
4734+
List<Lex_ident_sys> *column_names= nullptr);
47324735
bool parsed_create_view(SELECT_LEX_UNIT *unit, int check);
47334736
bool select_finalize(st_select_lex_unit *expr);
47344737
bool select_finalize(st_select_lex_unit *expr, Lex_select_lock l);

sql/sql_select.cc

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31613,6 +31613,9 @@ void TABLE_LIST::print(THD *thd, table_map eliminated_tables, String *str,
3161331613
str->append(' ');
3161431614
append_identifier_opt_casedn(thd, str, alias,
3161531615
lower_case_table_names == 1);
31616+
31617+
if (column_names && (column_names->elements > 0))
31618+
list_strlex_print(thd, str, column_names, true);
3161631619
}
3161731620

3161831621
if (index_hints)

0 commit comments

Comments
 (0)