summaryrefslogtreecommitdiff
path: root/sql/opt_range.cc
diff options
context:
space:
mode:
authorunknown <igor@rurik.mysql.com>2004-10-19 16:07:10 -0700
committerunknown <igor@rurik.mysql.com>2004-10-19 16:07:10 -0700
commita3e71bdbf54163ca8823aabc1c5938e5f593aa32 (patch)
treec4a004a87cda30de2a6a2e8f1edd255d89e8a247 /sql/opt_range.cc
parent24b608b23084f0576bd94066c887b4891d55233d (diff)
parent05933f13f7466a0057b0d5689300ded9101588f8 (diff)
downloadmariadb-git-a3e71bdbf54163ca8823aabc1c5938e5f593aa32.tar.gz
Merge for post-merge fixes for Item_equal patch.
BitKeeper/etc/ignore: auto-union mysql-test/r/range.result: Auto merged mysql-test/r/select.result: Auto merged mysql-test/t/range.test: Auto merged sql/item.cc: Auto merged sql/opt_range.cc: Auto merged sql/opt_sum.cc: Auto merged sql/sql_select.h: Auto merged sql/item.h: Manual merge sql/sql_select.cc: Manual merge
Diffstat (limited to 'sql/opt_range.cc')
-rw-r--r--sql/opt_range.cc260
1 files changed, 176 insertions, 84 deletions
diff --git a/sql/opt_range.cc b/sql/opt_range.cc
index 387537e76ba..1757ef7f864 100644
--- a/sql/opt_range.cc
+++ b/sql/opt_range.cc
@@ -3233,12 +3233,98 @@ QUICK_SELECT_I *TRP_ROR_UNION::make_quick(PARAM *param,
DBUG_RETURN(quick_roru);
}
-/****************************************************************************/
+
+/*
+ Build a SEL_TREE for a simple predicate
+
+ SYNOPSIS
+ get_func_mm_tree()
+ param PARAM from SQL_SELECT::test_quick_select
+ cond_func item for the predicate
+ field field in the predicate
+ value constant in the predicate
+ cmp_type compare type for the field
+
+ RETURN
+ Pointer to thre built tree
+*/
+
+static SEL_TREE *get_func_mm_tree(PARAM *param, Item_func *cond_func,
+ Field *field, Item *value,
+ Item_result cmp_type)
+{
+ SEL_TREE *tree= 0;
+ DBUG_ENTER("get_func_mm_tree");
+
+ switch (cond_func->functype()) {
+ case Item_func::NE_FUNC:
+ tree= get_mm_parts(param, cond_func, field, Item_func::LT_FUNC,
+ value, cmp_type);
+ if (tree)
+ {
+ tree= tree_or(param, tree, get_mm_parts(param, cond_func, field,
+ Item_func::GT_FUNC,
+ value, cmp_type));
+ }
+ break;
+ case Item_func::BETWEEN:
+ tree= get_mm_parts(param, cond_func, field, Item_func::GE_FUNC,
+ cond_func->arguments()[1],cmp_type);
+ if (tree)
+ {
+ tree= tree_and(param, tree, get_mm_parts(param, cond_func, field,
+ Item_func::LE_FUNC,
+ cond_func->arguments()[2],
+ cmp_type));
+ }
+ break;
+ case Item_func::IN_FUNC:
+ {
+ Item_func_in *func=(Item_func_in*) cond_func;
+ tree= get_mm_parts(param, cond_func, field, Item_func::EQ_FUNC,
+ func->arguments()[1], cmp_type);
+ if (tree)
+ {
+ Item **arg, **end;
+ for (arg= func->arguments()+2, end= arg+func->argument_count()-2;
+ arg < end ; arg++)
+ {
+ tree= tree_or(param, tree, get_mm_parts(param, cond_func, field,
+ Item_func::EQ_FUNC,
+ *arg,
+ cmp_type));
+ }
+ }
+ break;
+ }
+ default:
+ {
+ /*
+ Here the function for the following predicates are processed:
+ <, <=, =, >=, >, LIKE, IS NULL, IS NOT NULL.
+ If the predicate is of the form (value op field) it is handled
+ as the equivalent predicate (field rev_op value), e.g.
+ 2 <= a is handled as a >= 2.
+ */
+ Item_func::Functype func_type=
+ (value != cond_func->arguments()[0]) ? cond_func->functype() :
+ ((Item_bool_func2*) cond_func)->rev_functype();
+ tree= get_mm_parts(param, cond_func, field, func_type, value, cmp_type);
+ }
+ }
+
+ DBUG_RETURN(tree);
+
+}
+
/* make a select tree of all keys in condition */
static SEL_TREE *get_mm_tree(PARAM *param,COND *cond)
{
SEL_TREE *tree=0;
+ SEL_TREE *ftree= 0;
+ Item_field *field_item= 0;
+ Item *value;
DBUG_ENTER("get_mm_tree");
if (cond->type() == Item::COND_ITEM)
@@ -3286,9 +3372,12 @@ static SEL_TREE *get_mm_tree(PARAM *param,COND *cond)
DBUG_RETURN(new SEL_TREE(SEL_TREE::IMPOSSIBLE));
}
- table_map ref_tables=cond->used_tables();
+ table_map ref_tables= 0;
+ table_map param_comp= ~(param->prev_tables | param->read_tables |
+ param->current_table);
if (cond->type() != Item::FUNC_ITEM)
{ // Should be a field
+ ref_tables= cond->used_tables();
if ((ref_tables & param->current_table) ||
(ref_tables & ~(param->prev_tables | param->read_tables)))
DBUG_RETURN(0);
@@ -3299,80 +3388,99 @@ static SEL_TREE *get_mm_tree(PARAM *param,COND *cond)
if (cond_func->select_optimize() == Item_func::OPTIMIZE_NONE)
DBUG_RETURN(0); // Can't be calculated
- param->cond= cond;
-
- if (cond_func->functype() == Item_func::BETWEEN)
+ switch (cond_func->functype()) {
+ case Item_func::BETWEEN:
+ if (cond_func->arguments()[0]->type() != Item::FIELD_ITEM)
+ DBUG_RETURN(0);
+ field_item= (Item_field*) (cond_func->arguments()[0]);
+ value= NULL;
+ break;
+ case Item_func::IN_FUNC:
{
+ Item_func_in *func=(Item_func_in*) cond_func;
+ if (func->key_item()->type() != Item::FIELD_ITEM)
+ DBUG_RETURN(0);
+ field_item= (Item_field*) (func->key_item());
+ value= NULL;
+ break;
+ }
+ case Item_func::MULT_EQUAL_FUNC:
+ {
+ Item_equal *item_equal= (Item_equal *) cond;
+ if (!(value= item_equal->get_const()))
+ DBUG_RETURN(0);
+ Item_equal_iterator it(*item_equal);
+ ref_tables= value->used_tables();
+ while ((field_item= it++))
+ {
+ Field *field= field_item->field;
+ Item_result cmp_type= field->cmp_type();
+ if (!((ref_tables | field->table->map) & param_comp))
+ {
+ tree= get_mm_parts(param, cond, field, Item_func::EQ_FUNC,
+ value,cmp_type);
+ ftree= !ftree ? tree : tree_and(param, ftree, tree);
+ }
+ }
+
+ DBUG_RETURN(ftree);
+ }
+ default:
if (cond_func->arguments()[0]->type() == Item::FIELD_ITEM)
{
- Field *field=((Item_field*) (cond_func->arguments()[0]))->field;
- Item_result cmp_type=field->cmp_type();
- DBUG_RETURN(tree_and(param,
- get_mm_parts(param, cond_func, field,
- Item_func::GE_FUNC,
- cond_func->arguments()[1], cmp_type),
- get_mm_parts(param, cond_func, field,
- Item_func::LE_FUNC,
- cond_func->arguments()[2], cmp_type)));
+ field_item= (Item_field*) (cond_func->arguments()[0]);
+ value= cond_func->arg_count > 1 ? cond_func->arguments()[1] : 0;
}
- DBUG_RETURN(0);
+ else if (cond_func->have_rev_func() &&
+ cond_func->arguments()[1]->type() == Item::FIELD_ITEM)
+ {
+ field_item= (Item_field*) (cond_func->arguments()[1]);
+ value= cond_func->arguments()[0];
+ }
+ else
+ DBUG_RETURN(0);
}
- if (cond_func->functype() == Item_func::IN_FUNC)
- { // COND OR
- Item_func_in *func=(Item_func_in*) cond_func;
- if (func->key_item()->type() == Item::FIELD_ITEM)
- {
- Field *field=((Item_field*) (func->key_item()))->field;
- Item_result cmp_type=field->cmp_type();
- tree= get_mm_parts(param,cond_func,field,Item_func::EQ_FUNC,
- func->arguments()[1],cmp_type);
- if (!tree)
- DBUG_RETURN(tree); // Not key field
- for (uint i=2 ; i < func->argument_count(); i++)
+
+ /*
+ If the where condition contains a predicate (ti.field op const),
+ then not only SELL_TREE for this predicate is built, but
+ the trees for the results of substitution of ti.field for
+ each tj.field belonging to the same multiple equality as ti.field
+ are built as well.
+ E.g. for WHERE t1.a=t2.a AND t2.a > 10
+ a SEL_TREE for t2.a > 10 will be built for quick select from t2
+ and
+ a SEL_TREE for t1.a > 10 will be built for quick select from t1.
+ */
+
+ for (uint i= 0; i < cond_func->arg_count; i++)
+ {
+ Item *arg= cond_func->arguments()[i];
+ if (arg != field_item)
+ ref_tables|= arg->used_tables();
+ }
+ Field *field= field_item->field;
+ Item_result cmp_type= field->cmp_type();
+ if (!((ref_tables | field->table->map) & param_comp))
+ ftree= get_func_mm_tree(param, cond_func, field, value, cmp_type);
+ Item_equal *item_equal= field_item->item_equal;
+ if (item_equal)
+ {
+ Item_equal_iterator it(*item_equal);
+ Item_field *item;
+ while ((item= it++))
+ {
+ Field *f= item->field;
+ if (field->eq(f))
+ continue;
+ if (!((ref_tables | f->table->map) & param_comp))
{
- SEL_TREE *new_tree=get_mm_parts(param,cond_func,field,
- Item_func::EQ_FUNC,
- func->arguments()[i],cmp_type);
- tree=tree_or(param,tree,new_tree);
+ tree= get_func_mm_tree(param, cond_func, f, value, cmp_type);
+ ftree= !ftree ? tree : tree_and(param, ftree, tree);
}
- DBUG_RETURN(tree);
- }
- DBUG_RETURN(0); // Can't optimize this IN
- }
-
- if (ref_tables & ~(param->prev_tables | param->read_tables |
- param->current_table))
- DBUG_RETURN(0); // Can't be calculated yet
- if (!(ref_tables & param->current_table))
- DBUG_RETURN(new SEL_TREE(SEL_TREE::MAYBE)); // This may be FALSE or TRUE
-
- /* check field op const */
- /* btw, ft_func's arguments()[0] isn't FIELD_ITEM. SerG*/
- if (cond_func->arguments()[0]->type() == Item::FIELD_ITEM)
- {
- tree= get_mm_parts(param, cond_func,
- ((Item_field*) (cond_func->arguments()[0]))->field,
- cond_func->functype(),
- cond_func->arg_count > 1 ? cond_func->arguments()[1] :
- 0,
- ((Item_field*) (cond_func->arguments()[0]))->field->
- cmp_type());
- }
- /* check const op field */
- if (!tree &&
- cond_func->have_rev_func() &&
- cond_func->arguments()[1]->type() == Item::FIELD_ITEM)
- {
- DBUG_RETURN(get_mm_parts(param, cond_func,
- ((Item_field*)
- (cond_func->arguments()[1]))->field,
- ((Item_bool_func2*) cond_func)->rev_functype(),
- cond_func->arguments()[0],
- ((Item_field*)
- (cond_func->arguments()[1]))->field->cmp_type()
- ));
+ }
}
- DBUG_RETURN(tree);
+ DBUG_RETURN(ftree);
}
@@ -3381,17 +3489,10 @@ get_mm_parts(PARAM *param, COND *cond_func, Field *field,
Item_func::Functype type,
Item *value, Item_result cmp_type)
{
- bool ne_func= FALSE;
DBUG_ENTER("get_mm_parts");
if (field->table != param->table)
DBUG_RETURN(0);
- if (type == Item_func::NE_FUNC)
- {
- ne_func= TRUE;
- type= Item_func::LT_FUNC;
- }
-
KEY_PART *key_part = param->key_parts;
KEY_PART *end = param->key_parts_end;
SEL_TREE *tree=0;
@@ -3429,15 +3530,6 @@ get_mm_parts(PARAM *param, COND *cond_func, Field *field,
}
}
- if (ne_func)
- {
- SEL_TREE *tree2= get_mm_parts(param, cond_func,
- field, Item_func::GT_FUNC,
- value, cmp_type);
- if (tree2)
- tree= tree_or(param,tree,tree2);
- }
-
DBUG_RETURN(tree);
}