[Commits] 925d00e9978: # Das ist eine Kombination aus 13 Commits.

Oleksandr Byelkin sanja at mariadb.com
Tue Apr 10 14:22:08 EEST 2018


revision-id: 925d00e9978b2400d96249291e2526202b808287 (mariadb-10.3.5-91-g925d00e9978)
parent(s): 1eee986e0c6ef558422b820aa81a196b7f9a523e
author: halfspawn
committer: Oleksandr Byelkin
timestamp: 2018-04-10 13:22:08 +0200
message:

# Das ist eine Kombination aus 13 Commits.
# Das ist die erste Commit-Beschreibung:

MDEV-15739 sql_mode=ORACLE: Make LPAD and RPAD return NULL instead of empty string

# Die Commit-Beschreibung #2 wird ausgelassen:

# MDEV-11953: support of brackets in UNION/EXCEPT/INTERSECT operations

# Die Commit-Beschreibung #3 wird ausgelassen:

# Resolved merge conflicts.

# Die Commit-Beschreibung #4 wird ausgelassen:

# post rebase fixes

# Die Commit-Beschreibung #5 wird ausgelassen:

# more fix of usual INSERT

# Die Commit-Beschreibung #6 wird ausgelassen:

# post merge fixes

# Die Commit-Beschreibung #7 wird ausgelassen:

# fix for SHOW FIELDS & Co

# Die Commit-Beschreibung #8 wird ausgelassen:

# number assigning fixed

# Die Commit-Beschreibung #9 wird ausgelassen:

# Keep original SELECT_LEX to allow ON DUPLICATE expression works correctly

# Die Commit-Beschreibung #10 wird ausgelassen:

# allow subselects

# Die Commit-Beschreibung #11 wird ausgelassen:

# more subquery fixes

# Die Commit-Beschreibung #12 wird ausgelassen:

# duplicated test removed

# Die Commit-Beschreibung #13 wird ausgelassen:

# renamed bracket tests

---
 mysql-test/include/deadlock.inc                  |    2 +-
 mysql-test/main/brackets.result                  |  114 +
 mysql-test/main/brackets.test                    |   26 +
 mysql-test/main/cte_nonrecursive.result          |   24 +-
 mysql-test/main/deadlock_innodb.result           |    2 +-
 mysql-test/main/derived.result                   |    2 +-
 mysql-test/main/events_bugs.result               |    1 -
 mysql-test/main/events_bugs.test                 |    2 +-
 mysql-test/main/except.result                    |    8 +-
 mysql-test/main/except.test                      |    4 +-
 mysql-test/main/fulltext_order_by.result         |    4 +-
 mysql-test/main/func_analyse.result              |   22 +-
 mysql-test/main/func_analyse.test                |   17 +-
 mysql-test/main/intersect.result                 |   22 +-
 mysql-test/main/intersect.test                   |    4 +-
 mysql-test/main/join.result                      |    2 +-
 mysql-test/main/join_nested.result               |    2 +-
 mysql-test/main/join_nested.test                 |    2 +-
 mysql-test/main/join_nested_jcl6.result          |    2 +-
 mysql-test/main/parser.result                    |   55 +-
 mysql-test/main/parser.test                      |   55 +-
 mysql-test/main/query_cache.result               |   37 +-
 mysql-test/main/query_cache.test                 |   31 +-
 mysql-test/main/show_check.result                |    4 +-
 mysql-test/main/show_check.test                  |    2 +-
 mysql-test/main/sp-error.result                  |   10 +-
 mysql-test/main/sp-error.test                    |   10 +-
 mysql-test/main/sp.result                        |   14 +-
 mysql-test/main/sp.test                          |   27 +-
 mysql-test/main/sql_mode.result                  |    1 -
 mysql-test/main/sql_mode.test                    |    5 +-
 mysql-test/main/subselect.result                 |  141 +-
 mysql-test/main/subselect.test                   |   94 +-
 mysql-test/main/subselect_mat.result             |    4 +-
 mysql-test/main/subselect_no_exists_to_in.result |  141 +-
 mysql-test/main/subselect_no_mat.result          |  141 +-
 mysql-test/main/subselect_no_opts.result         |  141 +-
 mysql-test/main/subselect_no_scache.result       |  141 +-
 mysql-test/main/subselect_no_semijoin.result     |  141 +-
 mysql-test/main/subselect_sj.result              |    2 +-
 mysql-test/main/subselect_sj.test                |    2 +-
 mysql-test/main/subselect_sj_jcl6.result         |    2 +-
 mysql-test/main/subselect_sj_mat.result          |    4 +-
 mysql-test/main/subselect_sj_mat.test            |    4 +-
 mysql-test/main/union.result                     |   21 +-
 mysql-test/main/union.test                       |   18 +-
 mysql-test/main/view.result                      |   56 +-
 mysql-test/main/view.test                        |   56 +-
 mysql-test/r/sp-error.result                     | 2876 ++++++++++++++++++++++
 mysql-test/suite/compat/oracle/r/func_pad.result |   71 +
 mysql-test/suite/compat/oracle/t/func_pad.test   |   31 +
 sql/events.cc                                    |    9 +-
 sql/item.cc                                      |    3 +-
 sql/item_create.cc                               |  112 +-
 sql/item_strfunc.h                               |   40 +
 sql/item_subselect.cc                            |   20 +-
 sql/log_event.cc                                 |    7 +-
 sql/opt_range.cc                                 |    2 +-
 sql/opt_table_elimination.cc                     |    4 +-
 sql/set_var.cc                                   |    2 +-
 sql/sp_head.cc                                   |   13 +-
 sql/sp_head.h                                    |    5 +-
 sql/sp_rcontext.cc                               |   14 +-
 sql/sql_admin.cc                                 |   18 +-
 sql/sql_alter.cc                                 |    4 +-
 sql/sql_base.cc                                  |    8 +-
 sql/sql_base.h                                   |    6 +-
 sql/sql_cache.cc                                 |    8 +-
 sql/sql_class.cc                                 |    4 +-
 sql/sql_class.h                                  |    8 +-
 sql/sql_cte.cc                                   |   16 +-
 sql/sql_cte.h                                    |   26 +-
 sql/sql_delete.cc                                |   32 +-
 sql/sql_derived.cc                               |    3 +-
 sql/sql_do.cc                                    |    2 +-
 sql/sql_error.cc                                 |    2 +-
 sql/sql_help.cc                                  |   11 +-
 sql/sql_insert.cc                                |   40 +-
 sql/sql_lex.cc                                   |  938 ++++++-
 sql/sql_lex.h                                    |  234 +-
 sql/sql_load.cc                                  |    9 +-
 sql/sql_parse.cc                                 |  108 +-
 sql/sql_partition.cc                             |    3 +-
 sql/sql_partition_admin.cc                       |    4 +-
 sql/sql_prepare.cc                               |   50 +-
 sql/sql_priv.h                                   |    4 +
 sql/sql_profile.cc                               |    4 +-
 sql/sql_select.cc                                |   50 +-
 sql/sql_sequence.cc                              |    4 +-
 sql/sql_show.cc                                  |   28 +-
 sql/sql_table.cc                                 |    6 +-
 sql/sql_truncate.cc                              |    2 +-
 sql/sql_union.cc                                 |    2 +-
 sql/sql_update.cc                                |   30 +-
 sql/sql_view.cc                                  |   49 +-
 sql/sql_yacc.yy                                  | 2300 +++++++++--------
 sql/sql_yacc_ora.yy                              |  150 +-
 sql/structs.h                                    |   53 +
 sql/table.cc                                     |   34 +-
 sql/vtmd.cc                                      |    4 +-
 sql/wsrep_mysqld.cc                              |    4 +-
 storage/mroonga/ha_mroonga.cpp                   |    2 +-
 storage/spider/spd_db_mysql.cc                   |    2 +-
 storage/spider/spd_table.cc                      |    8 +-
 storage/tokudb/tokudb_dir_cmd.cc                 |    4 +-
 105 files changed, 6794 insertions(+), 2311 deletions(-)

diff --git a/mysql-test/include/deadlock.inc b/mysql-test/include/deadlock.inc
index 2fa61f48624..7ac2a16fc44 100644
--- a/mysql-test/include/deadlock.inc
+++ b/mysql-test/include/deadlock.inc
@@ -94,7 +94,7 @@ insert into t2 values(0, 0), (1, 20), (2, 30);
 commit;
 
 connection con1;
-select a,b from t2 UNION SELECT id, x from t1 FOR UPDATE;
+select a,b from t2 UNION (SELECT id, x from t1 FOR UPDATE);
 select * from t2;
 select * from t1;
 
diff --git a/mysql-test/main/brackets.result b/mysql-test/main/brackets.result
new file mode 100644
index 00000000000..05fba4cfad0
--- /dev/null
+++ b/mysql-test/main/brackets.result
@@ -0,0 +1,114 @@
+select 1 union ( select 2 union select 3);
+1
+1
+2
+3
+explain extended
+select 1 union ( select 2 union select 3);
+id	select_type	table	type	possible_keys	key	key_len	ref	rows	filtered	Extra
+1	PRIMARY	NULL	NULL	NULL	NULL	NULL	NULL	NULL	NULL	No tables used
+4	UNION	<derived2>	ALL	NULL	NULL	NULL	NULL	2	100.00	
+2	DERIVED	NULL	NULL	NULL	NULL	NULL	NULL	NULL	NULL	No tables used
+3	UNION	NULL	NULL	NULL	NULL	NULL	NULL	NULL	NULL	No tables used
+NULL	UNION RESULT	<union2,3>	ALL	NULL	NULL	NULL	NULL	NULL	NULL	
+NULL	UNION RESULT	<union1,4>	ALL	NULL	NULL	NULL	NULL	NULL	NULL	
+Warnings:
+Note	1003	/* select#1 */ select 1 AS `1` union /* select#4 */ select `__4`.`2` AS `2` from (/* select#2 */ select 2 AS `2` union /* select#3 */ select 3 AS `3`) `__4`
+select 1 union ( select 1 union select 1);
+1
+1
+explain extended
+select 1 union ( select 1 union select 1);
+id	select_type	table	type	possible_keys	key	key_len	ref	rows	filtered	Extra
+1	PRIMARY	NULL	NULL	NULL	NULL	NULL	NULL	NULL	NULL	No tables used
+4	UNION	<derived2>	ALL	NULL	NULL	NULL	NULL	2	100.00	
+2	DERIVED	NULL	NULL	NULL	NULL	NULL	NULL	NULL	NULL	No tables used
+3	UNION	NULL	NULL	NULL	NULL	NULL	NULL	NULL	NULL	No tables used
+NULL	UNION RESULT	<union2,3>	ALL	NULL	NULL	NULL	NULL	NULL	NULL	
+NULL	UNION RESULT	<union1,4>	ALL	NULL	NULL	NULL	NULL	NULL	NULL	
+Warnings:
+Note	1003	/* select#1 */ select 1 AS `1` union /* select#4 */ select `__4`.`1` AS `1` from (/* select#2 */ select 1 AS `1` union /* select#3 */ select 1 AS `1`) `__4`
+select 1 union all ( select 1 union select 1);
+1
+1
+1
+explain extended
+select 1 union all ( select 1 union select 1);
+id	select_type	table	type	possible_keys	key	key_len	ref	rows	filtered	Extra
+1	PRIMARY	NULL	NULL	NULL	NULL	NULL	NULL	NULL	NULL	No tables used
+4	UNION	<derived2>	ALL	NULL	NULL	NULL	NULL	2	100.00	
+2	DERIVED	NULL	NULL	NULL	NULL	NULL	NULL	NULL	NULL	No tables used
+3	UNION	NULL	NULL	NULL	NULL	NULL	NULL	NULL	NULL	No tables used
+NULL	UNION RESULT	<union2,3>	ALL	NULL	NULL	NULL	NULL	NULL	NULL	
+Warnings:
+Note	1003	/* select#1 */ select 1 AS `1` union all /* select#4 */ select `__4`.`1` AS `1` from (/* select#2 */ select 1 AS `1` union /* select#3 */ select 1 AS `1`) `__4`
+select 1 union ( select 1 union all select 1);
+1
+1
+explain extended
+select 1 union ( select 1 union all select 1);
+id	select_type	table	type	possible_keys	key	key_len	ref	rows	filtered	Extra
+1	PRIMARY	NULL	NULL	NULL	NULL	NULL	NULL	NULL	NULL	No tables used
+4	UNION	<derived2>	ALL	NULL	NULL	NULL	NULL	2	100.00	
+2	DERIVED	NULL	NULL	NULL	NULL	NULL	NULL	NULL	NULL	No tables used
+3	UNION	NULL	NULL	NULL	NULL	NULL	NULL	NULL	NULL	No tables used
+NULL	UNION RESULT	<union1,4>	ALL	NULL	NULL	NULL	NULL	NULL	NULL	
+Warnings:
+Note	1003	/* select#1 */ select 1 AS `1` union /* select#4 */ select `__4`.`1` AS `1` from (/* select#2 */ select 1 AS `1` union all /* select#3 */ select 1 AS `1`) `__4`
+select 1 union select 1 union all select 1;
+1
+1
+1
+explain extended
+select 1 union select 1 union all select 1;
+id	select_type	table	type	possible_keys	key	key_len	ref	rows	filtered	Extra
+1	PRIMARY	NULL	NULL	NULL	NULL	NULL	NULL	NULL	NULL	No tables used
+2	UNION	NULL	NULL	NULL	NULL	NULL	NULL	NULL	NULL	No tables used
+3	UNION	NULL	NULL	NULL	NULL	NULL	NULL	NULL	NULL	No tables used
+NULL	UNION RESULT	<union1,2,3>	ALL	NULL	NULL	NULL	NULL	NULL	NULL	
+Warnings:
+Note	1003	/* select#1 */ select 1 AS `1` union /* select#2 */ select 1 AS `1` union all /* select#3 */ select 1 AS `1`
+(select 1 as a) union (select 2) order by a;
+a
+1
+2
+explain extended
+(select 1 as a) union (select 2) order by a;
+id	select_type	table	type	possible_keys	key	key_len	ref	rows	filtered	Extra
+1	PRIMARY	NULL	NULL	NULL	NULL	NULL	NULL	NULL	NULL	No tables used
+2	UNION	NULL	NULL	NULL	NULL	NULL	NULL	NULL	NULL	No tables used
+NULL	UNION RESULT	<union1,2>	ALL	NULL	NULL	NULL	NULL	NULL	NULL	Using filesort
+Warnings:
+Note	1003	(/* select#1 */ select 1 AS `a`) union (/* select#2 */ select 2 AS `2`) order by `a`
+/* select#1 */ select 1 AS `a` union /* select#2 */ select 2 AS `2` order by `a`;
+a
+1
+2
+explain extended
+/* select#1 */ select 1 AS `a` union /* select#2 */ select 2 AS `2` order by `a`;
+id	select_type	table	type	possible_keys	key	key_len	ref	rows	filtered	Extra
+1	PRIMARY	NULL	NULL	NULL	NULL	NULL	NULL	NULL	NULL	No tables used
+2	UNION	NULL	NULL	NULL	NULL	NULL	NULL	NULL	NULL	No tables used
+NULL	UNION RESULT	<union1,2>	ALL	NULL	NULL	NULL	NULL	NULL	NULL	Using filesort
+Warnings:
+Note	1003	/* select#1 */ select 1 AS `a` union /* select#2 */ select 2 AS `2` order by `a`
+select 1 union ( select 1 union (select 1 union (select 1 union select 1)));
+1
+1
+explain extended all
+select 1 union ( select 1 union (select 1 union (select 1 union select 1)));
+id	select_type	table	type	possible_keys	key	key_len	ref	rows	filtered	Extra
+1	PRIMARY	NULL	NULL	NULL	NULL	NULL	NULL	NULL	NULL	No tables used
+8	UNION	<derived2>	ALL	NULL	NULL	NULL	NULL	2	100.00	
+2	DERIVED	NULL	NULL	NULL	NULL	NULL	NULL	NULL	NULL	No tables used
+7	UNION	<derived3>	ALL	NULL	NULL	NULL	NULL	2	100.00	
+3	DERIVED	NULL	NULL	NULL	NULL	NULL	NULL	NULL	NULL	No tables used
+6	UNION	<derived4>	ALL	NULL	NULL	NULL	NULL	2	100.00	
+4	DERIVED	NULL	NULL	NULL	NULL	NULL	NULL	NULL	NULL	No tables used
+5	UNION	NULL	NULL	NULL	NULL	NULL	NULL	NULL	NULL	No tables used
+NULL	UNION RESULT	<union4,5>	ALL	NULL	NULL	NULL	NULL	NULL	NULL	
+NULL	UNION RESULT	<union3,6>	ALL	NULL	NULL	NULL	NULL	NULL	NULL	
+NULL	UNION RESULT	<union2,7>	ALL	NULL	NULL	NULL	NULL	NULL	NULL	
+NULL	UNION RESULT	<union1,8>	ALL	NULL	NULL	NULL	NULL	NULL	NULL	
+Warnings:
+Note	1003	/* select#1/1 Filter Select: select `1` AS `1` */ select 1 AS `1` union /* select#8/1 */ select `__8`.`1` AS `1` from (/* select#2/2 Filter Select: select `1` AS `1` */ select 1 AS `1` union /* select#7/2 */ select `__7`.`1` AS `1` from (/* select#3/3 Filter Select: select `1` AS `1` */ select 1 AS `1` union /* select#6/3 */ select `__6`.`1` AS `1` from (/* select#4/4 Filter Select: select `1` AS `1` */ select 1 AS `1` union /* select#5/4 */ select 1 AS `1`) `__6`) `__7`) `__8`
diff --git a/mysql-test/main/brackets.test b/mysql-test/main/brackets.test
new file mode 100644
index 00000000000..3a4534dcf94
--- /dev/null
+++ b/mysql-test/main/brackets.test
@@ -0,0 +1,26 @@
+select 1 union ( select 2 union select 3);
+explain extended
+select 1 union ( select 2 union select 3);
+select 1 union ( select 1 union select 1);
+explain extended
+select 1 union ( select 1 union select 1);
+select 1 union all ( select 1 union select 1);
+explain extended
+select 1 union all ( select 1 union select 1);
+select 1 union ( select 1 union all select 1);
+explain extended
+select 1 union ( select 1 union all select 1);
+select 1 union select 1 union all select 1;
+explain extended
+select 1 union select 1 union all select 1;
+
+(select 1 as a) union (select 2) order by a;
+explain extended
+(select 1 as a) union (select 2) order by a;
+/* select#1 */ select 1 AS `a` union /* select#2 */ select 2 AS `2` order by `a`;
+explain extended
+/* select#1 */ select 1 AS `a` union /* select#2 */ select 2 AS `2` order by `a`;
+
+select 1 union ( select 1 union (select 1 union (select 1 union select 1)));
+explain extended all
+select 1 union ( select 1 union (select 1 union (select 1 union select 1)));
diff --git a/mysql-test/main/cte_nonrecursive.result b/mysql-test/main/cte_nonrecursive.result
index 534a386fe12..a1c4dca090c 100644
--- a/mysql-test/main/cte_nonrecursive.result
+++ b/mysql-test/main/cte_nonrecursive.result
@@ -151,8 +151,8 @@ with t as (select a from t1 where a<5)
 select * from t2 where c in (select a from t);
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
 1	PRIMARY	t2	ALL	NULL	NULL	NULL	NULL	4	
-1	PRIMARY	<subquery3>	eq_ref	distinct_key	distinct_key	4	func	1	
-3	MATERIALIZED	t1	ALL	NULL	NULL	NULL	NULL	8	Using where
+1	PRIMARY	<subquery2>	eq_ref	distinct_key	distinct_key	4	func	1	
+2	MATERIALIZED	t1	ALL	NULL	NULL	NULL	NULL	8	Using where
 explain
 select * from t2 
 where c in (select a from (select a from t1 where a<5) as t);
@@ -332,8 +332,8 @@ union
 select * from t where a >= 4;
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
 1	PRIMARY	t1	ALL	NULL	NULL	NULL	NULL	8	Using where
-3	UNION	t1	ALL	NULL	NULL	NULL	NULL	8	Using where
-NULL	UNION RESULT	<union1,3>	ALL	NULL	NULL	NULL	NULL	NULL	
+2	UNION	t1	ALL	NULL	NULL	NULL	NULL	8	Using where
+NULL	UNION RESULT	<union1,2>	ALL	NULL	NULL	NULL	NULL	NULL	
 explain
 select * from (select a from t1 where b >= 'c') as t
 where t.a < 2
@@ -418,10 +418,10 @@ t2.c in (with t as (select * from t1 where t1.a<5)
 select t2.c from t2,t where t2.c=t.a);
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
 1	PRIMARY	t2	ALL	NULL	NULL	NULL	NULL	4	
-1	PRIMARY	<subquery2>	eq_ref	distinct_key	distinct_key	4	func	1	
+1	PRIMARY	<subquery3>	eq_ref	distinct_key	distinct_key	4	func	1	
 1	PRIMARY	t1	ALL	NULL	NULL	NULL	NULL	8	Using where; Using join buffer (flat, BNL join)
-2	MATERIALIZED	t2	ALL	NULL	NULL	NULL	NULL	4	Using where
-2	MATERIALIZED	t1	ALL	NULL	NULL	NULL	NULL	8	Using where; Using join buffer (flat, BNL join)
+3	MATERIALIZED	t2	ALL	NULL	NULL	NULL	NULL	4	Using where
+3	MATERIALIZED	t1	ALL	NULL	NULL	NULL	NULL	8	Using where; Using join buffer (flat, BNL join)
 explain
 select t1.a,t1.b from t1,t2
 where t1.a>t2.c and
@@ -507,9 +507,9 @@ select t.a, count(*) from t1,t where t1.a=t.a  group by t.a;
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
 1	PRIMARY	t1	ALL	NULL	NULL	NULL	NULL	8	Using where; Using temporary; Using filesort
 1	PRIMARY	t1	ALL	NULL	NULL	NULL	NULL	8	Using where; Using join buffer (flat, BNL join)
-1	PRIMARY	<subquery3>	eq_ref	distinct_key	distinct_key	35	func	1	
-3	MATERIALIZED	t2	ALL	NULL	NULL	NULL	NULL	4	Using where
-3	MATERIALIZED	t1	ALL	NULL	NULL	NULL	NULL	8	Using where; Using join buffer (flat, BNL join)
+1	PRIMARY	<subquery4>	eq_ref	distinct_key	distinct_key	35	func	1	
+4	MATERIALIZED	t2	ALL	NULL	NULL	NULL	NULL	4	Using where
+4	MATERIALIZED	t1	ALL	NULL	NULL	NULL	NULL	8	Using where; Using join buffer (flat, BNL join)
 explain
 select t.a, count(*)
 from t1,
@@ -863,8 +863,8 @@ SELECT * FROM (WITH a AS (SELECT * FROM t1) SELECT 1) AS t1;
 1
 EXPLAIN SELECT * FROM (WITH a AS (SELECT * FROM t1) SELECT 1) AS t1;
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
-1	PRIMARY	<derived2>	system	NULL	NULL	NULL	NULL	1	
-2	SUBQUERY	NULL	NULL	NULL	NULL	NULL	NULL	NULL	No tables used
+1	PRIMARY	<derived3>	system	NULL	NULL	NULL	NULL	1	
+3	DERIVED	NULL	NULL	NULL	NULL	NULL	NULL	NULL	No tables used
 DROP TABLE t1;
 #
 # MDEV-10058: Suspicious EXPLAIN output for a derived table + WITH + joined table	
diff --git a/mysql-test/main/deadlock_innodb.result b/mysql-test/main/deadlock_innodb.result
index af78a6aa9d5..fca0ff6be0c 100644
--- a/mysql-test/main/deadlock_innodb.result
+++ b/mysql-test/main/deadlock_innodb.result
@@ -72,7 +72,7 @@ insert into t1 values(0, 0), (300, 300);
 insert into t2 values(0, 0), (1, 20), (2, 30);
 commit;
 connection con1;
-select a,b from t2 UNION SELECT id, x from t1 FOR UPDATE;
+select a,b from t2 UNION (SELECT id, x from t1 FOR UPDATE);
 a	b
 0	0
 20	1
diff --git a/mysql-test/main/derived.result b/mysql-test/main/derived.result
index ebbc08aa958..0ca050a53dc 100644
--- a/mysql-test/main/derived.result
+++ b/mysql-test/main/derived.result
@@ -225,7 +225,7 @@ ERROR HY000: The target table t1 of the UPDATE is not updatable
 delete from (select * 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 '(select * from t1)' at line 1
 insert into  (select * from t1) values (5);
-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 '(select * from t1) values (5)' at line 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 'select * from t1) values (5)' at line 1
 drop table t1;
 create table t1 (E1 INTEGER UNSIGNED NOT NULL, E2 INTEGER UNSIGNED NOT NULL, E3 INTEGER UNSIGNED NOT NULL, PRIMARY KEY(E1)
 );
diff --git a/mysql-test/main/events_bugs.result b/mysql-test/main/events_bugs.result
index b56912dea7e..5f0217aa5cd 100644
--- a/mysql-test/main/events_bugs.result
+++ b/mysql-test/main/events_bugs.result
@@ -729,7 +729,6 @@ DROP USER mysqltest_u1 at localhost;
 
 drop procedure if exists p;
 set @old_mode= @@sql_mode;
-set @@sql_mode= cast(pow(2,32)-1 as unsigned integer);
 create event e1 on schedule every 1 day do select 1;
 select @@sql_mode into @full_mode;
 set @@sql_mode= @old_mode;
diff --git a/mysql-test/main/events_bugs.test b/mysql-test/main/events_bugs.test
index 76288c8fbae..4a156307ff0 100644
--- a/mysql-test/main/events_bugs.test
+++ b/mysql-test/main/events_bugs.test
@@ -1179,7 +1179,7 @@ DROP USER mysqltest_u1 at localhost;
 drop procedure if exists p;
 --enable_warnings
 set @old_mode= @@sql_mode;
-set @@sql_mode= cast(pow(2,32)-1 as unsigned integer);
+# set @@sql_mode= cast(pow(2,32)-1 as unsigned integer);
 create event e1 on schedule every 1 day do select 1;
 select @@sql_mode into @full_mode;
 set @@sql_mode= @old_mode;
diff --git a/mysql-test/main/except.result b/mysql-test/main/except.result
index 594bb7118eb..23da19d46e3 100644
--- a/mysql-test/main/except.result
+++ b/mysql-test/main/except.result
@@ -24,7 +24,7 @@ id	select_type	table	type	possible_keys	key	key_len	ref	rows	filtered	Extra
 3	EXCEPT	t2	ALL	NULL	NULL	NULL	NULL	2	100.00	
 NULL	EXCEPT RESULT	<except2,3>	ALL	NULL	NULL	NULL	NULL	NULL	NULL	
 Warnings:
-Note	1003	/* select#1 */ select `a`.`a` AS `a`,`a`.`b` AS `b` from ((/* select#2 */ select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` from `test`.`t1`) except (/* select#3 */ select `test`.`t2`.`c` AS `c`,`test`.`t2`.`d` AS `d` from `test`.`t2`)) `a`
+Note	1003	/* select#1 */ select `a`.`a` AS `a`,`a`.`b` AS `b` from (/* select#2 */ select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` from `test`.`t1` except (/* select#3 */ select `test`.`t2`.`c` AS `c`,`test`.`t2`.`d` AS `d` from `test`.`t2`)) `a`
 EXPLAIN format=json (select a,b from t1) except (select c,d from t2);
 EXPLAIN
 {
@@ -229,7 +229,7 @@ id	select_type	table	type	possible_keys	key	key_len	ref	rows	filtered	Extra
 3	EXCEPT	t4	ALL	NULL	NULL	NULL	NULL	2	100.00	Using join buffer (flat, BNL join)
 NULL	EXCEPT RESULT	<except2,3>	ALL	NULL	NULL	NULL	NULL	NULL	NULL	
 Warnings:
-Note	1003	/* select#1 */ select `a`.`a` AS `a`,`a`.`b` AS `b`,`a`.`e` AS `e`,`a`.`f` AS `f` from ((/* select#2 */ select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b`,`test`.`t3`.`e` AS `e`,`test`.`t3`.`f` AS `f` from `test`.`t1` join `test`.`t3`) except (/* select#3 */ select `test`.`t2`.`c` AS `c`,`test`.`t2`.`d` AS `d`,`test`.`t4`.`g` AS `g`,`test`.`t4`.`h` AS `h` from `test`.`t2` join `test`.`t4`)) `a`
+Note	1003	/* select#1 */ select `a`.`a` AS `a`,`a`.`b` AS `b`,`a`.`e` AS `e`,`a`.`f` AS `f` from (/* select#2 */ select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b`,`test`.`t3`.`e` AS `e`,`test`.`t3`.`f` AS `f` from `test`.`t1` join `test`.`t3` except (/* select#3 */ select `test`.`t2`.`c` AS `c`,`test`.`t2`.`d` AS `d`,`test`.`t4`.`g` AS `g`,`test`.`t4`.`h` AS `h` from `test`.`t2` join `test`.`t4`)) `a`
 EXPLAIN format=json (select a,b,e,f from t1,t3) except (select c,d,g,h from t2,t4);
 EXPLAIN
 {
@@ -500,7 +500,7 @@ a
 (select 1 from dual) except (select 1 from dual);
 1
 (select 1 from dual into @v) except (select 1 from dual);
-ERROR HY000: Incorrect usage of EXCEPT and INTO
+ERROR 42000: Incorrect usage/placement of 'INTO'
 select 1 from dual ORDER BY 1 except select 1 from dual;
 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 'except select 1 from dual' at line 1
 select 1 as a from dual union all select 1 from dual;
@@ -508,7 +508,7 @@ a
 1
 1
 select 1 from dual except all select 1 from dual;
-ERROR HY000: Incorrect usage of EXCEPT and ALL
+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 'all select 1 from dual' at line 1
 create table t1 (a int, b blob, a1 int, b1 blob) engine=MyISAM;
 create table t2 (c int, d blob, c1 int, d1 blob) engine=MyISAM;
 insert into t1 values (1,"ddd", 1, "sdfrrwwww"),(2, "fgh", 2, "dffggtt");
diff --git a/mysql-test/main/except.test b/mysql-test/main/except.test
index f88d9b29e35..cd672ae6fbd 100644
--- a/mysql-test/main/except.test
+++ b/mysql-test/main/except.test
@@ -60,13 +60,13 @@ drop tables t1,t2,t3,t4;
 
 select 1 as a from dual except select 1 from dual;
 (select 1 from dual) except (select 1 from dual);
---error ER_WRONG_USAGE
+--error ER_CANT_USE_OPTION_HERE
 (select 1 from dual into @v) except (select 1 from dual);
 --error ER_PARSE_ERROR
 select 1 from dual ORDER BY 1 except select 1 from dual;
 
 select 1 as a from dual union all select 1 from dual;
---error ER_WRONG_USAGE
+--error ER_PARSE_ERROR
 select 1 from dual except all select 1 from dual;
 
 
diff --git a/mysql-test/main/fulltext_order_by.result b/mysql-test/main/fulltext_order_by.result
index c2f57c6f9c2..a350a55c75d 100644
--- a/mysql-test/main/fulltext_order_by.result
+++ b/mysql-test/main/fulltext_order_by.result
@@ -126,7 +126,7 @@ group by
 a.text, b.id, b.betreff
 order by 
 match(b.betreff) against ('+abc' in boolean mode) desc;
-ERROR 42000: Table 'b' from one of the SELECTs cannot be used in field list
+ERROR 42000: Table 'b' from one of the SELECTs cannot be used in ORDER clause
 select a.text, b.id, b.betreff
 from 
 t2 a inner join t3 b on a.id = b.forum inner join
@@ -142,7 +142,7 @@ where
 match(c.beitrag) against ('+abc' in boolean mode)
 order by 
 match(b.betreff) against ('+abc' in boolean mode) desc;
-ERROR 42000: Table 'b' from one of the SELECTs cannot be used in field list
+ERROR 42000: Table 'b' from one of the SELECTs cannot be used in ORDER clause
 select a.text, b.id, b.betreff
 from 
 t2 a inner join t3 b on a.id = b.forum inner join
diff --git a/mysql-test/main/func_analyse.result b/mysql-test/main/func_analyse.result
index 1e78e603bca..68ceb8aed02 100644
--- a/mysql-test/main/func_analyse.result
+++ b/mysql-test/main/func_analyse.result
@@ -19,7 +19,7 @@ test.t1.empty_string			0	0	4	0	0.0000	NULL	CHAR(0) NOT NULL
 test.t1.bool	N	Y	1	1	0	0	1.0000	NULL	ENUM('N','Y') NOT NULL
 test.t1.d	2002-03-03	2002-03-05	10	10	0	0	10.0000	NULL	ENUM('2002-03-03','2002-03-04','2002-03-05') NOT NULL
 create table t2 select * from t1 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 'procedure analyse()' at line 1
+ERROR 42000: Incorrect usage/placement of 'PROCEDURE'
 drop table t1;
 EXPLAIN SELECT 1 FROM (SELECT 1) a PROCEDURE ANALYSE();
 ERROR HY000: Incorrect usage of PROCEDURE and subquery
@@ -120,7 +120,7 @@ CREATE TABLE t1(a INT);
 INSERT INTO t1 VALUES (1),(2);
 # should not crash
 CREATE TABLE t2 SELECT 1 FROM t1, t1 t3 GROUP BY t3.a 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 'PROCEDURE ANALYSE()' at line 1
+ERROR 42000: Incorrect usage/placement of 'PROCEDURE'
 DROP TABLE t1;
 End of 5.0 tests
 #
@@ -158,16 +158,24 @@ Field_name	Min_value	Max_value	Min_length	Max_length	Empties_or_zeros	Nulls	Avg_
 ((SELECT 1 FROM DUAL PROCEDURE ANALYSE()));
 Field_name	Min_value	Max_value	Min_length	Max_length	Empties_or_zeros	Nulls	Avg_value_or_avg_length	Std	Optimal_fieldtype
 1	1	1	1	1	0	0	1.0000	0.0000	ENUM('1') NOT NULL
+(SELECT 1 FROM DUAL) PROCEDURE ANALYSE();
+Field_name	Min_value	Max_value	Min_length	Max_length	Empties_or_zeros	Nulls	Avg_value_or_avg_length	Std	Optimal_fieldtype
+1	1	1	1	1	0	0	1.0000	0.0000	ENUM('1') NOT NULL
+((SELECT 1 FROM DUAL)) PROCEDURE ANALYSE();
+Field_name	Min_value	Max_value	Min_length	Max_length	Empties_or_zeros	Nulls	Avg_value_or_avg_length	Std	Optimal_fieldtype
+1	1	1	1	1	0	0	1.0000	0.0000	ENUM('1') NOT NULL
+create table t1 (a int);
 SELECT * FROM t1 UNION SELECT * FROM t1 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 'PROCEDURE analyse()' at line 1
+ERROR 42000: Incorrect usage/placement of 'PROCEDURE'
+drop table t1;
 #
 # MDEV-10030 sql_yacc.yy: Split table_expression and remove PROCEDURE from create_select, select_paren_derived, select_derived2, query_specification
 #
 SELECT * FROM (SELECT * FROM t1 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 'PROCEDURE ANALYSE())' at line 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 '' at line 1
 SELECT * FROM t1 NATURAL JOIN (SELECT * FROM t2 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 'PROCEDURE ANALYSE())' at line 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 '' at line 1
 SELECT (SELECT 1 FROM t1 PROCEDURE ANALYSE()) FROM t2;
-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()) FROM t2' at line 1
+ERROR 42000: Incorrect usage/placement of 'PROCEDURE'
 SELECT ((SELECT 1 FROM t1 PROCEDURE ANALYSE())) FROM t2;
-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())) FROM t2' at line 1
+ERROR 42000: Incorrect usage/placement of 'PROCEDURE'
diff --git a/mysql-test/main/func_analyse.test b/mysql-test/main/func_analyse.test
index d99f5c0fa9a..24fdd9a10e2 100644
--- a/mysql-test/main/func_analyse.test
+++ b/mysql-test/main/func_analyse.test
@@ -11,7 +11,7 @@ insert into t1 values (1,2,"","Y","2002-03-03"), (3,4,"","N","2002-03-04"), (5,6
 select count(*) from t1 procedure analyse();
 select * from t1 procedure analyse();
 select * from t1 procedure analyse(2);
---error ER_PARSE_ERROR
+--error ER_CANT_USE_OPTION_HERE
 create table t2 select * from t1 procedure analyse();
 drop table t1;
 
@@ -127,7 +127,7 @@ CREATE TABLE t1(a INT);
 INSERT INTO t1 VALUES (1),(2);
 
 --echo # should not crash
---error ER_PARSE_ERROR
+--error ER_CANT_USE_OPTION_HERE
 CREATE TABLE t2 SELECT 1 FROM t1, t1 t3 GROUP BY t3.a PROCEDURE ANALYSE();
 
 DROP TABLE t1;
@@ -161,12 +161,17 @@ DROP TABLE t1, t2;
 --echo #
 --echo # Start of 10.2 tests
 --echo #
+# --error ER_PARSE_ERROR
 (SELECT 1 FROM DUAL PROCEDURE ANALYSE());
+# --error ER_PARSE_ERROR
 ((SELECT 1 FROM DUAL PROCEDURE ANALYSE()));
+(SELECT 1 FROM DUAL) PROCEDURE ANALYSE();
+((SELECT 1 FROM DUAL)) PROCEDURE ANALYSE();
 
-# TODO:
---error ER_PARSE_ERROR
+create table t1 (a int);
+--error ER_CANT_USE_OPTION_HERE
 SELECT * FROM t1 UNION SELECT * FROM t1 PROCEDURE analyse();
+drop table t1;
 
 --echo #
 --echo # MDEV-10030 sql_yacc.yy: Split table_expression and remove PROCEDURE from create_select, select_paren_derived, select_derived2, query_specification
@@ -177,7 +182,7 @@ SELECT * FROM (SELECT * FROM t1 PROCEDURE ANALYSE());
 --ERROR ER_PARSE_ERROR
 SELECT * FROM t1 NATURAL JOIN (SELECT * FROM t2 PROCEDURE ANALYSE());
 
---error ER_PARSE_ERROR
+--error ER_CANT_USE_OPTION_HERE
 SELECT (SELECT 1 FROM t1 PROCEDURE ANALYSE()) FROM t2;
---error ER_PARSE_ERROR
+--error ER_CANT_USE_OPTION_HERE
 SELECT ((SELECT 1 FROM t1 PROCEDURE ANALYSE())) FROM t2;
diff --git a/mysql-test/main/intersect.result b/mysql-test/main/intersect.result
index b589e8bd17e..b74c7ecbe0c 100644
--- a/mysql-test/main/intersect.result
+++ b/mysql-test/main/intersect.result
@@ -37,7 +37,7 @@ id	select_type	table	type	possible_keys	key	key_len	ref	rows	filtered	Extra
 4	INTERSECT	t3	ALL	NULL	NULL	NULL	NULL	3	100.00	
 NULL	INTERSECT RESULT	<intersect2,3,4>	ALL	NULL	NULL	NULL	NULL	NULL	NULL	
 Warnings:
-Note	1003	/* select#1 */ select `a`.`a` AS `a`,`a`.`b` AS `b` from ((/* select#2 */ select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` from `test`.`t1`) intersect (/* select#3 */ select `test`.`t2`.`c` AS `c`,`test`.`t2`.`d` AS `d` from `test`.`t2`) intersect (/* select#4 */ select `test`.`t3`.`e` AS `e`,`test`.`t3`.`f` AS `f` from `test`.`t3`)) `a`
+Note	1003	/* select#1 */ select `a`.`a` AS `a`,`a`.`b` AS `b` from (/* select#2 */ select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` from `test`.`t1` intersect (/* select#3 */ select `test`.`t2`.`c` AS `c`,`test`.`t2`.`d` AS `d` from `test`.`t2`) intersect (/* select#4 */ select `test`.`t3`.`e` AS `e`,`test`.`t3`.`f` AS `f` from `test`.`t3`)) `a`
 EXPLAIN format=json (select a,b from t1) intersect (select c,d from t2) intersect (select e,f from t3);
 EXPLAIN
 {
@@ -278,7 +278,7 @@ id	select_type	table	type	possible_keys	key	key_len	ref	rows	filtered	Extra
 3	INTERSECT	t3	ALL	NULL	NULL	NULL	NULL	3	100.00	Using join buffer (flat, BNL join)
 NULL	INTERSECT RESULT	<intersect2,3>	ALL	NULL	NULL	NULL	NULL	NULL	NULL	
 Warnings:
-Note	1003	/* select#1 */ select `a`.`a` AS `a`,`a`.`b` AS `b` from ((/* select#2 */ select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` from `test`.`t1`) intersect (/* select#3 */ select `test`.`t2`.`c` AS `c`,`test`.`t3`.`e` AS `e` from `test`.`t2` join `test`.`t3`)) `a`
+Note	1003	/* select#1 */ select `a`.`a` AS `a`,`a`.`b` AS `b` from (/* select#2 */ select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` from `test`.`t1` intersect (/* select#3 */ select `test`.`t2`.`c` AS `c`,`test`.`t3`.`e` AS `e` from `test`.`t2` join `test`.`t3`)) `a`
 EXPLAIN format=json (select a,b from t1) intersect (select c,e from t2,t3);
 EXPLAIN
 {
@@ -497,7 +497,7 @@ a
 1
 1
 (select 1 from dual into @v) intersect (select 1 from dual);
-ERROR HY000: Incorrect usage of INTERSECT and INTO
+ERROR 42000: Incorrect usage/placement of 'INTO'
 select 1 from dual ORDER BY 1 intersect select 1 from dual;
 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 'intersect select 1 from dual' at line 1
 select 1 as a from dual union all select 1 from dual;
@@ -505,7 +505,7 @@ a
 1
 1
 select 1 from dual intersect all select 1 from dual;
-ERROR HY000: Incorrect usage of INTERSECT and ALL
+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 'all select 1 from dual' at line 1
 create table t1 (a int, b blob, a1 int, b1 blob);
 create table t2 (c int, d blob, c1 int, d1 blob);
 insert into t1 values (1,"ddd", 1, "sdfrrwwww"),(2, "fgh", 2, "dffggtt");
@@ -599,14 +599,14 @@ explain extended
 (select a,b from t1) union (select c,d from t2) intersect (select e,f from t3) union (select 4,4);
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	filtered	Extra
 1	PRIMARY	t1	ALL	NULL	NULL	NULL	NULL	2	100.00	
-3	UNION	<derived2>	ALL	NULL	NULL	NULL	NULL	2	100.00	
+5	UNION	<derived2>	ALL	NULL	NULL	NULL	NULL	2	100.00	
 2	DERIVED	t2	ALL	NULL	NULL	NULL	NULL	2	100.00	
-4	INTERSECT	t3	ALL	NULL	NULL	NULL	NULL	2	100.00	
-NULL	INTERSECT RESULT	<intersect2,4>	ALL	NULL	NULL	NULL	NULL	NULL	NULL	
-5	UNION	NULL	NULL	NULL	NULL	NULL	NULL	NULL	NULL	No tables used
-NULL	UNION RESULT	<union1,3,5>	ALL	NULL	NULL	NULL	NULL	NULL	NULL	
+3	INTERSECT	t3	ALL	NULL	NULL	NULL	NULL	2	100.00	
+NULL	INTERSECT RESULT	<intersect2,3>	ALL	NULL	NULL	NULL	NULL	NULL	NULL	
+4	UNION	NULL	NULL	NULL	NULL	NULL	NULL	NULL	NULL	No tables used
+NULL	UNION RESULT	<union1,5,4>	ALL	NULL	NULL	NULL	NULL	NULL	NULL	
 Warnings:
-Note	1003	(/* select#1 */ select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` from `test`.`t1`) union /* select#3 */ select `__3`.`c` AS `c`,`__3`.`d` AS `d` from ((/* select#2 */ select `test`.`t2`.`c` AS `c`,`test`.`t2`.`d` AS `d` from `test`.`t2`) intersect (/* select#4 */ select `test`.`t3`.`e` AS `e`,`test`.`t3`.`f` AS `f` from `test`.`t3`)) `__3` union (/* select#5 */ select 4 AS `4`,4 AS `4`)
+Note	1003	(/* select#1 */ select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` from `test`.`t1`) union /* select#5 */ select `__5`.`c` AS `c`,`__5`.`d` AS `d` from ((/* select#2 */ select `test`.`t2`.`c` AS `c`,`test`.`t2`.`d` AS `d` from `test`.`t2`) intersect (/* select#3 */ select `test`.`t3`.`e` AS `e`,`test`.`t3`.`f` AS `f` from `test`.`t3`)) `__5` union (/* select#4 */ select 4 AS `4`,4 AS `4`)
 (select e,f from t3) intersect (select c,d from t2) union (select a,b from t1) union (select 4,4);
 e	f
 3	3
@@ -686,7 +686,7 @@ a	b
 drop procedure p1;
 show create view v1;
 View	Create View	character_set_client	collation_connection
-v1	CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS (select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` from `test`.`t1`) union select `__3`.`c` AS `c`,`__3`.`d` AS `d` from ((select `test`.`t2`.`c` AS `c`,`test`.`t2`.`d` AS `d` from `test`.`t2`) intersect (select `test`.`t3`.`e` AS `e`,`test`.`t3`.`f` AS `f` from `test`.`t3`)) `__3` union (select 4 AS `4`,4 AS `4`)	latin1	latin1_swedish_ci
+v1	CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS (select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` from `test`.`t1`) union select `__6`.`c` AS `c`,`__6`.`d` AS `d` from (select `test`.`t2`.`c` AS `c`,`test`.`t2`.`d` AS `d` from `test`.`t2` intersect (select `test`.`t3`.`e` AS `e`,`test`.`t3`.`f` AS `f` from `test`.`t3`)) `__6` union (select 4 AS `4`,4 AS `4`)	latin1	latin1_swedish_ci
 drop view v1;
 drop tables t1,t2,t3;
 #
diff --git a/mysql-test/main/intersect.test b/mysql-test/main/intersect.test
index d9d420c786b..72e6c3d632f 100644
--- a/mysql-test/main/intersect.test
+++ b/mysql-test/main/intersect.test
@@ -59,13 +59,13 @@ drop tables t1,t2,t3;
 
 select 1 as a from dual intersect select 1 from dual;
 (select 1 from dual) intersect (select 1 from dual);
---error ER_WRONG_USAGE
+--error ER_CANT_USE_OPTION_HERE
 (select 1 from dual into @v) intersect (select 1 from dual);
 --error ER_PARSE_ERROR
 select 1 from dual ORDER BY 1 intersect select 1 from dual;
 
 select 1 as a from dual union all select 1 from dual;
---error ER_WRONG_USAGE
+--error ER_PARSE_ERROR
 select 1 from dual intersect all select 1 from dual;
 
 
diff --git a/mysql-test/main/join.result b/mysql-test/main/join.result
index 046674d5569..5978b261b3a 100644
--- a/mysql-test/main/join.result
+++ b/mysql-test/main/join.result
@@ -1484,7 +1484,7 @@ DROP TABLE t1,t2,t3,t4,t5;
 # MDEV-4752: Segfault during parsing of illegal query
 #
 SELECT * FROM t5 JOIN (t1 JOIN t2 UNION SELECT * FROM t3 JOIN t4);
-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 'SELECT * FROM t3 JOIN t4)' at line 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 * FROM t3 JOIN t4)' at line 1
 #
 # MDEV-4959: join of const table with NULL fields
 #
diff --git a/mysql-test/main/join_nested.result b/mysql-test/main/join_nested.result
index 708c72fffb5..b6b4716d8b1 100644
--- a/mysql-test/main/join_nested.result
+++ b/mysql-test/main/join_nested.result
@@ -1150,7 +1150,7 @@ a	b	a	b
 4	2	2	2
 5	3	NULL	NULL
 SELECT t2.a,t2.b,t3.a,t3.b
-FROM t2 LEFT JOIN (t3) ON t2.b=t3.b
+FROM t2 LEFT JOIN t3 ON t2.b=t3.b
 WHERE t2.a = 4 OR (t2.a > 4 AND t3.a IS NULL);
 a	b	a	b
 4	2	1	2
diff --git a/mysql-test/main/join_nested.test b/mysql-test/main/join_nested.test
index e60b7827f75..77d0e4154c1 100644
--- a/mysql-test/main/join_nested.test
+++ b/mysql-test/main/join_nested.test
@@ -683,7 +683,7 @@ SELECT t2.a,t2.b,t3.a,t3.b
     WHERE t2.a = 4 OR (t2.a > 4 AND t3.a IS NULL);
 
 SELECT t2.a,t2.b,t3.a,t3.b
-  FROM t2 LEFT JOIN (t3) ON t2.b=t3.b
+  FROM t2 LEFT JOIN t3 ON t2.b=t3.b
     WHERE t2.a = 4 OR (t2.a > 4 AND t3.a IS NULL);
 
 ALTER TABLE t3
diff --git a/mysql-test/main/join_nested_jcl6.result b/mysql-test/main/join_nested_jcl6.result
index eb59531b7d2..de5ebfbe989 100644
--- a/mysql-test/main/join_nested_jcl6.result
+++ b/mysql-test/main/join_nested_jcl6.result
@@ -1161,7 +1161,7 @@ a	b	a	b
 4	2	2	2
 5	3	NULL	NULL
 SELECT t2.a,t2.b,t3.a,t3.b
-FROM t2 LEFT JOIN (t3) ON t2.b=t3.b
+FROM t2 LEFT JOIN t3 ON t2.b=t3.b
 WHERE t2.a = 4 OR (t2.a > 4 AND t3.a IS NULL);
 a	b	a	b
 4	2	1	2
diff --git a/mysql-test/main/parser.result b/mysql-test/main/parser.result
index a1c6e86a129..fd18b74be32 100644
--- a/mysql-test/main/parser.result
+++ b/mysql-test/main/parser.result
@@ -705,6 +705,9 @@ FOR UPDATE;
 1
 1
 SELECT 1 FROM DUAL WHERE 1 GROUP BY 1 HAVING 1 ORDER BY 1
+PROCEDURE ANALYSE();
+ERROR HY000: Can't use ORDER clause with this procedure
+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
@@ -715,7 +718,7 @@ FOR UPDATE) a;
 SELECT 1 FROM
 (SELECT 1 FROM DUAL WHERE 1 GROUP BY 1 HAVING 1 ORDER BY 1
 PROCEDURE ANALYSE() FOR UPDATE) 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 'PROCEDURE ANALYSE() FOR UPDATE) a' at line 3
+ERROR 42000: Incorrect usage/placement of 'PROCEDURE'
 SELECT 1 FROM t1
 WHERE EXISTS(SELECT 1 FROM DUAL WHERE 1 GROUP BY 1 HAVING 1 ORDER BY 1
 FOR UPDATE);
@@ -723,7 +726,7 @@ FOR UPDATE);
 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 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'PROCEDURE ANALYSE() FOR UPDATE)' at line 3
+ERROR 42000: Incorrect usage/placement of 'PROCEDURE'
 SELECT 1 FROM t1
 UNION
 SELECT 1 FROM DUAL WHERE 1 GROUP BY 1 HAVING 1 ORDER BY 1
@@ -734,7 +737,7 @@ SELECT 1 FROM t1
 UNION
 SELECT 1 FROM DUAL WHERE 1 GROUP BY 1 HAVING 1 ORDER BY 1
 PROCEDURE ANALYSE() FOR UPDATE;
-ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'PROCEDURE ANALYSE() FOR UPDATE' at line 4
+ERROR 42000: Incorrect usage/placement of 'PROCEDURE'
 SELECT 1 FROM DUAL PROCEDURE ANALYSE() 
 UNION
 SELECT 1 FROM t1;
@@ -750,11 +753,11 @@ FOR UPDATE);
 UNION 
 (SELECT 1 FROM DUAL WHERE 1 GROUP BY 1 HAVING 1 ORDER BY 1
 PROCEDURE ANALYSE() FOR UPDATE);
-ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'PROCEDURE ANALYSE() FOR UPDATE)' at line 4
+ERROR 42000: Incorrect usage/placement of 'PROCEDURE'
 # "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;
+(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
@@ -769,10 +772,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 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
+ERROR 42000: Incorrect usage/placement of 'INTO'
 SELECT 1 INTO @var17727401_1 FROM DUAL
 INTO @var17727401_2;
-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
+ERROR 42000: Incorrect usage/placement of '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
@@ -784,41 +787,29 @@ 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 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
+ERROR 42000: Incorrect usage/placement of '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
+ERROR 42000: Incorrect usage/placement of 'INTO'
 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
+ERROR 42000: Incorrect usage/placement of 'INTO'
 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
+ERROR 42000: Incorrect usage/placement of 'INTO'
 SELECT 1 FROM t1 INTO @var17727401 UNION SELECT 1 FROM t1 INTO 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 '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
+ERROR 42000: Undeclared variable: t1
 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 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
+ERROR 42000: Incorrect usage/placement of 'INTO'
 SELECT 1 FROM t1 PROCEDURE ANALYSE() 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
+ERROR 42000: Incorrect usage/placement of '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
+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 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
+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 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);
@@ -1265,19 +1256,19 @@ CREATE TABLE t1 (i INT);
 (SELECT * FROM t1 PROCEDURE ANALYSE(10, 10))
 UNION
 (SELECT * FROM t1 PROCEDURE ANALYSE(10, 10));
-ERROR HY000: Incorrect usage of UNION and SELECT ... PROCEDURE ANALYSE()
+ERROR 42000: Incorrect usage/placement of 'PROCEDURE'
 (SELECT * FROM t1 PROCEDURE ANALYSE(10, 10))
 UNION
 SELECT * FROM t1 PROCEDURE ANALYSE(10, 10);
-ERROR HY000: Incorrect usage of UNION and SELECT ... PROCEDURE ANALYSE()
+ERROR 42000: Incorrect usage/placement of 'PROCEDURE'
 (SELECT * FROM t1 PROCEDURE ANALYSE(10, 10))
 UNION
 (SELECT 1);
-ERROR HY000: Incorrect usage of UNION and SELECT ... PROCEDURE ANALYSE()
+ERROR 42000: Incorrect usage/placement of 'PROCEDURE'
 (SELECT * FROM t1 PROCEDURE ANALYSE(10, 10))
 UNION
 SELECT 1;
-ERROR HY000: Incorrect usage of UNION and SELECT ... PROCEDURE ANALYSE()
+ERROR 42000: Incorrect usage/placement of 'PROCEDURE'
 SELECT * FROM t1 PROCEDURE ANALYSE(10, 10)
 UNION
 (SELECT * FROM t1 PROCEDURE ANALYSE(10, 10));
diff --git a/mysql-test/main/parser.test b/mysql-test/main/parser.test
index 1f176c6afc5..e9c10159260 100644
--- a/mysql-test/main/parser.test
+++ b/mysql-test/main/parser.test
@@ -825,6 +825,9 @@ 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();
+--error ER_ORDER_WITH_PROC
 SELECT 1 FROM DUAL WHERE 1 GROUP BY 1 HAVING 1 ORDER BY 1
   PROCEDURE ANALYSE() FOR UPDATE;
 
@@ -832,7 +835,7 @@ SELECT 1 FROM
   (SELECT 1 FROM DUAL WHERE 1 GROUP BY 1 HAVING 1 ORDER BY 1
    FOR UPDATE) a;
 
---error ER_PARSE_ERROR
+--error ER_CANT_USE_OPTION_HERE
 SELECT 1 FROM
   (SELECT 1 FROM DUAL WHERE 1 GROUP BY 1 HAVING 1 ORDER BY 1
    PROCEDURE ANALYSE() FOR UPDATE) a;
@@ -841,7 +844,7 @@ SELECT 1 FROM t1
   WHERE EXISTS(SELECT 1 FROM DUAL WHERE 1 GROUP BY 1 HAVING 1 ORDER BY 1
                FOR UPDATE);
 
---error ER_PARSE_ERROR
+--error ER_CANT_USE_OPTION_HERE
 SELECT 1 FROM t1
   WHERE EXISTS(SELECT 1 FROM DUAL WHERE 1 GROUP BY 1 HAVING 1 ORDER BY 1
                PROCEDURE ANALYSE() FOR UPDATE);
@@ -851,7 +854,7 @@ UNION
 SELECT 1 FROM DUAL WHERE 1 GROUP BY 1 HAVING 1 ORDER BY 1
   FOR UPDATE;
 
---error ER_PARSE_ERROR
+--error ER_CANT_USE_OPTION_HERE
 SELECT 1 FROM t1
 UNION
 SELECT 1 FROM DUAL WHERE 1 GROUP BY 1 HAVING 1 ORDER BY 1
@@ -867,7 +870,7 @@ UNION
 (SELECT 1 FROM DUAL WHERE 1 GROUP BY 1 HAVING 1 ORDER BY 1
  FOR UPDATE);
 
---error ER_PARSE_ERROR
+--error ER_CANT_USE_OPTION_HERE
 (SELECT 1 FROM t1)
 UNION 
 (SELECT 1 FROM DUAL WHERE 1 GROUP BY 1 HAVING 1 ORDER BY 1
@@ -876,7 +879,7 @@ UNION
 --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 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;
 
 
@@ -889,10 +892,10 @@ SELECT 1 INTO @var17727401;
 SELECT 1 INTO @var17727401 FROM t1;
 SELECT 1 INTO @var17727401 FROM DUAL;
 
---error ER_PARSE_ERROR
+--error ER_CANT_USE_OPTION_HERE
 SELECT 1 INTO @var17727401_1 FROM t1 INTO @var17727401_2;
 
---error ER_PARSE_ERROR
+--error ER_CANT_USE_OPTION_HERE
 SELECT 1 INTO @var17727401_1 FROM DUAL
   INTO @var17727401_2;
 
@@ -902,45 +905,45 @@ 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_PARSE_ERROR
+--error ER_CANT_USE_OPTION_HERE
 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
+--error ER_CANT_USE_OPTION_HERE
 SELECT (SELECT 1 FROM t1 INTO @var17727401);
---error ER_PARSE_ERROR
+--error ER_CANT_USE_OPTION_HERE
 SELECT 1 FROM (SELECT 1 FROM t1 INTO @var17727401) a;
---error ER_PARSE_ERROR
+--error ER_CANT_USE_OPTION_HERE
 SELECT EXISTS(SELECT 1 FROM t1 INTO @var17727401);
 
 --error ER_PARSE_ERROR
 SELECT 1 FROM t1 INTO @var17727401 UNION SELECT 1 FROM t1 INTO t1;
---error ER_WRONG_USAGE
+--error ER_SP_UNDECLARED_VAR
 (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_PARSE_ERROR
+--error ER_CANT_USE_OPTION_HERE
 SELECT 1 INTO @var17727401 FROM t1 PROCEDURE ANALYSE();
 
---error ER_PARSE_ERROR
+--error ER_CANT_USE_OPTION_HERE
 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;
+# (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;
+#--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;
+# (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);
@@ -1276,22 +1279,22 @@ DROP TABLE t1;
 --echo #
 
 CREATE TABLE t1 (i INT);
---error ER_WRONG_USAGE
+--error ER_CANT_USE_OPTION_HERE
 (SELECT * FROM t1 PROCEDURE ANALYSE(10, 10))
 UNION
 (SELECT * FROM t1 PROCEDURE ANALYSE(10, 10));
 
---error ER_WRONG_USAGE
+--error ER_CANT_USE_OPTION_HERE
 (SELECT * FROM t1 PROCEDURE ANALYSE(10, 10))
 UNION
 SELECT * FROM t1 PROCEDURE ANALYSE(10, 10);
 
---error ER_WRONG_USAGE
+--error ER_CANT_USE_OPTION_HERE
 (SELECT * FROM t1 PROCEDURE ANALYSE(10, 10))
 UNION
 (SELECT 1);
 
---error ER_WRONG_USAGE
+--error ER_CANT_USE_OPTION_HERE
 (SELECT * FROM t1 PROCEDURE ANALYSE(10, 10))
 UNION
 SELECT 1;
diff --git a/mysql-test/main/query_cache.result b/mysql-test/main/query_cache.result
index 9c010cbffc7..be5b3e3ea48 100644
--- a/mysql-test/main/query_cache.result
+++ b/mysql-test/main/query_cache.result
@@ -847,13 +847,6 @@ select '1' || '3' from t1;
 1
 1
 1
-set SQL_MODE=oracle;
-select '1' || '3' from t1;
-'1' || '3'
-13
-13
-13
-13
 set SQL_MODE=default;
 drop table t1;
 create table t1 (a varchar(20), b int);
@@ -876,7 +869,7 @@ Variable_name	Value
 Qcache_queries_in_cache	0
 show status like "Qcache_inserts";
 Variable_name	Value
-Qcache_inserts	19
+Qcache_inserts	18
 show status like "Qcache_hits";
 Variable_name	Value
 Qcache_hits	6
@@ -889,7 +882,7 @@ Variable_name	Value
 Qcache_queries_in_cache	1
 show status like "Qcache_inserts";
 Variable_name	Value
-Qcache_inserts	20
+Qcache_inserts	19
 show status like "Qcache_hits";
 Variable_name	Value
 Qcache_hits	7
@@ -1858,17 +1851,17 @@ DROP TABLE t1;
 SET GLOBAL query_cache_size= default;
 CREATE TABLE t1( a INT );
 SET @v = ( SELECT SQL_CACHE    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 '1 )' at line 1
+ERROR 42000: Incorrect usage/placement of 'SQL_CACHE'
 SET @v = ( SELECT SQL_NO_CACHE 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 '1 )' at line 1
+ERROR 42000: Incorrect usage/placement of 'SQL_NO_CACHE'
 SELECT a FROM t1 WHERE a IN ( SELECT SQL_CACHE    a FROM t1 );
-ERROR 42S22: Unknown column 'SQL_CACHE' in 'field list'
+ERROR 42000: Incorrect usage/placement of 'SQL_CACHE'
 SELECT a FROM t1 WHERE a IN ( SELECT SQL_NO_CACHE a FROM t1 );
-ERROR 42S22: Unknown column 'SQL_NO_CACHE' in 'field list'
+ERROR 42000: Incorrect usage/placement of 'SQL_NO_CACHE'
 SELECT ( SELECT SQL_CACHE a FROM t1 );
-ERROR 42S22: Unknown column 'SQL_CACHE' in 'field list'
+ERROR 42000: Incorrect usage/placement of 'SQL_CACHE'
 SELECT ( SELECT SQL_NO_CACHE a FROM t1 );
-ERROR 42S22: Unknown column 'SQL_NO_CACHE' in 'field list'
+ERROR 42000: Incorrect usage/placement of 'SQL_NO_CACHE'
 SELECT SQL_CACHE * FROM t1;
 a
 SELECT SQL_NO_CACHE * FROM t1;
@@ -1878,18 +1871,18 @@ ERROR 42000: Incorrect usage/placement of 'SQL_CACHE'
 SELECT * FROM t1 UNION SELECT SQL_NO_CACHE * FROM t1;
 ERROR 42000: Incorrect usage/placement of 'SQL_NO_CACHE'
 SELECT * FROM t1 WHERE a IN (SELECT SQL_CACHE a FROM t1);
-ERROR 42S22: Unknown column 'SQL_CACHE' in 'field list'
+ERROR 42000: Incorrect usage/placement of 'SQL_CACHE'
 SELECT * FROM t1 WHERE a IN (SELECT a FROM t1 UNION SELECT SQL_CACHE a FROM t1);
-ERROR 42S22: Unknown column 'SQL_CACHE' in 'field list'
+ERROR 42000: Incorrect usage/placement of 'SQL_CACHE'
 SELECT * FROM t1 UNION SELECT SQL_NO_CACHE * FROM t1;
 ERROR 42000: Incorrect usage/placement of 'SQL_NO_CACHE'
 SELECT * FROM t1 WHERE a IN (SELECT SQL_NO_CACHE a FROM t1);
-ERROR 42S22: Unknown column 'SQL_NO_CACHE' in 'field list'
+ERROR 42000: Incorrect usage/placement of 'SQL_NO_CACHE'
 SELECT * FROM t1 WHERE a IN 
 (SELECT a FROM t1 UNION SELECT SQL_NO_CACHE a FROM t1);
-ERROR 42S22: Unknown column 'SQL_NO_CACHE' in 'field list'
+ERROR 42000: Incorrect usage/placement of 'SQL_NO_CACHE'
 SELECT SQL_CACHE SQL_NO_CACHE * FROM t1;
-ERROR HY000: Incorrect usage of SQL_CACHE and SQL_NO_CACHE
+ERROR HY000: Incorrect usage of SQL_NO_CACHE and SQL_CACHE
 SELECT SQL_NO_CACHE SQL_CACHE * FROM t1;
 ERROR HY000: Incorrect usage of SQL_NO_CACHE and SQL_CACHE
 SELECT SQL_CACHE * FROM t1 UNION SELECT SQL_CACHE * FROM t1;
@@ -1902,10 +1895,10 @@ SELECT SQL_NO_CACHE * FROM t1 UNION SELECT SQL_NO_CACHE * FROM t1;
 ERROR 42000: Incorrect usage/placement of 'SQL_NO_CACHE'
 SELECT SQL_CACHE * FROM t1 WHERE a IN 
 (SELECT SQL_NO_CACHE a FROM t1);
-ERROR 42S22: Unknown column 'SQL_NO_CACHE' in 'field list'
+ERROR 42000: Incorrect usage/placement of 'SQL_NO_CACHE'
 SELECT SQL_CACHE * FROM t1 WHERE a IN 
 (SELECT a FROM t1 UNION SELECT SQL_NO_CACHE a FROM t1);
-ERROR 42S22: Unknown column 'SQL_NO_CACHE' in 'field list'
+ERROR 42000: Incorrect usage/placement of 'SQL_NO_CACHE'
 DROP TABLE t1;
 End of 5.1 tests
 #
diff --git a/mysql-test/main/query_cache.test b/mysql-test/main/query_cache.test
index 1b1e24bc6f4..8a924bd1f15 100644
--- a/mysql-test/main/query_cache.test
+++ b/mysql-test/main/query_cache.test
@@ -620,8 +620,8 @@ select c from t1 order by c, id;
 set max_sort_length=default;
 # sql_mode
 select '1' || '3' from t1;
-set SQL_MODE=oracle;
-select '1' || '3' from t1;
+#set SQL_MODE=oracle;
+#select '1' || '3' from t1;
 set SQL_MODE=default;
 drop table t1;
 # group_concat_max_len
@@ -1534,22 +1534,21 @@ SET GLOBAL query_cache_size= default;
 #
 CREATE TABLE t1( a INT );
 
---error ER_PARSE_ERROR
+--error ER_CANT_USE_OPTION_HERE
 SET @v = ( SELECT SQL_CACHE    1 );
---error ER_PARSE_ERROR
+--error ER_CANT_USE_OPTION_HERE
 SET @v = ( SELECT SQL_NO_CACHE 1 );
 
 #
-# Keywords 'SQL_CACHE' and 'SQL_NO_CACHE' are allowed as column names.
-# Hence the error messages are not intuitive.
+# Keywords 'SQL_CACHE' and 'SQL_NO_CACHE'.
 #
---error ER_BAD_FIELD_ERROR 
+--error ER_CANT_USE_OPTION_HERE
 SELECT a FROM t1 WHERE a IN ( SELECT SQL_CACHE    a FROM t1 );
---error ER_BAD_FIELD_ERROR 
+--error ER_CANT_USE_OPTION_HERE
 SELECT a FROM t1 WHERE a IN ( SELECT SQL_NO_CACHE a FROM t1 );
---error ER_BAD_FIELD_ERROR
+--error ER_CANT_USE_OPTION_HERE
 SELECT ( SELECT SQL_CACHE a FROM t1 );
---error ER_BAD_FIELD_ERROR
+--error ER_CANT_USE_OPTION_HERE
 SELECT ( SELECT SQL_NO_CACHE a FROM t1 );
 
 SELECT SQL_CACHE * FROM t1;
@@ -1560,16 +1559,16 @@ SELECT SQL_NO_CACHE * FROM t1;
 SELECT * FROM t1 UNION SELECT SQL_CACHE * FROM t1;
 --error ER_CANT_USE_OPTION_HERE
 SELECT * FROM t1 UNION SELECT SQL_NO_CACHE * FROM t1;
---error ER_BAD_FIELD_ERROR
+--error ER_CANT_USE_OPTION_HERE
 SELECT * FROM t1 WHERE a IN (SELECT SQL_CACHE a FROM t1);
---error ER_BAD_FIELD_ERROR
+--error ER_CANT_USE_OPTION_HERE
 SELECT * FROM t1 WHERE a IN (SELECT a FROM t1 UNION SELECT SQL_CACHE a FROM t1);
 
 --error ER_CANT_USE_OPTION_HERE
 SELECT * FROM t1 UNION SELECT SQL_NO_CACHE * FROM t1;
---error ER_BAD_FIELD_ERROR
+--error ER_CANT_USE_OPTION_HERE
 SELECT * FROM t1 WHERE a IN (SELECT SQL_NO_CACHE a FROM t1);
---error ER_BAD_FIELD_ERROR
+--error ER_CANT_USE_OPTION_HERE
 SELECT * FROM t1 WHERE a IN 
   (SELECT a FROM t1 UNION SELECT SQL_NO_CACHE a FROM t1);
 --error ER_WRONG_USAGE
@@ -1584,10 +1583,10 @@ SELECT SQL_CACHE * FROM t1 UNION SELECT SQL_NO_CACHE * FROM t1;
 SELECT SQL_NO_CACHE * FROM t1 UNION SELECT SQL_CACHE * FROM t1;
 --error ER_CANT_USE_OPTION_HERE
 SELECT SQL_NO_CACHE * FROM t1 UNION SELECT SQL_NO_CACHE * FROM t1;
---error ER_BAD_FIELD_ERROR
+--error ER_CANT_USE_OPTION_HERE
 SELECT SQL_CACHE * FROM t1 WHERE a IN 
   (SELECT SQL_NO_CACHE a FROM t1);
---error ER_BAD_FIELD_ERROR
+--error ER_CANT_USE_OPTION_HERE
 SELECT SQL_CACHE * FROM t1 WHERE a IN 
   (SELECT a FROM t1 UNION SELECT SQL_NO_CACHE a FROM t1);
 
diff --git a/mysql-test/main/show_check.result b/mysql-test/main/show_check.result
index 5083f1e615b..f4e2047414c 100644
--- a/mysql-test/main/show_check.result
+++ b/mysql-test/main/show_check.result
@@ -757,11 +757,11 @@ View	Create View	character_set_client	collation_connection
 v1	CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select sql_no_cache current_timestamp() AS `NOW()`	binary	binary
 DROP VIEW v1;
 CREATE VIEW v1 AS SELECT SQL_CACHE SQL_NO_CACHE NOW();
-ERROR HY000: Incorrect usage of SQL_CACHE and SQL_NO_CACHE
+ERROR HY000: Incorrect usage of SQL_NO_CACHE and SQL_CACHE
 CREATE VIEW v1 AS SELECT SQL_NO_CACHE SQL_CACHE NOW();
 ERROR HY000: Incorrect usage of SQL_NO_CACHE and SQL_CACHE
 CREATE VIEW v1 AS SELECT SQL_CACHE SQL_NO_CACHE SQL_CACHE NOW();
-ERROR HY000: Incorrect usage of SQL_CACHE and SQL_NO_CACHE
+ERROR HY000: Option 'SQL_CACHE' used twice in statement
 CREATE PROCEDURE p1()
 BEGIN
 SET @s= 'CREATE VIEW v1 AS SELECT SQL_CACHE 1';
diff --git a/mysql-test/main/show_check.test b/mysql-test/main/show_check.test
index a24fa632ea5..b6885b1fcaf 100644
--- a/mysql-test/main/show_check.test
+++ b/mysql-test/main/show_check.test
@@ -558,7 +558,7 @@ CREATE VIEW v1 AS SELECT SQL_CACHE SQL_NO_CACHE NOW();
 --error ER_WRONG_USAGE
 CREATE VIEW v1 AS SELECT SQL_NO_CACHE SQL_CACHE NOW();
 
---error ER_WRONG_USAGE
+--error ER_DUP_ARGUMENT
 CREATE VIEW v1 AS SELECT SQL_CACHE SQL_NO_CACHE SQL_CACHE NOW();
 
 # Check CREATE VIEW in a prepared statement in a procedure.
diff --git a/mysql-test/main/sp-error.result b/mysql-test/main/sp-error.result
index fc43bdf17e9..de4c4cf3103 100644
--- a/mysql-test/main/sp-error.result
+++ b/mysql-test/main/sp-error.result
@@ -1227,16 +1227,16 @@ DROP PROCEDURE IF EXISTS bug14702;
 DROP TABLE IF EXISTS t1;
 CREATE TABLE t1 (i INT);
 CREATE PROCEDURE bug20953() CREATE VIEW v AS SELECT 1 INTO @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 @a' at line 1
+ERROR 42000: Incorrect usage/placement of 'INTO'
 CREATE PROCEDURE bug20953() CREATE VIEW v AS SELECT 1 INTO DUMPFILE "file";
-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 DUMPFILE "file"' at line 1
+ERROR 42000: Incorrect usage/placement of 'INTO'
 CREATE PROCEDURE bug20953() CREATE VIEW v AS SELECT 1 INTO OUTFILE "file";
-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 OUTFILE "file"' at line 1
+ERROR 42000: Incorrect usage/placement of 'INTO'
 CREATE PROCEDURE bug20953()
 CREATE VIEW v AS SELECT i FROM t1 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 'PROCEDURE ANALYSE()' at line 2
+ERROR 42000: Incorrect usage/placement of 'PROCEDURE'
 CREATE PROCEDURE bug20953() CREATE VIEW v AS SELECT 1 FROM (SELECT 1) AS d1 into @w;
-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 @w' at line 1
+ERROR 42000: Incorrect usage/placement of 'INTO'
 CREATE PROCEDURE bug20953(i INT) CREATE VIEW v AS SELECT i;
 ERROR HY000: View's SELECT contains a variable or parameter
 CREATE PROCEDURE bug20953()
diff --git a/mysql-test/main/sp-error.test b/mysql-test/main/sp-error.test
index 0e16948f438..88d9809265a 100644
--- a/mysql-test/main/sp-error.test
+++ b/mysql-test/main/sp-error.test
@@ -1785,16 +1785,16 @@ CREATE TABLE t1 (i INT);
 
 # We do not have to drop this procedure and view because they won't be
 # created.
---error ER_PARSE_ERROR
+--error ER_CANT_USE_OPTION_HERE
 CREATE PROCEDURE bug20953() CREATE VIEW v AS SELECT 1 INTO @a;
---error ER_PARSE_ERROR
+--error ER_CANT_USE_OPTION_HERE
 CREATE PROCEDURE bug20953() CREATE VIEW v AS SELECT 1 INTO DUMPFILE "file";
---error ER_PARSE_ERROR
+--error ER_CANT_USE_OPTION_HERE
 CREATE PROCEDURE bug20953() CREATE VIEW v AS SELECT 1 INTO OUTFILE "file";
---error ER_PARSE_ERROR
+--error ER_CANT_USE_OPTION_HERE
 CREATE PROCEDURE bug20953()
   CREATE VIEW v AS SELECT i FROM t1 PROCEDURE ANALYSE();
---error ER_PARSE_ERROR
+--error ER_CANT_USE_OPTION_HERE
 CREATE PROCEDURE bug20953() CREATE VIEW v AS SELECT 1 FROM (SELECT 1) AS d1 into @w;
 --error ER_VIEW_SELECT_VARIABLE
 CREATE PROCEDURE bug20953(i INT) CREATE VIEW v AS SELECT i;
diff --git a/mysql-test/main/sp.result b/mysql-test/main/sp.result
index 5e457fae1e0..a79d90de6d6 100644
--- a/mysql-test/main/sp.result
+++ b/mysql-test/main/sp.result
@@ -314,7 +314,7 @@ delete from t1|
 drop procedure b|
 drop procedure if exists b2|
 create procedure b2(x int)
-repeat(select 1 into outfile 'b2');
+repeat(select 1) into outfile 'b2';
 insert into test.t1 values (repeat("b2",3), x);
 set x = x-1;
 until x = 0 end repeat|
@@ -6904,18 +6904,6 @@ END	latin1	latin1_swedish_ci	latin1_swedish_ci
 
 DROP FUNCTION f1;
 
-drop procedure if exists p;
-set @old_mode= @@sql_mode;
-set @@sql_mode= cast(pow(2,32)-1 as unsigned integer);
-select @@sql_mode into @full_mode;
-create procedure p() as begin end;
-call p();
-set @@sql_mode= @old_mode;
-select replace(@full_mode, 'ALLOW_INVALID_DATES', 'INVALID_DATES') into @full_mode;
-select name from mysql.proc where name = 'p' and sql_mode = @full_mode;
-name
-p
-drop procedure p;
 CREATE DEFINER = 'root'@'localhost' PROCEDURE p1()
 NOT DETERMINISTIC
 CONTAINS SQL
diff --git a/mysql-test/main/sp.test b/mysql-test/main/sp.test
index c97f6dbba68..56dea012b42 100644
--- a/mysql-test/main/sp.test
+++ b/mysql-test/main/sp.test
@@ -440,7 +440,7 @@ drop procedure b|
 drop procedure if exists b2|
 --enable_warnings
 create procedure b2(x int)
-repeat(select 1 into outfile 'b2');
+repeat(select 1) into outfile 'b2';
   insert into test.t1 values (repeat("b2",3), x);
   set x = x-1;
 until x = 0 end repeat|
@@ -8223,19 +8223,20 @@ DROP FUNCTION f1;
 # the mysql.proc table.
 #
 
---disable_warnings
-drop procedure if exists p;
---enable_warnings
-set @old_mode= @@sql_mode;
-set @@sql_mode= cast(pow(2,32)-1 as unsigned integer);
-select @@sql_mode into @full_mode;
-create procedure p() as begin end;
-call p();
-set @@sql_mode= @old_mode;
+# XXX Oracle parser is not fixed jet
+#--disable_warnings
+#drop procedure if exists p;
+#--enable_warnings
+#set @old_mode= @@sql_mode;
+#set @@sql_mode= cast(pow(2,32)-1 as unsigned integer);
+#select @@sql_mode into @full_mode;
+#create procedure p() as begin end;
+#call p();
+#set @@sql_mode= @old_mode;
 # Rename SQL modes that differ in name between the server and the table definition.
-select replace(@full_mode, 'ALLOW_INVALID_DATES', 'INVALID_DATES') into @full_mode;
-select name from mysql.proc where name = 'p' and sql_mode = @full_mode;
-drop procedure p;
+#select replace(@full_mode, 'ALLOW_INVALID_DATES', 'INVALID_DATES') into @full_mode;
+#select name from mysql.proc where name = 'p' and sql_mode = @full_mode;
+#drop procedure p;
 
 #
 # Bug#43962 "Packets out of order" calling a SHOW TABLE STATUS
diff --git a/mysql-test/main/sql_mode.result b/mysql-test/main/sql_mode.result
index 02574c1c545..bb125693bd1 100644
--- a/mysql-test/main/sql_mode.result
+++ b/mysql-test/main/sql_mode.result
@@ -749,7 +749,6 @@ SET sql_mode=DEFAULT;
 CREATE OR REPLACE TABLE t1 (a TEXT);
 PREPARE stmt FROM 'INSERT INTO t1 (a) VALUES (2||3)';
 EXECUTE stmt;
-SET sql_mode=ORACLE;
 EXECUTE stmt;
 ALTER TABLE t1 ADD b INT;
 EXECUTE stmt;
diff --git a/mysql-test/main/sql_mode.test b/mysql-test/main/sql_mode.test
index 9f38dc935e7..3beff645b82 100644
--- a/mysql-test/main/sql_mode.test
+++ b/mysql-test/main/sql_mode.test
@@ -25,7 +25,8 @@ show create table t1;
 set @@sql_mode="no_field_options,mysql323,mysql40";
 show variables like 'sql_mode';
 show create table t1;
-set sql_mode="postgresql,oracle,mssql,db2,maxdb";
+# set sql_mode="postgresql,oracle,mssql,db2,maxdb";
+set sql_mode="postgresql,mssql,db2,maxdb";
 select @@sql_mode;
 show create table t1;
 drop table t1;
@@ -521,7 +522,7 @@ SET sql_mode=DEFAULT;
 CREATE OR REPLACE TABLE t1 (a TEXT);
 PREPARE stmt FROM 'INSERT INTO t1 (a) VALUES (2||3)';
 EXECUTE stmt;
-SET sql_mode=ORACLE;
+# SET sql_mode=ORACLE;
 EXECUTE stmt;
 ALTER TABLE t1 ADD b INT;
 EXECUTE stmt;
diff --git a/mysql-test/main/subselect.result b/mysql-test/main/subselect.result
index 1c087a3199c..ce03034e0c1 100644
--- a/mysql-test/main/subselect.result
+++ b/mysql-test/main/subselect.result
@@ -80,7 +80,7 @@ SELECT 1 FROM (SELECT 1 as a) b WHERE 1 IN (SELECT (SELECT a));
 1
 1
 select (SELECT 1 FROM (SELECT 1) a PROCEDURE ANALYSE(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 'PROCEDURE ANALYSE(1))' at line 1
+ERROR 42000: Incorrect usage/placement of 'PROCEDURE'
 SELECT 1 FROM (SELECT 1) a PROCEDURE ANALYSE((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 'SELECT 1))' at line 1
 SELECT (SELECT 1) as a FROM (SELECT 1) b WHERE (SELECT a) IS NULL;
@@ -179,7 +179,8 @@ select * from t2 where t2.b=(select a from t3 order by 1 desc limit 1);
 a	b
 1	7
 2	7
-(select * from t2 where t2.b=(select a from t3 order by 1 desc limit 1)) union (select * from t4 order by a limit 2) limit 3;
+(select * from t2 where t2.b=(select a from t3 order by 1 desc limit 1))
+union (select * from t4 order by a limit 2) order by a limit 3;
 a	b
 1	7
 2	7
@@ -3726,7 +3727,7 @@ SELECT sql_no_cache * FROM t1 WHERE NOT EXISTS
 i
 SELECT * FROM t1
 WHERE NOT EXISTS (((SELECT i FROM t1) UNION (SELECT i 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 'UNION (SELECT i FROM t1)))' at line 2
+i
 explain select ((select t11.i from t1 t11) union (select t12.i from t1 t12))
 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 'union (select t12.i from t1 t12))
@@ -5094,34 +5095,31 @@ INSERT INTO t1 VALUES (1),(2);
 CREATE TABLE t2( a INT, b INT );
 SELECT * 
 FROM (SELECT a INTO @var FROM t1 WHERE a = 2) t1a;
-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 @var FROM t1 WHERE a = 2) t1a' at line 2
+ERROR 42000: Incorrect usage/placement of 'INTO'
 SELECT * 
 FROM (SELECT a INTO OUTFILE 'file' FROM t1 WHERE a = 2) t1a;
-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 OUTFILE 'file' FROM t1 WHERE a = 2) t1a' at line 2
+ERROR 42000: Incorrect usage/placement of 'INTO'
 SELECT * 
 FROM (SELECT a INTO DUMPFILE 'file' FROM t1 WHERE a = 2) t1a;
-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 DUMPFILE 'file' FROM t1 WHERE a = 2) t1a' at line 2
+ERROR 42000: Incorrect usage/placement of 'INTO'
 SELECT * FROM ( 
 SELECT 1 a 
 UNION 
 SELECT a INTO @var FROM t1 WHERE a = 2 
 ) t1a;
-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 @var FROM t1 WHERE a = 2 
-) t1a' at line 4
+ERROR 42000: Incorrect usage/placement of 'INTO'
 SELECT * FROM ( 
 SELECT 1 a 
 UNION 
 SELECT a INTO OUTFILE 'file' FROM t1 WHERE a = 2 
 ) t1a;
-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 OUTFILE 'file' FROM t1 WHERE a = 2 
-) t1a' at line 4
+ERROR 42000: Incorrect usage/placement of 'INTO'
 SELECT * FROM ( 
 SELECT 1 a 
 UNION 
 SELECT a INTO DUMPFILE 'file' FROM t1 WHERE a = 2 
 ) t1a;
-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 DUMPFILE 'file' FROM t1 WHERE a = 2 
-) t1a' at line 4
+ERROR 42000: Incorrect usage/placement of 'INTO'
 SELECT * FROM (SELECT a FROM t1 WHERE a = 2) t1a;
 a
 2
@@ -5152,23 +5150,23 @@ SELECT * FROM (SELECT 1 UNION SELECT 1) t1a;
 1
 1
 SELECT * FROM ((SELECT 1 a INTO @a)) t1a;
-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 @a)) t1a' at line 1
+ERROR 42000: Incorrect usage/placement of 'INTO'
 SELECT * FROM ((SELECT 1 a INTO OUTFILE 'file' )) t1a;
-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 OUTFILE 'file' )) t1a' at line 1
+ERROR 42000: Incorrect usage/placement of 'INTO'
 SELECT * FROM ((SELECT 1 a INTO DUMPFILE 'file' )) t1a;
-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 DUMPFILE 'file' )) t1a' at line 1
+ERROR 42000: Incorrect usage/placement of 'INTO'
 SELECT * FROM (SELECT 1 a UNION (SELECT 1 a INTO @a)) t1a;
-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 @a)) t1a' at line 1
+ERROR 42000: Incorrect usage/placement of 'INTO'
 SELECT * FROM (SELECT 1 a UNION (SELECT 1 a INTO DUMPFILE 'file' )) t1a;
-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 DUMPFILE 'file' )) t1a' at line 1
+ERROR 42000: Incorrect usage/placement of 'INTO'
 SELECT * FROM (SELECT 1 a UNION (SELECT 1 a INTO OUTFILE 'file' )) t1a;
-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 OUTFILE 'file' )) t1a' at line 1
+ERROR 42000: Incorrect usage/placement of 'INTO'
 SELECT * FROM (SELECT 1 a UNION ((SELECT 1 a INTO @a))) t1a;
-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 @a))) t1a' at line 1
+ERROR 42000: Incorrect usage/placement of 'INTO'
 SELECT * FROM (SELECT 1 a UNION ((SELECT 1 a INTO DUMPFILE 'file' ))) t1a;
-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 DUMPFILE 'file' ))) t1a' at line 1
+ERROR 42000: Incorrect usage/placement of 'INTO'
 SELECT * FROM (SELECT 1 a UNION ((SELECT 1 a INTO OUTFILE 'file' ))) t1a;
-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 OUTFILE 'file' ))) t1a' at line 1
+ERROR 42000: Incorrect usage/placement of 'INTO'
 SELECT * FROM (SELECT 1 a ORDER BY a) t1a;
 a
 1
@@ -5186,35 +5184,23 @@ a	1
 1	1
 2	1
 SELECT * FROM t1 JOIN ((SELECT 1 UNION SELECT 1)) ON 1;
-ERROR 42000: Every derived table must have its own alias
+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;
-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 'SELECT 1)  ON 1' at line 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)  ON 1' at line 1
 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 'SELECT 1)) ON 1' at line 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)) ON 1' at line 1
 SELECT * FROM t1 JOIN  (t1 t1a)  t1a 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 't1a ON 1' at line 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 ')  t1a ON 1' at line 1
 SELECT * FROM t1 JOIN ((t1 t1a)) t1a 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 't1a ON 1' at line 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 ')) t1a ON 1' at line 1
 SELECT * FROM t1 JOIN  (t1 t1a)  ON 1;
-a	a
-1	1
-2	1
-1	2
-2	2
+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)) ON 1;
-a	a
-1	1
-2	1
-1	2
-2	2
+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 t1a);
-a
-1
-2
+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 ((t1 t1a));
-a
-1
-2
+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 t1 JOIN  (SELECT 1 t1a) alias ON 1;
 a	t1a
 1	1
@@ -5243,11 +5229,11 @@ SELECT * FROM t1 WHERE a = ANY ( SELECT 3 UNION SELECT 1 );
 a
 1
 SELECT * FROM t1 WHERE a = ANY ( SELECT 1 UNION SELECT 1 INTO @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 @a)' at line 1
+ERROR 42000: Incorrect usage/placement of 'INTO'
 SELECT * FROM t1 WHERE a = ANY ( SELECT 1 UNION SELECT 1 INTO OUTFILE 'file' );
-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 OUTFILE 'file' )' at line 1
+ERROR 42000: Incorrect usage/placement of 'INTO'
 SELECT * FROM t1 WHERE a = ANY ( SELECT 1 UNION SELECT 1 INTO DUMPFILE 'file' );
-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 DUMPFILE 'file' )' at line 1
+ERROR 42000: Incorrect usage/placement of 'INTO'
 SELECT * FROM t1 WHERE a = ( SELECT 1 );
 a
 1
@@ -5255,29 +5241,29 @@ SELECT * FROM t1 WHERE a = ( SELECT 1 UNION SELECT 1 );
 a
 1
 SELECT * FROM t1 WHERE a = ( SELECT 1 INTO @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 @a)' at line 1
+ERROR 42000: Incorrect usage/placement of 'INTO'
 SELECT * FROM t1 WHERE a = ( SELECT 1 INTO OUTFILE 'file' );
-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 OUTFILE 'file' )' at line 1
+ERROR 42000: Incorrect usage/placement of 'INTO'
 SELECT * FROM t1 WHERE a = ( SELECT 1 INTO DUMPFILE 'file' );
-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 DUMPFILE 'file' )' at line 1
+ERROR 42000: Incorrect usage/placement of 'INTO'
 SELECT * FROM t1 WHERE a = ( SELECT 1 UNION SELECT 1 INTO @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 @a)' at line 1
+ERROR 42000: Incorrect usage/placement of 'INTO'
 SELECT * FROM t1 WHERE a = ( SELECT 1 UNION SELECT 1 INTO OUTFILE 'file' );
-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 OUTFILE 'file' )' at line 1
+ERROR 42000: Incorrect usage/placement of 'INTO'
 SELECT * FROM t1 WHERE a = ( SELECT 1 UNION SELECT 1 INTO DUMPFILE 'file' );
-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 DUMPFILE 'file' )' at line 1
+ERROR 42000: Incorrect usage/placement of 'INTO'
 SELECT ( SELECT 1 INTO @v );
-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 @v )' at line 1
+ERROR 42000: Incorrect usage/placement of 'INTO'
 SELECT ( SELECT 1 INTO OUTFILE 'file' );
-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 OUTFILE 'file' )' at line 1
+ERROR 42000: Incorrect usage/placement of 'INTO'
 SELECT ( SELECT 1 INTO DUMPFILE 'file' );
-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 DUMPFILE 'file' )' at line 1
+ERROR 42000: Incorrect usage/placement of 'INTO'
 SELECT ( SELECT 1 UNION SELECT 1 INTO @v );
-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 @v )' at line 1
+ERROR 42000: Incorrect usage/placement of 'INTO'
 SELECT ( SELECT 1 UNION SELECT 1 INTO OUTFILE 'file' );
-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 OUTFILE 'file' )' at line 1
+ERROR 42000: Incorrect usage/placement of 'INTO'
 SELECT ( SELECT 1 UNION SELECT 1 INTO DUMPFILE 'file' );
-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 DUMPFILE 'file' )' at line 1
+ERROR 42000: Incorrect usage/placement of 'INTO'
 SELECT ( SELECT a FROM t1 WHERE a = 1 ), a FROM t1;
 ( SELECT a FROM t1 WHERE a = 1 )	a
 1	1
@@ -5289,11 +5275,14 @@ SELECT ( SELECT a FROM t1 WHERE a = 1 UNION SELECT 1 ), a FROM t1;
 SELECT * FROM t2 WHERE (a, b) IN (SELECT a, b FROM t2);
 a	b
 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
+1
+1
 ( 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 ) UNION SELECT 1' at line 1
+1
+1
 SELECT ( 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 1 UNION ( SELECT 1 UNION SELECT 1 ) )
+1
 SELECT ( ( 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 ( SELECT 1 UNION SELECT 1 UNION SELECT 1 );
@@ -5303,9 +5292,9 @@ SELECT ((SELECT 1 UNION SELECT 1 UNION SELECT 1));
 ((SELECT 1 UNION SELECT 1 UNION SELECT 1))
 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: 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 UNION SELECT 1 ) UNION SELECT 1 );
-ERROR 42000: Every derived table must have its own alias
+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 UNION SELECT 1 ) UNION SELECT 1 ) a;
 1
 1
@@ -5313,19 +5302,25 @@ SELECT * FROM ( SELECT 1 UNION SELECT 1 UNION SELECT 1 ) a;
 1
 1
 SELECT * FROM t1 WHERE a =     ( 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
+a
+1
 SELECT * FROM t1 WHERE a = ALL ( 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
+a
+1
 SELECT * FROM t1 WHERE a = ANY ( 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
+a
+1
 SELECT * FROM t1 WHERE a IN    ( 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
+a
+1
 SELECT * FROM t1 WHERE a =     ( ( 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 t1 WHERE a = ALL ( ( 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 )  UNION SELECT 1 )' at line 1
+a
+1
 SELECT * FROM t1 WHERE a = ANY ( ( 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 )  UNION SELECT 1 )' at line 1
+a
+1
 SELECT * FROM t1 WHERE a IN    ( ( 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 t1 WHERE a =     ( SELECT 1 UNION SELECT 1 UNION SELECT 1 );
@@ -5341,18 +5336,18 @@ SELECT * FROM t1 WHERE a IN    ( SELECT 1 UNION SELECT 1 UNION SELECT 1 );
 a
 1
 SELECT * FROM t1 WHERE EXISTS ( SELECT 1 UNION SELECT 1 INTO @v );
-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 @v )' at line 1
+ERROR 42000: Incorrect usage/placement of 'INTO'
 SELECT EXISTS(SELECT 1+1);
 EXISTS(SELECT 1+1)
 1
 SELECT EXISTS(SELECT 1+1 INTO @test);
-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 @test)' at line 1
+ERROR 42000: Incorrect usage/placement of 'INTO'
 SELECT * FROM t1 WHERE a IN ( SELECT 1 UNION SELECT 1 INTO @v );
-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 @v )' at line 1
+ERROR 42000: Incorrect usage/placement of 'INTO'
 SELECT * FROM t1 WHERE EXISTS ( SELECT 1 INTO @v );
-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 @v )' at line 1
+ERROR 42000: Incorrect usage/placement of 'INTO'
 SELECT * FROM t1 WHERE a IN ( SELECT 1 INTO @v );
-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 @v )' at line 1
+ERROR 42000: Incorrect usage/placement of 'INTO'
 DROP TABLE t1, t2;
 CREATE TABLE t1 (a ENUM('rainbow'));
 INSERT INTO t1 VALUES (),(),(),(),();
diff --git a/mysql-test/main/subselect.test b/mysql-test/main/subselect.test
index c5cec99cebf..9af3727df21 100644
--- a/mysql-test/main/subselect.test
+++ b/mysql-test/main/subselect.test
@@ -53,7 +53,7 @@ SELECT * FROM (SELECT 1 as id) b WHERE id IN (SELECT * FROM (SELECT 1 as id) c O
 SELECT * FROM (SELECT 1) a  WHERE 1 IN (SELECT 1,1);
 SELECT 1 IN (SELECT 1);
 SELECT 1 FROM (SELECT 1 as a) b WHERE 1 IN (SELECT (SELECT a));
--- error ER_PARSE_ERROR
+-- error ER_CANT_USE_OPTION_HERE
 select (SELECT 1 FROM (SELECT 1) a PROCEDURE ANALYSE(1));
 -- error ER_PARSE_ERROR
 SELECT 1 FROM (SELECT 1) a PROCEDURE ANALYSE((SELECT 1));
@@ -99,7 +99,8 @@ select (select a from t3), a from t2;
 select * from t2 where t2.a=(select a from t1);
 insert into t3 values (6),(7),(3);
 select * from t2 where t2.b=(select a from t3 order by 1 desc limit 1);
-(select * from t2 where t2.b=(select a from t3 order by 1 desc limit 1)) union (select * from t4 order by a limit 2) limit 3;
+(select * from t2 where t2.b=(select a from t3 order by 1 desc limit 1))
+union (select * from t4 order by a limit 2) order by a limit 3;
 (select * from t2 where t2.b=(select a from t3 order by 1 desc limit 1)) union (select * from t4 where t4.b=(select max(t2.a)*4 from t2) order by a);
 explain extended (select * from t2 where t2.b=(select a from t3 order by 1 desc limit 1)) union (select * from t4 where t4.b=(select max(t2.a)*4 from t2) order by a);
 select (select a from t3 where a<t2.a*4 order by 1 desc limit 1), a from t2;
@@ -2604,8 +2605,6 @@ SELECT sql_no_cache * FROM t1 WHERE NOT EXISTS
    (SELECT i FROM t1)
   );
 
-#TODO:not supported
---error ER_PARSE_ERROR
 SELECT * FROM t1
 WHERE NOT EXISTS (((SELECT i FROM t1) UNION (SELECT i FROM t1)));
 
@@ -4229,31 +4228,31 @@ INSERT INTO t1 VALUES (1),(2);
 
 CREATE TABLE t2( a INT, b INT );
 
---error ER_PARSE_ERROR
+--error ER_CANT_USE_OPTION_HERE
 SELECT * 
 FROM (SELECT a INTO @var FROM t1 WHERE a = 2) t1a;
---error ER_PARSE_ERROR
+--error ER_CANT_USE_OPTION_HERE
 SELECT * 
 FROM (SELECT a INTO OUTFILE 'file' FROM t1 WHERE a = 2) t1a;
---error ER_PARSE_ERROR
+--error ER_CANT_USE_OPTION_HERE
 SELECT * 
 FROM (SELECT a INTO DUMPFILE 'file' FROM t1 WHERE a = 2) t1a;
 
---error ER_PARSE_ERROR
+--error ER_CANT_USE_OPTION_HERE
 SELECT * FROM ( 
   SELECT 1 a 
   UNION 
   SELECT a INTO @var FROM t1 WHERE a = 2 
 ) t1a;
 
---error ER_PARSE_ERROR
+--error ER_CANT_USE_OPTION_HERE
 SELECT * FROM ( 
   SELECT 1 a 
   UNION 
   SELECT a INTO OUTFILE 'file' FROM t1 WHERE a = 2 
 ) t1a;
 
---error ER_PARSE_ERROR
+--error ER_CANT_USE_OPTION_HERE
 SELECT * FROM ( 
   SELECT 1 a 
   UNION 
@@ -4281,25 +4280,25 @@ SELECT * FROM (
 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
+--error ER_CANT_USE_OPTION_HERE
 SELECT * FROM ((SELECT 1 a INTO @a)) t1a;
---error ER_PARSE_ERROR
+--error ER_CANT_USE_OPTION_HERE
 SELECT * FROM ((SELECT 1 a INTO OUTFILE 'file' )) t1a;
---error ER_PARSE_ERROR
+--error ER_CANT_USE_OPTION_HERE
 SELECT * FROM ((SELECT 1 a INTO DUMPFILE 'file' )) t1a;
 
---error ER_PARSE_ERROR
+--error ER_CANT_USE_OPTION_HERE
 SELECT * FROM (SELECT 1 a UNION (SELECT 1 a INTO @a)) t1a;
---error ER_PARSE_ERROR
+--error ER_CANT_USE_OPTION_HERE
 SELECT * FROM (SELECT 1 a UNION (SELECT 1 a INTO DUMPFILE 'file' )) t1a;
---error ER_PARSE_ERROR
+--error ER_CANT_USE_OPTION_HERE
 SELECT * FROM (SELECT 1 a UNION (SELECT 1 a INTO OUTFILE 'file' )) t1a;
 
---error ER_PARSE_ERROR
+--error ER_CANT_USE_OPTION_HERE
 SELECT * FROM (SELECT 1 a UNION ((SELECT 1 a INTO @a))) t1a;
---error ER_PARSE_ERROR
+--error ER_CANT_USE_OPTION_HERE
 SELECT * FROM (SELECT 1 a UNION ((SELECT 1 a INTO DUMPFILE 'file' ))) t1a;
---error ER_PARSE_ERROR
+--error ER_CANT_USE_OPTION_HERE
 SELECT * FROM (SELECT 1 a UNION ((SELECT 1 a INTO OUTFILE 'file' ))) t1a;
 
 SELECT * FROM (SELECT 1 a ORDER BY a) t1a;
@@ -4313,7 +4312,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_DERIVED_MUST_HAVE_ALIAS
+--error ER_PARSE_ERROR
 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;
@@ -4324,10 +4323,14 @@ SELECT * FROM t1 JOIN  (t1 t1a)  t1a ON 1;
 --error ER_PARSE_ERROR
 SELECT * FROM t1 JOIN ((t1 t1a)) t1a ON 1;
 
+--error ER_PARSE_ERROR
 SELECT * FROM t1 JOIN  (t1 t1a)  ON 1;
+--error ER_PARSE_ERROR
 SELECT * FROM t1 JOIN ((t1 t1a)) ON 1;
 
+--error ER_PARSE_ERROR
 SELECT * FROM (t1 t1a);
+--error ER_PARSE_ERROR
 SELECT * FROM ((t1 t1a));
 
 SELECT * FROM t1 JOIN  (SELECT 1 t1a) alias ON 1;
@@ -4345,41 +4348,41 @@ SELECT * FROM t1 WHERE a = ALL ( SELECT 1 );
 SELECT * FROM t1 WHERE a = ALL ( SELECT 1 UNION SELECT 1 );
 SELECT * FROM t1 WHERE a = ANY ( SELECT 3 UNION SELECT 1 );
 
---error ER_PARSE_ERROR
+--error ER_CANT_USE_OPTION_HERE
 SELECT * FROM t1 WHERE a = ANY ( SELECT 1 UNION SELECT 1 INTO @a);
---error ER_PARSE_ERROR
+--error ER_CANT_USE_OPTION_HERE
 SELECT * FROM t1 WHERE a = ANY ( SELECT 1 UNION SELECT 1 INTO OUTFILE 'file' );
---error ER_PARSE_ERROR
+--error ER_CANT_USE_OPTION_HERE
 SELECT * FROM t1 WHERE a = ANY ( SELECT 1 UNION SELECT 1 INTO DUMPFILE 'file' );
 
 SELECT * FROM t1 WHERE a = ( SELECT 1 );
 SELECT * FROM t1 WHERE a = ( SELECT 1 UNION SELECT 1 );
---error ER_PARSE_ERROR
+--error ER_CANT_USE_OPTION_HERE
 SELECT * FROM t1 WHERE a = ( SELECT 1 INTO @a);
---error ER_PARSE_ERROR
+--error ER_CANT_USE_OPTION_HERE
 SELECT * FROM t1 WHERE a = ( SELECT 1 INTO OUTFILE 'file' );
---error ER_PARSE_ERROR
+--error ER_CANT_USE_OPTION_HERE
 SELECT * FROM t1 WHERE a = ( SELECT 1 INTO DUMPFILE 'file' );
 
---error ER_PARSE_ERROR
+--error ER_CANT_USE_OPTION_HERE
 SELECT * FROM t1 WHERE a = ( SELECT 1 UNION SELECT 1 INTO @a);
---error ER_PARSE_ERROR
+--error ER_CANT_USE_OPTION_HERE
 SELECT * FROM t1 WHERE a = ( SELECT 1 UNION SELECT 1 INTO OUTFILE 'file' );
---error ER_PARSE_ERROR
+--error ER_CANT_USE_OPTION_HERE
 SELECT * FROM t1 WHERE a = ( SELECT 1 UNION SELECT 1 INTO DUMPFILE 'file' );
 
---error ER_PARSE_ERROR
+--error ER_CANT_USE_OPTION_HERE
 SELECT ( SELECT 1 INTO @v );
---error ER_PARSE_ERROR
+--error ER_CANT_USE_OPTION_HERE
 SELECT ( SELECT 1 INTO OUTFILE 'file' );
---error ER_PARSE_ERROR
+--error ER_CANT_USE_OPTION_HERE
 SELECT ( SELECT 1 INTO DUMPFILE 'file' );
 
---error ER_PARSE_ERROR
+--error ER_CANT_USE_OPTION_HERE
 SELECT ( SELECT 1 UNION SELECT 1 INTO @v );
---error ER_PARSE_ERROR
+--error ER_CANT_USE_OPTION_HERE
 SELECT ( SELECT 1 UNION SELECT 1 INTO OUTFILE 'file' );
---error ER_PARSE_ERROR
+--error ER_CANT_USE_OPTION_HERE
 SELECT ( SELECT 1 UNION SELECT 1 INTO DUMPFILE 'file' );
 
 # Make sure context is popped when we leave the nested select
@@ -4391,12 +4394,9 @@ SELECT * FROM t2 WHERE (a, b) IN (SELECT a, b FROM t2);
 
 # Make sure the parser does not allow nested UNIONs anywhere
 
---error ER_PARSE_ERROR
 SELECT 1 UNION ( SELECT 1 UNION SELECT 1 );
---error ER_PARSE_ERROR
 ( SELECT 1 UNION SELECT 1 ) UNION SELECT 1;
 
---error ER_PARSE_ERROR
 SELECT ( SELECT 1 UNION ( SELECT 1 UNION SELECT 1 ) );
 --error ER_PARSE_ERROR
 SELECT ( ( SELECT 1 UNION SELECT 1 ) UNION SELECT 1;
@@ -4405,25 +4405,19 @@ 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_DERIVED_MUST_HAVE_ALIAS
+--error ER_PARSE_ERROR
 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
 SELECT * FROM t1 WHERE a =     ( SELECT 1 UNION ( SELECT 1 UNION SELECT 1 ) );
---error ER_PARSE_ERROR
 SELECT * FROM t1 WHERE a = ALL ( SELECT 1 UNION ( SELECT 1 UNION SELECT 1 ) );
---error ER_PARSE_ERROR
 SELECT * FROM t1 WHERE a = ANY ( SELECT 1 UNION ( SELECT 1 UNION SELECT 1 ) );
---error ER_PARSE_ERROR
 SELECT * FROM t1 WHERE a IN    ( SELECT 1 UNION ( SELECT 1 UNION SELECT 1 ) );
 
 --error ER_PARSE_ERROR
 SELECT * FROM t1 WHERE a =     ( ( SELECT 1 UNION SELECT 1 )  UNION SELECT 1 );
---error ER_PARSE_ERROR
 SELECT * FROM t1 WHERE a = ALL ( ( SELECT 1 UNION SELECT 1 )  UNION SELECT 1 );
---error ER_PARSE_ERROR
 SELECT * FROM t1 WHERE a = ANY ( ( SELECT 1 UNION SELECT 1 )  UNION SELECT 1 );
 --error ER_PARSE_ERROR
 SELECT * FROM t1 WHERE a IN    ( ( SELECT 1 UNION SELECT 1 )  UNION SELECT 1 );
@@ -4433,17 +4427,17 @@ SELECT * FROM t1 WHERE a = ALL ( SELECT 1 UNION SELECT 1 UNION SELECT 1 );
 SELECT * FROM t1 WHERE a = ANY ( SELECT 1 UNION SELECT 1 UNION SELECT 1 );
 SELECT * FROM t1 WHERE a IN    ( SELECT 1 UNION SELECT 1 UNION SELECT 1 );
 
---error ER_PARSE_ERROR
+--error ER_CANT_USE_OPTION_HERE
 SELECT * FROM t1 WHERE EXISTS ( SELECT 1 UNION SELECT 1 INTO @v );
 SELECT EXISTS(SELECT 1+1);
---error ER_PARSE_ERROR
+--error ER_CANT_USE_OPTION_HERE
 SELECT EXISTS(SELECT 1+1 INTO @test);
---error ER_PARSE_ERROR
+--error ER_CANT_USE_OPTION_HERE
 SELECT * FROM t1 WHERE a IN ( SELECT 1 UNION SELECT 1 INTO @v );
 
---error ER_PARSE_ERROR
+--error ER_CANT_USE_OPTION_HERE
 SELECT * FROM t1 WHERE EXISTS ( SELECT 1 INTO @v );
---error ER_PARSE_ERROR
+--error ER_CANT_USE_OPTION_HERE
 SELECT * FROM t1 WHERE a IN ( SELECT 1 INTO @v );
 
 DROP TABLE t1, t2;
diff --git a/mysql-test/main/subselect_mat.result b/mysql-test/main/subselect_mat.result
index 4d425d0fe5c..a570e74fc8c 100644
--- a/mysql-test/main/subselect_mat.result
+++ b/mysql-test/main/subselect_mat.result
@@ -2179,11 +2179,11 @@ drop database mysqltest4;
 # (both 1st and further executions)
 CREATE TABLE t1 (a INT NOT NULL) ENGINE=MyISAM;
 INSERT INTO t1 VALUES (0),(8);
-SELECT a FROM (SELECT DISTINCT * FROM t1) AS sq WHERE a IN (SELECT MIN(t2.a) FROM (t1 AS t2));
+SELECT a FROM (SELECT DISTINCT * FROM t1) AS sq WHERE a IN (SELECT MIN(t2.a) FROM t1 AS t2);
 a
 0
 PREPARE stmt FROM "
-SELECT a FROM (SELECT DISTINCT * FROM t1) AS sq WHERE a IN (SELECT MIN(t2.a) FROM (t1 AS t2))
+SELECT a FROM (SELECT DISTINCT * FROM t1) AS sq WHERE a IN (SELECT MIN(t2.a) FROM t1 AS t2)
 ";
 execute stmt;
 a
diff --git a/mysql-test/main/subselect_no_exists_to_in.result b/mysql-test/main/subselect_no_exists_to_in.result
index eb912d9e331..85b18c2ce9c 100644
--- a/mysql-test/main/subselect_no_exists_to_in.result
+++ b/mysql-test/main/subselect_no_exists_to_in.result
@@ -84,7 +84,7 @@ SELECT 1 FROM (SELECT 1 as a) b WHERE 1 IN (SELECT (SELECT a));
 1
 1
 select (SELECT 1 FROM (SELECT 1) a PROCEDURE ANALYSE(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 'PROCEDURE ANALYSE(1))' at line 1
+ERROR 42000: Incorrect usage/placement of 'PROCEDURE'
 SELECT 1 FROM (SELECT 1) a PROCEDURE ANALYSE((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 'SELECT 1))' at line 1
 SELECT (SELECT 1) as a FROM (SELECT 1) b WHERE (SELECT a) IS NULL;
@@ -183,7 +183,8 @@ select * from t2 where t2.b=(select a from t3 order by 1 desc limit 1);
 a	b
 1	7
 2	7
-(select * from t2 where t2.b=(select a from t3 order by 1 desc limit 1)) union (select * from t4 order by a limit 2) limit 3;
+(select * from t2 where t2.b=(select a from t3 order by 1 desc limit 1))
+union (select * from t4 order by a limit 2) order by a limit 3;
 a	b
 1	7
 2	7
@@ -3729,7 +3730,7 @@ SELECT sql_no_cache * FROM t1 WHERE NOT EXISTS
 i
 SELECT * FROM t1
 WHERE NOT EXISTS (((SELECT i FROM t1) UNION (SELECT i 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 'UNION (SELECT i FROM t1)))' at line 2
+i
 explain select ((select t11.i from t1 t11) union (select t12.i from t1 t12))
 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 'union (select t12.i from t1 t12))
@@ -5096,34 +5097,31 @@ INSERT INTO t1 VALUES (1),(2);
 CREATE TABLE t2( a INT, b INT );
 SELECT * 
 FROM (SELECT a INTO @var FROM t1 WHERE a = 2) t1a;
-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 @var FROM t1 WHERE a = 2) t1a' at line 2
+ERROR 42000: Incorrect usage/placement of 'INTO'
 SELECT * 
 FROM (SELECT a INTO OUTFILE 'file' FROM t1 WHERE a = 2) t1a;
-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 OUTFILE 'file' FROM t1 WHERE a = 2) t1a' at line 2
+ERROR 42000: Incorrect usage/placement of 'INTO'
 SELECT * 
 FROM (SELECT a INTO DUMPFILE 'file' FROM t1 WHERE a = 2) t1a;
-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 DUMPFILE 'file' FROM t1 WHERE a = 2) t1a' at line 2
+ERROR 42000: Incorrect usage/placement of 'INTO'
 SELECT * FROM ( 
 SELECT 1 a 
 UNION 
 SELECT a INTO @var FROM t1 WHERE a = 2 
 ) t1a;
-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 @var FROM t1 WHERE a = 2 
-) t1a' at line 4
+ERROR 42000: Incorrect usage/placement of 'INTO'
 SELECT * FROM ( 
 SELECT 1 a 
 UNION 
 SELECT a INTO OUTFILE 'file' FROM t1 WHERE a = 2 
 ) t1a;
-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 OUTFILE 'file' FROM t1 WHERE a = 2 
-) t1a' at line 4
+ERROR 42000: Incorrect usage/placement of 'INTO'
 SELECT * FROM ( 
 SELECT 1 a 
 UNION 
 SELECT a INTO DUMPFILE 'file' FROM t1 WHERE a = 2 
 ) t1a;
-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 DUMPFILE 'file' FROM t1 WHERE a = 2 
-) t1a' at line 4
+ERROR 42000: Incorrect usage/placement of 'INTO'
 SELECT * FROM (SELECT a FROM t1 WHERE a = 2) t1a;
 a
 2
@@ -5154,23 +5152,23 @@ SELECT * FROM (SELECT 1 UNION SELECT 1) t1a;
 1
 1
 SELECT * FROM ((SELECT 1 a INTO @a)) t1a;
-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 @a)) t1a' at line 1
+ERROR 42000: Incorrect usage/placement of 'INTO'
 SELECT * FROM ((SELECT 1 a INTO OUTFILE 'file' )) t1a;
-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 OUTFILE 'file' )) t1a' at line 1
+ERROR 42000: Incorrect usage/placement of 'INTO'
 SELECT * FROM ((SELECT 1 a INTO DUMPFILE 'file' )) t1a;
-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 DUMPFILE 'file' )) t1a' at line 1
+ERROR 42000: Incorrect usage/placement of 'INTO'
 SELECT * FROM (SELECT 1 a UNION (SELECT 1 a INTO @a)) t1a;
-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 @a)) t1a' at line 1
+ERROR 42000: Incorrect usage/placement of 'INTO'
 SELECT * FROM (SELECT 1 a UNION (SELECT 1 a INTO DUMPFILE 'file' )) t1a;
-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 DUMPFILE 'file' )) t1a' at line 1
+ERROR 42000: Incorrect usage/placement of 'INTO'
 SELECT * FROM (SELECT 1 a UNION (SELECT 1 a INTO OUTFILE 'file' )) t1a;
-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 OUTFILE 'file' )) t1a' at line 1
+ERROR 42000: Incorrect usage/placement of 'INTO'
 SELECT * FROM (SELECT 1 a UNION ((SELECT 1 a INTO @a))) t1a;
-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 @a))) t1a' at line 1
+ERROR 42000: Incorrect usage/placement of 'INTO'
 SELECT * FROM (SELECT 1 a UNION ((SELECT 1 a INTO DUMPFILE 'file' ))) t1a;
-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 DUMPFILE 'file' ))) t1a' at line 1
+ERROR 42000: Incorrect usage/placement of 'INTO'
 SELECT * FROM (SELECT 1 a UNION ((SELECT 1 a INTO OUTFILE 'file' ))) t1a;
-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 OUTFILE 'file' ))) t1a' at line 1
+ERROR 42000: Incorrect usage/placement of 'INTO'
 SELECT * FROM (SELECT 1 a ORDER BY a) t1a;
 a
 1
@@ -5188,35 +5186,23 @@ a	1
 1	1
 2	1
 SELECT * FROM t1 JOIN ((SELECT 1 UNION SELECT 1)) ON 1;
-ERROR 42000: Every derived table must have its own alias
+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;
-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 'SELECT 1)  ON 1' at line 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)  ON 1' at line 1
 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 'SELECT 1)) ON 1' at line 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)) ON 1' at line 1
 SELECT * FROM t1 JOIN  (t1 t1a)  t1a 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 't1a ON 1' at line 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 ')  t1a ON 1' at line 1
 SELECT * FROM t1 JOIN ((t1 t1a)) t1a 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 't1a ON 1' at line 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 ')) t1a ON 1' at line 1
 SELECT * FROM t1 JOIN  (t1 t1a)  ON 1;
-a	a
-1	1
-2	1
-1	2
-2	2
+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)) ON 1;
-a	a
-1	1
-2	1
-1	2
-2	2
+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 t1a);
-a
-1
-2
+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 ((t1 t1a));
-a
-1
-2
+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 t1 JOIN  (SELECT 1 t1a) alias ON 1;
 a	t1a
 1	1
@@ -5245,11 +5231,11 @@ SELECT * FROM t1 WHERE a = ANY ( SELECT 3 UNION SELECT 1 );
 a
 1
 SELECT * FROM t1 WHERE a = ANY ( SELECT 1 UNION SELECT 1 INTO @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 @a)' at line 1
+ERROR 42000: Incorrect usage/placement of 'INTO'
 SELECT * FROM t1 WHERE a = ANY ( SELECT 1 UNION SELECT 1 INTO OUTFILE 'file' );
-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 OUTFILE 'file' )' at line 1
+ERROR 42000: Incorrect usage/placement of 'INTO'
 SELECT * FROM t1 WHERE a = ANY ( SELECT 1 UNION SELECT 1 INTO DUMPFILE 'file' );
-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 DUMPFILE 'file' )' at line 1
+ERROR 42000: Incorrect usage/placement of 'INTO'
 SELECT * FROM t1 WHERE a = ( SELECT 1 );
 a
 1
@@ -5257,29 +5243,29 @@ SELECT * FROM t1 WHERE a = ( SELECT 1 UNION SELECT 1 );
 a
 1
 SELECT * FROM t1 WHERE a = ( SELECT 1 INTO @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 @a)' at line 1
+ERROR 42000: Incorrect usage/placement of 'INTO'
 SELECT * FROM t1 WHERE a = ( SELECT 1 INTO OUTFILE 'file' );
-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 OUTFILE 'file' )' at line 1
+ERROR 42000: Incorrect usage/placement of 'INTO'
 SELECT * FROM t1 WHERE a = ( SELECT 1 INTO DUMPFILE 'file' );
-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 DUMPFILE 'file' )' at line 1
+ERROR 42000: Incorrect usage/placement of 'INTO'
 SELECT * FROM t1 WHERE a = ( SELECT 1 UNION SELECT 1 INTO @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 @a)' at line 1
+ERROR 42000: Incorrect usage/placement of 'INTO'
 SELECT * FROM t1 WHERE a = ( SELECT 1 UNION SELECT 1 INTO OUTFILE 'file' );
-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 OUTFILE 'file' )' at line 1
+ERROR 42000: Incorrect usage/placement of 'INTO'
 SELECT * FROM t1 WHERE a = ( SELECT 1 UNION SELECT 1 INTO DUMPFILE 'file' );
-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 DUMPFILE 'file' )' at line 1
+ERROR 42000: Incorrect usage/placement of 'INTO'
 SELECT ( SELECT 1 INTO @v );
-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 @v )' at line 1
+ERROR 42000: Incorrect usage/placement of 'INTO'
 SELECT ( SELECT 1 INTO OUTFILE 'file' );
-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 OUTFILE 'file' )' at line 1
+ERROR 42000: Incorrect usage/placement of 'INTO'
 SELECT ( SELECT 1 INTO DUMPFILE 'file' );
-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 DUMPFILE 'file' )' at line 1
+ERROR 42000: Incorrect usage/placement of 'INTO'
 SELECT ( SELECT 1 UNION SELECT 1 INTO @v );
-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 @v )' at line 1
+ERROR 42000: Incorrect usage/placement of 'INTO'
 SELECT ( SELECT 1 UNION SELECT 1 INTO OUTFILE 'file' );
-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 OUTFILE 'file' )' at line 1
+ERROR 42000: Incorrect usage/placement of 'INTO'
 SELECT ( SELECT 1 UNION SELECT 1 INTO DUMPFILE 'file' );
-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 DUMPFILE 'file' )' at line 1
+ERROR 42000: Incorrect usage/placement of 'INTO'
 SELECT ( SELECT a FROM t1 WHERE a = 1 ), a FROM t1;
 ( SELECT a FROM t1 WHERE a = 1 )	a
 1	1
@@ -5291,11 +5277,14 @@ SELECT ( SELECT a FROM t1 WHERE a = 1 UNION SELECT 1 ), a FROM t1;
 SELECT * FROM t2 WHERE (a, b) IN (SELECT a, b FROM t2);
 a	b
 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
+1
+1
 ( 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 ) UNION SELECT 1' at line 1
+1
+1
 SELECT ( 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 1 UNION ( SELECT 1 UNION SELECT 1 ) )
+1
 SELECT ( ( 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 ( SELECT 1 UNION SELECT 1 UNION SELECT 1 );
@@ -5305,9 +5294,9 @@ SELECT ((SELECT 1 UNION SELECT 1 UNION SELECT 1));
 ((SELECT 1 UNION SELECT 1 UNION SELECT 1))
 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: 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 UNION SELECT 1 ) UNION SELECT 1 );
-ERROR 42000: Every derived table must have its own alias
+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 UNION SELECT 1 ) UNION SELECT 1 ) a;
 1
 1
@@ -5315,19 +5304,25 @@ SELECT * FROM ( SELECT 1 UNION SELECT 1 UNION SELECT 1 ) a;
 1
 1
 SELECT * FROM t1 WHERE a =     ( 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
+a
+1
 SELECT * FROM t1 WHERE a = ALL ( 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
+a
+1
 SELECT * FROM t1 WHERE a = ANY ( 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
+a
+1
 SELECT * FROM t1 WHERE a IN    ( 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
+a
+1
 SELECT * FROM t1 WHERE a =     ( ( 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 t1 WHERE a = ALL ( ( 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 )  UNION SELECT 1 )' at line 1
+a
+1
 SELECT * FROM t1 WHERE a = ANY ( ( 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 )  UNION SELECT 1 )' at line 1
+a
+1
 SELECT * FROM t1 WHERE a IN    ( ( 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 t1 WHERE a =     ( SELECT 1 UNION SELECT 1 UNION SELECT 1 );
@@ -5343,18 +5338,18 @@ SELECT * FROM t1 WHERE a IN    ( SELECT 1 UNION SELECT 1 UNION SELECT 1 );
 a
 1
 SELECT * FROM t1 WHERE EXISTS ( SELECT 1 UNION SELECT 1 INTO @v );
-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 @v )' at line 1
+ERROR 42000: Incorrect usage/placement of 'INTO'
 SELECT EXISTS(SELECT 1+1);
 EXISTS(SELECT 1+1)
 1
 SELECT EXISTS(SELECT 1+1 INTO @test);
-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 @test)' at line 1
+ERROR 42000: Incorrect usage/placement of 'INTO'
 SELECT * FROM t1 WHERE a IN ( SELECT 1 UNION SELECT 1 INTO @v );
-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 @v )' at line 1
+ERROR 42000: Incorrect usage/placement of 'INTO'
 SELECT * FROM t1 WHERE EXISTS ( SELECT 1 INTO @v );
-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 @v )' at line 1
+ERROR 42000: Incorrect usage/placement of 'INTO'
 SELECT * FROM t1 WHERE a IN ( SELECT 1 INTO @v );
-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 @v )' at line 1
+ERROR 42000: Incorrect usage/placement of 'INTO'
 DROP TABLE t1, t2;
 CREATE TABLE t1 (a ENUM('rainbow'));
 INSERT INTO t1 VALUES (),(),(),(),();
diff --git a/mysql-test/main/subselect_no_mat.result b/mysql-test/main/subselect_no_mat.result
index 72f30bbd21f..a2de845e5e4 100644
--- a/mysql-test/main/subselect_no_mat.result
+++ b/mysql-test/main/subselect_no_mat.result
@@ -87,7 +87,7 @@ SELECT 1 FROM (SELECT 1 as a) b WHERE 1 IN (SELECT (SELECT a));
 1
 1
 select (SELECT 1 FROM (SELECT 1) a PROCEDURE ANALYSE(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 'PROCEDURE ANALYSE(1))' at line 1
+ERROR 42000: Incorrect usage/placement of 'PROCEDURE'
 SELECT 1 FROM (SELECT 1) a PROCEDURE ANALYSE((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 'SELECT 1))' at line 1
 SELECT (SELECT 1) as a FROM (SELECT 1) b WHERE (SELECT a) IS NULL;
@@ -186,7 +186,8 @@ select * from t2 where t2.b=(select a from t3 order by 1 desc limit 1);
 a	b
 1	7
 2	7
-(select * from t2 where t2.b=(select a from t3 order by 1 desc limit 1)) union (select * from t4 order by a limit 2) limit 3;
+(select * from t2 where t2.b=(select a from t3 order by 1 desc limit 1))
+union (select * from t4 order by a limit 2) order by a limit 3;
 a	b
 1	7
 2	7
@@ -3729,7 +3730,7 @@ SELECT sql_no_cache * FROM t1 WHERE NOT EXISTS
 i
 SELECT * FROM t1
 WHERE NOT EXISTS (((SELECT i FROM t1) UNION (SELECT i 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 'UNION (SELECT i FROM t1)))' at line 2
+i
 explain select ((select t11.i from t1 t11) union (select t12.i from t1 t12))
 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 'union (select t12.i from t1 t12))
@@ -5094,34 +5095,31 @@ INSERT INTO t1 VALUES (1),(2);
 CREATE TABLE t2( a INT, b INT );
 SELECT * 
 FROM (SELECT a INTO @var FROM t1 WHERE a = 2) t1a;
-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 @var FROM t1 WHERE a = 2) t1a' at line 2
+ERROR 42000: Incorrect usage/placement of 'INTO'
 SELECT * 
 FROM (SELECT a INTO OUTFILE 'file' FROM t1 WHERE a = 2) t1a;
-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 OUTFILE 'file' FROM t1 WHERE a = 2) t1a' at line 2
+ERROR 42000: Incorrect usage/placement of 'INTO'
 SELECT * 
 FROM (SELECT a INTO DUMPFILE 'file' FROM t1 WHERE a = 2) t1a;
-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 DUMPFILE 'file' FROM t1 WHERE a = 2) t1a' at line 2
+ERROR 42000: Incorrect usage/placement of 'INTO'
 SELECT * FROM ( 
 SELECT 1 a 
 UNION 
 SELECT a INTO @var FROM t1 WHERE a = 2 
 ) t1a;
-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 @var FROM t1 WHERE a = 2 
-) t1a' at line 4
+ERROR 42000: Incorrect usage/placement of 'INTO'
 SELECT * FROM ( 
 SELECT 1 a 
 UNION 
 SELECT a INTO OUTFILE 'file' FROM t1 WHERE a = 2 
 ) t1a;
-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 OUTFILE 'file' FROM t1 WHERE a = 2 
-) t1a' at line 4
+ERROR 42000: Incorrect usage/placement of 'INTO'
 SELECT * FROM ( 
 SELECT 1 a 
 UNION 
 SELECT a INTO DUMPFILE 'file' FROM t1 WHERE a = 2 
 ) t1a;
-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 DUMPFILE 'file' FROM t1 WHERE a = 2 
-) t1a' at line 4
+ERROR 42000: Incorrect usage/placement of 'INTO'
 SELECT * FROM (SELECT a FROM t1 WHERE a = 2) t1a;
 a
 2
@@ -5152,23 +5150,23 @@ SELECT * FROM (SELECT 1 UNION SELECT 1) t1a;
 1
 1
 SELECT * FROM ((SELECT 1 a INTO @a)) t1a;
-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 @a)) t1a' at line 1
+ERROR 42000: Incorrect usage/placement of 'INTO'
 SELECT * FROM ((SELECT 1 a INTO OUTFILE 'file' )) t1a;
-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 OUTFILE 'file' )) t1a' at line 1
+ERROR 42000: Incorrect usage/placement of 'INTO'
 SELECT * FROM ((SELECT 1 a INTO DUMPFILE 'file' )) t1a;
-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 DUMPFILE 'file' )) t1a' at line 1
+ERROR 42000: Incorrect usage/placement of 'INTO'
 SELECT * FROM (SELECT 1 a UNION (SELECT 1 a INTO @a)) t1a;
-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 @a)) t1a' at line 1
+ERROR 42000: Incorrect usage/placement of 'INTO'
 SELECT * FROM (SELECT 1 a UNION (SELECT 1 a INTO DUMPFILE 'file' )) t1a;
-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 DUMPFILE 'file' )) t1a' at line 1
+ERROR 42000: Incorrect usage/placement of 'INTO'
 SELECT * FROM (SELECT 1 a UNION (SELECT 1 a INTO OUTFILE 'file' )) t1a;
-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 OUTFILE 'file' )) t1a' at line 1
+ERROR 42000: Incorrect usage/placement of 'INTO'
 SELECT * FROM (SELECT 1 a UNION ((SELECT 1 a INTO @a))) t1a;
-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 @a))) t1a' at line 1
+ERROR 42000: Incorrect usage/placement of 'INTO'
 SELECT * FROM (SELECT 1 a UNION ((SELECT 1 a INTO DUMPFILE 'file' ))) t1a;
-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 DUMPFILE 'file' ))) t1a' at line 1
+ERROR 42000: Incorrect usage/placement of 'INTO'
 SELECT * FROM (SELECT 1 a UNION ((SELECT 1 a INTO OUTFILE 'file' ))) t1a;
-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 OUTFILE 'file' ))) t1a' at line 1
+ERROR 42000: Incorrect usage/placement of 'INTO'
 SELECT * FROM (SELECT 1 a ORDER BY a) t1a;
 a
 1
@@ -5186,35 +5184,23 @@ a	1
 1	1
 2	1
 SELECT * FROM t1 JOIN ((SELECT 1 UNION SELECT 1)) ON 1;
-ERROR 42000: Every derived table must have its own alias
+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;
-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 'SELECT 1)  ON 1' at line 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)  ON 1' at line 1
 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 'SELECT 1)) ON 1' at line 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)) ON 1' at line 1
 SELECT * FROM t1 JOIN  (t1 t1a)  t1a 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 't1a ON 1' at line 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 ')  t1a ON 1' at line 1
 SELECT * FROM t1 JOIN ((t1 t1a)) t1a 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 't1a ON 1' at line 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 ')) t1a ON 1' at line 1
 SELECT * FROM t1 JOIN  (t1 t1a)  ON 1;
-a	a
-1	1
-2	1
-1	2
-2	2
+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)) ON 1;
-a	a
-1	1
-2	1
-1	2
-2	2
+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 t1a);
-a
-1
-2
+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 ((t1 t1a));
-a
-1
-2
+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 t1 JOIN  (SELECT 1 t1a) alias ON 1;
 a	t1a
 1	1
@@ -5243,11 +5229,11 @@ SELECT * FROM t1 WHERE a = ANY ( SELECT 3 UNION SELECT 1 );
 a
 1
 SELECT * FROM t1 WHERE a = ANY ( SELECT 1 UNION SELECT 1 INTO @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 @a)' at line 1
+ERROR 42000: Incorrect usage/placement of 'INTO'
 SELECT * FROM t1 WHERE a = ANY ( SELECT 1 UNION SELECT 1 INTO OUTFILE 'file' );
-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 OUTFILE 'file' )' at line 1
+ERROR 42000: Incorrect usage/placement of 'INTO'
 SELECT * FROM t1 WHERE a = ANY ( SELECT 1 UNION SELECT 1 INTO DUMPFILE 'file' );
-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 DUMPFILE 'file' )' at line 1
+ERROR 42000: Incorrect usage/placement of 'INTO'
 SELECT * FROM t1 WHERE a = ( SELECT 1 );
 a
 1
@@ -5255,29 +5241,29 @@ SELECT * FROM t1 WHERE a = ( SELECT 1 UNION SELECT 1 );
 a
 1
 SELECT * FROM t1 WHERE a = ( SELECT 1 INTO @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 @a)' at line 1
+ERROR 42000: Incorrect usage/placement of 'INTO'
 SELECT * FROM t1 WHERE a = ( SELECT 1 INTO OUTFILE 'file' );
-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 OUTFILE 'file' )' at line 1
+ERROR 42000: Incorrect usage/placement of 'INTO'
 SELECT * FROM t1 WHERE a = ( SELECT 1 INTO DUMPFILE 'file' );
-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 DUMPFILE 'file' )' at line 1
+ERROR 42000: Incorrect usage/placement of 'INTO'
 SELECT * FROM t1 WHERE a = ( SELECT 1 UNION SELECT 1 INTO @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 @a)' at line 1
+ERROR 42000: Incorrect usage/placement of 'INTO'
 SELECT * FROM t1 WHERE a = ( SELECT 1 UNION SELECT 1 INTO OUTFILE 'file' );
-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 OUTFILE 'file' )' at line 1
+ERROR 42000: Incorrect usage/placement of 'INTO'
 SELECT * FROM t1 WHERE a = ( SELECT 1 UNION SELECT 1 INTO DUMPFILE 'file' );
-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 DUMPFILE 'file' )' at line 1
+ERROR 42000: Incorrect usage/placement of 'INTO'
 SELECT ( SELECT 1 INTO @v );
-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 @v )' at line 1
+ERROR 42000: Incorrect usage/placement of 'INTO'
 SELECT ( SELECT 1 INTO OUTFILE 'file' );
-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 OUTFILE 'file' )' at line 1
+ERROR 42000: Incorrect usage/placement of 'INTO'
 SELECT ( SELECT 1 INTO DUMPFILE 'file' );
-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 DUMPFILE 'file' )' at line 1
+ERROR 42000: Incorrect usage/placement of 'INTO'
 SELECT ( SELECT 1 UNION SELECT 1 INTO @v );
-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 @v )' at line 1
+ERROR 42000: Incorrect usage/placement of 'INTO'
 SELECT ( SELECT 1 UNION SELECT 1 INTO OUTFILE 'file' );
-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 OUTFILE 'file' )' at line 1
+ERROR 42000: Incorrect usage/placement of 'INTO'
 SELECT ( SELECT 1 UNION SELECT 1 INTO DUMPFILE 'file' );
-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 DUMPFILE 'file' )' at line 1
+ERROR 42000: Incorrect usage/placement of 'INTO'
 SELECT ( SELECT a FROM t1 WHERE a = 1 ), a FROM t1;
 ( SELECT a FROM t1 WHERE a = 1 )	a
 1	1
@@ -5289,11 +5275,14 @@ SELECT ( SELECT a FROM t1 WHERE a = 1 UNION SELECT 1 ), a FROM t1;
 SELECT * FROM t2 WHERE (a, b) IN (SELECT a, b FROM t2);
 a	b
 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
+1
+1
 ( 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 ) UNION SELECT 1' at line 1
+1
+1
 SELECT ( 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 1 UNION ( SELECT 1 UNION SELECT 1 ) )
+1
 SELECT ( ( 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 ( SELECT 1 UNION SELECT 1 UNION SELECT 1 );
@@ -5303,9 +5292,9 @@ SELECT ((SELECT 1 UNION SELECT 1 UNION SELECT 1));
 ((SELECT 1 UNION SELECT 1 UNION SELECT 1))
 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: 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 UNION SELECT 1 ) UNION SELECT 1 );
-ERROR 42000: Every derived table must have its own alias
+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 UNION SELECT 1 ) UNION SELECT 1 ) a;
 1
 1
@@ -5313,19 +5302,25 @@ SELECT * FROM ( SELECT 1 UNION SELECT 1 UNION SELECT 1 ) a;
 1
 1
 SELECT * FROM t1 WHERE a =     ( 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
+a
+1
 SELECT * FROM t1 WHERE a = ALL ( 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
+a
+1
 SELECT * FROM t1 WHERE a = ANY ( 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
+a
+1
 SELECT * FROM t1 WHERE a IN    ( 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
+a
+1
 SELECT * FROM t1 WHERE a =     ( ( 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 t1 WHERE a = ALL ( ( 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 )  UNION SELECT 1 )' at line 1
+a
+1
 SELECT * FROM t1 WHERE a = ANY ( ( 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 )  UNION SELECT 1 )' at line 1
+a
+1
 SELECT * FROM t1 WHERE a IN    ( ( 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 t1 WHERE a =     ( SELECT 1 UNION SELECT 1 UNION SELECT 1 );
@@ -5341,18 +5336,18 @@ SELECT * FROM t1 WHERE a IN    ( SELECT 1 UNION SELECT 1 UNION SELECT 1 );
 a
 1
 SELECT * FROM t1 WHERE EXISTS ( SELECT 1 UNION SELECT 1 INTO @v );
-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 @v )' at line 1
+ERROR 42000: Incorrect usage/placement of 'INTO'
 SELECT EXISTS(SELECT 1+1);
 EXISTS(SELECT 1+1)
 1
 SELECT EXISTS(SELECT 1+1 INTO @test);
-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 @test)' at line 1
+ERROR 42000: Incorrect usage/placement of 'INTO'
 SELECT * FROM t1 WHERE a IN ( SELECT 1 UNION SELECT 1 INTO @v );
-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 @v )' at line 1
+ERROR 42000: Incorrect usage/placement of 'INTO'
 SELECT * FROM t1 WHERE EXISTS ( SELECT 1 INTO @v );
-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 @v )' at line 1
+ERROR 42000: Incorrect usage/placement of 'INTO'
 SELECT * FROM t1 WHERE a IN ( SELECT 1 INTO @v );
-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 @v )' at line 1
+ERROR 42000: Incorrect usage/placement of 'INTO'
 DROP TABLE t1, t2;
 CREATE TABLE t1 (a ENUM('rainbow'));
 INSERT INTO t1 VALUES (),(),(),(),();
diff --git a/mysql-test/main/subselect_no_opts.result b/mysql-test/main/subselect_no_opts.result
index de075d3245f..05cc0f44ff1 100644
--- a/mysql-test/main/subselect_no_opts.result
+++ b/mysql-test/main/subselect_no_opts.result
@@ -83,7 +83,7 @@ SELECT 1 FROM (SELECT 1 as a) b WHERE 1 IN (SELECT (SELECT a));
 1
 1
 select (SELECT 1 FROM (SELECT 1) a PROCEDURE ANALYSE(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 'PROCEDURE ANALYSE(1))' at line 1
+ERROR 42000: Incorrect usage/placement of 'PROCEDURE'
 SELECT 1 FROM (SELECT 1) a PROCEDURE ANALYSE((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 'SELECT 1))' at line 1
 SELECT (SELECT 1) as a FROM (SELECT 1) b WHERE (SELECT a) IS NULL;
@@ -182,7 +182,8 @@ select * from t2 where t2.b=(select a from t3 order by 1 desc limit 1);
 a	b
 1	7
 2	7
-(select * from t2 where t2.b=(select a from t3 order by 1 desc limit 1)) union (select * from t4 order by a limit 2) limit 3;
+(select * from t2 where t2.b=(select a from t3 order by 1 desc limit 1))
+union (select * from t4 order by a limit 2) order by a limit 3;
 a	b
 1	7
 2	7
@@ -3725,7 +3726,7 @@ SELECT sql_no_cache * FROM t1 WHERE NOT EXISTS
 i
 SELECT * FROM t1
 WHERE NOT EXISTS (((SELECT i FROM t1) UNION (SELECT i 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 'UNION (SELECT i FROM t1)))' at line 2
+i
 explain select ((select t11.i from t1 t11) union (select t12.i from t1 t12))
 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 'union (select t12.i from t1 t12))
@@ -5090,34 +5091,31 @@ INSERT INTO t1 VALUES (1),(2);
 CREATE TABLE t2( a INT, b INT );
 SELECT * 
 FROM (SELECT a INTO @var FROM t1 WHERE a = 2) t1a;
-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 @var FROM t1 WHERE a = 2) t1a' at line 2
+ERROR 42000: Incorrect usage/placement of 'INTO'
 SELECT * 
 FROM (SELECT a INTO OUTFILE 'file' FROM t1 WHERE a = 2) t1a;
-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 OUTFILE 'file' FROM t1 WHERE a = 2) t1a' at line 2
+ERROR 42000: Incorrect usage/placement of 'INTO'
 SELECT * 
 FROM (SELECT a INTO DUMPFILE 'file' FROM t1 WHERE a = 2) t1a;
-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 DUMPFILE 'file' FROM t1 WHERE a = 2) t1a' at line 2
+ERROR 42000: Incorrect usage/placement of 'INTO'
 SELECT * FROM ( 
 SELECT 1 a 
 UNION 
 SELECT a INTO @var FROM t1 WHERE a = 2 
 ) t1a;
-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 @var FROM t1 WHERE a = 2 
-) t1a' at line 4
+ERROR 42000: Incorrect usage/placement of 'INTO'
 SELECT * FROM ( 
 SELECT 1 a 
 UNION 
 SELECT a INTO OUTFILE 'file' FROM t1 WHERE a = 2 
 ) t1a;
-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 OUTFILE 'file' FROM t1 WHERE a = 2 
-) t1a' at line 4
+ERROR 42000: Incorrect usage/placement of 'INTO'
 SELECT * FROM ( 
 SELECT 1 a 
 UNION 
 SELECT a INTO DUMPFILE 'file' FROM t1 WHERE a = 2 
 ) t1a;
-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 DUMPFILE 'file' FROM t1 WHERE a = 2 
-) t1a' at line 4
+ERROR 42000: Incorrect usage/placement of 'INTO'
 SELECT * FROM (SELECT a FROM t1 WHERE a = 2) t1a;
 a
 2
@@ -5148,23 +5146,23 @@ SELECT * FROM (SELECT 1 UNION SELECT 1) t1a;
 1
 1
 SELECT * FROM ((SELECT 1 a INTO @a)) t1a;
-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 @a)) t1a' at line 1
+ERROR 42000: Incorrect usage/placement of 'INTO'
 SELECT * FROM ((SELECT 1 a INTO OUTFILE 'file' )) t1a;
-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 OUTFILE 'file' )) t1a' at line 1
+ERROR 42000: Incorrect usage/placement of 'INTO'
 SELECT * FROM ((SELECT 1 a INTO DUMPFILE 'file' )) t1a;
-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 DUMPFILE 'file' )) t1a' at line 1
+ERROR 42000: Incorrect usage/placement of 'INTO'
 SELECT * FROM (SELECT 1 a UNION (SELECT 1 a INTO @a)) t1a;
-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 @a)) t1a' at line 1
+ERROR 42000: Incorrect usage/placement of 'INTO'
 SELECT * FROM (SELECT 1 a UNION (SELECT 1 a INTO DUMPFILE 'file' )) t1a;
-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 DUMPFILE 'file' )) t1a' at line 1
+ERROR 42000: Incorrect usage/placement of 'INTO'
 SELECT * FROM (SELECT 1 a UNION (SELECT 1 a INTO OUTFILE 'file' )) t1a;
-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 OUTFILE 'file' )) t1a' at line 1
+ERROR 42000: Incorrect usage/placement of 'INTO'
 SELECT * FROM (SELECT 1 a UNION ((SELECT 1 a INTO @a))) t1a;
-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 @a))) t1a' at line 1
+ERROR 42000: Incorrect usage/placement of 'INTO'
 SELECT * FROM (SELECT 1 a UNION ((SELECT 1 a INTO DUMPFILE 'file' ))) t1a;
-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 DUMPFILE 'file' ))) t1a' at line 1
+ERROR 42000: Incorrect usage/placement of 'INTO'
 SELECT * FROM (SELECT 1 a UNION ((SELECT 1 a INTO OUTFILE 'file' ))) t1a;
-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 OUTFILE 'file' ))) t1a' at line 1
+ERROR 42000: Incorrect usage/placement of 'INTO'
 SELECT * FROM (SELECT 1 a ORDER BY a) t1a;
 a
 1
@@ -5182,35 +5180,23 @@ a	1
 1	1
 2	1
 SELECT * FROM t1 JOIN ((SELECT 1 UNION SELECT 1)) ON 1;
-ERROR 42000: Every derived table must have its own alias
+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;
-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 'SELECT 1)  ON 1' at line 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)  ON 1' at line 1
 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 'SELECT 1)) ON 1' at line 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)) ON 1' at line 1
 SELECT * FROM t1 JOIN  (t1 t1a)  t1a 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 't1a ON 1' at line 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 ')  t1a ON 1' at line 1
 SELECT * FROM t1 JOIN ((t1 t1a)) t1a 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 't1a ON 1' at line 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 ')) t1a ON 1' at line 1
 SELECT * FROM t1 JOIN  (t1 t1a)  ON 1;
-a	a
-1	1
-2	1
-1	2
-2	2
+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)) ON 1;
-a	a
-1	1
-2	1
-1	2
-2	2
+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 t1a);
-a
-1
-2
+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 ((t1 t1a));
-a
-1
-2
+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 t1 JOIN  (SELECT 1 t1a) alias ON 1;
 a	t1a
 1	1
@@ -5239,11 +5225,11 @@ SELECT * FROM t1 WHERE a = ANY ( SELECT 3 UNION SELECT 1 );
 a
 1
 SELECT * FROM t1 WHERE a = ANY ( SELECT 1 UNION SELECT 1 INTO @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 @a)' at line 1
+ERROR 42000: Incorrect usage/placement of 'INTO'
 SELECT * FROM t1 WHERE a = ANY ( SELECT 1 UNION SELECT 1 INTO OUTFILE 'file' );
-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 OUTFILE 'file' )' at line 1
+ERROR 42000: Incorrect usage/placement of 'INTO'
 SELECT * FROM t1 WHERE a = ANY ( SELECT 1 UNION SELECT 1 INTO DUMPFILE 'file' );
-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 DUMPFILE 'file' )' at line 1
+ERROR 42000: Incorrect usage/placement of 'INTO'
 SELECT * FROM t1 WHERE a = ( SELECT 1 );
 a
 1
@@ -5251,29 +5237,29 @@ SELECT * FROM t1 WHERE a = ( SELECT 1 UNION SELECT 1 );
 a
 1
 SELECT * FROM t1 WHERE a = ( SELECT 1 INTO @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 @a)' at line 1
+ERROR 42000: Incorrect usage/placement of 'INTO'
 SELECT * FROM t1 WHERE a = ( SELECT 1 INTO OUTFILE 'file' );
-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 OUTFILE 'file' )' at line 1
+ERROR 42000: Incorrect usage/placement of 'INTO'
 SELECT * FROM t1 WHERE a = ( SELECT 1 INTO DUMPFILE 'file' );
-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 DUMPFILE 'file' )' at line 1
+ERROR 42000: Incorrect usage/placement of 'INTO'
 SELECT * FROM t1 WHERE a = ( SELECT 1 UNION SELECT 1 INTO @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 @a)' at line 1
+ERROR 42000: Incorrect usage/placement of 'INTO'
 SELECT * FROM t1 WHERE a = ( SELECT 1 UNION SELECT 1 INTO OUTFILE 'file' );
-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 OUTFILE 'file' )' at line 1
+ERROR 42000: Incorrect usage/placement of 'INTO'
 SELECT * FROM t1 WHERE a = ( SELECT 1 UNION SELECT 1 INTO DUMPFILE 'file' );
-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 DUMPFILE 'file' )' at line 1
+ERROR 42000: Incorrect usage/placement of 'INTO'
 SELECT ( SELECT 1 INTO @v );
-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 @v )' at line 1
+ERROR 42000: Incorrect usage/placement of 'INTO'
 SELECT ( SELECT 1 INTO OUTFILE 'file' );
-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 OUTFILE 'file' )' at line 1
+ERROR 42000: Incorrect usage/placement of 'INTO'
 SELECT ( SELECT 1 INTO DUMPFILE 'file' );
-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 DUMPFILE 'file' )' at line 1
+ERROR 42000: Incorrect usage/placement of 'INTO'
 SELECT ( SELECT 1 UNION SELECT 1 INTO @v );
-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 @v )' at line 1
+ERROR 42000: Incorrect usage/placement of 'INTO'
 SELECT ( SELECT 1 UNION SELECT 1 INTO OUTFILE 'file' );
-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 OUTFILE 'file' )' at line 1
+ERROR 42000: Incorrect usage/placement of 'INTO'
 SELECT ( SELECT 1 UNION SELECT 1 INTO DUMPFILE 'file' );
-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 DUMPFILE 'file' )' at line 1
+ERROR 42000: Incorrect usage/placement of 'INTO'
 SELECT ( SELECT a FROM t1 WHERE a = 1 ), a FROM t1;
 ( SELECT a FROM t1 WHERE a = 1 )	a
 1	1
@@ -5285,11 +5271,14 @@ SELECT ( SELECT a FROM t1 WHERE a = 1 UNION SELECT 1 ), a FROM t1;
 SELECT * FROM t2 WHERE (a, b) IN (SELECT a, b FROM t2);
 a	b
 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
+1
+1
 ( 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 ) UNION SELECT 1' at line 1
+1
+1
 SELECT ( 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 1 UNION ( SELECT 1 UNION SELECT 1 ) )
+1
 SELECT ( ( 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 ( SELECT 1 UNION SELECT 1 UNION SELECT 1 );
@@ -5299,9 +5288,9 @@ SELECT ((SELECT 1 UNION SELECT 1 UNION SELECT 1));
 ((SELECT 1 UNION SELECT 1 UNION SELECT 1))
 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: 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 UNION SELECT 1 ) UNION SELECT 1 );
-ERROR 42000: Every derived table must have its own alias
+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 UNION SELECT 1 ) UNION SELECT 1 ) a;
 1
 1
@@ -5309,19 +5298,25 @@ SELECT * FROM ( SELECT 1 UNION SELECT 1 UNION SELECT 1 ) a;
 1
 1
 SELECT * FROM t1 WHERE a =     ( 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
+a
+1
 SELECT * FROM t1 WHERE a = ALL ( 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
+a
+1
 SELECT * FROM t1 WHERE a = ANY ( 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
+a
+1
 SELECT * FROM t1 WHERE a IN    ( 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
+a
+1
 SELECT * FROM t1 WHERE a =     ( ( 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 t1 WHERE a = ALL ( ( 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 )  UNION SELECT 1 )' at line 1
+a
+1
 SELECT * FROM t1 WHERE a = ANY ( ( 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 )  UNION SELECT 1 )' at line 1
+a
+1
 SELECT * FROM t1 WHERE a IN    ( ( 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 t1 WHERE a =     ( SELECT 1 UNION SELECT 1 UNION SELECT 1 );
@@ -5337,18 +5332,18 @@ SELECT * FROM t1 WHERE a IN    ( SELECT 1 UNION SELECT 1 UNION SELECT 1 );
 a
 1
 SELECT * FROM t1 WHERE EXISTS ( SELECT 1 UNION SELECT 1 INTO @v );
-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 @v )' at line 1
+ERROR 42000: Incorrect usage/placement of 'INTO'
 SELECT EXISTS(SELECT 1+1);
 EXISTS(SELECT 1+1)
 1
 SELECT EXISTS(SELECT 1+1 INTO @test);
-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 @test)' at line 1
+ERROR 42000: Incorrect usage/placement of 'INTO'
 SELECT * FROM t1 WHERE a IN ( SELECT 1 UNION SELECT 1 INTO @v );
-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 @v )' at line 1
+ERROR 42000: Incorrect usage/placement of 'INTO'
 SELECT * FROM t1 WHERE EXISTS ( SELECT 1 INTO @v );
-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 @v )' at line 1
+ERROR 42000: Incorrect usage/placement of 'INTO'
 SELECT * FROM t1 WHERE a IN ( SELECT 1 INTO @v );
-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 @v )' at line 1
+ERROR 42000: Incorrect usage/placement of 'INTO'
 DROP TABLE t1, t2;
 CREATE TABLE t1 (a ENUM('rainbow'));
 INSERT INTO t1 VALUES (),(),(),(),();
diff --git a/mysql-test/main/subselect_no_scache.result b/mysql-test/main/subselect_no_scache.result
index a594f5f85b9..1593ad50096 100644
--- a/mysql-test/main/subselect_no_scache.result
+++ b/mysql-test/main/subselect_no_scache.result
@@ -86,7 +86,7 @@ SELECT 1 FROM (SELECT 1 as a) b WHERE 1 IN (SELECT (SELECT a));
 1
 1
 select (SELECT 1 FROM (SELECT 1) a PROCEDURE ANALYSE(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 'PROCEDURE ANALYSE(1))' at line 1
+ERROR 42000: Incorrect usage/placement of 'PROCEDURE'
 SELECT 1 FROM (SELECT 1) a PROCEDURE ANALYSE((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 'SELECT 1))' at line 1
 SELECT (SELECT 1) as a FROM (SELECT 1) b WHERE (SELECT a) IS NULL;
@@ -185,7 +185,8 @@ select * from t2 where t2.b=(select a from t3 order by 1 desc limit 1);
 a	b
 1	7
 2	7
-(select * from t2 where t2.b=(select a from t3 order by 1 desc limit 1)) union (select * from t4 order by a limit 2) limit 3;
+(select * from t2 where t2.b=(select a from t3 order by 1 desc limit 1))
+union (select * from t4 order by a limit 2) order by a limit 3;
 a	b
 1	7
 2	7
@@ -3732,7 +3733,7 @@ SELECT sql_no_cache * FROM t1 WHERE NOT EXISTS
 i
 SELECT * FROM t1
 WHERE NOT EXISTS (((SELECT i FROM t1) UNION (SELECT i 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 'UNION (SELECT i FROM t1)))' at line 2
+i
 explain select ((select t11.i from t1 t11) union (select t12.i from t1 t12))
 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 'union (select t12.i from t1 t12))
@@ -5100,34 +5101,31 @@ INSERT INTO t1 VALUES (1),(2);
 CREATE TABLE t2( a INT, b INT );
 SELECT * 
 FROM (SELECT a INTO @var FROM t1 WHERE a = 2) t1a;
-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 @var FROM t1 WHERE a = 2) t1a' at line 2
+ERROR 42000: Incorrect usage/placement of 'INTO'
 SELECT * 
 FROM (SELECT a INTO OUTFILE 'file' FROM t1 WHERE a = 2) t1a;
-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 OUTFILE 'file' FROM t1 WHERE a = 2) t1a' at line 2
+ERROR 42000: Incorrect usage/placement of 'INTO'
 SELECT * 
 FROM (SELECT a INTO DUMPFILE 'file' FROM t1 WHERE a = 2) t1a;
-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 DUMPFILE 'file' FROM t1 WHERE a = 2) t1a' at line 2
+ERROR 42000: Incorrect usage/placement of 'INTO'
 SELECT * FROM ( 
 SELECT 1 a 
 UNION 
 SELECT a INTO @var FROM t1 WHERE a = 2 
 ) t1a;
-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 @var FROM t1 WHERE a = 2 
-) t1a' at line 4
+ERROR 42000: Incorrect usage/placement of 'INTO'
 SELECT * FROM ( 
 SELECT 1 a 
 UNION 
 SELECT a INTO OUTFILE 'file' FROM t1 WHERE a = 2 
 ) t1a;
-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 OUTFILE 'file' FROM t1 WHERE a = 2 
-) t1a' at line 4
+ERROR 42000: Incorrect usage/placement of 'INTO'
 SELECT * FROM ( 
 SELECT 1 a 
 UNION 
 SELECT a INTO DUMPFILE 'file' FROM t1 WHERE a = 2 
 ) t1a;
-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 DUMPFILE 'file' FROM t1 WHERE a = 2 
-) t1a' at line 4
+ERROR 42000: Incorrect usage/placement of 'INTO'
 SELECT * FROM (SELECT a FROM t1 WHERE a = 2) t1a;
 a
 2
@@ -5158,23 +5156,23 @@ SELECT * FROM (SELECT 1 UNION SELECT 1) t1a;
 1
 1
 SELECT * FROM ((SELECT 1 a INTO @a)) t1a;
-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 @a)) t1a' at line 1
+ERROR 42000: Incorrect usage/placement of 'INTO'
 SELECT * FROM ((SELECT 1 a INTO OUTFILE 'file' )) t1a;
-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 OUTFILE 'file' )) t1a' at line 1
+ERROR 42000: Incorrect usage/placement of 'INTO'
 SELECT * FROM ((SELECT 1 a INTO DUMPFILE 'file' )) t1a;
-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 DUMPFILE 'file' )) t1a' at line 1
+ERROR 42000: Incorrect usage/placement of 'INTO'
 SELECT * FROM (SELECT 1 a UNION (SELECT 1 a INTO @a)) t1a;
-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 @a)) t1a' at line 1
+ERROR 42000: Incorrect usage/placement of 'INTO'
 SELECT * FROM (SELECT 1 a UNION (SELECT 1 a INTO DUMPFILE 'file' )) t1a;
-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 DUMPFILE 'file' )) t1a' at line 1
+ERROR 42000: Incorrect usage/placement of 'INTO'
 SELECT * FROM (SELECT 1 a UNION (SELECT 1 a INTO OUTFILE 'file' )) t1a;
-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 OUTFILE 'file' )) t1a' at line 1
+ERROR 42000: Incorrect usage/placement of 'INTO'
 SELECT * FROM (SELECT 1 a UNION ((SELECT 1 a INTO @a))) t1a;
-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 @a))) t1a' at line 1
+ERROR 42000: Incorrect usage/placement of 'INTO'
 SELECT * FROM (SELECT 1 a UNION ((SELECT 1 a INTO DUMPFILE 'file' ))) t1a;
-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 DUMPFILE 'file' ))) t1a' at line 1
+ERROR 42000: Incorrect usage/placement of 'INTO'
 SELECT * FROM (SELECT 1 a UNION ((SELECT 1 a INTO OUTFILE 'file' ))) t1a;
-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 OUTFILE 'file' ))) t1a' at line 1
+ERROR 42000: Incorrect usage/placement of 'INTO'
 SELECT * FROM (SELECT 1 a ORDER BY a) t1a;
 a
 1
@@ -5192,35 +5190,23 @@ a	1
 1	1
 2	1
 SELECT * FROM t1 JOIN ((SELECT 1 UNION SELECT 1)) ON 1;
-ERROR 42000: Every derived table must have its own alias
+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;
-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 'SELECT 1)  ON 1' at line 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)  ON 1' at line 1
 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 'SELECT 1)) ON 1' at line 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)) ON 1' at line 1
 SELECT * FROM t1 JOIN  (t1 t1a)  t1a 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 't1a ON 1' at line 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 ')  t1a ON 1' at line 1
 SELECT * FROM t1 JOIN ((t1 t1a)) t1a 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 't1a ON 1' at line 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 ')) t1a ON 1' at line 1
 SELECT * FROM t1 JOIN  (t1 t1a)  ON 1;
-a	a
-1	1
-2	1
-1	2
-2	2
+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)) ON 1;
-a	a
-1	1
-2	1
-1	2
-2	2
+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 t1a);
-a
-1
-2
+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 ((t1 t1a));
-a
-1
-2
+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 t1 JOIN  (SELECT 1 t1a) alias ON 1;
 a	t1a
 1	1
@@ -5249,11 +5235,11 @@ SELECT * FROM t1 WHERE a = ANY ( SELECT 3 UNION SELECT 1 );
 a
 1
 SELECT * FROM t1 WHERE a = ANY ( SELECT 1 UNION SELECT 1 INTO @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 @a)' at line 1
+ERROR 42000: Incorrect usage/placement of 'INTO'
 SELECT * FROM t1 WHERE a = ANY ( SELECT 1 UNION SELECT 1 INTO OUTFILE 'file' );
-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 OUTFILE 'file' )' at line 1
+ERROR 42000: Incorrect usage/placement of 'INTO'
 SELECT * FROM t1 WHERE a = ANY ( SELECT 1 UNION SELECT 1 INTO DUMPFILE 'file' );
-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 DUMPFILE 'file' )' at line 1
+ERROR 42000: Incorrect usage/placement of 'INTO'
 SELECT * FROM t1 WHERE a = ( SELECT 1 );
 a
 1
@@ -5261,29 +5247,29 @@ SELECT * FROM t1 WHERE a = ( SELECT 1 UNION SELECT 1 );
 a
 1
 SELECT * FROM t1 WHERE a = ( SELECT 1 INTO @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 @a)' at line 1
+ERROR 42000: Incorrect usage/placement of 'INTO'
 SELECT * FROM t1 WHERE a = ( SELECT 1 INTO OUTFILE 'file' );
-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 OUTFILE 'file' )' at line 1
+ERROR 42000: Incorrect usage/placement of 'INTO'
 SELECT * FROM t1 WHERE a = ( SELECT 1 INTO DUMPFILE 'file' );
-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 DUMPFILE 'file' )' at line 1
+ERROR 42000: Incorrect usage/placement of 'INTO'
 SELECT * FROM t1 WHERE a = ( SELECT 1 UNION SELECT 1 INTO @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 @a)' at line 1
+ERROR 42000: Incorrect usage/placement of 'INTO'
 SELECT * FROM t1 WHERE a = ( SELECT 1 UNION SELECT 1 INTO OUTFILE 'file' );
-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 OUTFILE 'file' )' at line 1
+ERROR 42000: Incorrect usage/placement of 'INTO'
 SELECT * FROM t1 WHERE a = ( SELECT 1 UNION SELECT 1 INTO DUMPFILE 'file' );
-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 DUMPFILE 'file' )' at line 1
+ERROR 42000: Incorrect usage/placement of 'INTO'
 SELECT ( SELECT 1 INTO @v );
-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 @v )' at line 1
+ERROR 42000: Incorrect usage/placement of 'INTO'
 SELECT ( SELECT 1 INTO OUTFILE 'file' );
-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 OUTFILE 'file' )' at line 1
+ERROR 42000: Incorrect usage/placement of 'INTO'
 SELECT ( SELECT 1 INTO DUMPFILE 'file' );
-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 DUMPFILE 'file' )' at line 1
+ERROR 42000: Incorrect usage/placement of 'INTO'
 SELECT ( SELECT 1 UNION SELECT 1 INTO @v );
-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 @v )' at line 1
+ERROR 42000: Incorrect usage/placement of 'INTO'
 SELECT ( SELECT 1 UNION SELECT 1 INTO OUTFILE 'file' );
-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 OUTFILE 'file' )' at line 1
+ERROR 42000: Incorrect usage/placement of 'INTO'
 SELECT ( SELECT 1 UNION SELECT 1 INTO DUMPFILE 'file' );
-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 DUMPFILE 'file' )' at line 1
+ERROR 42000: Incorrect usage/placement of 'INTO'
 SELECT ( SELECT a FROM t1 WHERE a = 1 ), a FROM t1;
 ( SELECT a FROM t1 WHERE a = 1 )	a
 1	1
@@ -5295,11 +5281,14 @@ SELECT ( SELECT a FROM t1 WHERE a = 1 UNION SELECT 1 ), a FROM t1;
 SELECT * FROM t2 WHERE (a, b) IN (SELECT a, b FROM t2);
 a	b
 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
+1
+1
 ( 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 ) UNION SELECT 1' at line 1
+1
+1
 SELECT ( 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 1 UNION ( SELECT 1 UNION SELECT 1 ) )
+1
 SELECT ( ( 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 ( SELECT 1 UNION SELECT 1 UNION SELECT 1 );
@@ -5309,9 +5298,9 @@ SELECT ((SELECT 1 UNION SELECT 1 UNION SELECT 1));
 ((SELECT 1 UNION SELECT 1 UNION SELECT 1))
 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: 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 UNION SELECT 1 ) UNION SELECT 1 );
-ERROR 42000: Every derived table must have its own alias
+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 UNION SELECT 1 ) UNION SELECT 1 ) a;
 1
 1
@@ -5319,19 +5308,25 @@ SELECT * FROM ( SELECT 1 UNION SELECT 1 UNION SELECT 1 ) a;
 1
 1
 SELECT * FROM t1 WHERE a =     ( 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
+a
+1
 SELECT * FROM t1 WHERE a = ALL ( 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
+a
+1
 SELECT * FROM t1 WHERE a = ANY ( 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
+a
+1
 SELECT * FROM t1 WHERE a IN    ( 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
+a
+1
 SELECT * FROM t1 WHERE a =     ( ( 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 t1 WHERE a = ALL ( ( 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 )  UNION SELECT 1 )' at line 1
+a
+1
 SELECT * FROM t1 WHERE a = ANY ( ( 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 )  UNION SELECT 1 )' at line 1
+a
+1
 SELECT * FROM t1 WHERE a IN    ( ( 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 t1 WHERE a =     ( SELECT 1 UNION SELECT 1 UNION SELECT 1 );
@@ -5347,18 +5342,18 @@ SELECT * FROM t1 WHERE a IN    ( SELECT 1 UNION SELECT 1 UNION SELECT 1 );
 a
 1
 SELECT * FROM t1 WHERE EXISTS ( SELECT 1 UNION SELECT 1 INTO @v );
-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 @v )' at line 1
+ERROR 42000: Incorrect usage/placement of 'INTO'
 SELECT EXISTS(SELECT 1+1);
 EXISTS(SELECT 1+1)
 1
 SELECT EXISTS(SELECT 1+1 INTO @test);
-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 @test)' at line 1
+ERROR 42000: Incorrect usage/placement of 'INTO'
 SELECT * FROM t1 WHERE a IN ( SELECT 1 UNION SELECT 1 INTO @v );
-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 @v )' at line 1
+ERROR 42000: Incorrect usage/placement of 'INTO'
 SELECT * FROM t1 WHERE EXISTS ( SELECT 1 INTO @v );
-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 @v )' at line 1
+ERROR 42000: Incorrect usage/placement of 'INTO'
 SELECT * FROM t1 WHERE a IN ( SELECT 1 INTO @v );
-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 @v )' at line 1
+ERROR 42000: Incorrect usage/placement of 'INTO'
 DROP TABLE t1, t2;
 CREATE TABLE t1 (a ENUM('rainbow'));
 INSERT INTO t1 VALUES (),(),(),(),();
diff --git a/mysql-test/main/subselect_no_semijoin.result b/mysql-test/main/subselect_no_semijoin.result
index e068b28b017..2afc6dc8051 100644
--- a/mysql-test/main/subselect_no_semijoin.result
+++ b/mysql-test/main/subselect_no_semijoin.result
@@ -83,7 +83,7 @@ SELECT 1 FROM (SELECT 1 as a) b WHERE 1 IN (SELECT (SELECT a));
 1
 1
 select (SELECT 1 FROM (SELECT 1) a PROCEDURE ANALYSE(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 'PROCEDURE ANALYSE(1))' at line 1
+ERROR 42000: Incorrect usage/placement of 'PROCEDURE'
 SELECT 1 FROM (SELECT 1) a PROCEDURE ANALYSE((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 'SELECT 1))' at line 1
 SELECT (SELECT 1) as a FROM (SELECT 1) b WHERE (SELECT a) IS NULL;
@@ -182,7 +182,8 @@ select * from t2 where t2.b=(select a from t3 order by 1 desc limit 1);
 a	b
 1	7
 2	7
-(select * from t2 where t2.b=(select a from t3 order by 1 desc limit 1)) union (select * from t4 order by a limit 2) limit 3;
+(select * from t2 where t2.b=(select a from t3 order by 1 desc limit 1))
+union (select * from t4 order by a limit 2) order by a limit 3;
 a	b
 1	7
 2	7
@@ -3725,7 +3726,7 @@ SELECT sql_no_cache * FROM t1 WHERE NOT EXISTS
 i
 SELECT * FROM t1
 WHERE NOT EXISTS (((SELECT i FROM t1) UNION (SELECT i 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 'UNION (SELECT i FROM t1)))' at line 2
+i
 explain select ((select t11.i from t1 t11) union (select t12.i from t1 t12))
 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 'union (select t12.i from t1 t12))
@@ -5090,34 +5091,31 @@ INSERT INTO t1 VALUES (1),(2);
 CREATE TABLE t2( a INT, b INT );
 SELECT * 
 FROM (SELECT a INTO @var FROM t1 WHERE a = 2) t1a;
-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 @var FROM t1 WHERE a = 2) t1a' at line 2
+ERROR 42000: Incorrect usage/placement of 'INTO'
 SELECT * 
 FROM (SELECT a INTO OUTFILE 'file' FROM t1 WHERE a = 2) t1a;
-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 OUTFILE 'file' FROM t1 WHERE a = 2) t1a' at line 2
+ERROR 42000: Incorrect usage/placement of 'INTO'
 SELECT * 
 FROM (SELECT a INTO DUMPFILE 'file' FROM t1 WHERE a = 2) t1a;
-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 DUMPFILE 'file' FROM t1 WHERE a = 2) t1a' at line 2
+ERROR 42000: Incorrect usage/placement of 'INTO'
 SELECT * FROM ( 
 SELECT 1 a 
 UNION 
 SELECT a INTO @var FROM t1 WHERE a = 2 
 ) t1a;
-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 @var FROM t1 WHERE a = 2 
-) t1a' at line 4
+ERROR 42000: Incorrect usage/placement of 'INTO'
 SELECT * FROM ( 
 SELECT 1 a 
 UNION 
 SELECT a INTO OUTFILE 'file' FROM t1 WHERE a = 2 
 ) t1a;
-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 OUTFILE 'file' FROM t1 WHERE a = 2 
-) t1a' at line 4
+ERROR 42000: Incorrect usage/placement of 'INTO'
 SELECT * FROM ( 
 SELECT 1 a 
 UNION 
 SELECT a INTO DUMPFILE 'file' FROM t1 WHERE a = 2 
 ) t1a;
-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 DUMPFILE 'file' FROM t1 WHERE a = 2 
-) t1a' at line 4
+ERROR 42000: Incorrect usage/placement of 'INTO'
 SELECT * FROM (SELECT a FROM t1 WHERE a = 2) t1a;
 a
 2
@@ -5148,23 +5146,23 @@ SELECT * FROM (SELECT 1 UNION SELECT 1) t1a;
 1
 1
 SELECT * FROM ((SELECT 1 a INTO @a)) t1a;
-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 @a)) t1a' at line 1
+ERROR 42000: Incorrect usage/placement of 'INTO'
 SELECT * FROM ((SELECT 1 a INTO OUTFILE 'file' )) t1a;
-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 OUTFILE 'file' )) t1a' at line 1
+ERROR 42000: Incorrect usage/placement of 'INTO'
 SELECT * FROM ((SELECT 1 a INTO DUMPFILE 'file' )) t1a;
-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 DUMPFILE 'file' )) t1a' at line 1
+ERROR 42000: Incorrect usage/placement of 'INTO'
 SELECT * FROM (SELECT 1 a UNION (SELECT 1 a INTO @a)) t1a;
-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 @a)) t1a' at line 1
+ERROR 42000: Incorrect usage/placement of 'INTO'
 SELECT * FROM (SELECT 1 a UNION (SELECT 1 a INTO DUMPFILE 'file' )) t1a;
-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 DUMPFILE 'file' )) t1a' at line 1
+ERROR 42000: Incorrect usage/placement of 'INTO'
 SELECT * FROM (SELECT 1 a UNION (SELECT 1 a INTO OUTFILE 'file' )) t1a;
-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 OUTFILE 'file' )) t1a' at line 1
+ERROR 42000: Incorrect usage/placement of 'INTO'
 SELECT * FROM (SELECT 1 a UNION ((SELECT 1 a INTO @a))) t1a;
-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 @a))) t1a' at line 1
+ERROR 42000: Incorrect usage/placement of 'INTO'
 SELECT * FROM (SELECT 1 a UNION ((SELECT 1 a INTO DUMPFILE 'file' ))) t1a;
-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 DUMPFILE 'file' ))) t1a' at line 1
+ERROR 42000: Incorrect usage/placement of 'INTO'
 SELECT * FROM (SELECT 1 a UNION ((SELECT 1 a INTO OUTFILE 'file' ))) t1a;
-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 OUTFILE 'file' ))) t1a' at line 1
+ERROR 42000: Incorrect usage/placement of 'INTO'
 SELECT * FROM (SELECT 1 a ORDER BY a) t1a;
 a
 1
@@ -5182,35 +5180,23 @@ a	1
 1	1
 2	1
 SELECT * FROM t1 JOIN ((SELECT 1 UNION SELECT 1)) ON 1;
-ERROR 42000: Every derived table must have its own alias
+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;
-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 'SELECT 1)  ON 1' at line 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)  ON 1' at line 1
 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 'SELECT 1)) ON 1' at line 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)) ON 1' at line 1
 SELECT * FROM t1 JOIN  (t1 t1a)  t1a 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 't1a ON 1' at line 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 ')  t1a ON 1' at line 1
 SELECT * FROM t1 JOIN ((t1 t1a)) t1a 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 't1a ON 1' at line 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 ')) t1a ON 1' at line 1
 SELECT * FROM t1 JOIN  (t1 t1a)  ON 1;
-a	a
-1	1
-2	1
-1	2
-2	2
+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)) ON 1;
-a	a
-1	1
-2	1
-1	2
-2	2
+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 t1a);
-a
-1
-2
+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 ((t1 t1a));
-a
-1
-2
+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 t1 JOIN  (SELECT 1 t1a) alias ON 1;
 a	t1a
 1	1
@@ -5239,11 +5225,11 @@ SELECT * FROM t1 WHERE a = ANY ( SELECT 3 UNION SELECT 1 );
 a
 1
 SELECT * FROM t1 WHERE a = ANY ( SELECT 1 UNION SELECT 1 INTO @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 @a)' at line 1
+ERROR 42000: Incorrect usage/placement of 'INTO'
 SELECT * FROM t1 WHERE a = ANY ( SELECT 1 UNION SELECT 1 INTO OUTFILE 'file' );
-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 OUTFILE 'file' )' at line 1
+ERROR 42000: Incorrect usage/placement of 'INTO'
 SELECT * FROM t1 WHERE a = ANY ( SELECT 1 UNION SELECT 1 INTO DUMPFILE 'file' );
-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 DUMPFILE 'file' )' at line 1
+ERROR 42000: Incorrect usage/placement of 'INTO'
 SELECT * FROM t1 WHERE a = ( SELECT 1 );
 a
 1
@@ -5251,29 +5237,29 @@ SELECT * FROM t1 WHERE a = ( SELECT 1 UNION SELECT 1 );
 a
 1
 SELECT * FROM t1 WHERE a = ( SELECT 1 INTO @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 @a)' at line 1
+ERROR 42000: Incorrect usage/placement of 'INTO'
 SELECT * FROM t1 WHERE a = ( SELECT 1 INTO OUTFILE 'file' );
-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 OUTFILE 'file' )' at line 1
+ERROR 42000: Incorrect usage/placement of 'INTO'
 SELECT * FROM t1 WHERE a = ( SELECT 1 INTO DUMPFILE 'file' );
-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 DUMPFILE 'file' )' at line 1
+ERROR 42000: Incorrect usage/placement of 'INTO'
 SELECT * FROM t1 WHERE a = ( SELECT 1 UNION SELECT 1 INTO @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 @a)' at line 1
+ERROR 42000: Incorrect usage/placement of 'INTO'
 SELECT * FROM t1 WHERE a = ( SELECT 1 UNION SELECT 1 INTO OUTFILE 'file' );
-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 OUTFILE 'file' )' at line 1
+ERROR 42000: Incorrect usage/placement of 'INTO'
 SELECT * FROM t1 WHERE a = ( SELECT 1 UNION SELECT 1 INTO DUMPFILE 'file' );
-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 DUMPFILE 'file' )' at line 1
+ERROR 42000: Incorrect usage/placement of 'INTO'
 SELECT ( SELECT 1 INTO @v );
-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 @v )' at line 1
+ERROR 42000: Incorrect usage/placement of 'INTO'
 SELECT ( SELECT 1 INTO OUTFILE 'file' );
-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 OUTFILE 'file' )' at line 1
+ERROR 42000: Incorrect usage/placement of 'INTO'
 SELECT ( SELECT 1 INTO DUMPFILE 'file' );
-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 DUMPFILE 'file' )' at line 1
+ERROR 42000: Incorrect usage/placement of 'INTO'
 SELECT ( SELECT 1 UNION SELECT 1 INTO @v );
-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 @v )' at line 1
+ERROR 42000: Incorrect usage/placement of 'INTO'
 SELECT ( SELECT 1 UNION SELECT 1 INTO OUTFILE 'file' );
-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 OUTFILE 'file' )' at line 1
+ERROR 42000: Incorrect usage/placement of 'INTO'
 SELECT ( SELECT 1 UNION SELECT 1 INTO DUMPFILE 'file' );
-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 DUMPFILE 'file' )' at line 1
+ERROR 42000: Incorrect usage/placement of 'INTO'
 SELECT ( SELECT a FROM t1 WHERE a = 1 ), a FROM t1;
 ( SELECT a FROM t1 WHERE a = 1 )	a
 1	1
@@ -5285,11 +5271,14 @@ SELECT ( SELECT a FROM t1 WHERE a = 1 UNION SELECT 1 ), a FROM t1;
 SELECT * FROM t2 WHERE (a, b) IN (SELECT a, b FROM t2);
 a	b
 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
+1
+1
 ( 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 ) UNION SELECT 1' at line 1
+1
+1
 SELECT ( 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 1 UNION ( SELECT 1 UNION SELECT 1 ) )
+1
 SELECT ( ( 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 ( SELECT 1 UNION SELECT 1 UNION SELECT 1 );
@@ -5299,9 +5288,9 @@ SELECT ((SELECT 1 UNION SELECT 1 UNION SELECT 1));
 ((SELECT 1 UNION SELECT 1 UNION SELECT 1))
 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: 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 UNION SELECT 1 ) UNION SELECT 1 );
-ERROR 42000: Every derived table must have its own alias
+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 UNION SELECT 1 ) UNION SELECT 1 ) a;
 1
 1
@@ -5309,19 +5298,25 @@ SELECT * FROM ( SELECT 1 UNION SELECT 1 UNION SELECT 1 ) a;
 1
 1
 SELECT * FROM t1 WHERE a =     ( 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
+a
+1
 SELECT * FROM t1 WHERE a = ALL ( 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
+a
+1
 SELECT * FROM t1 WHERE a = ANY ( 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
+a
+1
 SELECT * FROM t1 WHERE a IN    ( 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
+a
+1
 SELECT * FROM t1 WHERE a =     ( ( 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 t1 WHERE a = ALL ( ( 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 )  UNION SELECT 1 )' at line 1
+a
+1
 SELECT * FROM t1 WHERE a = ANY ( ( 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 )  UNION SELECT 1 )' at line 1
+a
+1
 SELECT * FROM t1 WHERE a IN    ( ( 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 t1 WHERE a =     ( SELECT 1 UNION SELECT 1 UNION SELECT 1 );
@@ -5337,18 +5332,18 @@ SELECT * FROM t1 WHERE a IN    ( SELECT 1 UNION SELECT 1 UNION SELECT 1 );
 a
 1
 SELECT * FROM t1 WHERE EXISTS ( SELECT 1 UNION SELECT 1 INTO @v );
-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 @v )' at line 1
+ERROR 42000: Incorrect usage/placement of 'INTO'
 SELECT EXISTS(SELECT 1+1);
 EXISTS(SELECT 1+1)
 1
 SELECT EXISTS(SELECT 1+1 INTO @test);
-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 @test)' at line 1
+ERROR 42000: Incorrect usage/placement of 'INTO'
 SELECT * FROM t1 WHERE a IN ( SELECT 1 UNION SELECT 1 INTO @v );
-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 @v )' at line 1
+ERROR 42000: Incorrect usage/placement of 'INTO'
 SELECT * FROM t1 WHERE EXISTS ( SELECT 1 INTO @v );
-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 @v )' at line 1
+ERROR 42000: Incorrect usage/placement of 'INTO'
 SELECT * FROM t1 WHERE a IN ( SELECT 1 INTO @v );
-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 @v )' at line 1
+ERROR 42000: Incorrect usage/placement of 'INTO'
 DROP TABLE t1, t2;
 CREATE TABLE t1 (a ENUM('rainbow'));
 INSERT INTO t1 VALUES (),(),(),(),();
diff --git a/mysql-test/main/subselect_sj.result b/mysql-test/main/subselect_sj.result
index 9631192da33..fb286bc3d53 100644
--- a/mysql-test/main/subselect_sj.result
+++ b/mysql-test/main/subselect_sj.result
@@ -1675,7 +1675,7 @@ CREATE TABLE t3 ( f11 int) ;
 INSERT IGNORE INTO t3 VALUES (0);
 SELECT alias1.f11 AS field2
 FROM ( t3 AS alias2 JOIN t1 AS alias3 ON alias3.f10 = 1)
-LEFT JOIN ( t2 AS alias1 ) ON alias3.f11 = 1
+LEFT JOIN t2 AS alias1 ON alias3.f11 = 1
 WHERE alias2.f11 IN ( SELECT f11 FROM t2 )
 GROUP BY field2 ;
 field2
diff --git a/mysql-test/main/subselect_sj.test b/mysql-test/main/subselect_sj.test
index 6fdccee339d..2eda8ee3e29 100644
--- a/mysql-test/main/subselect_sj.test
+++ b/mysql-test/main/subselect_sj.test
@@ -1462,7 +1462,7 @@ INSERT IGNORE INTO t3 VALUES (0);
 
 SELECT alias1.f11 AS field2
 FROM ( t3 AS alias2 JOIN t1 AS alias3 ON alias3.f10 = 1)
-LEFT JOIN ( t2 AS alias1 ) ON alias3.f11 = 1
+LEFT JOIN t2 AS alias1 ON alias3.f11 = 1
 WHERE alias2.f11 IN ( SELECT f11 FROM t2 )
 GROUP BY field2 ;
 
diff --git a/mysql-test/main/subselect_sj_jcl6.result b/mysql-test/main/subselect_sj_jcl6.result
index 77a073ea2d3..4810d06f1c3 100644
--- a/mysql-test/main/subselect_sj_jcl6.result
+++ b/mysql-test/main/subselect_sj_jcl6.result
@@ -1688,7 +1688,7 @@ CREATE TABLE t3 ( f11 int) ;
 INSERT IGNORE INTO t3 VALUES (0);
 SELECT alias1.f11 AS field2
 FROM ( t3 AS alias2 JOIN t1 AS alias3 ON alias3.f10 = 1)
-LEFT JOIN ( t2 AS alias1 ) ON alias3.f11 = 1
+LEFT JOIN t2 AS alias1 ON alias3.f11 = 1
 WHERE alias2.f11 IN ( SELECT f11 FROM t2 )
 GROUP BY field2 ;
 field2
diff --git a/mysql-test/main/subselect_sj_mat.result b/mysql-test/main/subselect_sj_mat.result
index 9e1870875ce..579a9db0218 100644
--- a/mysql-test/main/subselect_sj_mat.result
+++ b/mysql-test/main/subselect_sj_mat.result
@@ -2219,11 +2219,11 @@ drop database mysqltest4;
 # (both 1st and further executions)
 CREATE TABLE t1 (a INT NOT NULL) ENGINE=MyISAM;
 INSERT INTO t1 VALUES (0),(8);
-SELECT a FROM (SELECT DISTINCT * FROM t1) AS sq WHERE a IN (SELECT MIN(t2.a) FROM (t1 AS t2));
+SELECT a FROM (SELECT DISTINCT * FROM t1) AS sq WHERE a IN (SELECT MIN(t2.a) FROM t1 AS t2);
 a
 0
 PREPARE stmt FROM "
-SELECT a FROM (SELECT DISTINCT * FROM t1) AS sq WHERE a IN (SELECT MIN(t2.a) FROM (t1 AS t2))
+SELECT a FROM (SELECT DISTINCT * FROM t1) AS sq WHERE a IN (SELECT MIN(t2.a) FROM t1 AS t2)
 ";
 execute stmt;
 a
diff --git a/mysql-test/main/subselect_sj_mat.test b/mysql-test/main/subselect_sj_mat.test
index bfd3b28a5b2..66c11b61435 100644
--- a/mysql-test/main/subselect_sj_mat.test
+++ b/mysql-test/main/subselect_sj_mat.test
@@ -1848,9 +1848,9 @@ drop database mysqltest4;
 CREATE TABLE t1 (a INT NOT NULL) ENGINE=MyISAM;
 INSERT INTO t1 VALUES (0),(8);
 
-SELECT a FROM (SELECT DISTINCT * FROM t1) AS sq WHERE a IN (SELECT MIN(t2.a) FROM (t1 AS t2));
+SELECT a FROM (SELECT DISTINCT * FROM t1) AS sq WHERE a IN (SELECT MIN(t2.a) FROM t1 AS t2);
 PREPARE stmt FROM "
-SELECT a FROM (SELECT DISTINCT * FROM t1) AS sq WHERE a IN (SELECT MIN(t2.a) FROM (t1 AS t2))
+SELECT a FROM (SELECT DISTINCT * FROM t1) AS sq WHERE a IN (SELECT MIN(t2.a) FROM t1 AS t2)
 ";
 execute stmt;
 execute stmt;
diff --git a/mysql-test/main/union.result b/mysql-test/main/union.result
index 4e5f9312e03..47ac8cf5319 100644
--- a/mysql-test/main/union.result
+++ b/mysql-test/main/union.result
@@ -81,7 +81,7 @@ a	b
 2	b
 1	a
 (select a,b from t1 limit 2)  union all (select a,b from t2 order by a limit 1) order by t1.b;
-ERROR 42000: Table 't1' from one of the SELECTs cannot be used in global ORDER clause
+ERROR 42000: Table 't1' from one of the SELECTs cannot be used in ORDER clause
 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;
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	filtered	Extra
 1	PRIMARY	t1	ALL	NULL	NULL	NULL	NULL	4	100.00	
@@ -494,7 +494,7 @@ drop temporary table t1;
 create table t1 select a from t1 union select a from t2;
 ERROR 42S01: Table 't1' already exists
 select a from t1 union select a from t2 order by t2.a;
-ERROR 42000: Table 't2' from one of the SELECTs cannot be used in field list
+ERROR 42000: Table 't2' from one of the SELECTs cannot be used in ORDER clause
 drop table t1,t2;
 select length(version()) > 1 as `*` UNION select 2;
 *
@@ -1532,11 +1532,8 @@ SELECT a FROM (SELECT a FROM t1 UNION SELECT a FROM t1 ORDER BY c) AS test;
 ERROR 42S22: Unknown column 'c' in 'order clause'
 DROP TABLE t1;
 (select 1 into @var) union (select 1);
-ERROR HY000: Incorrect usage of UNION and INTO
+ERROR 42000: Incorrect usage/placement of 'INTO'
 (select 1) union (select 1 into @var);
-select @var;
- at var
-1
 (select 2) union (select 1 into @var);
 ERROR 42000: Result consisted of more than one row
 CREATE TABLE t1 (a int);
@@ -1666,11 +1663,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 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
+ERROR 42000: Incorrect usage/placement of 'INTO'
 SELECT a INTO OUTFILE 'union.out.file7' FROM t1 UNION SELECT a 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 'UNION SELECT a FROM t1' at line 1
+ERROR 42000: Incorrect usage/placement of 'INTO'
 SELECT a INTO DUMPFILE 'union.out.file8' FROM t1 UNION SELECT a 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 'UNION SELECT a FROM t1' at line 1
+ERROR 42000: Incorrect usage/placement of 'INTO'
 # 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;
@@ -2019,14 +2016,14 @@ SET @@global.slow_query_log= @old_slow_query_log;
 CREATE TABLE t1 (a int);
 CREATE TABLE t2 (b int);
 CREATE TABLE t3 (c int);
-SELECT a FROM t1 UNION SELECT b FROM t2 JOIN (t3) ON ( t2.b = t3.c );
+SELECT a FROM t1 UNION SELECT b FROM t2 JOIN t3 ON ( t2.b = t3.c );
 a
 DROP TABLE t1, t2, t3;
 CREATE TABLE t1 (pk int NOT NULL);
 CREATE TABLE t2 (pk int NOT NULL, fk int NOT NULL);
-SELECT t1.pk FROM t1 LEFT JOIN (t2) ON (t1.pk = t2.fk)
+SELECT t1.pk FROM t1 LEFT JOIN t2 ON (t1.pk = t2.fk)
 UNION
-SELECT t1.pk FROM t1 LEFT JOIN (t2) ON (t1.pk = t2.fk);
+SELECT t1.pk FROM t1 LEFT JOIN t2 ON (t1.pk = t2.fk);
 pk
 DROP TABLE t1,t2;
 create table t1 (a int);
diff --git a/mysql-test/main/union.test b/mysql-test/main/union.test
index f86cae87524..463eb609151 100644
--- a/mysql-test/main/union.test
+++ b/mysql-test/main/union.test
@@ -973,12 +973,12 @@ DROP TABLE t1;
 
 #
 # Bug#23345: Wrongly allowed INTO in a non-last select of a UNION.
+# (fixed)
 #
---error 1221
+--error ER_CANT_USE_OPTION_HERE
 (select 1 into @var) union (select 1);
 (select 1) union (select 1 into @var);
-select @var;
---error 1172
+--error ER_TOO_MANY_ROWS
 (select 2) union (select 1 into @var);
 
 #
@@ -1102,11 +1102,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_PARSE_ERROR
+--error ER_CANT_USE_OPTION_HERE
 SELECT a INTO @v FROM t1 UNION SELECT a FROM t1;
---error ER_PARSE_ERROR
+--error ER_CANT_USE_OPTION_HERE
 SELECT a INTO OUTFILE 'union.out.file7' FROM t1 UNION SELECT a FROM t1;
---error ER_PARSE_ERROR
+--error ER_CANT_USE_OPTION_HERE
 SELECT a INTO DUMPFILE 'union.out.file8' FROM t1 UNION SELECT a FROM t1;
 
 -- echo # Tests fix in parser rule query_expression_body.
@@ -1361,15 +1361,15 @@ SET @@global.slow_query_log= @old_slow_query_log;
 CREATE TABLE t1 (a int);
 CREATE TABLE t2 (b int);
 CREATE TABLE t3 (c int);
-SELECT a FROM t1 UNION SELECT b FROM t2 JOIN (t3) ON ( t2.b = t3.c );
+SELECT a FROM t1 UNION SELECT b FROM t2 JOIN t3 ON ( t2.b = t3.c );
 
 DROP TABLE t1, t2, t3;
 
 CREATE TABLE t1 (pk int NOT NULL);
 CREATE TABLE t2 (pk int NOT NULL, fk int NOT NULL);
-SELECT t1.pk FROM t1 LEFT JOIN (t2) ON (t1.pk = t2.fk)
+SELECT t1.pk FROM t1 LEFT JOIN t2 ON (t1.pk = t2.fk)
 UNION
-SELECT t1.pk FROM t1 LEFT JOIN (t2) ON (t1.pk = t2.fk);
+SELECT t1.pk FROM t1 LEFT JOIN t2 ON (t1.pk = t2.fk);
 
 DROP TABLE t1,t2;
 
diff --git a/mysql-test/main/view.result b/mysql-test/main/view.result
index e61e2d2663d..0c8a3458170 100644
--- a/mysql-test/main/view.result
+++ b/mysql-test/main/view.result
@@ -919,12 +919,12 @@ select * from v4;
 ERROR 21000: Subquery returns more than 1 row
 drop view v4, v3, v2, v1;
 create view v1 as select 5 into @w;
-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 @w' at line 1
+ERROR 42000: Incorrect usage/placement of 'INTO'
 create view v1 as select 5 into outfile 'ttt';
-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 outfile 'ttt'' at line 1
+ERROR 42000: Incorrect usage/placement of 'INTO'
 create table t1 (a int);
 create view v1 as select a from t1 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 'procedure analyse()' at line 1
+ERROR 42000: Incorrect usage/placement of 'PROCEDURE'
 create view v1 as select 1 from (select 1) as d1;
 drop view v1;
 drop table t1;
@@ -3153,7 +3153,7 @@ DROP TABLE t1;
 DROP VIEW IF EXISTS v1;
 SELECT * FROM (SELECT 1) AS t into @w;
 CREATE VIEW v1 AS SELECT * FROM (SELECT 1) AS t into @w;
-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 @w' at line 1
+ERROR 42000: Incorrect usage/placement of 'INTO'
 # Previously the following would fail.
 SELECT * FROM (SELECT 1) AS t into @w;
 drop view if exists view_24532_a;
@@ -4093,7 +4093,7 @@ LEFT JOIN t5 e_alias_1 ON e_alias_1.e1 = a_alias_1.a1
 LEFT JOIN t6 f_alias_1 ON f_alias_1.f1 = a_alias_1.a1
 ;
 SELECT 1
-FROM ((  SELECT 1
+FROM (  SELECT 1
 FROM t1 a_alias_1
 LEFT JOIN (t2 b_alias_1 JOIN t1 a_alias_2) ON b_alias_1.b1 = a_alias_1.a1 AND a_alias_2.a1 = a_alias_1.a1
 LEFT JOIN t3 c_alias_1 ON c_alias_1.c1 = a_alias_1.a1
@@ -4101,8 +4101,8 @@ LEFT JOIN t4 d_alias_1 ON d_alias_1.d1 = a_alias_1.a1
 LEFT JOIN t3 c_alias_2 ON c_alias_2.c1 = a_alias_1.a1
 LEFT JOIN t5 e_alias_1 ON e_alias_1.e1 = a_alias_1.a1
 LEFT JOIN t6 f_alias_1 ON f_alias_1.f1 = a_alias_1.a1
-) t1)
-LEFT OUTER JOIN ((  SELECT 1
+) t1
+LEFT OUTER JOIN (  SELECT 1
 FROM t1 a_alias_1
 LEFT JOIN (t2 b_alias_1 JOIN t1 a_alias_2) ON b_alias_1.b1 = a_alias_1.a1 AND a_alias_2.a1 = a_alias_1.a1
 LEFT JOIN t3 c_alias_1 ON c_alias_1.c1 = a_alias_1.a1
@@ -4110,8 +4110,8 @@ LEFT JOIN t4 d_alias_1 ON d_alias_1.d1 = a_alias_1.a1
 LEFT JOIN t3 c_alias_2 ON c_alias_2.c1 = a_alias_1.a1
 LEFT JOIN t5 e_alias_1 ON e_alias_1.e1 = a_alias_1.a1
 LEFT JOIN t6 f_alias_1 ON f_alias_1.f1 = a_alias_1.a1
-) t2) ON 1=1
-LEFT OUTER JOIN ((  SELECT 1
+) t2 ON 1=1
+LEFT OUTER JOIN (  SELECT 1
 FROM t1 a_alias_1
 LEFT JOIN (t2 b_alias_1 JOIN t1 a_alias_2) ON b_alias_1.b1 = a_alias_1.a1 AND a_alias_2.a1 = a_alias_1.a1
 LEFT JOIN t3 c_alias_1 ON c_alias_1.c1 = a_alias_1.a1
@@ -4119,8 +4119,8 @@ LEFT JOIN t4 d_alias_1 ON d_alias_1.d1 = a_alias_1.a1
 LEFT JOIN t3 c_alias_2 ON c_alias_2.c1 = a_alias_1.a1
 LEFT JOIN t5 e_alias_1 ON e_alias_1.e1 = a_alias_1.a1
 LEFT JOIN t6 f_alias_1 ON f_alias_1.f1 = a_alias_1.a1
-) t3) ON 1=1
-LEFT OUTER JOIN ((  SELECT 1
+) t3 ON 1=1
+LEFT OUTER JOIN (  SELECT 1
 FROM t1 a_alias_1
 LEFT JOIN (t2 b_alias_1 JOIN t1 a_alias_2) ON b_alias_1.b1 = a_alias_1.a1 AND a_alias_2.a1 = a_alias_1.a1
 LEFT JOIN t3 c_alias_1 ON c_alias_1.c1 = a_alias_1.a1
@@ -4128,8 +4128,8 @@ LEFT JOIN t4 d_alias_1 ON d_alias_1.d1 = a_alias_1.a1
 LEFT JOIN t3 c_alias_2 ON c_alias_2.c1 = a_alias_1.a1
 LEFT JOIN t5 e_alias_1 ON e_alias_1.e1 = a_alias_1.a1
 LEFT JOIN t6 f_alias_1 ON f_alias_1.f1 = a_alias_1.a1
-) t4) ON 1=1
-LEFT OUTER JOIN ((  SELECT 1
+) t4 ON 1=1
+LEFT OUTER JOIN (  SELECT 1
 FROM t1 a_alias_1
 LEFT JOIN (t2 b_alias_1 JOIN t1 a_alias_2) ON b_alias_1.b1 = a_alias_1.a1 AND a_alias_2.a1 = a_alias_1.a1
 LEFT JOIN t3 c_alias_1 ON c_alias_1.c1 = a_alias_1.a1
@@ -4137,8 +4137,8 @@ LEFT JOIN t4 d_alias_1 ON d_alias_1.d1 = a_alias_1.a1
 LEFT JOIN t3 c_alias_2 ON c_alias_2.c1 = a_alias_1.a1
 LEFT JOIN t5 e_alias_1 ON e_alias_1.e1 = a_alias_1.a1
 LEFT JOIN t6 f_alias_1 ON f_alias_1.f1 = a_alias_1.a1
-) t5) ON 1=1
-LEFT OUTER JOIN ((  SELECT 1
+) t5 ON 1=1
+LEFT OUTER JOIN (  SELECT 1
 FROM t1 a_alias_1
 LEFT JOIN (t2 b_alias_1 JOIN t1 a_alias_2) ON b_alias_1.b1 = a_alias_1.a1 AND a_alias_2.a1 = a_alias_1.a1
 LEFT JOIN t3 c_alias_1 ON c_alias_1.c1 = a_alias_1.a1
@@ -4146,8 +4146,8 @@ LEFT JOIN t4 d_alias_1 ON d_alias_1.d1 = a_alias_1.a1
 LEFT JOIN t3 c_alias_2 ON c_alias_2.c1 = a_alias_1.a1
 LEFT JOIN t5 e_alias_1 ON e_alias_1.e1 = a_alias_1.a1
 LEFT JOIN t6 f_alias_1 ON f_alias_1.f1 = a_alias_1.a1
-) t6) ON 1=1
-LEFT OUTER JOIN ((  SELECT 1
+) t6 ON 1=1
+LEFT OUTER JOIN (  SELECT 1
 FROM t1 a_alias_1
 LEFT JOIN (t2 b_alias_1 JOIN t1 a_alias_2) ON b_alias_1.b1 = a_alias_1.a1 AND a_alias_2.a1 = a_alias_1.a1
 LEFT JOIN t3 c_alias_1 ON c_alias_1.c1 = a_alias_1.a1
@@ -4155,8 +4155,8 @@ LEFT JOIN t4 d_alias_1 ON d_alias_1.d1 = a_alias_1.a1
 LEFT JOIN t3 c_alias_2 ON c_alias_2.c1 = a_alias_1.a1
 LEFT JOIN t5 e_alias_1 ON e_alias_1.e1 = a_alias_1.a1
 LEFT JOIN t6 f_alias_1 ON f_alias_1.f1 = a_alias_1.a1
-) t7) ON 1=1
-LEFT OUTER JOIN ((  SELECT 1
+) t7 ON 1=1
+LEFT OUTER JOIN (  SELECT 1
 FROM t1 a_alias_1
 LEFT JOIN (t2 b_alias_1 JOIN t1 a_alias_2) ON b_alias_1.b1 = a_alias_1.a1 AND a_alias_2.a1 = a_alias_1.a1
 LEFT JOIN t3 c_alias_1 ON c_alias_1.c1 = a_alias_1.a1
@@ -4164,18 +4164,18 @@ LEFT JOIN t4 d_alias_1 ON d_alias_1.d1 = a_alias_1.a1
 LEFT JOIN t3 c_alias_2 ON c_alias_2.c1 = a_alias_1.a1
 LEFT JOIN t5 e_alias_1 ON e_alias_1.e1 = a_alias_1.a1
 LEFT JOIN t6 f_alias_1 ON f_alias_1.f1 = a_alias_1.a1
-) t8) ON 1=1
+) t8 ON 1=1
 ;
 1
 SELECT 1
-FROM (v1 t1)
-LEFT OUTER JOIN (v1 t2) ON 1=1
-LEFT OUTER JOIN (v1 t3) ON 1=1
-LEFT OUTER JOIN (v1 t4) ON 1=1
-LEFT OUTER JOIN (v1 t5) ON 1=1
-LEFT OUTER JOIN (v1 t6) ON 1=1
-LEFT OUTER JOIN (v1 t7) ON 1=1
-LEFT OUTER JOIN (v1 t8) ON 1=1
+FROM v1 t1
+LEFT OUTER JOIN v1 t2 ON 1=1
+LEFT OUTER JOIN v1 t3 ON 1=1
+LEFT OUTER JOIN v1 t4 ON 1=1
+LEFT OUTER JOIN v1 t5 ON 1=1
+LEFT OUTER JOIN v1 t6 ON 1=1
+LEFT OUTER JOIN v1 t7 ON 1=1
+LEFT OUTER JOIN v1 t8 ON 1=1
 ;
 1
 drop view v1;
diff --git a/mysql-test/main/view.test b/mysql-test/main/view.test
index f78ddd6f49e..fe7f22b1f89 100644
--- a/mysql-test/main/view.test
+++ b/mysql-test/main/view.test
@@ -833,12 +833,12 @@ drop view v4, v3, v2, v1;
 #
 # VIEW over SELECT with prohibited clauses
 #
--- error ER_PARSE_ERROR
+-- error ER_CANT_USE_OPTION_HERE
 create view v1 as select 5 into @w;
--- error ER_PARSE_ERROR
+-- error ER_CANT_USE_OPTION_HERE
 create view v1 as select 5 into outfile 'ttt';
 create table t1 (a int);
--- error ER_PARSE_ERROR
+-- error ER_CANT_USE_OPTION_HERE
 create view v1 as select a from t1 procedure analyse();
 # now derived tables are allowed
 create view v1 as select 1 from (select 1) as d1;
@@ -3109,7 +3109,7 @@ DROP VIEW IF EXISTS v1;
 let $query = SELECT * FROM (SELECT 1) AS t into @w;
 
 eval $query;
---error ER_PARSE_ERROR
+--error ER_CANT_USE_OPTION_HERE
 eval CREATE VIEW v1 AS $query;
 --echo # Previously the following would fail.
 eval $query;
@@ -4042,7 +4042,7 @@ CREATE OR REPLACE view v1 AS
 ;
 
 SELECT 1
-FROM ((  SELECT 1
+FROM (  SELECT 1
   FROM t1 a_alias_1
     LEFT JOIN (t2 b_alias_1 JOIN t1 a_alias_2) ON b_alias_1.b1 = a_alias_1.a1 AND a_alias_2.a1 = a_alias_1.a1
     LEFT JOIN t3 c_alias_1 ON c_alias_1.c1 = a_alias_1.a1
@@ -4050,8 +4050,8 @@ FROM ((  SELECT 1
     LEFT JOIN t3 c_alias_2 ON c_alias_2.c1 = a_alias_1.a1
     LEFT JOIN t5 e_alias_1 ON e_alias_1.e1 = a_alias_1.a1
     LEFT JOIN t6 f_alias_1 ON f_alias_1.f1 = a_alias_1.a1
-) t1)
-LEFT OUTER JOIN ((  SELECT 1
+) t1
+LEFT OUTER JOIN (  SELECT 1
   FROM t1 a_alias_1
     LEFT JOIN (t2 b_alias_1 JOIN t1 a_alias_2) ON b_alias_1.b1 = a_alias_1.a1 AND a_alias_2.a1 = a_alias_1.a1
     LEFT JOIN t3 c_alias_1 ON c_alias_1.c1 = a_alias_1.a1
@@ -4059,8 +4059,8 @@ LEFT OUTER JOIN ((  SELECT 1
     LEFT JOIN t3 c_alias_2 ON c_alias_2.c1 = a_alias_1.a1
     LEFT JOIN t5 e_alias_1 ON e_alias_1.e1 = a_alias_1.a1
     LEFT JOIN t6 f_alias_1 ON f_alias_1.f1 = a_alias_1.a1
-) t2) ON 1=1
-LEFT OUTER JOIN ((  SELECT 1
+) t2 ON 1=1
+LEFT OUTER JOIN (  SELECT 1
   FROM t1 a_alias_1
     LEFT JOIN (t2 b_alias_1 JOIN t1 a_alias_2) ON b_alias_1.b1 = a_alias_1.a1 AND a_alias_2.a1 = a_alias_1.a1
     LEFT JOIN t3 c_alias_1 ON c_alias_1.c1 = a_alias_1.a1
@@ -4068,8 +4068,8 @@ LEFT OUTER JOIN ((  SELECT 1
     LEFT JOIN t3 c_alias_2 ON c_alias_2.c1 = a_alias_1.a1
     LEFT JOIN t5 e_alias_1 ON e_alias_1.e1 = a_alias_1.a1
     LEFT JOIN t6 f_alias_1 ON f_alias_1.f1 = a_alias_1.a1
-) t3) ON 1=1
-LEFT OUTER JOIN ((  SELECT 1
+) t3 ON 1=1
+LEFT OUTER JOIN (  SELECT 1
   FROM t1 a_alias_1
     LEFT JOIN (t2 b_alias_1 JOIN t1 a_alias_2) ON b_alias_1.b1 = a_alias_1.a1 AND a_alias_2.a1 = a_alias_1.a1
     LEFT JOIN t3 c_alias_1 ON c_alias_1.c1 = a_alias_1.a1
@@ -4077,8 +4077,8 @@ LEFT OUTER JOIN ((  SELECT 1
     LEFT JOIN t3 c_alias_2 ON c_alias_2.c1 = a_alias_1.a1
     LEFT JOIN t5 e_alias_1 ON e_alias_1.e1 = a_alias_1.a1
     LEFT JOIN t6 f_alias_1 ON f_alias_1.f1 = a_alias_1.a1
-) t4) ON 1=1
-LEFT OUTER JOIN ((  SELECT 1
+) t4 ON 1=1
+LEFT OUTER JOIN (  SELECT 1
   FROM t1 a_alias_1
     LEFT JOIN (t2 b_alias_1 JOIN t1 a_alias_2) ON b_alias_1.b1 = a_alias_1.a1 AND a_alias_2.a1 = a_alias_1.a1
     LEFT JOIN t3 c_alias_1 ON c_alias_1.c1 = a_alias_1.a1
@@ -4086,8 +4086,8 @@ LEFT OUTER JOIN ((  SELECT 1
     LEFT JOIN t3 c_alias_2 ON c_alias_2.c1 = a_alias_1.a1
     LEFT JOIN t5 e_alias_1 ON e_alias_1.e1 = a_alias_1.a1
     LEFT JOIN t6 f_alias_1 ON f_alias_1.f1 = a_alias_1.a1
-) t5) ON 1=1
-LEFT OUTER JOIN ((  SELECT 1
+) t5 ON 1=1
+LEFT OUTER JOIN (  SELECT 1
   FROM t1 a_alias_1
     LEFT JOIN (t2 b_alias_1 JOIN t1 a_alias_2) ON b_alias_1.b1 = a_alias_1.a1 AND a_alias_2.a1 = a_alias_1.a1
     LEFT JOIN t3 c_alias_1 ON c_alias_1.c1 = a_alias_1.a1
@@ -4095,8 +4095,8 @@ LEFT OUTER JOIN ((  SELECT 1
     LEFT JOIN t3 c_alias_2 ON c_alias_2.c1 = a_alias_1.a1
     LEFT JOIN t5 e_alias_1 ON e_alias_1.e1 = a_alias_1.a1
     LEFT JOIN t6 f_alias_1 ON f_alias_1.f1 = a_alias_1.a1
-) t6) ON 1=1
-LEFT OUTER JOIN ((  SELECT 1
+) t6 ON 1=1
+LEFT OUTER JOIN (  SELECT 1
   FROM t1 a_alias_1
     LEFT JOIN (t2 b_alias_1 JOIN t1 a_alias_2) ON b_alias_1.b1 = a_alias_1.a1 AND a_alias_2.a1 = a_alias_1.a1
     LEFT JOIN t3 c_alias_1 ON c_alias_1.c1 = a_alias_1.a1
@@ -4104,8 +4104,8 @@ LEFT OUTER JOIN ((  SELECT 1
     LEFT JOIN t3 c_alias_2 ON c_alias_2.c1 = a_alias_1.a1
     LEFT JOIN t5 e_alias_1 ON e_alias_1.e1 = a_alias_1.a1
     LEFT JOIN t6 f_alias_1 ON f_alias_1.f1 = a_alias_1.a1
-) t7) ON 1=1
-LEFT OUTER JOIN ((  SELECT 1
+) t7 ON 1=1
+LEFT OUTER JOIN (  SELECT 1
   FROM t1 a_alias_1
     LEFT JOIN (t2 b_alias_1 JOIN t1 a_alias_2) ON b_alias_1.b1 = a_alias_1.a1 AND a_alias_2.a1 = a_alias_1.a1
     LEFT JOIN t3 c_alias_1 ON c_alias_1.c1 = a_alias_1.a1
@@ -4113,18 +4113,18 @@ LEFT OUTER JOIN ((  SELECT 1
     LEFT JOIN t3 c_alias_2 ON c_alias_2.c1 = a_alias_1.a1
     LEFT JOIN t5 e_alias_1 ON e_alias_1.e1 = a_alias_1.a1
     LEFT JOIN t6 f_alias_1 ON f_alias_1.f1 = a_alias_1.a1
-) t8) ON 1=1
+) t8 ON 1=1
 ;
 
 SELECT 1
-FROM (v1 t1)
-LEFT OUTER JOIN (v1 t2) ON 1=1
-LEFT OUTER JOIN (v1 t3) ON 1=1
-LEFT OUTER JOIN (v1 t4) ON 1=1
-LEFT OUTER JOIN (v1 t5) ON 1=1
-LEFT OUTER JOIN (v1 t6) ON 1=1
-LEFT OUTER JOIN (v1 t7) ON 1=1
-LEFT OUTER JOIN (v1 t8) ON 1=1
+FROM v1 t1
+LEFT OUTER JOIN v1 t2 ON 1=1
+LEFT OUTER JOIN v1 t3 ON 1=1
+LEFT OUTER JOIN v1 t4 ON 1=1
+LEFT OUTER JOIN v1 t5 ON 1=1
+LEFT OUTER JOIN v1 t6 ON 1=1
+LEFT OUTER JOIN v1 t7 ON 1=1
+LEFT OUTER JOIN v1 t8 ON 1=1
 ;
 
 drop view v1;
diff --git a/mysql-test/r/sp-error.result b/mysql-test/r/sp-error.result
new file mode 100644
index 00000000000..874e930fb5b
--- /dev/null
+++ b/mysql-test/r/sp-error.result
@@ -0,0 +1,2876 @@
+drop table if exists t1, t2;
+SELECT * FROM mysql.proc INTO OUTFILE 'MYSQLTEST_VARDIR/tmp/proc.txt';
+delete from mysql.proc;
+create procedure syntaxerror(t int)|
+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
+create procedure syntaxerror(t int)|
+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
+create procedure syntaxerror(t int)|
+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
+drop table if exists t3|
+create table t3 ( x int )|
+insert into t3 values (2), (3)|
+create procedure bad_into(out param int)
+select x from t3 into param|
+call bad_into(@x)|
+ERROR 42000: Result consisted of more than one row
+drop procedure bad_into|
+drop table t3|
+create procedure proc1()
+set @x = 42|
+create function func1() returns int
+return 42|
+create procedure foo()
+create procedure bar() set @x=3|
+ERROR 2F003: Can't create a PROCEDURE from within another stored routine
+create procedure foo()
+create function bar() returns double return 2.3|
+ERROR 2F003: Can't create a FUNCTION from within another stored routine
+create procedure proc1()
+set @x = 42|
+ERROR 42000: PROCEDURE proc1 already exists
+create function func1() returns int
+return 42|
+ERROR 42000: FUNCTION func1 already exists
+drop procedure proc1|
+drop function func1|
+alter procedure foo|
+ERROR 42000: PROCEDURE test.foo does not exist
+alter function foo|
+ERROR 42000: FUNCTION test.foo does not exist
+drop procedure foo|
+ERROR 42000: PROCEDURE test.foo does not exist
+drop function foo|
+ERROR 42000: FUNCTION test.foo does not exist
+call foo()|
+ERROR 42000: PROCEDURE test.foo does not exist
+drop procedure if exists foo|
+Warnings:
+Note	1305	PROCEDURE test.foo does not exist
+show create procedure foo|
+ERROR 42000: PROCEDURE foo does not exist
+show create function foo|
+ERROR 42000: FUNCTION foo does not exist
+create procedure foo()
+foo: loop
+leave bar;
+end loop|
+ERROR 42000: LEAVE with no matching label: bar
+create procedure foo()
+foo: loop
+iterate bar;
+end loop|
+ERROR 42000: ITERATE with no matching label: bar
+create procedure foo()
+foo: begin
+iterate foo;
+end|
+ERROR 42000: ITERATE with no matching label: foo
+create procedure foo()
+foo: loop
+foo: loop
+set @x=2;
+end loop foo;
+end loop foo|
+ERROR 42000: Redefining label foo
+create procedure foo()
+foo: loop
+set @x=2;
+end loop bar|
+ERROR 42000: End-label bar without match
+create procedure foo()
+return 42|
+ERROR 42000: RETURN is only allowed in a FUNCTION
+create procedure p(x int)
+set @x = x|
+create function f(x int) returns int
+return x+42|
+call p()|
+ERROR 42000: Incorrect number of arguments for PROCEDURE test.p; expected 1, got 0
+call p(1, 2)|
+ERROR 42000: Incorrect number of arguments for PROCEDURE test.p; expected 1, got 2
+select f()|
+ERROR 42000: Incorrect number of arguments for FUNCTION test.f; expected 1, got 0
+select f(1, 2)|
+ERROR 42000: Incorrect number of arguments for FUNCTION test.f; expected 1, got 2
+drop procedure p|
+drop function f|
+create procedure p(val int, out res int)
+begin
+declare x int default 0;
+declare continue handler for foo set x = 1;
+insert into test.t1 values (val);
+if (x) then
+set res = 0;
+else
+set res = 1;
+end if;
+end|
+ERROR 42000: Undefined CONDITION: foo
+create procedure p(val int, out res int)
+begin
+declare x int default 0;
+declare foo condition for 1146;
+declare continue handler for bar set x = 1;
+insert into test.t1 values (val);
+if (x) then
+set res = 0;
+else
+set res = 1;
+end if;
+end|
+ERROR 42000: Undefined CONDITION: bar
+create function f(val int) returns int
+begin
+declare x int;
+set x = val+3;
+end|
+ERROR 42000: No RETURN found in FUNCTION test.f
+create function f(val int) returns int
+begin
+declare x int;
+set x = val+3;
+if x < 4 then
+return x;
+end if;
+end|
+select f(10)|
+ERROR 2F005: FUNCTION f ended without RETURN
+drop function f|
+create procedure p()
+begin
+declare c cursor for insert into test.t1 values ("foo", 42);
+open c;
+close c;
+end|
+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 'insert into test.t1 values ("foo", 42);
+open c;
+close c;
+end' at line 3
+create procedure p()
+begin
+declare x int;
+declare c cursor for select * into x from test.t limit 1;
+open c;
+close c;
+end|
+ERROR 42000: Cursor SELECT must not have INTO
+create procedure p()
+begin
+declare c cursor for select * from test.t;
+open cc;
+close c;
+end|
+ERROR 42000: Undefined CURSOR: cc
+drop table if exists t1|
+create table t1 (val int)|
+create procedure p()
+begin
+declare c cursor for select * from test.t1;
+open c;
+open c;
+close c;
+end|
+call p()|
+ERROR 24000: Cursor is already open
+drop procedure p|
+create procedure p()
+begin
+declare c cursor for select * from test.t1;
+open c;
+close c;
+close c;
+end|
+call p()|
+ERROR 24000: Cursor is not open
+drop procedure p|
+alter procedure bar3 sql security invoker|
+ERROR 42000: PROCEDURE test.bar3 does not exist
+drop table t1|
+drop table if exists t1|
+create table t1 (val int, x float)|
+insert into t1 values (42, 3.1), (19, 1.2)|
+create procedure p()
+begin
+declare x int;
+declare c cursor for select * from t1;
+open c;
+fetch c into x, y;
+close c;
+end|
+ERROR 42000: Undeclared variable: y
+create procedure p()
+begin
+declare x int;
+declare c cursor for select * from t1;
+open c;
+fetch c into x;
+close c;
+end|
+call p()|
+ERROR HY000: Incorrect number of FETCH variables
+drop procedure p|
+create procedure p()
+begin
+declare x int;
+declare y float;
+declare z int;
+declare c cursor for select * from t1;
+open c;
+fetch c into x, y, z;
+close c;
+end|
+call p()|
+ERROR HY000: Incorrect number of FETCH variables
+drop procedure p|
+create procedure p(in x int, x char(10))
+begin
+end|
+ERROR 42000: Duplicate parameter: x
+create function p(x int, x char(10))
+begin
+end|
+ERROR 42000: Duplicate parameter: x
+create procedure p()
+begin
+declare x float;
+declare x int;
+end|
+ERROR 42000: Duplicate variable: x
+create procedure p()
+begin
+declare c condition for 1064;
+declare c condition for 1065;
+end|
+ERROR 42000: Duplicate condition: c
+create procedure p()
+begin
+declare c cursor for select * from t1;
+declare c cursor for select field from t1;
+end|
+ERROR 42000: Duplicate cursor: c
+create procedure u()
+use sptmp|
+ERROR 0A000: USE is not allowed in stored procedures
+create procedure p()
+begin
+declare c cursor for select * from t1;
+declare x int;
+end|
+ERROR 42000: Variable or condition declaration after cursor or handler declaration
+create procedure p()
+begin
+declare x int;
+declare continue handler for sqlstate '42S99' set x = 1;
+declare foo condition for sqlstate '42S99';
+end|
+ERROR 42000: Variable or condition declaration after cursor or handler declaration
+create procedure p()
+begin
+declare x int;
+declare continue handler for sqlstate '42S99' set x = 1;
+declare c cursor for select * from t1;
+end|
+ERROR 42000: Cursor declaration after handler declaration
+drop procedure if exists p|
+create procedure p(in x int, inout y int, out z int)
+begin
+set y = x+y;
+set z = x+y;
+end|
+set @tmp_x = 42|
+set @tmp_y = 3|
+set @tmp_z = 0|
+call p(@tmp_x, @tmp_y, @tmp_z)|
+select @tmp_x, @tmp_y, @tmp_z|
+ at tmp_x	@tmp_y	@tmp_z
+42	45	87
+call p(42, 43, @tmp_z)|
+ERROR 42000: OUT or INOUT argument 2 for routine test.p is not a variable or NEW pseudo-variable in BEFORE trigger
+call p(42, @tmp_y, 43)|
+ERROR 42000: OUT or INOUT argument 3 for routine test.p is not a variable or NEW pseudo-variable in BEFORE trigger
+drop procedure p|
+create procedure p() begin end|
+lock table t1 read|
+call p()|
+unlock tables|
+drop procedure p|
+lock tables t1 read, mysql.proc write|
+ERROR HY000: You can't combine write-locking of system tables with other tables or lock types
+lock tables mysql.proc write, mysql.user write|
+ERROR HY000: You can't combine write-locking of system tables with other tables or lock types
+lock tables t1 read, mysql.proc read|
+unlock tables|
+lock tables mysql.proc write|
+unlock tables|
+drop function if exists f1|
+create function f1(i int) returns int
+begin
+insert into t1 (val) values (i);
+return 0;
+end|
+select val, f1(val) from t1|
+ERROR HY000: Can't update table 't1' in stored function/trigger because it is already used by statement which invoked this stored function/trigger
+select val, f1(val) from t1 as tab|
+ERROR HY000: Can't update table 't1' in stored function/trigger because it is already used by statement which invoked this stored function/trigger
+select * from t1|
+val	x
+42	3.1
+19	1.2
+update t1 set val= f1(val)|
+ERROR HY000: Can't update table 't1' in stored function/trigger because it is already used by statement which invoked this stored function/trigger
+select * from t1|
+val	x
+42	3.1
+19	1.2
+select f1(17)|
+f1(17)
+0
+select * from t1|
+val	x
+42	3.1
+19	1.2
+17	NULL
+delete from t1 where val= 17|
+drop function f1|
+create procedure bug1965()
+begin
+declare c cursor for select val from t1 order by valname;
+open c;
+close c;
+end|
+call bug1965()|
+ERROR 42S22: Unknown column 'valname' in 'order clause'
+drop procedure bug1965|
+select 1 into a|
+ERROR 42000: Undeclared variable: a
+drop table if exists t3|
+create table t3 (column_1_0 int)|
+create procedure bug1653()
+update t3 set column_1 = 0|
+call bug1653()|
+ERROR 42S22: Unknown column 'column_1' in 'field list'
+drop table t3|
+create table t3 (column_1 int)|
+call bug1653()|
+drop procedure bug1653|
+drop table t3|
+create procedure bug2259()
+begin
+declare v1 int;
+declare c1 cursor for select s1 from t1;
+fetch c1 into v1;
+end|
+call bug2259()|
+ERROR 24000: Cursor is not open
+drop procedure bug2259|
+create procedure bug2272()
+begin
+declare v int;
+update t1 set v = 42;
+end|
+insert into t1 values (666, 51.3)|
+call bug2272()|
+ERROR 42S22: Unknown column 'v' in 'field list'
+truncate table t1|
+drop procedure bug2272|
+create procedure bug2329_1()
+begin
+declare v int;
+insert into t1 (v) values (5);
+end|
+create procedure bug2329_2()
+begin
+declare v int;
+replace t1 set v = 5;
+end|
+call bug2329_1()|
+ERROR 42S22: Unknown column 'v' in 'field list'
+call bug2329_2()|
+ERROR 42S22: Unknown column 'v' in 'field list'
+drop procedure bug2329_1|
+drop procedure bug2329_2|
+create function bug3287() returns int
+begin
+declare v int default null;
+case
+when v is not null then return 1;
+end case;
+return 2;
+end|
+select bug3287()|
+ERROR 20000: Case not found for CASE statement
+drop function bug3287|
+create procedure bug3287(x int)
+case x
+when 0 then
+insert into test.t1 values (x, 0.1);
+when 1 then
+insert into test.t1 values (x, 1.1);
+end case|
+call bug3287(2)|
+ERROR 20000: Case not found for CASE statement
+drop procedure bug3287|
+drop table if exists t3|
+create table t3 (s1 int, primary key (s1))|
+insert into t3 values (5),(6)|
+create procedure bug3279(out y int) 
+begin
+declare x int default 0;
+begin
+declare exit handler for sqlexception set x = x+1;
+insert into t3 values (5);
+end;
+if x < 2 then
+set x = x+1;
+insert into t3 values (6);
+end if;
+set y = x;
+end|
+set @x = 0|
+call bug3279(@x)|
+ERROR 23000: Duplicate entry '6' for key 'PRIMARY'
+select @x|
+ at x
+0
+drop procedure bug3279|
+drop table t3|
+create procedure nodb.bug3339() begin end|
+ERROR 42000: Unknown database 'nodb'
+create procedure bug2653_1(a int, out b int)
+set b = aa|
+create procedure bug2653_2(a int, out b int)
+begin
+if aa < 0 then
+set b = - a;
+else
+set b = a;
+end if;
+end|
+call bug2653_1(1, @b)|
+ERROR 42S22: Unknown column 'aa' in 'field list'
+call bug2653_2(2, @b)|
+ERROR 42S22: Unknown column 'aa' in 'field list'
+drop procedure bug2653_1|
+drop procedure bug2653_2|
+create procedure bug4344() drop procedure bug4344|
+ERROR HY000: Can't drop or alter a PROCEDURE from within another stored routine
+create procedure bug4344() drop function bug4344|
+ERROR HY000: Can't drop or alter a FUNCTION from within another stored routine
+drop procedure if exists bug3294|
+create procedure bug3294()
+begin
+declare continue handler for sqlexception drop table t5;
+drop table t5;
+drop table t5;
+end|
+create table t5 (x int)|
+call bug3294()|
+ERROR 42S02: Unknown table 'test.t5'
+drop procedure bug3294|
+drop procedure if exists bug8776_1|
+drop procedure if exists bug8776_2|
+drop procedure if exists bug8776_3|
+drop procedure if exists bug8776_4|
+create procedure bug8776_1()
+begin
+declare continue handler for sqlstate '42S0200test' begin end;
+begin end;
+end|
+ERROR 42000: Bad SQLSTATE: '42S0200test'
+create procedure bug8776_2()
+begin
+declare continue handler for sqlstate '4200' begin end;
+begin end;
+end|
+ERROR 42000: Bad SQLSTATE: '4200'
+create procedure bug8776_3()
+begin
+declare continue handler for sqlstate '420000' begin end;
+begin end;
+end|
+ERROR 42000: Bad SQLSTATE: '420000'
+create procedure bug8776_4()
+begin
+declare continue handler for sqlstate '42x00' begin end;
+begin end;
+end|
+ERROR 42000: Bad SQLSTATE: '42x00'
+create procedure bug6600()
+check table t1|
+ERROR 0A000: CHECK is not allowed in stored procedures
+create procedure bug6600()
+lock table t1 read|
+ERROR 0A000: LOCK is not allowed in stored procedures
+create procedure bug6600()
+unlock table t1|
+ERROR 0A000: UNLOCK is not allowed in stored procedures
+drop procedure if exists bug9566|
+create procedure bug9566()
+begin
+select * from t1;
+end|
+lock table t1 read|
+alter procedure bug9566 comment 'Some comment'|
+ERROR HY000: Can't execute the given command because you have active locked tables or an active transaction
+unlock tables|
+drop procedure bug9566|
+drop procedure if exists bug7299|
+create procedure bug7299()
+begin
+declare v int;
+declare c cursor for select val from t1;
+declare exit handler for sqlexception select 'Error!'; 
+open c;
+fetch c into v;
+end|
+truncate table t1|
+call bug7299()|
+ERROR 02000: No data - zero rows fetched, selected, or processed
+drop procedure bug7299|
+create procedure bug9073()
+begin
+declare continue handler for sqlexception select 1;
+declare continue handler for sqlexception select 2;
+end|
+ERROR 42000: Duplicate handler declared in the same block
+create procedure bug9073()
+begin
+declare condname1 condition for 1234;
+declare continue handler for condname1 select 1;
+declare exit handler for condname1 select 2;
+end|
+ERROR 42000: Duplicate handler declared in the same block
+create procedure bug9073()
+begin
+declare condname1 condition for sqlstate '42000';
+declare condname2 condition for sqlstate '42000';
+declare exit handler for condname1 select 1;
+declare continue handler for condname2 select 2;
+end|
+ERROR 42000: Duplicate handler declared in the same block
+create procedure bug9073()
+begin
+declare condname1 condition for sqlstate '42000';
+declare exit handler for condname1 select 1;
+declare exit handler for sqlstate '42000' select 2;
+end|
+ERROR 42000: Duplicate handler declared in the same block
+drop procedure if exists bug9073|
+create procedure bug9073()
+begin
+declare condname1 condition for sqlstate '42000';
+declare continue handler for condname1 select 1;
+begin
+declare exit handler for sqlstate '42000' select 2;
+begin
+declare continue handler for sqlstate '42000' select 3;
+end;
+end;
+end|
+drop procedure bug9073|
+create procedure bug7047()
+alter procedure bug7047|
+ERROR HY000: Can't drop or alter a PROCEDURE from within another stored routine
+create function bug7047() returns int
+begin
+alter function bug7047;
+return 0;
+end|
+ERROR HY000: Can't drop or alter a FUNCTION from within another stored routine
+create function bug8408() returns int
+begin
+select * from t1;
+return 0;
+end|
+ERROR 0A000: Not allowed to return a result set from a function
+create function bug8408() returns int
+begin
+show warnings;
+return 0;
+end|
+ERROR 0A000: Not allowed to return a result set from a function
+create function bug8408(a int) returns int
+begin
+declare b int;
+select b;
+return b;
+end|
+ERROR 0A000: Not allowed to return a result set from a function
+drop function if exists bug8408_f|
+drop procedure if exists bug8408_p|
+create function bug8408_f() returns int
+begin
+call bug8408_p();
+return 0;
+end|
+create procedure bug8408_p()
+select * from t1|
+call bug8408_p()|
+val	x
+select bug8408_f()|
+ERROR 0A000: Not allowed to return a result set from a function
+drop procedure bug8408_p|
+drop function bug8408_f|
+create function bug8408() returns int
+begin
+declare n int default 0;
+select count(*) into n from t1;
+return n;
+end|
+insert into t1 value (2, 2.7), (3, 3.14), (7, 7.0)|
+select *,bug8408() from t1|
+val	x	bug8408()
+2	2.7	3
+3	3.14	3
+7	7	3
+drop function bug8408|
+truncate table t1|
+drop procedure if exists bug10537|
+create procedure bug10537()
+load data local infile '/tmp/somefile' into table t1|
+ERROR 0A000: LOAD DATA is not allowed in stored procedures
+drop function if exists bug8409|
+create function bug8409()
+returns int
+begin
+flush tables;
+return 5;
+end|
+ERROR 0A000: FLUSH is not allowed in stored function or trigger
+create function bug8409() returns int begin reset query cache;
+return 1; end|
+ERROR 0A000: RESET is not allowed in stored function or trigger
+create function bug8409() returns int begin reset master;
+return 1; end|
+ERROR 0A000: RESET is not allowed in stored function or trigger
+create function bug8409() returns int begin reset slave;
+return 1; end|
+ERROR 0A000: RESET is not allowed in stored function or trigger
+create function bug8409() returns int begin flush hosts;
+return 1; end|
+ERROR 0A000: FLUSH is not allowed in stored function or trigger
+create function bug8409() returns int begin flush privileges;
+return 1; end|
+ERROR 0A000: FLUSH is not allowed in stored function or trigger
+create function bug8409() returns int begin flush tables with read lock;
+return 1; end|
+ERROR 0A000: FLUSH is not allowed in stored function or trigger
+create function bug8409() returns int begin flush tables;
+return 1; end|
+ERROR 0A000: FLUSH is not allowed in stored function or trigger
+create function bug8409() returns int begin flush logs;
+return 1; end|
+ERROR 0A000: FLUSH is not allowed in stored function or trigger
+create function bug8409() returns int begin flush status;
+return 1; end|
+ERROR 0A000: FLUSH is not allowed in stored function or trigger
+create function bug8409() returns int begin flush slave;
+return 1; end|
+ERROR 0A000: FLUSH is not allowed in stored function or trigger
+create function bug8409() returns int begin flush master;
+return 1; end|
+ERROR 0A000: FLUSH is not allowed in stored function or trigger
+create function bug8409() returns int begin flush des_key_file;
+return 1; end|
+ERROR 0A000: FLUSH is not allowed in stored function or trigger
+create function bug8409() returns int begin flush user_resources;
+return 1; end|
+ERROR 0A000: FLUSH is not allowed in stored function or trigger
+create procedure bug9529_901234567890123456789012345678901234567890123456789012345()
+begin
+end|
+ERROR 42000: Identifier name 'bug9529_901234567890123456789012345678901234567890123456789012345' is too long
+drop procedure if exists bug17015_0123456789012345678901234567890123456789012345678901234|
+create procedure bug17015_0123456789012345678901234567890123456789012345678901234()
+begin
+end|
+show procedure status like 'bug17015%'|
+Db	Name	Type	Definer	Modified	Created	Security_type	Comment	character_set_client	collation_connection	Database Collation
+test	bug17015_0123456789012345678901234567890123456789012345678901234	PROCEDURE	root at localhost	0000-00-00 00:00:00	0000-00-00 00:00:00	DEFINER		latin1	latin1_swedish_ci	latin1_swedish_ci
+drop procedure bug17015_0123456789012345678901234567890123456789012345678901234|
+drop procedure if exists bug10969|
+create procedure bug10969()
+begin
+declare s1 int default 0;
+select default(s1) from t30;
+end|
+ERROR 42000: Incorrect column name 's1'
+create procedure bug10969()
+begin
+declare s1 int default 0;
+select default(t30.s1) from t30;
+end|
+drop procedure bug10969|
+drop table t1|
+create table t1(f1 int);
+create table t2(f1 int);
+CREATE PROCEDURE SP001()
+P1: BEGIN
+DECLARE ENDTABLE INT DEFAULT 0;
+DECLARE TEMP_NUM INT;
+DECLARE TEMP_SUM INT;
+DECLARE C1 CURSOR FOR SELECT F1 FROM t1;
+DECLARE C2 CURSOR FOR SELECT F1 FROM t2;
+DECLARE CONTINUE HANDLER FOR NOT FOUND SET ENDTABLE = 1;
+SET ENDTABLE=0;
+SET TEMP_SUM=0;
+SET TEMP_NUM=0;
+OPEN C1;
+FETCH C1 INTO TEMP_NUM;
+WHILE ENDTABLE = 0 DO
+SET TEMP_SUM=TEMP_NUM+TEMP_SUM;
+FETCH C1 INTO TEMP_NUM;
+END WHILE;
+SELECT TEMP_SUM;
+CLOSE C1;
+CLOSE C1;
+SELECT 'end of proc';
+END P1|
+call SP001();
+TEMP_SUM
+0
+ERROR 24000: Cursor is not open
+drop procedure SP001;
+drop table t1, t2;
+drop function if exists bug11394|
+drop function if exists bug11394_1|
+drop function if exists bug11394_2|
+drop procedure if exists bug11394|
+create function bug11394(i int) returns int
+begin
+if i <= 0 then
+return 0;
+else
+return (i in (100, 200, bug11394(i-1), 400));
+end if;
+end|
+select bug11394(2)|
+ERROR HY000: Recursive stored functions and triggers are not allowed
+drop function bug11394|
+create function bug11394_1(i int) returns int
+begin
+if i <= 0 then
+return 0;
+else
+return (select bug11394_1(i-1));
+end if;
+end|
+select bug11394_1(2)|
+ERROR HY000: Recursive stored functions and triggers are not allowed
+drop function bug11394_1|
+create function bug11394_2(i int) returns int return i|
+select bug11394_2(bug11394_2(10))|
+bug11394_2(bug11394_2(10))
+10
+drop function bug11394_2|
+create procedure bug11394(i int, j int)
+begin
+if i > 0 then
+call bug11394(i - 1,(select 1));
+end if;
+end|
+call bug11394(2, 1)|
+ERROR HY000: Recursive limit 0 (as set by the max_sp_recursion_depth variable) was exceeded for routine bug11394
+set @@max_sp_recursion_depth=10|
+call bug11394(2, 1)|
+set @@max_sp_recursion_depth=default|
+drop procedure bug11394|
+CREATE PROCEDURE BUG_12490() HELP CONTENTS;
+ERROR 0A000: HELP is not allowed in stored procedures
+CREATE FUNCTION BUG_12490() RETURNS INT HELP CONTENTS;
+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 'HELP CONTENTS' at line 1
+CREATE TABLE t_bug_12490(a int);
+CREATE TRIGGER BUG_12490 BEFORE UPDATE ON t_bug_12490 FOR EACH ROW HELP CONTENTS;
+ERROR 0A000: HELP is not allowed in stored procedures
+DROP TABLE t_bug_12490;
+drop function if exists bug11834_1;
+drop function if exists bug11834_2;
+create function bug11834_1() returns int return 10;
+create function bug11834_2() returns int return bug11834_1();
+prepare stmt from "select bug11834_2()";
+execute stmt;
+bug11834_2()
+10
+execute stmt;
+bug11834_2()
+10
+drop function bug11834_1;
+execute stmt;
+ERROR 42000: FUNCTION test.bug11834_1 does not exist
+deallocate prepare stmt;
+drop function bug11834_2;
+DROP FUNCTION IF EXISTS bug12953|
+CREATE FUNCTION bug12953() RETURNS INT
+BEGIN
+OPTIMIZE TABLE t1;
+RETURN 1;
+END|
+ERROR 0A000: Not allowed to return a result set from a function
+DROP FUNCTION IF EXISTS bug12995|
+CREATE FUNCTION bug12995() RETURNS INT
+BEGIN
+HANDLER t1 OPEN;
+RETURN 1;
+END|
+ERROR 0A000: HANDLER is not allowed in stored procedures
+CREATE FUNCTION bug12995() RETURNS INT
+BEGIN
+HANDLER t1 READ FIRST;
+RETURN 1;
+END|
+ERROR 0A000: HANDLER is not allowed in stored procedures
+CREATE FUNCTION bug12995() RETURNS INT
+BEGIN
+HANDLER t1 CLOSE;
+RETURN 1;
+END|
+ERROR 0A000: HANDLER is not allowed in stored procedures
+SELECT bug12995()|
+ERROR 42000: FUNCTION test.bug12995 does not exist
+drop procedure if exists bug12712;
+drop function if exists bug12712;
+create procedure bug12712()
+set session autocommit = 0;
+select @@autocommit;
+@@autocommit
+1
+set @au = @@autocommit;
+call bug12712();
+select @@autocommit;
+@@autocommit
+0
+set session autocommit = @au;
+create function bug12712()
+returns int
+begin
+call bug12712();
+return 0;
+end|
+set @x = bug12712()|
+ERROR HY000: Not allowed to set autocommit from a stored function or trigger
+drop procedure bug12712|
+drop function bug12712|
+create function bug12712()
+returns int
+begin
+set session autocommit = 0;
+return 0;
+end|
+ERROR HY000: Not allowed to set autocommit from a stored function or trigger
+create function bug12712()
+returns int
+begin
+set @@autocommit = 0;
+return 0;
+end|
+ERROR HY000: Not allowed to set autocommit from a stored function or trigger
+create function bug12712()
+returns int
+begin
+set local autocommit = 0;
+return 0;
+end|
+ERROR HY000: Not allowed to set autocommit from a stored function or trigger
+create trigger bug12712
+before insert on t1 for each row set session autocommit = 0;
+ERROR HY000: Not allowed to set autocommit from a stored function or trigger
+drop procedure if exists bug13510_1|
+drop procedure if exists bug13510_2|
+drop procedure if exists bug13510_3|
+drop procedure if exists bug13510_4|
+create procedure bug13510_1()
+begin
+declare password varchar(10);
+set password = 'foo1';
+select password;
+end|
+ERROR 42000: Variable 'password' must be quoted with `...`, or renamed
+set names='foo2'|
+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
+create procedure bug13510_2()
+begin
+declare names varchar(10);
+set names = 'foo2';
+select names;
+end|
+ERROR 42000: Variable 'names' must be quoted with `...`, or renamed
+create procedure bug13510_3()
+begin
+declare password varchar(10);
+set `password` = 'foo3';
+select password;
+end|
+create procedure bug13510_4()
+begin
+declare names varchar(10);
+set `names` = 'foo4';
+select names;
+end|
+call bug13510_3()|
+password
+foo3
+call bug13510_4()|
+names
+foo4
+drop procedure bug13510_3|
+drop procedure bug13510_4|
+drop function if exists bug_13627_f|
+CREATE TABLE t1 (a int)|
+CREATE TRIGGER tr1 BEFORE INSERT ON t1 FOR EACH ROW BEGIN DROP TRIGGER test1; END |
+ERROR HY000: Explicit or implicit commit is not allowed in stored function or trigger
+CREATE FUNCTION bug_13627_f() returns int BEGIN DROP TRIGGER test1; return 1; END |
+ERROR HY000: Explicit or implicit commit is not allowed in stored function or trigger
+CREATE TRIGGER tr1 BEFORE INSERT ON t1 FOR EACH ROW BEGIN create table t2 (a int); END |
+ERROR HY000: Explicit or implicit commit is not allowed in stored function or trigger
+CREATE FUNCTION bug_13627_f() returns int BEGIN create table t2 (a int); return 1; END |
+ERROR HY000: Explicit or implicit commit is not allowed in stored function or trigger
+CREATE TRIGGER tr1 BEFORE INSERT ON t1 FOR EACH ROW BEGIN create index t1_i on t1 (a); END |
+ERROR HY000: Explicit or implicit commit is not allowed in stored function or trigger
+CREATE FUNCTION bug_13627_f() returns int BEGIN create index t1_i on t1 (a); return 1; END |
+ERROR HY000: Explicit or implicit commit is not allowed in stored function or trigger
+CREATE TRIGGER tr1 BEFORE INSERT ON t1 FOR EACH ROW BEGIN alter table t1 add column  b int; END |
+ERROR HY000: Explicit or implicit commit is not allowed in stored function or trigger
+CREATE FUNCTION bug_13627_f() returns int BEGIN alter table t1 add column  b int; return 1; END |
+ERROR HY000: Explicit or implicit commit is not allowed in stored function or trigger
+CREATE TRIGGER tr1 BEFORE INSERT ON t1 FOR EACH ROW BEGIN rename table t1 to t2; END |
+ERROR HY000: Explicit or implicit commit is not allowed in stored function or trigger
+CREATE FUNCTION bug_13627_f() returns int BEGIN rename table t1 to t2; return 1; END |
+ERROR HY000: Explicit or implicit commit is not allowed in stored function or trigger
+CREATE TRIGGER tr1 BEFORE INSERT ON t1 FOR EACH ROW BEGIN truncate table t1; END |
+ERROR HY000: Explicit or implicit commit is not allowed in stored function or trigger
+CREATE FUNCTION bug_13627_f() returns int BEGIN truncate table t1; return 1; END |
+ERROR HY000: Explicit or implicit commit is not allowed in stored function or trigger
+CREATE TRIGGER tr1 BEFORE INSERT ON t1 FOR EACH ROW BEGIN drop table t1; END |
+ERROR HY000: Explicit or implicit commit is not allowed in stored function or trigger
+CREATE FUNCTION bug_13627_f() returns int BEGIN drop table t1; return 1; END |
+ERROR HY000: Explicit or implicit commit is not allowed in stored function or trigger
+CREATE TRIGGER tr1 BEFORE INSERT ON t1 FOR EACH ROW BEGIN drop index t1_i on t1; END |
+ERROR HY000: Explicit or implicit commit is not allowed in stored function or trigger
+CREATE FUNCTION bug_13627_f() returns int BEGIN drop index t1_i on t1; return 1; END |
+ERROR HY000: Explicit or implicit commit is not allowed in stored function or trigger
+CREATE TRIGGER tr1 BEFORE INSERT ON t1 FOR EACH ROW BEGIN unlock tables; END |
+ERROR 0A000: UNLOCK is not allowed in stored procedures
+CREATE FUNCTION bug_13627_f() returns int BEGIN unlock tables; return 1; END |
+ERROR 0A000: UNLOCK is not allowed in stored procedures
+CREATE TRIGGER tr1 BEFORE INSERT ON t1 FOR EACH ROW BEGIN LOCK TABLE t1 READ; END |
+ERROR 0A000: LOCK is not allowed in stored procedures
+CREATE FUNCTION bug_13627_f() returns int BEGIN LOCK TABLE t1 READ; return 1; END |
+ERROR 0A000: LOCK is not allowed in stored procedures
+CREATE TRIGGER tr1 BEFORE INSERT ON t1 FOR EACH ROW BEGIN create database mysqltest; END |
+ERROR HY000: Explicit or implicit commit is not allowed in stored function or trigger
+CREATE FUNCTION bug_13627_f() returns int BEGIN create database mysqltest; return 1; END |
+ERROR HY000: Explicit or implicit commit is not allowed in stored function or trigger
+CREATE TRIGGER tr1 BEFORE INSERT ON t1 FOR EACH ROW BEGIN drop database mysqltest; END |
+ERROR HY000: Explicit or implicit commit is not allowed in stored function or trigger
+CREATE FUNCTION bug_13627_f() returns int BEGIN drop database mysqltest; return 1; END |
+ERROR HY000: Explicit or implicit commit is not allowed in stored function or trigger
+CREATE TRIGGER tr1 BEFORE INSERT ON t1 FOR EACH ROW BEGIN create user 'mysqltest_1'; END |
+ERROR HY000: Explicit or implicit commit is not allowed in stored function or trigger
+CREATE FUNCTION bug_13627_f() returns int BEGIN create user 'mysqltest_1'; return 1; END |
+ERROR HY000: Explicit or implicit commit is not allowed in stored function or trigger
+CREATE TRIGGER bug21975 BEFORE INSERT ON t1 FOR EACH ROW BEGIN grant select on t1 to 'mysqltest_1'; END |
+ERROR HY000: Explicit or implicit commit is not allowed in stored function or trigger
+CREATE FUNCTION bug21975() returns int BEGIN grant select on t1 to 'mysqltest_1'; return 1; END |
+ERROR HY000: Explicit or implicit commit is not allowed in stored function or trigger
+CREATE TRIGGER bug21975 BEFORE INSERT ON t1 FOR EACH ROW BEGIN revoke select on t1 from 'mysqltest_1'; END |
+ERROR HY000: Explicit or implicit commit is not allowed in stored function or trigger
+CREATE FUNCTION bug21975() returns int BEGIN revoke select on t1 from 'mysqltest_1'; return 1; END |
+ERROR HY000: Explicit or implicit commit is not allowed in stored function or trigger
+CREATE TRIGGER bug21975 BEFORE INSERT ON t1 FOR EACH ROW BEGIN revoke all privileges on *.* from 'mysqltest_1'; END |
+ERROR HY000: Explicit or implicit commit is not allowed in stored function or trigger
+CREATE FUNCTION bug21975() returns int BEGIN revoke all privileges on *.* from 'mysqltest_1'; return 1; END |
+ERROR HY000: Explicit or implicit commit is not allowed in stored function or trigger
+CREATE TRIGGER tr1 BEFORE INSERT ON t1 FOR EACH ROW BEGIN drop user 'mysqltest_1'; END |
+ERROR HY000: Explicit or implicit commit is not allowed in stored function or trigger
+CREATE FUNCTION bug_13627_f() returns int BEGIN drop user 'mysqltest_1'; return 1; END |
+ERROR HY000: Explicit or implicit commit is not allowed in stored function or trigger
+CREATE TRIGGER tr1 BEFORE INSERT ON t1 FOR EACH ROW BEGIN rename user 'mysqltest_2' to 'mysqltest_1'; END |
+ERROR HY000: Explicit or implicit commit is not allowed in stored function or trigger
+CREATE FUNCTION bug_13627_f() returns int BEGIN rename user 'mysqltest_2' to 'mysqltest_1'; return 1; END |
+ERROR HY000: Explicit or implicit commit is not allowed in stored function or trigger
+CREATE TRIGGER tr1 BEFORE INSERT ON t1 FOR EACH ROW BEGIN create view v1 as select 1; END |
+ERROR HY000: Explicit or implicit commit is not allowed in stored function or trigger
+CREATE FUNCTION bug_13627_f() returns int BEGIN create view v1 as select 1; return 1; END |
+ERROR HY000: Explicit or implicit commit is not allowed in stored function or trigger
+CREATE TRIGGER tr1 BEFORE INSERT ON t1 FOR EACH ROW BEGIN alter view v1 as select 1; END |
+ERROR 0A000: ALTER VIEW is not allowed in stored procedures
+CREATE FUNCTION bug_13627_f() returns int BEGIN alter view v1 as select 1; return 1; END |
+ERROR 0A000: ALTER VIEW is not allowed in stored procedures
+CREATE TRIGGER tr1 BEFORE INSERT ON t1 FOR EACH ROW BEGIN drop view v1; END |
+ERROR HY000: Explicit or implicit commit is not allowed in stored function or trigger
+CREATE FUNCTION bug_13627_f() returns int BEGIN drop view v1; return 1; END |
+ERROR HY000: Explicit or implicit commit is not allowed in stored function or trigger
+CREATE TRIGGER tr1 BEFORE INSERT ON t1 FOR EACH ROW BEGIN create trigger tr2 before insert on t1 for each row do select 1; END |
+ERROR 2F003: Can't create a TRIGGER from within another stored routine
+CREATE FUNCTION bug_13627_f() returns int BEGIN create trigger tr2 before insert on t1 for each row do select 1; return 1; END |
+ERROR 2F003: Can't create a TRIGGER from within another stored routine
+CREATE TRIGGER tr1 BEFORE INSERT ON t1 FOR EACH ROW BEGIN drop function bug_13627_f; END |
+ERROR HY000: Can't drop or alter a FUNCTION from within another stored routine
+CREATE FUNCTION bug_13627_f() returns int BEGIN drop function bug_13627_f; return 1; END |
+ERROR HY000: Can't drop or alter a FUNCTION from within another stored routine
+CREATE TRIGGER tr1 BEFORE INSERT ON t1 FOR EACH ROW BEGIN create function f2 () returns int return 1; END |
+ERROR 2F003: Can't create a FUNCTION from within another stored routine
+CREATE FUNCTION bug_13627_f() returns int BEGIN create function f2 () returns int return 1; return 1; END |
+ERROR 2F003: Can't create a FUNCTION from within another stored routine
+CREATE TRIGGER tr1 BEFORE INSERT ON t1 FOR EACH ROW
+BEGIN
+CREATE TEMPORARY TABLE t2 (a int);
+DROP TEMPORARY TABLE t2;
+END |
+CREATE FUNCTION bug_13627_f() returns int
+BEGIN
+CREATE TEMPORARY TABLE t2 (a int);
+DROP TEMPORARY TABLE t2;
+return 1;
+END |
+drop table t1|
+drop function bug_13627_f|
+drop function if exists bug12329;
+Warnings:
+Note	1305	FUNCTION test.bug12329 does not exist
+create table t1 as select 1 a;
+create table t2 as select 1 a;
+create function bug12329() returns int return (select a from t1);
+prepare stmt1 from 'select bug12329()';
+execute stmt1;
+bug12329()
+1
+drop function bug12329;
+create function bug12329() returns int return (select a+100 from t2);
+select bug12329();
+bug12329()
+101
+execute stmt1;
+bug12329()
+101
+deallocate prepare stmt1;
+drop function bug12329;
+drop table t1, t2;
+create database mysqltest1;
+use mysqltest1;
+drop database mysqltest1;
+create function f1() returns int return 1;
+ERROR 3D000: No database selected
+create procedure p1(out param1 int)
+begin
+select count(*) into param1 from t3;
+end|
+ERROR 3D000: No database selected
+use test;
+DROP PROCEDURE IF EXISTS bug13037_p1;
+DROP PROCEDURE IF EXISTS bug13037_p2;
+DROP PROCEDURE IF EXISTS bug13037_p3;
+CREATE PROCEDURE bug13037_p1()
+BEGIN
+IF bug13037_foo THEN
+SELECT 1;
+END IF;
+END|
+CREATE PROCEDURE bug13037_p2()
+BEGIN
+SET @bug13037_foo = bug13037_bar;
+END|
+CREATE PROCEDURE bug13037_p3()
+BEGIN
+SELECT bug13037_foo;
+END|
+
+CALL bug13037_p1();
+ERROR 42S22: Unknown column 'bug13037_foo' in 'field list'
+CALL bug13037_p2();
+ERROR 42S22: Unknown column 'bug13037_bar' in 'field list'
+CALL bug13037_p3();
+ERROR 42S22: Unknown column 'bug13037_foo' in 'field list'
+CALL bug13037_p1();
+ERROR 42S22: Unknown column 'bug13037_foo' in 'field list'
+CALL bug13037_p2();
+ERROR 42S22: Unknown column 'bug13037_bar' in 'field list'
+CALL bug13037_p3();
+ERROR 42S22: Unknown column 'bug13037_foo' in 'field list'
+DROP PROCEDURE bug13037_p1;
+DROP PROCEDURE bug13037_p2;
+DROP PROCEDURE bug13037_p3;
+create database mysqltest1;
+create database mysqltest2;
+use mysqltest1;
+drop database mysqltest1;
+create procedure mysqltest2.p1() select version();
+create procedure p2() select version();
+ERROR 3D000: No database selected
+use mysqltest2;
+show procedure status;
+Db	Name	Type	Definer	Modified	Created	Security_type	Comment	character_set_client	collation_connection	Database Collation
+mysqltest2	p1	PROCEDURE	root at localhost	0000-00-00 00:00:00	0000-00-00 00:00:00	DEFINER		latin1	latin1_swedish_ci	latin1_swedish_ci
+drop database mysqltest2;
+use test;
+DROP FUNCTION IF EXISTS bug13012|
+CREATE FUNCTION bug13012() RETURNS INT
+BEGIN
+REPAIR TABLE t1;
+RETURN 1;
+END|
+ERROR 0A000: Not allowed to return a result set from a function
+create table t1 (a int)|
+CREATE PROCEDURE bug13012_1() REPAIR TABLE t1|
+CREATE FUNCTION bug13012_2() RETURNS INT
+BEGIN
+CALL bug13012_1();
+RETURN 1;
+END|
+SELECT bug13012_2()|
+ERROR 0A000: Not allowed to return a result set from a function
+drop table t1|
+drop procedure bug13012_1|
+drop function bug13012_2|
+drop function if exists bug11555_1;
+drop function if exists bug11555_2;
+drop view if exists v1, v2, v3, v4;
+create function bug11555_1() returns int return (select max(i) from t1);
+create function bug11555_2() returns int return bug11555_1();
+create view v1 as select bug11555_1();
+drop view v1;
+create view v2 as select bug11555_2();
+drop view v2;
+create table t1 (i int);
+create view v1 as select bug11555_1();
+create view v2 as select bug11555_2();
+create view v3 as select * from v1;
+drop table t1;
+select * from v1;
+ERROR HY000: View 'test.v1' references invalid table(s) or column(s) or function(s) or definer/invoker of view lack rights to use them
+select * from v2;
+ERROR HY000: View 'test.v2' references invalid table(s) or column(s) or function(s) or definer/invoker of view lack rights to use them
+select * from v3;
+ERROR HY000: View 'test.v3' references invalid table(s) or column(s) or function(s) or definer/invoker of view lack rights to use them
+create view v4 as select * from v1;
+drop view v1, v2, v3, v4;
+drop function bug11555_1;
+drop function bug11555_2;
+create table t1 (i int);
+create table t2 (i int);
+create trigger t1_ai after insert on t1 for each row insert into t2 values (new.i);
+create view v1 as select * from t1;
+drop table t2;
+insert into v1 values (1);
+ERROR 42S02: Table 'test.t2' doesn't exist
+drop trigger t1_ai;
+create function bug11555_1() returns int return (select max(i) from t2);
+create trigger t1_ai after insert on t1 for each row set @a:=bug11555_1();
+insert into v1 values (2);
+ERROR 42S02: Table 'test.t2' doesn't exist
+drop function bug11555_1;
+drop table t1;
+drop view v1;
+drop procedure if exists ` bug15658`;
+create procedure ``() select 1;
+ERROR 42000: Incorrect routine name ''
+create procedure ` `() select 1;
+ERROR 42000: Incorrect routine name ' '
+create procedure `bug15658 `() select 1;
+ERROR 42000: Incorrect routine name 'bug15658 '
+create procedure ``.bug15658() select 1;
+ERROR 42000: Incorrect database name ''
+create procedure `x `.bug15658() select 1;
+ERROR 42000: Incorrect database name 'x '
+create procedure ` bug15658`() select 1;
+call ` bug15658`();
+1
+1
+show procedure status;
+Db	Name	Type	Definer	Modified	Created	Security_type	Comment	character_set_client	collation_connection	Database Collation
+test	 bug15658	PROCEDURE	root at localhost	0000-00-00 00:00:00	0000-00-00 00:00:00	DEFINER		latin1	latin1_swedish_ci	latin1_swedish_ci
+drop procedure ` bug15658`;
+drop function if exists bug14270;
+drop table if exists t1;
+create table t1 (s1 int primary key);
+create function bug14270() returns int
+begin
+load index into cache t1;
+return 1;
+end|
+ERROR 0A000: Not allowed to return a result set from a function
+create function bug14270() returns int
+begin
+cache index t1 key (`primary`) in keycache1;
+return 1;
+end|
+ERROR 0A000: Not allowed to return a result set from a function
+drop table t1;
+drop procedure if exists bug15091;
+create procedure bug15091()
+begin
+declare selectstr varchar(6000) default ' ';
+declare conditionstr varchar(5000)  default '';
+set selectstr = concat(selectstr,
+' and ',
+c.operatorid,
+'in (',conditionstr, ')');
+end|
+call bug15091();
+ERROR 42S02: Unknown table 'c' in field list
+drop procedure bug15091;
+drop function if exists bug16896;
+create aggregate function bug16896() returns int return 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 '() returns int return 1' at line 1
+DROP PROCEDURE IF EXISTS bug14702;
+CREATE IF NOT EXISTS PROCEDURE bug14702()
+BEGIN
+END;
+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 'IF NOT EXISTS PROCEDURE bug14702()
+BEGIN
+END' at line 1
+CREATE PROCEDURE IF NOT EXISTS bug14702()
+BEGIN
+END;
+DROP PROCEDURE IF EXISTS bug14702;
+DROP TABLE IF EXISTS t1;
+CREATE TABLE t1 (i INT);
+CREATE PROCEDURE bug20953() CREATE VIEW v AS SELECT 1 INTO @a;
+ERROR 42000: Incorrect usage/placement of 'INTO'
+CREATE PROCEDURE bug20953() CREATE VIEW v AS SELECT 1 INTO DUMPFILE "file";
+ERROR 42000: Incorrect usage/placement of 'INTO'
+CREATE PROCEDURE bug20953() CREATE VIEW v AS SELECT 1 INTO OUTFILE "file";
+ERROR 42000: Incorrect usage/placement of 'INTO'
+CREATE PROCEDURE bug20953()
+CREATE VIEW v AS SELECT i FROM t1 PROCEDURE ANALYSE();
+ERROR 42000: Incorrect usage/placement of 'PROCEDURE'
+CREATE PROCEDURE bug20953() CREATE VIEW v AS SELECT 1 FROM (SELECT 1) AS d1 into @w;
+ERROR 42000: Incorrect usage/placement of 'INTO'
+CREATE PROCEDURE bug20953(i INT) CREATE VIEW v AS SELECT i;
+ERROR HY000: View's SELECT contains a variable or parameter
+CREATE PROCEDURE bug20953()
+BEGIN
+DECLARE i INT;
+CREATE VIEW v AS SELECT i;
+END |
+ERROR HY000: View's SELECT contains a variable or parameter
+PREPARE stmt FROM "CREATE VIEW v AS SELECT ?";
+ERROR HY000: View's SELECT contains a variable or parameter
+DROP TABLE t1;
+drop tables if exists t1;
+drop procedure if exists bug24491;
+create table t1 (id int primary key auto_increment, value varchar(10));
+insert into t1 (id, value) values (1, 'FIRST'), (2, 'SECOND'), (3, 'THIRD');
+create procedure bug24491()
+insert into t1 (id, value) select * from (select 4 as i, 'FOURTH' as v) as y on duplicate key update v = 'DUP';
+call bug24491();
+ERROR 42S22: Unknown column 'v' in 'field list'
+call bug24491();
+ERROR 42S22: Unknown column 'v' in 'field list'
+drop procedure bug24491;
+create procedure bug24491()
+insert into t1 (id, value) select * from (select 4 as id, 'FOURTH' as value) as y on duplicate key update y.value = 'DUP';
+call bug24491();
+ERROR 42S22: Unknown column 'y.value' in 'field list'
+call bug24491();
+ERROR 42S22: Unknown column 'y.value' in 'field list'
+drop procedure bug24491;
+drop tables t1;
+DROP FUNCTION IF EXISTS bug18914_f1;
+DROP FUNCTION IF EXISTS bug18914_f2;
+DROP PROCEDURE IF EXISTS bug18914_p1;
+DROP PROCEDURE IF EXISTS bug18914_p2;
+DROP TABLE IF EXISTS t1, t2;
+CREATE TABLE t1 (i INT);
+CREATE PROCEDURE bug18914_p1() CREATE TABLE t2 (i INT);
+CREATE PROCEDURE bug18914_p2() DROP TABLE IF EXISTS no_such_table;
+CREATE FUNCTION bug18914_f1() RETURNS INT
+BEGIN
+CALL bug18914_p1();
+RETURN 1;
+END |
+CREATE FUNCTION bug18914_f2() RETURNS INT
+BEGIN
+CALL bug18914_p2();
+RETURN 1;
+END |
+CREATE TRIGGER t1_bi BEFORE INSERT ON t1 FOR EACH ROW
+CALL bug18914_p1();
+INSERT INTO t1 VALUES (1);
+ERROR HY000: Explicit or implicit commit is not allowed in stored function or trigger
+SELECT bug18914_f1();
+ERROR HY000: Explicit or implicit commit is not allowed in stored function or trigger
+SELECT bug18914_f2();
+ERROR HY000: Explicit or implicit commit is not allowed in stored function or trigger
+SELECT * FROM t2;
+ERROR 42S02: Table 'test.t2' doesn't exist
+DROP FUNCTION bug18914_f1;
+DROP FUNCTION bug18914_f2;
+DROP PROCEDURE bug18914_p1;
+DROP PROCEDURE bug18914_p2;
+DROP TABLE t1;
+drop table if exists bogus_table_20713;
+drop function if exists func_20713_a;
+drop function if exists func_20713_b;
+create table bogus_table_20713( id int(10) not null primary key);
+insert into bogus_table_20713 values (1), (2), (3);
+create function func_20713_a() returns int(11)
+begin
+declare id int;
+declare continue handler for sqlexception set id=null;
+set @in_func := 1;
+set id = (select id from bogus_table_20713 where id = 3);
+set @in_func := 2;
+return id;
+end//
+create function func_20713_b() returns int(11)
+begin
+declare id int;
+declare continue handler for sqlstate value '42S02' set id=null;
+set @in_func := 1;
+set id = (select id from bogus_table_20713 where id = 3);
+set @in_func := 2;
+return id;
+end//
+set @in_func := 0;
+select func_20713_a();
+func_20713_a()
+NULL
+select @in_func;
+ at in_func
+2
+set @in_func := 0;
+select func_20713_b();
+func_20713_b()
+NULL
+select @in_func;
+ at in_func
+2
+drop table bogus_table_20713;
+set @in_func := 0;
+select func_20713_a();
+func_20713_a()
+NULL
+select @in_func;
+ at in_func
+2
+set @in_func := 0;
+select func_20713_b();
+func_20713_b()
+NULL
+select @in_func;
+ at in_func
+2
+drop function if exists func_20713_a;
+drop function if exists func_20713_b;
+drop table if exists table_25345_a;
+drop table if exists table_25345_b;
+drop procedure if exists proc_25345;
+drop function if exists func_25345;
+drop function if exists func_25345_b;
+create table table_25345_a (a int);
+create table table_25345_b (b int);
+create procedure proc_25345()
+begin
+declare c1 cursor for select a from table_25345_a;
+declare c2 cursor for select b from table_25345_b;
+select 1 as result;
+end ||
+create function func_25345() returns int(11)
+begin
+call proc_25345();
+return 1;
+end ||
+create function func_25345_b() returns int(11)
+begin
+declare c1 cursor for select a from table_25345_a;
+declare c2 cursor for select b from table_25345_b;
+return 1;
+end ||
+call proc_25345();
+result
+1
+select func_25345();
+ERROR 0A000: Not allowed to return a result set from a function
+select func_25345_b();
+func_25345_b()
+1
+drop table table_25345_a;
+call proc_25345();
+result
+1
+select func_25345();
+ERROR 0A000: Not allowed to return a result set from a function
+select func_25345_b();
+func_25345_b()
+1
+drop table table_25345_b;
+drop procedure proc_25345;
+drop function func_25345;
+drop function func_25345_b;
+End of 5.0 tests
+drop function if exists bug16164;
+create function bug16164() returns int
+begin
+show authors;
+return 42;
+end|
+ERROR 0A000: Not allowed to return a result set from a function
+drop function if exists bug20701;
+create function bug20701() returns varchar(25) binary return "test";
+drop function bug20701;
+create function bug20701() returns varchar(25) return "test";
+drop function bug20701;
+create procedure proc_26503_error_1()
+begin
+retry:
+repeat
+begin
+declare continue handler for sqlexception
+begin
+iterate retry;
+end
+select "do something";
+end
+until true end repeat retry;
+end//
+ERROR 42000: ITERATE with no matching label: retry
+create procedure proc_26503_error_2()
+begin
+retry:
+repeat
+begin
+declare continue handler for sqlexception
+iterate retry;
+select "do something";
+end
+until true end repeat retry;
+end//
+ERROR 42000: ITERATE with no matching label: retry
+create procedure proc_26503_error_3()
+begin
+retry:
+repeat
+begin
+declare continue handler for sqlexception
+begin
+leave retry;
+end
+select "do something";
+end
+until true end repeat retry;
+end//
+ERROR 42000: LEAVE with no matching label: retry
+create procedure proc_26503_error_4()
+begin
+retry:
+repeat
+begin
+declare continue handler for sqlexception
+leave retry;
+select "do something";
+end
+until true end repeat retry;
+end//
+ERROR 42000: LEAVE with no matching label: retry
+drop procedure if exists proc_28360;
+drop function if exists func_28360;
+CREATE PROCEDURE proc_28360()
+BEGIN
+ALTER DATABASE `#mysql50#upgrade-me` UPGRADE DATA DIRECTORY NAME;
+END//
+ERROR HY000: Can't drop or alter a DATABASE from within another stored routine
+CREATE FUNCTION func_28360() RETURNS int
+BEGIN
+ALTER DATABASE `#mysql50#upgrade-me` UPGRADE DATA DIRECTORY NAME;
+RETURN 0;
+END//
+ERROR HY000: Can't drop or alter a DATABASE from within another stored routine
+DROP PROCEDURE IF EXISTS p1;
+CREATE PROCEDURE p1()
+BEGIN
+DECLARE c char(100);
+DECLARE cur1 CURSOR FOR SHOW TABLES;
+OPEN cur1;
+FETCH cur1 INTO c;
+select c;
+CLOSE cur1;
+END|
+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 'SHOW TABLES;
+OPEN cur1;
+FETCH cur1 INTO c;
+select c;
+CLOSE cur1;
+END' at line 4
+DROP DATABASE IF EXISTS mysqltest;
+CREATE DATABASE mysqltest;
+USE mysqltest;
+DROP DATABASE mysqltest;
+SELECT inexistent(), 1 + ,;
+ERROR 42000: FUNCTION inexistent does not exist
+SELECT inexistent();
+ERROR 42000: FUNCTION inexistent does not exist
+SELECT .inexistent();
+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 ..inexistent();
+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 '..inexistent()' at line 1
+USE test;
+create function f1() returns int
+begin
+set @test = 1, password = password('foo');
+return 1;
+end|
+ERROR HY000: Not allowed to set autocommit from a stored function or trigger
+create trigger t1
+before insert on t2 for each row set password = password('foo');|
+ERROR HY000: Not allowed to set autocommit from a stored function or trigger
+drop function if exists f1;
+drop function if exists f2;
+drop table if exists t1, t2;
+create function f1() returns int
+begin
+drop temporary table t1;
+return 1;
+end|
+create temporary table t1 as select f1();
+ERROR 42S02: Unknown table 'test.t1'
+create function f2() returns int
+begin
+create temporary table t2 as select f1();
+return 1;
+end|
+create temporary table t1 as select f2();
+ERROR 42S02: Unknown table 'test.t1'
+drop function f1;
+drop function f2;
+create function f1() returns int
+begin
+drop temporary table t2,t1;
+return 1;
+end|
+create function f2() returns int
+begin
+create temporary table t2 as select f1();
+return 1;
+end|
+create temporary table t1 as select f2();
+ERROR 42S02: Unknown table 'test.t2,test.t1'
+drop function f1;
+drop function f2;
+create temporary table t2(a int);
+select * from t2;
+a
+create function f2() returns int
+begin
+drop temporary table t2;
+return 1;
+end|
+select f2();
+f2()
+1
+drop function f2;
+drop table t2;
+ERROR 42S02: Unknown table 'test.t2'
+End of 5.1 tests
+drop procedure if exists proc_33983_a;
+drop procedure if exists proc_33983_b;
+drop procedure if exists proc_33983_c;
+drop procedure if exists proc_33983_d;
+create procedure proc_33983_a()
+begin
+label1:
+begin
+label2:
+begin
+select 1;
+end label1;
+end;
+end|
+ERROR 42000: End-label label1 without match
+create procedure proc_33983_b()
+begin
+label1:
+repeat
+label2:
+repeat
+select 1;
+until FALSE end repeat label1;
+until FALSE end repeat;
+end|
+ERROR 42000: End-label label1 without match
+create procedure proc_33983_c()
+begin
+label1:
+while TRUE do
+label2:
+while TRUE do
+select 1;
+end while label1;
+end while;
+end|
+ERROR 42000: End-label label1 without match
+create procedure proc_33983_d()
+begin
+label1:
+loop
+label2:
+loop
+select 1;
+end loop label1;
+end loop;
+end|
+ERROR 42000: End-label label1 without match
+CREATE TABLE t1 (a INT)|
+INSERT INTO t1 VALUES (1),(2)|
+CREATE PROCEDURE p1(a INT) BEGIN END|
+CALL p1((SELECT * FROM t1))|
+ERROR 21000: Subquery returns more than 1 row
+DROP PROCEDURE IF EXISTS p1|
+DROP TABLE t1|
+drop procedure if exists p1;
+create procedure p1()
+begin
+create table t1 (a int) engine=MyISAM;
+drop table t1;
+end|
+call p1();
+call p1();
+drop procedure p1;
+drop procedure if exists proc_8759;
+create procedure proc_8759()
+begin
+declare should_be_illegal condition for sqlstate '00000';
+declare continue handler for should_be_illegal set @x=0;
+end$$
+ERROR 42000: Bad SQLSTATE: '00000'
+create procedure proc_8759()
+begin
+declare continue handler for sqlstate '00000' set @x=0;
+end$$
+ERROR 42000: Bad SQLSTATE: '00000'
+drop procedure if exists proc_36510;
+create procedure proc_36510()
+begin
+declare should_be_illegal condition for sqlstate '00123';
+declare continue handler for should_be_illegal set @x=0;
+end$$
+ERROR 42000: Bad SQLSTATE: '00123'
+create procedure proc_36510()
+begin
+declare continue handler for sqlstate '00123' set @x=0;
+end$$
+ERROR 42000: Bad SQLSTATE: '00123'
+create procedure proc_36510()
+begin
+declare should_be_illegal condition for 0;
+declare continue handler for should_be_illegal set @x=0;
+end$$
+ERROR HY000: Incorrect CONDITION value: '0'
+create procedure proc_36510()
+begin
+declare continue handler for 0 set @x=0;
+end$$
+ERROR HY000: Incorrect CONDITION value: '0'
+drop procedure if exists p1;
+set @old_recursion_depth = @@max_sp_recursion_depth;
+set @@max_sp_recursion_depth = 255;
+create procedure p1(a int)
+begin
+declare continue handler for 1436 -- ER_STACK_OVERRUN_NEED_MORE
+select 'exception';
+call p1(a+1);
+end|
+call p1(1);
+set @@max_sp_recursion_depth = @old_recursion_depth;
+drop procedure p1;
+LOAD DATA INFILE '../../tmp/proc.txt' INTO TABLE mysql.proc;
+CREATE TABLE t1 (a INT, b INT);
+INSERT INTO t1 VALUES (1,1), (2,2);
+SELECT MAX (a) FROM t1 WHERE b = 999999;
+ERROR 42000: FUNCTION test.MAX does not exist. Check the 'Function Name Parsing and Resolution' section in the Reference Manual
+SELECT AVG (a) FROM t1 WHERE b = 999999;
+AVG (a)
+NULL
+SELECT non_existent (a) FROM t1 WHERE b = 999999;
+ERROR 42000: FUNCTION test.non_existent does not exist
+DROP TABLE t1;
+CREATE TABLE t1 ( f2 INTEGER, f3 INTEGER );
+INSERT INTO t1 VALUES  ( 1, 1 );
+CREATE FUNCTION func_1 () RETURNS INTEGER
+BEGIN
+INSERT INTO t1 SELECT * FROM t1 ;
+RETURN 1 ;
+END|
+INSERT INTO t1 SELECT * FROM (SELECT 2 AS f1, 2 AS f2) AS A WHERE func_1() = 5;
+ERROR HY000: Can't update table 't1' in stored function/trigger because it is already used by statement which invoked this stored function/trigger
+DROP FUNCTION func_1;
+DROP TABLE t1;
+#
+# Bug #47788: Crash in TABLE_LIST::hide_view_error on UPDATE + VIEW + 
+#   SP + MERGE + ALTER
+#
+CREATE TABLE t1 (pk INT, b INT, KEY (b));
+CREATE ALGORITHM = TEMPTABLE VIEW v1 AS SELECT * FROM t1;
+CREATE PROCEDURE p1 (a int) UPDATE IGNORE v1 SET b = a;
+CALL p1(5);
+ERROR HY000: The target table v1 of the UPDATE is not updatable
+ALTER TABLE t1 CHANGE COLUMN b b2 INT;
+CALL p1(7);
+ERROR HY000: View 'test.v1' references invalid table(s) or column(s) or function(s) or definer/invoker of view lack rights to use them
+DROP PROCEDURE p1;
+DROP VIEW v1;
+DROP TABLE t1;
+#
+# Bug#12428824 - PARSER STACK OVERFLOW AND CRASH IN SP_ADD_USED_ROUTINE
+#                WITH OBSCURE QUERY
+#
+SELECT very_long_fn_name_1111111111111111111111111111111111111111111111111111111111111111111111111222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222225555555555555555555555555577777777777777777777777777777777777777777777777777777777777777777777777788888888999999999999999999999();
+ERROR 42000: Identifier name 'very_long_fn_name_1111111111111111111111111111111111111111111111111111111111111111111111111222222222' is too long
+CALL very_long_pr_name_1111111111111111111111111111111111111111111111111111111111111111111111111222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222225555555555555555555555555577777777777777777777777777777777777777777777777777777777777777777777777788888888999999999999999999999();
+ERROR 42000: Identifier name 'very_long_pr_name_1111111111111111111111111111111111111111111111111111111111111111111111111222222222' is too long
+SELECT very_long_db_name_1111111111111111111111111111111111111111111111111111111111111111111111111222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222225555555555555555555555555577777777777777777777777777777777777777777777777777777777777777777777777788888888999999999999999999999.simple_func();
+ERROR 42000: Incorrect database name 'very_long_db_name_1111111111111111111111111111111111111111111111111111111111111111111111111222222222'
+CALL very_long_db_name_1111111111111111111111111111111111111111111111111111111111111111111111111222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222225555555555555555555555555577777777777777777777777777777777777777777777777777777777777777777777777788888888999999999999999999999.simple_proc();
+ERROR 42000: Incorrect database name 'very_long_db_name_1111111111111111111111111111111111111111111111111111111111111111111111111222222222'
+SELECT db_name.very_long_fn_name_111111111111111111111111111111111111111111111111111111111111111111111111122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222999999999999999999999();
+ERROR 42000: Identifier name 'very_long_fn_name_1111111111111111111111111111111111111111111111111111111111111111111111111222222222' is too long
+CALL db_name.very_long_pr_name_111111111111111111111111111111111111111111111111111111111111111111111111122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222999999999999999999999();
+ERROR 42000: Identifier name 'very_long_pr_name_1111111111111111111111111111111111111111111111111111111111111111111111111222222222' is too long
+End of 5.1 tests
+#
+# Bug#23032: Handlers declared in a SP do not handle warnings generated in sub-SP
+#
+
+# - Case 1
+
+DROP PROCEDURE IF EXISTS p1;
+DROP PROCEDURE IF EXISTS p2;
+DROP PROCEDURE IF EXISTS p3;
+DROP PROCEDURE IF EXISTS p4;
+DROP PROCEDURE IF EXISTS p5;
+DROP PROCEDURE IF EXISTS p6;
+CREATE PROCEDURE p1()
+BEGIN
+SELECT CAST('10 ' as unsigned integer);
+SELECT 1;
+CALL p2();
+END|
+CREATE PROCEDURE p2()
+BEGIN
+SELECT CAST('10 ' as unsigned integer);
+END|
+CALL p1();
+CAST('10 ' as unsigned integer)
+10
+1
+1
+CAST('10 ' as unsigned integer)
+10
+Warnings:
+Note	1292	Truncated incorrect INTEGER value: '10 '
+DROP PROCEDURE p1;
+DROP PROCEDURE p2;
+
+# - Case 2
+
+CREATE PROCEDURE p1()
+BEGIN
+DECLARE c INT DEFAULT 0;
+DECLARE CONTINUE HANDLER FOR SQLSTATE '22007' SET c = c + 1;
+CALL p2();
+CALL p3();
+CALL p4();
+SELECT c;
+SELECT @@warning_count;
+SHOW WARNINGS;
+END|
+CREATE PROCEDURE p2()
+BEGIN
+SELECT CAST('10 ' as unsigned integer);
+END|
+CREATE PROCEDURE p3()
+BEGIN
+SELECT CAST('10 ' as unsigned integer);
+SELECT 1;
+END|
+CREATE PROCEDURE p4()
+BEGIN
+SELECT CAST('10 ' as unsigned integer);
+CALL p2();
+END|
+CREATE PROCEDURE p5()
+BEGIN
+SELECT CAST('10 ' as unsigned integer);
+SHOW WARNINGS;
+END|
+CREATE PROCEDURE P6()
+BEGIN
+DECLARE c INT DEFAULT 0;
+DECLARE CONTINUE HANDLER FOR SQLSTATE '22007' SET c = c + 1;
+CALL p5();
+SELECT c;
+END|
+CALL p1();
+CAST('10 ' as unsigned integer)
+10
+CAST('10 ' as unsigned integer)
+10
+1
+1
+CAST('10 ' as unsigned integer)
+10
+CAST('10 ' as unsigned integer)
+10
+c
+3
+@@warning_count
+0
+Level	Code	Message
+CALL p6();
+CAST('10 ' as unsigned integer)
+10
+Level	Code	Message
+Note	1292	Truncated incorrect INTEGER value: '10 '
+c
+1
+DROP PROCEDURE p1;
+DROP PROCEDURE p2;
+DROP PROCEDURE p3;
+DROP PROCEDURE p4;
+DROP PROCEDURE p5;
+DROP PROCEDURE p6;
+
+# - Case 3: check that "Exception trumps No Data".
+
+DROP TABLE IF EXISTS t1;
+CREATE TABLE t1(a INT);
+INSERT INTO t1 VALUES (1), (2), (3);
+CREATE PROCEDURE p1()
+BEGIN
+DECLARE c CURSOR FOR SELECT a FROM t1;
+OPEN c;
+BEGIN
+DECLARE v1 INT;
+DECLARE v2 INT;
+DECLARE EXIT HANDLER FOR SQLEXCEPTION
+SELECT "Error caught (expected)";
+DECLARE EXIT HANDLER FOR NOT FOUND
+SELECT "End of Result Set found!";
+WHILE TRUE DO
+FETCH c INTO v1, v2;
+END WHILE;
+END;
+CLOSE c;
+SELECT a INTO @foo FROM t1 LIMIT 1; # Clear warning stack
+END|
+CALL p1();
+Error caught (expected)
+Error caught (expected)
+DROP PROCEDURE p1;
+DROP TABLE t1;
+#
+# Bug#36185: Incorrect precedence for warning and exception handlers
+#
+DROP TABLE IF EXISTS t1;
+DROP PROCEDURE IF EXISTS p1;
+CREATE TABLE t1 (a INT, b INT NOT NULL);
+CREATE PROCEDURE p1()
+BEGIN
+DECLARE CONTINUE HANDLER FOR SQLWARNING SELECT 'warning';
+DECLARE CONTINUE HANDLER FOR SQLEXCEPTION SELECT 'exception';
+INSERT INTO t1 VALUES (CAST('10 ' AS SIGNED), NULL);
+END|
+CALL p1();
+exception
+exception
+DROP TABLE t1;
+DROP PROCEDURE p1;
+#
+# Bug#5889: Exit handler for a warning doesn't hide the warning in trigger
+#
+SET sql_mode = 'NO_ENGINE_SUBSTITUTION';
+CREATE TABLE t1(a INT, b INT);
+INSERT INTO t1 VALUES (1, 2);
+CREATE TRIGGER t1_bu BEFORE UPDATE ON t1 FOR EACH ROW
+BEGIN
+DECLARE EXIT HANDLER FOR SQLWARNING
+SET NEW.a = 10;
+SET NEW.a = 99999999999;
+END|
+UPDATE t1 SET b = 20;
+SHOW WARNINGS;
+Level	Code	Message
+SELECT * FROM t1;
+a	b
+10	20
+DROP TRIGGER t1_bu;
+DROP TABLE t1;
+SET sql_mode = DEFAULT;
+#
+# Bug#9857: Stored procedures: handler for sqlwarning ignored
+#
+SET @sql_mode_saved = @@sql_mode;
+SET sql_mode = traditional;
+CREATE PROCEDURE p1()
+BEGIN
+DECLARE CONTINUE HANDLER FOR SQLWARNING
+SELECT 'warning caught (expected)';
+SELECT 5 / 0;
+END|
+CREATE PROCEDURE p2()
+BEGIN
+DECLARE CONTINUE HANDLER FOR SQLEXCEPTION
+SELECT 'error caught (unexpected)';
+SELECT 5 / 0;
+END|
+CALL p1();
+5 / 0
+NULL
+warning caught (expected)
+warning caught (expected)
+SHOW WARNINGS;
+Level	Code	Message
+CALL p2();
+5 / 0
+NULL
+Warnings:
+Warning	1365	Division by 0
+SHOW WARNINGS;
+Level	Code	Message
+Warning	1365	Division by 0
+DROP PROCEDURE p1;
+DROP PROCEDURE p2;
+SET sql_mode = @sql_mode_saved;
+#
+# Bug#55850: Trigger warnings not cleared.
+#
+DROP TABLE IF EXISTS t1;
+DROP TABLE IF EXISTS t2;
+DROP PROCEDURE IF EXISTS p1;
+CREATE TABLE t1(x SMALLINT, y SMALLINT, z SMALLINT);
+CREATE TABLE t2(a SMALLINT, b SMALLINT, c SMALLINT,
+d SMALLINT, e SMALLINT, f SMALLINT);
+CREATE TRIGGER t1_bi BEFORE INSERT ON t1 FOR EACH ROW
+INSERT IGNORE INTO t2(a, b, c) VALUES(99999, 99999, 99999);
+CREATE TRIGGER t1_ai AFTER INSERT ON t1 FOR EACH ROW
+INSERT IGNORE INTO t2(d, e, f) VALUES(99999, 99999, 99999);
+CREATE PROCEDURE p1()
+INSERT IGNORE INTO t1 VALUES(99999, 99999, 99999);
+
+CALL p1();
+Warnings:
+Warning	1264	Out of range value for column 'x' at row 1
+Warning	1264	Out of range value for column 'y' at row 1
+Warning	1264	Out of range value for column 'z' at row 1
+
+SHOW WARNINGS;
+Level	Code	Message
+Warning	1264	Out of range value for column 'x' at row 1
+Warning	1264	Out of range value for column 'y' at row 1
+Warning	1264	Out of range value for column 'z' at row 1
+
+DROP TABLE t1;
+DROP TABLE t2;
+DROP PROCEDURE p1;
+# ----------------------------------------------------------------------
+SET sql_mode = 'NO_ENGINE_SUBSTITUTION';
+CREATE TABLE t1(x SMALLINT, y SMALLINT, z SMALLINT);
+CREATE TABLE t2(a SMALLINT, b SMALLINT, c SMALLINT NOT NULL);
+CREATE TRIGGER t1_bi BEFORE INSERT ON t1 FOR EACH ROW
+BEGIN
+INSERT INTO t2 VALUES(
+CAST('111111 ' AS SIGNED),
+CAST('222222 ' AS SIGNED),
+NULL);
+END|
+CREATE PROCEDURE p1()
+INSERT INTO t1 VALUES(99999, 99999, 99999);
+
+CALL p1();
+ERROR 23000: Column 'c' cannot be null
+
+SHOW WARNINGS;
+Level	Code	Message
+Warning	1264	Out of range value for column 'x' at row 1
+Warning	1264	Out of range value for column 'y' at row 1
+Warning	1264	Out of range value for column 'z' at row 1
+Note	1292	Truncated incorrect INTEGER value: '111111 '
+Warning	1264	Out of range value for column 'a' at row 1
+Note	1292	Truncated incorrect INTEGER value: '222222 '
+Warning	1264	Out of range value for column 'b' at row 1
+Error	1048	Column 'c' cannot be null
+Note	4092	At line 6 in test.t1_bi
+Note	4092	At line 2 in test.p1
+
+DROP TABLE t1;
+DROP TABLE t2;
+DROP PROCEDURE p1;
+SET sql_mode = DEFAULT;
+
+###################################################################
+# Tests for the following bugs:
+#   - Bug#11763171: 55852 - Possibly inappropriate handler activation.
+#   - Bug#11749343: 38806 - Wrong scope for SQL HANDLERS in SP.
+###################################################################
+
+
+# -- Check that SQL-conditions thrown by Statement-blocks are
+# -- handled by Handler-decl blocks properly.
+
+CREATE PROCEDURE p1()
+BEGIN
+DECLARE CONTINUE HANDLER FOR SQLEXCEPTION
+SELECT 'H1' AS HandlerId;
+DECLARE CONTINUE HANDLER FOR SQLWARNING
+SELECT 'H2' AS HandlerId;
+SIGNAL SQLSTATE '01000'; # Should be handled by H2.
+END|
+
+CALL p1()|
+HandlerId
+H2
+
+# -- Check that SQL-conditions thrown by Statement-blocks are
+# -- handled by Handler-decl blocks properly in case of nested
+# -- SQL-blocks.
+
+CREATE PROCEDURE p2()
+BEGIN
+DECLARE CONTINUE HANDLER FOR SQLEXCEPTION
+SELECT 'H1' AS HandlerId;
+DECLARE CONTINUE HANDLER FOR SQLWARNING
+SELECT 'H2' AS HandlerId;
+BEGIN
+SELECT 'B1' AS BlockId;
+BEGIN
+SELECT 'B2' AS BlockId;
+BEGIN
+SELECT 'B3' AS BlockId;
+SIGNAL SQLSTATE '01000'; # Should be handled by H2.
+END;
+END;
+END;
+END|
+
+CALL p2()|
+BlockId
+B1
+BlockId
+B2
+BlockId
+B3
+HandlerId
+H2
+
+# -- Check SQL-handler resolution rules.
+
+CREATE PROCEDURE p3()
+BEGIN
+DECLARE CONTINUE HANDLER FOR SQLEXCEPTION
+SELECT 'H1' AS HandlerId;
+DECLARE CONTINUE HANDLER FOR SQLWARNING
+SELECT 'H2' AS HandlerId;
+DECLARE CONTINUE HANDLER FOR SQLSTATE '01000'
+    SELECT 'H3' AS HandlerId;
+SIGNAL SQLSTATE '01000'; # Should be handled by H3.
+END|
+
+CALL p3()|
+HandlerId
+H3
+
+CREATE PROCEDURE p4()
+BEGIN
+DECLARE CONTINUE HANDLER FOR SQLEXCEPTION
+SELECT 'H1' AS HandlerId;
+DECLARE CONTINUE HANDLER FOR SQLSTATE '01000'
+    SELECT 'H2' AS HandlerId;
+DECLARE CONTINUE HANDLER FOR SQLWARNING
+SELECT 'H3' AS HandlerId;
+SIGNAL SQLSTATE '01000'; # Should be handled by H2.
+END|
+
+CALL p4()|
+HandlerId
+H2
+
+CREATE PROCEDURE p5()
+BEGIN
+DECLARE CONTINUE HANDLER FOR SQLEXCEPTION
+SELECT 'H1' AS HandlerId;
+DECLARE CONTINUE HANDLER FOR SQLSTATE '01000'
+    SELECT 'H2' AS HandlerId;
+BEGIN
+DECLARE CONTINUE HANDLER FOR SQLWARNING
+SELECT 'H3' AS HandlerId;
+SIGNAL SQLSTATE '01000'; # Should be handled by H3.
+END;
+END|
+
+CALL p5()|
+HandlerId
+H3
+
+# -- Check that handlers don't handle its own exceptions.
+
+CREATE PROCEDURE p6()
+BEGIN
+DECLARE CONTINUE HANDLER FOR SQLEXCEPTION
+BEGIN
+SELECT 'H1' AS HandlerId;
+SIGNAL SQLSTATE 'HY000'; # Should *not* be handled by H1.
+END;
+SELECT 'S1' AS SignalId;
+SIGNAL SQLSTATE 'HY000'; # Should be handled by H1.
+END|
+
+CALL p6()|
+SignalId
+S1
+HandlerId
+H1
+ERROR HY000: Unhandled user-defined exception condition
+
+# -- Check that handlers don't handle its own warnings.
+
+CREATE PROCEDURE p7()
+BEGIN
+DECLARE CONTINUE HANDLER FOR SQLWARNING
+BEGIN
+SELECT 'H1' AS HandlerId;
+SIGNAL SQLSTATE '01000'; # Should *not* be handled by H1.
+END;
+SELECT 'S1' AS SignalId;
+SIGNAL SQLSTATE '01000'; # Should be handled by H1.
+END|
+
+CALL p7()|
+SignalId
+S1
+HandlerId
+H1
+Warnings:
+Warning	1642	Unhandled user-defined warning condition
+
+# -- Check that conditions for handlers are not handled by the handlers
+# -- from the same block.
+
+CREATE PROCEDURE p8()
+BEGIN
+DECLARE CONTINUE HANDLER FOR SQLWARNING
+SELECT 'H1' AS HandlerId;
+DECLARE CONTINUE HANDLER FOR SQLEXCEPTION
+BEGIN
+SELECT 'H2' AS HandlerId;
+SIGNAL SQLSTATE '01000'; # Should *not* be handled by H1.
+END;
+SELECT 'S1' AS SignalId;
+SIGNAL SQLSTATE 'HY000'; # Should be handled by H2.
+END|
+
+CALL p8()|
+SignalId
+S1
+HandlerId
+H2
+Warnings:
+Warning	1642	Unhandled user-defined warning condition
+
+# -- Check that conditions for handlers are not handled by the handlers
+# -- from the same block even if they are thrown deep down the stack.
+
+CREATE PROCEDURE p9()
+BEGIN
+DECLARE CONTINUE HANDLER FOR SQLSTATE '01000'
+    SELECT 'Wrong:H1:1' AS HandlerId;
+DECLARE CONTINUE HANDLER FOR SQLWARNING
+SELECT 'Wrong:H1:2' AS HandlerId;
+DECLARE CONTINUE HANDLER FOR SQLEXCEPTION
+BEGIN
+DECLARE CONTINUE HANDLER FOR SQLSTATE '01000'
+      SELECT 'Wrong:H2:1' AS HandlerId;
+DECLARE CONTINUE HANDLER FOR SQLWARNING
+SELECT 'Wrong:H2:2' AS HandlerId;
+DECLARE CONTINUE HANDLER FOR SQLEXCEPTION
+BEGIN
+DECLARE CONTINUE HANDLER FOR SQLSTATE '01000'
+        SELECT 'Wrong:H3:1' AS HandlerId;
+DECLARE CONTINUE HANDLER FOR SQLWARNING
+SELECT 'Wrong:H3:2' AS HandlerId;
+DECLARE CONTINUE HANDLER FOR SQLEXCEPTION
+BEGIN
+DECLARE CONTINUE HANDLER FOR SQLSTATE '01000'
+          SELECT 'Wrong:H4:1' AS HandlerId;
+DECLARE CONTINUE HANDLER FOR SQLWARNING
+SELECT 'Wrong:H4:2' AS HandlerId;
+DECLARE CONTINUE HANDLER FOR SQLEXCEPTION
+BEGIN
+DECLARE CONTINUE HANDLER FOR SQLSTATE '01000'
+            SELECT 'Wrong:H5:1' AS HandlerId;
+DECLARE CONTINUE HANDLER FOR SQLWARNING
+SELECT 'Wrong:H5:2' AS HandlerId;
+DECLARE CONTINUE HANDLER FOR SQLEXCEPTION
+BEGIN
+DECLARE CONTINUE HANDLER FOR SQLSTATE '01000'
+              SELECT 'Wrong:H6:1' AS HandlerId;
+DECLARE CONTINUE HANDLER FOR SQLWARNING
+SELECT 'Wrong:H6:2' AS HandlerId;
+DECLARE CONTINUE HANDLER FOR SQLEXCEPTION
+BEGIN
+SELECT 'H2' AS HandlerId;
+SIGNAL SQLSTATE '01000'; # Should *not* be handled by H1.
+END;
+SELECT 'S6' AS SignalId;
+SIGNAL SQLSTATE 'HY000';
+END;
+SELECT 'S5' AS SignalId;
+SIGNAL SQLSTATE 'HY000';
+END;
+SELECT 'S4' AS SignalId;
+SIGNAL SQLSTATE 'HY000';
+END;
+SELECT 'S3' AS SignalId;
+SIGNAL SQLSTATE 'HY000';
+END;
+SELECT 'S2' AS SignalId;
+SIGNAL SQLSTATE 'HY000';
+END;
+SELECT 'S1' AS SignalId;
+SIGNAL SQLSTATE 'HY000'; # Should be handled by H2.
+END|
+
+CALL p9()|
+SignalId
+S1
+SignalId
+S2
+SignalId
+S3
+SignalId
+S4
+SignalId
+S5
+SignalId
+S6
+HandlerId
+H2
+Warnings:
+Warning	1642	Unhandled user-defined warning condition
+
+# -- Check that handlers are choosen properly in case of deep stack and
+# -- nested SQL-blocks.
+
+CREATE PROCEDURE p10()
+BEGIN
+DECLARE CONTINUE HANDLER FOR SQLSTATE '01000'
+    SELECT 'H1' AS HandlerId;
+DECLARE CONTINUE HANDLER FOR SQLWARNING
+SELECT 'H2' AS HandlerId;
+BEGIN
+BEGIN
+BEGIN
+DECLARE CONTINUE HANDLER FOR SQLSTATE '01000'
+          SELECT 'Wrong:H1:1' AS HandlerId;
+DECLARE CONTINUE HANDLER FOR SQLWARNING
+SELECT 'Wrong:H1:2' AS HandlerId;
+DECLARE CONTINUE HANDLER FOR SQLEXCEPTION
+BEGIN
+DECLARE CONTINUE HANDLER FOR SQLSTATE '01000'
+            SELECT 'Wrong:H2:1' AS HandlerId;
+DECLARE CONTINUE HANDLER FOR SQLWARNING
+SELECT 'Wrong:H2:2' AS HandlerId;
+DECLARE CONTINUE HANDLER FOR SQLEXCEPTION
+BEGIN
+DECLARE CONTINUE HANDLER FOR SQLSTATE '01000'
+              SELECT 'Wrong:H3:1' AS HandlerId;
+DECLARE CONTINUE HANDLER FOR SQLWARNING
+SELECT 'Wrong:H3:2' AS HandlerId;
+DECLARE CONTINUE HANDLER FOR SQLEXCEPTION
+BEGIN
+DECLARE CONTINUE HANDLER FOR SQLSTATE '01000'
+                SELECT 'Wrong:H4:1' AS HandlerId;
+DECLARE CONTINUE HANDLER FOR SQLWARNING
+SELECT 'Wrong:H4:2' AS HandlerId;
+DECLARE CONTINUE HANDLER FOR SQLEXCEPTION
+BEGIN
+DECLARE CONTINUE HANDLER FOR SQLSTATE '01000'
+                  SELECT 'Wrong:H5:1' AS HandlerId;
+DECLARE CONTINUE HANDLER FOR SQLWARNING
+SELECT 'Wrong:H5:2' AS HandlerId;
+DECLARE CONTINUE HANDLER FOR SQLEXCEPTION
+BEGIN
+DECLARE CONTINUE HANDLER FOR SQLSTATE '01000'
+                    SELECT 'Wrong:H6:1' AS HandlerId;
+DECLARE CONTINUE HANDLER FOR SQLWARNING
+SELECT 'Wrong:H6:2' AS HandlerId;
+DECLARE CONTINUE HANDLER FOR SQLEXCEPTION
+BEGIN
+SELECT 'H2' AS HandlerId;
+SIGNAL SQLSTATE '01000'; # Should be handled by H1.
+END;
+SELECT 'S6' AS SignalId;
+SIGNAL SQLSTATE 'HY000';
+END;
+SELECT 'S5' AS SignalId;
+SIGNAL SQLSTATE 'HY000';
+END;
+SELECT 'S4' AS SignalId;
+SIGNAL SQLSTATE 'HY000';
+END;
+SELECT 'S3' AS SignalId;
+SIGNAL SQLSTATE 'HY000';
+END;
+SELECT 'S2' AS SignalId;
+SIGNAL SQLSTATE 'HY000';
+END;
+SELECT 'S1' AS SignalId;
+SIGNAL SQLSTATE 'HY000'; # Should be handled by H2.
+END;
+END;
+END;
+END|
+
+CALL p10()|
+SignalId
+S1
+SignalId
+S2
+SignalId
+S3
+SignalId
+S4
+SignalId
+S5
+SignalId
+S6
+HandlerId
+H2
+HandlerId
+H1
+
+# -- Test stored procedure from Peter's mail.
+
+CREATE PROCEDURE p11()
+BEGIN
+DECLARE CONTINUE HANDLER FOR SQLEXCEPTION
+SELECT 'H1' AS HandlerId;
+DECLARE CONTINUE HANDLER FOR SQLWARNING
+SELECT 'H2' AS HandlerId;
+BEGIN
+DECLARE CONTINUE HANDLER FOR SQLSTATE '01000', 1249
+BEGIN
+DECLARE CONTINUE HANDLER FOR SQLEXCEPTION
+SELECT 'H3' AS HandlerId;
+DECLARE CONTINUE HANDLER FOR SQLWARNING
+SELECT 'H4' AS HandlerId;
+BEGIN
+SELECT 'H5' AS HandlerId;
+SELECT 'S3' AS SignalId;
+SIGNAL SQLSTATE 'HY000'; # H3
+SELECT 'S4' AS SignalId;
+SIGNAL SQLSTATE '22003'; # H3
+SELECT 'S5' AS SignalId;
+SIGNAL SQLSTATE '01000' SET MYSQL_ERRNO = 1249; # H4
+END;
+END;
+SELECT 'S6' AS SignalId;
+SIGNAL SQLSTATE 'HY000'; # H1
+SELECT 'S7' AS SignalId;
+SIGNAL SQLSTATE '22003'; # H1
+SELECT 'S8' AS SignalId;
+SIGNAL SQLSTATE '01000' SET MYSQL_ERRNO = 1249; # H5
+END;
+SELECT 'S1' AS SignalId;
+SIGNAL SQLSTATE 'HY000'; # H1
+SELECT 'S2' AS SignalId;
+SIGNAL SQLSTATE '01000' SET MYSQL_ERRNO = 1249; # H2
+END|
+
+CALL p11()|
+SignalId
+S6
+HandlerId
+H1
+SignalId
+S7
+HandlerId
+H1
+SignalId
+S8
+HandlerId
+H5
+SignalId
+S3
+HandlerId
+H3
+SignalId
+S4
+HandlerId
+H3
+SignalId
+S5
+HandlerId
+H4
+SignalId
+S1
+HandlerId
+H1
+SignalId
+S2
+HandlerId
+H2
+
+# -- Check that runtime stack-trace can be deeper than parsing-time one.
+
+CREATE PROCEDURE p12()
+BEGIN
+DECLARE CONTINUE HANDLER FOR SQLSTATE '01001'
+  BEGIN
+DECLARE CONTINUE HANDLER FOR SQLSTATE '01001'
+    BEGIN
+DECLARE CONTINUE HANDLER FOR SQLSTATE '01001'
+      BEGIN
+DECLARE CONTINUE HANDLER FOR SQLSTATE '01001'
+        BEGIN
+DECLARE CONTINUE HANDLER FOR SQLSTATE '01001'
+          BEGIN
+SELECT 'H1:5' AS HandlerId;
+SIGNAL SQLSTATE '01002';
+END;
+SELECT 'H1:4' AS HandlerId;
+SIGNAL SQLSTATE '01001';
+END;
+SELECT 'H1:3' AS HandlerId;
+SIGNAL SQLSTATE '01001';
+END;
+SELECT 'H1:2' AS HandlerId;
+SIGNAL SQLSTATE '01001';
+END;
+SELECT 'H1:1' AS HandlerId;
+SIGNAL SQLSTATE '01001';
+END;
+#########################################################
+DECLARE CONTINUE HANDLER FOR SQLSTATE '01002'
+    SELECT 'OK' AS Msg;
+#########################################################
+BEGIN
+DECLARE CONTINUE HANDLER FOR SQLWARNING
+BEGIN
+DECLARE CONTINUE HANDLER FOR SQLWARNING
+BEGIN
+DECLARE CONTINUE HANDLER FOR SQLWARNING
+BEGIN
+DECLARE CONTINUE HANDLER FOR SQLWARNING
+BEGIN
+DECLARE CONTINUE HANDLER FOR SQLWARNING
+BEGIN
+SELECT 'H2:5' AS HandlerId;
+SIGNAL SQLSTATE '01001';
+END;
+SELECT 'H2:4' AS HandlerId;
+SIGNAL SQLSTATE '01000';
+END;
+SELECT 'H2:3' AS HandlerId;
+SIGNAL SQLSTATE '01000';
+END;
+SELECT 'H2:2' AS HandlerId;
+SIGNAL SQLSTATE '01000';
+END;
+SELECT 'H2:1' AS HandlerId;
+SIGNAL SQLSTATE '01000';
+END;
+#######################################################
+SELECT 'Throw 01000' AS Msg;
+SIGNAL SQLSTATE '01000';
+END;
+END|
+
+CALL p12()|
+Msg
+Throw 01000
+HandlerId
+H2:1
+HandlerId
+H2:2
+HandlerId
+H2:3
+HandlerId
+H2:4
+HandlerId
+H2:5
+HandlerId
+H1:1
+HandlerId
+H1:2
+HandlerId
+H1:3
+HandlerId
+H1:4
+HandlerId
+H1:5
+Warnings:
+Warning	1642	Unhandled user-defined warning condition
+
+# -- Check that handler-call-frames are removed properly for EXIT
+# -- handlers.
+
+CREATE PROCEDURE p13()
+BEGIN
+DECLARE CONTINUE HANDLER FOR SQLWARNING
+BEGIN
+DECLARE CONTINUE HANDLER FOR SQLWARNING
+BEGIN
+DECLARE EXIT HANDLER FOR SQLWARNING
+BEGIN
+SELECT 'EXIT handler 3' AS Msg;
+END;
+SELECT 'CONTINUE handler 2: 1' AS Msg;
+SIGNAL SQLSTATE '01000';
+SELECT 'CONTINUE handler 2: 2' AS Msg;
+END;
+SELECT 'CONTINUE handler 1: 1' AS Msg;
+SIGNAL SQLSTATE '01000';
+SELECT 'CONTINUE handler 1: 2' AS Msg;
+END;
+SELECT 'Throw 01000' AS Msg;
+SIGNAL SQLSTATE '01000';
+END|
+
+CALL p13()|
+Msg
+Throw 01000
+Msg
+CONTINUE handler 1: 1
+Msg
+CONTINUE handler 2: 1
+Msg
+EXIT handler 3
+Msg
+CONTINUE handler 1: 2
+
+# That's it. Cleanup.
+
+DROP PROCEDURE p1;
+DROP PROCEDURE p2;
+DROP PROCEDURE p3;
+DROP PROCEDURE p4;
+DROP PROCEDURE p5;
+DROP PROCEDURE p6;
+DROP PROCEDURE p7;
+DROP PROCEDURE p8;
+DROP PROCEDURE p9;
+DROP PROCEDURE p10;
+DROP PROCEDURE p11;
+DROP PROCEDURE p12;
+DROP PROCEDURE p13;
+
+# Bug#12731619: NESTED SP HANDLERS CAN TRIGGER ASSERTION
+
+DROP FUNCTION IF EXISTS f1;
+DROP TABLE IF EXISTS t1;
+CREATE TABLE t1(msg VARCHAR(255));
+CREATE FUNCTION f1() RETURNS INT
+BEGIN
+DECLARE CONTINUE HANDLER FOR SQLEXCEPTION               # handler 1
+BEGIN
+DECLARE CONTINUE HANDLER FOR SQLEXCEPTION             # handler 2
+BEGIN
+INSERT INTO t1 VALUE('WRONG: Inside H2');
+RETURN 2;
+END;
+INSERT INTO t1 VALUE('CORRECT: Inside H1');
+RETURN 1;
+END;
+BEGIN
+DECLARE CONTINUE HANDLER FOR SQLWARNING               # handler 3
+BEGIN
+INSERT INTO t1 VALUE('WRONG: Inside H3');
+RETURN 3;
+END;
+INSERT INTO t1 VALUE('CORRECT: Calling f1()');
+RETURN f1(); # -- exception here
+END;
+INSERT INTO t1 VALUE('WRONG: Returning 10');
+RETURN 10;
+END|
+
+SELECT f1();
+f1()
+1
+
+SELECT * FROM t1;
+msg
+CORRECT: Calling f1()
+CORRECT: Inside H1
+
+DROP FUNCTION f1;
+DROP TABLE t1;
+
+# Check that handled SQL-conditions are properly cleared from DA.
+
+DROP TABLE IF EXISTS t1;
+DROP TABLE IF EXISTS t2;
+DROP PROCEDURE IF EXISTS p1;
+DROP PROCEDURE IF EXISTS p2;
+DROP PROCEDURE IF EXISTS p3;
+DROP PROCEDURE IF EXISTS p4;
+DROP PROCEDURE IF EXISTS p5;
+CREATE TABLE t1(a CHAR, b CHAR, c CHAR);
+CREATE TABLE t2(a SMALLINT, b SMALLINT, c SMALLINT);
+
+# Check that SQL-conditions for which SQL-handler has been invoked,
+# are cleared from the Diagnostics Area. Note, there might be several
+# SQL-conditions, but SQL-handler must be invoked only once.
+
+CREATE PROCEDURE p1()
+BEGIN
+DECLARE EXIT HANDLER FOR SQLWARNING
+SELECT 'Warning caught' AS msg;
+# The INSERT below raises 3 SQL-conditions (warnings). The EXIT HANDLER
+# above must be invoked once (for one condition), but all three conditions
+# must be cleared from the Diagnostics Area.
+INSERT IGNORE INTO t1 VALUES('qqqq', 'ww', 'eee');
+# The following INSERT will not be executed, because of the EXIT HANDLER.
+INSERT INTO t1 VALUES('zzz', 'xx', 'yyyy');
+END|
+
+CALL p1()|
+msg
+Warning caught
+
+SELECT * FROM t1|
+a	b	c
+q	w	e
+
+# Check that SQL-conditions for which SQL-handler has *not* been
+# invoked, are *still* cleared from the Diagnostics Area.
+
+CREATE PROCEDURE p2()
+BEGIN
+DECLARE CONTINUE HANDLER FOR 1292
+SELECT 'Warning 1292 caught' AS msg;
+# The following INSERT raises 6 SQL-warnings with code 1292,
+# and 3 SQL-warnings with code 1264. The CONTINUE HANDLER above must be
+# invoked once, and all nine SQL-warnings must be cleared from
+# the Diagnostics Area.
+INSERT IGNORE INTO t2
+SELECT
+CAST(CONCAT(CAST('1 ' AS UNSIGNED INTEGER), '999999  ') AS SIGNED INTEGER),
+CAST(CONCAT(CAST('2 ' AS UNSIGNED INTEGER), '999999  ') AS SIGNED INTEGER),
+CAST(CONCAT(CAST('3 ' AS UNSIGNED INTEGER), '999999  ') AS SIGNED INTEGER);
+END|
+
+CALL p2()|
+msg
+Warning 1292 caught
+
+# Check that if there are two equally ranked SQL-handlers to handle
+# SQL-conditions from SQL-statement, only one of them will be invoked.
+
+CREATE PROCEDURE p3()
+BEGIN
+DECLARE CONTINUE HANDLER FOR 1292
+SELECT 'Warning 1292 caught' AS msg;
+DECLARE CONTINUE HANDLER FOR 1264
+SELECT 'Warning 1264 caught' AS msg;
+# The following INSERT raises 6 SQL-warnings with code 1292,
+# and 3 SQL-warnings with code 1264. Only one of the CONTINUE HANDLERs above
+# must be called, and only once. The SQL Standard does not define, which one
+# should be invoked.
+INSERT INTO t2
+SELECT
+CAST(CONCAT(CAST('1 ' AS UNSIGNED INTEGER), '999999  ') AS SIGNED INTEGER),
+CAST(CONCAT(CAST('2 ' AS UNSIGNED INTEGER), '999999  ') AS SIGNED INTEGER),
+CAST(CONCAT(CAST('3 ' AS UNSIGNED INTEGER), '999999  ') AS SIGNED INTEGER);
+END|
+
+CALL p3()|
+msg
+Warning 1264 caught
+
+# The same as p3, but 1264 comes first.
+
+CREATE PROCEDURE p4()
+BEGIN
+DECLARE CONTINUE HANDLER FOR 1292
+SELECT 'Warning 1292 caught' AS msg;
+DECLARE CONTINUE HANDLER FOR 1264
+SELECT 'Warning 1264 caught' AS msg;
+# The following INSERT raises 4 SQL-warnings with code 1292,
+# and 3 SQL-warnings with code 1264. Only one of the CONTINUE HANDLERs above
+# must be called, and only once. The SQL Standard does not define, which one
+# should be invoked.
+INSERT INTO t2
+SELECT
+CAST(999999 AS SIGNED INTEGER),
+CAST(CONCAT(CAST('2 ' AS UNSIGNED INTEGER), '999999  ') AS SIGNED INTEGER),
+CAST(CONCAT(CAST('3 ' AS UNSIGNED INTEGER), '999999  ') AS SIGNED INTEGER);
+END|
+
+CALL p4()|
+msg
+Warning 1264 caught
+
+# Check that if a SQL-handler raised its own SQL-conditions, there are
+# preserved after handler exit.
+
+CREATE PROCEDURE p5()
+BEGIN
+DECLARE EXIT HANDLER FOR 1292
+BEGIN
+SELECT 'Handler for 1292 (1)' AS Msg;
+SIGNAL SQLSTATE '01000' SET MYSQL_ERRNO = 1234;
+SHOW WARNINGS;
+SELECT 'Handler for 1292 (2)' AS Msg;
+END;
+INSERT IGNORE INTO t2
+SELECT
+CAST(999999 AS SIGNED INTEGER),
+CAST(CONCAT(CAST('2 ' AS UNSIGNED INTEGER), '999999  ') AS SIGNED INTEGER),
+CAST(CONCAT(CAST('3 ' AS UNSIGNED INTEGER), '999999  ') AS SIGNED INTEGER);
+END|
+
+CALL p5()|
+Msg
+Handler for 1292 (1)
+Level	Code	Message
+Warning	1234	Unhandled user-defined warning condition
+Msg
+Handler for 1292 (2)
+Warnings:
+Warning	1234	Unhandled user-defined warning condition
+
+# Check that SQL-conditions are available inside the handler, but
+# cleared after the handler exits.
+
+CREATE PROCEDURE p6()
+BEGIN
+DECLARE CONTINUE HANDLER FOR 1292
+BEGIN
+SHOW WARNINGS;
+SELECT 'Handler for 1292' Msg;
+END;
+INSERT IGNORE INTO t2
+SELECT
+CAST(CONCAT(CAST('1 ' AS UNSIGNED INTEGER), '999999  ') AS SIGNED INTEGER),
+CAST(CONCAT(CAST('2 ' AS UNSIGNED INTEGER), '999999  ') AS SIGNED INTEGER),
+CAST(CONCAT(CAST('3 ' AS UNSIGNED INTEGER), '999999  ') AS SIGNED INTEGER);
+END|
+
+CALL p6()|
+Level	Code	Message
+Note	1292	Truncated incorrect INTEGER value: '1 '
+Note	1292	Truncated incorrect INTEGER value: '1999999  '
+Warning	1264	Out of range value for column 'a' at row 1
+Note	1292	Truncated incorrect INTEGER value: '2 '
+Note	1292	Truncated incorrect INTEGER value: '2999999  '
+Warning	1264	Out of range value for column 'b' at row 1
+Note	1292	Truncated incorrect INTEGER value: '3 '
+Note	1292	Truncated incorrect INTEGER value: '3999999  '
+Warning	1264	Out of range value for column 'c' at row 1
+Msg
+Handler for 1292
+
+DROP PROCEDURE p1;
+DROP PROCEDURE p2;
+DROP PROCEDURE p3;
+DROP PROCEDURE p4;
+DROP PROCEDURE p5;
+DROP PROCEDURE p6;
+DROP TABLE t1;
+DROP TABLE t2;
+
+# Bug#13059316: ASSERTION FAILURE IN SP_RCONTEXT.CC 
+# Check DECLARE statements that raise conditions before handlers
+# are declared.
+
+DROP PROCEDURE IF EXISTS p1;
+DROP PROCEDURE IF EXISTS p2;
+SET sql_mode = '';
+CREATE PROCEDURE p1()
+BEGIN
+DECLARE var1 INTEGER DEFAULT 'string';
+DECLARE EXIT HANDLER FOR SQLWARNING SELECT 'H1';
+END|
+
+CALL p1()|
+Warnings:
+Warning	1366	Incorrect integer value: 'string' for column 'var1' at row 1
+
+SET sql_mode = DEFAULT;
+CREATE PROCEDURE p2()
+BEGIN
+DECLARE EXIT HANDLER FOR SQLWARNING SELECT 'H2';
+CALL p1();
+END|
+
+CALL p2()|
+H2
+H2
+
+DROP PROCEDURE p1;
+DROP PROCEDURE p2;
+#
+# Bug#13113222 RQG_SIGNAL_RESIGNAL FAILED WITH ASSERTION.
+#
+DROP PROCEDURE IF EXISTS p1;
+DROP PROCEDURE IF EXISTS p2;
+CREATE PROCEDURE p1()
+BEGIN
+DECLARE CONTINUE HANDLER FOR SQLEXCEPTION SELECT 'triggered p1';
+# This will trigger an error.
+SIGNAL SQLSTATE 'HY000';
+END|
+CREATE PROCEDURE p2()
+BEGIN
+DECLARE CONTINUE HANDLER FOR SQLWARNING SELECT 'triggered p2';
+# This will trigger a warning.
+SIGNAL SQLSTATE '01000';
+END|
+SET @old_max_error_count=  @@session.max_error_count;
+SET SESSION max_error_count= 0;
+CALL p1();
+triggered p1
+triggered p1
+CALL p2();
+SET SESSION max_error_count= @old_max_error_count;
+DROP PROCEDURE p1;
+DROP PROCEDURE p2;
+
+# Bug#12652873: 61392: Continue handler for NOT FOUND being triggered
+# from internal stored function.
+
+DROP FUNCTION IF EXISTS f1;
+DROP FUNCTION IF EXISTS f2;
+DROP TABLE IF EXISTS t1;
+
+CREATE TABLE t1 (a INT, b INT);
+INSERT INTO t1 VALUES (1, 2);
+
+# f1() raises NOT_FOUND condition.
+# Raising NOT_FOUND can not be simulated by SIGNAL,
+# because SIGNAL would raise SQL-error in that case.
+
+CREATE FUNCTION f1() RETURNS INTEGER
+BEGIN
+DECLARE v VARCHAR(5) DEFAULT -1;
+SELECT b FROM t1 WHERE a = 2 INTO v;
+RETURN v;
+END|
+
+# Here we check that the NOT_FOUND condition raised in f1()
+# is not visible in the outer function (f2), i.e. the continue
+# handler in f2() will not be called.
+
+CREATE FUNCTION f2() RETURNS INTEGER
+BEGIN
+DECLARE v INTEGER;
+DECLARE CONTINUE HANDLER FOR NOT FOUND
+SET @msg = 'Handler activated.';
+SELECT f1() INTO v;
+RETURN v;
+END|
+SET @msg = '';
+
+SELECT f2();
+f2()
+-1
+
+SELECT @msg;
+ at msg
+
+
+DROP FUNCTION f1;
+DROP FUNCTION f2;
+DROP TABLE t1;
diff --git a/mysql-test/suite/compat/oracle/r/func_pad.result b/mysql-test/suite/compat/oracle/r/func_pad.result
new file mode 100644
index 00000000000..ca7d52cd542
--- /dev/null
+++ b/mysql-test/suite/compat/oracle/r/func_pad.result
@@ -0,0 +1,71 @@
+SET sql_mode=ORACLE;
+#
+# MDEV-15739 -  sql_mode=ORACLE: Make LPAD and RPAD return NULL instead of empty string
+#
+SELECT RPAD('a',0), RPAD('abc',1), RPAD('abc',2) ;
+RPAD('a',0)	RPAD('abc',1)	RPAD('abc',2)
+NULL	a	ab
+SELECT RPAD('a',0,'.'), RPAD('abc',1,'.'), RPAD('abc',2,'.') ;
+RPAD('a',0,'.')	RPAD('abc',1,'.')	RPAD('abc',2,'.')
+NULL	a	ab
+SELECT LPAD('a',0), LPAD('abc',1), LPAD('abc',2) ;
+LPAD('a',0)	LPAD('abc',1)	LPAD('abc',2)
+NULL	a	ab
+SELECT LPAD('a',0,'.'), LPAD('abc',1,'.'), LPAD('abc',2,'.') ;
+LPAD('a',0,'.')	LPAD('abc',1,'.')	LPAD('abc',2,'.')
+NULL	a	ab
+CREATE TABLE t1 (c1 VARCHAR(10),c2 INTEGER, c3 VARCHAR(10), ord INTEGER);
+INSERT INTO t1 VALUES ('a',1,null,1);
+INSERT INTO t1 VALUES ('a',null,'.',2);
+INSERT INTO t1 VALUES (null,1,'.',3);
+INSERT INTO t1 VALUES ('a',-1,'.',4);
+INSERT INTO t1 VALUES ('a',0,'.',5);
+INSERT INTO t1 VALUES ('a',1,'.',6);
+INSERT INTO t1 VALUES ('a',2,'.',7);
+SELECT LPAD(c1,c2,c3), LPAD(c1,c2) FROM t1 ORDER BY ord;
+LPAD(c1,c2,c3)	LPAD(c1,c2)
+NULL	a
+NULL	NULL
+NULL	NULL
+NULL	NULL
+NULL	NULL
+a	a
+.a	 a
+SELECT RPAD(c1,c2,c3), RPAD(c1,c2) FROM t1 ORDER BY ord;
+RPAD(c1,c2,c3)	RPAD(c1,c2)
+NULL	a
+NULL	NULL
+NULL	NULL
+NULL	NULL
+NULL	NULL
+a	a
+a.	a 
+EXPLAIN EXTENDED SELECT RPAD('a',0,'.'), LPAD('a',0,'.'), LPAD(c1,c2,c3), LPAD(c1,c2), RPAD(c1,c2,c3), RPAD(c1,c2) FROM t1 ORDER BY ord;
+id	select_type	table	type	possible_keys	key	key_len	ref	rows	filtered	Extra
+1	SIMPLE	t1	ALL	NULL	NULL	NULL	NULL	7	100.00	Using filesort
+Warnings:
+Note	1003	select rpad_oracle('a',0,'.') AS "RPAD('a',0,'.')",lpad_oracle('a',0,'.') AS "LPAD('a',0,'.')",lpad_oracle("test"."t1"."c1","test"."t1"."c2","test"."t1"."c3") AS "LPAD(c1,c2,c3)",lpad_oracle("test"."t1"."c1","test"."t1"."c2") AS "LPAD(c1,c2)",rpad_oracle("test"."t1"."c1","test"."t1"."c2","test"."t1"."c3") AS "RPAD(c1,c2,c3)",rpad_oracle("test"."t1"."c1","test"."t1"."c2") AS "RPAD(c1,c2)" from "test"."t1" order by "test"."t1"."ord"
+CREATE VIEW v1 AS SELECT RPAD('a',0,'.') AS "C1", LPAD('a',0,'.') AS "C2", LPAD(c1,c2,c3) AS "C3", LPAD(c1,c2) AS "C4", RPAD(c1,c2,c3) AS "C5", RPAD(c1,c2) AS "C6" FROM t1 ORDER BY ord;
+SHOW CREATE VIEW v1;
+View	Create View	character_set_client	collation_connection
+v1	CREATE VIEW "v1" AS select rpad_oracle('a',0,'.') AS "C1",lpad_oracle('a',0,'.') AS "C2",lpad_oracle("t1"."c1","t1"."c2","t1"."c3") AS "C3",lpad_oracle("t1"."c1","t1"."c2") AS "C4",rpad_oracle("t1"."c1","t1"."c2","t1"."c3") AS "C5",rpad_oracle("t1"."c1","t1"."c2") AS "C6" from "t1" order by "t1"."ord"	latin1	latin1_swedish_ci
+SELECT * FROM v1;
+C1	C2	C3	C4	C5	C6
+NULL	NULL	NULL	a	NULL	a
+NULL	NULL	NULL	NULL	NULL	NULL
+NULL	NULL	NULL	NULL	NULL	NULL
+NULL	NULL	NULL	NULL	NULL	NULL
+NULL	NULL	NULL	NULL	NULL	NULL
+NULL	NULL	a	a	a	a
+NULL	NULL	.a	 a	a.	a 
+SELECT c1||'-'||c2||'-'||c3||'-'||c4||'-'||c5||'-'||c6 FROM v1;
+c1||'-'||c2||'-'||c3||'-'||c4||'-'||c5||'-'||c6
+---a--a
+-----
+-----
+-----
+-----
+--a-a-a-a
+--.a- a-a.-a 
+DROP VIEW v1;
+DROP TABLE t1;
diff --git a/mysql-test/suite/compat/oracle/t/func_pad.test b/mysql-test/suite/compat/oracle/t/func_pad.test
new file mode 100644
index 00000000000..bc33a9fa4f8
--- /dev/null
+++ b/mysql-test/suite/compat/oracle/t/func_pad.test
@@ -0,0 +1,31 @@
+SET sql_mode=ORACLE;
+
+--echo #
+--echo # MDEV-15739 -  sql_mode=ORACLE: Make LPAD and RPAD return NULL instead of empty string
+--echo #
+
+SELECT RPAD('a',0), RPAD('abc',1), RPAD('abc',2) ;
+SELECT RPAD('a',0,'.'), RPAD('abc',1,'.'), RPAD('abc',2,'.') ;
+SELECT LPAD('a',0), LPAD('abc',1), LPAD('abc',2) ;
+SELECT LPAD('a',0,'.'), LPAD('abc',1,'.'), LPAD('abc',2,'.') ;
+
+CREATE TABLE t1 (c1 VARCHAR(10),c2 INTEGER, c3 VARCHAR(10), ord INTEGER);
+INSERT INTO t1 VALUES ('a',1,null,1);
+INSERT INTO t1 VALUES ('a',null,'.',2);
+INSERT INTO t1 VALUES (null,1,'.',3);
+INSERT INTO t1 VALUES ('a',-1,'.',4);
+INSERT INTO t1 VALUES ('a',0,'.',5);
+INSERT INTO t1 VALUES ('a',1,'.',6);
+INSERT INTO t1 VALUES ('a',2,'.',7);
+
+SELECT LPAD(c1,c2,c3), LPAD(c1,c2) FROM t1 ORDER BY ord;
+SELECT RPAD(c1,c2,c3), RPAD(c1,c2) FROM t1 ORDER BY ord;
+
+EXPLAIN EXTENDED SELECT RPAD('a',0,'.'), LPAD('a',0,'.'), LPAD(c1,c2,c3), LPAD(c1,c2), RPAD(c1,c2,c3), RPAD(c1,c2) FROM t1 ORDER BY ord;
+
+CREATE VIEW v1 AS SELECT RPAD('a',0,'.') AS "C1", LPAD('a',0,'.') AS "C2", LPAD(c1,c2,c3) AS "C3", LPAD(c1,c2) AS "C4", RPAD(c1,c2,c3) AS "C5", RPAD(c1,c2) AS "C6" FROM t1 ORDER BY ord;
+SHOW CREATE VIEW v1;
+SELECT * FROM v1;
+SELECT c1||'-'||c2||'-'||c3||'-'||c4||'-'||c5||'-'||c6 FROM v1;
+DROP VIEW v1;
+DROP TABLE t1;
diff --git a/sql/events.cc b/sql/events.cc
index 2fbb16861f6..7568d03c0e0 100644
--- a/sql/events.cc
+++ b/sql/events.cc
@@ -826,12 +826,13 @@ Events::fill_schema_events(THD *thd, TABLE_LIST *tables, COND * /* cond */)
   */
   if (thd->lex->sql_command == SQLCOM_SHOW_EVENTS)
   {
-    DBUG_ASSERT(thd->lex->select_lex.db.str);
-    if (!is_infoschema_db(&thd->lex->select_lex.db) && // There is no events in I_S
-        check_access(thd, EVENT_ACL, thd->lex->select_lex.db.str,
+    DBUG_ASSERT(thd->lex->first_select_lex()->db.str);
+    if (!is_infoschema_db(&thd->lex->first_select_lex()->db) && // There is no events in I_S
+        check_access(thd, EVENT_ACL, thd->lex->first_select_lex()->db.str,
                      NULL, NULL, 0, 0))
       DBUG_RETURN(1);
-    db= normalize_db_name(thd->lex->select_lex.db.str, db_tmp, sizeof(db_tmp));
+    db= normalize_db_name(thd->lex->first_select_lex()->db.str,
+                          db_tmp, sizeof(db_tmp));
   }
   ret= db_repository->fill_schema_events(thd, tables, db);
 
diff --git a/sql/item.cc b/sql/item.cc
index b32967e8944..d74e5aa4948 100644
--- a/sql/item.cc
+++ b/sql/item.cc
@@ -734,7 +734,8 @@ Item_ident::Item_ident(THD *thd, TABLE_LIST *view_arg,
   :Item_result_field(thd), orig_db_name(NullS),
    orig_table_name(view_arg->table_name.str),
    orig_field_name(*field_name_arg),
-   context(&view_arg->view->select_lex.context),
+   /* TODO: suspicious use of first_select_lex */
+   context(&view_arg->view->first_select_lex()->context),
    db_name(NullS), table_name(view_arg->alias.str),
    field_name(*field_name_arg),
    alias_name_used(FALSE), cached_field_index(NO_CACHED_FIELD_INDEX),
diff --git a/sql/item_create.cc b/sql/item_create.cc
index a07e4c9c16b..901dfa06f40 100644
--- a/sql/item_create.cc
+++ b/sql/item_create.cc
@@ -2195,13 +2195,30 @@ class Create_func_lpad : public Create_native_func
 {
 public:
   virtual Item *create_native(THD *thd, LEX_CSTRING *name,
-                              List<Item> *item_list);
-
+                              List<Item> *item_list)
+  {
+    return thd->variables.sql_mode & MODE_ORACLE ?
+           create_native_oracle(thd, name, item_list) :
+           create_native_std(thd, name, item_list);
+  }
   static Create_func_lpad s_singleton;
 
 protected:
   Create_func_lpad() {}
   virtual ~Create_func_lpad() {}
+  Item *create_native_std(THD *thd, LEX_CSTRING *name, List<Item> *items);
+  Item *create_native_oracle(THD *thd, LEX_CSTRING *name, List<Item> *items);
+};
+
+
+class Create_func_lpad_oracle : public Create_func_lpad
+{
+public:
+  Item *create_native(THD *thd, LEX_CSTRING *name, List<Item> *item_list)
+  {
+    return create_native_oracle(thd, name, item_list);
+  }
+  static Create_func_lpad_oracle s_singleton;
 };
 
 
@@ -2648,13 +2665,30 @@ class Create_func_rpad : public Create_native_func
 {
 public:
   virtual Item *create_native(THD *thd, LEX_CSTRING *name,
-                              List<Item> *item_list);
-
+                              List<Item> *item_list)
+  {
+    return thd->variables.sql_mode & MODE_ORACLE ?
+           create_native_oracle(thd, name, item_list) :
+           create_native_std(thd, name, item_list);
+  }
   static Create_func_rpad s_singleton;
 
 protected:
   Create_func_rpad() {}
   virtual ~Create_func_rpad() {}
+  Item *create_native_std(THD *thd, LEX_CSTRING *name, List<Item> *items);
+  Item *create_native_oracle(THD *thd, LEX_CSTRING *name, List<Item> *items);
+};
+
+
+class Create_func_rpad_oracle : public Create_func_rpad
+{
+public:
+  Item *create_native(THD *thd, LEX_CSTRING *name, List<Item> *item_list)
+  {
+    return create_native_oracle(thd, name, item_list);
+  }
+  static Create_func_rpad_oracle s_singleton;
 };
 
 
@@ -5810,9 +5844,11 @@ Create_func_log2::create_1_arg(THD *thd, Item *arg1)
 
 Create_func_lpad Create_func_lpad::s_singleton;
 
+Create_func_lpad_oracle Create_func_lpad_oracle::s_singleton;
+
 Item*
-Create_func_lpad::create_native(THD *thd, LEX_CSTRING *name,
-                                List<Item> *item_list)
+Create_func_lpad::create_native_std(THD *thd, LEX_CSTRING *name,
+                                    List<Item> *item_list)
 {
   Item *func= NULL;
   int arg_count= item_list ? item_list->elements : 0;
@@ -5842,6 +5878,34 @@ Create_func_lpad::create_native(THD *thd, LEX_CSTRING *name,
 }
 
 
+Item*
+Create_func_lpad::create_native_oracle(THD *thd, LEX_CSTRING *name,
+                                       List<Item> *item_list)
+{
+  int arg_count= item_list ? item_list->elements : 0;
+  switch (arg_count) {
+  case 2:
+  {
+    Item *param_1= item_list->pop();
+    Item *param_2= item_list->pop();
+    return new (thd->mem_root) Item_func_lpad_oracle(thd, param_1, param_2);
+  }
+  case 3:
+  {
+    Item *param_1= item_list->pop();
+    Item *param_2= item_list->pop();
+    Item *param_3= item_list->pop();
+    return new (thd->mem_root) Item_func_lpad_oracle(thd, param_1,
+                                                     param_2, param_3);
+  }
+  default:
+    my_error(ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT, MYF(0), name->str);
+    break;
+  }
+  return NULL;
+}
+
+
 Create_func_ltrim Create_func_ltrim::s_singleton;
 
 Item*
@@ -6316,9 +6380,11 @@ Create_func_round::create_native(THD *thd, LEX_CSTRING *name,
 
 Create_func_rpad Create_func_rpad::s_singleton;
 
+Create_func_rpad_oracle Create_func_rpad_oracle::s_singleton;
+
 Item*
-Create_func_rpad::create_native(THD *thd, LEX_CSTRING *name,
-                                List<Item> *item_list)
+Create_func_rpad::create_native_std(THD *thd, LEX_CSTRING *name,
+                                    List<Item> *item_list)
 {
   Item *func= NULL;
   int arg_count= item_list ? item_list->elements : 0;
@@ -6348,6 +6414,34 @@ Create_func_rpad::create_native(THD *thd, LEX_CSTRING *name,
 }
 
 
+Item*
+Create_func_rpad::create_native_oracle(THD *thd, LEX_CSTRING *name,
+                                       List<Item> *item_list)
+{
+  int arg_count= item_list ? item_list->elements : 0;
+  switch (arg_count) {
+  case 2:
+  {
+    Item *param_1= item_list->pop();
+    Item *param_2= item_list->pop();
+    return new (thd->mem_root) Item_func_rpad_oracle(thd, param_1, param_2);
+  }
+  case 3:
+  {
+    Item *param_1= item_list->pop();
+    Item *param_2= item_list->pop();
+    Item *param_3= item_list->pop();
+    return new (thd->mem_root) Item_func_rpad_oracle(thd, param_1,
+                                                     param_2, param_3);
+  }
+  default:
+    my_error(ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT, MYF(0), name->str);
+    break;
+  }
+  return NULL;
+}
+
+
 Create_func_rtrim Create_func_rtrim::s_singleton;
 
 Item*
@@ -7021,6 +7115,7 @@ static Native_func_registry func_array[] =
   { { STRING_WITH_LEN("LOG2") }, BUILDER(Create_func_log2)},
   { { STRING_WITH_LEN("LOWER") }, BUILDER(Create_func_lcase)},
   { { STRING_WITH_LEN("LPAD") }, BUILDER(Create_func_lpad)},
+  { { STRING_WITH_LEN("LPAD_ORACLE") }, BUILDER(Create_func_lpad_oracle)},
   { { STRING_WITH_LEN("LTRIM") }, BUILDER(Create_func_ltrim)},
   { { STRING_WITH_LEN("LTRIM_ORACLE") }, BUILDER(Create_func_ltrim_oracle)},
   { { STRING_WITH_LEN("MAKEDATE") }, BUILDER(Create_func_makedate)},
@@ -7086,6 +7181,7 @@ static Native_func_registry func_array[] =
   { { STRING_WITH_LEN("REVERSE") }, BUILDER(Create_func_reverse)},
   { { STRING_WITH_LEN("ROUND") }, BUILDER(Create_func_round)},
   { { STRING_WITH_LEN("RPAD") }, BUILDER(Create_func_rpad)},
+  { { STRING_WITH_LEN("RPAD_ORACLE") }, BUILDER(Create_func_rpad_oracle)},
   { { STRING_WITH_LEN("RTRIM") }, BUILDER(Create_func_rtrim)},
   { { STRING_WITH_LEN("RTRIM_ORACLE") }, BUILDER(Create_func_rtrim_oracle)},
   { { STRING_WITH_LEN("SEC_TO_TIME") }, BUILDER(Create_func_sec_to_time)},
diff --git a/sql/item_strfunc.h b/sql/item_strfunc.h
index 4e1514c5476..18cda491efd 100644
--- a/sql/item_strfunc.h
+++ b/sql/item_strfunc.h
@@ -1120,6 +1120,26 @@ class Item_func_rpad :public Item_func_pad
 };
 
 
+class Item_func_rpad_oracle :public Item_func_rpad
+{
+  String *make_empty_result()
+  { null_value= 1; return NULL; }
+public:
+  Item_func_rpad_oracle(THD *thd, Item *arg1, Item *arg2, Item *arg3):
+    Item_func_rpad(thd, arg1, arg2, arg3) {}
+  Item_func_rpad_oracle(THD *thd, Item *arg1, Item *arg2):
+    Item_func_rpad(thd, arg1, arg2) {}
+  void fix_length_and_dec()
+  {
+    Item_func_rpad::fix_length_and_dec();
+    maybe_null= true;
+  }
+  const char *func_name() const { return "rpad_oracle"; }
+  Item *get_copy(THD *thd)
+  { return get_item_copy<Item_func_rpad_oracle>(thd, this); }
+};
+
+
 class Item_func_lpad :public Item_func_pad
 {
 public:
@@ -1134,6 +1154,26 @@ class Item_func_lpad :public Item_func_pad
 };
 
 
+class Item_func_lpad_oracle :public Item_func_lpad
+{
+  String *make_empty_result()
+  { null_value= 1; return NULL; }
+public:
+  Item_func_lpad_oracle(THD *thd, Item *arg1, Item *arg2, Item *arg3):
+    Item_func_lpad(thd, arg1, arg2, arg3) {}
+  Item_func_lpad_oracle(THD *thd, Item *arg1, Item *arg2):
+    Item_func_lpad(thd, arg1, arg2) {}
+  void fix_length_and_dec()
+  {
+    Item_func_lpad::fix_length_and_dec();
+    maybe_null= true;
+  }
+  const char *func_name() const { return "lpad_oracle"; }
+  Item *get_copy(THD *thd)
+  { return get_item_copy<Item_func_lpad_oracle>(thd, this); }
+};
+
+
 class Item_func_conv :public Item_str_func
 {
 public:
diff --git a/sql/item_subselect.cc b/sql/item_subselect.cc
index 6378e9b76bf..5a447cef23a 100644
--- a/sql/item_subselect.cc
+++ b/sql/item_subselect.cc
@@ -123,14 +123,7 @@ void Item_subselect::init(st_select_lex *select_lex,
     else
       engine= new subselect_single_select_engine(select_lex, result, this);
   }
-  {
-    SELECT_LEX *upper= unit->outer_select();
-    if (upper->parsing_place == IN_HAVING)
-      upper->subquery_in_having= 1;
-    /* The subquery is an expression cache candidate */
-    upper->expr_cache_may_be_used[upper->parsing_place]= TRUE;
-  }
-  DBUG_PRINT("info", ("engine: %p", engine));
+  DBUG_PRINT("info", ("engine: 0x%lx", (ulong)engine));
   DBUG_VOID_RETURN;
 }
 
@@ -219,7 +212,8 @@ Item_subselect::~Item_subselect()
   if (own_engine)
     delete engine;
   else
-    engine->cleanup();
+    if (engine)  // can be empty in case of EOM
+      engine->cleanup();
   engine= NULL;
   DBUG_VOID_RETURN;
 }
@@ -243,6 +237,14 @@ bool Item_subselect::fix_fields(THD *thd_param, Item **ref)
 
   DBUG_ASSERT(unit->thd == thd);
 
+  {
+    SELECT_LEX *upper= unit->outer_select();
+    if (upper->parsing_place == IN_HAVING)
+      upper->subquery_in_having= 1;
+    /* The subquery is an expression cache candidate */
+    upper->expr_cache_may_be_used[upper->parsing_place]= TRUE;
+  }
+
   status_var_increment(thd_param->status_var.feature_subquery);
 
   DBUG_ASSERT(fixed == 0);
diff --git a/sql/log_event.cc b/sql/log_event.cc
index cd47cbba9bd..2e342936893 100644
--- a/sql/log_event.cc
+++ b/sql/log_event.cc
@@ -4389,7 +4389,7 @@ Query_log_event::Query_log_event(THD* thd_arg, const char* query_arg, size_t que
         have to use the transactional cache to ensure we don't
         calculate any checksum for the CREATE part.
       */
-      trx_cache= (lex->select_lex.item_list.elements &&
+      trx_cache= (lex->first_select_lex()->item_list.elements &&
                   thd->is_current_stmt_binlog_format_row()) ||
                   (thd->variables.option_bits & OPTION_GTID_BEGIN);
       use_cache= (lex->tmp_table() &&
@@ -7339,8 +7339,9 @@ int Load_log_event::do_apply_event(NET* net, rpl_group_info *rgi,
 
       ex.skip_lines = skip_lines;
       List<Item> field_list;
-      thd->lex->select_lex.context.resolve_in_table_list_only(&tables);
-      set_fields(tables.db.str, field_list, &thd->lex->select_lex.context);
+      thd->lex->first_select_lex()->context.resolve_in_table_list_only(&tables);
+      set_fields(tables.db.str,
+                 field_list, &thd->lex->first_select_lex()->context);
       thd->variables.pseudo_thread_id= thread_id;
       if (net)
       {
diff --git a/sql/opt_range.cc b/sql/opt_range.cc
index 38dbed92a22..39c36cdd529 100644
--- a/sql/opt_range.cc
+++ b/sql/opt_range.cc
@@ -4543,7 +4543,7 @@ double get_sweep_read_cost(const PARAM *param, ha_rows records)
     if (max_cost != DBL_MAX  && (busy_blocks+index_reads_cost) >= n_blocks)
       return 1;
     */
-    JOIN *join= param->thd->lex->select_lex.join;
+    JOIN *join= param->thd->lex->first_select_lex()->join;
     if (!join || join->table_count == 1)
     {
       /* No join, assume reading is done in one 'sweep' */
diff --git a/sql/opt_table_elimination.cc b/sql/opt_table_elimination.cc
index ef9b07cca47..95743ecaad4 100644
--- a/sql/opt_table_elimination.cc
+++ b/sql/opt_table_elimination.cc
@@ -617,7 +617,7 @@ void eliminate_tables(JOIN *join)
     we should also take into account tables mentioned in "val".
   */
   if (join->thd->lex->sql_command == SQLCOM_INSERT_SELECT &&
-      join->select_lex == &thd->lex->select_lex)
+      join->select_lex == thd->lex->first_select_lex())
   {
     List_iterator<Item> val_it(thd->lex->value_list);
     while ((item= val_it++))
@@ -640,7 +640,7 @@ void eliminate_tables(JOIN *join)
       used_tables |= (*(cur_list->item))->used_tables();
   }
   
-  if (join->select_lex == &thd->lex->select_lex)
+  if (join->select_lex == thd->lex->first_select_lex())
   {
 
     /* Multi-table UPDATE: don't eliminate tables referred from SET statement */
diff --git a/sql/set_var.cc b/sql/set_var.cc
index bf373dde905..0923682a486 100644
--- a/sql/set_var.cc
+++ b/sql/set_var.cc
@@ -730,7 +730,7 @@ int sql_set_variables(THD *thd, List<set_var_base> *var_list, bool free)
 
 err:
   if (free)
-    free_underlaid_joins(thd, &thd->lex->select_lex);
+    free_underlaid_joins(thd, thd->lex->first_select_lex());
   DBUG_RETURN(error);
 }
 
diff --git a/sql/sp_head.cc b/sql/sp_head.cc
index c088dc6ba12..25ad3ceff25 100644
--- a/sql/sp_head.cc
+++ b/sql/sp_head.cc
@@ -317,7 +317,7 @@ sp_get_flags_for_command(LEX *lex)
        - EXPLAIN DELETE ...
        - ANALYZE DELETE ...
     */
-    if (lex->select_lex.item_list.is_empty() &&
+    if (lex->first_select_lex()->item_list.is_empty() &&
         !lex->describe && !lex->analyze_stmt)
       flags= 0;
     else
@@ -556,6 +556,7 @@ sp_head::sp_head(sp_package *parent, const Sp_handler *sph)
   m_backpatch_goto.empty();
   m_cont_backpatch.empty();
   m_lex.empty();
+  m_stmt_lex.empty();
   my_init_dynamic_array(&m_instr, sizeof(sp_instr *), 16, 8, MYF(0));
   my_hash_init(&m_sptabs, system_charset_info, 0, 0, 0, sp_table_key, 0, 0);
   my_hash_init(&m_sroutines, system_charset_info, 0, 0, 0, sp_sroutine_key,
@@ -830,13 +831,15 @@ sp_head::~sp_head()
     THD::lex. It is safe to not update LEX::ptr because further query
     string parsing and execution will be stopped anyway.
   */
+  DBUG_ASSERT(m_lex.elements == m_stmt_lex.elements);
   while ((lex= (LEX *)m_lex.pop()))
   {
     THD *thd= lex->thd;
     thd->lex->sphead= NULL;
     lex_end(thd->lex);
     delete thd->lex;
-    thd->lex= thd->stmt_lex= lex;
+    thd->lex= lex;
+    thd->stmt_lex= m_stmt_lex.pop();
   }
 
   my_hash_free(&m_sptabs);
@@ -2285,6 +2288,7 @@ sp_head::execute_procedure(THD *thd, List<Item> *args)
   if (!err_status)
   {
     err_status= execute(thd, TRUE);
+    DBUG_PRINT("info", ("execute returned %d", (int) err_status));
   }
 
   if (save_log_general)
@@ -2386,10 +2390,11 @@ sp_head::reset_lex(THD *thd, sp_lex_local *sublex)
 {
   DBUG_ENTER("sp_head::reset_lex");
   LEX *oldlex= thd->lex;
+  LEX *oldstmtlex= thd->stmt_lex;
 
-  thd->set_local_lex(sublex);
+  thd->set_local_lex(sublex, sublex);
 
-  DBUG_RETURN(m_lex.push_front(oldlex));
+  DBUG_RETURN(m_lex.push_front(oldlex) || m_stmt_lex.push_front(oldstmtlex));
 }
 
 
diff --git a/sql/sp_head.h b/sql/sp_head.h
index f588f79b599..f28e1919959 100644
--- a/sql/sp_head.h
+++ b/sql/sp_head.h
@@ -589,10 +589,12 @@ class sp_head :private Query_arena,
   {
     DBUG_ENTER("sp_head::restore_lex");
     LEX *oldlex= (LEX *) m_lex.pop();
+    LEX *oldstmtlex= (LEX *) m_stmt_lex.pop();
     if (!oldlex)
       DBUG_RETURN(false); // Nothing to restore
     LEX *sublex= thd->lex;
-    if (thd->restore_from_local_lex_to_old_lex(oldlex))// This restores thd->lex
+    // This restores thd->lex and thd->stmt_lex
+    if (thd->restore_from_local_lex_to_old_lex(oldlex, oldstmtlex))
       DBUG_RETURN(true);
     if (!sublex->sp_lex_in_use)
     {
@@ -858,6 +860,7 @@ class sp_head :private Query_arena,
 
   sp_pcontext *m_pcont;		///< Parse context
   List<LEX> m_lex;		///< Temp. store for the other lex
+  List<LEX> m_stmt_lex;		///< Temp. store for the other stmt_lex
   DYNAMIC_ARRAY m_instr;	///< The "instructions"
 
   enum backpatch_instr_type { GOTO, CPOP, HPOP };
diff --git a/sql/sp_rcontext.cc b/sql/sp_rcontext.cc
index 2e9ae23d7f9..19b23cd59ee 100644
--- a/sql/sp_rcontext.cc
+++ b/sql/sp_rcontext.cc
@@ -227,9 +227,10 @@ bool Qualified_column_ident::resolve_type_ref(THD *thd, Column_definition *def)
   // Make %TYPE variables see temporary tables that shadow permanent tables
   thd->temporary_tables= open_tables_state_backup.temporary_tables;
 
-  if ((table_list= lex.select_lex.add_table_to_list(thd, this, NULL, 0,
-                                                    TL_READ_NO_INSERT,
-                                                    MDL_SHARED_READ)) &&
+  if ((table_list=
+         lex.first_select_lex()->add_table_to_list(thd, this, NULL, 0,
+                                                   TL_READ_NO_INSERT,
+                                                   MDL_SHARED_READ)) &&
       !check_table_access(thd, SELECT_ACL, table_list, TRUE, UINT_MAX, FALSE) &&
       !open_tables_only_view_structure(thd, table_list,
                                        thd->mdl_context.has_locks()))
@@ -285,9 +286,10 @@ bool Table_ident::resolve_table_rowtype_ref(THD *thd,
   // Make %ROWTYPE variables see temporary tables that shadow permanent tables
   thd->temporary_tables= open_tables_state_backup.temporary_tables;
 
-  if ((table_list= lex.select_lex.add_table_to_list(thd, this, NULL, 0,
-                                                    TL_READ_NO_INSERT,
-                                                    MDL_SHARED_READ)) &&
+  if ((table_list=
+         lex.first_select_lex()->add_table_to_list(thd, this, NULL, 0,
+                                                   TL_READ_NO_INSERT,
+                                                   MDL_SHARED_READ)) &&
       !check_table_access(thd, SELECT_ACL, table_list, TRUE, UINT_MAX, FALSE) &&
       !open_tables_only_view_structure(thd, table_list,
                                        thd->mdl_context.has_locks()))
diff --git a/sql/sql_admin.cc b/sql/sql_admin.cc
index 82fc1cbfff7..610b1a9ffed 100644
--- a/sql/sql_admin.cc
+++ b/sql/sql_admin.cc
@@ -306,7 +306,7 @@ static bool open_only_one_table(THD* thd, TABLE_LIST* table,
                                 bool is_view_operator_func)
 {
   LEX *lex= thd->lex;
-  SELECT_LEX *select= &lex->select_lex;
+  SELECT_LEX *select= lex->first_select_lex();
   TABLE_LIST *save_next_global, *save_next_local;
   bool open_error;
   save_next_global= table->next_global;
@@ -1295,7 +1295,7 @@ bool mysql_preload_keys(THD* thd, TABLE_LIST* tables)
 bool Sql_cmd_analyze_table::execute(THD *thd)
 {
   LEX *m_lex= thd->lex;
-  TABLE_LIST *first_table= m_lex->select_lex.table_list.first;
+  TABLE_LIST *first_table= m_lex->first_select_lex()->table_list.first;
   bool res= TRUE;
   thr_lock_type lock_type = TL_READ_NO_INSERT;
   DBUG_ENTER("Sql_cmd_analyze_table::execute");
@@ -1315,7 +1315,7 @@ bool Sql_cmd_analyze_table::execute(THD *thd)
     */
     res= write_bin_log(thd, TRUE, thd->query(), thd->query_length());
   }
-  m_lex->select_lex.table_list.first= first_table;
+  m_lex->first_select_lex()->table_list.first= first_table;
   m_lex->query_tables= first_table;
 
 error:
@@ -1326,7 +1326,7 @@ bool Sql_cmd_analyze_table::execute(THD *thd)
 bool Sql_cmd_check_table::execute(THD *thd)
 {
   LEX *m_lex= thd->lex;
-  TABLE_LIST *first_table= m_lex->select_lex.table_list.first;
+  TABLE_LIST *first_table= m_lex->first_select_lex()->table_list.first;
   thr_lock_type lock_type = TL_READ_NO_INSERT;
   bool res= TRUE;
   DBUG_ENTER("Sql_cmd_check_table::execute");
@@ -1339,7 +1339,7 @@ bool Sql_cmd_check_table::execute(THD *thd)
                          lock_type, 0, 0, HA_OPEN_FOR_REPAIR, 0,
                          &handler::ha_check, &view_check);
 
-  m_lex->select_lex.table_list.first= first_table;
+  m_lex->first_select_lex()->table_list.first= first_table;
   m_lex->query_tables= first_table;
 
 error:
@@ -1350,7 +1350,7 @@ bool Sql_cmd_check_table::execute(THD *thd)
 bool Sql_cmd_optimize_table::execute(THD *thd)
 {
   LEX *m_lex= thd->lex;
-  TABLE_LIST *first_table= m_lex->select_lex.table_list.first;
+  TABLE_LIST *first_table= m_lex->first_select_lex()->table_list.first;
   bool res= TRUE;
   DBUG_ENTER("Sql_cmd_optimize_table::execute");
 
@@ -1372,7 +1372,7 @@ bool Sql_cmd_optimize_table::execute(THD *thd)
     */
     res= write_bin_log(thd, TRUE, thd->query(), thd->query_length());
   }
-  m_lex->select_lex.table_list.first= first_table;
+  m_lex->first_select_lex()->table_list.first= first_table;
   m_lex->query_tables= first_table;
 
 error:
@@ -1383,7 +1383,7 @@ bool Sql_cmd_optimize_table::execute(THD *thd)
 bool Sql_cmd_repair_table::execute(THD *thd)
 {
   LEX *m_lex= thd->lex;
-  TABLE_LIST *first_table= m_lex->select_lex.table_list.first;
+  TABLE_LIST *first_table= m_lex->first_select_lex()->table_list.first;
   bool res= TRUE;
   DBUG_ENTER("Sql_cmd_repair_table::execute");
 
@@ -1407,7 +1407,7 @@ bool Sql_cmd_repair_table::execute(THD *thd)
     */
     res= write_bin_log(thd, TRUE, thd->query(), thd->query_length());
   }
-  m_lex->select_lex.table_list.first= first_table;
+  m_lex->first_select_lex()->table_list.first= first_table;
   m_lex->query_tables= first_table;
 
 error:
diff --git a/sql/sql_alter.cc b/sql/sql_alter.cc
index 77e0c9d5298..e4c84c1c3cb 100644
--- a/sql/sql_alter.cc
+++ b/sql/sql_alter.cc
@@ -201,7 +201,7 @@ bool Sql_cmd_alter_table::execute(THD *thd)
 {
   LEX *lex= thd->lex;
   /* first SELECT_LEX (have special meaning for many of non-SELECTcommands) */
-  SELECT_LEX *select_lex= &lex->select_lex;
+  SELECT_LEX *select_lex= lex->first_select_lex();
   /* first table of first SELECT_LEX */
   TABLE_LIST *first_table= (TABLE_LIST*) select_lex->table_list.first;
   /*
@@ -345,7 +345,7 @@ bool Sql_cmd_alter_table::execute(THD *thd)
 bool Sql_cmd_discard_import_tablespace::execute(THD *thd)
 {
   /* first SELECT_LEX (have special meaning for many of non-SELECTcommands) */
-  SELECT_LEX *select_lex= &thd->lex->select_lex;
+  SELECT_LEX *select_lex= thd->lex->first_select_lex();
   /* first table of first SELECT_LEX */
   TABLE_LIST *table_list= (TABLE_LIST*) select_lex->table_list.first;
 
diff --git a/sql/sql_base.cc b/sql/sql_base.cc
index 9f7e97dc3ff..7916130ce2e 100644
--- a/sql/sql_base.cc
+++ b/sql/sql_base.cc
@@ -7435,7 +7435,7 @@ bool setup_tables(THD *thd, Name_resolution_context *context,
   TABLE_LIST *first_select_table= (select_insert ?
                                    tables->next_local:
                                    0);
-  SELECT_LEX *select_lex= select_insert ? &thd->lex->select_lex :
+  SELECT_LEX *select_lex= select_insert ? thd->lex->first_select_lex() :
                                           thd->lex->current_select;
   if (select_lex->first_cond_optimization)
   {
@@ -7463,7 +7463,7 @@ bool setup_tables(THD *thd, Name_resolution_context *context,
       {
         /* new counting for SELECT of INSERT ... SELECT command */
         first_select_table= 0;
-        thd->lex->select_lex.insert_tables= tablenr;
+        thd->lex->first_select_lex()->insert_tables= tablenr;
         tablenr= 0;
       }
       if(table_list->jtbm_subselect)
@@ -8017,7 +8017,7 @@ int setup_conds(THD *thd, TABLE_LIST *tables, List<TABLE_LIST> &leaves,
     from subquery of VIEW, because tables of subquery belongs to VIEW
     (see condition before prepare_check_option() call)
   */
-  bool it_is_update= (select_lex == &thd->lex->select_lex) &&
+  bool it_is_update= (select_lex == thd->lex->first_select_lex()) &&
     thd->lex->which_check_option_applicable();
   bool save_is_item_list_lookup= select_lex->is_item_list_lookup;
   TABLE_LIST *derived= select_lex->master_unit()->derived;
@@ -8033,7 +8033,7 @@ int setup_conds(THD *thd, TABLE_LIST *tables, List<TABLE_LIST> &leaves,
 
   for (table= tables; table; table= table->next_local)
   {
-    if (select_lex == &thd->lex->select_lex &&
+    if (select_lex == thd->lex->first_select_lex() &&
         select_lex->first_cond_optimization &&
         table->merged_for_insert &&
         table->prepare_where(thd, conds, FALSE))
diff --git a/sql/sql_base.h b/sql/sql_base.h
index a6a85d47dc9..6cbf6005f04 100644
--- a/sql/sql_base.h
+++ b/sql/sql_base.h
@@ -358,10 +358,12 @@ inline bool setup_fields_with_no_wrap(THD *thd, Ref_ptr_array ref_pointer_array,
                                       bool allow_sum_func)
 {
   bool res;
-  thd->lex->select_lex.no_wrap_view_item= TRUE;
+  SELECT_LEX *first= thd->lex->first_select_lex();
+  DBUG_ASSERT(thd->lex->current_select == first);
+  first->no_wrap_view_item= TRUE;
   res= setup_fields(thd, ref_pointer_array, item, column_usage,
                     sum_func_list, NULL,  allow_sum_func);
-  thd->lex->select_lex.no_wrap_view_item= FALSE;
+  first->no_wrap_view_item= FALSE;
   return res;
 }
 
diff --git a/sql/sql_cache.cc b/sql/sql_cache.cc
index c8f18556d50..9aee9e14870 100644
--- a/sql/sql_cache.cc
+++ b/sql/sql_cache.cc
@@ -4130,13 +4130,13 @@ Query_cache::is_cacheable(THD *thd, LEX *lex,
 
   if (thd->lex->safe_to_cache_query &&
       (thd->variables.query_cache_type == 1 ||
-       (thd->variables.query_cache_type == 2 && (lex->select_lex.options &
-						 OPTION_TO_QUERY_CACHE))) &&
+       (thd->variables.query_cache_type == 2 &&
+        (lex->first_select_lex()->options & OPTION_TO_QUERY_CACHE))) &&
       qc_is_able_to_intercept_result(thd))
   {
     DBUG_PRINT("qcache", ("options: %lx  %lx  type: %u",
                           (long) OPTION_TO_QUERY_CACHE,
-                          (long) lex->select_lex.options,
+                          (long) lex->first_select_lex()->options,
                           (int) thd->variables.query_cache_type));
 
     if (!(table_count= process_and_count_tables(thd, tables_used,
@@ -4157,7 +4157,7 @@ Query_cache::is_cacheable(THD *thd, LEX *lex,
 	     ("not interesting query: %d or not cacheable, options %lx %lx  type: %u  net->vio present: %u",
 	      (int) lex->sql_command,
 	      (long) OPTION_TO_QUERY_CACHE,
-	      (long) lex->select_lex.options,
+	      (long) lex->first_select_lex()->options,
 	      (int) thd->variables.query_cache_type,
               (uint) MY_TEST(qc_is_able_to_intercept_result(thd))));
   DBUG_RETURN(0);
diff --git a/sql/sql_class.cc b/sql/sql_class.cc
index 15a50910731..7ee1178ceee 100644
--- a/sql/sql_class.cc
+++ b/sql/sql_class.cc
@@ -1374,12 +1374,13 @@ void THD::init(bool skip_lock)
 }
 
 
-bool THD::restore_from_local_lex_to_old_lex(LEX *oldlex)
+bool THD::restore_from_local_lex_to_old_lex(LEX *oldlex, LEX *oldstmtlex)
 {
   DBUG_ASSERT(lex->sphead);
   if (lex->sphead->merge_lex(this, oldlex, lex))
     return true;
   lex= oldlex;
+  stmt_lex= oldstmtlex;
   return false;
 }
 
@@ -3798,6 +3799,7 @@ Statement::Statement(LEX *lex_arg, MEM_ROOT *mem_root_arg,
   id(id_arg),
   column_usage(MARK_COLUMNS_READ),
   lex(lex_arg),
+  stmt_lex(lex_arg),
   db(null_clex_str)
 {
   name= null_clex_str;
diff --git a/sql/sql_class.h b/sql/sql_class.h
index 434bc9c1416..5251533c1d8 100644
--- a/sql/sql_class.h
+++ b/sql/sql_class.h
@@ -4547,6 +4547,7 @@ class THD :public Statement,
   TMP_TABLE_SHARE* save_tmp_table_share(TABLE *table);
   void restore_tmp_table_share(TMP_TABLE_SHARE *share);
 
+  bool inline is_main_lex(LEX *lex) { return lex == &main_lex; }
 private:
   /* Whether a lock has been acquired? */
   bool m_tmp_tables_locked;
@@ -4724,7 +4725,7 @@ class THD :public Statement,
   /**
     Switch to a sublex, to parse a substatement or an expression.
   */
-  void set_local_lex(sp_lex_local *sublex)
+  void set_local_lex(sp_lex_local *sublex, LEX *stmtlex)
   {
     DBUG_ASSERT(lex->sphead);
     lex= stmt_lex= sublex;
@@ -4743,7 +4744,7 @@ class THD :public Statement,
 
     See also sp_head::merge_lex().
   */
-  bool restore_from_local_lex_to_old_lex(LEX *oldlex);
+  bool restore_from_local_lex_to_old_lex(LEX *oldlex, LEX *oldstmtlex);
 
   Item *sp_fix_func_item(Item **it_addr);
   Item *sp_prepare_func_item(Item **it_addr, uint cols= 1);
@@ -6135,7 +6136,8 @@ class select_dumpvar :public select_result_interceptor {
 
 inline bool add_item_to_list(THD *thd, Item *item)
 {
-  return thd->lex->current_select->add_item_to_list(thd, item);
+  bool res= thd->lex->current_select->add_item_to_list(thd, item);
+  return res;
 }
 
 inline bool add_value_to_list(THD *thd, Item *value)
diff --git a/sql/sql_cte.cc b/sql/sql_cte.cc
index a58a9254a82..4a2ff42733e 100644
--- a/sql/sql_cte.cc
+++ b/sql/sql_cte.cc
@@ -55,6 +55,14 @@ bool With_clause::add_with_element(With_element *elem)
 }
 
 
+void  st_select_lex_unit::set_with_clause(With_clause *with_cl)
+{ 
+  with_clause= with_cl;
+  if (with_clause)
+    with_clause->set_owner(this);
+}
+
+
 /**
   @brief
     Check dependencies between tables defined in a list of with clauses
@@ -683,7 +691,7 @@ void With_element::move_anchors_ahead()
   st_select_lex *next_sl;
   st_select_lex *new_pos= spec->first_select();
   st_select_lex *UNINIT_VAR(last_sl);
-  new_pos->linkage= UNION_TYPE;
+  new_pos->set_linkage(UNION_TYPE);
   for (st_select_lex *sl= new_pos; sl; sl= next_sl)
   {
     next_sl= sl->next_select(); 
@@ -829,9 +837,8 @@ st_select_lex_unit *With_element::clone_parsed_spec(THD *thd,
   if (parser_state.init(thd, (char*) unparsed_spec.str, (unsigned int)unparsed_spec.length))
     goto err;
   lex_start(thd);
-  with_select= &lex->select_lex;
-  with_select->select_number= ++thd->stmt_lex->current_select_number;
   parse_status= parse_sql(thd, &parser_state, 0);
+  with_select= lex->first_select_lex();
   if (parse_status)
     goto err;
 
@@ -982,7 +989,7 @@ bool With_element::prepare_unreferenced(THD *thd)
        rename_columns_of_derived_unit(thd, spec) ||
        check_duplicate_names(thd, first_sl->item_list, 1)))
     rc= true;
- 
+
   thd->lex->context_analysis_only&= ~CONTEXT_ANALYSIS_ONLY_DERIVED;
   return rc;
 }
@@ -1094,6 +1101,7 @@ bool TABLE_LIST::set_as_with_table(THD *thd, With_element *with_elem)
       return true;
   }
   derived->first_select()->linkage= DERIVED_TABLE_TYPE;
+  select_lex->add_statistics(derived);
   with_elem->inc_references();
   return false;
 }
diff --git a/sql/sql_cte.h b/sql/sql_cte.h
index 16b473f0665..4a194b2a38f 100644
--- a/sql/sql_cte.h
+++ b/sql/sql_cte.h
@@ -279,8 +279,7 @@ class With_clause : public Sql_alloc
   */
   With_clause *next_with_clause;
   /* Set to true if dependencies between with elements have been checked */
-  bool dependencies_are_checked; 
-
+  bool dependencies_are_checked;
   /* 
     The bitmap of all recursive with elements whose specifications
     are not complied with restrictions imposed by the SQL standards
@@ -304,9 +303,8 @@ class With_clause : public Sql_alloc
   bool with_recursive;
 
   With_clause(bool recursive_fl, With_clause *emb_with_clause)
-    : owner(NULL),
-      embedding_with_clause(emb_with_clause), next_with_clause(NULL),
-      dependencies_are_checked(false),  unrestricted(0),
+    : owner(NULL), embedding_with_clause(emb_with_clause),
+      next_with_clause(NULL), dependencies_are_checked(false), unrestricted(0),
       with_prepared_anchor(0), cleaned(0), stabilized(0),
       with_recursive(recursive_fl)
   { }
@@ -320,8 +318,12 @@ class With_clause : public Sql_alloc
     last_next= &this->next_with_clause;
   }
 
+  st_select_lex_unit *get_owner() { return owner; }
+
   void set_owner(st_select_lex_unit *unit) { owner= unit; }
 
+  void attach_to(st_select_lex *select_lex);
+
   With_clause *pop() { return embedding_with_clause; }
       
   bool check_dependencies();
@@ -354,7 +356,6 @@ bool With_element::is_unrestricted()
 }
 
 inline
-
 bool With_element::is_with_prepared_anchor() 
 {
   return owner->with_prepared_anchor & get_elem_map();
@@ -436,11 +437,14 @@ void With_element::prepare_for_next_iteration()
 
 
 inline
-void  st_select_lex_unit::set_with_clause(With_clause *with_cl)
-{ 
-    with_clause= with_cl;
-    if (with_clause)
-      with_clause->set_owner(this);
+void With_clause::attach_to(st_select_lex *select_lex)
+{
+  for (With_element *with_elem= with_list.first;
+       with_elem;
+       with_elem= with_elem->next)
+  {
+    select_lex->register_unit(with_elem->spec, NULL);
+  }
 }
 
 
diff --git a/sql/sql_delete.cc b/sql/sql_delete.cc
index b92dd4139b2..e60e7b1cc5e 100644
--- a/sql/sql_delete.cc
+++ b/sql/sql_delete.cc
@@ -285,7 +285,7 @@ bool mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds,
   bool          has_triggers;
   ORDER *order= (ORDER *) ((order_list && order_list->elements) ?
                            order_list->first : NULL);
-  SELECT_LEX   *select_lex= &thd->lex->select_lex;
+  SELECT_LEX   *select_lex= thd->lex->first_select_lex();
   killed_state killed_status= NOT_KILLED;
   THD::enum_binlog_query_type query_type= THD::ROW_QUERY_TYPE;
   bool binlog_is_row;
@@ -346,7 +346,7 @@ bool mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds,
     DBUG_RETURN(TRUE);
   }
   table->map=1;
-  query_plan.select_lex= &thd->lex->select_lex;
+  query_plan.select_lex= thd->lex->first_select_lex();
   query_plan.table= table;
   query_plan.updating_a_view= MY_TEST(table_list->view);
 
@@ -378,7 +378,7 @@ bool mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds,
 	  setup_order(thd, select_lex->ref_pointer_array, &tables,
                     fields, all_fields, order))
     {
-      free_underlaid_joins(thd, &thd->lex->select_lex);
+      free_underlaid_joins(thd, thd->lex->first_select_lex());
       DBUG_RETURN(TRUE);
     }
   }
@@ -922,14 +922,16 @@ int mysql_prepare_delete(THD *thd, TABLE_LIST *table_list,
                          bool *delete_while_scanning)
 {
   Item *fake_conds= 0;
-  SELECT_LEX *select_lex= &thd->lex->select_lex;
+  SELECT_LEX *select_lex= thd->lex->first_select_lex();
   DBUG_ENTER("mysql_prepare_delete");
   List<Item> all_fields;
 
   *delete_while_scanning= true;
   thd->lex->allow_sum_func= 0;
-  if (setup_tables_and_check_access(thd, &thd->lex->select_lex.context,
-                                    &thd->lex->select_lex.top_join_list,
+  if (setup_tables_and_check_access(thd,
+                                    &thd->lex->first_select_lex()->context,
+                                    &thd->lex->first_select_lex()->
+                                      top_join_list,
                                     table_list, 
                                     select_lex->leaf_tables, FALSE, 
                                     DELETE_ACL, SELECT_ACL, TRUE))
@@ -1011,21 +1013,23 @@ int mysql_multi_delete_prepare(THD *thd)
 
     lex->query_tables also point on local list of DELETE SELECT_LEX
   */
-  if (setup_tables_and_check_access(thd, &thd->lex->select_lex.context,
-                                    &thd->lex->select_lex.top_join_list,
+  if (setup_tables_and_check_access(thd,
+                                    &thd->lex->first_select_lex()->context,
+                                    &thd->lex->first_select_lex()->
+                                      top_join_list,
                                     lex->query_tables,
-                                    lex->select_lex.leaf_tables, FALSE, 
-                                    DELETE_ACL, SELECT_ACL, FALSE))
+                                    lex->first_select_lex()->leaf_tables,
+                                    FALSE, DELETE_ACL, SELECT_ACL, FALSE))
     DBUG_RETURN(TRUE);
 
-  if (lex->select_lex.handle_derived(thd->lex, DT_MERGE))  
+  if (lex->first_select_lex()->handle_derived(thd->lex, DT_MERGE))
     DBUG_RETURN(TRUE);
 
   /*
     Multi-delete can't be constructed over-union => we always have
     single SELECT on top and have to check underlying SELECTs of it
   */
-  lex->select_lex.exclude_from_table_unique_test= TRUE;
+  lex->first_select_lex()->exclude_from_table_unique_test= TRUE;
   /* Fix tables-to-be-deleted-from list to point at opened tables */
   for (target_tbl= (TABLE_LIST*) aux_tables;
        target_tbl;
@@ -1067,8 +1071,8 @@ int mysql_multi_delete_prepare(THD *thd)
     Reset the exclude flag to false so it doesn't interfare
     with further calls to unique_table
   */
-  lex->select_lex.exclude_from_table_unique_test= FALSE;
-  
+  lex->first_select_lex()->exclude_from_table_unique_test= FALSE;
+
   if (lex->save_prep_leaf_tables())
     DBUG_RETURN(TRUE);
   
diff --git a/sql/sql_derived.cc b/sql/sql_derived.cc
index ab66384c6cb..26b1fca473a 100644
--- a/sql/sql_derived.cc
+++ b/sql/sql_derived.cc
@@ -99,7 +99,8 @@ mysql_handle_derived(LEX *lex, uint phases)
         processed normally.
       */
       if (phases == DT_MERGE_FOR_INSERT &&
-          cursor && cursor->top_table()->select_lex != &lex->select_lex)
+          cursor && (cursor->top_table()->select_lex !=
+                     lex->first_select_lex()))
         continue;
       for (;
 	   cursor && !res;
diff --git a/sql/sql_do.cc b/sql/sql_do.cc
index 20a7aa75590..72acbd763e1 100644
--- a/sql/sql_do.cc
+++ b/sql/sql_do.cc
@@ -33,7 +33,7 @@ bool mysql_do(THD *thd, List<Item> &values)
     DBUG_RETURN(TRUE);
   while ((value = li++))
     (void) value->is_null();
-  free_underlaid_joins(thd, &thd->lex->select_lex);
+  free_underlaid_joins(thd, thd->lex->first_select_lex());
 
   if (thd->is_error())
   {
diff --git a/sql/sql_error.cc b/sql/sql_error.cc
index 67440aeed33..160bf7469c5 100644
--- a/sql/sql_error.cc
+++ b/sql/sql_error.cc
@@ -781,7 +781,7 @@ bool mysqld_show_warnings(THD *thd, ulong levels_to_show)
   List<Item> field_list;
   MEM_ROOT *mem_root= thd->mem_root;
   const Sql_condition *err;
-  SELECT_LEX *sel= &thd->lex->select_lex;
+  SELECT_LEX *sel= thd->lex->first_select_lex();
   SELECT_LEX_UNIT *unit= &thd->lex->unit;
   ulonglong idx= 0;
   Protocol *protocol=thd->protocol;
diff --git a/sql/sql_help.cc b/sql/sql_help.cc
index da38a2caf94..866bf86c733 100644
--- a/sql/sql_help.cc
+++ b/sql/sql_help.cc
@@ -87,7 +87,7 @@ enum enum_used_fields
 static bool init_fields(THD *thd, TABLE_LIST *tables,
 			struct st_find_field *find_fields, uint count)
 {
-  Name_resolution_context *context= &thd->lex->select_lex.context;
+  Name_resolution_context *context= &thd->lex->first_select_lex()->context;
   DBUG_ENTER("init_fields");
   context->resolve_in_table_list_only(tables);
   for (; count-- ; find_fields++)
@@ -719,10 +719,11 @@ static bool mysqld_help_internal(THD *thd, const char *mask)
     Init tables and fields to be usable from items
     tables do not contain VIEWs => we can pass 0 as conds
   */
-  thd->lex->select_lex.context.table_list=
-    thd->lex->select_lex.context.first_name_resolution_table= &tables[0];
-  if (setup_tables(thd, &thd->lex->select_lex.context,
-                   &thd->lex->select_lex.top_join_list,
+  thd->lex->first_select_lex()->context.table_list=
+    thd->lex->first_select_lex()->context.first_name_resolution_table=
+    &tables[0];
+  if (setup_tables(thd, &thd->lex->first_select_lex()->context,
+                   &thd->lex->first_select_lex()->top_join_list,
                    tables, leaves, FALSE, FALSE))
     goto error;
   memcpy((char*) used_fields, (char*) init_used_fields, sizeof(used_fields));
diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc
index 5a603bf16fe..62428e14d78 100644
--- a/sql/sql_insert.cc
+++ b/sql/sql_insert.cc
@@ -241,7 +241,7 @@ static int check_insert_fields(THD *thd, TABLE_LIST *table_list,
   }
   else
   {						// Part field list
-    SELECT_LEX *select_lex= &thd->lex->select_lex;
+    SELECT_LEX *select_lex= thd->lex->first_select_lex();
     Name_resolution_context *context= &select_lex->context;
     Name_resolution_context_state ctx_state;
     int res;
@@ -273,7 +273,7 @@ static int check_insert_fields(THD *thd, TABLE_LIST *table_list,
 
     /* Restore the current context. */
     ctx_state.restore_state(context, table_list);
-    thd->lex->select_lex.no_wrap_view_item= FALSE;
+    thd->lex->first_select_lex()->no_wrap_view_item= FALSE;
 
     if (res)
       DBUG_RETURN(-1);
@@ -657,7 +657,7 @@ static void save_insert_query_plan(THD* thd, TABLE_LIST *table_list)
   bool skip= MY_TEST(table_list->view);
 
   /* Save subquery children */
-  for (SELECT_LEX_UNIT *unit= thd->lex->select_lex.first_inner_unit();
+  for (SELECT_LEX_UNIT *unit= thd->lex->first_select_lex()->first_inner_unit();
        unit;
        unit= unit->next_unit())
   {
@@ -783,7 +783,7 @@ bool mysql_insert(THD *thd,TABLE_LIST *table_list,
   /* mysql_prepare_insert sets table_list->table if it was not set */
   table= table_list->table;
 
-  context= &thd->lex->select_lex.context;
+  context= &thd->lex->first_select_lex()->context;
   /*
     These three asserts test the hypothesis that the resetting of the name
     resolution context below is not necessary at all since the list of local
@@ -1073,7 +1073,7 @@ bool mysql_insert(THD *thd,TABLE_LIST *table_list,
   } while (bulk_parameters_iterations(thd));
 
 values_loop_end:
-  free_underlaid_joins(thd, &thd->lex->select_lex);
+  free_underlaid_joins(thd, thd->lex->first_select_lex());
   joins_freed= TRUE;
 
   /*
@@ -1261,7 +1261,7 @@ bool mysql_insert(THD *thd,TABLE_LIST *table_list,
     table->file->ha_release_auto_increment();
 
   if (!joins_freed)
-    free_underlaid_joins(thd, &thd->lex->select_lex);
+    free_underlaid_joins(thd, thd->lex->first_select_lex());
   thd->abort_on_warning= 0;
   DBUG_RETURN(retval);
 }
@@ -1291,7 +1291,7 @@ bool mysql_insert(THD *thd,TABLE_LIST *table_list,
 
 static bool check_view_insertability(THD * thd, TABLE_LIST *view)
 {
-  uint num= view->view->select_lex.item_list.elements;
+  uint num= view->view->first_select_lex()->item_list.elements;
   TABLE *table= view->table;
   Field_translator *trans_start= view->field_translation,
 		   *trans_end= trans_start + num;
@@ -1391,10 +1391,12 @@ static bool mysql_prepare_insert_check_table(THD *thd, TABLE_LIST *table_list,
      than INSERT.
   */
 
-  if (setup_tables_and_check_access(thd, &thd->lex->select_lex.context,
-                                    &thd->lex->select_lex.top_join_list,
+  if (setup_tables_and_check_access(thd,
+                                    &thd->lex->first_select_lex()->context,
+                                    &thd->lex->first_select_lex()->
+                                      top_join_list,
                                     table_list,
-                                    thd->lex->select_lex.leaf_tables,
+                                    thd->lex->first_select_lex()->leaf_tables,
                                     select_insert, INSERT_ACL, SELECT_ACL,
                                     TRUE))
     DBUG_RETURN(TRUE);
@@ -1402,7 +1404,7 @@ static bool mysql_prepare_insert_check_table(THD *thd, TABLE_LIST *table_list,
   if (insert_into_view && !fields.elements)
   {
     thd->lex->empty_field_list_on_rset= 1;
-    if (!thd->lex->select_lex.leaf_tables.head()->table ||
+    if (!thd->lex->first_select_lex()->leaf_tables.head()->table ||
         table_list->is_multitable())
     {
       my_error(ER_VIEW_NO_INSERT_FIELD_LIST, MYF(0),
@@ -1476,7 +1478,7 @@ bool mysql_prepare_insert(THD *thd, TABLE_LIST *table_list,
                           enum_duplicates duplic, COND **where,
                           bool select_insert)
 {
-  SELECT_LEX *select_lex= &thd->lex->select_lex;
+  SELECT_LEX *select_lex= thd->lex->first_select_lex();
   Name_resolution_context *context= &select_lex->context;
   Name_resolution_context_state ctx_state;
   bool insert_into_view= (table_list->view != 0);
@@ -3532,7 +3534,7 @@ bool Delayed_insert::handle_inserts(void)
 bool mysql_insert_select_prepare(THD *thd)
 {
   LEX *lex= thd->lex;
-  SELECT_LEX *select_lex= &lex->select_lex;
+  SELECT_LEX *select_lex= lex->first_select_lex();
   DBUG_ENTER("mysql_insert_select_prepare");
 
 
@@ -3622,7 +3624,7 @@ select_insert::prepare(List<Item> &values, SELECT_LEX_UNIT *u)
     select, LEX::current_select should point to the first select while
     we are fixing fields from insert list.
   */
-  lex->current_select= &lex->select_lex;
+  lex->current_select= lex->first_select_lex();
 
   res= (setup_fields(thd, Ref_ptr_array(),
                      values, MARK_COLUMNS_READ, 0, NULL, 0) ||
@@ -3641,7 +3643,7 @@ select_insert::prepare(List<Item> &values, SELECT_LEX_UNIT *u)
 
   if (info.handle_duplicates == DUP_UPDATE && !res)
   {
-    Name_resolution_context *context= &lex->select_lex.context;
+    Name_resolution_context *context= &lex->first_select_lex()->context;
     Name_resolution_context_state ctx_state;
 
     /* Save the state of the current name resolution context. */
@@ -3651,7 +3653,7 @@ select_insert::prepare(List<Item> &values, SELECT_LEX_UNIT *u)
     table_list->next_local= 0;
     context->resolve_in_table_list_only(table_list);
 
-    lex->select_lex.no_wrap_view_item= TRUE;
+    lex->first_select_lex()->no_wrap_view_item= TRUE;
     res= res ||
       check_update_fields(thd, context->table_list,
                           *info.update_fields, *info.update_values,
@@ -3662,15 +3664,15 @@ select_insert::prepare(List<Item> &values, SELECT_LEX_UNIT *u)
                            */
                           true,
                           &map);
-    lex->select_lex.no_wrap_view_item= FALSE;
+    lex->first_select_lex()->no_wrap_view_item= FALSE;
     /*
       When we are not using GROUP BY and there are no ungrouped aggregate functions 
       we can refer to other tables in the ON DUPLICATE KEY part.
       We use next_name_resolution_table descructively, so check it first (views?)
     */
     DBUG_ASSERT (!table_list->next_name_resolution_table);
-    if (lex->select_lex.group_list.elements == 0 &&
-        !lex->select_lex.with_sum_func)
+    if (lex->first_select_lex()->group_list.elements == 0 &&
+        !lex->first_select_lex()->with_sum_func)
       /*
         We must make a single context out of the two separate name resolution contexts :
         the INSERT table and the tables in the SELECT part of INSERT ... SELECT.
diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc
index ee434e4ffae..91002034c68 100644
--- a/sql/sql_lex.cc
+++ b/sql/sql_lex.cc
@@ -176,7 +176,7 @@ init_lex_with_single_table(THD *thd, TABLE *table, LEX *lex)
 {
   TABLE_LIST *table_list;
   Table_ident *table_ident;
-  SELECT_LEX *select_lex= &lex->select_lex;
+  SELECT_LEX *select_lex= lex->first_select_lex();
   Name_resolution_context *context= &select_lex->context;
   /*
     We will call the parser to create a part_info struct based on the
@@ -673,20 +673,26 @@ void LEX::start(THD *thd_arg)
              this, thd_arg->lex, thd_arg->stmt_lex));
 
   thd= unit.thd= thd_arg;
-  
+  DBUG_PRINT("info", ("Lex %p stmt_lex: %p", thd->lex, thd->stmt_lex));
+
   DBUG_ASSERT(!explain);
 
   context_stack.empty();
+  //empty select_stack
+  select_stack_top= 0;
   unit.init_query();
-  current_select_number= 1;
-  select_lex.linkage= UNSPECIFIED_TYPE;
+  current_select_number= 0;
+  builtin_select.linkage= UNSPECIFIED_TYPE;
+  builtin_select.set_linkage(UNSPECIFIED_TYPE);
+  builtin_select.distinct= TRUE;
   /* 'parent_lex' is used in init_query() so it must be before it. */
-  select_lex.parent_lex= this;
-  select_lex.init_query();
+  builtin_select.parent_lex= this;
+  builtin_select.init_query();
   curr_with_clause= 0;
   with_clauses_list= 0;
   with_clauses_list_last_next= &with_clauses_list;
   create_view= NULL;
+  field_list.empty();
   value_list.empty();
   update_list.empty();
   set_var_list.empty();
@@ -700,17 +706,17 @@ void LEX::start(THD *thd_arg)
   auxiliary_table_list.empty();
   unit.next= unit.master= unit.link_next= unit.return_to= 0;
   unit.prev= unit.link_prev= 0;
-  unit.slave= current_select= all_selects_list= &select_lex;
-  select_lex.master= &unit;
-  select_lex.prev= &unit.slave;
-  select_lex.link_next= select_lex.slave= select_lex.next= 0;
-  select_lex.link_prev= (st_select_lex_node**)&(all_selects_list);
-  select_lex.options= 0;
-  select_lex.sql_cache= SELECT_LEX::SQL_CACHE_UNSPECIFIED;
-  select_lex.init_order();
-  select_lex.group_list.empty();
-  if (select_lex.group_list_ptrs)
-    select_lex.group_list_ptrs->clear();
+  unit.slave= current_select= all_selects_list= &builtin_select;
+  builtin_select.master= &unit;
+  builtin_select.prev= &unit.slave;
+  builtin_select.link_next= builtin_select.slave= builtin_select.next= 0;
+  builtin_select.link_prev= (st_select_lex_node**)&(all_selects_list);
+  builtin_select.options= 0;
+  builtin_select.sql_cache= SELECT_LEX::SQL_CACHE_UNSPECIFIED;
+  builtin_select.init_order();
+  builtin_select.group_list.empty();
+  if (builtin_select.group_list_ptrs)
+    builtin_select.group_list_ptrs->clear();
   describe= 0;
   analyze_stmt= 0;
   explain_json= false;
@@ -720,14 +726,14 @@ void LEX::start(THD *thd_arg)
   safe_to_cache_query= 1;
   parsing_options.reset();
   empty_field_list_on_rset= 0;
-  select_lex.select_number= 1;
+  builtin_select.select_number= 1;
   part_info= 0;
-  select_lex.in_sum_expr=0;
-  select_lex.ftfunc_list_alloc.empty();
-  select_lex.ftfunc_list= &select_lex.ftfunc_list_alloc;
-  select_lex.group_list.empty();
-  select_lex.order_list.empty();
-  select_lex.gorder_list.empty();
+  builtin_select.in_sum_expr=0;
+  builtin_select.ftfunc_list_alloc.empty();
+  builtin_select.ftfunc_list= &builtin_select.ftfunc_list_alloc;
+  builtin_select.group_list.empty();
+  builtin_select.order_list.empty();
+  builtin_select.gorder_list.empty();
   m_sql_cmd= NULL;
   duplicates= DUP_ERROR;
   ignore= 0;
@@ -739,6 +745,8 @@ void LEX::start(THD *thd_arg)
   query_tables= 0;
   reset_query_tables_list(FALSE);
   expr_allows_subselect= TRUE;
+  selects_allow_into= FALSE;
+  selects_allow_procedure= FALSE;
   use_only_table_context= FALSE;
   parse_vcol_expr= FALSE;
   check_exists= FALSE;
@@ -749,7 +757,7 @@ void LEX::start(THD *thd_arg)
   event_parse_data= NULL;
   profile_options= PROFILE_NONE;
   nest_level=0 ;
-  select_lex.nest_level_base= &unit;
+  builtin_select.nest_level_base= &unit;
   allow_sum_func= 0;
   in_sum_func= NULL;
 
@@ -773,6 +781,13 @@ void LEX::start(THD *thd_arg)
   vers_conditions.empty();
 
   is_lex_started= TRUE;
+
+  next_is_main= FALSE;
+  next_is_down= FALSE;
+
+  wild= 0;
+  exchange= 0;
+
   DBUG_VOID_RETURN;
 }
 
@@ -1308,7 +1323,8 @@ int MYSQLlex(YYSTYPE *yylval, THD *thd)
 {
   Lex_input_stream *lip= & thd->m_parser_state->m_lip;
   int token;
-  
+  const int left_paren= (int) '(';
+
   if (lip->lookahead_token >= 0)
   {
     /*
@@ -1375,6 +1391,12 @@ int MYSQLlex(YYSTYPE *yylval, THD *thd)
     }
     break;
   case VALUES:
+    if (thd->lex->current_select &&
+       thd->lex->current_select->parsing_place == BEFORE_OPT_FIELD_LIST)
+    {
+      thd->lex->current_select->parsing_place= NO_MATTER;
+      break;
+    }
     if (thd->lex->current_select->parsing_place == IN_UPDATE_ON_DUP_KEY ||
         thd->lex->current_select->parsing_place == IN_PART_FUNC)
       return VALUE_SYM;
@@ -1391,6 +1413,33 @@ int MYSQLlex(YYSTYPE *yylval, THD *thd)
       lip->lookahead_token= token;
       return VALUES;
     }
+  case PARTITION_SYM:
+  case SELECT_SYM:
+  case UNION_SYM:
+    if (thd->lex->current_select &&
+        thd->lex->current_select->parsing_place == BEFORE_OPT_FIELD_LIST)
+    {
+      thd->lex->current_select->parsing_place= NO_MATTER;
+    }
+    break;
+  case left_paren:
+    if (!thd->lex->current_select ||
+        thd->lex->current_select->parsing_place != BEFORE_OPT_FIELD_LIST)
+      return token;
+    token= lex_one_token(yylval, thd);
+    lip->add_digest_token(token, yylval);
+    lip->lookahead_yylval= lip->yylval;
+    lip->yylval= NULL;
+    lip->lookahead_token= token;
+    thd->lex->current_select->parsing_place= NO_MATTER;
+    if (token == LIKE)
+      return LEFT_PAREN_LIKE;
+    if (token == WITH)
+      return LEFT_PAREN_WITH;
+    if (token != left_paren && token != SELECT_SYM)
+      return LEFT_PAREN_ALT;
+    else
+      return left_paren;
     break;
   default:
     break;
@@ -1888,7 +1937,7 @@ static int lex_one_token(YYSTYPE *yylval, THD *thd)
       return(TEXT_STRING);
     }
     case MY_LEX_COMMENT:			//  Comment
-      lex->select_lex.options|= OPTION_FOUND_COMMENT;
+      lex->builtin_select.options|= OPTION_FOUND_COMMENT;
       while ((c = lip->yyGet()) != '\n' && c) ;
       lip->yyUnget();                   // Safety against eof
       state = MY_LEX_START;		// Try again
@@ -1899,7 +1948,7 @@ static int lex_one_token(YYSTYPE *yylval, THD *thd)
 	state=MY_LEX_CHAR;		// Probable division
 	break;
       }
-      lex->select_lex.options|= OPTION_FOUND_COMMENT;
+      lex->builtin_select.options|= OPTION_FOUND_COMMENT;
       /* Reject '/' '*', since we might need to turn off the echo */
       lip->yyUnget();
 
@@ -2184,7 +2233,8 @@ void st_select_lex_node::init_query_common()
 {
   options= 0;
   sql_cache= SQL_CACHE_UNSPECIFIED;
-  linkage= UNSPECIFIED_TYPE;
+  set_linkage(UNSPECIFIED_TYPE);
+  distinct= TRUE;
   no_table_names_allowed= 0;
   uncacheable= 0;
 }
@@ -2192,7 +2242,7 @@ void st_select_lex_node::init_query_common()
 void st_select_lex_unit::init_query()
 {
   init_query_common();
-  linkage= GLOBAL_OPTIONS_TYPE;
+  set_linkage(GLOBAL_OPTIONS_TYPE);
   select_limit_cnt= HA_POS_ERROR;
   offset_limit_cnt= 0;
   union_distinct= 0;
@@ -2233,16 +2283,6 @@ void st_select_lex::init_query()
   having_fix_field= 0;
   context.select_lex= this;
   context.init();
-  /*
-    Add the name resolution context of the current (sub)query to the
-    stack of contexts for the whole query.
-    TODO:
-    push_context may return an error if there is no memory for a new
-    element in the stack, however this method has no return value,
-    thus push_context should be moved to a place where query
-    initialization is checked for failure.
-  */
-  parent_lex->push_context(&context, parent_lex->thd->mem_root);
   cond_count= between_count= with_wild= 0;
   max_equal_elems= 0;
   ref_pointer_array.reset();
@@ -2297,6 +2337,7 @@ void st_select_lex::init_select()
   /* Set limit and offset to default values */
   select_limit= 0;      /* denotes the default limit = HA_POS_ERROR */
   offset_limit= 0;      /* denotes the default offset = 0 */
+  is_set_query_expr_tail= false;
   with_sum_func= 0;
   is_correlated= 0;
   cur_pos_in_select_list= UNDEF_POS;
@@ -2357,6 +2398,23 @@ void st_select_lex_node::add_slave(st_select_lex_node *slave_arg)
   }
 }
 
+void st_select_lex_node::link_chain_down(st_select_lex_node *first)
+{
+  st_select_lex_node *last_node;
+  st_select_lex_node *node= first;
+  do
+  {
+    last_node= node;
+    node->master= this;
+    node= node->next;
+  } while (node);
+  if ((last_node->next= slave))
+  {
+    slave->prev= &last_node->next;
+  }
+  first->prev= &slave;
+  slave= first;
+}
 
 /*
   include on level down (but do not link)
@@ -2406,7 +2464,7 @@ void st_select_lex_node::fast_exclude()
   // Remove slave structure
   for (; slave; slave= slave->next)
     slave->fast_exclude();
-  
+
 }
 
 
@@ -3083,6 +3141,7 @@ LEX::LEX()
                       gtid_domain_static_buffer,
                       initial_gtid_domain_buffer_size,
                       initial_gtid_domain_buffer_size, 0);
+  unit.slave= &builtin_select;
 }
 
 
@@ -3109,12 +3168,12 @@ bool LEX::can_be_merged()
   // TODO: do not forget implement case when select_lex.table_list.elements==0
 
   /* find non VIEW subqueries/unions */
-  bool selects_allow_merge= (select_lex.next_select() == 0 &&
-                             !(select_lex.uncacheable &
+  bool selects_allow_merge= (first_select_lex()->next_select() == 0 &&
+                             !(first_select_lex()->uncacheable &
                                UNCACHEABLE_RAND));
   if (selects_allow_merge)
   {
-    for (SELECT_LEX_UNIT *tmp_unit= select_lex.first_inner_unit();
+    for (SELECT_LEX_UNIT *tmp_unit= first_select_lex()->first_inner_unit();
          tmp_unit;
          tmp_unit= tmp_unit->next_unit())
     {
@@ -3131,12 +3190,12 @@ bool LEX::can_be_merged()
   }
 
   return (selects_allow_merge &&
-	  select_lex.group_list.elements == 0 &&
-	  select_lex.having == 0 &&
-          select_lex.with_sum_func == 0 &&
-	  select_lex.table_list.elements >= 1 &&
-	  !(select_lex.options & SELECT_DISTINCT) &&
-          select_lex.select_limit == 0);
+	  first_select_lex()->group_list.elements == 0 &&
+	  first_select_lex()->having == 0 &&
+          first_select_lex()->with_sum_func == 0 &&
+	  first_select_lex()->table_list.elements >= 1 &&
+	  !(first_select_lex()->options & SELECT_DISTINCT) &&
+          first_select_lex()->select_limit == 0);
 }
 
 
@@ -3489,7 +3548,7 @@ void LEX::set_trg_event_type_for_tables()
     Do not iterate over sub-selects, only the tables in the outermost
     SELECT_LEX can be modified, if any.
   */
-  TABLE_LIST *tables= select_lex.get_table_list();
+  TABLE_LIST *tables= first_select_lex()->get_table_list();
 
   while (tables)
   {
@@ -3545,12 +3604,13 @@ TABLE_LIST *LEX::unlink_first_table(bool *link_to_local)
     /*
       and from local list if it is not empty
     */
-    if ((*link_to_local= MY_TEST(select_lex.table_list.first)))
+    if ((*link_to_local= MY_TEST(first_select_lex()->table_list.first)))
     {
-      select_lex.context.table_list= 
-        select_lex.context.first_name_resolution_table= first->next_local;
-      select_lex.table_list.first= first->next_local;
-      select_lex.table_list.elements--;	//safety
+      first_select_lex()->context.table_list=
+        first_select_lex()->context.first_name_resolution_table=
+        first->next_local;
+      first_select_lex()->table_list.first= first->next_local;
+      first_select_lex()->table_list.elements--;	//safety
       first->next_local= 0;
       /*
         Ensure that the global list has the same first table as the local
@@ -3581,7 +3641,7 @@ TABLE_LIST *LEX::unlink_first_table(bool *link_to_local)
 
 void LEX::first_lists_tables_same()
 {
-  TABLE_LIST *first_table= select_lex.table_list.first;
+  TABLE_LIST *first_table= first_select_lex()->table_list.first;
   if (query_tables != first_table && first_table != 0)
   {
     TABLE_LIST *next;
@@ -3606,6 +3666,25 @@ void LEX::first_lists_tables_same()
   }
 }
 
+void LEX::fix_first_select_number()
+{
+  SELECT_LEX *first= first_select_lex();
+  if (first && first->select_number != 1)
+  {
+    uint num= first->select_number;
+    for (SELECT_LEX *sel= all_selects_list;
+         sel;
+         sel= sel->next_select_in_list())
+    {
+      if (sel->select_number < num)
+        sel->select_number++;
+      if (sel->select_number > num)
+        sel->select_number--;
+    }
+    first->select_number= 1;
+  }
+}
+
 
 /*
   Link table back that was unlinked with unlink_first_table()
@@ -3631,10 +3710,10 @@ void LEX::link_first_table_back(TABLE_LIST *first,
 
     if (link_to_local)
     {
-      first->next_local= select_lex.table_list.first;
-      select_lex.context.table_list= first;
-      select_lex.table_list.first= first;
-      select_lex.table_list.elements++;	//safety
+      first->next_local= first_select_lex()->table_list.first;
+      first_select_lex()->context.table_list= first;
+      first_select_lex()->table_list.first= first;
+      first_select_lex()->table_list.elements++;	//safety
     }
   }
 }
@@ -3663,19 +3742,19 @@ void LEX::cleanup_after_one_table_open()
     NOTE: all units will be connected to thd->lex->select_lex, because we
     have not UNION on most upper level.
     */
-  if (all_selects_list != &select_lex)
+  if (all_selects_list != first_select_lex())
   {
     derived_tables= 0;
-    select_lex.exclude_from_table_unique_test= false;
+    first_select_lex()->exclude_from_table_unique_test= false;
     /* cleunup underlying units (units of VIEW) */
-    for (SELECT_LEX_UNIT *un= select_lex.first_inner_unit();
+    for (SELECT_LEX_UNIT *un= first_select_lex()->first_inner_unit();
          un;
          un= un->next_unit())
       un->cleanup();
     /* reduce all selects list to default state */
-    all_selects_list= &select_lex;
+    all_selects_list= first_select_lex();
     /* remove underlying units (units of VIEW) subtree */
-    select_lex.cut_subtree();
+    first_select_lex()->cut_subtree();
   }
 }
 
@@ -4541,7 +4620,7 @@ void st_select_lex::set_explain_type(bool on_the_fly)
       using_materialization= TRUE;
   }
 
-  if (&master_unit()->thd->lex->select_lex == this)
+  if (master_unit()->thd->lex->first_select_lex() == this)
   {
      type= is_primary ? "PRIMARY" : "SIMPLE";
   }
@@ -4736,8 +4815,8 @@ bool LEX::save_prep_leaf_tables()
   Query_arena *arena= thd->stmt_arena, backup;
   arena= thd->activate_stmt_arena_if_needed(&backup);
   //It is used for DETETE/UPDATE so top level has only one SELECT
-  DBUG_ASSERT(select_lex.next_select() == NULL);
-  bool res= select_lex.save_prep_leaf_tables(thd);
+  DBUG_ASSERT(first_select_lex()->next_select() == NULL);
+  bool res= first_select_lex()->save_prep_leaf_tables(thd);
 
   if (arena)
     thd->restore_active_arena(arena, &backup);
@@ -5066,8 +5145,13 @@ bool LEX::is_partition_management() const
 
 SELECT_LEX *LEX::exclude_last_select()
 {
-  DBUG_ENTER("SELECT_LEX::exclude_last_select");
-  SELECT_LEX *exclude= current_select;
+  return exclude_not_first_select(current_select);
+}
+
+SELECT_LEX *LEX::exclude_not_first_select(SELECT_LEX *exclude)
+{
+  DBUG_ENTER("LEX::exclude_not_first_select");
+  DBUG_PRINT("enter", ("exclude %p #%u", exclude, exclude->select_number));
   SELECT_LEX_UNIT *unit= exclude->master_unit();
   SELECT_LEX *sl;
   DBUG_ASSERT(unit->first_select() != exclude);
@@ -5078,13 +5162,228 @@ SELECT_LEX *LEX::exclude_last_select()
   DBUG_PRINT("info", ("excl: %p  unit: %p  prev: %p", exclude, unit, sl));
   if (!sl)
     DBUG_RETURN(NULL);
-  DBUG_ASSERT(exclude->next_select() == NULL);
-  exclude->exclude_from_tree();
+  DBUG_ASSERT(&sl->next == exclude->prev);
+
+  exclude->prev= NULL;
+
   current_select= sl;
   DBUG_RETURN(exclude);
 }
 
 
+SELECT_LEX_UNIT *LEX::alloc_unit()
+{
+  SELECT_LEX_UNIT *unit;
+  DBUG_ENTER("LEX::alloc_unit");
+  if (!(unit= new (thd->mem_root) SELECT_LEX_UNIT()))
+    DBUG_RETURN(NULL);
+
+  unit->init_query();
+  /* TODO: reentrant problem */
+  unit->thd= thd;
+  unit->link_next= 0;
+  unit->link_prev= 0;
+  /* TODO: remove return_to */
+  unit->return_to= NULL;
+  DBUG_RETURN(unit);
+}
+
+
+SELECT_LEX *LEX::alloc_select(bool select)
+{
+  SELECT_LEX *select_lex;
+  DBUG_ENTER("LEX::alloc_select");
+  if (!(select_lex= new (thd->mem_root) SELECT_LEX()))
+    DBUG_RETURN(NULL);
+  DBUG_PRINT("info", ("Allocate select: %p #%u  statement lex: %p",
+                      select_lex, thd->stmt_lex->current_select_number,
+                      thd->stmt_lex));
+  select_lex->select_number= ++thd->stmt_lex->current_select_number;
+  select_lex->parent_lex= this; /* Used in init_query. */
+  select_lex->init_query();
+  if (select)
+    select_lex->init_select();
+  select_lex->nest_level_base= &this->unit;
+  select_lex->include_global((st_select_lex_node**)&all_selects_list);
+  select_lex->context.resolve_in_select_list= TRUE;
+  DBUG_RETURN(select_lex);
+}
+
+SELECT_LEX_UNIT *
+LEX::create_unit(SELECT_LEX *first_sel)
+{
+  SELECT_LEX_UNIT *unit;
+  DBUG_ENTER("LEX::create_unit");
+
+  if (!(unit= alloc_unit()))
+    DBUG_RETURN(NULL);
+
+  unit->register_select_chain(first_sel);
+  if (first_sel->next_select())
+  {
+    unit->reset_distinct();
+    DBUG_ASSERT(!unit->fake_select_lex);
+    if (unit->add_fake_select_lex(thd))
+      DBUG_RETURN(NULL);
+  }
+  DBUG_RETURN(unit);
+}
+
+SELECT_LEX_UNIT *
+SELECT_LEX::attach_selects_chain(SELECT_LEX *first_sel,
+                                 Name_resolution_context *context)
+{
+  SELECT_LEX_UNIT *unit;
+  DBUG_ENTER("SELECT_LEX::attach_select_chain");
+
+  if (!(unit= parent_lex->alloc_unit()))
+    DBUG_RETURN(NULL);
+
+  unit->register_select_chain(first_sel);
+  register_unit(unit, context);
+  if (first_sel->next_select())
+  {
+    unit->reset_distinct();
+    DBUG_ASSERT(!unit->fake_select_lex);
+    if (unit->add_fake_select_lex(parent_lex->thd))
+      DBUG_RETURN(NULL);
+  }
+
+  DBUG_RETURN(unit);
+}
+
+SELECT_LEX *
+LEX::wrap_unit_into_derived(SELECT_LEX_UNIT *unit)
+{
+  SELECT_LEX *wrapping_sel;
+  Table_ident *ti;
+  DBUG_ENTER("LEX::wrap_unit_into_derived");
+
+  if (!(wrapping_sel= alloc_select(TRUE)))
+    DBUG_RETURN(NULL);
+  Name_resolution_context *context= &wrapping_sel->context;
+  context->init();
+  wrapping_sel->automatic_brackets= FALSE;
+
+  wrapping_sel->register_unit(unit, context);
+
+  /* stuff dummy SELECT * FROM (...) */
+
+  if (push_select(wrapping_sel)) // for Items & TABLE_LIST
+    DBUG_RETURN(NULL);
+
+  /* add SELECT list*/
+  {
+    Item *item= new (thd->mem_root)
+      Item_field(thd, context, NULL, NULL, &star_clex_str);
+    if (item == NULL)
+      goto err;
+    if (add_item_to_list(thd, item))
+      goto err;
+    (wrapping_sel->with_wild)++;
+  }
+
+  unit->first_select()->set_linkage(DERIVED_TABLE_TYPE);
+
+  ti= new (thd->mem_root) Table_ident(unit);
+  if (ti == NULL)
+    goto err;
+  {
+    char buff[10];
+    TABLE_LIST *table_list;
+    LEX_CSTRING alias;
+    alias.length= my_snprintf(buff, sizeof(buff),
+                              "__%u", wrapping_sel->select_number);
+    alias.str= thd->strmake(buff, alias.length);
+    if (!alias.str)
+      goto err;
+
+    if (!(table_list= wrapping_sel->add_table_to_list(thd, ti, &alias,
+                                                      0, TL_READ,
+                                                      MDL_SHARED_READ)))
+      goto err;
+
+    context->resolve_in_table_list_only(table_list);
+    wrapping_sel->add_joined_table(table_list);
+  }
+
+  pop_select();
+
+  derived_tables|= DERIVED_SUBQUERY;
+
+  DBUG_RETURN(wrapping_sel);
+
+err:
+  pop_select();
+  DBUG_RETURN(NULL);
+}
+
+SELECT_LEX *LEX::link_selects_chain_down(SELECT_LEX *sel)
+{
+  SELECT_LEX *dummy_select;
+  SELECT_LEX_UNIT *unit;
+  Table_ident *ti;
+  DBUG_ENTER("LEX::link_selects_chain_down");
+
+  if (!(dummy_select= alloc_select(TRUE)))
+     DBUG_RETURN(NULL);
+  Name_resolution_context *context= &dummy_select->context;
+  dummy_select->automatic_brackets= FALSE;
+
+  if (!(unit= dummy_select->attach_selects_chain(sel, context)))
+    DBUG_RETURN(NULL);
+
+  /* stuff dummy SELECT * FROM (...) */
+
+  if (push_select(dummy_select)) // for Items & TABLE_LIST
+    DBUG_RETURN(NULL);
+
+  /* add SELECT list*/
+  {
+    Item *item= new (thd->mem_root)
+      Item_field(thd, context, NULL, NULL, &star_clex_str);
+    if (item == NULL)
+      goto err;
+    if (add_item_to_list(thd, item))
+      goto err;
+    (dummy_select->with_wild)++;
+  }
+
+  sel->set_linkage(DERIVED_TABLE_TYPE);
+
+  ti= new (thd->mem_root) Table_ident(unit);
+  if (ti == NULL)
+    goto err;
+  {
+    char buff[10];
+    TABLE_LIST *table_list;
+    LEX_CSTRING alias;
+    alias.length= my_snprintf(buff, sizeof(buff),
+                              "__%u", dummy_select->select_number);
+    alias.str= thd->strmake(buff, alias.length);
+    if (!alias.str)
+      goto err;
+
+    if (!(table_list= dummy_select->add_table_to_list(thd, ti, &alias,
+                                                      0, TL_READ,
+                                                      MDL_SHARED_READ)))
+      goto err;
+
+    context->resolve_in_table_list_only(table_list);
+    dummy_select->add_joined_table(table_list);
+  }
+
+  pop_select();
+
+  derived_tables|= DERIVED_SUBQUERY;
+
+  DBUG_RETURN(dummy_select);
+
+err:
+  pop_select();
+  DBUG_RETURN(NULL);
+}
+
 /**
   Put given (new) SELECT_LEX level below after currect (last) SELECT
 
@@ -5107,13 +5406,43 @@ SELECT_LEX *LEX::exclude_last_select()
 bool LEX::add_unit_in_brackets(SELECT_LEX *nselect)
 {
   DBUG_ENTER("LEX::add_unit_in_brackets");
-  bool distinct= nselect->master_unit()->union_distinct == nselect;
-  bool rc= add_select_to_union_list(distinct, nselect->linkage, 0);
-  if (rc)
+  SELECT_LEX_UNIT *unit= nselect->master_unit();
+  int old_nest_level= nselect->nest_level;
+  bool distinct= unit->union_distinct == nselect;
+  if (add_select_to_union_list(distinct, nselect->linkage, 0))
     DBUG_RETURN(TRUE);
-  SELECT_LEX* dummy_select= current_select;
-  dummy_select->automatic_brackets= TRUE;
-  dummy_select->linkage= nselect->linkage;
+
+  SELECT_LEX *dummy= current_select;
+  dummy->next= NULL;
+  if (make_select_in_brackets(current_select, nselect, FALSE))
+    DBUG_RETURN(TRUE);
+
+  if (!distinct && nselect->master_unit()->union_distinct)
+  {
+    // move distinct pointer
+    if (unit->union_distinct->master_unit() != unit)
+    {
+      unit->union_distinct->master_unit()->union_distinct= unit->union_distinct;
+      unit->union_distinct= NULL;
+    }
+  }
+  else if (distinct)
+    unit->union_distinct= NULL;// distinct was moved by add_select_to_union_list
+
+  dummy->set_nest_level(old_nest_level);
+  DBUG_RETURN(FALSE);
+}
+
+
+bool LEX::make_select_in_brackets(SELECT_LEX* dummy_select,
+                                  SELECT_LEX *nselect, bool automatic)
+{
+  DBUG_ENTER("LEX::make_select_in_brackets");
+
+  int old_nest_level= nselect->nest_level;
+  dummy_select->automatic_brackets= automatic;
+  dummy_select->set_linkage(nselect->linkage);
+  current_select= dummy_select; // for mysql_new_select & Items
 
   /* stuff dummy SELECT * FROM (...) */
   Name_resolution_context *context= &dummy_select->context;
@@ -5128,12 +5457,19 @@ bool LEX::add_unit_in_brackets(SELECT_LEX *nselect)
     DBUG_RETURN(TRUE);
   (dummy_select->with_wild)++;
 
-  rc= mysql_new_select(this, 1, nselect);
-  nselect->linkage= DERIVED_TABLE_TYPE;
-  DBUG_ASSERT(nselect->outer_select() == dummy_select);
+  nselect->set_linkage(DERIVED_TABLE_TYPE);
+  SELECT_LEX *sl= nselect;
+  bool down= TRUE;
+  do{
+    SELECT_LEX *next= sl->next_select();
+    if (mysql_new_select(this, down, sl))
+      DBUG_RETURN(TRUE);
+    down= FALSE;
+    DBUG_ASSERT(sl->outer_select() == dummy_select);
+    sl= next;
+  } while (sl);
 
   current_select= dummy_select;
-  current_select->nest_level--;
 
   SELECT_LEX_UNIT *unit= nselect->master_unit();
   Table_ident *ti= new (thd->mem_root) Table_ident(unit);
@@ -5157,12 +5493,63 @@ bool LEX::add_unit_in_brackets(SELECT_LEX *nselect)
 
   derived_tables|= DERIVED_SUBQUERY;
 
+  if (dummy_select->set_nest_level(old_nest_level))
+    DBUG_RETURN(TRUE);
+
   current_select= nselect;
-  current_select->nest_level++;
-  DBUG_RETURN(rc);
+  DBUG_RETURN(FALSE);
+}
+
+bool LEX::push_context(Name_resolution_context *context)
+{
+  DBUG_ENTER("LEX::push_context");
+  DBUG_PRINT("info", ("Context: %p Select: %p (%d)",
+                       context, context->select_lex,
+                       (context->select_lex ?
+                        context->select_lex->select_number:
+                        0)));
+  bool res= context_stack.push_front(context, thd->mem_root);
+  DBUG_RETURN(res);
+}
+
+
+bool LEX::push_new_select(SELECT_LEX *last)
+{
+  DBUG_ENTER("LEX::push new_select");
+  DBUG_PRINT("info", ("Push last select: %p (%d)",
+                       last, last->select_number));
+  bool res= last_select_stack.push_front(last, thd->mem_root);
+  DBUG_RETURN(res);
+}
+
+
+bool check_intersect_prefix(SELECT_LEX* first_in_unit)
+{
+  SELECT_LEX *sel;
+  for (sel= first_in_unit->next_select();
+       sel && sel->linkage == INTERSECT_TYPE;
+       sel= sel->next_select())
+    ;
+  return (sel == NULL);
 }
 
 
+SELECT_LEX *LEX::pop_new_select_and_wrap()
+{
+  DBUG_ENTER("LEX::pop_new_select_and_wrap");
+  SELECT_LEX *sel;
+  SELECT_LEX *last= pop_new_select();
+  SELECT_LEX *first= last->next_select();
+  last->cut_next();
+  enum sub_select_type op= first->linkage;
+  bool ds= first->distinct;
+  if (!(sel= link_selects_chain_down(first)))
+      DBUG_RETURN(NULL);
+  last->link_neighbour(sel);
+  sel->set_linkage_and_distinct(op, ds);
+  DBUG_RETURN(sel);
+}
+
 /**
   Checks if we need finish "automatic brackets" mode
 
@@ -6559,7 +6946,6 @@ Item_param *LEX::add_placeholder(THD *thd, const LEX_CSTRING *name,
     my_error(ER_VIEW_SELECT_VARIABLE, MYF(0));
     return NULL;
   }
-
   Query_fragment pos(thd, sphead, start, end);
   Item_param *item= new (thd->mem_root) Item_param(thd, name,
                                                    pos.pos(), pos.length());
@@ -7410,6 +7796,156 @@ Item *st_select_lex::build_cond_for_grouping_fields(THD *thd, Item *cond,
 }
 
 
+bool st_select_lex::set_nest_level(int new_nest_level)
+{
+  DBUG_ENTER("st_select_lex::set_nest_level");
+  DBUG_PRINT("enter", ("select #%d %p nest level: %d",
+                       select_number, this, new_nest_level));
+  if (new_nest_level > (int) MAX_SELECT_NESTING)
+  {
+    my_error(ER_TOO_HIGH_LEVEL_OF_NESTING_FOR_SELECT, MYF(0));
+    DBUG_RETURN(TRUE);
+  }
+  nest_level= new_nest_level;
+  new_nest_level++;
+  for (SELECT_LEX_UNIT *u= first_inner_unit(); u; u= u->next_unit())
+  {
+    if (u->set_nest_level(new_nest_level))
+      DBUG_RETURN(TRUE);
+  }
+  DBUG_RETURN(FALSE);
+}
+
+bool st_select_lex_unit::set_nest_level(int new_nest_level)
+{
+  DBUG_ENTER("st_select_lex_unit::set_nest_level");
+  for(SELECT_LEX *sl= first_select(); sl; sl= sl->next_select())
+  {
+    if (sl->set_nest_level(new_nest_level))
+      DBUG_RETURN(TRUE);
+  }
+  if (fake_select_lex &&
+      fake_select_lex->set_nest_level(new_nest_level))
+    DBUG_RETURN(TRUE);
+  DBUG_RETURN(FALSE);
+}
+
+
+bool st_select_lex::check_parameters(SELECT_LEX *main_select)
+{
+  DBUG_ENTER("st_select_lex::check_parameters");
+  DBUG_PRINT("enter", ("select #%d %p nest level: %d",
+                       select_number, this, nest_level));
+
+
+  if ((options & OPTION_INTO_CLAUSE) &&
+       (!parent_lex->selects_allow_into ||
+        next_select() != NULL ||
+        nest_level != 1))
+  {
+    my_error(ER_CANT_USE_OPTION_HERE, MYF(0), "INTO");
+    DBUG_RETURN(TRUE);
+  }
+
+  if (options & OPTION_PROCEDURE_CLAUSE)
+  {
+    if (!parent_lex->selects_allow_procedure ||
+        next_select() != NULL ||
+        this != master_unit()->first_select() ||
+        nest_level != 1)
+    {
+      my_error(ER_CANT_USE_OPTION_HERE, MYF(0), "PROCEDURE");
+      DBUG_RETURN(TRUE);
+    }
+    if (options & OPTION_INTO_CLAUSE)
+    {
+      my_error(ER_CANT_USE_OPTION_HERE, MYF(0), "INTO");
+      DBUG_RETURN(TRUE);
+    }
+  }
+
+  if ((options & SELECT_HIGH_PRIORITY) && this != main_select)
+  {
+    my_error(ER_CANT_USE_OPTION_HERE, MYF(0), "HIGH_PRIORITY");
+    DBUG_RETURN(TRUE);
+  }
+  if ((options & OPTION_BUFFER_RESULT) && this != main_select)
+  {
+    my_error(ER_CANT_USE_OPTION_HERE, MYF(0), "SQL_BUFFER_RESULT");
+    DBUG_RETURN(TRUE);
+  }
+  if ((options & OPTION_FOUND_ROWS) && this != main_select)
+  {
+    my_error(ER_CANT_USE_OPTION_HERE, MYF(0), "SQL_CALC_FOUND_ROWS");
+    DBUG_RETURN(TRUE);
+  }
+  if (options & OPTION_NO_QUERY_CACHE)
+  {
+    /*
+      Allow this flag only on the first top-level SELECT statement, if
+      SQL_CACHE wasn't specified.
+    */
+    if (this != main_select)
+    {
+      my_error(ER_CANT_USE_OPTION_HERE, MYF(0), "SQL_NO_CACHE");
+      DBUG_RETURN(TRUE);
+    }
+    if (main_select->sql_cache == SELECT_LEX::SQL_CACHE)
+    {
+      my_error(ER_WRONG_USAGE, MYF(0), "SQL_CACHE", "SQL_NO_CACHE");
+      DBUG_RETURN(TRUE);
+    }
+    parent_lex->safe_to_cache_query=0;
+    main_select->sql_cache= SELECT_LEX::SQL_NO_CACHE;
+  }
+  if (options & OPTION_TO_QUERY_CACHE)
+  {
+    /*
+      Allow this flag only on the first top-level SELECT statement, if
+      SQL_NO_CACHE wasn't specified.
+    */
+    if (this != main_select)
+    {
+      my_error(ER_CANT_USE_OPTION_HERE, MYF(0), "SQL_CACHE");
+      DBUG_RETURN(TRUE);
+    }
+    if (main_select->sql_cache == SELECT_LEX::SQL_NO_CACHE)
+    {
+      my_error(ER_WRONG_USAGE, MYF(0), "SQL_NO_CACHE", "SQL_CACHE");
+      DBUG_RETURN(TRUE);
+    }
+    parent_lex->safe_to_cache_query=1;
+    main_select->sql_cache= SELECT_LEX::SQL_CACHE;
+  }
+
+  for (SELECT_LEX_UNIT *u= first_inner_unit(); u; u= u->next_unit())
+  {
+    if (u->check_parameters(main_select))
+      DBUG_RETURN(TRUE);
+  }
+  DBUG_RETURN(FALSE);
+}
+
+
+bool st_select_lex_unit::check_parameters(SELECT_LEX *main_select)
+{
+  for(SELECT_LEX *sl= first_select(); sl; sl= sl->next_select())
+  {
+    if (sl->check_parameters(main_select))
+      return TRUE;
+  }
+  return fake_select_lex && fake_select_lex->check_parameters(main_select);
+}
+
+
+bool LEX::check_main_unit_semantics()
+{
+  if (unit.set_nest_level(1) ||
+      unit.check_parameters(first_select_lex()))
+    return TRUE;
+  return FALSE;
+}
+
 int set_statement_var_if_exists(THD *thd, const char *var_name,
                                 size_t var_name_length, ulonglong value)
 {
@@ -7477,10 +8013,10 @@ bool LEX::create_or_alter_view_finalize(THD *thd, Table_ident *table_ident)
 {
   sql_command= SQLCOM_CREATE_VIEW;
   /* first table in list is target VIEW name */
-  if (!select_lex.add_table_to_list(thd, table_ident, NULL,
-                                    TL_OPTION_UPDATING,
-                                    TL_IGNORE,
-                                    MDL_EXCLUSIVE))
+  if (!first_select_lex()->add_table_to_list(thd, table_ident, NULL,
+                                             TL_OPTION_UPDATING,
+                                             TL_IGNORE,
+                                             MDL_EXCLUSIVE))
     return true;
   query_tables->open_strategy= TABLE_LIST::OPEN_STUB;
   return false;
@@ -7765,3 +8301,225 @@ Item *Lex_trim_st::make_item_func_trim(THD *thd) const
          make_item_func_trim_oracle(thd) :
          make_item_func_trim_std(thd);
 }
+
+
+void st_select_lex_unit::reset_distinct()
+{
+  union_distinct= NULL;
+  for(SELECT_LEX *sl= first_select()->next_select();
+      sl;
+      sl= sl->next_select())
+  {
+    if (sl->distinct)
+    {
+      union_distinct= sl;
+      return;
+    }
+  }
+}
+
+
+void st_select_lex_unit::fix_distinct(st_select_lex_unit *new_unit)
+{
+  if (union_distinct)
+  {
+    if (this != union_distinct->master_unit())
+    {
+      DBUG_ASSERT(new_unit == union_distinct->master_unit());
+      new_unit->union_distinct= union_distinct;
+      reset_distinct();
+    }
+    else
+      new_unit->reset_distinct();
+  }
+}
+
+
+void st_select_lex_unit::register_select_chain(SELECT_LEX *first_sel)
+{
+  DBUG_ASSERT(first_sel != 0);
+  slave= first_sel;
+  first_sel->prev= &slave;
+  for(SELECT_LEX *sel=first_sel; sel; sel= sel->next_select())
+  {
+    sel->master= (st_select_lex_node *)this;
+    uncacheable|= sel->uncacheable;
+  }
+}
+
+
+void st_select_lex::register_unit(SELECT_LEX_UNIT *unit,
+                                  Name_resolution_context *outer_context)
+{
+  if ((unit->next= slave))
+    slave->prev= &unit->next;
+  unit->prev= &slave;
+  slave= unit;
+  unit->master= this;
+  uncacheable|= unit->uncacheable;
+
+  for(SELECT_LEX *sel= unit->first_select();sel; sel= sel->next_select())
+  {
+    sel->context.outer_context= outer_context;
+  }
+}
+
+
+void st_select_lex::add_statistics(SELECT_LEX_UNIT *unit)
+{
+  for (;
+       unit;
+       unit= unit->next_unit())
+    for(SELECT_LEX *child= unit->first_select();
+        child;
+        child= child->next_select())
+    {
+      /*
+        A subselect can add fields to an outer select.
+        Reserve space for them.
+      */
+      select_n_where_fields+= child->select_n_where_fields;
+      /*
+        Aggregate functions in having clause may add fields
+        to an outer select. Count them also.
+      */
+      select_n_having_items+= child->select_n_having_items;
+    }
+}
+
+
+bool LEX::main_select_push()
+{
+  DBUG_ENTER("LEX::main_select_push");
+  current_select_number= 1;
+  builtin_select.select_number= 1;
+  if (push_select(&builtin_select))
+    DBUG_RETURN(TRUE);
+  DBUG_RETURN(FALSE);
+}
+
+bool Lex_order_limit_lock::set_to(SELECT_LEX *sel)
+{
+  /*TODO: lock */
+  //if (lock.defined_lock && sel == sel->master_unit()->fake_select_lex)
+  //  return TRUE;
+  if (lock.defined_timeout)
+  {
+    THD *thd= sel->parent_lex->thd;
+     if (set_statement_var_if_exists(thd,
+                                     C_STRING_WITH_LEN("lock_wait_timeout"),
+                                     lock.timeout) ||
+         set_statement_var_if_exists(thd,
+                                     C_STRING_WITH_LEN("innodb_lock_wait_timeout"),
+                                     lock.timeout))
+       return TRUE;
+  }
+  if (lock.defined_lock)
+  {
+    sel->parent_lex->safe_to_cache_query= 0;
+    if (lock.update_lock)
+    {
+      sel->lock_type= TL_WRITE;
+      sel->set_lock_for_tables(TL_WRITE);
+    }
+    else
+    {
+      sel->lock_type= TL_READ_WITH_SHARED_LOCKS;
+      sel->set_lock_for_tables(TL_READ_WITH_SHARED_LOCKS);
+    }
+  }
+  sel->explicit_limit= limit.explicit_limit;
+  sel->select_limit= limit.select_limit;
+  sel->offset_limit= limit.offset_limit;
+  if (order_list)
+  {
+    if (sel->linkage != GLOBAL_OPTIONS_TYPE &&
+        sel->olap != UNSPECIFIED_OLAP_TYPE &&
+        (sel->linkage != UNION_TYPE || sel->braces))
+    {
+      my_error(ER_WRONG_USAGE, MYF(0),
+          "CUBE/ROLLUP", "ORDER BY");
+      return TRUE;
+    }
+    sel->order_list= *(order_list);
+  }
+  sel->is_set_query_expr_tail= true;
+  return FALSE;
+}
+
+
+static void change_item_list_context(List<Item> *list,
+                                     Name_resolution_context *context)
+{
+  List_iterator_fast<Item> it (*list);
+  Item *item;
+  while((item= it++))
+  {
+    item->walk(&Item::change_context_processor, FALSE, (void *)context);
+  }
+}
+
+
+bool LEX::insert_select_hack(SELECT_LEX *sel)
+{
+  DBUG_ENTER("LEX::insert_select_hack");
+
+  DBUG_ASSERT(first_select_lex() == &builtin_select);
+  DBUG_ASSERT(sel != NULL);
+
+  if (builtin_select.first_inner_unit())
+  {
+    sel->link_chain_down(builtin_select.first_inner_unit());
+    builtin_select.slave= NULL;
+  }
+
+  if (builtin_select.link_prev)
+  {
+    if ((*builtin_select.link_prev= builtin_select.link_next))
+      ((st_select_lex *)builtin_select.link_next)->link_prev=
+        builtin_select.link_prev;
+    builtin_select.link_prev= NULL; // indicator of removal
+  }
+
+  set_main_unit(sel->master_unit());
+
+  DBUG_ASSERT(builtin_select.table_list.elements == 1);
+  TABLE_LIST *insert_table= builtin_select.table_list.first;
+
+  if (!(insert_table->next_local= sel->table_list.first))
+  {
+    sel->table_list.next= &insert_table->next_local;
+  }
+  sel->table_list.first= insert_table;
+  sel->table_list.elements++;
+  insert_table->select_lex= sel;
+
+  sel->context.first_name_resolution_table= insert_table;
+  builtin_select.context= sel->context;
+  change_item_list_context(&field_list, &sel->context);
+
+  if (sel->tvc && !sel->next_select() &&
+      (sql_command == SQLCOM_INSERT_SELECT ||
+       sql_command == SQLCOM_REPLACE_SELECT))
+  {
+    DBUG_PRINT("info", ("'Unual' INSERT detected"));
+    many_values= sel->tvc->lists_of_values;
+    sel->options= sel->tvc->select_options;
+    sel->tvc= NULL;
+    if (sql_command == SQLCOM_INSERT_SELECT)
+      sql_command= SQLCOM_INSERT;
+    else
+      sql_command= SQLCOM_REPLACE;
+  }
+
+
+  for (SELECT_LEX *sel= all_selects_list;
+       sel;
+       sel= sel->next_select_in_list())
+  {
+    if (sel->select_number != 1)
+      sel->select_number--;
+  };
+
+  DBUG_RETURN(FALSE);
+}
diff --git a/sql/sql_lex.h b/sql/sql_lex.h
index 59088e867d1..724559acb4d 100644
--- a/sql/sql_lex.h
+++ b/sql/sql_lex.h
@@ -74,6 +74,16 @@ enum sub_select_type
   UNION_TYPE, INTERSECT_TYPE, EXCEPT_TYPE,
   GLOBAL_OPTIONS_TYPE, DERIVED_TABLE_TYPE, OLAP_TYPE
 };
+
+inline int cmp_unit_op(enum sub_select_type op1, enum sub_select_type op2)
+{
+  DBUG_ASSERT(op1 >= UNION_TYPE && op1 <= EXCEPT_TYPE);
+  DBUG_ASSERT(op2 >= UNION_TYPE && op2 <= EXCEPT_TYPE);
+  return (op1 == INTERSECT_TYPE ? 1 : 0) - (op2 == INTERSECT_TYPE ? 1 : 0);
+}
+
+bool check_intersect_prefix(SELECT_LEX* first_in_unit);
+
 enum unit_common_op {OP_MIX, OP_UNION, OP_INTERSECT, OP_EXCEPT};
 
 enum enum_view_suid
@@ -193,6 +203,7 @@ struct LEX_TYPE
   additional "partitions" column even if partitioning is not compiled in.
 */
 #define DESCRIBE_PARTITIONS	4
+#define DESCRIBE_EXTENDED2	8
 
 #ifdef MYSQL_SERVER
 
@@ -431,7 +442,7 @@ class Index_hint : public Sql_alloc
    unit is container of either
      - One SELECT
      - UNION of selects
-   select_lex and unit are both inherited form select_lex_node
+   select_lex and unit are both inherited form st_select_lex_node
    neighbors are two select_lex or units on the same level
 
    All select describing structures linked with following pointers:
@@ -577,6 +588,7 @@ class st_select_lex_node {
   {
     return linkage == UNION_TYPE || linkage == INTERSECT_TYPE || linkage == EXCEPT_TYPE;
   }
+  bool distinct;
   bool no_table_names_allowed; /* used for global order by */
 
   static void *operator new(size_t size, MEM_ROOT *mem_root) throw ()
@@ -597,10 +609,29 @@ class st_select_lex_node {
   void include_down(st_select_lex_node *upper);
   void add_slave(st_select_lex_node *slave_arg);
   void include_neighbour(st_select_lex_node *before);
+  void link_chain_down(st_select_lex_node *first);
+  void link_neighbour(st_select_lex_node *neighbour)
+  {
+    DBUG_ASSERT(next == NULL);
+    DBUG_ASSERT(neighbour != NULL);
+    next= neighbour;
+    neighbour->prev= &next;
+  }
+  void cut_next() { next= NULL; }
   void include_standalone(st_select_lex_node *sel, st_select_lex_node **ref);
   void include_global(st_select_lex_node **plink);
   void exclude();
   void exclude_from_tree();
+  void exclude_from_global()
+  {
+    if (!link_prev)
+      return;
+    if (((*link_prev)= link_next))
+      link_next->link_prev= link_prev;
+    link_next= NULL;
+    link_prev= NULL;
+  }
+
 
   void set_slave(st_select_lex_node *slave_arg) { slave= slave_arg; }
   void move_node(st_select_lex_node *where_to_move)
@@ -616,6 +647,22 @@ class st_select_lex_node {
   st_select_lex_node *insert_chain_before(st_select_lex_node **ptr_pos_to_insert,
                                           st_select_lex_node *end_chain_node);
   void move_as_slave(st_select_lex_node *new_master);
+  void set_linkage(enum sub_select_type l)
+  {
+    DBUG_ENTER("st_select_lex_node::set_linkage");
+    DBUG_PRINT("info", ("node: %p  linkage: %d->%d", this, linkage, l));
+    linkage= l;
+    DBUG_VOID_RETURN;
+  }
+  /*
+    This method created for reiniting LEX in mysql_admin_table() and can be
+    used only if you are going remove all SELECT_LEX & units except belonger
+    to LEX (LEX::unit & LEX::select, for other purposes there are
+    SELECT_LEX_UNIT::exclude_level & SELECT_LEX_UNIT::exclude_tree.
+
+    It is also used in parsing to detach builtin select.
+  */
+  void cut_subtree() { slave= 0; }
   friend class st_select_lex_unit;
   friend bool mysql_new_select(LEX *lex, bool move_down, SELECT_LEX *sel);
   friend bool mysql_make_view(THD *thd, TABLE_SHARE *share, TABLE_LIST *table,
@@ -625,6 +672,8 @@ class st_select_lex_node {
   friend bool mysql_derived_merge(THD *thd, LEX *lex,
                                   TABLE_LIST *orig_table_list);
   friend bool TABLE_LIST::init_derived(THD *thd, bool init_view);
+
+  friend class st_select_lex;
 private:
   void fast_exclude();
 };
@@ -670,9 +719,9 @@ class st_select_lex_unit: public st_select_lex_node {
   {
   }
 
-
   TABLE *table; /* temporary table using for appending UNION results */
   select_result *result;
+  st_select_lex *pre_last_parse;
   bool  prepared, // prepare phase already performed for UNION (unit)
     optimized, // optimize phase already performed for UNION (unit)
     optimized_2,
@@ -759,7 +808,7 @@ class st_select_lex_unit: public st_select_lex_node {
   {
     return reinterpret_cast<st_select_lex*>(slave);
   }
-  inline void set_with_clause(With_clause *with_cl);
+  void set_with_clause(With_clause *with_cl);
   st_select_lex_unit* next_unit()
   {
     return reinterpret_cast<st_select_lex_unit*>(next);
@@ -801,6 +850,16 @@ class st_select_lex_unit: public st_select_lex_node {
   int save_union_explain(Explain_query *output);
   int save_union_explain_part2(Explain_query *output);
   unit_common_op common_op();
+
+  void reset_distinct();
+  void fix_distinct(st_select_lex_unit *new_unit);
+
+  void register_select_chain(SELECT_LEX *first_sel);
+
+  bool set_nest_level(int new_nest_level);
+  bool check_parameters(SELECT_LEX *main_select);
+
+  friend class st_select_lex;
 };
 
 typedef class st_select_lex_unit SELECT_LEX_UNIT;
@@ -922,6 +981,7 @@ class st_select_lex: public st_select_lex_node
   SQL_I_List<ORDER> order_list;   /* ORDER clause */
   SQL_I_List<ORDER> gorder_list;
   Item *select_limit, *offset_limit;  /* LIMIT clause parameters */
+  bool is_set_query_expr_tail;
 
   /// Array of pointers to top elements of all_fields list
   Ref_ptr_array ref_pointer_array;
@@ -1051,6 +1111,10 @@ class st_select_lex: public st_select_lex_node
   void init_query();
   void init_select();
   st_select_lex_unit* master_unit() { return (st_select_lex_unit*) master; }
+  inline void set_master_unit(st_select_lex_unit *master_unit)
+  {
+    master= (st_select_lex_node *)master_unit;
+  }
   st_select_lex_unit* first_inner_unit() 
   { 
     return (st_select_lex_unit*) slave; 
@@ -1283,6 +1347,32 @@ class st_select_lex: public st_select_lex_node
     DBUG_ASSERT(this != sel);
     select_n_where_fields+= sel->select_n_where_fields;
   }
+  inline void set_linkage_and_distinct(enum sub_select_type l, bool d)
+  {
+    DBUG_ENTER("SELECT_LEX::set_linkage_and_distinct");
+    DBUG_PRINT("info", ("select: %p  distinct %d", this, d));
+    set_linkage(l);
+    DBUG_ASSERT(l == UNION_TYPE ||
+                l == INTERSECT_TYPE ||
+                l == EXCEPT_TYPE);
+    if (d && master_unit() && master_unit()->union_distinct != this)
+      master_unit()->union_distinct= this;
+    distinct= d;
+    DBUG_VOID_RETURN;
+  }
+  bool set_nest_level(int new_nest_level);
+  bool check_parameters(SELECT_LEX *main_select);
+  void mark_select()
+  {
+    DBUG_ENTER("st_select_lex::mark_select()");
+    DBUG_PRINT("info", ("Select #%d", select_number));
+    DBUG_VOID_RETURN;
+  }
+  void register_unit(SELECT_LEX_UNIT *unit,
+                     Name_resolution_context *outer_context);
+  SELECT_LEX_UNIT *attach_selects_chain(SELECT_LEX *sel,
+                                        Name_resolution_context *context);
+  void add_statistics(SELECT_LEX_UNIT *unit);
 };
 typedef class st_select_lex SELECT_LEX;
 
@@ -2676,7 +2766,8 @@ class Query_arena_memroot;
 struct LEX: public Query_tables_list
 {
   SELECT_LEX_UNIT unit;                         /* most upper unit */
-  SELECT_LEX select_lex;                        /* first SELECT_LEX */
+  inline SELECT_LEX *first_select_lex() {return unit.first_select();}
+  SELECT_LEX builtin_select;
   /* current SELECT_LEX in parsing */
   SELECT_LEX *current_select;
   /* list of all SELECT_LEX */
@@ -2786,6 +2877,9 @@ struct LEX: public Query_tables_list
     required a local context, the parser pops the top-most context.
   */
   List<Name_resolution_context> context_stack;
+  List<SELECT_LEX> last_select_stack;
+  SELECT_LEX *select_stack[MAX_SELECT_NESTING];
+  uint select_stack_top;
 
   SQL_I_List<ORDER> proc_list;
   SQL_I_List<TABLE_LIST> auxiliary_table_list, save_list;
@@ -2825,6 +2919,8 @@ struct LEX: public Query_tables_list
     syntax error back.
   */
   bool expr_allows_subselect;
+  bool selects_allow_into;
+  bool selects_allow_procedure;
   /*
     A special command "PARSE_VCOL_EXPR" is defined for the parser 
     to translate a defining expression of a virtual column into an 
@@ -2879,6 +2975,8 @@ struct LEX: public Query_tables_list
   enum enum_yes_no_unknown tx_chain, tx_release;
   bool safe_to_cache_query;
   bool subqueries, ignore;
+  bool next_is_main; // use "main" SELECT_LEX for nrxt allocation;
+  bool next_is_down; // use "main" SELECT_LEX for nrxt allocation;
   st_parsing_options parsing_options;
   Alter_info alter_info;
   /*
@@ -3080,20 +3178,24 @@ struct LEX: public Query_tables_list
       SELECT_LEX *sl;
       SELECT_LEX_UNIT *un;
       for (sl= current_select, un= sl->master_unit();
-          un != &unit;
-          sl= sl->outer_select(), un= sl->master_unit())
+           un && un != &unit;
+           sl= sl->outer_select(), un= (sl ? sl->master_unit() : NULL))
       {
-        sl->uncacheable|= cause;
-        un->uncacheable|= cause;
+       sl->uncacheable|= cause;
+       un->uncacheable|= cause;
       }
-      select_lex.uncacheable|= cause;
+      if (sl)
+        sl->uncacheable|= cause;
     }
+    if (first_select_lex())
+      first_select_lex()->uncacheable|= cause;
   }
   void set_trg_event_type_for_tables();
 
   TABLE_LIST *unlink_first_table(bool *link_to_local);
   void link_first_table_back(TABLE_LIST *first, bool link_to_local);
   void first_lists_tables_same();
+  void fix_first_select_number();
 
   bool can_be_merged();
   bool can_use_merged();
@@ -3131,14 +3233,90 @@ struct LEX: public Query_tables_list
 
   void cleanup_after_one_table_open();
 
-  bool push_context(Name_resolution_context *context, MEM_ROOT *mem_root)
+  bool push_context(Name_resolution_context *context);
+
+  void pop_context()
   {
-    return context_stack.push_front(context, mem_root);
+    DBUG_ENTER("LEX::pop_context");
+    Name_resolution_context *context= context_stack.pop();
+    DBUG_PRINT("info", ("Pop context %p Select: %p (%d)",
+                         context, context->select_lex,
+                         (context->select_lex ?
+                          context->select_lex->select_number:
+                          0)));
+    DBUG_VOID_RETURN;
   }
 
-  void pop_context()
+  bool push_new_select(SELECT_LEX *last);
+
+  SELECT_LEX *pop_new_select()
+  {
+    DBUG_ENTER("LEX::pop_new_select");
+    SELECT_LEX* last= last_select_stack.pop();
+    DBUG_PRINT("info", ("Pop last elect: %p (%d)",
+                         last, last->select_number));
+    DBUG_RETURN(last);
+  }
+
+  SELECT_LEX *select_stack_head()
+  {
+    if (likely(select_stack_top))
+      return select_stack[select_stack_top - 1];
+    return NULL;
+  }
+
+
+  bool push_select(SELECT_LEX *select_lex)
+  {
+    DBUG_ENTER("LEX::push_select");
+    DBUG_PRINT("info", ("Top Select was %p (%d)  depth: %u  pushed: %p (%d)",
+                        select_stack_head(),
+                        select_stack_top,
+                        (select_stack_top ?
+                         select_stack_head()->select_number :
+                         0),
+                        select_lex, select_lex->select_number));
+    if (unlikely(select_stack_top == MAX_SELECT_NESTING))
+    {
+      my_error(ER_TOO_HIGH_LEVEL_OF_NESTING_FOR_SELECT, MYF(0));
+      DBUG_RETURN(TRUE);
+    }
+    if (push_context(&select_lex->context))
+      DBUG_RETURN(TRUE);
+    select_stack[select_stack_top++]= select_lex;
+    current_select= select_lex;
+    DBUG_RETURN(FALSE);
+  }
+
+  SELECT_LEX *pop_select()
   {
-    context_stack.pop();
+    DBUG_ENTER("LEX::pop_select");
+    SELECT_LEX *select_lex;
+    if (likely(select_stack_top))
+      select_lex= select_stack[--select_stack_top];
+    else
+      select_lex= 0;
+    DBUG_PRINT("info", ("Top Select is %p (%d)  depth: %u  poped: %p (%d)",
+                        select_stack_head(),
+                        select_stack_top,
+                        (select_stack_top ?
+                         select_stack_head()->select_number :
+                         0),
+                        select_lex,
+                        (select_lex ? select_lex->select_number : 0)));
+    DBUG_ASSERT(select_lex);
+
+    pop_context();
+
+    if (unlikely(!select_stack_top))
+    {
+      current_select= NULL;
+      DBUG_PRINT("info", ("Top Select is empty"));
+    }
+    else
+      current_select= select_stack[select_stack_top - 1];
+
+    DBUG_RETURN(select_lex);
   }
 
   bool copy_db_to(LEX_CSTRING *to);
@@ -3172,9 +3350,8 @@ struct LEX: public Query_tables_list
       on its top. So select_lex (as the first added) will be at the tail 
       of the list.
     */ 
-    if (&select_lex == all_selects_list && !sroutines.records)
+    if (first_select_lex() == all_selects_list && !sroutines.records)
     {
-      DBUG_ASSERT(!all_selects_list->next_select_in_list());
       return TRUE;
     }
     return FALSE;
@@ -3743,6 +3920,7 @@ struct LEX: public Query_tables_list
   bool if_exists() const { return create_info.if_exists(); }
 
   SELECT_LEX *exclude_last_select();
+  SELECT_LEX *exclude_not_first_select(SELECT_LEX *exclude);
   bool add_unit_in_brackets(SELECT_LEX *nselect);
   void check_automatic_up(enum sub_select_type type);
   bool create_or_alter_view_finalize(THD *thd, Table_ident *table_ident);
@@ -3751,7 +3929,6 @@ struct LEX: public Query_tables_list
   bool add_create_view(THD *thd, DDL_options_st ddl,
                        uint16 algorithm, enum_view_suid suid,
                        Table_ident *table_ident);
-
   bool add_grant_command(THD *thd, enum_sql_command sql_command_arg,
                          stored_procedure_type type_arg);
 
@@ -3760,6 +3937,31 @@ struct LEX: public Query_tables_list
     return create_info.vers_info;
   }
   sp_package *get_sp_package() const;
+
+  bool make_select_in_brackets(SELECT_LEX* dummy_select,
+                               SELECT_LEX *nselect, bool automatic);
+
+  SELECT_LEX_UNIT *alloc_unit();
+  SELECT_LEX *alloc_select(bool is_select);
+  SELECT_LEX_UNIT *create_unit(SELECT_LEX*);
+  SELECT_LEX *wrap_unit_into_derived(SELECT_LEX_UNIT *unit);
+  SELECT_LEX *link_selects_chain_down(SELECT_LEX *sel);
+  bool main_select_push();
+  bool insert_select_hack(SELECT_LEX *sel);
+  SELECT_LEX *pop_new_select_and_wrap();
+
+  void set_main_unit(st_select_lex_unit *u)
+  {
+    unit.options= u->options;
+    unit.uncacheable= u->uncacheable;
+    unit.register_select_chain(u->first_select());
+    unit.first_select()->options|= builtin_select.options;
+    unit.fake_select_lex= u->fake_select_lex;
+    unit.union_distinct= u->union_distinct;
+    unit.set_with_clause(u->with_clause);
+    builtin_select.exclude_from_global();
+  }
+  bool check_main_unit_semantics();
 };
 
 
diff --git a/sql/sql_load.cc b/sql/sql_load.cc
index cfa92f170ab..c81a8203be9 100644
--- a/sql/sql_load.cc
+++ b/sql/sql_load.cc
@@ -390,10 +390,13 @@ int mysql_load(THD *thd, const sql_exchange *ex, TABLE_LIST *table_list,
   if (mysql_handle_single_derived(thd->lex, table_list, DT_MERGE_FOR_INSERT) ||
       mysql_handle_single_derived(thd->lex, table_list, DT_PREPARE))
     DBUG_RETURN(TRUE);
-  if (setup_tables_and_check_access(thd, &thd->lex->select_lex.context,
-                                    &thd->lex->select_lex.top_join_list,
+  if (setup_tables_and_check_access(thd,
+                                    &thd->lex->first_select_lex()->context,
+                                    &thd->lex->first_select_lex()->
+                                      top_join_list,
                                     table_list,
-                                    thd->lex->select_lex.leaf_tables, FALSE,
+                                    thd->lex->first_select_lex()->leaf_tables,
+                                    FALSE,
                                     INSERT_ACL | UPDATE_ACL,
                                     INSERT_ACL | UPDATE_ACL, FALSE))
      DBUG_RETURN(-1);
diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc
index b89d78874f5..4ac1f59dcc1 100644
--- a/sql/sql_parse.cc
+++ b/sql/sql_parse.cc
@@ -2000,10 +2000,10 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
       Init TABLE_LIST members necessary when the undelrying
       table is view.
     */
-    table_list.select_lex= &(thd->lex->select_lex);
+    table_list.select_lex= thd->lex->first_select_lex();
     thd->lex->
-      select_lex.table_list.link_in_list(&table_list,
-                                         &table_list.next_local);
+      first_select_lex()->table_list.link_in_list(&table_list,
+                                                  &table_list.next_local);
     thd->lex->add_to_query_tables(&table_list);
 
     if (is_infoschema_db(&table_list.db))
@@ -2566,23 +2566,24 @@ int prepare_schema_table(THD *thd, LEX *lex, Table_ident *table_ident,
     DBUG_RETURN(1);
 #else
     {
-      if (lex->select_lex.db.str == NULL &&
-          lex->copy_db_to(&lex->select_lex.db))
+      if (lex->first_select_lex()->db.str == NULL &&
+          lex->copy_db_to(&lex->first_select_lex()->db))
       {
         DBUG_RETURN(1);
       }
       schema_select_lex= new (thd->mem_root) SELECT_LEX();
       schema_select_lex->table_list.first= NULL;
       if (lower_case_table_names == 1)
-        lex->select_lex.db.str= thd->strdup(lex->select_lex.db.str);
-      schema_select_lex->db= lex->select_lex.db;
+        lex->first_select_lex()->db.str=
+          thd->strdup(lex->first_select_lex()->db.str);
+      schema_select_lex->db= lex->first_select_lex()->db;
       /*
         check_db_name() may change db.str if lower_case_table_names == 1,
         but that's ok as the db is allocted above in this case.
       */
-      if (check_db_name((LEX_STRING*) &lex->select_lex.db))
+      if (check_db_name((LEX_STRING*) &lex->first_select_lex()->db))
       {
-        my_error(ER_WRONG_DB_NAME, MYF(0), lex->select_lex.db.str);
+        my_error(ER_WRONG_DB_NAME, MYF(0), lex->first_select_lex()->db.str);
         DBUG_RETURN(1);
       }
       break;
@@ -2621,7 +2622,8 @@ int prepare_schema_table(THD *thd, LEX *lex, Table_ident *table_ident,
   default:
     break;
   }
-  
+  if (schema_select_lex)
+    schema_select_lex->set_master_unit(&lex->unit);
   SELECT_LEX *select_lex= lex->current_select;
   if (make_schema_select(thd, select_lex, get_schema_table(schema_table_idx)))
     DBUG_RETURN(1);
@@ -3223,7 +3225,7 @@ mysql_execute_command(THD *thd)
   int  up_result= 0;
   LEX  *lex= thd->lex;
   /* first SELECT_LEX (have special meaning for many of non-SELECTcommands) */
-  SELECT_LEX *select_lex= &lex->select_lex;
+  SELECT_LEX *select_lex= lex->first_select_lex();
   /* first table of first SELECT_LEX */
   TABLE_LIST *first_table= select_lex->table_list.first;
   /* list of all tables in query */
@@ -3266,6 +3268,7 @@ mysql_execute_command(THD *thd)
     DBUG_ASSERT(first_table == all_tables && first_table != 0);
   */
   lex->first_lists_tables_same();
+  lex->fix_first_select_number();
   /* should be assigned after making first tables same */
   all_tables= lex->query_tables;
   /* set context for commands which do not use setup_tables */
@@ -7551,7 +7554,7 @@ void THD::reset_for_next_command(bool do_clear_error)
     We also assign stmt_lex in lex_start(), but during bootstrap this
     code is executed first.
   */
-  stmt_lex= &main_lex; stmt_lex->current_select_number= 1;
+  stmt_lex= &main_lex; stmt_lex->current_select_number= 0;
   DBUG_PRINT("info", ("Lex %p stmt_lex: %p", lex, stmt_lex));
   /*
     Those two lines below are theoretically unneeded as
@@ -7639,11 +7642,7 @@ mysql_init_select(LEX *lex)
   SELECT_LEX *select_lex= lex->current_select;
   select_lex->init_select();
   lex->wild= 0;
-  if (select_lex == &lex->select_lex)
-  {
-    DBUG_ASSERT(lex->result == 0);
-    lex->exchange= 0;
-  }
+  lex->exchange= 0;
 }
 
 
@@ -7664,6 +7663,7 @@ mysql_new_select(LEX *lex, bool move_down, SELECT_LEX *select_lex)
 {
   THD *thd= lex->thd;
   bool new_select= select_lex == NULL;
+  int old_nest_level= lex->current_select->nest_level;
   DBUG_ENTER("mysql_new_select");
 
   if (new_select)
@@ -7675,27 +7675,19 @@ mysql_new_select(LEX *lex, bool move_down, SELECT_LEX *select_lex)
     select_lex->init_query();
     select_lex->init_select();
   }
-  lex->nest_level++;
-  if (lex->nest_level > (int) MAX_SELECT_NESTING)
-  {
-    my_error(ER_TOO_HIGH_LEVEL_OF_NESTING_FOR_SELECT, MYF(0));
-    DBUG_RETURN(1);
-  }
-  select_lex->nest_level= lex->nest_level;
   select_lex->nest_level_base= &thd->lex->unit;
   if (move_down)
   {
+    lex->nest_level++;
+    if (select_lex->set_nest_level(old_nest_level + 1))
+      DBUG_RETURN(1);
     SELECT_LEX_UNIT *unit;
     lex->subqueries= TRUE;
     /* first select_lex of subselect or derived table */
-    if (!(unit= new (thd->mem_root) SELECT_LEX_UNIT()))
+    if (!(unit= lex->alloc_unit()))
       DBUG_RETURN(1);
 
-    unit->init_query();
-    unit->thd= thd;
     unit->include_down(lex->current_select);
-    unit->link_next= 0;
-    unit->link_prev= 0;
     unit->return_to= lex->current_select;
     select_lex->include_down(unit);
     /*
@@ -7729,15 +7721,13 @@ mysql_new_select(LEX *lex, bool move_down, SELECT_LEX *select_lex)
                "SELECT ... PROCEDURE ANALYSE()");
       DBUG_RETURN(TRUE);
     }
-    // SELECT 1 FROM t1 ORDER BY 1 UNION SELECT 1 FROM t1 -- not possible
-    DBUG_ASSERT(!lex->current_select->order_list.first ||
-                lex->current_select->braces);
-    // SELECT 1 FROM t1 LIMIT 1 UNION SELECT 1 FROM t1;   -- not possible
-    DBUG_ASSERT(!lex->current_select->explicit_limit ||
-                lex->current_select->braces);
 
+    SELECT_LEX_NODE *save_slave= select_lex->slave;
     select_lex->include_neighbour(lex->current_select);
-    SELECT_LEX_UNIT *unit= select_lex->master_unit();                              
+    select_lex->slave= save_slave;
+    SELECT_LEX_UNIT *unit= select_lex->master_unit();
+    if (select_lex->set_nest_level(old_nest_level))
+      DBUG_RETURN(1);
     if (!unit->fake_select_lex && unit->add_fake_select_lex(lex->thd))
       DBUG_RETURN(1);
     select_lex->context.outer_context= 
@@ -7793,9 +7783,10 @@ void mysql_init_multi_delete(LEX *lex)
 {
   lex->sql_command=  SQLCOM_DELETE_MULTI;
   mysql_init_select(lex);
-  lex->select_lex.select_limit= 0;
+  lex->first_select_lex()->select_limit= 0;
   lex->unit.select_limit_cnt= HA_POS_ERROR;
-  lex->select_lex.table_list.save_and_clear(&lex->auxiliary_table_list);
+  lex->first_select_lex()->table_list.
+    save_and_clear(&lex->auxiliary_table_list);
   lex->query_tables= 0;
   lex->query_tables_last= &lex->query_tables;
 }
@@ -8080,7 +8071,7 @@ bool mysql_test_parse_for_slave(THD *thd, char *rawbuf, uint length)
     thd->reset_for_next_command();
 
     if (!parse_sql(thd, & parser_state, NULL, true) &&
-        all_tables_not_ok(thd, lex->select_lex.table_list.first))
+        all_tables_not_ok(thd, lex->first_select_lex()->table_list.first))
       error= 1;                  /* Ignore question */
     thd->end_statement();
   }
@@ -8162,6 +8153,10 @@ TABLE_LIST *st_select_lex::add_table_to_list(THD *thd,
   LEX_CSTRING alias_str;
   LEX *lex= thd->lex;
   DBUG_ENTER("add_table_to_list");
+  DBUG_PRINT("enter", ("Table '%s' (%p)  Select %p (%u)",
+                        (alias ? alias->str : table->table.str),
+                        table,
+                        this, select_number));
 
   if (!table)
     DBUG_RETURN(0);				// End of memory
@@ -8255,7 +8250,7 @@ TABLE_LIST *st_select_lex::add_table_to_list(THD *thd,
     ptr->schema_table_name= ptr->table_name;
     ptr->schema_table= schema_table;
   }
-  ptr->select_lex=  lex->current_select;
+  ptr->select_lex= this;
   /*
     We can't cache internal temporary tables between prepares as the
     table may be deleted before next exection.
@@ -8361,7 +8356,6 @@ bool st_select_lex::init_nested_join(THD *thd)
   nested_join= ptr->nested_join=
     ((NESTED_JOIN*) ((uchar*) ptr + ALIGN_SIZE(sizeof(TABLE_LIST))));
 
-  join_list->push_front(ptr, thd->mem_root);
   ptr->embedding= embedding;
   ptr->join_list= join_list;
   ptr->alias.str="(nested_join)";
@@ -8469,7 +8463,6 @@ TABLE_LIST *st_select_lex::nest_last_join(THD *thd)
         ptr->join_using_fields= prev_join_using;
     }
   }
-  join_list->push_front(ptr, thd->mem_root);
   nested_join->used_tables= nested_join->not_null_tables= (table_map) 0;
   DBUG_RETURN(ptr);
 }
@@ -8661,7 +8654,7 @@ void st_select_lex::set_lock_for_tables(thr_lock_type lock_type)
 bool st_select_lex_unit::add_fake_select_lex(THD *thd_arg)
 {
   SELECT_LEX *first_sl= first_select();
-  DBUG_ENTER("add_fake_select_lex");
+  DBUG_ENTER("st_select_lex_unit::add_fake_select_lex");
   DBUG_ASSERT(!fake_select_lex);
 
   if (!(fake_select_lex= new (thd_arg->mem_root) SELECT_LEX()))
@@ -8671,16 +8664,19 @@ bool st_select_lex_unit::add_fake_select_lex(THD *thd_arg)
   fake_select_lex->select_number= INT_MAX;
   fake_select_lex->parent_lex= thd_arg->lex; /* Used in init_query. */
   fake_select_lex->make_empty_select();
-  fake_select_lex->linkage= GLOBAL_OPTIONS_TYPE;
+  fake_select_lex->set_linkage(GLOBAL_OPTIONS_TYPE);
   fake_select_lex->select_limit= 0;
 
+  fake_select_lex->no_table_names_allowed= 1;
+
   fake_select_lex->context.outer_context=first_sl->context.outer_context;
   /* allow item list resolving in fake select for ORDER BY */
   fake_select_lex->context.resolve_in_select_list= TRUE;
   fake_select_lex->context.select_lex= fake_select_lex;  
 
   fake_select_lex->nest_level_base= first_select()->nest_level_base;
-  fake_select_lex->nest_level=first_select()->nest_level;
+  if (fake_select_lex->set_nest_level(first_select()->nest_level))
+    DBUG_RETURN(1);
 
   if (!is_unit_op())
   {
@@ -8693,7 +8689,7 @@ bool st_select_lex_unit::add_fake_select_lex(THD *thd_arg)
     fake_select_lex->no_table_names_allowed= 1;
     thd_arg->lex->current_select= fake_select_lex;
   }
-  thd_arg->lex->pop_context();
+  //thd_arg->lex->pop_context("add fake");
   DBUG_RETURN(0);
 }
 
@@ -8729,7 +8725,7 @@ push_new_name_resolution_context(THD *thd,
     left_op->first_leaf_for_name_resolution();
   on_context->last_name_resolution_table=
     right_op->last_leaf_for_name_resolution();
-  return thd->lex->push_context(on_context, thd->mem_root);
+  return thd->lex->push_context(on_context);
 }
 
 
@@ -9084,7 +9080,7 @@ bool check_simple_select()
 {
   THD *thd= current_thd;
   LEX *lex= thd->lex;
-  if (lex->current_select != &lex->select_lex)
+  if (lex->current_select != lex->first_select_lex())
   {
     char command[80];
     Lex_input_stream *lip= & thd->m_parser_state->m_lip;
@@ -9183,7 +9179,7 @@ bool multi_update_precheck(THD *thd, TABLE_LIST *tables)
 {
   TABLE_LIST *table;
   LEX *lex= thd->lex;
-  SELECT_LEX *select_lex= &lex->select_lex;
+  SELECT_LEX *select_lex= lex->first_select_lex();
   DBUG_ENTER("multi_update_precheck");
 
   if (select_lex->item_list.elements != lex->value_list.elements)
@@ -9219,7 +9215,7 @@ bool multi_update_precheck(THD *thd, TABLE_LIST *tables)
   /*
     Is there tables of subqueries?
   */
-  if (&lex->select_lex != lex->all_selects_list)
+  if (lex->first_select_lex() != lex->all_selects_list)
   {
     DBUG_PRINT("info",("Checking sub query list"));
     for (table= tables; table; table= table->next_global)
@@ -9253,7 +9249,7 @@ bool multi_update_precheck(THD *thd, TABLE_LIST *tables)
 
 bool multi_delete_precheck(THD *thd, TABLE_LIST *tables)
 {
-  SELECT_LEX *select_lex= &thd->lex->select_lex;
+  SELECT_LEX *select_lex= thd->lex->first_select_lex();
   TABLE_LIST *aux_tables= thd->lex->auxiliary_table_list.first;
   TABLE_LIST **save_query_tables_own_last= thd->lex->query_tables_own_last;
   DBUG_ENTER("multi_delete_precheck");
@@ -9370,7 +9366,7 @@ static TABLE_LIST *multi_delete_table_match(LEX *lex, TABLE_LIST *tbl,
 
 bool multi_delete_set_locks_and_link_aux_tables(LEX *lex)
 {
-  TABLE_LIST *tables= lex->select_lex.table_list.first;
+  TABLE_LIST *tables= lex->first_select_lex()->table_list.first;
   TABLE_LIST *target_tbl;
   DBUG_ENTER("multi_delete_set_locks_and_link_aux_tables");
 
@@ -9412,7 +9408,8 @@ bool multi_delete_set_locks_and_link_aux_tables(LEX *lex)
 bool update_precheck(THD *thd, TABLE_LIST *tables)
 {
   DBUG_ENTER("update_precheck");
-  if (thd->lex->select_lex.item_list.elements != thd->lex->value_list.elements)
+  if (thd->lex->first_select_lex()->item_list.elements !=
+      thd->lex->value_list.elements)
   {
     my_message(ER_WRONG_VALUE_COUNT, ER_THD(thd, ER_WRONG_VALUE_COUNT), MYF(0));
     DBUG_RETURN(TRUE);
@@ -9503,7 +9500,7 @@ void create_table_set_open_action_and_adjust_tables(LEX *lex)
   else
     create_table->open_type= OT_BASE_ONLY;
 
-  if (!lex->select_lex.item_list.elements)
+  if (!lex->first_select_lex()->item_list.elements)
   {
     /*
       Avoid opening and locking target table for ordinary CREATE TABLE
@@ -9534,7 +9531,7 @@ bool create_table_precheck(THD *thd, TABLE_LIST *tables,
                            TABLE_LIST *create_table)
 {
   LEX *lex= thd->lex;
-  SELECT_LEX *select_lex= &lex->select_lex;
+  SELECT_LEX *select_lex= lex->first_select_lex();
   ulong want_priv;
   bool error= TRUE;                                 // Error message is given
   DBUG_ENTER("create_table_precheck");
@@ -10044,6 +10041,7 @@ bool parse_sql(THD *thd, Parser_state *parser_state,
          ((thd->variables.sql_mode & MODE_ORACLE) ?
           ORAparse(thd) :
           MYSQLparse(thd)) != 0;
+  thd->lex->current_select= thd->lex->first_select_lex();
 
   /*
     Check that if MYSQLparse() failed either thd->is_error() is set, or an
diff --git a/sql/sql_partition.cc b/sql/sql_partition.cc
index 09c59c862ad..ef226526e8c 100644
--- a/sql/sql_partition.cc
+++ b/sql/sql_partition.cc
@@ -833,7 +833,8 @@ static bool fix_fields_part_func(THD *thd, Item* func_expr, TABLE *table,
     goto end;
   table->get_fields_in_item_tree= true;
 
-  func_expr->walk(&Item::change_context_processor, 0, &lex.select_lex.context);
+  func_expr->walk(&Item::change_context_processor, 0,
+                  &lex.first_select_lex()->context);
   thd->where= "partition function";
   /*
     In execution we must avoid the use of thd->change_item_tree since
diff --git a/sql/sql_partition_admin.cc b/sql/sql_partition_admin.cc
index 6e176a40e6c..b4a42dd6bb2 100644
--- a/sql/sql_partition_admin.cc
+++ b/sql/sql_partition_admin.cc
@@ -51,7 +51,7 @@ bool Sql_cmd_alter_table_exchange_partition::execute(THD *thd)
   /* Moved from mysql_execute_command */
   LEX *lex= thd->lex;
   /* first SELECT_LEX (have special meaning for many of non-SELECTcommands) */
-  SELECT_LEX *select_lex= &lex->select_lex;
+  SELECT_LEX *select_lex= lex->first_select_lex();
   /* first table of first SELECT_LEX */
   TABLE_LIST *first_table= (TABLE_LIST*) select_lex->table_list.first;
   /*
@@ -735,7 +735,7 @@ bool Sql_cmd_alter_table_truncate_partition::execute(THD *thd)
   int error;
   ha_partition *partition;
   ulong timeout= thd->variables.lock_wait_timeout;
-  TABLE_LIST *first_table= thd->lex->select_lex.table_list.first;
+  TABLE_LIST *first_table= thd->lex->first_select_lex()->table_list.first;
   Alter_info *alter_info= &thd->lex->alter_info;
   uint table_counter, i;
   List<String> partition_names_list;
diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc
index 24f3cc66c6b..bdc817b7432 100644
--- a/sql/sql_prepare.cc
+++ b/sql/sql_prepare.cc
@@ -1340,7 +1340,7 @@ static int mysql_test_update(Prepared_statement *stmt,
   THD *thd= stmt->thd;
   uint table_count= 0;
   TABLE_LIST *update_source_table;
-  SELECT_LEX *select= &stmt->lex->select_lex;
+  SELECT_LEX *select= stmt->lex->first_select_lex();
 #ifndef NO_EMBEDDED_ACCESS_CHECKS
   uint          want_privilege;
 #endif
@@ -1396,10 +1396,10 @@ static int mysql_test_update(Prepared_statement *stmt,
   table_list->table->grant.want_privilege= want_privilege;
   table_list->register_want_access(want_privilege);
 #endif
-  thd->lex->select_lex.no_wrap_view_item= TRUE;
+  thd->lex->first_select_lex()->no_wrap_view_item= TRUE;
   res= setup_fields(thd, Ref_ptr_array(),
                     select->item_list, MARK_COLUMNS_READ, 0, NULL, 0);
-  thd->lex->select_lex.no_wrap_view_item= FALSE;
+  thd->lex->first_select_lex()->no_wrap_view_item= FALSE;
   if (res)
     goto error;
 #ifndef NO_EMBEDDED_ACCESS_CHECKS
@@ -1464,10 +1464,10 @@ static bool mysql_test_delete(Prepared_statement *stmt,
     goto error;
   }
 
-  DBUG_RETURN(mysql_prepare_delete(thd, table_list, 
-                                   lex->select_lex.with_wild, 
-                                   lex->select_lex.item_list,
-                                   &lex->select_lex.where,
+  DBUG_RETURN(mysql_prepare_delete(thd, table_list,
+                                   lex->first_select_lex()->with_wild,
+                                   lex->first_select_lex()->item_list,
+                                   &lex->first_select_lex()->where,
                                    &delete_while_scanning));
 error:
   DBUG_RETURN(TRUE);
@@ -1499,7 +1499,7 @@ static int mysql_test_select(Prepared_statement *stmt,
   SELECT_LEX_UNIT *unit= &lex->unit;
   DBUG_ENTER("mysql_test_select");
 
-  lex->select_lex.context.resolve_in_select_list= TRUE;
+  lex->first_select_lex()->context.resolve_in_select_list= TRUE;
 
   ulong privilege= lex->exchange ? SELECT_ACL | FILE_ACL : SELECT_ACL;
   if (tables)
@@ -1533,7 +1533,7 @@ static int mysql_test_select(Prepared_statement *stmt,
   if (!lex->describe && !thd->lex->analyze_stmt && !stmt->is_sql_prepare())
   {
     /* Make copy of item list, as change_columns may change it */
-    List<Item> fields(lex->select_lex.item_list);
+    List<Item> fields(lex->first_select_lex()->item_list);
 
     /* Change columns if a procedure like analyse() */
     if (unit->last_procedure && unit->last_procedure->change_columns(thd, fields))
@@ -1691,7 +1691,7 @@ static bool select_like_stmt_test(Prepared_statement *stmt,
   THD *thd= stmt->thd;
   LEX *lex= stmt->lex;
 
-  lex->select_lex.context.resolve_in_select_list= TRUE;
+  lex->first_select_lex()->context.resolve_in_select_list= TRUE;
 
   if (specific_prepare && (*specific_prepare)(thd))
     DBUG_RETURN(TRUE);
@@ -1759,7 +1759,7 @@ static bool mysql_test_create_table(Prepared_statement *stmt)
   DBUG_ENTER("mysql_test_create_table");
   THD *thd= stmt->thd;
   LEX *lex= stmt->lex;
-  SELECT_LEX *select_lex= &lex->select_lex;
+  SELECT_LEX *select_lex= lex->first_select_lex();
   bool res= FALSE;
   bool link_to_local;
   TABLE_LIST *create_table= lex->query_tables;
@@ -2079,7 +2079,7 @@ static bool mysql_test_multidelete(Prepared_statement *stmt,
 {
   THD *thd= stmt->thd;
 
-  thd->lex->current_select= &thd->lex->select_lex;
+  thd->lex->current_select= thd->lex->first_select_lex();
   if (add_item_to_list(thd, new (thd->mem_root)
                        Item_null(thd)))
   {
@@ -2118,13 +2118,14 @@ static bool mysql_test_multidelete(Prepared_statement *stmt,
 
 static int mysql_insert_select_prepare_tester(THD *thd)
 {
-  SELECT_LEX *first_select= &thd->lex->select_lex;
+  SELECT_LEX *first_select= thd->lex->first_select_lex();
   TABLE_LIST *second_table= first_select->table_list.first->next_local;
 
   /* Skip first table, which is the table we are inserting in */
   first_select->table_list.first= second_table;
-  thd->lex->select_lex.context.table_list=
-    thd->lex->select_lex.context.first_name_resolution_table= second_table;
+  thd->lex->first_select_lex()->context.table_list=
+    thd->lex->first_select_lex()->context.first_name_resolution_table=
+    second_table;
 
   return mysql_insert_select_prepare(thd);
 }
@@ -2159,7 +2160,7 @@ static bool mysql_test_insert_select(Prepared_statement *stmt,
     return 1;
 
   /* store it, because mysql_insert_select_prepare_tester change it */
-  first_local_table= lex->select_lex.table_list.first;
+  first_local_table= lex->first_select_lex()->table_list.first;
   DBUG_ASSERT(first_local_table != 0);
 
   res=
@@ -2167,7 +2168,7 @@ static bool mysql_test_insert_select(Prepared_statement *stmt,
                                     &mysql_insert_select_prepare_tester,
                                     OPTION_SETUP_TABLES_DONE);
   /* revert changes  made by mysql_insert_select_prepare_tester */
-  lex->select_lex.table_list.first= first_local_table;
+  lex->first_select_lex()->table_list.first= first_local_table;
   return res;
 }
 
@@ -2193,7 +2194,7 @@ static int mysql_test_handler_read(Prepared_statement *stmt,
   SQL_HANDLER *ha_table;
   DBUG_ENTER("mysql_test_handler_read");
 
-  lex->select_lex.context.resolve_in_select_list= TRUE;
+  lex->first_select_lex()->context.resolve_in_select_list= TRUE;
 
   /*
     We don't have to test for permissions as this is already done during
@@ -2202,7 +2203,7 @@ static int mysql_test_handler_read(Prepared_statement *stmt,
   if (!(ha_table= mysql_ha_read_prepare(thd, tables, lex->ha_read_mode,
                                         lex->ident.str,
                                         lex->insert_list,
-                                        lex->select_lex.where)))
+                                        lex->first_select_lex()->where)))
     DBUG_RETURN(1);
 
   if (!stmt->is_sql_prepare())
@@ -2241,7 +2242,7 @@ static bool check_prepared_statement(Prepared_statement *stmt)
 {
   THD *thd= stmt->thd;
   LEX *lex= stmt->lex;
-  SELECT_LEX *select_lex= &lex->select_lex;
+  SELECT_LEX *select_lex= lex->first_select_lex();
   TABLE_LIST *tables;
   enum enum_sql_command sql_command= lex->sql_command;
   int res= 0;
@@ -2250,10 +2251,11 @@ static bool check_prepared_statement(Prepared_statement *stmt)
                       sql_command, stmt->param_count));
 
   lex->first_lists_tables_same();
+  lex->fix_first_select_number();
   tables= lex->query_tables;
 
   /* set context for commands which do not use setup_tables */
-  lex->select_lex.context.resolve_in_table_list_only(select_lex->
+  lex->first_select_lex()->context.resolve_in_table_list_only(select_lex->
                                                      get_table_list());
 
   /* Reset warning count for each query that uses tables */
@@ -2999,7 +3001,7 @@ void reinit_stmt_before_use(THD *thd, LEX *lex)
   {
     tables->reinit_before_use(thd);
   }
-  lex->current_select= &lex->select_lex;
+  lex->current_select= lex->first_select_lex();
 
 
   if (lex->result)
@@ -4535,8 +4537,8 @@ bool Prepared_statement::validate_metadata(Prepared_statement *copy)
   if (is_sql_prepare() || lex->describe)
     return FALSE;
 
-  if (lex->select_lex.item_list.elements !=
-      copy->lex->select_lex.item_list.elements)
+  if (lex->first_select_lex()->item_list.elements !=
+      copy->lex->first_select_lex()->item_list.elements)
   {
     /** Column counts mismatch, update the client */
     thd->server_status|= SERVER_STATUS_METADATA_CHANGED;
diff --git a/sql/sql_priv.h b/sql/sql_priv.h
index ba37d933f12..ef8cb39f0ff 100644
--- a/sql/sql_priv.h
+++ b/sql/sql_priv.h
@@ -184,6 +184,9 @@
 #define OPTION_SKIP_REPLICATION         (1ULL << 37) // THD, user
 #define OPTION_RPL_SKIP_PARALLEL        (1ULL << 38)
 #define OPTION_FOUND_COMMENT            (1ULL << 39) // SELECT, intern, parser
+#define OPTION_NO_QUERY_CACHE           (1ULL << 40) // SELECT, user
+#define OPTION_INTO_CLAUSE              (1ULL << 41) // Internal usage
+#define OPTION_PROCEDURE_CLAUSE         (1ULL << 42) // Internal usage
 
 /* The rest of the file is included in the server only */
 #ifndef MYSQL_CLIENT
@@ -356,6 +359,7 @@ enum enum_parsing_place
   IN_ORDER_BY,
   IN_UPDATE_ON_DUP_KEY,
   IN_PART_FUNC,
+  BEFORE_OPT_FIELD_LIST,
   PARSING_PLACE_SIZE /* always should be the last */
 };
 
diff --git a/sql/sql_profile.cc b/sql/sql_profile.cc
index 13f03fed5f3..6ca21aebb37 100644
--- a/sql/sql_profile.cc
+++ b/sql/sql_profile.cc
@@ -110,7 +110,7 @@ int make_profile_table_for_show(THD *thd, ST_SCHEMA_TABLE *schema_table)
   };
 
   ST_FIELD_INFO *field_info;
-  Name_resolution_context *context= &thd->lex->select_lex.context;
+  Name_resolution_context *context= &thd->lex->first_select_lex()->context;
   int i;
 
   for (i= 0; schema_table->fields_info[i].field_name != NULL; i++)
@@ -402,7 +402,7 @@ bool PROFILING::show_profiles()
   QUERY_PROFILE *prof;
   List<Item> field_list;
   MEM_ROOT *mem_root= thd->mem_root;
-  SELECT_LEX *sel= &thd->lex->select_lex;
+  SELECT_LEX *sel= thd->lex->first_select_lex();
   SELECT_LEX_UNIT *unit= &thd->lex->unit;
   ha_rows idx= 0;
   Protocol *protocol= thd->protocol;
diff --git a/sql/sql_select.cc b/sql/sql_select.cc
index 50c525743ff..8c144d692bb 100644
--- a/sql/sql_select.cc
+++ b/sql/sql_select.cc
@@ -351,7 +351,7 @@ bool handle_select(THD *thd, LEX *lex, select_result *result,
                    ulong setup_tables_done_option)
 {
   bool res;
-  register SELECT_LEX *select_lex = &lex->select_lex;
+  register SELECT_LEX *select_lex= lex->first_select_lex();
   DBUG_ENTER("handle_select");
   MYSQL_SELECT_START(thd->query());
 
@@ -1424,13 +1424,14 @@ bool JOIN::prepare_stage2()
 
 bool JOIN::build_explain()
 {
+  DBUG_ENTER("JOIN::build_explain");
   create_explain_query_if_not_exists(thd->lex, thd->mem_root);
   have_query_plan= QEP_AVAILABLE;
   if (save_explain_data(thd->lex->explain, false /* can overwrite */,
                         need_tmp,
                         !skip_sort_order && !no_order && (order || group_list),
                         select_distinct))
-    return 1;
+    DBUG_RETURN(1);
   uint select_nr= select_lex->select_number;
   JOIN_TAB *curr_tab= join_tab + exec_join_tab_cnt();
   for (uint i= 0; i < aggr_tables; i++, curr_tab++)
@@ -1448,7 +1449,7 @@ bool JOIN::build_explain()
                          get_using_temporary_read_tracker();
     }
   }
-  return 0;
+  DBUG_RETURN(0);
 }
 
 
@@ -3714,6 +3715,15 @@ bool JOIN::save_explain_data(Explain_query *output, bool can_overwrite,
                              bool need_tmp_table, bool need_order, 
                              bool distinct)
 {
+  DBUG_ENTER("JOIN::save_explain_data");
+  DBUG_PRINT("enter", ("Save explain Select_lex: %u (%p)  parent lex: %p  stmt_lex: %p  present select: %u (%p)",
+                        select_lex->select_number, select_lex,
+                        select_lex->parent_lex, thd->stmt_lex,
+                        (output->get_select(select_lex->select_number) ?
+                         select_lex->select_number : 0),
+                        (output->get_select(select_lex->select_number) ?
+                         output->get_select(select_lex->select_number)
+                         ->select_lex : NULL)));
   /*
     If there is SELECT in this statemet with the same number it must be the
     same SELECT
@@ -3740,8 +3750,9 @@ bool JOIN::save_explain_data(Explain_query *output, bool can_overwrite,
       /* It's a degenerate join */
       message= zero_result_cause ? zero_result_cause : "No tables used";
     }
-    return save_explain_data_intern(thd->lex->explain, need_tmp_table, need_order,
-                                    distinct, message);
+    bool rc= save_explain_data_intern(thd->lex->explain, need_tmp_table,
+                                      need_order, distinct, message);
+    DBUG_RETURN(rc);
   }
   
   /*
@@ -3763,11 +3774,11 @@ bool JOIN::save_explain_data(Explain_query *output, bool can_overwrite,
       {
         if (!(join_tab[i].filesort->tracker=
               new Filesort_tracker(thd->lex->analyze_stmt)))
-          return 1;
+          DBUG_RETURN(1);
       }
     }
   }
-  return 0;
+  DBUG_RETURN(0);
 }
 
 
@@ -12610,7 +12621,8 @@ void JOIN::join_free()
       !(select_options & SELECT_NO_UNLOCK) &&
       !select_lex->subquery_in_having &&
       (select_lex == (thd->lex->unit.fake_select_lex ?
-                      thd->lex->unit.fake_select_lex : &thd->lex->select_lex)))
+                      thd->lex->unit.fake_select_lex :
+                      thd->lex->first_select_lex())))
   {
     /*
       TODO: unlock tables even if the join isn't top level select in the
@@ -18429,7 +18441,7 @@ create_internal_tmp_table_from_heap(THD *thd, TABLE *table,
   new_table.no_rows= table->no_rows;
   if (create_internal_tmp_table(&new_table, table->key_info, start_recinfo,
                                 recinfo,
-                                thd->lex->select_lex.options | 
+                                thd->lex->builtin_select.options |
 			        thd->variables.option_bits))
     goto err2;
   if (open_tmp_table(&new_table))
@@ -24945,7 +24957,8 @@ bool JOIN_TAB::save_explain_data(Explain_table_access *eta,
     */
     if (real_table->merged_for_insert)
     {
-      TABLE_LIST *view_child= real_table->view->select_lex.table_list.first;
+      TABLE_LIST *view_child=
+        real_table->view->first_select_lex()->table_list.first;
       for (;view_child; view_child= view_child->next_local)
       {
         if (view_child->table == table)
@@ -25398,8 +25411,9 @@ int JOIN::save_explain_data_intern(Explain_query *output,
 {
   JOIN *join= this; /* Legacy: this code used to be a non-member function */
   DBUG_ENTER("JOIN::save_explain_data_intern");
-  DBUG_PRINT("info", ("Select %p, type %s, message %s",
-		      join->select_lex, join->select_lex->type,
+  DBUG_PRINT("info", ("Select %p (%u), type %s, message %s",
+		      join->select_lex,  join->select_lex->select_number,
+                      join->select_lex->type,
 		      message ? message : "NULL"));
   DBUG_ASSERT(have_query_plan == QEP_AVAILABLE);
   /* fake_select_lex is created/printed by Explain_union */
@@ -26053,6 +26067,18 @@ void st_select_lex::print(THD *thd, String *str, enum_query_type query_type)
   {
     str->append("/* select#");
     str->append_ulonglong(select_number);
+    if (thd->lex->describe & DESCRIBE_EXTENDED2)
+    {
+      str->append("/");
+      str->append_ulonglong(nest_level);
+
+      if (master_unit()->fake_select_lex &&
+          master_unit()->first_select() == this)
+      {
+        str->append(" Filter Select: ");
+        master_unit()->fake_select_lex->print(thd, str, query_type);
+      }
+    }
     str->append(" */ ");
   }
 
diff --git a/sql/sql_sequence.cc b/sql/sql_sequence.cc
index 18f0028908f..1ee20785e9c 100644
--- a/sql/sql_sequence.cc
+++ b/sql/sql_sequence.cc
@@ -220,8 +220,8 @@ bool check_sequence_fields(LEX *lex, List<Create_field> *fields)
 
 err:
   my_error(ER_SEQUENCE_INVALID_TABLE_STRUCTURE, MYF(0),
-           lex->select_lex.table_list.first->db.str,
-           lex->select_lex.table_list.first->table_name.str, reason);
+           lex->first_select_lex()->table_list.first->db.str,
+           lex->first_select_lex()->table_list.first->table_name.str, reason);
   DBUG_RETURN(TRUE);
 }
 
diff --git a/sql/sql_show.cc b/sql/sql_show.cc
index 895a974eb02..87cc1934c98 100644
--- a/sql/sql_show.cc
+++ b/sql/sql_show.cc
@@ -4160,8 +4160,9 @@ bool get_lookup_field_values(THD *thd, COND *cond, TABLE_LIST *tables,
   case SQLCOM_SHOW_TABLE_STATUS:
   case SQLCOM_SHOW_TRIGGERS:
   case SQLCOM_SHOW_EVENTS:
-    thd->make_lex_string(&lookup_field_values->db_value, 
-                         lex->select_lex.db.str, lex->select_lex.db.length);
+    thd->make_lex_string(&lookup_field_values->db_value,
+                         lex->first_select_lex()->db.str,
+                         lex->first_select_lex()->db.length);
     if (wild)
     {
       thd->make_lex_string(&lookup_field_values->table_value, 
@@ -4554,10 +4555,10 @@ fill_schema_table_by_open(THD *thd, MEM_ROOT *mem_root,
     temporary LEX. The latter is required to correctly open views and
     produce table describing their structure.
   */
-  if (make_table_list(thd, &lex->select_lex, &db_name, &table_name))
+  if (make_table_list(thd, lex->first_select_lex(), &db_name, &table_name))
     goto end;
 
-  table_list= lex->select_lex.table_list.first;
+  table_list= lex->first_select_lex()->table_list.first;
 
   if (is_show_fields_or_keys)
   {
@@ -6817,7 +6818,7 @@ static int get_schema_views_record(THD *thd, TABLE_LIST *tables,
           & 'field_translation_end' are uninitialized is this
           case.
         */
-        List<Item> *fields= &tables->view->select_lex.item_list;
+        List<Item> *fields= &tables->view->first_select_lex()->item_list;
         List_iterator<Item> it(*fields);
         Item *item;
         Item_field *field;
@@ -7796,7 +7797,8 @@ int fill_open_tables(THD *thd, TABLE_LIST *tables, COND *cond)
   TABLE *table= tables->table;
   CHARSET_INFO *cs= system_charset_info;
   OPEN_TABLE_LIST *open_list;
-  if (!(open_list=list_open_tables(thd,thd->lex->select_lex.db.str, wild))
+  if (!(open_list=list_open_tables(thd, thd->lex->first_select_lex()->db.str,
+                                   wild))
             && thd->is_fatal_error)
     DBUG_RETURN(1);
 
@@ -8291,7 +8293,7 @@ TABLE *create_schema_table(THD *thd, TABLE_LIST *table_list)
   tmp_table_param->table_charset= cs;
   tmp_table_param->field_count= field_count;
   tmp_table_param->schema_table= 1;
-  SELECT_LEX *select_lex= thd->lex->current_select;
+  SELECT_LEX *select_lex= table_list->select_lex;
   bool keep_row_order= is_show_command(thd);
   if (!(table= create_tmp_table(thd, tmp_table_param,
                                 field_list, (ORDER*) 0, 0, 0, 
@@ -8328,7 +8330,7 @@ TABLE *create_schema_table(THD *thd, TABLE_LIST *table_list)
 static int make_old_format(THD *thd, ST_SCHEMA_TABLE *schema_table)
 {
   ST_FIELD_INFO *field_info= schema_table->fields_info;
-  Name_resolution_context *context= &thd->lex->select_lex.context;
+  Name_resolution_context *context= &thd->lex->first_select_lex()->context;
   for (; field_info->field_name; field_info++)
   {
     if (field_info->old_name)
@@ -8388,14 +8390,14 @@ int make_table_names_old_format(THD *thd, ST_SCHEMA_TABLE *schema_table)
   char tmp[128];
   String buffer(tmp,sizeof(tmp), thd->charset());
   LEX *lex= thd->lex;
-  Name_resolution_context *context= &lex->select_lex.context;
+  Name_resolution_context *context= &lex->first_select_lex()->context;
   ST_FIELD_INFO *field_info= &schema_table->fields_info[2];
   LEX_CSTRING field_name= {field_info->field_name,
                            strlen(field_info->field_name) };
 
   buffer.length(0);
   buffer.append(field_info->old_name);
-  buffer.append(&lex->select_lex.db);
+  buffer.append(&lex->first_select_lex()->db);
   if (lex->wild && lex->wild->ptr())
   {
     buffer.append(STRING_WITH_LEN(" ("));
@@ -8428,7 +8430,7 @@ int make_columns_old_format(THD *thd, ST_SCHEMA_TABLE *schema_table)
   int fields_arr[]= {3, 15, 14, 6, 16, 5, 17, 18, 19, -1};
   int *field_num= fields_arr;
   ST_FIELD_INFO *field_info;
-  Name_resolution_context *context= &thd->lex->select_lex.context;
+  Name_resolution_context *context= &thd->lex->first_select_lex()->context;
 
   for (; *field_num >= 0; field_num++)
   {
@@ -8459,7 +8461,7 @@ int make_character_sets_old_format(THD *thd, ST_SCHEMA_TABLE *schema_table)
   int fields_arr[]= {0, 2, 1, 3, -1};
   int *field_num= fields_arr;
   ST_FIELD_INFO *field_info;
-  Name_resolution_context *context= &thd->lex->select_lex.context;
+  Name_resolution_context *context= &thd->lex->first_select_lex()->context;
 
   for (; *field_num >= 0; field_num++)
   {
@@ -8486,7 +8488,7 @@ int make_proc_old_format(THD *thd, ST_SCHEMA_TABLE *schema_table)
   int fields_arr[]= {2, 3, 4, 27, 24, 23, 22, 26, 28, 29, 30, -1};
   int *field_num= fields_arr;
   ST_FIELD_INFO *field_info;
-  Name_resolution_context *context= &thd->lex->select_lex.context;
+  Name_resolution_context *context= &thd->lex->first_select_lex()->context;
 
   for (; *field_num >= 0; field_num++)
   {
diff --git a/sql/sql_table.cc b/sql/sql_table.cc
index 2dd45221771..1e9889eb3dc 100644
--- a/sql/sql_table.cc
+++ b/sql/sql_table.cc
@@ -4944,7 +4944,7 @@ int create_table_impl(THD *thd,
         /*
           Restart statement transactions for the case of CREATE ... SELECT.
         */
-        if (thd->lex->select_lex.item_list.elements &&
+        if (thd->lex->first_select_lex()->item_list.elements &&
             restart_trans_for_tables(thd, thd->lex->query_tables))
           goto err;
       }
@@ -10426,8 +10426,8 @@ copy_data_between_tables(THD *thd, TABLE *from, TABLE *to,
       Filesort_tracker dummy_tracker(false);
       Filesort fsort(order, HA_POS_ERROR, true, NULL);
 
-      if (thd->lex->select_lex.setup_ref_array(thd, order_num) ||
-          setup_order(thd, thd->lex->select_lex.ref_pointer_array,
+      if (thd->lex->first_select_lex()->setup_ref_array(thd, order_num) ||
+          setup_order(thd, thd->lex->first_select_lex()->ref_pointer_array,
                       &tables, fields, all_fields, order))
         goto err;
 
diff --git a/sql/sql_truncate.cc b/sql/sql_truncate.cc
index 2ddb4bc042c..dabd88e90a4 100644
--- a/sql/sql_truncate.cc
+++ b/sql/sql_truncate.cc
@@ -489,7 +489,7 @@ bool Sql_cmd_truncate_table::truncate_table(THD *thd, TABLE_LIST *table_ref)
 bool Sql_cmd_truncate_table::execute(THD *thd)
 {
   bool res= TRUE;
-  TABLE_LIST *table= thd->lex->select_lex.table_list.first;
+  TABLE_LIST *table= thd->lex->first_select_lex()->table_list.first;
   DBUG_ENTER("Sql_cmd_truncate_table::execute");
 
   if (check_one_table_access(thd, DROP_ACL, table))
diff --git a/sql/sql_union.cc b/sql/sql_union.cc
index 0149c2848c2..5b84ec45dba 100644
--- a/sql/sql_union.cc
+++ b/sql/sql_union.cc
@@ -1387,7 +1387,7 @@ bool st_select_lex_unit::exec()
         union_result->change_select();
       if (fake_select_lex)
       {
-        if (sl != &thd->lex->select_lex)
+        if (sl != thd->lex->first_select_lex())
           fake_select_lex->uncacheable|= sl->uncacheable;
         else
           fake_select_lex->uncacheable= 0;
diff --git a/sql/sql_update.cc b/sql/sql_update.cc
index 38638d3aa1d..8e7bbadf902 100644
--- a/sql/sql_update.cc
+++ b/sql/sql_update.cc
@@ -318,7 +318,7 @@ int mysql_update(THD *thd,
   SQL_SELECT	*select= NULL;
   SORT_INFO     *file_sort= 0;
   READ_RECORD	info;
-  SELECT_LEX    *select_lex= &thd->lex->select_lex;
+  SELECT_LEX    *select_lex= thd->lex->first_select_lex();
   ulonglong     id;
   List<Item> all_fields;
   killed_state killed_status= NOT_KILLED;
@@ -375,7 +375,7 @@ int mysql_update(THD *thd,
   table->covering_keys= table->s->keys_in_use;
   table->quick_keys.clear_all();
 
-  query_plan.select_lex= &thd->lex->select_lex;
+  query_plan.select_lex= thd->lex->first_select_lex();
   query_plan.table= table;
 #ifndef NO_EMBEDDED_ACCESS_CHECKS
   /* Force privilege re-checking for views after they have been opened. */
@@ -1241,7 +1241,7 @@ bool mysql_prepare_update(THD *thd, TABLE_LIST *table_list,
   TABLE *table= table_list->table;
 #endif
   List<Item> all_fields;
-  SELECT_LEX *select_lex= &thd->lex->select_lex;
+  SELECT_LEX *select_lex= thd->lex->first_select_lex();
   DBUG_ENTER("mysql_prepare_update");
 
 #ifndef NO_EMBEDDED_ACCESS_CHECKS
@@ -1518,7 +1518,7 @@ int mysql_multi_update_prepare(THD *thd)
   LEX *lex= thd->lex;
   TABLE_LIST *table_list= lex->query_tables;
   TABLE_LIST *tl;
-  List<Item> *fields= &lex->select_lex.item_list;
+  List<Item> *fields= &lex->first_select_lex()->item_list;
   table_map tables_for_update;
   bool update_view= 0;
   /*
@@ -1560,14 +1560,15 @@ int mysql_multi_update_prepare(THD *thd)
   if (mysql_handle_derived(lex, DT_PREPARE))
     DBUG_RETURN(TRUE);
 
-  if (setup_tables_and_check_access(thd, &lex->select_lex.context,
-                                    &lex->select_lex.top_join_list,
+  if (setup_tables_and_check_access(thd,
+                                    &lex->first_select_lex()->context,
+                                    &lex->first_select_lex()->top_join_list,
                                     table_list,
-                                    lex->select_lex.leaf_tables, FALSE,
-                                    UPDATE_ACL, SELECT_ACL, FALSE))
+                                    lex->first_select_lex()->leaf_tables,
+                                    FALSE, UPDATE_ACL, SELECT_ACL, FALSE))
     DBUG_RETURN(TRUE);
 
-  if (lex->select_lex.handle_derived(thd->lex, DT_MERGE))  
+  if (lex->first_select_lex()->handle_derived(thd->lex, DT_MERGE))
     DBUG_RETURN(TRUE);
 
   if (setup_fields_with_no_wrap(thd, Ref_ptr_array(),
@@ -1590,13 +1591,14 @@ int mysql_multi_update_prepare(THD *thd)
 
   thd->table_map_for_update= tables_for_update= get_table_map(fields);
 
-  if (unsafe_key_update(lex->select_lex.leaf_tables, tables_for_update))
+  if (unsafe_key_update(lex->first_select_lex()->leaf_tables,
+                        tables_for_update))
     DBUG_RETURN(true);
 
   /*
     Setup timestamp handling and locking mode
   */
-  List_iterator<TABLE_LIST> ti(lex->select_lex.leaf_tables);
+  List_iterator<TABLE_LIST> ti(lex->first_select_lex()->leaf_tables);
   while ((tl= ti++))
   {
     TABLE *table= tl->table;
@@ -1689,7 +1691,7 @@ int mysql_multi_update_prepare(THD *thd)
     Check that we are not using table that we are updating, but we should
     skip all tables of UPDATE SELECT itself
   */
-  lex->select_lex.exclude_from_table_unique_test= TRUE;
+  lex->first_select_lex()->exclude_from_table_unique_test= TRUE;
   /* We only need SELECT privilege for columns in the values list */
   ti.rewind();
   while ((tl= ti++))
@@ -1711,7 +1713,7 @@ int mysql_multi_update_prepare(THD *thd)
     Set exclude_from_table_unique_test value back to FALSE. It is needed for
     further check in multi_update::prepare whether to use record cache.
   */
-  lex->select_lex.exclude_from_table_unique_test= FALSE;
+  lex->first_select_lex()->exclude_from_table_unique_test= FALSE;
 
   if (lex->save_prep_leaf_tables())
     DBUG_RETURN(TRUE);
@@ -1740,7 +1742,7 @@ bool mysql_multi_update(THD *thd,
   DBUG_ENTER("mysql_multi_update");
   
   if (!(*result= new (thd->mem_root) multi_update(thd, table_list,
-                                 &thd->lex->select_lex.leaf_tables,
+                                 &thd->lex->first_select_lex()->leaf_tables,
                                  fields, values,
                                  handle_duplicates, ignore)))
   {
diff --git a/sql/sql_view.cc b/sql/sql_view.cc
index b84dc46cae6..1b1451126b1 100644
--- a/sql/sql_view.cc
+++ b/sql/sql_view.cc
@@ -254,7 +254,7 @@ bool create_view_precheck(THD *thd, TABLE_LIST *tables, TABLE_LIST *view,
   LEX *lex= thd->lex;
   /* first table in list is target VIEW name => cut off it */
   TABLE_LIST *tbl;
-  SELECT_LEX *select_lex= &lex->select_lex;
+  SELECT_LEX *select_lex= lex->first_select_lex();
   SELECT_LEX *sl;
   bool res= TRUE;
   DBUG_ENTER("create_view_precheck");
@@ -323,7 +323,9 @@ bool create_view_precheck(THD *thd, TABLE_LIST *tables, TABLE_LIST *view,
     }
   }
 
-  if (&lex->select_lex != lex->all_selects_list)
+#if 0
+  if (lex->first_select_lex() != lex->all_selects_list)
+#endif
   {
     /* check tables of subqueries */
     for (tbl= tables; tbl; tbl= tbl->next_global)
@@ -399,7 +401,7 @@ bool mysql_create_view(THD *thd, TABLE_LIST *views,
   TABLE_LIST *view= lex->unlink_first_table(&link_to_local);
   TABLE_LIST *tables= lex->query_tables;
   TABLE_LIST *tbl;
-  SELECT_LEX *select_lex= &lex->select_lex;
+  SELECT_LEX *select_lex= lex->first_select_lex();
   SELECT_LEX *sl;
   SELECT_LEX_UNIT *unit= &lex->unit;
   bool res= FALSE;
@@ -995,7 +997,7 @@ static int mysql_register_view(THD *thd, TABLE_LIST *view,
                               view->algorithm != VIEW_ALGORITHM_TMPTABLE)))
   {
     /* TODO: change here when we will support UNIONs */
-    for (TABLE_LIST *tbl= lex->select_lex.table_list.first;
+    for (TABLE_LIST *tbl= lex->first_select_lex()->table_list.first;
 	 tbl;
 	 tbl= tbl->next_local)
     {
@@ -1114,8 +1116,8 @@ static int mysql_register_view(THD *thd, TABLE_LIST *view,
     UNION
   */
   if (view->updatable_view &&
-      !lex->select_lex.master_unit()->is_unit_op() &&
-      !(lex->select_lex.table_list.first)->next_local &&
+      !lex->first_select_lex()->master_unit()->is_unit_op() &&
+      !(lex->first_select_lex()->table_list.first)->next_local &&
       find_table_in_global_list(lex->query_tables->next_global,
 				&lex->query_tables->db,
 				&lex->query_tables->table_name))
@@ -1162,7 +1164,8 @@ static int mysql_register_view(THD *thd, TABLE_LIST *view,
 bool mysql_make_view(THD *thd, TABLE_SHARE *share, TABLE_LIST *table,
                      bool open_view_no_parse)
 {
-  SELECT_LEX *end, *UNINIT_VAR(view_select);
+  SELECT_LEX_NODE *end;
+  SELECT_LEX *UNINIT_VAR(view_select);
   LEX *old_lex, *lex;
   Query_arena *arena, backup;
   TABLE_LIST *top_view= table->top_table();
@@ -1359,8 +1362,6 @@ bool mysql_make_view(THD *thd, TABLE_SHARE *share, TABLE_LIST *table,
       goto end;
 
     lex_start(thd);
-    view_select= &lex->select_lex;
-    view_select->select_number= ++thd->stmt_lex->current_select_number;
 
     sql_mode_t saved_mode= thd->variables.sql_mode;
     /* switch off modes which can prevent normal parsing of VIEW
@@ -1395,6 +1396,8 @@ bool mysql_make_view(THD *thd, TABLE_SHARE *share, TABLE_LIST *table,
 
     parse_status= parse_sql(thd, & parser_state, table->view_creation_ctx);
 
+    view_select= lex->first_select_lex();
+
     /* Restore environment. */
 
     if ((old_lex->sql_command == SQLCOM_SHOW_FIELDS) ||
@@ -1544,7 +1547,7 @@ bool mysql_make_view(THD *thd, TABLE_SHARE *share, TABLE_LIST *table,
         This may change in future, for example if we enable merging of
         views with subqueries in select list.
       */
-      view_main_select_tables= lex->select_lex.table_list.first;
+      view_main_select_tables= lex->first_select_lex()->table_list.first;
 
       /*
         Let us set proper lock type for tables of the view's main
@@ -1572,7 +1575,7 @@ bool mysql_make_view(THD *thd, TABLE_SHARE *share, TABLE_LIST *table,
 
       /* Fields in this view can be used in upper select in case of merge.  */
       if (table->select_lex)
-        table->select_lex->add_where_field(&lex->select_lex);
+        table->select_lex->add_where_field(lex->first_select_lex());
     }
     /*
       This method has a dependency on the proper lock type being set,
@@ -1594,8 +1597,8 @@ bool mysql_make_view(THD *thd, TABLE_SHARE *share, TABLE_LIST *table,
     old_lex->safe_to_cache_query= (old_lex->safe_to_cache_query &&
 				   lex->safe_to_cache_query);
     /* move SQL_CACHE to whole query */
-    if (view_select->options & OPTION_TO_QUERY_CACHE)
-      old_lex->select_lex.options|= OPTION_TO_QUERY_CACHE;
+    if (lex->first_select_lex()->options & OPTION_TO_QUERY_CACHE)
+      old_lex->first_select_lex()->options|= OPTION_TO_QUERY_CACHE;
 
 #ifndef NO_EMBEDDED_ACCESS_CHECKS
     if (table->view_suid)
@@ -1677,9 +1680,10 @@ bool mysql_make_view(THD *thd, TABLE_SHARE *share, TABLE_LIST *table,
         tbl->grant.want_privilege= top_view->grant.orig_want_privilege;
 
       /* prepare view context */
-      lex->select_lex.context.resolve_in_table_list_only(view_main_select_tables);
-      lex->select_lex.context.outer_context= 0;
-      lex->select_lex.select_n_having_items+=
+      lex->first_select_lex()->
+        context.resolve_in_table_list_only(view_main_select_tables);
+      lex->first_select_lex()->context.outer_context= 0;
+      lex->first_select_lex()->select_n_having_items+=
         table->select_lex->select_n_having_items;
 
       table->where= view_select->where;
@@ -1690,12 +1694,13 @@ bool mysql_make_view(THD *thd, TABLE_SHARE *share, TABLE_LIST *table,
       */
       if (!table->select_lex->master_unit()->is_unit_op() &&
           table->select_lex->order_list.elements == 0)
-        table->select_lex->order_list.push_back(&lex->select_lex.order_list);
+        table->select_lex->order_list.
+          push_back(&lex->first_select_lex()->order_list);
       else
       {
         if (old_lex->sql_command == SQLCOM_SELECT &&
             (old_lex->describe & DESCRIBE_EXTENDED) &&
-            lex->select_lex.order_list.elements &&
+            lex->first_select_lex()->order_list.elements &&
             !table->select_lex->master_unit()->is_unit_op())
         {
           push_warning_printf(thd, Sql_condition::WARN_LEVEL_NOTE,
@@ -1730,7 +1735,11 @@ bool mysql_make_view(THD *thd, TABLE_SHARE *share, TABLE_LIST *table,
   lex->unit.include_down(table->select_lex);
   lex->unit.slave= view_select; // fix include_down initialisation
   /* global SELECT list linking */
-  end= view_select;	// primary SELECT_LEX is always last
+  /*
+    The primary SELECT_LEX is always last (because parsed first) if WITH not
+    used, otherwise it is good start point for last element finding
+  */
+  for (end= view_select; end->link_next; end= end->link_next);
   end->link_next= old_lex->all_selects_list;
   old_lex->all_selects_list->link_prev= &end->link_next;
   old_lex->all_selects_list= lex->all_selects_list;
@@ -1913,7 +1922,7 @@ bool check_key_in_view(THD *thd, TABLE_LIST *view)
   */
   if ((!view->view && !view->belong_to_view) ||
       thd->lex->sql_command == SQLCOM_INSERT ||
-      thd->lex->select_lex.select_limit == 0)
+      thd->lex->first_select_lex()->select_limit == 0)
     DBUG_RETURN(FALSE); /* it is normal table or query without LIMIT */
   table= view->table;
   view= view->top_table();
diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy
index 9eddce0c110..6b472058353 100644
--- a/sql/sql_yacc.yy
+++ b/sql/sql_yacc.yy
@@ -511,6 +511,7 @@ bool LEX::add_select_to_union_list(bool is_union_distinct,
 {
   const char *type_name= (type == INTERSECT_TYPE ? "INTERSECT" :
                      (type == EXCEPT_TYPE ? "EXCEPT" : "UNION"));
+  DBUG_ENTER("LEX::add_select_to_union_list");
   /*
      Only the last SELECT can have INTO. Since the grammar won't allow INTO in
      a nested SELECT, we make this check only when creating a top-level SELECT.
@@ -518,28 +519,28 @@ bool LEX::add_select_to_union_list(bool is_union_distinct,
   if (is_top_level && result)
   {
     my_error(ER_WRONG_USAGE, MYF(0), type_name, "INTO");
-    return TRUE;
+    DBUG_RETURN(TRUE);
   }
   if (current_select->order_list.first && !current_select->braces)
   {
     my_error(ER_WRONG_USAGE, MYF(0), type_name, "ORDER BY");
-    return TRUE;
+    DBUG_RETURN(TRUE);
   }
 
   if (current_select->explicit_limit && !current_select->braces)
   {
     my_error(ER_WRONG_USAGE, MYF(0), type_name, "LIMIT");
-    return TRUE;
+    DBUG_RETURN(TRUE);
   }
   if (current_select->linkage == GLOBAL_OPTIONS_TYPE)
   {
     thd->parse_error();
-    return TRUE;
+    DBUG_RETURN(TRUE);
   }
   if (!is_union_distinct && (type == INTERSECT_TYPE || type == EXCEPT_TYPE))
   {
     my_error(ER_WRONG_USAGE, MYF(0), type_name, "ALL");
-    return TRUE;
+    DBUG_RETURN(TRUE);
   }
   /*
     Priority implementation, but also trying to keep things as flat
@@ -554,27 +555,24 @@ bool LEX::add_select_to_union_list(bool is_union_distinct,
     */
     SELECT_LEX *prev= exclude_last_select();
     if (add_unit_in_brackets(prev))
-      return TRUE;
-    return add_select_to_union_list(is_union_distinct, type, 0);
+      DBUG_RETURN(TRUE);
+    bool res= add_select_to_union_list(is_union_distinct, type, 0);
+    DBUG_RETURN(res);
   }
   else
   {
     check_automatic_up(type);
   }
-  /* This counter shouldn't be incremented for UNION parts */
-  nest_level--;
   if (mysql_new_select(this, 0, NULL))
-    return TRUE;
+    DBUG_RETURN(TRUE);
   mysql_init_select(this);
-  current_select->linkage= type;
+  current_select->set_linkage(type);
   if (is_union_distinct) /* UNION DISTINCT - remember position */
   {
     current_select->master_unit()->union_distinct=
       current_select;
   }
-  else
-    DBUG_ASSERT(type == UNION_TYPE);
-  return FALSE;
+  DBUG_RETURN(FALSE);
 }
 
 
@@ -619,6 +617,7 @@ void sp_create_assignment_lex(THD *thd, bool no_lookahead)
         lex->sphead->m_tmp_query= lip->get_tok_end();
     /* Inherit from outer lex. */
     lex->option_type= old_lex->option_type;
+    lex->main_select_push();
   }
 }
 
@@ -678,6 +677,9 @@ bool sp_create_assignment_instr(THD *thd, bool no_lookahead)
       if (sp->add_instr(i))
         return true;
     }
+    lex->pop_select();
+    if (Lex->check_main_unit_semantics())
+      return true;
     enum_var_type inner_option_type= lex->option_type;
     if (lex->sphead->restore_lex(thd))
       return true;
@@ -796,6 +798,20 @@ Virtual_column_info *add_virtual_expression(THD *thd, Item *expr)
     uint offset;
   } sp_cursor_name_and_offset;
   vers_history_point_t vers_history_point;
+  struct
+  {
+    enum sub_select_type unit_type;
+    bool distinct;
+  } unit_operation;
+  struct
+  {
+    SELECT_LEX *first;
+    SELECT_LEX *prev_last;
+  } select_list;
+  SQL_I_List<ORDER> *select_order;
+  Lex_select_lock select_lock;
+  Lex_select_limit select_limit;
+  Lex_order_limit_lock *order_limit_lock;
 
   /* pointers */
   Create_field *create_field;
@@ -841,6 +857,7 @@ Virtual_column_info *add_virtual_expression(THD *thd, Item *expr)
 
   handlerton *db_type;
   st_select_lex *select_lex;
+  st_select_lex_unit *select_lex_unit;
   struct p_elem_val *p_elem_value;
   class Window_frame *window_frame;
   class Window_frame_bound *window_frame_bound;
@@ -849,7 +866,6 @@ Virtual_column_info *add_virtual_expression(THD *thd, Item *expr)
 
   /* enums */
   enum enum_view_suid view_suid;
-  enum sub_select_type unit_type;
   enum Condition_information_item::Name cond_info_item_name;
   enum enum_diag_condition_item_name diag_condition_item_name;
   enum Diagnostics_information::Which_area diag_area;
@@ -888,10 +904,10 @@ bool my_yyoverflow(short **a, YYSTYPE **b, size_t *yystacksize);
 %parse-param { THD *thd }
 %lex-param { THD *thd }
 /*
-  Currently there are 139 shift/reduce conflicts.
+  Currently there are 96 shift/reduce conflicts.
   We should not introduce new conflicts any more.
 */
-%expect 139
+%expect 135
 
 /*
    Comments for TOKENS.
@@ -1210,6 +1226,9 @@ bool my_yyoverflow(short **a, YYSTYPE **b, size_t *yystacksize);
 %token  LEAVES
 %token  LEAVE_SYM
 %token  LEFT                          /* SQL-2003-R */
+%token  LEFT_PAREN_ALT                /* INTERNAL */
+%token  LEFT_PAREN_WITH               /* INTERNAL */
+%token  LEFT_PAREN_LIKE               /* INTERNAL */
 %token  LESS_SYM
 %token  LEVEL_SYM
 %token  LEX_HOSTNAME
@@ -1671,7 +1690,8 @@ bool my_yyoverflow(short **a, YYSTYPE **b, size_t *yystacksize);
         NCHAR_STRING
 
 %type <lex_str_ptr>
-        opt_table_alias
+        opt_table_alias_clause
+        table_alias_clause
 
 %type <lex_string_with_pos>
         ident ident_with_tok_start
@@ -1716,7 +1736,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, size_t *yystacksize);
         opt_temporary all_or_any opt_distinct opt_glimit_clause
         opt_ignore_leaves fulltext_options union_option
         opt_not
-        select_derived_init transaction_access_mode_types
+        transaction_access_mode_types
         opt_natural_language_mode opt_query_expansion
         opt_ev_status opt_ev_on_completion ev_on_completion opt_ev_comment
         ev_alter_on_schedule_completion opt_ev_rename_to opt_ev_sql_stmt
@@ -1834,11 +1854,8 @@ bool my_yyoverflow(short **a, YYSTYPE **b, size_t *yystacksize);
         join_table_list  join_table
         table_factor table_ref esc_table_ref
         table_primary_ident table_primary_derived
-        select_derived derived_table_list
-        select_derived_union
-        derived_simple_table
-        derived_query_specification
-        derived_table_value_constructor
+        derived_table_list table_reference_list_parens
+        nested_table_reference_list join_table_parens
 %type <date_time_type> date_time_type;
 %type <interval> interval
 
@@ -1876,14 +1893,16 @@ bool my_yyoverflow(short **a, YYSTYPE **b, size_t *yystacksize);
         UNDERSCORE_CHARSET
 
 %type <select_lex> subselect
-        get_select_lex get_select_lex_derived
-        simple_table
         query_specification
-        query_term_union_not_ready
-        query_term_union_ready
-        query_expression_body
-        select_paren_derived
         table_value_constructor
+        simple_table
+        query_primary
+        query_primary_parens
+
+%type <select_lex_unit>
+        query_expression_body
+        query_expression
+        query_expression_unit
 
 %type <boolfunc2creator> comp_op
 
@@ -1895,7 +1914,21 @@ bool my_yyoverflow(short **a, YYSTYPE **b, size_t *yystacksize);
 
 %type <virtual_column> opt_check_constraint check_constraint virtual_column_func
         column_default_expr
-%type <unit_type> unit_type_decl
+
+%type <unit_operation> unit_type_decl
+
+%type <select_lock>
+        opt_select_lock_type
+        select_lock_type
+        opt_lock_wait_timeout_new
+
+%type <select_limit> opt_limit_clause limit_clause limit_options
+
+%type <order_limit_lock>
+        query_expression_tail
+        order_or_limit
+
+%type <select_order> opt_order_clause order_clause order_list
 
 %type <NONE>
         analyze_stmt_command
@@ -1915,7 +1948,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, size_t *yystacksize);
         assign_to_keycache_parts
         preload_list preload_list_or_parts preload_keys preload_keys_parts
         select_item_list select_item values_list no_braces
-        opt_limit_clause delete_limit_clause fields opt_values values
+        delete_limit_clause fields opt_values values
         procedure_list procedure_list2 procedure_item
         field_def handler opt_generated_always
         opt_ignore opt_column opt_restrict
@@ -1935,9 +1968,8 @@ bool my_yyoverflow(short **a, YYSTYPE **b, size_t *yystacksize);
         table_to_table_list table_to_table opt_table_list opt_as
         handler_rkey_function handler_read_or_scan
         single_multi table_wild_list table_wild_one opt_wild
-        union_clause union_list
-        subselect_start opt_and charset
-        subselect_end select_var_list select_var_list_init help 
+        opt_and charset
+        select_var_list select_var_list_init help
         opt_extended_describe shutdown
         opt_format_json
         prepare prepare_src execute deallocate
@@ -2066,7 +2098,7 @@ query:
           END_OF_INPUT
           {
             if (!thd->bootstrap &&
-              (!(thd->lex->select_lex.options & OPTION_FOUND_COMMENT)))
+              (!(thd->lex->builtin_select.options & OPTION_FOUND_COMMENT)))
               my_yyabort_error((ER_EMPTY_QUERY, MYF(0)));
 
             thd->lex->sql_command= SQLCOM_EMPTY_QUERY;
@@ -2190,14 +2222,22 @@ deallocate_or_drop:
         ;
 
 prepare:
-          PREPARE_SYM ident FROM prepare_src
+          PREPARE_SYM
+          {
+            if (Lex->main_select_push())
+              MYSQL_YYABORT;
+          }
+          ident FROM prepare_src
           {
             LEX *lex= thd->lex;
             if (lex->table_or_sp_used())
               my_yyabort_error((ER_SUBQUERIES_NOT_SUPPORTED, MYF(0),
                                "PREPARE..FROM"));
+            if (Lex->check_main_unit_semantics())
+              MYSQL_YYABORT;
             lex->sql_command= SQLCOM_PREPARE;
-            lex->prepared_stmt_name= $2;
+            lex->prepared_stmt_name= $3;
+            Lex->pop_select(); //main select
           }
         ;
 
@@ -2216,10 +2256,21 @@ execute:
             LEX *lex= thd->lex;
             lex->sql_command= SQLCOM_EXECUTE;
             lex->prepared_stmt_name= $2;
+            if (Lex->main_select_push())
+              MYSQL_YYABORT;
           }
           execute_using
-          {}
-        | EXECUTE_SYM IMMEDIATE_SYM prepare_src
+          {
+            Lex->pop_select(); //main select
+            if (Lex->check_main_unit_semantics())
+              MYSQL_YYABORT;
+          }
+        | EXECUTE_SYM IMMEDIATE_SYM
+          {
+            if (Lex->main_select_push())
+              MYSQL_YYABORT;
+          }
+          prepare_src
           {
             if (Lex->table_or_sp_used())
               my_yyabort_error((ER_SUBQUERIES_NOT_SUPPORTED, MYF(0),
@@ -2227,7 +2278,11 @@ execute:
             Lex->sql_command= SQLCOM_EXECUTE_IMMEDIATE;
           }
           execute_using
-          {}
+          {
+            Lex->pop_select(); //main select
+            if (Lex->check_main_unit_semantics())
+              MYSQL_YYABORT;
+          }
         ;
 
 execute_using:
@@ -2512,15 +2567,22 @@ connection_name:
 /* create a table */
 
 create:
-          create_or_replace opt_temporary TABLE_SYM opt_if_not_exists table_ident
+          create_or_replace opt_temporary TABLE_SYM opt_if_not_exists
           {
             LEX *lex= thd->lex;
             lex->create_info.init();
+            if (lex->main_select_push())
+              MYSQL_YYABORT;
+            lex->current_select->parsing_place= BEFORE_OPT_FIELD_LIST;
             if (lex->set_command_with_check(SQLCOM_CREATE_TABLE, $2, $1 | $4))
                MYSQL_YYABORT;
-            if (!lex->select_lex.add_table_to_list(thd, $5, NULL,
-                                                   TL_OPTION_UPDATING,
-                                                   TL_WRITE, MDL_EXCLUSIVE))
+          }
+          table_ident
+          {
+            LEX *lex= thd->lex;
+            if (!lex->builtin_select.add_table_to_list(thd, $6, NULL,
+                                                       TL_OPTION_UPDATING,
+                                                       TL_WRITE, MDL_EXCLUSIVE))
               MYSQL_YYABORT;
             lex->alter_info.reset();
             /*
@@ -2535,7 +2597,7 @@ create:
           create_body
           {
             LEX *lex= thd->lex;
-            lex->current_select= &lex->select_lex; 
+            lex->current_select= &lex->builtin_select;
             if ((lex->create_info.used_fields & HA_CREATE_USED_ENGINE) &&
                 !lex->create_info.db_type)
             {
@@ -2544,20 +2606,23 @@ create:
                                   ER_WARN_USING_OTHER_HANDLER,
                                   ER_THD(thd, ER_WARN_USING_OTHER_HANDLER),
                                   hton_name(lex->create_info.db_type)->str,
-                                  $5->table.str);
+                                  $6->table.str);
             }
             create_table_set_open_action_and_adjust_tables(lex);
+            Lex->pop_select(); //main select
           }
        | create_or_replace opt_temporary SEQUENCE_SYM opt_if_not_exists table_ident
          {
            LEX *lex= thd->lex;
+           if (Lex->main_select_push())
+             MYSQL_YYABORT;
            lex->create_info.init();
            if (lex->set_command_with_check(SQLCOM_CREATE_SEQUENCE, $2, $1 | $4))
               MYSQL_YYABORT;
 
-           if (!lex->select_lex.add_table_to_list(thd, $5, NULL,
-                                                  TL_OPTION_UPDATING,
-                                                  TL_WRITE, MDL_EXCLUSIVE))
+           if (!lex->builtin_select.add_table_to_list(thd, $5, NULL,
+                                                      TL_OPTION_UPDATING,
+                                                      TL_WRITE, MDL_EXCLUSIVE))
              MYSQL_YYABORT;
 
                /*
@@ -2580,8 +2645,8 @@ create:
             if (lex->create_info.seq_create_info->check_and_adjust(1))
             {
               my_error(ER_SEQUENCE_INVALID_DATA, MYF(0),
-                       lex->select_lex.table_list.first->db.str,
-                       lex->select_lex.table_list.first->table_name.str);
+                       lex->builtin_select.table_list.first->db.str,
+                       lex->builtin_select.table_list.first->table_name.str);
               MYSQL_YYABORT;
             }
 
@@ -2593,7 +2658,7 @@ create:
 	    Lex->create_info.used_fields|= HA_CREATE_USED_SEQUENCE;
             Lex->create_info.sequence= 1;
 
-            lex->current_select= &lex->select_lex;
+            lex->current_select= &lex->builtin_select;
             if ((lex->create_info.used_fields & HA_CREATE_USED_ENGINE) &&
                 !lex->create_info.db_type)
             {
@@ -2605,42 +2670,69 @@ create:
                                   $5->table.str);
             }
             create_table_set_open_action_and_adjust_tables(lex);
+            Lex->pop_select(); //main select
           }
-        | create_or_replace opt_unique INDEX_SYM opt_if_not_exists ident
+        | create_or_replace opt_unique INDEX_SYM opt_if_not_exists
+          {
+            if (Lex->main_select_push())
+              MYSQL_YYABORT;
+          }
+          ident
           opt_key_algorithm_clause
           ON table_ident
           {
-            if (Lex->add_create_index_prepare($8))
+            if (Lex->add_create_index_prepare($9))
               MYSQL_YYABORT;
-            if (Lex->add_create_index($2, &$5, $6, $1 | $4))
+            if (Lex->add_create_index($2, &$6, $7, $1 | $4))
               MYSQL_YYABORT;
           }
           '(' key_list ')' opt_lock_wait_timeout normal_key_options
-          opt_index_lock_algorithm { }
-        | create_or_replace fulltext INDEX_SYM opt_if_not_exists ident
+          opt_index_lock_algorithm
+          {
+            Lex->pop_select(); //main select
+          }
+        | create_or_replace fulltext INDEX_SYM
+          {
+            if (Lex->main_select_push())
+              MYSQL_YYABORT;
+          }
+          opt_if_not_exists ident
           ON table_ident
           {
-            if (Lex->add_create_index_prepare($7))
+            if (Lex->add_create_index_prepare($8))
               MYSQL_YYABORT;
-            if (Lex->add_create_index($2, &$5, HA_KEY_ALG_UNDEF, $1 | $4))
+            if (Lex->add_create_index($2, &$6, HA_KEY_ALG_UNDEF, $1 | $5))
               MYSQL_YYABORT;
           }
           '(' key_list ')' opt_lock_wait_timeout fulltext_key_options
-          opt_index_lock_algorithm { }
-        | create_or_replace spatial INDEX_SYM opt_if_not_exists ident
+          opt_index_lock_algorithm
+          {
+            Lex->pop_select(); //main select
+          }
+        | create_or_replace spatial INDEX_SYM
+          {
+            if (Lex->main_select_push())
+              MYSQL_YYABORT;
+          }
+          opt_if_not_exists ident
           ON table_ident
           {
-            if (Lex->add_create_index_prepare($7))
+            if (Lex->add_create_index_prepare($8))
               MYSQL_YYABORT;
-            if (Lex->add_create_index($2, &$5, HA_KEY_ALG_UNDEF, $1 | $4))
+            if (Lex->add_create_index($2, &$6, HA_KEY_ALG_UNDEF, $1 | $5))
               MYSQL_YYABORT;
           }
           '(' key_list ')' opt_lock_wait_timeout spatial_key_options
-          opt_index_lock_algorithm { }
+          opt_index_lock_algorithm
+          {
+            Lex->pop_select(); //main select
+          }
         | create_or_replace DATABASE opt_if_not_exists ident
           {
             Lex->create_info.default_table_charset= NULL;
             Lex->create_info.used_fields= 0;
+            if (Lex->main_select_push())
+              MYSQL_YYABORT;
           }
           opt_create_database_options
           {
@@ -2648,58 +2740,104 @@ create:
             if (lex->set_command_with_check(SQLCOM_CREATE_DB, 0, $1 | $3))
                MYSQL_YYABORT;
             lex->name= $4;
+            Lex->pop_select(); //main select
           }
         | create_or_replace definer_opt opt_view_suid VIEW_SYM
           opt_if_not_exists table_ident
           {
+            if (Lex->main_select_push())
+              MYSQL_YYABORT;
             if (Lex->add_create_view(thd, $1 | $5,
                                      DTYPE_ALGORITHM_UNDEFINED, $3, $6))
               MYSQL_YYABORT;
           }
           view_list_opt AS view_select
-          { }
+          {
+            Lex->pop_select(); //main select
+          }
         | create_or_replace view_algorithm definer_opt opt_view_suid VIEW_SYM
           opt_if_not_exists table_ident
           {
             if (Lex->add_create_view(thd, $1 | $6, $2, $4, $7))
               MYSQL_YYABORT;
+            if (Lex->main_select_push())
+              MYSQL_YYABORT;
           }
           view_list_opt AS view_select
-          { }
+          {
+            Lex->pop_select(); //main select
+          }
         | create_or_replace definer_opt TRIGGER_SYM
-          { Lex->create_info.set($1); }
+          {
+            if (Lex->main_select_push())
+              MYSQL_YYABORT;
+            Lex->create_info.set($1);
+          }
           trigger_tail
-          { }
+          {
+            Lex->pop_select(); //main select
+          }
         | create_or_replace definer_opt PROCEDURE_SYM
-          { Lex->create_info.set($1); }
+          {
+            if (Lex->main_select_push())
+              MYSQL_YYABORT;
+            Lex->create_info.set($1);
+          }
           sp_tail
-          { }
+          {
+            Lex->pop_select(); //main select
+          }
         | create_or_replace definer_opt EVENT_SYM
-          { Lex->create_info.set($1); }
+          {
+            if (Lex->main_select_push())
+              MYSQL_YYABORT;
+            Lex->create_info.set($1);
+          }
           event_tail
-          { }
+          {
+            Lex->pop_select(); //main select
+          }
         | create_or_replace definer FUNCTION_SYM
           {
+            if (Lex->main_select_push())
+              MYSQL_YYABORT;
             Lex->create_info.set($1);
           }
-          sf_tail_not_aggregate
-          { }
+          sf_tail
+          {
+            Lex->pop_select(); //main select
+          }
         | create_or_replace definer AGGREGATE_SYM FUNCTION_SYM
           {
+            if (Lex->main_select_push())
+              MYSQL_YYABORT;
             Lex->create_info.set($1);
+            
           }
           sf_tail_aggregate
-          { }
+          {
+            Lex->pop_select(); //main select
+          }
         | create_or_replace no_definer FUNCTION_SYM
-          { Lex->create_info.set($1); }
+          {
+            if (Lex->main_select_push())
+              MYSQL_YYABORT;
+            Lex->create_info.set($1);
+          }
           create_function_tail
-          { }
+          {
+            Lex->pop_select(); //main select
+          }
         | create_or_replace no_definer AGGREGATE_SYM FUNCTION_SYM
           {
+            if (Lex->main_select_push())
+              MYSQL_YYABORT;
             Lex->create_info.set($1);
           }
           create_aggregate_function_tail
-          { }
+          {
+            Lex->pop_select(); //main select
+          }
         | create_or_replace USER_SYM opt_if_not_exists clear_privileges grant_list
           opt_require_clause opt_resource_options
           {
@@ -3098,7 +3236,7 @@ clear_privileges:
            lex->columns.empty();
            lex->grant= lex->grant_tot_col= 0;
            lex->all_privileges= 0;
-           lex->select_lex.db= null_clex_str;
+           lex->builtin_select.db= null_clex_str;
            lex->ssl_type= SSL_TYPE_NOT_SPECIFIED;
            lex->ssl_cipher= lex->x509_subject= lex->x509_issuer= 0;
            bzero((char *)&(lex->mqh),sizeof(lex->mqh));
@@ -3168,8 +3306,13 @@ call:
           {
             if (Lex->call_statement_start(thd, $2))
               MYSQL_YYABORT;
+            if (Lex->main_select_push())
+              MYSQL_YYABORT;
+          }
+          opt_sp_cparam_list
+          {
+            Lex->pop_select(); //main select
           }
-          opt_sp_cparam_list {}
         ;
 
 /* CALL parameters */
@@ -3586,10 +3729,16 @@ sp_hcond:
         ;
 
 signal_stmt:
-          SIGNAL_SYM signal_value opt_set_signal_information
+          SIGNAL_SYM
+          {
+            if (Lex->main_select_push())
+              YYABORT;
+          }
+          signal_value opt_set_signal_information
           {
-            if (Lex->add_signal_statement(thd, $2))
+            if (Lex->add_signal_statement(thd, $3))
               MYSQL_YYABORT;
+            Lex->pop_select(); //main select
           }
         ;
 
@@ -3715,9 +3864,14 @@ resignal_stmt:
         ;
 
 get_diagnostics:
-          GET_SYM which_area DIAGNOSTICS_SYM diagnostics_information
+          GET_SYM which_area DIAGNOSTICS_SYM
           {
-            Diagnostics_information *info= $4;
+            if (Lex->main_select_push())
+              YYABORT;
+          }
+          diagnostics_information
+          {
+            Diagnostics_information *info= $5;
 
             info->set_which_da($2);
 
@@ -3726,6 +3880,7 @@ get_diagnostics:
 
             if (Lex->m_sql_cmd == NULL)
               MYSQL_YYABORT;
+            Lex->pop_select(); //main select
           }
         ;
 
@@ -3893,7 +4048,16 @@ sp_decl_idents:
 
 sp_opt_default:
           /* Empty */ { $$ = NULL; }
-        | DEFAULT expr { $$ = $2; }
+        | DEFAULT
+          {
+            if (Lex->main_select_push())
+              MYSQL_YYABORT;
+          }
+          expr
+          {
+            Lex->pop_select(); //main select
+            $$ = $3;
+          }
         ;
 
 /*
@@ -3995,10 +4159,15 @@ sp_proc_stmt_statement:
 
 sp_proc_stmt_return:
           RETURN_SYM 
-          { Lex->sphead->reset_lex(thd); }
+          {
+            Lex->sphead->reset_lex(thd);
+            if (Lex->main_select_push())
+              MYSQL_YYABORT;
+          }
           expr
           {
             LEX *lex= Lex;
+            lex->pop_select(); //main select
             sp_head *sp= lex->sphead;
             if (sp->m_handler->add_instr_freturn(thd, sp, lex->spcont,
                                                  $3, lex) ||
@@ -4036,6 +4205,8 @@ assignment_source_expr:
           {
             DBUG_ASSERT(thd->free_list == NULL);
             Lex->sphead->reset_lex(thd, $1);
+            if (Lex->main_select_push())
+              MYSQL_YYABORT;
           }
           expr
           {
@@ -4044,6 +4215,7 @@ assignment_source_expr:
             $$->sp_lex_in_use= true;
             $$->set_item_and_free_list($3, thd->free_list);
             thd->free_list= NULL;
+            Lex->pop_select(); //main select
             if ($$->sphead->restore_lex(thd))
               MYSQL_YYABORT;
           }
@@ -4176,9 +4348,14 @@ sp_fetch_list:
         ;
 
 sp_if:
-          { Lex->sphead->reset_lex(thd); }
+          {
+            Lex->sphead->reset_lex(thd);
+            if (Lex->main_select_push())
+              MYSQL_YYABORT;
+          }
           expr THEN_SYM
           {
+            Lex->pop_select(); //main select
             LEX *lex= Lex;
             sp_head *sp= lex->sphead;
             sp_pcontext *ctx= lex->spcont;
@@ -4290,12 +4467,18 @@ case_stmt_specification:
         ;
 
 case_stmt_body:
-          { Lex->sphead->reset_lex(thd); /* For expr $2 */ }
+          {
+            Lex->sphead->reset_lex(thd); /* For expr $2 */
+
+            if (Lex->main_select_push())
+              MYSQL_YYABORT;
+          }
           expr
           {
             if (Lex->case_stmt_action_expr($2))
               MYSQL_YYABORT;
 
+            Lex->pop_select(); //main select
             if (Lex->sphead->restore_lex(thd))
               MYSQL_YYABORT;
           }
@@ -4319,6 +4502,9 @@ simple_when_clause:
           WHEN_SYM
           {
             Lex->sphead->reset_lex(thd); /* For expr $3 */
+
+            if (Lex->main_select_push())
+              MYSQL_YYABORT;
           }
           expr
           {
@@ -4327,6 +4513,8 @@ simple_when_clause:
             LEX *lex= Lex;
             if (lex->case_stmt_action_when($3, true))
               MYSQL_YYABORT;
+
+            lex->pop_select(); //main select
             /* For expr $3 */
             if (lex->sphead->restore_lex(thd))
               MYSQL_YYABORT;
@@ -4343,12 +4531,17 @@ searched_when_clause:
           WHEN_SYM
           {
             Lex->sphead->reset_lex(thd); /* For expr $3 */
+
+            if (Lex->main_select_push())
+              MYSQL_YYABORT;
           }
           expr
           {
             LEX *lex= Lex;
             if (lex->case_stmt_action_when($3, false))
               MYSQL_YYABORT;
+
+            lex->pop_select(); //main select
             /* For expr $3 */
             if (lex->sphead->restore_lex(thd))
               MYSQL_YYABORT;
@@ -4497,6 +4690,7 @@ while_body:
             LEX *lex= Lex;
             if (lex->sp_while_loop_expression(thd, $1))
               MYSQL_YYABORT;
+            Lex->pop_select(); //main select pushed before while_body use
             if (lex->sphead->restore_lex(thd))
               MYSQL_YYABORT;
           }
@@ -4509,7 +4703,12 @@ while_body:
 
 repeat_body:
           sp_proc_stmts1 UNTIL_SYM 
-          { Lex->sphead->reset_lex(thd); }
+          {
+            Lex->sphead->reset_lex(thd);
+
+            if (Lex->main_select_push())
+              MYSQL_YYABORT;
+          }
           expr END REPEAT_SYM
           {
             LEX *lex= Lex;
@@ -4520,6 +4719,8 @@ repeat_body:
             if (i == NULL ||
                 lex->sphead->add_instr(i))
               MYSQL_YYABORT;
+
+            lex->pop_select(); //main select
             if (lex->sphead->restore_lex(thd))
               MYSQL_YYABORT;
             /* We can shortcut the cont_backpatch here */
@@ -4548,8 +4749,12 @@ sp_labeled_control:
             if (Lex->sp_push_loop_label(thd, &$1))
               MYSQL_YYABORT;
             Lex->sphead->reset_lex(thd);
+
+            if (Lex->main_select_push())
+              MYSQL_YYABORT;
           }
           while_body pop_sp_loop_label
+
           { }
         | sp_label FOR_SYM
           {
@@ -4601,9 +4806,13 @@ sp_unlabeled_control:
             if (Lex->sp_push_loop_empty_label(thd))
               MYSQL_YYABORT;
             Lex->sphead->reset_lex(thd);
+
+            if (Lex->main_select_push())
+              MYSQL_YYABORT;
           }
           while_body
           {
+            // while body pop main select
             Lex->sp_pop_loop_empty_label(thd);
           }
         | FOR_SYM
@@ -5030,25 +5239,15 @@ size_number:
 */
 
 create_body:
-          '(' create_field_list ')'
+          create_field_list_parens
           { Lex->create_info.option_list= NULL; }
           opt_create_table_options opt_create_partitioning opt_create_select {}
         | opt_create_table_options opt_create_partitioning opt_create_select {}
-        /*
-          the following rule is redundant, but there's a shift/reduce
-          conflict that prevents the rule above from parsing a syntax like
-          CREATE TABLE t1 (SELECT 1);
-        */
-        | '(' create_select_query_specification ')'
-        | '(' create_select_query_specification ')'
-          { Select->set_braces(1);} union_list {}
-        | '(' create_select_query_specification ')'
-          { Select->set_braces(1);} union_order_or_limit {}
         | create_like
           {
 
             Lex->create_info.add(DDL_options_st::OPT_LIKE);
-            TABLE_LIST *src_table= Lex->select_lex.add_table_to_list(thd,
+            TABLE_LIST *src_table= Lex->builtin_select.add_table_to_list(thd,
                                         $1, NULL, 0, TL_READ, MDL_SHARED_READ);
             if (! src_table)
               MYSQL_YYABORT;
@@ -5059,7 +5258,7 @@ create_body:
 
 create_like:
           LIKE table_ident                      { $$= $2; }
-        | '(' LIKE table_ident ')'              { $$= $3; }
+        | LEFT_PAREN_LIKE LIKE table_ident ')'  { $$= $3; }
         ;
 
 opt_create_select:
@@ -5068,23 +5267,42 @@ opt_create_select:
         ;
 
 create_select_query_expression:
-          opt_with_clause SELECT_SYM create_select_part2 opt_table_expression
-          create_select_part4
-          { 
-            Select->set_braces(0);
-            Select->set_with_clause($1);
+          query_expression
+          {
+            SELECT_LEX *first_select= $1->first_select();
+
+            if (Lex->sql_command == SQLCOM_INSERT ||
+                Lex->sql_command == SQLCOM_REPLACE)
+            {
+              if (Lex->sql_command == SQLCOM_INSERT)
+                Lex->sql_command= SQLCOM_INSERT_SELECT;
+              else
+                Lex->sql_command= SQLCOM_REPLACE_SELECT;
+            }
+            Lex->insert_select_hack(first_select);
+            if (Lex->check_main_unit_semantics())
+              MYSQL_YYABORT;
+
           }
-          union_clause
-        | opt_with_clause SELECT_SYM create_select_part2 
-          create_select_part3_union_not_ready create_select_part4
+        | LEFT_PAREN_WITH with_clause query_expression_body ')'
           {
-            Select->set_with_clause($1);
+            SELECT_LEX *first_select= $3->first_select();
+            $3->set_with_clause($2);
+            $2->attach_to(first_select);
+
+            Lex->insert_select_hack(first_select);
+            if (Lex->check_main_unit_semantics())
+              MYSQL_YYABORT;
+
+            if (Lex->sql_command == SQLCOM_INSERT ||
+                Lex->sql_command == SQLCOM_REPLACE)
+            {
+              if (Lex->sql_command == SQLCOM_INSERT)
+                Lex->sql_command= SQLCOM_INSERT_SELECT;
+              else
+                Lex->sql_command= SQLCOM_REPLACE_SELECT;
+            }
           }
-        | '(' create_select_query_specification ')'
-        | '(' create_select_query_specification ')'
-          { Select->set_braces(1);} union_list {}
-        | '(' create_select_query_specification ')'
-          { Select->set_braces(1);} union_order_or_limit {}
         ;
 
 opt_create_partitioning:
@@ -5170,13 +5388,17 @@ partition_entry:
               thd->parse_error(ER_PARTITION_ENTRY_ERROR);
               MYSQL_YYABORT;
             }
-            DBUG_ASSERT(Lex->part_info->table);
+            if (Lex->main_select_push())
+              MYSQL_YYABORT;
             /*
               We enter here when opening the frm file to translate
               partition info string into part_info data structure.
             */
           }
-          partition {}
+          partition
+          {
+            Lex->pop_select(); //main select
+          }
         ;
 
 partition:
@@ -5898,56 +6120,6 @@ opt_versioning_interval_start:
  End of partition parser part
 */
 
-create_select_query_specification:
-          opt_with_clause SELECT_SYM create_select_part2 create_select_part3
-          create_select_part4
-          {
-            Select->set_with_clause($1);
-          }
-        ;
-
-create_select_part2:
-          {
-            LEX *lex=Lex;
-            if (lex->sql_command == SQLCOM_INSERT)
-              lex->sql_command= SQLCOM_INSERT_SELECT;
-            else if (lex->sql_command == SQLCOM_REPLACE)
-              lex->sql_command= SQLCOM_REPLACE_SELECT;
-            /*
-              The following work only with the local list, the global list
-              is created correctly in this case
-            */
-            lex->current_select->table_list.save_and_clear(&lex->save_list);
-            mysql_init_select(lex);
-            lex->current_select->parsing_place= SELECT_LIST;
-          }
-          select_options select_item_list
-          {
-            Select->parsing_place= NO_MATTER;
-          }
-        ;
-
-create_select_part3:
-          opt_table_expression
-        | create_select_part3_union_not_ready
-        ;
-
-create_select_part3_union_not_ready:
-          table_expression order_or_limit
-        | order_or_limit
-        ;
-
-create_select_part4:
-          opt_select_lock_type
-          {
-            /*
-              The following work only with the local list, the global list
-              is created correctly in this case
-            */
-            Lex->current_select->table_list.push_front(&Lex->save_list);
-          }
-        ;
-
 opt_as:
           /* empty */ {}
         | AS {}
@@ -6165,7 +6337,7 @@ create_table_option:
           }
         | UNION_SYM opt_equal
           {
-            Lex->select_lex.table_list.save_and_clear(&Lex->save_list);
+            Lex->builtin_select.table_list.save_and_clear(&Lex->save_list);
           }
           '(' opt_table_list ')'
           {
@@ -6174,8 +6346,8 @@ create_table_option:
               from the global list.
             */
             LEX *lex=Lex;
-            lex->create_info.merge_list= lex->select_lex.table_list;
-            lex->select_lex.table_list= lex->save_list;
+            lex->create_info.merge_list= lex->builtin_select.table_list;
+            lex->builtin_select.table_list= lex->save_list;
             /*
               When excluding union list from the global list we assume that
               elements of the former immediately follow elements which represent
@@ -6376,6 +6548,13 @@ create_field_list:
         }
         ;
 
+create_field_list_parens:
+        LEFT_PAREN_ALT field_list ')'
+        {
+          Lex->create_last_non_select_table= Lex->last_table();
+        }
+        ;
+
 field_list:
           field_list_item
         | field_list ',' field_list_item
@@ -6702,6 +6881,8 @@ parse_vcol_expr:
               Prevent the end user from invoking this command.
             */
             MYSQL_YYABORT_UNLESS(Lex->parse_vcol_expr);
+            if (Lex->main_select_push())
+              MYSQL_YYABORT;
           }
           expr
           {
@@ -6709,13 +6890,29 @@ parse_vcol_expr:
             if (!v)
               MYSQL_YYABORT;
             Lex->last_field->vcol_info= v;
+            Lex->pop_select(); //main select
           }
         ;
 
 parenthesized_expr:
-          subselect
+          remember_tok_start
+          query_expression
           {
-            $$= new (thd->mem_root) Item_singlerow_subselect(thd, $1);
+            if (!Lex->expr_allows_subselect ||
+               Lex->sql_command == (int)SQLCOM_PURGE)
+            {
+              thd->parse_error(ER_SYNTAX_ERROR, $1);
+              MYSQL_YYABORT;
+            }
+
+            // Add the subtree of subquery to the current SELECT_LEX
+            SELECT_LEX *curr_sel= Lex->select_stack_head();
+            DBUG_ASSERT(Lex->current_select == curr_sel);
+            curr_sel->register_unit($2, &curr_sel->context);
+            curr_sel->add_statistics($2);
+
+            $$= new (thd->mem_root)
+              Item_singlerow_subselect(thd, $2->first_select());
             if ($$ == NULL)
               MYSQL_YYABORT;
           }
@@ -7636,22 +7833,24 @@ alter:
             Lex->table_type= TABLE_TYPE_UNKNOWN;
             Lex->sql_command= SQLCOM_ALTER_TABLE;
             Lex->duplicates= DUP_ERROR; 
-            Lex->select_lex.init_order();
+            Lex->builtin_select.init_order();
             Lex->create_info.init();
             Lex->create_info.row_type= ROW_TYPE_NOT_USED;
             Lex->alter_info.reset();
             Lex->no_write_to_binlog= 0;
             Lex->create_info.storage_media= HA_SM_DEFAULT;
+            if (Lex->main_select_push())
+              MYSQL_YYABORT;
             DBUG_ASSERT(!Lex->m_sql_cmd);
           }
           alter_options TABLE_SYM table_ident opt_lock_wait_timeout
           {
-            if (!Lex->select_lex.add_table_to_list(thd, $5, NULL,
+            if (!Lex->builtin_select.add_table_to_list(thd, $5, NULL,
                                                    TL_OPTION_UPDATING,
                                                    TL_READ_NO_INSERT,
                                                    MDL_SHARED_UPGRADABLE))
               MYSQL_YYABORT;
-            Lex->select_lex.db= (Lex->select_lex.table_list.first)->db;
+            Lex->builtin_select.db= (Lex->builtin_select.table_list.first)->db;
             Lex->create_last_non_select_table= Lex->last_table();
           }
           alter_commands
@@ -7662,12 +7861,15 @@ alter:
               Lex->m_sql_cmd= new (thd->mem_root) Sql_cmd_alter_table();
               if (Lex->m_sql_cmd == NULL)
                 MYSQL_YYABORT;
+              Lex->pop_select(); //main select
             }
           }
         | ALTER DATABASE ident_or_empty
           {
             Lex->create_info.default_table_charset= NULL;
             Lex->create_info.used_fields= 0;
+            if (Lex->main_select_push())
+              MYSQL_YYABORT;
           }
           create_database_options
           {
@@ -7676,6 +7878,7 @@ alter:
             lex->name= $3;
             if (lex->name.str == NULL && lex->copy_db_to(&lex->name))
               MYSQL_YYABORT;
+            Lex->pop_select(); //main select
           }
         | ALTER DATABASE ident UPGRADE_SYM DATA_SYM DIRECTORY_SYM NAME_SYM
           {
@@ -7691,6 +7894,8 @@ alter:
 
             if (lex->sphead)
               my_yyabort_error((ER_SP_NO_DROP_SP, MYF(0), "PROCEDURE"));
+            if (Lex->main_select_push())
+              MYSQL_YYABORT;
             lex->sp_chistics.init();
           }
           sp_a_chistics
@@ -7699,6 +7904,9 @@ alter:
 
             lex->sql_command= SQLCOM_ALTER_PROCEDURE;
             lex->spname= $3;
+            Lex->pop_select(); //main select
+            if (Lex->check_main_unit_semantics())
+              MYSQL_YYABORT;
           }
         | ALTER FUNCTION_SYM sp_name
           {
@@ -7706,6 +7914,8 @@ alter:
 
             if (lex->sphead)
               my_yyabort_error((ER_SP_NO_DROP_SP, MYF(0), "FUNCTION"));
+            if (Lex->main_select_push())
+              MYSQL_YYABORT;
             lex->sp_chistics.init();
           }
           sp_a_chistics
@@ -7714,14 +7924,23 @@ alter:
 
             lex->sql_command= SQLCOM_ALTER_FUNCTION;
             lex->spname= $3;
+            Lex->pop_select(); //main select
+            if (Lex->check_main_unit_semantics())
+              MYSQL_YYABORT;
           }
         | ALTER view_algorithm definer_opt opt_view_suid VIEW_SYM table_ident
           {
+            if (Lex->main_select_push())
+              MYSQL_YYABORT;
             if (Lex->add_alter_view(thd, $2, $4, $6))
               MYSQL_YYABORT;
           }
           view_list_opt AS view_select
-          {}
+          {
+            Lex->pop_select(); //main select
+            if (Lex->check_main_unit_semantics())
+              MYSQL_YYABORT;
+          }
         | ALTER definer_opt opt_view_suid VIEW_SYM table_ident
           /*
             We have two separate rules for ALTER VIEW rather that
@@ -7729,14 +7948,22 @@ alter:
             with the ALTER EVENT below.
           */
           {
+            if (Lex->main_select_push())
+              MYSQL_YYABORT;
             if (Lex->add_alter_view(thd, VIEW_ALGORITHM_INHERIT, $3, $5))
               MYSQL_YYABORT;
           }
           view_list_opt AS view_select
-          {}
+          {
+            Lex->pop_select(); //main select
+            if (Lex->check_main_unit_semantics())
+              MYSQL_YYABORT;
+          }
         | ALTER definer_opt remember_name EVENT_SYM sp_name
           {
-            /* 
+            if (Lex->main_select_push())
+              MYSQL_YYABORT;
+            /*
               It is safe to use Lex->spname because
               ALTER EVENT xxx RENATE TO yyy DO ALTER EVENT RENAME TO
               is not allowed. Lex->spname is used in the case of RENAME TO
@@ -7768,6 +7995,8 @@ alter:
             */
             Lex->sql_command= SQLCOM_ALTER_EVENT;
             Lex->stmt_definition_end= (char*)YYLIP->get_cpp_ptr();
+
+            Lex->pop_select(); //main select
           }
         | ALTER TABLESPACE alter_tablespace_info
           {
@@ -7811,15 +8040,17 @@ alter:
             lex->create_info.init();
             lex->no_write_to_binlog= 0;
             DBUG_ASSERT(!lex->m_sql_cmd);
+            if (Lex->main_select_push())
+              MYSQL_YYABORT;
           }
           table_ident
           {
             LEX *lex= Lex;
             if (!(lex->create_info.seq_create_info= new (thd->mem_root)
                                                      sequence_definition()) ||
-                !lex->select_lex.add_table_to_list(thd, $5, NULL,
-                                                   TL_OPTION_SEQUENCE,
-                                                   TL_WRITE, MDL_EXCLUSIVE))
+                !lex->builtin_select.add_table_to_list(thd, $5, NULL,
+                                                       TL_OPTION_SEQUENCE,
+                                                       TL_WRITE, MDL_EXCLUSIVE))
               MYSQL_YYABORT;
           }
           sequence_defs
@@ -7828,6 +8059,9 @@ alter:
             Lex->m_sql_cmd= new (thd->mem_root) Sql_cmd_alter_sequence($3);
             if (Lex->m_sql_cmd == NULL)
               MYSQL_YYABORT;
+            Lex->pop_select(); //main select
+            if (Lex->check_main_unit_semantics())
+              MYSQL_YYABORT;
           }
         ;
 
@@ -7977,18 +8211,18 @@ alter_commands:
           WITH TABLE_SYM table_ident have_partitioning
           {
             LEX *lex= thd->lex;
-            lex->select_lex.db= $6->db;
-            if (lex->select_lex.db.str == NULL &&
-                lex->copy_db_to(&lex->select_lex.db))
+            lex->builtin_select.db=$6->db;
+            if (lex->builtin_select.db.str == NULL &&
+                lex->copy_db_to(&lex->builtin_select.db))
             {
               MYSQL_YYABORT;
             }
             lex->name= $6->table;
             lex->alter_info.partition_flags|= ALTER_PARTITION_EXCHANGE;
-            if (!lex->select_lex.add_table_to_list(thd, $6, NULL,
-                                                   TL_OPTION_UPDATING,
-                                                   TL_READ_NO_INSERT,
-                                                   MDL_SHARED_NO_WRITE))
+            if (!lex->builtin_select.add_table_to_list(thd, $6, NULL,
+                                                       TL_OPTION_UPDATING,
+                                                       TL_READ_NO_INSERT,
+                                                       MDL_SHARED_NO_WRITE))
               MYSQL_YYABORT;
             DBUG_ASSERT(!lex->m_sql_cmd);
             lex->m_sql_cmd= new (thd->mem_root)
@@ -8233,9 +8467,9 @@ alter_list_item:
         | RENAME opt_to table_ident
           {
             LEX *lex=Lex;
-            lex->select_lex.db= $3->db;
-            if (lex->select_lex.db.str == NULL &&
-                lex->copy_db_to(&lex->select_lex.db))
+            lex->builtin_select.db= $3->db;
+            if (lex->builtin_select.db.str == NULL &&
+                lex->copy_db_to(&lex->builtin_select.db))
             {
               MYSQL_YYABORT;
             }
@@ -8522,9 +8756,13 @@ checksum:
             lex->sql_command = SQLCOM_CHECKSUM;
             /* Will be overridden during execution. */
             YYPS->m_lock_type= TL_UNLOCK;
+            if (Lex->main_select_push())
+              MYSQL_YYABORT;
           }
           table_list opt_checksum_type
-          {}
+          {
+            Lex->pop_select(); //main select
+          }
         ;
 
 opt_checksum_type:
@@ -8550,6 +8788,8 @@ repair:
             lex->alter_info.reset();
             /* Will be overridden during execution. */
             YYPS->m_lock_type= TL_UNLOCK;
+            if (Lex->main_select_push())
+              MYSQL_YYABORT;
           }
           repair_table_or_view
           {
@@ -8558,6 +8798,7 @@ repair:
             lex->m_sql_cmd= new (thd->mem_root) Sql_cmd_repair_table();
             if (lex->m_sql_cmd == NULL)
               MYSQL_YYABORT;
+            Lex->pop_select(); //main select
           }
         ;
 
@@ -8586,6 +8827,8 @@ analyze:
           ANALYZE_SYM opt_no_write_to_binlog table_or_tables
           {
             LEX *lex=Lex;
+            if (lex->main_select_push())
+              YYABORT;
             lex->sql_command = SQLCOM_ANALYZE;
             lex->no_write_to_binlog= $2;
             lex->check_opt.init();
@@ -8600,6 +8843,7 @@ analyze:
             lex->m_sql_cmd= new (thd->mem_root) Sql_cmd_analyze_table();
             if (lex->m_sql_cmd == NULL)
               MYSQL_YYABORT;
+            Lex->pop_select(); //main select
           }
         ;
 
@@ -8716,6 +8960,8 @@ check:    CHECK_SYM
             lex->alter_info.reset();
             /* Will be overridden during execution. */
             YYPS->m_lock_type= TL_UNLOCK;
+            if (Lex->main_select_push())
+              MYSQL_YYABORT;
           }
           check_view_or_table
           {
@@ -8726,6 +8972,7 @@ check:    CHECK_SYM
             lex->m_sql_cmd= new (thd->mem_root) Sql_cmd_check_table();
             if (lex->m_sql_cmd == NULL)
               MYSQL_YYABORT;
+            Lex->pop_select(); //main select
           }
         ;
 
@@ -8763,6 +9010,8 @@ optimize:
             lex->alter_info.reset();
             /* Will be overridden during execution. */
             YYPS->m_lock_type= TL_UNLOCK;
+            if (Lex->main_select_push())
+              MYSQL_YYABORT;
           }
           table_list opt_lock_wait_timeout
           {
@@ -8771,6 +9020,7 @@ optimize:
             lex->m_sql_cmd= new (thd->mem_root) Sql_cmd_optimize_table();
             if (lex->m_sql_cmd == NULL)
               MYSQL_YYABORT;
+            Lex->pop_select(); //main select
           }
         ;
 
@@ -8784,9 +9034,13 @@ rename:
           RENAME table_or_tables
           {
             Lex->sql_command= SQLCOM_RENAME_TABLE;
+            if (Lex->main_select_push())
+              MYSQL_YYABORT;
           }
           table_to_table_list
-          {}
+          {
+            Lex->pop_select(); //main select
+          }
         | RENAME USER_SYM clear_privileges rename_list
           {
             Lex->sql_command = SQLCOM_RENAME_USER;
@@ -8880,9 +9134,13 @@ preload:
             LEX *lex=Lex;
             lex->sql_command=SQLCOM_PRELOAD_KEYS;
             lex->alter_info.reset();
+            if (Lex->main_select_push())
+              MYSQL_YYABORT;
           }
           preload_list_or_parts
-          {}
+          {
+            Lex->pop_select(); //main select
+          }
         ;
 
 preload_list_or_parts:
@@ -8925,8 +9183,8 @@ adm_partition:
 
 cache_keys_spec:
           {
-            Lex->select_lex.alloc_index_hints(thd);
-            Select->set_index_hint_type(INDEX_HINT_USE, 
+            Lex->builtin_select.alloc_index_hints(thd);
+            Select->set_index_hint_type(INDEX_HINT_USE,
                                         INDEX_HINT_MASK_ALL);
           }
           cache_key_list_or_empty
@@ -8947,217 +9205,350 @@ opt_ignore_leaves:
   Select : retrieve data from table
 */
 
-
 select:
-          opt_with_clause select_init
+          query_expression
           {
-            LEX *lex= Lex;
-            lex->sql_command= SQLCOM_SELECT;
-            lex->current_select->set_with_clause($1);
+            Lex->selects_allow_into= TRUE;
+            Lex->selects_allow_procedure= TRUE;
+            Lex->set_main_unit($1);
+            if (Lex->check_main_unit_semantics())
+              MYSQL_YYABORT;
+
+            SELECT_LEX *fake= Lex->unit.fake_select_lex;
+            if (fake)
+            {
+              fake->no_table_names_allowed= 1;
+              Lex->push_select(fake);
+            }
+            else
+              Lex->push_select(Lex->first_select_lex());
+            Lex->sql_command= SQLCOM_SELECT;
           }
         ;
 
-select_init:
-          SELECT_SYM select_options_and_item_list select_init3
-        | table_value_constructor
-        | table_value_constructor union_list
-        | table_value_constructor union_order_or_limit
-        | '(' select_paren ')'
-        | '(' select_paren ')' union_list
-        | '(' select_paren ')' union_order_or_limit
-        ;
 
-union_list_part2:
-          SELECT_SYM select_options_and_item_list select_init3_union_query_term
-        | table_value_constructor
-        | table_value_constructor union_list
-        | table_value_constructor union_order_or_limit
-        | '(' select_paren_union_query_term ')'
-        | '(' select_paren_union_query_term ')' union_list
-        | '(' select_paren_union_query_term ')' union_order_or_limit
+simple_table:
+          query_specification      { $$= $1; }
+        | table_value_constructor  { $$= $1; }
         ;
-
-select_paren:
+        
+table_value_constructor:
+	  VALUES
+	  {
+	    LEX *lex=Lex;
+            //lex->field_list.empty();
+            lex->many_values.empty();
+            lex->insert_list=0;
+	  }
+	  values_list
+	  {
+	    LEX *lex=Lex;
+            if (!($$= lex->alloc_select(TRUE)) ||
+                  lex->push_select($$))
+              MYSQL_YYABORT;
+            $$->init_select();
+	    if (!($$->tvc=
+	          new (lex->thd->mem_root) table_value_constr(lex->many_values, $$, $$->options)))
+	      MYSQL_YYABORT;
+	    lex->many_values.empty();
+	  }
+	;
+	
+query_specification:
+          SELECT_SYM
           {
-            Lex->current_select->set_braces(true);
+            SELECT_LEX *sel;
+            LEX *lex= Lex;
+            if (!(sel= lex->alloc_select(TRUE)) ||
+                  lex->push_select(sel))
+              MYSQL_YYABORT;
+            sel->init_select();
+            sel->braces= FALSE;
           }
-          table_value_constructor
+          select_options
           {
-            DBUG_ASSERT(Lex->current_select->braces);
+            Select->parsing_place= SELECT_LIST;
           }
-        |
+          select_item_list
           {
-            /*
-              In order to correctly parse UNION's global ORDER BY we need to
-              set braces before parsing the clause.
-            */
-            Lex->current_select->set_braces(true);
+            Select->parsing_place= NO_MATTER;
           }
-          SELECT_SYM select_options_and_item_list select_part3
-          opt_select_lock_type
+          opt_into
+          opt_from_clause
+          opt_where_clause
+          opt_group_clause
+          opt_having_clause
+          opt_window_clause
           {
-            DBUG_ASSERT(Lex->current_select->braces);
+            $$= Lex->pop_select();
           }
-        | '(' select_paren ')'
         ;
 
-select_paren_union_query_term:
-          {
-            /*
-              In order to correctly parse UNION's global ORDER BY we need to
-              set braces before parsing the clause.
-            */
-            Lex->current_select->set_braces(true);
-          }
-          SELECT_SYM select_options_and_item_list select_part3_union_query_term
-          opt_select_lock_type
-          {
-            DBUG_ASSERT(Lex->current_select->braces);
-          }
-        | '(' select_paren_union_query_term ')'
+opt_from_clause:
+        /* Empty */
+        | from_clause
         ;
 
-select_paren_view:
-          {
-            /*
-              In order to correctly parse UNION's global ORDER BY we need to
-              set braces before parsing the clause.
-            */
-            Lex->current_select->set_braces(true);
-          }
-          SELECT_SYM select_options_and_item_list select_part3_view
-          opt_select_lock_type
-          {
-            DBUG_ASSERT(Lex->current_select->braces);
-          }
-        | '(' select_paren_view ')'
+
+query_primary:
+          simple_table
+          { $$= $1; }
+        | query_primary_parens
+          { $$= $1; }
         ;
 
-/* The equivalent of select_paren for nested queries. */
-select_paren_derived:
+query_primary_parens:
+          '(' query_expression_unit
           {
-            Lex->current_select->set_braces(true);
+            SELECT_LEX *last= $2->pre_last_parse->next_select();
+            int cmp= cmp_unit_op($2->first_select()->next_select()->linkage,
+                                last->linkage);
+            if (cmp < 0)
+            {
+              if (!check_intersect_prefix($2->first_select()))
+              {
+                if (Lex->pop_new_select_and_wrap() == NULL)
+                  MYSQL_YYABORT;
+              }
+            }
+            Lex->push_select($2->fake_select_lex);
           }
-          table_value_constructor
+          query_expression_tail ')'
           {
-            DBUG_ASSERT(Lex->current_select->braces);
-            $$= Lex->current_select->master_unit()->first_select();
+            Lex->pop_select();
+            if ($4)
+            {
+              ($4)->set_to($2->fake_select_lex);
+            }
+            $$= $2->first_select();
           }
-        |
+        | '(' query_primary
           {
-            Lex->current_select->set_braces(true);
+            Lex->push_select($2);
           }
-          SELECT_SYM select_part2_derived
-          opt_table_expression
-          opt_order_clause
-          opt_limit_clause
-          opt_select_lock_type
+          query_expression_tail ')'
           {
-            DBUG_ASSERT(Lex->current_select->braces);
-            $$= Lex->current_select->master_unit()->first_select();
+            Lex->pop_select();
+            $$= $2;
+            $$->braces= TRUE;
+            if ($4)
+            {
+              if ($2->next_select())
+              {
+                SELECT_LEX_UNIT *unit= $2->master_unit();
+                if (!unit)
+                  unit= Lex->create_unit($2);
+                if (!unit)
+                  YYABORT;
+                if (!unit->fake_select_lex->is_set_query_expr_tail)
+                  $4->set_to(unit->fake_select_lex);
+                else
+                {
+                  $$= Lex->wrap_unit_into_derived(unit);
+                  if (!$$)
+                    YYABORT;
+                  $4->set_to($$);
+                }
+              }
+              else if (!$2->is_set_query_expr_tail)
+              {
+                $4->set_to($2);
+              }
+              else
+              {
+                SELECT_LEX_UNIT *unit= Lex->create_unit($2);
+                if (!unit)
+                  YYABORT;
+                $$= Lex->wrap_unit_into_derived(unit);
+                if (!$$)
+                  YYABORT;
+                $4->set_to($$);
+              }
+            }
           }
-        | '(' select_paren_derived ')'  { $$= $2; }
         ;
 
-select_init3:
-          opt_table_expression
-          opt_select_lock_type
+query_expression_unit:
+          query_primary
+          unit_type_decl
+          query_primary
           {
-            /* Parentheses carry no meaning here */
-            Lex->current_select->set_braces(false);
+            SELECT_LEX *sel1;
+            SELECT_LEX *sel2;
+            if (!$1->next_select())
+              sel1= $1;
+            else
+            {
+              sel1= Lex->wrap_unit_into_derived($1->master_unit());
+              if (!sel1)
+                YYABORT;
+            }
+            if (!$3->next_select())
+              sel2= $3;
+            else
+            {
+              sel2= Lex->wrap_unit_into_derived($3->master_unit());
+              if (!sel2)
+                YYABORT;
+            }
+            sel1->link_neighbour(sel2);
+            sel2->set_linkage_and_distinct($2.unit_type, $2.distinct);
+            $$= Lex->create_unit(sel1);
+            $$->pre_last_parse= sel1;
+            if ($$ == NULL)
+              YYABORT;
           }
-          union_clause
-        | select_part3_union_not_ready
-          opt_select_lock_type
+        | query_expression_unit
+          unit_type_decl
+          query_primary
           {
-            /* Parentheses carry no meaning here */
-            Lex->current_select->set_braces(false);
-          }
-        ;
-
+            SELECT_LEX *sel1;
+            if (!$3->next_select())
+              sel1= $3;
+            else
+            {
+              sel1= Lex->wrap_unit_into_derived($3->master_unit());
+              if (!sel1)
+                YYABORT;
+            }
+            SELECT_LEX *last= $1->pre_last_parse->next_select();
 
-select_init3_union_query_term:
-          opt_table_expression
-          opt_select_lock_type
-          {
-            /* Parentheses carry no meaning here */
-            Lex->current_select->set_braces(false);
-          }
-          union_clause
-        | select_part3_union_not_ready_noproc
-          opt_select_lock_type
-          {
-            /* Parentheses carry no meaning here */
-            Lex->current_select->set_braces(false);
+            int cmp= cmp_unit_op($2.unit_type, last->linkage);
+            if (cmp == 0)
+            {
+              // do nothing, this part will be just connected
+            }
+            else if (cmp > 0)
+            {
+              // Store beginning and continue to connect parts
+              if (Lex->push_new_select($1->pre_last_parse))
+                MYSQL_YYABORT;
+            }
+            else /* cmp < 0 */
+            {
+              // wrap stored part in a select, then continue to connect parts
+              if (!check_intersect_prefix($1->first_select()))
+              {
+                if ((last= Lex->pop_new_select_and_wrap()) == NULL)
+                  MYSQL_YYABORT;
+                last->set_master_unit($1);
+              }
+            }
+            last->link_neighbour(sel1);
+            sel1->set_master_unit($1);
+            sel1->set_linkage_and_distinct($2.unit_type, $2.distinct);
+            $$= $1;
+            $$->pre_last_parse= last;
           }
         ;
 
-
-select_init3_view:
-          opt_table_expression opt_select_lock_type
+query_expression_body:
+          query_primary
           {
-            Lex->current_select->set_braces(false);
+            Lex->push_select($1);
           }
-        | opt_table_expression opt_select_lock_type
+          query_expression_tail
           {
-            Lex->current_select->set_braces(false);
+            Lex->pop_select();
+            SELECT_LEX *sel= $1;
+            if ($3)
+            {
+              if ($1->next_select())
+              {
+                SELECT_LEX_UNIT *unit= $1->master_unit();
+                if (!unit)
+                  unit= Lex->create_unit($1);
+                if (!unit)
+                  YYABORT;
+                if (!unit->fake_select_lex->is_set_query_expr_tail)
+                  $3->set_to(unit->fake_select_lex);
+                else
+                {
+                  SELECT_LEX *sel= Lex->wrap_unit_into_derived(unit);
+                  if (!sel)
+                    YYABORT;
+                  $3->set_to(sel);
+                }
+              }
+              else if (!$1->is_set_query_expr_tail)
+                $3->set_to($1);
+              else
+              {
+                SELECT_LEX_UNIT *unit= $1->master_unit();
+                if (!unit)
+                  unit= Lex->create_unit($1);
+                if (!unit)
+                  YYABORT;
+                sel= Lex->wrap_unit_into_derived(unit);
+                if (!sel)
+                  YYABORT;
+                $3->set_to(sel);
+              }
+            }
+            $$= Lex->create_unit(sel);
+            if ($$ == NULL)
+              YYABORT;
           }
-          union_list_view
-        | order_or_limit opt_select_lock_type
+        | query_expression_unit
           {
-            Lex->current_select->set_braces(false);
+            SELECT_LEX *last= $1->pre_last_parse->next_select();
+            int cmp= cmp_unit_op($1->first_select()->next_select()->linkage,
+                                last->linkage);
+            if (cmp < 0)
+            {
+              if (!check_intersect_prefix($1->first_select()))
+              {
+                if (Lex->pop_new_select_and_wrap() == NULL)
+                  MYSQL_YYABORT;
+              }
+            }
+            Lex->push_select($1->fake_select_lex);
           }
-        | table_expression order_or_limit opt_select_lock_type
+          query_expression_tail
           {
-            Lex->current_select->set_braces(false);
+            Lex->pop_select();
+            if ($3)
+            {
+              ($3)->set_to($1->fake_select_lex);
+            }
+            $$= $1;
           }
         ;
 
-/*
-  The SELECT parts after select_item_list that cannot be followed by UNION.
-*/
-
-select_part3:
-          opt_table_expression
-        | select_part3_union_not_ready
-        ;
-
-select_part3_union_query_term:
-          opt_table_expression
-        | select_part3_union_not_ready_noproc
-        ;
-
-select_part3_view:
-          opt_table_expression
-        | order_or_limit
-        | table_expression order_or_limit
+query_expression:
+          opt_with_clause
+          query_expression_body
+          {
+            if ($1)
+            {
+              $2->set_with_clause($1);
+              $1->attach_to($2->first_select());
+            }
+            $$= $2;
+          }
         ;
 
-select_part3_union_not_ready:
-          select_part3_union_not_ready_noproc
-        | table_expression procedure_clause
-        | table_expression order_or_limit procedure_clause
-        ;
+subselect:
+          remember_tok_start
+          query_expression
+          {
+            if (!Lex->expr_allows_subselect ||
+                Lex->sql_command == (int)SQLCOM_PURGE)
+            {
+              thd->parse_error(ER_SYNTAX_ERROR, $1);
+              MYSQL_YYABORT;
+            }
 
-select_part3_union_not_ready_noproc:
-          order_or_limit
-        | into opt_table_expression opt_order_clause opt_limit_clause
-        | table_expression into
-        | table_expression order_or_limit
-        | table_expression order_or_limit into
-        ;
+            // Add the subtree of subquery to the current SELECT_LEX
+            SELECT_LEX *curr_sel= Lex->select_stack_head();
+            DBUG_ASSERT(Lex->current_select == curr_sel);
+            if (curr_sel)
+            {
+              curr_sel->register_unit($2, &curr_sel->context);
+              curr_sel->add_statistics($2);
+            }
 
-select_options_and_item_list:
-          {
-            LEX *lex= Lex;
-            SELECT_LEX *sel= lex->current_select;
-            if (sel->linkage != UNION_TYPE)
-              mysql_init_select(lex);
-            lex->current_select->parsing_place= SELECT_LIST;
-          }
-          select_options select_item_list
-          {
-            Select->parsing_place= NO_MATTER;
+            $$= $2->first_select();
           }
         ;
 
@@ -9165,18 +9556,6 @@ select_options_and_item_list:
 /**
   <table expression>, as in the SQL standard.
 */
-table_expression:
-          from_clause
-          opt_where_clause
-          opt_group_clause
-          opt_having_clause
-          opt_window_clause
-        ;
-
-opt_table_expression:
-            /* Empty */
-          | table_expression
-        ;
 
 from_clause:
           FROM table_reference_list
@@ -9276,59 +9655,63 @@ select_option:
           query_expression_option
         | SQL_NO_CACHE_SYM
           {
-            /* 
-              Allow this flag only on the first top-level SELECT statement, if
-              SQL_CACHE wasn't specified, and only once per query.
-             */
-            if (Lex->current_select != &Lex->select_lex)
-              my_yyabort_error((ER_CANT_USE_OPTION_HERE, MYF(0), "SQL_NO_CACHE"));
-            if (Lex->select_lex.sql_cache == SELECT_LEX::SQL_CACHE)
-              my_yyabort_error((ER_WRONG_USAGE, MYF(0), "SQL_CACHE", "SQL_NO_CACHE"));
-            if (Lex->select_lex.sql_cache == SELECT_LEX::SQL_NO_CACHE)
+            /*
+              Allow this flag once per query.
+            */
+            if (Select->options & OPTION_NO_QUERY_CACHE)
               my_yyabort_error((ER_DUP_ARGUMENT, MYF(0), "SQL_NO_CACHE"));
-
-            Lex->safe_to_cache_query=0;
-            Lex->select_lex.options&= ~OPTION_TO_QUERY_CACHE;
-            Lex->select_lex.sql_cache= SELECT_LEX::SQL_NO_CACHE;
+            Select->options|= OPTION_NO_QUERY_CACHE;
           }
         | SQL_CACHE_SYM
           {
-            /* 
-              Allow this flag only on the first top-level SELECT statement, if
-              SQL_NO_CACHE wasn't specified, and only once per query.
-             */
-            if (Lex->current_select != &Lex->select_lex)
-              my_yyabort_error((ER_CANT_USE_OPTION_HERE, MYF(0), "SQL_CACHE"));
-            if (Lex->select_lex.sql_cache == SELECT_LEX::SQL_NO_CACHE)
-              my_yyabort_error((ER_WRONG_USAGE, MYF(0), "SQL_NO_CACHE", "SQL_CACHE"));
-            if (Lex->select_lex.sql_cache == SELECT_LEX::SQL_CACHE)
+            /*
+              Allow this flag once per query.
+            */
+            if (Select->options & OPTION_TO_QUERY_CACHE)
               my_yyabort_error((ER_DUP_ARGUMENT, MYF(0), "SQL_CACHE"));
-
-            Lex->safe_to_cache_query=1;
-            Lex->select_lex.options|= OPTION_TO_QUERY_CACHE;
-            Lex->select_lex.sql_cache= SELECT_LEX::SQL_CACHE;
+            Select->options|= OPTION_TO_QUERY_CACHE;
           }
         ;
 
 opt_select_lock_type:
           /* empty */
-        | FOR_SYM UPDATE_SYM opt_lock_wait_timeout
+          { $$.empty(); }
+        | select_lock_type
+          { $$= $1; }
+        ;
+
+select_lock_type:
+          FOR_SYM UPDATE_SYM opt_lock_wait_timeout_new
           {
-            LEX *lex=Lex;
-            lex->current_select->lock_type= TL_WRITE;
-            lex->current_select->set_lock_for_tables(TL_WRITE);
-            lex->safe_to_cache_query=0;
+            $$= $3;
+            $$.defined_lock= TRUE;
+            $$.update_lock= TRUE;
           }
-        | LOCK_SYM IN_SYM SHARE_SYM MODE_SYM opt_lock_wait_timeout
+        | LOCK_SYM IN_SYM SHARE_SYM MODE_SYM opt_lock_wait_timeout_new
           {
-            LEX *lex=Lex;
-            lex->current_select->lock_type= TL_READ_WITH_SHARED_LOCKS;
-            lex->current_select->
-              set_lock_for_tables(TL_READ_WITH_SHARED_LOCKS);
-            lex->safe_to_cache_query=0;
+            $$= $5;
+            $$.defined_lock= TRUE;
+            $$.update_lock= FALSE;
           }
         ;
 
+opt_lock_wait_timeout_new:
+        /* empty */
+        {
+          $$.empty();
+        }
+        | WAIT_SYM ulong_num
+        {
+          $$.defined_timeout= TRUE;
+          $$.timeout= $2;
+        }
+        | NOWAIT_SYM
+        {
+          $$.defined_timeout= TRUE;
+          $$.timeout= 0;
+        }
+      ;
+
 select_item_list:
           select_item_list ',' select_item
         | select_item
@@ -11565,10 +11948,15 @@ esc_table_ref:
 /* Equivalent to <table reference list> in the SQL:2003 standard. */
 /* Warning - may return NULL in case of incomplete SELECT */
 derived_table_list:
-          esc_table_ref { $$=$1; }
+          esc_table_ref
+         {
+           $$=$1;
+           Select->add_joined_table($1);
+         }
         | derived_table_list ',' esc_table_ref
           {
             MYSQL_YYABORT_UNLESS($1 && ($$=$3));
+            Select->add_joined_table($3);
           }
         ;
 
@@ -11587,11 +11975,18 @@ join_table:
             left-associative joins.
           */
           table_ref normal_join table_ref %prec TABLE_REF_PRIORITY
-          { MYSQL_YYABORT_UNLESS($1 && ($$=$3)); $3->straight=$2; }
+          {
+            MYSQL_YYABORT_UNLESS($1 && ($$=$3));
+            Select->add_joined_table($1);
+            Select->add_joined_table($3);
+            $3->straight=$2;
+          }
         | table_ref normal_join table_ref
           ON
           {
             MYSQL_YYABORT_UNLESS($1 && $3);
+            Select->add_joined_table($1);
+            Select->add_joined_table($3);
             /* Change the current name resolution context to a local context. */
             if (push_new_name_resolution_context(thd, $1, $3))
               MYSQL_YYABORT;
@@ -11608,6 +12003,8 @@ join_table:
           USING
           {
             MYSQL_YYABORT_UNLESS($1 && $3);
+            Select->add_joined_table($1);
+            Select->add_joined_table($3);
           }
           '(' using_list ')'
           { 
@@ -11618,6 +12015,8 @@ join_table:
         | table_ref NATURAL inner_join table_factor
           {
             MYSQL_YYABORT_UNLESS($1 && ($$=$4));
+            Select->add_joined_table($1);
+            Select->add_joined_table($4);
 	    $4->straight=$3;
             add_join_natural($1,$4,NULL,Select);
           }
@@ -11627,6 +12026,8 @@ join_table:
           ON
           {
             MYSQL_YYABORT_UNLESS($1 && $5);
+            Select->add_joined_table($1);
+            Select->add_joined_table($5);
             /* Change the current name resolution context to a local context. */
             if (push_new_name_resolution_context(thd, $1, $5))
               MYSQL_YYABORT;
@@ -11643,6 +12044,8 @@ join_table:
         | table_ref LEFT opt_outer JOIN_SYM table_factor
           {
             MYSQL_YYABORT_UNLESS($1 && $5);
+            Select->add_joined_table($1);
+            Select->add_joined_table($5);
           }
           USING '(' using_list ')'
           { 
@@ -11653,6 +12056,8 @@ join_table:
         | table_ref NATURAL LEFT opt_outer JOIN_SYM table_factor
           {
             MYSQL_YYABORT_UNLESS($1 && $6);
+            Select->add_joined_table($1);
+            Select->add_joined_table($6);
             add_join_natural($1,$6,NULL,Select);
             $6->outer_join|=JOIN_TYPE_LEFT;
             $$=$6;
@@ -11663,6 +12068,8 @@ join_table:
           ON
           {
             MYSQL_YYABORT_UNLESS($1 && $5);
+            Select->add_joined_table($1);
+            Select->add_joined_table($5);
             /* Change the current name resolution context to a local context. */
             if (push_new_name_resolution_context(thd, $1, $5))
               MYSQL_YYABORT;
@@ -11680,6 +12087,8 @@ join_table:
         | table_ref RIGHT opt_outer JOIN_SYM table_factor
           {
             MYSQL_YYABORT_UNLESS($1 && $5);
+            Select->add_joined_table($1);
+            Select->add_joined_table($5);
           }
           USING '(' using_list ')'
           {
@@ -11691,6 +12100,8 @@ join_table:
         | table_ref NATURAL RIGHT opt_outer JOIN_SYM table_factor
           {
             MYSQL_YYABORT_UNLESS($1 && $6);
+            Select->add_joined_table($1);
+            Select->add_joined_table($6);
             add_join_natural($6,$1,NULL,Select);
             LEX *lex= Lex;
             if (!($$= lex->current_select->convert_right_join()))
@@ -11726,42 +12137,71 @@ use_partition:
           }
         ;
   
-/* 
-   This is a flattening of the rules <table factor> and <table primary>
-   in the SQL:2003 standard, since we don't have <sample clause>
-
-   I.e.
-   <table factor> ::= <table primary> [ <sample clause> ]
-*/   
-/* Warning - may return NULL in case of incomplete SELECT */
 table_factor:
-          table_primary_ident
-        | table_primary_derived
+          table_primary_ident { $$= $1; }
+        | table_primary_derived { $$= $1; }
+        | join_table_parens { $$= $1; }
+        | table_reference_list_parens { $$= $1; }
+        ;
+
+table_reference_list_parens:
+          '(' table_reference_list_parens ')' { $$= $2; }
+        | '(' nested_table_reference_list ')'
+          {
+            if (!($$= Select->end_nested_join(thd)))
+              MYSQL_YYABORT;
+          }
+        ;
+
+nested_table_reference_list:
+          table_ref ',' table_ref
+          {
+            if (Select->init_nested_join(thd))
+              MYSQL_YYABORT;
+            Select->add_joined_table($1);
+            Select->add_joined_table($3);
+            $$= $1->embedding;
+          }
+        | nested_table_reference_list ',' table_ref
+          {
+            Select->add_joined_table($3);
+            $$= $1;
+          }
         ;
 
+join_table_parens:
+          '(' join_table_parens ')' { $$= $2; }
+        | '(' join_table ')'
+          {
+            LEX *lex= Lex;
+            if (!($$= lex->current_select->nest_last_join(thd)))
+            {
+              thd->parse_error();
+              MYSQL_YYABORT;
+            }
+          }
+        ;
+
+
 table_primary_ident:
+          table_ident opt_use_partition opt_for_system_time_clause
+          opt_table_alias_clause opt_key_definition
           {
-            DBUG_ASSERT(Select);
             SELECT_LEX *sel= Select;
             sel->table_join_options= 0;
-          }
-          table_ident opt_use_partition opt_for_system_time_clause opt_table_alias opt_key_definition
-          {
-            if (!($$= Select->add_table_to_list(thd, $2, $5,
+            if (!($$= Select->add_table_to_list(thd, $1, $4,
                                                 Select->get_table_join_options(),
                                                 YYPS->m_lock_type,
                                                 YYPS->m_mdl_type,
                                                 Select->pop_index_hints(),
-                                                $3)))
+                                                $2)))
               MYSQL_YYABORT;
-            Select->add_joined_table($$);
-            if ($4)
+            if ($3)
               $$->vers_conditions= Lex->vers_conditions;
           }
         ;
 
 
-
 /*
   Represents a flattening of the following rules from the SQL:2003
   standard. This sub-rule corresponds to the sub-rule
@@ -11779,289 +12219,66 @@ table_primary_ident:
 */
 
 table_primary_derived:
-          '(' get_select_lex select_derived_union ')' opt_for_system_time_clause opt_table_alias
+          query_primary_parens opt_for_system_time_clause table_alias_clause
           {
-            /* Use $2 instead of Lex->current_select as derived table will
-               alter value of Lex->current_select. */
-            if (!($3 || $6) && $2->embedding &&
-                !$2->embedding->nested_join->join_list.elements)
+            LEX *lex=Lex;
+            lex->derived_tables|= DERIVED_SUBQUERY;
+            $1->linkage= DERIVED_TABLE_TYPE;
+            $1->braces= FALSE;
+            // Add the subtree of subquery to the current SELECT_LEX
+            SELECT_LEX *curr_sel= Lex->select_stack_head();
+            DBUG_ASSERT(Lex->current_select == curr_sel);
+            SELECT_LEX_UNIT *unit= $1->master_unit();
+            if (!unit)
             {
-              /* we have a derived table ($3 == NULL) but no alias,
-                 Since we are nested in further parentheses so we
-                 can pass NULL to the outer level parentheses
-                 Permits parsing of "((((select ...))) as xyz)" */
-              $$= 0;
+              unit= Lex->create_unit($1);
+              if (!unit)
+                YYABORT;
             }
-            else if (!$3)
-            {
-              /* Handle case of derived table, alias may be NULL if there
-                 are no outer parentheses, add_table_to_list() will throw
-                 error in this case */
-              LEX *lex=Lex;
-              lex->check_automatic_up(UNSPECIFIED_TYPE);
-              SELECT_LEX *sel= lex->current_select;
-              SELECT_LEX_UNIT *unit= sel->master_unit();
-              lex->current_select= sel= unit->outer_select();
-              Table_ident *ti= new (thd->mem_root) Table_ident(unit);
-              if (ti == NULL)
-                MYSQL_YYABORT;
-              if (!($$= sel->add_table_to_list(thd,
-                                               ti, $6, 0,
-                                               TL_READ, MDL_SHARED_READ)))
+            curr_sel->register_unit(unit, &curr_sel->context);
+            curr_sel->add_statistics(unit);
 
-                MYSQL_YYABORT;
-              sel->add_joined_table($$);
-              lex->pop_context();
-              lex->nest_level--;
-            }
-            else if ($6 != NULL)
-            {
-              /*
-                Tables with or without joins within parentheses cannot
-                have aliases, and we ruled out derived tables above.
-              */
-              thd->parse_error();
-              MYSQL_YYABORT;
-            }
-            else
-            {
-              /* nested join: FROM (t1 JOIN t2 ...),
-                 nest_level is the same as in the outer query */
-              $$= $3;
-            }
-            /*
-              Fields in derived table can be used in upper select in
-              case of merge. We do not add HAVING fields because we do
-              not merge such derived. We do not add union because
-              also do not merge them
-            */
-            if ($$ && $$->derived &&
-                !$$->derived->first_select()->next_select())
-              $$->select_lex->add_where_field($$->derived->first_select());
-            if ($5)
-            {
-              MYSQL_YYABORT_UNLESS(!$3);
-              $$->vers_conditions= Lex->vers_conditions;
-            }
-          }
-          /* Represents derived table with WITH clause */
-        | '(' get_select_lex subselect_start
-              with_clause query_expression_body
-              subselect_end ')' opt_for_system_time_clause opt_table_alias
-          {
-            LEX *lex=Lex;
-            SELECT_LEX *sel= $2;
-            SELECT_LEX_UNIT *unit= $5->master_unit();
             Table_ident *ti= new (thd->mem_root) Table_ident(unit);
             if (ti == NULL)
               MYSQL_YYABORT;
-            $5->set_with_clause($4);
-            lex->current_select= sel;
-            if (!($$= sel->add_table_to_list(lex->thd,
-                                             ti, $9, 0,
-                                             TL_READ, MDL_SHARED_READ)))
-              MYSQL_YYABORT;
-            sel->add_joined_table($$);
-            if ($8)
-              $$->vers_conditions= Lex->vers_conditions;
-          } 
-        ;
-
-/*
-  This rule accepts just about anything. The reason is that we have
-  empty-producing rules in the beginning of rules, in this case
-  subselect_start. This forces bison to take a decision which rules to
-  reduce by long before it has seen any tokens. This approach ties us
-  to a very limited class of parseable languages, and unfortunately
-  SQL is not one of them. The chosen 'solution' was this rule, which
-  produces just about anything, even complete bogus statements, for
-  instance ( table UNION SELECT 1 ).
-  Fortunately, we know that the semantic value returned by
-  select_derived is NULL if it contained a derived table, and a pointer to
-  the base table's TABLE_LIST if it was a base table. So in the rule
-  regarding union's, we throw a parse error manually and pretend it
-  was bison that did it.
- 
-  Also worth noting is that this rule concerns query expressions in
-  the from clause only. Top level select statements and other types of
-  subqueries have their own union rules.
-*/
-select_derived_union:
-          select_derived
-        | select_derived union_order_or_limit
-          {
-            if ($1)
-            {
-              thd->parse_error();
+            if (!($$= curr_sel->add_table_to_list(lex->thd,
+                                                  ti, $3, 0,
+                                                  TL_READ, MDL_SHARED_READ)))
               MYSQL_YYABORT;
-            }
-          }
-        | select_derived union_head_non_top
-          {
-            if ($1)
+            if ($2)
             {
-              thd->parse_error();
-              MYSQL_YYABORT;
+              $$->vers_conditions= Lex->vers_conditions;
             }
           }
-          union_list_derived_part2
-        | derived_simple_table opt_select_lock_type
-        | derived_simple_table order_or_limit opt_select_lock_type
-        | derived_simple_table opt_select_lock_type union_list_derived
-       ;
-
-union_list_derived_part2:
-         query_term_union_not_ready { Lex->pop_context(); }
-       | query_term_union_ready     { Lex->pop_context(); }
-       | query_term_union_ready     { Lex->pop_context(); } union_list_derived
-       ;
-
-union_list_derived:
-         union_head_non_top union_list_derived_part2
-       ;
-
-
-/* The equivalent of select_init2 for nested queries. */
-select_init2_derived:
-          select_part2_derived
+        | '('
+          query_expression
+          ')' opt_for_system_time_clause table_alias_clause
           {
-            Select->set_braces(0);
-          }
-        ;
+            LEX *lex=Lex;
+            lex->derived_tables|= DERIVED_SUBQUERY;
+            $2->first_select()->linkage= DERIVED_TABLE_TYPE;
 
-/* The equivalent of select_part2 for nested queries. */
-select_part2_derived:
-          {
-            LEX *lex= Lex;
-            SELECT_LEX *sel= lex->current_select;
-            if (sel->linkage != UNION_TYPE)
-              mysql_init_select(lex);
-            lex->current_select->parsing_place= SELECT_LIST;
-          }
-          opt_query_expression_options select_item_list
-          {
-            Select->parsing_place= NO_MATTER;
-          }
-        ;
 
-/* handle contents of parentheses in join expression */
-select_derived:
-          get_select_lex_derived derived_table_list
-          {
-            LEX *lex= Lex;
-            /* for normal joins, $2 != NULL and end_nested_join() != NULL,
-               for derived tables, both must equal NULL */
+            // Add the subtree of subquery to the current SELECT_LEX
+            SELECT_LEX *curr_sel= Lex->select_stack_head();
+            DBUG_ASSERT(Lex->current_select == curr_sel);
+            curr_sel->register_unit($2, &curr_sel->context);
+            curr_sel->add_statistics($2);
 
-            if (!($$= $1->end_nested_join(lex->thd)) && $2)
-              MYSQL_YYABORT;
-            if (!$2 && $$)
-            {
-              thd->parse_error();
-              MYSQL_YYABORT;
-            }
-          }
-        ;
-
-derived_simple_table:
-          derived_query_specification     { $$= $1; }
-        | derived_table_value_constructor { $$= $1; }
-        ;
-/*
-  Similar to query_specification, but for derived tables.
-  Example: the inner parenthesized SELECT in this query:
-    SELECT * FROM (SELECT * FROM t1);
-*/
-derived_query_specification:
-          SELECT_SYM select_derived_init select_derived2
-          {
-            if ($2)
-              Select->set_braces(1);
-            $$= NULL;
-          }
-        ;
-
-derived_table_value_constructor:
-          VALUES
-          {
-	    LEX *lex=Lex;
-            lex->field_list.empty();
-            lex->many_values.empty();
-            lex->insert_list=0;
-	  }
-          values_list
-          {
-            LEX *lex= Lex;
-            lex->derived_tables|= DERIVED_SUBQUERY;
-            if (!lex->expr_allows_subselect ||
-                lex->sql_command == (int)SQLCOM_PURGE)
-            {
-              thd->parse_error();
+            Table_ident *ti= new (thd->mem_root) Table_ident($2);
+            if (ti == NULL)
               MYSQL_YYABORT;
-            }
-            if (lex->current_select->linkage == GLOBAL_OPTIONS_TYPE ||
-                mysql_new_select(lex, 1, NULL))
+            if (!($$= curr_sel->add_table_to_list(lex->thd,
+                                                  ti, $5, 0,
+                                                  TL_READ, MDL_SHARED_READ)))
               MYSQL_YYABORT;
-            mysql_init_select(lex);
-            lex->current_select->linkage= DERIVED_TABLE_TYPE;
-
-            if (!(lex->current_select->tvc=
-	          new (lex->thd->mem_root) table_value_constr(lex->many_values,
-							      lex->current_select,
-							      lex->current_select->options)))
-	      MYSQL_YYABORT;
-	    lex->many_values.empty();
-            $$= NULL;
-          }
-        ;
-
-
-select_derived2:
-          {
-            LEX *lex= Lex;
-            lex->derived_tables|= DERIVED_SUBQUERY;
-            if (!lex->expr_allows_subselect ||
-                lex->sql_command == (int)SQLCOM_PURGE)
+            if ($4)
             {
-              thd->parse_error();
-              MYSQL_YYABORT;
+              $$->vers_conditions= Lex->vers_conditions;
             }
-            if (lex->current_select->linkage == GLOBAL_OPTIONS_TYPE ||
-                mysql_new_select(lex, 1, NULL))
-              MYSQL_YYABORT;
-            mysql_init_select(lex);
-            lex->current_select->linkage= DERIVED_TABLE_TYPE;
-            lex->current_select->parsing_place= SELECT_LIST;
-          }
-          select_options select_item_list
-          {
-            Select->parsing_place= NO_MATTER;
           }
-          opt_table_expression
-        ;
-
-get_select_lex:
-          /* Empty */ { $$= Select; }
         ;
 
-get_select_lex_derived:
-          get_select_lex
-          {
-            LEX *lex= Lex;
-            if ($1->init_nested_join(lex->thd))
-              MYSQL_YYABORT;
-          }
-       ;
-
-select_derived_init:
-          {
-            LEX *lex= Lex;
-
-            TABLE_LIST *embedding= lex->current_select->embedding;
-            $$= embedding &&
-                !embedding->nested_join->join_list.elements;
-            /* return true if we are deeply nested */
-          }
-        ;
 
 opt_outer:
           /* empty */ {}
@@ -12192,9 +12409,14 @@ table_alias:
         | '='
         ;
 
-opt_table_alias:
+opt_table_alias_clause:
           /* empty */ { $$=0; }
-        | table_alias ident_table_alias
+
+        | table_alias_clause { $$= $1; }
+        ;
+
+table_alias_clause:
+          table_alias ident_table_alias
           {
             $$= (LEX_CSTRING*) thd->memdup(&$2,sizeof(LEX_STRING));
             if ($$ == NULL)
@@ -12361,7 +12583,7 @@ opt_window_partition_clause:
 
 opt_window_order_clause:
           /* empty */ { }
-        | ORDER_SYM BY order_list
+        | ORDER_SYM BY order_list { Select->order_list= *($3); } 
         ;
 
 opt_window_frame_clause:
@@ -12485,64 +12707,35 @@ alter_order_item:
 
 opt_order_clause:
           /* empty */
+          { $$= NULL; }
         | order_clause
+          { $$= $1; }
         ;
 
 order_clause:
           ORDER_SYM BY
           {
-            LEX *lex=Lex;
-            SELECT_LEX *sel= lex->current_select;
-            SELECT_LEX_UNIT *unit= sel-> master_unit();
-            if (sel->linkage != GLOBAL_OPTIONS_TYPE &&
-                sel->olap != UNSPECIFIED_OLAP_TYPE &&
-                (sel->linkage != UNION_TYPE || sel->braces))
-            {
-              my_error(ER_WRONG_USAGE, MYF(0),
-                       "CUBE/ROLLUP", "ORDER BY");
-              MYSQL_YYABORT;
-            }
-            if (lex->sql_command != SQLCOM_ALTER_TABLE &&
-                !unit->fake_select_lex)
-            {
-              /*
-                A query of the of the form (SELECT ...) ORDER BY order_list is
-                executed in the same way as the query
-                SELECT ... ORDER BY order_list
-                unless the SELECT construct contains ORDER BY or LIMIT clauses.
-                Otherwise we create a fake SELECT_LEX if it has not been created
-                yet.
-              */
-              SELECT_LEX *first_sl= unit->first_select();
-              if (!unit->is_unit_op() &&
-                  (first_sl->order_list.elements || 
-                   first_sl->select_limit) &&            
-                  unit->add_fake_select_lex(thd))
-                MYSQL_YYABORT;
-            }
-            if (sel->master_unit()->is_unit_op() && !sel->braces)
-            {
-               /*
-                 At this point we don't know yet whether this is the last
-                 select in union or not, but we move ORDER BY to
-                 fake_select_lex anyway. If there would be one more select
-                 in union mysql_new_select will correctly throw error.
-               */
-               DBUG_ASSERT(sel->master_unit()->fake_select_lex);
-               lex->current_select= sel->master_unit()->fake_select_lex;
-             }
+            thd->where= "ORDER clause";
           }
           order_list
           {
-
+            $$= $4;
           }
          ;
 
 order_list:
           order_list ',' order_ident order_dir
-          { if (add_order_to_list(thd, $3,(bool) $4)) MYSQL_YYABORT; }
+          {
+            $$= $1;
+            if (add_to_list(thd, *$$, $3,(bool) $4))
+              MYSQL_YYABORT;
+          }
         | order_ident order_dir
-          { if (add_order_to_list(thd, $1,(bool) $2)) MYSQL_YYABORT; }
+          {
+            $$= new (thd->mem_root) SQL_I_List<ORDER>();
+            if (add_to_list(thd, *$$, $1, (bool) $2))
+              MYSQL_YYABORT;
+          }
         ;
 
 order_dir:
@@ -12552,63 +12745,61 @@ order_dir:
         ;
 
 opt_limit_clause:
-          /* empty */ {}
-        | limit_clause {}
+          /* empty */
+          { $$.empty(); }
+        | limit_clause
+          { $$= $1; }
         ;
 
-limit_clause_init:
-          LIMIT
-          {
-            SELECT_LEX *sel= Select;
-            if (sel->master_unit()->is_unit_op() && !sel->braces)
-            {
-              /* Move LIMIT that belongs to UNION to fake_select_lex */
-              Lex->current_select= sel->master_unit()->fake_select_lex;
-              DBUG_ASSERT(Select);
-            }
-          }
-        ;  
-
 limit_clause:
-          limit_clause_init limit_options
+          LIMIT limit_options
           {
-            SELECT_LEX *sel= Select;
-            if (!sel->select_limit->basic_const_item() ||
-                sel->select_limit->val_int() > 0)
+            $$= $2;
+            if (!$$.select_limit->basic_const_item() ||
+                $$.select_limit->val_int() > 0)
               Lex->set_stmt_unsafe(LEX::BINLOG_STMT_UNSAFE_LIMIT);
           }
-        | limit_clause_init limit_options
+        | LIMIT limit_options
           ROWS_SYM EXAMINED_SYM limit_rows_option
           {
+            $$= $2;
             Lex->set_stmt_unsafe(LEX::BINLOG_STMT_UNSAFE_LIMIT);
           }
-        | limit_clause_init ROWS_SYM EXAMINED_SYM limit_rows_option
+        | LIMIT ROWS_SYM EXAMINED_SYM limit_rows_option
           {
+            $$.select_limit= 0;
+            $$.offset_limit= 0;
+            $$.explicit_limit= 1;
             Lex->set_stmt_unsafe(LEX::BINLOG_STMT_UNSAFE_LIMIT);
           }
         ;
 
+opt_global_limit_clause:
+          opt_limit_clause
+          {
+            Select->explicit_limit= $1.explicit_limit;
+            Select->select_limit= $1.select_limit;
+            Select->offset_limit= $1.offset_limit;
+          }
+
 limit_options:
           limit_option
           {
-            SELECT_LEX *sel= Select;
-            sel->select_limit= $1;
-            sel->offset_limit= 0;
-            sel->explicit_limit= 1;
+            $$.select_limit= $1;
+            $$.offset_limit= 0;
+            $$.explicit_limit= 1;
           }
         | limit_option ',' limit_option
           {
-            SELECT_LEX *sel= Select;
-            sel->select_limit= $3;
-            sel->offset_limit= $1;
-            sel->explicit_limit= 1;
+            $$.select_limit= $3;
+            $$.offset_limit= $1;
+            $$.explicit_limit= 1;
           }
         | limit_option OFFSET_SYM limit_option
           {
-            SELECT_LEX *sel= Select;
-            sel->select_limit= $1;
-            sel->offset_limit= $3;
-            sel->explicit_limit= 1;
+            $$.select_limit= $1;
+            $$.offset_limit= $3;
+            $$.explicit_limit= 1;
           }
         ;
 
@@ -12677,6 +12868,66 @@ delete_limit_clause:
        | LIMIT limit_option ROWS_SYM EXAMINED_SYM { thd->parse_error(); MYSQL_YYABORT; }
         ;
 
+query_expression_tail:
+          /* empty */ { $$= NULL; }
+        | order_or_limit opt_select_lock_type
+          {
+            $$= $1;
+            $$->lock= $2;
+          }
+        | order_or_limit procedure_or_into opt_select_lock_type
+          {
+            $$= $1;
+            $$->lock= $3;
+          }
+        | procedure_or_into opt_select_lock_type
+          {
+            $$= new(thd->mem_root) Lex_order_limit_lock;
+            if (!$$)
+              YYABORT;
+            $$->order_list= NULL;
+            $$->limit.empty();
+            $$->lock= $2;
+          }
+        | select_lock_type
+          {
+            $$= new(thd->mem_root) Lex_order_limit_lock;
+            if (!$$)
+              YYABORT;
+            $$->order_list= NULL;
+            $$->limit.empty();
+            $$->lock= $1;
+          }
+        ;
+
+procedure_or_into:
+          procedure_clause
+        | into
+        | procedure_clause into
+        ;
+
+order_or_limit:
+          order_clause opt_limit_clause
+          {
+            $$= new(thd->mem_root) Lex_order_limit_lock;
+            if (!$$)
+              YYABORT;
+            $$->order_list= $1;
+            $$->limit= $2;
+          }
+        | limit_clause
+          {
+            Lex_order_limit_lock *op= $$= new(thd->mem_root) Lex_order_limit_lock;
+            if (!$$)
+              YYABORT;
+            op->order_list= NULL;
+            op->limit= $1;
+            $$->order_list= NULL;
+            $$->limit= $1;
+          }
+        ;
+
+
 opt_plus:
           /* empty */
         | '+'
@@ -12746,14 +12997,11 @@ bool:
         | TRUE_SYM  { $$= 1; }
         | FALSE_SYM { $$= 0; }
 
-
 procedure_clause:
           PROCEDURE_SYM ident /* Procedure name */
           {
             LEX *lex=Lex;
 
-            DBUG_ASSERT(&lex->select_lex == lex->current_select);
-
             lex->proc_list.elements=0;
             lex->proc_list.first=0;
             lex->proc_list.next= &lex->proc_list.first;
@@ -12773,6 +13021,7 @@ procedure_clause:
               parameters are reduced.
             */
             Lex->expr_allows_subselect= false;
+            Select->options|= OPTION_PROCEDURE_CLAUSE;
           }
           '(' procedure_list ')'
           {
@@ -12853,8 +13102,21 @@ select_outvar:
           }
         ;
 
+opt_into:
+          /* empty */
+        | into
+        ;
 into:
           INTO into_destination
+          {
+            if (!(Select->options & OPTION_INTO_CLAUSE))
+              Select->options|= OPTION_INTO_CLAUSE;
+            else
+            {
+              my_error(ER_CANT_USE_OPTION_HERE, MYF(0), "INTO");
+              MYSQL_YYABORT;
+            }
+          }
         ;
 
 into_destination:
@@ -12900,10 +13162,15 @@ do:
             LEX *lex=Lex;
             lex->sql_command = SQLCOM_DO;
             mysql_init_select(lex);
+            if (Lex->main_select_push())
+              MYSQL_YYABORT;
           }
           expr_list
           {
             Lex->insert_list= $3;
+            Lex->pop_select(); //main select
+            if (Lex->check_main_unit_semantics())
+              MYSQL_YYABORT;
           }
         ;
 
@@ -13120,16 +13387,23 @@ insert:
             LEX *lex= Lex;
             lex->sql_command= SQLCOM_INSERT;
             lex->duplicates= DUP_ERROR; 
+            if (Lex->main_select_push())
+              MYSQL_YYABORT;
             mysql_init_select(lex);
+            lex->current_select->parsing_place= BEFORE_OPT_FIELD_LIST;
           }
           insert_lock_option
           opt_ignore insert2
           {
             Select->set_lock_for_tables($3);
-            Lex->current_select= &Lex->select_lex;
+            Lex->current_select= Lex->first_select_lex();
           }
           insert_field_spec opt_insert_update
-          {}
+          {
+            Lex->pop_select(); //main select
+            if (Lex->check_main_unit_semantics())
+              MYSQL_YYABORT;
+          }
         ;
 
 replace:
@@ -13138,15 +13412,22 @@ replace:
             LEX *lex=Lex;
             lex->sql_command = SQLCOM_REPLACE;
             lex->duplicates= DUP_REPLACE;
+            if (Lex->main_select_push())
+              MYSQL_YYABORT;
             mysql_init_select(lex);
+            lex->current_select->parsing_place= BEFORE_OPT_FIELD_LIST;
           }
           replace_lock_option insert2
           {
             Select->set_lock_for_tables($3);
-            Lex->current_select= &Lex->select_lex;
+            Lex->current_select= Lex->first_select_lex();
           }
           insert_field_spec
-          {}
+          {
+            Lex->pop_select(); //main select
+            if (Lex->check_main_unit_semantics())
+              MYSQL_YYABORT;
+          }
         ;
 
 insert_lock_option:
@@ -13192,35 +13473,44 @@ insert_table:
           table_name_with_opt_use_partition
           {
             LEX *lex=Lex;
-            lex->field_list.empty();
+            //lex->field_list.empty();
             lex->many_values.empty();
             lex->insert_list=0;
           };
 
 insert_field_spec:
           insert_values {}
-        | '(' ')' insert_values {}
-        | '(' fields ')' insert_values {}
+        | insert_field_list insert_values {}
         | SET
           {
             LEX *lex=Lex;
             if (!(lex->insert_list= new (thd->mem_root) List_item) ||
                 lex->many_values.push_back(lex->insert_list, thd->mem_root))
               MYSQL_YYABORT;
+            lex->current_select->parsing_place= NO_MATTER;
           }
           ident_eq_list
         ;
 
+insert_field_list:
+          LEFT_PAREN_ALT opt_fields ')'
+        ;
+
+opt_fields:
+          /* empty */
+        | fields
+        ;
+
 fields:
           fields ',' insert_ident
           { Lex->field_list.push_back($3, thd->mem_root); }
         | insert_ident { Lex->field_list.push_back($1, thd->mem_root); }
         ;
 
+
+
 insert_values:
-          VALUES values_list {}
-        | VALUE_SYM values_list {}
-        | create_select_query_expression {}
+         create_select_query_expression {}
         ;
 
 values_list:
@@ -13330,6 +13620,8 @@ update:
           UPDATE_SYM
           {
             LEX *lex= Lex;
+            if (Lex->main_select_push())
+              MYSQL_YYABORT;
             mysql_init_select(lex);
             lex->sql_command= SQLCOM_UPDATE;
             lex->duplicates= DUP_ERROR; 
@@ -13338,13 +13630,14 @@ update:
           SET update_list
           {
             LEX *lex= Lex;
-            if (lex->select_lex.table_list.elements > 1)
+            if (lex->builtin_select.table_list.elements > 1)
               lex->sql_command= SQLCOM_UPDATE_MULTI;
-            else if (lex->select_lex.get_table_list()->derived)
+            else if (lex->builtin_select.get_table_list()->derived)
             {
               /* it is single table update and it is update of derived table */
               my_error(ER_NON_UPDATABLE_TABLE, MYF(0),
-                       lex->select_lex.get_table_list()->alias.str, "UPDATE");
+                       lex->builtin_select.get_table_list()->alias.str,
+                       "UPDATE");
               MYSQL_YYABORT;
             }
             /*
@@ -13354,7 +13647,14 @@ update:
             */
             Select->set_lock_for_tables($3);
           }
-          opt_where_clause opt_order_clause delete_limit_clause {}
+          opt_where_clause opt_order_clause delete_limit_clause
+          {
+            if ($10)
+              Select->order_list= *($10);
+            Lex->pop_select(); //main select
+            if (Lex->check_main_unit_semantics())
+              MYSQL_YYABORT;
+          }
         ;
 
 update_list:
@@ -13400,9 +13700,11 @@ delete:
             mysql_init_select(lex);
             YYPS->m_lock_type= TL_WRITE_DEFAULT;
             YYPS->m_mdl_type= MDL_SHARED_WRITE;
+            if (Lex->main_select_push())
+              MYSQL_YYABORT;
 
             lex->ignore= 0;
-            lex->select_lex.init_order();
+            lex->builtin_select.init_order();
           }
           delete_part2
           ;
@@ -13445,9 +13747,16 @@ single_multi:
           opt_where_clause
           opt_order_clause
           delete_limit_clause
-          opt_select_expressions {}
+          opt_select_expressions 
+          {
+            if ($3)
+              Select->order_list= *($3);
+            Lex->pop_select(); //main select
+          }
         | table_wild_list
           {
+            if (Lex->main_select_push())
+              MYSQL_YYABORT;
             mysql_init_multi_delete(Lex);
             YYPS->m_lock_type= TL_READ_DEFAULT;
             YYPS->m_mdl_type= MDL_SHARED_READ;
@@ -13456,9 +13765,14 @@ single_multi:
           {
             if (multi_delete_set_locks_and_link_aux_tables(Lex))
               MYSQL_YYABORT;
+            Lex->pop_select(); //main select
+            if (Lex->check_main_unit_semantics())
+              MYSQL_YYABORT;
           }
         | FROM table_alias_ref_list
           {
+            if (Lex->main_select_push())
+              MYSQL_YYABORT;
             mysql_init_multi_delete(Lex);
             YYPS->m_lock_type= TL_READ_DEFAULT;
             YYPS->m_mdl_type= MDL_SHARED_READ;
@@ -13467,6 +13781,9 @@ single_multi:
           {
             if (multi_delete_set_locks_and_link_aux_tables(Lex))
               MYSQL_YYABORT;
+            Lex->pop_select(); //main select
+            if (Lex->check_main_unit_semantics())
+              MYSQL_YYABORT;
           }
         ;
 
@@ -13530,10 +13847,12 @@ truncate:
           {
             LEX* lex= Lex;
             lex->sql_command= SQLCOM_TRUNCATE;
+            if (Lex->main_select_push())
+              MYSQL_YYABORT;
             lex->alter_info.reset();
-            lex->select_lex.options= 0;
-            lex->select_lex.sql_cache= SELECT_LEX::SQL_CACHE_UNSPECIFIED;
-            lex->select_lex.init_order();
+            lex->builtin_select.options= 0;
+            lex->builtin_select.sql_cache= SELECT_LEX::SQL_CACHE_UNSPECIFIED;
+            lex->builtin_select.init_order();
             YYPS->m_lock_type= TL_WRITE;
             YYPS->m_mdl_type= MDL_EXCLUSIVE;
           }
@@ -13544,6 +13863,7 @@ truncate:
             lex->m_sql_cmd= new (thd->mem_root) Sql_cmd_truncate_table();
             if (lex->m_sql_cmd == NULL)
               MYSQL_YYABORT;
+            Lex->pop_select(); //main select
           }
         ;
 
@@ -13618,6 +13938,8 @@ show:
             LEX *lex=Lex;
             lex->wild=0;
             lex->ident= null_clex_str;
+            if (Lex->main_select_push())
+              MYSQL_YYABORT;
             mysql_init_select(lex);
             lex->current_select->parsing_place= SELECT_LIST;
             lex->create_info.init();
@@ -13625,6 +13947,7 @@ show:
           show_param
           {
             Select->parsing_place= NO_MATTER;
+            Lex->pop_select(); //main select
           }
         ;
 
@@ -13640,7 +13963,7 @@ show_param:
            {
              LEX *lex= Lex;
              lex->sql_command= SQLCOM_SHOW_TABLES;
-             lex->select_lex.db= $3;
+             lex->first_select_lex()->db= $3;
              if (prepare_schema_table(thd, lex, 0, SCH_TABLE_NAMES))
                MYSQL_YYABORT;
            }
@@ -13648,7 +13971,7 @@ show_param:
            {
              LEX *lex= Lex;
              lex->sql_command= SQLCOM_SHOW_TRIGGERS;
-             lex->select_lex.db= $3;
+             lex->first_select_lex()->db= $3;
              if (prepare_schema_table(thd, lex, 0, SCH_TRIGGERS))
                MYSQL_YYABORT;
            }
@@ -13656,7 +13979,7 @@ show_param:
            {
              LEX *lex= Lex;
              lex->sql_command= SQLCOM_SHOW_EVENTS;
-             lex->select_lex.db= $2;
+             lex->first_select_lex()->db= $2;
              if (prepare_schema_table(thd, lex, 0, SCH_EVENTS))
                MYSQL_YYABORT;
            }
@@ -13664,7 +13987,7 @@ show_param:
            {
              LEX *lex= Lex;
              lex->sql_command= SQLCOM_SHOW_TABLE_STATUS;
-             lex->select_lex.db= $3;
+             lex->first_select_lex()->db= $3;
              if (prepare_schema_table(thd, lex, 0, SCH_TABLES))
                MYSQL_YYABORT;
            }
@@ -13672,7 +13995,7 @@ show_param:
           {
             LEX *lex= Lex;
             lex->sql_command= SQLCOM_SHOW_OPEN_TABLES;
-            lex->select_lex.db= $3;
+            lex->first_select_lex()->db= $3;
             if (prepare_schema_table(thd, lex, 0, SCH_OPEN_TABLES))
               MYSQL_YYABORT;
           }
@@ -13722,12 +14045,13 @@ show_param:
             LEX *lex= Lex;
             lex->sql_command= SQLCOM_SHOW_BINLOG_EVENTS;
           }
-          opt_limit_clause
+          opt_global_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
+          }
+          opt_global_limit_clause
         | keys_or_index from_or_in table_ident opt_db opt_where_clause
           {
             LEX *lex= Lex;
@@ -13769,13 +14093,13 @@ show_param:
             LEX_CSTRING var= {STRING_WITH_LEN("error_count")};
             (void) create_select_for_variable(thd, &var);
           }
-        | WARNINGS opt_limit_clause
+        | WARNINGS opt_global_limit_clause
           { Lex->sql_command = SQLCOM_SHOW_WARNS;}
-        | ERRORS opt_limit_clause
+        | ERRORS opt_global_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
+        | PROFILE_SYM opt_profile_defs opt_profile_args opt_global_limit_clause
           { 
             LEX *lex= Lex;
             lex->sql_command= SQLCOM_SHOW_PROFILE;
@@ -13836,7 +14160,7 @@ show_param:
           {
             LEX *lex= Lex;
             lex->sql_command = SQLCOM_SHOW_CREATE;
-            if (!lex->select_lex.add_table_to_list(thd, $3, NULL,0))
+            if (!lex->builtin_select.add_table_to_list(thd, $3, NULL,0))
               MYSQL_YYABORT;
             lex->create_info.storage_media= HA_SM_DEFAULT;
 
@@ -13852,7 +14176,7 @@ show_param:
           {
             LEX *lex= Lex;
             lex->sql_command = SQLCOM_SHOW_CREATE;
-            if (!lex->select_lex.add_table_to_list(thd, $3, NULL, 0))
+            if (!lex->builtin_select.add_table_to_list(thd, $3, NULL, 0))
               MYSQL_YYABORT;
             lex->table_type= TABLE_TYPE_VIEW;
           }
@@ -13860,7 +14184,7 @@ show_param:
           {
             LEX *lex= Lex;
             lex->sql_command = SQLCOM_SHOW_CREATE;
-            if (!lex->select_lex.add_table_to_list(thd, $3, NULL, 0))
+            if (!lex->builtin_select.add_table_to_list(thd, $3, NULL, 0))
               MYSQL_YYABORT;
             lex->table_type= TABLE_TYPE_SEQUENCE;
           }
@@ -14076,7 +14400,7 @@ describe:
             mysql_init_select(lex);
             lex->current_select->parsing_place= SELECT_LIST;
             lex->sql_command= SQLCOM_SHOW_FIELDS;
-            lex->select_lex.db= null_clex_str;
+            lex->builtin_select.db= null_clex_str;
             lex->verbose= 0;
             if (prepare_schema_table(thd, lex, $2, SCH_COLUMNS))
               MYSQL_YYABORT;
@@ -14090,7 +14414,7 @@ describe:
           explainable_command
           {
             LEX *lex=Lex;
-            lex->select_lex.options|= SELECT_DESCRIBE;
+            lex->first_select_lex()->options|= SELECT_DESCRIBE;
           }
         ;
 
@@ -14116,6 +14440,8 @@ analyze_stmt_command:
 
 opt_extended_describe:
           EXTENDED_SYM   { Lex->describe|= DESCRIBE_EXTENDED; }
+        | EXTENDED_SYM ALL
+          { Lex->describe|= DESCRIBE_EXTENDED | DESCRIBE_EXTENDED2; }
         | PARTITIONS_SYM { Lex->describe|= DESCRIBE_PARTITIONS; }
         | opt_format_json {}
         ;
@@ -14158,8 +14484,7 @@ flush:
             lex->type= 0;
             lex->no_write_to_binlog= $2;
           }
-          flush_options
-          {}
+          flush_options {}
         ;
 
 flush_options:
@@ -14176,6 +14501,7 @@ flush_options:
           opt_table_list opt_flush_lock
           {}
         | flush_options_list
+          {}
         ;
 
 opt_flush_lock:
@@ -14349,9 +14675,13 @@ purge:
             LEX *lex=Lex;
             lex->type=0;
             lex->sql_command = SQLCOM_PURGE;
+            if (lex->main_select_push())
+              MYSQL_YYABORT;
           }
           purge_options
-          {}
+          {
+            Lex->pop_select(); //main select
+          }
         ;
 
 purge_options:
@@ -14369,6 +14699,8 @@ purge_option:
             lex->value_list.empty();
             lex->value_list.push_front($2, thd->mem_root);
             lex->sql_command= SQLCOM_PURGE_BEFORE;
+            if (Lex->check_main_unit_semantics())
+              MYSQL_YYABORT;
           }
         ;
 
@@ -14378,6 +14710,8 @@ kill:
           KILL_SYM
           {
             LEX *lex=Lex;
+            if (lex->main_select_push())
+              YYABORT;
             lex->value_list.empty();
             lex->users_list.empty();
             lex->sql_command= SQLCOM_KILL;
@@ -14386,6 +14720,7 @@ kill:
           kill_type kill_option kill_expr
           {
             Lex->kill_signal= (killed_state) ($3 | $4);
+            Lex->pop_select(); //main select
           }
         ;
 
@@ -14429,7 +14764,7 @@ use:
           {
             LEX *lex=Lex;
             lex->sql_command=SQLCOM_CHANGE_DB;
-            lex->select_lex.db= $2;
+            lex->builtin_select.db= $2;
           }
         ;
 
@@ -14446,6 +14781,8 @@ load:
                        $2 == FILETYPE_CSV ? "LOAD DATA" : "LOAD XML");
               MYSQL_YYABORT;
             }
+            if (Lex->main_select_push())
+              MYSQL_YYABORT;
           }
           load_data_lock opt_local INFILE TEXT_STRING_filesystem
           {
@@ -14472,7 +14809,11 @@ load:
           opt_xml_rows_identified_by
           opt_field_term opt_line_term opt_ignore_lines opt_field_or_var_spec
           opt_load_data_set_spec
-          {}
+          {
+            Lex->pop_select(); //main select
+            if (Lex->check_main_unit_semantics())
+              MYSQL_YYABORT;
+          }
           ;
 
 data_or_xml:
@@ -14864,17 +15205,21 @@ opt_with_clause:
 
 
 with_clause:
-        WITH opt_recursive
+          WITH opt_recursive
           {
+             LEX *lex= Lex;
              With_clause *with_clause=
              new With_clause($2, Lex->curr_with_clause);
              if (with_clause == NULL)
                MYSQL_YYABORT;
-             Lex->derived_tables|= DERIVED_WITH;
-             Lex->curr_with_clause= with_clause;
+             lex->derived_tables|= DERIVED_WITH;
+             lex->curr_with_clause= with_clause;
              with_clause->add_to_list(Lex->with_clauses_list_last_next);
+             if (lex->current_select &&
+                 lex->current_select->parsing_place == BEFORE_OPT_FIELD_LIST)
+               lex->current_select->parsing_place= NO_MATTER;
           }
-        with_list
+          with_list
           {
             $$= Lex->curr_with_clause;
             Lex->curr_with_clause= Lex->curr_with_clause->pop();
@@ -14903,9 +15248,9 @@ with_list_element:
               MYSQL_YYABORT;
             Lex->with_column_list.empty();
           }
-          AS '(' remember_name subselect remember_end ')'
+          AS '(' remember_name query_expression remember_end ')'
  	  {
-            With_element *elem= new With_element($1, *$2, $7->master_unit());
+            With_element *elem= new With_element($1, *$2, $7);
 	    if (elem == NULL || Lex->curr_with_clause->add_with_element(elem))
 	      MYSQL_YYABORT;
 	    if (elem->set_unparsed_spec(thd, $6+1, $8))
@@ -15785,14 +16130,22 @@ set:
           SET
           {
             LEX *lex=Lex;
+            if (lex->main_select_push())
+              MYSQL_YYABORT;
             lex->set_stmt_init();
             lex->var_list.empty();
             sp_create_assignment_lex(thd, yychar == YYEMPTY);
           }
           start_option_value_list
-          {}
+          {
+            Lex->pop_select(); //main select
+            if (Lex->check_main_unit_semantics())
+              MYSQL_YYABORT;
+          }
         | SET STATEMENT_SYM
           {
+            if (Lex->main_select_push())
+              MYSQL_YYABORT;
             Lex->set_stmt_init();
           }
           set_stmt_option_value_following_option_type_list
@@ -15802,6 +16155,9 @@ set:
               my_yyabort_error((ER_SUBQUERIES_NOT_SUPPORTED, MYF(0), "SET STATEMENT"));
             lex->stmt_var_list= lex->var_list;
             lex->var_list.empty();
+            Lex->pop_select(); //main select
+            if (Lex->check_main_unit_semantics())
+              MYSQL_YYABORT;
           }
           FOR_SYM verb_clause
 	  {}
@@ -16183,9 +16539,13 @@ lock:
             if (lex->sphead)
               my_yyabort_error((ER_SP_BADSTATEMENT, MYF(0), "LOCK"));
             lex->sql_command= SQLCOM_LOCK_TABLES;
+            if (Lex->main_select_push())
+              MYSQL_YYABORT;
           }
           table_lock_list opt_lock_wait_timeout
-          {}
+          {
+            Lex->pop_select(); //main select
+          }
         ;
 
 opt_lock_wait_timeout:
@@ -16216,7 +16576,7 @@ table_lock_list:
         ;
 
 table_lock:
-          table_ident opt_table_alias lock_option
+          table_ident opt_table_alias_clause lock_option
           {
             thr_lock_type lock_type= (thr_lock_type) $3;
             bool lock_for_write= (lock_type >= TL_WRITE_ALLOW_WRITE);
@@ -16250,9 +16610,13 @@ unlock:
             if (lex->sphead)
               my_yyabort_error((ER_SP_BADSTATEMENT, MYF(0), "UNLOCK"));
             lex->sql_command= SQLCOM_UNLOCK_TABLES;
+            if (Lex->main_select_push())
+              MYSQL_YYABORT;
           }
           table_or_tables
-          {}
+          {
+            Lex->pop_select(); //main select
+          }
         ;
 
 /*
@@ -16260,25 +16624,36 @@ unlock:
 */
 
 handler:
-          HANDLER_SYM table_ident OPEN_SYM opt_table_alias
+          HANDLER_SYM
+          {
+            if (Lex->main_select_push())
+              MYSQL_YYABORT;
+          }
+          handler_tail
+          {
+            Lex->pop_select(); //main select
+          }
+
+handler_tail:
+          table_ident OPEN_SYM opt_table_alias_clause
           {
             LEX *lex= Lex;
             if (lex->sphead)
               my_yyabort_error((ER_SP_BADSTATEMENT, MYF(0), "HANDLER"));
             lex->sql_command = SQLCOM_HA_OPEN;
-            if (!lex->current_select->add_table_to_list(thd, $2, $4, 0))
+            if (!lex->current_select->add_table_to_list(thd, $1, $3, 0))
               MYSQL_YYABORT;
           }
-        | HANDLER_SYM table_ident_nodb CLOSE_SYM
+        | table_ident_nodb CLOSE_SYM
           {
             LEX *lex= Lex;
             if (lex->sphead)
               my_yyabort_error((ER_SP_BADSTATEMENT, MYF(0), "HANDLER"));
             lex->sql_command = SQLCOM_HA_CLOSE;
-            if (!lex->current_select->add_table_to_list(thd, $2, 0, 0))
+            if (!lex->current_select->add_table_to_list(thd, $1, 0, 0))
               MYSQL_YYABORT;
           }
-        | HANDLER_SYM table_ident_nodb READ_SYM
+        | table_ident_nodb READ_SYM
           {
             LEX *lex=Lex;
             if (lex->sphead)
@@ -16286,20 +16661,24 @@ handler:
             lex->expr_allows_subselect= FALSE;
             lex->sql_command = SQLCOM_HA_READ;
             lex->ha_rkey_mode= HA_READ_KEY_EXACT; /* Avoid purify warnings */
-            Item *one= new (thd->mem_root) Item_int(thd, (int32) 1);
-            if (one == NULL)
-              MYSQL_YYABORT;
-            lex->current_select->select_limit= one;
-            lex->current_select->offset_limit= 0;
-            lex->limit_rows_examined= 0;
-            if (!lex->current_select->add_table_to_list(thd, $2, 0, 0))
+            if (!lex->current_select->add_table_to_list(thd, $1, 0, 0))
               MYSQL_YYABORT;
           }
-          handler_read_or_scan opt_where_clause opt_limit_clause
+          handler_read_or_scan opt_where_clause opt_global_limit_clause
           {
-            Lex->expr_allows_subselect= TRUE;
+            LEX *lex=Lex;
+            lex->expr_allows_subselect= TRUE;
+            if (!lex->current_select->explicit_limit)
+            {
+              Item *one= new (thd->mem_root) Item_int(thd, (int32) 1);
+              if (one == NULL)
+                MYSQL_YYABORT;
+              lex->current_select->select_limit= one;
+              lex->current_select->offset_limit= 0;
+              lex->limit_rows_examined= 0;
+            }
             /* Stored functions are not supported for HANDLER READ. */
-            if (Lex->uses_stored_routines())
+            if (lex->uses_stored_routines())
             {
               my_error(ER_NOT_SUPPORTED_YET, MYF(0),
                        "stored functions in HANDLER ... READ");
@@ -16930,219 +17309,27 @@ release:
 */
 
 unit_type_decl:
-          UNION_SYM
-          { $$= UNION_TYPE; }
+          UNION_SYM union_option
+          { $$.unit_type= UNION_TYPE; $$.distinct= $2; }
         | INTERSECT_SYM
-          { $$= INTERSECT_TYPE; }
+          { $$.unit_type= INTERSECT_TYPE; $$.distinct= 1; }
         | EXCEPT_SYM
-          { $$= EXCEPT_TYPE; }
+          { $$.unit_type= EXCEPT_TYPE; $$.distinct= 1; }
 
 
-union_clause:
-          /* empty */ {}
-        | union_list
-        ;
-
-union_list:
-          unit_type_decl union_option
-          {
-            if (Lex->add_select_to_union_list((bool)$2, $1, TRUE))
-              MYSQL_YYABORT;
-          }
-          union_list_part2
-          {
-            /*
-              Remove from the name resolution context stack the context of the
-              last select in the union.
-            */
-            Lex->pop_context();
-          }
-        ;
-
-union_list_view:
-          unit_type_decl union_option
-          {
-            if (Lex->add_select_to_union_list((bool)$2, $1, TRUE))
-              MYSQL_YYABORT;
-          }
-          query_expression_body_view
-          {
-            Lex->pop_context();
-          }
-        ;
-
-union_order_or_limit:
-          {
-            LEX *lex= thd->lex;
-            DBUG_ASSERT(lex->current_select->linkage != GLOBAL_OPTIONS_TYPE);
-            SELECT_LEX *sel= lex->current_select;
-            SELECT_LEX_UNIT *unit= sel->master_unit();
-            SELECT_LEX *fake= unit->fake_select_lex;
-            if (fake)
-            {
-              fake->no_table_names_allowed= 1;
-              lex->current_select= fake;
-            }
-            thd->where= "global ORDER clause";
-          }
-          order_or_limit
-          {
-            thd->lex->current_select->no_table_names_allowed= 0;
-            thd->where= "";
-          }
-        ;
-
-order_or_limit:
-          order_clause opt_limit_clause
-        | limit_clause
-        ;
-
 /*
   Start a UNION, for non-top level query expressions.
 */
-union_head_non_top:
-          unit_type_decl union_option
-          {
-            if (Lex->add_select_to_union_list((bool)$2, $1, FALSE))
-              MYSQL_YYABORT;
-          }
-        ;
-
 union_option:
           /* empty */ { $$=1; }
         | DISTINCT  { $$=1; }
         | ALL       { $$=0; }
         ;
 
-simple_table:
-          query_specification      { $$= $1; }
-        | table_value_constructor  { $$= $1; }
-        ;
-        
-table_value_constructor:
-	  VALUES
-	  {
-	    LEX *lex=Lex;
-            lex->field_list.empty();
-            lex->many_values.empty();
-            lex->insert_list=0;
-	  }
-	  values_list
-	  { 
-	    LEX *lex=Lex;
-	    $$= lex->current_select;
-	    mysql_init_select(Lex);
-	    if (!($$->tvc=
-	          new (lex->thd->mem_root) table_value_constr(lex->many_values, $$, $$->options)))
-	      MYSQL_YYABORT;
-	    lex->many_values.empty();
-	  }
-	;
-	
-/*
-  Corresponds to the SQL Standard
-  <query specification> ::=
-    SELECT [ <set quantifier> ] <select list> <table expression>
-
-  Notes:
-  - We allow more options in addition to <set quantifier>
-  - <table expression> is optional in MariaDB
-*/
-query_specification:
-          SELECT_SYM select_init2_derived opt_table_expression
-          {
-            $$= Lex->current_select->master_unit()->first_select();
-          }
-        ;
-
-query_term_union_not_ready:
-          simple_table order_or_limit opt_select_lock_type { $$= $1; }
-        | '(' select_paren_derived ')' union_order_or_limit       { $$= $2; }
-        ;
-
-query_term_union_ready:
-          simple_table opt_select_lock_type                { $$= $1; }
-        | '(' select_paren_derived ')'                            { $$= $2; }
-        ;
-
-query_expression_body:
-          query_term_union_not_ready                                { $$= $1; }
-        | query_term_union_ready                                    { $$= $1; }
-        | query_term_union_ready union_list_derived                 { $$= $1; }
-        ;
-
-/* Corresponds to <query expression> in the SQL:2003 standard. */
-subselect:
-          subselect_start opt_with_clause query_expression_body subselect_end
-          { 
-            $3->set_with_clause($2);
-            $$= $3;
-          }
-        ;
-
-subselect_start:
-          {
-            LEX *lex=Lex;
-            if (!lex->expr_allows_subselect ||
-               lex->sql_command == (int)SQLCOM_PURGE)
-            {
-              thd->parse_error();
-              MYSQL_YYABORT;
-            }
-            /* 
-              we are making a "derived table" for the parenthesis
-              as we need to have a lex level to fit the union 
-              after the parenthesis, e.g. 
-              (SELECT .. ) UNION ...  becomes 
-              SELECT * FROM ((SELECT ...) UNION ...)
-            */
-            if (mysql_new_select(Lex, 1, NULL))
-              MYSQL_YYABORT;
-          }
-        ;
-
-subselect_end:
-          {
-            LEX *lex=Lex;
-
-            lex->check_automatic_up(UNSPECIFIED_TYPE);
-            lex->pop_context();
-            SELECT_LEX *child= lex->current_select;
-            lex->current_select = lex->current_select->return_after_parsing();
-            lex->nest_level--;
-            lex->current_select->n_child_sum_items += child->n_sum_items;
-            /*
-              A subselect can add fields to an outer select. Reserve space for
-              them.
-            */
-            lex->current_select->select_n_where_fields+=
-            child->select_n_where_fields;
-
-            /*
-              Aggregate functions in having clause may add fields to an outer
-              select. Count them also.
-            */
-            lex->current_select->select_n_having_items+=
-            child->select_n_having_items;
-          }
-        ;
-
-opt_query_expression_options:
-          /* empty */
-        | query_expression_option_list
-        ;
-
-query_expression_option_list:
-          query_expression_option_list query_expression_option
-        | query_expression_option
-        ;
-
 query_expression_option:
           STRAIGHT_JOIN { Select->options|= SELECT_STRAIGHT_JOIN; }
         | HIGH_PRIORITY
           {
-            if (check_simple_select())
-              MYSQL_YYABORT;
             YYPS->m_lock_type= TL_READ_HIGH_PRIORITY;
             YYPS->m_mdl_type= MDL_SHARED_READ;
             Select->options|= SELECT_HIGH_PRIORITY;
@@ -17150,18 +17337,8 @@ query_expression_option:
         | DISTINCT         { Select->options|= SELECT_DISTINCT; }
         | SQL_SMALL_RESULT { Select->options|= SELECT_SMALL_RESULT; }
         | SQL_BIG_RESULT   { Select->options|= SELECT_BIG_RESULT; }
-        | SQL_BUFFER_RESULT
-          {
-            if (check_simple_select())
-              MYSQL_YYABORT;
-            Select->options|= OPTION_BUFFER_RESULT;
-          }
-        | SQL_CALC_FOUND_ROWS
-          {
-            if (check_simple_select())
-              MYSQL_YYABORT;
-            Select->options|= OPTION_FOUND_ROWS;
-          }
+        | SQL_BUFFER_RESULT { Select->options|= OPTION_BUFFER_RESULT; }
+        | SQL_CALC_FOUND_ROWS { Select->options|= OPTION_FOUND_ROWS; }
         | ALL { Select->options|= SELECT_ALL; }
         ;
 
@@ -17249,35 +17426,28 @@ view_select:
             lex->parsing_options.allows_variable= FALSE;
             lex->create_view->select.str= (char *) YYLIP->get_cpp_ptr();
           }
-          opt_with_clause query_expression_body_view view_check_option
+          query_expression
+          view_check_option
           {
             LEX *lex= Lex;
+            SQL_I_List<TABLE_LIST> *save= &lex->first_select_lex()->table_list;
+            lex->set_main_unit($2);
+            if (lex->check_main_unit_semantics())
+              MYSQL_YYABORT;
+            lex->first_select_lex()->table_list.push_front(save);
+            lex->current_select= Lex->first_select_lex();
             size_t len= YYLIP->get_cpp_ptr() - lex->create_view->select.str;
             void *create_view_select= thd->memdup(lex->create_view->select.str, len);
             lex->create_view->select.length= len;
             lex->create_view->select.str= (char *) create_view_select;
+            size_t not_used;
             trim_whitespace(thd->charset(),
-                            &lex->create_view->select);
-            lex->create_view->check= $4;
+                            &lex->create_view->select, &not_used);
+            lex->create_view->check= $3;
             lex->parsing_options.allows_variable= TRUE;
-            lex->current_select->set_with_clause($2);
           }
         ;
 
-/*
-  SQL Standard <query expression body> for VIEWs.
-  Does not include INTO and PROCEDURE clauses.
-*/
-query_expression_body_view:
-          SELECT_SYM select_options_and_item_list select_init3_view
-        | table_value_constructor
-        | table_value_constructor union_order_or_limit
-        | table_value_constructor union_list_view
-        | '(' select_paren_view ')'
-        | '(' select_paren_view ')' union_order_or_limit
-        | '(' select_paren_view ')' union_list_view
-        ;
-
 view_check_option:
           /* empty */                     { $$= VIEW_CHECK_NONE; }
         | WITH CHECK_SYM OPTION           { $$= VIEW_CHECK_CASCADED; }
@@ -17381,11 +17551,11 @@ trigger_tail:
               sp_proc_stmt alternatives are not saving/restoring LEX, so
               lex->query_tables can be wiped out.
             */
-            if (!lex->select_lex.add_table_to_list(thd, $10,
-                                                   (LEX_CSTRING*) 0,
-                                                   TL_OPTION_UPDATING,
-                                                   TL_READ_NO_INSERT,
-                                                   MDL_SHARED_NO_WRITE))
+            if (!lex->builtin_select.add_table_to_list(thd, $10,
+                                                       (LEX_CSTRING*) 0,
+                                                       TL_OPTION_UPDATING,
+                                                       TL_READ_NO_INSERT,
+                                                       MDL_SHARED_NO_WRITE))
               MYSQL_YYABORT;
           }
         ;
diff --git a/sql/sql_yacc_ora.yy b/sql/sql_yacc_ora.yy
index ec2aeeaefba..c1512434d72 100644
--- a/sql/sql_yacc_ora.yy
+++ b/sql/sql_yacc_ora.yy
@@ -1481,7 +1481,7 @@ query:
           END_OF_INPUT
           {
             if (!thd->bootstrap &&
-              (!(thd->lex->select_lex.options & OPTION_FOUND_COMMENT)))
+              (!(thd->lex->builtin_select.options & OPTION_FOUND_COMMENT)))
               my_yyabort_error((ER_EMPTY_QUERY, MYF(0)));
 
             thd->lex->sql_command= SQLCOM_EMPTY_QUERY;
@@ -1934,9 +1934,9 @@ create:
             lex->create_info.init();
             if (lex->set_command_with_check(SQLCOM_CREATE_TABLE, $2, $1 | $4))
                MYSQL_YYABORT;
-            if (!lex->select_lex.add_table_to_list(thd, $5, NULL,
-                                                   TL_OPTION_UPDATING,
-                                                   TL_WRITE, MDL_EXCLUSIVE))
+            if (!lex->builtin_select.add_table_to_list(thd, $5, NULL,
+                                                       TL_OPTION_UPDATING,
+                                                       TL_WRITE, MDL_EXCLUSIVE))
               MYSQL_YYABORT;
             lex->alter_info.reset();
             /*
@@ -1951,7 +1951,7 @@ create:
           create_body
           {
             LEX *lex= thd->lex;
-            lex->current_select= &lex->select_lex; 
+            lex->current_select= &lex->builtin_select;
             if ((lex->create_info.used_fields & HA_CREATE_USED_ENGINE) &&
                 !lex->create_info.db_type)
             {
@@ -1971,9 +1971,9 @@ create:
            if (lex->set_command_with_check(SQLCOM_CREATE_SEQUENCE, $2, $1 | $4))
               MYSQL_YYABORT;
 
-           if (!lex->select_lex.add_table_to_list(thd, $5, NULL,
-                                                  TL_OPTION_UPDATING,
-                                                  TL_WRITE, MDL_EXCLUSIVE))
+           if (!lex->builtin_select.add_table_to_list(thd, $5, NULL,
+                                                      TL_OPTION_UPDATING,
+                                                      TL_WRITE, MDL_EXCLUSIVE))
              MYSQL_YYABORT;
 
                /*
@@ -1996,8 +1996,8 @@ create:
             if (lex->create_info.seq_create_info->check_and_adjust(1))
             {
               my_error(ER_SEQUENCE_INVALID_DATA, MYF(0),
-                       lex->select_lex.table_list.first->db.str,
-                       lex->select_lex.table_list.first->table_name.str);
+                       lex->builtin_select.table_list.first->db.str,
+                       lex->builtin_select.table_list.first->table_name.str);
               MYSQL_YYABORT;
             }
 
@@ -2009,7 +2009,7 @@ create:
 	    Lex->create_info.used_fields|= HA_CREATE_USED_SEQUENCE;
             Lex->create_info.sequence= 1;
 
-            lex->current_select= &lex->select_lex;
+            lex->current_select= &lex->builtin_select;
             if ((lex->create_info.used_fields & HA_CREATE_USED_ENGINE) &&
                 !lex->create_info.db_type)
             {
@@ -2724,7 +2724,7 @@ clear_privileges:
            lex->columns.empty();
            lex->grant= lex->grant_tot_col= 0;
            lex->all_privileges= 0;
-           lex->select_lex.db= null_clex_str;
+           lex->builtin_select.db= null_clex_str;
            lex->ssl_type= SSL_TYPE_NOT_SPECIFIED;
            lex->ssl_cipher= lex->x509_subject= lex->x509_issuer= 0;
            bzero((char *)&(lex->mqh),sizeof(lex->mqh));
@@ -4999,7 +4999,7 @@ create_body:
           {
 
             Lex->create_info.add(DDL_options_st::OPT_LIKE);
-            TABLE_LIST *src_table= Lex->select_lex.add_table_to_list(thd,
+            TABLE_LIST *src_table= Lex->builtin_select.add_table_to_list(thd,
                                         $1, NULL, 0, TL_READ, MDL_SHARED_READ);
             if (! src_table)
               MYSQL_YYABORT;
@@ -6009,7 +6009,7 @@ create_table_option:
           }
         | UNION_SYM opt_equal
           {
-            Lex->select_lex.table_list.save_and_clear(&Lex->save_list);
+            Lex->builtin_select.table_list.save_and_clear(&Lex->save_list);
           }
           '(' opt_table_list ')'
           {
@@ -6018,8 +6018,8 @@ create_table_option:
               from the global list.
             */
             LEX *lex=Lex;
-            lex->create_info.merge_list= lex->select_lex.table_list;
-            lex->select_lex.table_list= lex->save_list;
+            lex->create_info.merge_list= lex->builtin_select.table_list;
+            lex->builtin_select.table_list= lex->save_list;
             /*
               When excluding union list from the global list we assume that
               elements of the former immediately follow elements which represent
@@ -7468,7 +7468,7 @@ alter:
             Lex->table_type= TABLE_TYPE_UNKNOWN;
             Lex->sql_command= SQLCOM_ALTER_TABLE;
             Lex->duplicates= DUP_ERROR; 
-            Lex->select_lex.init_order();
+            Lex->builtin_select.init_order();
             Lex->create_info.init();
             Lex->create_info.row_type= ROW_TYPE_NOT_USED;
             Lex->alter_info.reset();
@@ -7478,12 +7478,12 @@ alter:
           }
           alter_options TABLE_SYM table_ident opt_lock_wait_timeout
           {
-            if (!Lex->select_lex.add_table_to_list(thd, $5, NULL,
-                                                   TL_OPTION_UPDATING,
-                                                   TL_READ_NO_INSERT,
-                                                   MDL_SHARED_UPGRADABLE))
+            if (!Lex->builtin_select.add_table_to_list(thd, $5, NULL,
+                                                       TL_OPTION_UPDATING,
+                                                       TL_READ_NO_INSERT,
+                                                       MDL_SHARED_UPGRADABLE))
               MYSQL_YYABORT;
-            Lex->select_lex.db= (Lex->select_lex.table_list.first)->db;
+            Lex->builtin_select.db= (Lex->builtin_select.table_list.first)->db;
             Lex->create_last_non_select_table= Lex->last_table();
           }
           alter_commands
@@ -7649,9 +7649,9 @@ alter:
             LEX *lex= Lex;
             if (!(lex->create_info.seq_create_info= new (thd->mem_root)
                                                      sequence_definition()) ||
-                !lex->select_lex.add_table_to_list(thd, $5, NULL,
-                                                   TL_OPTION_SEQUENCE,
-                                                   TL_WRITE, MDL_EXCLUSIVE))
+                !lex->builtin_select.add_table_to_list(thd, $5, NULL,
+                                                       TL_OPTION_SEQUENCE,
+                                                       TL_WRITE, MDL_EXCLUSIVE))
               MYSQL_YYABORT;
           }
           sequence_defs
@@ -7809,18 +7809,17 @@ alter_commands:
           WITH TABLE_SYM table_ident have_partitioning
           {
             LEX *lex= thd->lex;
-            lex->select_lex.db= $6->db;
-            if (lex->select_lex.db.str == NULL &&
-                lex->copy_db_to(&lex->select_lex.db))
+            if (lex->builtin_select.db.str == NULL &&
+                lex->copy_db_to(&lex->builtin_select.db))
             {
               MYSQL_YYABORT;
             }
             lex->name= $6->table;
             lex->alter_info.partition_flags|= ALTER_PARTITION_EXCHANGE;
-            if (!lex->select_lex.add_table_to_list(thd, $6, NULL,
-                                                   TL_OPTION_UPDATING,
-                                                   TL_READ_NO_INSERT,
-                                                   MDL_SHARED_NO_WRITE))
+            if (!lex->builtin_select.add_table_to_list(thd, $6, NULL,
+                                                       TL_OPTION_UPDATING,
+                                                       TL_READ_NO_INSERT,
+                                                       MDL_SHARED_NO_WRITE))
               MYSQL_YYABORT;
             DBUG_ASSERT(!lex->m_sql_cmd);
             lex->m_sql_cmd= new (thd->mem_root)
@@ -8061,9 +8060,9 @@ alter_list_item:
         | RENAME opt_to table_ident
           {
             LEX *lex=Lex;
-            lex->select_lex.db= $3->db;
-            if (lex->select_lex.db.str == NULL &&
-                lex->copy_db_to(&lex->select_lex.db))
+            lex->builtin_select.db= $3->db;
+            if (lex->builtin_select.db.str == NULL &&
+                lex->copy_db_to(&lex->builtin_select.db))
             {
               MYSQL_YYABORT;
             }
@@ -8740,8 +8739,8 @@ adm_partition:
 
 cache_keys_spec:
           {
-            Lex->select_lex.alloc_index_hints(thd);
-            Select->set_index_hint_type(INDEX_HINT_USE, 
+            Lex->builtin_select.alloc_index_hints(thd);
+            Select->set_index_hint_type(INDEX_HINT_USE,
                                         INDEX_HINT_MASK_ALL);
           }
           cache_key_list_or_empty
@@ -9010,16 +9009,16 @@ select_option:
               Allow this flag only on the first top-level SELECT statement, if
               SQL_CACHE wasn't specified, and only once per query.
              */
-            if (Lex->current_select != &Lex->select_lex)
+            if (Lex->current_select != &Lex->builtin_select)
               my_yyabort_error((ER_CANT_USE_OPTION_HERE, MYF(0), "SQL_NO_CACHE"));
-            if (Lex->select_lex.sql_cache == SELECT_LEX::SQL_CACHE)
+            if (Lex->builtin_select.sql_cache == SELECT_LEX::SQL_CACHE)
               my_yyabort_error((ER_WRONG_USAGE, MYF(0), "SQL_CACHE", "SQL_NO_CACHE"));
-            if (Lex->select_lex.sql_cache == SELECT_LEX::SQL_NO_CACHE)
+            if (Lex->builtin_select.sql_cache == SELECT_LEX::SQL_NO_CACHE)
               my_yyabort_error((ER_DUP_ARGUMENT, MYF(0), "SQL_NO_CACHE"));
 
             Lex->safe_to_cache_query=0;
-            Lex->select_lex.options&= ~OPTION_TO_QUERY_CACHE;
-            Lex->select_lex.sql_cache= SELECT_LEX::SQL_NO_CACHE;
+            Lex->builtin_select.options&= ~OPTION_TO_QUERY_CACHE;
+            Lex->builtin_select.sql_cache= SELECT_LEX::SQL_NO_CACHE;
           }
         | SQL_CACHE_SYM
           {
@@ -9027,16 +9026,16 @@ select_option:
               Allow this flag only on the first top-level SELECT statement, if
               SQL_NO_CACHE wasn't specified, and only once per query.
              */
-            if (Lex->current_select != &Lex->select_lex)
+            if (Lex->current_select != &Lex->builtin_select)
               my_yyabort_error((ER_CANT_USE_OPTION_HERE, MYF(0), "SQL_CACHE"));
-            if (Lex->select_lex.sql_cache == SELECT_LEX::SQL_NO_CACHE)
+            if (Lex->builtin_select.sql_cache == SELECT_LEX::SQL_NO_CACHE)
               my_yyabort_error((ER_WRONG_USAGE, MYF(0), "SQL_NO_CACHE", "SQL_CACHE"));
-            if (Lex->select_lex.sql_cache == SELECT_LEX::SQL_CACHE)
+            if (Lex->builtin_select.sql_cache == SELECT_LEX::SQL_CACHE)
               my_yyabort_error((ER_DUP_ARGUMENT, MYF(0), "SQL_CACHE"));
 
             Lex->safe_to_cache_query=1;
-            Lex->select_lex.options|= OPTION_TO_QUERY_CACHE;
-            Lex->select_lex.sql_cache= SELECT_LEX::SQL_CACHE;
+            Lex->builtin_select.options|= OPTION_TO_QUERY_CACHE;
+            Lex->builtin_select.sql_cache= SELECT_LEX::SQL_CACHE;
           }
         ;
 
@@ -11605,7 +11604,7 @@ table_primary_derived:
 
                 MYSQL_YYABORT;
               sel->add_joined_table($$);
-              lex->pop_context();
+              //lex->pop_context("derived");
               lex->nest_level--;
             }
             else if ($5 != NULL)
@@ -11777,7 +11776,7 @@ select_derived2:
                 mysql_new_select(lex, 1, NULL))
               MYSQL_YYABORT;
             mysql_init_select(lex);
-            lex->current_select->linkage= DERIVED_TABLE_TYPE;
+            lex->current_select->set_linkage(DERIVED_TABLE_TYPE);
             lex->current_select->parsing_place= SELECT_LIST;
           }
           select_options select_item_list
@@ -12500,7 +12499,7 @@ procedure_clause:
           {
             LEX *lex=Lex;
 
-            DBUG_ASSERT(&lex->select_lex == lex->current_select);
+            DBUG_ASSERT(&lex->builtin_select == lex->current_select);
 
             lex->proc_list.elements=0;
             lex->proc_list.first=0;
@@ -12890,7 +12889,7 @@ insert:
           opt_ignore insert2
           {
             Select->set_lock_for_tables($3);
-            Lex->current_select= &Lex->select_lex;
+            Lex->current_select= &Lex->builtin_select;
           }
           insert_field_spec opt_insert_update
           {}
@@ -12907,7 +12906,7 @@ replace:
           replace_lock_option insert2
           {
             Select->set_lock_for_tables($3);
-            Lex->current_select= &Lex->select_lex;
+            Lex->current_select= &Lex->builtin_select;
           }
           insert_field_spec
           {}
@@ -13102,13 +13101,14 @@ update:
           SET update_list
           {
             LEX *lex= Lex;
-            if (lex->select_lex.table_list.elements > 1)
+            if (lex->builtin_select.table_list.elements > 1)
               lex->sql_command= SQLCOM_UPDATE_MULTI;
-            else if (lex->select_lex.get_table_list()->derived)
+            else if (lex->builtin_select.get_table_list()->derived)
             {
               /* it is single table update and it is update of derived table */
               my_error(ER_NON_UPDATABLE_TABLE, MYF(0),
-                       lex->select_lex.get_table_list()->alias.str, "UPDATE");
+                       lex->builtin_select.get_table_list()->alias.str,
+                       "UPDATE");
               MYSQL_YYABORT;
             }
             /*
@@ -13166,7 +13166,7 @@ delete:
             YYPS->m_mdl_type= MDL_SHARED_WRITE;
 
             lex->ignore= 0;
-            lex->select_lex.init_order();
+            lex->builtin_select.init_order();
           }
           opt_delete_options single_multi
         ;
@@ -13271,9 +13271,9 @@ truncate:
             LEX* lex= Lex;
             lex->sql_command= SQLCOM_TRUNCATE;
             lex->alter_info.reset();
-            lex->select_lex.options= 0;
-            lex->select_lex.sql_cache= SELECT_LEX::SQL_CACHE_UNSPECIFIED;
-            lex->select_lex.init_order();
+            lex->builtin_select.options= 0;
+            lex->builtin_select.sql_cache= SELECT_LEX::SQL_CACHE_UNSPECIFIED;
+            lex->builtin_select.init_order();
             YYPS->m_lock_type= TL_WRITE;
             YYPS->m_mdl_type= MDL_EXCLUSIVE;
           }
@@ -13387,7 +13387,7 @@ show_param:
            {
              LEX *lex= Lex;
              lex->sql_command= SQLCOM_SHOW_TABLES;
-             lex->select_lex.db= $3;
+             lex->builtin_select.db= $3;
              if (prepare_schema_table(thd, lex, 0, SCH_TABLE_NAMES))
                MYSQL_YYABORT;
            }
@@ -13395,7 +13395,7 @@ show_param:
            {
              LEX *lex= Lex;
              lex->sql_command= SQLCOM_SHOW_TRIGGERS;
-             lex->select_lex.db= $3;
+             lex->builtin_select.db= $3;
              if (prepare_schema_table(thd, lex, 0, SCH_TRIGGERS))
                MYSQL_YYABORT;
            }
@@ -13403,7 +13403,7 @@ show_param:
            {
              LEX *lex= Lex;
              lex->sql_command= SQLCOM_SHOW_EVENTS;
-             lex->select_lex.db= $2;
+             lex->builtin_select.db= $2;
              if (prepare_schema_table(thd, lex, 0, SCH_EVENTS))
                MYSQL_YYABORT;
            }
@@ -13411,7 +13411,7 @@ show_param:
            {
              LEX *lex= Lex;
              lex->sql_command= SQLCOM_SHOW_TABLE_STATUS;
-             lex->select_lex.db= $3;
+             lex->builtin_select.db= $3;
              if (prepare_schema_table(thd, lex, 0, SCH_TABLES))
                MYSQL_YYABORT;
            }
@@ -13419,7 +13419,7 @@ show_param:
           {
             LEX *lex= Lex;
             lex->sql_command= SQLCOM_SHOW_OPEN_TABLES;
-            lex->select_lex.db= $3;
+            lex->builtin_select.db= $3;
             if (prepare_schema_table(thd, lex, 0, SCH_OPEN_TABLES))
               MYSQL_YYABORT;
           }
@@ -13583,7 +13583,7 @@ show_param:
           {
             LEX *lex= Lex;
             lex->sql_command = SQLCOM_SHOW_CREATE;
-            if (!lex->select_lex.add_table_to_list(thd, $3, NULL,0))
+            if (!lex->builtin_select.add_table_to_list(thd, $3, NULL,0))
               MYSQL_YYABORT;
             lex->create_info.storage_media= HA_SM_DEFAULT;
           }
@@ -13591,7 +13591,7 @@ show_param:
           {
             LEX *lex= Lex;
             lex->sql_command = SQLCOM_SHOW_CREATE;
-            if (!lex->select_lex.add_table_to_list(thd, $3, NULL, 0))
+            if (!lex->builtin_select.add_table_to_list(thd, $3, NULL, 0))
               MYSQL_YYABORT;
             lex->table_type= TABLE_TYPE_VIEW;
           }
@@ -13599,7 +13599,7 @@ show_param:
           {
             LEX *lex= Lex;
             lex->sql_command = SQLCOM_SHOW_CREATE;
-            if (!lex->select_lex.add_table_to_list(thd, $3, NULL, 0))
+            if (!lex->builtin_select.add_table_to_list(thd, $3, NULL, 0))
               MYSQL_YYABORT;
             lex->table_type= TABLE_TYPE_SEQUENCE;
           }
@@ -13815,7 +13815,7 @@ describe:
             mysql_init_select(lex);
             lex->current_select->parsing_place= SELECT_LIST;
             lex->sql_command= SQLCOM_SHOW_FIELDS;
-            lex->select_lex.db= null_clex_str;
+            lex->builtin_select.db= null_clex_str;
             lex->verbose= 0;
             if (prepare_schema_table(thd, lex, $2, SCH_COLUMNS))
               MYSQL_YYABORT;
@@ -13829,7 +13829,7 @@ describe:
           explainable_command
           {
             LEX *lex=Lex;
-            lex->select_lex.options|= SELECT_DESCRIBE;
+            lex->builtin_select.options|= SELECT_DESCRIBE;
           }
         ;
 
@@ -14150,7 +14150,7 @@ use:
           {
             LEX *lex=Lex;
             lex->sql_command=SQLCOM_CHANGE_DB;
-            lex->select_lex.db= $2;
+            lex->builtin_select.db= $2;
           }
         ;
 
@@ -17221,11 +17221,11 @@ trigger_tail:
               sp_proc_stmt alternatives are not saving/restoring LEX, so
               lex->query_tables can be wiped out.
             */
-            if (!lex->select_lex.add_table_to_list(thd, $10,
-                                                   (LEX_CSTRING*) 0,
-                                                   TL_OPTION_UPDATING,
-                                                   TL_READ_NO_INSERT,
-                                                   MDL_SHARED_NO_WRITE))
+            if (!lex->builtin_select.add_table_to_list(thd, $10,
+                                                       (LEX_CSTRING*) 0,
+                                                       TL_OPTION_UPDATING,
+                                                       TL_READ_NO_INSERT,
+                                                       MDL_SHARED_NO_WRITE))
               MYSQL_YYABORT;
           }
         ;
diff --git a/sql/structs.h b/sql/structs.h
index 01d99517fed..19c2405e75d 100644
--- a/sql/structs.h
+++ b/sql/structs.h
@@ -759,6 +759,59 @@ struct Lex_string_with_pos_st: public LEX_CSTRING
   const char *m_pos;
 };
 
+class Lex_select_lock
+{
+public:
+  struct
+  {
+    uint defined_lock:1;
+    uint update_lock:1;
+    uint defined_timeout:1;
+  };
+  ulong timeout;
+
+
+  void empty()
+  {
+    defined_lock= update_lock= defined_timeout= FALSE;
+    timeout= 0;
+  }
+};
+
+class Lex_select_limit
+{
+public:
+  bool explicit_limit;
+  Item *select_limit, *offset_limit;
+
+  void empty()
+  {
+    explicit_limit= FALSE;
+    select_limit= offset_limit= NULL;
+  }
+};
+
+struct st_order;
+class st_select_lex;
+
+/**
+  ORDER BY ... LIMIT parameters;
+*/
+class Lex_order_limit_lock
+{
+public:
+  SQL_I_List<st_order> *order_list;   /* ORDER clause */
+  Lex_select_lock lock;
+  Lex_select_limit limit;
+
+  static void *operator new(size_t size, MEM_ROOT *mem_root) throw ()
+  { return alloc_root(mem_root, size); }
+  Lex_order_limit_lock() :order_list(NULL)
+  {}
+
+  bool set_to(st_select_lex *sel);
+};
+
 
 class Load_data_param
 {
diff --git a/sql/table.cc b/sql/table.cc
index 4f90d429ce5..0916bb82634 100644
--- a/sql/table.cc
+++ b/sql/table.cc
@@ -2702,7 +2702,7 @@ static bool sql_unusable_for_discovery(THD *thd, handlerton *engine,
   if (lex->create_info.like())
     return 1;
   // ... create select
-  if (lex->select_lex.item_list.elements)
+  if (lex->first_select_lex()->item_list.elements)
     return 1;
   // ... temporary
   if (create_info->tmp_table())
@@ -4951,13 +4951,13 @@ bool TABLE_LIST::single_table_updatable()
 {
   if (!updatable)
     return false;
-  if (view && view->select_lex.table_list.elements == 1)
+  if (view && view->first_select_lex()->table_list.elements == 1)
   {
     /*
       We need to check deeply only single table views. Multi-table views
       will be turned to multi-table updates and then checked by leaf tables
     */
-    return (((TABLE_LIST *)view->select_lex.table_list.first)->
+    return (((TABLE_LIST *)view->first_select_lex()->table_list.first)->
             single_table_updatable());
   }
   return true;
@@ -4994,7 +4994,8 @@ merge_on_conds(THD *thd, TABLE_LIST *table, bool is_cascaded)
     cond= table->on_expr->copy_andor_structure(thd);
   if (!table->view)
     DBUG_RETURN(cond);
-  for (TABLE_LIST *tbl= (TABLE_LIST*)table->view->select_lex.table_list.first;
+  for (TABLE_LIST *tbl=
+         (TABLE_LIST*)table->view->first_select_lex()->table_list.first;
        tbl;
        tbl= tbl->next_local)
   {
@@ -5036,7 +5037,7 @@ bool TABLE_LIST::prep_check_option(THD *thd, uint8 check_opt_type)
 {
   DBUG_ENTER("TABLE_LIST::prep_check_option");
   bool is_cascaded= check_opt_type == VIEW_CHECK_CASCADED;
-  TABLE_LIST *merge_underlying_list= view->select_lex.get_table_list();
+  TABLE_LIST *merge_underlying_list= view->first_select_lex()->get_table_list();
   for (TABLE_LIST *tbl= merge_underlying_list; tbl; tbl= tbl->next_local)
   {
     /* see comment of check_opt_type parameter */
@@ -5158,7 +5159,7 @@ TABLE_LIST *TABLE_LIST::find_underlying_table(TABLE *table_to_find)
   if (!view)
     return 0;
 
-  for (TABLE_LIST *tbl= view->select_lex.get_table_list();
+  for (TABLE_LIST *tbl= view->first_select_lex()->get_table_list();
        tbl;
        tbl= tbl->next_local)
   {
@@ -5329,7 +5330,8 @@ bool TABLE_LIST::set_insert_values(MEM_ROOT *mem_root)
   {
     DBUG_PRINT("info", ("setting insert_value for view"));
     DBUG_ASSERT(is_view_or_derived() && is_merged_derived());
-    for (TABLE_LIST *tbl= (TABLE_LIST*)view->select_lex.table_list.first;
+    for (TABLE_LIST *tbl=
+           (TABLE_LIST*)view->first_select_lex()->table_list.first;
          tbl;
          tbl= tbl->next_local)
       if (tbl->set_insert_values(mem_root))
@@ -5496,7 +5498,7 @@ void TABLE_LIST::register_want_access(ulong want_access)
   }
   if (!view)
     return;
-  for (TABLE_LIST *tbl= view->select_lex.get_table_list();
+  for (TABLE_LIST *tbl= view->first_select_lex()->get_table_list();
        tbl;
        tbl= tbl->next_local)
     tbl->register_want_access(want_access);
@@ -5688,6 +5690,7 @@ void TABLE_LIST::set_check_materialized()
       The subtree should be already excluded
     */
     DBUG_ASSERT(!derived->first_select()->first_inner_unit() ||
+                derived->first_select()->first_inner_unit()->with_element ||
                 derived->first_select()->first_inner_unit()->first_select()->
                 exclude_from_table_unique_test);
   }
@@ -5704,14 +5707,14 @@ TABLE *TABLE_LIST::get_real_join_table()
       break;
     /* we do not support merging of union yet */
     DBUG_ASSERT(tbl->view == NULL ||
-               tbl->view->select_lex.next_select() == NULL);
+               tbl->view->first_select_lex()->next_select() == NULL);
     DBUG_ASSERT(tbl->derived == NULL ||
                tbl->derived->first_select()->next_select() == NULL);
 
     {
       List_iterator_fast<TABLE_LIST>
         ti(tbl->view != NULL ?
-           tbl->view->select_lex.top_join_list :
+           tbl->view->first_select_lex()->top_join_list :
            tbl->derived->first_select()->top_join_list);
       for (;;)
       {
@@ -5882,7 +5885,7 @@ Item *Field_iterator_view::create_item(THD *thd)
 Item *create_view_field(THD *thd, TABLE_LIST *view, Item **field_ref,
                         LEX_CSTRING *name)
 {
-  bool save_wrapper= thd->lex->select_lex.no_wrap_view_item;
+  bool save_wrapper= thd->lex->first_select_lex()->no_wrap_view_item;
   Item *field= *field_ref;
   DBUG_ENTER("create_view_field");
 
@@ -5913,8 +5916,9 @@ Item *create_view_field(THD *thd, TABLE_LIST *view, Item **field_ref,
   {
     DBUG_RETURN(field);
   }
-  Name_resolution_context *context= view->view ? &view->view->select_lex.context :
-                                    &thd->lex->select_lex.context;
+  Name_resolution_context *context= (view->view ?
+                                     &view->view->first_select_lex()->context:
+                                     &thd->lex->first_select_lex()->context);
   Item *item= (new (thd->mem_root)
                Item_direct_view_ref(thd, context, field_ref, view->alias.str,
                                     name, view));
@@ -8646,7 +8650,7 @@ bool TR_table::query(ulonglong trx_id)
   READ_RECORD info;
   int error;
   List<TABLE_LIST> dummy;
-  SELECT_LEX &slex= thd->lex->select_lex;
+  SELECT_LEX &slex= *(thd->lex->first_select_lex());
   Name_resolution_context_backup backup(slex.context, *this);
   Item *field= newx Item_field(thd, &slex.context, (*this)[FLD_TRX_ID]);
   Item *value= newx Item_int(thd, trx_id);
@@ -8676,7 +8680,7 @@ bool TR_table::query(MYSQL_TIME &commit_time, bool backwards)
   READ_RECORD info;
   int error;
   List<TABLE_LIST> dummy;
-  SELECT_LEX &slex= thd->lex->select_lex;
+  SELECT_LEX &slex= *(thd->lex->first_select_lex());
   Name_resolution_context_backup backup(slex.context, *this);
   Item *field= newx Item_field(thd, &slex.context, (*this)[FLD_COMMIT_TS]);
   Item *value= newx Item_datetime_literal(thd, &commit_time, 6);
diff --git a/sql/vtmd.cc b/sql/vtmd.cc
index b63d7bf3650..30e8b33f210 100644
--- a/sql/vtmd.cc
+++ b/sql/vtmd.cc
@@ -517,13 +517,13 @@ VTMD_table::find_archive_name(THD *thd, String &out)
   SQL_SELECT *select= NULL;
   COND *conds= NULL;
   List<TABLE_LIST> dummy;
-  SELECT_LEX &select_lex= thd->lex->select_lex;
+  SELECT_LEX &select_lex= *(thd->lex->first_select_lex());
 
   Local_da local_da(thd, ER_VERS_VTMD_ERROR);
   if (open(thd, local_da))
     return true;
 
-  Name_resolution_context &ctx= thd->lex->select_lex.context;
+  Name_resolution_context &ctx= thd->lex->first_select_lex()->context;
   TABLE_LIST *table_list= ctx.table_list;
   TABLE_LIST *first_name_resolution_table= ctx.first_name_resolution_table;
   table_map map = vtmd.table->map;
diff --git a/sql/wsrep_mysqld.cc b/sql/wsrep_mysqld.cc
index def52cb2675..4f9ff51eaf7 100644
--- a/sql/wsrep_mysqld.cc
+++ b/sql/wsrep_mysqld.cc
@@ -1329,7 +1329,7 @@ static int
 create_view_query(THD *thd, uchar** buf, size_t* buf_len)
 {
     LEX *lex= thd->lex;
-    SELECT_LEX *select_lex= &lex->select_lex;
+    SELECT_LEX *select_lex= lex->first_select_lex();
     TABLE_LIST *first_table= select_lex->table_list.first;
     TABLE_LIST *views = first_table;
     LEX_USER *definer;
@@ -1421,7 +1421,7 @@ static bool wsrep_can_run_in_toi(THD *thd, const char *db, const char *table,
   DBUG_ASSERT(table_list || db);
 
   LEX* lex= thd->lex;
-  SELECT_LEX* select_lex= &lex->select_lex;
+  SELECT_LEX* select_lex= lex->first_select_lex();
   TABLE_LIST* first_table= select_lex->table_list.first;
 
   switch (lex->sql_command)
diff --git a/storage/mroonga/ha_mroonga.cpp b/storage/mroonga/ha_mroonga.cpp
index 55c6b5d330e..cf486c199b3 100644
--- a/storage/mroonga/ha_mroonga.cpp
+++ b/storage/mroonga/ha_mroonga.cpp
@@ -193,7 +193,7 @@ static mysql_mutex_t *mrn_LOCK_open;
 #if MYSQL_VERSION_ID >= 50706 && !defined(MRN_MARIADB_P)
 #  define MRN_LEX_GET_TABLE_LIST(lex) (lex)->select_lex->table_list.first
 #else
-#  define MRN_LEX_GET_TABLE_LIST(lex) (lex)->select_lex.table_list.first
+#  define MRN_LEX_GET_TABLE_LIST(lex) (lex)->first_select_lex()->table_list.first
 #endif
 
 #if MYSQL_VERSION_ID >= 50706 && !defined(MRN_MARIADB_P)
diff --git a/storage/spider/spd_db_mysql.cc b/storage/spider/spd_db_mysql.cc
index 6ff2e25bc27..b8463adcfef 100644
--- a/storage/spider/spd_db_mysql.cc
+++ b/storage/spider/spd_db_mysql.cc
@@ -7217,7 +7217,7 @@ int spider_mysql_handler::append_select(
     if (result_list->lock_type != F_WRLCK && spider->lock_mode < 1)
     {
       /* no lock */
-      st_select_lex *select_lex = &spider->trx->thd->lex->select_lex;
+      st_select_lex *select_lex = spider->trx->thd->lex->first_select_lex();
       if (
         select_lex->sql_cache == SELECT_LEX::SQL_CACHE &&
         (spider->share->query_cache_sync & 1)
diff --git a/storage/spider/spd_table.cc b/storage/spider/spd_table.cc
index fde470daadd..0c5bdac4e70 100644
--- a/storage/spider/spd_table.cc
+++ b/storage/spider/spd_table.cc
@@ -9018,8 +9018,14 @@ int spider_set_direct_limit_offset(
   )
     DBUG_RETURN(FALSE);
 
+  /*
+    TODO: following comment is wrong or the check is wrong (correct
+    check for derived table will be something like select_lex->linkage,
+    if they need only top level it is better to check nested level and do
+      not loose UNIONS & Co
+  */
   // must not be derived table
-  if (&thd->lex->select_lex != select_lex)
+  if (thd->lex->first_select_lex() != select_lex)
     DBUG_RETURN(FALSE);
 
   spider->direct_select_offset = offset_limit;
diff --git a/storage/tokudb/tokudb_dir_cmd.cc b/storage/tokudb/tokudb_dir_cmd.cc
index 5431cbab7aa..d0da92eab27 100644
--- a/storage/tokudb/tokudb_dir_cmd.cc
+++ b/storage/tokudb/tokudb_dir_cmd.cc
@@ -50,11 +50,11 @@ static int MDL_and_TDC(THD *thd,
     table_arg.str = const_cast<char *>(table);
     table_arg.length = strlen(table);
     Table_ident table_ident(thd, &db_arg, &table_arg, true);;
-    thd->lex->select_lex.add_table_to_list(
+    thd->lex->first_select_lex()->add_table_to_list(
         thd, &table_ident, NULL, 1, TL_UNLOCK, MDL_EXCLUSIVE, 0, 0, 0);
     /* The lock will be released at the end of mysq_execute_command() */
     error = lock_table_names(thd,
-                             thd->lex->select_lex.table_list.first,
+                             thd->lex->first_select_lex()->table_list.first,
                              NULL,
                              thd->variables.lock_wait_timeout,
                              0);


More information about the commits mailing list