Commit b3d84df1 authored by unknown's avatar unknown
Browse files

A fix and test case for the bug reported by Reggie: if character set

of client equals to character set of connection, possibly required
conversion to character set of column is not performed
(prepared statements, data is supplied using placeholders).


sql/item.cc:
  Fix for the bug reported by Reggie: if character_set_connection
  is equal to character_set_client, placeholder's value is not converted
  furhter to character set of column when it's different.
  This is because the original implementation left placeholder's character
  set intact (binary) if there were no need for client->connection conversion.
tests/client_test.c:
  A test case for the conversion bug.
parent 7bcd40bd
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -1218,6 +1218,10 @@ bool Item_param::convert_str_value(THD *thd)
                              value.cs_info.character_set_client,
                              value.cs_info.final_character_set_of_str_value);
    }
    else
      str_value.set_charset(value.cs_info.final_character_set_of_str_value);
    /* Here str_value is guaranteed to be in final_character_set_of_str_value */

    max_length= str_value.length();
    decimals= 0;
    /*
+71 −0
Original line number Diff line number Diff line
@@ -11152,6 +11152,73 @@ static void test_bug4172()
}


static void test_conversion()
{
  MYSQL_STMT *stmt;
  const char *stmt_text;
  int rc;
  MYSQL_BIND bind[1];
  char buff[4];
  ulong length;

  myheader("test_conversion");

  stmt_text= "DROP TABLE IF EXISTS t1";
  rc= mysql_real_query(mysql, stmt_text, strlen(stmt_text));
  myquery(rc);
  stmt_text= "CREATE TABLE t1 (a TEXT) DEFAULT CHARSET latin1";
  rc= mysql_real_query(mysql, stmt_text, strlen(stmt_text));
  myquery(rc);
  stmt_text= "SET character_set_connection=utf8, character_set_client=utf8, "
             " character_set_results=latin1";
  rc= mysql_real_query(mysql, stmt_text, strlen(stmt_text));
  myquery(rc);

  stmt= mysql_stmt_init(mysql);

  stmt_text= "INSERT INTO t1 (a) VALUES (?)";
  rc= mysql_stmt_prepare(stmt, stmt_text, strlen(stmt_text));
  check_execute(stmt, rc);

  bzero(bind, sizeof(bind));
  bind[0].buffer= buff;
  bind[0].length= &length;
  bind[0].buffer_type= MYSQL_TYPE_STRING;

  mysql_stmt_bind_param(stmt, bind);

  buff[0]= 0xC3;
  buff[1]= 0xA0;
  length= 2;

  rc= mysql_stmt_execute(stmt);
  check_execute(stmt, rc);

  stmt_text= "SELECT a FROM t1";
  rc= mysql_stmt_prepare(stmt, stmt_text, strlen(stmt_text));
  check_execute(stmt, rc);
  rc= mysql_stmt_execute(stmt);
  check_execute(stmt, rc);

  bind[0].buffer_length= sizeof(buff);
  mysql_stmt_bind_result(stmt, bind);

  rc= mysql_stmt_fetch(stmt);
  DIE_UNLESS(rc == 0);
  DIE_UNLESS(length == 1);
  DIE_UNLESS((uchar) buff[0] == 0xE0);
  rc= mysql_stmt_fetch(stmt);
  DIE_UNLESS(rc == MYSQL_NO_DATA);

  mysql_stmt_close(stmt);
  stmt_text= "DROP TABLE t1";
  rc= mysql_real_query(mysql, stmt_text, strlen(stmt_text));
  myquery(rc);
  stmt_text= "SET NAMES DEFAULT";
  rc= mysql_real_query(mysql, stmt_text, strlen(stmt_text));
  myquery(rc);
}


/*
  Read and parse arguments and MySQL options from my.cnf
@@ -11471,6 +11538,10 @@ int main(int argc, char **argv)
    test_bug6096();         /* max_length for numeric columns */
    test_bug4172();         /* floating point conversions in libmysql */

    test_conversion();      /* placeholder value is not converted to
                               character set of column if character set
                               of connection equals to character set of
                               client */
    /*
      XXX: PLEASE RUN THIS PROGRAM UNDER VALGRIND AND VERIFY THAT YOUR TEST
      DOESN'T CONTAIN WARNINGS/ERRORS BEFORE YOU PUSH.