Bug #29536: timestamp inconsistent in replication around 1970

MySQL replicates the time zone only when operations that involve
it are performed. This is controlled by a flag. But this flag
is set only on successful operation.
The flag must be set also when there is an error that involves
a timezone (so the master would replicate the error to the slaves). 

Fixed by moving the setting of the flag before the operation
(so it apples to errors as well).
parent 2bfbe2cd
...@@ -130,3 +130,21 @@ t ...@@ -130,3 +130,21 @@ t
2005-01-01 08:00:00 2005-01-01 08:00:00
drop table t1, t2; drop table t1, t2;
set global time_zone= @my_time_zone; set global time_zone= @my_time_zone;
End of 4.1 tests
CREATE TABLE t1 (a INT, b TIMESTAMP);
INSERT INTO t1 VALUES (1, NOW());
SET @@session.time_zone='Japan';
UPDATE t1 SET b= '1970-01-01 08:59:59' WHERE a= 1;
Warnings:
Warning 1264 Out of range value adjusted for column 'b' at row 1
SELECT * FROM t1 ORDER BY a;
a b
1 0000-00-00 00:00:00
SET @@session.time_zone='Japan';
SELECT * FROM t1 ORDER BY a;
a b
1 0000-00-00 00:00:00
SET @@session.time_zone = default;
DROP TABLE t1;
SET @@session.time_zone = default;
End of 5.0 tests
...@@ -126,8 +126,33 @@ connection master; ...@@ -126,8 +126,33 @@ connection master;
drop table t1, t2; drop table t1, t2;
sync_slave_with_master; sync_slave_with_master;
# End of 4.1 tests
# Restore original timezone # Restore original timezone
connection master; connection master;
set global time_zone= @my_time_zone; set global time_zone= @my_time_zone;
--echo End of 4.1 tests
#
# Bug #29536: timestamp inconsistent in replication around 1970
#
connection master;
CREATE TABLE t1 (a INT, b TIMESTAMP);
INSERT INTO t1 VALUES (1, NOW());
SET @@session.time_zone='Japan';
UPDATE t1 SET b= '1970-01-01 08:59:59' WHERE a= 1;
SELECT * FROM t1 ORDER BY a;
sync_slave_with_master;
SET @@session.time_zone='Japan';
# must procdure the same result as the SELECT on the master
SELECT * FROM t1 ORDER BY a;
SET @@session.time_zone = default;
connection master;
DROP TABLE t1;
SET @@session.time_zone = default;
--echo End of 5.0 tests
...@@ -4462,6 +4462,7 @@ longlong Field_timestamp::val_int(void) ...@@ -4462,6 +4462,7 @@ longlong Field_timestamp::val_int(void)
MYSQL_TIME time_tmp; MYSQL_TIME time_tmp;
THD *thd= table ? table->in_use : current_thd; THD *thd= table ? table->in_use : current_thd;
thd->time_zone_used= 1;
#ifdef WORDS_BIGENDIAN #ifdef WORDS_BIGENDIAN
if (table && table->s->db_low_byte_first) if (table && table->s->db_low_byte_first)
temp=uint4korr(ptr); temp=uint4korr(ptr);
...@@ -4473,7 +4474,6 @@ longlong Field_timestamp::val_int(void) ...@@ -4473,7 +4474,6 @@ longlong Field_timestamp::val_int(void)
return(0); /* purecov: inspected */ return(0); /* purecov: inspected */
thd->variables.time_zone->gmt_sec_to_TIME(&time_tmp, (my_time_t)temp); thd->variables.time_zone->gmt_sec_to_TIME(&time_tmp, (my_time_t)temp);
thd->time_zone_used= 1;
return time_tmp.year * LL(10000000000) + time_tmp.month * LL(100000000) + return time_tmp.year * LL(10000000000) + time_tmp.month * LL(100000000) +
time_tmp.day * 1000000L + time_tmp.hour * 10000L + time_tmp.day * 1000000L + time_tmp.hour * 10000L +
...@@ -4492,6 +4492,7 @@ String *Field_timestamp::val_str(String *val_buffer, String *val_ptr) ...@@ -4492,6 +4492,7 @@ String *Field_timestamp::val_str(String *val_buffer, String *val_ptr)
to= (char*) val_buffer->ptr(); to= (char*) val_buffer->ptr();
val_buffer->length(field_length); val_buffer->length(field_length);
thd->time_zone_used= 1;
#ifdef WORDS_BIGENDIAN #ifdef WORDS_BIGENDIAN
if (table && table->s->db_low_byte_first) if (table && table->s->db_low_byte_first)
temp=uint4korr(ptr); temp=uint4korr(ptr);
...@@ -4507,7 +4508,6 @@ String *Field_timestamp::val_str(String *val_buffer, String *val_ptr) ...@@ -4507,7 +4508,6 @@ String *Field_timestamp::val_str(String *val_buffer, String *val_ptr)
val_buffer->set_charset(&my_charset_bin); // Safety val_buffer->set_charset(&my_charset_bin); // Safety
thd->variables.time_zone->gmt_sec_to_TIME(&time_tmp,(my_time_t)temp); thd->variables.time_zone->gmt_sec_to_TIME(&time_tmp,(my_time_t)temp);
thd->time_zone_used= 1;
temp= time_tmp.year % 100; temp= time_tmp.year % 100;
if (temp < YY_PART_YEAR - 1) if (temp < YY_PART_YEAR - 1)
...@@ -4557,6 +4557,7 @@ bool Field_timestamp::get_date(MYSQL_TIME *ltime, uint fuzzydate) ...@@ -4557,6 +4557,7 @@ bool Field_timestamp::get_date(MYSQL_TIME *ltime, uint fuzzydate)
{ {
long temp; long temp;
THD *thd= table ? table->in_use : current_thd; THD *thd= table ? table->in_use : current_thd;
thd->time_zone_used= 1;
#ifdef WORDS_BIGENDIAN #ifdef WORDS_BIGENDIAN
if (table && table->s->db_low_byte_first) if (table && table->s->db_low_byte_first)
temp=uint4korr(ptr); temp=uint4korr(ptr);
...@@ -4572,7 +4573,6 @@ bool Field_timestamp::get_date(MYSQL_TIME *ltime, uint fuzzydate) ...@@ -4572,7 +4573,6 @@ bool Field_timestamp::get_date(MYSQL_TIME *ltime, uint fuzzydate)
else else
{ {
thd->variables.time_zone->gmt_sec_to_TIME(ltime, (my_time_t)temp); thd->variables.time_zone->gmt_sec_to_TIME(ltime, (my_time_t)temp);
thd->time_zone_used= 1;
} }
return 0; return 0;
} }
......
...@@ -228,11 +228,11 @@ my_time_t TIME_to_timestamp(THD *thd, const MYSQL_TIME *t, my_bool *in_dst_time_ ...@@ -228,11 +228,11 @@ my_time_t TIME_to_timestamp(THD *thd, const MYSQL_TIME *t, my_bool *in_dst_time_
my_time_t timestamp; my_time_t timestamp;
*in_dst_time_gap= 0; *in_dst_time_gap= 0;
thd->time_zone_used= 1;
timestamp= thd->variables.time_zone->TIME_to_gmt_sec(t, in_dst_time_gap); timestamp= thd->variables.time_zone->TIME_to_gmt_sec(t, in_dst_time_gap);
if (timestamp) if (timestamp)
{ {
thd->time_zone_used= 1;
return timestamp; return timestamp;
} }
......
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