From ea9a393a868dda808bd0c7a3f03b28208eb6570f Mon Sep 17 00:00:00 2001 From: Alexander Barkov Date: Tue, 24 May 2016 14:18:46 +0400 Subject: MDEV-10103 Disallow syntactically UNION SELECT .. PROCEDURE ANALYSE() --- mysql-test/r/func_analyse.result | 2 +- mysql-test/r/parser.result | 4 +-- mysql-test/t/func_analyse.test | 2 +- mysql-test/t/parser.test | 4 +-- sql/sql_yacc.yy | 68 +++++++++++++++++++++++++++++++++------- 5 files changed, 62 insertions(+), 18 deletions(-) diff --git a/mysql-test/r/func_analyse.result b/mysql-test/r/func_analyse.result index bc8ec445e73..1e78e603bca 100644 --- a/mysql-test/r/func_analyse.result +++ b/mysql-test/r/func_analyse.result @@ -159,7 +159,7 @@ Field_name Min_value Max_value Min_length Max_length Empties_or_zeros Nulls Avg_ Field_name Min_value Max_value Min_length Max_length Empties_or_zeros Nulls Avg_value_or_avg_length Std Optimal_fieldtype 1 1 1 1 1 0 0 1.0000 0.0000 ENUM('1') NOT NULL SELECT * FROM t1 UNION SELECT * FROM t1 PROCEDURE analyse(); -ERROR HY000: Incorrect usage of PROCEDURE and subquery +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'PROCEDURE analyse()' at line 1 # # MDEV-10030 sql_yacc.yy: Split table_expression and remove PROCEDURE from create_select, select_paren_derived, select_derived2, query_specification # diff --git a/mysql-test/r/parser.result b/mysql-test/r/parser.result index 54f84f88e05..f0cfde65b57 100644 --- a/mysql-test/r/parser.result +++ b/mysql-test/r/parser.result @@ -705,7 +705,7 @@ SELECT 1 FROM t1 UNION SELECT 1 FROM DUAL WHERE 1 GROUP BY 1 HAVING 1 ORDER BY 1 PROCEDURE ANALYSE() FOR UPDATE; -ERROR HY000: Incorrect usage of PROCEDURE and subquery +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'PROCEDURE ANALYSE() FOR UPDATE' at line 4 SELECT 1 FROM DUAL PROCEDURE ANALYSE() UNION SELECT 1 FROM t1; @@ -721,7 +721,7 @@ FOR UPDATE); UNION (SELECT 1 FROM DUAL WHERE 1 GROUP BY 1 HAVING 1 ORDER BY 1 PROCEDURE ANALYSE() FOR UPDATE); -ERROR HY000: Incorrect usage of PROCEDURE and subquery +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'PROCEDURE ANALYSE() FOR UPDATE)' at line 4 # "FOR UPDATE" tests SELECT 1 FROM t1 UNION SELECT 1 FROM t1 ORDER BY 1 LIMIT 1; 1 diff --git a/mysql-test/t/func_analyse.test b/mysql-test/t/func_analyse.test index 6c30c0ca630..d99f5c0fa9a 100644 --- a/mysql-test/t/func_analyse.test +++ b/mysql-test/t/func_analyse.test @@ -165,7 +165,7 @@ DROP TABLE t1, t2; ((SELECT 1 FROM DUAL PROCEDURE ANALYSE())); # TODO: ---error ER_WRONG_USAGE +--error ER_PARSE_ERROR SELECT * FROM t1 UNION SELECT * FROM t1 PROCEDURE analyse(); --echo # diff --git a/mysql-test/t/parser.test b/mysql-test/t/parser.test index 0065c5d0b5c..aae6b2c34be 100644 --- a/mysql-test/t/parser.test +++ b/mysql-test/t/parser.test @@ -825,7 +825,7 @@ UNION SELECT 1 FROM DUAL WHERE 1 GROUP BY 1 HAVING 1 ORDER BY 1 FOR UPDATE; ---error ER_WRONG_USAGE +--error ER_PARSE_ERROR SELECT 1 FROM t1 UNION SELECT 1 FROM DUAL WHERE 1 GROUP BY 1 HAVING 1 ORDER BY 1 @@ -841,7 +841,7 @@ UNION (SELECT 1 FROM DUAL WHERE 1 GROUP BY 1 HAVING 1 ORDER BY 1 FOR UPDATE); ---error ER_WRONG_USAGE +--error ER_PARSE_ERROR (SELECT 1 FROM t1) UNION (SELECT 1 FROM DUAL WHERE 1 GROUP BY 1 HAVING 1 ORDER BY 1 diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index ac43129372c..260f570ffd2 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -8528,6 +8528,11 @@ select_init: | '(' select_paren ')' union_opt ; +union_list_part2: + SELECT_SYM select_options_and_item_list select_init3_union_query_term + | '(' select_paren_union_query_term ')' union_opt + ; + select_paren: { /* @@ -8545,6 +8550,23 @@ select_paren: | '(' select_paren ')' ; +select_paren_union_query_term: + { + /* + In order to correctly parse UNION's global ORDER BY we need to + set braces before parsing the clause. + */ + Lex->current_select->set_braces(true); + } + SELECT_SYM select_options_and_item_list select_part3_union_query_term + opt_select_lock_type + { + if (setup_select_in_parentheses(Lex)) + MYSQL_YYABORT; + } + | '(' select_paren_union_query_term ')' + ; + select_paren_view: { /* @@ -8597,6 +8619,23 @@ select_init3: ; +select_init3_union_query_term: + opt_table_expression + opt_select_lock_type + { + /* Parentheses carry no meaning here */ + Lex->current_select->set_braces(false); + } + union_clause + | select_part3_union_not_ready_noproc + opt_select_lock_type + { + /* Parentheses carry no meaning here */ + Lex->current_select->set_braces(false); + } + ; + + select_init3_view: opt_table_expression opt_select_lock_type { @@ -8617,28 +8656,38 @@ select_init3_view: } ; +/* + The SELECT parts after select_item_list that cannot be followed by UNION. +*/ + select_part3: opt_table_expression | select_part3_union_not_ready ; +select_part3_union_query_term: + opt_table_expression + | select_part3_union_not_ready_noproc + ; + select_part3_view: opt_table_expression | order_or_limit | table_expression order_or_limit ; -/* - The SELECT parts after select_item_list that cannot be followed by UNION. -*/ select_part3_union_not_ready: + select_part3_union_not_ready_noproc + | table_expression procedure_clause + | table_expression order_or_limit procedure_clause + ; + +select_part3_union_not_ready_noproc: order_or_limit | into opt_table_expression opt_order_clause opt_limit_clause | table_expression into - | table_expression procedure_clause | table_expression order_or_limit | table_expression order_or_limit into - | table_expression order_or_limit procedure_clause ; select_options_and_item_list: @@ -12012,12 +12061,7 @@ procedure_clause: { LEX *lex=Lex; - if (&lex->select_lex != lex->current_select) - { - // SELECT * FROM t1 UNION SELECT * FROM t2 PROCEDURE ANALYSE(); - my_error(ER_WRONG_USAGE, MYF(0), "PROCEDURE", "subquery"); - MYSQL_YYABORT; - } + DBUG_ASSERT(&lex->select_lex == lex->current_select); lex->proc_list.elements=0; lex->proc_list.first=0; @@ -16361,7 +16405,7 @@ union_list: if (add_select_to_union_list(Lex, (bool)$2, TRUE)) MYSQL_YYABORT; } - select_init + union_list_part2 { /* Remove from the name resolution context stack the context of the -- cgit v1.2.1