Hi, Sanja! On Aug 31, sanja@mariadb.com wrote:
revision-id: 93a7c11c51e2f5c0ca98600924172e452b6188b6 (mariadb-10.1.6-24-g93a7c11) parent(s): d07b780db239a909e667edf5657e3633e80d1451 committer: Oleksandr Byelkin timestamp: 2015-08-31 13:10:01 +0200 message:
MDEV-8380: Subquery parse error
backport mysql parser fixes 0034963fbf199696792491bcb79d5f0731c98804 5948561812bc691bd0c13cf518a3fe77d9daf920
diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc index 6c835c4..1d9aca9 100644 --- a/sql/sql_lex.cc +++ b/sql/sql_lex.cc @@ -546,6 +546,7 @@ void lex_start(THD *thd) lex->limit_rows_examined_cnt= ULONGLONG_MAX; lex->var_list.empty(); lex->stmt_var_list.empty(); + lex->proc_list.elements=0;
why? this wasn't in the patches you've backported.
lex->is_lex_started= TRUE; DBUG_VOID_RETURN; @@ -852,6 +853,29 @@ bool Lex_input_stream::get_text(LEX_STRING *dst, int pre_skip, int post_skip) }
+uint Lex_input_stream::get_lineno(const char *raw_ptr) +{ + DBUG_ASSERT(m_buf <= raw_ptr && raw_ptr < m_end_of_query); + if (!(m_buf <= raw_ptr && raw_ptr < m_end_of_query)) + return 1; + + uint ret= 1; + const CHARSET_INFO *cs= m_thd->charset(); + for (const char *c= m_buf; c < raw_ptr; c++) + { + uint mb_char_len; + if (use_mb(cs) && (mb_char_len= my_ismbchar(cs, c, m_end_of_query))) + { + c+= mb_char_len - 1; // skip the rest of the multibyte character + continue; // we don't expect '\n' there + } + if (*c == '\n') + ret++; + } + return ret; +}
why? this doesn't seem to be used anywhere.
+ + /* ** Calc type of integer; long integer, longlong integer or real. ** Returns smallest type that match the string. diff --git a/sql/sql_lex.h b/sql/sql_lex.h index 09a3d5e..529c4d5 100644 --- a/sql/sql_lex.h +++ b/sql/sql_lex.h @@ -2087,6 +2087,8 @@ class Lex_input_stream CHARSET_INFO *txt_cs, const char *end_ptr);
+ uint get_lineno(const char *raw_ptr); + /** Current thread. */ THD *m_thd;
diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 5e58ceb..f7eed09 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -6932,11 +6932,28 @@ mysql_new_select(LEX *lex, bool move_down) } else { + bool const outer_most= (lex->current_select->master_unit() == &lex->unit); + if (outer_most && lex->result) + { + my_error(ER_WRONG_USAGE, MYF(0), "UNION", "INTO"); + DBUG_RETURN(TRUE); + } + if (lex->proc_list.elements!=0) + { + my_error(ER_WRONG_USAGE, MYF(0), "UNION", + "SELECT ... PROCEDURE ANALYSE()"); + DBUG_RETURN(TRUE); + }
why couldn't parser do it?
if (lex->current_select->order_list.first && !lex->current_select->braces) { my_error(ER_WRONG_USAGE, MYF(0), "UNION", "ORDER BY"); DBUG_RETURN(1); } + if (lex->current_select->explicit_limit && !lex->current_select->braces) + { + my_error(ER_WRONG_USAGE, MYF(0), "UNION", "LIMIT"); + DBUG_RETURN(1); + }
why couldn't parser do it?
select_lex->include_neighbour(lex->current_select); SELECT_LEX_UNIT *unit= select_lex->master_unit(); if (!unit->fake_select_lex && unit->add_fake_select_lex(lex->thd)) diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index 0e2db26..b79c2ce 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -1,5 +1,5 @@ /* - Copyright (c) 2000, 2015, Oracle and/or its affiliates. + Copyrig ht(c) 2000, 2015, Oracle and/or its affiliates.
typo?
Copyright (c) 2010, 2015, MariaDB
This program is free software; you can redistribute it and/or modify @@ -1001,10 +1001,10 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize); %parse-param { THD *thd } %lex-param { THD *thd } /* - Currently there are 164 shift/reduce conflicts. + Currently there are 160 shift/reduce conflicts. We should not introduce new conflicts any more. */ -%expect 164 +%expect 160
/* Comments for TOKENS. @@ -1731,6 +1731,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize); opt_default_time_precision case_stmt_body opt_bin_mod opt_if_exists_table_element opt_if_not_exists_table_element + opt_into opt_procedure_clause
%type <object_ddl_options> create_or_replace @@ -5548,7 +5549,7 @@ create_select: { Select->parsing_place= NO_MATTER; } - opt_select_from + table_expression { /* The following work only with the local list, the global list @@ -5943,11 +5944,6 @@ merge_insert_types: | LAST_SYM { $$= MERGE_INSERT_TO_LAST; } ;
-opt_select_from: - opt_limit_clause {} - | select_from opt_select_lock_type - ; - udf_type: STRING_SYM {$$ = (int) STRING_RESULT; } | REAL {$$ = (int) REAL_RESULT; } @@ -8397,6 +8393,7 @@ select_paren_derived: Lex->current_select->set_braces(true); } SELECT_SYM select_part2_derived + table_expression { if (setup_select_in_parentheses(Lex)) MYSQL_YYABORT; @@ -8414,7 +8411,45 @@ select_init2: union_clause ;
+/* + Theoretically we can merge all 3 right hand sides of the select_part2 + rule into one, however such a transformation adds one shift/reduce + conflict more. +*/ select_part2: + select_options_and_item_list + opt_order_clause + opt_limit_clause + opt_select_lock_type + | select_options_and_item_list into opt_select_lock_type + | select_options_and_item_list + opt_into + from_clause + opt_where_clause + opt_group_clause + opt_having_clause + opt_order_clause + opt_limit_clause + opt_procedure_clause + opt_into + opt_select_lock_type
why not table_expression here?
+ { + if ($2 && $10) + { + /* double "INTO" clause */ + my_error(ER_WRONG_USAGE, MYF(0), "INTO", "INTO"); + MYSQL_YYABORT; + } + if ($9 && ($2 || $10)) + { + /* "INTO" with "PROCEDURE ANALYSE" */ + my_error(ER_WRONG_USAGE, MYF(0), "PROCEDURE", "INTO"); + MYSQL_YYABORT; + } + }
Why couldn't parser do that?
+ ; + +select_options_and_item_list: { LEX *lex= Lex; SELECT_LEX *sel= lex->current_select; @@ -8426,27 +8461,36 @@ select_part2: { Select->parsing_place= NO_MATTER; } - select_into opt_select_lock_type ;
-select_into: - opt_order_clause opt_limit_clause {} - | into - | select_from - | into select_from - | select_from into +table_expression: + opt_from_clause + opt_where_clause + opt_group_clause + opt_having_clause + opt_order_clause + opt_limit_clause + opt_procedure_clause + opt_select_lock_type + ; + +from_clause: + FROM table_reference_list + ; + +opt_from_clause: + /* empty */ + | from_clause ;
-select_from: - FROM join_table_list +table_reference_list: + join_table_list { Select->context.table_list= Select->context.first_name_resolution_table= Select->table_list.first; } - opt_where_clause opt_group_clause opt_having_clause - opt_order_clause opt_limit_clause opt_procedure_clause - | FROM DUAL_SYM opt_where_clause opt_limit_clause + | DUAL_SYM /* oracle compatibility: oracle always requires FROM clause, and DUAL is system table without fields. Is "SELECT 1 FROM DUAL" any better than "SELECT 1" ? @@ -10888,9 +10932,7 @@ select_derived_union: last select in the union. */ Lex->pop_context(); - } - opt_union_order_or_limit - { + if ($1 != NULL) { my_parse_error(ER_THD(thd, ER_SYNTAX_ERROR)); @@ -10910,12 +10952,14 @@ select_init2_derived: my_parse_error(ER_THD(thd, ER_SYNTAX_ERROR)); MYSQL_YYABORT; } + /* if (sel->linkage == UNION_TYPE && sel->master_unit()->first_select()->braces) { my_parse_error(ER_THD(thd, ER_SYNTAX_ERROR)); MYSQL_YYABORT; } + */
what was wrong with that? if it's not needed anymore, delete it, don't just comment it out.
} ;
@@ -10932,7 +10976,6 @@ select_part2_derived: { Select->parsing_place= NO_MATTER; } - opt_select_from opt_select_lock_type ;
/* handle contents of parentheses in join expression */ @@ -10980,7 +11023,7 @@ select_derived2: { Select->parsing_place= NO_MATTER; } - opt_select_from + table_expression ;
get_select_lex: @@ -11556,7 +11599,7 @@ choice: ;
opt_procedure_clause: - /* empty */ + /* empty */ { $$= false; } | PROCEDURE_SYM ident /* Procedure name */ { LEX *lex=Lex; @@ -11585,6 +11628,9 @@ opt_procedure_clause: Lex->uncacheable(UNCACHEABLE_SIDEEFFECT); } '(' procedure_list ')' + { + $$= true; + } ;
procedure_list: @@ -11661,6 +11707,11 @@ select_outvar: } ;
+opt_into: + /* empty */ { $$= false; } + | into { $$= true; } + ; + into: INTO { @@ -12496,7 +12547,8 @@ show_param: { LEX *lex= Lex; lex->sql_command= SQLCOM_SHOW_BINLOG_EVENTS; - } opt_limit_clause + } + opt_limit_clause | RELAYLOG_SYM optional_connection_name EVENTS_SYM binlog_in binlog_from { LEX *lex= Lex; @@ -15836,17 +15888,19 @@ union_option:
query_specification: SELECT_SYM select_init2_derived - { + table_expression + { $$= Lex->current_select->master_unit()->first_select(); } | '(' select_paren_derived ')' + opt_union_order_or_limit { $$= Lex->current_select->master_unit()->first_select(); } ;
query_expression_body: - query_specification opt_union_order_or_limit + query_specification | query_expression_body UNION_SYM union_option { @@ -15854,7 +15908,6 @@ query_expression_body: MYSQL_YYABORT; } query_specification - opt_union_order_or_limit { Lex->pop_context(); $$= $1; diff --git a/mysql-test/r/parser.result b/mysql-test/r/parser.result index 1d29f2c..01cc9d7 100644 --- a/mysql-test/r/parser.result +++ b/mysql-test/r/parser.result @@ -650,3 +650,230 @@ CREATE TABLE t1(a INT); SELECT * FROM t1 JOIN ((SELECT 1 AS b) UNION ALL (SELECT 2 AS b) ORDER BY b DESC) s1 WHERE a=1; a b DROP TABLE t1; +# +# Test of collective fix for three parser bugs: +# +# Bug #17727401, Bug #17426017, Bug #17473479: +# The server accepts wrong syntax and then fails in different ways +# +CREATE TABLE t1 (i INT); +# bug #17426017 +SELECT (SELECT EXISTS(SELECT * LIMIT 1 ORDER BY VALUES (c00))); +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 'ORDER BY VALUES (c00)))' at line 1 +# bug#17473479 +CREATE TABLE a(a int); +CREATE TABLE b(a int); +DELETE FROM b ORDER BY(SELECT 1 FROM a ORDER BY a ORDER BY a); +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 'ORDER BY a)' at line 1 +DROP TABLE a, b; +# bug #17727401 +SELECT '' IN (SELECT '1' c FROM t1 ORDER BY '' ORDER BY '') FROM t1; +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 'ORDER BY '') FROM t1' at line 1 +# regression & coverage tests +# uniform syntax for FROM DUAL clause: +SELECT 1 FROM DUAL WHERE 1 GROUP BY 1 HAVING 1 ORDER BY 1 +FOR UPDATE; +1 +1 +SELECT 1 FROM DUAL WHERE 1 GROUP BY 1 HAVING 1 ORDER BY 1 +PROCEDURE ANALYSE() FOR UPDATE; +ERROR HY000: Can't use ORDER clause with this procedure +SELECT 1 FROM +(SELECT 1 FROM DUAL WHERE 1 GROUP BY 1 HAVING 1 ORDER BY 1 +FOR UPDATE) a; +1 +1 +SELECT 1 FROM +(SELECT 1 FROM DUAL WHERE 1 GROUP BY 1 HAVING 1 ORDER BY 1 +PROCEDURE ANALYSE() FOR UPDATE) a; +ERROR HY000: Incorrect usage of PROCEDURE and subquery +SELECT 1 FROM t1 +WHERE EXISTS(SELECT 1 FROM DUAL WHERE 1 GROUP BY 1 HAVING 1 ORDER BY 1 +FOR UPDATE); +1 +SELECT 1 FROM t1 +WHERE EXISTS(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 +SELECT 1 FROM t1 +UNION +SELECT 1 FROM DUAL WHERE 1 GROUP BY 1 HAVING 1 ORDER BY 1 +FOR UPDATE; +1 +1 +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 +SELECT 1 FROM DUAL PROCEDURE ANALYSE() +UNION +SELECT 1 FROM t1; +ERROR HY000: Incorrect usage of UNION and SELECT ... PROCEDURE ANALYSE() +(SELECT 1 FROM t1) +UNION +(SELECT 1 FROM DUAL WHERE 1 GROUP BY 1 HAVING 1 ORDER BY 1 +FOR UPDATE); +1 +1 +(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 +# "FOR UPDATE" tests +SELECT 1 FROM t1 UNION SELECT 1 FROM t1 ORDER BY 1 LIMIT 1; +1 +SELECT 1 FROM t1 FOR UPDATE UNION SELECT 1 FROM t1 ORDER BY 1 LIMIT 1; +1 +SELECT 1 FROM t1 UNION SELECT 1 FROM t1 ORDER BY 1 LIMIT 1 FOR UPDATE; +1 +# "INTO" clause tests +SELECT 1 FROM t1 INTO @var17727401; +Warnings: +Warning 1329 No data - zero rows fetched, selected, or processed +SELECT 1 FROM DUAL INTO @var17727401; +SELECT 1 INTO @var17727401; +SELECT 1 INTO @var17727401 FROM t1; +Warnings: +Warning 1329 No data - zero rows fetched, selected, or processed +SELECT 1 INTO @var17727401 FROM DUAL; +SELECT 1 INTO @var17727401_1 FROM t1 INTO @var17727401_2; +ERROR HY000: Incorrect usage of INTO and INTO +SELECT 1 INTO @var17727401_1 FROM DUAL +INTO @var17727401_2; +ERROR HY000: Incorrect usage of INTO and INTO +SELECT 1 INTO @var17727401 FROM t1 WHERE 1 GROUP BY 1 HAVING 1 ORDER BY 1 LIMIT 1; +Warnings: +Warning 1329 No data - zero rows fetched, selected, or processed +SELECT 1 FROM t1 WHERE 1 GROUP BY 1 HAVING 1 ORDER BY 1 LIMIT 1 INTO @var17727401; +Warnings: +Warning 1329 No data - zero rows fetched, selected, or processed +SELECT 1 FROM t1 WHERE 1 INTO @var17727401 GROUP BY 1 HAVING 1 ORDER BY 1 LIMIT 1; +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 'GROUP BY 1 HAVING 1 ORDER BY 1 LIMIT 1' at line 1 +SELECT 1 INTO @var17727401_1 +FROM t1 WHERE 1 GROUP BY 1 HAVING 1 ORDER BY 1 LIMIT 1 +INTO @var17727401_2; +ERROR HY000: Incorrect usage of INTO and INTO +SELECT (SELECT 1 FROM t1 INTO @var17727401); +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 'INTO @var17727401)' at line 1 +SELECT 1 FROM (SELECT 1 FROM t1 INTO @var17727401) a; +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 'INTO @var17727401) a' at line 1 +SELECT EXISTS(SELECT 1 FROM t1 INTO @var17727401); +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 'INTO @var17727401)' at line 1 +SELECT 1 FROM t1 INTO @var17727401 UNION SELECT 1 FROM t1 INTO t1; +ERROR HY000: Incorrect usage of UNION and INTO +(SELECT 1 FROM t1 INTO @var17727401) UNION (SELECT 1 FROM t1 INTO t1); +ERROR HY000: Incorrect usage of UNION and INTO +SELECT 1 FROM t1 UNION SELECT 1 FROM t1 INTO @var17727401; +Warnings: +Warning 1329 No data - zero rows fetched, selected, or processed +SELECT 1 INTO @var17727401 FROM t1 PROCEDURE ANALYSE(); +ERROR HY000: Incorrect usage of PROCEDURE and INTO +SELECT 1 FROM t1 PROCEDURE ANALYSE() INTO @var17727401; +ERROR HY000: Incorrect usage of PROCEDURE and INTO +# ORDER and LIMIT clause combinations +(SELECT 1 FROM t1 ORDER BY 1) ORDER BY 1; +1 +(SELECT 1 FROM t1 LIMIT 1) LIMIT 1; +1 +((SELECT 1 FROM t1 ORDER BY 1) ORDER BY 1) ORDER BY 1; +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 'ORDER BY 1) ORDER BY 1' at line 1 +((SELECT 1 FROM t1 LIMIT 1) LIMIT 1) LIMIT 1; +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 'LIMIT 1) LIMIT 1' at line 1 +(SELECT 1 FROM t1 ORDER BY 1) LIMIT 1; +1 +(SELECT 1 FROM t1 LIMIT 1) ORDER BY 1; +1 +((SELECT 1 FROM t1 ORDER BY 1) LIMIT 1) ORDER BY 1); +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 'LIMIT 1) ORDER BY 1)' at line 1 +((SELECT 1 FROM t1 LIMIT 1) ORDER BY 1) LIMIT 1); +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 'ORDER BY 1) LIMIT 1)' at line 1 +SELECT 1 FROM t1 UNION SELECT 1 FROM t1 ORDER BY 1; +1 +SELECT (SELECT 1 FROM t1 UNION SELECT 1 FROM t1 ORDER BY 1); +(SELECT 1 FROM t1 UNION SELECT 1 FROM t1 ORDER BY 1) +NULL +SELECT 1 FROM (SELECT 1 FROM t1 UNION SELECT 1 FROM t1 ORDER BY 1) a; +1 +SELECT 1 FROM t1 UNION SELECT 1 FROM t1 LIMIT 1; +1 +SELECT (SELECT 1 FROM t1 UNION SELECT 1 FROM t1 LIMIT 1); +(SELECT 1 FROM t1 UNION SELECT 1 FROM t1 LIMIT 1) +NULL +SELECT 1 FROM (SELECT 1 FROM t1 UNION SELECT 1 FROM t1 LIMIT 1) a; +1 +SELECT 1 FROM t1 UNION SELECT 1 FROM t1 ORDER BY 1 LIMIT 1; +1 +SELECT (SELECT 1 FROM t1 UNION SELECT 1 FROM t1 ORDER BY 1 LIMIT 1); +(SELECT 1 FROM t1 UNION SELECT 1 FROM t1 ORDER BY 1 LIMIT 1) +NULL +SELECT 1 FROM (SELECT 1 FROM t1 UNION SELECT 1 FROM t1 ORDER BY 1 LIMIT 1) a; +1 +SELECT 1 FROM t1 UNION SELECT 1 FROM t1 LIMIT 1 ORDER BY 1; +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 'ORDER BY 1' at line 1 +SELECT (SELECT 1 FROM t1 UNION SELECT 1 FROM t1 LIMIT 1 ORDER BY 1); +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 'ORDER BY 1)' at line 1 +SELECT 1 FROM (SELECT 1 FROM t1 UNION SELECT 1 FROM t1 LIMIT 1 ORDER BY 1) a; +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 'ORDER BY 1) a' at line 1 +SELECT 1 FROM t1 ORDER BY 1 UNION SELECT 1 FROM t1; +ERROR HY000: Incorrect usage of UNION and ORDER BY +SELECT (SELECT 1 FROM t1 ORDER BY 1 UNION SELECT 1 FROM t1); +ERROR HY000: Incorrect usage of UNION and ORDER BY +SELECT 1 FROM (SELECT 1 FROM t1 ORDER BY 1 UNION SELECT 1 FROM t1) a; +ERROR HY000: Incorrect usage of UNION and ORDER BY +SELECT 1 FROM t1 LIMIT 1 UNION SELECT 1 FROM t1; +ERROR HY000: Incorrect usage of UNION and LIMIT +SELECT (SELECT 1 FROM t1 LIMIT 1 UNION SELECT 1 FROM t1); +ERROR HY000: Incorrect usage of UNION and LIMIT +SELECT 1 FROM (SELECT 1 FROM t1 LIMIT 1 UNION SELECT 1 FROM t1) a; +ERROR HY000: Incorrect usage of UNION and LIMIT +SELECT 1 FROM t1 ORDER BY 1 LIMIT 1 UNION SELECT 1 FROM t1; +ERROR HY000: Incorrect usage of UNION and ORDER BY +SELECT (SELECT 1 FROM t1 ORDER BY 1 LIMIT 1 UNION SELECT 1 FROM t1); +ERROR HY000: Incorrect usage of UNION and ORDER BY +SELECT 1 FROM (SELECT 1 FROM t1 ORDER BY 1 LIMIT 1 UNION SELECT 1 FROM t1) a; +ERROR HY000: Incorrect usage of UNION and ORDER BY +SELECT 1 FROM t1 LIMIT 1 ORDER BY 1 UNION SELECT 1 FROM t1; +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 'ORDER BY 1 UNION SELECT 1 FROM t1' at line 1 +SELECT (SELECT 1 FROM t1 LIMIT 1 ORDER BY 1 UNION SELECT 1 FROM t1); +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 'ORDER BY 1 UNION SELECT 1 FROM t1)' at line 1 +SELECT 1 FROM (SELECT 1 FROM t1 LIMIT 1 ORDER BY 1 UNION SELECT 1 FROM t1) a; +ERROR HY000: Incorrect usage of UNION and ORDER BY +SELECT 1 FROM t1 ORDER BY 1 UNION SELECT 1 FROM t1 ORDER BY 1; +ERROR HY000: Incorrect usage of UNION and ORDER BY +SELECT (SELECT 1 FROM t1 ORDER BY 1 UNION SELECT 1 FROM t1 ORDER BY 1); +ERROR HY000: Incorrect usage of UNION and ORDER BY +SELECT 1 FROM (SELECT 1 FROM t1 ORDER BY 1 UNION SELECT 1 FROM t1 ORDER BY 1) a; +ERROR HY000: Incorrect usage of UNION and ORDER BY +SELECT 1 FROM t1 LIMIT 1 UNION SELECT 1 FROM t1 LIMIT 1; +ERROR HY000: Incorrect usage of UNION and LIMIT +SELECT (SELECT 1 FROM t1 LIMIT 1 UNION SELECT 1 FROM t1 LIMIT 1); +ERROR HY000: Incorrect usage of UNION and LIMIT +SELECT 1 FROM (SELECT 1 FROM t1 LIMIT 1 UNION SELECT 1 FROM t1 LIMIT 1) a; +ERROR HY000: Incorrect usage of UNION and LIMIT +SELECT 1 FROM t1 LIMIT 1 UNION SELECT 1 FROM t1 ORDER BY 1; +ERROR HY000: Incorrect usage of UNION and LIMIT +SELECT (SELECT 1 FROM t1 LIMIT 1 UNION SELECT 1 FROM t1 ORDER BY 1); +ERROR HY000: Incorrect usage of UNION and LIMIT +SELECT 1 FROM (SELECT 1 FROM t1 LIMIT 1 UNION SELECT 1 FROM t1 ORDER BY 1) a; +ERROR HY000: Incorrect usage of UNION and LIMIT +SELECT 1 FROM t1 ORDER BY 1 UNION SELECT 1 FROM t1 LIMIT 1; +ERROR HY000: Incorrect usage of UNION and ORDER BY +SELECT (SELECT 1 FROM t1 ORDER BY 1 UNION SELECT 1 FROM t1 LIMIT 1); +ERROR HY000: Incorrect usage of UNION and ORDER BY +SELECT 1 FROM (SELECT 1 FROM t1 ORDER BY 1 UNION SELECT 1 FROM t1 LIMIT 1) a; +ERROR HY000: Incorrect usage of UNION and ORDER BY +DROP TABLE t1; +# +# MDEV-8380: Subquery parse error +# +CREATE TABLE t1 ( a INT); +INSERT INTO t1 VALUES ( 2 ); +SELECT * +FROM ( (SELECT a FROM t1 ORDER BY a) UNION (SELECT 1 as b ORDER BY b ) ) AS a1 +WHERE a1.a = 1 OR a1.a = 2; +a +2 +1 +DROP TABLE t1; diff --git a/mysql-test/r/subselect.result b/mysql-test/r/subselect.result index 3732f62..b9f9fb0 100644 --- a/mysql-test/r/subselect.result +++ b/mysql-test/r/subselect.result @@ -5132,8 +5132,9 @@ SELECT a FROM t1 WHERE a = 2 a 1 2 -SELECT * FROM ((SELECT 1 a) UNION SELECT 1 a); -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 ')' at line 1 +SELECT * FROM ((SELECT 1 a) UNION SELECT 1 a) q; +a +1 SELECT * FROM (SELECT 1 a UNION (SELECT 1 a)) alias; a 1 @@ -5175,7 +5176,7 @@ a 1 1 1 2 1 SELECT * FROM t1 JOIN ((SELECT 1 UNION SELECT 1)) ON 1; -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 ')) ON 1' at line 1 +ERROR 42000: Every derived table must have its own alias SELECT * FROM t1 JOIN (t1 t1a UNION SELECT 1) ON 1; 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 ') ON 1' at line 1 SELECT * FROM t1 JOIN ((t1 t1a UNION SELECT 1)) ON 1; @@ -5294,7 +5295,10 @@ SELECT ((SELECT 1 UNION SELECT 1 UNION SELECT 1)); SELECT * FROM ( SELECT 1 UNION ( SELECT 1 UNION SELECT 1 ) ); 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 'UNION SELECT 1 ) )' at line 1 SELECT * FROM ( ( SELECT 1 UNION SELECT 1 ) UNION SELECT 1 ); -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 ') UNION SELECT 1 )' at line 1 +ERROR 42000: Every derived table must have its own alias +SELECT * FROM ( ( SELECT 1 UNION SELECT 1 ) UNION SELECT 1 ) a; +1 +1 SELECT * FROM ( SELECT 1 UNION SELECT 1 UNION SELECT 1 ) a; 1 1 diff --git a/mysql-test/r/subselect_no_exists_to_in.result b/mysql-test/r/subselect_no_exists_to_in.result index 140b790..902c45f 100644 --- a/mysql-test/r/subselect_no_exists_to_in.result +++ b/mysql-test/r/subselect_no_exists_to_in.result @@ -5134,8 +5134,9 @@ SELECT a FROM t1 WHERE a = 2 a 1 2 -SELECT * FROM ((SELECT 1 a) UNION SELECT 1 a); -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 ')' at line 1 +SELECT * FROM ((SELECT 1 a) UNION SELECT 1 a) q; +a +1 SELECT * FROM (SELECT 1 a UNION (SELECT 1 a)) alias; a 1 @@ -5177,7 +5178,7 @@ a 1 1 1 2 1 SELECT * FROM t1 JOIN ((SELECT 1 UNION SELECT 1)) ON 1; -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 ')) ON 1' at line 1 +ERROR 42000: Every derived table must have its own alias SELECT * FROM t1 JOIN (t1 t1a UNION SELECT 1) ON 1; 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 ') ON 1' at line 1 SELECT * FROM t1 JOIN ((t1 t1a UNION SELECT 1)) ON 1; @@ -5296,7 +5297,10 @@ SELECT ((SELECT 1 UNION SELECT 1 UNION SELECT 1)); SELECT * FROM ( SELECT 1 UNION ( SELECT 1 UNION SELECT 1 ) ); 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 'UNION SELECT 1 ) )' at line 1 SELECT * FROM ( ( SELECT 1 UNION SELECT 1 ) UNION SELECT 1 ); -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 ') UNION SELECT 1 )' at line 1 +ERROR 42000: Every derived table must have its own alias +SELECT * FROM ( ( SELECT 1 UNION SELECT 1 ) UNION SELECT 1 ) a; +1 +1 SELECT * FROM ( SELECT 1 UNION SELECT 1 UNION SELECT 1 ) a; 1 1 diff --git a/mysql-test/r/subselect_no_mat.result b/mysql-test/r/subselect_no_mat.result index 99ac9f4..89034b7 100644 --- a/mysql-test/r/subselect_no_mat.result +++ b/mysql-test/r/subselect_no_mat.result @@ -5132,8 +5132,9 @@ SELECT a FROM t1 WHERE a = 2 a 1 2 -SELECT * FROM ((SELECT 1 a) UNION SELECT 1 a); -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 ')' at line 1 +SELECT * FROM ((SELECT 1 a) UNION SELECT 1 a) q; +a +1 SELECT * FROM (SELECT 1 a UNION (SELECT 1 a)) alias; a 1 @@ -5175,7 +5176,7 @@ a 1 1 1 2 1 SELECT * FROM t1 JOIN ((SELECT 1 UNION SELECT 1)) ON 1; -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 ')) ON 1' at line 1 +ERROR 42000: Every derived table must have its own alias SELECT * FROM t1 JOIN (t1 t1a UNION SELECT 1) ON 1; 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 ') ON 1' at line 1 SELECT * FROM t1 JOIN ((t1 t1a UNION SELECT 1)) ON 1; @@ -5294,7 +5295,10 @@ SELECT ((SELECT 1 UNION SELECT 1 UNION SELECT 1)); SELECT * FROM ( SELECT 1 UNION ( SELECT 1 UNION SELECT 1 ) ); 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 'UNION SELECT 1 ) )' at line 1 SELECT * FROM ( ( SELECT 1 UNION SELECT 1 ) UNION SELECT 1 ); -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 ') UNION SELECT 1 )' at line 1 +ERROR 42000: Every derived table must have its own alias +SELECT * FROM ( ( SELECT 1 UNION SELECT 1 ) UNION SELECT 1 ) a; +1 +1 SELECT * FROM ( SELECT 1 UNION SELECT 1 UNION SELECT 1 ) a; 1 1 diff --git a/mysql-test/r/subselect_no_opts.result b/mysql-test/r/subselect_no_opts.result index 7ecd40c..6e90aac 100644 --- a/mysql-test/r/subselect_no_opts.result +++ b/mysql-test/r/subselect_no_opts.result @@ -5128,8 +5128,9 @@ SELECT a FROM t1 WHERE a = 2 a 1 2 -SELECT * FROM ((SELECT 1 a) UNION SELECT 1 a); -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 ')' at line 1 +SELECT * FROM ((SELECT 1 a) UNION SELECT 1 a) q; +a +1 SELECT * FROM (SELECT 1 a UNION (SELECT 1 a)) alias; a 1 @@ -5171,7 +5172,7 @@ a 1 1 1 2 1 SELECT * FROM t1 JOIN ((SELECT 1 UNION SELECT 1)) ON 1; -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 ')) ON 1' at line 1 +ERROR 42000: Every derived table must have its own alias SELECT * FROM t1 JOIN (t1 t1a UNION SELECT 1) ON 1; 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 ') ON 1' at line 1 SELECT * FROM t1 JOIN ((t1 t1a UNION SELECT 1)) ON 1; @@ -5290,7 +5291,10 @@ SELECT ((SELECT 1 UNION SELECT 1 UNION SELECT 1)); SELECT * FROM ( SELECT 1 UNION ( SELECT 1 UNION SELECT 1 ) ); 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 'UNION SELECT 1 ) )' at line 1 SELECT * FROM ( ( SELECT 1 UNION SELECT 1 ) UNION SELECT 1 ); -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 ') UNION SELECT 1 )' at line 1 +ERROR 42000: Every derived table must have its own alias +SELECT * FROM ( ( SELECT 1 UNION SELECT 1 ) UNION SELECT 1 ) a; +1 +1 SELECT * FROM ( SELECT 1 UNION SELECT 1 UNION SELECT 1 ) a; 1 1 diff --git a/mysql-test/r/subselect_no_scache.result b/mysql-test/r/subselect_no_scache.result index c70db6f..1c18817 100644 --- a/mysql-test/r/subselect_no_scache.result +++ b/mysql-test/r/subselect_no_scache.result @@ -5138,8 +5138,9 @@ SELECT a FROM t1 WHERE a = 2 a 1 2 -SELECT * FROM ((SELECT 1 a) UNION SELECT 1 a); -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 ')' at line 1 +SELECT * FROM ((SELECT 1 a) UNION SELECT 1 a) q; +a +1 SELECT * FROM (SELECT 1 a UNION (SELECT 1 a)) alias; a 1 @@ -5181,7 +5182,7 @@ a 1 1 1 2 1 SELECT * FROM t1 JOIN ((SELECT 1 UNION SELECT 1)) ON 1; -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 ')) ON 1' at line 1 +ERROR 42000: Every derived table must have its own alias SELECT * FROM t1 JOIN (t1 t1a UNION SELECT 1) ON 1; 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 ') ON 1' at line 1 SELECT * FROM t1 JOIN ((t1 t1a UNION SELECT 1)) ON 1; @@ -5300,7 +5301,10 @@ SELECT ((SELECT 1 UNION SELECT 1 UNION SELECT 1)); SELECT * FROM ( SELECT 1 UNION ( SELECT 1 UNION SELECT 1 ) ); 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 'UNION SELECT 1 ) )' at line 1 SELECT * FROM ( ( SELECT 1 UNION SELECT 1 ) UNION SELECT 1 ); -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 ') UNION SELECT 1 )' at line 1 +ERROR 42000: Every derived table must have its own alias +SELECT * FROM ( ( SELECT 1 UNION SELECT 1 ) UNION SELECT 1 ) a; +1 +1 SELECT * FROM ( SELECT 1 UNION SELECT 1 UNION SELECT 1 ) a; 1 1 diff --git a/mysql-test/r/subselect_no_semijoin.result b/mysql-test/r/subselect_no_semijoin.result index 6a7d6b3..de9c4e8 100644 --- a/mysql-test/r/subselect_no_semijoin.result +++ b/mysql-test/r/subselect_no_semijoin.result @@ -5128,8 +5128,9 @@ SELECT a FROM t1 WHERE a = 2 a 1 2 -SELECT * FROM ((SELECT 1 a) UNION SELECT 1 a); -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 ')' at line 1 +SELECT * FROM ((SELECT 1 a) UNION SELECT 1 a) q; +a +1 SELECT * FROM (SELECT 1 a UNION (SELECT 1 a)) alias; a 1 @@ -5171,7 +5172,7 @@ a 1 1 1 2 1 SELECT * FROM t1 JOIN ((SELECT 1 UNION SELECT 1)) ON 1; -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 ')) ON 1' at line 1 +ERROR 42000: Every derived table must have its own alias SELECT * FROM t1 JOIN (t1 t1a UNION SELECT 1) ON 1; 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 ') ON 1' at line 1 SELECT * FROM t1 JOIN ((t1 t1a UNION SELECT 1)) ON 1; @@ -5290,7 +5291,10 @@ SELECT ((SELECT 1 UNION SELECT 1 UNION SELECT 1)); SELECT * FROM ( SELECT 1 UNION ( SELECT 1 UNION SELECT 1 ) ); 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 'UNION SELECT 1 ) )' at line 1 SELECT * FROM ( ( SELECT 1 UNION SELECT 1 ) UNION SELECT 1 ); -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 ') UNION SELECT 1 )' at line 1 +ERROR 42000: Every derived table must have its own alias +SELECT * FROM ( ( SELECT 1 UNION SELECT 1 ) UNION SELECT 1 ) a; +1 +1 SELECT * FROM ( SELECT 1 UNION SELECT 1 UNION SELECT 1 ) a; 1 1 diff --git a/mysql-test/r/union.result b/mysql-test/r/union.result index ef1749e..9b7a1c5 100644 --- a/mysql-test/r/union.result +++ b/mysql-test/r/union.result @@ -89,6 +89,10 @@ id select_type table type possible_keys key key_len ref rows filtered Extra NULL UNION RESULT <union1,2> ALL NULL NULL NULL NULL NULL NULL Using filesort Warnings: Note 1003 (select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` from `test`.`t1` limit 2) union all (select `test`.`t2`.`a` AS `a`,`test`.`t2`.`b` AS `b` from `test`.`t2` order by `test`.`t2`.`a` limit 1) order by `b` desc +select count(*) from ( +(select a,b from t1 limit 2) union all (select a,b from t2 order by a)) q; +count(*) +6 (select sql_calc_found_rows a,b from t1 limit 2) union all (select a,b from t2 order by a) limit 2; a b 1 a @@ -96,6 +100,10 @@ a b select found_rows(); found_rows() 6 +select count(*) from ( +select a,b from t1 union all select a,b from t2) q; +count(*) +8 select sql_calc_found_rows a,b from t1 union all select a,b from t2 limit 2; a b 1 a @@ -308,12 +316,20 @@ create table t1 (a int); insert into t1 values (1),(2),(3); create table t2 (a int); insert into t2 values (3),(4),(5); +SELECT COUNT(*) FROM ( +(SELECT * FROM t1) UNION all (SELECT * FROM t2)) q; +COUNT(*) +6 (SELECT SQL_CALC_FOUND_ROWS * FROM t1) UNION all (SELECT * FROM t2) LIMIT 1; a 1 select found_rows(); found_rows() 6 +SELECT COUNT(*) FROM ( +(SELECT * FROM t1 LIMIT 1) UNION all (SELECT * FROM t2)) q; +COUNT(*) +4 (SELECT SQL_CALC_FOUND_ROWS * FROM t1 LIMIT 1) UNION all (SELECT * FROM t2) LIMIT 2; a 1 @@ -321,6 +337,10 @@ a select found_rows(); found_rows() 4 +SELECT COUNT(*) FROM ( +(SELECT * FROM t1 LIMIT 1) UNION all (SELECT * FROM t2)) q; +COUNT(*) +4 (SELECT SQL_CALC_FOUND_ROWS * FROM t1 LIMIT 1) UNION all (SELECT * FROM t2); a 1 @@ -330,6 +350,10 @@ a select found_rows(); found_rows() 4 +SELECT COUNT(*) FROM ( +(SELECT * FROM t1) UNION all (SELECT * FROM t2 LIMIT 1)) q; +COUNT(*) +4 (SELECT SQL_CALC_FOUND_ROWS * FROM t1) UNION all (SELECT * FROM t2 LIMIT 1); a 1 @@ -345,6 +369,16 @@ a select found_rows(); found_rows() 4 +SELECT COUNT(*) FROM ( +(SELECT * FROM t1 LIMIT 1) UNION SELECT * FROM t2) q; +COUNT(*) +4 +(SELECT SQL_CALC_FOUND_ROWS * FROM t1 LIMIT 1) UNION SELECT * FROM t2 LIMIT 1; +a +1 +select found_rows(); +found_rows() +4 SELECT SQL_CALC_FOUND_ROWS * FROM t1 LIMIT 1 UNION all SELECT * FROM t2 LIMIT 2; ERROR HY000: Incorrect usage of UNION and LIMIT SELECT SQL_CALC_FOUND_ROWS * FROM t1 UNION all SELECT * FROM t2 LIMIT 2; @@ -354,13 +388,29 @@ a select found_rows(); found_rows() 6 +SELECT COUNT(*) FROM ( +SELECT * FROM t1 UNION SELECT * FROM t2) q; +COUNT(*) +5 SELECT SQL_CALC_FOUND_ROWS * FROM t1 UNION SELECT * FROM t2 LIMIT 2; a 1 2 +SELECT COUNT(*) FROM ( +(SELECT * FROM t1 LIMIT 1) UNION all SELECT * FROM t2) q; +COUNT(*) +4 +(SELECT SQL_CALC_FOUND_ROWS * FROM t1 LIMIT 1) UNION all SELECT * FROM t2 LIMIT 2; +a +1 +3 select found_rows(); found_rows() -5 +4 +SELECT COUNT(*) FROM ( +SELECT * FROM t1 UNION all SELECT * FROM t2) q; +COUNT(*) +6 SELECT SQL_CALC_FOUND_ROWS * FROM t1 UNION SELECT * FROM t2 LIMIT 100; a 1 @@ -373,10 +423,39 @@ found_rows() 5 SELECT SQL_CALC_FOUND_ROWS * FROM t1 LIMIT 100 UNION SELECT * FROM t2; ERROR HY000: Incorrect usage of UNION and LIMIT +SELECT COUNT(*) FROM ( +(SELECT * FROM t1 LIMIT 100) UNION SELECT * FROM t2) q; +COUNT(*) +5 +(SELECT SQL_CALC_FOUND_ROWS * FROM t1 LIMIT 100) UNION SELECT * FROM t2; +a +1 +2 +3 +4 +5 SELECT SQL_CALC_FOUND_ROWS * FROM t1 LIMIT 1 UNION SELECT * FROM t2; ERROR HY000: Incorrect usage of UNION and LIMIT +SELECT COUNT(*) FROM ( +(SELECT * FROM t1 LIMIT 1) UNION SELECT * FROM t2) q; +COUNT(*) +4 +(SELECT SQL_CALC_FOUND_ROWS * FROM t1 LIMIT 1) UNION SELECT * FROM t2; +a +1 +3 +4 +5 SELECT SQL_CALC_FOUND_ROWS * FROM t1 LIMIT 1 UNION SELECT * FROM t2 LIMIT 2; ERROR HY000: Incorrect usage of UNION and LIMIT +SELECT COUNT(*) FROM ( +(SELECT * FROM t1 LIMIT 1) UNION SELECT * FROM t2) q; +COUNT(*) +4 +(SELECT SQL_CALC_FOUND_ROWS * FROM t1 LIMIT 1) UNION SELECT * FROM t2 LIMIT 2; +a +1 +3 SELECT SQL_CALC_FOUND_ROWS * FROM t1 UNION SELECT * FROM t2 LIMIT 2,2; a 3 @@ -384,8 +463,21 @@ a select found_rows(); found_rows() 5 +SELECT COUNT(*) FROM ( +SELECT * FROM t1 UNION SELECT * FROM t2) q; +COUNT(*) +5 SELECT SQL_CALC_FOUND_ROWS * FROM t1 limit 2,2 UNION SELECT * FROM t2; ERROR HY000: Incorrect usage of UNION and LIMIT +SELECT COUNT(*) FROM ( +(SELECT * FROM t1 limit 2,2) UNION SELECT * FROM t2) q; +COUNT(*) +3 +(SELECT SQL_CALC_FOUND_ROWS * FROM t1 limit 2,2) UNION SELECT * FROM t2; +a +3 +4 +5 SELECT * FROM t1 UNION SELECT * FROM t2 ORDER BY a desc LIMIT 1; a 5 diff --git a/mysql-test/t/parser.test b/mysql-test/t/parser.test index 31c6ab9..0a19b03 100644 --- a/mysql-test/t/parser.test +++ b/mysql-test/t/parser.test @@ -765,3 +765,259 @@ DROP TABLE t1; CREATE TABLE t1(a INT); SELECT * FROM t1 JOIN ((SELECT 1 AS b) UNION ALL (SELECT 2 AS b) ORDER BY b DESC) s1 WHERE a=1; DROP TABLE t1; + + +--echo # +--echo # Test of collective fix for three parser bugs: +--echo # +--echo # Bug #17727401, Bug #17426017, Bug #17473479: +--echo # The server accepts wrong syntax and then fails in different ways +--echo # + +CREATE TABLE t1 (i INT); + +--echo # bug #17426017 +--error ER_PARSE_ERROR +SELECT (SELECT EXISTS(SELECT * LIMIT 1 ORDER BY VALUES (c00))); + +--echo # bug#17473479 +CREATE TABLE a(a int); +CREATE TABLE b(a int); +--error ER_PARSE_ERROR +DELETE FROM b ORDER BY(SELECT 1 FROM a ORDER BY a ORDER BY a); +DROP TABLE a, b; + +--echo # bug #17727401 +--error ER_PARSE_ERROR +SELECT '' IN (SELECT '1' c FROM t1 ORDER BY '' ORDER BY '') FROM t1; + +--echo # regression & coverage tests + +--echo # uniform syntax for FROM DUAL clause: + +SELECT 1 FROM DUAL WHERE 1 GROUP BY 1 HAVING 1 ORDER BY 1 + FOR UPDATE; + +--error ER_ORDER_WITH_PROC +SELECT 1 FROM DUAL WHERE 1 GROUP BY 1 HAVING 1 ORDER BY 1 + PROCEDURE ANALYSE() FOR UPDATE; + +SELECT 1 FROM + (SELECT 1 FROM DUAL WHERE 1 GROUP BY 1 HAVING 1 ORDER BY 1 + FOR UPDATE) a; + +--error ER_WRONG_USAGE +SELECT 1 FROM + (SELECT 1 FROM DUAL WHERE 1 GROUP BY 1 HAVING 1 ORDER BY 1 + PROCEDURE ANALYSE() FOR UPDATE) a; + +SELECT 1 FROM t1 + WHERE EXISTS(SELECT 1 FROM DUAL WHERE 1 GROUP BY 1 HAVING 1 ORDER BY 1 + FOR UPDATE); + +--error ER_WRONG_USAGE +SELECT 1 FROM t1 + WHERE EXISTS(SELECT 1 FROM DUAL WHERE 1 GROUP BY 1 HAVING 1 ORDER BY 1 + PROCEDURE ANALYSE() FOR UPDATE); + +SELECT 1 FROM t1 +UNION +SELECT 1 FROM DUAL WHERE 1 GROUP BY 1 HAVING 1 ORDER BY 1 + FOR UPDATE; + +--error ER_WRONG_USAGE +SELECT 1 FROM t1 +UNION +SELECT 1 FROM DUAL WHERE 1 GROUP BY 1 HAVING 1 ORDER BY 1 + PROCEDURE ANALYSE() FOR UPDATE; + +--error ER_WRONG_USAGE +SELECT 1 FROM DUAL PROCEDURE ANALYSE() +UNION +SELECT 1 FROM t1; + +(SELECT 1 FROM t1) +UNION +(SELECT 1 FROM DUAL WHERE 1 GROUP BY 1 HAVING 1 ORDER BY 1 + FOR UPDATE); + +--error ER_WRONG_USAGE +(SELECT 1 FROM t1) +UNION +(SELECT 1 FROM DUAL WHERE 1 GROUP BY 1 HAVING 1 ORDER BY 1 + PROCEDURE ANALYSE() FOR UPDATE); + +--echo # "FOR UPDATE" tests + +SELECT 1 FROM t1 UNION SELECT 1 FROM t1 ORDER BY 1 LIMIT 1; +SELECT 1 FROM t1 FOR UPDATE UNION SELECT 1 FROM t1 ORDER BY 1 LIMIT 1; +SELECT 1 FROM t1 UNION SELECT 1 FROM t1 ORDER BY 1 LIMIT 1 FOR UPDATE; + + +--echo # "INTO" clause tests + +SELECT 1 FROM t1 INTO @var17727401; +SELECT 1 FROM DUAL INTO @var17727401; +SELECT 1 INTO @var17727401; + +SELECT 1 INTO @var17727401 FROM t1; +SELECT 1 INTO @var17727401 FROM DUAL; + +--error ER_WRONG_USAGE +SELECT 1 INTO @var17727401_1 FROM t1 INTO @var17727401_2; + +--error ER_WRONG_USAGE +SELECT 1 INTO @var17727401_1 FROM DUAL + INTO @var17727401_2; + +SELECT 1 INTO @var17727401 FROM t1 WHERE 1 GROUP BY 1 HAVING 1 ORDER BY 1 LIMIT 1; +SELECT 1 FROM t1 WHERE 1 GROUP BY 1 HAVING 1 ORDER BY 1 LIMIT 1 INTO @var17727401; + +--error ER_PARSE_ERROR +SELECT 1 FROM t1 WHERE 1 INTO @var17727401 GROUP BY 1 HAVING 1 ORDER BY 1 LIMIT 1; + +--error ER_WRONG_USAGE +SELECT 1 INTO @var17727401_1 + FROM t1 WHERE 1 GROUP BY 1 HAVING 1 ORDER BY 1 LIMIT 1 + INTO @var17727401_2; + +--error ER_PARSE_ERROR +SELECT (SELECT 1 FROM t1 INTO @var17727401); +--error ER_PARSE_ERROR +SELECT 1 FROM (SELECT 1 FROM t1 INTO @var17727401) a; +--error ER_PARSE_ERROR +SELECT EXISTS(SELECT 1 FROM t1 INTO @var17727401); + +--error ER_WRONG_USAGE +SELECT 1 FROM t1 INTO @var17727401 UNION SELECT 1 FROM t1 INTO t1; +--error ER_WRONG_USAGE +(SELECT 1 FROM t1 INTO @var17727401) UNION (SELECT 1 FROM t1 INTO t1); + +SELECT 1 FROM t1 UNION SELECT 1 FROM t1 INTO @var17727401; + +--error ER_WRONG_USAGE +SELECT 1 INTO @var17727401 FROM t1 PROCEDURE ANALYSE(); + +--error ER_WRONG_USAGE +SELECT 1 FROM t1 PROCEDURE ANALYSE() INTO @var17727401; + +--echo # ORDER and LIMIT clause combinations + +# Limited support for (SELECT ...) ORDER/LIMIT: + +(SELECT 1 FROM t1 ORDER BY 1) ORDER BY 1; +(SELECT 1 FROM t1 LIMIT 1) LIMIT 1; + +--error ER_PARSE_ERROR +((SELECT 1 FROM t1 ORDER BY 1) ORDER BY 1) ORDER BY 1; +--error ER_PARSE_ERROR +((SELECT 1 FROM t1 LIMIT 1) LIMIT 1) LIMIT 1; + +(SELECT 1 FROM t1 ORDER BY 1) LIMIT 1; +(SELECT 1 FROM t1 LIMIT 1) ORDER BY 1; + +--error ER_PARSE_ERROR +((SELECT 1 FROM t1 ORDER BY 1) LIMIT 1) ORDER BY 1); +--error ER_PARSE_ERROR +((SELECT 1 FROM t1 LIMIT 1) ORDER BY 1) LIMIT 1); + +# ORDER/LIMIT and UNION: + +let $q=SELECT 1 FROM t1 UNION SELECT 1 FROM t1 ORDER BY 1; +eval $q; +eval SELECT ($q); +eval SELECT 1 FROM ($q) a; + +let $q=SELECT 1 FROM t1 UNION SELECT 1 FROM t1 LIMIT 1; +eval $q; +eval SELECT ($q); +eval SELECT 1 FROM ($q) a; + +let $q=SELECT 1 FROM t1 UNION SELECT 1 FROM t1 ORDER BY 1 LIMIT 1; +eval $q; +eval SELECT ($q); +eval SELECT 1 FROM ($q) a; + +let $q=SELECT 1 FROM t1 UNION SELECT 1 FROM t1 LIMIT 1 ORDER BY 1; +--error ER_PARSE_ERROR +eval $q; +--error ER_PARSE_ERROR +eval SELECT ($q); +--error ER_PARSE_ERROR +eval SELECT 1 FROM ($q) a; + +let $q=SELECT 1 FROM t1 ORDER BY 1 UNION SELECT 1 FROM t1; +--error ER_WRONG_USAGE +eval $q; +--error ER_WRONG_USAGE +eval SELECT ($q); +--error ER_WRONG_USAGE +eval SELECT 1 FROM ($q) a; + +let $q=SELECT 1 FROM t1 LIMIT 1 UNION SELECT 1 FROM t1; +--error ER_WRONG_USAGE +eval $q; +--error ER_WRONG_USAGE +eval SELECT ($q); +--error ER_WRONG_USAGE +eval SELECT 1 FROM ($q) a; + +let $q=SELECT 1 FROM t1 ORDER BY 1 LIMIT 1 UNION SELECT 1 FROM t1; +--error ER_WRONG_USAGE +eval $q; +--error ER_WRONG_USAGE +eval SELECT ($q); +--error ER_WRONG_USAGE +eval SELECT 1 FROM ($q) a; + +let $q=SELECT 1 FROM t1 LIMIT 1 ORDER BY 1 UNION SELECT 1 FROM t1; +--error ER_PARSE_ERROR +eval $q; +--error ER_PARSE_ERROR +eval SELECT ($q); +--error ER_WRONG_USAGE +eval SELECT 1 FROM ($q) a; + +let $q=SELECT 1 FROM t1 ORDER BY 1 UNION SELECT 1 FROM t1 ORDER BY 1; +--error ER_WRONG_USAGE +eval $q; +--error ER_WRONG_USAGE +eval SELECT ($q); +--error ER_WRONG_USAGE +eval SELECT 1 FROM ($q) a; + +let $q=SELECT 1 FROM t1 LIMIT 1 UNION SELECT 1 FROM t1 LIMIT 1; +--error ER_WRONG_USAGE +eval $q; +--error ER_WRONG_USAGE +eval SELECT ($q); +--error ER_WRONG_USAGE +eval SELECT 1 FROM ($q) a; + +let $q=SELECT 1 FROM t1 LIMIT 1 UNION SELECT 1 FROM t1 ORDER BY 1; +--error ER_WRONG_USAGE +eval $q; +--error ER_WRONG_USAGE +eval SELECT ($q); +--error ER_WRONG_USAGE +eval SELECT 1 FROM ($q) a; + +let $q=SELECT 1 FROM t1 ORDER BY 1 UNION SELECT 1 FROM t1 LIMIT 1; +--error ER_WRONG_USAGE +eval $q; +--error ER_WRONG_USAGE +eval SELECT ($q); +--error ER_WRONG_USAGE +eval SELECT 1 FROM ($q) a; + +DROP TABLE t1; + +--echo # +--echo # MDEV-8380: Subquery parse error +--echo # +CREATE TABLE t1 ( a INT); +INSERT INTO t1 VALUES ( 2 ); +SELECT * +FROM ( (SELECT a FROM t1 ORDER BY a) UNION (SELECT 1 as b ORDER BY b ) ) AS a1 +WHERE a1.a = 1 OR a1.a = 2; +DROP TABLE t1; diff --git a/mysql-test/t/subselect.test b/mysql-test/t/subselect.test index 80efe7a..8fb9658 100644 --- a/mysql-test/t/subselect.test +++ b/mysql-test/t/subselect.test @@ -4274,8 +4274,7 @@ SELECT * FROM (
# This was not allowed previously. Possibly, it should be allowed on the future. # For now, the intent is to keep the fix as non-intrusive as possible. ---error ER_PARSE_ERROR -SELECT * FROM ((SELECT 1 a) UNION SELECT 1 a); +SELECT * FROM ((SELECT 1 a) UNION SELECT 1 a) q; SELECT * FROM (SELECT 1 a UNION (SELECT 1 a)) alias; SELECT * FROM (SELECT 1 UNION SELECT 1) t1a; --error ER_PARSE_ERROR @@ -4310,7 +4309,7 @@ SELECT * FROM (SELECT 1 a UNION SELECT 1 a ORDER BY a LIMIT 1) t1a; # aliases after. # SELECT * FROM t1 JOIN (SELECT 1 UNION SELECT 1) alias ON 1; ---error ER_PARSE_ERROR +--error ER_DERIVED_MUST_HAVE_ALIAS SELECT * FROM t1 JOIN ((SELECT 1 UNION SELECT 1)) ON 1; --error ER_PARSE_ERROR SELECT * FROM t1 JOIN (t1 t1a UNION SELECT 1) ON 1; @@ -4402,8 +4401,9 @@ SELECT ((SELECT 1 UNION SELECT 1 UNION SELECT 1));
--error ER_PARSE_ERROR SELECT * FROM ( SELECT 1 UNION ( SELECT 1 UNION SELECT 1 ) ); ---error ER_PARSE_ERROR +--error ER_DERIVED_MUST_HAVE_ALIAS SELECT * FROM ( ( SELECT 1 UNION SELECT 1 ) UNION SELECT 1 ); +SELECT * FROM ( ( SELECT 1 UNION SELECT 1 ) UNION SELECT 1 ) a; SELECT * FROM ( SELECT 1 UNION SELECT 1 UNION SELECT 1 ) a;
--error ER_PARSE_ERROR diff --git a/mysql-test/t/union.test b/mysql-test/t/union.test index b8b040b..56fb2e3 100644 --- a/mysql-test/t/union.test +++ b/mysql-test/t/union.test @@ -26,8 +26,12 @@ select 't1',b,count(*) from t1 group by b UNION select 't2',b,count(*) from t2 g --error 1250 (select a,b from t1 limit 2) union all (select a,b from t2 order by a limit 1) order by t1.b; explain extended (select a,b from t1 limit 2) union all (select a,b from t2 order by a limit 1) order by b desc; +select count(*) from ( +(select a,b from t1 limit 2) union all (select a,b from t2 order by a)) q; (select sql_calc_found_rows a,b from t1 limit 2) union all (select a,b from t2 order by a) limit 2; select found_rows(); +select count(*) from ( +select a,b from t1 union all select a,b from t2) q; select sql_calc_found_rows a,b from t1 union all select a,b from t2 limit 2; select found_rows();
@@ -206,18 +210,30 @@ create table t2 (a int); insert into t2 values (3),(4),(5);
# Test global limits +SELECT COUNT(*) FROM ( +(SELECT * FROM t1) UNION all (SELECT * FROM t2)) q; (SELECT SQL_CALC_FOUND_ROWS * FROM t1) UNION all (SELECT * FROM t2) LIMIT 1; select found_rows(); +SELECT COUNT(*) FROM ( +(SELECT * FROM t1 LIMIT 1) UNION all (SELECT * FROM t2)) q; (SELECT SQL_CALC_FOUND_ROWS * FROM t1 LIMIT 1) UNION all (SELECT * FROM t2) LIMIT 2; select found_rows();
# Test cases where found_rows() should return number of returned rows +SELECT COUNT(*) FROM ( +(SELECT * FROM t1 LIMIT 1) UNION all (SELECT * FROM t2)) q; (SELECT SQL_CALC_FOUND_ROWS * FROM t1 LIMIT 1) UNION all (SELECT * FROM t2); select found_rows(); +SELECT COUNT(*) FROM ( +(SELECT * FROM t1) UNION all (SELECT * FROM t2 LIMIT 1)) q; (SELECT SQL_CALC_FOUND_ROWS * FROM t1) UNION all (SELECT * FROM t2 LIMIT 1); select found_rows(); (SELECT SQL_CALC_FOUND_ROWS * FROM t1 LIMIT 1) UNION SELECT * FROM t2 LIMIT 1; select found_rows(); +SELECT COUNT(*) FROM ( +(SELECT * FROM t1 LIMIT 1) UNION SELECT * FROM t2) q; +(SELECT SQL_CALC_FOUND_ROWS * FROM t1 LIMIT 1) UNION SELECT * FROM t2 LIMIT 1; +select found_rows();
# In these case found_rows() should work --error ER_WRONG_USAGE @@ -226,20 +242,41 @@ SELECT SQL_CALC_FOUND_ROWS * FROM t1 UNION all SELECT * FROM t2 LIMIT 2; select found_rows();
# The following examples will not be exact +SELECT COUNT(*) FROM ( +SELECT * FROM t1 UNION SELECT * FROM t2) q; SELECT SQL_CALC_FOUND_ROWS * FROM t1 UNION SELECT * FROM t2 LIMIT 2; +SELECT COUNT(*) FROM ( +(SELECT * FROM t1 LIMIT 1) UNION all SELECT * FROM t2) q; +(SELECT SQL_CALC_FOUND_ROWS * FROM t1 LIMIT 1) UNION all SELECT * FROM t2 LIMIT 2; select found_rows(); +SELECT COUNT(*) FROM ( +SELECT * FROM t1 UNION all SELECT * FROM t2) q; SELECT SQL_CALC_FOUND_ROWS * FROM t1 UNION SELECT * FROM t2 LIMIT 100; select found_rows(); --error ER_WRONG_USAGE SELECT SQL_CALC_FOUND_ROWS * FROM t1 LIMIT 100 UNION SELECT * FROM t2; +SELECT COUNT(*) FROM ( +(SELECT * FROM t1 LIMIT 100) UNION SELECT * FROM t2) q; +(SELECT SQL_CALC_FOUND_ROWS * FROM t1 LIMIT 100) UNION SELECT * FROM t2; --error ER_WRONG_USAGE SELECT SQL_CALC_FOUND_ROWS * FROM t1 LIMIT 1 UNION SELECT * FROM t2; +SELECT COUNT(*) FROM ( +(SELECT * FROM t1 LIMIT 1) UNION SELECT * FROM t2) q; +(SELECT SQL_CALC_FOUND_ROWS * FROM t1 LIMIT 1) UNION SELECT * FROM t2; --error ER_WRONG_USAGE SELECT SQL_CALC_FOUND_ROWS * FROM t1 LIMIT 1 UNION SELECT * FROM t2 LIMIT 2; +SELECT COUNT(*) FROM ( +(SELECT * FROM t1 LIMIT 1) UNION SELECT * FROM t2) q; +(SELECT SQL_CALC_FOUND_ROWS * FROM t1 LIMIT 1) UNION SELECT * FROM t2 LIMIT 2; SELECT SQL_CALC_FOUND_ROWS * FROM t1 UNION SELECT * FROM t2 LIMIT 2,2; select found_rows(); +SELECT COUNT(*) FROM ( +SELECT * FROM t1 UNION SELECT * FROM t2) q; --error ER_WRONG_USAGE SELECT SQL_CALC_FOUND_ROWS * FROM t1 limit 2,2 UNION SELECT * FROM t2; +SELECT COUNT(*) FROM ( +(SELECT * FROM t1 limit 2,2) UNION SELECT * FROM t2) q; +(SELECT SQL_CALC_FOUND_ROWS * FROM t1 limit 2,2) UNION SELECT * FROM t2;
# Test some limits with ORDER BY SELECT * FROM t1 UNION SELECT * FROM t2 ORDER BY a desc LIMIT 1;
Regards, Sergei