mirror of
https://github.com/MariaDB/server.git
synced 2025-01-31 11:01:52 +01:00
Merge bk-internal:/home/bk/mysql-4.0/
into serg.mylan:/usr/home/serg/Abk/mysql-4.0
This commit is contained in:
commit
bc9f6cde50
7 changed files with 102 additions and 35 deletions
|
@ -130,7 +130,11 @@ int main(int argc,char *argv[])
|
|||
#error
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_SNPRINTF
|
||||
snprintf(buf,MAX_LEN,"%.*s",(int) keylen,info->lastkey+1);
|
||||
#else
|
||||
sprintf(buf,"%.*s",(int) keylen,info->lastkey+1);
|
||||
#endif
|
||||
casedn_str(buf);
|
||||
total++;
|
||||
lengths[keylen]++;
|
||||
|
|
|
@ -165,7 +165,9 @@ my_bool _mi_read_pack_info(MI_INFO *info, pbool fix_keys)
|
|||
diff_length=(int) rec_reflength - (int) share->base.rec_reflength;
|
||||
if (fix_keys)
|
||||
share->rec_reflength=rec_reflength;
|
||||
share->base.min_block_length=share->min_pack_length+share->pack.ref_length;
|
||||
share->base.min_block_length=share->min_pack_length+1;
|
||||
if (share->min_pack_length > 254)
|
||||
share->base.min_block_length+=2;
|
||||
|
||||
if (!(share->decode_trees=(MI_DECODE_TREE*)
|
||||
my_malloc((uint) (trees*sizeof(MI_DECODE_TREE)+
|
||||
|
|
|
@ -226,3 +226,31 @@ insert into t1 values (0,1,NULL,"aaa"), (1,1,NULL,"aaa"), (2,1,NULL,"aaa"),
|
|||
select a.id1, b.idnull from t1 as a, t1 as b where a.id2=1 and a.id1=1 and b.id1=a.idnull order by b.id2 desc limit 1;
|
||||
id1 idnull
|
||||
drop table t1;
|
||||
create table t1 (x int, y int, index(x), index(y));
|
||||
insert into t1 (x) values (1),(2),(3),(4),(5),(6),(7),(8),(9);
|
||||
update t1 set y=x;
|
||||
explain select * from t1, t1 t2 where t1.y = 2 and t2.x between 7 and t1.y+0;
|
||||
table type possible_keys key key_len ref rows Extra
|
||||
t1 ref y y 5 const 1 Using where
|
||||
t2 range x x 5 NULL 4 Using where
|
||||
explain select * from t1, t1 t2 where t1.y = 2 and t2.x >= 7 and t2.x <= t1.y+0;
|
||||
table type possible_keys key key_len ref rows Extra
|
||||
t1 ref y y 5 const 1 Using where
|
||||
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;
|
||||
table type possible_keys key key_len ref rows Extra
|
||||
t1 ref y y 5 const 1 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;
|
||||
table type possible_keys key key_len ref rows Extra
|
||||
t1 ref y y 5 const 1 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 between 0 and t1.y;
|
||||
table type possible_keys key key_len ref rows Extra
|
||||
t1 ref y y 5 const 1 Using where
|
||||
t2 ALL x NULL NULL NULL 9 Using where
|
||||
explain select * from t1, t1 t2 where t1.y = 2 and t2.x >= 0 and t2.x <= t1.y;
|
||||
table type possible_keys key key_len ref rows Extra
|
||||
t1 ref y y 5 const 1 Using where
|
||||
t2 range x x 5 NULL 2 Using where
|
||||
drop table t1;
|
||||
|
|
|
@ -183,3 +183,20 @@ insert into t1 values (0,1,NULL,"aaa"), (1,1,NULL,"aaa"), (2,1,NULL,"aaa"),
|
|||
select a.id1, b.idnull from t1 as a, t1 as b where a.id2=1 and a.id1=1 and b.id1=a.idnull order by b.id2 desc limit 1;
|
||||
drop table t1;
|
||||
|
||||
#
|
||||
# BETWEEN problems
|
||||
#
|
||||
create table t1 (x int, y int, index(x), index(y));
|
||||
insert into t1 (x) values (1),(2),(3),(4),(5),(6),(7),(8),(9);
|
||||
update t1 set y=x;
|
||||
# between with only one end fixed
|
||||
explain select * from t1, t1 t2 where t1.y = 2 and t2.x between 7 and t1.y+0;
|
||||
explain select * from t1, t1 t2 where t1.y = 2 and t2.x >= 7 and t2.x <= t1.y+0;
|
||||
# between with both expressions on both ends
|
||||
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 >= t1.y-1 and t2.x <= t1.y+1;
|
||||
# equation propagation
|
||||
explain select * from t1, t1 t2 where t1.y = 2 and t2.x between 0 and t1.y;
|
||||
explain select * from t1, t1 t2 where t1.y = 2 and t2.x >= 0 and t2.x <= t1.y;
|
||||
drop table t1;
|
||||
|
||||
|
|
|
@ -742,7 +742,7 @@ void Field_decimal::store(double nr)
|
|||
char buff[320];
|
||||
|
||||
fyllchar = zerofill ? (char) '0' : (char) ' ';
|
||||
#ifdef HAVE_SNPRINTF_
|
||||
#ifdef HAVE_SNPRINTF
|
||||
buff[sizeof(buff)-1]=0; // Safety
|
||||
snprintf(buff,sizeof(buff)-1, "%.*f",(int) dec,nr);
|
||||
#else
|
||||
|
|
|
@ -794,18 +794,15 @@ static SEL_TREE *get_mm_tree(PARAM *param,COND *cond)
|
|||
DBUG_RETURN(new SEL_TREE(SEL_TREE::ALWAYS));
|
||||
DBUG_RETURN(new SEL_TREE(SEL_TREE::IMPOSSIBLE));
|
||||
}
|
||||
|
||||
table_map ref_tables=cond->used_tables();
|
||||
if (ref_tables & ~(param->prev_tables | param->read_tables |
|
||||
param->current_table))
|
||||
DBUG_RETURN(0); // Can't be calculated yet
|
||||
if (cond->type() != Item::FUNC_ITEM)
|
||||
{ // Should be a field
|
||||
if (ref_tables & param->current_table)
|
||||
DBUG_RETURN(0);
|
||||
DBUG_RETURN(new SEL_TREE(SEL_TREE::MAYBE));
|
||||
}
|
||||
if (!(ref_tables & param->current_table))
|
||||
DBUG_RETURN(new SEL_TREE(SEL_TREE::MAYBE)); // This may be false or true
|
||||
|
||||
Item_func *cond_func= (Item_func*) cond;
|
||||
if (cond_func->select_optimize() == Item_func::OPTIMIZE_NONE)
|
||||
DBUG_RETURN(0); // Can't be calculated
|
||||
|
@ -847,6 +844,12 @@ static SEL_TREE *get_mm_tree(PARAM *param,COND *cond)
|
|||
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)
|
||||
|
|
|
@ -1425,28 +1425,34 @@ merge_key_fields(KEY_FIELD *start,KEY_FIELD *new_fields,KEY_FIELD *end,
|
|||
|
||||
static void
|
||||
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)
|
||||
{
|
||||
bool exists_optimize=0;
|
||||
if (!(field->flags & PART_KEY_FLAG))
|
||||
{
|
||||
// Don't remove column IS NULL on a LEFT JOIN table
|
||||
if (!eq_func || !value || value->type() != Item::NULL_ITEM ||
|
||||
!field->table->maybe_null || field->null_ptr)
|
||||
if (!eq_func || (*value)->type() != Item::NULL_ITEM ||
|
||||
!field->table->maybe_null || field->null_ptr)
|
||||
return; // Not a key. Skip it
|
||||
exists_optimize=1;
|
||||
}
|
||||
else
|
||||
{
|
||||
table_map used_tables=0;
|
||||
if (value && (used_tables=value->used_tables()) &
|
||||
(field->table->map | RAND_TABLE_BIT))
|
||||
bool optimizable=0;
|
||||
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;
|
||||
if (!(usable_tables & field->table->map))
|
||||
{
|
||||
if (!eq_func || !value || value->type() != Item::NULL_ITEM ||
|
||||
!field->table->maybe_null || field->null_ptr)
|
||||
if (!eq_func || (*value)->type() != Item::NULL_ITEM ||
|
||||
!field->table->maybe_null || field->null_ptr)
|
||||
return; // Can't use left join optimize
|
||||
exists_optimize=1;
|
||||
}
|
||||
|
@ -1457,12 +1463,6 @@ add_key_field(KEY_FIELD **key_fields,uint and_level,
|
|||
field->table->keys_in_use_for_query);
|
||||
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:
|
||||
Field op constant
|
||||
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,
|
|||
Field op formula
|
||||
Field IS NULL
|
||||
Field IS NOT NULL
|
||||
Field BETWEEN ...
|
||||
Field IN ...
|
||||
*/
|
||||
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
|
||||
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 ||
|
||||
field->result_type() == STRING_RESULT &&
|
||||
value->result_type() != STRING_RESULT &&
|
||||
field->cmp_type() != value->result_type())
|
||||
(*value)->result_type() != STRING_RESULT &&
|
||||
field->cmp_type() != (*value)->result_type())
|
||||
return;
|
||||
}
|
||||
}
|
||||
DBUG_ASSERT(num_values == 1);
|
||||
// DBUG_ASSERT(eq_func); /* QQ: Can I uncomment this ASSERT ? */
|
||||
/* Store possible eq field */
|
||||
(*key_fields)->field=field;
|
||||
(*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)->exists_optimize=exists_optimize;
|
||||
(*key_fields)++;
|
||||
|
@ -1541,10 +1551,12 @@ add_key_fields(JOIN_TAB *stat,KEY_FIELD **key_fields,uint *and_level,
|
|||
case Item_func::OPTIMIZE_NONE:
|
||||
break;
|
||||
case Item_func::OPTIMIZE_KEY:
|
||||
// BETWEEN or IN
|
||||
if (cond_func->key_item()->type() == Item::FIELD_ITEM)
|
||||
add_key_field(key_fields,*and_level,
|
||||
((Item_field*) (cond_func->key_item()))->field,
|
||||
0,(Item*) 0,usable_tables);
|
||||
((Item_field*) (cond_func->key_item()))->field, 0,
|
||||
cond_func->arguments()+1, cond_func->argument_count()-1,
|
||||
usable_tables);
|
||||
break;
|
||||
case Item_func::OPTIMIZE_OP:
|
||||
{
|
||||
|
@ -1556,7 +1568,7 @@ add_key_fields(JOIN_TAB *stat,KEY_FIELD **key_fields,uint *and_level,
|
|||
add_key_field(key_fields,*and_level,
|
||||
((Item_field*) (cond_func->arguments()[0]))->field,
|
||||
equal_func,
|
||||
(cond_func->arguments()[1]),usable_tables);
|
||||
cond_func->arguments()+1, 1, usable_tables);
|
||||
}
|
||||
if (cond_func->arguments()[1]->type() == Item::FIELD_ITEM &&
|
||||
cond_func->functype() != Item_func::LIKE_FUNC)
|
||||
|
@ -1564,7 +1576,7 @@ add_key_fields(JOIN_TAB *stat,KEY_FIELD **key_fields,uint *and_level,
|
|||
add_key_field(key_fields,*and_level,
|
||||
((Item_field*) (cond_func->arguments()[1]))->field,
|
||||
equal_func,
|
||||
(cond_func->arguments()[0]),usable_tables);
|
||||
cond_func->arguments(),1,usable_tables);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -1572,10 +1584,11 @@ add_key_fields(JOIN_TAB *stat,KEY_FIELD **key_fields,uint *and_level,
|
|||
/* column_name IS [NOT] NULL */
|
||||
if (cond_func->arguments()[0]->type() == Item::FIELD_ITEM)
|
||||
{
|
||||
Item *tmp=new Item_null;
|
||||
add_key_field(key_fields,*and_level,
|
||||
((Item_field*) (cond_func->arguments()[0]))->field,
|
||||
cond_func->functype() == Item_func::ISNULL_FUNC,
|
||||
new Item_null, usable_tables);
|
||||
&tmp, 1, usable_tables);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -3267,7 +3280,7 @@ change_cond_ref_to_const(I_List<COND_CMP> *save_list,Item *and_father,
|
|||
|
||||
|
||||
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)
|
||||
{
|
||||
if (cond->type() == Item::COND_ITEM)
|
||||
|
@ -3293,7 +3306,7 @@ propagate_cond_constants(I_List<COND_CMP> *save_list,COND *and_level,
|
|||
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 &&
|
||||
(((Item_func*) cond)->functype() == Item_func::EQ_FUNC ||
|
||||
|
@ -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()[0]);
|
||||
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()[1]);
|
||||
}
|
||||
|
@ -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()[1]);
|
||||
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()[0]);
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue