summaryrefslogtreecommitdiff
path: root/sql/opt_range.cc
diff options
context:
space:
mode:
authorGeorgi Kodinov <kgeorge@mysql.com>2008-10-01 19:49:59 +0300
committerGeorgi Kodinov <kgeorge@mysql.com>2008-10-01 19:49:59 +0300
commitf80fbfa282966db86d771bdb1eab2db4382f7f3e (patch)
tree2a384fb264d7447ce7dec4586f2e3b29b9875378 /sql/opt_range.cc
parent1901da7f517f6f1877990ad004d3b716533e1d3e (diff)
parente59a03616599a84def4a0e6be6aee53d6d618c61 (diff)
downloadmariadb-git-f80fbfa282966db86d771bdb1eab2db4382f7f3e.tar.gz
merge of bug #37943 5.0-bugteam -> 5.1-bugteam
Diffstat (limited to 'sql/opt_range.cc')
-rw-r--r--sql/opt_range.cc76
1 files changed, 74 insertions, 2 deletions
diff --git a/sql/opt_range.cc b/sql/opt_range.cc
index 28ee8af0699..d2f098e710c 100644
--- a/sql/opt_range.cc
+++ b/sql/opt_range.cc
@@ -574,6 +574,7 @@ public:
keys_map.clear_all();
bzero((char*) keys,sizeof(keys));
}
+ SEL_TREE(SEL_TREE *arg, RANGE_OPT_PARAM *param);
/*
Note: there may exist SEL_TREE objects with sel_tree->type=KEY and
keys[i]=0 for all i. (SergeyP: it is not clear whether there is any
@@ -767,6 +768,7 @@ public:
trees_next(trees),
trees_end(trees + PREALLOCED_TREES)
{}
+ SEL_IMERGE (SEL_IMERGE *arg, RANGE_OPT_PARAM *param);
int or_sel_tree(RANGE_OPT_PARAM *param, SEL_TREE *tree);
int or_sel_tree_with_checks(RANGE_OPT_PARAM *param, SEL_TREE *new_tree);
int or_sel_imerge_with_checks(RANGE_OPT_PARAM *param, SEL_IMERGE* imerge);
@@ -883,6 +885,61 @@ int SEL_IMERGE::or_sel_imerge_with_checks(RANGE_OPT_PARAM *param, SEL_IMERGE* im
}
+SEL_TREE::SEL_TREE(SEL_TREE *arg, RANGE_OPT_PARAM *param): Sql_alloc()
+{
+ keys_map= arg->keys_map;
+ type= arg->type;
+ for (int idx= 0; idx < MAX_KEY; idx++)
+ {
+ if ((keys[idx]= arg->keys[idx]))
+ keys[idx]->increment_use_count(1);
+ }
+
+ List_iterator<SEL_IMERGE> it(arg->merges);
+ for (SEL_IMERGE *el= it++; el; el= it++)
+ {
+ SEL_IMERGE *merge= new SEL_IMERGE(el, param);
+ if (!merge || merge->trees == merge->trees_next)
+ {
+ merges.empty();
+ return;
+ }
+ merges.push_back (merge);
+ }
+}
+
+
+SEL_IMERGE::SEL_IMERGE (SEL_IMERGE *arg, RANGE_OPT_PARAM *param) : Sql_alloc()
+{
+ uint elements= (arg->trees_end - arg->trees);
+ if (elements > PREALLOCED_TREES)
+ {
+ uint size= elements * sizeof (SEL_TREE **);
+ if (!(trees= (SEL_TREE **)alloc_root(param->mem_root, size)))
+ goto mem_err;
+ }
+ else
+ trees= &trees_prealloced[0];
+
+ trees_next= trees;
+ trees_end= trees + elements;
+
+ for (SEL_TREE **tree = trees, **arg_tree= arg->trees; tree < trees_end;
+ tree++, arg_tree++)
+ {
+ if (!(*tree= new SEL_TREE(*arg_tree, param)))
+ goto mem_err;
+ }
+
+ return;
+
+mem_err:
+ trees= &trees_prealloced[0];
+ trees_next= trees;
+ trees_end= trees;
+}
+
+
/*
Perform AND operation on two index_merge lists and store result in *im1.
*/
@@ -942,10 +999,23 @@ int imerge_list_or_tree(RANGE_OPT_PARAM *param,
{
SEL_IMERGE *imerge;
List_iterator<SEL_IMERGE> it(*im1);
+ bool tree_used= FALSE;
while ((imerge= it++))
{
- if (imerge->or_sel_tree_with_checks(param, tree))
+ SEL_TREE *or_tree;
+ if (tree_used)
+ {
+ or_tree= new SEL_TREE (tree, param);
+ if (!or_tree ||
+ (or_tree->keys_map.is_clear_all() && or_tree->merges.is_empty()))
+ return FALSE;
+ }
+ else
+ or_tree= tree;
+
+ if (imerge->or_sel_tree_with_checks(param, or_tree))
it.remove();
+ tree_used= TRUE;
}
return im1->is_empty();
}
@@ -5547,7 +5617,9 @@ get_mm_parts(RANGE_OPT_PARAM *param, COND *cond_func, Field *field,
tree->keys_map.set_bit(key_part->key);
}
}
-
+
+ if (tree && tree->merges.is_empty() && tree->keys_map.is_clear_all())
+ tree= NULL;
DBUG_RETURN(tree);
}