Commit 083acc29 authored by serg@serg.mylan's avatar serg@serg.mylan

BETWEEN bug fix: non-const expressions on both ends

parent df8b7799
...@@ -240,7 +240,7 @@ t2 range x x 5 NULL 4 Using where ...@@ -240,7 +240,7 @@ t2 range x x 5 NULL 4 Using where
explain select * from t1, t1 t2 where t1.y = 2 and t2.x between t1.y-1 and t1.y+1; explain select * from t1, t1 t2 where t1.y = 2 and t2.x between t1.y-1 and t1.y+1;
table type possible_keys key key_len ref rows Extra table type possible_keys key key_len ref rows Extra
t1 ref y y 5 const 1 Using where t1 ref y y 5 const 1 Using where
t2 ALL x NULL NULL NULL 9 Using where t2 ALL x NULL NULL NULL 9 Range checked for each record (index map: 1)
explain select * from t1, t1 t2 where t1.y = 2 and t2.x >= t1.y-1 and t2.x <= t1.y+1; explain select * from t1, t1 t2 where t1.y = 2 and t2.x >= t1.y-1 and t2.x <= t1.y+1;
table type possible_keys key key_len ref rows Extra table type possible_keys key key_len ref rows Extra
t1 ref y y 5 const 1 Using where t1 ref y y 5 const 1 Using where
......
...@@ -1425,28 +1425,34 @@ merge_key_fields(KEY_FIELD *start,KEY_FIELD *new_fields,KEY_FIELD *end, ...@@ -1425,28 +1425,34 @@ merge_key_fields(KEY_FIELD *start,KEY_FIELD *new_fields,KEY_FIELD *end,
static void static void
add_key_field(KEY_FIELD **key_fields,uint and_level, add_key_field(KEY_FIELD **key_fields,uint and_level,
Field *field,bool eq_func,Item *value, Field *field,bool eq_func,Item **value, uint num_values,
table_map usable_tables) table_map usable_tables)
{ {
bool exists_optimize=0; bool exists_optimize=0;
if (!(field->flags & PART_KEY_FLAG)) if (!(field->flags & PART_KEY_FLAG))
{ {
// Don't remove column IS NULL on a LEFT JOIN table // Don't remove column IS NULL on a LEFT JOIN table
if (!eq_func || !value || value->type() != Item::NULL_ITEM || if (!eq_func || (*value)->type() != Item::NULL_ITEM ||
!field->table->maybe_null || field->null_ptr) !field->table->maybe_null || field->null_ptr)
return; // Not a key. Skip it return; // Not a key. Skip it
exists_optimize=1; exists_optimize=1;
} }
else else
{ {
table_map used_tables=0; table_map used_tables=0;
if (value && (used_tables=value->used_tables()) & bool optimizable=0;
(field->table->map | RAND_TABLE_BIT)) for (uint i=0; i<num_values; i++)
{
used_tables|=(*value)->used_tables();
if (!((*value)->used_tables() & (field->table->map | RAND_TABLE_BIT)))
optimizable=1;
}
if (!optimizable)
return; return;
if (!(usable_tables & field->table->map)) if (!(usable_tables & field->table->map))
{ {
if (!eq_func || !value || value->type() != Item::NULL_ITEM || if (!eq_func || (*value)->type() != Item::NULL_ITEM ||
!field->table->maybe_null || field->null_ptr) !field->table->maybe_null || field->null_ptr)
return; // Can't use left join optimize return; // Can't use left join optimize
exists_optimize=1; exists_optimize=1;
} }
...@@ -1457,12 +1463,6 @@ add_key_field(KEY_FIELD **key_fields,uint and_level, ...@@ -1457,12 +1463,6 @@ add_key_field(KEY_FIELD **key_fields,uint and_level,
field->table->keys_in_use_for_query); field->table->keys_in_use_for_query);
stat[0].keys|= possible_keys; // Add possible keys stat[0].keys|= possible_keys; // Add possible keys
if (!value)
{ // Probably BETWEEN or IN
stat[0].const_keys |= possible_keys;
return; // Can't be used as eq key
}
/* Save the following cases: /* Save the following cases:
Field op constant Field op constant
Field LIKE constant where constant doesn't start with a wildcard Field LIKE constant where constant doesn't start with a wildcard
...@@ -1470,24 +1470,34 @@ add_key_field(KEY_FIELD **key_fields,uint and_level, ...@@ -1470,24 +1470,34 @@ add_key_field(KEY_FIELD **key_fields,uint and_level,
Field op formula Field op formula
Field IS NULL Field IS NULL
Field IS NOT NULL Field IS NOT NULL
Field BETWEEN ...
Field IN ...
*/ */
stat[0].key_dependent|=used_tables; stat[0].key_dependent|=used_tables;
if (value->const_item())
stat[0].const_keys |= possible_keys; bool is_const=1;
for (uint i=0; i<num_values; i++)
is_const&= (*value)->const_item();
if (is_const)
stat[0].const_keys |= possible_keys;
/* We can't always use indexes when comparing a string index to a /* 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 */ number. cmp_type() is checked to allow compare of dates to numbers
also eq_func is NEVER true when num_values > 1
*/
if (!eq_func || if (!eq_func ||
field->result_type() == STRING_RESULT && field->result_type() == STRING_RESULT &&
value->result_type() != STRING_RESULT && (*value)->result_type() != STRING_RESULT &&
field->cmp_type() != value->result_type()) field->cmp_type() != (*value)->result_type())
return; return;
} }
} }
DBUG_ASSERT(num_values == 1);
// DBUG_ASSERT(eq_func); /* QQ: Can I uncomment this ASSERT ? */
/* Store possible eq field */ /* Store possible eq field */
(*key_fields)->field=field; (*key_fields)->field=field;
(*key_fields)->eq_func=eq_func; (*key_fields)->eq_func=eq_func;
(*key_fields)->val=value; (*key_fields)->val=*value;
(*key_fields)->level=(*key_fields)->const_level=and_level; (*key_fields)->level=(*key_fields)->const_level=and_level;
(*key_fields)->exists_optimize=exists_optimize; (*key_fields)->exists_optimize=exists_optimize;
(*key_fields)++; (*key_fields)++;
...@@ -1541,10 +1551,12 @@ add_key_fields(JOIN_TAB *stat,KEY_FIELD **key_fields,uint *and_level, ...@@ -1541,10 +1551,12 @@ add_key_fields(JOIN_TAB *stat,KEY_FIELD **key_fields,uint *and_level,
case Item_func::OPTIMIZE_NONE: case Item_func::OPTIMIZE_NONE:
break; break;
case Item_func::OPTIMIZE_KEY: case Item_func::OPTIMIZE_KEY:
// BETWEEN or IN
if (cond_func->key_item()->type() == Item::FIELD_ITEM) if (cond_func->key_item()->type() == Item::FIELD_ITEM)
add_key_field(key_fields,*and_level, add_key_field(key_fields,*and_level,
((Item_field*) (cond_func->key_item()))->field, ((Item_field*) (cond_func->key_item()))->field, 0,
0,(Item*) 0,usable_tables); cond_func->arguments()+1, cond_func->argument_count()-1,
usable_tables);
break; break;
case Item_func::OPTIMIZE_OP: case Item_func::OPTIMIZE_OP:
{ {
...@@ -1556,7 +1568,7 @@ add_key_fields(JOIN_TAB *stat,KEY_FIELD **key_fields,uint *and_level, ...@@ -1556,7 +1568,7 @@ add_key_fields(JOIN_TAB *stat,KEY_FIELD **key_fields,uint *and_level,
add_key_field(key_fields,*and_level, add_key_field(key_fields,*and_level,
((Item_field*) (cond_func->arguments()[0]))->field, ((Item_field*) (cond_func->arguments()[0]))->field,
equal_func, equal_func,
(cond_func->arguments()[1]),usable_tables); cond_func->arguments()+1, 1, usable_tables);
} }
if (cond_func->arguments()[1]->type() == Item::FIELD_ITEM && if (cond_func->arguments()[1]->type() == Item::FIELD_ITEM &&
cond_func->functype() != Item_func::LIKE_FUNC) cond_func->functype() != Item_func::LIKE_FUNC)
...@@ -1564,7 +1576,7 @@ add_key_fields(JOIN_TAB *stat,KEY_FIELD **key_fields,uint *and_level, ...@@ -1564,7 +1576,7 @@ add_key_fields(JOIN_TAB *stat,KEY_FIELD **key_fields,uint *and_level,
add_key_field(key_fields,*and_level, add_key_field(key_fields,*and_level,
((Item_field*) (cond_func->arguments()[1]))->field, ((Item_field*) (cond_func->arguments()[1]))->field,
equal_func, equal_func,
(cond_func->arguments()[0]),usable_tables); cond_func->arguments(),1,usable_tables);
} }
break; break;
} }
...@@ -1572,10 +1584,11 @@ add_key_fields(JOIN_TAB *stat,KEY_FIELD **key_fields,uint *and_level, ...@@ -1572,10 +1584,11 @@ add_key_fields(JOIN_TAB *stat,KEY_FIELD **key_fields,uint *and_level,
/* column_name IS [NOT] NULL */ /* column_name IS [NOT] NULL */
if (cond_func->arguments()[0]->type() == Item::FIELD_ITEM) if (cond_func->arguments()[0]->type() == Item::FIELD_ITEM)
{ {
Item *tmp=new Item_null;
add_key_field(key_fields,*and_level, add_key_field(key_fields,*and_level,
((Item_field*) (cond_func->arguments()[0]))->field, ((Item_field*) (cond_func->arguments()[0]))->field,
cond_func->functype() == Item_func::ISNULL_FUNC, cond_func->functype() == Item_func::ISNULL_FUNC,
new Item_null, usable_tables); &tmp, 1, usable_tables);
} }
break; break;
} }
...@@ -3267,7 +3280,7 @@ change_cond_ref_to_const(I_List<COND_CMP> *save_list,Item *and_father, ...@@ -3267,7 +3280,7 @@ change_cond_ref_to_const(I_List<COND_CMP> *save_list,Item *and_father,
static void static void
propagate_cond_constants(I_List<COND_CMP> *save_list,COND *and_level, propagate_cond_constants(I_List<COND_CMP> *save_list,COND *and_father,
COND *cond) COND *cond)
{ {
if (cond->type() == Item::COND_ITEM) if (cond->type() == Item::COND_ITEM)
...@@ -3293,7 +3306,7 @@ propagate_cond_constants(I_List<COND_CMP> *save_list,COND *and_level, ...@@ -3293,7 +3306,7 @@ propagate_cond_constants(I_List<COND_CMP> *save_list,COND *and_level,
cond_cmp->cmp_func->arguments()[1]); cond_cmp->cmp_func->arguments()[1]);
} }
} }
else if (and_level != cond && !cond->marker) // In a AND group else if (and_father != cond && !cond->marker) // In a AND group
{ {
if (cond->type() == Item::FUNC_ITEM && if (cond->type() == Item::FUNC_ITEM &&
(((Item_func*) cond)->functype() == Item_func::EQ_FUNC || (((Item_func*) cond)->functype() == Item_func::EQ_FUNC ||
...@@ -3311,7 +3324,7 @@ propagate_cond_constants(I_List<COND_CMP> *save_list,COND *and_level, ...@@ -3311,7 +3324,7 @@ propagate_cond_constants(I_List<COND_CMP> *save_list,COND *and_level,
func->arguments()[1]=resolve_const_item(func->arguments()[1], func->arguments()[1]=resolve_const_item(func->arguments()[1],
func->arguments()[0]); func->arguments()[0]);
func->update_used_tables(); func->update_used_tables();
change_cond_ref_to_const(save_list,and_level,and_level, change_cond_ref_to_const(save_list,and_father,and_father,
func->arguments()[0], func->arguments()[0],
func->arguments()[1]); func->arguments()[1]);
} }
...@@ -3320,7 +3333,7 @@ propagate_cond_constants(I_List<COND_CMP> *save_list,COND *and_level, ...@@ -3320,7 +3333,7 @@ propagate_cond_constants(I_List<COND_CMP> *save_list,COND *and_level,
func->arguments()[0]=resolve_const_item(func->arguments()[0], func->arguments()[0]=resolve_const_item(func->arguments()[0],
func->arguments()[1]); func->arguments()[1]);
func->update_used_tables(); func->update_used_tables();
change_cond_ref_to_const(save_list,and_level,and_level, change_cond_ref_to_const(save_list,and_father,and_father,
func->arguments()[1], func->arguments()[1],
func->arguments()[0]); func->arguments()[0]);
} }
......
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