Commit 4014c093 authored by unknown's avatar unknown
Browse files

Fix for BUG#4500 "set character set replicates incorrectly"

We must not reset the charset in slave after each statement, otherwise the SET CHARACTER SET is cancelled immediately.
Instead, we write a SET CHARACTER SET DEFAULT to the master's binlog when needed (like we already do for SET FOREIGN_KEY_CHECKS);
such writing is not necessary in 4.1 (in 4.1 the bug does not exist, as the SET ONE_SHOT syntax is used).
I have written a test and it works, but I'm not pushing the test as it requires building with all charsets.
I have noticed differences between what is inserted in the master's table in 4.0 and 4.1, and alerted Bar.


sql/log.cc:
  When SET CHARACTER SET has been used, we must reset the charset after the writing the statement, in the binlog.
  In 4.1, this resetting is already achieved by the SET ONE_SHOT syntax.
sql/log_event.cc:
  In slave, we must not simply reset the charset after each statement: if we do this, the charset gets
  immediately after executing the SET CHARACTER SET! (BUG#4500).
parent 434d385a
Loading
Loading
Loading
Loading
+17 −5
Original line number Diff line number Diff line
@@ -1208,13 +1208,25 @@ bool MYSQL_LOG::write(Log_event* event_info)

    /* Write log events to reset the 'run environment' of the SQL command */

    if (thd && thd->options & OPTION_NO_FOREIGN_KEY_CHECKS)
    if (thd)
    {
      if (thd->options & OPTION_NO_FOREIGN_KEY_CHECKS)
      {
        Query_log_event e(thd, "SET FOREIGN_KEY_CHECKS=1", 24, 0);
        e.set_log_pos(this);
        if (e.write(file))
          goto err;
      }
#if MYSQL_VERSION_ID < 40100      
      if (thd->variables.convert_set)
      {
	Query_log_event e(thd, "SET CHARACTER SET DEFAULT", 25, 0);
	e.set_log_pos(this);
	if (e.write(file))
	  goto err;
      }
#endif
    }

    /*
      Tell for transactional table handlers up to which position in the
+0 −2
Original line number Diff line number Diff line
@@ -1932,8 +1932,6 @@ Default database: '%s'. Query: '%s'",
  thd->query= 0;			// just to be sure
  thd->query_length= 0;
  VOID(pthread_mutex_unlock(&LOCK_thread_count));
  // assume no convert for next query unless set explictly
  thd->variables.convert_set = 0;
  close_thread_tables(thd);      
  free_root(&thd->mem_root,MYF(MY_KEEP_PREALLOC));
  return (thd->query_error ? thd->query_error : Log_event::exec_event(rli));