Commit f3f9855d authored by unknown's avatar unknown

Bug #32036: EXISTS within a WHERE clause with a UNION

  crashes MySQL 5.122
There was a difference in how UNIONs are handled
on top level and when in sub-query.
Because the rules for sub-queries were syntactically
allowing cases that are not currently supported by
the server we had crashes (this bug) or wrong results
(bug 32051).
Fixed by making the syntax rules for UNIONs match the 
ones at top level.

These rules however do not support nesting UNIONs, e.g.
(SELECT a FROM t1 UNION ALL SELECT b FROM t2) 
 UNION
(SELECT c FROM t3 UNION ALL SELECT d FROM t4)
Supports for statements with nested UNIONs will be
added in a future version.


mysql-test/r/subselect.result:
  Bug #32036: test case
mysql-test/t/subselect.test:
  Bug #32036: test case
sql/sql_yacc.yy:
  Bug #32036: Make the syntax rules for UNIONs in subqueries the same
  as for top level UNIONs.
parent b603746f
......@@ -3558,22 +3558,19 @@ SELECT sql_no_cache * FROM t1 WHERE NOT EXISTS
(SELECT i FROM t1) UNION
(SELECT i FROM t1)
);
i
ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'UNION
(SELECT i FROM t1)
)' at line 3
SELECT * FROM t1
WHERE NOT EXISTS (((SELECT i FROM t1) UNION (SELECT i FROM t1)));
i
ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'UNION (SELECT i FROM t1)))' at line 2
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 MySQL server version for the right syntax to use near 'union (select t12.i from t1 t12))
from t1' at line 1
explain select * from t1 where not exists
((select t11.i from t1 t11) union (select t12.i from t1 t12));
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1 system NULL NULL NULL NULL 0 const row not found
2 SUBQUERY NULL NULL NULL NULL NULL NULL NULL No tables used
3 SUBQUERY NULL NULL NULL NULL NULL NULL NULL no matching row in const table
4 UNION t12 system NULL NULL NULL NULL 0 const row not found
NULL UNION RESULT <union2,4> ALL NULL NULL NULL NULL NULL
ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'union (select t12.i from t1 t12))' at line 2
DROP TABLE t1;
CREATE TABLE t1 (a VARCHAR(250), b INT auto_increment, PRIMARY KEY (b));
insert into t1 (a) values (FLOOR(rand() * 100));
......@@ -4150,4 +4147,26 @@ SELECT ((a1,a2) IN (SELECT * FROM t2 WHERE b2 > 0)) IS NULL FROM t1;
0
0
DROP TABLE t1, t2;
CREATE TABLE t1 (a INT);
CREATE TABLE t2 (a INT);
INSERT INTO t1 VALUES (1),(2);
INSERT INTO t2 VALUES (1),(2);
SELECT 2 FROM t1 WHERE EXISTS ((SELECT 1 FROM t2 WHERE t1.a=t2.a));
2
2
2
EXPLAIN EXTENDED
SELECT 2 FROM t1 WHERE EXISTS ((SELECT 1 FROM t2 WHERE t1.a=t2.a));
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 2 Using where
2 DEPENDENT SUBQUERY t2 ALL NULL NULL NULL NULL 2 Using where
Warnings:
Note 1276 Field or reference 'test.t1.a' of SELECT #2 was resolved in SELECT #1
Note 1003 select 2 AS `2` from `test`.`t1` where exists(select 1 AS `1` from `test`.`t2` where (`test`.`t1`.`a` = `test`.`t2`.`a`))
EXPLAIN EXTENDED
SELECT 2 FROM t1 WHERE EXISTS ((SELECT 1 FROM t2 WHERE t1.a=t2.a) UNION
(SELECT 1 FROM t2 WHERE t1.a = t2.a));
ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'UNION
(SELECT 1 FROM t2 WHERE t1.a = t2.a))' at line 2
DROP TABLE t1,t2;
End of 5.0 tests.
......@@ -2448,12 +2448,16 @@ DROP TABLE t1, t2;
CREATE TABLE t1 (i INT);
(SELECT i FROM t1) UNION (SELECT i FROM t1);
#TODO:not supported
--error ER_PARSE_ERROR
SELECT sql_no_cache * FROM t1 WHERE NOT EXISTS
(
(SELECT i FROM t1) UNION
(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)));
......@@ -2461,7 +2465,9 @@ WHERE NOT EXISTS (((SELECT i FROM t1) UNION (SELECT i FROM t1)));
--error 1064
explain select ((select t11.i from t1 t11) union (select t12.i from t1 t12))
from t1;
#supported
#TODO:not supported
--error ER_PARSE_ERROR
explain select * from t1 where not exists
((select t11.i from t1 t11) union (select t12.i from t1 t12));
......@@ -3002,4 +3008,27 @@ INSERT INTO t2 VALUES (103, 203);
SELECT ((a1,a2) IN (SELECT * FROM t2 WHERE b2 > 0)) IS NULL FROM t1;
DROP TABLE t1, t2;
#
# Bug #32036: EXISTS within a WHERE clause with a UNION crashes MySQL 5.122
#
CREATE TABLE t1 (a INT);
CREATE TABLE t2 (a INT);
INSERT INTO t1 VALUES (1),(2);
INSERT INTO t2 VALUES (1),(2);
SELECT 2 FROM t1 WHERE EXISTS ((SELECT 1 FROM t2 WHERE t1.a=t2.a));
EXPLAIN EXTENDED
SELECT 2 FROM t1 WHERE EXISTS ((SELECT 1 FROM t2 WHERE t1.a=t2.a));
#TODO:not supported
--error ER_PARSE_ERROR
EXPLAIN EXTENDED
SELECT 2 FROM t1 WHERE EXISTS ((SELECT 1 FROM t2 WHERE t1.a=t2.a) UNION
(SELECT 1 FROM t2 WHERE t1.a = t2.a));
DROP TABLE t1,t2;
--echo End of 5.0 tests.
......@@ -1137,7 +1137,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
%type <variable> internal_variable_name
%type <select_lex> subselect subselect_init
%type <select_lex> subselect take_first_select
get_select_lex
%type <boolfunc2creator> comp_op
......@@ -9422,35 +9422,22 @@ union_option:
| ALL { $$=0; }
;
take_first_select: /* empty */
{
$$= Lex->current_select->master_unit()->first_select();
};
subselect:
SELECT_SYM subselect_start subselect_init subselect_end
SELECT_SYM subselect_start select_init2 take_first_select
subselect_end
{
$$= $3;
$$= $4;
}
| '(' subselect_start subselect ')'
{
THD *thd= YYTHD;
/*
note that a local variable can't be used for
$3 as it's used in local variable construction
and some compilers can't guarnatee the order
in which the local variables are initialized.
*/
List_iterator<Item> it($3->item_list);
Item *item;
/*
we must fill the items list for the "derived table".
*/
while ((item= it++))
add_item_to_list(thd, item);
}
union_clause subselect_end { $$= $3; };
subselect_init:
select_init2
{
$$= Lex->current_select->master_unit()->first_select();
};
| '(' subselect_start select_paren take_first_select
subselect_end ')'
{
$$= $4;
};
subselect_start:
{
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment