Skip to content

Commit 1e7b8f0

Browse files
Martin Hanssonroylyseng
Martin Hansson
authored andcommitted
WL#12535: Retrieve the stored timestamp as UTC datetime
Implement SQL standard clause AT TIME ZONE for values of type TIMESTAMP, combined with a CAST to DATETIME. The purpose of this is to convert the UTC part of a TIMESTAMP to a DATETIME, without also converting the value to the local time zone. It can be used to obtain the UTC value in the client. For this reason, the time zone part of the AT TIME ZONE clause must be specified as '+00:00' or UTC (which is equivalent to the former). For completeness, we also convert DATETIME values, such as literals, in the same manner. Reviewed by: Roy Lyseng <roy.lyseng@oracle.com> Change-Id: I805cd4722add368acc4ced383ae3c9cb786db4c3
1 parent a6ff2ae commit 1e7b8f0

19 files changed

+416
-84
lines changed

mysql-test/r/func_at_time_zone.result

+49
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
#
2+
# This file contains tests for the AT TIME ZONE operator.
3+
#
4+
SET time_zone = '+01:00';
5+
SELECT cast(TIMESTAMP'2019-10-10 10:11:12' AT TIME ZONE 'UTC' AS DATETIME);
6+
cast(TIMESTAMP'2019-10-10 10:11:12' AT TIME ZONE 'UTC' AS DATETIME)
7+
2019-10-10 09:11:12
8+
SELECT cast(TIMESTAMP'2019-10-10 10:11:12' AT TIME ZONE '+00:00' AS DATETIME);
9+
cast(TIMESTAMP'2019-10-10 10:11:12' AT TIME ZONE '+00:00' AS DATETIME)
10+
2019-10-10 09:11:12
11+
SELECT cast(TIMESTAMP'2019-10-10 10:11:12+00:00' AT TIME ZONE '+00:00' AS DATETIME);
12+
cast(TIMESTAMP'2019-10-10 10:11:12+00:00' AT TIME ZONE '+00:00' AS DATETIME)
13+
2019-10-10 10:11:12
14+
# Casting from invalid types.
15+
SELECT cast( TIME'10:10' AT TIME ZONE 'UTC' AS DATETIME );
16+
ERROR HY000: Cannot cast value to TIMESTAMP WITH TIME ZONE.
17+
SELECT cast( '2019-10-10' AT TIME ZONE 'UTC' AS DATETIME );
18+
ERROR HY000: Cannot cast value to TIMESTAMP WITH TIME ZONE.
19+
SELECT cast( 123 AT TIME ZONE 'UTC' AS DATETIME );
20+
ERROR HY000: Cannot cast value to TIMESTAMP WITH TIME ZONE.
21+
# Table data
22+
CREATE TABLE t1 ( a TIMESTAMP, b DATETIME );
23+
INSERT INTO t1 VALUES ( '2019-10-10 10:11:12+00:00', '2019-10-10 10:11:12+00:00' );
24+
SELECT * FROM t1;
25+
a b
26+
2019-10-10 11:11:12 2019-10-10 11:11:12
27+
SELECT cast( a AT TIME ZONE '+00:00' AS DATETIME ) FROM t1;
28+
cast( a AT TIME ZONE '+00:00' AS DATETIME )
29+
2019-10-10 10:11:12
30+
SELECT cast( b AT TIME ZONE '+00:00' AS DATETIME ) FROM t1;
31+
ERROR HY000: Cannot cast value to TIMESTAMP WITH TIME ZONE.
32+
SET time_zone = '+12:34';
33+
SELECT cast( a AT TIME ZONE '+00:00' AS DATETIME ) FROM t1;
34+
cast( a AT TIME ZONE '+00:00' AS DATETIME )
35+
2019-10-10 10:11:12
36+
SELECT cast( b AT TIME ZONE '+00:00' AS DATETIME ) FROM t1;
37+
ERROR HY000: Cannot cast value to TIMESTAMP WITH TIME ZONE.
38+
DROP TABLE t1;
39+
SELECT cast( '2019-10-10 10:11' AT TIME ZONE 'UTC' AS DATETIME );
40+
ERROR HY000: Cannot cast value to TIMESTAMP WITH TIME ZONE.
41+
SET time_zone = DEFAULT;
42+
#
43+
# Bug#31405594: WL12535: BACKTRACE:ITEM_FUNC_AT_TIME_ZONE |
44+
# SELECT_LEX_UNIT::EXECUTEITERATORQUER
45+
#
46+
RENAME TABLE mysql.time_zone TO time_zone_backup;
47+
CREATE TABLE t1 ( a TIMESTAMP );
48+
DROP TABLE t1;
49+
RENAME TABLE time_zone_backup TO mysql.time_zone;

mysql-test/r/information_schema_keywords.result

+1
Original file line numberDiff line numberDiff line change
@@ -710,3 +710,4 @@ XOR 1
710710
YEAR 0
711711
YEAR_MONTH 1
712712
ZEROFILL 1
713+
ZONE 0

mysql-test/r/parser.result

+46
Original file line numberDiff line numberDiff line change
@@ -2686,3 +2686,49 @@ SELECT @var;
26862686
SELECT @var;
26872687
@var
26882688
4
2689+
#
2690+
# <time zone> syntax.
2691+
#
2692+
SET time_zone = '+01:00';
2693+
SELECT cast( DATE'2019-10-10' AT LOCAL AS DATETIME );
2694+
ERROR 42000: This version of MySQL doesn't yet support 'AT LOCAL'
2695+
SELECT cast( DATE'2019-10-10' AT TIME ZONE 'UTC' AS DATETIME );
2696+
ERROR HY000: Cannot cast value to TIMESTAMP WITH TIME ZONE.
2697+
SELECT cast( TIME'10:10' AT LOCAL AS DATETIME );
2698+
ERROR 42000: This version of MySQL doesn't yet support 'AT LOCAL'
2699+
SELECT cast( TIME'10:10' AT TIME ZONE '+01:00' AS DATETIME );
2700+
ERROR HY000: Cannot cast value to TIMESTAMP WITH TIME ZONE.
2701+
SELECT cast( TIME'10:10' AT TIME ZONE INTERVAL 'UTC' AS DATETIME );
2702+
ERROR HY000: Cannot cast value to TIMESTAMP WITH TIME ZONE.
2703+
SELECT cast( TIME'10:10' AT TIME ZONE '' AS DATETIME );
2704+
ERROR HY000: Cannot cast value to TIMESTAMP WITH TIME ZONE.
2705+
SELECT cast( TIME'10:10' AT TIME ZONE INTERVAL '' AS DATETIME );
2706+
ERROR HY000: Cannot cast value to TIMESTAMP WITH TIME ZONE.
2707+
SELECT cast( TIMESTAMP'2019-10-10 10:11:12' AT LOCAL AS DATETIME );
2708+
ERROR 42000: This version of MySQL doesn't yet support 'AT LOCAL'
2709+
SELECT cast( NULL AT TIME ZONE 'UTC' AS DATETIME );
2710+
cast( NULL AT TIME ZONE 'UTC' AS DATETIME )
2711+
NULL
2712+
# Casting to prohibited types
2713+
SELECT cast( TIMESTAMP'2019-10-10 10:40:00' AT TIME ZONE 'UTC' AS BINARY );
2714+
ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'BINARY )' at line 1
2715+
SELECT cast( TIMESTAMP'2019-10-10 10:40:00' AT TIME ZONE 'UTC' AS CHAR );
2716+
ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'CHAR )' at line 1
2717+
SELECT cast( TIMESTAMP'2019-10-10 10:40:00' AT TIME ZONE 'UTC' AS DATE );
2718+
ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'DATE )' at line 1
2719+
SELECT cast( TIMESTAMP'2019-10-10 10:40:00' AT TIME ZONE 'UTC' AS DECIMAL );
2720+
ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'DECIMAL )' at line 1
2721+
SELECT cast( TIMESTAMP'2019-10-10 10:40:00' AT TIME ZONE 'UTC' AS DOUBLE );
2722+
ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'DOUBLE )' at line 1
2723+
SELECT cast( TIMESTAMP'2019-10-10 10:40:00' AT TIME ZONE 'UTC' AS FLOAT );
2724+
ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'FLOAT )' at line 1
2725+
SELECT cast( TIMESTAMP'2019-10-10 10:40:00' AT TIME ZONE 'UTC' AS SIGNED INTEGER );
2726+
ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'SIGNED INTEGER )' at line 1
2727+
SELECT cast( TIMESTAMP'2019-10-10 10:40:00' AT TIME ZONE 'UTC' AS TIME );
2728+
ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'TIME )' at line 1
2729+
SELECT cast( TIMESTAMP'2019-10-10 10:40:00' AT TIME ZONE 'UTC' AS UNSIGNED INTEGER );
2730+
ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'UNSIGNED INTEGER )' at line 1
2731+
SELECT cast( TIMESTAMP'2019-10-10 10:40:00' AT TIME ZONE 'UTC' AS JSON );
2732+
ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'JSON )' at line 1
2733+
SELECT cast( TIMESTAMP'2019-10-10 10:40:00' AT TIME ZONE 'UTC' AS REAL );
2734+
ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'REAL )' at line 1

mysql-test/t/func_at_time_zone.test

+57
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
--echo #
2+
--echo # This file contains tests for the AT TIME ZONE operator.
3+
--echo #
4+
5+
SET time_zone = '+01:00';
6+
7+
SELECT cast(TIMESTAMP'2019-10-10 10:11:12' AT TIME ZONE 'UTC' AS DATETIME);
8+
SELECT cast(TIMESTAMP'2019-10-10 10:11:12' AT TIME ZONE '+00:00' AS DATETIME);
9+
SELECT cast(TIMESTAMP'2019-10-10 10:11:12+00:00' AT TIME ZONE '+00:00' AS DATETIME);
10+
--echo # Casting from invalid types.
11+
--error ER_INVALID_CAST
12+
SELECT cast( TIME'10:10' AT TIME ZONE 'UTC' AS DATETIME );
13+
--error ER_INVALID_CAST
14+
SELECT cast( '2019-10-10' AT TIME ZONE 'UTC' AS DATETIME );
15+
--error ER_INVALID_CAST
16+
SELECT cast( 123 AT TIME ZONE 'UTC' AS DATETIME );
17+
18+
--echo # Table data
19+
CREATE TABLE t1 ( a TIMESTAMP, b DATETIME );
20+
21+
INSERT INTO t1 VALUES ( '2019-10-10 10:11:12+00:00', '2019-10-10 10:11:12+00:00' );
22+
23+
SELECT * FROM t1;
24+
25+
SELECT cast( a AT TIME ZONE '+00:00' AS DATETIME ) FROM t1;
26+
27+
--error ER_INVALID_CAST
28+
SELECT cast( b AT TIME ZONE '+00:00' AS DATETIME ) FROM t1;
29+
30+
SET time_zone = '+12:34';
31+
32+
SELECT cast( a AT TIME ZONE '+00:00' AS DATETIME ) FROM t1;
33+
34+
--error ER_INVALID_CAST
35+
SELECT cast( b AT TIME ZONE '+00:00' AS DATETIME ) FROM t1;
36+
37+
DROP TABLE t1;
38+
39+
--error ER_INVALID_CAST
40+
SELECT cast( '2019-10-10 10:11' AT TIME ZONE 'UTC' AS DATETIME );
41+
42+
SET time_zone = DEFAULT;
43+
44+
--echo #
45+
--echo # Bug#31405594: WL12535: BACKTRACE:ITEM_FUNC_AT_TIME_ZONE |
46+
--echo # SELECT_LEX_UNIT::EXECUTEITERATORQUER
47+
--echo #
48+
49+
RENAME TABLE mysql.time_zone TO time_zone_backup;
50+
51+
CREATE TABLE t1 ( a TIMESTAMP );
52+
#--error ER_UNKNOWN_TIME_ZONE
53+
#SELECT cast( a AT TIME ZONE 'UTC' AS DATETIME ) FROM t1;
54+
55+
DROP TABLE t1;
56+
57+
RENAME TABLE time_zone_backup TO mysql.time_zone;

mysql-test/t/parser.test

+51
Original file line numberDiff line numberDiff line change
@@ -2579,3 +2579,54 @@ SELECT @var;
25792579

25802580
(SELECT 4) INTO @var;
25812581
SELECT @var;
2582+
2583+
--echo #
2584+
--echo # <time zone> syntax.
2585+
--echo #
2586+
2587+
SET time_zone = '+01:00';
2588+
2589+
--error ER_NOT_SUPPORTED_YET
2590+
SELECT cast( DATE'2019-10-10' AT LOCAL AS DATETIME );
2591+
--error ER_INVALID_CAST
2592+
SELECT cast( DATE'2019-10-10' AT TIME ZONE 'UTC' AS DATETIME );
2593+
2594+
--error ER_NOT_SUPPORTED_YET
2595+
SELECT cast( TIME'10:10' AT LOCAL AS DATETIME );
2596+
--error ER_INVALID_CAST
2597+
SELECT cast( TIME'10:10' AT TIME ZONE '+01:00' AS DATETIME );
2598+
--error ER_INVALID_CAST
2599+
SELECT cast( TIME'10:10' AT TIME ZONE INTERVAL 'UTC' AS DATETIME );
2600+
--error ER_INVALID_CAST
2601+
SELECT cast( TIME'10:10' AT TIME ZONE '' AS DATETIME );
2602+
--error ER_INVALID_CAST
2603+
SELECT cast( TIME'10:10' AT TIME ZONE INTERVAL '' AS DATETIME );
2604+
2605+
--error ER_NOT_SUPPORTED_YET
2606+
SELECT cast( TIMESTAMP'2019-10-10 10:11:12' AT LOCAL AS DATETIME );
2607+
2608+
SELECT cast( NULL AT TIME ZONE 'UTC' AS DATETIME );
2609+
2610+
--echo # Casting to prohibited types
2611+
--error ER_PARSE_ERROR
2612+
SELECT cast( TIMESTAMP'2019-10-10 10:40:00' AT TIME ZONE 'UTC' AS BINARY );
2613+
--error ER_PARSE_ERROR
2614+
SELECT cast( TIMESTAMP'2019-10-10 10:40:00' AT TIME ZONE 'UTC' AS CHAR );
2615+
--error ER_PARSE_ERROR
2616+
SELECT cast( TIMESTAMP'2019-10-10 10:40:00' AT TIME ZONE 'UTC' AS DATE );
2617+
--error ER_PARSE_ERROR
2618+
SELECT cast( TIMESTAMP'2019-10-10 10:40:00' AT TIME ZONE 'UTC' AS DECIMAL );
2619+
--error ER_PARSE_ERROR
2620+
SELECT cast( TIMESTAMP'2019-10-10 10:40:00' AT TIME ZONE 'UTC' AS DOUBLE );
2621+
--error ER_PARSE_ERROR
2622+
SELECT cast( TIMESTAMP'2019-10-10 10:40:00' AT TIME ZONE 'UTC' AS FLOAT );
2623+
--error ER_PARSE_ERROR
2624+
SELECT cast( TIMESTAMP'2019-10-10 10:40:00' AT TIME ZONE 'UTC' AS SIGNED INTEGER );
2625+
--error ER_PARSE_ERROR
2626+
SELECT cast( TIMESTAMP'2019-10-10 10:40:00' AT TIME ZONE 'UTC' AS TIME );
2627+
--error ER_PARSE_ERROR
2628+
SELECT cast( TIMESTAMP'2019-10-10 10:40:00' AT TIME ZONE 'UTC' AS UNSIGNED INTEGER );
2629+
--error ER_PARSE_ERROR
2630+
SELECT cast( TIMESTAMP'2019-10-10 10:40:00' AT TIME ZONE 'UTC' AS JSON );
2631+
--error ER_PARSE_ERROR
2632+
SELECT cast( TIMESTAMP'2019-10-10 10:40:00' AT TIME ZONE 'UTC' AS REAL );

share/messages_to_clients.txt

+6
Original file line numberDiff line numberDiff line change
@@ -9402,6 +9402,12 @@ ER_CHARACTER_SET_MISMATCH
94029402
ER_WARN_VAR_VALUE_CHANGE_NOT_SUPPORTED
94039403
eng "Changing %s not supported on this platform. Falling back to the default."
94049404

9405+
ER_INVALID_TIME_ZONE_INTERVAL
9406+
eng "Invalid time zone interval: '%s'"
9407+
9408+
ER_INVALID_CAST
9409+
eng "Cannot cast value to %s."
9410+
94059411
ER_HYPERGRAPH_NOT_SUPPORTED_YET 42000
94069412
eng "The hypergraph optimizer does not yet support '%s'"
94079413

sql/event_parse_data.cc

+13-13
Original file line numberDiff line numberDiff line change
@@ -43,9 +43,9 @@
4343
#include "sql/sql_const.h"
4444
#include "sql/sql_error.h"
4545
#include "sql/sql_lex.h"
46-
#include "sql/sql_time.h" // TIME_to_timestamp
4746
#include "sql/table.h"
4847
#include "sql_string.h" // validate_string
48+
#include "tztime.h" // Time_zone
4949

5050
/*
5151
Set a name of the event
@@ -157,7 +157,6 @@ bool Event_parse_data::check_dates(THD *thd, int previous_on_completion) {
157157
*/
158158

159159
int Event_parse_data::init_execute_at(THD *thd) {
160-
bool not_used;
161160
MYSQL_TIME ltime;
162161
my_time_t ltime_utc;
163162

@@ -174,10 +173,11 @@ int Event_parse_data::init_execute_at(THD *thd) {
174173
(starts_null && ends_null)));
175174
DBUG_ASSERT(starts_null && ends_null);
176175

177-
if ((not_used = item_execute_at->get_date(&ltime, TIME_NO_ZERO_DATE)))
178-
goto wrong_value;
176+
if ((item_execute_at->get_date(&ltime, TIME_NO_ZERO_DATE))) goto wrong_value;
177+
178+
bool is_in_dst_gap_ignored;
179+
ltime_utc = thd->time_zone()->TIME_to_gmt_sec(&ltime, &is_in_dst_gap_ignored);
179180

180-
ltime_utc = TIME_to_timestamp(thd, &ltime, &not_used);
181181
if (!ltime_utc) {
182182
DBUG_PRINT("error", ("Execute AT after year 2037"));
183183
goto wrong_value;
@@ -319,7 +319,6 @@ int Event_parse_data::init_interval(THD *thd) {
319319
*/
320320

321321
int Event_parse_data::init_starts(THD *thd) {
322-
bool not_used;
323322
MYSQL_TIME ltime;
324323
my_time_t ltime_utc;
325324

@@ -329,10 +328,11 @@ int Event_parse_data::init_starts(THD *thd) {
329328
if (!item_starts->fixed && item_starts->fix_fields(thd, &item_starts))
330329
goto wrong_value;
331330

332-
if ((not_used = item_starts->get_date(&ltime, TIME_NO_ZERO_DATE)))
333-
goto wrong_value;
331+
if ((item_starts->get_date(&ltime, TIME_NO_ZERO_DATE))) goto wrong_value;
332+
333+
bool is_in_dst_gap_ignored;
334+
ltime_utc = thd->time_zone()->TIME_to_gmt_sec(&ltime, &is_in_dst_gap_ignored);
334335

335-
ltime_utc = TIME_to_timestamp(thd, &ltime, &not_used);
336336
if (!ltime_utc) goto wrong_value;
337337

338338
DBUG_PRINT("info", ("now: %ld starts: %ld", (long)thd->query_start_in_secs(),
@@ -368,7 +368,6 @@ int Event_parse_data::init_starts(THD *thd) {
368368
*/
369369

370370
int Event_parse_data::init_ends(THD *thd) {
371-
bool not_used;
372371
MYSQL_TIME ltime;
373372
my_time_t ltime_utc;
374373

@@ -379,10 +378,11 @@ int Event_parse_data::init_ends(THD *thd) {
379378
goto error_bad_params;
380379

381380
DBUG_PRINT("info", ("convert to TIME"));
382-
if ((not_used = item_ends->get_date(&ltime, TIME_NO_ZERO_DATE)))
383-
goto error_bad_params;
384381

385-
ltime_utc = TIME_to_timestamp(thd, &ltime, &not_used);
382+
if ((item_ends->get_date(&ltime, TIME_NO_ZERO_DATE))) goto error_bad_params;
383+
384+
bool is_in_dst_gap_ignored;
385+
ltime_utc = thd->time_zone()->TIME_to_gmt_sec(&ltime, &is_in_dst_gap_ignored);
386386
if (!ltime_utc) goto error_bad_params;
387387

388388
/* Check whether ends is after starts */

sql/field.cc

+6-5
Original file line numberDiff line numberDiff line change
@@ -2123,7 +2123,7 @@ bool Field::get_timestamp(struct timeval *tm, int *warnings) const {
21232123
MYSQL_TIME ltime;
21242124
DBUG_ASSERT(!is_null());
21252125
return get_date(&ltime, TIME_FUZZY_DATE) ||
2126-
datetime_to_timeval(current_thd, &ltime, tm, warnings);
2126+
datetime_to_timeval(&ltime, *current_thd->time_zone(), tm, warnings);
21272127
}
21282128

21292129
/**
@@ -4892,13 +4892,14 @@ void Field_temporal_with_date_and_time::store_timestamp(
48924892
}
48934893

48944894
bool Field_temporal_with_date_and_time::convert_TIME_to_timestamp(
4895-
THD *thd, const MYSQL_TIME *ltime, struct timeval *tm, int *warnings) {
4895+
const MYSQL_TIME *ltime, const Time_zone &tz, struct timeval *tm,
4896+
int *warnings) {
48964897
/*
48974898
No need to do check_date(TIME_NO_ZERO_IN_DATE),
48984899
because it has been done earlier in
48994900
store_time(), number_to_datetime() or str_to_datetime().
49004901
*/
4901-
if (datetime_with_no_zero_in_date_to_timeval(thd, ltime, tm, warnings)) {
4902+
if (datetime_with_no_zero_in_date_to_timeval(ltime, tz, tm, warnings)) {
49024903
tm->tv_sec = tm->tv_usec = 0;
49034904
return true;
49044905
}
@@ -4994,7 +4995,7 @@ type_conversion_status Field_timestamp::store_internal(const MYSQL_TIME *ltime,
49944995
int *warnings) {
49954996
THD *thd = table ? table->in_use : current_thd;
49964997
struct timeval tm;
4997-
convert_TIME_to_timestamp(thd, ltime, &tm, warnings);
4998+
convert_TIME_to_timestamp(ltime, *thd->time_zone(), &tm, warnings);
49984999
const type_conversion_status error =
49995000
time_warning_to_type_conversion_status(*warnings);
50005001
store_timestamp_internal(&tm);
@@ -5158,7 +5159,7 @@ type_conversion_status Field_timestampf::store_internal(const MYSQL_TIME *ltime,
51585159
int *warnings) {
51595160
THD *thd = table ? table->in_use : current_thd;
51605161
struct timeval tm;
5161-
convert_TIME_to_timestamp(thd, ltime, &tm, warnings);
5162+
convert_TIME_to_timestamp(ltime, *thd->time_zone(), &tm, warnings);
51625163
const type_conversion_status error =
51635164
time_warning_to_type_conversion_status(*warnings);
51645165
store_timestamp_internal(&tm);

sql/field.h

+8-3
Original file line numberDiff line numberDiff line change
@@ -1198,8 +1198,13 @@ class Field {
11981198
return TYPE_OK;
11991199
}
12001200
/**
1201-
Returns timestamp value in "struct timeval" format.
1202-
This method is used in "SELECT UNIX_TIMESTAMP(field)"
1201+
Returns a UTC component in `struct timeval` format. This interface
1202+
makes any column appear to be `TIMESTAMP`, i.e. stored in UTC, and
1203+
returns the UTC component in (optionally fractional) seconds. This means
1204+
converting _to_ UTC from the current session's time zone for types other
1205+
than `TIMESTAMP`.
1206+
1207+
This method was expressly written for `SELECT UNIX_TIMESTAMP(field)`
12031208
to avoid conversion from timestamp to MYSQL_TIME and back.
12041209
*/
12051210
virtual bool get_timestamp(struct timeval *tm, int *warnings) const;
@@ -2948,7 +2953,7 @@ class Field_temporal_with_date_and_time : public Field_temporal_with_date {
29482953
to the number of fractional second digits.
29492954
*/
29502955
virtual void store_timestamp_internal(const struct timeval *tm) = 0;
2951-
bool convert_TIME_to_timestamp(THD *thd, const MYSQL_TIME *ltime,
2956+
bool convert_TIME_to_timestamp(const MYSQL_TIME *ltime, const Time_zone &tz,
29522957
struct timeval *tm, int *error);
29532958

29542959
public:

sql/item.cc

+2-1
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,7 @@
7979
#include "sql/sql_view.h" // VIEW_ANY_ACL
8080
#include "sql/system_variables.h"
8181
#include "sql/thd_raii.h"
82+
#include "sql/tztime.h" // my_tz_UTC
8283
#include "template_utils.h"
8384
#include "typelib.h"
8485
#include "unsafe_string_append.h"
@@ -1415,7 +1416,7 @@ bool Item::get_timeval(struct timeval *tm, int *warnings) {
14151416
if (null_value) return true; /* Value is NULL */
14161417
goto zero; /* Could not extract date from the value */
14171418
}
1418-
if (datetime_to_timeval(current_thd, &ltime, tm, warnings))
1419+
if (datetime_to_timeval(&ltime, *current_thd->time_zone(), tm, warnings))
14191420
goto zero; /* Value is out of the supported range */
14201421
return false; /* Value is a good Unix timestamp */
14211422
zero:

0 commit comments

Comments
 (0)