summaryrefslogtreecommitdiff
path: root/storage
diff options
context:
space:
mode:
authorSergei Golubchik <serg@mariadb.org>2018-05-14 10:47:13 +0200
committerSergei Golubchik <serg@mariadb.org>2018-05-17 15:33:39 +0200
commitdfd6702a29643e8f3d875b4d67bcf021714432a5 (patch)
treee87d1a05899bd668536e3d174fee5fb361bb0627 /storage
parent28dbdf3d79cfd39ffa2e1d087662ac82c9281d1d (diff)
downloadmariadb-git-dfd6702a29643e8f3d875b4d67bcf021714432a5.tar.gz
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.
Diffstat (limited to 'storage')
-rw-r--r--storage/federatedx/federatedx_io_mysql.cc3
-rw-r--r--storage/federatedx/ha_federatedx.cc25
2 files changed, 27 insertions, 1 deletions
diff --git a/storage/federatedx/federatedx_io_mysql.cc b/storage/federatedx/federatedx_io_mysql.cc
index a83e54513d3..cc4d8ca7c70 100644
--- a/storage/federatedx/federatedx_io_mysql.cc
+++ b/storage/federatedx/federatedx_io_mysql.cc
@@ -453,7 +453,8 @@ int federatedx_io_mysql::actual_query(const char *buffer, size_t length)
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);
}
diff --git a/storage/federatedx/ha_federatedx.cc b/storage/federatedx/ha_federatedx.cc
index 8c21906fe84..8f793230926 100644
--- a/storage/federatedx/ha_federatedx.cc
+++ b/storage/federatedx/ha_federatedx.cc
@@ -318,6 +318,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "sql_servers.h"
#include "sql_analyse.h" // append_escaped()
#include "sql_show.h" // append_identifier()
+#include "tztime.h" // my_tz_find()
#ifdef I_AM_PARANOID
#define MIN_PORT 1023
@@ -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_where= sizeof(" WHERE ") - 1;
+static Time_zone *UTC= 0;
+
/* Static declaration for handerton */
static handler *federatedx_create_handler(handlerton *hton,
TABLE_SHARE *table,
@@ -860,8 +863,10 @@ uint ha_federatedx::convert_row_to_internal_format(uchar *record,
Field **field;
int column= 0;
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");
+ table->in_use->variables.time_zone= UTC;
lengths= io->fetch_lengths(result);
for (field= table->field; *field; field++, column++)
@@ -885,6 +890,7 @@ uint ha_federatedx::convert_row_to_internal_format(uchar *record,
}
(*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_RETURN(0);
}
@@ -1213,6 +1219,7 @@ bool ha_federatedx::create_where_from_key(String *to,
char tmpbuff[FEDERATEDX_QUERY_BUFFER_SIZE];
String tmp(tmpbuff, sizeof(tmpbuff), system_charset_info);
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;
DBUG_ENTER("ha_federatedx::create_where_from_key");
@@ -1220,6 +1227,7 @@ bool ha_federatedx::create_where_from_key(String *to,
if (start_key == NULL && end_key == NULL)
DBUG_RETURN(1);
+ table->in_use->variables.time_zone= UTC;
old_map= dbug_tmp_use_all_columns(table, table->write_set);
for (uint i= 0; i <= 1; i++)
{
@@ -1397,6 +1405,7 @@ prepare_for_next_key_part:
}
}
dbug_tmp_restore_column_map(table->write_set, old_map);
+ table->in_use->variables.time_zone= saved_time_zone;
if (both_not_null)
if (tmp.append(STRING_WITH_LEN(") ")))
@@ -1412,6 +1421,7 @@ prepare_for_next_key_part:
err:
dbug_tmp_restore_column_map(table->write_set, old_map);
+ table->in_use->variables.time_zone= saved_time_zone;
DBUG_RETURN(1);
}
@@ -1582,6 +1592,12 @@ static FEDERATEDX_SHARE *get_share(const char *table_name, TABLE *table)
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_length= (int)strlen(table_name);
if (parse_url(&mem_root, &tmp_share, table->s, 0))
@@ -1978,9 +1994,11 @@ int ha_federatedx::write_row(uchar *buf)
String insert_field_value_string(insert_field_value_buffer,
sizeof(insert_field_value_buffer),
&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);
DBUG_ENTER("ha_federatedx::write_row");
+ table->in_use->variables.time_zone= UTC;
values_string.length(0);
insert_field_value_string.length(0);
@@ -2033,6 +2051,7 @@ int ha_federatedx::write_row(uchar *buf)
}
}
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
@@ -2340,6 +2359,8 @@ int ha_federatedx::update_row(const uchar *old_data, const uchar *new_data)
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++)
{
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)
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 */
update_string.length(update_string.length() - sizeof_trailing_comma);
@@ -2451,6 +2473,8 @@ int ha_federatedx::delete_row(const uchar *buf)
share->table_name_length, ident_quote_char);
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++)
{
Field *cur_field= *field;
@@ -2478,6 +2502,7 @@ int ha_federatedx::delete_row(const uchar *buf)
delete_string.append(STRING_WITH_LEN(" AND "));
}
}
+ table->in_use->variables.time_zone= saved_time_zone;
// Remove trailing AND
delete_string.length(delete_string.length() - sizeof_trailing_and);