Commit ed040fe2 authored by monty@hundin.mysql.fi's avatar monty@hundin.mysql.fi

Fix for bug in WHERE key='j' or key='J'

parent 82d87ebd
...@@ -46897,6 +46897,8 @@ not yet 100% confident in this code. ...@@ -46897,6 +46897,8 @@ not yet 100% confident in this code.
@appendixsubsec Changes in release 3.23.50 @appendixsubsec Changes in release 3.23.50
@itemize @bullet @itemize @bullet
@item @item
Fixed bug when using @code{WHERE key_column = 'J' or key_column='j'}.
@item
Fixed core-dump bug when using @code{--log-bin} with @code{LOAD DATA Fixed core-dump bug when using @code{--log-bin} with @code{LOAD DATA
INFILE} without an active database. INFILE} without an active database.
@item @item
...@@ -46934,7 +46936,7 @@ Don't give warning for statement that is only a comment; This is needed for ...@@ -46934,7 +46936,7 @@ Don't give warning for statement that is only a comment; This is needed for
@code{mysqldump --disable-keys} to work. @code{mysqldump --disable-keys} to work.
@item @item
Fixed unlikely caching bug when doing a join without keys. In this case Fixed unlikely caching bug when doing a join without keys. In this case
the last used field for a table always returned @code{NULL}. the last used column for a table always returned @code{NULL}.
@item @item
Added options to make @code{LOAD DATA LOCAL INFILE} more secure. Added options to make @code{LOAD DATA LOCAL INFILE} more secure.
@item @item
...@@ -251,7 +251,7 @@ static struct option long_options[] = ...@@ -251,7 +251,7 @@ static struct option long_options[] =
static void print_version(void) static void print_version(void)
{ {
printf("%s Ver 1.11 for %s on %s\n",my_progname,SYSTEM_TYPE,MACHINE_TYPE); printf("%s Ver 1.12 for %s on %s\n",my_progname,SYSTEM_TYPE,MACHINE_TYPE);
} }
static void usage(void) static void usage(void)
...@@ -594,10 +594,7 @@ static int compress(PACK_MRG_INFO *mrg,char *result_table) ...@@ -594,10 +594,7 @@ static int compress(PACK_MRG_INFO *mrg,char *result_table)
else else
{ {
if (tmp_dir[0]) if (tmp_dir[0])
{ error=my_copy(new_name,org_name,MYF(MY_WME));
if (!(error=my_copy(new_name,org_name,MYF(MY_WME))))
VOID(my_delete(new_name,MYF(MY_WME)));
}
else else
error=my_rename(new_name,org_name,MYF(MY_WME)); error=my_rename(new_name,org_name,MYF(MY_WME));
if (!error) if (!error)
...@@ -607,13 +604,8 @@ static int compress(PACK_MRG_INFO *mrg,char *result_table) ...@@ -607,13 +604,8 @@ static int compress(PACK_MRG_INFO *mrg,char *result_table)
else else
{ {
if (tmp_dir[0]) if (tmp_dir[0])
{ error=my_copy(new_name,org_name,
MYF(MY_WME | MY_HOLD_ORIGINAL_MODES | MY_COPYTIME));
if (!(error=my_copy(new_name,org_name,
MYF(MY_WME | MY_HOLD_ORIGINAL_MODES
| MY_COPYTIME))))
VOID(my_delete(new_name,MYF(MY_WME)));
}
else else
error=my_redel(org_name,new_name,MYF(MY_WME | MY_COPYTIME)); error=my_redel(org_name,new_name,MYF(MY_WME | MY_COPYTIME));
} }
...@@ -627,6 +619,7 @@ static int compress(PACK_MRG_INFO *mrg,char *result_table) ...@@ -627,6 +619,7 @@ static int compress(PACK_MRG_INFO *mrg,char *result_table)
if (error) if (error)
{ {
VOID(fprintf(stderr,"Aborting: %s is not compressed\n",org_name)); VOID(fprintf(stderr,"Aborting: %s is not compressed\n",org_name));
VOID(my_delete(new_name,MYF(MY_WME)));
DBUG_RETURN(-1); DBUG_RETURN(-1);
} }
if (write_loop || verbose) if (write_loop || verbose)
......
...@@ -55,3 +55,13 @@ believe ...@@ -55,3 +55,13 @@ believe
believe in love believe in love
aString aString
believe in myself believe in myself
count(*)
602
count(*)
602
count(*)
602
count(*)
389
count(*)
213
...@@ -105,7 +105,6 @@ drop table t1; ...@@ -105,7 +105,6 @@ drop table t1;
# Problem with binary strings # Problem with binary strings
# #
DROP TABLE IF EXISTS t1;
CREATE TABLE t1 ( CREATE TABLE t1 (
t1ID int(10) unsigned NOT NULL auto_increment, t1ID int(10) unsigned NOT NULL auto_increment,
art char(1) binary NOT NULL default '', art char(1) binary NOT NULL default '',
...@@ -161,4 +160,6 @@ INSERT INTO t1 (art) VALUES ('j'),('J'),('j'),('J'),('j'),('J'),('j'),('J'),('j' ...@@ -161,4 +160,6 @@ INSERT INTO t1 (art) VALUES ('j'),('J'),('j'),('J'),('j'),('J'),('j'),('J'),('j'
select count(*) from t1 where upper(art) = 'J'; select count(*) from t1 where upper(art) = 'J';
select count(*) from t1 where art = 'J' or art = 'j'; select count(*) from t1 where art = 'J' or art = 'j';
select count(*) from t1 where art = 'j' or art = 'J'; select count(*) from t1 where art = 'j' or art = 'J';
select count(*) from t1 where art = 'j';
select count(*) from t1 where art = 'J';
drop table t1; drop table t1;
...@@ -59,12 +59,28 @@ void Item::set_name(char *str,uint length) ...@@ -59,12 +59,28 @@ void Item::set_name(char *str,uint length)
} }
} }
bool Item::eq(const Item *item) const // Only doing this on conds /*
This function is only called when comparing items in the WHERE clause
*/
bool Item::eq(const Item *item, bool binary_cmp) const
{ {
return type() == item->type() && name && item->name && return type() == item->type() && name && item->name &&
!my_strcasecmp(name,item->name); !my_strcasecmp(name,item->name);
} }
bool Item_string::eq(const Item *item, bool binary_cmp) const
{
if (type() == item->type())
{
if (binary_cmp)
return !stringcmp(&str_value, &item->str_value);
return !sortcmp(&str_value, &item->str_value);
}
return 0;
}
/* /*
Get the value of the function as a TIME structure. Get the value of the function as a TIME structure.
As a extra convenience the time structure is reset on error! As a extra convenience the time structure is reset on error!
...@@ -202,7 +218,7 @@ longlong Item_field::val_int_result() ...@@ -202,7 +218,7 @@ longlong Item_field::val_int_result()
return result_field->val_int(); return result_field->val_int();
} }
bool Item_field::eq(const Item *item) const bool Item_field::eq(const Item *item, bool binary_cmp) const
{ {
return item->type() == FIELD_ITEM && ((Item_field*) item)->field == field; return item->type() == FIELD_ITEM && ((Item_field*) item)->field == field;
} }
...@@ -245,7 +261,8 @@ void Item_string::print(String *str) ...@@ -245,7 +261,8 @@ void Item_string::print(String *str)
str->append('\''); str->append('\'');
} }
bool Item_null::eq(const Item *item) const { return item->type() == type(); } bool Item_null::eq(const Item *item, bool binary_cmp) const
{ return item->type() == type(); }
double Item_null::val() { null_value=1; return 0.0; } double Item_null::val() { null_value=1; return 0.0; }
longlong Item_null::val_int() { null_value=1; return 0; } longlong Item_null::val_int() { null_value=1; return 0; }
/* ARGSUSED */ /* ARGSUSED */
......
...@@ -56,7 +56,7 @@ class Item { ...@@ -56,7 +56,7 @@ class Item {
virtual void save_org_in_field(Field *field) virtual void save_org_in_field(Field *field)
{ (void) save_in_field(field); } { (void) save_in_field(field); }
virtual bool send(String *str); virtual bool send(String *str);
virtual bool eq(const Item *) const; virtual bool eq(const Item *, bool binary_cmp) const;
virtual Item_result result_type () const { return REAL_RESULT; } virtual Item_result result_type () const { return REAL_RESULT; }
virtual enum Type type() const =0; virtual enum Type type() const =0;
virtual double val()=0; virtual double val()=0;
...@@ -109,7 +109,7 @@ class Item_field :public Item_ident ...@@ -109,7 +109,7 @@ class Item_field :public Item_ident
{} {}
Item_field(Field *field); Item_field(Field *field);
enum Type type() const { return FIELD_ITEM; } enum Type type() const { return FIELD_ITEM; }
bool eq(const Item *item) const; bool eq(const Item *item, bool binary_cmp) const;
double val(); double val();
longlong val_int(); longlong val_int();
String *val_str(String*); String *val_str(String*);
...@@ -138,7 +138,7 @@ class Item_null :public Item ...@@ -138,7 +138,7 @@ class Item_null :public Item
Item_null(char *name_par=0) Item_null(char *name_par=0)
{ maybe_null=null_value=TRUE; name= name_par ? name_par : (char*) "NULL";} { maybe_null=null_value=TRUE; name= name_par ? name_par : (char*) "NULL";}
enum Type type() const { return NULL_ITEM; } enum Type type() const { return NULL_ITEM; }
bool eq(const Item *item) const; bool eq(const Item *item, bool binary_cmp) const;
double val(); double val();
longlong val_int(); longlong val_int();
String *val_str(String *str); String *val_str(String *str);
...@@ -247,6 +247,7 @@ class Item_string :public Item ...@@ -247,6 +247,7 @@ class Item_string :public Item
void make_field(Send_field *field); void make_field(Send_field *field);
enum Item_result result_type () const { return STRING_RESULT; } enum Item_result result_type () const { return STRING_RESULT; }
bool basic_const_item() const { return 1; } bool basic_const_item() const { return 1; }
bool eq(const Item *item, bool binary_cmp) const;
Item *new_item() { return new Item_string(name,str_value.ptr(),max_length); } Item *new_item() { return new Item_string(name,str_value.ptr(),max_length); }
String *const_string() { return &str_value; } String *const_string() { return &str_value; }
inline void append(char *str,uint length) { str_value.append(str,length); } inline void append(char *str,uint length) { str_value.append(str,length); }
...@@ -306,7 +307,8 @@ class Item_ref :public Item_ident ...@@ -306,7 +307,8 @@ class Item_ref :public Item_ident
Item_ref(Item **item, char *table_name_par,char *field_name_par) Item_ref(Item **item, char *table_name_par,char *field_name_par)
:Item_ident(NullS,table_name_par,field_name_par),ref(item) {} :Item_ident(NullS,table_name_par,field_name_par),ref(item) {}
enum Type type() const { return REF_ITEM; } enum Type type() const { return REF_ITEM; }
bool eq(const Item *item) const { return (*ref)->eq(item); } bool eq(const Item *item, bool binary_cmp) const
{ return (*ref)->eq(item, binary_cmp); }
~Item_ref() { if (ref) delete *ref; } ~Item_ref() { if (ref) delete *ref; }
double val() double val()
{ {
......
...@@ -148,7 +148,7 @@ void Item_func::print_op(String *str) ...@@ -148,7 +148,7 @@ void Item_func::print_op(String *str)
str->append(')'); str->append(')');
} }
bool Item_func::eq(const Item *item) const bool Item_func::eq(const Item *item, bool binary_cmp) const
{ {
/* Assume we don't have rtti */ /* Assume we don't have rtti */
if (this == item) if (this == item)
...@@ -160,7 +160,7 @@ bool Item_func::eq(const Item *item) const ...@@ -160,7 +160,7 @@ bool Item_func::eq(const Item *item) const
func_name() != item_func->func_name()) func_name() != item_func->func_name())
return 0; return 0;
for (uint i=0; i < arg_count ; i++) for (uint i=0; i < arg_count ; i++)
if (!args[i]->eq(item_func->args[i])) if (!args[i]->eq(item_func->args[i], binary_cmp))
return 0; return 0;
return 1; return 1;
} }
...@@ -1882,7 +1882,7 @@ void Item_func_get_user_var::print(String *str) ...@@ -1882,7 +1882,7 @@ void Item_func_get_user_var::print(String *str)
str->append(')'); str->append(')');
} }
bool Item_func_get_user_var::eq(const Item *item) const bool Item_func_get_user_var::eq(const Item *item, bool binary_cmp) const
{ {
/* Assume we don't have rtti */ /* Assume we don't have rtti */
if (this == item) if (this == item)
...@@ -2135,7 +2135,7 @@ bool Item_func_match::fix_index() ...@@ -2135,7 +2135,7 @@ bool Item_func_match::fix_index()
return 1; return 1;
} }
bool Item_func_match::eq(const Item *item) const bool Item_func_match::eq(const Item *item, bool binary_cmp) const
{ {
if (item->type() != FUNC_ITEM) if (item->type() != FUNC_ITEM)
return 0; return 0;
...@@ -2146,7 +2146,7 @@ bool Item_func_match::eq(const Item *item) const ...@@ -2146,7 +2146,7 @@ bool Item_func_match::eq(const Item *item) const
Item_func_match *ifm=(Item_func_match*) item; Item_func_match *ifm=(Item_func_match*) item;
if (key == ifm->key && table == ifm->table && if (key == ifm->key && table == ifm->table &&
key_item()->eq(ifm->key_item())) key_item()->eq(ifm->key_item(), binary_cmp))
return 1; return 1;
return 0; return 0;
......
...@@ -98,7 +98,7 @@ class Item_func :public Item_result_field ...@@ -98,7 +98,7 @@ class Item_func :public Item_result_field
void make_field(Send_field *field); void make_field(Send_field *field);
table_map used_tables() const; table_map used_tables() const;
void update_used_tables(); void update_used_tables();
bool eq(const Item *item) const; bool eq(const Item *item, bool binary_cmp) const;
virtual optimize_type select_optimize() const { return OPTIMIZE_NONE; } virtual optimize_type select_optimize() const { return OPTIMIZE_NONE; }
virtual bool have_rev_func() const { return 0; } virtual bool have_rev_func() const { return 0; }
virtual Item *key_item() const { return args[0]; } virtual Item *key_item() const { return args[0]; }
...@@ -842,7 +842,7 @@ class Item_func_get_user_var :public Item_func ...@@ -842,7 +842,7 @@ class Item_func_get_user_var :public Item_func
bool const_item() const { return const_var_flag; } bool const_item() const { return const_var_flag; }
table_map used_tables() const table_map used_tables() const
{ return const_var_flag ? 0 : RAND_TABLE_BIT; } { return const_var_flag ? 0 : RAND_TABLE_BIT; }
bool eq(const Item *item) const; bool eq(const Item *item, bool binary_cmp) const;
}; };
...@@ -887,7 +887,7 @@ class Item_func_match :public Item_real_func ...@@ -887,7 +887,7 @@ class Item_func_match :public Item_real_func
enum Functype functype() const { return FT_FUNC; } enum Functype functype() const { return FT_FUNC; }
void update_used_tables() {} void update_used_tables() {}
bool fix_fields(THD *thd,struct st_table_list *tlist); bool fix_fields(THD *thd,struct st_table_list *tlist);
bool eq(const Item *) const; bool eq(const Item *, bool binary_cmp) const;
double val(); double val();
longlong val_int() { return val()!=0.0; } longlong val_int() { return val()!=0.0; }
......
...@@ -1718,7 +1718,7 @@ find_item_in_list(Item *find,List<Item> &items) ...@@ -1718,7 +1718,7 @@ find_item_in_list(Item *find,List<Item> &items)
{ {
if (found) if (found)
{ {
if ((*found)->eq(item)) if ((*found)->eq(item,0))
continue; // Same field twice (Access?) continue; // Same field twice (Access?)
if (current_thd->where) if (current_thd->where)
my_printf_error(ER_NON_UNIQ_ERROR,ER(ER_NON_UNIQ_ERROR),MYF(0), my_printf_error(ER_NON_UNIQ_ERROR,ER(ER_NON_UNIQ_ERROR),MYF(0),
...@@ -1734,7 +1734,7 @@ find_item_in_list(Item *find,List<Item> &items) ...@@ -1734,7 +1734,7 @@ find_item_in_list(Item *find,List<Item> &items)
} }
} }
} }
else if (!table_name && (item->eq(find) || else if (!table_name && (item->eq(find,0) ||
find->name && find->name &&
!my_strcasecmp(item->name,find->name))) !my_strcasecmp(item->name,find->name)))
{ {
...@@ -2213,7 +2213,7 @@ int setup_ftfuncs(THD *thd) ...@@ -2213,7 +2213,7 @@ int setup_ftfuncs(THD *thd)
lj.rewind(); lj.rewind();
while ((ftf2=lj++) != ftf) while ((ftf2=lj++) != ftf)
{ {
if (ftf->eq(ftf2) && !ftf2->master) if (ftf->eq(ftf2,1) && !ftf2->master)
ftf2->master=ftf; ftf2->master=ftf;
} }
} }
......
...@@ -1100,14 +1100,14 @@ merge_key_fields(KEY_FIELD *start,KEY_FIELD *new_fields,KEY_FIELD *end, ...@@ -1100,14 +1100,14 @@ merge_key_fields(KEY_FIELD *start,KEY_FIELD *new_fields,KEY_FIELD *end,
{ {
if (new_fields->val->used_tables()) if (new_fields->val->used_tables())
{ {
if (old->val->eq(new_fields->val)) if (old->val->eq(new_fields->val, old->field->binary()))
{ {
old->level=old->const_level=and_level; old->level=old->const_level=and_level;
old->exists_optimize&=new_fields->exists_optimize; old->exists_optimize&=new_fields->exists_optimize;
} }
} }
else if (old->val->eq(new_fields->val) && old->eq_func && else if (old->val->eq(new_fields->val, old->field->binary()) &&
new_fields->eq_func) old->eq_func && new_fields->eq_func)
{ {
old->level=old->const_level=and_level; old->level=old->const_level=and_level;
old->exists_optimize&=new_fields->exists_optimize; old->exists_optimize&=new_fields->exists_optimize;
...@@ -2602,7 +2602,7 @@ eq_ref_table(JOIN *join, ORDER *start_order, JOIN_TAB *tab) ...@@ -2602,7 +2602,7 @@ eq_ref_table(JOIN *join, ORDER *start_order, JOIN_TAB *tab)
ORDER *order; ORDER *order;
for (order=start_order ; order ; order=order->next) for (order=start_order ; order ; order=order->next)
{ {
if ((*ref_item)->eq(order->item[0])) if ((*ref_item)->eq(order->item[0],0))
break; break;
} }
if (order) if (order)
...@@ -2859,7 +2859,7 @@ change_cond_ref_to_const(I_List<COND_CMP> *save_list,Item *and_father, ...@@ -2859,7 +2859,7 @@ change_cond_ref_to_const(I_List<COND_CMP> *save_list,Item *and_father,
Item *right_item= func->arguments()[1]; Item *right_item= func->arguments()[1];
Item_func::Functype functype= func->functype(); Item_func::Functype functype= func->functype();
if (right_item->eq(field) && left_item != value) if (right_item->eq(field,0) && left_item != value)
{ {
Item *tmp=value->new_item(); Item *tmp=value->new_item();
if (tmp) if (tmp)
...@@ -2878,7 +2878,7 @@ change_cond_ref_to_const(I_List<COND_CMP> *save_list,Item *and_father, ...@@ -2878,7 +2878,7 @@ change_cond_ref_to_const(I_List<COND_CMP> *save_list,Item *and_father,
func->arguments()[1]->result_type())); func->arguments()[1]->result_type()));
} }
} }
else if (left_item->eq(field) && right_item != value) else if (left_item->eq(field,0) && right_item != value)
{ {
Item *tmp=value->new_item(); Item *tmp=value->new_item();
if (tmp) if (tmp)
...@@ -3118,7 +3118,7 @@ remove_eq_conds(COND *cond,Item::cond_result *cond_value) ...@@ -3118,7 +3118,7 @@ remove_eq_conds(COND *cond,Item::cond_result *cond_value)
{ // boolan compare function { // boolan compare function
Item *left_item= ((Item_func*) cond)->arguments()[0]; Item *left_item= ((Item_func*) cond)->arguments()[0];
Item *right_item= ((Item_func*) cond)->arguments()[1]; Item *right_item= ((Item_func*) cond)->arguments()[1];
if (left_item->eq(right_item)) if (left_item->eq(right_item,1))
{ {
if (!left_item->maybe_null || if (!left_item->maybe_null ||
((Item_func*) cond)->functype() == Item_func::EQUAL_FUNC) ((Item_func*) cond)->functype() == Item_func::EQUAL_FUNC)
...@@ -3163,22 +3163,22 @@ const_expression_in_where(COND *cond, Item *comp_item, Item **const_item) ...@@ -3163,22 +3163,22 @@ const_expression_in_where(COND *cond, Item *comp_item, Item **const_item)
return 0; return 0;
Item *left_item= ((Item_func*) cond)->arguments()[0]; Item *left_item= ((Item_func*) cond)->arguments()[0];
Item *right_item= ((Item_func*) cond)->arguments()[1]; Item *right_item= ((Item_func*) cond)->arguments()[1];
if (left_item->eq(comp_item)) if (left_item->eq(comp_item,1))
{ {
if (right_item->const_item()) if (right_item->const_item())
{ {
if (*const_item) if (*const_item)
return right_item->eq(*const_item); return right_item->eq(*const_item, 1);
*const_item=right_item; *const_item=right_item;
return 1; return 1;
} }
} }
else if (right_item->eq(comp_item)) else if (right_item->eq(comp_item,1))
{ {
if (left_item->const_item()) if (left_item->const_item())
{ {
if (*const_item) if (*const_item)
return left_item->eq(*const_item); return left_item->eq(*const_item, 1);
*const_item=left_item; *const_item=left_item;
return 1; return 1;
} }
...@@ -4970,7 +4970,7 @@ static bool test_if_ref(Item_field *left_item,Item *right_item) ...@@ -4970,7 +4970,7 @@ static bool test_if_ref(Item_field *left_item,Item *right_item)
if (!field->table->const_table && !field->table->maybe_null) if (!field->table->const_table && !field->table->maybe_null)
{ {
Item *ref_item=part_of_refkey(field->table,field); Item *ref_item=part_of_refkey(field->table,field);
if (ref_item && ref_item->eq(right_item)) if (ref_item && ref_item->eq(right_item,1))
{ {
if (right_item->type() == Item::FIELD_ITEM) if (right_item->type() == Item::FIELD_ITEM)
return (field->eq_def(((Item_field *) right_item)->field)); return (field->eq_def(((Item_field *) right_item)->field));
...@@ -6151,7 +6151,7 @@ test_if_subpart(ORDER *a,ORDER *b) ...@@ -6151,7 +6151,7 @@ test_if_subpart(ORDER *a,ORDER *b)
{ {
for (; a && b; a=a->next,b=b->next) for (; a && b; a=a->next,b=b->next)
{ {
if ((*a->item)->eq(*b->item)) if ((*a->item)->eq(*b->item,1))
a->asc=b->asc; a->asc=b->asc;
else else
return 0; return 0;
...@@ -6178,7 +6178,7 @@ get_sort_by_table(ORDER *a,ORDER *b,TABLE_LIST *tables) ...@@ -6178,7 +6178,7 @@ get_sort_by_table(ORDER *a,ORDER *b,TABLE_LIST *tables)
for (; a && b; a=a->next,b=b->next) for (; a && b; a=a->next,b=b->next)
{ {
if (!(*a->item)->eq(*b->item)) if (!(*a->item)->eq(*b->item,1))
DBUG_RETURN(0); DBUG_RETURN(0);
map|=a->item[0]->used_tables(); map|=a->item[0]->used_tables();
} }
......
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