Commit dfd6702a authored by Sergei Golubchik's avatar Sergei Golubchik

MDEV-16157 federated corrupts timestamps

do "set time_zone='+00:00'" on remote server
after connecting.

temporarily reset local time zone to my_tz_OFFSET0
whenever Field::val_str() or Field::store()
methods are used.
parent 28dbdf3d
connect master,127.0.0.1,root,,test,$MASTER_MYPORT,;
connect slave,127.0.0.1,root,,test,$SLAVE_MYPORT,;
connection master;
CREATE DATABASE federated;
connection slave;
CREATE DATABASE federated;
connection slave;
set global time_zone='Europe/Moscow';
set time_zone='Europe/Moscow';
create table federated.t1 (dt datetime, ts timestamp, unique(ts));
connection master;
set time_zone='+01:00';
create table t1 engine=federated connection='mysql://root@127.0.0.1:SLAVE_PORT/federated/t1';
set @@timestamp=1;
insert t1 values (now(), now());
set @@timestamp=2147483647;
insert t1 values (now(), now());
set @@timestamp=1067121000;
insert t1 values (now(), now());
set @@timestamp=1067124600;
insert t1 values (now(), now());
set @@timestamp=0;
select * from t1;
dt ts
1970-01-01 01:00:01 1970-01-01 01:00:01
2038-01-19 04:14:07 2038-01-19 04:14:07
2003-10-25 23:30:00 2003-10-25 23:30:00
2003-10-26 00:30:00 2003-10-26 00:30:00
delete from t1 where ts='1970-01-01 01:00:01';
select * from t1;
dt ts
2038-01-19 04:14:07 2038-01-19 04:14:07
2003-10-25 23:30:00 2003-10-25 23:30:00
2003-10-26 00:30:00 2003-10-26 00:30:00
insert t1 values ('1970-01-01 01:00:01', now());
update t1 set ts=dt;
select * from t1;
dt ts
1970-01-01 01:00:01 1970-01-01 01:00:01
2038-01-19 04:14:07 2038-01-19 04:14:07
2003-10-25 23:30:00 2003-10-25 23:30:00
2003-10-26 00:30:00 2003-10-26 00:30:00
select * from t1 where ts='2003-10-25 23:30:00';
dt ts
2003-10-25 23:30:00 2003-10-25 23:30:00
select * from t1 where ts='2003-10-26 00:30:00';
dt ts
2003-10-26 00:30:00 2003-10-26 00:30:00
connection slave;
select * from federated.t1;
dt ts
1970-01-01 01:00:01 1970-01-01 03:00:01
2038-01-19 04:14:07 2038-01-19 06:14:07
2003-10-25 23:30:00 2003-10-26 02:30:00
2003-10-26 00:30:00 2003-10-26 02:30:00
set global time_zone=default;
connection master;
drop table t1;
connection master;
DROP TABLE IF EXISTS federated.t1;
DROP DATABASE IF EXISTS federated;
connection slave;
DROP TABLE IF EXISTS federated.t1;
DROP DATABASE IF EXISTS federated;
source have_federatedx.inc;
source include/federated.inc;
connection slave;
set global time_zone='Europe/Moscow';
set time_zone='Europe/Moscow';
create table federated.t1 (dt datetime, ts timestamp, unique(ts));
connection master;
set time_zone='+01:00';
replace_result $SLAVE_MYPORT SLAVE_PORT;
eval create table t1 engine=federated connection='mysql://root@127.0.0.1:$SLAVE_MYPORT/federated/t1';
set @@timestamp=1; # min value
insert t1 values (now(), now());
set @@timestamp=2147483647; # max value
insert t1 values (now(), now());
set @@timestamp=1067121000; # DST ambiguous (in Europe/Moscow)
insert t1 values (now(), now());
set @@timestamp=1067124600; # DST ambiguous (in Europe/Moscow)
insert t1 values (now(), now());
set @@timestamp=0;
# reads
select * from t1;
# deletes
delete from t1 where ts='1970-01-01 01:00:01';
select * from t1;
# updates
insert t1 values ('1970-01-01 01:00:01', now());
update t1 set ts=dt;
select * from t1;
# index lookups
select * from t1 where ts='2003-10-25 23:30:00';
select * from t1 where ts='2003-10-26 00:30:00';
connection slave;
select * from federated.t1;
set global time_zone=default;
connection master;
drop table t1;
source include/federated_cleanup.inc;
...@@ -453,7 +453,8 @@ int federatedx_io_mysql::actual_query(const char *buffer, size_t length) ...@@ -453,7 +453,8 @@ int federatedx_io_mysql::actual_query(const char *buffer, size_t length)
mysql.reconnect= 1; mysql.reconnect= 1;
} }
error= mysql_real_query(&mysql, buffer, (ulong)length); if (!(error= mysql_real_query(&mysql, STRING_WITH_LEN("set time_zone='+00:00'"))))
error= mysql_real_query(&mysql, buffer, (ulong)length);
DBUG_RETURN(error); DBUG_RETURN(error);
} }
......
...@@ -318,6 +318,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ...@@ -318,6 +318,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "sql_servers.h" #include "sql_servers.h"
#include "sql_analyse.h" // append_escaped() #include "sql_analyse.h" // append_escaped()
#include "sql_show.h" // append_identifier() #include "sql_show.h" // append_identifier()
#include "tztime.h" // my_tz_find()
#ifdef I_AM_PARANOID #ifdef I_AM_PARANOID
#define MIN_PORT 1023 #define MIN_PORT 1023
...@@ -340,6 +341,8 @@ static const uint sizeof_trailing_comma= sizeof(", ") - 1; ...@@ -340,6 +341,8 @@ static const uint sizeof_trailing_comma= sizeof(", ") - 1;
static const uint sizeof_trailing_and= sizeof(" AND ") - 1; static const uint sizeof_trailing_and= sizeof(" AND ") - 1;
static const uint sizeof_trailing_where= sizeof(" WHERE ") - 1; static const uint sizeof_trailing_where= sizeof(" WHERE ") - 1;
static Time_zone *UTC= 0;
/* Static declaration for handerton */ /* Static declaration for handerton */
static handler *federatedx_create_handler(handlerton *hton, static handler *federatedx_create_handler(handlerton *hton,
TABLE_SHARE *table, TABLE_SHARE *table,
...@@ -860,8 +863,10 @@ uint ha_federatedx::convert_row_to_internal_format(uchar *record, ...@@ -860,8 +863,10 @@ uint ha_federatedx::convert_row_to_internal_format(uchar *record,
Field **field; Field **field;
int column= 0; int column= 0;
my_bitmap_map *old_map= dbug_tmp_use_all_columns(table, table->write_set); my_bitmap_map *old_map= dbug_tmp_use_all_columns(table, table->write_set);
Time_zone *saved_time_zone= table->in_use->variables.time_zone;
DBUG_ENTER("ha_federatedx::convert_row_to_internal_format"); DBUG_ENTER("ha_federatedx::convert_row_to_internal_format");
table->in_use->variables.time_zone= UTC;
lengths= io->fetch_lengths(result); lengths= io->fetch_lengths(result);
for (field= table->field; *field; field++, column++) for (field= table->field; *field; field++, column++)
...@@ -885,6 +890,7 @@ uint ha_federatedx::convert_row_to_internal_format(uchar *record, ...@@ -885,6 +890,7 @@ uint ha_federatedx::convert_row_to_internal_format(uchar *record,
} }
(*field)->move_field_offset(-old_ptr); (*field)->move_field_offset(-old_ptr);
} }
table->in_use->variables.time_zone= saved_time_zone;
dbug_tmp_restore_column_map(table->write_set, old_map); dbug_tmp_restore_column_map(table->write_set, old_map);
DBUG_RETURN(0); DBUG_RETURN(0);
} }
...@@ -1213,6 +1219,7 @@ bool ha_federatedx::create_where_from_key(String *to, ...@@ -1213,6 +1219,7 @@ bool ha_federatedx::create_where_from_key(String *to,
char tmpbuff[FEDERATEDX_QUERY_BUFFER_SIZE]; char tmpbuff[FEDERATEDX_QUERY_BUFFER_SIZE];
String tmp(tmpbuff, sizeof(tmpbuff), system_charset_info); String tmp(tmpbuff, sizeof(tmpbuff), system_charset_info);
const key_range *ranges[2]= { start_key, end_key }; const key_range *ranges[2]= { start_key, end_key };
Time_zone *saved_time_zone= table->in_use->variables.time_zone;
my_bitmap_map *old_map; my_bitmap_map *old_map;
DBUG_ENTER("ha_federatedx::create_where_from_key"); DBUG_ENTER("ha_federatedx::create_where_from_key");
...@@ -1220,6 +1227,7 @@ bool ha_federatedx::create_where_from_key(String *to, ...@@ -1220,6 +1227,7 @@ bool ha_federatedx::create_where_from_key(String *to,
if (start_key == NULL && end_key == NULL) if (start_key == NULL && end_key == NULL)
DBUG_RETURN(1); DBUG_RETURN(1);
table->in_use->variables.time_zone= UTC;
old_map= dbug_tmp_use_all_columns(table, table->write_set); old_map= dbug_tmp_use_all_columns(table, table->write_set);
for (uint i= 0; i <= 1; i++) for (uint i= 0; i <= 1; i++)
{ {
...@@ -1397,6 +1405,7 @@ bool ha_federatedx::create_where_from_key(String *to, ...@@ -1397,6 +1405,7 @@ bool ha_federatedx::create_where_from_key(String *to,
} }
} }
dbug_tmp_restore_column_map(table->write_set, old_map); dbug_tmp_restore_column_map(table->write_set, old_map);
table->in_use->variables.time_zone= saved_time_zone;
if (both_not_null) if (both_not_null)
if (tmp.append(STRING_WITH_LEN(") "))) if (tmp.append(STRING_WITH_LEN(") ")))
...@@ -1412,6 +1421,7 @@ bool ha_federatedx::create_where_from_key(String *to, ...@@ -1412,6 +1421,7 @@ bool ha_federatedx::create_where_from_key(String *to,
err: err:
dbug_tmp_restore_column_map(table->write_set, old_map); dbug_tmp_restore_column_map(table->write_set, old_map);
table->in_use->variables.time_zone= saved_time_zone;
DBUG_RETURN(1); DBUG_RETURN(1);
} }
...@@ -1582,6 +1592,12 @@ static FEDERATEDX_SHARE *get_share(const char *table_name, TABLE *table) ...@@ -1582,6 +1592,12 @@ static FEDERATEDX_SHARE *get_share(const char *table_name, TABLE *table)
mysql_mutex_lock(&federatedx_mutex); mysql_mutex_lock(&federatedx_mutex);
if (unlikely(!UTC))
{
String tz_00_name(STRING_WITH_LEN("+00:00"), &my_charset_bin);
UTC= my_tz_find(current_thd, &tz_00_name);
}
tmp_share.share_key= table_name; tmp_share.share_key= table_name;
tmp_share.share_key_length= (int)strlen(table_name); tmp_share.share_key_length= (int)strlen(table_name);
if (parse_url(&mem_root, &tmp_share, table->s, 0)) if (parse_url(&mem_root, &tmp_share, table->s, 0))
...@@ -1978,9 +1994,11 @@ int ha_federatedx::write_row(uchar *buf) ...@@ -1978,9 +1994,11 @@ int ha_federatedx::write_row(uchar *buf)
String insert_field_value_string(insert_field_value_buffer, String insert_field_value_string(insert_field_value_buffer,
sizeof(insert_field_value_buffer), sizeof(insert_field_value_buffer),
&my_charset_bin); &my_charset_bin);
Time_zone *saved_time_zone= table->in_use->variables.time_zone;
my_bitmap_map *old_map= dbug_tmp_use_all_columns(table, table->read_set); my_bitmap_map *old_map= dbug_tmp_use_all_columns(table, table->read_set);
DBUG_ENTER("ha_federatedx::write_row"); DBUG_ENTER("ha_federatedx::write_row");
table->in_use->variables.time_zone= UTC;
values_string.length(0); values_string.length(0);
insert_field_value_string.length(0); insert_field_value_string.length(0);
...@@ -2033,6 +2051,7 @@ int ha_federatedx::write_row(uchar *buf) ...@@ -2033,6 +2051,7 @@ int ha_federatedx::write_row(uchar *buf)
} }
} }
dbug_tmp_restore_column_map(table->read_set, old_map); dbug_tmp_restore_column_map(table->read_set, old_map);
table->in_use->variables.time_zone= saved_time_zone;
/* /*
if there were no fields, we don't want to add a closing paren if there were no fields, we don't want to add a closing paren
...@@ -2340,6 +2359,8 @@ int ha_federatedx::update_row(const uchar *old_data, const uchar *new_data) ...@@ -2340,6 +2359,8 @@ int ha_federatedx::update_row(const uchar *old_data, const uchar *new_data)
field=oldvalue field=oldvalue
*/ */
Time_zone *saved_time_zone= table->in_use->variables.time_zone;
table->in_use->variables.time_zone= UTC;
for (Field **field= table->field; *field; field++) for (Field **field= table->field; *field; field++)
{ {
if (bitmap_is_set(table->write_set, (*field)->field_index)) if (bitmap_is_set(table->write_set, (*field)->field_index))
...@@ -2391,6 +2412,7 @@ int ha_federatedx::update_row(const uchar *old_data, const uchar *new_data) ...@@ -2391,6 +2412,7 @@ int ha_federatedx::update_row(const uchar *old_data, const uchar *new_data)
where_string.append(STRING_WITH_LEN(" AND ")); where_string.append(STRING_WITH_LEN(" AND "));
} }
} }
table->in_use->variables.time_zone= saved_time_zone;
/* Remove last ', '. This works as there must be at least on updated field */ /* Remove last ', '. This works as there must be at least on updated field */
update_string.length(update_string.length() - sizeof_trailing_comma); update_string.length(update_string.length() - sizeof_trailing_comma);
...@@ -2451,6 +2473,8 @@ int ha_federatedx::delete_row(const uchar *buf) ...@@ -2451,6 +2473,8 @@ int ha_federatedx::delete_row(const uchar *buf)
share->table_name_length, ident_quote_char); share->table_name_length, ident_quote_char);
delete_string.append(STRING_WITH_LEN(" WHERE ")); delete_string.append(STRING_WITH_LEN(" WHERE "));
Time_zone *saved_time_zone= table->in_use->variables.time_zone;
table->in_use->variables.time_zone= UTC;
for (Field **field= table->field; *field; field++) for (Field **field= table->field; *field; field++)
{ {
Field *cur_field= *field; Field *cur_field= *field;
...@@ -2478,6 +2502,7 @@ int ha_federatedx::delete_row(const uchar *buf) ...@@ -2478,6 +2502,7 @@ int ha_federatedx::delete_row(const uchar *buf)
delete_string.append(STRING_WITH_LEN(" AND ")); delete_string.append(STRING_WITH_LEN(" AND "));
} }
} }
table->in_use->variables.time_zone= saved_time_zone;
// Remove trailing AND // Remove trailing AND
delete_string.length(delete_string.length() - sizeof_trailing_and); delete_string.length(delete_string.length() - sizeof_trailing_and);
......
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