summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorunknown <bar@bar.mysql.r18.ru>2003-05-23 10:45:46 +0500
committerunknown <bar@bar.mysql.r18.ru>2003-05-23 10:45:46 +0500
commit5d4fbc021a0bba300f85c0136a467e6961af5555 (patch)
tree9cf7ca218ba396f6b8fea51d4289850601b748a5
parent46c730e62cd02a6e68aded98e03d633c14e61f3b (diff)
downloadmariadb-git-5d4fbc021a0bba300f85c0136a467e6961af5555.tar.gz
Automatic conversion into supersets (utf8, ucs2) for comparison in some cases
USER(), DATABASE() and VERSION() return in utf8 now
-rw-r--r--sql/item_cmpfunc.cc56
-rw-r--r--sql/item_strfunc.cc8
-rw-r--r--sql/item_strfunc.h8
3 files changed, 65 insertions, 7 deletions
diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc
index dfc46793ee7..7392ef6c276 100644
--- a/sql/item_cmpfunc.cc
+++ b/sql/item_cmpfunc.cc
@@ -133,6 +133,60 @@ bool Item_bool_func2::fix_fields(THD *thd, struct st_table_list *tables,
{
if (Item_int_func::fix_fields(thd, tables, ref))
return 1;
+
+ /*
+ We allow to convert to Unicode character sets in some cases.
+ The conditions when conversion is possible are:
+ - arguments A and B have different charsets
+ - A wins according to coercibility rules
+ - character set of A is superset for character set of B
+
+ If all of the above is true, then it's possible to convert
+ B into the character set of A, and then compare according
+ to the collation of A.
+ */
+
+ if (args[0] && args[1])
+ {
+ uint strong= 0;
+ uint weak= 0;
+
+ if ((args[0]->coercibility < args[1]->coercibility) &&
+ !my_charset_same(args[0]->charset(), args[1]->charset()) &&
+ (args[0]->charset()->state & MY_CS_UNICODE))
+ {
+ weak= 1;
+ }
+ else if ((args[1]->coercibility < args[0]->coercibility) &&
+ !my_charset_same(args[0]->charset(), args[1]->charset()) &&
+ (args[1]->charset()->state & MY_CS_UNICODE))
+ {
+ strong= 1;
+ }
+
+ if (strong || weak)
+ {
+ Item* conv= 0;
+ if (args[weak]->type() == STRING_ITEM)
+ {
+ String tmp, cstr;
+ String *ostr= args[weak]->val_str(&tmp);
+ cstr.copy(ostr->ptr(), ostr->length(), ostr->charset(),
+ args[strong]->charset());
+ conv= new Item_string(cstr.ptr(),cstr.length(),cstr.charset(),
+ args[weak]->coercibility);
+ ((Item_string*)conv)->str_value.copy();
+ }
+ else
+ {
+ conv= new Item_func_conv_charset(args[weak],args[strong]->charset());
+ conv->coercibility= args[weak]->coercibility;
+ }
+ args[weak]= conv ? conv : args[weak];
+ set_cmp_charset(args[0]->charset(), args[0]->coercibility,
+ args[1]->charset(), args[1]->coercibility);
+ }
+ }
if (!cmp_charset)
{
/* set_cmp_charset() failed */
@@ -156,6 +210,8 @@ void Item_bool_func2::fix_length_and_dec()
*/
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)
{
diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc
index dd48314596b..078e3f213a0 100644
--- a/sql/item_strfunc.cc
+++ b/sql/item_strfunc.cc
@@ -1459,10 +1459,12 @@ String *Item_func_database::val_str(String *str)
{
THD *thd= current_thd;
if (!thd->db)
+ {
str->length(0);
+ str->set_charset(system_charset_info);
+ }
else
- str->copy((const char*) thd->db,(uint) strlen(thd->db),
- system_charset_info, default_charset());
+ str->copy((const char*) thd->db,(uint) strlen(thd->db),system_charset_info);
return str;
}
@@ -1471,7 +1473,7 @@ String *Item_func_database::val_str(String *str)
String *Item_func_user::val_str(String *str)
{
THD *thd=current_thd;
- CHARSET_INFO *cs= default_charset();
+ CHARSET_INFO *cs= system_charset_info;
const char *host= thd->host_or_ip;
uint res_length;
diff --git a/sql/item_strfunc.h b/sql/item_strfunc.h
index c798faddfcb..8ae5c995375 100644
--- a/sql/item_strfunc.h
+++ b/sql/item_strfunc.h
@@ -337,8 +337,8 @@ public:
String *val_str(String *);
void fix_length_and_dec()
{
- max_length= MAX_FIELD_NAME * default_charset()->mbmaxlen;
- set_charset(default_charset());
+ max_length= MAX_FIELD_NAME * system_charset_info->mbmaxlen;
+ set_charset(system_charset_info);
}
const char *func_name() const { return "database"; }
};
@@ -350,8 +350,8 @@ public:
String *val_str(String *);
void fix_length_and_dec()
{
- max_length= (USERNAME_LENGTH+HOSTNAME_LENGTH+1)*default_charset()->mbmaxlen;
- set_charset(default_charset());
+ max_length= (USERNAME_LENGTH+HOSTNAME_LENGTH+1)*system_charset_info->mbmaxlen;
+ set_charset(system_charset_info);
}
const char *func_name() const { return "user"; }
};