summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJacob Mathew <jacob.mathew@mariadb.com>2018-07-09 14:25:37 -0700
committerJacob Mathew <jacob.mathew@mariadb.com>2018-07-09 14:25:37 -0700
commit97cc9d34e3e27f8354e55c43d19d8f313b7ae6fd (patch)
treeec2aa5e9fae5c1662110d81195dbeefd250a901e
parentb27ec709350e13c5cdc08dcdcaeb31b1cc0f803e (diff)
downloadmariadb-git-97cc9d34e3e27f8354e55c43d19d8f313b7ae6fd.tar.gz
MDEV-16246: insert timestamp into spider table from mysqldump gets wrong time zone.bb-10.3-MDEV-16246
The problem occurred because the Spider node was incorrectly handling timestamp values sent to and received from the data nodes. The problem has been corrected as follows: - Added logic to set and maintain the UTC time zone on the data nodes. To prevent timestamp ambiguity, it is necessary for the data nodes to use a time zone such as UTC which does not have daylight savings time. - Removed the spider_sync_time_zone configuration variable, which did not solve the problem and which interfered with the solution. - Added logic to convert to the UTC time zone all timestamp values sent to and received from the data nodes. This is done for both unique and non-unique timestamp columns. It is done for WHERE clauses, applying to SELECT, UPDATE and DELETE statements, and for UPDATE columns. - Disabled Spider's use of direct update when any of the columns to update is a timestamp column. This is necessary to prevent false duplicate key value errors. - Added a new test spider.timestamp to thoroughly test Spider's handling of timestamp values. Author: Jacob Mathew. Reviewer: Kentoku Shiba.
-rw-r--r--sql/ha_partition.cc12
-rw-r--r--sql/ha_partition.h4
-rw-r--r--sql/handler.h4
-rw-r--r--sql/sql_update.cc5
-rw-r--r--storage/spider/ha_spider.cc94
-rw-r--r--storage/spider/ha_spider.h34
-rw-r--r--storage/spider/mysql-test/spider/r/timestamp.result370
-rw-r--r--storage/spider/mysql-test/spider/t/timestamp.test465
-rw-r--r--storage/spider/mysql-test/spider/t/timestamp_deinit.inc13
-rw-r--r--storage/spider/mysql-test/spider/t/timestamp_init.inc45
-rw-r--r--storage/spider/spd_conn.cc18
-rw-r--r--storage/spider/spd_conn.h6
-rw-r--r--storage/spider/spd_db_conn.cc473
-rw-r--r--storage/spider/spd_db_conn.h14
-rw-r--r--storage/spider/spd_db_include.h1
-rw-r--r--storage/spider/spd_db_mysql.cc242
-rw-r--r--storage/spider/spd_db_mysql.h2
-rw-r--r--storage/spider/spd_db_oracle.h2
-rw-r--r--storage/spider/spd_group_by_handler.cc24
-rw-r--r--storage/spider/spd_include.h2
-rw-r--r--storage/spider/spd_param.cc21
-rw-r--r--storage/spider/spd_param.h3
-rw-r--r--storage/spider/spd_trx.cc5
23 files changed, 1575 insertions, 284 deletions
diff --git a/sql/ha_partition.cc b/sql/ha_partition.cc
index 0775d67a592..20873c01771 100644
--- a/sql/ha_partition.cc
+++ b/sql/ha_partition.cc
@@ -11142,13 +11142,14 @@ int ha_partition::end_bulk_delete()
SYNOPSIS
direct_update_rows_init()
+ update fields Pointer to the list of fields to update
RETURN VALUE
>0 Error
0 Success
*/
-int ha_partition::direct_update_rows_init()
+int ha_partition::direct_update_rows_init(List<Item> *update_fields)
{
int error;
uint i, found;
@@ -11174,8 +11175,8 @@ int ha_partition::direct_update_rows_init()
{
file= m_file[i];
if (unlikely((error= (m_pre_calling ?
- file->pre_direct_update_rows_init() :
- file->direct_update_rows_init()))))
+ file->pre_direct_update_rows_init(update_fields) :
+ file->direct_update_rows_init(update_fields)))))
{
DBUG_PRINT("info", ("partition FALSE by storage engine"));
DBUG_RETURN(error);
@@ -11213,20 +11214,21 @@ int ha_partition::direct_update_rows_init()
SYNOPSIS
pre_direct_update_rows_init()
+ update fields Pointer to the list of fields to update
RETURN VALUE
>0 Error
0 Success
*/
-int ha_partition::pre_direct_update_rows_init()
+int ha_partition::pre_direct_update_rows_init(List<Item> *update_fields)
{
bool save_m_pre_calling;
int error;
DBUG_ENTER("ha_partition::pre_direct_update_rows_init");
save_m_pre_calling= m_pre_calling;
m_pre_calling= TRUE;
- error= direct_update_rows_init();
+ error= direct_update_rows_init(update_fields);
m_pre_calling= save_m_pre_calling;
DBUG_RETURN(error);
}
diff --git a/sql/ha_partition.h b/sql/ha_partition.h
index e661d0badd3..8a251016703 100644
--- a/sql/ha_partition.h
+++ b/sql/ha_partition.h
@@ -620,8 +620,8 @@ public:
virtual int bulk_update_row(const uchar *old_data, const uchar *new_data,
ha_rows *dup_key_found);
virtual int update_row(const uchar * old_data, const uchar * new_data);
- virtual int direct_update_rows_init();
- virtual int pre_direct_update_rows_init();
+ virtual int direct_update_rows_init(List<Item> *update_fields);
+ virtual int pre_direct_update_rows_init(List<Item> *update_fields);
virtual int direct_update_rows(ha_rows *update_rows);
virtual int pre_direct_update_rows();
virtual bool start_bulk_delete();
diff --git a/sql/handler.h b/sql/handler.h
index 3d1b764bd14..6828173282d 100644
--- a/sql/handler.h
+++ b/sql/handler.h
@@ -4399,12 +4399,12 @@ private:
/* Perform initialization for a direct update request */
public:
int ha_direct_update_rows(ha_rows *update_rows);
- virtual int direct_update_rows_init()
+ virtual int direct_update_rows_init(List<Item> *update_fields)
{
return HA_ERR_WRONG_COMMAND;
}
private:
- virtual int pre_direct_update_rows_init()
+ virtual int pre_direct_update_rows_init(List<Item> *update_fields)
{
return HA_ERR_WRONG_COMMAND;
}
diff --git a/sql/sql_update.cc b/sql/sql_update.cc
index c0fa2b4d7fe..cb7bcdc33a1 100644
--- a/sql/sql_update.cc
+++ b/sql/sql_update.cc
@@ -615,6 +615,9 @@ int mysql_update(THD *thd,
- Note that Spider can handle ORDER BY and LIMIT in a cluster with
one data node. These conditions are therefore checked in
direct_update_rows_init().
+ - Update fields include a unique timestamp field
+ - The storage engine may not be able to avoid false duplicate key
+ errors. This condition is checked in direct_update_rows_init().
Direct update does not require a WHERE clause
@@ -637,7 +640,7 @@ int mysql_update(THD *thd,
if (!table->file->info_push(INFO_KIND_UPDATE_FIELDS, &fields) &&
!table->file->info_push(INFO_KIND_UPDATE_VALUES, &values) &&
- !table->file->direct_update_rows_init())
+ !table->file->direct_update_rows_init(&fields))
{
do_direct_update= TRUE;
diff --git a/storage/spider/ha_spider.cc b/storage/spider/ha_spider.cc
index 9668e4cfbdb..bd302f155d2 100644
--- a/storage/spider/ha_spider.cc
+++ b/storage/spider/ha_spider.cc
@@ -10064,13 +10064,11 @@ int ha_spider::update_row(
#ifdef HANDLER_HAS_DIRECT_UPDATE_ROWS
#ifdef HANDLER_HAS_DIRECT_UPDATE_ROWS_WITH_HS
-int ha_spider::direct_update_rows_init(
- uint mode,
- KEY_MULTI_RANGE *ranges,
- uint range_count,
- bool sorted,
- const uchar *new_data
-) {
+int ha_spider::direct_update_rows_init(List<Item> *update_fields, uint mode,
+ KEY_MULTI_RANGE *ranges,
+ uint range_count, bool sorted,
+ const uchar *new_data)
+{
#if defined(HS_HAS_SQLCOM) && defined(HAVE_HANDLERSOCKET)
int error_num;
#endif
@@ -10098,7 +10096,7 @@ int ha_spider::direct_update_rows_init(
DBUG_RETURN(pre_direct_init_result);
}
DBUG_RETURN(bulk_access_link_exec_tgt->spider->direct_update_rows_init(
- mode, ranges, range_count, sorted, new_data));
+ update_fields, mode, ranges, range_count, sorted, new_data));
}
#endif
direct_update_init(
@@ -10202,14 +10200,46 @@ int ha_spider::direct_update_rows_init(
DBUG_RETURN(HA_ERR_WRONG_COMMAND);
}
#else
-int ha_spider::direct_update_rows_init()
+/**
+ Perform initialization for a direct update request.
+
+ @param update fields Pointer to the list of fields to update.
+
+ @return >0 Error.
+ 0 Success.
+*/
+
+int ha_spider::direct_update_rows_init(List<Item> *update_fields)
{
st_select_lex *select_lex;
longlong select_limit;
longlong offset_limit;
+ List_iterator<Item> it(*update_fields);
+ Item *item;
+ Field *field;
THD *thd = trx->thd;
DBUG_ENTER("ha_spider::direct_update_rows_init");
DBUG_PRINT("info",("spider this=%p", this));
+
+ while ((item = it++))
+ {
+ if (item->type() == Item::FIELD_ITEM)
+ {
+ field = ((Item_field *)item)->field;
+
+ if (field->type() == FIELD_TYPE_TIMESTAMP &&
+ field->flags & UNIQUE_KEY_FLAG)
+ {
+ /*
+ Spider cannot perform direct update on unique timestamp fields.
+ To avoid false duplicate key errors, the table needs to be
+ updated one row at a time.
+ */
+ DBUG_RETURN(HA_ERR_WRONG_COMMAND);
+ }
+ }
+ }
+
#ifdef HA_CAN_BULK_ACCESS
if (
bulk_access_executing &&
@@ -10227,7 +10257,8 @@ int ha_spider::direct_update_rows_init()
pre_direct_init_result));
DBUG_RETURN(pre_direct_init_result);
}
- DBUG_RETURN(bulk_access_link_exec_tgt->spider->direct_update_rows_init());
+ DBUG_RETURN(bulk_access_link_exec_tgt->spider->
+ direct_update_rows_init(List<Item> *update_fields));
}
#endif
direct_update_init(
@@ -10298,31 +10329,41 @@ int ha_spider::direct_update_rows_init()
#ifdef HA_CAN_BULK_ACCESS
#ifdef HANDLER_HAS_DIRECT_UPDATE_ROWS_WITH_HS
-int ha_spider::pre_direct_update_rows_init(
- uint mode,
- KEY_MULTI_RANGE *ranges,
- uint range_count,
- bool sorted,
- const uchar *new_data
-) {
+int ha_spider::pre_direct_update_rows_init(List<Item> *update_fields,
+ uint mode,
+ KEY_MULTI_RANGE *ranges,
+ uint range_count, bool sorted,
+ const uchar *new_data)
+{
int error_num;
DBUG_ENTER("ha_spider::pre_direct_update_rows_init");
DBUG_PRINT("info",("spider this=%p", this));
if (bulk_access_started)
{
error_num = bulk_access_link_current->spider->
- pre_direct_update_rows_init(
- mode, ranges, range_count, sorted, new_data);
+ pre_direct_update_rows_init(update_fields, mode, ranges, range_count,
+ sorted, new_data);
bulk_access_link_current->spider->bulk_access_pre_called = TRUE;
bulk_access_link_current->called = TRUE;
DBUG_RETURN(error_num);
}
- pre_direct_init_result = direct_update_rows_init(
- mode, ranges, range_count, sorted, new_data);
+ pre_direct_init_result = direct_update_rows_init(update_fields, mode,
+ ranges, range_count,
+ sorted, new_data);
DBUG_RETURN(pre_direct_init_result);
}
#else
-int ha_spider::pre_direct_update_rows_init()
+/**
+ Do initialization for performing parallel direct update
+ for a handlersocket update request.
+
+ @param update fields Pointer to the list of fields to update.
+
+ @return >0 Error.
+ 0 Success.
+*/
+
+int ha_spider::pre_direct_update_rows_init(List<Item> *update_fields)
{
int error_num;
DBUG_ENTER("ha_spider::pre_direct_update_rows_init");
@@ -10330,12 +10371,12 @@ int ha_spider::pre_direct_update_rows_init()
if (bulk_access_started)
{
error_num = bulk_access_link_current->spider->
- pre_direct_update_rows_init();
+ pre_direct_update_rows_init(update_fields);
bulk_access_link_current->spider->bulk_access_pre_called = TRUE;
bulk_access_link_current->called = TRUE;
DBUG_RETURN(error_num);
}
- pre_direct_init_result = direct_update_rows_init();
+ pre_direct_init_result = direct_update_rows_init(update_fields);
DBUG_RETURN(pre_direct_init_result);
}
#endif
@@ -15733,8 +15774,9 @@ int ha_spider::print_item_type(
dbton_hdl = dbton_handler[dbton_id];
if (
dbton_hdl->first_link_idx >= 0 &&
- (error_num = spider_db_print_item_type(item, this, str,
- alias, alias_length, dbton_id, FALSE, NULL))
+ (error_num = spider_db_print_item_type(item, NULL, this, str,
+ alias, alias_length, dbton_id,
+ FALSE, NULL))
) {
DBUG_RETURN(error_num);
}
diff --git a/storage/spider/ha_spider.h b/storage/spider/ha_spider.h
index b79e1b89fbf..66e5cf8a452 100644
--- a/storage/spider/ha_spider.h
+++ b/storage/spider/ha_spider.h
@@ -587,35 +587,29 @@ public:
);
#ifdef HANDLER_HAS_DIRECT_UPDATE_ROWS
#ifdef HANDLER_HAS_DIRECT_UPDATE_ROWS_WITH_HS
- inline int direct_update_rows_init()
+ inline int direct_update_rows_init(List<Item> *update_fields)
{
- return direct_update_rows_init(2, NULL, 0, FALSE, NULL);
+ return direct_update_rows_init(update_fields, 2, NULL, 0, FALSE, NULL);
}
- int direct_update_rows_init(
- uint mode,
- KEY_MULTI_RANGE *ranges,
- uint range_count,
- bool sorted,
- const uchar *new_data
- );
+ int direct_update_rows_init(List<Item> *update_fields, uint mode,
+ KEY_MULTI_RANGE *ranges, uint range_count,
+ bool sorted, const uchar *new_data);
#else
- int direct_update_rows_init();
+ int direct_update_rows_init(List<Item> *update_fields);
#endif
#ifdef HA_CAN_BULK_ACCESS
#ifdef HANDLER_HAS_DIRECT_UPDATE_ROWS_WITH_HS
- inline int pre_direct_update_rows_init()
+ inline int pre_direct_update_rows_init(List<Item> *update_fields)
{
- return pre_direct_update_rows_init(2, NULL, 0, FALSE, NULL);
+ return pre_direct_update_rows_init(update_fields,
+ 2, NULL, 0, FALSE, NULL);
}
- int pre_direct_update_rows_init(
- uint mode,
- KEY_MULTI_RANGE *ranges,
- uint range_count,
- bool sorted,
- uchar *new_data
- );
+ int pre_direct_update_rows_init(List<Item> *update_fields,
+ uint mode, KEY_MULTI_RANGE *ranges,
+ uint range_count, bool sorted,
+ uchar *new_data);
#else
- int pre_direct_update_rows_init();
+ int pre_direct_update_rows_init(List<Item> *update_fields);
#endif
#endif
#ifdef HANDLER_HAS_DIRECT_UPDATE_ROWS_WITH_HS
diff --git a/storage/spider/mysql-test/spider/r/timestamp.result b/storage/spider/mysql-test/spider/r/timestamp.result
new file mode 100644
index 00000000000..df40549cab2
--- /dev/null
+++ b/storage/spider/mysql-test/spider/r/timestamp.result
@@ -0,0 +1,370 @@
+for master_1
+for child2
+child2_1
+child2_2
+child2_3
+for child3
+child3_1
+child3_2
+child3_3
+
+Initialize Time Zone
+connection master_1;
+SET GLOBAL time_zone='MET';
+SET time_zone='MET';
+connection child2_1;
+SET GLOBAL time_zone='MET';
+SET time_zone='MET';
+
+drop and create databases
+connection master_1;
+DROP DATABASE IF EXISTS ts_test_local;
+CREATE DATABASE ts_test_local;
+USE ts_test_local;
+connection child2_1;
+SET @old_log_output = @@global.log_output;
+SET GLOBAL log_output = 'TABLE,FILE';
+DROP DATABASE IF EXISTS ts_test_remote;
+CREATE DATABASE ts_test_remote;
+USE ts_test_remote;
+
+test select 1
+connection master_1;
+SELECT 1;
+1
+1
+connection child2_1;
+SELECT 1;
+1
+1
+
+create table
+connection child2_1;
+CHILD2_1_DROP_TABLES
+CHILD2_1_CREATE_TABLES
+TRUNCATE TABLE mysql.general_log;
+connection master_1;
+DROP TABLE IF EXISTS tbl_a;
+CREATE TABLE tbl_a (
+col_a INT UNSIGNED NOT NULL AUTO_INCREMENT,
+col_dt DATETIME,
+col_ts TIMESTAMP NOT NULL
+DEFAULT current_timestamp() ON UPDATE current_timestamp(),
+PRIMARY KEY(col_a),
+) MASTER_1_ENGINE MASTER_1_AUTO_INCREMENT_2_1 MASTER_1_COMMENT_2_1
+SHOW CREATE TABLE tbl_a;
+Table Create Table
+tbl_a CREATE TABLE `tbl_a` (
+ `col_a` int(10) unsigned NOT NULL AUTO_INCREMENT,
+ `col_dt` datetime DEFAULT NULL,
+ `col_ts` timestamp NOT NULL DEFAULT current_timestamp() ON UPDATE current_timestamp(),
+ PRIMARY KEY (`col_a`),
+ UNIQUE KEY `i_ts` (`col_ts`)
+) ENGINE=SPIDER AUTO_INCREMENT=17 DEFAULT CHARSET=utf8mb4 COMMENT='database "ts_test_remote", table "tbl_a", srv "s_2_1"'
+
+Set a different time zone that has DST
+SET time_zone='+01:00';
+
+Insert Rows
+connection master_1;
+Min value
+SET @@timestamp=1;
+INSERT INTO tbl_a VALUES (1, now(), now());
+SET @@timestamp=0;
+Ambiguous DST values for MET time zone that result in the
+same UTC timestamp
+INSERT INTO tbl_a VALUES (2, '2018-03-25 02:00:00', '2018-03-25 02:00:00');
+INSERT INTO tbl_a VALUES (3, '2018-03-25 02:30:00', '2018-03-25 02:30:00');
+Ambiguous DST values for MET time zone in the 2:00 am to 3:00 am hour
+that occur twice when transitioning from DST to standard time
+SET @@timestamp=1540686600;
+INSERT INTO tbl_a VALUES (4, now(), now());
+SET @@timestamp=1540690200;
+INSERT INTO tbl_a VALUES (5, now(), now());
+Max value
+SET @@timestamp=2147483647;
+INSERT INTO tbl_a VALUES (6, now(), now());
+SET @@timestamp=0;
+
+SELECTs
+connection child2_1;
+TRUNCATE TABLE mysql.general_log;
+connection master_1;
+SELECT *, unix_timestamp(col_ts) FROM tbl_a;
+col_a col_dt col_ts unix_timestamp(col_ts)
+1 1970-01-01 01:00:01 1970-01-01 01:00:01 1
+2 2018-03-25 02:00:00 2018-03-25 02:00:00 1521939600
+3 2018-03-25 02:30:00 2018-03-25 02:30:00 1521941400
+4 2018-10-28 01:30:00 2018-10-28 01:30:00 1540686600
+5 2018-10-28 02:30:00 2018-10-28 02:30:00 1540690200
+6 2038-01-19 04:14:07 2038-01-19 04:14:07 2147483647
+connection child2_1;
+SELECT argument FROM mysql.general_log WHERE argument LIKE '%select %';
+argument
+select `col_a`,`col_dt`,`col_ts` from `ts_test_remote`.`tbl_a`
+SELECT argument FROM mysql.general_log WHERE argument LIKE '%select %'
+SELECT col_a, col_dt, col_ts, unix_timestamp(col_ts) FROM tbl_a ORDER BY col_a;
+col_a col_dt col_ts unix_timestamp(col_ts)
+1 1970-01-01 01:00:01 1970-01-01 01:00:01 1
+2 2018-03-25 02:00:00 2018-03-25 03:00:00 1521939600
+3 2018-03-25 02:30:00 2018-03-25 03:30:00 1521941400
+4 2018-10-28 01:30:00 2018-10-28 02:30:00 1540686600
+5 2018-10-28 02:30:00 2018-10-28 02:30:00 1540690200
+6 2038-01-19 04:14:07 2038-01-19 04:14:07 2147483647
+
+DELETEs
+connection child2_1;
+TRUNCATE TABLE mysql.general_log;
+connection master_1;
+DELETE FROM tbl_a WHERE col_ts='1970-01-01 01:00:01';
+SELECT *, unix_timestamp(col_ts) FROM tbl_a;
+col_a col_dt col_ts unix_timestamp(col_ts)
+2 2018-03-25 02:00:00 2018-03-25 02:00:00 1521939600
+3 2018-03-25 02:30:00 2018-03-25 02:30:00 1521941400
+4 2018-10-28 01:30:00 2018-10-28 01:30:00 1540686600
+5 2018-10-28 02:30:00 2018-10-28 02:30:00 1540690200
+6 2038-01-19 04:14:07 2038-01-19 04:14:07 2147483647
+connection child2_1;
+SELECT argument FROM mysql.general_log WHERE argument LIKE '%select %';
+argument
+select `col_a`,`col_dt`,`col_ts` from `ts_test_remote`.`tbl_a`
+SELECT argument FROM mysql.general_log WHERE argument LIKE '%select %'
+SELECT col_a, col_dt, col_ts, unix_timestamp(col_ts) FROM tbl_a ORDER BY col_a;
+col_a col_dt col_ts unix_timestamp(col_ts)
+2 2018-03-25 02:00:00 2018-03-25 03:00:00 1521939600
+3 2018-03-25 02:30:00 2018-03-25 03:30:00 1521941400
+4 2018-10-28 01:30:00 2018-10-28 02:30:00 1540686600
+5 2018-10-28 02:30:00 2018-10-28 02:30:00 1540690200
+6 2038-01-19 04:14:07 2038-01-19 04:14:07 2147483647
+connection child2_1;
+TRUNCATE TABLE mysql.general_log;
+connection master_1;
+SET @@timestamp=1;
+INSERT INTO tbl_a VALUES (1, now(), now());
+SET @@timestamp=0;
+SELECT *, unix_timestamp(col_ts) FROM tbl_a;
+col_a col_dt col_ts unix_timestamp(col_ts)
+1 1970-01-01 01:00:01 1970-01-01 01:00:01 1
+2 2018-03-25 02:00:00 2018-03-25 02:00:00 1521939600
+3 2018-03-25 02:30:00 2018-03-25 02:30:00 1521941400
+4 2018-10-28 01:30:00 2018-10-28 01:30:00 1540686600
+5 2018-10-28 02:30:00 2018-10-28 02:30:00 1540690200
+6 2038-01-19 04:14:07 2038-01-19 04:14:07 2147483647
+connection child2_1;
+SELECT argument FROM mysql.general_log WHERE argument LIKE '%select %';
+argument
+select `col_a`,`col_dt`,`col_ts` from `ts_test_remote`.`tbl_a`
+SELECT argument FROM mysql.general_log WHERE argument LIKE '%select %'
+SELECT col_a, col_dt, col_ts, unix_timestamp(col_ts) FROM tbl_a ORDER BY col_a;
+col_a col_dt col_ts unix_timestamp(col_ts)
+1 1970-01-01 01:00:01 1970-01-01 01:00:01 1
+2 2018-03-25 02:00:00 2018-03-25 03:00:00 1521939600
+3 2018-03-25 02:30:00 2018-03-25 03:30:00 1521941400
+4 2018-10-28 01:30:00 2018-10-28 02:30:00 1540686600
+5 2018-10-28 02:30:00 2018-10-28 02:30:00 1540690200
+6 2038-01-19 04:14:07 2038-01-19 04:14:07 2147483647
+
+UPDATEs
+connection child2_1;
+TRUNCATE TABLE mysql.general_log;
+connection master_1;
+UPDATE tbl_a SET col_ts=col_dt;
+SELECT *, unix_timestamp(col_ts) FROM tbl_a;
+col_a col_dt col_ts unix_timestamp(col_ts)
+1 1970-01-01 01:00:01 1970-01-01 01:00:01 1
+2 2018-03-25 02:00:00 2018-03-25 02:00:00 1521939600
+3 2018-03-25 02:30:00 2018-03-25 02:30:00 1521941400
+4 2018-10-28 01:30:00 2018-10-28 01:30:00 1540686600
+5 2018-10-28 02:30:00 2018-10-28 02:30:00 1540690200
+6 2038-01-19 04:14:07 2038-01-19 04:14:07 2147483647
+connection child2_1;
+SELECT argument FROM mysql.general_log WHERE argument LIKE '%select %';
+argument
+select `col_a`,`col_dt`,`col_ts` from `ts_test_remote`.`tbl_a` for update
+select `col_a`,`col_dt`,`col_ts` from `ts_test_remote`.`tbl_a`
+SELECT argument FROM mysql.general_log WHERE argument LIKE '%select %'
+SELECT col_a, col_dt, col_ts, unix_timestamp(col_ts) FROM tbl_a ORDER BY col_a;
+col_a col_dt col_ts unix_timestamp(col_ts)
+1 1970-01-01 01:00:01 1970-01-01 01:00:01 1
+2 2018-03-25 02:00:00 2018-03-25 03:00:00 1521939600
+3 2018-03-25 02:30:00 2018-03-25 03:30:00 1521941400
+4 2018-10-28 01:30:00 2018-10-28 02:30:00 1540686600
+5 2018-10-28 02:30:00 2018-10-28 02:30:00 1540690200
+6 2038-01-19 04:14:07 2038-01-19 04:14:07 2147483647
+
+Lookups
+connection child2_1;
+TRUNCATE TABLE mysql.general_log;
+connection master_1;
+SELECT *, unix_timestamp(col_ts) FROM tbl_a WHERE col_ts > '2018-01-01';
+col_a col_dt col_ts unix_timestamp(col_ts)
+2 2018-03-25 02:00:00 2018-03-25 02:00:00 1521939600
+3 2018-03-25 02:30:00 2018-03-25 02:30:00 1521941400
+4 2018-10-28 01:30:00 2018-10-28 01:30:00 1540686600
+5 2018-10-28 02:30:00 2018-10-28 02:30:00 1540690200
+6 2038-01-19 04:14:07 2038-01-19 04:14:07 2147483647
+SELECT *, unix_timestamp(col_ts) FROM tbl_a WHERE col_ts < '2018-10-28 02:30:00';
+col_a col_dt col_ts unix_timestamp(col_ts)
+1 1970-01-01 01:00:01 1970-01-01 01:00:01 1
+2 2018-03-25 02:00:00 2018-03-25 02:00:00 1521939600
+3 2018-03-25 02:30:00 2018-03-25 02:30:00 1521941400
+4 2018-10-28 01:30:00 2018-10-28 01:30:00 1540686600
+SELECT *, unix_timestamp(col_ts) FROM tbl_a WHERE '2018-10-28 02:30:00' > col_ts;
+col_a col_dt col_ts unix_timestamp(col_ts)
+1 1970-01-01 01:00:01 1970-01-01 01:00:01 1
+2 2018-03-25 02:00:00 2018-03-25 02:00:00 1521939600
+3 2018-03-25 02:30:00 2018-03-25 02:30:00 1521941400
+4 2018-10-28 01:30:00 2018-10-28 01:30:00 1540686600
+SELECT *, unix_timestamp(col_ts) FROM tbl_a WHERE col_ts BETWEEN '2018-10-28 01:30:00' AND '2018-10-28 02:30:00';
+col_a col_dt col_ts unix_timestamp(col_ts)
+4 2018-10-28 01:30:00 2018-10-28 01:30:00 1540686600
+5 2018-10-28 02:30:00 2018-10-28 02:30:00 1540690200
+SELECT *, unix_timestamp(col_ts) FROM tbl_a WHERE col_ts >= '2018-10-28 01:30:00' AND col_ts <= '2018-10-28 02:30:00';
+col_a col_dt col_ts unix_timestamp(col_ts)
+4 2018-10-28 01:30:00 2018-10-28 01:30:00 1540686600
+5 2018-10-28 02:30:00 2018-10-28 02:30:00 1540690200
+SELECT *, unix_timestamp(col_ts) FROM tbl_a WHERE col_ts > 180325020000;
+col_a col_dt col_ts unix_timestamp(col_ts)
+3 2018-03-25 02:30:00 2018-03-25 02:30:00 1521941400
+4 2018-10-28 01:30:00 2018-10-28 01:30:00 1540686600
+5 2018-10-28 02:30:00 2018-10-28 02:30:00 1540690200
+6 2038-01-19 04:14:07 2038-01-19 04:14:07 2147483647
+SELECT *, unix_timestamp(col_ts) FROM tbl_a WHERE col_ts > 19700101010001;
+col_a col_dt col_ts unix_timestamp(col_ts)
+2 2018-03-25 02:00:00 2018-03-25 02:00:00 1521939600
+3 2018-03-25 02:30:00 2018-03-25 02:30:00 1521941400
+4 2018-10-28 01:30:00 2018-10-28 01:30:00 1540686600
+5 2018-10-28 02:30:00 2018-10-28 02:30:00 1540690200
+6 2038-01-19 04:14:07 2038-01-19 04:14:07 2147483647
+connection child2_1;
+SELECT argument FROM mysql.general_log WHERE argument LIKE '%select %';
+argument
+select `col_a`,`col_dt`,`col_ts` from `ts_test_remote`.`tbl_a` where (`col_ts` > '2017-12-31 23:00:00') order by `col_ts`
+select `col_a`,`col_dt`,`col_ts` from `ts_test_remote`.`tbl_a` where (`col_ts` < '2018-10-28 01:30:00') order by `col_ts`
+select `col_a`,`col_dt`,`col_ts` from `ts_test_remote`.`tbl_a` where ('2018-10-28 01:30:00' > `col_ts`) order by `col_ts`
+select `col_a`,`col_dt`,`col_ts` from `ts_test_remote`.`tbl_a` where `col_ts` >= '2018-10-28 00:30:00' and `col_ts` <= '2018-10-28 01:30:00' and (`col_ts` between '2018-10-28 00:30:00' and '2018-10-28 01:30:00') order by `col_ts`
+select `col_a`,`col_dt`,`col_ts` from `ts_test_remote`.`tbl_a` where `col_ts` >= '2018-10-28 00:30:00' and `col_ts` <= '2018-10-28 01:30:00' and ((`col_ts` >= '2018-10-28 00:30:00') and (`col_ts` <= '2018-10-28 01:30:00')) order by `col_ts`
+select `col_a`,`col_dt`,`col_ts` from `ts_test_remote`.`tbl_a` where (`col_ts` > '2018-03-25 01:00:00') order by `col_ts`
+select `col_a`,`col_dt`,`col_ts` from `ts_test_remote`.`tbl_a` where (`col_ts` > '1970-01-01 00:00:01') order by `col_ts`
+SELECT argument FROM mysql.general_log WHERE argument LIKE '%select %'
+SELECT col_a, col_dt, col_ts, unix_timestamp(col_ts) FROM tbl_a ORDER BY col_a;
+col_a col_dt col_ts unix_timestamp(col_ts)
+1 1970-01-01 01:00:01 1970-01-01 01:00:01 1
+2 2018-03-25 02:00:00 2018-03-25 03:00:00 1521939600
+3 2018-03-25 02:30:00 2018-03-25 03:30:00 1521941400
+4 2018-10-28 01:30:00 2018-10-28 02:30:00 1540686600
+5 2018-10-28 02:30:00 2018-10-28 02:30:00 1540690200
+6 2038-01-19 04:14:07 2038-01-19 04:14:07 2147483647
+
+Drop the index on the timestamp column
+connection child2_1;
+DROP INDEX i_ts ON tbl_a;
+SHOW CREATE TABLE tbl_a;
+Table Create Table
+tbl_a CREATE TABLE `tbl_a` (
+ `col_a` int(10) unsigned NOT NULL AUTO_INCREMENT,
+ `col_dt` datetime DEFAULT NULL,
+ `col_ts` timestamp NOT NULL DEFAULT current_timestamp() ON UPDATE current_timestamp(),
+ PRIMARY KEY (`col_a`)
+) ENGINE=InnoDB AUTO_INCREMENT=17 DEFAULT CHARSET=utf8mb4
+TRUNCATE TABLE mysql.general_log;
+connection master_1;
+DROP INDEX i_ts ON tbl_a;
+SHOW CREATE TABLE tbl_a;
+Table Create Table
+tbl_a CREATE TABLE `tbl_a` (
+ `col_a` int(10) unsigned NOT NULL AUTO_INCREMENT,
+ `col_dt` datetime DEFAULT NULL,
+ `col_ts` timestamp NOT NULL DEFAULT current_timestamp() ON UPDATE current_timestamp(),
+ PRIMARY KEY (`col_a`)
+) ENGINE=SPIDER AUTO_INCREMENT=17 DEFAULT CHARSET=utf8mb4 COMMENT='database "ts_test_remote", table "tbl_a", srv "s_2_1"'
+
+Retry lookups on unindexed timestamp column
+connection child2_1;
+TRUNCATE TABLE mysql.general_log;
+connection master_1;
+SELECT *, unix_timestamp(col_ts) FROM tbl_a WHERE col_ts > '2018-01-01';
+col_a col_dt col_ts unix_timestamp(col_ts)
+2 2018-03-25 02:00:00 2018-03-25 02:00:00 1521939600
+3 2018-03-25 02:30:00 2018-03-25 02:30:00 1521941400
+4 2018-10-28 01:30:00 2018-10-28 01:30:00 1540686600
+5 2018-10-28 02:30:00 2018-10-28 02:30:00 1540690200
+6 2038-01-19 04:14:07 2038-01-19 04:14:07 2147483647
+SELECT *, unix_timestamp(col_ts) FROM tbl_a WHERE col_ts < '2018-10-28 02:30:00';
+col_a col_dt col_ts unix_timestamp(col_ts)
+1 1970-01-01 01:00:01 1970-01-01 01:00:01 1
+2 2018-03-25 02:00:00 2018-03-25 02:00:00 1521939600
+3 2018-03-25 02:30:00 2018-03-25 02:30:00 1521941400
+4 2018-10-28 01:30:00 2018-10-28 01:30:00 1540686600
+SELECT *, unix_timestamp(col_ts) FROM tbl_a WHERE '2018-10-28 02:30:00' > col_ts;
+col_a col_dt col_ts unix_timestamp(col_ts)
+1 1970-01-01 01:00:01 1970-01-01 01:00:01 1
+2 2018-03-25 02:00:00 2018-03-25 02:00:00 1521939600
+3 2018-03-25 02:30:00 2018-03-25 02:30:00 1521941400
+4 2018-10-28 01:30:00 2018-10-28 01:30:00 1540686600
+SELECT *, unix_timestamp(col_ts) FROM tbl_a WHERE col_ts BETWEEN '2018-10-28 01:30:00' AND '2018-10-28 02:30:00';
+col_a col_dt col_ts unix_timestamp(col_ts)
+4 2018-10-28 01:30:00 2018-10-28 01:30:00 1540686600
+5 2018-10-28 02:30:00 2018-10-28 02:30:00 1540690200
+SELECT *, unix_timestamp(col_ts) FROM tbl_a WHERE col_ts >= '2018-10-28 01:30:00' AND col_ts <= '2018-10-28 02:30:00';
+col_a col_dt col_ts unix_timestamp(col_ts)
+4 2018-10-28 01:30:00 2018-10-28 01:30:00 1540686600
+5 2018-10-28 02:30:00 2018-10-28 02:30:00 1540690200
+SELECT *, unix_timestamp(col_ts) FROM tbl_a WHERE col_ts > 180325020000;
+col_a col_dt col_ts unix_timestamp(col_ts)
+3 2018-03-25 02:30:00 2018-03-25 02:30:00 1521941400
+4 2018-10-28 01:30:00 2018-10-28 01:30:00 1540686600
+5 2018-10-28 02:30:00 2018-10-28 02:30:00 1540690200
+6 2038-01-19 04:14:07 2038-01-19 04:14:07 2147483647
+SELECT *, unix_timestamp(col_ts) FROM tbl_a WHERE col_ts > 19700101010001;
+col_a col_dt col_ts unix_timestamp(col_ts)
+2 2018-03-25 02:00:00 2018-03-25 02:00:00 1521939600
+3 2018-03-25 02:30:00 2018-03-25 02:30:00 1521941400
+4 2018-10-28 01:30:00 2018-10-28 01:30:00 1540686600
+5 2018-10-28 02:30:00 2018-10-28 02:30:00 1540690200
+6 2038-01-19 04:14:07 2038-01-19 04:14:07 2147483647
+connection child2_1;
+SELECT argument FROM mysql.general_log WHERE argument LIKE '%select %';
+argument
+select `col_a`,`col_dt`,`col_ts` from `ts_test_remote`.`tbl_a` where (`col_ts` > '2017-12-31 23:00:00')
+select `col_a`,`col_dt`,`col_ts` from `ts_test_remote`.`tbl_a` where (`col_ts` < '2018-10-28 01:30:00')
+select `col_a`,`col_dt`,`col_ts` from `ts_test_remote`.`tbl_a` where ('2018-10-28 01:30:00' > `col_ts`)
+select `col_a`,`col_dt`,`col_ts` from `ts_test_remote`.`tbl_a` where (`col_ts` between '2018-10-28 00:30:00' and '2018-10-28 01:30:00')
+select `col_a`,`col_dt`,`col_ts` from `ts_test_remote`.`tbl_a` where ((`col_ts` >= '2018-10-28 00:30:00') and (`col_ts` <= '2018-10-28 01:30:00'))
+select `col_a`,`col_dt`,`col_ts` from `ts_test_remote`.`tbl_a` where (`col_ts` > '2018-03-25 01:00:00')
+select `col_a`,`col_dt`,`col_ts` from `ts_test_remote`.`tbl_a` where (`col_ts` > '1970-01-01 00:00:01')
+SELECT argument FROM mysql.general_log WHERE argument LIKE '%select %'
+SELECT col_a, col_dt, col_ts, unix_timestamp(col_ts) FROM tbl_a ORDER BY col_a;
+col_a col_dt col_ts unix_timestamp(col_ts)
+1 1970-01-01 01:00:01 1970-01-01 01:00:01 1
+2 2018-03-25 02:00:00 2018-03-25 03:00:00 1521939600
+3 2018-03-25 02:30:00 2018-03-25 03:30:00 1521941400
+4 2018-10-28 01:30:00 2018-10-28 02:30:00 1540686600
+5 2018-10-28 02:30:00 2018-10-28 02:30:00 1540690200
+6 2038-01-19 04:14:07 2038-01-19 04:14:07 2147483647
+
+Restore Time Zone settings
+connection master_1;
+SET GLOBAL time_zone=DEFAULT;
+SET time_zone=DEFAULT;
+connection child2_1;
+SET GLOBAL time_zone=DEFAULT;
+SET time_zone=DEFAULT;
+
+deinit
+connection master_1;
+DROP DATABASE IF EXISTS ts_test_local;
+connection child2_1;
+DROP DATABASE IF EXISTS ts_test_remote;
+SET GLOBAL log_output = @old_log_output;
+for master_1
+for child2
+child2_1
+child2_2
+child2_3
+for child3
+child3_1
+child3_2
+child3_3
+
+end of test
diff --git a/storage/spider/mysql-test/spider/t/timestamp.test b/storage/spider/mysql-test/spider/t/timestamp.test
new file mode 100644
index 00000000000..7008638cc4a
--- /dev/null
+++ b/storage/spider/mysql-test/spider/t/timestamp.test
@@ -0,0 +1,465 @@
+--source timestamp_init.inc
+
+--echo
+--echo Initialize Time Zone
+--connection master_1
+SET GLOBAL time_zone='MET';
+SET time_zone='MET';
+if ($USE_CHILD_GROUP2)
+{
+ --connection child2_1
+ SET GLOBAL time_zone='MET';
+ SET time_zone='MET';
+}
+
+--echo
+--echo drop and create databases
+--connection master_1
+--disable_warnings
+DROP DATABASE IF EXISTS ts_test_local;
+CREATE DATABASE ts_test_local;
+USE ts_test_local;
+if ($USE_CHILD_GROUP2)
+{
+ --connection child2_1
+ if ($USE_GENERAL_LOG)
+ {
+ SET @old_log_output = @@global.log_output;
+ SET GLOBAL log_output = 'TABLE,FILE';
+ }
+ DROP DATABASE IF EXISTS ts_test_remote;
+ CREATE DATABASE ts_test_remote;
+ USE ts_test_remote;
+}
+--enable_warnings
+
+--echo
+--echo test select 1
+--connection master_1
+SELECT 1;
+if ($USE_CHILD_GROUP2)
+{
+ if (!$OUTPUT_CHILD_GROUP2)
+ {
+ --disable_query_log
+ --disable_result_log
+ }
+ --connection child2_1
+ SELECT 1;
+ if (!$OUTPUT_CHILD_GROUP2)
+ {
+ --enable_query_log
+ --enable_result_log
+ }
+}
+
+--echo
+--echo create table
+if ($USE_CHILD_GROUP2)
+{
+ if (!$OUTPUT_CHILD_GROUP2)
+ {
+ --disable_query_log
+ --disable_result_log
+ }
+ --connection child2_1
+ if ($OUTPUT_CHILD_GROUP2)
+ {
+ --disable_query_log
+ echo CHILD2_1_DROP_TABLES;
+ echo CHILD2_1_CREATE_TABLES;
+ }
+ --disable_warnings
+ eval $CHILD2_1_DROP_TABLES;
+ --enable_warnings
+ eval $CHILD2_1_CREATE_TABLES;
+ if ($OUTPUT_CHILD_GROUP2)
+ {
+ --enable_query_log
+ }
+ if ($USE_GENERAL_LOG)
+ {
+ TRUNCATE TABLE mysql.general_log;
+ }
+ if (!$OUTPUT_CHILD_GROUP2)
+ {
+ --enable_query_log
+ --enable_result_log
+ }
+}
+--connection master_1
+--disable_warnings
+DROP TABLE IF EXISTS tbl_a;
+--enable_warnings
+--disable_query_log
+echo CREATE TABLE tbl_a (
+ col_a INT UNSIGNED NOT NULL AUTO_INCREMENT,
+ col_dt DATETIME,
+ col_ts TIMESTAMP NOT NULL
+ DEFAULT current_timestamp() ON UPDATE current_timestamp(),
+ PRIMARY KEY(col_a),
+
+) MASTER_1_ENGINE MASTER_1_AUTO_INCREMENT_2_1 MASTER_1_COMMENT_2_1;
+eval CREATE TABLE tbl_a (
+ col_a INT UNSIGNED NOT NULL AUTO_INCREMENT,
+ col_dt DATETIME,
+ col_ts TIMESTAMP NOT NULL
+ DEFAULT current_timestamp() ON UPDATE current_timestamp(),
+ PRIMARY KEY(col_a),
+ UNIQUE INDEX i_ts (col_ts)
+) $MASTER_1_ENGINE $MASTER_1_AUTO_INCREMENT_2_1 $MASTER_1_COMMENT_2_1;
+--enable_query_log
+SHOW CREATE TABLE tbl_a;
+
+--echo
+--echo Set a different time zone that has DST
+SET time_zone='+01:00';
+
+--echo
+--echo Insert Rows
+--connection master_1
+--echo Min value
+SET @@timestamp=1;
+INSERT INTO tbl_a VALUES (1, now(), now());
+SET @@timestamp=0;
+--echo Ambiguous DST values for MET time zone that result in the
+--echo same UTC timestamp
+INSERT INTO tbl_a VALUES (2, '2018-03-25 02:00:00', '2018-03-25 02:00:00');
+INSERT INTO tbl_a VALUES (3, '2018-03-25 02:30:00', '2018-03-25 02:30:00');
+--echo Ambiguous DST values for MET time zone in the 2:00 am to 3:00 am hour
+--echo that occur twice when transitioning from DST to standard time
+SET @@timestamp=1540686600;
+INSERT INTO tbl_a VALUES (4, now(), now());
+SET @@timestamp=1540690200;
+INSERT INTO tbl_a VALUES (5, now(), now());
+--echo Max value
+SET @@timestamp=2147483647;
+INSERT INTO tbl_a VALUES (6, now(), now());
+SET @@timestamp=0;
+
+--echo
+--echo SELECTs
+if ($USE_CHILD_GROUP2)
+{
+ if (!$OUTPUT_CHILD_GROUP2)
+ {
+ --disable_query_log
+ --disable_result_log
+ }
+ --connection child2_1
+ if ($USE_GENERAL_LOG)
+ {
+ TRUNCATE TABLE mysql.general_log;
+ }
+ if (!$OUTPUT_CHILD_GROUP2)
+ {
+ --enable_query_log
+ --enable_result_log
+ }
+}
+--connection master_1
+SELECT *, unix_timestamp(col_ts) FROM tbl_a;
+if ($USE_CHILD_GROUP2)
+{
+ if (!$OUTPUT_CHILD_GROUP2)
+ {
+ --disable_query_log
+ --disable_result_log
+ }
+ --connection child2_1
+ if ($USE_GENERAL_LOG)
+ {
+ eval $CHILD2_1_SELECT_ARGUMENT1;
+ }
+ eval $CHILD2_1_SELECT_TABLES;
+ if (!$OUTPUT_CHILD_GROUP2)
+ {
+ --enable_query_log
+ --enable_result_log
+ }
+}
+
+--echo
+--echo DELETEs
+if ($USE_CHILD_GROUP2)
+{
+ if (!$OUTPUT_CHILD_GROUP2)
+ {
+ --disable_query_log
+ --disable_result_log
+ }
+ --connection child2_1
+ if ($USE_GENERAL_LOG)
+ {
+ TRUNCATE TABLE mysql.general_log;
+ }
+ if (!$OUTPUT_CHILD_GROUP2)
+ {
+ --enable_query_log
+ --enable_result_log
+ }
+}
+--connection master_1
+DELETE FROM tbl_a WHERE col_ts='1970-01-01 01:00:01';
+SELECT *, unix_timestamp(col_ts) FROM tbl_a;
+if ($USE_CHILD_GROUP2)
+{
+ if (!$OUTPUT_CHILD_GROUP2)
+ {
+ --disable_query_log
+ --disable_result_log
+ }
+ --connection child2_1
+ if ($USE_GENERAL_LOG)
+ {
+ eval $CHILD2_1_SELECT_ARGUMENT1;
+ }
+ eval $CHILD2_1_SELECT_TABLES;
+ if (!$OUTPUT_CHILD_GROUP2)
+ {
+ --enable_query_log
+ --enable_result_log
+ }
+}
+if ($USE_CHILD_GROUP2)
+{
+ if (!$OUTPUT_CHILD_GROUP2)
+ {
+ --disable_query_log
+ --disable_result_log
+ }
+ --connection child2_1
+ if ($USE_GENERAL_LOG)
+ {
+ TRUNCATE TABLE mysql.general_log;
+ }
+ if (!$OUTPUT_CHILD_GROUP2)
+ {
+ --enable_query_log
+ --enable_result_log
+ }
+}
+--connection master_1
+SET @@timestamp=1;
+INSERT INTO tbl_a VALUES (1, now(), now());
+SET @@timestamp=0;
+SELECT *, unix_timestamp(col_ts) FROM tbl_a;
+if ($USE_CHILD_GROUP2)
+{
+ if (!$OUTPUT_CHILD_GROUP2)
+ {
+ --disable_query_log
+ --disable_result_log
+ }
+ --connection child2_1
+ if ($USE_GENERAL_LOG)
+ {
+ eval $CHILD2_1_SELECT_ARGUMENT1;
+ }
+ eval $CHILD2_1_SELECT_TABLES;
+ if (!$OUTPUT_CHILD_GROUP2)
+ {
+ --enable_query_log
+ --enable_result_log
+ }
+}
+
+--echo
+--echo UPDATEs
+if ($USE_CHILD_GROUP2)
+{
+ if (!$OUTPUT_CHILD_GROUP2)
+ {
+ --disable_query_log
+ --disable_result_log
+ }
+ --connection child2_1
+ if ($USE_GENERAL_LOG)
+ {
+ TRUNCATE TABLE mysql.general_log;
+ }
+ if (!$OUTPUT_CHILD_GROUP2)
+ {
+ --enable_query_log
+ --enable_result_log
+ }
+}
+--connection master_1
+UPDATE tbl_a SET col_ts=col_dt;
+SELECT *, unix_timestamp(col_ts) FROM tbl_a;
+if ($USE_CHILD_GROUP2)
+{
+ if (!$OUTPUT_CHILD_GROUP2)
+ {
+ --disable_query_log
+ --disable_result_log
+ }
+ --connection child2_1
+ if ($USE_GENERAL_LOG)
+ {
+ eval $CHILD2_1_SELECT_ARGUMENT1;
+ }
+ eval $CHILD2_1_SELECT_TABLES;
+ if (!$OUTPUT_CHILD_GROUP2)
+ {
+ --enable_query_log
+ --enable_result_log
+ }
+}
+
+--echo
+--echo Lookups
+if ($USE_CHILD_GROUP2)
+{
+ if (!$OUTPUT_CHILD_GROUP2)
+ {
+ --disable_query_log
+ --disable_result_log
+ }
+ --connection child2_1
+ if ($USE_GENERAL_LOG)
+ {
+ TRUNCATE TABLE mysql.general_log;
+ }
+ if (!$OUTPUT_CHILD_GROUP2)
+ {
+ --enable_query_log
+ --enable_result_log
+ }
+}
+--connection master_1
+SELECT *, unix_timestamp(col_ts) FROM tbl_a WHERE col_ts > '2018-01-01';
+SELECT *, unix_timestamp(col_ts) FROM tbl_a WHERE col_ts < '2018-10-28 02:30:00';
+SELECT *, unix_timestamp(col_ts) FROM tbl_a WHERE '2018-10-28 02:30:00' > col_ts;
+SELECT *, unix_timestamp(col_ts) FROM tbl_a WHERE col_ts BETWEEN '2018-10-28 01:30:00' AND '2018-10-28 02:30:00';
+SELECT *, unix_timestamp(col_ts) FROM tbl_a WHERE col_ts >= '2018-10-28 01:30:00' AND col_ts <= '2018-10-28 02:30:00';
+SELECT *, unix_timestamp(col_ts) FROM tbl_a WHERE col_ts > 180325020000;
+SELECT *, unix_timestamp(col_ts) FROM tbl_a WHERE col_ts > 19700101010001;
+if ($USE_CHILD_GROUP2)
+{
+ if (!$OUTPUT_CHILD_GROUP2)
+ {
+ --disable_query_log
+ --disable_result_log
+ }
+ --connection child2_1
+ if ($USE_GENERAL_LOG)
+ {
+ eval $CHILD2_1_SELECT_ARGUMENT1;
+ }
+ eval $CHILD2_1_SELECT_TABLES;
+ if (!$OUTPUT_CHILD_GROUP2)
+ {
+ --enable_query_log
+ --enable_result_log
+ }
+}
+
+--echo
+--echo Drop the index on the timestamp column
+if ($USE_CHILD_GROUP2)
+{
+ if (!$OUTPUT_CHILD_GROUP2)
+ {
+ --disable_query_log
+ --disable_result_log
+ }
+ --connection child2_1
+ eval $CHILD2_1_DROP_INDEX;
+ eval $CHILD2_1_SHOW_CREATE_TABLE;
+ if ($OUTPUT_CHILD_GROUP2)
+ {
+ --enable_query_log
+ }
+ if ($USE_GENERAL_LOG)
+ {
+ TRUNCATE TABLE mysql.general_log;
+ }
+ if (!$OUTPUT_CHILD_GROUP2)
+ {
+ --enable_query_log
+ --enable_result_log
+ }
+}
+--connection master_1
+DROP INDEX i_ts ON tbl_a;
+SHOW CREATE TABLE tbl_a;
+
+--echo
+--echo Retry lookups on unindexed timestamp column
+if ($USE_CHILD_GROUP2)
+{
+ if (!$OUTPUT_CHILD_GROUP2)
+ {
+ --disable_query_log
+ --disable_result_log
+ }
+ --connection child2_1
+ if ($USE_GENERAL_LOG)
+ {
+ TRUNCATE TABLE mysql.general_log;
+ }
+ if (!$OUTPUT_CHILD_GROUP2)
+ {
+ --enable_query_log
+ --enable_result_log
+ }
+}
+--connection master_1
+SELECT *, unix_timestamp(col_ts) FROM tbl_a WHERE col_ts > '2018-01-01';
+SELECT *, unix_timestamp(col_ts) FROM tbl_a WHERE col_ts < '2018-10-28 02:30:00';
+SELECT *, unix_timestamp(col_ts) FROM tbl_a WHERE '2018-10-28 02:30:00' > col_ts;
+SELECT *, unix_timestamp(col_ts) FROM tbl_a WHERE col_ts BETWEEN '2018-10-28 01:30:00' AND '2018-10-28 02:30:00';
+SELECT *, unix_timestamp(col_ts) FROM tbl_a WHERE col_ts >= '2018-10-28 01:30:00' AND col_ts <= '2018-10-28 02:30:00';
+SELECT *, unix_timestamp(col_ts) FROM tbl_a WHERE col_ts > 180325020000;
+SELECT *, unix_timestamp(col_ts) FROM tbl_a WHERE col_ts > 19700101010001;
+if ($USE_CHILD_GROUP2)
+{
+ if (!$OUTPUT_CHILD_GROUP2)
+ {
+ --disable_query_log
+ --disable_result_log
+ }
+ --connection child2_1
+ if ($USE_GENERAL_LOG)
+ {
+ eval $CHILD2_1_SELECT_ARGUMENT1;
+ }
+ eval $CHILD2_1_SELECT_TABLES;
+ if (!$OUTPUT_CHILD_GROUP2)
+ {
+ --enable_query_log
+ --enable_result_log
+ }
+}
+
+--echo
+--echo Restore Time Zone settings
+--connection master_1
+SET GLOBAL time_zone=DEFAULT;
+SET time_zone=DEFAULT;
+if ($USE_CHILD_GROUP2)
+{
+ --connection child2_1
+ SET GLOBAL time_zone=DEFAULT;
+ SET time_zone=DEFAULT;
+}
+
+--echo
+--echo deinit
+--disable_warnings
+--connection master_1
+DROP DATABASE IF EXISTS ts_test_local;
+if ($USE_CHILD_GROUP2)
+{
+ --connection child2_1
+ DROP DATABASE IF EXISTS ts_test_remote;
+ if ($USE_GENERAL_LOG)
+ {
+ SET GLOBAL log_output = @old_log_output;
+ }
+}
+--enable_warnings
+--source timestamp_deinit.inc
+--echo
+--echo end of test
diff --git a/storage/spider/mysql-test/spider/t/timestamp_deinit.inc b/storage/spider/mysql-test/spider/t/timestamp_deinit.inc
new file mode 100644
index 00000000000..52be67a1d09
--- /dev/null
+++ b/storage/spider/mysql-test/spider/t/timestamp_deinit.inc
@@ -0,0 +1,13 @@
+--let $MASTER_1_COMMENT_2_1= $MASTER_1_COMMENT_2_1_BACKUP
+--let $CHILD2_1_DROP_TABLES= $CHILD2_1_DROP_TABLES_BACKUP
+--let $CHILD2_1_CREATE_TABLES= $CHILD2_1_CREATE_TABLES_BACKUP
+--let $CHILD2_1_SELECT_TABLES= $CHILD2_1_SELECT_TABLES_BACKUP
+--let $OUTPUT_CHILD_GROUP2= $OUTPUT_CHILD_GROUP2_BACKUP
+--let $USE_GENERAL_LOG= $USE_GENERAL_LOG_BACKUP
+--disable_warnings
+--disable_query_log
+--disable_result_log
+--source ../t/test_deinit.inc
+--enable_result_log
+--enable_query_log
+--enable_warnings
diff --git a/storage/spider/mysql-test/spider/t/timestamp_init.inc b/storage/spider/mysql-test/spider/t/timestamp_init.inc
new file mode 100644
index 00000000000..12049ab34fa
--- /dev/null
+++ b/storage/spider/mysql-test/spider/t/timestamp_init.inc
@@ -0,0 +1,45 @@
+--disable_warnings
+--disable_query_log
+--disable_result_log
+--source ../t/test_init.inc
+--enable_result_log
+--enable_query_log
+--enable_warnings
+
+--let $MASTER_1_COMMENT_2_1_BACKUP= $MASTER_1_COMMENT_2_1
+let $MASTER_1_COMMENT_2_1=
+ COMMENT='database "ts_test_remote", table "tbl_a", srv "s_2_1"';
+let $MASTER_1_AUTO_INCREMENT_2_1=
+ AUTO_INCREMENT=17 DEFAULT CHARSET=utf8mb4;
+let $MASTER_1_AUTO_INCREMENT1=
+ AUTO_INCREMENT=17 DEFAULT CHARSET=utf8mb4;
+let $MASTER_1_AUTO_INCREMENT2=
+ AUTO_INCREMENT=17 DEFAULT CHARSET=utf8mb4;
+let $CHILD2_1_AUTO_INCREMENT=
+ AUTO_INCREMENT=17 DEFAULT CHARSET=utf8mb4;
+--let $CHILD2_1_DROP_TABLES_BACKUP= $CHILD2_1_DROP_TABLES
+let $CHILD2_1_DROP_TABLES=
+ DROP TABLE IF EXISTS tbl_a;
+--let $CHILD2_1_CREATE_TABLES_BACKUP= $CHILD2_1_CREATE_TABLES
+let $CHILD2_1_CREATE_TABLES=
+ CREATE TABLE tbl_a (
+ col_a INT UNSIGNED NOT NULL AUTO_INCREMENT,
+ col_dt DATETIME,
+ col_ts TIMESTAMP NOT NULL
+ DEFAULT current_timestamp() ON UPDATE current_timestamp(),
+ PRIMARY KEY(col_a),
+ UNIQUE INDEX i_ts (col_ts)
+ ) $CHILD2_1_ENGINE $CHILD2_1_AUTO_INCREMENT;
+--let $CHILD2_1_SELECT_TABLES_BACKUP= $CHILD2_1_SELECT_TABLES
+let $CHILD2_1_SELECT_TABLES=
+ SELECT col_a, col_dt, col_ts, unix_timestamp(col_ts) FROM tbl_a ORDER BY col_a;
+let $CHILD2_1_SELECT_ARGUMENT1=
+ SELECT argument FROM mysql.general_log WHERE argument LIKE '%select %';
+let $CHILD2_1_DROP_INDEX=
+ DROP INDEX i_ts ON tbl_a;
+let $CHILD2_1_SHOW_CREATE_TABLE=
+ SHOW CREATE TABLE tbl_a;
+--let $OUTPUT_CHILD_GROUP2_BACKUP= $OUTPUT_CHILD_GROUP2
+--let $OUTPUT_CHILD_GROUP2= 1
+--let $USE_GENERAL_LOG_BACKUP= $USE_GENERAL_LOG
+--let $USE_GENERAL_LOG= 1
diff --git a/storage/spider/spd_conn.cc b/storage/spider/spd_conn.cc
index 0ca7555385c..148ad43d337 100644
--- a/storage/spider/spd_conn.cc
+++ b/storage/spider/spd_conn.cc
@@ -88,6 +88,9 @@ extern PSI_thread_key spd_key_thd_bg_mon;
#endif
#endif
+/* UTC time zone for timestamp columns */
+extern Time_zone *UTC;
+
HASH spider_open_connections;
uint spider_open_connections_id;
HASH spider_ipport_conns;
@@ -454,6 +457,13 @@ SPIDER_CONN *spider_create_conn(
char *tmp_ssl_cipher, *tmp_ssl_key, *tmp_default_file, *tmp_default_group;
DBUG_ENTER("spider_create_conn");
+ if (unlikely(!UTC))
+ {
+ /* UTC time zone for timestamp columns */
+ String tz_00_name(STRING_WITH_LEN("+00:00"), &my_charset_bin);
+ UTC = my_tz_find(current_thd, &tz_00_name);
+ }
+
#if defined(HS_HAS_SQLCOM) && defined(HAVE_HANDLERSOCKET)
if (conn_kind == SPIDER_CONN_KIND_MYSQL)
{
@@ -1429,6 +1439,14 @@ void spider_conn_queue_time_zone(
DBUG_VOID_RETURN;
}
+void spider_conn_queue_UTC_time_zone(SPIDER_CONN *conn)
+{
+ DBUG_ENTER("spider_conn_queue_time_zone");
+ DBUG_PRINT("info", ("spider conn=%p", conn));
+ spider_conn_queue_time_zone(conn, UTC);
+ DBUG_VOID_RETURN;
+}
+
void spider_conn_queue_start_transaction(
SPIDER_CONN *conn
) {
diff --git a/storage/spider/spd_conn.h b/storage/spider/spd_conn.h
index 48c9d206d97..998658c5353 100644
--- a/storage/spider/spd_conn.h
+++ b/storage/spider/spd_conn.h
@@ -13,6 +13,8 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+#include "tztime.h"
+
#define SPIDER_LOCK_MODE_NO_LOCK 0
#define SPIDER_LOCK_MODE_SHARED 1
#define SPIDER_LOCK_MODE_EXCLUSIVE 2
@@ -137,6 +139,10 @@ void spider_conn_queue_time_zone(
Time_zone *time_zone
);
+void spider_conn_queue_UTC_time_zone(
+ SPIDER_CONN *conn
+);
+
void spider_conn_queue_start_transaction(
SPIDER_CONN *conn
);
diff --git a/storage/spider/spd_db_conn.cc b/storage/spider/spd_db_conn.cc
index 83de99e0d2f..ac5701a8274 100644
--- a/storage/spider/spd_db_conn.cc
+++ b/storage/spider/spd_db_conn.cc
@@ -76,6 +76,9 @@ extern HASH spider_open_connections;
pthread_mutex_t spider_open_conn_mutex;
const char spider_dig_upper[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
+/* UTC time zone for timestamp columns */
+extern Time_zone *UTC;
+
int spider_db_connect(
const SPIDER_SHARE *share,
SPIDER_CONN *conn,
@@ -191,10 +194,14 @@ int spider_db_connect(
}
DBUG_RETURN(error_num);
}
+
conn->connect_error = 0;
conn->opened_handlers = 0;
conn->db_conn->reset_opened_handler();
++conn->connection_id;
+
+ /* Set the connection's time zone to UTC */
+ spider_conn_queue_UTC_time_zone(conn);
DBUG_RETURN(0);
}
@@ -2866,12 +2873,20 @@ int spider_db_fetch_row(
my_ptrdiff_t ptr_diff
) {
int error_num;
+ THD *thd = field->table->in_use;
+ Time_zone *saved_time_zone = thd->variables.time_zone;
DBUG_ENTER("spider_db_fetch_row");
DBUG_PRINT("info", ("spider field_name %s", field->field_name.str));
DBUG_PRINT("info", ("spider fieldcharset %s", field->charset()->csname));
+
+ thd->variables.time_zone = UTC;
+
field->move_field_offset(ptr_diff);
error_num = row->store_to_field(field, share->access_charset);
field->move_field_offset(-ptr_diff);
+
+ thd->variables.time_zone = saved_time_zone;
+
DBUG_RETURN(error_num);
}
@@ -8449,18 +8464,80 @@ int spider_db_flush_logs(
DBUG_RETURN(0);
}
-int spider_db_print_item_type(
- Item *item,
- ha_spider *spider,
- spider_string *str,
- const char *alias,
- uint alias_length,
- uint dbton_id,
- bool use_fields,
- spider_fields *fields
-) {
+/**
+ Find the field among the items in an expression tree.
+
+ @param item_list List of items of the expression.
+ @param item_count Number of items in the item list.
+ @param start_item Index of the first item to consider.
+ @param str String into which the expression is to be printed.
+ @param func_name Function or operator name.
+ @param func_name_length Length of function or operator name.
+
+ @return Pointer to the field in the item list if the list
+ contains only one field; NULL otherwise.
+*/
+
+Field *spider_db_find_field_in_item_list(Item **item_list, uint item_count,
+ uint start_item, spider_string *str,
+ const char *func_name,
+ int func_name_length)
+{
+ uint item_num;
+ Item *item;
+ Field *field = NULL;
+ DBUG_ENTER("spider_db_find_field_in_item_list");
+
+ if (str && func_name_length)
+ {
+ if (strncasecmp(func_name, ",", 1))
+ {
+ /* A known function or operator */
+ for (item_num = start_item; item_num < item_count; item_num++)
+ {
+ item = item_list[item_num];
+
+ if (item->type() == Item::FIELD_ITEM)
+ {
+ if (field)
+ {
+ /* Field is not relevant if there are multiple fields */
+ DBUG_RETURN(NULL);
+ }
+
+ field = ((Item_field *) item)->field;
+ }
+ }
+ }
+ }
+
+ DBUG_RETURN(field);
+}
+
+/**
+ Print an operand value within a statement generated for an expression.
+
+ @param item Operand value to print.
+ @param field Field related to the operand value.
+ @param spider Spider.
+ @param str String into which the value is to be printed.
+ @param alias Name related to the operand.
+ @param alias_length Length of the name.
+ @param dbton_id Spider Db/Table id.
+ @param use_fields Use fields or exchange fields.
+ @param fields Array of fields in the expression.
+
+ @return Error code.
+*/
+
+int spider_db_print_item_type(Item *item, Field *field, ha_spider *spider,
+ spider_string *str, const char *alias,
+ uint alias_length, uint dbton_id,
+ bool use_fields, spider_fields *fields)
+{
DBUG_ENTER("spider_db_print_item_type");
DBUG_PRINT("info",("spider COND type=%d", item->type()));
+
switch (item->type())
{
case Item::FUNC_ITEM:
@@ -8484,19 +8561,25 @@ int spider_db_print_item_type(
DBUG_RETURN(spider_db_open_item_row((Item_row *) item, spider, str,
alias, alias_length, dbton_id, use_fields, fields));
case Item::STRING_ITEM:
- DBUG_RETURN(spider_db_open_item_string(item, spider, str,
- alias, alias_length, dbton_id, use_fields, fields));
+ DBUG_RETURN(spider_db_open_item_string(item, field, spider, str,
+ alias, alias_length, dbton_id,
+ use_fields, fields));
case Item::INT_ITEM:
case Item::REAL_ITEM:
case Item::DECIMAL_ITEM:
- DBUG_RETURN(spider_db_open_item_int(item, spider, str,
- alias, alias_length, dbton_id, use_fields, fields));
+ DBUG_RETURN(spider_db_open_item_int(item, field, spider, str,
+ alias, alias_length, dbton_id,
+ use_fields, fields));
case Item::CACHE_ITEM:
- DBUG_RETURN(spider_db_open_item_cache((Item_cache *)item, spider, str,
- alias, alias_length, dbton_id, use_fields, fields));
+ DBUG_RETURN(spider_db_open_item_cache((Item_cache *) item, field,
+ spider, str, alias, alias_length,
+ dbton_id, use_fields, fields));
case Item::INSERT_VALUE_ITEM:
- DBUG_RETURN(spider_db_open_item_insert_value((Item_insert_value *)item,
- spider, str, alias, alias_length, dbton_id, use_fields, fields));
+ DBUG_RETURN(spider_db_open_item_insert_value((Item_insert_value *) item,
+ field, spider, str,
+ alias, alias_length,
+ dbton_id,
+ use_fields, fields));
case Item::SUBSELECT_ITEM:
case Item::TRIGGER_FIELD_ITEM:
#ifdef SPIDER_HAS_EXPR_CACHE_ITEM
@@ -8525,6 +8608,7 @@ int spider_db_print_item_type(
}
break;
}
+
DBUG_RETURN(0);
}
@@ -8556,8 +8640,9 @@ restart_first:
{
if (str)
restart_pos = str->length();
- if ((error_num = spider_db_print_item_type(item, spider, str,
- alias, alias_length, dbton_id, use_fields, fields)))
+ if ((error_num = spider_db_print_item_type(item, NULL, spider, str,
+ alias, alias_length, dbton_id,
+ use_fields, fields)))
{
if (
str &&
@@ -8590,8 +8675,9 @@ restart_first:
str->q_append(SPIDER_SQL_SPACE_STR, SPIDER_SQL_SPACE_LEN);
}
- if ((error_num = spider_db_print_item_type(item, spider, str,
- alias, alias_length, dbton_id, use_fields, fields)))
+ if ((error_num = spider_db_print_item_type(item, NULL, spider, str,
+ alias, alias_length, dbton_id,
+ use_fields, fields)))
{
if (
str &&
@@ -8827,8 +8913,9 @@ int spider_db_open_item_ref(
}
DBUG_RETURN(0);
}
- DBUG_RETURN(spider_db_print_item_type(*(item_ref->ref), spider, str,
- alias, alias_length, dbton_id, use_fields, fields));
+ DBUG_RETURN(spider_db_print_item_type(*(item_ref->ref), NULL, spider,
+ str, alias, alias_length, dbton_id,
+ use_fields, fields));
}
DBUG_RETURN(spider_db_open_item_ident((Item_ident *) item_ref, spider, str,
alias, alias_length, dbton_id, use_fields, fields));
@@ -8857,8 +8944,9 @@ int spider_db_open_item_row(
for (roop_count = 0; roop_count < cols; roop_count++)
{
item = item_row->element_index(roop_count);
- if ((error_num = spider_db_print_item_type(item, spider, str,
- alias, alias_length, dbton_id, use_fields, fields)))
+ if ((error_num = spider_db_print_item_type(item, NULL, spider, str,
+ alias, alias_length, dbton_id,
+ use_fields, fields)))
DBUG_RETURN(error_num);
if (str)
{
@@ -8868,8 +8956,9 @@ int spider_db_open_item_row(
}
}
item = item_row->element_index(roop_count);
- if ((error_num = spider_db_print_item_type(item, spider, str,
- alias, alias_length, dbton_id, use_fields, fields)))
+ if ((error_num = spider_db_print_item_type(item, NULL, spider, str,
+ alias, alias_length, dbton_id,
+ use_fields, fields)))
DBUG_RETURN(error_num);
if (str)
{
@@ -8881,104 +8970,251 @@ int spider_db_open_item_row(
DBUG_RETURN(0);
}
-int spider_db_open_item_string(
- Item *item,
- ha_spider *spider,
- spider_string *str,
- const char *alias,
- uint alias_length,
- uint dbton_id,
- bool use_fields,
- spider_fields *fields
-) {
+/**
+ Print a string value within a generated statement.
+
+ @param item String value to print.
+ @param field Field related to the string value.
+ @param spider Spider.
+ @param str String into which the value is to be printed.
+ @param alias Name related to the string value.
+ @param alias_length Length of the name.
+ @param dbton_id Spider Db/Table id.
+ @param use_fields Use fields or exchange fields.
+ @param fields Array of fields in an expression containing
+ the string value.
+
+ @return Error code.
+*/
+
+int spider_db_open_item_string(Item *item, Field *field, ha_spider *spider,
+ spider_string *str,
+ const char *alias, uint alias_length,
+ uint dbton_id,
+ bool use_fields, spider_fields *fields)
+{
+ int error_num = 0;
DBUG_ENTER("spider_db_open_item_string");
+
if (str)
{
+ THD *thd = NULL;
+ TABLE *table;
+ my_bitmap_map *saved_map;
+ Time_zone *saved_time_zone;
char tmp_buf[MAX_FIELD_WIDTH];
spider_string tmp_str(tmp_buf, MAX_FIELD_WIDTH, str->charset());
String *tmp_str2;
+ String str_value;
tmp_str.init_calc_mem(126);
+
if (!(tmp_str2 = item->val_str(tmp_str.get_str())))
{
if (str->reserve(SPIDER_SQL_NULL_LEN))
- DBUG_RETURN(HA_ERR_OUT_OF_MEM);
+ {
+ error_num = HA_ERR_OUT_OF_MEM;
+ goto error;
+ }
str->q_append(SPIDER_SQL_NULL_STR, SPIDER_SQL_NULL_LEN);
- } else {
+ }
+ else
+ {
+ if (field && field->type() == FIELD_TYPE_TIMESTAMP)
+ {
+ /*
+ Store the string value in the field. This is necessary
+ when the statement contains more than one value for the
+ same field.
+ */
+ table = field->table;
+ thd = table->in_use;
+ saved_map = dbug_tmp_use_all_columns(table, table->write_set);
+ item->save_in_field(field, FALSE);
+ saved_time_zone = thd->variables.time_zone;
+ thd->variables.time_zone = UTC;
+
+ /* Retrieve the stored value converted to UTC */
+ tmp_str2 = field->val_str(&str_value);
+
+ if (!tmp_str2)
+ {
+ error_num = HA_ERR_OUT_OF_MEM;
+ goto error;
+ }
+ }
+
if (str->reserve(SPIDER_SQL_VALUE_QUOTE_LEN * 2 +
- tmp_str2->length() * 2))
- DBUG_RETURN(HA_ERR_OUT_OF_MEM);
- tmp_str.mem_calc();
+ tmp_str2->length() * 2))
+ {
+ error_num = HA_ERR_OUT_OF_MEM;
+ goto error;
+ }
+ if (!thd)
+ tmp_str.mem_calc();
str->q_append(SPIDER_SQL_VALUE_QUOTE_STR, SPIDER_SQL_VALUE_QUOTE_LEN);
str->append_escape_string(tmp_str2->ptr(), tmp_str2->length());
- if (
- str->reserve(SPIDER_SQL_VALUE_QUOTE_LEN)
- )
- DBUG_RETURN(HA_ERR_OUT_OF_MEM);
+ if (str->reserve(SPIDER_SQL_VALUE_QUOTE_LEN))
+ {
+ error_num = HA_ERR_OUT_OF_MEM;
+ goto error;
+ }
str->q_append(SPIDER_SQL_VALUE_QUOTE_STR, SPIDER_SQL_VALUE_QUOTE_LEN);
}
+
+error:
+ if (thd)
+ {
+ thd->variables.time_zone = saved_time_zone;
+ dbug_tmp_restore_column_map(table->write_set, saved_map);
+ }
}
- DBUG_RETURN(0);
+
+ DBUG_RETURN(error_num);
}
-int spider_db_open_item_int(
- Item *item,
- ha_spider *spider,
- spider_string *str,
- const char *alias,
- uint alias_length,
- uint dbton_id,
- bool use_fields,
- spider_fields *fields
-) {
+/**
+ Print an integer value within a generated statement.
+
+ @param item Integer value to print.
+ @param field Field related to the integer value.
+ @param spider Spider.
+ @param str String into which the value is to be printed.
+ @param alias Name related to the integer value.
+ @param alias_length Length of the name.
+ @param dbton_id Spider Db/Table id.
+ @param use_fields Use fields or exchange fields.
+ @param fields Array of fields in an expression containing
+ the integer value.
+
+ @return Error code.
+*/
+
+int spider_db_open_item_int(Item *item, Field *field, ha_spider *spider,
+ spider_string *str,
+ const char *alias, uint alias_length,
+ uint dbton_id,
+ bool use_fields, spider_fields *fields)
+{
+ int error_num = 0;
DBUG_ENTER("spider_db_open_item_int");
+
if (str)
{
+ THD *thd = NULL;
+ TABLE *table;
+ bool print_quoted_string;
+ my_bitmap_map *saved_map;
+ Time_zone *saved_time_zone;
char tmp_buf[MAX_FIELD_WIDTH];
spider_string tmp_str(tmp_buf, MAX_FIELD_WIDTH, str->charset());
+ String str_value;
String *tmp_str2;
tmp_str.init_calc_mem(127);
+
if (!(tmp_str2 = item->val_str(tmp_str.get_str())))
- DBUG_RETURN(HA_ERR_OUT_OF_MEM);
+ {
+ error_num = HA_ERR_OUT_OF_MEM;
+ goto error;
+ }
tmp_str.mem_calc();
+
+ if (field && field->type() == FIELD_TYPE_TIMESTAMP)
+ {
+ /*
+ Store the int value in the field. This is necessary
+ when the statement contains more than one value for the
+ same field.
+ */
+ table = field->table;
+ thd = table->in_use;
+ saved_map = dbug_tmp_use_all_columns(table, table->write_set);
+ item->save_in_field(field, FALSE);
+ saved_time_zone = thd->variables.time_zone;
+ thd->variables.time_zone = UTC;
+ print_quoted_string = TRUE;
+ }
+ else
+ {
#ifdef SPIDER_ITEM_HAS_CMP_TYPE
- DBUG_PRINT("info",("spider cmp_type=%u", item->cmp_type()));
- if (item->cmp_type() == TIME_RESULT)
+ DBUG_PRINT("info", ("spider cmp_type=%u", item->cmp_type()));
+ if (item->cmp_type() == TIME_RESULT)
+ print_quoted_string = TRUE;
+ else
+#endif
+ print_quoted_string = FALSE;
+ }
+
+ if (print_quoted_string)
{
+ if (thd)
+ {
+ /* Retrieve the stored value converted to UTC */
+ tmp_str2 = field->val_str(&str_value);
+
+ if (!tmp_str2)
+ {
+ error_num = HA_ERR_OUT_OF_MEM;
+ goto error;
+ }
+ }
+
if (str->reserve(SPIDER_SQL_VALUE_QUOTE_LEN * 2 + tmp_str2->length()))
DBUG_RETURN(HA_ERR_OUT_OF_MEM);
str->q_append(SPIDER_SQL_VALUE_QUOTE_STR, SPIDER_SQL_VALUE_QUOTE_LEN);
str->append(*tmp_str2);
str->q_append(SPIDER_SQL_VALUE_QUOTE_STR, SPIDER_SQL_VALUE_QUOTE_LEN);
- } else {
-#endif
+ }
+ else
+ {
if (str->append(*tmp_str2))
- DBUG_RETURN(HA_ERR_OUT_OF_MEM);
-#ifdef SPIDER_ITEM_HAS_CMP_TYPE
+ error_num = HA_ERR_OUT_OF_MEM;
+ }
+
+error:
+ if (thd)
+ {
+ thd->variables.time_zone = saved_time_zone;
+ dbug_tmp_restore_column_map(table->write_set, saved_map);
}
-#endif
}
- DBUG_RETURN(0);
+
+ DBUG_RETURN(error_num);
}
-int spider_db_open_item_cache(
- Item_cache *item_cache,
- ha_spider *spider,
- spider_string *str,
- const char *alias,
- uint alias_length,
- uint dbton_id,
- bool use_fields,
- spider_fields *fields
-) {
+/**
+ Print a cached value within a generated statement.
+
+ @param item Cached value to print.
+ @param field Field related to the cached value.
+ @param spider Spider.
+ @param str String into which the value is to be printed.
+ @param alias Name related to the cached value.
+ @param alias_length Length of the name.
+ @param dbton_id Spider Db/Table id.
+ @param use_fields Use fields or exchange fields.
+ @param fields Array of fields in the expression containing
+ the cached value.
+
+ @return Error code.
+*/
+
+int spider_db_open_item_cache(Item_cache *item_cache, Field *field,
+ ha_spider *spider, spider_string *str,
+ const char *alias, uint alias_length,
+ uint dbton_id,
+ bool use_fields, spider_fields *fields)
+{
DBUG_ENTER("spider_db_open_item_cache");
if (!item_cache->const_item())
DBUG_RETURN(ER_SPIDER_COND_SKIP_NUM);
DBUG_PRINT("info",("spider result_type=%u", item_cache->result_type()));
+
switch (item_cache->result_type())
{
case STRING_RESULT:
- DBUG_RETURN(spider_db_open_item_string(item_cache, spider, str,
- alias, alias_length, dbton_id, use_fields, fields));
+ DBUG_RETURN(spider_db_open_item_string(item_cache, field, spider, str,
+ alias, alias_length, dbton_id,
+ use_fields, fields));
case ROW_RESULT:
{
int error_num;
@@ -8993,9 +9229,11 @@ int spider_db_open_item_cache(
for (roop_count = 0; roop_count < item_count; ++roop_count)
{
if ((error_num = spider_db_open_item_cache(
- (Item_cache *) item_cache_row->element_index(roop_count),
- spider, str, alias, alias_length, dbton_id, use_fields, fields
- ))) {
+ (Item_cache *)
+ item_cache_row->element_index(roop_count),
+ NULL, spider, str, alias, alias_length,
+ dbton_id, use_fields, fields)))
+ {
DBUG_RETURN(error_num);
}
if (str)
@@ -9006,9 +9244,11 @@ int spider_db_open_item_cache(
}
}
if ((error_num = spider_db_open_item_cache(
- (Item_cache *) item_cache_row->element_index(roop_count),
- spider, str, alias, alias_length, dbton_id, use_fields, fields
- ))) {
+ (Item_cache *)
+ item_cache_row->element_index(roop_count),
+ NULL, spider, str, alias, alias_length,
+ dbton_id, use_fields, fields)))
+ {
DBUG_RETURN(error_num);
}
if (str)
@@ -9026,22 +9266,38 @@ int spider_db_open_item_cache(
default:
break;
}
- DBUG_RETURN(spider_db_open_item_int(item_cache, spider, str,
- alias, alias_length, dbton_id, use_fields, fields));
+
+ DBUG_RETURN(spider_db_open_item_int(item_cache, field, spider, str,
+ alias, alias_length, dbton_id,
+ use_fields, fields));
}
-int spider_db_open_item_insert_value(
- Item_insert_value *item_insert_value,
- ha_spider *spider,
- spider_string *str,
- const char *alias,
- uint alias_length,
- uint dbton_id,
- bool use_fields,
- spider_fields *fields
-) {
+/**
+ Print an INSERT value within a generated INSERT statement.
+
+ @param item INSERT value to print.
+ @param field Field related to the INSERT value.
+ @param spider Spider.
+ @param str String into which the value is to be printed.
+ @param alias Name related to the INSERT value.
+ @param alias_length Length of the name.
+ @param dbton_id Spider Db/Table id.
+ @param use_fields Use fields or exchange fields.
+ @param fields Array of fields in the expression.
+
+ @return Error code.
+*/
+
+int spider_db_open_item_insert_value(Item_insert_value *item_insert_value,
+ Field *field, ha_spider *spider,
+ spider_string *str,
+ const char *alias, uint alias_length,
+ uint dbton_id,
+ bool use_fields, spider_fields *fields)
+{
int error_num;
DBUG_ENTER("spider_db_open_item_insert_value");
+
if (item_insert_value->arg)
{
if (str)
@@ -9051,8 +9307,10 @@ int spider_db_open_item_insert_value(
str->q_append(SPIDER_SQL_VALUES_STR, SPIDER_SQL_VALUES_LEN);
str->q_append(SPIDER_SQL_OPEN_PAREN_STR, SPIDER_SQL_OPEN_PAREN_LEN);
}
- if ((error_num = spider_db_print_item_type(item_insert_value->arg, spider,
- str, alias, alias_length, dbton_id, use_fields, fields)))
+ if ((error_num = spider_db_print_item_type(item_insert_value->arg, field,
+ spider, str, alias,
+ alias_length, dbton_id,
+ use_fields, fields)))
DBUG_RETURN(error_num);
if (str)
{
@@ -9061,6 +9319,7 @@ int spider_db_open_item_insert_value(
str->q_append(SPIDER_SQL_CLOSE_PAREN_STR, SPIDER_SQL_CLOSE_PAREN_LEN);
}
}
+
DBUG_RETURN(0);
}
@@ -9116,9 +9375,10 @@ int spider_db_append_update_columns(
while ((field = fi++))
{
value = vi++;
- if ((error_num = spider_db_print_item_type(
- (Item *) field, spider, str, alias, alias_length, dbton_id,
- use_fields, fields)))
+ if ((error_num = spider_db_print_item_type((Item *) field, NULL, spider,
+ str, alias, alias_length,
+ dbton_id,
+ use_fields, fields)))
{
if (
error_num == ER_SPIDER_COND_SKIP_NUM &&
@@ -9136,9 +9396,12 @@ int spider_db_append_update_columns(
DBUG_RETURN(HA_ERR_OUT_OF_MEM);
str->q_append(SPIDER_SQL_EQUAL_STR, SPIDER_SQL_EQUAL_LEN);
}
- if ((error_num = spider_db_print_item_type(
- (Item *) value, spider, str, alias, alias_length, dbton_id,
- use_fields, fields)))
+ if ((error_num = spider_db_print_item_type((Item *) value,
+ ((Item_field *) field)->field,
+ spider, str,
+ alias, alias_length,
+ dbton_id,
+ use_fields, fields)))
DBUG_RETURN(error_num);
if (str)
{
diff --git a/storage/spider/spd_db_conn.h b/storage/spider/spd_db_conn.h
index 7977e61da58..879ab3540c1 100644
--- a/storage/spider/spd_db_conn.h
+++ b/storage/spider/spd_db_conn.h
@@ -838,8 +838,18 @@ int spider_db_flush_logs(
ha_spider *spider
);
+Field *spider_db_find_field_in_item_list(
+ Item **item_list,
+ uint item_count,
+ uint start_item,
+ spider_string *str,
+ const char *func_name,
+ int func_name_length
+);
+
int spider_db_print_item_type(
Item *item,
+ Field *field,
ha_spider *spider,
spider_string *str,
const char *alias,
@@ -930,6 +940,7 @@ int spider_db_open_item_row(
int spider_db_open_item_string(
Item *item,
+ Field *field,
ha_spider *spider,
spider_string *str,
const char *alias,
@@ -941,6 +952,7 @@ int spider_db_open_item_string(
int spider_db_open_item_int(
Item *item,
+ Field *field,
ha_spider *spider,
spider_string *str,
const char *alias,
@@ -952,6 +964,7 @@ int spider_db_open_item_int(
int spider_db_open_item_cache(
Item_cache *item_cache,
+ Field *field,
ha_spider *spider,
spider_string *str,
const char *alias,
@@ -963,6 +976,7 @@ int spider_db_open_item_cache(
int spider_db_open_item_insert_value(
Item_insert_value *item_insert_value,
+ Field *field,
ha_spider *spider,
spider_string *str,
const char *alias,
diff --git a/storage/spider/spd_db_include.h b/storage/spider/spd_db_include.h
index 2913f911587..639bb6dac2d 100644
--- a/storage/spider/spd_db_include.h
+++ b/storage/spider/spd_db_include.h
@@ -17,6 +17,7 @@
#if defined(HS_HAS_SQLCOM) && defined(HAVE_HANDLERSOCKET)
#include "hstcpcli.hpp"
#endif
+#include "tztime.h"
#define SPIDER_DBTON_SIZE 15
diff --git a/storage/spider/spd_db_mysql.cc b/storage/spider/spd_db_mysql.cc
index 21bbaaea2c9..db685c50b85 100644
--- a/storage/spider/spd_db_mysql.cc
+++ b/storage/spider/spd_db_mysql.cc
@@ -179,6 +179,9 @@ static const char *spider_db_timefunc_interval_str[] =
" minute_microsecond", " second_microsecond"
};
+/* UTC time zone for timestamp columns */
+Time_zone *UTC = 0;
+
int spider_mysql_init()
{
DBUG_ENTER("spider_mysql_init");
@@ -3192,9 +3195,13 @@ int spider_db_mysql_util::append_column_value(
spider_string tmp_str(buf, MAX_FIELD_WIDTH, &my_charset_bin);
String *ptr;
uint length;
+ THD *thd = field->table->in_use;
+ Time_zone *saved_time_zone = thd->variables.time_zone;
DBUG_ENTER("spider_db_mysql_util::append_column_value");
tmp_str.init_calc_mem(113);
+ thd->variables.time_zone = UTC;
+
if (new_ptr)
{
if (
@@ -3205,7 +3212,8 @@ int spider_db_mysql_util::append_column_value(
tmp_str.set_quick((char *) new_ptr + HA_KEY_BLOB_LENGTH, length,
&my_charset_bin);
ptr = tmp_str.get_str();
- } else if (field->type() == MYSQL_TYPE_GEOMETRY)
+ }
+ else if (field->type() == MYSQL_TYPE_GEOMETRY)
{
/*
uint mlength = SIZEOF_STORED_DOUBLE, lcnt;
@@ -3282,14 +3290,21 @@ int spider_db_mysql_util::append_column_value(
tmp_str.q_append((char *) new_ptr + SIZEOF_STORED_DOUBLE * 3,
SIZEOF_STORED_DOUBLE);
ptr = tmp_str.get_str();
- } else {
+ }
+ else
+ {
ptr = field->val_str(tmp_str.get_str(), new_ptr);
tmp_str.mem_calc();
}
- } else {
+ }
+ else
+ {
ptr = field->val_str(tmp_str.get_str());
tmp_str.mem_calc();
}
+
+ thd->variables.time_zone = saved_time_zone;
+
DBUG_PRINT("info", ("spider field->type() is %d", field->type()));
DBUG_PRINT("info", ("spider ptr->length() is %d", ptr->length()));
/*
@@ -3335,7 +3350,8 @@ int spider_db_mysql_util::append_column_value(
append_escaped_util(str, tmp_str2.get_str())
)
DBUG_RETURN(HA_ERR_OUT_OF_MEM);
- } else if (str->append(*ptr))
+ }
+ else if (str->append(*ptr))
DBUG_RETURN(HA_ERR_OUT_OF_MEM);
if (str->reserve(SPIDER_SQL_VALUE_QUOTE_LEN))
DBUG_RETURN(HA_ERR_OUT_OF_MEM);
@@ -3604,12 +3620,13 @@ int spider_db_mysql_util::open_item_func(
uint dbton_id = spider_dbton_mysql.dbton_id;
int error_num;
Item *item, **item_list = item_func->arguments();
- uint roop_count, item_count = item_func->argument_count(), start_item = 0;
+ Field *field;
+ uint loop_count, item_count = item_func->argument_count(), start_item = 0;
const char *func_name = SPIDER_SQL_NULL_CHAR_STR,
- *separete_str = SPIDER_SQL_NULL_CHAR_STR,
+ *separator_str = SPIDER_SQL_NULL_CHAR_STR,
*last_str = SPIDER_SQL_NULL_CHAR_STR;
int func_name_length = SPIDER_SQL_NULL_CHAR_LEN,
- separete_str_length = SPIDER_SQL_NULL_CHAR_LEN,
+ separator_str_length = SPIDER_SQL_NULL_CHAR_LEN,
last_str_length = SPIDER_SQL_NULL_CHAR_LEN;
int use_pushdown_udf;
bool merge_func = FALSE;
@@ -3675,8 +3692,9 @@ int spider_db_mysql_util::open_item_func(
) {
if (str)
str->length(str->length() - SPIDER_SQL_OPEN_PAREN_LEN);
- DBUG_RETURN(spider_db_open_item_int(item_func, spider, str,
- alias, alias_length, dbton_id, use_fields, fields));
+ DBUG_RETURN(spider_db_open_item_int(item_func, NULL, spider, str,
+ alias, alias_length, dbton_id,
+ use_fields, fields));
} else if (
!strncasecmp("case", func_name, func_name_length)
) {
@@ -3695,8 +3713,8 @@ int spider_db_mysql_util::open_item_func(
alias, alias_length, dbton_id, use_fields, fields)))
DBUG_RETURN(error_num);
}
- for (roop_count = 0; roop_count < item_func_case->ncases;
- roop_count += 2)
+ for (loop_count = 0; loop_count < item_func_case->ncases;
+ loop_count += 2)
{
if (str)
{
@@ -3705,7 +3723,7 @@ int spider_db_mysql_util::open_item_func(
str->q_append(SPIDER_SQL_WHEN_STR, SPIDER_SQL_WHEN_LEN);
}
if ((error_num = spider_db_print_item_type(
- item_list[roop_count], spider, str,
+ item_list[loop_count], spider, str,
alias, alias_length, dbton_id, use_fields, fields)))
DBUG_RETURN(error_num);
if (str)
@@ -3715,7 +3733,7 @@ int spider_db_mysql_util::open_item_func(
str->q_append(SPIDER_SQL_THEN_STR, SPIDER_SQL_THEN_LEN);
}
if ((error_num = spider_db_print_item_type(
- item_list[roop_count + 1], spider, str,
+ item_list[loop_count + 1], spider, str,
alias, alias_length, dbton_id, use_fields, fields)))
DBUG_RETURN(error_num);
}
@@ -3765,8 +3783,10 @@ int spider_db_mysql_util::open_item_func(
) {
if (str)
str->length(str->length() - SPIDER_SQL_OPEN_PAREN_LEN);
- DBUG_RETURN(spider_db_open_item_string(item_func, spider, str,
- alias, alias_length, dbton_id, use_fields, fields));
+ DBUG_RETURN(spider_db_open_item_string(item_func, NULL, spider, str,
+ alias, alias_length,
+ dbton_id,
+ use_fields, fields));
} else if (
!strncasecmp("convert", func_name, func_name_length)
) {
@@ -3790,8 +3810,9 @@ int spider_db_mysql_util::open_item_func(
) {
if (str)
str->length(str->length() - SPIDER_SQL_OPEN_PAREN_LEN);
- DBUG_RETURN(spider_db_open_item_string(item_func, spider, str,
- alias, alias_length, dbton_id, use_fields, fields));
+ DBUG_RETURN(spider_db_open_item_string(item_func, NULL, spider, str,
+ alias, alias_length, dbton_id,
+ use_fields, fields));
} else if (func_name_length == 9 &&
!strncasecmp("isnottrue", func_name, func_name_length)
) {
@@ -3817,8 +3838,8 @@ int spider_db_mysql_util::open_item_func(
}
func_name = SPIDER_SQL_COMMA_STR;
func_name_length = SPIDER_SQL_COMMA_LEN;
- separete_str = SPIDER_SQL_COMMA_STR;
- separete_str_length = SPIDER_SQL_COMMA_LEN;
+ separator_str = SPIDER_SQL_COMMA_STR;
+ separator_str_length = SPIDER_SQL_COMMA_LEN;
break;
}
} else if (func_name_length == 12)
@@ -3906,8 +3927,10 @@ int spider_db_mysql_util::open_item_func(
{
if (str)
str->length(str->length() - SPIDER_SQL_OPEN_PAREN_LEN);
- DBUG_RETURN(spider_db_open_item_string(item_func, spider, str,
- alias, alias_length, dbton_id, use_fields, fields));
+ DBUG_RETURN(spider_db_open_item_string(item_func, NULL, spider, str,
+ alias, alias_length,
+ dbton_id,
+ use_fields, fields));
} else if (!strncasecmp("timestampdiff", func_name, func_name_length))
{
#ifdef ITEM_FUNC_TIMESTAMPDIFF_ARE_PUBLIC
@@ -4232,8 +4255,11 @@ int spider_db_mysql_util::open_item_func(
func_name = spider_db_timefunc_interval_str[
item_date_add_interval->int_type];
func_name_length = strlen(func_name);
- if ((error_num = spider_db_print_item_type(item_list[0], spider, str,
- alias, alias_length, dbton_id, use_fields, fields)))
+ if ((error_num = spider_db_print_item_type(item_list[0], NULL,
+ spider, str,
+ alias, alias_length,
+ dbton_id,
+ use_fields, fields)))
DBUG_RETURN(error_num);
if (str)
{
@@ -4249,8 +4275,11 @@ int spider_db_mysql_util::open_item_func(
str->q_append(SPIDER_SQL_INTERVAL_STR, SPIDER_SQL_INTERVAL_LEN);
}
}
- if ((error_num = spider_db_print_item_type(item_list[1], spider, str,
- alias, alias_length, dbton_id, use_fields, fields)))
+ if ((error_num = spider_db_print_item_type(item_list[1], NULL,
+ spider, str,
+ alias, alias_length,
+ dbton_id,
+ use_fields, fields)))
DBUG_RETURN(error_num);
if (str)
{
@@ -4272,16 +4301,17 @@ int spider_db_mysql_util::open_item_func(
}
func_name = SPIDER_SQL_COMMA_STR;
func_name_length = SPIDER_SQL_COMMA_LEN;
- separete_str = SPIDER_SQL_COMMA_STR;
- separete_str_length = SPIDER_SQL_COMMA_LEN;
+ separator_str = SPIDER_SQL_COMMA_STR;
+ separator_str_length = SPIDER_SQL_COMMA_LEN;
last_str = SPIDER_SQL_CLOSE_PAREN_STR;
last_str_length = SPIDER_SQL_CLOSE_PAREN_LEN;
break;
case Item_func::NOW_FUNC:
if (str)
str->length(str->length() - SPIDER_SQL_OPEN_PAREN_LEN);
- DBUG_RETURN(spider_db_open_item_string(item_func, spider, str,
- alias, alias_length, dbton_id, use_fields, fields));
+ DBUG_RETURN(spider_db_open_item_string(item_func, NULL, spider, str,
+ alias, alias_length, dbton_id,
+ use_fields, fields));
case Item_func::CHAR_TYPECAST_FUNC:
DBUG_PRINT("info",("spider CHAR_TYPECAST_FUNC"));
{
@@ -4406,15 +4436,15 @@ int spider_db_mysql_util::open_item_func(
{
func_name = SPIDER_SQL_NOT_IN_STR;
func_name_length = SPIDER_SQL_NOT_IN_LEN;
- separete_str = SPIDER_SQL_COMMA_STR;
- separete_str_length = SPIDER_SQL_COMMA_LEN;
+ separator_str = SPIDER_SQL_COMMA_STR;
+ separator_str_length = SPIDER_SQL_COMMA_LEN;
last_str = SPIDER_SQL_CLOSE_PAREN_STR;
last_str_length = SPIDER_SQL_CLOSE_PAREN_LEN;
} else {
func_name = SPIDER_SQL_IN_STR;
func_name_length = SPIDER_SQL_IN_LEN;
- separete_str = SPIDER_SQL_COMMA_STR;
- separete_str_length = SPIDER_SQL_COMMA_LEN;
+ separator_str = SPIDER_SQL_COMMA_STR;
+ separator_str_length = SPIDER_SQL_COMMA_LEN;
last_str = SPIDER_SQL_CLOSE_PAREN_STR;
last_str_length = SPIDER_SQL_CLOSE_PAREN_LEN;
}
@@ -4424,13 +4454,13 @@ int spider_db_mysql_util::open_item_func(
{
func_name = SPIDER_SQL_NOT_BETWEEN_STR;
func_name_length = SPIDER_SQL_NOT_BETWEEN_LEN;
- separete_str = SPIDER_SQL_AND_STR;
- separete_str_length = SPIDER_SQL_AND_LEN;
+ separator_str = SPIDER_SQL_AND_STR;
+ separator_str_length = SPIDER_SQL_AND_LEN;
} else {
func_name = (char*) item_func->func_name();
func_name_length = strlen(func_name);
- separete_str = SPIDER_SQL_AND_STR;
- separete_str_length = SPIDER_SQL_AND_LEN;
+ separator_str = SPIDER_SQL_AND_STR;
+ separator_str_length = SPIDER_SQL_AND_LEN;
}
break;
case Item_func::UDF_FUNC:
@@ -4451,8 +4481,8 @@ int spider_db_mysql_util::open_item_func(
}
func_name = SPIDER_SQL_COMMA_STR;
func_name_length = SPIDER_SQL_COMMA_LEN;
- separete_str = SPIDER_SQL_COMMA_STR;
- separete_str_length = SPIDER_SQL_COMMA_LEN;
+ separator_str = SPIDER_SQL_COMMA_STR;
+ separator_str_length = SPIDER_SQL_COMMA_LEN;
last_str = SPIDER_SQL_CLOSE_PAREN_STR;
last_str_length = SPIDER_SQL_CLOSE_PAREN_LEN;
break;
@@ -4472,11 +4502,13 @@ int spider_db_mysql_util::open_item_func(
if (str)
str->length(str->length() - SPIDER_SQL_OPEN_PAREN_LEN);
if (item_func->result_type() == STRING_RESULT)
- DBUG_RETURN(spider_db_open_item_string(item_func, spider, str,
- alias, alias_length, dbton_id, use_fields, fields));
+ DBUG_RETURN(spider_db_open_item_string(item_func, NULL, spider, str,
+ alias, alias_length, dbton_id,
+ use_fields, fields));
else
- DBUG_RETURN(spider_db_open_item_int(item_func, spider, str,
- alias, alias_length, dbton_id, use_fields, fields));
+ DBUG_RETURN(spider_db_open_item_int(item_func, NULL, spider, str,
+ alias, alias_length, dbton_id,
+ use_fields, fields));
case Item_func::FT_FUNC:
if (spider_db_check_ft_idx(item_func, spider) == MAX_KEY)
DBUG_RETURN(ER_SPIDER_COND_SKIP_NUM);
@@ -4487,8 +4519,8 @@ int spider_db_mysql_util::open_item_func(
DBUG_RETURN(HA_ERR_OUT_OF_MEM);
str->q_append(SPIDER_SQL_MATCH_STR, SPIDER_SQL_MATCH_LEN);
}
- separete_str = SPIDER_SQL_COMMA_STR;
- separete_str_length = SPIDER_SQL_COMMA_LEN;
+ separator_str = SPIDER_SQL_COMMA_STR;
+ separator_str_length = SPIDER_SQL_COMMA_LEN;
last_str = SPIDER_SQL_CLOSE_PAREN_STR;
last_str_length = SPIDER_SQL_CLOSE_PAREN_LEN;
break;
@@ -4505,8 +4537,8 @@ int spider_db_mysql_util::open_item_func(
}
func_name = SPIDER_SQL_COMMA_STR;
func_name_length = SPIDER_SQL_COMMA_LEN;
- separete_str = SPIDER_SQL_COMMA_STR;
- separete_str_length = SPIDER_SQL_COMMA_LEN;
+ separator_str = SPIDER_SQL_COMMA_STR;
+ separator_str_length = SPIDER_SQL_COMMA_LEN;
last_str = SPIDER_SQL_CLOSE_PAREN_STR;
last_str_length = SPIDER_SQL_CLOSE_PAREN_LEN;
break;
@@ -4537,8 +4569,8 @@ int spider_db_mysql_util::open_item_func(
}
func_name = SPIDER_SQL_COMMA_STR;
func_name_length = SPIDER_SQL_COMMA_LEN;
- separete_str = SPIDER_SQL_COMMA_STR;
- separete_str_length = SPIDER_SQL_COMMA_LEN;
+ separator_str = SPIDER_SQL_COMMA_STR;
+ separator_str_length = SPIDER_SQL_COMMA_LEN;
last_str = SPIDER_SQL_CLOSE_PAREN_STR;
last_str_length = SPIDER_SQL_CLOSE_PAREN_LEN;
break;
@@ -4571,23 +4603,39 @@ int spider_db_mysql_util::open_item_func(
}
DBUG_PRINT("info",("spider func_name = %s", func_name));
DBUG_PRINT("info",("spider func_name_length = %d", func_name_length));
- DBUG_PRINT("info",("spider separete_str = %s", separete_str));
- DBUG_PRINT("info",("spider separete_str_length = %d", separete_str_length));
+ DBUG_PRINT("info",("spider separator_str = %s", separator_str));
+ DBUG_PRINT("info",("spider separator_str_length = %d", separator_str_length));
DBUG_PRINT("info",("spider last_str = %s", last_str));
DBUG_PRINT("info",("spider last_str_length = %d", last_str_length));
+
if (item_count)
{
+ /* Find the field in the list of items of the expression tree */
+ field = spider_db_find_field_in_item_list(item_list,
+ item_count, start_item,
+ str,
+ func_name, func_name_length);
+
item_count--;
- for (roop_count = start_item; roop_count < item_count; roop_count++)
- {
- item = item_list[roop_count];
- if ((error_num = spider_db_print_item_type(item, spider, str,
- alias, alias_length, dbton_id, use_fields, fields)))
+
+ /*
+ Loop through the items of the current function expression to
+ print its portion of the statement
+ */
+ for (loop_count = start_item; loop_count < item_count; loop_count++)
+ {
+ item = item_list[loop_count];
+ if ((error_num = spider_db_print_item_type(item, field, spider, str,
+ alias, alias_length,
+ dbton_id,
+ use_fields, fields)))
DBUG_RETURN(error_num);
- if (roop_count == 1)
+
+ if (loop_count == 1)
{
- func_name = separete_str;
- func_name_length = separete_str_length;
+ /* Remaining operands need to be preceded by the separator */
+ func_name = separator_str;
+ func_name_length = separator_str_length;
}
if (str)
{
@@ -4598,11 +4646,16 @@ int spider_db_mysql_util::open_item_func(
str->q_append(SPIDER_SQL_SPACE_STR, SPIDER_SQL_SPACE_LEN);
}
}
- item = item_list[roop_count];
- if ((error_num = spider_db_print_item_type(item, spider, str,
- alias, alias_length, dbton_id, use_fields, fields)))
+
+ /* Print the last operand value */
+ item = item_list[loop_count];
+ if ((error_num = spider_db_print_item_type(item, field, spider, str,
+ alias, alias_length,
+ dbton_id,
+ use_fields, fields)))
DBUG_RETURN(error_num);
}
+
if (item_func->functype() == Item_func::FT_FUNC)
{
Item_func_match *item_func_match = (Item_func_match *)item_func;
@@ -4613,8 +4666,9 @@ int spider_db_mysql_util::open_item_func(
str->q_append(SPIDER_SQL_AGAINST_STR, SPIDER_SQL_AGAINST_LEN);
}
item = item_list[0];
- if ((error_num = spider_db_print_item_type(item, spider, str,
- alias, alias_length, dbton_id, use_fields, fields)))
+ if ((error_num = spider_db_print_item_type(item, NULL, spider, str,
+ alias, alias_length, dbton_id,
+ use_fields, fields)))
DBUG_RETURN(error_num);
if (str)
{
@@ -4701,8 +4755,11 @@ int spider_db_mysql_util::open_item_sum_func(
for (roop_count = 0; roop_count < item_count; roop_count++)
{
item = args[roop_count];
- if ((error_num = spider_db_print_item_type(item, spider, str,
- alias, alias_length, dbton_id, use_fields, fields)))
+ if ((error_num = spider_db_print_item_type(item, NULL,
+ spider, str,
+ alias, alias_length,
+ dbton_id,
+ use_fields, fields)))
DBUG_RETURN(error_num);
if (str)
{
@@ -4712,8 +4769,10 @@ int spider_db_mysql_util::open_item_sum_func(
}
}
item = args[roop_count];
- if ((error_num = spider_db_print_item_type(item, spider, str,
- alias, alias_length, dbton_id, use_fields, fields)))
+ if ((error_num = spider_db_print_item_type(item, NULL, spider, str,
+ alias, alias_length,
+ dbton_id,
+ use_fields, fields)))
DBUG_RETURN(error_num);
}
if (str)
@@ -7592,8 +7651,9 @@ int spider_mysql_handler::check_item_type(
int error_num;
DBUG_ENTER("spider_mysql_handler::check_item_type");
DBUG_PRINT("info",("spider this=%p", this));
- error_num = spider_db_print_item_type(item, spider, NULL, NULL, 0,
- spider_dbton_mysql.dbton_id, FALSE, NULL);
+ error_num = spider_db_print_item_type(item, NULL, spider, NULL, NULL, 0,
+ spider_dbton_mysql.dbton_id,
+ FALSE, NULL);
DBUG_RETURN(error_num);
}
@@ -8391,9 +8451,11 @@ int spider_mysql_handler::append_condition(
str->q_append(SPIDER_SQL_AND_STR, SPIDER_SQL_AND_LEN);
}
}
- if ((error_num = spider_db_print_item_type(
- (Item *) tmp_cond->cond, spider, str, alias, alias_length,
- spider_dbton_mysql.dbton_id, FALSE, NULL)))
+ if ((error_num = spider_db_print_item_type((Item *) tmp_cond->cond,
+ NULL, spider, str,
+ alias, alias_length,
+ spider_dbton_mysql.dbton_id,
+ FALSE, NULL)))
{
if (str && error_num == ER_SPIDER_COND_SKIP_NUM)
{
@@ -8715,8 +8777,10 @@ int spider_mysql_handler::append_group_by(
str->q_append(SPIDER_SQL_GROUP_STR, SPIDER_SQL_GROUP_LEN);
for (; group; group = group->next)
{
- if ((error_num = spider_db_print_item_type((*group->item), spider, str,
- alias, alias_length, spider_dbton_mysql.dbton_id, FALSE, NULL)))
+ if ((error_num = spider_db_print_item_type((*group->item), NULL, spider,
+ str, alias, alias_length,
+ spider_dbton_mysql.dbton_id,
+ FALSE, NULL)))
{
DBUG_RETURN(error_num);
}
@@ -8908,8 +8972,9 @@ int spider_mysql_handler::append_key_order_for_direct_order_limit_with_alias(
order = order->next)
{
if ((error_num =
- spider_db_print_item_type((*order->item), spider, str, alias,
- alias_length, spider_dbton_mysql.dbton_id, FALSE, NULL)))
+ spider_db_print_item_type((*order->item), NULL, spider, str, alias,
+ alias_length, spider_dbton_mysql.dbton_id,
+ FALSE, NULL)))
{
DBUG_PRINT("info",("spider error=%d", error_num));
DBUG_RETURN(error_num);
@@ -12768,8 +12833,10 @@ int spider_mysql_handler::append_item_type_part(
default:
DBUG_RETURN(0);
}
- error_num = spider_db_print_item_type(item, spider, str, alias, alias_length,
- spider_dbton_mysql.dbton_id, use_fields, fields);
+ error_num = spider_db_print_item_type(item, NULL, spider, str,
+ alias, alias_length,
+ spider_dbton_mysql.dbton_id,
+ use_fields, fields);
DBUG_RETURN(error_num);
}
@@ -12815,8 +12882,9 @@ int spider_mysql_handler::append_list_item_select(
DBUG_PRINT("info",("spider this=%p", this));
while ((item = it++))
{
- if ((error_num = spider_db_print_item_type(item, spider, str,
- alias, alias_length, dbton_id, use_fields, fields)))
+ if ((error_num = spider_db_print_item_type(item, NULL, spider, str,
+ alias, alias_length, dbton_id,
+ use_fields, fields)))
{
DBUG_RETURN(error_num);
}
@@ -12883,8 +12951,10 @@ int spider_mysql_handler::append_group_by(
str->q_append(SPIDER_SQL_GROUP_STR, SPIDER_SQL_GROUP_LEN);
for (; order; order = order->next)
{
- if ((error_num = spider_db_print_item_type((*order->item), spider, str,
- alias, alias_length, dbton_id, use_fields, fields)))
+ if ((error_num = spider_db_print_item_type((*order->item), NULL, spider,
+ str, alias, alias_length,
+ dbton_id,
+ use_fields, fields)))
{
DBUG_RETURN(error_num);
}
@@ -12941,8 +13011,10 @@ int spider_mysql_handler::append_order_by(
str->q_append(SPIDER_SQL_ORDER_STR, SPIDER_SQL_ORDER_LEN);
for (; order; order = order->next)
{
- if ((error_num = spider_db_print_item_type((*order->item), spider, str,
- alias, alias_length, dbton_id, use_fields, fields)))
+ if ((error_num = spider_db_print_item_type((*order->item), NULL, spider,
+ str, alias, alias_length,
+ dbton_id,
+ use_fields, fields)))
{
DBUG_RETURN(error_num);
}
diff --git a/storage/spider/spd_db_mysql.h b/storage/spider/spd_db_mysql.h
index 766c15971ec..25cad01c66c 100644
--- a/storage/spider/spd_db_mysql.h
+++ b/storage/spider/spd_db_mysql.h
@@ -13,6 +13,8 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+#include "tztime.h"
+
class spider_db_mysql_util: public spider_db_util
{
public:
diff --git a/storage/spider/spd_db_oracle.h b/storage/spider/spd_db_oracle.h
index 2e9da5cab84..6962ff4884f 100644
--- a/storage/spider/spd_db_oracle.h
+++ b/storage/spider/spd_db_oracle.h
@@ -13,6 +13,8 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+#include "tztime.h"
+
class spider_db_oracle;
class spider_db_oracle_result;
diff --git a/storage/spider/spd_group_by_handler.cc b/storage/spider/spd_group_by_handler.cc
index 673248d0530..a5328464bb6 100644
--- a/storage/spider/spd_group_by_handler.cc
+++ b/storage/spider/spd_group_by_handler.cc
@@ -1727,8 +1727,8 @@ group_by_handler *spider_create_group_by_handler(
while ((item = it++))
{
DBUG_PRINT("info",("spider select item=%p", item));
- if (spider_db_print_item_type(item, spider, NULL, NULL, 0,
- roop_count, TRUE, fields_arg))
+ if (spider_db_print_item_type(item, NULL, spider, NULL, NULL, 0,
+ roop_count, TRUE, fields_arg))
{
DBUG_PRINT("info",("spider dbton_id=%d can't create select", roop_count));
spider_clear_bit(dbton_bitmap, roop_count);
@@ -1741,8 +1741,9 @@ group_by_handler *spider_create_group_by_handler(
DBUG_PRINT("info",("spider query->where=%p", query->where));
if (query->where)
{
- if (spider_db_print_item_type(query->where, spider, NULL, NULL, 0,
- roop_count, TRUE, fields_arg))
+ if (spider_db_print_item_type(query->where, NULL, spider, NULL,
+ NULL, 0, roop_count,
+ TRUE, fields_arg))
{
DBUG_PRINT("info",("spider dbton_id=%d can't create where", roop_count));
spider_clear_bit(dbton_bitmap, roop_count);
@@ -1757,8 +1758,9 @@ group_by_handler *spider_create_group_by_handler(
{
for (order = query->group_by; order; order = order->next)
{
- if (spider_db_print_item_type((*order->item), spider, NULL, NULL, 0,
- roop_count, TRUE, fields_arg))
+ if (spider_db_print_item_type((*order->item), NULL, spider, NULL,
+ NULL, 0, roop_count,
+ TRUE, fields_arg))
{
DBUG_PRINT("info",("spider dbton_id=%d can't create group by", roop_count));
spider_clear_bit(dbton_bitmap, roop_count);
@@ -1775,8 +1777,9 @@ group_by_handler *spider_create_group_by_handler(
{
for (order = query->order_by; order; order = order->next)
{
- if (spider_db_print_item_type((*order->item), spider, NULL, NULL, 0,
- roop_count, TRUE, fields_arg))
+ if (spider_db_print_item_type((*order->item), NULL, spider, NULL,
+ NULL, 0, roop_count,
+ TRUE, fields_arg))
{
DBUG_PRINT("info",("spider dbton_id=%d can't create order by", roop_count));
spider_clear_bit(dbton_bitmap, roop_count);
@@ -1791,8 +1794,9 @@ group_by_handler *spider_create_group_by_handler(
DBUG_PRINT("info",("spider query->having=%p", query->having));
if (query->having)
{
- if (spider_db_print_item_type(query->having, spider, NULL, NULL, 0,
- roop_count, TRUE, fields_arg))
+ if (spider_db_print_item_type(query->having, NULL, spider, NULL,
+ NULL, 0, roop_count,
+ TRUE, fields_arg))
{
DBUG_PRINT("info",("spider dbton_id=%d can't create having", roop_count));
spider_clear_bit(dbton_bitmap, roop_count);
diff --git a/storage/spider/spd_include.h b/storage/spider/spd_include.h
index bede60412e2..79e030b0872 100644
--- a/storage/spider/spd_include.h
+++ b/storage/spider/spd_include.h
@@ -13,6 +13,8 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+#include "tztime.h"
+
#define SPIDER_DETAIL_VERSION "3.3.13"
#define SPIDER_HEX_VERSION 0x0303
diff --git a/storage/spider/spd_param.cc b/storage/spider/spd_param.cc
index 9a771fe8357..9c7aa4dcdcb 100644
--- a/storage/spider/spd_param.cc
+++ b/storage/spider/spd_param.cc
@@ -929,26 +929,6 @@ bool spider_param_sync_autocommit(
}
/*
- FALSE: no sync
- TRUE: sync
- */
-static MYSQL_THDVAR_BOOL(
- sync_time_zone, /* name */
- PLUGIN_VAR_OPCMDARG, /* opt */
- "Sync time_zone", /* comment */
- NULL, /* check */
- NULL, /* update */
- FALSE /* def */
-);
-
-bool spider_param_sync_time_zone(
- THD *thd
-) {
- DBUG_ENTER("spider_param_sync_time_zone");
- DBUG_RETURN(THDVAR(thd, sync_time_zone));
-}
-
-/*
FALSE: not use
TRUE: use
*/
@@ -3332,7 +3312,6 @@ static struct st_mysql_sys_var* spider_system_variables[] = {
MYSQL_SYSVAR(block_size),
MYSQL_SYSVAR(selupd_lock_mode),
MYSQL_SYSVAR(sync_autocommit),
- MYSQL_SYSVAR(sync_time_zone),
MYSQL_SYSVAR(use_default_database),
MYSQL_SYSVAR(internal_sql_log_off),
MYSQL_SYSVAR(bulk_size),
diff --git a/storage/spider/spd_param.h b/storage/spider/spd_param.h
index 9a358c54be5..06df06a3129 100644
--- a/storage/spider/spd_param.h
+++ b/storage/spider/spd_param.h
@@ -107,9 +107,6 @@ int spider_param_selupd_lock_mode(
bool spider_param_sync_autocommit(
THD *thd
);
-bool spider_param_sync_time_zone(
- THD *thd
-);
bool spider_param_use_default_database(
THD *thd
);
diff --git a/storage/spider/spd_trx.cc b/storage/spider/spd_trx.cc
index cf60a0376bb..e09c7fa6c45 100644
--- a/storage/spider/spd_trx.cc
+++ b/storage/spider/spd_trx.cc
@@ -26,6 +26,7 @@
#include "sql_class.h"
#include "sql_partition.h"
#include "records.h"
+#include "tztime.h"
#endif
#include "spd_err.h"
#include "spd_param.h"
@@ -1840,7 +1841,6 @@ int spider_internal_start_trx(
SPIDER_TRX *trx = spider->trx;
THD *thd = trx->thd;
bool sync_autocommit = spider_param_sync_autocommit(thd);
- bool sync_time_zone = spider_param_sync_time_zone(thd);
double ping_interval_at_trx_start =
spider_param_ping_interval_at_trx_start(thd);
bool xa_lock = FALSE;
@@ -1867,9 +1867,6 @@ int spider_internal_start_trx(
if (
(error_num = spider_check_and_set_sql_log_off(thd, conn,
&spider->need_mons[link_idx])) ||
- (sync_time_zone &&
- (error_num = spider_check_and_set_time_zone(thd, conn,
- &spider->need_mons[link_idx]))) ||
(sync_autocommit &&
(error_num = spider_check_and_set_autocommit(thd, conn,
&spider->need_mons[link_idx])))