summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorunknown <gbichot@production.mysql.com>2005-03-22 00:26:12 +0100
committerunknown <gbichot@production.mysql.com>2005-03-22 00:26:12 +0100
commitac46bf77aecd84eae40400afd5ffb79e93ab4b24 (patch)
treea68553da2993095e4192c9deed704a0dc63b5e8b
parent6fc7c0742e99d45a1cedf9363ef705e85f8a563d (diff)
downloadmariadb-git-ac46bf77aecd84eae40400afd5ffb79e93ab4b24.tar.gz
Last part of WL#1062: better replication of timezones: no more use
of SET ONE_SHOT; storing tz info directly in event (if this info is needed), it's now allowed to have different global tz on master and slave. client/mysqlbinlog.cc: we need MAX_TIME_ZONE_NAME_LENGTH when processing log_event.h, and it's declared in mysql_priv.h mysql-test/r/rpl_timezone.result: result update mysql-test/t/rpl_timezone-slave.opt: Now that we can have different global value of timezone on master and slave, let's test it. mysql-test/t/rpl_timezone.test: Tests of the new replication of timezones: checking the output of mysqlbinlog, replication of CONVERT_TZ(). sql/ha_innodb.cc: No very fast shutdown on Netware (anyway it's disabled on all platforms, but this is so that we don't forget to keep it disabled on Netware in the future). sql/log.cc: No more need to write SET ONE_SHOT to binlog for character set and timezone (as we store this info directly nin the Query_log_event now). sql/log_event.cc: Exclude ::write() methods if MYSQL_CLIENT. Storing timezone info in the Query_log_event in master. Re-reading it in slave. Small code cleanups. I plan to not store the end 0 of catalog in binlog events soon. sql/log_event.h: replication of time zones: a place for tz info in Query_log_event, in LAST_EVENT_INFO. Plus if we are compiling a client, we don't need the ::write() methods, so keeping them out (of mysqlbinlog.cc; keeping them in, resulted in problem that mysqlbinlog does not know Timezone structure). sql/mysql_priv.h: moving this define from tztime.h (tztime.h has things which are too much for a client like mysqlbinlog). sql/set_var.cc: It's now allowed to change global value of charset or timezone even if using binlogging or if being a slave. Making CONVERT_TZ(,,@@session.time_zone) replicate. sql/set_var.h: these ::check()s are not needed anymore (changing global charset or timezone is now allowed even if binlogging or slave) sql/slave.cc: No more need to check for same global timezone if master is 5.x (ok, strictly speaking if it is > 5.0.3 but this is alpha). sql/slave.h: a function to wrap settings of charset to default. sql/tztime.cc: Adaptation of my_tz_find() to the case where it's not called from inside a query (i.e. cannot join its tz tables to the query's ones): this variant opens the tz tables itself, reads from them, and closes them. This is presently only used by the slave SQL thread (when it sets the tz before executing a query). sql/tztime.h: declaration of new function, plus moving symbol to mysql_priv.h for easier usage in mysqlbinlog (Dmitri, pardon me). BitKeeper/etc/logging_ok: Logging to logging@openlogging.org accepted
-rw-r--r--BitKeeper/etc/logging_ok1
-rw-r--r--client/mysqlbinlog.cc2
-rw-r--r--mysql-test/r/rpl_timezone.result65
-rw-r--r--mysql-test/t/rpl_timezone-slave.opt2
-rw-r--r--mysql-test/t/rpl_timezone.test34
-rw-r--r--sql/ha_innodb.cc4
-rw-r--r--sql/log.cc51
-rw-r--r--sql/log_event.cc165
-rw-r--r--sql/log_event.h45
-rw-r--r--sql/mysql_priv.h6
-rw-r--r--sql/set_var.cc56
-rw-r--r--sql/set_var.h6
-rw-r--r--sql/slave.cc21
-rw-r--r--sql/slave.h1
-rw-r--r--sql/tztime.cc56
-rw-r--r--sql/tztime.h7
16 files changed, 322 insertions, 200 deletions
diff --git a/BitKeeper/etc/logging_ok b/BitKeeper/etc/logging_ok
index eff53f4a789..46814ec8517 100644
--- a/BitKeeper/etc/logging_ok
+++ b/BitKeeper/etc/logging_ok
@@ -48,6 +48,7 @@ dlenev@build.mysql.com
dlenev@jabberwock.localdomain
dlenev@mysql.com
ejonore@mc03.ndb.mysql.com
+gbichot@production.mysql.com
gbichot@quadita2.mysql.com
georg@beethoven.local
georg@beethoven.site
diff --git a/client/mysqlbinlog.cc b/client/mysqlbinlog.cc
index c296447def9..59c90f59e8e 100644
--- a/client/mysqlbinlog.cc
+++ b/client/mysqlbinlog.cc
@@ -33,9 +33,9 @@
#undef MYSQL_SERVER
#include "client_priv.h"
#include <my_time.h>
-#include "log_event.h"
/* That one is necessary for defines of OPTION_NO_FOREIGN_KEY_CHECKS etc */
#include "mysql_priv.h"
+#include "log_event.h"
#define BIN_LOG_HEADER_SIZE 4
#define PROBE_HEADER_LEN (EVENT_LEN_OFFSET+4)
diff --git a/mysql-test/r/rpl_timezone.result b/mysql-test/r/rpl_timezone.result
index cd2c4d099be..8975333d1db 100644
--- a/mysql-test/r/rpl_timezone.result
+++ b/mysql-test/r/rpl_timezone.result
@@ -4,21 +4,31 @@ reset master;
reset slave;
drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
start slave;
+set timestamp=100000000;
create table t1 (t timestamp);
create table t2 (t char(32));
select @@time_zone;
@@time_zone
+Japan
+select @@time_zone;
+@@time_zone
Europe/Moscow
+insert into t1 values ('20050101000000'), ('20050611093902');
set time_zone='UTC';
insert into t1 values ('20040101000000'), ('20040611093902');
select * from t1;
t
+2004-12-31 21:00:00
+2005-06-11 05:39:02
2004-01-01 00:00:00
2004-06-11 09:39:02
+set time_zone='UTC';
select * from t1;
t
-2004-01-01 03:00:00
-2004-06-11 13:39:02
+2004-12-31 21:00:00
+2005-06-11 05:39:02
+2004-01-01 00:00:00
+2004-06-11 09:39:02
delete from t1;
set time_zone='Europe/Moscow';
insert into t1 values ('20040101000000'), ('20040611093902');
@@ -26,19 +36,35 @@ select * from t1;
t
2004-01-01 00:00:00
2004-06-11 09:39:02
+set time_zone='Europe/Moscow';
select * from t1;
t
2004-01-01 00:00:00
2004-06-11 09:39:02
-show binlog events;
-Log_name Pos Event_type Server_id End_log_pos Info
-master-bin.000001 # Format_desc 1 # Server ver: VERSION, Binlog ver: 4
-master-bin.000001 # Query 1 # use `test`; create table t1 (t timestamp)
-master-bin.000001 # Query 1 # use `test`; create table t2 (t char(32))
-master-bin.000001 # Query 1 # use `test`; SET ONE_SHOT TIME_ZONE='UTC'
-master-bin.000001 # Query 1 # use `test`; insert into t1 values ('20040101000000'), ('20040611093902')
-master-bin.000001 # Query 1 # use `test`; delete from t1
-master-bin.000001 # Query 1 # use `test`; insert into t1 values ('20040101000000'), ('20040611093902')
+/*!40019 SET @@session.max_insert_delayed_threads=0*/;
+/*!50003 SET @OLD_COMPLETION_TYPE=@@COMPLETION_TYPE,COMPLETION_TYPE=0*/;
+ROLLBACK;
+use test;
+SET TIMESTAMP=100000000;
+SET @@session.foreign_key_checks=1, @@session.sql_auto_is_null=1, @@session.unique_checks=1;
+SET @@session.sql_mode=0;
+SET @@session.character_set_client=8,@@session.collation_connection=8,@@session.collation_server=8;
+create table t1 (t timestamp);
+SET TIMESTAMP=100000000;
+create table t2 (t char(32));
+SET TIMESTAMP=100000000;
+SET @@session.time_zone='Europe/Moscow';
+insert into t1 values ('20050101000000'), ('20050611093902');
+SET TIMESTAMP=100000000;
+SET @@session.time_zone='UTC';
+insert into t1 values ('20040101000000'), ('20040611093902');
+SET TIMESTAMP=100000000;
+delete from t1;
+SET TIMESTAMP=100000000;
+SET @@session.time_zone='Europe/Moscow';
+insert into t1 values ('20040101000000'), ('20040611093902');
+ROLLBACK;
+/*!50003 SET COMPLETION_TYPE=@OLD_COMPLETION_TYPE*/;
set time_zone='MET';
insert into t2 (select t from t1);
select * from t1;
@@ -52,10 +78,6 @@ t
delete from t2;
set timestamp=1000072000;
insert into t2 values (current_timestamp), (current_date), (current_time);
-set timestamp=1000072000;
-select current_timestamp, current_date, current_time;
-current_timestamp current_date current_time
-2001-09-10 01:46:40 2001-09-10 01:46:40
select * from t2;
t
2001-09-09 23:46:40
@@ -73,5 +95,16 @@ t
2001-09-09 03:46:40
1000000000
set global time_zone='MET';
-ERROR HY000: Binary logging and replication forbid changing the global server time zone
+delete from t2;
+set time_zone='UTC';
+insert into t2 values(convert_tz('2004-01-01 00:00:00','MET',@@time_zone));
+insert into t2 values(convert_tz('2005-01-01 00:00:00','MET','Japan'));
+select * from t2;
+t
+2003-12-31 23:00:00
+2005-01-01 08:00:00
+select * from t2;
+t
+2003-12-31 23:00:00
+2005-01-01 08:00:00
drop table t1, t2;
diff --git a/mysql-test/t/rpl_timezone-slave.opt b/mysql-test/t/rpl_timezone-slave.opt
index 8e43bfbbb7e..191182c329c 100644
--- a/mysql-test/t/rpl_timezone-slave.opt
+++ b/mysql-test/t/rpl_timezone-slave.opt
@@ -1 +1 @@
---default-time-zone=Europe/Moscow
+--default-time-zone=Japan
diff --git a/mysql-test/t/rpl_timezone.test b/mysql-test/t/rpl_timezone.test
index 3c180ca8849..a49cdd0acd2 100644
--- a/mysql-test/t/rpl_timezone.test
+++ b/mysql-test/t/rpl_timezone.test
@@ -3,21 +3,25 @@ source include/master-slave.inc;
# Some preparations
let $VERSION=`select version()`;
+set timestamp=100000000; # for fixed output of mysqlbinlog
create table t1 (t timestamp);
create table t2 (t char(32));
+connection slave;
+select @@time_zone;
+
#
# Let us check how well replication works when we are saving datetime
# value in TIMESTAMP field.
#
connection master;
select @@time_zone;
+insert into t1 values ('20050101000000'), ('20050611093902');
set time_zone='UTC';
insert into t1 values ('20040101000000'), ('20040611093902');
select * from t1;
-# On slave we still in 'Europe/Moscow' so we should see equivalent but
-# textually different values.
sync_slave_with_master;
+set time_zone='UTC';
select * from t1;
# Let us check also that setting of time_zone back to default also works
@@ -28,12 +32,11 @@ set time_zone='Europe/Moscow';
insert into t1 values ('20040101000000'), ('20040611093902');
select * from t1;
sync_slave_with_master;
+set time_zone='Europe/Moscow';
select * from t1;
connection master;
-# We should not see SET ONE_SHOT time_zone before second insert
---replace_result $VERSION VERSION
---replace_column 2 # 5 #
-show binlog events;
+--replace_result $MYSQL_TEST_DIR MYSQL_TEST_DIR
+--exec $MYSQL_BINLOG --short-form $MYSQL_TEST_DIR/var/log/master-bin.000001
#
# Now let us check how well we replicate statments reading TIMESTAMP fields
@@ -54,10 +57,6 @@ delete from t2;
set timestamp=1000072000;
insert into t2 values (current_timestamp), (current_date), (current_time);
sync_slave_with_master;
-# Values in ouput of these to queries should differ because we are in
-# in 'MET' on master and in 'Europe/Moscow on slave...
-set timestamp=1000072000;
-select current_timestamp, current_date, current_time;
select * from t2;
#
@@ -73,13 +72,24 @@ sync_slave_with_master;
select * from t2;
#
-# Let us check that we are not allowing to set global time_zone with
+# Let us check that we are allowing to set global time_zone with
# replication
#
connection master;
---error 1387
set global time_zone='MET';
+#
+# Let us see if CONVERT_TZ(@@time_zone) replicates
+#
+delete from t2;
+set time_zone='UTC';
+insert into t2 values(convert_tz('2004-01-01 00:00:00','MET',@@time_zone));
+insert into t2 values(convert_tz('2005-01-01 00:00:00','MET','Japan'));
+select * from t2;
+sync_slave_with_master;
+select * from t2;
+
# Clean up
+connection master;
drop table t1, t2;
sync_slave_with_master;
diff --git a/sql/ha_innodb.cc b/sql/ha_innodb.cc
index 870ad1af52b..24f1579544b 100644
--- a/sql/ha_innodb.cc
+++ b/sql/ha_innodb.cc
@@ -1307,6 +1307,9 @@ innobase_end(void)
}
#endif
if (innodb_inited) {
+
+#ifndef __NETWARE__ /* NetWare can't close unclosed files, kill remaining
+ threads, etc, so we disable the very fast shutdown */
if (innobase_very_fast_shutdown) {
srv_very_fast_shutdown = TRUE;
fprintf(stderr,
@@ -1314,6 +1317,7 @@ innobase_end(void)
"InnoDB: the InnoDB buffer pool to data files. At the next mysqld startup\n"
"InnoDB: InnoDB will do a crash recovery!\n");
}
+#endif
innodb_inited = 0;
if (innobase_shutdown_for_mysql() != DB_SUCCESS) {
diff --git a/sql/log.cc b/sql/log.cc
index 43786990797..0c1d6836cce 100644
--- a/sql/log.cc
+++ b/sql/log.cc
@@ -1638,57 +1638,6 @@ bool MYSQL_LOG::write(Log_event *event_info)
if (thd)
{
-#if MYSQL_VERSION_ID < 50003
- /*
- To make replication of charsets working in 4.1 we are writing values
- of charset related variables before every statement in the binlog,
- if values of those variables differ from global server-wide defaults.
- We are using SET ONE_SHOT command so that the charset vars get reset
- to default after the first non-SET statement.
- In the next 5.0 this won't be needed as we will use the new binlog
- format to store charset info.
- */
- if ((thd->variables.character_set_client->number !=
- global_system_variables.collation_server->number) ||
- (thd->variables.character_set_client->number !=
- thd->variables.collation_connection->number) ||
- (thd->variables.collation_server->number !=
- thd->variables.collation_connection->number))
- {
- char buf[200];
- int written= my_snprintf(buf, sizeof(buf)-1,
- "SET ONE_SHOT CHARACTER_SET_CLIENT=%u,\
-COLLATION_CONNECTION=%u,COLLATION_DATABASE=%u,COLLATION_SERVER=%u",
- (uint) thd->variables.character_set_client->number,
- (uint) thd->variables.collation_connection->number,
- (uint) thd->variables.collation_database->number,
- (uint) thd->variables.collation_server->number);
- Query_log_event e(thd, buf, written, 0, FALSE);
- if (e.write(file))
- goto err;
- }
-#endif
- /*
- We use the same ONE_SHOT trick for making replication of time zones
- working in 4.1. Again in 5.0 we have better means for doing this.
-
- TODO: we should do like we now do with charsets (no more ONE_SHOT;
- logging in each event in a compact format). Dmitri says we can do:
- if (time_zone_used) write the timezone to binlog (in a format to be
- defined).
- */
- if (thd->time_zone_used &&
- thd->variables.time_zone != global_system_variables.time_zone)
- {
- char buf[MAX_TIME_ZONE_NAME_LENGTH + 26];
- char *buf_end= strxmov(buf, "SET ONE_SHOT TIME_ZONE='",
- thd->variables.time_zone->get_name()->ptr(),
- "'", NullS);
- Query_log_event e(thd, buf, buf_end - buf, 0, FALSE);
- if (e.write(file))
- goto err;
- }
-
if (thd->last_insert_id_used)
{
Intvar_log_event e(thd,(uchar) LAST_INSERT_ID_EVENT,
diff --git a/sql/log_event.cc b/sql/log_event.cc
index ba018e859c1..666c2427ac5 100644
--- a/sql/log_event.cc
+++ b/sql/log_event.cc
@@ -506,8 +506,6 @@ void Log_event::init_show_field_list(List<Item>* field_list)
field_list->push_back(new Item_empty_string("Info", 20));
}
-#endif /* !MYSQL_CLIENT */
-
/*
Log_event::write()
@@ -592,7 +590,6 @@ bool Log_event::write_header(IO_CACHE* file, ulong event_data_length)
*/
-#ifndef MYSQL_CLIENT
int Log_event::read_log_event(IO_CACHE* file, String* packet,
pthread_mutex_t* log_lock)
{
@@ -956,6 +953,7 @@ void Query_log_event::pack_info(Protocol *protocol)
}
#endif
+#ifndef MYSQL_CLIENT
/*
Query_log_event::write()
@@ -973,7 +971,8 @@ bool Query_log_event::write(IO_CACHE* file)
1+8+ // code of sql_mode and sql_mode
1+1+FN_REFLEN+ // code of catalog and catalog length and catalog
1+4+ // code of autoinc and the 2 autoinc variables
- 1+6 // code of charset and charset
+ 1+6+ // code of charset and charset
+ 1+1+MAX_TIME_ZONE_NAME_LENGTH // code of tz and tz length and tz name
], *start, *start_of_status;
ulong event_length;
@@ -1030,20 +1029,20 @@ bool Query_log_event::write(IO_CACHE* file)
start_of_status= start= buf+QUERY_HEADER_LEN;
if (flags2_inited)
{
- *(start++)= Q_FLAGS2_CODE;
+ *start++= Q_FLAGS2_CODE;
int4store(start, flags2);
start+= 4;
}
if (sql_mode_inited)
{
- *(start++)= Q_SQL_MODE_CODE;
+ *start++= Q_SQL_MODE_CODE;
int8store(start, (ulonglong)sql_mode);
start+= 8;
}
- if (catalog_len >= 0) // i.e. "catalog inited" (false for 4.0 events)
+ if (catalog_len) // i.e. "catalog inited" (false for 4.0 events)
{
- *(start++)= Q_CATALOG_CODE;
- *(start++)= (uchar) catalog_len;
+ *start++= Q_CATALOG_CODE;
+ *start++= (uchar) catalog_len;
bmove(start, catalog, catalog_len);
start+= catalog_len;
/*
@@ -1071,15 +1070,24 @@ bool Query_log_event::write(IO_CACHE* file)
}
if (charset_inited)
{
- *(start++)= Q_CHARSET_CODE;
+ *start++= Q_CHARSET_CODE;
memcpy(start, charset, 6);
start+= 6;
}
+ if (time_zone_len)
+ {
+ /* In the TZ sys table, column Name is of length 64 so this should be ok */
+ DBUG_ASSERT(time_zone_len <= MAX_TIME_ZONE_NAME_LENGTH);
+ *start++= Q_TIME_ZONE_CODE;
+ *start++= time_zone_len;
+ memcpy(start, time_zone_str, time_zone_len);
+ start+= time_zone_len;
+ }
/*
Here there could be code like
if (command-line-option-which-says-"log_this_variable" && inited)
{
- *(start++)= Q_THIS_VARIABLE_CODE;
+ *start++= Q_THIS_VARIABLE_CODE;
int4store(start, this_variable);
start+= 4;
}
@@ -1108,8 +1116,6 @@ bool Query_log_event::write(IO_CACHE* file)
/*
Query_log_event::Query_log_event()
*/
-
-#ifndef MYSQL_CLIENT
Query_log_event::Query_log_event(THD* thd_arg, const char* query_arg,
ulong query_length, bool using_trans,
bool suppress_use)
@@ -1150,6 +1156,18 @@ Query_log_event::Query_log_event(THD* thd_arg, const char* query_arg,
int2store(charset, thd_arg->variables.character_set_client->number);
int2store(charset+2, thd_arg->variables.collation_connection->number);
int2store(charset+4, thd_arg->variables.collation_server->number);
+ if (thd_arg->time_zone_used)
+ {
+ /*
+ Note that our event becomes dependent on the Time_zone object
+ representing the time zone. Fortunately such objects are never deleted
+ or changed during mysqld's lifetime.
+ */
+ time_zone_len= thd_arg->variables.time_zone->get_name()->length();
+ time_zone_str= thd_arg->variables.time_zone->get_name()->ptr();
+ }
+ else
+ time_zone_len= 0;
DBUG_PRINT("info",("Query_log_event has flags2=%lu sql_mode=%lu",flags2,sql_mode));
}
#endif /* MYSQL_CLIENT */
@@ -1163,15 +1181,17 @@ Query_log_event::Query_log_event(THD* thd_arg, const char* query_arg,
Query_log_event::Query_log_event(const char* buf, uint event_len,
const Format_description_log_event *description_event,
Log_event_type event_type)
- :Log_event(buf, description_event), data_buf(0), query(NullS), catalog(NullS),
+ :Log_event(buf, description_event), data_buf(0), query(NullS),
db(NullS), catalog_len(0), status_vars_len(0),
flags2_inited(0), sql_mode_inited(0), charset_inited(0),
- auto_increment_increment(1), auto_increment_offset(1)
+ auto_increment_increment(1), auto_increment_offset(1),
+ time_zone_len(0)
{
ulong data_len;
uint32 tmp;
uint8 common_header_len, post_header_len;
- const char *start, *end;
+ char *start;
+ const char *end;
DBUG_ENTER("Query_log_event::Query_log_event(char*,...)");
common_header_len= description_event->common_header_len;
@@ -1191,7 +1211,7 @@ Query_log_event::Query_log_event(const char* buf, uint event_len,
slave_proxy_id= thread_id = uint4korr(buf + Q_THREAD_ID_OFFSET);
exec_time = uint4korr(buf + Q_EXEC_TIME_OFFSET);
- db_len = (uint)buf[Q_DB_LEN_OFFSET];
+ db_len = (uint)buf[Q_DB_LEN_OFFSET]; // TODO: add a check of all *_len vars
error_code = uint2korr(buf + Q_ERR_CODE_OFFSET);
/*
@@ -1217,7 +1237,7 @@ Query_log_event::Query_log_event(const char* buf, uint event_len,
/* variable-part: the status vars; only in MySQL 5.0 */
start= (char*) (buf+post_header_len);
- end= (char*) (start+status_vars_len);
+ end= (const char*) (start+status_vars_len);
for (const uchar* pos= (const uchar*) start; pos < (const uchar*) end;)
{
switch (*pos++) {
@@ -1240,8 +1260,7 @@ Query_log_event::Query_log_event(const char* buf, uint event_len,
break;
}
case Q_CATALOG_CODE:
- catalog_len= *pos;
- if (catalog_len)
+ if ((catalog_len= *pos))
catalog= (char*) pos+1; // Will be copied later
pos+= catalog_len+2;
break;
@@ -1257,6 +1276,13 @@ Query_log_event::Query_log_event(const char* buf, uint event_len,
pos+= 6;
break;
}
+ case Q_TIME_ZONE_CODE:
+ {
+ if ((time_zone_len= *pos))
+ time_zone_str= (char *)(pos+1);
+ pos+= time_zone_len+1;
+ break;
+ }
default:
/* That's why you must write status vars in growing order of code */
DBUG_PRINT("info",("Query_log_event has unknown status vars (first has\
@@ -1265,24 +1291,29 @@ Query_log_event::Query_log_event(const char* buf, uint event_len,
}
}
- /* A 2nd variable part; this is common to all versions */
-
- if (!(start= data_buf = (char*) my_malloc(catalog_len + data_len +2, MYF(MY_WME))))
+ if (!(start= data_buf = (char*) my_malloc(catalog_len + 1 +
+ time_zone_len + 1 +
+ data_len + 1, MYF(MY_WME))))
DBUG_VOID_RETURN;
- if (catalog) // If catalog is given
+ if (catalog_len) // If catalog is given
{
- memcpy((char*) start, catalog, catalog_len+1); // Copy name and end \0
+ memcpy(start, catalog, catalog_len+1); // Copy name and end \0
catalog= start;
start+= catalog_len+1;
}
+ if (time_zone_len)
+ {
+ memcpy(start, time_zone_str, time_zone_len);
+ time_zone_str= start;
+ start+= time_zone_len;
+ *start++= 0;
+ }
+ /* A 2nd variable part; this is common to all versions */
memcpy((char*) start, end, data_len); // Copy db and query
- ((char*) start)[data_len]= '\0'; // End query with \0 (For safetly)
+ start[data_len]= '\0'; // End query with \0 (For safetly)
db= start;
query= start + db_len + 1;
q_len= data_len - db_len -1;
- /* This is used to detect wrong parsing. Could be removed in the future. */
- DBUG_PRINT("info", ("catalog: '%s' len: %u db: '%s' len: %u q_len: %lu",
- catalog, (uint) catalog_len, db, (uint) db_len,q_len));
DBUG_VOID_RETURN;
}
@@ -1390,6 +1421,8 @@ void Query_log_event::print_query_header(FILE* file, bool short_form,
last_event_info->auto_increment_offset= auto_increment_offset;
}
+ /* TODO: print the catalog when we feature SET CATALOG */
+
if (likely(charset_inited))
{
if (unlikely(!last_event_info->charset_inited)) /* first Query event */
@@ -1410,6 +1443,14 @@ void Query_log_event::print_query_header(FILE* file, bool short_form,
memcpy(last_event_info->charset, charset, 6);
}
}
+ if (time_zone_len)
+ {
+ if (bcmp(last_event_info->time_zone_str, time_zone_str, time_zone_len+1))
+ {
+ fprintf(file,"SET @@session.time_zone='%s';\n", time_zone_str);
+ memcpy(last_event_info->time_zone_str, time_zone_str, time_zone_len+1);
+ }
+ }
}
@@ -1443,7 +1484,7 @@ int Query_log_event::exec_event(struct st_relay_log_info* rli, const char *query
alloced block (see Query_log_event::exec_event()). Same for thd->db.
Thank you.
*/
- thd->catalog= (char*) catalog;
+ thd->catalog= catalog_len ? (char *) catalog : (char *)"";
thd->db_length= db_len;
thd->db= (char*) rewrite_db(db, &thd->db_length);
thd->variables.auto_increment_increment= auto_increment_increment;
@@ -1513,20 +1554,28 @@ int Query_log_event::exec_event(struct st_relay_log_info* rli, const char *query
get_charset(uint2korr(charset+4), MYF(MY_WME))))
{
/*
- We updated the thd->variables with nonsensical values (0), and the
- thread is not guaranteed to terminate now (as it may be configured
- to ignore EE_UNKNOWN_CHARSET);if we're going to execute a next
- statement we'll have a new charset info with it, so no problem to
- have stored 0 in thd->variables. But we invalidate cached
- charset to force a check next time (otherwise if next time
- charset is unknown again we won't detect it).
+ We updated the thd->variables with nonsensical values (0). Let's
+ set them to something safe (i.e. which avoids crash), and we'll
+ stop with EE_UNKNOWN_CHARSET in compare_errors (unless set to
+ ignore this error).
*/
- rli->cached_charset_invalidate();
+ set_slave_thread_default_charset(thd, rli);
goto compare_errors;
}
thd->update_charset(); // for the charset change to take effect
}
}
+ if (time_zone_len)
+ {
+ String tmp(time_zone_str, time_zone_len, &my_charset_bin);
+ if (!(thd->variables.time_zone=
+ my_tz_find_with_opening_tz_tables(thd, &tmp)))
+ {
+ my_error(ER_UNKNOWN_TIME_ZONE, MYF(0), tmp.c_ptr());
+ thd->variables.time_zone= global_system_variables.time_zone;
+ goto compare_errors;
+ }
+ }
/* Execute the query (note that we bypass dispatch_command()) */
mysql_parse(thd, thd->query, thd->query_length);
@@ -1751,6 +1800,7 @@ Start_log_event_v3::Start_log_event_v3(const char* buf,
Start_log_event_v3::write()
*/
+#ifndef MYSQL_CLIENT
bool Start_log_event_v3::write(IO_CACHE* file)
{
char buff[START_V3_HEADER_LEN];
@@ -1760,6 +1810,7 @@ bool Start_log_event_v3::write(IO_CACHE* file)
return (write_header(file, sizeof(buff)) ||
my_b_safe_write(file, (byte*) buff, sizeof(buff)));
}
+#endif
/*
@@ -1975,7 +2026,7 @@ Format_description_log_event(const char* buf,
DBUG_VOID_RETURN;
}
-
+#ifndef MYSQL_CLIENT
bool Format_description_log_event::write(IO_CACHE* file)
{
/*
@@ -1992,6 +2043,7 @@ bool Format_description_log_event::write(IO_CACHE* file)
return (write_header(file, sizeof(buff)) ||
my_b_safe_write(file, buff, sizeof(buff)));
}
+#endif
/*
SYNOPSIS
@@ -2208,6 +2260,8 @@ void Load_log_event::pack_info(Protocol *protocol)
#endif /* defined(HAVE_REPLICATION) && !defined(MYSQL_CLIENT) */
+#ifndef MYSQL_CLIENT
+
/*
Load_log_event::write_data_header()
*/
@@ -2249,7 +2303,6 @@ bool Load_log_event::write_data_body(IO_CACHE* file)
Load_log_event::Load_log_event()
*/
-#ifndef MYSQL_CLIENT
Load_log_event::Load_log_event(THD *thd_arg, sql_exchange *ex,
const char *db_arg, const char *table_name_arg,
List<Item> &fields_arg,
@@ -2863,6 +2916,7 @@ Rotate_log_event::Rotate_log_event(const char* buf, uint event_len,
Rotate_log_event::write()
*/
+#ifndef MYSQL_CLIENT
bool Rotate_log_event::write(IO_CACHE* file)
{
char buf[ROTATE_HEADER_LEN];
@@ -2871,7 +2925,7 @@ bool Rotate_log_event::write(IO_CACHE* file)
my_b_safe_write(file, (byte*)buf, ROTATE_HEADER_LEN) ||
my_b_safe_write(file, (byte*)new_log_ident, (uint) ident_len));
}
-
+#endif
/*
Rotate_log_event::exec_event()
@@ -2929,17 +2983,10 @@ int Rotate_log_event::exec_event(struct st_relay_log_info* rli)
master is 4.0 then the events are in the slave's format (conversion).
*/
set_slave_thread_options(thd);
+ set_slave_thread_default_charset(thd, rli);
thd->variables.sql_mode= global_system_variables.sql_mode;
thd->variables.auto_increment_increment=
thd->variables.auto_increment_offset= 1;
- thd->variables.character_set_client=
- global_system_variables.character_set_client;
- thd->variables.collation_connection=
- global_system_variables.collation_connection;
- thd->variables.collation_server=
- global_system_variables.collation_server;
- thd->update_charset();
- rli->cached_charset_invalidate();
}
pthread_mutex_unlock(&rli->data_lock);
pthread_cond_broadcast(&rli->data_cond);
@@ -3001,6 +3048,7 @@ const char* Intvar_log_event::get_var_type_name()
Intvar_log_event::write()
*/
+#ifndef MYSQL_CLIENT
bool Intvar_log_event::write(IO_CACHE* file)
{
byte buf[9];
@@ -3009,6 +3057,7 @@ bool Intvar_log_event::write(IO_CACHE* file)
return (write_header(file, sizeof(buf)) ||
my_b_safe_write(file, buf, sizeof(buf)));
}
+#endif
/*
@@ -3093,6 +3142,7 @@ Rand_log_event::Rand_log_event(const char* buf,
}
+#ifndef MYSQL_CLIENT
bool Rand_log_event::write(IO_CACHE* file)
{
byte buf[16];
@@ -3101,6 +3151,7 @@ bool Rand_log_event::write(IO_CACHE* file)
return (write_header(file, sizeof(buf)) ||
my_b_safe_write(file, buf, sizeof(buf)));
}
+#endif
#ifdef MYSQL_CLIENT
@@ -3164,11 +3215,13 @@ Xid_log_event(const char* buf,
}
+#ifndef MYSQL_CLIENT
bool Xid_log_event::write(IO_CACHE* file)
{
return write_header(file, sizeof(xid)) ||
my_b_safe_write(file, (byte*) &xid, sizeof(xid));
}
+#endif
#ifdef MYSQL_CLIENT
@@ -3302,6 +3355,7 @@ User_var_log_event(const char* buf,
}
+#ifndef MYSQL_CLIENT
bool User_var_log_event::write(IO_CACHE* file)
{
char buf[UV_NAME_LEN_SIZE];
@@ -3361,6 +3415,7 @@ bool User_var_log_event::write(IO_CACHE* file)
my_b_safe_write(file, (byte*) buf1, buf1_length) ||
my_b_safe_write(file, (byte*) pos, val_len));
}
+#endif
/*
@@ -3634,6 +3689,7 @@ int Slave_log_event::get_data_size()
}
+#ifndef MYSQL_CLIENT
bool Slave_log_event::write(IO_CACHE* file)
{
ulong event_length= get_data_size();
@@ -3644,6 +3700,7 @@ bool Slave_log_event::write(IO_CACHE* file)
return (write_header(file, event_length) ||
my_b_safe_write(file, (byte*) mem_pool, event_length));
}
+#endif
void Slave_log_event::init_from_mem_pool(int data_size)
@@ -3770,7 +3827,6 @@ Create_file_log_event(THD* thd_arg, sql_exchange* ex,
sql_ex.force_new_format();
DBUG_VOID_RETURN;
}
-#endif /* !MYSQL_CLIENT */
/*
@@ -3815,6 +3871,7 @@ bool Create_file_log_event::write_base(IO_CACHE* file)
return res;
}
+#endif /* !MYSQL_CLIENT */
/*
Create_file_log_event ctor
@@ -4042,6 +4099,7 @@ Append_block_log_event::Append_block_log_event(const char* buf, uint len,
Append_block_log_event::write()
*/
+#ifndef MYSQL_CLIENT
bool Append_block_log_event::write(IO_CACHE* file)
{
byte buf[APPEND_BLOCK_HEADER_LEN];
@@ -4050,6 +4108,7 @@ bool Append_block_log_event::write(IO_CACHE* file)
my_b_safe_write(file, buf, APPEND_BLOCK_HEADER_LEN) ||
my_b_safe_write(file, (byte*) block, block_len));
}
+#endif
/*
@@ -4171,6 +4230,7 @@ Delete_file_log_event::Delete_file_log_event(const char* buf, uint len,
Delete_file_log_event::write()
*/
+#ifndef MYSQL_CLIENT
bool Delete_file_log_event::write(IO_CACHE* file)
{
byte buf[DELETE_FILE_HEADER_LEN];
@@ -4178,6 +4238,7 @@ bool Delete_file_log_event::write(IO_CACHE* file)
return (write_header(file, sizeof(buf)) ||
my_b_safe_write(file, buf, sizeof(buf)));
}
+#endif
/*
@@ -4265,6 +4326,7 @@ Execute_load_log_event::Execute_load_log_event(const char* buf, uint len,
Execute_load_log_event::write()
*/
+#ifndef MYSQL_CLIENT
bool Execute_load_log_event::write(IO_CACHE* file)
{
byte buf[EXEC_LOAD_HEADER_LEN];
@@ -4272,6 +4334,7 @@ bool Execute_load_log_event::write(IO_CACHE* file)
return (write_header(file, sizeof(buf)) ||
my_b_safe_write(file, buf, sizeof(buf)));
}
+#endif
/*
@@ -4475,6 +4538,7 @@ ulong Execute_load_query_log_event::get_post_header_size_for_derived()
}
+#ifndef MYSQL_CLIENT
bool
Execute_load_query_log_event::write_post_header_for_derived(IO_CACHE* file)
{
@@ -4485,6 +4549,7 @@ Execute_load_query_log_event::write_post_header_for_derived(IO_CACHE* file)
*(buf + 4 + 4 + 4)= (char)dup_handling;
return my_b_safe_write(file, (byte*) buf, EXECUTE_LOAD_QUERY_EXTRA_HEADER_LEN);
}
+#endif
#ifdef MYSQL_CLIENT
diff --git a/sql/log_event.h b/sql/log_event.h
index 43a801da851..72142db0aa7 100644
--- a/sql/log_event.h
+++ b/sql/log_event.h
@@ -237,6 +237,7 @@ struct sql_ex_info
#define Q_CATALOG_CODE 2
#define Q_AUTO_INCREMENT 3
#define Q_CHARSET_CODE 4
+#define Q_TIME_ZONE_CODE 5
/* Intvar event post-header */
@@ -448,6 +449,7 @@ typedef struct st_last_event_info
ulong auto_increment_increment, auto_increment_offset;
bool charset_inited;
char charset[6]; // 3 variables, each of them storable in 2 bytes
+ char time_zone_str[MAX_TIME_ZONE_NAME_LENGTH];
st_last_event_info()
:flags2_inited(0), sql_mode_inited(0),
auto_increment_increment(1),auto_increment_offset(1), charset_inited(0)
@@ -459,6 +461,7 @@ typedef struct st_last_event_info
*/
bzero(db, sizeof(db));
bzero(charset, sizeof(charset));
+ bzero(time_zone_str, sizeof(time_zone_str));
}
} LAST_EVENT_INFO;
#endif
@@ -583,6 +586,7 @@ public:
my_free((gptr) ptr, MYF(MY_WME|MY_ALLOW_ZERO_PTR));
}
+#ifndef MYSQL_CLIENT
bool write_header(IO_CACHE* file, ulong data_length);
virtual bool write(IO_CACHE* file)
{
@@ -590,13 +594,14 @@ public:
write_data_header(file) ||
write_data_body(file));
}
- virtual bool is_artificial_event() { return 0; }
virtual bool write_data_header(IO_CACHE* file)
{ return 0; }
virtual bool write_data_body(IO_CACHE* file __attribute__((unused)))
{ return 0; }
+#endif
virtual Log_event_type get_type_code() = 0;
virtual bool is_valid() const = 0;
+ virtual bool is_artificial_event() { return 0; }
inline bool get_cache_stmt() { return cache_stmt; }
Log_event(const char* buf, const Format_description_log_event* description_event);
virtual ~Log_event() { free_temp_buf();}
@@ -672,7 +677,7 @@ public:
concerned) from here.
*/
- int catalog_len; // <= 255 char; -1 means uninited
+ uint catalog_len; // <= 255 char; 0 means uninited
/*
We want to be able to store a variable number of N-bit status vars:
@@ -714,6 +719,8 @@ public:
ulong sql_mode;
ulong auto_increment_increment, auto_increment_offset;
char charset[6];
+ uint time_zone_len; /* 0 means uninited */
+ const char *time_zone_str;
#ifndef MYSQL_CLIENT
@@ -737,12 +744,13 @@ public:
~Query_log_event()
{
if (data_buf)
- {
my_free((gptr) data_buf, MYF(0));
- }
}
Log_event_type get_type_code() { return QUERY_EVENT; }
+#ifndef MYSQL_CLIENT
bool write(IO_CACHE* file);
+ virtual bool write_post_header_for_derived(IO_CACHE* file) { return FALSE; }
+#endif
bool is_valid() const { return query != 0; }
/*
@@ -751,7 +759,6 @@ public:
*/
virtual ulong get_post_header_size_for_derived() { return 0; }
/* Writes derived event-specific part of post header. */
- virtual bool write_post_header_for_derived(IO_CACHE* file) { return FALSE; }
};
#ifdef HAVE_REPLICATION
@@ -790,7 +797,9 @@ public:
int get_data_size();
bool is_valid() const { return master_host != 0; }
Log_event_type get_type_code() { return SLAVE_EVENT; }
+#ifndef MYSQL_CLIENT
bool write(IO_CACHE* file);
+#endif
};
#endif /* HAVE_REPLICATION */
@@ -885,8 +894,10 @@ public:
{
return sql_ex.new_format() ? NEW_LOAD_EVENT: LOAD_EVENT;
}
+#ifndef MYSQL_CLIENT
bool write_data_header(IO_CACHE* file);
bool write_data_body(IO_CACHE* file);
+#endif
bool is_valid() const { return table_name != 0; }
int get_data_size()
{
@@ -962,7 +973,9 @@ public:
const Format_description_log_event* description_event);
~Start_log_event_v3() {}
Log_event_type get_type_code() { return START_EVENT_V3;}
+#ifndef MYSQL_CLIENT
bool write(IO_CACHE* file);
+#endif
bool is_valid() const { return 1; }
int get_data_size()
{
@@ -1004,7 +1017,9 @@ public:
const Format_description_log_event* description_event);
~Format_description_log_event() { my_free((gptr)post_header_len, MYF(0)); }
Log_event_type get_type_code() { return FORMAT_DESCRIPTION_EVENT;}
+#ifndef MYSQL_CLIENT
bool write(IO_CACHE* file);
+#endif
bool is_valid() const
{
return ((common_header_len >= ((binlog_version==1) ? OLD_HEADER_LEN :
@@ -1054,7 +1069,9 @@ public:
Log_event_type get_type_code() { return INTVAR_EVENT;}
const char* get_var_type_name();
int get_data_size() { return 9; /* sizeof(type) + sizeof(val) */;}
+#ifndef MYSQL_CLIENT
bool write(IO_CACHE* file);
+#endif
bool is_valid() const { return 1; }
};
@@ -1092,7 +1109,9 @@ class Rand_log_event: public Log_event
~Rand_log_event() {}
Log_event_type get_type_code() { return RAND_EVENT;}
int get_data_size() { return 16; /* sizeof(ulonglong) * 2*/ }
+#ifndef MYSQL_CLIENT
bool write(IO_CACHE* file);
+#endif
bool is_valid() const { return 1; }
};
@@ -1127,7 +1146,9 @@ class Xid_log_event: public Log_event
~Xid_log_event() {}
Log_event_type get_type_code() { return XID_EVENT;}
int get_data_size() { return sizeof(xid); }
+#ifndef MYSQL_CLIENT
bool write(IO_CACHE* file);
+#endif
bool is_valid() const { return 1; }
};
@@ -1169,7 +1190,9 @@ public:
User_var_log_event(const char* buf, const Format_description_log_event* description_event);
~User_var_log_event() {}
Log_event_type get_type_code() { return USER_VAR_EVENT;}
+#ifndef MYSQL_CLIENT
bool write(IO_CACHE* file);
+#endif
bool is_valid() const { return 1; }
};
@@ -1239,7 +1262,9 @@ public:
Log_event_type get_type_code() { return ROTATE_EVENT;}
int get_data_size() { return ident_len + ROTATE_HEADER_LEN;}
bool is_valid() const { return new_log_ident != 0; }
+#ifndef MYSQL_CLIENT
bool write(IO_CACHE* file);
+#endif
};
@@ -1299,6 +1324,7 @@ public:
4 + 1 + block_len);
}
bool is_valid() const { return inited_from_old || block != 0; }
+#ifndef MYSQL_CLIENT
bool write_data_header(IO_CACHE* file);
bool write_data_body(IO_CACHE* file);
/*
@@ -1306,6 +1332,7 @@ public:
write it as Load event - used on the slave
*/
bool write_base(IO_CACHE* file);
+#endif
};
@@ -1352,7 +1379,9 @@ public:
Log_event_type get_type_code() { return APPEND_BLOCK_EVENT;}
int get_data_size() { return block_len + APPEND_BLOCK_HEADER_LEN ;}
bool is_valid() const { return block != 0; }
+#ifndef MYSQL_CLIENT
bool write(IO_CACHE* file);
+#endif
const char* get_db() { return db; }
};
@@ -1386,7 +1415,9 @@ public:
Log_event_type get_type_code() { return DELETE_FILE_EVENT;}
int get_data_size() { return DELETE_FILE_HEADER_LEN ;}
bool is_valid() const { return file_id != 0; }
+#ifndef MYSQL_CLIENT
bool write(IO_CACHE* file);
+#endif
const char* get_db() { return db; }
};
@@ -1419,7 +1450,9 @@ public:
Log_event_type get_type_code() { return EXEC_LOAD_EVENT;}
int get_data_size() { return EXEC_LOAD_HEADER_LEN ;}
bool is_valid() const { return file_id != 0; }
+#ifndef MYSQL_CLIENT
bool write(IO_CACHE* file);
+#endif
const char* get_db() { return db; }
};
@@ -1507,7 +1540,9 @@ public:
bool is_valid() const { return Query_log_event::is_valid() && file_id != 0; }
ulong get_post_header_size_for_derived();
+#ifndef MYSQL_CLIENT
bool write_post_header_for_derived(IO_CACHE* file);
+#endif
};
diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h
index ba9f382fc33..64e7b2cdccf 100644
--- a/sql/mysql_priv.h
+++ b/sql/mysql_priv.h
@@ -257,6 +257,12 @@ extern CHARSET_INFO *national_charset_info, *table_alias_charset;
/* Flag set if setup_tables already done */
#define OPTION_SETUP_TABLES_DONE (1L << 30)
+/*
+ Maximum length of time zone name that we support
+ (Time zone name is char(64) in db). mysqlbinlog needs it.
+*/
+#define MAX_TIME_ZONE_NAME_LENGTH 72
+
/* The rest of the file is included in the server only */
#ifndef MYSQL_CLIENT
diff --git a/sql/set_var.cc b/sql/set_var.cc
index 23dbb22399b..9e74c9452da 100644
--- a/sql/set_var.cc
+++ b/sql/set_var.cc
@@ -2095,27 +2095,6 @@ void sys_var_character_set_server::set_default(THD *thd, enum_var_type type)
}
}
-#if defined(HAVE_REPLICATION) && (MYSQL_VERSION_ID < 50003)
-bool sys_var_character_set_server::check(THD *thd, set_var *var)
-{
- /*
- To be perfect we should fail even if we are a 5.0.3 slave, a 4.1 master,
- and user wants to change our global character set variables. Because
- replicating a 4.1 assumes those are not changed. But that's not easy to
- do.
- */
- if ((var->type == OPT_GLOBAL) &&
- (mysql_bin_log.is_open() ||
- active_mi->slave_running || active_mi->rli.slave_running))
- {
- my_error(ER_LOGGING_PROHIBIT_CHANGING_OF, MYF(0),
- "character set, collation");
- return 1;
- }
- return sys_var_character_set::check(thd,var);
-}
-#endif
-
CHARSET_INFO ** sys_var_character_set_database::ci_ptr(THD *thd,
enum_var_type type)
{
@@ -2208,20 +2187,6 @@ void sys_var_collation_database::set_default(THD *thd, enum_var_type type)
}
}
-#if defined(HAVE_REPLICATION) && (MYSQL_VERSION_ID < 50003)
-bool sys_var_collation_server::check(THD *thd, set_var *var)
-{
- if ((var->type == OPT_GLOBAL) &&
- (mysql_bin_log.is_open() ||
- active_mi->slave_running || active_mi->rli.slave_running))
- {
- my_error(ER_LOGGING_PROHIBIT_CHANGING_OF, MYF(0),
- "character set, collation");
- return 1;
- }
- return sys_var_collation::check(thd,var);
-}
-#endif
bool sys_var_collation_server::update(THD *thd, set_var *var)
{
@@ -2560,16 +2525,6 @@ bool sys_var_thd_time_zone::check(THD *thd, set_var *var)
String str(buff, sizeof(buff), &my_charset_latin1);
String *res= var->value->val_str(&str);
-#if defined(HAVE_REPLICATION)
- if ((var->type == OPT_GLOBAL) &&
- (mysql_bin_log.is_open() ||
- active_mi->slave_running || active_mi->rli.slave_running))
- {
- my_error(ER_LOGGING_PROHIBIT_CHANGING_OF, MYF(0), "time zone");
- return 1;
- }
-#endif
-
if (!(var->save_result.time_zone=
my_tz_find(res, thd->lex->time_zone_tables_used)))
{
@@ -2605,7 +2560,18 @@ byte *sys_var_thd_time_zone::value_ptr(THD *thd, enum_var_type type,
if (type == OPT_GLOBAL)
return (byte *)(global_system_variables.time_zone->get_name()->ptr());
else
+ {
+ /*
+ This is an ugly fix for replication: we don't replicate properly queries
+ invoking system variables' values to update tables; but
+ CONVERT_TZ(,,@@session.time_zone) is so popular that we make it
+ replicable (i.e. we tell the binlog code to store the session
+ timezone). If it's the global value which was used we can't replicate
+ (binlog code stores session value only).
+ */
+ thd->time_zone_used= 1;
return (byte *)(thd->variables.time_zone->get_name()->ptr());
+ }
}
diff --git a/sql/set_var.h b/sql/set_var.h
index d78c228c142..585f6df3547 100644
--- a/sql/set_var.h
+++ b/sql/set_var.h
@@ -565,9 +565,6 @@ class sys_var_character_set_server :public sys_var_character_set
public:
sys_var_character_set_server(const char *name_arg) :
sys_var_character_set(name_arg) {}
-#if defined(HAVE_REPLICATION) && (MYSQL_VERSION_ID < 50003)
- bool check(THD *thd, set_var *var);
-#endif
void set_default(THD *thd, enum_var_type type);
CHARSET_INFO **ci_ptr(THD *thd, enum_var_type type);
};
@@ -603,9 +600,6 @@ class sys_var_collation_server :public sys_var_collation
{
public:
sys_var_collation_server(const char *name_arg) :sys_var_collation(name_arg) {}
-#if defined(HAVE_REPLICATION) && (MYSQL_VERSION_ID < 50003)
- bool check(THD *thd, set_var *var);
-#endif
bool update(THD *thd, set_var *var);
void set_default(THD *thd, enum_var_type type);
byte *value_ptr(THD *thd, enum_var_type type, LEX_STRING *base);
diff --git a/sql/slave.cc b/sql/slave.cc
index 73dd0fd13c3..9e42206d4a3 100644
--- a/sql/slave.cc
+++ b/sql/slave.cc
@@ -1421,7 +1421,7 @@ not always make sense; please check the manual before using it).";
We don't test equality of global collation_database either as it's is
going to be deprecated (made read-only) in 4.1 very soon.
The test is only relevant if master < 5.0.3 (we'll test only if it's older
- than the 5 branch; < 5.0.3 was alpha...), as >= 5.0.3 master stores
+ than the 5 branch; < 5.0.4 were alpha...), as >= 5.0.4 master stores
charset info in each binlog event.
We don't do it for 3.23 because masters <3.23.50 hang on
SELECT @@unknown_var (BUG#7965 - see changelog of 3.23.50). So finally we
@@ -1456,11 +1456,10 @@ be equal for replication to work";
such check will broke everything for them. (And now everything will
work for them because by default both their master and slave will have
'SYSTEM' time zone).
-
- TODO: when the new replication of timezones is sorted out with Dmitri,
- change >= '4' to == '4'.
+ This check is only necessary for 4.x masters (and < 5.0.4 masters but
+ those were alpha).
*/
- if ((*mysql->server_version >= '4') &&
+ if ((*mysql->server_version == '4') &&
!mysql_real_query(mysql, "SELECT @@GLOBAL.TIME_ZONE", 25) &&
(master_res= mysql_store_result(mysql)))
{
@@ -2770,6 +2769,18 @@ void set_slave_thread_options(THD* thd)
thd->variables.completion_type= 0;
}
+void set_slave_thread_default_charset(THD* thd, RELAY_LOG_INFO *rli)
+{
+ thd->variables.character_set_client=
+ global_system_variables.character_set_client;
+ thd->variables.collation_connection=
+ global_system_variables.collation_connection;
+ thd->variables.collation_server=
+ global_system_variables.collation_server;
+ thd->update_charset();
+ rli->cached_charset_invalidate();
+}
+
/*
init_slave_thread()
*/
diff --git a/sql/slave.h b/sql/slave.h
index ee5541ffe08..bc41cd4deca 100644
--- a/sql/slave.h
+++ b/sql/slave.h
@@ -562,6 +562,7 @@ int init_relay_log_pos(RELAY_LOG_INFO* rli,const char* log,ulonglong pos,
int purge_relay_logs(RELAY_LOG_INFO* rli, THD *thd, bool just_reset,
const char** errmsg);
void set_slave_thread_options(THD* thd);
+void set_slave_thread_default_charset(THD* thd, RELAY_LOG_INFO *rli);
void rotate_relay_log(MASTER_INFO* mi);
extern "C" pthread_handler_decl(handle_slave_io,arg);
diff --git a/sql/tztime.cc b/sql/tztime.cc
index bd9d49f0ab0..983c630071e 100644
--- a/sql/tztime.cc
+++ b/sql/tztime.cc
@@ -2178,7 +2178,7 @@ my_tz_find(const String * name, TABLE_LIST *tz_tables)
DBUG_PRINT("enter", ("time zone name='%s'",
name ? ((String *)name)->c_ptr() : "NULL"));
- DBUG_ASSERT(!time_zone_tables_exist || tz_tables);
+ DBUG_ASSERT(!time_zone_tables_exist || tz_tables || current_thd->slave_thread);
if (!name)
DBUG_RETURN(0);
@@ -2210,7 +2210,7 @@ my_tz_find(const String * name, TABLE_LIST *tz_tables)
(const byte *)name->ptr(),
name->length())))
result_tz= tmp_tzname->tz;
- else if (time_zone_tables_exist)
+ else if (time_zone_tables_exist && tz_tables)
result_tz= tz_load_from_open_tables(name, tz_tables);
}
@@ -2219,6 +2219,58 @@ my_tz_find(const String * name, TABLE_LIST *tz_tables)
DBUG_RETURN(result_tz);
}
+
+/*
+ A more standalone version of my_tz_find(): will open tz tables if needed.
+ This is so far only used by replication, where time zone setting does not
+ happen in the usual query context.
+
+ SYNOPSIS
+ my_tz_find_with_opening_tz_tables()
+ thd - pointer to thread's THD structure
+ name - time zone specification
+
+ DESCRIPTION
+ This function tries to find a time zone which matches the named passed in
+ argument. If it fails, it will open time zone tables and re-try the
+ search.
+ This function is needed for the slave SQL thread, which does not do the
+ addition of time zone tables which is usually done during query parsing
+ (as time zone setting by slave does not happen in mysql_parse() but
+ before). So it needs to open tz tables by itself if needed.
+ See notes of my_tz_find() as they also apply here.
+
+ RETURN VALUE
+ Pointer to corresponding Time_zone object. 0 - in case of bad time zone
+ specification or other error.
+
+*/
+Time_zone *my_tz_find_with_opening_tz_tables(THD *thd, const String *name)
+{
+ Time_zone *tz;
+ DBUG_ENTER("my_tz_find_with_opening_tables");
+ DBUG_ASSERT(thd);
+ DBUG_ASSERT(thd->slave_thread); // intended for use with slave thread only
+ if (!(tz= my_tz_find(name, 0)) && time_zone_tables_exist)
+ {
+ /*
+ Probably we have not loaded this time zone yet so let us look it up in
+ our time zone tables. Note that if we don't have tz tables on this
+ slave, we don't even try.
+ */
+ TABLE_LIST tables[4];
+ TABLE_LIST *dummy;
+ TABLE_LIST **dummyp= &dummy;
+ tz_init_table_list(tables, &dummyp);
+ if (simple_open_n_lock_tables(thd, tables))
+ DBUG_RETURN(0);
+ tz= my_tz_find(name, tables);
+ /* We need to close tables _now_ to not pollute coming query */
+ close_thread_tables(thd);
+ }
+ DBUG_RETURN(tz);
+}
+
#endif /* !defined(TESTTIME) && !defined(TZINFO2SQL) */
diff --git a/sql/tztime.h b/sql/tztime.h
index caf663fc8cb..777e521d761 100644
--- a/sql/tztime.h
+++ b/sql/tztime.h
@@ -61,6 +61,7 @@ extern Time_zone * my_tz_UTC;
extern Time_zone * my_tz_SYSTEM;
extern TABLE_LIST * my_tz_get_table_list(THD *thd, TABLE_LIST ***global_next_ptr);
extern Time_zone * my_tz_find(const String *name, TABLE_LIST *tz_tables);
+extern Time_zone * my_tz_find_with_opening_tz_tables(THD *thd, const String *name);
extern my_bool my_tz_init(THD *org_thd, const char *default_tzname, my_bool bootstrap);
extern void my_tz_free();
@@ -96,10 +97,4 @@ inline bool my_tz_check_n_skip_implicit_tables(TABLE_LIST **table,
return FALSE;
}
-/*
- Maximum length of time zone name that we support
- (Time zone name is char(64) in db)
-*/
-#define MAX_TIME_ZONE_NAME_LENGTH 72
-
#endif /* !defined(TESTTIME) && !defined(TZINFO2SQL) */