mirror of
https://github.com/MariaDB/server.git
synced 2025-07-30 16:24:05 +03:00
Fixed bug mdev-7992.
'Not exists' optimization can be used for nested outer joins only if IS NULL predicate from the WHERE condition is activated. So we have to check that all guards that wrap this predicate are in the 'open' state. This patch supports usage of 'Not exists' optimization for any outer join, no matter how it's nested in other outer joins. This patch is also considered as a proper fix for bugs #49322/#58490 and LP #817360.
This commit is contained in:
@ -1870,4 +1870,99 @@ f4
|
||||
NULL
|
||||
NULL
|
||||
DROP TABLE t1,t2,t3,t4,t5;
|
||||
#
|
||||
# MDEV-7992: Nested left joins + 'not exists' optimization
|
||||
#
|
||||
CREATE TABLE t1(
|
||||
K1 INT PRIMARY KEY,
|
||||
Name VARCHAR(15)
|
||||
);
|
||||
INSERT INTO t1 VALUES
|
||||
(1,'T1Row1'), (2,'T1Row2');
|
||||
CREATE TABLE t2(
|
||||
K2 INT PRIMARY KEY,
|
||||
K1r INT,
|
||||
rowTimestamp DATETIME,
|
||||
Event VARCHAR(15)
|
||||
);
|
||||
INSERT INTO t2 VALUES
|
||||
(1, 1, '2015-04-13 10:42:11' ,'T1Row1Event1'),
|
||||
(2, 1, '2015-04-13 10:42:12' ,'T1Row1Event2'),
|
||||
(3, 1, '2015-04-13 10:42:12' ,'T1Row1Event3');
|
||||
SELECT t1a.*, t2a.*,
|
||||
t2i.K2 AS K2B, t2i.K1r AS K1rB,
|
||||
t2i.rowTimestamp AS rowTimestampB, t2i.Event AS EventB
|
||||
FROM
|
||||
t1 t1a JOIN t2 t2a ON t2a.K1r = t1a.K1
|
||||
LEFT JOIN
|
||||
( t1 t1i LEFT JOIN t2 t2i ON t2i.K1r = t1i.K1)
|
||||
ON (t1i.K1 = 1) AND
|
||||
(((t2i.K1r = t1a.K1 AND t2i.rowTimestamp > t2a.rowTimestamp ) OR
|
||||
(t2i.rowTimestamp = t2a.rowTimestamp AND t2i.K2 > t2a.K2))
|
||||
OR (t2i.K2 IS NULL))
|
||||
WHERE
|
||||
t2a.K1r = 1 AND t2i.K2 IS NULL;
|
||||
K1 Name K2 K1r rowTimestamp Event K2B K1rB rowTimestampB EventB
|
||||
1 T1Row1 3 1 2015-04-13 10:42:12 T1Row1Event3 NULL NULL NULL NULL
|
||||
EXPLAIN EXTENDED SELECT t1a.*, t2a.*,
|
||||
t2i.K2 AS K2B, t2i.K1r AS K1rB,
|
||||
t2i.rowTimestamp AS rowTimestampB, t2i.Event AS EventB
|
||||
FROM
|
||||
t1 t1a JOIN t2 t2a ON t2a.K1r = t1a.K1
|
||||
LEFT JOIN
|
||||
( t1 t1i LEFT JOIN t2 t2i ON t2i.K1r = t1i.K1)
|
||||
ON (t1i.K1 = 1) AND
|
||||
(((t2i.K1r = t1a.K1 AND t2i.rowTimestamp > t2a.rowTimestamp ) OR
|
||||
(t2i.rowTimestamp = t2a.rowTimestamp AND t2i.K2 > t2a.K2))
|
||||
OR (t2i.K2 IS NULL))
|
||||
WHERE
|
||||
t2a.K1r = 1 AND t2i.K2 IS NULL;
|
||||
id select_type table type possible_keys key key_len ref rows filtered Extra
|
||||
1 SIMPLE t1a const PRIMARY PRIMARY 4 const 1 100.00
|
||||
1 SIMPLE t2a ALL NULL NULL NULL NULL 3 100.00 Using where
|
||||
1 SIMPLE t1i const PRIMARY PRIMARY 4 const 1 100.00 Using index
|
||||
1 SIMPLE t2i ALL NULL NULL NULL NULL 3 100.00 Using where; Not exists
|
||||
Warnings:
|
||||
Note 1003 select 1 AS `K1`,'T1Row1' AS `Name`,`test`.`t2a`.`K2` AS `K2`,`test`.`t2a`.`K1r` AS `K1r`,`test`.`t2a`.`rowTimestamp` AS `rowTimestamp`,`test`.`t2a`.`Event` AS `Event`,`test`.`t2i`.`K2` AS `K2B`,`test`.`t2i`.`K1r` AS `K1rB`,`test`.`t2i`.`rowTimestamp` AS `rowTimestampB`,`test`.`t2i`.`Event` AS `EventB` from `test`.`t1` `t1a` join `test`.`t2` `t2a` left join (`test`.`t1` `t1i` left join `test`.`t2` `t2i` on((`test`.`t2i`.`K1r` = 1))) on(((`test`.`t1i`.`K1` = 1) and (((`test`.`t2i`.`K1r` = 1) and (`test`.`t2i`.`rowTimestamp` > `test`.`t2a`.`rowTimestamp`)) or ((`test`.`t2i`.`rowTimestamp` = `test`.`t2a`.`rowTimestamp`) and (`test`.`t2i`.`K2` > `test`.`t2a`.`K2`)) or isnull(`test`.`t2i`.`K2`)))) where ((`test`.`t2a`.`K1r` = 1) and isnull(`test`.`t2i`.`K2`))
|
||||
CREATE VIEW v1 AS
|
||||
SELECT t2i.*
|
||||
FROM t1 as t1i LEFT JOIN t2 as t2i ON t2i.K1r = t1i.K1
|
||||
WHERE t1i.K1 = 1 ;
|
||||
SELECT
|
||||
t1a.*, t2a.*, t2b.K2 as K2B, t2b.K1r as K1rB,
|
||||
t2b.rowTimestamp as rowTimestampB, t2b.Event as EventB
|
||||
FROM
|
||||
t1 as t1a JOIN t2 as t2a ON t2a.K1r = t1a.K1
|
||||
LEFT JOIN
|
||||
v1 as t2b
|
||||
ON ((t2b.K1r = t1a.K1 AND t2b.rowTimestamp > t2a.rowTimestamp) OR
|
||||
(t2b.rowTimestamp = t2a.rowTimestamp AND t2b.K2 > t2a.K2))
|
||||
OR (t2b.K2 IS NULL)
|
||||
WHERE
|
||||
t1a.K1 = 1 AND
|
||||
t2b.K2 IS NULL;
|
||||
K1 Name K2 K1r rowTimestamp Event K2B K1rB rowTimestampB EventB
|
||||
1 T1Row1 3 1 2015-04-13 10:42:12 T1Row1Event3 NULL NULL NULL NULL
|
||||
EXPLAIN EXTENDED SELECT
|
||||
t1a.*, t2a.*, t2b.K2 as K2B, t2b.K1r as K1rB,
|
||||
t2b.rowTimestamp as rowTimestampB, t2b.Event as EventB
|
||||
FROM
|
||||
t1 as t1a JOIN t2 as t2a ON t2a.K1r = t1a.K1
|
||||
LEFT JOIN
|
||||
v1 as t2b
|
||||
ON ((t2b.K1r = t1a.K1 AND t2b.rowTimestamp > t2a.rowTimestamp) OR
|
||||
(t2b.rowTimestamp = t2a.rowTimestamp AND t2b.K2 > t2a.K2))
|
||||
OR (t2b.K2 IS NULL)
|
||||
WHERE
|
||||
t1a.K1 = 1 AND
|
||||
t2b.K2 IS NULL;
|
||||
id select_type table type possible_keys key key_len ref rows filtered Extra
|
||||
1 SIMPLE t1a const PRIMARY PRIMARY 4 const 1 100.00
|
||||
1 SIMPLE t2a ALL NULL NULL NULL NULL 3 100.00 Using where
|
||||
1 SIMPLE t1i const PRIMARY PRIMARY 4 const 1 100.00 Using index
|
||||
1 SIMPLE t2i ALL NULL NULL NULL NULL 3 100.00 Using where; Not exists
|
||||
Warnings:
|
||||
Note 1003 select 1 AS `K1`,'T1Row1' AS `Name`,`t2a`.`K2` AS `K2`,`t2a`.`K1r` AS `K1r`,`t2a`.`rowTimestamp` AS `rowTimestamp`,`t2a`.`Event` AS `Event`,`test`.`t2i`.`K2` AS `K2B`,`test`.`t2i`.`K1r` AS `K1rB`,`test`.`t2i`.`rowTimestamp` AS `rowTimestampB`,`test`.`t2i`.`Event` AS `EventB` from `test`.`t1` `t1a` join `test`.`t2` `t2a` left join (`test`.`t1` `t1i` left join `test`.`t2` `t2i` on((`test`.`t2i`.`K1r` = 1))) on(((`test`.`t1i`.`K1` = 1) and (((`test`.`t2i`.`K1r` = 1) and (`test`.`t2i`.`rowTimestamp` > `t2a`.`rowTimestamp`)) or ((`test`.`t2i`.`rowTimestamp` = `t2a`.`rowTimestamp`) and (`test`.`t2i`.`K2` > `t2a`.`K2`)) or isnull(`test`.`t2i`.`K2`)))) where ((`t2a`.`K1r` = 1) and isnull(`test`.`t2i`.`K2`))
|
||||
DROP VIEW v1;
|
||||
DROP TABLE t1,t2;
|
||||
set optimizer_search_depth= @tmp_mdev621;
|
||||
|
Reference in New Issue
Block a user