--source include/have_partition.inc --echo # --echo # Bug#18167648: WRONG RESULTS WITH PARTITIONING, INDEX_MERGE AND NO PK --echo # CREATE TABLE t1 ( a smallint, b smallint, c smallint, KEY a (a), KEY b (b) ) ENGINE = MyISAM PARTITION BY HASH (c) PARTITIONS 3; CREATE TABLE t2 (a tinyint) ENGINE = MyISAM; INSERT INTO t2 VALUES (1),(2),(3),(4),(5),(6),(7),(8),(9),(10),(11),(12),(13), (14),(15),(16); SET SESSION optimizer_switch="index_merge=on"; SET SESSION optimizer_switch="index_merge_intersection=on"; SET SESSION optimizer_switch="index_merge_union=off"; SET SESSION optimizer_switch="index_merge_sort_union=off"; INSERT INTO t1 VALUES (1,1,0), (1,1,0), (2,1,0), (2,2,1), (1,1,1), (2,2,4); --echo # Add some rows to make the index_merge_intersect possible INSERT INTO t1 SELECT 1,1,0 FROM t2 A, t2 B; INSERT INTO t1 SELECT 1,1,1 FROM t2 A, t2 B; INSERT INTO t1 SELECT 1,1,2 FROM t2 A, t2 B LIMIT 68; SELECT COUNT(*) FROM t1; ANALYZE TABLE t1; # For plan debugging let $use_optimizer_trace=0; if ($use_optimizer_trace) { SET optimizer_trace="enabled=on"; } EXPLAIN SELECT a,b,c FROM t1 WHERE b = 2 AND a = 2; if ($use_optimizer_trace) { SELECT TRACE FROM INFORMATION_SCHEMA.OPTIMIZER_TRACE; } --echo # Before fix: --echo # (p0 - partition 0, R3 - 3rd record in that partition = offset) --echo # Make 'a' read p0-R3, p1-R1, p1-R3 --echo # Make 'b' read p1-R1, p1-R3 --echo # 'b' will skip p1-R1 since R3 is bigger than R1. # b reads first row from p1 (0x0) # b returns 0x0 from p1 # a reads 3rd row from p0 (0xe) # a read first row from p1 (0x0) # a returns 0xe from p0 # b skips (0xe from p0 > 0x0 from p1) # b reads 3rd row from p1 (0xe) # b returns 0xe from p1 # a skips (0xe from p1 > 0xe from p0) # a returns 0x0 from p1 # a reads 3rd row from p1 (0xe) # a returns 0xe from p1 # MATCH! (0xe from p1 == 0xe from p1) SELECT a,b,c FROM t1 WHERE b = 2 AND a = 2; SET @old_opt_switch = @@session.optimizer_switch; SET SESSION optimizer_switch="index_merge_intersection=off"; --echo # Without index_merge_intersection SELECT a,b,c FROM t1 WHERE b = 2 AND a = 2; EXPLAIN SELECT a,b,c FROM t1 WHERE b = 2 AND a = 2; SET SESSION optimizer_switch="index_merge_union=on"; EXPLAIN SELECT a,b,c FROM t1 WHERE (b = 2 OR a = 2) AND c > 0 AND c < 100; if ($use_optimizer_trace) { SELECT TRACE FROM INFORMATION_SCHEMA.OPTIMIZER_TRACE; } # First there where a bug where index_init() was called with sorted=false :( # Before fix of secondary sort in ha_partition: # b reads first row from p1 (0x0) # b returns 0x0 from p1 # a reads 3rd row from p0 (0xe) # a read first row from p1 (0x0) # a returns 0xe from p0 # b < a in priority queue # b reads 3rd row from p1 (0xe) # b returns 0xe from p1 # Fetch row 0x0 from p1 (2,2,1) # a returns 0x0 frop p1 # Fetch row 0xe from p0 (2,1,0), but is filtered away from evaluate_join_record # a reads 3rd from from p1 (0xe) # a returns 0xe from p1 # Fetch row 0x0 from p1 (2,2,1) (Dup, doh). # Fetch row 0xe from p1 (2,2,4) SELECT a,b,c FROM t1 WHERE (b = 2 OR a = 2) AND c > 0 AND c < 100; SET SESSION optimizer_switch="index_merge_union=off"; SELECT a,b,c FROM t1 WHERE (b = 2 OR a = 2) AND c > 0 AND c < 100; EXPLAIN SELECT a,b,c FROM t1 WHERE (b = 2 OR a = 2) AND c > 0 AND c < 100; SET SESSION optimizer_switch="index_merge_sort_union=on"; EXPLAIN SELECT a,b,c FROM t1 WHERE (b >= 2 OR a >= 2) AND c > 0 AND c < 100; if ($use_optimizer_trace) { SELECT TRACE FROM INFORMATION_SCHEMA.OPTIMIZER_TRACE; SET SESSION optimizer_trace="enabled=off"; } --echo # Not affected, added for completeness... # Verified that it does not demand sorted results, index_init(sorted=false)! SELECT a,b,c FROM t1 WHERE (b >= 2 OR a >= 2) AND c > 0 AND c < 100; SET SESSION optimizer_switch="index_merge_sort_union=off"; SELECT a,b,c FROM t1 WHERE (b >= 2 OR a >= 2) AND c > 0 AND c < 100; EXPLAIN SELECT a,b,c FROM t1 WHERE (b >= 2 OR a >= 2) AND c > 0 AND c < 100; SET @@session.optimizer_switch = @old_opt_switch; DROP TABLE t1, t2;