From 629449172a5b0a6975663ca1ac420789e00b941d Mon Sep 17 00:00:00 2001 From: Rucha Deodhar Date: Fri, 30 Apr 2021 23:14:57 +0530 Subject: MDEV-25462: Assertion `m_status == DA_ERROR || m_status == DA_OK || m_status == DA_OK_BULK' failed in Diagnostics_area::message from get_schema_tables_record Analysis: SET NAMES changes character set for character_set_client, character_set_connection, character_set_results to 'filename'. The .frm file of view has @xx sequences in the SELECT query, which give parsing error because 'filename' character set is not parser friendly. When we get parsing error (ER_PARSE_ERROR), we directly return true without setting error status. This is caught later in assertion. Fix: Disallow 'filename' character set in SET NAMES because it is not parser friendly. --- sql/sql_view.cc | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'sql/sql_view.cc') diff --git a/sql/sql_view.cc b/sql/sql_view.cc index 0701c5233ac..0547a2fe856 100644 --- a/sql/sql_view.cc +++ b/sql/sql_view.cc @@ -878,6 +878,13 @@ static int mysql_register_view(THD *thd, TABLE_LIST *view, { LEX *lex= thd->lex; + /* + Ensure character set number != 17 (character set = filename) and mbminlen=1 + because these character sets are not parser friendly, which can give weird + sequence in .frm file of view and later give parsing error. + */ + DBUG_ASSERT(thd->charset()->mbminlen == 1 && thd->charset()->number != 17); + /* View definition query -- a SELECT statement that fully defines view. It is generated from the Item-tree built from the original (specified by -- cgit v1.2.1 From 43c9fcefc07d2f42b65950e76adfbc3c1e8acb28 Mon Sep 17 00:00:00 2001 From: Igor Babaev Date: Wed, 12 May 2021 19:32:29 -0700 Subject: MDEV-23886 Reusing CTE inside a function fails with table doesn't exist In the code existed just before this patch binding of a table reference to the specification of the corresponding CTE happens in the function open_and_process_table(). If the table reference is not the first in the query the specification is cloned in the same way as the specification of a view is cloned for any reference of the view. This works fine for standalone queries, but does not work for stored procedures / functions for the following reason. When the first call of a stored procedure/ function SP is processed the body of SP is parsed. When a query of SP is parsed the info on each encountered table reference is put into a TABLE_LIST object linked into a global chain associated with the query. When parsing of the query is finished the basic info on the table references from this chain except table references to derived tables and information schema tables is put in one hash table associated with SP. When parsing of the body of SP is finished this hash table is used to construct TABLE_LIST objects for all table references mentioned in SP and link them into the list of such objects passed to a pre-locking process that calls open_and_process_table() for each table from the list. When a TABLE_LIST for a view is encountered the view is opened and its specification is parsed. For any table reference occurred in the specification a new TABLE_LIST object is created to be included into the list for pre-locking. After all objects in the pre-locking have been looked through the tables mentioned in the list are locked. Note that the objects referenced CTEs are just skipped here as it is impossible to resolve these references without any info on the context where they occur. Now the statements from the body of SP are executed one by one that. At the very beginning of the execution of a query the tables used in the query are opened and open_and_process_table() now is called for each table reference mentioned in the list of TABLE_LIST objects associated with the query that was built when the query was parsed. For each table reference first the reference is checked against CTEs definitions in whose scope it occurred. If such definition is found the reference is considered resolved and if this is not the first reference to the found CTE the the specification of the CTE is re-parsed and the result of the parsing is added to the parsing tree of the query as a sub-tree. If this sub-tree contains table references to other tables they are added to the list of TABLE_LIST objects associated with the query in order the referenced tables to be opened. When the procedure that opens the tables comes to the TABLE_LIST object created for a non-first reference to a CTE it discovers that the referenced table instance is not locked and reports an error. Thus processing non-first table references to a CTE similar to how references to view are processed does not work for queries used in stored procedures / functions. And the main problem is that the current pre-locking mechanism employed for stored procedures / functions does not allow to save the context in which a CTE reference occur. It's not trivial to save the info about the context where a CTE reference occurs while the resolution of the table reference cannot be done without this context and consequentially the specification for the table reference cannot be determined. This patch solves the above problem by moving resolution of all CTE references at the parsing stage. More exactly references to CTEs occurred in a query are resolved right after parsing of the query has finished. After resolution any CTE reference it is marked as a reference to to derived table. So it is excluded from the hash table created for pre-locking used base tables and view when the first call of a stored procedure / function is processed. This solution required recursive calls of the parser. The function THD::sql_parser() has been added specifically for recursive invocations of the parser. --- sql/sql_view.cc | 9 --------- 1 file changed, 9 deletions(-) (limited to 'sql/sql_view.cc') diff --git a/sql/sql_view.cc b/sql/sql_view.cc index 0547a2fe856..39744fe5704 100644 --- a/sql/sql_view.cc +++ b/sql/sql_view.cc @@ -432,12 +432,6 @@ bool mysql_create_view(THD *thd, TABLE_LIST *views, lex->link_first_table_back(view, link_to_local); view->open_type= OT_BASE_ONLY; - if (check_dependencies_in_with_clauses(lex->with_clauses_list)) - { - res= TRUE; - goto err; - } - WSREP_TO_ISOLATION_BEGIN(WSREP_MYSQL_DB, NULL, NULL); /* @@ -1406,9 +1400,6 @@ bool mysql_make_view(THD *thd, TABLE_SHARE *share, TABLE_LIST *table, TABLE_LIST *tbl; Security_context *security_ctx= 0; - if (check_dependencies_in_with_clauses(thd->lex->with_clauses_list)) - goto err; - /* Check rights to run commands (ANALYZE SELECT, EXPLAIN SELECT & SHOW CREATE) which show underlying tables. -- cgit v1.2.1