Commit f260de5c authored by Sergey Petrunya's avatar Sergey Petrunya

MWL#17: Table elimination

- Address review feedback: change expression analyzer used to be a copy-paste
  of ref analyzer. ref analyzer, besides doing ref analysis, also collected 
  info about keys which had sargable predicates. We didn't need that part here.
parent b70cb552
...@@ -233,11 +233,10 @@ void build_eq_deps_for_cond(Table_elimination *te, Equality_module **fdeps, ...@@ -233,11 +233,10 @@ void build_eq_deps_for_cond(Table_elimination *te, Equality_module **fdeps,
uint *and_level, Item *cond, uint *and_level, Item *cond,
table_map usable_tables); table_map usable_tables);
static static
void add_eq_dep(Table_elimination *te, void add_eq_dep(Table_elimination *te, Equality_module **eq_dep,
Equality_module **eq_dep, uint and_level, uint and_level,
Item_func *cond, Field *field, Item_func *cond, Item *left, Item *right,
bool eq_func, Item **value, table_map usable_tables);
uint num_values, table_map usable_tables);
static static
Equality_module *merge_func_deps(Equality_module *start, Equality_module *new_fields, Equality_module *merge_func_deps(Equality_module *start, Equality_module *new_fields,
Equality_module *end, uint and_level); Equality_module *end, uint and_level);
...@@ -314,87 +313,54 @@ void build_eq_deps_for_cond(Table_elimination *te, Equality_module **fdeps, ...@@ -314,87 +313,54 @@ void build_eq_deps_for_cond(Table_elimination *te, Equality_module **fdeps,
if (cond->type() != Item::FUNC_ITEM) if (cond->type() != Item::FUNC_ITEM)
return; return;
Item_func *cond_func= (Item_func*) cond; Item_func *cond_func= (Item_func*) cond;
switch (cond_func->select_optimize()) { Item **args= cond_func->arguments();
case Item_func::OPTIMIZE_NONE: Item *fld;
break;
case Item_func::OPTIMIZE_KEY: switch (cond_func->functype()) {
{ case Item_func::IN_FUNC:
Item **values;
// BETWEEN, IN, NE
if (cond_func->key_item()->real_item()->type() == Item::FIELD_ITEM &&
!(cond_func->used_tables() & OUTER_REF_TABLE_BIT))
{
values= cond_func->arguments()+1;
if (cond_func->functype() == Item_func::NE_FUNC &&
cond_func->arguments()[1]->real_item()->type() == Item::FIELD_ITEM &&
!(cond_func->arguments()[0]->used_tables() & OUTER_REF_TABLE_BIT))
values--;
DBUG_ASSERT(cond_func->functype() != Item_func::IN_FUNC ||
cond_func->argument_count() != 2);
add_eq_dep(te, fdeps, *and_level, cond_func,
((Item_field*)(cond_func->key_item()->real_item()))->field,
0, values,
cond_func->argument_count()-1,
usable_tables);
}
if (cond_func->functype() == Item_func::BETWEEN)
{
values= cond_func->arguments();
for (uint i= 1 ; i < cond_func->argument_count() ; i++)
{ {
Item_field *field_item; if (cond_func->argument_count() == 2)
if (cond_func->arguments()[i]->real_item()->type() == Item::FIELD_ITEM
&&
!(cond_func->arguments()[i]->used_tables() & OUTER_REF_TABLE_BIT))
{ {
field_item= (Item_field *) (cond_func->arguments()[i]->real_item()); add_eq_dep(te, fdeps, *and_level, cond_func, args[0], args[1],
add_eq_dep(te, fdeps, *and_level, cond_func, usable_tables);
field_item->field, 0, values, 1, usable_tables); add_eq_dep(te, fdeps, *and_level, cond_func, args[1], args[0],
} usable_tables);
}
} }
break;
} }
case Item_func::OPTIMIZE_OP: case Item_func::BETWEEN:
{ {
bool equal_func=(cond_func->functype() == Item_func::EQ_FUNC || if (!((Item_func_between*)cond)->negated &&
cond_func->functype() == Item_func::EQUAL_FUNC); args[1]->eq(args[2], ((Item_field*)fld)->field->binary()))
if (cond_func->arguments()[0]->real_item()->type() == Item::FIELD_ITEM &&
!(cond_func->arguments()[0]->used_tables() & OUTER_REF_TABLE_BIT))
{ {
add_eq_dep(te, fdeps, *and_level, cond_func, add_eq_dep(te, fdeps, *and_level, cond_func, args[0], args[1],
((Item_field*)(cond_func->arguments()[0])->real_item())->field, usable_tables);
equal_func, add_eq_dep(te, fdeps, *and_level, cond_func, args[1], args[0],
cond_func->arguments()+1, 1, usable_tables); usable_tables);
} }
if (cond_func->arguments()[1]->real_item()->type() == Item::FIELD_ITEM && break;
cond_func->functype() != Item_func::LIKE_FUNC &&
!(cond_func->arguments()[1]->used_tables() & OUTER_REF_TABLE_BIT))
{
add_eq_dep(te, fdeps, *and_level, cond_func,
((Item_field*)(cond_func->arguments()[1])->real_item())->field,
equal_func,
cond_func->arguments(),1,usable_tables);
} }
case Item_func::EQ_FUNC:
case Item_func::EQUAL_FUNC:
{
add_eq_dep(te, fdeps, *and_level, cond_func, args[0], args[1],
usable_tables);
add_eq_dep(te, fdeps, *and_level, cond_func, args[1], args[0],
usable_tables);
break; break;
} }
case Item_func::OPTIMIZE_NULL: case Item_func::ISNULL_FUNC:
/* column_name IS [NOT] NULL */
if (cond_func->arguments()[0]->real_item()->type() == Item::FIELD_ITEM &&
!(cond_func->used_tables() & OUTER_REF_TABLE_BIT))
{ {
Item *tmp=new Item_null; Item *tmp=new Item_null;
if (unlikely(!tmp)) // Should never be true if (unlikely(!tmp)) // Should never be true
return; return;
add_eq_dep(te, fdeps, *and_level, cond_func, add_eq_dep(te, fdeps, *and_level, cond_func, args[0], args[1],
((Item_field*)(cond_func->arguments()[0])->real_item())->field, usable_tables);
cond_func->functype() == Item_func::ISNULL_FUNC,
&tmp, 1, usable_tables);
}
break; break;
case Item_func::OPTIMIZE_EQUAL: }
case Item_func::MULT_EQUAL_FUNC:
{
Item_equal *item_equal= (Item_equal *) cond; Item_equal *item_equal= (Item_equal *) cond;
Item *const_item= item_equal->get_const(); Item *const_item= item_equal->get_const();
Item_equal_iterator it(*item_equal); Item_equal_iterator it(*item_equal);
...@@ -408,8 +374,8 @@ void build_eq_deps_for_cond(Table_elimination *te, Equality_module **fdeps, ...@@ -408,8 +374,8 @@ void build_eq_deps_for_cond(Table_elimination *te, Equality_module **fdeps,
*/ */
while ((item= it++)) while ((item= it++))
{ {
add_eq_dep(te, fdeps, *and_level, cond_func, item->field, add_eq_dep(te, fdeps, *and_level, cond_func, item, const_item,
TRUE, &const_item, 1, usable_tables); usable_tables);
} }
} }
else else
...@@ -424,12 +390,13 @@ void build_eq_deps_for_cond(Table_elimination *te, Equality_module **fdeps, ...@@ -424,12 +390,13 @@ void build_eq_deps_for_cond(Table_elimination *te, Equality_module **fdeps,
while ((item= fi++)) while ((item= fi++))
{ {
Field *field= item->field; Field *field= item->field;
while ((item= it++)) Item_field *item2;
while ((item2= it++))
{ {
if (!field->eq(item->field)) if (!field->eq(item2->field))
{ {
add_eq_dep(te, fdeps, *and_level, cond_func, field, add_eq_dep(te, fdeps, *and_level, cond_func, item, item2,
TRUE, (Item **) &item, 1, usable_tables); usable_tables);
} }
} }
it.rewind(); it.rewind();
...@@ -437,6 +404,9 @@ void build_eq_deps_for_cond(Table_elimination *te, Equality_module **fdeps, ...@@ -437,6 +404,9 @@ void build_eq_deps_for_cond(Table_elimination *te, Equality_module **fdeps,
} }
break; break;
} }
default:
break;
}
} }
...@@ -567,54 +537,19 @@ Equality_module *merge_func_deps(Equality_module *start, Equality_module *new_fi ...@@ -567,54 +537,19 @@ Equality_module *merge_func_deps(Equality_module *start, Equality_module *new_fi
static static
void add_eq_dep(Table_elimination *te, Equality_module **eq_dep, void add_eq_dep(Table_elimination *te, Equality_module **eq_dep,
uint and_level, Item_func *cond, Field *field, uint and_level, Item_func *cond,
bool eq_func, Item **value, uint num_values, Item *left, Item *right, table_map usable_tables)
table_map usable_tables)
{ {
if (!(field->table->map & usable_tables)) if ((left->used_tables() & usable_tables) &&
return; !(right->used_tables() & RAND_TABLE_BIT) &&
left->real_item()->type() == Item::FIELD_ITEM)
for (uint i=0; i<num_values; i++)
{
if ((value[i])->used_tables() & RAND_TABLE_BIT)
return;
}
/*
Save the following cases:
Field op constant
Field LIKE constant where constant doesn't start with a wildcard
Field = field2 where field2 is in a different table
Field op formula
Field IS NULL
Field IS NOT NULL
Field BETWEEN ...
Field IN ...
*/
/*
We can't always use indexes when comparing a string index to a
number. cmp_type() is checked to allow compare of dates to numbers.
eq_func is NEVER true when num_values > 1
*/
if (!eq_func)
{ {
/* Field *field= ((Item_field*)left->real_item())->field;
Additional optimization: if we're processing "t.key BETWEEN c1 AND c1"
then proceed as if we were processing "t.key = c1".
*/
if ((cond->functype() != Item_func::BETWEEN) ||
((Item_func_between*) cond)->negated ||
!value[0]->eq(value[1], field->binary()))
return;
eq_func= TRUE;
}
if (field->result_type() == STRING_RESULT) if (field->result_type() == STRING_RESULT)
{ {
if ((*value)->result_type() != STRING_RESULT) if (right->result_type() != STRING_RESULT)
{ {
if (field->cmp_type() != (*value)->result_type()) if (field->cmp_type() != right->result_type())
return; return;
} }
else else
...@@ -629,13 +564,13 @@ void add_eq_dep(Table_elimination *te, Equality_module **eq_dep, ...@@ -629,13 +564,13 @@ void add_eq_dep(Table_elimination *te, Equality_module **eq_dep,
} }
} }
DBUG_ASSERT(eq_func);
/* Store possible eq field */ /* Store possible eq field */
(*eq_dep)->type= Module_dep::MODULE_EXPRESSION; //psergey-todo; (*eq_dep)->type= Module_dep::MODULE_EXPRESSION; //psergey-todo;
(*eq_dep)->field= get_field_value(te, field); (*eq_dep)->field= get_field_value(te, field);
(*eq_dep)->expression= *value; (*eq_dep)->expression= right;
(*eq_dep)->level= and_level; (*eq_dep)->level= and_level;
(*eq_dep)++; (*eq_dep)++;
}
} }
...@@ -1150,6 +1085,12 @@ void run_elimination_wave(Table_elimination *te, Module_dep *bound_modules) ...@@ -1150,6 +1085,12 @@ void run_elimination_wave(Table_elimination *te, Module_dep *bound_modules)
{ {
Outer_join_module *outer_join_dep= (Outer_join_module*)bound_modules; Outer_join_module *outer_join_dep= (Outer_join_module*)bound_modules;
mark_as_eliminated(te->join, outer_join_dep->table_list); mark_as_eliminated(te->join, outer_join_dep->table_list);
if (!--te->n_outer_joins)
{
DBUG_PRINT("info", ("Table elimination eliminated everything"
" it theoretically could"));
return;
}
break; break;
} }
case Module_dep::MODULE_MULTI_EQUALITY: case Module_dep::MODULE_MULTI_EQUALITY:
......
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