Commit 4153259e authored by Igor Babaev's avatar Igor Babaev

Fixed bug #637978.

Fixed a bug in the new code for WL#24 that caused generation of
an invalid index-merge access plan.
parent 9ee08757
...@@ -1360,3 +1360,29 @@ id c1 c2 c3 ...@@ -1360,3 +1360,29 @@ id c1 c2 c3
select * from t1 where (c1=' 100000' or c2=' 2000000') and c3='2'; select * from t1 where (c1=' 100000' or c2=' 2000000') and c3='2';
id c1 c2 c3 id c1 c2 c3
drop table t1; drop table t1;
CREATE TABLE t1 (
a smallint DEFAULT NULL,
pk int NOT NULL AUTO_INCREMENT PRIMARY KEY,
b varchar(10) DEFAULT NULL,
c varchar(64) DEFAULT NULL,
INDEX idx1 (a),
INDEX idx2 (b),
INDEX idx3 (c)
);
SELECT COUNT(*) FROM t1 IGNORE INDEX (idx2,idx3)
WHERE c = 'i' OR b IN ( 'Arkansas' , 'd' , 'pdib' , 'can' ) OR
(pk BETWEEN 120 AND 79 + 255 OR a IN ( 4 , 179 , 1 ) ) AND a > 8 ;
COUNT(*)
5
SELECT COUNT(*) FROM t1
WHERE c = 'i' OR b IN ( 'Arkansas' , 'd' , 'pdib' , 'can' ) OR
(pk BETWEEN 120 AND 79 + 255 OR a IN ( 4 , 179 , 1 ) ) AND a > 8 ;
COUNT(*)
5
EXPLAIN
SELECT COUNT(*) FROM t1
WHERE c = 'i' OR b IN ( 'Arkansas' , 'd' , 'pdib' , 'can' ) OR
(pk BETWEEN 120 AND 79 + 255 OR a IN ( 4 , 179 , 1 ) ) AND a > 8 ;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 index_merge PRIMARY,idx1,idx2,idx3 idx3,idx2,PRIMARY,idx1 67,13,4,3 NULL 8 Using sort_union(idx3,idx2,PRIMARY,idx1); Using where
DROP TABLE t1;
...@@ -1361,4 +1361,30 @@ id c1 c2 c3 ...@@ -1361,4 +1361,30 @@ id c1 c2 c3
select * from t1 where (c1=' 100000' or c2=' 2000000') and c3='2'; select * from t1 where (c1=' 100000' or c2=' 2000000') and c3='2';
id c1 c2 c3 id c1 c2 c3
drop table t1; drop table t1;
CREATE TABLE t1 (
a smallint DEFAULT NULL,
pk int NOT NULL AUTO_INCREMENT PRIMARY KEY,
b varchar(10) DEFAULT NULL,
c varchar(64) DEFAULT NULL,
INDEX idx1 (a),
INDEX idx2 (b),
INDEX idx3 (c)
);
SELECT COUNT(*) FROM t1 IGNORE INDEX (idx2,idx3)
WHERE c = 'i' OR b IN ( 'Arkansas' , 'd' , 'pdib' , 'can' ) OR
(pk BETWEEN 120 AND 79 + 255 OR a IN ( 4 , 179 , 1 ) ) AND a > 8 ;
COUNT(*)
5
SELECT COUNT(*) FROM t1
WHERE c = 'i' OR b IN ( 'Arkansas' , 'd' , 'pdib' , 'can' ) OR
(pk BETWEEN 120 AND 79 + 255 OR a IN ( 4 , 179 , 1 ) ) AND a > 8 ;
COUNT(*)
5
EXPLAIN
SELECT COUNT(*) FROM t1
WHERE c = 'i' OR b IN ( 'Arkansas' , 'd' , 'pdib' , 'can' ) OR
(pk BETWEEN 120 AND 79 + 255 OR a IN ( 4 , 179 , 1 ) ) AND a > 8 ;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 index_merge PRIMARY,idx1,idx2,idx3 idx3,idx2,idx1,PRIMARY 67,13,3,4 NULL 9 Using sort_union(idx3,idx2,idx1,PRIMARY); Using where
DROP TABLE t1;
SET SESSION STORAGE_ENGINE=DEFAULT; SET SESSION STORAGE_ENGINE=DEFAULT;
...@@ -846,7 +846,75 @@ select * from t1 where (c1=' 100000' or c2=' 2000000') and c3='2'; ...@@ -846,7 +846,75 @@ select * from t1 where (c1=' 100000' or c2=' 2000000') and c3='2';
drop table t1; drop table t1;
#
# Bug #637978: invalid index merge access plan causes to wrong results
#
CREATE TABLE t1 (
a smallint DEFAULT NULL,
pk int NOT NULL AUTO_INCREMENT PRIMARY KEY,
b varchar(10) DEFAULT NULL,
c varchar(64) DEFAULT NULL,
INDEX idx1 (a),
INDEX idx2 (b),
INDEX idx3 (c)
);
--disable_query_log
--disable_result_log
INSERT INTO t1 VALUES
(30371,99001,'dl','e'),(3,99002,'Ohio','t'),(9,99003,'Delaware','xb'),
(0,99004,'Pennsylvan','i'),(-199,99005,'y','d'),(0,99006,'with','Rhode Island'),
(3,99007,'km','qkmiimdxbdljsejtsfrvwlrgacinbmfuosflnenlpomkmvbig'),
(22860,99008,'ovqkmiimdx','uovqkmiimdxbdljsejtsfrvwlrgacinbmfuosflnenlpomkmvbig'),
(212,99009,'f','p'),(NULL,99010,'i','k'),(20426,99011,'Vermont','New York'),
(0,99012,'Oregon','w'),(31831,99013,'s','isrcijpuovqkmiimdxbdljsejtsfrvwl'),
(123,99014,'t','p'),(32767,99015,'q','Maine'),
(NULL,99016,'know','qqqpisrcijpuovqkmiimdxbdljsejtsfrvwlrgacinbmfuosflnenlpo'),
(1,99017,'going','North Carolina'),(-717,99018,'ad','Indiana'),
(32767,99019,'Maryland','aa'),(31280,99020,'Nebraska','Colorado'),
(0,99021,'q','Ohio'),
(5989,99022,'rovaadtqqq','lrovaadtqqqpisrcijpuovqkmiimdxbdljsejtsfrvwlrgacinb'),
(89,99023,'n','Pennsylvania'),(0,99024,'Florida','c'),(97,99025,'Maine','y'),
(149,99026,'xaemnl','Idaho'),(NULL,99027,'h','y'),(26276,99028,'going','New York'),
(242,99029,'bdhxaemnlr','sbdhxaemnlrovaadtqqqpisrcijpuovqkmiimdxb'),
(32767,99030,'if','a'),(26581,99031,'Arizona','q'),(45,99032,'ysazsbdhxa','f'),
(0,99033,'qv','s'),(NULL,99034,'Louisiana','lqvfysazsbdhxaemnlrovaadtqqqpisrc'),
(160,99035,'Connecticu','x'),(23241,99036,'lx','q'),(0,99037,'u','Colorado'),
(-19141,99038,'w','h'),(218,99039,'s','uo'),(4,99040,'Montana','Oklahoma'),
(97,99041,'r','ls'),(32767,99042,'q','v'),(7,99043,'mlsuownlnl','did'),
(NULL,99044,'ui','i'),(2,99045,'to','I\'ll'),(0,99046,'Nevada','g'),
(3251,99047,'y','New York'),(0,99048,'wyttuimlsu','you\'re'),
(7,99049,'he','South Carolina'),(32767,99050,'s','right'),
(172,99051,'Arizona','e'),(0,99052,'x','lxmvwyttuimlsuownlnlxklq'),
(NULL,99053,'f','wfjlxmvwyttuimlsuownlnlxklqvfysazs'),(44,99054,'s','n'),
(-17561,99055,'me','wm'),(88,99056,'y','my'),(7313,99057,'jx','New Hampshire'),
(63,99058,'zl','South Carolina'),(9,99059,'ma','Illinois'),
(6,99060,'lamazljxpg','like'),(17021,99061,'x','v'),(0,99062,'New Mexico','j'),
(179,99427,'fliq','because'),
(107,99063,'Virginia','Mississippi'),
(0,99064,'si','to'),(113,99065,'Illinois','Kansas'),(20808,99066,'tsi','d'),
(-15372,99067,'d','vdftsidjtvulamazljxpgiwmbnmwfjlxmvwyttuimlsuownlnl'),
(0,99068,'y','then'),(2,99069,'all','b'),(NULL,99070,'by','Wisconsin'),
(4,99071,'about','right'),(5,99072,'m','s'),(0,99073,'e','Pennsylvania'),
(-28284,99074,'x','f'),(1,99075,'Rhode Isla','Georgia'),(NULL,99076,'p','was'),
(168,99077,'Tennessee','Minnesota'),(18349,99078,'x','Rhode Island'),
(5,99079,'as','d'),(12217,99080,'c','i'),(0,99081,'rdvdxboydm','s'),
(19132,99082,'her','jerdvdxboydmpefbiesqbyyvdftsidjtvulamazljxpgiwmbn'),
(0,99083,'all','jhjerdvdxboydmpefbiesqbyyvdftsidjtvulamazljx'),
(32767,99084,'s','flj'),(-4947,99085,'something','Vermont'),
(0,99086,'cjfljhjerd','Washington');
--enable_query_log
--enable_result_log
SELECT COUNT(*) FROM t1 IGNORE INDEX (idx2,idx3)
WHERE c = 'i' OR b IN ( 'Arkansas' , 'd' , 'pdib' , 'can' ) OR
(pk BETWEEN 120 AND 79 + 255 OR a IN ( 4 , 179 , 1 ) ) AND a > 8 ;
SELECT COUNT(*) FROM t1
WHERE c = 'i' OR b IN ( 'Arkansas' , 'd' , 'pdib' , 'can' ) OR
(pk BETWEEN 120 AND 79 + 255 OR a IN ( 4 , 179 , 1 ) ) AND a > 8 ;
EXPLAIN
SELECT COUNT(*) FROM t1
WHERE c = 'i' OR b IN ( 'Arkansas' , 'd' , 'pdib' , 'can' ) OR
(pk BETWEEN 120 AND 79 + 255 OR a IN ( 4 , 179 , 1 ) ) AND a > 8 ;
DROP TABLE t1;
...@@ -890,10 +890,12 @@ class SEL_IMERGE : public Sql_alloc ...@@ -890,10 +890,12 @@ class SEL_IMERGE : public Sql_alloc
int and_sel_tree(RANGE_OPT_PARAM *param, SEL_TREE *tree, int and_sel_tree(RANGE_OPT_PARAM *param, SEL_TREE *tree,
SEL_IMERGE *new_imerge); SEL_IMERGE *new_imerge);
int or_sel_tree_with_checks(RANGE_OPT_PARAM *param, int or_sel_tree_with_checks(RANGE_OPT_PARAM *param,
uint n_init_trees,
SEL_TREE *new_tree, SEL_TREE *new_tree,
bool is_first_check_pass, bool is_first_check_pass,
bool *is_last_check_pass); bool *is_last_check_pass);
int or_sel_imerge_with_checks(RANGE_OPT_PARAM *param, int or_sel_imerge_with_checks(RANGE_OPT_PARAM *param,
uint n_init_trees,
SEL_IMERGE* imerge, SEL_IMERGE* imerge,
bool is_first_check_pass, bool is_first_check_pass,
bool *is_last_check_pass); bool *is_last_check_pass);
...@@ -1026,6 +1028,7 @@ int SEL_IMERGE::and_sel_tree(RANGE_OPT_PARAM *param, SEL_TREE *tree, ...@@ -1026,6 +1028,7 @@ int SEL_IMERGE::and_sel_tree(RANGE_OPT_PARAM *param, SEL_TREE *tree,
SYNOPSIS SYNOPSIS
or_sel_tree_with_checks() or_sel_tree_with_checks()
param Context info for the operation param Context info for the operation
n_trees Number of trees in this imerge to check for oring
tree SEL_TREE whose range part is to be ored tree SEL_TREE whose range part is to be ored
is_first_check_pass <=> the first call of the function for this imerge is_first_check_pass <=> the first call of the function for this imerge
is_last_check_pass OUT <=> no more calls of the function for this imerge is_last_check_pass OUT <=> no more calls of the function for this imerge
...@@ -1075,14 +1078,14 @@ int SEL_IMERGE::and_sel_tree(RANGE_OPT_PARAM *param, SEL_TREE *tree, ...@@ -1075,14 +1078,14 @@ int SEL_IMERGE::and_sel_tree(RANGE_OPT_PARAM *param, SEL_TREE *tree,
*/ */
int SEL_IMERGE::or_sel_tree_with_checks(RANGE_OPT_PARAM *param, int SEL_IMERGE::or_sel_tree_with_checks(RANGE_OPT_PARAM *param,
uint n_trees,
SEL_TREE *tree, SEL_TREE *tree,
bool is_first_check_pass, bool is_first_check_pass,
bool *is_last_check_pass) bool *is_last_check_pass)
{ {
*is_last_check_pass= TRUE; *is_last_check_pass= TRUE;
for (SEL_TREE** or_tree = trees; SEL_TREE** or_tree = trees;
or_tree != trees_next; for (uint i= 0; i < n_trees; i++, or_tree++)
or_tree++)
{ {
SEL_TREE *result= 0; SEL_TREE *result= 0;
key_map result_keys; key_map result_keys;
...@@ -1152,8 +1155,9 @@ int SEL_IMERGE::or_sel_tree_with_checks(RANGE_OPT_PARAM *param, ...@@ -1152,8 +1155,9 @@ int SEL_IMERGE::or_sel_tree_with_checks(RANGE_OPT_PARAM *param,
Perform OR operation on this imerge and and another imerge Perform OR operation on this imerge and and another imerge
SYNOPSIS SYNOPSIS
or_sel_tree_with_checks() or_sel_imerge_with_checks()
param Context info for the operation param Context info for the operation
n_trees Number of trees in this imerge to check for oring
imerge The second operand of the operation imerge The second operand of the operation
is_first_check_pass <=> the first call of the function for this imerge is_first_check_pass <=> the first call of the function for this imerge
is_last_check_pass OUT <=> no more calls of the function for this imerge is_last_check_pass OUT <=> no more calls of the function for this imerge
...@@ -1176,18 +1180,19 @@ int SEL_IMERGE::or_sel_tree_with_checks(RANGE_OPT_PARAM *param, ...@@ -1176,18 +1180,19 @@ int SEL_IMERGE::or_sel_tree_with_checks(RANGE_OPT_PARAM *param,
*/ */
int SEL_IMERGE::or_sel_imerge_with_checks(RANGE_OPT_PARAM *param, int SEL_IMERGE::or_sel_imerge_with_checks(RANGE_OPT_PARAM *param,
uint n_trees,
SEL_IMERGE* imerge, SEL_IMERGE* imerge,
bool is_first_check_pass, bool is_first_check_pass,
bool *is_last_check_pass) bool *is_last_check_pass)
{ {
*is_last_check_pass= TRUE; *is_last_check_pass= TRUE;
for (SEL_TREE** tree= imerge->trees; SEL_TREE** tree= imerge->trees;
tree != imerge->trees_next; for (uint i= 0; i < n_trees; i++, tree++)
tree++)
{ {
uint rc; uint rc;
bool is_last; bool is_last= TRUE;
rc= or_sel_tree_with_checks(param, *tree, is_first_check_pass, &is_last); rc= or_sel_tree_with_checks(param, n_trees, *tree,
is_first_check_pass, &is_last);
if (!is_last) if (!is_last)
*is_last_check_pass= FALSE; *is_last_check_pass= FALSE;
if (rc) if (rc)
...@@ -1368,7 +1373,7 @@ int imerge_list_or_list(RANGE_OPT_PARAM *param, ...@@ -1368,7 +1373,7 @@ int imerge_list_or_list(RANGE_OPT_PARAM *param,
im1->empty(); im1->empty();
im1->push_back(imerge); im1->push_back(imerge);
rc= imerge->or_sel_imerge_with_checks(param, im2->head(), rc= imerge->or_sel_imerge_with_checks(param, elems, im2->head(),
TRUE, &is_last_check_pass); TRUE, &is_last_check_pass);
if (rc) if (rc)
{ {
...@@ -1386,7 +1391,7 @@ int imerge_list_or_list(RANGE_OPT_PARAM *param, ...@@ -1386,7 +1391,7 @@ int imerge_list_or_list(RANGE_OPT_PARAM *param,
if (new_imerge) if (new_imerge)
{ {
is_last_check_pass= TRUE; is_last_check_pass= TRUE;
rc= new_imerge->or_sel_imerge_with_checks(param, im2->head(), rc= new_imerge->or_sel_imerge_with_checks(param, elems, im2->head(),
FALSE, &is_last_check_pass); FALSE, &is_last_check_pass);
if (!rc) if (!rc)
im1->push_back(new_imerge); im1->push_back(new_imerge);
...@@ -1463,14 +1468,14 @@ int imerge_list_or_tree(RANGE_OPT_PARAM *param, ...@@ -1463,14 +1468,14 @@ int imerge_list_or_tree(RANGE_OPT_PARAM *param,
if (or_tree) if (or_tree)
{ {
uint elems= imerge->trees_next-imerge->trees; uint elems= imerge->trees_next-imerge->trees;
rc= imerge->or_sel_tree_with_checks(param, or_tree, rc= imerge->or_sel_tree_with_checks(param, elems, or_tree,
TRUE, &is_last_check_pass); TRUE, &is_last_check_pass);
if (!is_last_check_pass) if (!is_last_check_pass)
{ {
SEL_IMERGE *new_imerge= new SEL_IMERGE(imerge, elems, param); SEL_IMERGE *new_imerge= new SEL_IMERGE(imerge, elems, param);
if (new_imerge) if (new_imerge)
{ {
rc1= new_imerge->or_sel_tree_with_checks(param, or_tree, rc1= new_imerge->or_sel_tree_with_checks(param, elems, or_tree,
FALSE, &is_last_check_pass); FALSE, &is_last_check_pass);
if (!rc1) if (!rc1)
additional_merges.push_back(new_imerge); additional_merges.push_back(new_imerge);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment