mirror of
https://github.com/MariaDB/server.git
synced 2025-07-29 05:21:33 +03:00
Fix for bug in WHERE key='j' or key='J'
This commit is contained in:
@ -46897,6 +46897,8 @@ not yet 100% confident in this code.
|
||||
@appendixsubsec Changes in release 3.23.50
|
||||
@itemize @bullet
|
||||
@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
|
||||
INFILE} without an active database.
|
||||
@item
|
||||
@ -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.
|
||||
@item
|
||||
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
|
||||
Added options to make @code{LOAD DATA LOCAL INFILE} more secure.
|
||||
@item
|
||||
|
@ -251,7 +251,7 @@ static struct option long_options[] =
|
||||
|
||||
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)
|
||||
@ -594,10 +594,7 @@ static int compress(PACK_MRG_INFO *mrg,char *result_table)
|
||||
else
|
||||
{
|
||||
if (tmp_dir[0])
|
||||
{
|
||||
if (!(error=my_copy(new_name,org_name,MYF(MY_WME))))
|
||||
VOID(my_delete(new_name,MYF(MY_WME)));
|
||||
}
|
||||
error=my_copy(new_name,org_name,MYF(MY_WME));
|
||||
else
|
||||
error=my_rename(new_name,org_name,MYF(MY_WME));
|
||||
if (!error)
|
||||
@ -607,13 +604,8 @@ static int compress(PACK_MRG_INFO *mrg,char *result_table)
|
||||
else
|
||||
{
|
||||
if (tmp_dir[0])
|
||||
{
|
||||
|
||||
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)));
|
||||
}
|
||||
error=my_copy(new_name,org_name,
|
||||
MYF(MY_WME | MY_HOLD_ORIGINAL_MODES | MY_COPYTIME));
|
||||
else
|
||||
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)
|
||||
if (error)
|
||||
{
|
||||
VOID(fprintf(stderr,"Aborting: %s is not compressed\n",org_name));
|
||||
VOID(my_delete(new_name,MYF(MY_WME)));
|
||||
DBUG_RETURN(-1);
|
||||
}
|
||||
if (write_loop || verbose)
|
||||
|
@ -55,3 +55,13 @@ believe
|
||||
believe in love
|
||||
aString
|
||||
believe in myself
|
||||
count(*)
|
||||
602
|
||||
count(*)
|
||||
602
|
||||
count(*)
|
||||
602
|
||||
count(*)
|
||||
389
|
||||
count(*)
|
||||
213
|
||||
|
@ -105,7 +105,6 @@ drop table t1;
|
||||
# Problem with binary strings
|
||||
#
|
||||
|
||||
DROP TABLE IF EXISTS t1;
|
||||
CREATE TABLE t1 (
|
||||
t1ID int(10) unsigned NOT NULL auto_increment,
|
||||
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'
|
||||
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';
|
||||
select count(*) from t1 where art = 'J';
|
||||
drop table t1;
|
||||
|
23
sql/item.cc
23
sql/item.cc
@ -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 &&
|
||||
!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.
|
||||
As a extra convenience the time structure is reset on error!
|
||||
@ -202,7 +218,7 @@ longlong Item_field::val_int_result()
|
||||
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;
|
||||
}
|
||||
@ -245,7 +261,8 @@ void Item_string::print(String *str)
|
||||
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; }
|
||||
longlong Item_null::val_int() { null_value=1; return 0; }
|
||||
/* ARGSUSED */
|
||||
|
10
sql/item.h
10
sql/item.h
@ -56,7 +56,7 @@ public:
|
||||
virtual void save_org_in_field(Field *field)
|
||||
{ (void) save_in_field(field); }
|
||||
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 enum Type type() const =0;
|
||||
virtual double val()=0;
|
||||
@ -109,7 +109,7 @@ public:
|
||||
{}
|
||||
Item_field(Field *field);
|
||||
enum Type type() const { return FIELD_ITEM; }
|
||||
bool eq(const Item *item) const;
|
||||
bool eq(const Item *item, bool binary_cmp) const;
|
||||
double val();
|
||||
longlong val_int();
|
||||
String *val_str(String*);
|
||||
@ -138,7 +138,7 @@ public:
|
||||
Item_null(char *name_par=0)
|
||||
{ maybe_null=null_value=TRUE; name= name_par ? name_par : (char*) "NULL";}
|
||||
enum Type type() const { return NULL_ITEM; }
|
||||
bool eq(const Item *item) const;
|
||||
bool eq(const Item *item, bool binary_cmp) const;
|
||||
double val();
|
||||
longlong val_int();
|
||||
String *val_str(String *str);
|
||||
@ -247,6 +247,7 @@ public:
|
||||
void make_field(Send_field *field);
|
||||
enum Item_result result_type () const { return STRING_RESULT; }
|
||||
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); }
|
||||
String *const_string() { return &str_value; }
|
||||
inline void append(char *str,uint length) { str_value.append(str,length); }
|
||||
@ -306,7 +307,8 @@ public:
|
||||
Item_ref(Item **item, char *table_name_par,char *field_name_par)
|
||||
:Item_ident(NullS,table_name_par,field_name_par),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; }
|
||||
double val()
|
||||
{
|
||||
|
@ -148,7 +148,7 @@ void Item_func::print_op(String *str)
|
||||
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 */
|
||||
if (this == item)
|
||||
@ -160,7 +160,7 @@ bool Item_func::eq(const Item *item) const
|
||||
func_name() != item_func->func_name())
|
||||
return 0;
|
||||
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 1;
|
||||
}
|
||||
@ -1882,7 +1882,7 @@ void Item_func_get_user_var::print(String *str)
|
||||
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 */
|
||||
if (this == item)
|
||||
@ -2135,7 +2135,7 @@ bool Item_func_match::fix_index()
|
||||
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)
|
||||
return 0;
|
||||
@ -2146,7 +2146,7 @@ bool Item_func_match::eq(const Item *item) const
|
||||
Item_func_match *ifm=(Item_func_match*) item;
|
||||
|
||||
if (key == ifm->key && table == ifm->table &&
|
||||
key_item()->eq(ifm->key_item()))
|
||||
key_item()->eq(ifm->key_item(), binary_cmp))
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
|
@ -98,7 +98,7 @@ public:
|
||||
void make_field(Send_field *field);
|
||||
table_map used_tables() const;
|
||||
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 bool have_rev_func() const { return 0; }
|
||||
virtual Item *key_item() const { return args[0]; }
|
||||
@ -842,7 +842,7 @@ public:
|
||||
bool const_item() const { return const_var_flag; }
|
||||
table_map used_tables() const
|
||||
{ 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 @@ public:
|
||||
enum Functype functype() const { return FT_FUNC; }
|
||||
void update_used_tables() {}
|
||||
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();
|
||||
longlong val_int() { return val()!=0.0; }
|
||||
|
||||
|
@ -1718,7 +1718,7 @@ find_item_in_list(Item *find,List<Item> &items)
|
||||
{
|
||||
if (found)
|
||||
{
|
||||
if ((*found)->eq(item))
|
||||
if ((*found)->eq(item,0))
|
||||
continue; // Same field twice (Access?)
|
||||
if (current_thd->where)
|
||||
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)
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (!table_name && (item->eq(find) ||
|
||||
else if (!table_name && (item->eq(find,0) ||
|
||||
find->name &&
|
||||
!my_strcasecmp(item->name,find->name)))
|
||||
{
|
||||
@ -2213,7 +2213,7 @@ int setup_ftfuncs(THD *thd)
|
||||
lj.rewind();
|
||||
while ((ftf2=lj++) != ftf)
|
||||
{
|
||||
if (ftf->eq(ftf2) && !ftf2->master)
|
||||
if (ftf->eq(ftf2,1) && !ftf2->master)
|
||||
ftf2->master=ftf;
|
||||
}
|
||||
}
|
||||
|
@ -1100,14 +1100,14 @@ merge_key_fields(KEY_FIELD *start,KEY_FIELD *new_fields,KEY_FIELD *end,
|
||||
{
|
||||
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->exists_optimize&=new_fields->exists_optimize;
|
||||
}
|
||||
}
|
||||
else if (old->val->eq(new_fields->val) && old->eq_func &&
|
||||
new_fields->eq_func)
|
||||
else if (old->val->eq(new_fields->val, old->field->binary()) &&
|
||||
old->eq_func && new_fields->eq_func)
|
||||
{
|
||||
old->level=old->const_level=and_level;
|
||||
old->exists_optimize&=new_fields->exists_optimize;
|
||||
@ -2602,7 +2602,7 @@ eq_ref_table(JOIN *join, ORDER *start_order, JOIN_TAB *tab)
|
||||
ORDER *order;
|
||||
for (order=start_order ; order ; order=order->next)
|
||||
{
|
||||
if ((*ref_item)->eq(order->item[0]))
|
||||
if ((*ref_item)->eq(order->item[0],0))
|
||||
break;
|
||||
}
|
||||
if (order)
|
||||
@ -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_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();
|
||||
if (tmp)
|
||||
@ -2878,7 +2878,7 @@ change_cond_ref_to_const(I_List<COND_CMP> *save_list,Item *and_father,
|
||||
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();
|
||||
if (tmp)
|
||||
@ -3118,7 +3118,7 @@ remove_eq_conds(COND *cond,Item::cond_result *cond_value)
|
||||
{ // boolan compare function
|
||||
Item *left_item= ((Item_func*) cond)->arguments()[0];
|
||||
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 ||
|
||||
((Item_func*) cond)->functype() == Item_func::EQUAL_FUNC)
|
||||
@ -3163,22 +3163,22 @@ const_expression_in_where(COND *cond, Item *comp_item, Item **const_item)
|
||||
return 0;
|
||||
Item *left_item= ((Item_func*) cond)->arguments()[0];
|
||||
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 (*const_item)
|
||||
return right_item->eq(*const_item);
|
||||
return right_item->eq(*const_item, 1);
|
||||
*const_item=right_item;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
else if (right_item->eq(comp_item))
|
||||
else if (right_item->eq(comp_item,1))
|
||||
{
|
||||
if (left_item->const_item())
|
||||
{
|
||||
if (*const_item)
|
||||
return left_item->eq(*const_item);
|
||||
return left_item->eq(*const_item, 1);
|
||||
*const_item=left_item;
|
||||
return 1;
|
||||
}
|
||||
@ -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)
|
||||
{
|
||||
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)
|
||||
return (field->eq_def(((Item_field *) right_item)->field));
|
||||
@ -6151,7 +6151,7 @@ test_if_subpart(ORDER *a,ORDER *b)
|
||||
{
|
||||
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;
|
||||
else
|
||||
return 0;
|
||||
@ -6178,7 +6178,7 @@ get_sort_by_table(ORDER *a,ORDER *b,TABLE_LIST *tables)
|
||||
|
||||
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);
|
||||
map|=a->item[0]->used_tables();
|
||||
}
|
||||
|
Reference in New Issue
Block a user