← Back to team overview

maria-developers team mailing list archive

MDEV-10036 sql_yacc.yy: Split select_part2 to disallow syntactically bad constructs with INTO, PROCEDURE, UNION

 

  Hi Sergei,

Please review a patch for MDEV-10036.


This is the next step for:
MDEV-8909 union parser cleanup


Thanks!
diff --git a/mysql-test/r/limit_rows_examined.result b/mysql-test/r/limit_rows_examined.result
index 318039d..cce8ee5 100644
--- a/mysql-test/r/limit_rows_examined.result
+++ b/mysql-test/r/limit_rows_examined.result
@@ -173,10 +173,8 @@ Warning	1931	Query execution was interrupted. The query examined at least 8 rows
 select * from t1, t2 where c1 = c2 LIMIT ROWS EXAMINED 0
 UNION
 select * from t1, t2 where c1 < c2 LIMIT ROWS EXAMINED 6;
-c1	c2
-bb	bb
-Warnings:
-Warning	1931	Query execution was interrupted. The query examined at least 8 rows, which exceeds LIMIT ROWS EXAMINED (6). The query result may be incomplete.
+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 * from t1, t2 where c1 < c2 LIMIT ROWS EXAMINED 6' at line 2
 (select * from t1, t2 where c1 = c2 LIMIT ROWS EXAMINED 0)
 UNION
 (select * from t1, t2 where c1 < c2 LIMIT ROWS EXAMINED 0)
diff --git a/mysql-test/r/parser.result b/mysql-test/r/parser.result
index 18a8e13..1a39bca 100644
--- a/mysql-test/r/parser.result
+++ b/mysql-test/r/parser.result
@@ -709,7 +709,8 @@ 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()
+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 FROM t1' at line 2
 (SELECT 1 FROM t1)
 UNION 
 (SELECT 1 FROM DUAL WHERE 1 GROUP BY 1 HAVING 1 ORDER BY 1
@@ -739,10 +740,10 @@ 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
+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_2' at line 1
 SELECT 1 INTO @var17727401_1 FROM DUAL
 INTO @var17727401_2;
-ERROR HY000: Incorrect usage of INTO and INTO
+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_2' at line 2
 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
@@ -754,7 +755,7 @@ ERROR 42000: You have an error in your SQL syntax; check the manual that corresp
 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
+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_2' at line 3
 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;
@@ -762,16 +763,16 @@ ERROR 42000: You have an error in your SQL syntax; check the manual that corresp
 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
+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 FROM t1 INTO t1' 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 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
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'PROCEDURE ANALYSE()' at line 1
 SELECT 1 FROM t1 PROCEDURE ANALYSE() INTO @var17727401;
-ERROR HY000: Incorrect usage of PROCEDURE and INTO
+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
 # ORDER and LIMIT clause combinations
 (SELECT 1 FROM t1 ORDER BY 1) ORDER BY 1;
 1
@@ -817,19 +818,19 @@ ERROR 42000: You have an error in your SQL syntax; check the manual that corresp
 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
+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 FROM t1' at line 1
 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
+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 FROM t1' at line 1
 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
+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 FROM t1' at line 1
 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;
@@ -841,25 +842,25 @@ ERROR 42000: You have an error in your SQL syntax; check the manual that corresp
 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
+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 FROM t1 ORDER BY 1' at line 1
 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
+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 FROM t1 LIMIT 1' at line 1
 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
+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 FROM t1 ORDER BY 1' at line 1
 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
+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 FROM t1 LIMIT 1' at line 1
 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;
diff --git a/mysql-test/r/union.result b/mysql-test/r/union.result
index 12f18d6..6a52bc0 100644
--- a/mysql-test/r/union.result
+++ b/mysql-test/r/union.result
@@ -124,9 +124,9 @@ ERROR 21000: The used SELECT statements have a different number of columns
 explain select a,b from t1 union select 1 limit 0;
 ERROR 21000: The used SELECT statements have a different number of columns
 select a,b from t1 into outfile 'skr' union select a,b from t2;
-ERROR HY000: Incorrect usage of UNION and INTO
+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 a,b from t2' at line 1
 select a,b from t1 order by a union select a,b from t2;
-ERROR HY000: Incorrect usage of UNION and ORDER BY
+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 a,b from t2' at line 1
 insert into t3 select a from t1 order by a union select a from t2;
 ERROR HY000: Incorrect usage of UNION and ORDER BY
 create table t3 select a,b from t1 union select a from t2;
@@ -380,7 +380,7 @@ 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
+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 all SELECT * FROM t2 LIMIT 2' at line 1
 SELECT SQL_CALC_FOUND_ROWS * FROM t1 UNION all SELECT * FROM t2 LIMIT 2;
 a
 1
@@ -422,7 +422,7 @@ select found_rows();
 found_rows()
 5
 SELECT SQL_CALC_FOUND_ROWS * FROM t1 LIMIT 100 UNION SELECT * FROM t2;
-ERROR HY000: Incorrect usage of UNION and LIMIT
+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 * FROM t2' at line 1
 SELECT COUNT(*) FROM (
 (SELECT                     * FROM t1 LIMIT 100) UNION SELECT * FROM t2) q;
 COUNT(*)
@@ -435,7 +435,7 @@ a
 4
 5
 SELECT SQL_CALC_FOUND_ROWS * FROM t1 LIMIT 1 UNION SELECT * FROM t2;
-ERROR HY000: Incorrect usage of UNION and LIMIT
+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 * FROM t2' at line 1
 SELECT COUNT(*) FROM (
 (SELECT                     * FROM t1 LIMIT 1) UNION SELECT * FROM t2) q;
 COUNT(*)
@@ -447,7 +447,7 @@ a
 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
+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 * FROM t2 LIMIT 2' at line 1
 SELECT COUNT(*) FROM (
 (SELECT                     * FROM t1 LIMIT 1) UNION SELECT * FROM t2) q;
 COUNT(*)
@@ -468,7 +468,7 @@ 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
+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 * FROM t2' at line 1
 SELECT COUNT(*) FROM (
 (SELECT                     * FROM t1 limit 2,2) UNION SELECT * FROM t2) q;
 COUNT(*)
@@ -1569,7 +1569,8 @@ UNION ALL
 SELECT b, COUNT(*) FROM t2 GROUP BY b WITH ROLLUP ORDER BY a
 UNION
 SELECT 1,1;
-ERROR HY000: Incorrect usage of UNION and ORDER BY
+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,1' at line 4
 DROP TABLE t1,t2;
 CREATE TABLE t1 (a INT);
 INSERT INTO t1 VALUES (1), (2), (3);
@@ -1647,11 +1648,11 @@ SELECT a FROM t1 UNION SELECT a INTO @v FROM t1;
 SELECT a FROM t1 UNION SELECT a INTO OUTFILE 'union.out.file5' FROM t1;
 SELECT a FROM t1 UNION SELECT a INTO OUTFILE 'union.out.file6' FROM t1;
 SELECT a INTO @v FROM t1 UNION SELECT a FROM t1;
-ERROR HY000: Incorrect usage of UNION and INTO
+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 a FROM t1' at line 1
 SELECT a INTO OUTFILE 'union.out.file7' FROM t1 UNION SELECT a FROM t1;
-ERROR HY000: Incorrect usage of UNION and INTO
+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 a FROM t1' at line 1
 SELECT a INTO DUMPFILE 'union.out.file8' FROM t1 UNION SELECT a FROM t1;
-ERROR HY000: Incorrect usage of UNION and INTO
+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 a FROM t1' at line 1
 # Tests fix in parser rule query_expression_body.
 SELECT ( SELECT a UNION SELECT a ) INTO @v FROM t1;
 SELECT ( SELECT a UNION SELECT a ) INTO OUTFILE  'union.out.file3' FROM t1;
diff --git a/mysql-test/t/limit_rows_examined.test b/mysql-test/t/limit_rows_examined.test
index 3825302..3f7424d 100644
--- a/mysql-test/t/limit_rows_examined.test
+++ b/mysql-test/t/limit_rows_examined.test
@@ -125,6 +125,7 @@ UNION
 UNION
 (select * from t1, t2 where c1 < c2 LIMIT ROWS EXAMINED 6);
 
+--error ER_PARSE_ERROR
 select * from t1, t2 where c1 = c2 LIMIT ROWS EXAMINED 0
 UNION
 select * from t1, t2 where c1 < c2 LIMIT ROWS EXAMINED 6;
diff --git a/mysql-test/t/parser.test b/mysql-test/t/parser.test
index 86cc3c4..a143a61 100644
--- a/mysql-test/t/parser.test
+++ b/mysql-test/t/parser.test
@@ -831,7 +831,7 @@ UNION
 SELECT 1 FROM DUAL WHERE 1 GROUP BY 1 HAVING 1 ORDER BY 1
   PROCEDURE ANALYSE() FOR UPDATE;
 
---error ER_WRONG_USAGE
+--error ER_PARSE_ERROR
 SELECT 1 FROM DUAL PROCEDURE ANALYSE() 
 UNION
 SELECT 1 FROM t1;
@@ -863,10 +863,10 @@ SELECT 1 INTO @var17727401;
 SELECT 1 INTO @var17727401 FROM t1;
 SELECT 1 INTO @var17727401 FROM DUAL;
 
---error ER_WRONG_USAGE
+--error ER_PARSE_ERROR
 SELECT 1 INTO @var17727401_1 FROM t1 INTO @var17727401_2;
 
---error ER_WRONG_USAGE
+--error ER_PARSE_ERROR
 SELECT 1 INTO @var17727401_1 FROM DUAL
   INTO @var17727401_2;
 
@@ -876,7 +876,7 @@ SELECT 1 FROM t1 WHERE 1 GROUP BY 1 HAVING 1 ORDER BY 1 LIMIT 1 INTO @var1772740
 --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
+--error ER_PARSE_ERROR
 SELECT 1 INTO @var17727401_1
   FROM t1 WHERE 1 GROUP BY 1 HAVING 1 ORDER BY 1 LIMIT 1
   INTO @var17727401_2;
@@ -888,17 +888,17 @@ 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
+--error ER_PARSE_ERROR
 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
+--error ER_PARSE_ERROR
 SELECT 1 INTO @var17727401 FROM t1 PROCEDURE ANALYSE();
 
---error ER_WRONG_USAGE
+--error ER_PARSE_ERROR
 SELECT 1 FROM t1 PROCEDURE ANALYSE() INTO @var17727401;
 
 --echo # ORDER and LIMIT clause combinations
@@ -947,7 +947,7 @@ eval SELECT ($q);
 eval SELECT 1 FROM ($q) a;
 
 let $q=SELECT 1 FROM t1 ORDER BY 1 UNION SELECT 1 FROM t1;
---error ER_WRONG_USAGE
+--error ER_PARSE_ERROR
 eval $q;
 --error ER_WRONG_USAGE
 eval SELECT ($q);
@@ -955,7 +955,7 @@ eval SELECT ($q);
 eval SELECT 1 FROM ($q) a;
 
 let $q=SELECT 1 FROM t1 LIMIT 1 UNION SELECT 1 FROM t1;
---error ER_WRONG_USAGE
+--error ER_PARSE_ERROR
 eval $q;
 --error ER_WRONG_USAGE
 eval SELECT ($q);
@@ -963,7 +963,7 @@ eval SELECT ($q);
 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
+--error ER_PARSE_ERROR
 eval $q;
 --error ER_WRONG_USAGE
 eval SELECT ($q);
@@ -979,7 +979,7 @@ eval SELECT ($q);
 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
+--error ER_PARSE_ERROR
 eval $q;
 --error ER_WRONG_USAGE
 eval SELECT ($q);
@@ -987,7 +987,7 @@ eval SELECT ($q);
 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
+--error ER_PARSE_ERROR
 eval $q;
 --error ER_WRONG_USAGE
 eval SELECT ($q);
@@ -995,7 +995,7 @@ eval SELECT ($q);
 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
+--error ER_PARSE_ERROR
 eval $q;
 --error ER_WRONG_USAGE
 eval SELECT ($q);
@@ -1003,7 +1003,7 @@ eval SELECT ($q);
 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
+--error ER_PARSE_ERROR
 eval $q;
 --error ER_WRONG_USAGE
 eval SELECT ($q);
diff --git a/mysql-test/t/union.test b/mysql-test/t/union.test
index f2026a6..d7c6744 100644
--- a/mysql-test/t/union.test
+++ b/mysql-test/t/union.test
@@ -50,10 +50,10 @@ explain select 1 union select a,b from t1 union select 1;
 --error 1222
 explain select a,b from t1 union select 1 limit 0;
 
---error 1221
+--error ER_PARSE_ERROR
 select a,b from t1 into outfile 'skr' union select a,b from t2;
 
---error 1221
+--error ER_PARSE_ERROR
 select a,b from t1 order by a union select a,b from t2;
 
 --error 1221
@@ -236,7 +236,7 @@ SELECT COUNT(*) FROM (
 select found_rows();
 
 # In these case found_rows() should work
---error ER_WRONG_USAGE
+--error ER_PARSE_ERROR
 SELECT SQL_CALC_FOUND_ROWS * FROM t1 LIMIT 1 UNION all SELECT * FROM t2 LIMIT 2;
 SELECT SQL_CALC_FOUND_ROWS * FROM t1 UNION all SELECT * FROM t2 LIMIT 2;
 select found_rows();
@@ -253,17 +253,17 @@ 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
+--error ER_PARSE_ERROR
 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
+--error ER_PARSE_ERROR
 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
+--error ER_PARSE_ERROR
 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;
@@ -272,7 +272,7 @@ 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
+--error ER_PARSE_ERROR
 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;
@@ -999,7 +999,7 @@ SELECT a,1 FROM t1
 UNION 
 (SELECT b, COUNT(*) FROM t2 GROUP BY b WITH ROLLUP ORDER BY a);
 
---error ER_WRONG_USAGE
+--error ER_PARSE_ERROR
 SELECT a,1 FROM t1
 UNION ALL
 SELECT b, COUNT(*) FROM t2 GROUP BY b WITH ROLLUP ORDER BY a
@@ -1087,11 +1087,11 @@ SELECT a INTO DUMPFILE 'union.out.file2' FROM (
 SELECT a FROM t1 UNION SELECT a INTO @v FROM t1;
 SELECT a FROM t1 UNION SELECT a INTO OUTFILE 'union.out.file5' FROM t1;
 SELECT a FROM t1 UNION SELECT a INTO OUTFILE 'union.out.file6' FROM t1;
---error ER_WRONG_USAGE
+--error ER_PARSE_ERROR
 SELECT a INTO @v FROM t1 UNION SELECT a FROM t1;
---error ER_WRONG_USAGE
+--error ER_PARSE_ERROR
 SELECT a INTO OUTFILE 'union.out.file7' FROM t1 UNION SELECT a FROM t1;
---error ER_WRONG_USAGE
+--error ER_PARSE_ERROR
 SELECT a INTO DUMPFILE 'union.out.file8' FROM t1 UNION SELECT a FROM t1;
 
 -- echo # Tests fix in parser rule query_expression_body.
diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy
index 04c1ba7..b5e4280 100644
--- a/sql/sql_yacc.yy
+++ b/sql/sql_yacc.yy
@@ -1793,7 +1793,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
+        procedure_clause
 	opt_recursive
 
 %type <object_ddl_options>
@@ -8533,7 +8533,8 @@ select_paren:
             */
             Lex->current_select->set_braces(true);
           }
-          SELECT_SYM select_part2
+          SELECT_SYM select_options_and_item_list select_part3
+          opt_select_lock_type
           {
             if (setup_select_in_parentheses(Lex))
               MYSQL_YYABORT;
@@ -8559,50 +8560,42 @@ select_paren_derived:
         ;
 
 select_init2:
-          select_part2
+          select_options_and_item_list
+          opt_table_expression
+          opt_select_lock_type
           {
-            LEX *lex= Lex;
             /* Parentheses carry no meaning here */
-            lex->current_select->set_braces(false);
+            Lex->current_select->set_braces(false);
           }
           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
-          table_expression
-          opt_order_clause
-          opt_limit_clause
-          opt_procedure_clause
-          opt_into
+          select_part3_union_not_ready
           opt_select_lock_type
           {
-            if ($2 && $7)
-            {
-              /* double "INTO" clause */
-              my_error(ER_WRONG_USAGE, MYF(0), "INTO", "INTO");
-              MYSQL_YYABORT;
-            }
-            if ($6 && ($2 || $7))
-            {
-              /* "INTO" with "PROCEDURE ANALYSE" */
-              my_error(ER_WRONG_USAGE, MYF(0), "PROCEDURE", "INTO");
-              MYSQL_YYABORT;
-            }
+            /* Parentheses carry no meaning here */
+            Lex->current_select->set_braces(false);
           }
         ;
 
+
+select_part3:
+          opt_table_expression
+        | select_part3_union_not_ready
+        ;
+
+/*
+  The SELECT parts after select_item_list that cannot be followed by UNION.
+*/
+select_part3_union_not_ready:
+          order_or_limit
+        | into opt_table_expression opt_order_clause opt_limit_clause
+        | table_expression into
+        | table_expression procedure_clause
+        | table_expression order_or_limit
+        | table_expression order_or_limit into
+        | table_expression order_or_limit procedure_clause
+        ;
+
 select_options_and_item_list:
           {
             LEX *lex= Lex;
@@ -11946,9 +11939,8 @@ choice:
 	| DEFAULT { $$= HA_CHOICE_UNDEF; }
 	;
 
-opt_procedure_clause:
-          /* empty */ { $$= false; }
-        | PROCEDURE_SYM ident /* Procedure name */
+procedure_clause:
+          PROCEDURE_SYM ident /* Procedure name */
           {
             LEX *lex=Lex;
 
@@ -12069,11 +12061,6 @@ select_outvar:
           }
         ;
 
-opt_into:
-          /* empty */ { $$= false; }
-        | into        { $$= true; }
-        ;
-
 into:
           INTO
           {

Follow ups