mirror of
https://github.com/MariaDB/server.git
synced 2025-11-30 01:19:40 +01:00
Fixes a scenario where an IN subquery returned the wrong result
because the pushed WHERE clause was not retained for downstream
result filtering. For example:
CREATE TABLE t1 (c1 TEXT, UNIQUE (c1(1)));
INSERT INTO t1 (c1) VALUES ('a');
SELECT 'abc' IN (SELECT c1 FROM t1);
Internally, he 'abc' IN subquery condition becomes the constant
condition:
'abc' = t1.c1 or t1.c1 is null
Prior to this patch, this condition was incorrectly removed when
converting the subquery engine to an index lookup-based engine.
Now eligible conditions are preserved during such engine rewrites.
161 lines
4.3 KiB
Text
161 lines
4.3 KiB
Text
ALTER DATABASE test CHARACTER SET latin1 COLLATE latin1_swedish_ci;
|
|
CREATE TABLE t1 (pk INT AUTO_INCREMENT PRIMARY KEY, a varchar(30000), UNIQUE (a)) ENGINE=innodb;
|
|
INSERT INTO t1 (a) VALUES (20),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL);
|
|
SELECT * FROM t1 WHERE a BETWEEN '1' AND '100';
|
|
pk a
|
|
DROP TABLE t1;
|
|
CREATE TABLE t2 (n BLOB, UNIQUE(n));
|
|
INSERT INTO t2 VALUES (1);
|
|
DELETE FROM t2 WHERE n = 1;
|
|
DROP TABLE t2;
|
|
ALTER DATABASE test CHARACTER SET utf8mb4 COLLATE utf8mb4_uca1400_ai_ci;
|
|
CREATE TABLE t1 (c1 TEXT, UNIQUE (c1(1)));
|
|
SHOW CREATE TABLE t1;
|
|
Table Create Table
|
|
t1 CREATE TABLE `t1` (
|
|
`c1` text DEFAULT NULL,
|
|
UNIQUE KEY `c1` (`c1`(1))
|
|
) ENGINE=MyISAM DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_uca1400_ai_ci
|
|
INSERT INTO t1 (c1) VALUES ('a');
|
|
SELECT 'abc' IN (SELECT c1 FROM t1);
|
|
'abc' IN (SELECT c1 FROM t1)
|
|
0
|
|
EXPLAIN format=json SELECT 'abc' IN (SELECT c1 FROM t1);
|
|
EXPLAIN
|
|
{
|
|
"query_block": {
|
|
"select_id": 1,
|
|
"table": {
|
|
"message": "No tables used"
|
|
},
|
|
"subqueries": [
|
|
{
|
|
"query_block": {
|
|
"select_id": 2,
|
|
"table": {
|
|
"message": "Impossible WHERE noticed after reading const tables"
|
|
}
|
|
}
|
|
}
|
|
]
|
|
}
|
|
}
|
|
SELECT c1 FROM t1 WHERE ('abc' IN (SELECT c1 FROM t1)) IS FALSE;
|
|
c1
|
|
a
|
|
DROP TABLE t1;
|
|
CREATE TABLE t1 (c1 TEXT, c2 TEXT, UNIQUE (c1(1)));
|
|
SHOW CREATE TABLE t1;
|
|
Table Create Table
|
|
t1 CREATE TABLE `t1` (
|
|
`c1` text DEFAULT NULL,
|
|
`c2` text DEFAULT NULL,
|
|
UNIQUE KEY `c1` (`c1`(1))
|
|
) ENGINE=MyISAM DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_uca1400_ai_ci
|
|
INSERT INTO t1 (c1, c2) VALUES ('a','b');
|
|
SELECT ('abc', 'xyz') IN (SELECT c1, c2 FROM t1);
|
|
('abc', 'xyz') IN (SELECT c1, c2 FROM t1)
|
|
0
|
|
EXPLAIN format=json SELECT ('abc', 'xyz') IN (SELECT c1, c2 FROM t1);
|
|
EXPLAIN
|
|
{
|
|
"query_block": {
|
|
"select_id": 1,
|
|
"table": {
|
|
"message": "No tables used"
|
|
},
|
|
"subqueries": [
|
|
{
|
|
"query_block": {
|
|
"select_id": 2,
|
|
"table": {
|
|
"message": "Impossible WHERE noticed after reading const tables"
|
|
}
|
|
}
|
|
}
|
|
]
|
|
}
|
|
}
|
|
SELECT * FROM t1 WHERE (('abc', 'xyz') IN (SELECT c1, c2 FROM t1)) IS FALSE;
|
|
c1 c2
|
|
a b
|
|
DROP TABLE t1;
|
|
CREATE TABLE t1 (c1 TEXT, c2 TEXT, UNIQUE (c1(3)));
|
|
SHOW CREATE TABLE t1;
|
|
Table Create Table
|
|
t1 CREATE TABLE `t1` (
|
|
`c1` text DEFAULT NULL,
|
|
`c2` text DEFAULT NULL,
|
|
UNIQUE KEY `c1` (`c1`(3))
|
|
) ENGINE=MyISAM DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_uca1400_ai_ci
|
|
INSERT INTO t1 (c1, c2) VALUES ('abc','xyz');
|
|
SELECT ('abc', 'xyz') IN (SELECT c1, c2 FROM t1) IS FALSE;
|
|
('abc', 'xyz') IN (SELECT c1, c2 FROM t1) IS FALSE
|
|
0
|
|
EXPLAIN format=json SELECT ('abc', 'xyz') IN (SELECT c1, c2 FROM t1) IS FALSE;
|
|
EXPLAIN
|
|
{
|
|
"query_block": {
|
|
"select_id": 1,
|
|
"table": {
|
|
"message": "No tables used"
|
|
},
|
|
"subqueries": [
|
|
{
|
|
"query_block": {
|
|
"select_id": 2,
|
|
"const_condition": "(convert('abc' using utf8mb4) = 'abc' or 'abc' is null) and (convert('xyz' using utf8mb4) = 'xyz' or 'xyz' is null)",
|
|
"having_condition": "'abc' is null and 'xyz' is null",
|
|
"nested_loop": [
|
|
{
|
|
"table": {
|
|
"table_name": "t1",
|
|
"access_type": "system",
|
|
"rows": 1,
|
|
"filtered": 100
|
|
}
|
|
}
|
|
]
|
|
}
|
|
}
|
|
]
|
|
}
|
|
}
|
|
SELECT * FROM t1 WHERE (('abc', 'xyz') IN (SELECT c1, c2 FROM t1)) IS FALSE;
|
|
c1 c2
|
|
SELECT ('abc', 'xyz') IN (SELECT c1, c2 FROM t1) IS TRUE;
|
|
('abc', 'xyz') IN (SELECT c1, c2 FROM t1) IS TRUE
|
|
1
|
|
EXPLAIN format=json SELECT ('abc', 'xyz') IN (SELECT c1, c2 FROM t1) IS TRUE;
|
|
EXPLAIN
|
|
{
|
|
"query_block": {
|
|
"select_id": 1,
|
|
"table": {
|
|
"message": "No tables used"
|
|
},
|
|
"subqueries": [
|
|
{
|
|
"query_block": {
|
|
"select_id": 2,
|
|
"const_condition": "(convert('abc' using utf8mb4) = 'abc' or 'abc' is null) and (convert('xyz' using utf8mb4) = 'xyz' or 'xyz' is null)",
|
|
"having_condition": "'abc' is null and 'xyz' is null",
|
|
"nested_loop": [
|
|
{
|
|
"table": {
|
|
"table_name": "t1",
|
|
"access_type": "system",
|
|
"rows": 1,
|
|
"filtered": 100
|
|
}
|
|
}
|
|
]
|
|
}
|
|
}
|
|
]
|
|
}
|
|
}
|
|
SELECT * FROM t1 WHERE (('abc', 'xyz') IN (SELECT c1, c2 FROM t1)) IS TRUE;
|
|
c1 c2
|
|
abc xyz
|
|
DROP TABLE t1;
|