summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorOleksandr Byelkin <sanja@mariadb.com>2015-08-18 13:28:17 +0200
committerOleksandr Byelkin <sanja@mariadb.com>2015-09-14 16:20:14 +0200
commit4430d555a34b8471fde9615dc2f8c301f319f65e (patch)
tree34f71c80e71468e54beec17f97a5b7d647133bd8
parent5fe8b747e9e3440f2f746accca0eb11e287a6713 (diff)
downloadmariadb-git-mdev-8380.tar.gz
MDEV-8380: Subquery parse errormdev-8380
backport mysql parser fixes 0034963fbf199696792491bcb79d5f0731c98804 5948561812bc691bd0c13cf518a3fe77d9daf920
-rw-r--r--mysql-test/r/parser.result227
-rw-r--r--mysql-test/r/subselect.result12
-rw-r--r--mysql-test/r/subselect_no_exists_to_in.result12
-rw-r--r--mysql-test/r/subselect_no_mat.result12
-rw-r--r--mysql-test/r/subselect_no_opts.result12
-rw-r--r--mysql-test/r/subselect_no_scache.result12
-rw-r--r--mysql-test/r/subselect_no_semijoin.result12
-rw-r--r--mysql-test/r/union.result94
-rw-r--r--mysql-test/t/parser.test256
-rw-r--r--mysql-test/t/subselect.test8
-rw-r--r--mysql-test/t/union.test37
-rw-r--r--sql/sql_lex.cc1
-rw-r--r--sql/sql_parse.cc17
-rw-r--r--sql/sql_yacc.yy168
14 files changed, 780 insertions, 100 deletions
diff --git a/mysql-test/r/parser.result b/mysql-test/r/parser.result
index 1d29f2c4a0e..01cc9d79aaf 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 3732f62d5e5..b9f9fb05c21 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 140b7902660..902c45ff213 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 99ac9f4b300..89034b7995d 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 7ecd40c3863..6e90aac09ed 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 c70db6f8cc0..1c18817ae8d 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 6a7d6b3a81c..de9c4e8a12b 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 ef1749eda52..9b7a1c57aa1 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 31c6ab92ba8..0a19b03a4eb 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 80efe7a97ae..8fb9658260b 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 b8b040b0d0d..56fb2e3a13d 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;
diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc
index 6c835c4293f..2033eb86d8f 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;
lex->is_lex_started= TRUE;
DBUG_VOID_RETURN;
diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc
index 5e58ceb9621..f7eed09c789 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);
+ }
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);
+ }
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 811ee4f97d5..d03b05cfb84 100644
--- a/sql/sql_yacc.yy
+++ b/sql/sql_yacc.yy
@@ -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 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
+ {
+ 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;
+ }
+ }
+ ;
+
+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 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
;
-select_from:
- FROM join_table_list
+from_clause:
+ FROM table_reference_list
+ ;
+
+opt_from_clause:
+ /* empty */
+ | from_clause
+ ;
+
+table_reference_list:
+ join_table_list
{
Select->context.table_list=
Select->context.first_name_resolution_table=
Select->table_list.first;
}
- where_clause group_clause having_clause
- opt_order_clause opt_limit_clause procedure_clause
- | FROM DUAL_SYM 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" ?
@@ -8530,7 +8574,7 @@ select_option:
}
;
-select_lock_type:
+opt_select_lock_type:
/* empty */
| FOR_SYM UPDATE_SYM
{
@@ -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,6 @@ 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;
- }
}
;
@@ -10932,7 +10968,6 @@ select_part2_derived:
{
Select->parsing_place= NO_MATTER;
}
- opt_select_from select_lock_type
;
/* handle contents of parentheses in join expression */
@@ -10980,7 +11015,7 @@ select_derived2:
{
Select->parsing_place= NO_MATTER;
}
- opt_select_from
+ table_expression
;
get_select_lex:
@@ -11157,7 +11192,7 @@ opt_all:
| ALL
;
-where_clause:
+opt_where_clause:
/* empty */ { Select->where= 0; }
| WHERE
{
@@ -11173,7 +11208,7 @@ where_clause:
}
;
-having_clause:
+opt_having_clause:
/* empty */
| HAVING
{
@@ -11210,7 +11245,7 @@ opt_escape:
group by statement in select
*/
-group_clause:
+opt_group_clause:
/* empty */
| GROUP_SYM BY group_list olap_opt
;
@@ -11358,25 +11393,6 @@ order_dir:
| DESC { $$ =0; }
;
-opt_limit_clause_init:
- /* empty */
- {
- LEX *lex= Lex;
- SELECT_LEX *sel= lex->current_select;
- if (sel->master_unit()->is_union() && !sel->braces)
- {
- /* Move LIMIT that belongs to UNION to fake_select_lex */
- Lex->current_select= sel->master_unit()->fake_select_lex;
- DBUG_ASSERT(Select);
- }
- sel= lex->current_select;
- sel->offset_limit= 0;
- sel->select_limit= 0;
- lex->limit_rows_examined= 0;
- }
- | limit_clause {}
- ;
-
opt_limit_clause:
/* empty */ {}
| limit_clause {}
@@ -11574,8 +11590,8 @@ choice:
| DEFAULT { $$= HA_CHOICE_UNDEF; }
;
-procedure_clause:
- /* empty */
+opt_procedure_clause:
+ /* empty */ { $$= false; }
| PROCEDURE_SYM ident /* Procedure name */
{
LEX *lex=Lex;
@@ -11604,6 +11620,9 @@ procedure_clause:
Lex->uncacheable(UNCACHEABLE_SIDEEFFECT);
}
'(' procedure_list ')'
+ {
+ $$= true;
+ }
;
procedure_list:
@@ -11680,6 +11699,11 @@ select_outvar:
}
;
+opt_into:
+ /* empty */ { $$= false; }
+ | into { $$= true; }
+ ;
+
into:
INTO
{
@@ -12172,7 +12196,7 @@ update:
*/
Select->set_lock_for_tables($3);
}
- where_clause opt_order_clause delete_limit_clause {}
+ opt_where_clause opt_order_clause delete_limit_clause {}
;
update_list:
@@ -12237,7 +12261,7 @@ single_multi:
YYPS->m_lock_type= TL_READ_DEFAULT;
YYPS->m_mdl_type= MDL_SHARED_READ;
}
- where_clause opt_order_clause
+ opt_where_clause opt_order_clause
delete_limit_clause {}
opt_select_expressions {}
| table_wild_list
@@ -12246,7 +12270,7 @@ single_multi:
YYPS->m_lock_type= TL_READ_DEFAULT;
YYPS->m_mdl_type= MDL_SHARED_READ;
}
- FROM join_table_list where_clause
+ FROM join_table_list opt_where_clause
{
if (multi_delete_set_locks_and_link_aux_tables(Lex))
MYSQL_YYABORT;
@@ -12257,7 +12281,7 @@ single_multi:
YYPS->m_lock_type= TL_READ_DEFAULT;
YYPS->m_mdl_type= MDL_SHARED_READ;
}
- USING join_table_list where_clause
+ USING join_table_list opt_where_clause
{
if (multi_delete_set_locks_and_link_aux_tables(Lex))
MYSQL_YYABORT;
@@ -12515,13 +12539,14 @@ show_param:
{
LEX *lex= Lex;
lex->sql_command= SQLCOM_SHOW_BINLOG_EVENTS;
- } opt_limit_clause_init
+ }
+ opt_limit_clause
| RELAYLOG_SYM optional_connection_name EVENTS_SYM binlog_in binlog_from
{
LEX *lex= Lex;
lex->sql_command= SQLCOM_SHOW_RELAYLOG_EVENTS;
- } opt_limit_clause_init
- | keys_or_index from_or_in table_ident opt_db where_clause
+ } opt_limit_clause
+ | keys_or_index from_or_in table_ident opt_db opt_where_clause
{
LEX *lex= Lex;
lex->sql_command= SQLCOM_SHOW_KEYS;
@@ -12556,13 +12581,13 @@ show_param:
{ (void) create_select_for_variable("warning_count"); }
| COUNT_SYM '(' '*' ')' ERRORS
{ (void) create_select_for_variable("error_count"); }
- | WARNINGS opt_limit_clause_init
+ | WARNINGS opt_limit_clause
{ Lex->sql_command = SQLCOM_SHOW_WARNS;}
- | ERRORS opt_limit_clause_init
+ | ERRORS opt_limit_clause
{ Lex->sql_command = SQLCOM_SHOW_ERRORS;}
| PROFILES_SYM
{ Lex->sql_command = SQLCOM_SHOW_PROFILES; }
- | PROFILE_SYM opt_profile_defs opt_profile_args opt_limit_clause_init
+ | PROFILE_SYM opt_profile_defs opt_profile_args opt_limit_clause
{
LEX *lex= Lex;
lex->sql_command= SQLCOM_SHOW_PROFILE;
@@ -15124,7 +15149,7 @@ handler:
if (!lex->current_select->add_table_to_list(lex->thd, $2, 0, 0))
MYSQL_YYABORT;
}
- handler_read_or_scan where_clause opt_limit_clause
+ handler_read_or_scan opt_where_clause opt_limit_clause
{
Lex->expr_allows_subselect= TRUE;
/* Stored functions are not supported for HANDLER READ. */
@@ -15843,7 +15868,7 @@ union_order_or_limit:
;
order_or_limit:
- order_clause opt_limit_clause_init
+ order_clause opt_limit_clause
| limit_clause
;
@@ -15855,17 +15880,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
{
@@ -15873,7 +15900,6 @@ query_expression_body:
MYSQL_YYABORT;
}
query_specification
- opt_union_order_or_limit
{
Lex->pop_context();
$$= $1;