Commit 06164d5d authored by unknown's avatar unknown
Browse files

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.
parent b488e987
Loading
Loading
Loading
Loading
+17 −0
Original line number Diff line number Diff line
@@ -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;
+17 −0
Original line number Diff line number Diff line
@@ -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;
+27 −1
Original line number Diff line number Diff line
@@ -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);
+1 −0
Original line number Diff line number Diff line
@@ -1194,6 +1194,7 @@ class Item_param :public Item
    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