summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorunknown <bar@mysql.com>2005-11-29 09:21:57 +0400
committerunknown <bar@mysql.com>2005-11-29 09:21:57 +0400
commit0fa8fc66df7c6450dcf6d7dd2b18146ebae7b44d (patch)
treeb74e661da9a9d15e3c99cacc629945407989dc46
parent57bfc6ddcbdc3011b9b080802840936f793b9a55 (diff)
parent72d19611d198164e1fcd2e16b270a11824d860bf (diff)
downloadmariadb-git-0fa8fc66df7c6450dcf6d7dd2b18146ebae7b44d.tar.gz
Merge abarkov@bk-internal.mysql.com:/home/bk/mysql-4.1
into mysql.com:/usr/home/bar/mysql-4.1.b10446 sql/item.cc: Auto merged
-rw-r--r--mysql-test/r/ctype_recoding.result9
-rw-r--r--mysql-test/t/ctype_recoding.test11
-rw-r--r--sql/item.cc12
-rw-r--r--sql/item_strfunc.cc2
-rw-r--r--sql/item_strfunc.h34
5 files changed, 53 insertions, 15 deletions
diff --git a/mysql-test/r/ctype_recoding.result b/mysql-test/r/ctype_recoding.result
index 1c75988fd21..0b5c6f8974c 100644
--- a/mysql-test/r/ctype_recoding.result
+++ b/mysql-test/r/ctype_recoding.result
@@ -181,11 +181,18 @@ select * from t1 where a=_koi8r'×ÁÓÑ';
a
×ÁÓÑ
select * from t1 where a=concat(_koi8r'×ÁÓÑ');
-ERROR HY000: Illegal mix of collations (cp1251_general_ci,IMPLICIT) and (koi8r_general_ci,COERCIBLE) for operation '='
+a
+×ÁÓÑ
select * from t1 where a=_latin1'×ÁÓÑ';
ERROR HY000: Illegal mix of collations (cp1251_general_ci,IMPLICIT) and (latin1_swedish_ci,COERCIBLE) for operation '='
drop table t1;
set names latin1;
+create table t1 (a char(10) character set utf8 collate utf8_bin);
+insert into t1 values (' xxx');
+select * from t1 where a=lpad('xxx',10,' ');
+a
+ xxx
+drop table t1;
set names koi8r;
create table t1 (c1 char(10) character set cp1251);
insert into t1 values ('ß');
diff --git a/mysql-test/t/ctype_recoding.test b/mysql-test/t/ctype_recoding.test
index 9949ef88da4..5648cea7fd3 100644
--- a/mysql-test/t/ctype_recoding.test
+++ b/mysql-test/t/ctype_recoding.test
@@ -144,8 +144,7 @@ create table t1 (a char(10) character set cp1251);
insert into t1 values (_koi8r'×ÁÓÑ');
# this is possible:
select * from t1 where a=_koi8r'×ÁÓÑ';
-# this is not possible, because we have a function, not just a constant:
---error 1267
+# this is possible, because we have a function with constant arguments:
select * from t1 where a=concat(_koi8r'×ÁÓÑ');
# this is not posible, cannot convert _latin1'×ÁÓÑ' into cp1251:
--error 1267
@@ -154,6 +153,14 @@ drop table t1;
set names latin1;
#
+# Bug#10446 Illegal mix of collations
+#
+create table t1 (a char(10) character set utf8 collate utf8_bin);
+insert into t1 values (' xxx');
+select * from t1 where a=lpad('xxx',10,' ');
+drop table t1;
+
+#
# Check more automatic conversion
#
set names koi8r;
diff --git a/sql/item.cc b/sql/item.cc
index 6ca2627dbff..60fa53bf798 100644
--- a/sql/item.cc
+++ b/sql/item.cc
@@ -211,16 +211,8 @@ bool Item::eq(const Item *item, bool binary_cmp) const
Item *Item::safe_charset_converter(CHARSET_INFO *tocs)
{
- /*
- Allow conversion from and to "binary".
- Don't allow automatic conversion to non-Unicode charsets,
- as it potentially loses data.
- */
- if (collation.collation != &my_charset_bin &&
- tocs != &my_charset_bin &&
- !(tocs->state & MY_CS_UNICODE))
- return NULL; // safe conversion is not possible
- return new Item_func_conv_charset(this, tocs);
+ Item_func_conv_charset *conv= new Item_func_conv_charset(this, tocs, 1);
+ return conv->safe ? conv : NULL;
}
diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc
index 6ca6ce62c54..60cb3348590 100644
--- a/sql/item_strfunc.cc
+++ b/sql/item_strfunc.cc
@@ -2252,6 +2252,8 @@ String *Item_func_conv::val_str(String *str)
String *Item_func_conv_charset::val_str(String *str)
{
DBUG_ASSERT(fixed == 1);
+ if (use_cached_value)
+ return null_value ? 0 : &str_value;
String *arg= args[0]->val_str(str);
uint dummy_errors;
if (!arg)
diff --git a/sql/item_strfunc.h b/sql/item_strfunc.h
index 87aee9ac25c..c4505fce248 100644
--- a/sql/item_strfunc.h
+++ b/sql/item_strfunc.h
@@ -614,10 +614,40 @@ public:
class Item_func_conv_charset :public Item_str_func
{
+ bool use_cached_value;
public:
+ bool safe;
CHARSET_INFO *conv_charset; // keep it public
- Item_func_conv_charset(Item *a, CHARSET_INFO *cs) :Item_str_func(a)
- { conv_charset=cs; }
+ Item_func_conv_charset(Item *a, CHARSET_INFO *cs) :Item_str_func(a)
+ { conv_charset= cs; use_cached_value= 0; safe= 0; }
+ Item_func_conv_charset(Item *a, CHARSET_INFO *cs, bool cache_if_const)
+ :Item_str_func(a)
+ {
+ DBUG_ASSERT(args[0]->fixed);
+ conv_charset= cs;
+ if (cache_if_const && args[0]->const_item())
+ {
+ uint errors= 0;
+ String tmp, *str= args[0]->val_str(&tmp);
+ if (!str || str_value.copy(str->ptr(), str->length(),
+ str->charset(), conv_charset, &errors))
+ null_value= 1;
+ use_cached_value= 1;
+ safe= (errors == 0);
+ }
+ else
+ {
+ use_cached_value= 0;
+ /*
+ Conversion from and to "binary" is safe.
+ Conversion to Unicode is safe.
+ Other kind of conversions are potentially lossy.
+ */
+ safe= (args[0]->collation.collation == &my_charset_bin ||
+ cs == &my_charset_bin ||
+ (cs->state & MY_CS_UNICODE));
+ }
+ }
String *val_str(String *);
void fix_length_and_dec();
const char *func_name() const { return "convert"; }