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