From 06164d5dd5d0f2e47850d6823d37645c21f892e8 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 20 Oct 2005 11:56:27 +0500 Subject: [PATCH] Bug#12371: executing prepared statement fails (illegal mix of collations) ctype_utf8.test, ctype_utf8.result: Adding test case. item.h: item.cc: Adding Item_param::safe_charset_converter sql/item.cc: Bug#12371: executing prepared statement fails (illegal mix of collations) Adding Item_param::safe_charset_converter sql/item.h: Adding Item_param::safe_charset_converter mysql-test/r/ctype_utf8.result: Adding test case. mysql-test/t/ctype_utf8.test: Adding test case. --- mysql-test/r/ctype_utf8.result | 17 +++++++++++++++++ mysql-test/t/ctype_utf8.test | 17 +++++++++++++++++ sql/item.cc | 28 +++++++++++++++++++++++++++- sql/item.h | 1 + 4 files changed, 62 insertions(+), 1 deletion(-) diff --git a/mysql-test/r/ctype_utf8.result b/mysql-test/r/ctype_utf8.result index 29133c53cf9..405eff25746 100644 --- a/mysql-test/r/ctype_utf8.result +++ b/mysql-test/r/ctype_utf8.result @@ -1131,3 +1131,20 @@ a i い drop table t1,t2; +set names utf8; +create table t1 (a char(10), b varchar(10)); +insert into t1 values ('bar','kostja'); +insert into t1 values ('kostja','bar'); +prepare my_stmt from "select * from t1 where a=?"; +set @a:='bar'; +execute my_stmt using @a; +a b +bar kostja +set @a:='kostja'; +execute my_stmt using @a; +a b +kostja bar +set @a:=null; +execute my_stmt using @a; +a b +drop table if exists t1; diff --git a/mysql-test/t/ctype_utf8.test b/mysql-test/t/ctype_utf8.test index 6628175198c..fb6f2f58e35 100644 --- a/mysql-test/t/ctype_utf8.test +++ b/mysql-test/t/ctype_utf8.test @@ -916,3 +916,20 @@ insert into t1 values('a'),('a'),(0xE38182),(0xE38182); insert into t1 values('i'),('i'),(0xE38184),(0xE38184); select * from t1 union distinct select * from t2; drop table t1,t2; + + +# +# Bug#12371: executing prepared statement fails (illegal mix of collations) +# +set names utf8; +create table t1 (a char(10), b varchar(10)); +insert into t1 values ('bar','kostja'); +insert into t1 values ('kostja','bar'); +prepare my_stmt from "select * from t1 where a=?"; +set @a:='bar'; +execute my_stmt using @a; +set @a:='kostja'; +execute my_stmt using @a; +set @a:=null; +execute my_stmt using @a; +drop table if exists t1; diff --git a/sql/item.cc b/sql/item.cc index 3d05cc19c08..b2aca750475 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -696,6 +696,32 @@ Item *Item_string::safe_charset_converter(CHARSET_INFO *tocs) } +Item *Item_param::safe_charset_converter(CHARSET_INFO *tocs) +{ + if (const_item()) + { + Item_string *conv; + uint cnv_errors; + char buf[MAX_FIELD_WIDTH]; + String tmp(buf, sizeof(buf), &my_charset_bin); + String cstr, *ostr= val_str(&tmp); + /* + As safe_charset_converter is not executed for + a parameter bound to NULL, ostr should never be 0. + */ + cstr.copy(ostr->ptr(), ostr->length(), ostr->charset(), tocs, &cnv_errors); + if (cnv_errors || !(conv= new Item_string(cstr.ptr(), cstr.length(), + cstr.charset(), + collation.derivation))) + return NULL; + conv->str_value.copy(); + conv->str_value.mark_as_const(); + return conv; + } + return NULL; +} + + Item *Item_static_string_func::safe_charset_converter(CHARSET_INFO *tocs) { Item_string *conv; @@ -1351,7 +1377,7 @@ bool agg_item_charsets(DTCollation &coll, const char *fname, been created in prepare. In this case register the change for rollback. */ - if (arena) + if (arena && arena->is_conventional()) *arg= conv; else thd->change_item_tree(arg, conv); diff --git a/sql/item.h b/sql/item.h index 7a7e080db02..3e52cbe5fd7 100644 --- a/sql/item.h +++ b/sql/item.h @@ -1194,6 +1194,7 @@ public: constant, assert otherwise. This method is called only if basic_const_item returned TRUE. */ + Item *safe_charset_converter(CHARSET_INFO *tocs); Item *new_item(); /* Implement by-value equality evaluation if parameter value