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.
parent 371850a4
...@@ -48,6 +48,7 @@ dlenev@build.mysql.com ...@@ -48,6 +48,7 @@ dlenev@build.mysql.com
dlenev@jabberwock.localdomain dlenev@jabberwock.localdomain
dlenev@mysql.com dlenev@mysql.com
ejonore@mc03.ndb.mysql.com ejonore@mc03.ndb.mysql.com
gbichot@production.mysql.com
gbichot@quadita2.mysql.com gbichot@quadita2.mysql.com
georg@beethoven.local georg@beethoven.local
georg@beethoven.site georg@beethoven.site
......
...@@ -33,9 +33,9 @@ ...@@ -33,9 +33,9 @@
#undef MYSQL_SERVER #undef MYSQL_SERVER
#include "client_priv.h" #include "client_priv.h"
#include <my_time.h> #include <my_time.h>
#include "log_event.h"
/* That one is necessary for defines of OPTION_NO_FOREIGN_KEY_CHECKS etc */ /* That one is necessary for defines of OPTION_NO_FOREIGN_KEY_CHECKS etc */
#include "mysql_priv.h" #include "mysql_priv.h"
#include "log_event.h"
#define BIN_LOG_HEADER_SIZE 4 #define BIN_LOG_HEADER_SIZE 4
#define PROBE_HEADER_LEN (EVENT_LEN_OFFSET+4) #define PROBE_HEADER_LEN (EVENT_LEN_OFFSET+4)
......
...@@ -4,21 +4,31 @@ reset master; ...@@ -4,21 +4,31 @@ reset master;
reset slave; reset slave;
drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9; drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
start slave; start slave;
set timestamp=100000000;
create table t1 (t timestamp); create table t1 (t timestamp);
create table t2 (t char(32)); create table t2 (t char(32));
select @@time_zone; select @@time_zone;
@@time_zone @@time_zone
Japan
select @@time_zone;
@@time_zone
Europe/Moscow Europe/Moscow
insert into t1 values ('20050101000000'), ('20050611093902');
set time_zone='UTC'; set time_zone='UTC';
insert into t1 values ('20040101000000'), ('20040611093902'); insert into t1 values ('20040101000000'), ('20040611093902');
select * from t1; select * from t1;
t t
2004-12-31 21:00:00
2005-06-11 05:39:02
2004-01-01 00:00:00 2004-01-01 00:00:00
2004-06-11 09:39:02 2004-06-11 09:39:02
set time_zone='UTC';
select * from t1; select * from t1;
t t
2004-01-01 03:00:00 2004-12-31 21:00:00
2004-06-11 13:39:02 2005-06-11 05:39:02
2004-01-01 00:00:00
2004-06-11 09:39:02
delete from t1; delete from t1;
set time_zone='Europe/Moscow'; set time_zone='Europe/Moscow';
insert into t1 values ('20040101000000'), ('20040611093902'); insert into t1 values ('20040101000000'), ('20040611093902');
...@@ -26,19 +36,35 @@ select * from t1; ...@@ -26,19 +36,35 @@ select * from t1;
t t
2004-01-01 00:00:00 2004-01-01 00:00:00
2004-06-11 09:39:02 2004-06-11 09:39:02
set time_zone='Europe/Moscow';
select * from t1; select * from t1;
t t
2004-01-01 00:00:00 2004-01-01 00:00:00
2004-06-11 09:39:02 2004-06-11 09:39:02
show binlog events; /*!40019 SET @@session.max_insert_delayed_threads=0*/;
Log_name Pos Event_type Server_id End_log_pos Info /*!50003 SET @OLD_COMPLETION_TYPE=@@COMPLETION_TYPE,COMPLETION_TYPE=0*/;
master-bin.000001 # Format_desc 1 # Server ver: VERSION, Binlog ver: 4 ROLLBACK;
master-bin.000001 # Query 1 # use `test`; create table t1 (t timestamp) use test;
master-bin.000001 # Query 1 # use `test`; create table t2 (t char(32)) SET TIMESTAMP=100000000;
master-bin.000001 # Query 1 # use `test`; SET ONE_SHOT TIME_ZONE='UTC' SET @@session.foreign_key_checks=1, @@session.sql_auto_is_null=1, @@session.unique_checks=1;
master-bin.000001 # Query 1 # use `test`; insert into t1 values ('20040101000000'), ('20040611093902') SET @@session.sql_mode=0;
master-bin.000001 # Query 1 # use `test`; delete from t1 SET @@session.character_set_client=8,@@session.collation_connection=8,@@session.collation_server=8;
master-bin.000001 # Query 1 # use `test`; insert into t1 values ('20040101000000'), ('20040611093902') 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'; set time_zone='MET';
insert into t2 (select t from t1); insert into t2 (select t from t1);
select * from t1; select * from t1;
...@@ -52,10 +78,6 @@ t ...@@ -52,10 +78,6 @@ t
delete from t2; delete from t2;
set timestamp=1000072000; set timestamp=1000072000;
insert into t2 values (current_timestamp), (current_date), (current_time); 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; select * from t2;
t t
2001-09-09 23:46:40 2001-09-09 23:46:40
...@@ -73,5 +95,16 @@ t ...@@ -73,5 +95,16 @@ t
2001-09-09 03:46:40 2001-09-09 03:46:40
1000000000 1000000000
set global time_zone='MET'; 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; drop table t1, t2;
--default-time-zone=Europe/Moscow --default-time-zone=Japan
...@@ -3,21 +3,25 @@ source include/master-slave.inc; ...@@ -3,21 +3,25 @@ source include/master-slave.inc;
# Some preparations # Some preparations
let $VERSION=`select version()`; let $VERSION=`select version()`;
set timestamp=100000000; # for fixed output of mysqlbinlog
create table t1 (t timestamp); create table t1 (t timestamp);
create table t2 (t char(32)); create table t2 (t char(32));
connection slave;
select @@time_zone;
# #
# Let us check how well replication works when we are saving datetime # Let us check how well replication works when we are saving datetime
# value in TIMESTAMP field. # value in TIMESTAMP field.
# #
connection master; connection master;
select @@time_zone; select @@time_zone;
insert into t1 values ('20050101000000'), ('20050611093902');
set time_zone='UTC'; set time_zone='UTC';
insert into t1 values ('20040101000000'), ('20040611093902'); insert into t1 values ('20040101000000'), ('20040611093902');
select * from t1; select * from t1;
# On slave we still in 'Europe/Moscow' so we should see equivalent but
# textually different values.
sync_slave_with_master; sync_slave_with_master;
set time_zone='UTC';
select * from t1; select * from t1;
# Let us check also that setting of time_zone back to default also works # Let us check also that setting of time_zone back to default also works
...@@ -28,12 +32,11 @@ set time_zone='Europe/Moscow'; ...@@ -28,12 +32,11 @@ set time_zone='Europe/Moscow';
insert into t1 values ('20040101000000'), ('20040611093902'); insert into t1 values ('20040101000000'), ('20040611093902');
select * from t1; select * from t1;
sync_slave_with_master; sync_slave_with_master;
set time_zone='Europe/Moscow';
select * from t1; select * from t1;
connection master; connection master;
# We should not see SET ONE_SHOT time_zone before second insert --replace_result $MYSQL_TEST_DIR MYSQL_TEST_DIR
--replace_result $VERSION VERSION --exec $MYSQL_BINLOG --short-form $MYSQL_TEST_DIR/var/log/master-bin.000001
--replace_column 2 # 5 #
show binlog events;
# #
# Now let us check how well we replicate statments reading TIMESTAMP fields # Now let us check how well we replicate statments reading TIMESTAMP fields
...@@ -54,10 +57,6 @@ delete from t2; ...@@ -54,10 +57,6 @@ delete from t2;
set timestamp=1000072000; set timestamp=1000072000;
insert into t2 values (current_timestamp), (current_date), (current_time); insert into t2 values (current_timestamp), (current_date), (current_time);
sync_slave_with_master; 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; select * from t2;
# #
...@@ -73,13 +72,24 @@ sync_slave_with_master; ...@@ -73,13 +72,24 @@ sync_slave_with_master;
select * from t2; 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 # replication
# #
connection master; connection master;
--error 1387
set global time_zone='MET'; 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 # Clean up
connection master;
drop table t1, t2; drop table t1, t2;
sync_slave_with_master; sync_slave_with_master;
...@@ -1307,6 +1307,9 @@ innobase_end(void) ...@@ -1307,6 +1307,9 @@ innobase_end(void)
} }
#endif #endif
if (innodb_inited) { 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) { if (innobase_very_fast_shutdown) {
srv_very_fast_shutdown = TRUE; srv_very_fast_shutdown = TRUE;
fprintf(stderr, fprintf(stderr,
...@@ -1314,6 +1317,7 @@ innobase_end(void) ...@@ -1314,6 +1317,7 @@ innobase_end(void)
"InnoDB: the InnoDB buffer pool to data files. At the next mysqld startup\n" "InnoDB: the InnoDB buffer pool to data files. At the next mysqld startup\n"
"InnoDB: InnoDB will do a crash recovery!\n"); "InnoDB: InnoDB will do a crash recovery!\n");
} }
#endif
innodb_inited = 0; innodb_inited = 0;
if (innobase_shutdown_for_mysql() != DB_SUCCESS) { if (innobase_shutdown_for_mysql() != DB_SUCCESS) {
......
...@@ -1638,57 +1638,6 @@ bool MYSQL_LOG::write(Log_event *event_info) ...@@ -1638,57 +1638,6 @@ bool MYSQL_LOG::write(Log_event *event_info)
if (thd) 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) if (thd->last_insert_id_used)
{ {
Intvar_log_event e(thd,(uchar) LAST_INSERT_ID_EVENT, Intvar_log_event e(thd,(uchar) LAST_INSERT_ID_EVENT,
......
...@@ -506,8 +506,6 @@ void Log_event::init_show_field_list(List<Item>* field_list) ...@@ -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)); field_list->push_back(new Item_empty_string("Info", 20));
} }
#endif /* !MYSQL_CLIENT */
/* /*
Log_event::write() Log_event::write()
...@@ -592,7 +590,6 @@ bool Log_event::write_header(IO_CACHE* file, ulong event_data_length) ...@@ -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, int Log_event::read_log_event(IO_CACHE* file, String* packet,
pthread_mutex_t* log_lock) pthread_mutex_t* log_lock)
{ {
...@@ -956,6 +953,7 @@ void Query_log_event::pack_info(Protocol *protocol) ...@@ -956,6 +953,7 @@ void Query_log_event::pack_info(Protocol *protocol)
} }
#endif #endif
#ifndef MYSQL_CLIENT
/* /*
Query_log_event::write() Query_log_event::write()
...@@ -973,7 +971,8 @@ bool Query_log_event::write(IO_CACHE* file) ...@@ -973,7 +971,8 @@ bool Query_log_event::write(IO_CACHE* file)
1+8+ // code of sql_mode and sql_mode 1+8+ // code of sql_mode and sql_mode
1+1+FN_REFLEN+ // code of catalog and catalog length and catalog 1+1+FN_REFLEN+ // code of catalog and catalog length and catalog
1+4+ // code of autoinc and the 2 autoinc variables 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; ], *start, *start_of_status;
ulong event_length; ulong event_length;
...@@ -1030,20 +1029,20 @@ bool Query_log_event::write(IO_CACHE* file) ...@@ -1030,20 +1029,20 @@ bool Query_log_event::write(IO_CACHE* file)
start_of_status= start= buf+QUERY_HEADER_LEN; start_of_status= start= buf+QUERY_HEADER_LEN;
if (flags2_inited) if (flags2_inited)
{ {
*(start++)= Q_FLAGS2_CODE; *start++= Q_FLAGS2_CODE;
int4store(start, flags2); int4store(start, flags2);
start+= 4; start+= 4;
} }
if (sql_mode_inited) if (sql_mode_inited)
{ {
*(start++)= Q_SQL_MODE_CODE; *start++= Q_SQL_MODE_CODE;
int8store(start, (ulonglong)sql_mode); int8store(start, (ulonglong)sql_mode);
start+= 8; 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++= Q_CATALOG_CODE;
*(start++)= (uchar) catalog_len; *start++= (uchar) catalog_len;
bmove(start, catalog, catalog_len); bmove(start, catalog, catalog_len);
start+= catalog_len; start+= catalog_len;
/* /*
...@@ -1071,15 +1070,24 @@ bool Query_log_event::write(IO_CACHE* file) ...@@ -1071,15 +1070,24 @@ bool Query_log_event::write(IO_CACHE* file)
} }
if (charset_inited) if (charset_inited)
{ {
*(start++)= Q_CHARSET_CODE; *start++= Q_CHARSET_CODE;
memcpy(start, charset, 6); memcpy(start, charset, 6);
start+= 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 Here there could be code like
if (command-line-option-which-says-"log_this_variable" && inited) if (command-line-option-which-says-"log_this_variable" && inited)
{ {
*(start++)= Q_THIS_VARIABLE_CODE; *start++= Q_THIS_VARIABLE_CODE;
int4store(start, this_variable); int4store(start, this_variable);
start+= 4; start+= 4;
} }
...@@ -1108,8 +1116,6 @@ bool Query_log_event::write(IO_CACHE* file) ...@@ -1108,8 +1116,6 @@ bool Query_log_event::write(IO_CACHE* file)
/* /*
Query_log_event::Query_log_event() Query_log_event::Query_log_event()
*/ */
#ifndef MYSQL_CLIENT
Query_log_event::Query_log_event(THD* thd_arg, const char* query_arg, Query_log_event::Query_log_event(THD* thd_arg, const char* query_arg,
ulong query_length, bool using_trans, ulong query_length, bool using_trans,
bool suppress_use) bool suppress_use)
...@@ -1150,6 +1156,18 @@ Query_log_event::Query_log_event(THD* thd_arg, const char* query_arg, ...@@ -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, thd_arg->variables.character_set_client->number);
int2store(charset+2, thd_arg->variables.collation_connection->number); int2store(charset+2, thd_arg->variables.collation_connection->number);
int2store(charset+4, thd_arg->variables.collation_server->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)); DBUG_PRINT("info",("Query_log_event has flags2=%lu sql_mode=%lu",flags2,sql_mode));
} }
#endif /* MYSQL_CLIENT */ #endif /* MYSQL_CLIENT */
...@@ -1163,15 +1181,17 @@ Query_log_event::Query_log_event(THD* thd_arg, const char* query_arg, ...@@ -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, Query_log_event::Query_log_event(const char* buf, uint event_len,
const Format_description_log_event *description_event, const Format_description_log_event *description_event,
Log_event_type event_type) 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), db(NullS), catalog_len(0), status_vars_len(0),
flags2_inited(0), sql_mode_inited(0), charset_inited(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; ulong data_len;
uint32 tmp; uint32 tmp;
uint8 common_header_len, post_header_len; 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*,...)"); DBUG_ENTER("Query_log_event::Query_log_event(char*,...)");
common_header_len= description_event->common_header_len; common_header_len= description_event->common_header_len;
...@@ -1191,7 +1211,7 @@ Query_log_event::Query_log_event(const char* buf, uint event_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); slave_proxy_id= thread_id = uint4korr(buf + Q_THREAD_ID_OFFSET);
exec_time = uint4korr(buf + Q_EXEC_TIME_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); error_code = uint2korr(buf + Q_ERR_CODE_OFFSET);
/* /*
...@@ -1217,7 +1237,7 @@ Query_log_event::Query_log_event(const char* buf, uint event_len, ...@@ -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 */ /* variable-part: the status vars; only in MySQL 5.0 */
start= (char*) (buf+post_header_len); 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;) for (const uchar* pos= (const uchar*) start; pos < (const uchar*) end;)
{ {
switch (*pos++) { switch (*pos++) {
...@@ -1240,8 +1260,7 @@ Query_log_event::Query_log_event(const char* buf, uint event_len, ...@@ -1240,8 +1260,7 @@ Query_log_event::Query_log_event(const char* buf, uint event_len,
break; break;
} }
case Q_CATALOG_CODE: case Q_CATALOG_CODE:
catalog_len= *pos; if ((catalog_len= *pos))
if (catalog_len)
catalog= (char*) pos+1; // Will be copied later catalog= (char*) pos+1; // Will be copied later
pos+= catalog_len+2; pos+= catalog_len+2;
break; break;
...@@ -1257,6 +1276,13 @@ Query_log_event::Query_log_event(const char* buf, uint event_len, ...@@ -1257,6 +1276,13 @@ Query_log_event::Query_log_event(const char* buf, uint event_len,
pos+= 6; pos+= 6;
break; break;
} }
case Q_TIME_ZONE_CODE:
{
if ((time_zone_len= *pos))
time_zone_str= (char *)(pos+1);
pos+= time_zone_len+1;
break;
}
default: default:
/* That's why you must write status vars in growing order of code */ /* 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\ 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, ...@@ -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 + 1 +
time_zone_len + 1 +
if (!(start= data_buf = (char*) my_malloc(catalog_len + data_len +2, MYF(MY_WME)))) data_len + 1, MYF(MY_WME))))
DBUG_VOID_RETURN; 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; catalog= start;
start+= catalog_len+1; 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 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; db= start;
query= start + db_len + 1; query= start + db_len + 1;
q_len= data_len - 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; DBUG_VOID_RETURN;
} }
...@@ -1390,6 +1421,8 @@ void Query_log_event::print_query_header(FILE* file, bool short_form, ...@@ -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; last_event_info->auto_increment_offset= auto_increment_offset;
} }
/* TODO: print the catalog when we feature SET CATALOG */
if (likely(charset_inited)) if (likely(charset_inited))
{ {
if (unlikely(!last_event_info->charset_inited)) /* first Query event */ 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, ...@@ -1410,6 +1443,14 @@ void Query_log_event::print_query_header(FILE* file, bool short_form,
memcpy(last_event_info->charset, charset, 6); 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 ...@@ -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. alloced block (see Query_log_event::exec_event()). Same for thd->db.
Thank you. Thank you.
*/ */
thd->catalog= (char*) catalog; thd->catalog= catalog_len ? (char *) catalog : (char *)"";
thd->db_length= db_len; thd->db_length= db_len;
thd->db= (char*) rewrite_db(db, &thd->db_length); thd->db= (char*) rewrite_db(db, &thd->db_length);
thd->variables.auto_increment_increment= auto_increment_increment; 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 ...@@ -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)))) get_charset(uint2korr(charset+4), MYF(MY_WME))))
{ {
/* /*
We updated the thd->variables with nonsensical values (0), and the We updated the thd->variables with nonsensical values (0). Let's
thread is not guaranteed to terminate now (as it may be configured set them to something safe (i.e. which avoids crash), and we'll
to ignore EE_UNKNOWN_CHARSET);if we're going to execute a next stop with EE_UNKNOWN_CHARSET in compare_errors (unless set to
statement we'll have a new charset info with it, so no problem to ignore this error).
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).
*/ */
rli->cached_charset_invalidate(); set_slave_thread_default_charset(thd, rli);
goto compare_errors; goto compare_errors;
} }
thd->update_charset(); // for the charset change to take effect 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()) */ /* Execute the query (note that we bypass dispatch_command()) */
mysql_parse(thd, thd->query, thd->query_length); mysql_parse(thd, thd->query, thd->query_length);
...@@ -1751,6 +1800,7 @@ Start_log_event_v3::Start_log_event_v3(const char* buf, ...@@ -1751,6 +1800,7 @@ Start_log_event_v3::Start_log_event_v3(const char* buf,
Start_log_event_v3::write() Start_log_event_v3::write()
*/ */
#ifndef MYSQL_CLIENT
bool Start_log_event_v3::write(IO_CACHE* file) bool Start_log_event_v3::write(IO_CACHE* file)
{ {
char buff[START_V3_HEADER_LEN]; char buff[START_V3_HEADER_LEN];
...@@ -1760,6 +1810,7 @@ bool Start_log_event_v3::write(IO_CACHE* file) ...@@ -1760,6 +1810,7 @@ bool Start_log_event_v3::write(IO_CACHE* file)
return (write_header(file, sizeof(buff)) || return (write_header(file, sizeof(buff)) ||
my_b_safe_write(file, (byte*) buff, sizeof(buff))); my_b_safe_write(file, (byte*) buff, sizeof(buff)));
} }
#endif
/* /*
...@@ -1975,7 +2026,7 @@ Format_description_log_event(const char* buf, ...@@ -1975,7 +2026,7 @@ Format_description_log_event(const char* buf,
DBUG_VOID_RETURN; DBUG_VOID_RETURN;
} }
#ifndef MYSQL_CLIENT
bool Format_description_log_event::write(IO_CACHE* file) bool Format_description_log_event::write(IO_CACHE* file)
{ {
/* /*
...@@ -1992,6 +2043,7 @@ 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)) || return (write_header(file, sizeof(buff)) ||
my_b_safe_write(file, buff, sizeof(buff))); my_b_safe_write(file, buff, sizeof(buff)));
} }
#endif
/* /*
SYNOPSIS SYNOPSIS
...@@ -2208,6 +2260,8 @@ void Load_log_event::pack_info(Protocol *protocol) ...@@ -2208,6 +2260,8 @@ void Load_log_event::pack_info(Protocol *protocol)
#endif /* defined(HAVE_REPLICATION) && !defined(MYSQL_CLIENT) */ #endif /* defined(HAVE_REPLICATION) && !defined(MYSQL_CLIENT) */
#ifndef MYSQL_CLIENT
/* /*
Load_log_event::write_data_header() Load_log_event::write_data_header()
*/ */
...@@ -2249,7 +2303,6 @@ bool Load_log_event::write_data_body(IO_CACHE* file) ...@@ -2249,7 +2303,6 @@ bool Load_log_event::write_data_body(IO_CACHE* file)
Load_log_event::Load_log_event() Load_log_event::Load_log_event()
*/ */
#ifndef MYSQL_CLIENT
Load_log_event::Load_log_event(THD *thd_arg, sql_exchange *ex, Load_log_event::Load_log_event(THD *thd_arg, sql_exchange *ex,
const char *db_arg, const char *table_name_arg, const char *db_arg, const char *table_name_arg,
List<Item> &fields_arg, List<Item> &fields_arg,
...@@ -2863,6 +2916,7 @@ Rotate_log_event::Rotate_log_event(const char* buf, uint event_len, ...@@ -2863,6 +2916,7 @@ Rotate_log_event::Rotate_log_event(const char* buf, uint event_len,
Rotate_log_event::write() Rotate_log_event::write()
*/ */
#ifndef MYSQL_CLIENT
bool Rotate_log_event::write(IO_CACHE* file) bool Rotate_log_event::write(IO_CACHE* file)
{ {
char buf[ROTATE_HEADER_LEN]; char buf[ROTATE_HEADER_LEN];
...@@ -2871,7 +2925,7 @@ bool Rotate_log_event::write(IO_CACHE* file) ...@@ -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*)buf, ROTATE_HEADER_LEN) ||
my_b_safe_write(file, (byte*)new_log_ident, (uint) ident_len)); my_b_safe_write(file, (byte*)new_log_ident, (uint) ident_len));
} }
#endif
/* /*
Rotate_log_event::exec_event() Rotate_log_event::exec_event()
...@@ -2929,17 +2983,10 @@ int Rotate_log_event::exec_event(struct st_relay_log_info* rli) ...@@ -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). master is 4.0 then the events are in the slave's format (conversion).
*/ */
set_slave_thread_options(thd); set_slave_thread_options(thd);
set_slave_thread_default_charset(thd, rli);
thd->variables.sql_mode= global_system_variables.sql_mode; thd->variables.sql_mode= global_system_variables.sql_mode;
thd->variables.auto_increment_increment= thd->variables.auto_increment_increment=
thd->variables.auto_increment_offset= 1; 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_mutex_unlock(&rli->data_lock);
pthread_cond_broadcast(&rli->data_cond); pthread_cond_broadcast(&rli->data_cond);
...@@ -3001,6 +3048,7 @@ const char* Intvar_log_event::get_var_type_name() ...@@ -3001,6 +3048,7 @@ const char* Intvar_log_event::get_var_type_name()
Intvar_log_event::write() Intvar_log_event::write()
*/ */
#ifndef MYSQL_CLIENT
bool Intvar_log_event::write(IO_CACHE* file) bool Intvar_log_event::write(IO_CACHE* file)
{ {
byte buf[9]; byte buf[9];
...@@ -3009,6 +3057,7 @@ bool Intvar_log_event::write(IO_CACHE* file) ...@@ -3009,6 +3057,7 @@ bool Intvar_log_event::write(IO_CACHE* file)
return (write_header(file, sizeof(buf)) || return (write_header(file, sizeof(buf)) ||
my_b_safe_write(file, buf, sizeof(buf))); my_b_safe_write(file, buf, sizeof(buf)));
} }
#endif
/* /*
...@@ -3093,6 +3142,7 @@ Rand_log_event::Rand_log_event(const char* buf, ...@@ -3093,6 +3142,7 @@ Rand_log_event::Rand_log_event(const char* buf,
} }
#ifndef MYSQL_CLIENT
bool Rand_log_event::write(IO_CACHE* file) bool Rand_log_event::write(IO_CACHE* file)
{ {
byte buf[16]; byte buf[16];
...@@ -3101,6 +3151,7 @@ bool Rand_log_event::write(IO_CACHE* file) ...@@ -3101,6 +3151,7 @@ bool Rand_log_event::write(IO_CACHE* file)
return (write_header(file, sizeof(buf)) || return (write_header(file, sizeof(buf)) ||
my_b_safe_write(file, buf, sizeof(buf))); my_b_safe_write(file, buf, sizeof(buf)));
} }
#endif
#ifdef MYSQL_CLIENT #ifdef MYSQL_CLIENT
...@@ -3164,11 +3215,13 @@ Xid_log_event(const char* buf, ...@@ -3164,11 +3215,13 @@ Xid_log_event(const char* buf,
} }
#ifndef MYSQL_CLIENT
bool Xid_log_event::write(IO_CACHE* file) bool Xid_log_event::write(IO_CACHE* file)
{ {
return write_header(file, sizeof(xid)) || return write_header(file, sizeof(xid)) ||
my_b_safe_write(file, (byte*) &xid, sizeof(xid)); my_b_safe_write(file, (byte*) &xid, sizeof(xid));
} }
#endif
#ifdef MYSQL_CLIENT #ifdef MYSQL_CLIENT
...@@ -3302,6 +3355,7 @@ User_var_log_event(const char* buf, ...@@ -3302,6 +3355,7 @@ User_var_log_event(const char* buf,
} }
#ifndef MYSQL_CLIENT
bool User_var_log_event::write(IO_CACHE* file) bool User_var_log_event::write(IO_CACHE* file)
{ {
char buf[UV_NAME_LEN_SIZE]; char buf[UV_NAME_LEN_SIZE];
...@@ -3361,6 +3415,7 @@ bool User_var_log_event::write(IO_CACHE* file) ...@@ -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*) buf1, buf1_length) ||
my_b_safe_write(file, (byte*) pos, val_len)); my_b_safe_write(file, (byte*) pos, val_len));
} }
#endif
/* /*
...@@ -3634,6 +3689,7 @@ int Slave_log_event::get_data_size() ...@@ -3634,6 +3689,7 @@ int Slave_log_event::get_data_size()
} }
#ifndef MYSQL_CLIENT
bool Slave_log_event::write(IO_CACHE* file) bool Slave_log_event::write(IO_CACHE* file)
{ {
ulong event_length= get_data_size(); ulong event_length= get_data_size();
...@@ -3644,6 +3700,7 @@ bool Slave_log_event::write(IO_CACHE* file) ...@@ -3644,6 +3700,7 @@ bool Slave_log_event::write(IO_CACHE* file)
return (write_header(file, event_length) || return (write_header(file, event_length) ||
my_b_safe_write(file, (byte*) mem_pool, event_length)); my_b_safe_write(file, (byte*) mem_pool, event_length));
} }
#endif
void Slave_log_event::init_from_mem_pool(int data_size) 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, ...@@ -3770,7 +3827,6 @@ Create_file_log_event(THD* thd_arg, sql_exchange* ex,
sql_ex.force_new_format(); sql_ex.force_new_format();
DBUG_VOID_RETURN; DBUG_VOID_RETURN;
} }
#endif /* !MYSQL_CLIENT */
/* /*
...@@ -3815,6 +3871,7 @@ bool Create_file_log_event::write_base(IO_CACHE* file) ...@@ -3815,6 +3871,7 @@ bool Create_file_log_event::write_base(IO_CACHE* file)
return res; return res;
} }
#endif /* !MYSQL_CLIENT */
/* /*
Create_file_log_event ctor Create_file_log_event ctor
...@@ -4042,6 +4099,7 @@ Append_block_log_event::Append_block_log_event(const char* buf, uint len, ...@@ -4042,6 +4099,7 @@ Append_block_log_event::Append_block_log_event(const char* buf, uint len,
Append_block_log_event::write() Append_block_log_event::write()
*/ */
#ifndef MYSQL_CLIENT
bool Append_block_log_event::write(IO_CACHE* file) bool Append_block_log_event::write(IO_CACHE* file)
{ {
byte buf[APPEND_BLOCK_HEADER_LEN]; byte buf[APPEND_BLOCK_HEADER_LEN];
...@@ -4050,6 +4108,7 @@ bool Append_block_log_event::write(IO_CACHE* file) ...@@ -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, buf, APPEND_BLOCK_HEADER_LEN) ||
my_b_safe_write(file, (byte*) block, block_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, ...@@ -4171,6 +4230,7 @@ Delete_file_log_event::Delete_file_log_event(const char* buf, uint len,
Delete_file_log_event::write() Delete_file_log_event::write()
*/ */
#ifndef MYSQL_CLIENT
bool Delete_file_log_event::write(IO_CACHE* file) bool Delete_file_log_event::write(IO_CACHE* file)
{ {
byte buf[DELETE_FILE_HEADER_LEN]; byte buf[DELETE_FILE_HEADER_LEN];
...@@ -4178,6 +4238,7 @@ bool Delete_file_log_event::write(IO_CACHE* file) ...@@ -4178,6 +4238,7 @@ bool Delete_file_log_event::write(IO_CACHE* file)
return (write_header(file, sizeof(buf)) || return (write_header(file, sizeof(buf)) ||
my_b_safe_write(file, buf, 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, ...@@ -4265,6 +4326,7 @@ Execute_load_log_event::Execute_load_log_event(const char* buf, uint len,
Execute_load_log_event::write() Execute_load_log_event::write()
*/ */
#ifndef MYSQL_CLIENT
bool Execute_load_log_event::write(IO_CACHE* file) bool Execute_load_log_event::write(IO_CACHE* file)
{ {
byte buf[EXEC_LOAD_HEADER_LEN]; byte buf[EXEC_LOAD_HEADER_LEN];
...@@ -4272,6 +4334,7 @@ bool Execute_load_log_event::write(IO_CACHE* file) ...@@ -4272,6 +4334,7 @@ bool Execute_load_log_event::write(IO_CACHE* file)
return (write_header(file, sizeof(buf)) || return (write_header(file, sizeof(buf)) ||
my_b_safe_write(file, buf, 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() ...@@ -4475,6 +4538,7 @@ ulong Execute_load_query_log_event::get_post_header_size_for_derived()
} }
#ifndef MYSQL_CLIENT
bool bool
Execute_load_query_log_event::write_post_header_for_derived(IO_CACHE* file) 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) ...@@ -4485,6 +4549,7 @@ Execute_load_query_log_event::write_post_header_for_derived(IO_CACHE* file)
*(buf + 4 + 4 + 4)= (char)dup_handling; *(buf + 4 + 4 + 4)= (char)dup_handling;
return my_b_safe_write(file, (byte*) buf, EXECUTE_LOAD_QUERY_EXTRA_HEADER_LEN); return my_b_safe_write(file, (byte*) buf, EXECUTE_LOAD_QUERY_EXTRA_HEADER_LEN);
} }
#endif
#ifdef MYSQL_CLIENT #ifdef MYSQL_CLIENT
......
...@@ -237,6 +237,7 @@ struct sql_ex_info ...@@ -237,6 +237,7 @@ struct sql_ex_info
#define Q_CATALOG_CODE 2 #define Q_CATALOG_CODE 2
#define Q_AUTO_INCREMENT 3 #define Q_AUTO_INCREMENT 3
#define Q_CHARSET_CODE 4 #define Q_CHARSET_CODE 4
#define Q_TIME_ZONE_CODE 5
/* Intvar event post-header */ /* Intvar event post-header */
...@@ -448,6 +449,7 @@ typedef struct st_last_event_info ...@@ -448,6 +449,7 @@ typedef struct st_last_event_info
ulong auto_increment_increment, auto_increment_offset; ulong auto_increment_increment, auto_increment_offset;
bool charset_inited; bool charset_inited;
char charset[6]; // 3 variables, each of them storable in 2 bytes 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() st_last_event_info()
:flags2_inited(0), sql_mode_inited(0), :flags2_inited(0), sql_mode_inited(0),
auto_increment_increment(1),auto_increment_offset(1), charset_inited(0) auto_increment_increment(1),auto_increment_offset(1), charset_inited(0)
...@@ -459,6 +461,7 @@ typedef struct st_last_event_info ...@@ -459,6 +461,7 @@ typedef struct st_last_event_info
*/ */
bzero(db, sizeof(db)); bzero(db, sizeof(db));
bzero(charset, sizeof(charset)); bzero(charset, sizeof(charset));
bzero(time_zone_str, sizeof(time_zone_str));
} }
} LAST_EVENT_INFO; } LAST_EVENT_INFO;
#endif #endif
...@@ -583,6 +586,7 @@ class Log_event ...@@ -583,6 +586,7 @@ class Log_event
my_free((gptr) ptr, MYF(MY_WME|MY_ALLOW_ZERO_PTR)); my_free((gptr) ptr, MYF(MY_WME|MY_ALLOW_ZERO_PTR));
} }
#ifndef MYSQL_CLIENT
bool write_header(IO_CACHE* file, ulong data_length); bool write_header(IO_CACHE* file, ulong data_length);
virtual bool write(IO_CACHE* file) virtual bool write(IO_CACHE* file)
{ {
...@@ -590,13 +594,14 @@ class Log_event ...@@ -590,13 +594,14 @@ class Log_event
write_data_header(file) || write_data_header(file) ||
write_data_body(file)); write_data_body(file));
} }
virtual bool is_artificial_event() { return 0; }
virtual bool write_data_header(IO_CACHE* file) virtual bool write_data_header(IO_CACHE* file)
{ return 0; } { return 0; }
virtual bool write_data_body(IO_CACHE* file __attribute__((unused))) virtual bool write_data_body(IO_CACHE* file __attribute__((unused)))
{ return 0; } { return 0; }
#endif
virtual Log_event_type get_type_code() = 0; virtual Log_event_type get_type_code() = 0;
virtual bool is_valid() const = 0; virtual bool is_valid() const = 0;
virtual bool is_artificial_event() { return 0; }
inline bool get_cache_stmt() { return cache_stmt; } inline bool get_cache_stmt() { return cache_stmt; }
Log_event(const char* buf, const Format_description_log_event* description_event); Log_event(const char* buf, const Format_description_log_event* description_event);
virtual ~Log_event() { free_temp_buf();} virtual ~Log_event() { free_temp_buf();}
...@@ -672,7 +677,7 @@ class Query_log_event: public Log_event ...@@ -672,7 +677,7 @@ class Query_log_event: public Log_event
concerned) from here. 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: We want to be able to store a variable number of N-bit status vars:
...@@ -714,6 +719,8 @@ class Query_log_event: public Log_event ...@@ -714,6 +719,8 @@ class Query_log_event: public Log_event
ulong sql_mode; ulong sql_mode;
ulong auto_increment_increment, auto_increment_offset; ulong auto_increment_increment, auto_increment_offset;
char charset[6]; char charset[6];
uint time_zone_len; /* 0 means uninited */
const char *time_zone_str;
#ifndef MYSQL_CLIENT #ifndef MYSQL_CLIENT
...@@ -737,12 +744,13 @@ class Query_log_event: public Log_event ...@@ -737,12 +744,13 @@ class Query_log_event: public Log_event
~Query_log_event() ~Query_log_event()
{ {
if (data_buf) if (data_buf)
{
my_free((gptr) data_buf, MYF(0)); my_free((gptr) data_buf, MYF(0));
} }
}
Log_event_type get_type_code() { return QUERY_EVENT; } Log_event_type get_type_code() { return QUERY_EVENT; }
#ifndef MYSQL_CLIENT
bool write(IO_CACHE* file); 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; } bool is_valid() const { return query != 0; }
/* /*
...@@ -751,7 +759,6 @@ class Query_log_event: public Log_event ...@@ -751,7 +759,6 @@ class Query_log_event: public Log_event
*/ */
virtual ulong get_post_header_size_for_derived() { return 0; } virtual ulong get_post_header_size_for_derived() { return 0; }
/* Writes derived event-specific part of post header. */ /* Writes derived event-specific part of post header. */
virtual bool write_post_header_for_derived(IO_CACHE* file) { return FALSE; }
}; };
#ifdef HAVE_REPLICATION #ifdef HAVE_REPLICATION
...@@ -790,7 +797,9 @@ class Slave_log_event: public Log_event ...@@ -790,7 +797,9 @@ class Slave_log_event: public Log_event
int get_data_size(); int get_data_size();
bool is_valid() const { return master_host != 0; } bool is_valid() const { return master_host != 0; }
Log_event_type get_type_code() { return SLAVE_EVENT; } Log_event_type get_type_code() { return SLAVE_EVENT; }
#ifndef MYSQL_CLIENT
bool write(IO_CACHE* file); bool write(IO_CACHE* file);
#endif
}; };
#endif /* HAVE_REPLICATION */ #endif /* HAVE_REPLICATION */
...@@ -885,8 +894,10 @@ class Load_log_event: public Log_event ...@@ -885,8 +894,10 @@ class Load_log_event: public Log_event
{ {
return sql_ex.new_format() ? NEW_LOAD_EVENT: LOAD_EVENT; return sql_ex.new_format() ? NEW_LOAD_EVENT: LOAD_EVENT;
} }
#ifndef MYSQL_CLIENT
bool write_data_header(IO_CACHE* file); bool write_data_header(IO_CACHE* file);
bool write_data_body(IO_CACHE* file); bool write_data_body(IO_CACHE* file);
#endif
bool is_valid() const { return table_name != 0; } bool is_valid() const { return table_name != 0; }
int get_data_size() int get_data_size()
{ {
...@@ -962,7 +973,9 @@ class Start_log_event_v3: public Log_event ...@@ -962,7 +973,9 @@ class Start_log_event_v3: public Log_event
const Format_description_log_event* description_event); const Format_description_log_event* description_event);
~Start_log_event_v3() {} ~Start_log_event_v3() {}
Log_event_type get_type_code() { return START_EVENT_V3;} Log_event_type get_type_code() { return START_EVENT_V3;}
#ifndef MYSQL_CLIENT
bool write(IO_CACHE* file); bool write(IO_CACHE* file);
#endif
bool is_valid() const { return 1; } bool is_valid() const { return 1; }
int get_data_size() int get_data_size()
{ {
...@@ -1004,7 +1017,9 @@ class Format_description_log_event: public Start_log_event_v3 ...@@ -1004,7 +1017,9 @@ class Format_description_log_event: public Start_log_event_v3
const Format_description_log_event* description_event); const Format_description_log_event* description_event);
~Format_description_log_event() { my_free((gptr)post_header_len, MYF(0)); } ~Format_description_log_event() { my_free((gptr)post_header_len, MYF(0)); }
Log_event_type get_type_code() { return FORMAT_DESCRIPTION_EVENT;} Log_event_type get_type_code() { return FORMAT_DESCRIPTION_EVENT;}
#ifndef MYSQL_CLIENT
bool write(IO_CACHE* file); bool write(IO_CACHE* file);
#endif
bool is_valid() const bool is_valid() const
{ {
return ((common_header_len >= ((binlog_version==1) ? OLD_HEADER_LEN : return ((common_header_len >= ((binlog_version==1) ? OLD_HEADER_LEN :
...@@ -1054,7 +1069,9 @@ class Intvar_log_event: public Log_event ...@@ -1054,7 +1069,9 @@ class Intvar_log_event: public Log_event
Log_event_type get_type_code() { return INTVAR_EVENT;} Log_event_type get_type_code() { return INTVAR_EVENT;}
const char* get_var_type_name(); const char* get_var_type_name();
int get_data_size() { return 9; /* sizeof(type) + sizeof(val) */;} int get_data_size() { return 9; /* sizeof(type) + sizeof(val) */;}
#ifndef MYSQL_CLIENT
bool write(IO_CACHE* file); bool write(IO_CACHE* file);
#endif
bool is_valid() const { return 1; } bool is_valid() const { return 1; }
}; };
...@@ -1092,7 +1109,9 @@ class Rand_log_event: public Log_event ...@@ -1092,7 +1109,9 @@ class Rand_log_event: public Log_event
~Rand_log_event() {} ~Rand_log_event() {}
Log_event_type get_type_code() { return RAND_EVENT;} Log_event_type get_type_code() { return RAND_EVENT;}
int get_data_size() { return 16; /* sizeof(ulonglong) * 2*/ } int get_data_size() { return 16; /* sizeof(ulonglong) * 2*/ }
#ifndef MYSQL_CLIENT
bool write(IO_CACHE* file); bool write(IO_CACHE* file);
#endif
bool is_valid() const { return 1; } bool is_valid() const { return 1; }
}; };
...@@ -1127,7 +1146,9 @@ class Xid_log_event: public Log_event ...@@ -1127,7 +1146,9 @@ class Xid_log_event: public Log_event
~Xid_log_event() {} ~Xid_log_event() {}
Log_event_type get_type_code() { return XID_EVENT;} Log_event_type get_type_code() { return XID_EVENT;}
int get_data_size() { return sizeof(xid); } int get_data_size() { return sizeof(xid); }
#ifndef MYSQL_CLIENT
bool write(IO_CACHE* file); bool write(IO_CACHE* file);
#endif
bool is_valid() const { return 1; } bool is_valid() const { return 1; }
}; };
...@@ -1169,7 +1190,9 @@ class User_var_log_event: public Log_event ...@@ -1169,7 +1190,9 @@ class User_var_log_event: public Log_event
User_var_log_event(const char* buf, const Format_description_log_event* description_event); User_var_log_event(const char* buf, const Format_description_log_event* description_event);
~User_var_log_event() {} ~User_var_log_event() {}
Log_event_type get_type_code() { return USER_VAR_EVENT;} Log_event_type get_type_code() { return USER_VAR_EVENT;}
#ifndef MYSQL_CLIENT
bool write(IO_CACHE* file); bool write(IO_CACHE* file);
#endif
bool is_valid() const { return 1; } bool is_valid() const { return 1; }
}; };
...@@ -1239,7 +1262,9 @@ class Rotate_log_event: public Log_event ...@@ -1239,7 +1262,9 @@ class Rotate_log_event: public Log_event
Log_event_type get_type_code() { return ROTATE_EVENT;} Log_event_type get_type_code() { return ROTATE_EVENT;}
int get_data_size() { return ident_len + ROTATE_HEADER_LEN;} int get_data_size() { return ident_len + ROTATE_HEADER_LEN;}
bool is_valid() const { return new_log_ident != 0; } bool is_valid() const { return new_log_ident != 0; }
#ifndef MYSQL_CLIENT
bool write(IO_CACHE* file); bool write(IO_CACHE* file);
#endif
}; };
...@@ -1299,6 +1324,7 @@ class Create_file_log_event: public Load_log_event ...@@ -1299,6 +1324,7 @@ class Create_file_log_event: public Load_log_event
4 + 1 + block_len); 4 + 1 + block_len);
} }
bool is_valid() const { return inited_from_old || block != 0; } bool is_valid() const { return inited_from_old || block != 0; }
#ifndef MYSQL_CLIENT
bool write_data_header(IO_CACHE* file); bool write_data_header(IO_CACHE* file);
bool write_data_body(IO_CACHE* file); bool write_data_body(IO_CACHE* file);
/* /*
...@@ -1306,6 +1332,7 @@ class Create_file_log_event: public Load_log_event ...@@ -1306,6 +1332,7 @@ class Create_file_log_event: public Load_log_event
write it as Load event - used on the slave write it as Load event - used on the slave
*/ */
bool write_base(IO_CACHE* file); bool write_base(IO_CACHE* file);
#endif
}; };
...@@ -1352,7 +1379,9 @@ class Append_block_log_event: public Log_event ...@@ -1352,7 +1379,9 @@ class Append_block_log_event: public Log_event
Log_event_type get_type_code() { return APPEND_BLOCK_EVENT;} Log_event_type get_type_code() { return APPEND_BLOCK_EVENT;}
int get_data_size() { return block_len + APPEND_BLOCK_HEADER_LEN ;} int get_data_size() { return block_len + APPEND_BLOCK_HEADER_LEN ;}
bool is_valid() const { return block != 0; } bool is_valid() const { return block != 0; }
#ifndef MYSQL_CLIENT
bool write(IO_CACHE* file); bool write(IO_CACHE* file);
#endif
const char* get_db() { return db; } const char* get_db() { return db; }
}; };
...@@ -1386,7 +1415,9 @@ class Delete_file_log_event: public Log_event ...@@ -1386,7 +1415,9 @@ class Delete_file_log_event: public Log_event
Log_event_type get_type_code() { return DELETE_FILE_EVENT;} Log_event_type get_type_code() { return DELETE_FILE_EVENT;}
int get_data_size() { return DELETE_FILE_HEADER_LEN ;} int get_data_size() { return DELETE_FILE_HEADER_LEN ;}
bool is_valid() const { return file_id != 0; } bool is_valid() const { return file_id != 0; }
#ifndef MYSQL_CLIENT
bool write(IO_CACHE* file); bool write(IO_CACHE* file);
#endif
const char* get_db() { return db; } const char* get_db() { return db; }
}; };
...@@ -1419,7 +1450,9 @@ class Execute_load_log_event: public Log_event ...@@ -1419,7 +1450,9 @@ class Execute_load_log_event: public Log_event
Log_event_type get_type_code() { return EXEC_LOAD_EVENT;} Log_event_type get_type_code() { return EXEC_LOAD_EVENT;}
int get_data_size() { return EXEC_LOAD_HEADER_LEN ;} int get_data_size() { return EXEC_LOAD_HEADER_LEN ;}
bool is_valid() const { return file_id != 0; } bool is_valid() const { return file_id != 0; }
#ifndef MYSQL_CLIENT
bool write(IO_CACHE* file); bool write(IO_CACHE* file);
#endif
const char* get_db() { return db; } const char* get_db() { return db; }
}; };
...@@ -1507,7 +1540,9 @@ class Execute_load_query_log_event: public Query_log_event ...@@ -1507,7 +1540,9 @@ class Execute_load_query_log_event: public Query_log_event
bool is_valid() const { return Query_log_event::is_valid() && file_id != 0; } bool is_valid() const { return Query_log_event::is_valid() && file_id != 0; }
ulong get_post_header_size_for_derived(); ulong get_post_header_size_for_derived();
#ifndef MYSQL_CLIENT
bool write_post_header_for_derived(IO_CACHE* file); bool write_post_header_for_derived(IO_CACHE* file);
#endif
}; };
......
...@@ -257,6 +257,12 @@ extern CHARSET_INFO *national_charset_info, *table_alias_charset; ...@@ -257,6 +257,12 @@ extern CHARSET_INFO *national_charset_info, *table_alias_charset;
/* Flag set if setup_tables already done */ /* Flag set if setup_tables already done */
#define OPTION_SETUP_TABLES_DONE (1L << 30) #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 */ /* The rest of the file is included in the server only */
#ifndef MYSQL_CLIENT #ifndef MYSQL_CLIENT
......
...@@ -2095,27 +2095,6 @@ void sys_var_character_set_server::set_default(THD *thd, enum_var_type type) ...@@ -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, CHARSET_INFO ** sys_var_character_set_database::ci_ptr(THD *thd,
enum_var_type type) enum_var_type type)
{ {
...@@ -2208,20 +2187,6 @@ void sys_var_collation_database::set_default(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) 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) ...@@ -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 str(buff, sizeof(buff), &my_charset_latin1);
String *res= var->value->val_str(&str); 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= if (!(var->save_result.time_zone=
my_tz_find(res, thd->lex->time_zone_tables_used))) 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, ...@@ -2605,7 +2560,18 @@ byte *sys_var_thd_time_zone::value_ptr(THD *thd, enum_var_type type,
if (type == OPT_GLOBAL) if (type == OPT_GLOBAL)
return (byte *)(global_system_variables.time_zone->get_name()->ptr()); return (byte *)(global_system_variables.time_zone->get_name()->ptr());
else 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()); return (byte *)(thd->variables.time_zone->get_name()->ptr());
}
} }
......
...@@ -565,9 +565,6 @@ class sys_var_character_set_server :public sys_var_character_set ...@@ -565,9 +565,6 @@ class sys_var_character_set_server :public sys_var_character_set
public: public:
sys_var_character_set_server(const char *name_arg) : sys_var_character_set_server(const char *name_arg) :
sys_var_character_set(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); void set_default(THD *thd, enum_var_type type);
CHARSET_INFO **ci_ptr(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 ...@@ -603,9 +600,6 @@ class sys_var_collation_server :public sys_var_collation
{ {
public: public:
sys_var_collation_server(const char *name_arg) :sys_var_collation(name_arg) {} 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); bool update(THD *thd, set_var *var);
void set_default(THD *thd, enum_var_type type); void set_default(THD *thd, enum_var_type type);
byte *value_ptr(THD *thd, enum_var_type type, LEX_STRING *base); byte *value_ptr(THD *thd, enum_var_type type, LEX_STRING *base);
......
...@@ -1421,7 +1421,7 @@ not always make sense; please check the manual before using it)."; ...@@ -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 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. 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 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. charset info in each binlog event.
We don't do it for 3.23 because masters <3.23.50 hang on 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 SELECT @@unknown_var (BUG#7965 - see changelog of 3.23.50). So finally we
...@@ -1456,11 +1456,10 @@ be equal for replication to work"; ...@@ -1456,11 +1456,10 @@ be equal for replication to work";
such check will broke everything for them. (And now everything will such check will broke everything for them. (And now everything will
work for them because by default both their master and slave will have work for them because by default both their master and slave will have
'SYSTEM' time zone). 'SYSTEM' time zone).
This check is only necessary for 4.x masters (and < 5.0.4 masters but
TODO: when the new replication of timezones is sorted out with Dmitri, those were alpha).
change >= '4' to == '4'.
*/ */
if ((*mysql->server_version >= '4') && if ((*mysql->server_version == '4') &&
!mysql_real_query(mysql, "SELECT @@GLOBAL.TIME_ZONE", 25) && !mysql_real_query(mysql, "SELECT @@GLOBAL.TIME_ZONE", 25) &&
(master_res= mysql_store_result(mysql))) (master_res= mysql_store_result(mysql)))
{ {
...@@ -2770,6 +2769,18 @@ void set_slave_thread_options(THD* thd) ...@@ -2770,6 +2769,18 @@ void set_slave_thread_options(THD* thd)
thd->variables.completion_type= 0; 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() init_slave_thread()
*/ */
......
...@@ -562,6 +562,7 @@ int init_relay_log_pos(RELAY_LOG_INFO* rli,const char* log,ulonglong pos, ...@@ -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, int purge_relay_logs(RELAY_LOG_INFO* rli, THD *thd, bool just_reset,
const char** errmsg); const char** errmsg);
void set_slave_thread_options(THD* thd); 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); void rotate_relay_log(MASTER_INFO* mi);
extern "C" pthread_handler_decl(handle_slave_io,arg); extern "C" pthread_handler_decl(handle_slave_io,arg);
......
...@@ -2178,7 +2178,7 @@ my_tz_find(const String * name, TABLE_LIST *tz_tables) ...@@ -2178,7 +2178,7 @@ my_tz_find(const String * name, TABLE_LIST *tz_tables)
DBUG_PRINT("enter", ("time zone name='%s'", DBUG_PRINT("enter", ("time zone name='%s'",
name ? ((String *)name)->c_ptr() : "NULL")); 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) if (!name)
DBUG_RETURN(0); DBUG_RETURN(0);
...@@ -2210,7 +2210,7 @@ my_tz_find(const String * name, TABLE_LIST *tz_tables) ...@@ -2210,7 +2210,7 @@ my_tz_find(const String * name, TABLE_LIST *tz_tables)
(const byte *)name->ptr(), (const byte *)name->ptr(),
name->length()))) name->length())))
result_tz= tmp_tzname->tz; 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); result_tz= tz_load_from_open_tables(name, tz_tables);
} }
...@@ -2219,6 +2219,58 @@ my_tz_find(const String * name, TABLE_LIST *tz_tables) ...@@ -2219,6 +2219,58 @@ my_tz_find(const String * name, TABLE_LIST *tz_tables)
DBUG_RETURN(result_tz); 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) */ #endif /* !defined(TESTTIME) && !defined(TZINFO2SQL) */
......
...@@ -61,6 +61,7 @@ extern Time_zone * my_tz_UTC; ...@@ -61,6 +61,7 @@ extern Time_zone * my_tz_UTC;
extern Time_zone * my_tz_SYSTEM; extern Time_zone * my_tz_SYSTEM;
extern TABLE_LIST * my_tz_get_table_list(THD *thd, TABLE_LIST ***global_next_ptr); 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(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 my_bool my_tz_init(THD *org_thd, const char *default_tzname, my_bool bootstrap);
extern void my_tz_free(); extern void my_tz_free();
...@@ -96,10 +97,4 @@ inline bool my_tz_check_n_skip_implicit_tables(TABLE_LIST **table, ...@@ -96,10 +97,4 @@ inline bool my_tz_check_n_skip_implicit_tables(TABLE_LIST **table,
return FALSE; 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) */ #endif /* !defined(TESTTIME) && !defined(TZINFO2SQL) */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment