summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorunknown <bar@bar.mysql.r18.ru>2003-06-24 17:12:07 +0500
committerunknown <bar@bar.mysql.r18.ru>2003-06-24 17:12:07 +0500
commit3eaf8865ecdb8db3e5bc7c1b59716dfcff79dc92 (patch)
tree77e24de3dd69ace8f45ad249879fa0b92f6e44d7
parent40654c71f4275c5ec324142a7a640f8ae08e7f54 (diff)
downloadmariadb-git-3eaf8865ecdb8db3e5bc7c1b59716dfcff79dc92.tar.gz
String comparison functions now use the same DTCollation with
CONCAT() and other string functions. This allows to reuse a lot if code and to simplify further development.
-rw-r--r--sql/item.cc67
-rw-r--r--sql/item.h12
-rw-r--r--sql/item_cmpfunc.cc135
-rw-r--r--sql/item_cmpfunc.h10
-rw-r--r--sql/item_func.cc5
-rw-r--r--sql/item_strfunc.cc50
6 files changed, 111 insertions, 168 deletions
diff --git a/sql/item.cc b/sql/item.cc
index 4c7b30b0410..950f27c5d69 100644
--- a/sql/item.cc
+++ b/sql/item.cc
@@ -183,44 +183,61 @@ CHARSET_INFO * Item::default_charset() const
return current_thd->variables.collation_connection;
}
-bool Item::set_charset(CHARSET_INFO *cs1, Derivation co1,
- CHARSET_INFO *cs2, Derivation co2)
+bool DTCollation::aggregate(DTCollation &dt)
{
- if (cs1 == &my_charset_bin || cs2 == &my_charset_bin)
+ if (collation == &my_charset_bin || dt.collation == &my_charset_bin)
{
- set_charset(&my_charset_bin, DERIVATION_NONE);
+ collation= &my_charset_bin;
+ derivation= derivation > dt.derivation ? derivation : dt.derivation;
return 0;
}
-
- if (!my_charset_same(cs1,cs2))
- return 1;
-
- if (co1 < co2)
+
+ if (!my_charset_same(collation, dt.collation))
{
- set_charset(cs1, co1);
+ /*
+ We do allow to use binary strings (like BLOBS)
+ together with character strings.
+ Binaries have more precedance
+ */
+ if ((derivation <= dt.derivation) && (collation == &my_charset_bin))
+ {
+ // Do nothing
+ }
+ else if ((dt.derivation <= derivation) && (dt.collation==&my_charset_bin))
+ {
+ set(dt);
+ }
+ else
+ {
+ set(0, DERIVATION_NONE);
+ return 1;
+ }
}
- else if (co2 < co1)
+ else if (derivation < dt.derivation)
{
- set_charset(cs2, co2);
+ // Do nothing
}
- else // co2 == co1
+ else if (dt.derivation < derivation)
{
- if (cs1 != cs2)
+ set(dt);
+ }
+ else
+ {
+ if (collation == dt.collation)
{
- if (co1 == DERIVATION_EXPLICIT)
- {
- return 1;
- }
- else
+ // Do nothing
+ }
+ else
+ {
+ if (derivation == DERIVATION_EXPLICIT)
{
- CHARSET_INFO *bin= get_charset_by_csname(cs1->csname, MY_CS_BINSORT,MYF(0));
- if (!bin)
- return 1;
- set_charset(bin, DERIVATION_NONE);
+ set(0, DERIVATION_NONE);
+ return 1;
}
+ CHARSET_INFO *bin= get_charset_by_csname(collation->csname,
+ MY_CS_BINSORT,MYF(0));
+ set(bin, DERIVATION_NONE);
}
- else
- set_charset(cs2, co2);
}
return 0;
}
diff --git a/sql/item.h b/sql/item.h
index ce79e70e5d6..e80648b89de 100644
--- a/sql/item.h
+++ b/sql/item.h
@@ -52,10 +52,10 @@ public:
collation= collation_arg;
derivation= derivation_arg;
}
- void set(DTCollation *dt)
+ void set(DTCollation &dt)
{
- collation= dt->collation;
- derivation= dt->derivation;
+ collation= dt.collation;
+ derivation= dt.derivation;
}
void set(CHARSET_INFO *collation_arg, Derivation derivation_arg)
{
@@ -66,7 +66,9 @@ public:
{ collation= collation_arg; }
void set(Derivation derivation_arg)
{ derivation= derivation_arg; }
- bool aggregate(DTCollation *dt);
+ bool aggregate(DTCollation &dt);
+ bool set(DTCollation &dt1, DTCollation &dt2)
+ { set(dt1); return aggregate(dt2); }
const char *derivation_name() const
{
switch(derivation)
@@ -183,8 +185,6 @@ public:
collation.collation= collation_arg->collation;
collation.derivation= collation_arg->derivation;
}
- bool set_charset(CHARSET_INFO *cs1, Derivation dv1,
- CHARSET_INFO *cs2, Derivation dv2);
bool binary() const
{ return charset()->state & MY_CS_BINSORT ? 1 : 0 ; }
diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc
index 035f85a45ba..52bd14ed515 100644
--- a/sql/item_cmpfunc.cc
+++ b/sql/item_cmpfunc.cc
@@ -96,72 +96,26 @@ static bool convert_constant_item(Field *field, Item **item)
return 0;
}
-bool Item_bool_func2::set_cmp_charset(CHARSET_INFO *cs1, Derivation co1,
- CHARSET_INFO *cs2, Derivation co2)
-{
- if (cs1 == &my_charset_bin || cs2 == &my_charset_bin)
- {
- cmp_charset= &my_charset_bin;
- //coercibility= co1 > co2 ? co1 : co2;
- return 0;
- }
-
- if (!my_charset_same(cs1, cs2))
- {
- /*
- We do allow to use BLOBS together with character strings
- BLOBS have more precedance
- */
- if ((co1 <= co2) && (cs1==&my_charset_bin))
- {
- cmp_charset= cs1;
- //coercibility= co1;
- }
- else if ((co2 <= co1) && (cs2==&my_charset_bin))
- {
- cmp_charset= cs2;
- //coercibility= co2;
- }
- else
- {
- cmp_charset= 0;
- //coercibility= DERIVATION_NOCOLL;
- return 1;
- }
- }
- else if (co1 < co2)
- {
- cmp_charset= cs1;
- //coercibility= co1;
- }
- else if (co2 < co1)
- {
- cmp_charset= cs2;
- //coercibility= co1;
- }
- else
- {
- if (cs1 == cs2)
- {
- cmp_charset= cs1;
- //coercibility= co1;
- }
- else
- {
- //coercibility= DERIVATION_NOCOLL;
- cmp_charset= 0;
- return (co1 == DERIVATION_EXPLICIT) ? 1 : 0;
- }
- }
- return 0;
-}
-
bool Item_bool_func2::fix_fields(THD *thd, struct st_table_list *tables,
Item ** ref)
{
if (Item_int_func::fix_fields(thd, tables, ref))
return 1;
+ return 0;
+}
+
+
+void Item_bool_func2::fix_length_and_dec()
+{
+ max_length= 1; // Function returns 0 or 1
+
+ /*
+ As some compare functions are generated after sql_yacc,
+ we have to check for out of memory conditions here
+ */
+ if (!args[0] || !args[1])
+ return;
/*
We allow to convert to Unicode character sets in some cases.
@@ -209,35 +163,12 @@ bool Item_bool_func2::fix_fields(THD *thd, struct st_table_list *tables,
else
{
conv= new Item_func_conv_charset(args[weak],args[strong]->charset());
- //conv->coercibility= args[weak]->derivation();
+ conv->collation.set(args[weak]->derivation());
}
args[weak]= conv ? conv : args[weak];
- set_cmp_charset(args[0]->charset(), args[0]->derivation(),
- args[1]->charset(), args[1]->derivation());
}
}
- if (!cmp_charset)
- {
- /* set_cmp_charset() failed */
- my_coll_agg_error(args[0]->collation, args[1]->collation, func_name());
- return 1;
- }
- return 0;
-}
-
-
-void Item_bool_func2::fix_length_and_dec()
-{
- max_length= 1; // Function returns 0 or 1
-
- /*
- As some compare functions are generated after sql_yacc,
- we have to check for out of memory conditions here
- */
- if (!args[0] || !args[1])
- return;
-
-
+
// Make a special case of compare with fields to get nicer DATE comparisons
if (args[0]->type() == FIELD_ITEM)
{
@@ -248,7 +179,8 @@ void Item_bool_func2::fix_length_and_dec()
{
cmp.set_cmp_func(this, tmp_arg, tmp_arg+1,
INT_RESULT); // Works for all types.
- cmp_charset= &my_charset_bin; // For test in fix_fields
+ cmp_collation.set(&my_charset_bin,
+ DERIVATION_NONE); // For test in fix_fields
return;
}
}
@@ -262,7 +194,8 @@ void Item_bool_func2::fix_length_and_dec()
{
cmp.set_cmp_func(this, tmp_arg, tmp_arg+1,
INT_RESULT); // Works for all types.
- cmp_charset= &my_charset_bin; // For test in fix_fields
+ cmp_collation.set(&my_charset_bin,
+ DERIVATION_NONE); // For test in fix_fields
return;
}
}
@@ -272,8 +205,12 @@ void Item_bool_func2::fix_length_and_dec()
We must set cmp_charset here as we may be called from for an automatic
generated item, like in natural join
*/
- set_cmp_charset(args[0]->charset(), args[0]->derivation(),
- args[1]->charset(), args[1]->derivation());
+ if (cmp_collation.set(args[0]->collation, args[1]->collation))
+ {
+ /* set_cmp_charset() failed */
+ my_coll_agg_error(args[0]->collation, args[1]->collation, func_name());
+ return;
+ }
}
@@ -315,7 +252,7 @@ int Arg_comparator::compare_string()
if ((res2= (*b)->val_str(&owner->tmp_value2)))
{
owner->null_value= 0;
- return sortcmp(res1,res2,owner->cmp_charset);
+ return sortcmp(res1,res2,owner->cmp_collation.collation);
}
}
owner->null_value= 1;
@@ -329,7 +266,7 @@ int Arg_comparator::compare_e_string()
res2= (*b)->val_str(&owner->tmp_value2);
if (!res1 || !res2)
return test(res1 == res2);
- return test(sortcmp(res1, res2, owner->cmp_charset) == 0);
+ return test(sortcmp(res1, res2, owner->cmp_collation.collation) == 0);
}
@@ -558,7 +495,7 @@ longlong Item_func_strcmp::val_int()
null_value=1;
return 0;
}
- int value= sortcmp(a,b,cmp_charset);
+ int value= sortcmp(a,b,cmp_collation.collation);
null_value=0;
return !value ? 0 : (value < 0 ? (longlong) -1 : (longlong) 1);
}
@@ -750,8 +687,7 @@ Item_func_ifnull::fix_length_and_dec()
args[1]->result_type())) !=
REAL_RESULT)
decimals= 0;
- if (set_charset(args[0]->charset(),args[0]->derivation(),
- args[1]->charset(),args[1]->derivation()))
+ if (collation.set(args[0]->collation,args[1]->collation))
my_coll_agg_error(args[0]->collation, args[1]->collation, func_name());
}
@@ -828,8 +764,7 @@ Item_func_if::fix_length_and_dec()
else if (arg1_type == STRING_RESULT || arg2_type == STRING_RESULT)
{
cached_result_type = STRING_RESULT;
- if (set_charset(args[1]->charset(), args[1]->derivation(),
- args[2]->charset(), args[2]->derivation()))
+ if (collation.set(args[1]->collation, args[2]->collation))
{
my_coll_agg_error(args[0]->collation, args[1]->collation, func_name());
return;
@@ -1944,7 +1879,7 @@ longlong Item_func_like::val_int()
null_value=0;
if (canDoTurboBM)
return turboBM_matches(res->ptr(), res->length()) ? 1 : 0;
- return my_wildcmp(cmp_charset,
+ return my_wildcmp(cmp_collation.collation,
res->ptr(),res->ptr()+res->length(),
res2->ptr(),res2->ptr()+res2->length(),
escape,wild_one,wild_many) ? 0 : 1;
@@ -2148,7 +2083,7 @@ void Item_func_like::turboBM_compute_suffixes(int *suff)
*splm1 = pattern_len;
- if (cmp_charset == &my_charset_bin)
+ if (cmp_collation.collation == &my_charset_bin)
{
int i;
for (i = pattern_len - 2; i >= 0; i--)
@@ -2251,7 +2186,7 @@ void Item_func_like::turboBM_compute_bad_character_shifts()
for (i = bmBc; i < end; i++)
*i = pattern_len;
- if (cmp_charset == &my_charset_bin)
+ if (cmp_collation.collation == &my_charset_bin)
{
for (j = 0; j < plm1; j++)
bmBc[(uint) (uchar) pattern[j]] = plm1 - j;
@@ -2282,7 +2217,7 @@ bool Item_func_like::turboBM_matches(const char* text, int text_len) const
const int tlmpl= text_len - pattern_len;
/* Searching */
- if (cmp_charset == &my_charset_bin)
+ if (cmp_collation.collation == &my_charset_bin)
{
while (j <= tlmpl)
{
diff --git a/sql/item_cmpfunc.h b/sql/item_cmpfunc.h
index b38248d87e1..70e477402d9 100644
--- a/sql/item_cmpfunc.h
+++ b/sql/item_cmpfunc.h
@@ -112,25 +112,25 @@ class Item_bool_func2 :public Item_int_func
protected:
Arg_comparator cmp;
String tmp_value1,tmp_value2;
- CHARSET_INFO *cmp_charset;
+ DTCollation cmp_collation;
public:
Item_bool_func2(Item *a,Item *b):
- Item_int_func(a,b), cmp(tmp_arg, tmp_arg+1), cmp_charset(0) {}
+ Item_int_func(a,b), cmp(tmp_arg, tmp_arg+1)
+ { cmp_collation.set(0,DERIVATION_NONE);}
bool fix_fields(THD *thd, TABLE_LIST *tlist, Item ** ref);
void fix_length_and_dec();
void set_cmp_func()
{
cmp.set_cmp_func(this, tmp_arg, tmp_arg+1);
}
- bool set_cmp_charset(CHARSET_INFO *cs1, Derivation co1,
- CHARSET_INFO *cs2, Derivation co2);
optimize_type select_optimize() const { return OPTIMIZE_OP; }
virtual enum Functype rev_functype() const { return UNKNOWN_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 test(cmp_charset->state & MY_CS_BINSORT); }
+ virtual bool binary() const
+ { return test(cmp_collation.collation->state & MY_CS_BINSORT); }
static Item_bool_func2* eq_creator(Item *a, Item *b);
static Item_bool_func2* ne_creator(Item *a, Item *b);
diff --git a/sql/item_func.cc b/sql/item_func.cc
index 170260c6819..d0362ea9369 100644
--- a/sql/item_func.cc
+++ b/sql/item_func.cc
@@ -867,9 +867,8 @@ void Item_func_min_max::fix_length_and_dec()
maybe_null=0;
cmp_type=item_cmp_type(cmp_type,args[i]->result_type());
if (i==0)
- set_charset(*args[i]);
- else if (set_charset(charset(), derivation(),
- args[i]->charset(), args[i]->derivation()))
+ collation.set(args[0]->collation);
+ if (collation.aggregate(args[i]->collation))
{
my_coll_agg_error(collation, args[i]->collation, func_name());
break;
diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc
index 23df49c81be..1c770456793 100644
--- a/sql/item_strfunc.cc
+++ b/sql/item_strfunc.cc
@@ -324,12 +324,11 @@ void Item_func_concat::fix_length_and_dec()
bool first_coll= 1;
max_length=0;
- set_charset(*args[0]);
+ collation.set(args[0]->collation);
for (uint i=0 ; i < arg_count ; i++)
{
max_length+=args[i]->max_length;
- if (set_charset(charset(), derivation(),
- args[i]->charset(), args[i]->derivation()))
+ if (collation.aggregate(args[i]->collation))
{
my_coll_agg_error(collation, args[i]->collation, func_name());
break;
@@ -627,13 +626,12 @@ void Item_func_concat_ws::split_sum_func(Item **ref_pointer_array,
void Item_func_concat_ws::fix_length_and_dec()
{
- set_charset(*separator);
+ collation.set(separator->collation);
max_length=separator->max_length*(arg_count-1);
for (uint i=0 ; i < arg_count ; i++)
{
max_length+=args[i]->max_length;
- if (set_charset(charset(), derivation(),
- args[i]->charset(), args[i]->derivation()))
+ if (collation.aggregate(args[i]->collation))
{
my_coll_agg_error(collation, args[i]->collation, func_name());
break;
@@ -828,12 +826,11 @@ void Item_func_replace::fix_length_and_dec()
max_length=MAX_BLOB_WIDTH;
maybe_null=1;
}
- set_charset(*args[0]);
+ collation.set(args[0]->collation);
for (i=1; i<3; i++)
{
- if (set_charset(charset(), derivation(),
- args[i]->charset(), args[i]->derivation()))
+ if (collation.aggregate(args[i]->collation))
{
my_coll_agg_error(collation, args[i]->collation, func_name());
break;
@@ -875,10 +872,10 @@ null:
void Item_func_insert::fix_length_and_dec()
{
- if (set_charset(args[0]->charset(), args[0]->derivation(),
- args[3]->charset(), args[3]->derivation()))
+ if (collation.set(args[0]->collation, args[3]->collation))
{
my_coll_agg_error(args[0]->collation, args[3]->collation, func_name());
+ return;
}
max_length=args[0]->max_length+args[3]->max_length;
if (max_length > MAX_BLOB_WIDTH)
@@ -1316,13 +1313,12 @@ void Item_func_trim::fix_length_and_dec()
max_length= args[0]->max_length;
if (arg_count == 1)
{
- set_charset(*args[0]);
+ collation.set(args[0]->collation);
remove.set_charset(charset());
remove.set_ascii(" ",1);
}
else
- if (set_charset(args[1]->charset(), args[1]->derivation(),
- args[0]->charset(), args[0]->derivation()))
+ if (collation.set(args[1]->collation, args[0]->collation))
{
my_coll_agg_error(args[1]->collation, args[0]->collation, func_name());
}
@@ -1668,11 +1664,10 @@ void Item_func_elt::fix_length_and_dec()
set_if_bigger(max_length,args[i]->max_length);
set_if_bigger(decimals,args[i]->decimals);
if (i == 0)
- set_charset(*args[0]);
+ collation.set(args[0]->collation);
else
{
- if (set_charset(charset(), derivation(),
- args[i]->charset(), args[i]->derivation()))
+ if (collation.aggregate(args[i]->collation))
{
my_coll_agg_error(collation, args[i]->collation, func_name());
break;
@@ -1770,12 +1765,11 @@ void Item_func_make_set::split_sum_func(Item **ref_pointer_array,
void Item_func_make_set::fix_length_and_dec()
{
max_length=arg_count-1;
- set_charset(*args[0]);
+ collation.set(args[0]->collation);
for (uint i=0 ; i < arg_count ; i++)
{
max_length+=args[i]->max_length;
- if (set_charset(charset(), derivation(),
- args[i]->charset(), args[i]->derivation()))
+ if (collation.aggregate(args[i]->collation))
{
my_coll_agg_error(collation, args[i]->collation, func_name());
break;
@@ -1963,10 +1957,10 @@ err:
void Item_func_rpad::fix_length_and_dec()
{
- if (set_charset(args[0]->charset(), args[0]->derivation(),
- args[2]->charset(), args[2]->derivation()))
+ if (collation.set(args[0]->collation, args[2]->collation))
{
my_coll_agg_error(args[0]->collation, args[2]->collation, func_name());
+ return;
}
if (args[1]->const_item())
@@ -2029,10 +2023,10 @@ String *Item_func_rpad::val_str(String *str)
void Item_func_lpad::fix_length_and_dec()
{
- if (set_charset(args[0]->charset(), args[0]->derivation(),
- args[2]->charset(), args[2]->derivation()))
+ if (collation.set(args[0]->collation, args[2]->collation))
{
my_coll_agg_error(args[0]->collation, args[2]->collation, func_name());
+ return;
}
if (args[1]->const_item())
@@ -2152,9 +2146,8 @@ String *Item_func_conv_charset::val_str(String *str)
void Item_func_conv_charset::fix_length_and_dec()
{
- set_charset(conv_charset);
- max_length = args[0]->max_length*conv_charset->mbmaxlen;
set_charset(conv_charset, DERIVATION_IMPLICIT);
+ max_length = args[0]->max_length*conv_charset->mbmaxlen;
}
@@ -2449,11 +2442,10 @@ void Item_func_export_set::fix_length_and_dec()
uint sep_length=(arg_count > 3 ? args[3]->max_length : 1);
max_length=length*64+sep_length*63;
- set_charset(*args[1]);
+ collation.set(args[1]->collation);
for (i=2 ; i < 4 && i < arg_count ; i++)
{
- if (set_charset(charset(), derivation(),
- args[i]->charset(), args[i]->derivation()))
+ if (collation.aggregate(args[i]->collation))
{
my_coll_agg_error(collation, args[i]->collation, func_name());
break;