Skip to content

Commit f82b7fd

Browse files
author
Martin Hansson
committed
Bug#18892055: MISSING DATA ON SELECT ... IN WITH JOINS AND INNODB
ENGINE When the inner table of an outer join has a (part of) a where condition pushed to it, this subcondition is deactivated until we have found a row for the table. When we do find a row, the predicate is activated and evaluated, and hence the row may get rejected after all. But the semijoin loose scan algorithm always proceeded as if the row was accepted. Concretely, the QEP_TAB::found_match was unconditionally set to true, when it should be set to true only if 'found' is true. Semi-join loose scan is not easily provoked on the outer table of an outer join, hence the convoluted test case. This conclusion is not easily drawn by reading the documentation, so it has been slightly improved upon. (cherry picked from commit 4dab7d84224c4bf0987cde24cbc2076a348b0389)
1 parent 3a1bbd4 commit f82b7fd

29 files changed

+2235
-15
lines changed

mysql-test/include/subquery_sj.inc

+70
Original file line numberDiff line numberDiff line change
@@ -6837,3 +6837,73 @@ ORDER BY field1
68376837
DROP TABLE t1, t2, t3, t4, t5;
68386838

68396839
# New tests go here.
6840+
6841+
--echo #
6842+
--echo # Bug#18892055: MISSING DATA ON SELECT ... IN WITH JOINS AND INNODB
6843+
--echo # ENGINE
6844+
--echo #
6845+
6846+
CREATE TABLE t1 (
6847+
col_int_key INT,
6848+
pk INT NOT NULL,
6849+
PRIMARY KEY (pk),
6850+
KEY col_int_key (col_int_key)
6851+
) ENGINE = INNODB;
6852+
INSERT INTO t1 VALUES
6853+
( 0, 3 ),
6854+
( 0, 4 ),
6855+
( 3, 1 ),
6856+
( 900000000, 2 ),
6857+
( 1368719360, 5 ),
6858+
( 1922236416, 6 ),
6859+
( 8,7 );
6860+
6861+
CREATE TABLE t2 (
6862+
pk INT NOT NULL,
6863+
col_int INT,
6864+
PRIMARY KEY (pk)
6865+
) ENGINE = INNODB;
6866+
INSERT INTO t2 VALUES
6867+
( 1, 3 ),
6868+
( 2, 2 ),
6869+
( 3, 8 ),
6870+
( 4, 7 );
6871+
6872+
CREATE TABLE t3 (
6873+
col_int_key INT,
6874+
col_int INT,
6875+
KEY (col_int_key)
6876+
) ENGINE = INNODB;
6877+
INSERT INTO t3 VALUES
6878+
( 5, 1 ),
6879+
( -1, -1 ),
6880+
( 300000000, 1 ),
6881+
( 8, 1 );
6882+
6883+
CREATE TABLE t4 ( col_int_key INT ) ENGINE = INNODB;
6884+
INSERT INTO t4 VALUES
6885+
(0),
6886+
(3),
6887+
(8),
6888+
(900000000),
6889+
(1368719360),
6890+
(1922236416);
6891+
6892+
ANALYZE TABLE t1, t2, t3, t4;
6893+
6894+
let $query=
6895+
SELECT *
6896+
FROM t4
6897+
WHERE (col_int_key) IN (
6898+
SELECT t1.col_int_key
6899+
FROM t1 LEFT JOIN ( t2 JOIN t3 ON t3.col_int_key = t2.col_int ) USING ( pk )
6900+
WHERE t3.col_int IS NULL
6901+
)
6902+
ORDER BY col_int_key
6903+
;
6904+
6905+
eval explain $query;
6906+
6907+
eval $query;
6908+
6909+
DROP TABLE t1, t2, t3, t4;

mysql-test/r/subquery_sj_all.result

+85
Original file line numberDiff line numberDiff line change
@@ -12008,4 +12008,89 @@ ORDER BY field1
1200812008
;
1200912009
field1
1201012010
DROP TABLE t1, t2, t3, t4, t5;
12011+
#
12012+
# Bug#18892055: MISSING DATA ON SELECT ... IN WITH JOINS AND INNODB
12013+
# ENGINE
12014+
#
12015+
CREATE TABLE t1 (
12016+
col_int_key INT,
12017+
pk INT NOT NULL,
12018+
PRIMARY KEY (pk),
12019+
KEY col_int_key (col_int_key)
12020+
) ENGINE = INNODB;
12021+
INSERT INTO t1 VALUES
12022+
( 0, 3 ),
12023+
( 0, 4 ),
12024+
( 3, 1 ),
12025+
( 900000000, 2 ),
12026+
( 1368719360, 5 ),
12027+
( 1922236416, 6 ),
12028+
( 8,7 );
12029+
CREATE TABLE t2 (
12030+
pk INT NOT NULL,
12031+
col_int INT,
12032+
PRIMARY KEY (pk)
12033+
) ENGINE = INNODB;
12034+
INSERT INTO t2 VALUES
12035+
( 1, 3 ),
12036+
( 2, 2 ),
12037+
( 3, 8 ),
12038+
( 4, 7 );
12039+
CREATE TABLE t3 (
12040+
col_int_key INT,
12041+
col_int INT,
12042+
KEY (col_int_key)
12043+
) ENGINE = INNODB;
12044+
INSERT INTO t3 VALUES
12045+
( 5, 1 ),
12046+
( -1, -1 ),
12047+
( 300000000, 1 ),
12048+
( 8, 1 );
12049+
CREATE TABLE t4 ( col_int_key INT ) ENGINE = INNODB;
12050+
INSERT INTO t4 VALUES
12051+
(0),
12052+
(3),
12053+
(8),
12054+
(900000000),
12055+
(1368719360),
12056+
(1922236416);
12057+
ANALYZE TABLE t1, t2, t3, t4;
12058+
Table Op Msg_type Msg_text
12059+
test.t1 analyze status OK
12060+
test.t2 analyze status OK
12061+
test.t3 analyze status OK
12062+
test.t4 analyze status OK
12063+
explain SELECT *
12064+
FROM t4
12065+
WHERE (col_int_key) IN (
12066+
SELECT t1.col_int_key
12067+
FROM t1 LEFT JOIN ( t2 JOIN t3 ON t3.col_int_key = t2.col_int ) USING ( pk )
12068+
WHERE t3.col_int IS NULL
12069+
)
12070+
ORDER BY col_int_key
12071+
;
12072+
id select_type table partitions type possible_keys key key_len ref rows filtered Extra
12073+
1 SIMPLE t1 NULL index col_int_key col_int_key 5 NULL 7 85.71 Using index; Using temporary; Using filesort; LooseScan
12074+
1 SIMPLE t2 NULL eq_ref PRIMARY PRIMARY 4 test.t1.pk 1 100.00 NULL
12075+
1 SIMPLE t3 NULL ref col_int_key col_int_key 5 test.t2.col_int 1 25.00 Using where; FirstMatch(t1)
12076+
1 SIMPLE t4 NULL ALL NULL NULL NULL NULL 6 16.67 Using where; Using join buffer (Block Nested Loop)
12077+
Warnings:
12078+
Note 1003 /* select#1 */ select `test`.`t4`.`col_int_key` AS `col_int_key` from `test`.`t4` semi join (`test`.`t1` left join (`test`.`t2` join `test`.`t3`) on(((`test`.`t1`.`pk` = `test`.`t2`.`pk`) and (`test`.`t3`.`col_int_key` = `test`.`t2`.`col_int`)))) where ((`test`.`t4`.`col_int_key` = `test`.`t1`.`col_int_key`) and isnull(`test`.`t3`.`col_int`)) order by `test`.`t4`.`col_int_key`
12079+
SELECT *
12080+
FROM t4
12081+
WHERE (col_int_key) IN (
12082+
SELECT t1.col_int_key
12083+
FROM t1 LEFT JOIN ( t2 JOIN t3 ON t3.col_int_key = t2.col_int ) USING ( pk )
12084+
WHERE t3.col_int IS NULL
12085+
)
12086+
ORDER BY col_int_key
12087+
;
12088+
col_int_key
12089+
0
12090+
3
12091+
8
12092+
900000000
12093+
1368719360
12094+
1922236416
12095+
DROP TABLE t1, t2, t3, t4;
1201112096
set optimizer_switch=default;

mysql-test/r/subquery_sj_all_bka.result

+85
Original file line numberDiff line numberDiff line change
@@ -12014,5 +12014,90 @@ ORDER BY field1
1201412014
;
1201512015
field1
1201612016
DROP TABLE t1, t2, t3, t4, t5;
12017+
#
12018+
# Bug#18892055: MISSING DATA ON SELECT ... IN WITH JOINS AND INNODB
12019+
# ENGINE
12020+
#
12021+
CREATE TABLE t1 (
12022+
col_int_key INT,
12023+
pk INT NOT NULL,
12024+
PRIMARY KEY (pk),
12025+
KEY col_int_key (col_int_key)
12026+
) ENGINE = INNODB;
12027+
INSERT INTO t1 VALUES
12028+
( 0, 3 ),
12029+
( 0, 4 ),
12030+
( 3, 1 ),
12031+
( 900000000, 2 ),
12032+
( 1368719360, 5 ),
12033+
( 1922236416, 6 ),
12034+
( 8,7 );
12035+
CREATE TABLE t2 (
12036+
pk INT NOT NULL,
12037+
col_int INT,
12038+
PRIMARY KEY (pk)
12039+
) ENGINE = INNODB;
12040+
INSERT INTO t2 VALUES
12041+
( 1, 3 ),
12042+
( 2, 2 ),
12043+
( 3, 8 ),
12044+
( 4, 7 );
12045+
CREATE TABLE t3 (
12046+
col_int_key INT,
12047+
col_int INT,
12048+
KEY (col_int_key)
12049+
) ENGINE = INNODB;
12050+
INSERT INTO t3 VALUES
12051+
( 5, 1 ),
12052+
( -1, -1 ),
12053+
( 300000000, 1 ),
12054+
( 8, 1 );
12055+
CREATE TABLE t4 ( col_int_key INT ) ENGINE = INNODB;
12056+
INSERT INTO t4 VALUES
12057+
(0),
12058+
(3),
12059+
(8),
12060+
(900000000),
12061+
(1368719360),
12062+
(1922236416);
12063+
ANALYZE TABLE t1, t2, t3, t4;
12064+
Table Op Msg_type Msg_text
12065+
test.t1 analyze status OK
12066+
test.t2 analyze status OK
12067+
test.t3 analyze status OK
12068+
test.t4 analyze status OK
12069+
explain SELECT *
12070+
FROM t4
12071+
WHERE (col_int_key) IN (
12072+
SELECT t1.col_int_key
12073+
FROM t1 LEFT JOIN ( t2 JOIN t3 ON t3.col_int_key = t2.col_int ) USING ( pk )
12074+
WHERE t3.col_int IS NULL
12075+
)
12076+
ORDER BY col_int_key
12077+
;
12078+
id select_type table partitions type possible_keys key key_len ref rows filtered Extra
12079+
1 SIMPLE t1 NULL index col_int_key col_int_key 5 NULL 7 85.71 Using index; Using temporary; Using filesort; LooseScan
12080+
1 SIMPLE t2 NULL eq_ref PRIMARY PRIMARY 4 test.t1.pk 1 100.00 NULL
12081+
1 SIMPLE t3 NULL ref col_int_key col_int_key 5 test.t2.col_int 1 25.00 Using where; FirstMatch(t1)
12082+
1 SIMPLE t4 NULL ALL NULL NULL NULL NULL 6 16.67 Using where; Using join buffer (Block Nested Loop)
12083+
Warnings:
12084+
Note 1003 /* select#1 */ select `test`.`t4`.`col_int_key` AS `col_int_key` from `test`.`t4` semi join (`test`.`t1` left join (`test`.`t2` join `test`.`t3`) on(((`test`.`t1`.`pk` = `test`.`t2`.`pk`) and (`test`.`t3`.`col_int_key` = `test`.`t2`.`col_int`)))) where ((`test`.`t4`.`col_int_key` = `test`.`t1`.`col_int_key`) and isnull(`test`.`t3`.`col_int`)) order by `test`.`t4`.`col_int_key`
12085+
SELECT *
12086+
FROM t4
12087+
WHERE (col_int_key) IN (
12088+
SELECT t1.col_int_key
12089+
FROM t1 LEFT JOIN ( t2 JOIN t3 ON t3.col_int_key = t2.col_int ) USING ( pk )
12090+
WHERE t3.col_int IS NULL
12091+
)
12092+
ORDER BY col_int_key
12093+
;
12094+
col_int_key
12095+
0
12096+
3
12097+
8
12098+
900000000
12099+
1368719360
12100+
1922236416
12101+
DROP TABLE t1, t2, t3, t4;
1201712102
set optimizer_switch=default;
1201812103
set optimizer_switch=default;

mysql-test/r/subquery_sj_all_bka_nixbnl.result

+85
Original file line numberDiff line numberDiff line change
@@ -12013,5 +12013,90 @@ ORDER BY field1
1201312013
;
1201412014
field1
1201512015
DROP TABLE t1, t2, t3, t4, t5;
12016+
#
12017+
# Bug#18892055: MISSING DATA ON SELECT ... IN WITH JOINS AND INNODB
12018+
# ENGINE
12019+
#
12020+
CREATE TABLE t1 (
12021+
col_int_key INT,
12022+
pk INT NOT NULL,
12023+
PRIMARY KEY (pk),
12024+
KEY col_int_key (col_int_key)
12025+
) ENGINE = INNODB;
12026+
INSERT INTO t1 VALUES
12027+
( 0, 3 ),
12028+
( 0, 4 ),
12029+
( 3, 1 ),
12030+
( 900000000, 2 ),
12031+
( 1368719360, 5 ),
12032+
( 1922236416, 6 ),
12033+
( 8,7 );
12034+
CREATE TABLE t2 (
12035+
pk INT NOT NULL,
12036+
col_int INT,
12037+
PRIMARY KEY (pk)
12038+
) ENGINE = INNODB;
12039+
INSERT INTO t2 VALUES
12040+
( 1, 3 ),
12041+
( 2, 2 ),
12042+
( 3, 8 ),
12043+
( 4, 7 );
12044+
CREATE TABLE t3 (
12045+
col_int_key INT,
12046+
col_int INT,
12047+
KEY (col_int_key)
12048+
) ENGINE = INNODB;
12049+
INSERT INTO t3 VALUES
12050+
( 5, 1 ),
12051+
( -1, -1 ),
12052+
( 300000000, 1 ),
12053+
( 8, 1 );
12054+
CREATE TABLE t4 ( col_int_key INT ) ENGINE = INNODB;
12055+
INSERT INTO t4 VALUES
12056+
(0),
12057+
(3),
12058+
(8),
12059+
(900000000),
12060+
(1368719360),
12061+
(1922236416);
12062+
ANALYZE TABLE t1, t2, t3, t4;
12063+
Table Op Msg_type Msg_text
12064+
test.t1 analyze status OK
12065+
test.t2 analyze status OK
12066+
test.t3 analyze status OK
12067+
test.t4 analyze status OK
12068+
explain SELECT *
12069+
FROM t4
12070+
WHERE (col_int_key) IN (
12071+
SELECT t1.col_int_key
12072+
FROM t1 LEFT JOIN ( t2 JOIN t3 ON t3.col_int_key = t2.col_int ) USING ( pk )
12073+
WHERE t3.col_int IS NULL
12074+
)
12075+
ORDER BY col_int_key
12076+
;
12077+
id select_type table partitions type possible_keys key key_len ref rows filtered Extra
12078+
1 SIMPLE t1 NULL index col_int_key col_int_key 5 NULL 7 85.71 Using index; Using temporary; Using filesort; LooseScan
12079+
1 SIMPLE t2 NULL eq_ref PRIMARY PRIMARY 4 test.t1.pk 1 100.00 NULL
12080+
1 SIMPLE t3 NULL ref col_int_key col_int_key 5 test.t2.col_int 1 25.00 Using where; FirstMatch(t1)
12081+
1 SIMPLE t4 NULL ALL NULL NULL NULL NULL 6 16.67 Using where
12082+
Warnings:
12083+
Note 1003 /* select#1 */ select `test`.`t4`.`col_int_key` AS `col_int_key` from `test`.`t4` semi join (`test`.`t1` left join (`test`.`t2` join `test`.`t3`) on(((`test`.`t1`.`pk` = `test`.`t2`.`pk`) and (`test`.`t3`.`col_int_key` = `test`.`t2`.`col_int`)))) where ((`test`.`t4`.`col_int_key` = `test`.`t1`.`col_int_key`) and isnull(`test`.`t3`.`col_int`)) order by `test`.`t4`.`col_int_key`
12084+
SELECT *
12085+
FROM t4
12086+
WHERE (col_int_key) IN (
12087+
SELECT t1.col_int_key
12088+
FROM t1 LEFT JOIN ( t2 JOIN t3 ON t3.col_int_key = t2.col_int ) USING ( pk )
12089+
WHERE t3.col_int IS NULL
12090+
)
12091+
ORDER BY col_int_key
12092+
;
12093+
col_int_key
12094+
0
12095+
3
12096+
8
12097+
900000000
12098+
1368719360
12099+
1922236416
12100+
DROP TABLE t1, t2, t3, t4;
1201612101
set optimizer_switch=default;
1201712102
set optimizer_switch=default;

0 commit comments

Comments
 (0)