Commit f95eb829 authored by bar@bar.mysql.r18.ru's avatar bar@bar.mysql.r18.ru

stringcmp() and sortcmp() have been unified

into the only one sortcmp() with additional
CHARSET_INFO *cmp_charset argument.
parent 143c8505
......@@ -120,8 +120,8 @@ 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 !sortcmp(&str_value, &item->str_value, &my_charset_bin);
return !sortcmp(&str_value, &item->str_value, charset());
}
return 0;
}
......@@ -1355,7 +1355,7 @@ bool field_is_equal_to_item(Field *field,Item *item)
if (item->null_value)
return 1; // This must be true
field->val_str(&field_tmp,&field_tmp);
return !stringcmp(&field_tmp,item_result);
return !sortcmp(&field_tmp,item_result,&my_charset_bin);
}
if (res_type == INT_RESULT)
return 1; // Both where of type int
......
......@@ -56,10 +56,8 @@ bool Item_str_buff::cmp(void)
}
else if (null_value)
return 0; // new and old value was null
else if (!item->binary())
tmp= sortcmp(&value,res) != 0;
else
tmp= stringcmp(&value,res) != 0;
tmp= sortcmp(&value,res,item->charset()) != 0;
if (tmp)
value.copy(*res); // Remember for next cmp
return tmp;
......
......@@ -125,7 +125,9 @@ void Item_bool_func2::fix_length_and_dec()
}
}
set_cmp_func();
binary_cmp= args[0]->binary() || args[1]->binary();
/* QQ: COERCIBILITY */
cmp_charset= (args[0]->binary() || args[1]->binary()) ?
&my_charset_bin : args[0]->charset();
}
......@@ -167,7 +169,7 @@ int Arg_comparator::compare_string()
if ((res2= (*b)->val_str(&owner->tmp_value2)))
{
owner->null_value= 0;
return owner->binary_cmp ? stringcmp(res1,res2) : sortcmp(res1,res2);
return sortcmp(res1,res2,owner->cmp_charset);
}
}
owner->null_value= 1;
......@@ -181,8 +183,7 @@ int Arg_comparator::compare_e_string()
res2= (*b)->val_str(&owner->tmp_value2);
if (!res1 || !res2)
return test(res1 == res2);
return (owner->binary_cmp ? test(stringcmp(res1, res2) == 0) :
test(sortcmp(res1, res2) == 0));
return test(sortcmp(res1, res2, owner->cmp_charset) == 0);
}
......@@ -402,7 +403,7 @@ longlong Item_func_strcmp::val_int()
null_value=1;
return 0;
}
int value= binary_cmp ? stringcmp(a,b) : sortcmp(a,b);
int value= sortcmp(a,b,cmp_charset);
null_value=0;
return !value ? 0 : (value < 0 ? (longlong) -1 : (longlong) 1);
}
......@@ -482,10 +483,11 @@ void Item_func_between::fix_length_and_dec()
cmp_type=item_cmp_type(args[0]->result_type(),
item_cmp_type(args[1]->result_type(),
args[2]->result_type()));
/* QQ: COERCIBILITY */
if (args[0]->binary() | args[1]->binary() | args[2]->binary())
string_compare=stringcmp;
cmp_charset= &my_charset_bin;
else
string_compare=sortcmp;
cmp_charset= args[0]->charset();
/*
Make a special case of compare with date/time and longlong fields.
......@@ -517,17 +519,17 @@ longlong Item_func_between::val_int()
a=args[1]->val_str(&value1);
b=args[2]->val_str(&value2);
if (!args[1]->null_value && !args[2]->null_value)
return (string_compare(value,a) >= 0 && string_compare(value,b) <= 0) ?
1 : 0;
return (sortcmp(value,a,cmp_charset) >= 0 &&
sortcmp(value,b,cmp_charset) <= 0) ? 1 : 0;
if (args[1]->null_value && args[2]->null_value)
null_value=1;
else if (args[1]->null_value)
{
null_value= string_compare(value,b) <= 0; // not null if false range.
null_value= sortcmp(value,b,cmp_charset) <= 0; // not null if false range.
}
else
{
null_value= string_compare(value,a) >= 0; // not null if false range.
null_value= sortcmp(value,a,cmp_charset) >= 0; // not null if false range.
}
}
else if (cmp_type == INT_RESULT)
......@@ -809,12 +811,13 @@ Item *Item_func_case::find_item(String *str)
}
if ((tmp=args[i]->val_str(str))) // If not null
{
/* QQ: COERCIBILITY */
if (first_expr_is_binary || args[i]->binary())
{
if (stringcmp(tmp,first_expr_str)==0)
if (sortcmp(tmp,first_expr_str,&my_charset_bin)==0)
return args[i+1];
}
else if (sortcmp(tmp,first_expr_str)==0)
else if (sortcmp(tmp,first_expr_str,tmp->charset())==0)
return args[i+1];
}
break;
......@@ -1211,10 +1214,7 @@ cmp_item* cmp_item::get_comparator(Item *item)
{
switch (item->result_type()) {
case STRING_RESULT:
if (item->binary())
return new cmp_item_binary_string;
else
return new cmp_item_sort_string;
return new cmp_item_sort_string(item->charset());
break;
case INT_RESULT:
return new cmp_item_int;
......@@ -1234,12 +1234,7 @@ cmp_item* cmp_item::get_comparator(Item *item)
cmp_item* cmp_item_sort_string::make_same()
{
return new cmp_item_sort_string_in_static();
}
cmp_item* cmp_item_binary_string::make_same()
{
return new cmp_item_binary_string_in_static();
return new cmp_item_sort_string_in_static(cmp_charset);
}
cmp_item* cmp_item_int::make_same()
......@@ -1346,6 +1341,22 @@ bool Item_func_in::nulls_in_row()
return 0;
}
static int srtcmp_in(const String *x,const String *y)
{
CHARSET_INFO *cs= x->charset();
return cs->strnncollsp(cs,
(unsigned char *) x->ptr(),x->length(),
(unsigned char *) y->ptr(),y->length());
}
static int bincmp_in(const String *x,const String *y)
{
CHARSET_INFO *cs= &my_charset_bin;
return cs->strnncollsp(cs,
(unsigned char *) x->ptr(),x->length(),
(unsigned char *) y->ptr(),y->length());
}
void Item_func_in::fix_length_and_dec()
{
/*
......@@ -1357,9 +1368,9 @@ void Item_func_in::fix_length_and_dec()
switch (item->result_type()) {
case STRING_RESULT:
if (item->binary())
array=new in_string(arg_count,(qsort_cmp) stringcmp);
array=new in_string(arg_count,(qsort_cmp) srtcmp_in);
else
array=new in_string(arg_count,(qsort_cmp) sortcmp);
array=new in_string(arg_count,(qsort_cmp) bincmp_in);
break;
case INT_RESULT:
array= new in_longlong(arg_count);
......@@ -1759,8 +1770,9 @@ bool Item_func_like::fix_fields(THD *thd, TABLE_LIST *tlist, Item ** ref)
/*
Comparision is by default done according to character set of LIKE
QQ: COERCIBILITY
*/
if (binary_cmp)
if (cmp_charset == &my_charset_bin)
set_charset(&my_charset_bin);
else
set_charset(args[1]->charset());
......@@ -1877,7 +1889,7 @@ longlong Item_func_regex::val_int()
null_value=1;
return 0;
}
if (!regex_compiled || stringcmp(res2,&prev_regexp))
if (!regex_compiled || sortcmp(res2,&prev_regexp,&my_charset_bin))
{
prev_regexp.copy(*res2);
if (regex_compiled)
......@@ -1936,7 +1948,7 @@ void Item_func_like::turboBM_compute_suffixes(int *suff)
*splm1 = pattern_len;
if (binary_cmp)
if (cmp_charset == &my_charset_bin)
{
int i;
for (i = pattern_len - 2; i >= 0; i--)
......@@ -2039,7 +2051,7 @@ void Item_func_like::turboBM_compute_bad_character_shifts()
for (i = bmBc; i < end; i++)
*i = pattern_len;
if (binary_cmp)
if (cmp_charset == &my_charset_bin)
{
for (j = 0; j < plm1; j++)
bmBc[(uint) (uchar) pattern[j]] = plm1 - j;
......@@ -2070,7 +2082,7 @@ bool Item_func_like::turboBM_matches(const char* text, int text_len) const
const int tlmpl= text_len - pattern_len;
/* Searching */
if (binary_cmp)
if (cmp_charset == &my_charset_bin)
{
while (j <= tlmpl)
{
......
......@@ -112,7 +112,7 @@ class Item_bool_func2 :public Item_int_func
protected:
Arg_comparator cmp;
String tmp_value1,tmp_value2;
bool binary_cmp;
CHARSET_INFO *cmp_charset;
public:
Item_bool_func2(Item *a,Item *b):
......@@ -127,7 +127,7 @@ class Item_bool_func2 :public Item_int_func
bool have_rev_func() const { return rev_functype() != UNKNOWN_FUNC; }
void print(String *str) { Item_func::print_op(str); }
bool is_null() { return test(args[0]->is_null() || args[1]->is_null()); }
virtual bool binary() const { return binary_cmp; }
virtual bool binary() const { return test(cmp_charset->state & MY_CS_BINSORT); }
static Item_bool_func2* eq_creator(Item *a, Item *b);
static Item_bool_func2* ne_creator(Item *a, Item *b);
......@@ -242,7 +242,7 @@ class Item_func_ne :public Item_bool_rowready_func2
class Item_func_between :public Item_int_func
{
int (*string_compare)(const String *x,const String *y);
CHARSET_INFO *cmp_charset;
public:
Item_result cmp_type;
String value0,value1,value2;
......@@ -263,7 +263,9 @@ class Item_func_strcmp :public Item_bool_func2
void fix_length_and_dec()
{
max_length=2;
binary_cmp= args[0]->binary() || args[1]->binary();
/* QQ: COERCIBILITY */
cmp_charset= args[0]->binary() || args[1]->binary() ?
&my_charset_bin : args[0]->charset();
}
optimize_type select_optimize() const { return OPTIMIZE_NONE; }
const char *func_name() const { return "strcmp"; }
......@@ -439,7 +441,8 @@ class in_double :public in_vector
class cmp_item :public Sql_alloc
{
public:
cmp_item() {}
CHARSET_INFO *cmp_charset;
cmp_item() { cmp_charset= &my_charset_bin; }
virtual ~cmp_item() {}
virtual void store_value(Item *item)= 0;
virtual int cmp(Item *item)= 0;
......@@ -453,18 +456,14 @@ class cmp_item :public Sql_alloc
}
};
typedef int (*str_cmp_func_pointer)(const String *, const String *);
class cmp_item_string :public cmp_item
{
protected:
str_cmp_func_pointer str_cmp_func;
String *value_res;
public:
cmp_item_string (str_cmp_func_pointer cmp): str_cmp_func(cmp) {}
cmp_item_string (CHARSET_INFO *cs) { cmp_charset= cs; }
friend class cmp_item_sort_string;
friend class cmp_item_binary_string;
friend class cmp_item_sort_string_in_static;
friend class cmp_item_binary_string_in_static;
};
class cmp_item_sort_string :public cmp_item_string
......@@ -473,12 +472,9 @@ class cmp_item_sort_string :public cmp_item_string
char value_buff[80];
String value;
public:
cmp_item_sort_string(str_cmp_func_pointer cmp):
cmp_item_string(cmp),
value(value_buff, sizeof(value_buff), default_charset_info) {}
cmp_item_sort_string():
cmp_item_string(&sortcmp),
value(value_buff, sizeof(value_buff), default_charset_info) {}
cmp_item_sort_string(CHARSET_INFO *cs):
cmp_item_string(cs),
value(value_buff, sizeof(value_buff), cs) {}
void store_value(Item *item)
{
value_res= item->val_str(&value);
......@@ -489,22 +485,16 @@ class cmp_item_sort_string :public cmp_item_string
String tmp(buff, sizeof(buff), default_charset_info), *res;
if (!(res= arg->val_str(&tmp)))
return 1; /* Can't be right */
return (*str_cmp_func)(value_res, res);
return sortcmp(value_res, res, cmp_charset);
}
int compare(cmp_item *c)
{
cmp_item_string *cmp= (cmp_item_string *)c;
return (*str_cmp_func)(value_res, cmp->value_res);
return sortcmp(value_res, cmp->value_res, cmp_charset);
}
cmp_item *make_same();
};
class cmp_item_binary_string :public cmp_item_sort_string {
public:
cmp_item_binary_string(): cmp_item_sort_string(&stringcmp) {}
cmp_item *make_same();
};
class cmp_item_int :public cmp_item
{
longlong value;
......@@ -590,9 +580,8 @@ class cmp_item_sort_string_in_static :public cmp_item_string
protected:
String value;
public:
cmp_item_sort_string_in_static(str_cmp_func_pointer cmp):
cmp_item_string(cmp) {}
cmp_item_sort_string_in_static(): cmp_item_string(&sortcmp) {}
cmp_item_sort_string_in_static(CHARSET_INFO *cs):
cmp_item_string(cs) {}
void store_value(Item *item)
{
value_res= item->val_str(&value);
......@@ -606,21 +595,11 @@ class cmp_item_sort_string_in_static :public cmp_item_string
int compare(cmp_item *c)
{
cmp_item_string *cmp= (cmp_item_string *)c;
return (*str_cmp_func)(value_res, cmp->value_res);
return sortcmp(value_res, cmp->value_res, cmp_charset);
}
cmp_item * make_same()
{
return new cmp_item_sort_string_in_static();
}
};
class cmp_item_binary_string_in_static :public cmp_item_sort_string_in_static {
public:
cmp_item_binary_string_in_static():
cmp_item_sort_string_in_static(&stringcmp) {}
cmp_item * make_same()
{
return new cmp_item_binary_string_in_static();
return new cmp_item_sort_string_in_static(cmp_charset);
}
};
......
......@@ -107,7 +107,7 @@ Item_func::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
return 0; // Fatal error if flag is set!
if (arg_count)
{ // Print purify happy
coercibility= COER_NOCOLL;
bool first_coll= 1;
for (arg=args, arg_end=args+arg_count; arg != arg_end ; arg++)
{
if ((*arg)->fix_fields(thd, tables, arg) ||
......@@ -122,15 +122,17 @@ Item_func::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
Set return character set to first argument if we are returning a
string.
*/
if ((*arg)->binary())
if (first_coll)
{
set_charset(&my_charset_bin);
coercibility= COER_NOCOLL;
set_charset((*arg)->charset());
coercibility= (*args)->coercibility;
first_coll= 0;
}
else if (coercibility== COER_NOCOLL)
else if ((*arg)->charset() == &my_charset_bin ||
charset() == &my_charset_bin)
{
coercibility= (*arg)->coercibility;
set_charset((*arg)->charset());
set_charset(&my_charset_bin);
coercibility= COER_NOCOLL;
}
else if ((*arg)->coercibility < coercibility)
{
......@@ -864,6 +866,7 @@ void Item_func_min_max::fix_length_and_dec()
max_length=0;
maybe_null=1;
cmp_type=args[0]->result_type();
for (uint i=0 ; i < arg_count ; i++)
{
if (max_length < args[i]->max_length)
......@@ -873,11 +876,11 @@ void Item_func_min_max::fix_length_and_dec()
if (!args[i]->maybe_null)
maybe_null=0;
cmp_type=item_cmp_type(cmp_type,args[i]->result_type());
if (args[i]->binary())
if (i==0)
set_charset(args[i]->charset());
else if (args[i]->charset() == &my_charset_bin)
set_charset(&my_charset_bin);
}
if (cmp_type == STRING_RESULT)
str_cmp_function= binary() ? stringcmp : sortcmp;
}
......@@ -922,7 +925,7 @@ String *Item_func_min_max::val_str(String *str)
res2= args[i]->val_str(res == str ? &tmp_value : str);
if (res2)
{
int cmp= (*str_cmp_function)(res,res2);
int cmp= sortcmp(res,res2,charset());
if ((cmp_sign < 0 ? cmp : -cmp) < 0)
res=res2;
}
......
......@@ -524,7 +524,6 @@ class Item_func_min_max :public Item_func
Item_result cmp_type;
String tmp_value;
int cmp_sign;
int (*str_cmp_function)(const String *x,const String *y);
public:
Item_func_min_max(List<Item> &list,int cmp_sign_arg) :Item_func(list),
cmp_type(INT_RESULT), cmp_sign(cmp_sign_arg) {}
......
......@@ -183,12 +183,17 @@ Item_sum_hybrid::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
return 1;
hybrid_type=item->result_type();
if (hybrid_type == INT_RESULT)
{
cmp_charset= &my_charset_bin;
max_length=20;
}
else if (hybrid_type == REAL_RESULT)
{
cmp_charset= &my_charset_bin;
max_length=float_length(decimals);
else
}else
{
str_cmp_function= item->binary() ? stringcmp : sortcmp;
cmp_charset= item->charset();
max_length=item->max_length;
}
decimals=item->decimals;
......@@ -440,7 +445,7 @@ bool Item_sum_min::add()
{
String *result=args[0]->val_str(&tmp_value);
if (!args[0]->null_value &&
(null_value || (*str_cmp_function)(&value,result) > 0))
(null_value || sortcmp(&value,result,cmp_charset) > 0))
{
value.copy(*result);
null_value=0;
......@@ -487,7 +492,7 @@ bool Item_sum_max::add()
{
String *result=args[0]->val_str(&tmp_value);
if (!args[0]->null_value &&
(null_value || (*str_cmp_function)(&value,result) < 0))
(null_value || sortcmp(&value,result,cmp_charset) < 0))
{
value.copy(*result);
null_value=0;
......@@ -762,7 +767,7 @@ Item_sum_hybrid::min_max_update_str_field(int offset)
result_field->ptr-=offset;
if (result_field->is_null() ||
(cmp_sign * (*str_cmp_function)(res_str,&tmp_value)) < 0)
(cmp_sign * sortcmp(res_str,&tmp_value,cmp_charset)) < 0)
result_field->store(res_str->ptr(),res_str->length(),res_str->charset());
else
{ // Use old value
......
......@@ -369,17 +369,19 @@ class Item_sum_hybrid :public Item_sum
enum_field_types hybrid_field_type;
int cmp_sign;
table_map used_table_cache;
int (*str_cmp_function)(const String *x,const String *y);
CHARSET_INFO *cmp_charset;
public:
Item_sum_hybrid(Item *item_par,int sign)
:Item_sum(item_par), hybrid_type(INT_RESULT), cmp_sign(sign),
used_table_cache(~(table_map) 0)
used_table_cache(~(table_map) 0),
cmp_charset(&my_charset_bin)
{}
Item_sum_hybrid(THD *thd, Item_sum_hybrid &item):
Item_sum(thd, item), value(item.value), tmp_value(item.tmp_value),
sum(item.sum), sum_int(item.sum_int), hybrid_type(item.hybrid_type),
cmp_sign(item.cmp_sign), used_table_cache(used_table_cache) {}
cmp_sign(item.cmp_sign), used_table_cache(used_table_cache),
cmp_charset(item.cmp_charset) {}
bool fix_fields(THD *, TABLE_LIST *, Item **);
table_map used_tables() const { return used_table_cache; }
bool const_item() const { return !used_table_cache; }
......
......@@ -41,13 +41,13 @@
int sortcmp2(void* cmp_arg __attribute__((unused)),
const String *a,const String *b)
{
return sortcmp(a,b);
return sortcmp(a,b,a->charset());
}
int stringcmp2(void* cmp_arg __attribute__((unused)),
const String *a,const String *b)
{
return stringcmp(a,b);
return sortcmp(a,b,&my_charset_bin);
}
int compare_double2(void* cmp_arg __attribute__((unused)),
......@@ -329,20 +329,10 @@ void field_str::add()
if (length > max_length)
max_length = length;
if (item->binary())
{
if (stringcmp(res, &min_arg) < 0)
min_arg.copy(*res);
if (stringcmp(res, &max_arg) > 0)
max_arg.copy(*res);
}
else
{
if (sortcmp(res, &min_arg) < 0)
min_arg.copy(*res);
if (sortcmp(res, &max_arg) > 0)
max_arg.copy(*res);
}
if (sortcmp(res, &min_arg,item->charset()) < 0)
min_arg.copy(*res);
if (sortcmp(res, &max_arg,item->charset()) > 0)
max_arg.copy(*res);
}
if (room_in_tree)
......
......@@ -538,30 +538,14 @@ void String::qs_append(const char &c)
}
int sortcmp(const String *x,const String *y)
int sortcmp(const String *x,const String *y, CHARSET_INFO *cs)
{
CHARSET_INFO *cs= x->str_charset;
return cs->strnncollsp(cs,
(unsigned char *) x->ptr(),x->length(),
(unsigned char *) y->ptr(),y->length());
}
int stringcmp(const String *x,const String *y)
{
const char *s= x->ptr();
const char *t= y->ptr();
uint32 x_len=x->length(),y_len=y->length(),len=min(x_len,y_len);
while (len--)
{
if (*s++ != *t++)
return ((int) (uchar) s[-1] - (int) (uchar) t[-1]);
}
return (int) (x_len-y_len);
}
String *copy_if_not_alloced(String *to,String *from,uint32 from_length)
{
if (from->Alloced_length >= from_length)
......
......@@ -25,8 +25,7 @@
#endif
class String;
int sortcmp(const String *a,const String *b);
int stringcmp(const String *a,const String *b);
int sortcmp(const String *a,const String *b, CHARSET_INFO *cs);
String *copy_if_not_alloced(String *a,String *b,uint32 arg_length);
class String
......@@ -205,8 +204,7 @@ class String
void strip_sp();
inline void caseup() { my_caseup(str_charset,Ptr,str_length); }
inline void casedn() { my_casedn(str_charset,Ptr,str_length); }
friend int sortcmp(const String *a,const String *b);
friend int stringcmp(const String *a,const String *b);
friend int sortcmp(const String *a,const String *b, CHARSET_INFO *cs);
friend String *copy_if_not_alloced(String *a,String *b,uint32 arg_length);
uint32 numchars();
int charpos(int i,uint32 offset=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