diff options
author | Igor Babaev <igor@askmonty.org> | 2023-02-27 10:51:22 -0800 |
---|---|---|
committer | Igor Babaev <igor@askmonty.org> | 2023-02-27 10:51:22 -0800 |
commit | 841e8877ccb8ef5d692a22b4447383a360557326 (patch) | |
tree | 8885b507ee0218a61ccd38a0fe59d713d1a7dcd1 /sql | |
parent | 839c7fcf38ef17f9627f63ebec3e82d814912973 (diff) | |
download | mariadb-git-841e8877ccb8ef5d692a22b4447383a360557326.tar.gz |
MDEV-28603 Invalid view when its definition uses TVC as single-value subquery
Subselect_single_value_engine cannot handle table value constructor used as
subquery. That's why any table value constructor TVC used as subquery is
converted into a select over derived table whose specification is TVC.
Currently the names of the columns of the derived table DT are taken from
the first element of TVC and if the k-th component of the element happens
to be a subquery the text representation of this subquery serves as the
name of the k-th column of the derived table. References of all columns of
the derived table DT compose the select list of the result of the conversion.
If a definition of a view contained a table value constructor used as a
subquery and the view was registered after this conversion had been
applied we could register an invalid view definition if the first element
of TVC contained a subquery as its component: the name of this component
was taken from the original subquery, while the name of the corresponding
column of the derived table was taken from the text representation of the
subquery produced by the function SELECT_LEX::print() and these names were
usually differ from each other.
To avoid registration of such invalid views the function SELECT_LEX::print()
now prints the original TVC instead of the select in which this TVC has
been wrapped. Now the specification of registered view looks like as if no
conversions from TVC to selects were done.
Approved by Oleksandr Byelkin <sanja@mariadb.com>
Diffstat (limited to 'sql')
-rw-r--r-- | sql/mysqld.h | 2 | ||||
-rw-r--r-- | sql/sql_lex.cc | 1 | ||||
-rw-r--r-- | sql/sql_lex.h | 3 | ||||
-rw-r--r-- | sql/sql_select.cc | 6 | ||||
-rw-r--r-- | sql/sql_show.cc | 3 | ||||
-rw-r--r-- | sql/sql_tvc.cc | 1 | ||||
-rw-r--r-- | sql/sql_view.cc | 6 |
7 files changed, 18 insertions, 4 deletions
diff --git a/sql/mysqld.h b/sql/mysqld.h index 60afb0b9dba..f521ea23638 100644 --- a/sql/mysqld.h +++ b/sql/mysqld.h @@ -755,6 +755,8 @@ enum enum_query_type // it evaluates to. Should be used for error messages, so that they // don't reveal values. QT_NO_DATA_EXPANSION= (1 << 9), + // Remove wrappers added for TVC when creating or showing view + QT_NO_WRAPPERS_FOR_TVC_IN_VIEW= (1 << 11), }; diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc index 24958b5adcc..62c7556dcd6 100644 --- a/sql/sql_lex.cc +++ b/sql/sql_lex.cc @@ -2487,6 +2487,7 @@ void st_select_lex::init_select() curr_tvc_name= 0; in_tvc= false; versioned_tables= 0; + is_tvc_wrapper= false; } /* diff --git a/sql/sql_lex.h b/sql/sql_lex.h index 3545a4e8d74..8f25426a09c 100644 --- a/sql/sql_lex.h +++ b/sql/sql_lex.h @@ -1132,7 +1132,8 @@ public: st_select_lex. */ uint curr_tvc_name; - + /* true <=> select has been created a TVC wrapper */ + bool is_tvc_wrapper; /* Needed to correctly generate 'PRIMARY' or 'SIMPLE' for select_type column of EXPLAIN diff --git a/sql/sql_select.cc b/sql/sql_select.cc index f83bf32130e..2c12d1c4c65 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -27992,6 +27992,12 @@ void st_select_lex::print(THD *thd, String *str, enum_query_type query_type) return; } + if (is_tvc_wrapper && (query_type & QT_NO_WRAPPERS_FOR_TVC_IN_VIEW)) + { + first_inner_unit()->first_select()->print(thd, str, query_type); + return; + } + if ((query_type & QT_SHOW_SELECT_NUMBER) && thd->lex->all_selects_list && thd->lex->all_selects_list->link_next && diff --git a/sql/sql_show.cc b/sql/sql_show.cc index 9fee8ce5a6c..1ad20ac7593 100644 --- a/sql/sql_show.cc +++ b/sql/sql_show.cc @@ -2707,7 +2707,8 @@ static int show_create_view(THD *thd, TABLE_LIST *table, String *buff) a different syntax, like when ANSI_QUOTES is defined. */ table->view->unit.print(buff, enum_query_type(QT_VIEW_INTERNAL | - QT_ITEM_ORIGINAL_FUNC_NULLIF)); + QT_ITEM_ORIGINAL_FUNC_NULLIF | + QT_NO_WRAPPERS_FOR_TVC_IN_VIEW)); if (table->with_check != VIEW_CHECK_NONE) { diff --git a/sql/sql_tvc.cc b/sql/sql_tvc.cc index d8e6770465d..71377d3661d 100644 --- a/sql/sql_tvc.cc +++ b/sql/sql_tvc.cc @@ -673,6 +673,7 @@ st_select_lex *wrap_tvc(THD *thd, st_select_lex *tvc_sl, wrapper_sl->parent_lex= lex; /* Used in init_query. */ wrapper_sl->init_query(); wrapper_sl->init_select(); + wrapper_sl->is_tvc_wrapper= true; wrapper_sl->nest_level= tvc_sl->nest_level; wrapper_sl->parsing_place= tvc_sl->parsing_place; diff --git a/sql/sql_view.cc b/sql/sql_view.cc index 1efbc68fb8a..54debf98eff 100644 --- a/sql/sql_view.cc +++ b/sql/sql_view.cc @@ -956,10 +956,12 @@ static int mysql_register_view(THD *thd, TABLE_LIST *view, thd->variables.sql_mode&= ~MODE_ANSI_QUOTES; lex->unit.print(&view_query, enum_query_type(QT_VIEW_INTERNAL | - QT_ITEM_ORIGINAL_FUNC_NULLIF)); + QT_ITEM_ORIGINAL_FUNC_NULLIF | + QT_NO_WRAPPERS_FOR_TVC_IN_VIEW)); lex->unit.print(&is_query, enum_query_type(QT_TO_SYSTEM_CHARSET | QT_WITHOUT_INTRODUCERS | - QT_ITEM_ORIGINAL_FUNC_NULLIF)); + QT_ITEM_ORIGINAL_FUNC_NULLIF | + QT_NO_WRAPPERS_FOR_TVC_IN_VIEW)); thd->variables.sql_mode|= sql_mode; } |