summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--mysql-test/r/range_vs_index_merge.result26
-rw-r--r--mysql-test/r/range_vs_index_merge_innodb.result26
-rwxr-xr-xmysql-test/t/range_vs_index_merge.test70
-rw-r--r--sql/opt_range.cc39
4 files changed, 143 insertions, 18 deletions
diff --git a/mysql-test/r/range_vs_index_merge.result b/mysql-test/r/range_vs_index_merge.result
index 0563a0e491f..0f9c46f182d 100644
--- a/mysql-test/r/range_vs_index_merge.result
+++ b/mysql-test/r/range_vs_index_merge.result
@@ -1360,3 +1360,29 @@ id c1 c2 c3
select * from t1 where (c1=' 100000' or c2=' 2000000') and c3='2';
id c1 c2 c3
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;
diff --git a/mysql-test/r/range_vs_index_merge_innodb.result b/mysql-test/r/range_vs_index_merge_innodb.result
index dd97415b1dc..2251119996a 100644
--- a/mysql-test/r/range_vs_index_merge_innodb.result
+++ b/mysql-test/r/range_vs_index_merge_innodb.result
@@ -1361,4 +1361,30 @@ id c1 c2 c3
select * from t1 where (c1=' 100000' or c2=' 2000000') and c3='2';
id c1 c2 c3
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;
diff --git a/mysql-test/t/range_vs_index_merge.test b/mysql-test/t/range_vs_index_merge.test
index aa5f4620ffe..f57fced6da6 100755
--- a/mysql-test/t/range_vs_index_merge.test
+++ b/mysql-test/t/range_vs_index_merge.test
@@ -846,7 +846,75 @@ select * from t1 where (c1=' 100000' or c2=' 2000000') and c3='2';
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;
diff --git a/sql/opt_range.cc b/sql/opt_range.cc
index 9fac099855e..1342c1ef331 100644
--- a/sql/opt_range.cc
+++ b/sql/opt_range.cc
@@ -890,10 +890,12 @@ public:
int and_sel_tree(RANGE_OPT_PARAM *param, SEL_TREE *tree,
SEL_IMERGE *new_imerge);
int or_sel_tree_with_checks(RANGE_OPT_PARAM *param,
+ uint n_init_trees,
SEL_TREE *new_tree,
bool is_first_check_pass,
bool *is_last_check_pass);
int or_sel_imerge_with_checks(RANGE_OPT_PARAM *param,
+ uint n_init_trees,
SEL_IMERGE* imerge,
bool is_first_check_pass,
bool *is_last_check_pass);
@@ -1025,7 +1027,8 @@ int SEL_IMERGE::and_sel_tree(RANGE_OPT_PARAM *param, SEL_TREE *tree,
SYNOPSIS
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
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
@@ -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,
+ uint n_trees,
SEL_TREE *tree,
bool is_first_check_pass,
bool *is_last_check_pass)
{
- *is_last_check_pass= TRUE;
- for (SEL_TREE** or_tree = trees;
- or_tree != trees_next;
- or_tree++)
+ *is_last_check_pass= TRUE;
+ SEL_TREE** or_tree = trees;
+ for (uint i= 0; i < n_trees; i++, or_tree++)
{
SEL_TREE *result= 0;
key_map result_keys;
@@ -1116,7 +1119,7 @@ int SEL_IMERGE::or_sel_tree_with_checks(RANGE_OPT_PARAM *param,
(key1)->test_use_count(key1);
}
#endif
- }
+ }
}
}
else if(is_first_check_pass)
@@ -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
SYNOPSIS
- or_sel_tree_with_checks()
- param Context info for the operation
+ or_sel_imerge_with_checks()
+ 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
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
@@ -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,
+ uint n_trees,
SEL_IMERGE* imerge,
bool is_first_check_pass,
bool *is_last_check_pass)
{
*is_last_check_pass= TRUE;
- for (SEL_TREE** tree= imerge->trees;
- tree != imerge->trees_next;
- tree++)
+ SEL_TREE** tree= imerge->trees;
+ for (uint i= 0; i < n_trees; i++, tree++)
{
uint rc;
- bool is_last;
- rc= or_sel_tree_with_checks(param, *tree, is_first_check_pass, &is_last);
+ bool is_last= TRUE;
+ rc= or_sel_tree_with_checks(param, n_trees, *tree,
+ is_first_check_pass, &is_last);
if (!is_last)
*is_last_check_pass= FALSE;
if (rc)
@@ -1368,7 +1373,7 @@ int imerge_list_or_list(RANGE_OPT_PARAM *param,
im1->empty();
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);
if (rc)
{
@@ -1386,7 +1391,7 @@ int imerge_list_or_list(RANGE_OPT_PARAM *param,
if (new_imerge)
{
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);
if (!rc)
im1->push_back(new_imerge);
@@ -1463,14 +1468,14 @@ int imerge_list_or_tree(RANGE_OPT_PARAM *param,
if (or_tree)
{
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);
if (!is_last_check_pass)
{
SEL_IMERGE *new_imerge= new SEL_IMERGE(imerge, elems, param);
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);
if (!rc1)
additional_merges.push_back(new_imerge);