Commit 61eb9e40 authored by unknown's avatar unknown

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
parent a3b092e5
......@@ -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
......
......@@ -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)
......
......@@ -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;
--default-time-zone=Europe/Moscow
--default-time-zone=Japan
......@@ -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;
......@@ -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) {
......
......@@ -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,
......
......@@ -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
......
......@@ -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 @@ class Log_event
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 @@ class Log_event
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 @@ class Query_log_event: public Log_event
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 @@ class Query_log_event: public Log_event
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 @@ class Query_log_event: public Log_event
~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 @@ class Query_log_event: public Log_event
*/
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 @@ class Slave_log_event: public Log_event
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 @@ class Load_log_event: public Log_event
{
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 @@ class Start_log_event_v3: public Log_event
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 @@ class Format_description_log_event: public Start_log_event_v3
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 @@ class Intvar_log_event: public Log_event
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 @@ 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() {}
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 @@ class Rotate_log_event: public Log_event
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 @@ class Create_file_log_event: public Load_log_event
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 @@ class Create_file_log_event: public Load_log_event
write it as Load event - used on the slave
*/
bool write_base(IO_CACHE* file);
#endif
};
......@@ -1352,7 +1379,9 @@ class Append_block_log_event: public Log_event
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 @@ class Delete_file_log_event: public Log_event
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 @@ class Execute_load_log_event: public Log_event
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 @@ class Execute_load_query_log_event: public Query_log_event
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
};
......
......@@ -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
......
......@@ -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());
}
}
......
......@@ -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);
......
......@@ -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()
*/
......
......@@ -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);
......
......@@ -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) */
......
......@@ -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) */
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