From a68f171585da08a855df1958caab3264a4b74006 Mon Sep 17 00:00:00 2001
From: unknown <aelkin@mysql.com>
Date: Fri, 10 Feb 2006 15:12:27 +0200
Subject: [PATCH] BUG#16217 fix partly backported from 5.0. It is different in
 mysqlbinlog part. This changeset is assumed to stay in 4.1.

client/mysql.cc:
  BUG#16217 forced to introduce a separate mysql client command.
  Feature is backported from 5.0, precisely
  ChangeSet 1.2034 06/02/09 16:23:09 aelkin@mysql.com
  (under second review at the moment)
mysql-test/r/mysqlbinlog.result:
  changed in 5.0
mysql-test/t/mysqlbinlog.test:
  backported from 5.0. The last part of the test to mimic bug#16217
sql/log_event.cc:
  Inserting exclaiming comment command for mysql client made differently than in 5.0.
  Parsing still is cheap enough not to think to modify server code instead.
---
 client/mysql.cc                 | 26 +++++++++++++++++++++++++-
 mysql-test/r/mysqlbinlog.result | 19 ++++++++++++++++++-
 mysql-test/t/mysqlbinlog.test   | 19 ++++++++++++++++++-
 sql/log_event.cc                | 12 ++++++++++++
 4 files changed, 73 insertions(+), 3 deletions(-)

diff --git a/client/mysql.cc b/client/mysql.cc
index d76195535a3..2f9031b84b8 100644
--- a/client/mysql.cc
+++ b/client/mysql.cc
@@ -190,7 +190,7 @@ static int com_quit(String *str,char*),
 	   com_connect(String *str,char*), com_status(String *str,char*),
 	   com_use(String *str,char*), com_source(String *str, char*),
 	   com_rehash(String *str, char*), com_tee(String *str, char*),
-           com_notee(String *str, char*),
+           com_notee(String *str, char*), com_charset(String *str,char*),
            com_prompt(String *str, char*), com_delimiter(String *str, char*);
 
 #ifdef USE_POPEN
@@ -263,6 +263,8 @@ static COMMANDS commands[] = {
     "Set outfile [to_outfile]. Append everything into given outfile." },
   { "use",    'u', com_use,    1,
     "Use another database. Takes database name as argument." },
+  { "charset_name",    'C', com_charset,    1,
+    "Switch to another charset. Might be needed for processing binlog." },
   /* Get bash-like expansion for some commands */
   { "create table",     0, 0, 0, ""},
   { "create database",  0, 0, 0, ""},
@@ -1850,6 +1852,28 @@ com_clear(String *buffer,char *line __attribute__((unused)))
   return 0;
 }
 
+	/* ARGSUSED */
+static int
+com_charset(String *buffer __attribute__((unused)), char *line)
+{
+  char buff[256], *param;
+  CHARSET_INFO * new_cs;
+  strmake(buff, line, sizeof(buff) - 1);
+  param= get_arg(buff, 0);
+  if (!param || !*param)
+  {
+    return put_info("Usage: \\C char_setname | charset charset_name", 
+		    INFO_ERROR, 0);
+  }
+  new_cs= get_charset_by_csname(param, MY_CS_PRIMARY, MYF(MY_WME));
+  if (new_cs)
+  {
+    charset_info= new_cs;
+    put_info("Charset changed", INFO_INFO);
+  }
+  else put_info("Charset is not found", INFO_INFO);
+  return 0;
+}
 
 /*
   Execute command
diff --git a/mysql-test/r/mysqlbinlog.result b/mysql-test/r/mysqlbinlog.result
index e88ece6b361..adaf0dad56b 100644
--- a/mysql-test/r/mysqlbinlog.result
+++ b/mysql-test/r/mysqlbinlog.result
@@ -84,4 +84,21 @@ SET INSERT_ID=1;
 use test;
 SET TIMESTAMP=1000000000;
 insert into t1 values ("Alas");
-drop table t1, t2;
+flush logs;
+create table t3 (f text character set utf8);
+create table t4 (f text character set cp932);
+flush logs;
+rename table t3 to t03, t4 to t04;
+select HEX(f) from t03;
+HEX(f)
+E382BD
+select HEX(f) from t3;
+HEX(f)
+E382BD
+select HEX(f) from t04;
+HEX(f)
+835C
+select HEX(f) from t4;
+HEX(f)
+835C
+drop table t1, t2, t03, t04, t3, t4;
diff --git a/mysql-test/t/mysqlbinlog.test b/mysql-test/t/mysqlbinlog.test
index 0f9faa5c337..871886331f6 100644
--- a/mysql-test/t/mysqlbinlog.test
+++ b/mysql-test/t/mysqlbinlog.test
@@ -98,7 +98,24 @@ select "--- --position --" as "";
 --replace_result $MYSQL_TEST_DIR MYSQL_TEST_DIR
 --exec $MYSQL_BINLOG --short-form --local-load=$MYSQL_TEST_DIR/var/tmp/ --read-from-remote-server --position=27 --user=root --host=127.0.0.1 --port=$MASTER_MYPORT master-bin.000002
 
+
+# Bug#16217 (mysql client did not know how not switch its internal charset)
+flush logs;
+create table t3 (f text character set utf8);
+create table t4 (f text character set cp932); 
+--exec $MYSQL --default-character-set=utf8 test -e "insert into t3 values(_utf8'ソ')"
+--exec $MYSQL --default-character-set=cp932 test -e "insert into t4 values(_cp932'�\');"
+flush logs;
+rename table t3 to t03, t4 to t04;
+--exec $MYSQL_BINLOG --short-form $MYSQL_TEST_DIR/var/log/master-bin.000004 | $MYSQL --default-character-set=utf8
+# original and recovered data must be equal
+select HEX(f) from t03;
+select HEX(f) from t3;
+select HEX(f) from t04;
+select HEX(f) from t4;
+
+
 # clean up
-drop table t1, t2;
+drop table t1, t2, t03, t04, t3, t4; 
 
 # End of 4.1 tests
diff --git a/sql/log_event.cc b/sql/log_event.cc
index 3f545df5776..19c32b2d28e 100644
--- a/sql/log_event.cc
+++ b/sql/log_event.cc
@@ -949,6 +949,7 @@ Query_log_event::Query_log_event(const char* buf, int event_len,
 void Query_log_event::print(FILE* file, bool short_form, char* last_db)
 {
   char buff[40],*end;				// Enough for SET TIMESTAMP
+  const uint set_len= sizeof("SET ONE_SHOT CHARACTER_SET_CLIENT=") - 1;
   if (!short_form)
   {
     print_header(file);
@@ -978,6 +979,17 @@ void Query_log_event::print(FILE* file, bool short_form, char* last_db)
   my_fwrite(file, (byte*) buff, (uint) (end-buff),MYF(MY_NABP | MY_WME));
   if (flags & LOG_EVENT_THREAD_SPECIFIC_F)
     fprintf(file,"SET @@session.pseudo_thread_id=%lu;\n",(ulong)thread_id);
+  /* charset_name command for mysql client */
+  if (!strncmp(query, "SET ONE_SHOT CHARACTER_SET_CLIENT=", set_len))
+  {
+    char * endptr;
+    int cs_number= strtoul(query + set_len, &endptr, 10);
+    DBUG_ASSERT(*endptr == ',');
+    CHARSET_INFO *cs_info= get_charset(cs_number, MYF(MY_WME));
+    if (cs_info) {
+      fprintf(file, "/*!\\C %s */;\n", cs_info->csname);
+    }
+  }
   my_fwrite(file, (byte*) query, q_len, MYF(MY_NABP | MY_WME));
   fprintf(file, ";\n");
 }