mirror of
https://github.com/MariaDB/server.git
synced 2025-08-01 03:47:19 +03:00
Bug#21904 (parser problem when using IN with a double "(())")
Before this fix, a IN predicate of the form: "IN (( subselect ))", with two parenthesis, would be evaluated as a single row subselect: if the subselect returns more that 1 row, the statement would fail. The SQL:2003 standard defines a special exception in the specification, and mandates that this particular form of IN predicate shall be equivalent to "IN ( subselect )", which involves a table subquery and works with more than 1 row. This fix implements "IN (( subselect ))", "IN ((( subselect )))" etc as per the SQL:2003 requirement. All the details related to the implementation of this change have been commented in the code, and the relevant sections of the SQL:2003 spec are given for reference, so they are not repeated here. Having access to the spec is a requirement to review in depth this patch. mysql-test/r/subselect.result: Implement IN predicate special exceptions with subselects. mysql-test/t/subselect.test: Implement IN predicate special exceptions with subselects. sql/item_subselect.cc: Implement IN predicate special exceptions with subselects. sql/item_subselect.h: Implement IN predicate special exceptions with subselects. sql/sql_yacc.yy: Implement IN predicate special exceptions with subselects, cleanup.
This commit is contained in:
@ -3592,3 +3592,116 @@ FROM t1) t;
|
||||
COUNT(*)
|
||||
3000
|
||||
DROP TABLE t1,t2;
|
||||
DROP TABLE IF EXISTS t1;
|
||||
DROP TABLE IF EXISTS t2;
|
||||
DROP TABLE IF EXISTS t1xt2;
|
||||
CREATE TABLE t1 (
|
||||
id_1 int(5) NOT NULL,
|
||||
t varchar(4) DEFAULT NULL
|
||||
);
|
||||
CREATE TABLE t2 (
|
||||
id_2 int(5) NOT NULL,
|
||||
t varchar(4) DEFAULT NULL
|
||||
);
|
||||
CREATE TABLE t1xt2 (
|
||||
id_1 int(5) NOT NULL,
|
||||
id_2 int(5) NOT NULL
|
||||
);
|
||||
INSERT INTO t1 VALUES (1, 'a'), (2, 'b'), (3, 'c'), (4, 'd');
|
||||
INSERT INTO t2 VALUES (2, 'bb'), (3, 'cc'), (4, 'dd'), (12, 'aa');
|
||||
INSERT INTO t1xt2 VALUES (2, 2), (3, 3), (4, 4);
|
||||
SELECT DISTINCT t1.id_1 FROM t1 WHERE
|
||||
(12 IN (SELECT t1xt2.id_2 FROM t1xt2 WHERE t1.id_1 = t1xt2.id_1));
|
||||
id_1
|
||||
SELECT DISTINCT t1.id_1 FROM t1 WHERE
|
||||
(12 IN ((SELECT t1xt2.id_2 FROM t1xt2 WHERE t1.id_1 = t1xt2.id_1)));
|
||||
id_1
|
||||
SELECT DISTINCT t1.id_1 FROM t1 WHERE
|
||||
(12 IN (((SELECT t1xt2.id_2 FROM t1xt2 WHERE t1.id_1 = t1xt2.id_1))));
|
||||
id_1
|
||||
SELECT DISTINCT t1.id_1 FROM t1 WHERE
|
||||
(12 NOT IN (SELECT t1xt2.id_2 FROM t1xt2 WHERE t1.id_1 = t1xt2.id_1));
|
||||
id_1
|
||||
1
|
||||
2
|
||||
3
|
||||
4
|
||||
SELECT DISTINCT t1.id_1 FROM t1 WHERE
|
||||
(12 NOT IN ((SELECT t1xt2.id_2 FROM t1xt2 where t1.id_1 = t1xt2.id_1)));
|
||||
id_1
|
||||
1
|
||||
2
|
||||
3
|
||||
4
|
||||
SELECT DISTINCT t1.id_1 FROM t1 WHERE
|
||||
(12 NOT IN (((SELECT t1xt2.id_2 FROM t1xt2 where t1.id_1 = t1xt2.id_1))));
|
||||
id_1
|
||||
1
|
||||
2
|
||||
3
|
||||
4
|
||||
insert INTO t1xt2 VALUES (1, 12);
|
||||
SELECT DISTINCT t1.id_1 FROM t1 WHERE
|
||||
(12 IN (SELECT t1xt2.id_2 FROM t1xt2 WHERE t1.id_1 = t1xt2.id_1));
|
||||
id_1
|
||||
1
|
||||
SELECT DISTINCT t1.id_1 FROM t1 WHERE
|
||||
(12 IN ((SELECT t1xt2.id_2 FROM t1xt2 WHERE t1.id_1 = t1xt2.id_1)));
|
||||
id_1
|
||||
1
|
||||
SELECT DISTINCT t1.id_1 FROM t1 WHERE
|
||||
(12 IN (((SELECT t1xt2.id_2 FROM t1xt2 WHERE t1.id_1 = t1xt2.id_1))));
|
||||
id_1
|
||||
1
|
||||
SELECT DISTINCT t1.id_1 FROM t1 WHERE
|
||||
(12 NOT IN (SELECT t1xt2.id_2 FROM t1xt2 WHERE t1.id_1 = t1xt2.id_1));
|
||||
id_1
|
||||
2
|
||||
3
|
||||
4
|
||||
SELECT DISTINCT t1.id_1 FROM t1 WHERE
|
||||
(12 NOT IN ((SELECT t1xt2.id_2 FROM t1xt2 WHERE t1.id_1 = t1xt2.id_1)));
|
||||
id_1
|
||||
2
|
||||
3
|
||||
4
|
||||
SELECT DISTINCT t1.id_1 FROM t1 WHERE
|
||||
(12 NOT IN (((SELECT t1xt2.id_2 FROM t1xt2 WHERE t1.id_1 = t1xt2.id_1))));
|
||||
id_1
|
||||
2
|
||||
3
|
||||
4
|
||||
insert INTO t1xt2 VALUES (2, 12);
|
||||
SELECT DISTINCT t1.id_1 FROM t1 WHERE
|
||||
(12 IN (SELECT t1xt2.id_2 FROM t1xt2 WHERE t1.id_1 = t1xt2.id_1));
|
||||
id_1
|
||||
1
|
||||
2
|
||||
SELECT DISTINCT t1.id_1 FROM t1 WHERE
|
||||
(12 IN ((SELECT t1xt2.id_2 FROM t1xt2 WHERE t1.id_1 = t1xt2.id_1)));
|
||||
id_1
|
||||
1
|
||||
2
|
||||
SELECT DISTINCT t1.id_1 FROM t1 WHERE
|
||||
(12 IN (((SELECT t1xt2.id_2 FROM t1xt2 WHERE t1.id_1 = t1xt2.id_1))));
|
||||
id_1
|
||||
1
|
||||
2
|
||||
SELECT DISTINCT t1.id_1 FROM t1 WHERE
|
||||
(12 NOT IN (SELECT t1xt2.id_2 FROM t1xt2 WHERE t1.id_1 = t1xt2.id_1));
|
||||
id_1
|
||||
3
|
||||
4
|
||||
SELECT DISTINCT t1.id_1 FROM t1 WHERE
|
||||
(12 NOT IN ((SELECT t1xt2.id_2 FROM t1xt2 WHERE t1.id_1 = t1xt2.id_1)));
|
||||
id_1
|
||||
3
|
||||
4
|
||||
SELECT DISTINCT t1.id_1 FROM t1 WHERE
|
||||
(12 NOT IN (((SELECT t1xt2.id_2 FROM t1xt2 WHERE t1.id_1 = t1xt2.id_1))));
|
||||
id_1
|
||||
3
|
||||
4
|
||||
DROP TABLE t1;
|
||||
DROP TABLE t2;
|
||||
DROP TABLE t1xt2;
|
||||
|
@ -2496,3 +2496,103 @@ SELECT SQL_NO_CACHE COUNT(*)
|
||||
FROM t1) t;
|
||||
|
||||
DROP TABLE t1,t2;
|
||||
|
||||
#
|
||||
# Bug#21904 (parser problem when using IN with a double "(())")
|
||||
#
|
||||
|
||||
--disable_warnings
|
||||
DROP TABLE IF EXISTS t1;
|
||||
DROP TABLE IF EXISTS t2;
|
||||
DROP TABLE IF EXISTS t1xt2;
|
||||
--enable_warnings
|
||||
|
||||
CREATE TABLE t1 (
|
||||
id_1 int(5) NOT NULL,
|
||||
t varchar(4) DEFAULT NULL
|
||||
);
|
||||
|
||||
CREATE TABLE t2 (
|
||||
id_2 int(5) NOT NULL,
|
||||
t varchar(4) DEFAULT NULL
|
||||
);
|
||||
|
||||
CREATE TABLE t1xt2 (
|
||||
id_1 int(5) NOT NULL,
|
||||
id_2 int(5) NOT NULL
|
||||
);
|
||||
|
||||
INSERT INTO t1 VALUES (1, 'a'), (2, 'b'), (3, 'c'), (4, 'd');
|
||||
|
||||
INSERT INTO t2 VALUES (2, 'bb'), (3, 'cc'), (4, 'dd'), (12, 'aa');
|
||||
|
||||
INSERT INTO t1xt2 VALUES (2, 2), (3, 3), (4, 4);
|
||||
|
||||
# subselect returns 0 rows
|
||||
|
||||
SELECT DISTINCT t1.id_1 FROM t1 WHERE
|
||||
(12 IN (SELECT t1xt2.id_2 FROM t1xt2 WHERE t1.id_1 = t1xt2.id_1));
|
||||
|
||||
SELECT DISTINCT t1.id_1 FROM t1 WHERE
|
||||
(12 IN ((SELECT t1xt2.id_2 FROM t1xt2 WHERE t1.id_1 = t1xt2.id_1)));
|
||||
|
||||
SELECT DISTINCT t1.id_1 FROM t1 WHERE
|
||||
(12 IN (((SELECT t1xt2.id_2 FROM t1xt2 WHERE t1.id_1 = t1xt2.id_1))));
|
||||
|
||||
SELECT DISTINCT t1.id_1 FROM t1 WHERE
|
||||
(12 NOT IN (SELECT t1xt2.id_2 FROM t1xt2 WHERE t1.id_1 = t1xt2.id_1));
|
||||
|
||||
SELECT DISTINCT t1.id_1 FROM t1 WHERE
|
||||
(12 NOT IN ((SELECT t1xt2.id_2 FROM t1xt2 where t1.id_1 = t1xt2.id_1)));
|
||||
|
||||
SELECT DISTINCT t1.id_1 FROM t1 WHERE
|
||||
(12 NOT IN (((SELECT t1xt2.id_2 FROM t1xt2 where t1.id_1 = t1xt2.id_1))));
|
||||
|
||||
insert INTO t1xt2 VALUES (1, 12);
|
||||
|
||||
# subselect returns 1 row
|
||||
|
||||
SELECT DISTINCT t1.id_1 FROM t1 WHERE
|
||||
(12 IN (SELECT t1xt2.id_2 FROM t1xt2 WHERE t1.id_1 = t1xt2.id_1));
|
||||
|
||||
SELECT DISTINCT t1.id_1 FROM t1 WHERE
|
||||
(12 IN ((SELECT t1xt2.id_2 FROM t1xt2 WHERE t1.id_1 = t1xt2.id_1)));
|
||||
|
||||
SELECT DISTINCT t1.id_1 FROM t1 WHERE
|
||||
(12 IN (((SELECT t1xt2.id_2 FROM t1xt2 WHERE t1.id_1 = t1xt2.id_1))));
|
||||
|
||||
SELECT DISTINCT t1.id_1 FROM t1 WHERE
|
||||
(12 NOT IN (SELECT t1xt2.id_2 FROM t1xt2 WHERE t1.id_1 = t1xt2.id_1));
|
||||
|
||||
SELECT DISTINCT t1.id_1 FROM t1 WHERE
|
||||
(12 NOT IN ((SELECT t1xt2.id_2 FROM t1xt2 WHERE t1.id_1 = t1xt2.id_1)));
|
||||
|
||||
SELECT DISTINCT t1.id_1 FROM t1 WHERE
|
||||
(12 NOT IN (((SELECT t1xt2.id_2 FROM t1xt2 WHERE t1.id_1 = t1xt2.id_1))));
|
||||
|
||||
insert INTO t1xt2 VALUES (2, 12);
|
||||
|
||||
# subselect returns more than 1 row
|
||||
|
||||
SELECT DISTINCT t1.id_1 FROM t1 WHERE
|
||||
(12 IN (SELECT t1xt2.id_2 FROM t1xt2 WHERE t1.id_1 = t1xt2.id_1));
|
||||
|
||||
SELECT DISTINCT t1.id_1 FROM t1 WHERE
|
||||
(12 IN ((SELECT t1xt2.id_2 FROM t1xt2 WHERE t1.id_1 = t1xt2.id_1)));
|
||||
|
||||
SELECT DISTINCT t1.id_1 FROM t1 WHERE
|
||||
(12 IN (((SELECT t1xt2.id_2 FROM t1xt2 WHERE t1.id_1 = t1xt2.id_1))));
|
||||
|
||||
SELECT DISTINCT t1.id_1 FROM t1 WHERE
|
||||
(12 NOT IN (SELECT t1xt2.id_2 FROM t1xt2 WHERE t1.id_1 = t1xt2.id_1));
|
||||
|
||||
SELECT DISTINCT t1.id_1 FROM t1 WHERE
|
||||
(12 NOT IN ((SELECT t1xt2.id_2 FROM t1xt2 WHERE t1.id_1 = t1xt2.id_1)));
|
||||
|
||||
SELECT DISTINCT t1.id_1 FROM t1 WHERE
|
||||
(12 NOT IN (((SELECT t1xt2.id_2 FROM t1xt2 WHERE t1.id_1 = t1xt2.id_1))));
|
||||
|
||||
DROP TABLE t1;
|
||||
DROP TABLE t2;
|
||||
DROP TABLE t1xt2;
|
||||
|
||||
|
Reference in New Issue
Block a user