Wrong result (extra rows, not grouped) with JOIN, AND in ON condition, multi-part key, GROUP BY, OR in WHERE, MyISAM or Aria
Affects | Status | Importance | Assigned to | Milestone | |
---|---|---|---|---|---|
MariaDB |
Fix Released
|
Medium
|
Oleksandr "Sanja" Byelkin |
Bug Description
The following query
SELECT t2_1.b
FROM t1 JOIN t2 AS t2_1 JOIN t2 AS t2_2
ON (t2_2.b = t2_1.b ) AND (t2_2.c = t2_1.c )
WHERE
( SELECT COUNT(*) FROM t2 ) IS NOT NULL
OR a = t2_1.c
GROUP BY t2_1.b;
on the test data returns multiple rows for some values of t2_1.b, which should not be happening because of GROUP BY.
bzr version-info
revision-id: <email address hidden>
date: 2012-03-28 13:58:14 +0300
build-date: 2012-03-28 19:36:15 +0400
revno: 3481
Notes:
Could not move ON condition under WHERE, the problem goes away.
In the test data t1 contains one row, could not add more -- the problem goes away.
Reproducible with the provided test case on MyISAM or Aria tables, but not InnoDB.
Reproducible with standard optimizer_switch as well as with all OFFs (except for in_to_exists or materialization, as one of them has to be ON to get the query executed).
Reproducible on MariaDB 5.3.5, MariaDB 5.5 revno 3353.
Not reproducible on MariaDB 5.2 revno 3126.
Not reproducible on MySQL 5.1.60, MySQL 5.5 revno 3737, MySQL trunk revno 3706.
EXPLAIN with minimal optimizer switch -- all OFFs except for in_to_exists (wrong result):
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1 system NULL NULL NULL NULL 1 100.00
1 PRIMARY t2_1 index c c 9 NULL 3 100.00 Using where; Using index
1 PRIMARY t2_2 ref c c 9 test.t2_
2 SUBQUERY NULL NULL NULL NULL NULL NULL NULL NULL Select tables optimized away
Warnings:
Note 1003 select `test`.`t2_1`.`b` AS `b` from `test`.`t1` join `test`.`t2` `t2_1` join `test`.`t2` `t2_2` where ((`test`.`t2_2`.`c` = `test`.`t2_1`.`c`) and (`test`.`t2_2`.`b` = `test`.`t2_1`.`b`) and (((select count(0) from `test`.`t2`) is not null) or (`test`.`t2_1`.`c` = 'x'))) group by `test`.`t2_1`.`b`
Minimal optimizer_switch: in_to_exists=on
Full optimizer_switch: index_merge=
Test case:
SET optimizer_switch = 'in_to_exists=on';
CREATE TABLE t1 ( a VARCHAR(1) ) ENGINE=MyISAM;
INSERT INTO t1 VALUES ('x');
CREATE TABLE t2 ( b INT, c VARCHAR(1), KEY (c, b) ) ENGINE=MyISAM;
INSERT INTO t2 VALUES
(4, 'd'),(8, 'g'),(3, 'x'),(3, 'f'),
(0, 'p'),(3, 'j'),(8, 'c');
SELECT t2_1.b
FROM t1 JOIN t2 AS t2_1 JOIN t2 AS t2_2
ON (t2_2.b = t2_1.b ) AND (t2_2.c = t2_1.c )
WHERE
( SELECT COUNT(*) FROM t2 ) IS NOT NULL
OR a = t2_1.c
GROUP BY t2_1.b;
# End of test case
# Expected result:
# b
# --
# 0
# 3
# 4
# 8
# Actual result:
# b
# --
# 8
# 4
# 3
# 8
# 3
# 0
# 3
Related branches
tags: | added: optimizer |
tags: | added: wrong-result |
Changed in maria: | |
status: | New → In Progress |
Changed in maria: | |
status: | In Progress → Fix Committed |
Setting importance to medium for now, due to t1 being 1-row table, looks like an edge case. Please adjust if further analysis shows otherwise.