[Commits] a64a078e76c: MDEV-11953: support of brackets in UNION/EXCEPT/INTERSECT operations
revision-id: a64a078e76c3372f075c7eaed9729a03e524cd47 (mariadb-10.3.6-5-ga64a078e76c) parent(s): d3ff133390231d8224843995af6b11f6a381803e author: Oleksandr Byelkin committer: Oleksandr Byelkin timestamp: 2018-05-22 19:08:39 +0200 message: MDEV-11953: support of brackets in UNION/EXCEPT/INTERSECT operations --- mysql-test/include/deadlock.inc | 2 +- mysql-test/main/brackets.result | 184 ++ mysql-test/main/brackets.test | 69 + mysql-test/main/cte_nonrecursive.result | 40 +- mysql-test/main/deadlock_innodb.result | 2 +- mysql-test/main/derived_cond_pushdown.result | 6 +- 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 | 26 +- mysql-test/main/query_cache.test | 27 +- 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 | 2 +- mysql-test/main/sp.test | 2 +- 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/table_value_constr.result | 1 - 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/suite/funcs_1/r/innodb_views.result | 2 +- mysql-test/suite/funcs_1/r/memory_views.result | 2 +- mysql-test/suite/funcs_1/views/views_master.inc | 2 +- mysql-test/suite/innodb/r/innodb.result | 2 +- mysql-test/suite/innodb/t/innodb.test | 2 +- .../suite/innodb_fts/r/fulltext_order_by.result | 4 +- mysql-test/suite/versioning/r/select2.result | 2 +- sql/events.cc | 9 +- sql/item.cc | 8 +- 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 | 953 +++++++- sql/sql_lex.h | 234 +- sql/sql_load.cc | 9 +- sql/sql_parse.cc | 109 +- sql/sql_partition.cc | 3 +- sql/sql_partition_admin.cc | 4 +- sql/sql_prepare.cc | 50 +- sql/sql_priv.h | 5 + 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 | 2319 +++++++++++--------- sql/sql_yacc_ora.yy | 2205 +++++++++++-------- sql/structs.h | 53 + sql/table.cc | 34 +- 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 +- 103 files changed, 4984 insertions(+), 3172 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..a943dafecf7 --- /dev/null +++ b/mysql-test/main/brackets.result @@ -0,0 +1,184 @@ +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/0 Filter Select: select `1` AS `1` */ select 1 AS `1` union /* select#8/0 */ select `__8`.`1` AS `1` from (/* select#2/1 Filter Select: select `1` AS `1` */ select 1 AS `1` union /* select#7/1 */ select `__7`.`1` AS `1` from (/* select#3/2 Filter Select: select `1` AS `1` */ select 1 AS `1` union /* select#6/2 */ select `__6`.`1` AS `1` from (/* select#4/3 Filter Select: select `1` AS `1` */ select 1 AS `1` union /* select#5/3 */ select 1 AS `1`) `__6`) `__7`) `__8` +# +# MDEV-6341: INSERT ... SELECT UNION with parenthesis +# +create table t1 (a int, b int); +insert into t1 (select 1,1 union select 2,2); +select * from t1 order by 1; +a b +1 1 +2 2 +delete from t1; +insert into t1 select 1,1 union select 2,2; +select * from t1 order by 1; +a b +1 1 +2 2 +drop table t1; +CREATE OR REPLACE TABLE t1 AS SELECT 1 AS a UNION SELECT 2; +select * from t1 order by 1; +a +1 +2 +drop table t1; +CREATE OR REPLACE TABLE t1 AS (SELECT 1 AS a UNION SELECT 2); +select * from t1 order by 1; +a +1 +2 +drop table t1; +CREATE OR REPLACE VIEW v1 AS (SELECT 1 AS a); +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 1 AS `a`) latin1 latin1_swedish_ci +drop view v1; +CREATE OR REPLACE VIEW v1 AS SELECT 1 AS a UNION SELECT 2; +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 1 AS `a` union select 2 AS `2` latin1 latin1_swedish_ci +drop view v1; +CREATE OR REPLACE VIEW v1 AS (SELECT 1 AS a UNION SELECT 2); +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 1 AS `a` union select 2 AS `2` latin1 latin1_swedish_ci +drop view v1; +# +# MDEV-10028: Syntax error on ((SELECT ...) UNION (SELECT ...)) +# +CREATE TABLE t1 (a INT); +INSERT INTO t1 VALUES (10); +INSERT INTO t1 VALUES (20); +INSERT INTO t1 VALUES (30); +((SELECT a FROM t1) UNION (SELECT a FROM t1)); +a +10 +20 +30 +(SELECT * FROM t1 UNION SELECT * FROM t1); +a +10 +20 +30 +((SELECT a FROM t1) LIMIT 1); +a +10 +SELECT * FROM (SELECT 1 UNION (SELECT 2 UNION SELECT 3)) t1; +1 +1 +2 +3 +DROP TABLE t1; +# End of 10.4 tests diff --git a/mysql-test/main/brackets.test b/mysql-test/main/brackets.test new file mode 100644 index 00000000000..d3477f501a1 --- /dev/null +++ b/mysql-test/main/brackets.test @@ -0,0 +1,69 @@ +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))); + +--echo # +--echo # MDEV-6341: INSERT ... SELECT UNION with parenthesis +--echo # +create table t1 (a int, b int); +insert into t1 (select 1,1 union select 2,2); +select * from t1 order by 1; +delete from t1; +insert into t1 select 1,1 union select 2,2; +select * from t1 order by 1; +drop table t1; +CREATE OR REPLACE TABLE t1 AS SELECT 1 AS a UNION SELECT 2; +select * from t1 order by 1; +drop table t1; +CREATE OR REPLACE TABLE t1 AS (SELECT 1 AS a UNION SELECT 2); +select * from t1 order by 1; +drop table t1; +CREATE OR REPLACE VIEW v1 AS (SELECT 1 AS a); +show create view v1; +drop view v1; +CREATE OR REPLACE VIEW v1 AS SELECT 1 AS a UNION SELECT 2; +show create view v1; +drop view v1; +CREATE OR REPLACE VIEW v1 AS (SELECT 1 AS a UNION SELECT 2); +show create view v1; +drop view v1; + + +--echo # +--echo # MDEV-10028: Syntax error on ((SELECT ...) UNION (SELECT ...)) +--echo # +CREATE TABLE t1 (a INT); +INSERT INTO t1 VALUES (10); +INSERT INTO t1 VALUES (20); +INSERT INTO t1 VALUES (30); + +((SELECT a FROM t1) UNION (SELECT a FROM t1)); +(SELECT * FROM t1 UNION SELECT * FROM t1); +((SELECT a FROM t1) LIMIT 1); +SELECT * FROM (SELECT 1 UNION (SELECT 2 UNION SELECT 3)) t1; +DROP TABLE t1; + +--echo # End of 10.4 tests diff --git a/mysql-test/main/cte_nonrecursive.result b/mysql-test/main/cte_nonrecursive.result index 534a386fe12..89ffd94f9f7 100644 --- a/mysql-test/main/cte_nonrecursive.result +++ b/mysql-test/main/cte_nonrecursive.result @@ -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 @@ -461,10 +461,10 @@ t.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 Using where -1 PRIMARY <subquery3> eq_ref distinct_key distinct_key 4 func 1 +1 PRIMARY <subquery4> 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) -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) +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 t1.a,t1.b from t1, (select c from t2 where c >= 4) as t where t1.a=t.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, @@ -597,8 +597,8 @@ explain select * from v2; id select_type table type possible_keys key key_len ref rows Extra 1 PRIMARY t2 ALL NULL NULL NULL NULL 4 Using where -1 PRIMARY <derived3> ref key0 key0 5 test.t2.c 2 -3 DERIVED t1 ALL NULL NULL NULL NULL 8 Using where; Using temporary; Using filesort +1 PRIMARY <derived2> ref key0 key0 5 test.t2.c 2 +2 DERIVED t1 ALL NULL NULL NULL NULL 8 Using where; Using temporary; Using filesort # with clause in the specification of a view that whose definition # table alias for a with table create view v3 as @@ -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 @@ -1116,17 +1116,17 @@ select * from cte_e as cte_e1 where a > 1 union select * from cte_e as cte_e2; id select_type table type possible_keys key key_len ref rows filtered Extra -1 PRIMARY <derived2> ALL NULL NULL NULL NULL 14 100.00 Using where -2 DERIVED t1 ALL NULL NULL NULL NULL 7 100.00 Using where +1 PRIMARY <derived4> ALL NULL NULL NULL NULL 14 100.00 Using where +4 DERIVED t1 ALL NULL NULL NULL NULL 7 100.00 Using where 5 UNION t1 ALL NULL NULL NULL NULL 7 100.00 Using where -NULL UNION RESULT <union2,5> ALL NULL NULL NULL NULL NULL NULL -6 UNION <derived9> ALL NULL NULL NULL NULL 14 100.00 -9 DERIVED t1 ALL NULL NULL NULL NULL 7 100.00 Using where +NULL UNION RESULT <union4,5> ALL NULL NULL NULL NULL NULL NULL +6 UNION <derived11> ALL NULL NULL NULL NULL 14 100.00 +11 DERIVED t1 ALL NULL NULL NULL NULL 7 100.00 Using where 12 UNION t1 ALL NULL NULL NULL NULL 7 100.00 Using where -NULL UNION RESULT <union9,12> ALL NULL NULL NULL NULL NULL NULL +NULL UNION RESULT <union11,12> ALL NULL NULL NULL NULL NULL NULL NULL UNION RESULT <union1,6> ALL NULL NULL NULL NULL NULL NULL Warnings: -Note 1003 with cte_e as (with cte_o as (with cte_i as (/* select#4 */ select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` < 7)/* select#3 */ select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` > 1)/* select#2 */ select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` < 3 and `test`.`t1`.`a` > 1 and `test`.`t1`.`a` < 7 and `test`.`t1`.`a` > 1 union /* select#5 */ select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` > 4 and `test`.`t1`.`a` > 1 and `test`.`t1`.`a` < 7 and `test`.`t1`.`a` > 1)/* select#1 */ select `cte_e1`.`a` AS `a` from `cte_e` `cte_e1` where `cte_e1`.`a` > 1 union /* select#6 */ select `cte_e2`.`a` AS `a` from (with cte_o as (with cte_i as (/* select#11 */ select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` < 7)/* select#10 */ select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` > 1)/* select#9 */ select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` < 3 and `test`.`t1`.`a` > 1 and `test`.`t1`.`a` < 7 union /* select#12 */ select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` > 4 and `test`.`t1`.`a` > 1 and `test`.`t1`.`a` < 7) `cte_e2` +Note 1003 with cte_e as (with cte_o as (with cte_i as (select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` < 7)select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` > 1)select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` < 3 and `test`.`t1`.`a` > 1 and `test`.`t1`.`a` < 7 and `test`.`t1`.`a` > 1 union select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` > 4 and `test`.`t1`.`a` > 1 and `test`.`t1`.`a` < 7 and `test`.`t1`.`a` > 1)select `cte_e1`.`a` AS `a` from `cte_e` `cte_e1` where `cte_e1`.`a` > 1 union select `cte_e2`.`a` AS `a` from (with cte_o as (with cte_i as (select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` < 7)select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` > 1)select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` < 3 and `test`.`t1`.`a` > 1 and `test`.`t1`.`a` < 7 union select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` > 4 and ` test`.`t1`.`a` > 1 and `test`.`t1`.`a` < 7) `cte_e2` drop table t1; # # MDEV-13753: embedded CTE in a VIEW created in prepared statement 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_cond_pushdown.result b/mysql-test/main/derived_cond_pushdown.result index 6887ad11284..353ae9d804f 100644 --- a/mysql-test/main/derived_cond_pushdown.result +++ b/mysql-test/main/derived_cond_pushdown.result @@ -8935,7 +8935,7 @@ EXPLAIN "access_type": "ALL", "rows": 18, "filtered": 100, - "attached_condition": "__3.a > 5 and __3.c > 200", + "attached_condition": "__5.a > 5 and __5.c > 200", "materialized": { "query_block": { "union_result": { @@ -9561,7 +9561,7 @@ EXPLAIN "access_type": "ALL", "rows": 18, "filtered": 100, - "attached_condition": "__3.a > 4 and __3.c < 130", + "attached_condition": "__5.a > 4 and __5.c < 130", "materialized": { "query_block": { "union_result": { @@ -9707,7 +9707,7 @@ EXPLAIN "access_type": "ALL", "rows": 18, "filtered": 100, - "attached_condition": "__3.a > 4 and __3.c < 130", + "attached_condition": "__6.a > 4 and __6.c < 130", "materialized": { "query_block": { "union_result": { 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..fa198ee6e17 100644 --- a/mysql-test/main/query_cache.result +++ b/mysql-test/main/query_cache.result @@ -1858,17 +1858,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 +1878,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 +1902,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..389aa0de2fa 100644 --- a/mysql-test/main/query_cache.test +++ b/mysql-test/main/query_cache.test @@ -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 582ea33d903..3e8e2243725 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| diff --git a/mysql-test/main/sp.test b/mysql-test/main/sp.test index 7a6fc3e711d..6308a0906c7 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| 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 463ec53e7bb..39c0d1dd22b 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 6a4a1a4ad5b..b241be77df7 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/table_value_constr.result b/mysql-test/main/table_value_constr.result index 39caba331ef..ed9c198197c 100644 --- a/mysql-test/main/table_value_constr.result +++ b/mysql-test/main/table_value_constr.result @@ -366,7 +366,6 @@ values (1,2); 1 2 1 2 3 4 -1 2 # combination of different structures that uses VALUES structures : UNION + UNION ALL values (1,2),(3,4) union all 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; -@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 63207ea6a67..ab02e48ebaa 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 82ef38f0eb6..615b9bf552c 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/suite/funcs_1/r/innodb_views.result b/mysql-test/suite/funcs_1/r/innodb_views.result index b00d1a56c90..bf523d47515 100644 --- a/mysql-test/suite/funcs_1/r/innodb_views.result +++ b/mysql-test/suite/funcs_1/r/innodb_views.result @@ -3497,7 +3497,7 @@ DROP VIEW IF EXISTS v2 ; CREATE TABLE t1 (f1 BIGINT) ; SET @x=0; CREATE or REPLACE VIEW v1 AS Select 1 INTO @x; -ERROR 42000: You 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 @x' at line 1 +ERROR 42000: Incorrect usage/placement of 'INTO' Select @x; @x 0 diff --git a/mysql-test/suite/funcs_1/r/memory_views.result b/mysql-test/suite/funcs_1/r/memory_views.result index 5ac5c838fb5..57a6813b2fb 100644 --- a/mysql-test/suite/funcs_1/r/memory_views.result +++ b/mysql-test/suite/funcs_1/r/memory_views.result @@ -3498,7 +3498,7 @@ DROP VIEW IF EXISTS v2 ; CREATE TABLE t1 (f1 BIGINT) ; SET @x=0; CREATE or REPLACE VIEW v1 AS Select 1 INTO @x; -ERROR 42000: You 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 @x' at line 1 +ERROR 42000: Incorrect usage/placement of 'INTO' Select @x; @x 0 diff --git a/mysql-test/suite/funcs_1/views/views_master.inc b/mysql-test/suite/funcs_1/views/views_master.inc index 17f5c1e5529..e4b58111612 100644 --- a/mysql-test/suite/funcs_1/views/views_master.inc +++ b/mysql-test/suite/funcs_1/views/views_master.inc @@ -266,7 +266,7 @@ CREATE TABLE t1 (f1 BIGINT) ; # SELECT INTO is illegal SET @x=0; ---error ER_PARSE_ERROR +--error ER_CANT_USE_OPTION_HERE CREATE or REPLACE VIEW v1 AS Select 1 INTO @x; Select @x; diff --git a/mysql-test/suite/innodb/r/innodb.result b/mysql-test/suite/innodb/r/innodb.result index aafd31ae6f1..005fd70534a 100644 --- a/mysql-test/suite/innodb/r/innodb.result +++ b/mysql-test/suite/innodb/r/innodb.result @@ -1608,7 +1608,7 @@ INSERT INTO t1 VALUES (1),(2),(3); CREATE TABLE t2 (b_id tinyint(4) NOT NULL default '0',b_a tinyint(4) NOT NULL default '0', PRIMARY KEY (b_id), KEY (b_a), CONSTRAINT fk_b_a FOREIGN KEY (b_a) REFERENCES t1 (a_id) ON DELETE CASCADE ON UPDATE NO ACTION) ENGINE=InnoDB DEFAULT CHARSET=latin1; INSERT INTO t2 VALUES (1,1),(2,1),(3,1),(4,2),(5,2); -SELECT * FROM (SELECT t1.*,GROUP_CONCAT(t2.b_id SEPARATOR ',') as b_list FROM (t1 LEFT JOIN (t2) on t1.a_id = t2.b_a) GROUP BY t1.a_id ) AS xyz; +SELECT * FROM (SELECT t1.*,GROUP_CONCAT(t2.b_id SEPARATOR ',') as b_list FROM (t1 LEFT JOIN t2 on t1.a_id = t2.b_a) GROUP BY t1.a_id ) AS xyz; a_id b_list 1 1,2,3 2 4,5 diff --git a/mysql-test/suite/innodb/t/innodb.test b/mysql-test/suite/innodb/t/innodb.test index 472b47899db..dd8a67eeec2 100644 --- a/mysql-test/suite/innodb/t/innodb.test +++ b/mysql-test/suite/innodb/t/innodb.test @@ -1253,7 +1253,7 @@ CREATE TABLE t2 (b_id tinyint(4) NOT NULL default '0',b_a tinyint(4) NOT NULL de CONSTRAINT fk_b_a FOREIGN KEY (b_a) REFERENCES t1 (a_id) ON DELETE CASCADE ON UPDATE NO ACTION) ENGINE=InnoDB DEFAULT CHARSET=latin1; --enable_warnings INSERT INTO t2 VALUES (1,1),(2,1),(3,1),(4,2),(5,2); -SELECT * FROM (SELECT t1.*,GROUP_CONCAT(t2.b_id SEPARATOR ',') as b_list FROM (t1 LEFT JOIN (t2) on t1.a_id = t2.b_a) GROUP BY t1.a_id ) AS xyz; +SELECT * FROM (SELECT t1.*,GROUP_CONCAT(t2.b_id SEPARATOR ',') as b_list FROM (t1 LEFT JOIN t2 on t1.a_id = t2.b_a) GROUP BY t1.a_id ) AS xyz; DROP TABLE t2; DROP TABLE t1; diff --git a/mysql-test/suite/innodb_fts/r/fulltext_order_by.result b/mysql-test/suite/innodb_fts/r/fulltext_order_by.result index 503f117d02f..0d3a4a85b86 100644 --- a/mysql-test/suite/innodb_fts/r/fulltext_order_by.result +++ b/mysql-test/suite/innodb_fts/r/fulltext_order_by.result @@ -129,7 +129,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 @@ -145,7 +145,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/suite/versioning/r/select2.result b/mysql-test/suite/versioning/r/select2.result index 9267ab8c913..3f29a958907 100644 --- a/mysql-test/suite/versioning/r/select2.result +++ b/mysql-test/suite/versioning/r/select2.result @@ -331,6 +331,6 @@ x y select * from (select * from t1 for system_time all, t2 for system_time all) for system_time all as t; ERROR HY000: Table `t` is not system-versioned select * from (t1 for system_time all join t2 for system_time all) for system_time 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 '' 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 'system_time all' at line 1 drop view v1; drop table t1, t2; 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 c19ad32f6ce..cee22e746d5 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), @@ -3077,7 +3078,10 @@ Item_field::Item_field(THD *thd, Field *f) have_privileges(0), any_privileges(0) { set_field(f); - + /* + field_name and table_name should not point to garbage + if this item is to be reused + */ orig_table_name= table_name; orig_field_name= field_name; with_field= 1; 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 f7847bae89d..7129f362fd2 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 5ce6a6b001c..9ceede71792 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -7436,7 +7436,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) { @@ -7464,7 +7464,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) @@ -8018,7 +8018,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; @@ -8034,7 +8034,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 7b7d34c6bc0..8f1deee3821 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 a7c33cbc504..b6476963727 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); @@ -6134,7 +6135,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 0a12d01596b..4a8f4e71d1d 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; @@ -350,7 +350,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); @@ -382,7 +382,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); } } @@ -926,14 +926,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)) @@ -1015,21 +1017,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; @@ -1071,8 +1075,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 2df740b6811..685b812196a 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 392aa52825e..aa51af80407 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); @@ -3530,7 +3532,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"); @@ -3619,7 +3621,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) || @@ -3636,7 +3638,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. */ @@ -3646,7 +3648,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, @@ -3657,15 +3659,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 6f1d8b815fe..db055eb012e 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; @@ -748,8 +756,8 @@ void LEX::start(THD *thd_arg) name= null_clex_str; event_parse_data= NULL; profile_options= PROFILE_NONE; - nest_level=0 ; - select_lex.nest_level_base= &unit; + nest_level= 0; + 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) { /* @@ -1325,6 +1341,8 @@ int MYSQLlex(YYSTYPE *yylval, THD *thd) token= lex_one_token(yylval, thd); lip->add_digest_token(token, yylval); + SELECT_LEX *curr_sel= thd->lex->current_select; + switch(token) { case WITH: /* @@ -1375,8 +1393,16 @@ int MYSQLlex(YYSTYPE *yylval, THD *thd) } break; case VALUES: - if (thd->lex->current_select->parsing_place == IN_UPDATE_ON_DUP_KEY || - thd->lex->current_select->parsing_place == IN_PART_FUNC) + if (curr_sel && + (curr_sel->parsing_place == BEFORE_OPT_LIST || + curr_sel->parsing_place == AFTER_LIST)) + { + curr_sel->parsing_place= NO_MATTER; + break; + } + if (curr_sel && + (curr_sel->parsing_place == IN_UPDATE_ON_DUP_KEY || + curr_sel->parsing_place == IN_PART_FUNC)) return VALUE_SYM; token= lex_one_token(yylval, thd); lip->add_digest_token(token, yylval); @@ -1391,6 +1417,43 @@ int MYSQLlex(YYSTYPE *yylval, THD *thd) lip->lookahead_token= token; return VALUES; } + case VALUE_SYM: + if (curr_sel && + (curr_sel->parsing_place == BEFORE_OPT_LIST || + curr_sel->parsing_place == AFTER_LIST)) + { + curr_sel->parsing_place= NO_MATTER; + return VALUES; + } + break; + case PARTITION_SYM: + case SELECT_SYM: + case UNION_SYM: + if (curr_sel && + (curr_sel->parsing_place == BEFORE_OPT_LIST || + curr_sel->parsing_place == AFTER_LIST)) + { + curr_sel->parsing_place= NO_MATTER; + } + break; + case left_paren: + if (!curr_sel || + curr_sel->parsing_place != BEFORE_OPT_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; + curr_sel->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 +1951,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 +1962,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 +2247,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 +2256,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 +2297,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 +2351,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 +2412,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 +2478,7 @@ void st_select_lex_node::fast_exclude() // Remove slave structure for (; slave; slave= slave->next) slave->fast_exclude(); - + } @@ -3083,6 +3155,7 @@ LEX::LEX() gtid_domain_static_buffer, initial_gtid_domain_buffer_size, initial_gtid_domain_buffer_size, 0); + unit.slave= &builtin_select; } @@ -3109,12 +3182,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 +3204,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 +3562,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 +3618,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 +3655,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 +3680,23 @@ 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++; + } + first->select_number= 1; + } +} + /* Link table back that was unlinked with unlink_first_table() @@ -3631,10 +3722,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 +3754,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 +4632,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 +4827,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 +5157,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 +5174,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 +5418,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 +5469,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,11 +5505,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); + sel->set_master_unit(last->master_unit()); + DBUG_RETURN(sel); +} /** Checks if we need finish "automatic brackets" mode @@ -6559,7 +6959,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()); @@ -7415,6 +7814,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 != 0)) + { + 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 != 0) + { + 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(0) || + 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) { @@ -7468,10 +8017,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; @@ -7881,3 +8430,221 @@ void st_select_lex::pushdown_cond_into_where_clause(THD *thd, Item *cond, *remaining_cond= cond; } + + +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); + + DBUG_ASSERT(builtin_select.first_inner_unit() == 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", ("'Usual' 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 89e3abe284f..4fc74474d56 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; @@ -1052,6 +1112,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; @@ -1288,6 +1352,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; @@ -2669,7 +2759,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 */ @@ -2779,6 +2870,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; @@ -2818,6 +2912,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 @@ -2872,6 +2968,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; /* @@ -3073,20 +3171,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(); @@ -3124,14 +3226,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); @@ -3165,9 +3343,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; @@ -3736,6 +3913,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); @@ -3744,7 +3922,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); @@ -3753,6 +3930,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 fbcf09758e6..6dc7c195041 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -2004,10 +2004,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)) @@ -2570,23 +2570,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; @@ -2625,7 +2626,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); @@ -3222,7 +3224,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 */ @@ -3265,6 +3267,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 */ @@ -7534,7 +7537,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 @@ -7621,11 +7624,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; } @@ -7646,6 +7645,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) @@ -7657,27 +7657,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); /* @@ -7711,15 +7703,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= @@ -7775,9 +7765,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; } @@ -8068,7 +8059,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(); } @@ -8150,6 +8141,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 @@ -8243,7 +8238,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. @@ -8349,7 +8344,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)"; @@ -8457,7 +8451,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); } @@ -8649,7 +8642,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())) @@ -8659,16 +8652,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()) { @@ -8681,7 +8677,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); } @@ -8717,7 +8713,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); } @@ -9072,7 +9068,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; @@ -9171,7 +9167,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) @@ -9207,7 +9203,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) @@ -9241,7 +9237,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"); @@ -9358,7 +9354,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"); @@ -9400,7 +9396,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); @@ -9491,7 +9488,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 @@ -9522,7 +9519,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"); @@ -10032,6 +10029,8 @@ bool parse_sql(THD *thd, Parser_state *parser_state, ((thd->variables.sql_mode & MODE_ORACLE) ? ORAparse(thd) : MYSQLparse(thd)) != 0; + DBUG_ASSERT(opt_bootstrap | mysql_parse_status || thd->lex->select_stack_top == 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 7d2e1bae741..7fda6198dcf 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 @@ -358,6 +361,8 @@ enum enum_parsing_place IN_ORDER_BY, IN_UPDATE_ON_DUP_KEY, IN_PART_FUNC, + BEFORE_OPT_LIST, + AFTER_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 9672180080e..ac6b1a72337 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()); @@ -1388,13 +1388,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++) @@ -1412,7 +1413,7 @@ bool JOIN::build_explain() get_using_temporary_read_tracker(); } } - return 0; + DBUG_RETURN(0); } @@ -3722,6 +3723,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 @@ -3748,8 +3758,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); } /* @@ -3771,11 +3782,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); } @@ -12618,7 +12629,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 @@ -18430,7 +18442,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)) @@ -24946,7 +24958,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) @@ -25399,8 +25412,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 */ @@ -26054,6 +26068,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 38a13c49278..fb7a023e817 100644 --- a/sql/sql_show.cc +++ b/sql/sql_show.cc @@ -4144,8 +4144,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, @@ -4538,10 +4539,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) { @@ -6746,7 +6747,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; @@ -7725,7 +7726,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); @@ -8220,7 +8222,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, @@ -8257,7 +8259,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) @@ -8317,14 +8319,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(" (")); @@ -8357,7 +8359,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++) { @@ -8388,7 +8390,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++) { @@ -8415,7 +8417,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 448d095c876..1322d86302e 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -4890,7 +4890,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; } @@ -10237,8 +10237,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 e910d48c75c..d1795f9c80f 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 d69156ced9b..b5e3bb4f73d 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 135 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_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,51 @@ 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; + + // fix "main" select + SELECT_LEX *blt= Lex->pop_select(); + DBUG_ASSERT(blt == &Lex->builtin_select); + Lex->push_select(first_select); } - 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); + + 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; + + // fix "main" select + SELECT_LEX *blt= Lex->pop_select(); + DBUG_ASSERT(blt == &Lex->builtin_select); + Lex->push_select(first_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 +5397,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 +6129,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 +6346,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 +6355,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 +6557,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 +6890,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 +6899,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 +7842,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 @@ -7663,11 +7871,14 @@ alter: 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 +7887,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 +7903,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 +7913,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 +7923,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 +7933,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 +7957,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 +8004,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 +8049,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 +8068,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 +8220,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 +8476,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 +8765,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 +8797,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 +8807,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 +8836,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 +8852,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 +8969,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 +8981,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 +9019,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 +9029,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 +9043,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 +9143,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 +9192,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 +9214,347 @@ 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; + + 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; + SELECT_LEX *sel; + //lex->field_list.empty(); + lex->many_values.empty(); + lex->insert_list=0; + if (!(sel= lex->alloc_select(TRUE)) || + lex->push_select(sel)) + MYSQL_YYABORT; + sel->init_select(); + sel->braces= FALSE; // just initialisation + } + values_list + { + LEX *lex=Lex; + $$= lex->pop_select(); // above TVC 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 +9562,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 @@ -9274,59 +9659,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 @@ -11563,10 +11952,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); } ; @@ -11585,11 +11979,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; @@ -11606,6 +12007,8 @@ join_table: USING { MYSQL_YYABORT_UNLESS($1 && $3); + Select->add_joined_table($1); + Select->add_joined_table($3); } '(' using_list ')' { @@ -11616,6 +12019,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); } @@ -11625,6 +12030,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; @@ -11641,6 +12048,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 ')' { @@ -11651,6 +12060,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; @@ -11661,6 +12072,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; @@ -11678,6 +12091,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 ')' { @@ -11689,6 +12104,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())) @@ -11724,42 +12141,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 @@ -11777,289 +12223,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))) + if (!($$= curr_sel->add_table_to_list(lex->thd, + ti, $3, 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(); - 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 - { - Select->set_braces(0); - } - ; - -/* 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 + | '(' + query_expression + ')' opt_for_system_time_clause table_alias_clause { - LEX *lex= Lex; - /* for normal joins, $2 != NULL and end_nested_join() != NULL, - for derived tables, both must equal NULL */ + LEX *lex=Lex; + lex->derived_tables|= DERIVED_SUBQUERY; + $2->first_select()->linkage= DERIVED_TABLE_TYPE; - 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; - } - ; + // 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); -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 */ {} @@ -12190,9 +12413,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) @@ -12359,7 +12587,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: @@ -12483,64 +12711,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: @@ -12550,63 +12749,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); } ; -limit_options: - limit_option +opt_global_limit_clause: + opt_limit_clause { - SELECT_LEX *sel= Select; - sel->select_limit= $1; - sel->offset_limit= 0; - sel->explicit_limit= 1; + Select->explicit_limit= $1.explicit_limit; + Select->select_limit= $1.select_limit; + Select->offset_limit= $1.offset_limit; + } + +limit_options: + limit_option + { + $$.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; } ; @@ -12675,6 +12872,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 */ | '+' @@ -12744,14 +13001,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; @@ -12771,6 +13025,7 @@ procedure_clause: parameters are reduced. */ Lex->expr_allows_subselect= false; + Select->options|= OPTION_PROCEDURE_CLAUSE; } '(' procedure_list ')' { @@ -12851,8 +13106,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: @@ -12898,10 +13166,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; } ; @@ -13118,16 +13391,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_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: @@ -13136,15 +13416,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_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: @@ -13190,35 +13477,47 @@ 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 ')' + { + Lex->current_select->parsing_place= AFTER_LIST; + } + ; + +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: @@ -13328,6 +13627,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; @@ -13336,13 +13637,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; } /* @@ -13352,7 +13654,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: @@ -13398,9 +13707,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 ; @@ -13421,6 +13732,7 @@ delete_part2: | HISTORY_SYM delete_single_table opt_delete_system_time { Lex->last_table()->vers_conditions= Lex->vers_conditions; + Lex->pop_select(); //main select } ; @@ -13443,9 +13755,18 @@ 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 { + /* XXX + 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; @@ -13454,9 +13775,16 @@ 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 { + /* XXX + 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; @@ -13465,6 +13793,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; } ; @@ -13528,10 +13859,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; } @@ -13542,6 +13875,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 } ; @@ -13616,6 +13950,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(); @@ -13623,6 +13959,7 @@ show: show_param { Select->parsing_place= NO_MATTER; + Lex->pop_select(); //main select } ; @@ -13638,7 +13975,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; } @@ -13646,7 +13983,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; } @@ -13654,7 +13991,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; } @@ -13662,7 +13999,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; } @@ -13670,7 +14007,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; } @@ -13720,12 +14057,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; @@ -13767,13 +14105,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; @@ -13834,7 +14172,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; } @@ -13842,7 +14180,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; } @@ -13850,7 +14188,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; } @@ -14066,7 +14404,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; @@ -14080,7 +14418,7 @@ describe: explainable_command { LEX *lex=Lex; - lex->select_lex.options|= SELECT_DESCRIBE; + lex->first_select_lex()->options|= SELECT_DESCRIBE; } ; @@ -14106,6 +14444,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 {} ; @@ -14148,8 +14488,7 @@ flush: lex->type= 0; lex->no_write_to_binlog= $2; } - flush_options - {} + flush_options {} ; flush_options: @@ -14166,6 +14505,7 @@ flush_options: opt_table_list opt_flush_lock {} | flush_options_list + {} ; opt_flush_lock: @@ -14339,9 +14679,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: @@ -14359,6 +14703,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; } ; @@ -14368,6 +14714,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; @@ -14376,6 +14724,7 @@ kill: kill_type kill_option kill_expr { Lex->kill_signal= (killed_state) ($3 | $4); + Lex->pop_select(); //main select } ; @@ -14419,7 +14768,7 @@ use: { LEX *lex=Lex; lex->sql_command=SQLCOM_CHANGE_DB; - lex->select_lex.db= $2; + lex->builtin_select.db= $2; } ; @@ -14436,6 +14785,9 @@ load: $2 == FILETYPE_CSV ? "LOAD DATA" : "LOAD XML"); MYSQL_YYABORT; } + if (lex->main_select_push()) + MYSQL_YYABORT; + mysql_init_select(lex); } load_data_lock opt_local INFILE TEXT_STRING_filesystem { @@ -14462,7 +14814,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: @@ -14854,17 +15210,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_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(); @@ -14893,9 +15253,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)) @@ -15775,14 +16135,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 @@ -15792,6 +16160,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 {} @@ -16173,9 +16544,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: @@ -16206,7 +16581,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); @@ -16240,9 +16615,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 + } ; /* @@ -16250,25 +16629,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) @@ -16276,20 +16666,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"); @@ -16920,219 +17314,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; } - - -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= ""; - } - ; + { $$.unit_type= EXCEPT_TYPE; $$.distinct= 1; } -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; @@ -17140,18 +17342,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; } ; @@ -17239,35 +17431,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, ¬_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; } @@ -17371,11 +17556,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..7dd065d59ab 100644 --- a/sql/sql_yacc_ora.yy +++ b/sql/sql_yacc_ora.yy @@ -186,6 +186,20 @@ void ORAerror(THD *thd, const char *s) LEX_CSTRING name; uint offset; } sp_cursor_name_and_offset; + 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; @@ -231,6 +245,7 @@ void ORAerror(THD *thd, const char *s) 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; @@ -240,7 +255,6 @@ void ORAerror(THD *thd, const char *s) /* enums */ enum enum_sp_suid_behaviour sp_suid; 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; @@ -277,10 +291,10 @@ bool my_yyoverflow(short **a, YYSTYPE **b, size_t *yystacksize); %parse-param { THD *thd } %lex-param { THD *thd } /* - Currently there are 104 shift/reduce conflicts. + Currently there are 99 shift/reduce conflicts. We should not introduce new conflicts any more. */ -%expect 104 +%expect 99 /* Comments for TOKENS. @@ -599,6 +613,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 @@ -1063,7 +1080,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 @@ -1111,7 +1129,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 @@ -1231,9 +1249,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_query_specification + derived_table_list table_reference_list_parens + nested_table_reference_list join_table_parens %type <date_time_type> date_time_type; %type <interval> interval @@ -1276,12 +1293,16 @@ bool my_yyoverflow(short **a, YYSTYPE **b, size_t *yystacksize); UNDERSCORE_CHARSET %type <select_lex> subselect - get_select_lex get_select_lex_derived query_specification - query_term_union_not_ready - query_term_union_ready + table_value_constructor + simple_table + query_primary + query_primary_parens + +%type <select_lex_unit> query_expression_body - select_paren_derived + query_expression + query_expression_unit %type <boolfunc2creator> comp_op @@ -1293,7 +1314,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 @@ -1313,7 +1348,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 @@ -1333,9 +1368,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 @@ -1481,7 +1515,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; @@ -1606,14 +1640,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 } ; @@ -1632,10 +1674,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), @@ -1643,7 +1696,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: @@ -1928,15 +1985,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_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(); /* @@ -1951,7 +2015,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) { @@ -1960,20 +2024,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; /* @@ -1996,8 +2063,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 +2076,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) { @@ -2021,42 +2088,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 + { + if (Lex->main_select_push()) + MYSQL_YYABORT; } - | create_or_replace opt_unique INDEX_SYM opt_if_not_exists ident + 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 { @@ -2064,51 +2158,94 @@ 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->main_select_push()) + MYSQL_YYABORT; if (Lex->add_create_view(thd, $1 | $6, $2, $4, $7)) 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_standalone - { } + { + 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 - { Lex->create_info.set($1); } + { + if (Lex->main_select_push()) + MYSQL_YYABORT; + Lex->create_info.set($1); + } sf_tail_standalone - { } + { + 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); Lex->udf.type= UDFTYPE_AGGREGATE; } udf_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 { @@ -2724,7 +2861,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)); @@ -2815,8 +2952,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 */ @@ -3346,10 +3488,16 @@ raise_stmt: ; signal_stmt: - SIGNAL_SYM signal_value opt_set_signal_information + SIGNAL_SYM { - if (Lex->add_signal_statement(thd, $2)) + if (Lex->main_select_push()) + YYABORT; + } + signal_value opt_set_signal_information + { + if (Lex->add_signal_statement(thd, $3)) MYSQL_YYABORT; + Lex->pop_select(); //main select } ; @@ -3475,9 +3623,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); @@ -3486,6 +3639,7 @@ get_diagnostics: if (Lex->m_sql_cmd == NULL) MYSQL_YYABORT; + Lex->pop_select(); //main select } ; @@ -3666,8 +3820,26 @@ sp_decl_idents: sp_opt_default: /* Empty */ { $$ = NULL; } - | DEFAULT expr { $$ = $2; } - | SET_VAR expr { $$ = $2; } + | DEFAULT + { + if (Lex->main_select_push()) + MYSQL_YYABORT; + } + expr + { + Lex->pop_select(); //main select + $$ = $3; + } + | SET_VAR + { + if (Lex->main_select_push()) + MYSQL_YYABORT; + } + expr + { + Lex->pop_select(); //main select + $$ = $3; + } ; sp_proc_stmt: @@ -3784,10 +3956,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) || @@ -3804,7 +3981,14 @@ sp_proc_stmt_return: ; reset_lex_expr: - { Lex->sphead->reset_lex(thd); } expr { $$= $2; } + { + Lex->sphead->reset_lex(thd); + // will be poped in sp_proc_stmt_exit or sp_proc_stmt_continue + if (Lex->main_select_push()) + MYSQL_YYABORT; + } + expr + { $$= $2; } ; sp_proc_stmt_exit: @@ -3820,12 +4004,14 @@ sp_proc_stmt_exit: } | EXIT_SYM WHEN_SYM reset_lex_expr { + Lex->pop_select(); //main select pushed in reset_lex_expr if (Lex->sp_exit_statement(thd, $3) || Lex->sphead->restore_lex(thd)) MYSQL_YYABORT; } | EXIT_SYM label_ident WHEN_SYM reset_lex_expr { + Lex->pop_select(); //main select pushed in reset_lex_expr if (Lex->sp_exit_statement(thd, &$2, $4) || Lex->sphead->restore_lex(thd)) MYSQL_YYABORT; @@ -3845,12 +4031,14 @@ sp_proc_stmt_continue: } | CONTINUE_SYM WHEN_SYM reset_lex_expr { + Lex->pop_select(); //main select pushed in reset_lex_expr if (Lex->sp_continue_statement(thd, $3) || Lex->sphead->restore_lex(thd)) MYSQL_YYABORT; } | CONTINUE_SYM label_ident WHEN_SYM reset_lex_expr { + Lex->pop_select(); //main select pushed in reset_lex_expr if (Lex->sp_continue_statement(thd, &$2, $4) || Lex->sphead->restore_lex(thd)) MYSQL_YYABORT; @@ -3902,6 +4090,8 @@ assignment_source_expr: { DBUG_ASSERT(thd->free_list == NULL); Lex->sphead->reset_lex(thd, $1); + if (Lex->main_select_push()) + MYSQL_YYABORT; } expr { @@ -3910,6 +4100,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; } @@ -4030,9 +4221,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; @@ -4144,12 +4340,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; } @@ -4173,6 +4375,9 @@ simple_when_clause: WHEN_SYM { Lex->sphead->reset_lex(thd); /* For expr $3 */ + + if (Lex->main_select_push()) + MYSQL_YYABORT; } expr { @@ -4181,6 +4386,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; @@ -4197,12 +4404,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; @@ -4442,6 +4654,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; } @@ -4454,7 +4667,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; @@ -4465,6 +4683,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 */ @@ -4493,8 +4713,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 + { } | labels_declaration_oracle FOR_SYM { @@ -4546,9 +4770,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 @@ -4981,25 +5209,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; @@ -5010,7 +5228,7 @@ create_body: create_like: LIKE table_ident { $$= $2; } - | '(' LIKE table_ident ')' { $$= $3; } + | LEFT_PAREN_LIKE LIKE table_ident ')' { $$= $3; } ; opt_create_select: @@ -5019,23 +5237,51 @@ 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; + + // fix "main" select + SELECT_LEX *blt= Lex->pop_select(); + DBUG_ASSERT(blt == &Lex->builtin_select); + Lex->push_select(first_select); } - 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); + + 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; + + // fix "main" select + SELECT_LEX *blt= Lex->pop_select(); + DBUG_ASSERT(blt == &Lex->builtin_select); + Lex->push_select(first_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: @@ -5126,8 +5372,13 @@ partition_entry: We enter here when opening the frm file to translate partition info string into part_info data structure. */ + if (Lex->main_select_push()) + MYSQL_YYABORT; + } + partition + { + Lex->pop_select(); //main select } - partition {} ; partition: @@ -5742,56 +5993,6 @@ opt_part_option: 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 {} @@ -6009,7 +6210,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 +6219,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 @@ -6195,6 +6396,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 @@ -6462,6 +6670,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 { @@ -6469,13 +6679,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; } @@ -7468,22 +7694,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, - 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 @@ -7495,11 +7723,14 @@ alter: 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 { @@ -7508,6 +7739,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 { @@ -7523,6 +7755,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 @@ -7531,6 +7765,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 { @@ -7538,6 +7775,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 @@ -7546,14 +7785,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 @@ -7561,14 +7809,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 @@ -7600,6 +7856,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 { @@ -7643,15 +7901,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 @@ -7660,6 +7920,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; } ; @@ -7809,18 +8072,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 +8323,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; } @@ -8337,9 +8599,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: @@ -8365,6 +8631,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 { @@ -8373,6 +8641,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 } ; @@ -8401,6 +8670,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(); @@ -8415,6 +8686,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 } ; @@ -8531,6 +8803,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 { @@ -8541,6 +8815,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 } ; @@ -8578,6 +8853,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 { @@ -8586,6 +8863,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 } ; @@ -8599,9 +8877,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; @@ -8695,9 +8977,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: @@ -8740,8 +9026,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 @@ -8764,192 +9050,345 @@ opt_ignore_leaves: 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; + + Lex->sql_command= SQLCOM_SELECT; } ; -select_init: - SELECT_SYM select_options_and_item_list select_init3 - | '(' 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 - | '(' 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; + SELECT_LEX *sel; + //lex->field_list.empty(); + lex->many_values.empty(); + lex->insert_list=0; + if (!(sel= lex->alloc_select(TRUE)) || + lex->push_select(sel)) + MYSQL_YYABORT; + sel->init_select(); + sel->braces= FALSE; // just initialisation + } + values_list + { + LEX *lex=Lex; + $$= lex->pop_select(); // above TVC 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 { - /* - 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_LEX *sel; + LEX *lex= Lex; + if (!(sel= lex->alloc_select(TRUE)) || + lex->push_select(sel)) + MYSQL_YYABORT; + sel->init_select(); + sel->braces= FALSE; } - SELECT_SYM select_options_and_item_list select_part3 - opt_select_lock_type + select_options { - DBUG_ASSERT(Lex->current_select->braces); + Select->parsing_place= SELECT_LIST; } - | '(' select_paren ')' - ; - -select_paren_union_query_term: + 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_union_query_term - 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_union_query_term ')' ; -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 ')' +opt_from_clause: + /* Empty */ + | from_clause + ; + +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); } - 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(); + if ($4) + { + ($4)->set_to($2->fake_select_lex); + } + $$= $2->first_select(); } - | '(' select_paren_derived ')' { $$= $2; } - ; - -select_init3: - opt_table_expression - opt_select_lock_type + | '(' query_primary { - /* Parentheses carry no meaning here */ - Lex->current_select->set_braces(false); + Lex->push_select($2); } - union_clause - | select_part3_union_not_ready - opt_select_lock_type + query_expression_tail ')' { - /* Parentheses carry no meaning here */ - Lex->current_select->set_braces(false); + 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_init3_union_query_term: - 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_noproc - 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(); + + 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(); } ; @@ -8957,18 +9396,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 @@ -9006,59 +9433,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 @@ -11362,10 +11793,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); } ; @@ -11384,11 +11820,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; @@ -11405,6 +11848,8 @@ join_table: USING { MYSQL_YYABORT_UNLESS($1 && $3); + Select->add_joined_table($1); + Select->add_joined_table($3); } '(' using_list ')' { @@ -11415,6 +11860,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); } @@ -11424,6 +11871,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; @@ -11440,6 +11889,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 ')' { @@ -11450,6 +11901,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; @@ -11460,6 +11913,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; @@ -11477,6 +11932,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 ')' { @@ -11488,6 +11945,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())) @@ -11522,40 +11981,70 @@ use_partition: $$= $3; } ; - -/* - 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_table_alias_clause opt_key_definition { SELECT_LEX *sel= Select; sel->table_join_options= 0; - } - table_ident opt_use_partition opt_table_alias opt_key_definition - { - if (!($$= Select->add_table_to_list(thd, $2, $4, + if (!($$= Select->add_table_to_list(thd, $1, $3, 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($$); } ; - /* Represents a flattening of the following rules from the SQL:2003 standard. This sub-rule corresponds to the sub-rule @@ -11573,242 +12062,56 @@ table_primary_ident: */ table_primary_derived: - '(' get_select_lex select_derived_union ')' opt_table_alias + query_primary_parens table_alias_clause { - /* Use $2 instead of Lex->current_select as derived table will - alter value of Lex->current_select. */ - if (!($3 || $5) && $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, $5, 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 ($5 != 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()); - } - /* Represents derived table with WITH clause */ - | '(' get_select_lex subselect_start - with_clause query_expression_body - subselect_end ')' 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, $8, 0, - TL_READ, MDL_SHARED_READ))) + if (!($$= curr_sel->add_table_to_list(lex->thd, + ti, $2, 0, + TL_READ, MDL_SHARED_READ))) MYSQL_YYABORT; - sel->add_joined_table($$); - } - ; - -/* - 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(); - MYSQL_YYABORT; - } - } - | select_derived union_head_non_top - { - if ($1) - { - thd->parse_error(); - MYSQL_YYABORT; - } } - union_list_derived_part2 - | derived_query_specification opt_select_lock_type - | derived_query_specification order_or_limit opt_select_lock_type - | derived_query_specification 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 - { - Select->set_braces(0); - } - ; - -/* 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 + | '(' + query_expression + ')' table_alias_clause { - LEX *lex= Lex; - /* for normal joins, $2 != NULL and end_nested_join() != NULL, - for derived tables, both must equal NULL */ + LEX *lex=Lex; + lex->derived_tables|= DERIVED_SUBQUERY; + $2->first_select()->linkage= DERIVED_TABLE_TYPE; - if (!($$= $1->end_nested_join(lex->thd)) && $2) - MYSQL_YYABORT; - if (!$2 && $$) - { - thd->parse_error(); - MYSQL_YYABORT; - } - } - ; -/* - 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; - } - ; + // 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); -select_derived2: - { - LEX *lex= Lex; - lex->derived_tables|= DERIVED_SUBQUERY; - if (!lex->expr_allows_subselect || - lex->sql_command == (int)SQLCOM_PURGE) - { - thd->parse_error(); - MYSQL_YYABORT; - } - if (lex->current_select->linkage == GLOBAL_OPTIONS_TYPE || - mysql_new_select(lex, 1, NULL)) + Table_ident *ti= new (thd->mem_root) Table_ident($2); + if (ti == 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)) + if (!($$= curr_sel->add_table_to_list(lex->thd, + ti, $4, 0, + TL_READ, MDL_SHARED_READ))) 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: @@ -11940,9 +12243,14 @@ table_alias: | '=' ; -opt_table_alias: +opt_table_alias_clause: /* empty */ { $$=0; } - | table_alias ident + + | table_alias_clause { $$= $1; } + ; + +table_alias_clause: + table_alias ident { $$= (LEX_CSTRING*) thd->memdup(&$2,sizeof(LEX_STRING)); if ($$ == NULL) @@ -12109,7 +12417,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: @@ -12233,64 +12541,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: @@ -12300,63 +12579,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; } ; @@ -12425,6 +12702,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 */ | '+' @@ -12494,14 +12831,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; @@ -12521,6 +12855,7 @@ procedure_clause: parameters are reduced. */ Lex->expr_allows_subselect= false; + Select->options|= OPTION_PROCEDURE_CLAUSE; } '(' procedure_list ')' { @@ -12601,8 +12936,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: @@ -12648,10 +12996,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; } ; @@ -12883,17 +13236,24 @@ insert: { LEX *lex= Lex; lex->sql_command= SQLCOM_INSERT; - lex->duplicates= DUP_ERROR; - mysql_init_select(lex); + lex->duplicates= DUP_ERROR; + if (Lex->main_select_push()) + MYSQL_YYABORT; + mysql_init_select(lex); + lex->current_select->parsing_place= BEFORE_OPT_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: @@ -12902,15 +13262,22 @@ replace: LEX *lex=Lex; lex->sql_command = SQLCOM_REPLACE; lex->duplicates= DUP_REPLACE; - mysql_init_select(lex); + if (Lex->main_select_push()) + MYSQL_YYABORT; + mysql_init_select(lex); + lex->current_select->parsing_place= BEFORE_OPT_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: @@ -12956,35 +13323,47 @@ 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 ')' + { + Lex->current_select->parsing_place= AFTER_LIST; + } + ; + +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: @@ -13094,6 +13473,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; @@ -13102,13 +13483,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; } /* @@ -13118,7 +13500,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: @@ -13164,9 +13553,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(); } opt_delete_options single_multi ; @@ -13185,7 +13576,12 @@ single_multi: } opt_where_clause opt_order_clause delete_limit_clause {} - opt_select_expressions {} + opt_select_expressions + { + if ($6) + Select->order_list= *($6); + Lex->pop_select(); //main select + } | table_wild_list { mysql_init_multi_delete(Lex); @@ -13196,6 +13592,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; } | FROM table_alias_ref_list { @@ -13207,6 +13606,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; } ; @@ -13270,10 +13672,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; } @@ -13284,6 +13688,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 } opt_truncate_table_storage_clause { } ; @@ -13365,6 +13770,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(); @@ -13372,6 +13779,7 @@ show: show_param { Select->parsing_place= NO_MATTER; + Lex->pop_select(); //main select } ; @@ -13387,7 +13795,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; } @@ -13395,7 +13803,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; } @@ -13403,7 +13811,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; } @@ -13411,7 +13819,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; } @@ -13419,7 +13827,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; } @@ -13469,12 +13877,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; @@ -13516,13 +13925,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; @@ -13583,7 +13992,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 +14000,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 +14008,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 +14224,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 +14238,7 @@ describe: explainable_command { LEX *lex=Lex; - lex->select_lex.options|= SELECT_DESCRIBE; + lex->first_select_lex()->options|= SELECT_DESCRIBE; } ; @@ -13855,6 +14264,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 {} ; @@ -13897,8 +14308,7 @@ flush: lex->type= 0; lex->no_write_to_binlog= $2; } - flush_options - {} + flush_options {} ; flush_options: @@ -13915,6 +14325,7 @@ flush_options: opt_table_list opt_flush_lock {} | flush_options_list + {} ; opt_flush_lock: @@ -14070,9 +14481,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: @@ -14090,6 +14505,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; } ; @@ -14099,6 +14516,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; @@ -14107,6 +14526,7 @@ kill: kill_type kill_option kill_expr { Lex->kill_signal= (killed_state) ($3 | $4); + Lex->pop_select(); //main select } ; @@ -14150,7 +14570,7 @@ use: { LEX *lex=Lex; lex->sql_command=SQLCOM_CHANGE_DB; - lex->select_lex.db= $2; + lex->builtin_select.db= $2; } ; @@ -14167,6 +14587,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 { @@ -14193,7 +14615,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: @@ -14597,17 +15023,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_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(); @@ -14636,9 +15066,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)) @@ -15589,14 +16019,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 @@ -15606,6 +16044,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 {} @@ -16038,9 +16479,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: @@ -16071,7 +16516,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); @@ -16105,9 +16550,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 + } ; /* @@ -16115,25 +16564,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) @@ -16141,20 +16601,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"); @@ -16800,83 +17264,16 @@ 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; } - - -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 - ; + { $$.unit_type= EXCEPT_TYPE; $$.distinct= 1; } /* 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; } @@ -16884,110 +17281,10 @@ union_option: | ALL { $$=0; } ; -/* - 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: - query_specification order_or_limit opt_select_lock_type { $$= $1; } - | '(' select_paren_derived ')' union_order_or_limit { $$= $2; } - ; - -query_term_union_ready: - query_specification 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; @@ -16996,18 +17293,8 @@ query_expression_option: | UNIQUE_SYM { 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; } ; @@ -17095,32 +17382,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, ¬_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 - | '(' 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; } @@ -17221,11 +17504,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 cb3eb068e68..116d5bb135b 100644 --- a/sql/table.cc +++ b/sql/table.cc @@ -2689,7 +2689,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()) @@ -4938,13 +4938,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; @@ -4981,7 +4981,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) { @@ -5023,7 +5024,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 */ @@ -5145,7 +5146,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) { @@ -5316,7 +5317,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)) @@ -5483,7 +5485,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); @@ -5675,6 +5677,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); } @@ -5691,14 +5694,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 (;;) { @@ -5869,7 +5872,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"); @@ -5900,8 +5903,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)); @@ -8424,7 +8428,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); @@ -8454,7 +8458,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/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 76032ca80f0..48d29602bf2 100644 --- a/storage/spider/spd_table.cc +++ b/storage/spider/spd_table.cc @@ -9077,8 +9077,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);
participants (1)
-
Oleksandr Byelkin