mirror of
https://github.com/MariaDB/server.git
synced 2025-08-08 11:22:35 +03:00
MDEV-32148 Inefficient WHERE timestamp_column=datetime_const_expr
Changing the way how a the following conditions are evaluated: WHERE timestamp_column=datetime_const_expr (for all comparison operators: =, <=>, <, >, <=, >=, <> and for NULLIF) Before the change it was always performed as DATETIME. That was not efficient, as involved per-row TIMESTAMP->DATETIME conversion for timestamp_column. For example, in case of the SYSTEM time zone it involved a localtime_r() call, which is known to be slow. After the change it's performed as TIMESTAMP in many cases. This allows to avoid per-row conversion, as it works the other way around: datetime_const_expr is converted to TIMESTAMP once before the execution stage. Note, datetime_const_expr must be inside monotone continuous periods of the current time zone, i.e. not near these anomalies: - DST changes (spring forward, fall back) - leap seconds
This commit is contained in:
@@ -2917,7 +2917,7 @@ ORDER BY timestamp DESC;
|
||||
id select_type table type possible_keys key key_len ref rows filtered Extra
|
||||
1 SIMPLE t1 ALL ixEventWhoisDomainDomain,ixEventWhoisDomainTimestamp NULL NULL NULL 60 22.22 Using where; Using filesort
|
||||
Warnings:
|
||||
Note 1003 select `test`.`t1`.`id` AS `id`,`test`.`t1`.`domain` AS `domain`,`test`.`t1`.`registrant_name` AS `registrant_name`,`test`.`t1`.`registrant_organization` AS `registrant_organization`,`test`.`t1`.`registrant_street1` AS `registrant_street1`,`test`.`t1`.`registrant_street2` AS `registrant_street2`,`test`.`t1`.`registrant_street3` AS `registrant_street3`,`test`.`t1`.`registrant_street4` AS `registrant_street4`,`test`.`t1`.`registrant_street5` AS `registrant_street5`,`test`.`t1`.`registrant_city` AS `registrant_city`,`test`.`t1`.`registrant_postal_code` AS `registrant_postal_code`,`test`.`t1`.`registrant_country` AS `registrant_country`,`test`.`t1`.`registrant_email` AS `registrant_email`,`test`.`t1`.`registrant_telephone` AS `registrant_telephone`,`test`.`t1`.`administrative_name` AS `administrative_name`,`test`.`t1`.`administrative_organization` AS `administrative_organization`,`test`.`t1`.`administrative_street1` AS `administrative_street1`,`test`.`t1`.`administrative_street2` AS `administrative_street2`,`test`.`t1`.`administrative_street3` AS `administrative_street3`,`test`.`t1`.`administrative_street4` AS `administrative_street4`,`test`.`t1`.`administrative_street5` AS `administrative_street5`,`test`.`t1`.`administrative_city` AS `administrative_city`,`test`.`t1`.`administrative_postal_code` AS `administrative_postal_code`,`test`.`t1`.`administrative_country` AS `administrative_country`,`test`.`t1`.`administrative_email` AS `administrative_email`,`test`.`t1`.`administrative_telephone` AS `administrative_telephone`,`test`.`t1`.`technical_name` AS `technical_name`,`test`.`t1`.`technical_organization` AS `technical_organization`,`test`.`t1`.`technical_street1` AS `technical_street1`,`test`.`t1`.`technical_street2` AS `technical_street2`,`test`.`t1`.`technical_street3` AS `technical_street3`,`test`.`t1`.`technical_street4` AS `technical_street4`,`test`.`t1`.`technical_street5` AS `technical_street5`,`test`.`t1`.`technical_city` AS `technical_city`,`test`.`t1`.`technical_postal_code` AS `technical_postal_code`,`test`.`t1`.`technical_country` AS `technical_country`,`test`.`t1`.`technical_email` AS `technical_email`,`test`.`t1`.`technical_telephone` AS `technical_telephone`,`test`.`t1`.`json` AS `json`,`test`.`t1`.`timestamp` AS `timestamp` from `test`.`t1` where `test`.`t1`.`domain` = 'www.mailhost.i-dev.fr' and `test`.`t1`.`timestamp` >= <cache>('2017-01-30 08:24:51' + interval -1 month) order by `test`.`t1`.`timestamp` desc
|
||||
Note 1003 select `test`.`t1`.`id` AS `id`,`test`.`t1`.`domain` AS `domain`,`test`.`t1`.`registrant_name` AS `registrant_name`,`test`.`t1`.`registrant_organization` AS `registrant_organization`,`test`.`t1`.`registrant_street1` AS `registrant_street1`,`test`.`t1`.`registrant_street2` AS `registrant_street2`,`test`.`t1`.`registrant_street3` AS `registrant_street3`,`test`.`t1`.`registrant_street4` AS `registrant_street4`,`test`.`t1`.`registrant_street5` AS `registrant_street5`,`test`.`t1`.`registrant_city` AS `registrant_city`,`test`.`t1`.`registrant_postal_code` AS `registrant_postal_code`,`test`.`t1`.`registrant_country` AS `registrant_country`,`test`.`t1`.`registrant_email` AS `registrant_email`,`test`.`t1`.`registrant_telephone` AS `registrant_telephone`,`test`.`t1`.`administrative_name` AS `administrative_name`,`test`.`t1`.`administrative_organization` AS `administrative_organization`,`test`.`t1`.`administrative_street1` AS `administrative_street1`,`test`.`t1`.`administrative_street2` AS `administrative_street2`,`test`.`t1`.`administrative_street3` AS `administrative_street3`,`test`.`t1`.`administrative_street4` AS `administrative_street4`,`test`.`t1`.`administrative_street5` AS `administrative_street5`,`test`.`t1`.`administrative_city` AS `administrative_city`,`test`.`t1`.`administrative_postal_code` AS `administrative_postal_code`,`test`.`t1`.`administrative_country` AS `administrative_country`,`test`.`t1`.`administrative_email` AS `administrative_email`,`test`.`t1`.`administrative_telephone` AS `administrative_telephone`,`test`.`t1`.`technical_name` AS `technical_name`,`test`.`t1`.`technical_organization` AS `technical_organization`,`test`.`t1`.`technical_street1` AS `technical_street1`,`test`.`t1`.`technical_street2` AS `technical_street2`,`test`.`t1`.`technical_street3` AS `technical_street3`,`test`.`t1`.`technical_street4` AS `technical_street4`,`test`.`t1`.`technical_street5` AS `technical_street5`,`test`.`t1`.`technical_city` AS `technical_city`,`test`.`t1`.`technical_postal_code` AS `technical_postal_code`,`test`.`t1`.`technical_country` AS `technical_country`,`test`.`t1`.`technical_email` AS `technical_email`,`test`.`t1`.`technical_telephone` AS `technical_telephone`,`test`.`t1`.`json` AS `json`,`test`.`t1`.`timestamp` AS `timestamp` from `test`.`t1` where `test`.`t1`.`domain` = 'www.mailhost.i-dev.fr' and `test`.`t1`.`timestamp` >= TIMESTAMP/*WITH LOCAL TIME ZONE*/'2016-12-30 08:24:51' order by `test`.`t1`.`timestamp` desc
|
||||
SET optimizer_switch=@save_optimizer_switch;
|
||||
DROP TABLE t1;
|
||||
#
|
||||
|
@@ -678,3 +678,188 @@ SELECT a, UNIX_TIMESTAMP(a) FROM t1 WHERE a >= ALL (SELECT * FROM t1);
|
||||
a UNIX_TIMESTAMP(a)
|
||||
2010-10-31 02:25:25 1288481125
|
||||
DROP TABLE t1;
|
||||
#
|
||||
# MDEV-32148 Inefficient WHERE timestamp_column=datetime_expr
|
||||
#
|
||||
#
|
||||
# Testing a DST change (fall back)
|
||||
#
|
||||
SET time_zone='Europe/Moscow';
|
||||
SET @first_second_after_dst_fall_back=1288479600;
|
||||
CREATE TABLE t1 (a TIMESTAMP NULL);
|
||||
INSERT INTO t1 VALUES ('2001-01-01 10:20:30'),('2001-01-01 10:20:31');
|
||||
#
|
||||
# Optimized (more than 24 hours before the DST fall back)
|
||||
#
|
||||
SET timestamp=@first_second_after_dst_fall_back-24*3600-1;
|
||||
SELECT UNIX_TIMESTAMP(), NOW();
|
||||
UNIX_TIMESTAMP() NOW()
|
||||
1288393199 2010-10-30 02:59:59
|
||||
EXPLAIN EXTENDED SELECT * FROM t1 WHERE a=now();
|
||||
id select_type table type possible_keys key key_len ref rows filtered Extra
|
||||
1 SIMPLE t1 ALL NULL NULL NULL NULL 2 100.00 Using where
|
||||
Warnings:
|
||||
Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = TIMESTAMP/*WITH LOCAL TIME ZONE*/'2010-10-30 02:59:59'
|
||||
#
|
||||
# Not optimized (24 hours before the DST fall back)
|
||||
#
|
||||
SET timestamp=@first_second_after_dst_fall_back-24*3600;
|
||||
SELECT UNIX_TIMESTAMP(), NOW();
|
||||
UNIX_TIMESTAMP() NOW()
|
||||
1288393200 2010-10-30 03:00:00
|
||||
EXPLAIN EXTENDED SELECT * FROM t1 WHERE a=now();
|
||||
id select_type table type possible_keys key key_len ref rows filtered Extra
|
||||
1 SIMPLE t1 ALL NULL NULL NULL NULL 2 100.00 Using where
|
||||
Warnings:
|
||||
Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = <cache>(current_timestamp())
|
||||
#
|
||||
# Not optimized (less than 24 hours after the DST fall back)
|
||||
#
|
||||
SET timestamp=@first_second_after_dst_fall_back+24*3600-1;
|
||||
SELECT UNIX_TIMESTAMP(), NOW();
|
||||
UNIX_TIMESTAMP() NOW()
|
||||
1288565999 2010-11-01 01:59:59
|
||||
EXPLAIN EXTENDED SELECT * FROM t1 WHERE a=now();
|
||||
id select_type table type possible_keys key key_len ref rows filtered Extra
|
||||
1 SIMPLE t1 ALL NULL NULL NULL NULL 2 100.00 Using where
|
||||
Warnings:
|
||||
Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = <cache>(current_timestamp())
|
||||
#
|
||||
# Optimized (24 hours after the DST fall back)
|
||||
#
|
||||
SET timestamp=@first_second_after_dst_fall_back+24*3600;
|
||||
SELECT UNIX_TIMESTAMP(), NOW();
|
||||
UNIX_TIMESTAMP() NOW()
|
||||
1288566000 2010-11-01 02:00:00
|
||||
EXPLAIN EXTENDED SELECT * FROM t1 WHERE a=now();
|
||||
id select_type table type possible_keys key key_len ref rows filtered Extra
|
||||
1 SIMPLE t1 ALL NULL NULL NULL NULL 2 100.00 Using where
|
||||
Warnings:
|
||||
Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = TIMESTAMP/*WITH LOCAL TIME ZONE*/'2010-11-01 02:00:00'
|
||||
DROP TABLE t1;
|
||||
SET time_zone=DEFAULT;
|
||||
#
|
||||
# Testing a DST change (spring forward)
|
||||
#
|
||||
SET time_zone='Europe/Moscow';
|
||||
SET @first_second_after_dst_spring_forward=1301180400;
|
||||
CREATE TABLE t1 (a TIMESTAMP NULL);
|
||||
INSERT INTO t1 VALUES ('2001-01-01 10:20:30'),('2001-01-01 10:20:31');
|
||||
#
|
||||
# Optimized (more than 24 hours before the DST sprint forward)
|
||||
#
|
||||
SET timestamp=@first_second_after_dst_spring_forward-24*3600-1;
|
||||
SELECT UNIX_TIMESTAMP(), NOW();
|
||||
UNIX_TIMESTAMP() NOW()
|
||||
1301093999 2011-03-26 01:59:59
|
||||
EXPLAIN EXTENDED SELECT * FROM t1 WHERE a=now();
|
||||
id select_type table type possible_keys key key_len ref rows filtered Extra
|
||||
1 SIMPLE t1 ALL NULL NULL NULL NULL 2 100.00 Using where
|
||||
Warnings:
|
||||
Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = TIMESTAMP/*WITH LOCAL TIME ZONE*/'2011-03-26 01:59:59'
|
||||
#
|
||||
# Not optimized (24 hours before the DST sprint forward)
|
||||
#
|
||||
SET timestamp=@first_second_after_dst_spring_forward-24*3600;
|
||||
SELECT UNIX_TIMESTAMP(), NOW();
|
||||
UNIX_TIMESTAMP() NOW()
|
||||
1301094000 2011-03-26 02:00:00
|
||||
EXPLAIN EXTENDED SELECT * FROM t1 WHERE a=now();
|
||||
id select_type table type possible_keys key key_len ref rows filtered Extra
|
||||
1 SIMPLE t1 ALL NULL NULL NULL NULL 2 100.00 Using where
|
||||
Warnings:
|
||||
Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = <cache>(current_timestamp())
|
||||
#
|
||||
# Not optimized (less than 24 hours after the DST sprint forward)
|
||||
#
|
||||
SET timestamp=@first_second_after_dst_spring_forward+24*3600-1;
|
||||
SELECT UNIX_TIMESTAMP(), NOW();
|
||||
UNIX_TIMESTAMP() NOW()
|
||||
1301266799 2011-03-28 02:59:59
|
||||
EXPLAIN EXTENDED SELECT * FROM t1 WHERE a=now();
|
||||
id select_type table type possible_keys key key_len ref rows filtered Extra
|
||||
1 SIMPLE t1 ALL NULL NULL NULL NULL 2 100.00 Using where
|
||||
Warnings:
|
||||
Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = <cache>(current_timestamp())
|
||||
#
|
||||
# Optimized (24 hours after the DST sprint forward)
|
||||
#
|
||||
SET timestamp=@first_second_after_dst_spring_forward+24*3600;
|
||||
SELECT UNIX_TIMESTAMP(), NOW();
|
||||
UNIX_TIMESTAMP() NOW()
|
||||
1301266800 2011-03-28 03:00:00
|
||||
EXPLAIN EXTENDED SELECT * FROM t1 WHERE a=now();
|
||||
id select_type table type possible_keys key key_len ref rows filtered Extra
|
||||
1 SIMPLE t1 ALL NULL NULL NULL NULL 2 100.00 Using where
|
||||
Warnings:
|
||||
Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = TIMESTAMP/*WITH LOCAL TIME ZONE*/'2011-03-28 03:00:00'
|
||||
DROP TABLE t1;
|
||||
#
|
||||
# Testing a leap second
|
||||
#
|
||||
SET time_zone='leap/Europe/Moscow';
|
||||
SET @leap_second=362793609;
|
||||
/*The 60th leap second*/
|
||||
CREATE TABLE t1 (a TIMESTAMP);
|
||||
SET timestamp=@leap_second-1;
|
||||
INSERT INTO t1 VALUES (NOW());
|
||||
SET timestamp=@leap_second;
|
||||
INSERT INTO t1 VALUES (NOW());
|
||||
SET timestamp=@leap_second+1;
|
||||
INSERT INTO t1 VALUES (NOW());
|
||||
SELECT UNIX_TIMESTAMP(a), a FROM t1 ORDER BY UNIX_TIMESTAMP(a);
|
||||
UNIX_TIMESTAMP(a) a
|
||||
362793608 1981-07-01 03:59:59
|
||||
362793609 1981-07-01 03:59:59
|
||||
362793610 1981-07-01 04:00:00
|
||||
INSERT INTO t1 VALUES ('2001-01-01 10:20:30');
|
||||
#
|
||||
# Optimized (more than 24 hours before the leap second)
|
||||
#
|
||||
SET timestamp=@leap_second-24*3600-1;
|
||||
SELECT UNIX_TIMESTAMP(), NOW();
|
||||
UNIX_TIMESTAMP() NOW()
|
||||
362707208 1981-06-30 03:59:59
|
||||
EXPLAIN EXTENDED SELECT * FROM t1 WHERE a=now();
|
||||
id select_type table type possible_keys key key_len ref rows filtered Extra
|
||||
1 SIMPLE t1 ALL NULL NULL NULL NULL 4 100.00 Using where
|
||||
Warnings:
|
||||
Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = TIMESTAMP/*WITH LOCAL TIME ZONE*/'1981-06-30 03:59:59'
|
||||
#
|
||||
# Not optimized (24 hours before the leap second)
|
||||
#
|
||||
SET timestamp=@leap_second-24*3600;
|
||||
SELECT UNIX_TIMESTAMP(), NOW();
|
||||
UNIX_TIMESTAMP() NOW()
|
||||
362707209 1981-06-30 04:00:00
|
||||
EXPLAIN EXTENDED SELECT * FROM t1 WHERE a=now();
|
||||
id select_type table type possible_keys key key_len ref rows filtered Extra
|
||||
1 SIMPLE t1 ALL NULL NULL NULL NULL 4 100.00 Using where
|
||||
Warnings:
|
||||
Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = <cache>(current_timestamp())
|
||||
#
|
||||
# Not optimized (less than 24 hours after the leap second)
|
||||
#
|
||||
SET timestamp=@leap_second+24*3600-1;
|
||||
SELECT UNIX_TIMESTAMP(), NOW();
|
||||
UNIX_TIMESTAMP() NOW()
|
||||
362880008 1981-07-02 03:59:58
|
||||
EXPLAIN EXTENDED SELECT * FROM t1 WHERE a=now();
|
||||
id select_type table type possible_keys key key_len ref rows filtered Extra
|
||||
1 SIMPLE t1 ALL NULL NULL NULL NULL 4 100.00 Using where
|
||||
Warnings:
|
||||
Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = <cache>(current_timestamp())
|
||||
#
|
||||
# Not optimized (24 hours after the leap second)
|
||||
#
|
||||
SET timestamp=@leap_second+24*3600;
|
||||
SELECT UNIX_TIMESTAMP(), NOW();
|
||||
UNIX_TIMESTAMP() NOW()
|
||||
362880009 1981-07-02 03:59:59
|
||||
EXPLAIN EXTENDED SELECT * FROM t1 WHERE a=now();
|
||||
id select_type table type possible_keys key key_len ref rows filtered Extra
|
||||
1 SIMPLE t1 ALL NULL NULL NULL NULL 4 100.00 Using where
|
||||
Warnings:
|
||||
Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = TIMESTAMP/*WITH LOCAL TIME ZONE*/'1981-07-02 03:59:59'
|
||||
DROP TABLE t1;
|
||||
SET time_zone=DEFAULT;
|
||||
|
@@ -630,3 +630,155 @@ SELECT a, UNIX_TIMESTAMP(a) FROM t1 ORDER BY a;
|
||||
SELECT a, UNIX_TIMESTAMP(a) FROM t1 WHERE a <= ALL (SELECT * FROM t1);
|
||||
SELECT a, UNIX_TIMESTAMP(a) FROM t1 WHERE a >= ALL (SELECT * FROM t1);
|
||||
DROP TABLE t1;
|
||||
|
||||
|
||||
--echo #
|
||||
--echo # MDEV-32148 Inefficient WHERE timestamp_column=datetime_expr
|
||||
--echo #
|
||||
|
||||
--echo #
|
||||
--echo # Testing a DST change (fall back)
|
||||
--echo #
|
||||
|
||||
SET time_zone='Europe/Moscow';
|
||||
# '2010-10-31 02:59:59' (1288479599)
|
||||
# '2010-10-31 02:00:00' (1288479600)
|
||||
SET @first_second_after_dst_fall_back=1288479600;
|
||||
|
||||
CREATE TABLE t1 (a TIMESTAMP NULL);
|
||||
INSERT INTO t1 VALUES ('2001-01-01 10:20:30'),('2001-01-01 10:20:31');
|
||||
|
||||
--echo #
|
||||
--echo # Optimized (more than 24 hours before the DST fall back)
|
||||
--echo #
|
||||
|
||||
SET timestamp=@first_second_after_dst_fall_back-24*3600-1;
|
||||
SELECT UNIX_TIMESTAMP(), NOW();
|
||||
EXPLAIN EXTENDED SELECT * FROM t1 WHERE a=now();
|
||||
|
||||
--echo #
|
||||
--echo # Not optimized (24 hours before the DST fall back)
|
||||
--echo #
|
||||
|
||||
SET timestamp=@first_second_after_dst_fall_back-24*3600;
|
||||
SELECT UNIX_TIMESTAMP(), NOW();
|
||||
EXPLAIN EXTENDED SELECT * FROM t1 WHERE a=now();
|
||||
|
||||
--echo #
|
||||
--echo # Not optimized (less than 24 hours after the DST fall back)
|
||||
--echo #
|
||||
|
||||
SET timestamp=@first_second_after_dst_fall_back+24*3600-1;
|
||||
SELECT UNIX_TIMESTAMP(), NOW();
|
||||
EXPLAIN EXTENDED SELECT * FROM t1 WHERE a=now();
|
||||
|
||||
--echo #
|
||||
--echo # Optimized (24 hours after the DST fall back)
|
||||
--echo #
|
||||
|
||||
SET timestamp=@first_second_after_dst_fall_back+24*3600;
|
||||
SELECT UNIX_TIMESTAMP(), NOW();
|
||||
EXPLAIN EXTENDED SELECT * FROM t1 WHERE a=now();
|
||||
|
||||
DROP TABLE t1;
|
||||
SET time_zone=DEFAULT;
|
||||
|
||||
|
||||
--echo #
|
||||
--echo # Testing a DST change (spring forward)
|
||||
--echo #
|
||||
|
||||
SET time_zone='Europe/Moscow';
|
||||
# '2011-03-27 01:59:59' (1301180399)
|
||||
# '2011-03-27 03:00:00' (1301180400)
|
||||
SET @first_second_after_dst_spring_forward=1301180400;
|
||||
|
||||
CREATE TABLE t1 (a TIMESTAMP NULL);
|
||||
INSERT INTO t1 VALUES ('2001-01-01 10:20:30'),('2001-01-01 10:20:31');
|
||||
|
||||
--echo #
|
||||
--echo # Optimized (more than 24 hours before the DST sprint forward)
|
||||
--echo #
|
||||
|
||||
SET timestamp=@first_second_after_dst_spring_forward-24*3600-1;
|
||||
SELECT UNIX_TIMESTAMP(), NOW();
|
||||
EXPLAIN EXTENDED SELECT * FROM t1 WHERE a=now();
|
||||
|
||||
--echo #
|
||||
--echo # Not optimized (24 hours before the DST sprint forward)
|
||||
--echo #
|
||||
|
||||
SET timestamp=@first_second_after_dst_spring_forward-24*3600;
|
||||
SELECT UNIX_TIMESTAMP(), NOW();
|
||||
EXPLAIN EXTENDED SELECT * FROM t1 WHERE a=now();
|
||||
|
||||
--echo #
|
||||
--echo # Not optimized (less than 24 hours after the DST sprint forward)
|
||||
--echo #
|
||||
|
||||
SET timestamp=@first_second_after_dst_spring_forward+24*3600-1;
|
||||
SELECT UNIX_TIMESTAMP(), NOW();
|
||||
EXPLAIN EXTENDED SELECT * FROM t1 WHERE a=now();
|
||||
|
||||
--echo #
|
||||
--echo # Optimized (24 hours after the DST sprint forward)
|
||||
--echo #
|
||||
|
||||
SET timestamp=@first_second_after_dst_spring_forward+24*3600;
|
||||
SELECT UNIX_TIMESTAMP(), NOW();
|
||||
EXPLAIN EXTENDED SELECT * FROM t1 WHERE a=now();
|
||||
|
||||
DROP TABLE t1;
|
||||
|
||||
--echo #
|
||||
--echo # Testing a leap second
|
||||
--echo #
|
||||
|
||||
SET time_zone='leap/Europe/Moscow';
|
||||
SET @leap_second=362793609; /*The 60th leap second*/
|
||||
|
||||
CREATE TABLE t1 (a TIMESTAMP);
|
||||
SET timestamp=@leap_second-1;
|
||||
INSERT INTO t1 VALUES (NOW());
|
||||
SET timestamp=@leap_second;
|
||||
INSERT INTO t1 VALUES (NOW());
|
||||
SET timestamp=@leap_second+1;
|
||||
INSERT INTO t1 VALUES (NOW());
|
||||
SELECT UNIX_TIMESTAMP(a), a FROM t1 ORDER BY UNIX_TIMESTAMP(a);
|
||||
INSERT INTO t1 VALUES ('2001-01-01 10:20:30');
|
||||
|
||||
--echo #
|
||||
--echo # Optimized (more than 24 hours before the leap second)
|
||||
--echo #
|
||||
|
||||
SET timestamp=@leap_second-24*3600-1;
|
||||
SELECT UNIX_TIMESTAMP(), NOW();
|
||||
EXPLAIN EXTENDED SELECT * FROM t1 WHERE a=now();
|
||||
|
||||
--echo #
|
||||
--echo # Not optimized (24 hours before the leap second)
|
||||
--echo #
|
||||
|
||||
SET timestamp=@leap_second-24*3600;
|
||||
SELECT UNIX_TIMESTAMP(), NOW();
|
||||
EXPLAIN EXTENDED SELECT * FROM t1 WHERE a=now();
|
||||
|
||||
--echo #
|
||||
--echo # Not optimized (less than 24 hours after the leap second)
|
||||
--echo #
|
||||
|
||||
SET timestamp=@leap_second+24*3600-1;
|
||||
SELECT UNIX_TIMESTAMP(), NOW();
|
||||
EXPLAIN EXTENDED SELECT * FROM t1 WHERE a=now();
|
||||
|
||||
--echo #
|
||||
--echo # Not optimized (24 hours after the leap second)
|
||||
--echo #
|
||||
|
||||
SET timestamp=@leap_second+24*3600;
|
||||
SELECT UNIX_TIMESTAMP(), NOW();
|
||||
EXPLAIN EXTENDED SELECT * FROM t1 WHERE a=now();
|
||||
|
||||
DROP TABLE t1;
|
||||
|
||||
SET time_zone=DEFAULT;
|
||||
|
@@ -872,13 +872,13 @@ SELECT * FROM t1 WHERE LENGTH(a)=19 AND a=' 2001-01-01 00:00:00';
|
||||
id select_type table type possible_keys key key_len ref rows filtered Extra
|
||||
1 SIMPLE t1 ALL NULL NULL NULL NULL 2 100.00 Using where
|
||||
Warnings:
|
||||
Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = TIMESTAMP'2001-01-01 00:00:00'
|
||||
Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = TIMESTAMP/*WITH LOCAL TIME ZONE*/'2001-01-01 00:00:00'
|
||||
EXPLAIN EXTENDED
|
||||
SELECT * FROM t1 WHERE LENGTH(a)=19+RAND() AND a=' 2001-01-01 00:00:00';
|
||||
id select_type table type possible_keys key key_len ref rows filtered Extra
|
||||
1 SIMPLE t1 ALL NULL NULL NULL NULL 2 100.00 Using where
|
||||
Warnings:
|
||||
Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = TIMESTAMP'2001-01-01 00:00:00' and <cache>(octet_length(TIMESTAMP'2001-01-01 00:00:00')) = 19 + rand()
|
||||
Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = TIMESTAMP/*WITH LOCAL TIME ZONE*/'2001-01-01 00:00:00' and <cache>(octet_length(TIMESTAMP/*WITH LOCAL TIME ZONE*/'2001-01-01 00:00:00')) = 19 + rand()
|
||||
EXPLAIN EXTENDED
|
||||
SELECT * FROM t1 WHERE LENGTH(a)=30+RAND() AND a=' garbage ';
|
||||
id select_type table type possible_keys key key_len ref rows filtered Extra
|
||||
@@ -905,13 +905,13 @@ SELECT * FROM t1 WHERE LENGTH(a)=19 AND a=TIMESTAMP'2001-01-01 00:00:00.000000';
|
||||
id select_type table type possible_keys key key_len ref rows filtered Extra
|
||||
1 SIMPLE t1 ALL NULL NULL NULL NULL 2 100.00 Using where
|
||||
Warnings:
|
||||
Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = TIMESTAMP'2001-01-01 00:00:00.000000'
|
||||
Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = TIMESTAMP/*WITH LOCAL TIME ZONE*/'2001-01-01 00:00:00.000000'
|
||||
EXPLAIN EXTENDED
|
||||
SELECT * FROM t1 WHERE LENGTH(a)=30+RAND() AND a=TIMESTAMP'2001-01-01 00:00:00.000000';
|
||||
id select_type table type possible_keys key key_len ref rows filtered Extra
|
||||
1 SIMPLE t1 ALL NULL NULL NULL NULL 2 100.00 Using where
|
||||
Warnings:
|
||||
Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = TIMESTAMP'2001-01-01 00:00:00.000000' and <cache>(octet_length(TIMESTAMP'2001-01-01 00:00:00')) = 30 + rand()
|
||||
Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = TIMESTAMP/*WITH LOCAL TIME ZONE*/'2001-01-01 00:00:00.000000' and <cache>(octet_length(TIMESTAMP'2001-01-01 00:00:00')) = 30 + rand()
|
||||
DROP TABLE t1;
|
||||
CREATE TABLE t1 (a TIMESTAMP(6));;
|
||||
INSERT INTO t1 VALUES ('2001-01-01 00:00:00.000000'),('2001-01-01 00:00:01.000000');
|
||||
@@ -930,13 +930,13 @@ SELECT * FROM t1 WHERE LENGTH(a)=26 AND a=TIMESTAMP'2001-01-01 00:00:00.000000';
|
||||
id select_type table type possible_keys key key_len ref rows filtered Extra
|
||||
1 SIMPLE t1 ALL NULL NULL NULL NULL 2 100.00 Using where
|
||||
Warnings:
|
||||
Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = TIMESTAMP'2001-01-01 00:00:00.000000'
|
||||
Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = TIMESTAMP/*WITH LOCAL TIME ZONE*/'2001-01-01 00:00:00.000000'
|
||||
EXPLAIN EXTENDED
|
||||
SELECT * FROM t1 WHERE LENGTH(a)=40+RAND() AND a=TIMESTAMP'2001-01-01 00:00:00.000000';
|
||||
id select_type table type possible_keys key key_len ref rows filtered Extra
|
||||
1 SIMPLE t1 ALL NULL NULL NULL NULL 2 100.00 Using where
|
||||
Warnings:
|
||||
Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = TIMESTAMP'2001-01-01 00:00:00.000000' and <cache>(octet_length(TIMESTAMP'2001-01-01 00:00:00.000000')) = 40 + rand()
|
||||
Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = TIMESTAMP/*WITH LOCAL TIME ZONE*/'2001-01-01 00:00:00.000000' and <cache>(octet_length(TIMESTAMP/*WITH LOCAL TIME ZONE*/'2001-01-01 00:00:00.000000')) = 40 + rand()
|
||||
DROP TABLE t1;
|
||||
SET timestamp=UNIX_TIMESTAMP('2001-01-01 10:20:30');
|
||||
CREATE TABLE t1 (a TIMESTAMP);;
|
||||
@@ -956,13 +956,13 @@ SELECT * FROM t1 WHERE LENGTH(a)=19 AND a=TIME'00:00:00';
|
||||
id select_type table type possible_keys key key_len ref rows filtered Extra
|
||||
1 SIMPLE t1 ALL NULL NULL NULL NULL 2 100.00 Using where
|
||||
Warnings:
|
||||
Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = TIMESTAMP'2001-01-01 00:00:00'
|
||||
Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = TIMESTAMP/*WITH LOCAL TIME ZONE*/'2001-01-01 00:00:00'
|
||||
EXPLAIN EXTENDED
|
||||
SELECT * FROM t1 WHERE LENGTH(a)=40+RAND() AND a=TIME'00:00:00';
|
||||
id select_type table type possible_keys key key_len ref rows filtered Extra
|
||||
1 SIMPLE t1 ALL NULL NULL NULL NULL 2 100.00 Using where
|
||||
Warnings:
|
||||
Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = TIMESTAMP'2001-01-01 00:00:00' and <cache>(octet_length(TIMESTAMP'2001-01-01 00:00:00')) = 40 + rand()
|
||||
Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = TIMESTAMP/*WITH LOCAL TIME ZONE*/'2001-01-01 00:00:00' and <cache>(octet_length(TIMESTAMP/*WITH LOCAL TIME ZONE*/'2001-01-01 00:00:00')) = 40 + rand()
|
||||
DROP TABLE t1;
|
||||
#
|
||||
# End of 10.1 tests
|
||||
@@ -1347,6 +1347,540 @@ SET time_zone=DEFAULT;
|
||||
# End of 10.4 tests
|
||||
#
|
||||
#
|
||||
# Start of 10.6 tests
|
||||
#
|
||||
#
|
||||
# MDEV-32148 Inefficient WHERE timestamp_column=datetime_expr
|
||||
#
|
||||
SET time_zone='+00:00';
|
||||
CREATE TABLE t1 (a TIMESTAMP);
|
||||
INSERT INTO t1 VALUES ('0000-00-00 00:00:00');
|
||||
INSERT INTO t1 VALUES ('2001-01-01 10:20:30'), ('2001-01-01 10:20:31');
|
||||
#
|
||||
# Comparison predicates: Bad TIMESTAMP values preserve DATETIME comparison
|
||||
#
|
||||
EXPLAIN EXTENDED SELECT * FROM t1 WHERE a=TIMESTAMP'1001-01-01 10:20:30';
|
||||
id select_type table type possible_keys key key_len ref rows filtered Extra
|
||||
1 SIMPLE t1 ALL NULL NULL NULL NULL 3 100.00 Using where
|
||||
Warnings:
|
||||
Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = TIMESTAMP'1001-01-01 10:20:30'
|
||||
EXPLAIN EXTENDED SELECT * FROM t1 WHERE a=TIMESTAMP'2001-01-00 00:00:00';
|
||||
id select_type table type possible_keys key key_len ref rows filtered Extra
|
||||
1 SIMPLE t1 ALL NULL NULL NULL NULL 3 100.00 Using where
|
||||
Warnings:
|
||||
Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = TIMESTAMP'2001-01-00 00:00:00'
|
||||
EXPLAIN EXTENDED SELECT * FROM t1 WHERE a=TIMESTAMP'2040-01-01 10:20:30';
|
||||
id select_type table type possible_keys key key_len ref rows filtered Extra
|
||||
1 SIMPLE t1 ALL NULL NULL NULL NULL 3 100.00 Using where
|
||||
Warnings:
|
||||
Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = TIMESTAMP'2040-01-01 10:20:30'
|
||||
EXPLAIN EXTENDED SELECT * FROM t1 WHERE a='1001-01-01 10:20:30';
|
||||
id select_type table type possible_keys key key_len ref rows filtered Extra
|
||||
1 SIMPLE t1 ALL NULL NULL NULL NULL 3 100.00 Using where
|
||||
Warnings:
|
||||
Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = TIMESTAMP'1001-01-01 10:20:30'
|
||||
EXPLAIN EXTENDED SELECT * FROM t1 WHERE a='2001-01-00 00:00:00';
|
||||
id select_type table type possible_keys key key_len ref rows filtered Extra
|
||||
1 SIMPLE t1 ALL NULL NULL NULL NULL 3 100.00 Using where
|
||||
Warnings:
|
||||
Warning 1292 Incorrect datetime value: '2001-01-00 00:00:00'
|
||||
Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = '2001-01-00 00:00:00'
|
||||
EXPLAIN EXTENDED SELECT * FROM t1 WHERE a='2040-01-01 10:20:30';
|
||||
id select_type table type possible_keys key key_len ref rows filtered Extra
|
||||
1 SIMPLE t1 ALL NULL NULL NULL NULL 3 100.00 Using where
|
||||
Warnings:
|
||||
Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = TIMESTAMP'2040-01-01 10:20:30'
|
||||
EXPLAIN EXTENDED SELECT * FROM t1 WHERE a=10010101102030;
|
||||
id select_type table type possible_keys key key_len ref rows filtered Extra
|
||||
1 SIMPLE t1 ALL NULL NULL NULL NULL 3 100.00 Using where
|
||||
Warnings:
|
||||
Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = 10010101102030
|
||||
EXPLAIN EXTENDED SELECT * FROM t1 WHERE a=20010100000000;
|
||||
id select_type table type possible_keys key key_len ref rows filtered Extra
|
||||
1 SIMPLE t1 ALL NULL NULL NULL NULL 3 100.00 Using where
|
||||
Warnings:
|
||||
Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = 20010100000000
|
||||
EXPLAIN EXTENDED SELECT * FROM t1 WHERE a=20400101102030;
|
||||
id select_type table type possible_keys key key_len ref rows filtered Extra
|
||||
1 SIMPLE t1 ALL NULL NULL NULL NULL 3 100.00 Using where
|
||||
Warnings:
|
||||
Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = 20400101102030
|
||||
EXPLAIN EXTENDED SELECT * FROM t1 WHERE a=10010101102030e0;
|
||||
id select_type table type possible_keys key key_len ref rows filtered Extra
|
||||
1 SIMPLE t1 ALL NULL NULL NULL NULL 3 100.00 Using where
|
||||
Warnings:
|
||||
Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = 10010101102030e0
|
||||
EXPLAIN EXTENDED SELECT * FROM t1 WHERE a=20010100000000e0;
|
||||
id select_type table type possible_keys key key_len ref rows filtered Extra
|
||||
1 SIMPLE t1 ALL NULL NULL NULL NULL 3 100.00 Using where
|
||||
Warnings:
|
||||
Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = 20010100000000e0
|
||||
EXPLAIN EXTENDED SELECT * FROM t1 WHERE a=20400101102030e0;
|
||||
id select_type table type possible_keys key key_len ref rows filtered Extra
|
||||
1 SIMPLE t1 ALL NULL NULL NULL NULL 3 100.00 Using where
|
||||
Warnings:
|
||||
Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = 20400101102030e0
|
||||
EXPLAIN EXTENDED SELECT * FROM t1 WHERE a=10010101102030.0;
|
||||
id select_type table type possible_keys key key_len ref rows filtered Extra
|
||||
1 SIMPLE t1 ALL NULL NULL NULL NULL 3 100.00 Using where
|
||||
Warnings:
|
||||
Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = 10010101102030.0
|
||||
EXPLAIN EXTENDED SELECT * FROM t1 WHERE a=20010100000000.0;
|
||||
id select_type table type possible_keys key key_len ref rows filtered Extra
|
||||
1 SIMPLE t1 ALL NULL NULL NULL NULL 3 100.00 Using where
|
||||
Warnings:
|
||||
Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = 20010100000000.0
|
||||
EXPLAIN EXTENDED SELECT * FROM t1 WHERE a=20400101102030.0;
|
||||
id select_type table type possible_keys key key_len ref rows filtered Extra
|
||||
1 SIMPLE t1 ALL NULL NULL NULL NULL 3 100.00 Using where
|
||||
Warnings:
|
||||
Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = 20400101102030.0
|
||||
EXPLAIN EXTENDED SELECT * FROM t1 WHERE a=DATE_ADD('2020-01-01 10:20:30', INTERVAL 30 YEAR);
|
||||
id select_type table type possible_keys key key_len ref rows filtered Extra
|
||||
1 SIMPLE t1 ALL NULL NULL NULL NULL 3 100.00 Using where
|
||||
Warnings:
|
||||
Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = TIMESTAMP'2050-01-01 10:20:30'
|
||||
EXPLAIN EXTENDED SELECT * FROM t1 WHERE COALESCE(NULL, a)=DATE_ADD('2020-01-01 10:20:30', INTERVAL 30 YEAR);
|
||||
id select_type table type possible_keys key key_len ref rows filtered Extra
|
||||
1 SIMPLE t1 ALL NULL NULL NULL NULL 3 100.00 Using where
|
||||
Warnings:
|
||||
Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where coalesce(NULL,`test`.`t1`.`a`) = <cache>('2020-01-01 10:20:30' + interval 30 year)
|
||||
#
|
||||
# Comparison predicates: Good TIMESTAMP values switch to TIMESTAMP comparison
|
||||
#
|
||||
EXPLAIN EXTENDED SELECT * FROM t1 WHERE a=TIMESTAMP'0000-00-00 00:00:00';
|
||||
id select_type table type possible_keys key key_len ref rows filtered Extra
|
||||
1 SIMPLE t1 ALL NULL NULL NULL NULL 3 100.00 Using where
|
||||
Warnings:
|
||||
Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = TIMESTAMP/*WITH LOCAL TIME ZONE*/'0000-00-00 00:00:00'
|
||||
EXPLAIN EXTENDED SELECT * FROM t1 WHERE a=TIMESTAMP'2001-01-01 10:20:30';
|
||||
id select_type table type possible_keys key key_len ref rows filtered Extra
|
||||
1 SIMPLE t1 ALL NULL NULL NULL NULL 3 100.00 Using where
|
||||
Warnings:
|
||||
Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = TIMESTAMP/*WITH LOCAL TIME ZONE*/'2001-01-01 10:20:30'
|
||||
EXPLAIN EXTENDED SELECT * FROM t1 WHERE a='0000-00-00 00:00:00';
|
||||
id select_type table type possible_keys key key_len ref rows filtered Extra
|
||||
1 SIMPLE t1 ALL NULL NULL NULL NULL 3 100.00 Using where
|
||||
Warnings:
|
||||
Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = TIMESTAMP/*WITH LOCAL TIME ZONE*/'0000-00-00 00:00:00'
|
||||
EXPLAIN EXTENDED SELECT * FROM t1 WHERE a='2001-01-01 10:20:30';
|
||||
id select_type table type possible_keys key key_len ref rows filtered Extra
|
||||
1 SIMPLE t1 ALL NULL NULL NULL NULL 3 100.00 Using where
|
||||
Warnings:
|
||||
Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = TIMESTAMP/*WITH LOCAL TIME ZONE*/'2001-01-01 10:20:30'
|
||||
EXPLAIN EXTENDED SELECT * FROM t1 WHERE a=0;
|
||||
id select_type table type possible_keys key key_len ref rows filtered Extra
|
||||
1 SIMPLE t1 ALL NULL NULL NULL NULL 3 100.00 Using where
|
||||
Warnings:
|
||||
Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = TIMESTAMP/*WITH LOCAL TIME ZONE*/'0000-00-00 00:00:00'
|
||||
EXPLAIN EXTENDED SELECT * FROM t1 WHERE a=20010101102030;
|
||||
id select_type table type possible_keys key key_len ref rows filtered Extra
|
||||
1 SIMPLE t1 ALL NULL NULL NULL NULL 3 100.00 Using where
|
||||
Warnings:
|
||||
Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = TIMESTAMP/*WITH LOCAL TIME ZONE*/'2001-01-01 10:20:30'
|
||||
EXPLAIN EXTENDED SELECT * FROM t1 WHERE a=0e0;
|
||||
id select_type table type possible_keys key key_len ref rows filtered Extra
|
||||
1 SIMPLE t1 ALL NULL NULL NULL NULL 3 100.00 Using where
|
||||
Warnings:
|
||||
Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = TIMESTAMP/*WITH LOCAL TIME ZONE*/'0000-00-00 00:00:00.000000'
|
||||
EXPLAIN EXTENDED SELECT * FROM t1 WHERE a=20010101102030e0;
|
||||
id select_type table type possible_keys key key_len ref rows filtered Extra
|
||||
1 SIMPLE t1 ALL NULL NULL NULL NULL 3 100.00 Using where
|
||||
Warnings:
|
||||
Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = TIMESTAMP/*WITH LOCAL TIME ZONE*/'2001-01-01 10:20:30.000000'
|
||||
EXPLAIN EXTENDED SELECT * FROM t1 WHERE a=0.0;
|
||||
id select_type table type possible_keys key key_len ref rows filtered Extra
|
||||
1 SIMPLE t1 ALL NULL NULL NULL NULL 3 100.00 Using where
|
||||
Warnings:
|
||||
Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = TIMESTAMP/*WITH LOCAL TIME ZONE*/'0000-00-00 00:00:00.0'
|
||||
EXPLAIN EXTENDED SELECT * FROM t1 WHERE a=20010101102030.0;
|
||||
id select_type table type possible_keys key key_len ref rows filtered Extra
|
||||
1 SIMPLE t1 ALL NULL NULL NULL NULL 3 100.00 Using where
|
||||
Warnings:
|
||||
Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = TIMESTAMP/*WITH LOCAL TIME ZONE*/'2001-01-01 10:20:30.0'
|
||||
EXPLAIN EXTENDED SELECT * FROM t1 WHERE a=DATE_ADD('2001-01-01 10:20:00', INTERVAL 30 SECOND);
|
||||
id select_type table type possible_keys key key_len ref rows filtered Extra
|
||||
1 SIMPLE t1 ALL NULL NULL NULL NULL 3 100.00 Using where
|
||||
Warnings:
|
||||
Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = TIMESTAMP/*WITH LOCAL TIME ZONE*/'2001-01-01 10:20:30'
|
||||
EXPLAIN EXTENDED SELECT * FROM t1 WHERE COALESCE(NULL, a)=DATE_ADD('2001-01-01 10:20:00', INTERVAL 30 SECOND);
|
||||
id select_type table type possible_keys key key_len ref rows filtered Extra
|
||||
1 SIMPLE t1 ALL NULL NULL NULL NULL 3 100.00 Using where
|
||||
Warnings:
|
||||
Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where coalesce(NULL,`test`.`t1`.`a`) = TIMESTAMP/*WITH LOCAL TIME ZONE*/'2001-01-01 10:20:30'
|
||||
#
|
||||
# Corner cases: DATETIME values before the supported optimization range
|
||||
# FROM_UNIXTIME(0)..FROM_UNIXTIME(24*3600-1)
|
||||
#
|
||||
EXPLAIN EXTENDED SELECT * FROM t1 WHERE a=TIMESTAMP'1970-01-01 00:00:00';
|
||||
id select_type table type possible_keys key key_len ref rows filtered Extra
|
||||
1 SIMPLE t1 ALL NULL NULL NULL NULL 3 100.00 Using where
|
||||
Warnings:
|
||||
Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = TIMESTAMP'1970-01-01 00:00:00'
|
||||
EXPLAIN EXTENDED SELECT * FROM t1 WHERE a=TIMESTAMP'1970-01-01 23:59:59';
|
||||
id select_type table type possible_keys key key_len ref rows filtered Extra
|
||||
1 SIMPLE t1 ALL NULL NULL NULL NULL 3 100.00 Using where
|
||||
Warnings:
|
||||
Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = TIMESTAMP'1970-01-01 23:59:59'
|
||||
EXPLAIN EXTENDED SELECT * FROM t1 WHERE a=TIMESTAMP'1970-01-01 23:59:59.999999';
|
||||
id select_type table type possible_keys key key_len ref rows filtered Extra
|
||||
1 SIMPLE t1 ALL NULL NULL NULL NULL 3 100.00 Using where
|
||||
Warnings:
|
||||
Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = TIMESTAMP'1970-01-01 23:59:59.999999'
|
||||
EXPLAIN EXTENDED SELECT * FROM t1 WHERE a=TIMESTAMP'1970-01-01 23:59:59.9999999';
|
||||
id select_type table type possible_keys key key_len ref rows filtered Extra
|
||||
1 SIMPLE t1 ALL NULL NULL NULL NULL 3 100.00 Using where
|
||||
Warnings:
|
||||
Note 1292 Truncated incorrect DATETIME value: '1970-01-01 23:59:59.9999999'
|
||||
Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = TIMESTAMP'1970-01-01 23:59:59.999999'
|
||||
EXPLAIN EXTENDED SELECT * FROM t1 WHERE a=FROM_UNIXTIME(24*3600-1);
|
||||
id select_type table type possible_keys key key_len ref rows filtered Extra
|
||||
1 SIMPLE t1 ALL NULL NULL NULL NULL 3 100.00 Using where
|
||||
Warnings:
|
||||
Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = <cache>(from_unixtime(24 * 3600 - 1))
|
||||
#
|
||||
# Corner cases: DATETIME values inside the supported optimization range:
|
||||
# FROM_UNIXTIME(24*3600) .. FROM_UNIXTIME(0x7FFFFFFF-24*3600)
|
||||
#
|
||||
EXPLAIN EXTENDED SELECT * FROM t1 WHERE a=FROM_UNIXTIME(24*3600);
|
||||
id select_type table type possible_keys key key_len ref rows filtered Extra
|
||||
1 SIMPLE t1 ALL NULL NULL NULL NULL 3 100.00 Using where
|
||||
Warnings:
|
||||
Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = TIMESTAMP/*WITH LOCAL TIME ZONE*/'1970-01-02 00:00:00'
|
||||
EXPLAIN EXTENDED SELECT * FROM t1 WHERE a=TIMESTAMP'1970-01-02 00:00:00';
|
||||
id select_type table type possible_keys key key_len ref rows filtered Extra
|
||||
1 SIMPLE t1 ALL NULL NULL NULL NULL 3 100.00 Using where
|
||||
Warnings:
|
||||
Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = TIMESTAMP/*WITH LOCAL TIME ZONE*/'1970-01-02 00:00:00'
|
||||
EXPLAIN EXTENDED SELECT * FROM t1 WHERE a=TIMESTAMP'2038-01-18 03:14:07';
|
||||
id select_type table type possible_keys key key_len ref rows filtered Extra
|
||||
1 SIMPLE t1 ALL NULL NULL NULL NULL 3 100.00 Using where
|
||||
Warnings:
|
||||
Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = TIMESTAMP/*WITH LOCAL TIME ZONE*/'2038-01-18 03:14:07'
|
||||
EXPLAIN EXTENDED SELECT * FROM t1 WHERE a=FROM_UNIXTIME(0x7FFFFFFF-24*3600);
|
||||
id select_type table type possible_keys key key_len ref rows filtered Extra
|
||||
1 SIMPLE t1 ALL NULL NULL NULL NULL 3 100.00 Using where
|
||||
Warnings:
|
||||
Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = TIMESTAMP/*WITH LOCAL TIME ZONE*/'2038-01-18 03:14:07'
|
||||
#
|
||||
# Corner cases: DATETIME values after the supported optimization range
|
||||
# FROM_UNIXTIME(0x7FFFFFFF-24*3600+1) .. FROM_UNIXTIME(0x7FFFFFFF)
|
||||
#
|
||||
EXPLAIN EXTENDED SELECT * FROM t1 WHERE a=FROM_UNIXTIME(0x7FFFFFFF-24*3600+1);
|
||||
id select_type table type possible_keys key key_len ref rows filtered Extra
|
||||
1 SIMPLE t1 ALL NULL NULL NULL NULL 3 100.00 Using where
|
||||
Warnings:
|
||||
Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = <cache>(from_unixtime(0x7fffffff - 24 * 3600 + 1))
|
||||
EXPLAIN EXTENDED SELECT * FROM t1 WHERE a=TIMESTAMP'2038-01-18 03:14:08';
|
||||
id select_type table type possible_keys key key_len ref rows filtered Extra
|
||||
1 SIMPLE t1 ALL NULL NULL NULL NULL 3 100.00 Using where
|
||||
Warnings:
|
||||
Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = TIMESTAMP'2038-01-18 03:14:08'
|
||||
EXPLAIN EXTENDED SELECT * FROM t1 WHERE a=TIMESTAMP'2038-01-19 03:14:07';
|
||||
id select_type table type possible_keys key key_len ref rows filtered Extra
|
||||
1 SIMPLE t1 ALL NULL NULL NULL NULL 3 100.00 Using where
|
||||
Warnings:
|
||||
Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = TIMESTAMP'2038-01-19 03:14:07'
|
||||
EXPLAIN EXTENDED SELECT * FROM t1 WHERE a=FROM_UNIXTIME(0x7FFFFFFF);
|
||||
id select_type table type possible_keys key key_len ref rows filtered Extra
|
||||
1 SIMPLE t1 ALL NULL NULL NULL NULL 3 100.00 Using where
|
||||
Warnings:
|
||||
Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = <cache>(from_unixtime(0x7fffffff))
|
||||
#
|
||||
# Corner cases: rounding
|
||||
#
|
||||
SET sql_mode=TIME_ROUND_FRACTIONAL;
|
||||
#
|
||||
# Not optimized (before the supported range)
|
||||
#
|
||||
EXPLAIN EXTENDED SELECT * FROM t1 WHERE a=TIMESTAMP'1970-01-01 23:59:59.999999';
|
||||
id select_type table type possible_keys key key_len ref rows filtered Extra
|
||||
1 SIMPLE t1 ALL NULL NULL NULL NULL 3 100.00 Using where
|
||||
Warnings:
|
||||
Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = TIMESTAMP'1970-01-01 23:59:59.999999'
|
||||
#
|
||||
# Optimized
|
||||
#
|
||||
EXPLAIN EXTENDED SELECT * FROM t1 WHERE a=TIMESTAMP'1970-01-01 23:59:59.9999999';
|
||||
id select_type table type possible_keys key key_len ref rows filtered Extra
|
||||
1 SIMPLE t1 ALL NULL NULL NULL NULL 3 100.00 Using where
|
||||
Warnings:
|
||||
Note 1292 Truncated incorrect DATETIME value: '1970-01-01 23:59:59.9999999'
|
||||
Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = TIMESTAMP/*WITH LOCAL TIME ZONE*/'1970-01-02 00:00:00.000000'
|
||||
EXPLAIN EXTENDED SELECT * FROM t1 WHERE a=TIMESTAMP'2038-01-18 03:14:07.999999';
|
||||
id select_type table type possible_keys key key_len ref rows filtered Extra
|
||||
1 SIMPLE t1 ALL NULL NULL NULL NULL 3 100.00 Using where
|
||||
Warnings:
|
||||
Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = TIMESTAMP/*WITH LOCAL TIME ZONE*/'2038-01-18 03:14:07.999999'
|
||||
#
|
||||
# Not optimized (after the supported range)
|
||||
#
|
||||
EXPLAIN EXTENDED SELECT * FROM t1 WHERE a=TIMESTAMP'2038-01-18 03:14:07.9999999';
|
||||
id select_type table type possible_keys key key_len ref rows filtered Extra
|
||||
1 SIMPLE t1 ALL NULL NULL NULL NULL 3 100.00 Using where
|
||||
Warnings:
|
||||
Note 1292 Truncated incorrect DATETIME value: '2038-01-18 03:14:07.9999999'
|
||||
Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = TIMESTAMP'2038-01-18 03:14:08.000000'
|
||||
SET sql_mode=DEFAULT;
|
||||
#
|
||||
# NULLIF: Bad TIMESTAMP values preserve DATETIME comparison
|
||||
#
|
||||
EXPLAIN EXTENDED SELECT * FROM t1 WHERE NULLIF(a,TIMESTAMP'1001-01-01 10:20:30');
|
||||
id select_type table type possible_keys key key_len ref rows filtered Extra
|
||||
1 SIMPLE t1 ALL NULL NULL NULL NULL 3 100.00 Using where
|
||||
Warnings:
|
||||
Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where nullif(`test`.`t1`.`a`,TIMESTAMP'1001-01-01 10:20:30')
|
||||
EXPLAIN EXTENDED SELECT * FROM t1 WHERE NULLIF(a,TIMESTAMP'2001-01-00 00:00:00');
|
||||
id select_type table type possible_keys key key_len ref rows filtered Extra
|
||||
1 SIMPLE t1 ALL NULL NULL NULL NULL 3 100.00 Using where
|
||||
Warnings:
|
||||
Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where nullif(`test`.`t1`.`a`,TIMESTAMP'2001-01-00 00:00:00')
|
||||
EXPLAIN EXTENDED SELECT * FROM t1 WHERE NULLIF(a,TIMESTAMP'2040-01-01 10:20:30');
|
||||
id select_type table type possible_keys key key_len ref rows filtered Extra
|
||||
1 SIMPLE t1 ALL NULL NULL NULL NULL 3 100.00 Using where
|
||||
Warnings:
|
||||
Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where nullif(`test`.`t1`.`a`,TIMESTAMP'2040-01-01 10:20:30')
|
||||
EXPLAIN EXTENDED SELECT * FROM t1 WHERE NULLIF(a,'1001-01-01 10:20:30');
|
||||
id select_type table type possible_keys key key_len ref rows filtered Extra
|
||||
1 SIMPLE t1 ALL NULL NULL NULL NULL 3 100.00 Using where
|
||||
Warnings:
|
||||
Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where nullif(`test`.`t1`.`a`,'1001-01-01 10:20:30')
|
||||
EXPLAIN EXTENDED SELECT * FROM t1 WHERE NULLIF(a,'2001-01-00 00:00:00');
|
||||
id select_type table type possible_keys key key_len ref rows filtered Extra
|
||||
1 SIMPLE t1 ALL NULL NULL NULL NULL 3 100.00 Using where
|
||||
Warnings:
|
||||
Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where nullif(`test`.`t1`.`a`,'2001-01-00 00:00:00')
|
||||
EXPLAIN EXTENDED SELECT * FROM t1 WHERE NULLIF(a,'2040-01-01 10:20:30');
|
||||
id select_type table type possible_keys key key_len ref rows filtered Extra
|
||||
1 SIMPLE t1 ALL NULL NULL NULL NULL 3 100.00 Using where
|
||||
Warnings:
|
||||
Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where nullif(`test`.`t1`.`a`,'2040-01-01 10:20:30')
|
||||
EXPLAIN EXTENDED SELECT * FROM t1 WHERE NULLIF(a,10010101102030);
|
||||
id select_type table type possible_keys key key_len ref rows filtered Extra
|
||||
1 SIMPLE t1 ALL NULL NULL NULL NULL 3 100.00 Using where
|
||||
Warnings:
|
||||
Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where nullif(`test`.`t1`.`a`,10010101102030)
|
||||
EXPLAIN EXTENDED SELECT * FROM t1 WHERE NULLIF(a,20010100000000);
|
||||
id select_type table type possible_keys key key_len ref rows filtered Extra
|
||||
1 SIMPLE t1 ALL NULL NULL NULL NULL 3 100.00 Using where
|
||||
Warnings:
|
||||
Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where nullif(`test`.`t1`.`a`,20010100000000)
|
||||
EXPLAIN EXTENDED SELECT * FROM t1 WHERE NULLIF(a,20400101102030);
|
||||
id select_type table type possible_keys key key_len ref rows filtered Extra
|
||||
1 SIMPLE t1 ALL NULL NULL NULL NULL 3 100.00 Using where
|
||||
Warnings:
|
||||
Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where nullif(`test`.`t1`.`a`,20400101102030)
|
||||
EXPLAIN EXTENDED SELECT * FROM t1 WHERE NULLIF(a,10010101102030e0);
|
||||
id select_type table type possible_keys key key_len ref rows filtered Extra
|
||||
1 SIMPLE t1 ALL NULL NULL NULL NULL 3 100.00 Using where
|
||||
Warnings:
|
||||
Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where nullif(`test`.`t1`.`a`,10010101102030e0)
|
||||
EXPLAIN EXTENDED SELECT * FROM t1 WHERE NULLIF(a,20010100000000e0);
|
||||
id select_type table type possible_keys key key_len ref rows filtered Extra
|
||||
1 SIMPLE t1 ALL NULL NULL NULL NULL 3 100.00 Using where
|
||||
Warnings:
|
||||
Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where nullif(`test`.`t1`.`a`,20010100000000e0)
|
||||
EXPLAIN EXTENDED SELECT * FROM t1 WHERE NULLIF(a,20400101102030e0);
|
||||
id select_type table type possible_keys key key_len ref rows filtered Extra
|
||||
1 SIMPLE t1 ALL NULL NULL NULL NULL 3 100.00 Using where
|
||||
Warnings:
|
||||
Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where nullif(`test`.`t1`.`a`,20400101102030e0)
|
||||
EXPLAIN EXTENDED SELECT * FROM t1 WHERE NULLIF(a,10010101102030.0);
|
||||
id select_type table type possible_keys key key_len ref rows filtered Extra
|
||||
1 SIMPLE t1 ALL NULL NULL NULL NULL 3 100.00 Using where
|
||||
Warnings:
|
||||
Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where nullif(`test`.`t1`.`a`,10010101102030.0)
|
||||
EXPLAIN EXTENDED SELECT * FROM t1 WHERE NULLIF(a,20010100000000.0);
|
||||
id select_type table type possible_keys key key_len ref rows filtered Extra
|
||||
1 SIMPLE t1 ALL NULL NULL NULL NULL 3 100.00 Using where
|
||||
Warnings:
|
||||
Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where nullif(`test`.`t1`.`a`,20010100000000.0)
|
||||
EXPLAIN EXTENDED SELECT * FROM t1 WHERE NULLIF(a,20400101102030.0);
|
||||
id select_type table type possible_keys key key_len ref rows filtered Extra
|
||||
1 SIMPLE t1 ALL NULL NULL NULL NULL 3 100.00 Using where
|
||||
Warnings:
|
||||
Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where nullif(`test`.`t1`.`a`,20400101102030.0)
|
||||
#
|
||||
# NULLIF: Good TIMESTAMP values switch to TIMESTAMP comparison
|
||||
#
|
||||
EXPLAIN EXTENDED SELECT * FROM t1 WHERE NULLIF(a,TIMESTAMP'0000-00-00 00:00:00');
|
||||
id select_type table type possible_keys key key_len ref rows filtered Extra
|
||||
1 SIMPLE t1 ALL NULL NULL NULL NULL 3 100.00 Using where
|
||||
Warnings:
|
||||
Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where nullif(`test`.`t1`.`a`,TIMESTAMP/*WITH LOCAL TIME ZONE*/'0000-00-00 00:00:00')
|
||||
EXPLAIN EXTENDED SELECT * FROM t1 WHERE NULLIF(a,TIMESTAMP'2001-01-01 10:20:30');
|
||||
id select_type table type possible_keys key key_len ref rows filtered Extra
|
||||
1 SIMPLE t1 ALL NULL NULL NULL NULL 3 100.00 Using where
|
||||
Warnings:
|
||||
Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where nullif(`test`.`t1`.`a`,TIMESTAMP/*WITH LOCAL TIME ZONE*/'2001-01-01 10:20:30')
|
||||
EXPLAIN EXTENDED SELECT * FROM t1 WHERE NULLIF(a,'0000-00-00 00:00:00');
|
||||
id select_type table type possible_keys key key_len ref rows filtered Extra
|
||||
1 SIMPLE t1 ALL NULL NULL NULL NULL 3 100.00 Using where
|
||||
Warnings:
|
||||
Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where nullif(`test`.`t1`.`a`,TIMESTAMP/*WITH LOCAL TIME ZONE*/'0000-00-00 00:00:00')
|
||||
EXPLAIN EXTENDED SELECT * FROM t1 WHERE NULLIF(a,'2001-01-01 10:20:30');
|
||||
id select_type table type possible_keys key key_len ref rows filtered Extra
|
||||
1 SIMPLE t1 ALL NULL NULL NULL NULL 3 100.00 Using where
|
||||
Warnings:
|
||||
Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where nullif(`test`.`t1`.`a`,TIMESTAMP/*WITH LOCAL TIME ZONE*/'2001-01-01 10:20:30')
|
||||
EXPLAIN EXTENDED SELECT * FROM t1 WHERE NULLIF(a,0);
|
||||
id select_type table type possible_keys key key_len ref rows filtered Extra
|
||||
1 SIMPLE t1 ALL NULL NULL NULL NULL 3 100.00 Using where
|
||||
Warnings:
|
||||
Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where nullif(`test`.`t1`.`a`,TIMESTAMP/*WITH LOCAL TIME ZONE*/'0000-00-00 00:00:00')
|
||||
EXPLAIN EXTENDED SELECT * FROM t1 WHERE NULLIF(a,20010101102030);
|
||||
id select_type table type possible_keys key key_len ref rows filtered Extra
|
||||
1 SIMPLE t1 ALL NULL NULL NULL NULL 3 100.00 Using where
|
||||
Warnings:
|
||||
Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where nullif(`test`.`t1`.`a`,TIMESTAMP/*WITH LOCAL TIME ZONE*/'2001-01-01 10:20:30')
|
||||
EXPLAIN EXTENDED SELECT * FROM t1 WHERE NULLIF(a,0e0);
|
||||
id select_type table type possible_keys key key_len ref rows filtered Extra
|
||||
1 SIMPLE t1 ALL NULL NULL NULL NULL 3 100.00 Using where
|
||||
Warnings:
|
||||
Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where nullif(`test`.`t1`.`a`,TIMESTAMP/*WITH LOCAL TIME ZONE*/'0000-00-00 00:00:00.000000')
|
||||
EXPLAIN EXTENDED SELECT * FROM t1 WHERE NULLIF(a,20010101102030e0);
|
||||
id select_type table type possible_keys key key_len ref rows filtered Extra
|
||||
1 SIMPLE t1 ALL NULL NULL NULL NULL 3 100.00 Using where
|
||||
Warnings:
|
||||
Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where nullif(`test`.`t1`.`a`,TIMESTAMP/*WITH LOCAL TIME ZONE*/'2001-01-01 10:20:30.000000')
|
||||
EXPLAIN EXTENDED SELECT * FROM t1 WHERE NULLIF(a,0.0);
|
||||
id select_type table type possible_keys key key_len ref rows filtered Extra
|
||||
1 SIMPLE t1 ALL NULL NULL NULL NULL 3 100.00 Using where
|
||||
Warnings:
|
||||
Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where nullif(`test`.`t1`.`a`,TIMESTAMP/*WITH LOCAL TIME ZONE*/'0000-00-00 00:00:00.0')
|
||||
EXPLAIN EXTENDED SELECT * FROM t1 WHERE NULLIF(a,20010101102030.0);
|
||||
id select_type table type possible_keys key key_len ref rows filtered Extra
|
||||
1 SIMPLE t1 ALL NULL NULL NULL NULL 3 100.00 Using where
|
||||
Warnings:
|
||||
Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where nullif(`test`.`t1`.`a`,TIMESTAMP/*WITH LOCAL TIME ZONE*/'2001-01-01 10:20:30.0')
|
||||
#
|
||||
# Subqueries with bad TIMESTAMP values
|
||||
# It's not clear from the output if the comparison is done as DATETIME or TIMESTAMP
|
||||
#
|
||||
CREATE TABLE t2 (a DATETIME);
|
||||
INSERT INTO t2 VALUES ('1001-01-01 10:20:30');
|
||||
EXPLAIN EXTENDED SELECT * FROM t1 WHERE a=(SELECT MAX(a) FROM t2);
|
||||
id select_type table type possible_keys key key_len ref rows filtered Extra
|
||||
1 PRIMARY t1 ALL NULL NULL NULL NULL 3 100.00 Using where
|
||||
2 SUBQUERY t2 system NULL NULL NULL NULL 1 100.00
|
||||
Warnings:
|
||||
Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = (/* select#2 */ select max('1001-01-01 10:20:30') from dual)
|
||||
DROP TABLE t2;
|
||||
CREATE TABLE t2 (a DATETIME);
|
||||
INSERT INTO t2 VALUES ('2001-00-00 00:00:00');
|
||||
EXPLAIN EXTENDED SELECT * FROM t1 WHERE a=(SELECT MAX(a) FROM t2);
|
||||
id select_type table type possible_keys key key_len ref rows filtered Extra
|
||||
1 PRIMARY t1 ALL NULL NULL NULL NULL 3 100.00 Using where
|
||||
2 SUBQUERY t2 system NULL NULL NULL NULL 1 100.00
|
||||
Warnings:
|
||||
Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = (/* select#2 */ select max('2001-00-00 00:00:00') from dual)
|
||||
DROP TABLE t2;
|
||||
CREATE TABLE t2 (a DATETIME);
|
||||
INSERT INTO t2 VALUES ('2040-01-01 10:20:30');
|
||||
EXPLAIN EXTENDED SELECT * FROM t1 WHERE a=(SELECT MAX(a) FROM t2);
|
||||
id select_type table type possible_keys key key_len ref rows filtered Extra
|
||||
1 PRIMARY t1 ALL NULL NULL NULL NULL 3 100.00 Using where
|
||||
2 SUBQUERY t2 system NULL NULL NULL NULL 1 100.00
|
||||
Warnings:
|
||||
Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = (/* select#2 */ select max('2040-01-01 10:20:30') from dual)
|
||||
DROP TABLE t2;
|
||||
#
|
||||
# Subqueries with good TIMESTAMP values
|
||||
# It's not clear from the output if the comparison is done as DATETIME or TIMESTAMP
|
||||
#
|
||||
CREATE TABLE t2 (a DATETIME);
|
||||
INSERT INTO t2 VALUES ('0000-00-00 00:00:00');
|
||||
EXPLAIN EXTENDED SELECT * FROM t1 WHERE a=(SELECT MAX(a) FROM t2);
|
||||
id select_type table type possible_keys key key_len ref rows filtered Extra
|
||||
1 PRIMARY t1 ALL NULL NULL NULL NULL 3 100.00 Using where
|
||||
2 SUBQUERY t2 system NULL NULL NULL NULL 1 100.00
|
||||
Warnings:
|
||||
Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = (/* select#2 */ select max('0000-00-00 00:00:00') from dual)
|
||||
DROP TABLE t2;
|
||||
CREATE TABLE t2 (a DATETIME);
|
||||
INSERT INTO t2 VALUES ('2001-01-01 10:20:30');
|
||||
EXPLAIN EXTENDED SELECT * FROM t1 WHERE a=(SELECT MAX(a) FROM t2);
|
||||
id select_type table type possible_keys key key_len ref rows filtered Extra
|
||||
1 PRIMARY t1 ALL NULL NULL NULL NULL 3 100.00 Using where
|
||||
2 SUBQUERY t2 system NULL NULL NULL NULL 1 100.00
|
||||
Warnings:
|
||||
Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = (/* select#2 */ select max('2001-01-01 10:20:30') from dual)
|
||||
DROP TABLE t2;
|
||||
#
|
||||
# Trivial equality elimination
|
||||
# Covers Type_handler_timestamp_common::Item_const_eq()
|
||||
#
|
||||
EXPLAIN EXTENDED SELECT * FROM t1
|
||||
WHERE IF(a='2001-01-01 00:00:00',1,0)=IF(a='2001-01-01 00:00:00',1,0);
|
||||
id select_type table type possible_keys key key_len ref rows filtered Extra
|
||||
1 SIMPLE t1 ALL NULL NULL NULL NULL 3 100.00 Using where
|
||||
Warnings:
|
||||
Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where if(`test`.`t1`.`a` = TIMESTAMP/*WITH LOCAL TIME ZONE*/'2001-01-01 00:00:00',1,0) = if(`test`.`t1`.`a` = TIMESTAMP/*WITH LOCAL TIME ZONE*/'2001-01-01 00:00:00',1,0)
|
||||
EXECUTE IMMEDIATE 'EXPLAIN EXTENDED SELECT * FROM t1 WHERE (a<=>?)=(a<=>?)'
|
||||
USING '2001-01-01 00:00:00', '2001-01-01 00:00:00';
|
||||
id select_type table type possible_keys key key_len ref rows filtered Extra
|
||||
1 SIMPLE t1 ALL NULL NULL NULL NULL 3 100.00
|
||||
Warnings:
|
||||
Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where 1
|
||||
#
|
||||
# Equal field propagation: Good TIMESTAMP values switch to TIMESTAMP comparison
|
||||
#
|
||||
EXPLAIN EXTENDED SELECT * FROM t1 WHERE LENGTH(a)=19 AND a=TIMESTAMP'2001-01-01 10:20:30';
|
||||
id select_type table type possible_keys key key_len ref rows filtered Extra
|
||||
1 SIMPLE t1 ALL NULL NULL NULL NULL 3 100.00 Using where
|
||||
Warnings:
|
||||
Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = TIMESTAMP/*WITH LOCAL TIME ZONE*/'2001-01-01 10:20:30'
|
||||
EXPLAIN EXTENDED SELECT * FROM t1 WHERE LENGTH(a)=19 AND a='2001-01-01 10:20:30';
|
||||
id select_type table type possible_keys key key_len ref rows filtered Extra
|
||||
1 SIMPLE t1 ALL NULL NULL NULL NULL 3 100.00 Using where
|
||||
Warnings:
|
||||
Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = TIMESTAMP/*WITH LOCAL TIME ZONE*/'2001-01-01 10:20:30'
|
||||
EXPLAIN EXTENDED SELECT * FROM t1 WHERE LENGTH(a)=19 AND a=20010101102030;
|
||||
id select_type table type possible_keys key key_len ref rows filtered Extra
|
||||
1 SIMPLE t1 ALL NULL NULL NULL NULL 3 100.00 Using where
|
||||
Warnings:
|
||||
Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = TIMESTAMP/*WITH LOCAL TIME ZONE*/'2001-01-01 10:20:30'
|
||||
EXPLAIN EXTENDED SELECT * FROM t1 WHERE LENGTH(a)=19 AND a=20010101102030e0;
|
||||
id select_type table type possible_keys key key_len ref rows filtered Extra
|
||||
1 SIMPLE t1 ALL NULL NULL NULL NULL 3 100.00 Using where
|
||||
Warnings:
|
||||
Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = TIMESTAMP/*WITH LOCAL TIME ZONE*/'2001-01-01 10:20:30.000000'
|
||||
EXPLAIN EXTENDED SELECT * FROM t1 WHERE LENGTH(a)=19 AND a=20010101102030.0;
|
||||
id select_type table type possible_keys key key_len ref rows filtered Extra
|
||||
1 SIMPLE t1 ALL NULL NULL NULL NULL 3 100.00 Using where
|
||||
Warnings:
|
||||
Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = TIMESTAMP/*WITH LOCAL TIME ZONE*/'2001-01-01 10:20:30.0'
|
||||
EXPLAIN EXTENDED SELECT * FROM t1 WHERE LENGTH(a)=19+RAND() AND a=TIMESTAMP'2001-01-01 10:20:30';
|
||||
id select_type table type possible_keys key key_len ref rows filtered Extra
|
||||
1 SIMPLE t1 ALL NULL NULL NULL NULL 3 100.00 Using where
|
||||
Warnings:
|
||||
Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = TIMESTAMP/*WITH LOCAL TIME ZONE*/'2001-01-01 10:20:30' and <cache>(octet_length(TIMESTAMP/*WITH LOCAL TIME ZONE*/'2001-01-01 10:20:30')) = 19 + rand()
|
||||
EXPLAIN EXTENDED SELECT * FROM t1 WHERE LENGTH(a)=19+RAND() AND a='2001-01-01 10:20:30';
|
||||
id select_type table type possible_keys key key_len ref rows filtered Extra
|
||||
1 SIMPLE t1 ALL NULL NULL NULL NULL 3 100.00 Using where
|
||||
Warnings:
|
||||
Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = TIMESTAMP/*WITH LOCAL TIME ZONE*/'2001-01-01 10:20:30' and <cache>(octet_length(TIMESTAMP/*WITH LOCAL TIME ZONE*/'2001-01-01 10:20:30')) = 19 + rand()
|
||||
EXPLAIN EXTENDED SELECT * FROM t1 WHERE LENGTH(a)=19+RAND() AND a=20010101102030;
|
||||
id select_type table type possible_keys key key_len ref rows filtered Extra
|
||||
1 SIMPLE t1 ALL NULL NULL NULL NULL 3 100.00 Using where
|
||||
Warnings:
|
||||
Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = TIMESTAMP/*WITH LOCAL TIME ZONE*/'2001-01-01 10:20:30' and <cache>(octet_length(TIMESTAMP/*WITH LOCAL TIME ZONE*/'2001-01-01 10:20:30')) = 19 + rand()
|
||||
EXPLAIN EXTENDED SELECT * FROM t1 WHERE LENGTH(a)=19+RAND() AND a=20010101102030e0;
|
||||
id select_type table type possible_keys key key_len ref rows filtered Extra
|
||||
1 SIMPLE t1 ALL NULL NULL NULL NULL 3 100.00 Using where
|
||||
Warnings:
|
||||
Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = TIMESTAMP/*WITH LOCAL TIME ZONE*/'2001-01-01 10:20:30.000000' and <cache>(octet_length(TIMESTAMP'2001-01-01 10:20:30')) = 19 + rand()
|
||||
EXPLAIN EXTENDED SELECT * FROM t1 WHERE LENGTH(a)=19+RAND() AND a=20010101102030.0;
|
||||
id select_type table type possible_keys key key_len ref rows filtered Extra
|
||||
1 SIMPLE t1 ALL NULL NULL NULL NULL 3 100.00 Using where
|
||||
Warnings:
|
||||
Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = TIMESTAMP/*WITH LOCAL TIME ZONE*/'2001-01-01 10:20:30.0' and <cache>(octet_length(TIMESTAMP'2001-01-01 10:20:30')) = 19 + rand()
|
||||
DROP TABLE t1;
|
||||
SET time_zone=DEFAULT;
|
||||
#
|
||||
# End of 10.6 tests
|
||||
#
|
||||
#
|
||||
# MDEV-29225 make explicit_defaults_for_timestamps SESSION variable
|
||||
#
|
||||
set explicit_defaults_for_timestamp=OFF;
|
||||
|
@@ -907,6 +907,246 @@ SET time_zone=DEFAULT;
|
||||
--echo # End of 10.4 tests
|
||||
--echo #
|
||||
|
||||
--echo #
|
||||
--echo # Start of 10.6 tests
|
||||
--echo #
|
||||
|
||||
--echo #
|
||||
--echo # MDEV-32148 Inefficient WHERE timestamp_column=datetime_expr
|
||||
--echo #
|
||||
|
||||
SET time_zone='+00:00';
|
||||
CREATE TABLE t1 (a TIMESTAMP);
|
||||
INSERT INTO t1 VALUES ('0000-00-00 00:00:00');
|
||||
INSERT INTO t1 VALUES ('2001-01-01 10:20:30'), ('2001-01-01 10:20:31');
|
||||
|
||||
--echo #
|
||||
--echo # Comparison predicates: Bad TIMESTAMP values preserve DATETIME comparison
|
||||
--echo #
|
||||
|
||||
EXPLAIN EXTENDED SELECT * FROM t1 WHERE a=TIMESTAMP'1001-01-01 10:20:30';
|
||||
EXPLAIN EXTENDED SELECT * FROM t1 WHERE a=TIMESTAMP'2001-01-00 00:00:00';
|
||||
EXPLAIN EXTENDED SELECT * FROM t1 WHERE a=TIMESTAMP'2040-01-01 10:20:30';
|
||||
|
||||
EXPLAIN EXTENDED SELECT * FROM t1 WHERE a='1001-01-01 10:20:30';
|
||||
EXPLAIN EXTENDED SELECT * FROM t1 WHERE a='2001-01-00 00:00:00';
|
||||
EXPLAIN EXTENDED SELECT * FROM t1 WHERE a='2040-01-01 10:20:30';
|
||||
|
||||
EXPLAIN EXTENDED SELECT * FROM t1 WHERE a=10010101102030;
|
||||
EXPLAIN EXTENDED SELECT * FROM t1 WHERE a=20010100000000;
|
||||
EXPLAIN EXTENDED SELECT * FROM t1 WHERE a=20400101102030;
|
||||
|
||||
EXPLAIN EXTENDED SELECT * FROM t1 WHERE a=10010101102030e0;
|
||||
EXPLAIN EXTENDED SELECT * FROM t1 WHERE a=20010100000000e0;
|
||||
EXPLAIN EXTENDED SELECT * FROM t1 WHERE a=20400101102030e0;
|
||||
|
||||
EXPLAIN EXTENDED SELECT * FROM t1 WHERE a=10010101102030.0;
|
||||
EXPLAIN EXTENDED SELECT * FROM t1 WHERE a=20010100000000.0;
|
||||
EXPLAIN EXTENDED SELECT * FROM t1 WHERE a=20400101102030.0;
|
||||
|
||||
EXPLAIN EXTENDED SELECT * FROM t1 WHERE a=DATE_ADD('2020-01-01 10:20:30', INTERVAL 30 YEAR);
|
||||
EXPLAIN EXTENDED SELECT * FROM t1 WHERE COALESCE(NULL, a)=DATE_ADD('2020-01-01 10:20:30', INTERVAL 30 YEAR);
|
||||
|
||||
--echo #
|
||||
--echo # Comparison predicates: Good TIMESTAMP values switch to TIMESTAMP comparison
|
||||
--echo #
|
||||
|
||||
EXPLAIN EXTENDED SELECT * FROM t1 WHERE a=TIMESTAMP'0000-00-00 00:00:00';
|
||||
EXPLAIN EXTENDED SELECT * FROM t1 WHERE a=TIMESTAMP'2001-01-01 10:20:30';
|
||||
|
||||
EXPLAIN EXTENDED SELECT * FROM t1 WHERE a='0000-00-00 00:00:00';
|
||||
EXPLAIN EXTENDED SELECT * FROM t1 WHERE a='2001-01-01 10:20:30';
|
||||
|
||||
EXPLAIN EXTENDED SELECT * FROM t1 WHERE a=0;
|
||||
EXPLAIN EXTENDED SELECT * FROM t1 WHERE a=20010101102030;
|
||||
|
||||
EXPLAIN EXTENDED SELECT * FROM t1 WHERE a=0e0;
|
||||
EXPLAIN EXTENDED SELECT * FROM t1 WHERE a=20010101102030e0;
|
||||
|
||||
EXPLAIN EXTENDED SELECT * FROM t1 WHERE a=0.0;
|
||||
EXPLAIN EXTENDED SELECT * FROM t1 WHERE a=20010101102030.0;
|
||||
|
||||
EXPLAIN EXTENDED SELECT * FROM t1 WHERE a=DATE_ADD('2001-01-01 10:20:00', INTERVAL 30 SECOND);
|
||||
EXPLAIN EXTENDED SELECT * FROM t1 WHERE COALESCE(NULL, a)=DATE_ADD('2001-01-01 10:20:00', INTERVAL 30 SECOND);
|
||||
|
||||
--echo #
|
||||
--echo # Corner cases: DATETIME values before the supported optimization range
|
||||
--echo # FROM_UNIXTIME(0)..FROM_UNIXTIME(24*3600-1)
|
||||
--echo #
|
||||
|
||||
EXPLAIN EXTENDED SELECT * FROM t1 WHERE a=TIMESTAMP'1970-01-01 00:00:00';
|
||||
EXPLAIN EXTENDED SELECT * FROM t1 WHERE a=TIMESTAMP'1970-01-01 23:59:59';
|
||||
EXPLAIN EXTENDED SELECT * FROM t1 WHERE a=TIMESTAMP'1970-01-01 23:59:59.999999';
|
||||
|
||||
# Truncation of the 7th flactional digit produces a NOTE only without --ps
|
||||
--disable_ps_protocol
|
||||
EXPLAIN EXTENDED SELECT * FROM t1 WHERE a=TIMESTAMP'1970-01-01 23:59:59.9999999';
|
||||
--enable_ps_protocol
|
||||
EXPLAIN EXTENDED SELECT * FROM t1 WHERE a=FROM_UNIXTIME(24*3600-1);
|
||||
|
||||
--echo #
|
||||
--echo # Corner cases: DATETIME values inside the supported optimization range:
|
||||
--echo # FROM_UNIXTIME(24*3600) .. FROM_UNIXTIME(0x7FFFFFFF-24*3600)
|
||||
--echo #
|
||||
|
||||
EXPLAIN EXTENDED SELECT * FROM t1 WHERE a=FROM_UNIXTIME(24*3600);
|
||||
EXPLAIN EXTENDED SELECT * FROM t1 WHERE a=TIMESTAMP'1970-01-02 00:00:00';
|
||||
EXPLAIN EXTENDED SELECT * FROM t1 WHERE a=TIMESTAMP'2038-01-18 03:14:07';
|
||||
EXPLAIN EXTENDED SELECT * FROM t1 WHERE a=FROM_UNIXTIME(0x7FFFFFFF-24*3600);
|
||||
|
||||
--echo #
|
||||
--echo # Corner cases: DATETIME values after the supported optimization range
|
||||
--echo # FROM_UNIXTIME(0x7FFFFFFF-24*3600+1) .. FROM_UNIXTIME(0x7FFFFFFF)
|
||||
--echo #
|
||||
|
||||
EXPLAIN EXTENDED SELECT * FROM t1 WHERE a=FROM_UNIXTIME(0x7FFFFFFF-24*3600+1);
|
||||
EXPLAIN EXTENDED SELECT * FROM t1 WHERE a=TIMESTAMP'2038-01-18 03:14:08';
|
||||
EXPLAIN EXTENDED SELECT * FROM t1 WHERE a=TIMESTAMP'2038-01-19 03:14:07';
|
||||
EXPLAIN EXTENDED SELECT * FROM t1 WHERE a=FROM_UNIXTIME(0x7FFFFFFF);
|
||||
|
||||
--echo #
|
||||
--echo # Corner cases: rounding
|
||||
--echo #
|
||||
|
||||
SET sql_mode=TIME_ROUND_FRACTIONAL;
|
||||
|
||||
--echo #
|
||||
--echo # Not optimized (before the supported range)
|
||||
--echo #
|
||||
EXPLAIN EXTENDED SELECT * FROM t1 WHERE a=TIMESTAMP'1970-01-01 23:59:59.999999';
|
||||
|
||||
--echo #
|
||||
--echo # Optimized
|
||||
--echo #
|
||||
--disable_ps_protocol
|
||||
EXPLAIN EXTENDED SELECT * FROM t1 WHERE a=TIMESTAMP'1970-01-01 23:59:59.9999999';
|
||||
--enable_ps_protocol
|
||||
EXPLAIN EXTENDED SELECT * FROM t1 WHERE a=TIMESTAMP'2038-01-18 03:14:07.999999';
|
||||
|
||||
--echo #
|
||||
--echo # Not optimized (after the supported range)
|
||||
--echo #
|
||||
--disable_ps_protocol
|
||||
EXPLAIN EXTENDED SELECT * FROM t1 WHERE a=TIMESTAMP'2038-01-18 03:14:07.9999999';
|
||||
--enable_ps_protocol
|
||||
|
||||
SET sql_mode=DEFAULT;
|
||||
|
||||
--echo #
|
||||
--echo # NULLIF: Bad TIMESTAMP values preserve DATETIME comparison
|
||||
--echo #
|
||||
|
||||
EXPLAIN EXTENDED SELECT * FROM t1 WHERE NULLIF(a,TIMESTAMP'1001-01-01 10:20:30');
|
||||
EXPLAIN EXTENDED SELECT * FROM t1 WHERE NULLIF(a,TIMESTAMP'2001-01-00 00:00:00');
|
||||
EXPLAIN EXTENDED SELECT * FROM t1 WHERE NULLIF(a,TIMESTAMP'2040-01-01 10:20:30');
|
||||
|
||||
EXPLAIN EXTENDED SELECT * FROM t1 WHERE NULLIF(a,'1001-01-01 10:20:30');
|
||||
EXPLAIN EXTENDED SELECT * FROM t1 WHERE NULLIF(a,'2001-01-00 00:00:00');
|
||||
EXPLAIN EXTENDED SELECT * FROM t1 WHERE NULLIF(a,'2040-01-01 10:20:30');
|
||||
|
||||
EXPLAIN EXTENDED SELECT * FROM t1 WHERE NULLIF(a,10010101102030);
|
||||
EXPLAIN EXTENDED SELECT * FROM t1 WHERE NULLIF(a,20010100000000);
|
||||
EXPLAIN EXTENDED SELECT * FROM t1 WHERE NULLIF(a,20400101102030);
|
||||
|
||||
EXPLAIN EXTENDED SELECT * FROM t1 WHERE NULLIF(a,10010101102030e0);
|
||||
EXPLAIN EXTENDED SELECT * FROM t1 WHERE NULLIF(a,20010100000000e0);
|
||||
EXPLAIN EXTENDED SELECT * FROM t1 WHERE NULLIF(a,20400101102030e0);
|
||||
|
||||
EXPLAIN EXTENDED SELECT * FROM t1 WHERE NULLIF(a,10010101102030.0);
|
||||
EXPLAIN EXTENDED SELECT * FROM t1 WHERE NULLIF(a,20010100000000.0);
|
||||
EXPLAIN EXTENDED SELECT * FROM t1 WHERE NULLIF(a,20400101102030.0);
|
||||
|
||||
--echo #
|
||||
--echo # NULLIF: Good TIMESTAMP values switch to TIMESTAMP comparison
|
||||
--echo #
|
||||
|
||||
EXPLAIN EXTENDED SELECT * FROM t1 WHERE NULLIF(a,TIMESTAMP'0000-00-00 00:00:00');
|
||||
EXPLAIN EXTENDED SELECT * FROM t1 WHERE NULLIF(a,TIMESTAMP'2001-01-01 10:20:30');
|
||||
|
||||
EXPLAIN EXTENDED SELECT * FROM t1 WHERE NULLIF(a,'0000-00-00 00:00:00');
|
||||
EXPLAIN EXTENDED SELECT * FROM t1 WHERE NULLIF(a,'2001-01-01 10:20:30');
|
||||
|
||||
EXPLAIN EXTENDED SELECT * FROM t1 WHERE NULLIF(a,0);
|
||||
EXPLAIN EXTENDED SELECT * FROM t1 WHERE NULLIF(a,20010101102030);
|
||||
|
||||
EXPLAIN EXTENDED SELECT * FROM t1 WHERE NULLIF(a,0e0);
|
||||
EXPLAIN EXTENDED SELECT * FROM t1 WHERE NULLIF(a,20010101102030e0);
|
||||
|
||||
EXPLAIN EXTENDED SELECT * FROM t1 WHERE NULLIF(a,0.0);
|
||||
EXPLAIN EXTENDED SELECT * FROM t1 WHERE NULLIF(a,20010101102030.0);
|
||||
|
||||
|
||||
--echo #
|
||||
--echo # Subqueries with bad TIMESTAMP values
|
||||
--echo # It's not clear from the output if the comparison is done as DATETIME or TIMESTAMP
|
||||
--echo #
|
||||
|
||||
CREATE TABLE t2 (a DATETIME);
|
||||
INSERT INTO t2 VALUES ('1001-01-01 10:20:30');
|
||||
EXPLAIN EXTENDED SELECT * FROM t1 WHERE a=(SELECT MAX(a) FROM t2);
|
||||
DROP TABLE t2;
|
||||
|
||||
CREATE TABLE t2 (a DATETIME);
|
||||
INSERT INTO t2 VALUES ('2001-00-00 00:00:00');
|
||||
EXPLAIN EXTENDED SELECT * FROM t1 WHERE a=(SELECT MAX(a) FROM t2);
|
||||
DROP TABLE t2;
|
||||
|
||||
CREATE TABLE t2 (a DATETIME);
|
||||
INSERT INTO t2 VALUES ('2040-01-01 10:20:30');
|
||||
EXPLAIN EXTENDED SELECT * FROM t1 WHERE a=(SELECT MAX(a) FROM t2);
|
||||
DROP TABLE t2;
|
||||
|
||||
--echo #
|
||||
--echo # Subqueries with good TIMESTAMP values
|
||||
--echo # It's not clear from the output if the comparison is done as DATETIME or TIMESTAMP
|
||||
--echo #
|
||||
|
||||
CREATE TABLE t2 (a DATETIME);
|
||||
INSERT INTO t2 VALUES ('0000-00-00 00:00:00');
|
||||
EXPLAIN EXTENDED SELECT * FROM t1 WHERE a=(SELECT MAX(a) FROM t2);
|
||||
DROP TABLE t2;
|
||||
|
||||
CREATE TABLE t2 (a DATETIME);
|
||||
INSERT INTO t2 VALUES ('2001-01-01 10:20:30');
|
||||
EXPLAIN EXTENDED SELECT * FROM t1 WHERE a=(SELECT MAX(a) FROM t2);
|
||||
DROP TABLE t2;
|
||||
|
||||
--echo #
|
||||
--echo # Trivial equality elimination
|
||||
--echo # Covers Type_handler_timestamp_common::Item_const_eq()
|
||||
--echo #
|
||||
|
||||
EXPLAIN EXTENDED SELECT * FROM t1
|
||||
WHERE IF(a='2001-01-01 00:00:00',1,0)=IF(a='2001-01-01 00:00:00',1,0);
|
||||
|
||||
EXECUTE IMMEDIATE 'EXPLAIN EXTENDED SELECT * FROM t1 WHERE (a<=>?)=(a<=>?)'
|
||||
USING '2001-01-01 00:00:00', '2001-01-01 00:00:00';
|
||||
|
||||
|
||||
--echo #
|
||||
--echo # Equal field propagation: Good TIMESTAMP values switch to TIMESTAMP comparison
|
||||
--echo #
|
||||
|
||||
EXPLAIN EXTENDED SELECT * FROM t1 WHERE LENGTH(a)=19 AND a=TIMESTAMP'2001-01-01 10:20:30';
|
||||
EXPLAIN EXTENDED SELECT * FROM t1 WHERE LENGTH(a)=19 AND a='2001-01-01 10:20:30';
|
||||
EXPLAIN EXTENDED SELECT * FROM t1 WHERE LENGTH(a)=19 AND a=20010101102030;
|
||||
EXPLAIN EXTENDED SELECT * FROM t1 WHERE LENGTH(a)=19 AND a=20010101102030e0;
|
||||
EXPLAIN EXTENDED SELECT * FROM t1 WHERE LENGTH(a)=19 AND a=20010101102030.0;
|
||||
|
||||
EXPLAIN EXTENDED SELECT * FROM t1 WHERE LENGTH(a)=19+RAND() AND a=TIMESTAMP'2001-01-01 10:20:30';
|
||||
EXPLAIN EXTENDED SELECT * FROM t1 WHERE LENGTH(a)=19+RAND() AND a='2001-01-01 10:20:30';
|
||||
EXPLAIN EXTENDED SELECT * FROM t1 WHERE LENGTH(a)=19+RAND() AND a=20010101102030;
|
||||
EXPLAIN EXTENDED SELECT * FROM t1 WHERE LENGTH(a)=19+RAND() AND a=20010101102030e0;
|
||||
EXPLAIN EXTENDED SELECT * FROM t1 WHERE LENGTH(a)=19+RAND() AND a=20010101102030.0;
|
||||
|
||||
DROP TABLE t1;
|
||||
|
||||
SET time_zone=DEFAULT;
|
||||
|
||||
--echo #
|
||||
--echo # End of 10.6 tests
|
||||
--echo #
|
||||
|
||||
--echo #
|
||||
--echo # MDEV-29225 make explicit_defaults_for_timestamps SESSION variable
|
||||
--echo #
|
||||
|
@@ -40,7 +40,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
|
||||
3 UNION e ALL NULL NULL NULL NULL 4 100.00 Using where
|
||||
NULL UNION RESULT <union2,3> ALL NULL NULL NULL NULL NULL NULL
|
||||
Warnings:
|
||||
Note 1003 with ancestors as (/* select#2 */ select `test`.`e`.`emp_id` AS `emp_id`,`test`.`e`.`name` AS `name`,`test`.`e`.`mgr` AS `mgr`,`test`.`e`.`salary` AS `salary` from `test`.`emp` FOR SYSTEM_TIME AS OF TIMESTAMP @`ts_1` `e` where `test`.`e`.`name` = 'bill' and `test`.`e`.`row_end` > @`ts_1` and `test`.`e`.`row_start` <= @`ts_1` union /* select#3 */ select `test`.`e`.`emp_id` AS `emp_id`,`test`.`e`.`name` AS `name`,`test`.`e`.`mgr` AS `mgr`,`test`.`e`.`salary` AS `salary` from `test`.`emp` FOR SYSTEM_TIME AS OF TIMESTAMP @`ts_1` `e` where `test`.`e`.`row_end` > @`ts_1` and `test`.`e`.`row_start` <= @`ts_1`)/* select#1 */ select `ancestors`.`emp_id` AS `emp_id`,`ancestors`.`name` AS `name`,`ancestors`.`mgr` AS `mgr`,`ancestors`.`salary` AS `salary` from `ancestors`
|
||||
Note 1003 with ancestors as (/* select#2 */ select `test`.`e`.`emp_id` AS `emp_id`,`test`.`e`.`name` AS `name`,`test`.`e`.`mgr` AS `mgr`,`test`.`e`.`salary` AS `salary` from `test`.`emp` FOR SYSTEM_TIME AS OF TIMESTAMP @`ts_1` `e` where `test`.`e`.`name` = 'bill' and `test`.`e`.`row_end` > TIMESTAMP/*WITH LOCAL TIME ZONE*/'YYYY-MM-DD hh:ss:mm:.uuuuuu' and `test`.`e`.`row_start` <= TIMESTAMP/*WITH LOCAL TIME ZONE*/'YYYY-MM-DD hh:ss:mm:.uuuuuu' union /* select#3 */ select `test`.`e`.`emp_id` AS `emp_id`,`test`.`e`.`name` AS `name`,`test`.`e`.`mgr` AS `mgr`,`test`.`e`.`salary` AS `salary` from `test`.`emp` FOR SYSTEM_TIME AS OF TIMESTAMP @`ts_1` `e` where `test`.`e`.`row_end` > TIMESTAMP/*WITH LOCAL TIME ZONE*/'YYYY-MM-DD hh:ss:mm:.uuuuuu' and `test`.`e`.`row_start` <= TIMESTAMP/*WITH LOCAL TIME ZONE*/'YYYY-MM-DD hh:ss:mm:.uuuuuu')/* select#1 */ select `ancestors`.`emp_id` AS `emp_id`,`ancestors`.`name` AS `name`,`ancestors`.`mgr` AS `mgr`,`ancestors`.`salary` AS `salary` from `ancestors`
|
||||
select row_start into @ts_2 from emp where name="john";
|
||||
explain extended /* All report to 'Bill' */
|
||||
with recursive
|
||||
@@ -64,7 +64,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
|
||||
3 RECURSIVE UNION <derived2> ref key0 key0 5 test.e.mgr 1 100.00
|
||||
NULL UNION RESULT <union2,3> ALL NULL NULL NULL NULL NULL NULL
|
||||
Warnings:
|
||||
Note 1003 with recursive ancestors as (/* select#2 */ select `test`.`e`.`emp_id` AS `emp_id`,`test`.`e`.`name` AS `name`,`test`.`e`.`mgr` AS `mgr`,`test`.`e`.`salary` AS `salary` from `test`.`emp` FOR SYSTEM_TIME AS OF TIMESTAMP @`ts_1` `e` where `test`.`e`.`name` = 'bill' and `test`.`e`.`row_end` > @`ts_1` and `test`.`e`.`row_start` <= @`ts_1` union /* select#3 */ select `test`.`e`.`emp_id` AS `emp_id`,`test`.`e`.`name` AS `name`,`test`.`e`.`mgr` AS `mgr`,`test`.`e`.`salary` AS `salary` from `test`.`emp` FOR SYSTEM_TIME AS OF TIMESTAMP @`ts_1` `e` join `ancestors` `a` where `a`.`emp_id` = `test`.`e`.`mgr` and `test`.`e`.`row_end` > @`ts_1` and `test`.`e`.`row_start` <= @`ts_1`)/* select#1 */ select `ancestors`.`emp_id` AS `emp_id`,`ancestors`.`name` AS `name`,`ancestors`.`mgr` AS `mgr`,`ancestors`.`salary` AS `salary` from `ancestors`
|
||||
Note 1003 with recursive ancestors as (/* select#2 */ select `test`.`e`.`emp_id` AS `emp_id`,`test`.`e`.`name` AS `name`,`test`.`e`.`mgr` AS `mgr`,`test`.`e`.`salary` AS `salary` from `test`.`emp` FOR SYSTEM_TIME AS OF TIMESTAMP @`ts_1` `e` where `test`.`e`.`name` = 'bill' and `test`.`e`.`row_end` > TIMESTAMP/*WITH LOCAL TIME ZONE*/'YYYY-MM-DD hh:ss:mm:.uuuuuu' and `test`.`e`.`row_start` <= TIMESTAMP/*WITH LOCAL TIME ZONE*/'YYYY-MM-DD hh:ss:mm:.uuuuuu' union /* select#3 */ select `test`.`e`.`emp_id` AS `emp_id`,`test`.`e`.`name` AS `name`,`test`.`e`.`mgr` AS `mgr`,`test`.`e`.`salary` AS `salary` from `test`.`emp` FOR SYSTEM_TIME AS OF TIMESTAMP @`ts_1` `e` join `ancestors` `a` where `a`.`emp_id` = `test`.`e`.`mgr` and `test`.`e`.`row_end` > TIMESTAMP/*WITH LOCAL TIME ZONE*/'YYYY-MM-DD hh:ss:mm:.uuuuuu' and `test`.`e`.`row_start` <= TIMESTAMP/*WITH LOCAL TIME ZONE*/'YYYY-MM-DD hh:ss:mm:.uuuuuu')/* select#1 */ select `ancestors`.`emp_id` AS `emp_id`,`ancestors`.`name` AS `name`,`ancestors`.`mgr` AS `mgr`,`ancestors`.`salary` AS `salary` from `ancestors`
|
||||
/* All report to 'Bill' */
|
||||
with recursive
|
||||
ancestors
|
||||
@@ -105,7 +105,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
|
||||
3 RECURSIVE UNION <derived2> ref key0 key0 5 test.e.mgr 1 100.00
|
||||
NULL UNION RESULT <union2,3> ALL NULL NULL NULL NULL NULL NULL
|
||||
Warnings:
|
||||
Note 1003 with recursive ancestors as (/* select#2 */ select `test`.`e`.`emp_id` AS `emp_id`,`test`.`e`.`name` AS `name`,`test`.`e`.`mgr` AS `mgr`,`test`.`e`.`salary` AS `salary` from `test`.`emp` FOR SYSTEM_TIME AS OF TIMESTAMP @`ts_1` `e` where `test`.`e`.`name` = 'bill' and `test`.`e`.`row_end` > @`ts_1` and `test`.`e`.`row_start` <= @`ts_1` union /* select#3 */ select `test`.`e`.`emp_id` AS `emp_id`,`test`.`e`.`name` AS `name`,`test`.`e`.`mgr` AS `mgr`,`test`.`e`.`salary` AS `salary` from `test`.`emp` FOR SYSTEM_TIME AS OF TIMESTAMP @`ts_1` `e` join `ancestors` `a` where `a`.`emp_id` = `test`.`e`.`mgr` and `test`.`e`.`row_end` > @`ts_1` and `test`.`e`.`row_start` <= @`ts_1`)/* select#1 */ select `ancestors`.`emp_id` AS `emp_id`,`ancestors`.`name` AS `name`,`ancestors`.`mgr` AS `mgr`,`ancestors`.`salary` AS `salary` from `ancestors`
|
||||
Note 1003 with recursive ancestors as (/* select#2 */ select `test`.`e`.`emp_id` AS `emp_id`,`test`.`e`.`name` AS `name`,`test`.`e`.`mgr` AS `mgr`,`test`.`e`.`salary` AS `salary` from `test`.`emp` FOR SYSTEM_TIME AS OF TIMESTAMP @`ts_1` `e` where `test`.`e`.`name` = 'bill' and `test`.`e`.`row_end` > TIMESTAMP/*WITH LOCAL TIME ZONE*/'YYYY-MM-DD hh:ss:mm:.uuuuuu' and `test`.`e`.`row_start` <= TIMESTAMP/*WITH LOCAL TIME ZONE*/'YYYY-MM-DD hh:ss:mm:.uuuuuu' union /* select#3 */ select `test`.`e`.`emp_id` AS `emp_id`,`test`.`e`.`name` AS `name`,`test`.`e`.`mgr` AS `mgr`,`test`.`e`.`salary` AS `salary` from `test`.`emp` FOR SYSTEM_TIME AS OF TIMESTAMP @`ts_1` `e` join `ancestors` `a` where `a`.`emp_id` = `test`.`e`.`mgr` and `test`.`e`.`row_end` > TIMESTAMP/*WITH LOCAL TIME ZONE*/'YYYY-MM-DD hh:ss:mm:.uuuuuu' and `test`.`e`.`row_start` <= TIMESTAMP/*WITH LOCAL TIME ZONE*/'YYYY-MM-DD hh:ss:mm:.uuuuuu')/* select#1 */ select `ancestors`.`emp_id` AS `emp_id`,`ancestors`.`name` AS `name`,`ancestors`.`mgr` AS `mgr`,`ancestors`.`salary` AS `salary` from `ancestors`
|
||||
with recursive
|
||||
ancestors
|
||||
as
|
||||
@@ -146,7 +146,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
|
||||
3 RECURSIVE UNION <derived2> ref key0 key0 5 test.e.mgr 1 100.00
|
||||
NULL UNION RESULT <union2,3> ALL NULL NULL NULL NULL NULL NULL
|
||||
Warnings:
|
||||
Note 1003 with recursive ancestors as (/* select#2 */ select `test`.`e`.`emp_id` AS `emp_id`,`test`.`e`.`name` AS `name`,`test`.`e`.`mgr` AS `mgr`,`test`.`e`.`salary` AS `salary` from `test`.`emp` FOR SYSTEM_TIME AS OF TIMESTAMP @`ts_1` `e` where `test`.`e`.`name` = 'bill' and `test`.`e`.`row_end` > @`ts_1` and `test`.`e`.`row_start` <= @`ts_1` union /* select#3 */ select `test`.`e`.`emp_id` AS `emp_id`,`test`.`e`.`name` AS `name`,`test`.`e`.`mgr` AS `mgr`,`test`.`e`.`salary` AS `salary` from `test`.`emp` FOR SYSTEM_TIME AS OF TIMESTAMP @`ts_1` `e` join `ancestors` `a` where `a`.`emp_id` = `test`.`e`.`mgr` and `test`.`e`.`row_end` > @`ts_1` and `test`.`e`.`row_start` <= @`ts_1`)/* select#1 */ select `test`.`emp`.`name` AS `name` from `test`.`emp` semi join (`ancestors`) where `ancestors`.`emp_id` = `test`.`emp`.`emp_id` and `test`.`emp`.`row_end` = TIMESTAMP'2038-01-19 03:14:07.999999'
|
||||
Note 1003 with recursive ancestors as (/* select#2 */ select `test`.`e`.`emp_id` AS `emp_id`,`test`.`e`.`name` AS `name`,`test`.`e`.`mgr` AS `mgr`,`test`.`e`.`salary` AS `salary` from `test`.`emp` FOR SYSTEM_TIME AS OF TIMESTAMP @`ts_1` `e` where `test`.`e`.`name` = 'bill' and `test`.`e`.`row_end` > TIMESTAMP/*WITH LOCAL TIME ZONE*/'YYYY-MM-DD hh:ss:mm:.uuuuuu' and `test`.`e`.`row_start` <= TIMESTAMP/*WITH LOCAL TIME ZONE*/'YYYY-MM-DD hh:ss:mm:.uuuuuu' union /* select#3 */ select `test`.`e`.`emp_id` AS `emp_id`,`test`.`e`.`name` AS `name`,`test`.`e`.`mgr` AS `mgr`,`test`.`e`.`salary` AS `salary` from `test`.`emp` FOR SYSTEM_TIME AS OF TIMESTAMP @`ts_1` `e` join `ancestors` `a` where `a`.`emp_id` = `test`.`e`.`mgr` and `test`.`e`.`row_end` > TIMESTAMP/*WITH LOCAL TIME ZONE*/'YYYY-MM-DD hh:ss:mm:.uuuuuu' and `test`.`e`.`row_start` <= TIMESTAMP/*WITH LOCAL TIME ZONE*/'YYYY-MM-DD hh:ss:mm:.uuuuuu')/* select#1 */ select `test`.`emp`.`name` AS `name` from `test`.`emp` semi join (`ancestors`) where `ancestors`.`emp_id` = `test`.`emp`.`emp_id` and `test`.`emp`.`row_end` = TIMESTAMP'2038-01-19 03:14:07.999999'
|
||||
with recursive
|
||||
ancestors
|
||||
as
|
||||
|
@@ -211,12 +211,12 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
|
||||
1 SIMPLE t2 ALL NULL NULL NULL NULL 3 100.00 Using where
|
||||
1 SIMPLE t1 ALL NULL NULL NULL NULL 5 100.00 Using where; Using join buffer (flat, BNL join)
|
||||
Query A:
|
||||
Note 1003 select `test`.`t1`.`x` AS `x`,`test`.`t1`.`y` AS `y1`,`test`.`t2`.`x` AS `x2`,`test`.`t2`.`y` AS `y2` from `test`.`t1` FOR SYSTEM_TIME AS OF TIMESTAMP current_timestamp(6) join `test`.`t2` FOR SYSTEM_TIME AS OF TIMESTAMP current_timestamp(6) where `test`.`t1`.`x` = `test`.`t2`.`x` and `test`.`t2`.`row_end` > <cache>(current_timestamp(6)) and `test`.`t2`.`row_start` <= <cache>(current_timestamp(6)) and `test`.`t1`.`row_end` > <cache>(current_timestamp(6)) and `test`.`t1`.`row_start` <= <cache>(current_timestamp(6))
|
||||
Note 1003 select `test`.`t1`.`x` AS `x`,`test`.`t1`.`y` AS `y1`,`test`.`t2`.`x` AS `x2`,`test`.`t2`.`y` AS `y2` from `test`.`t1` FOR SYSTEM_TIME AS OF TIMESTAMP current_timestamp(6) join `test`.`t2` FOR SYSTEM_TIME AS OF TIMESTAMP current_timestamp(6) where `test`.`t1`.`x` = `test`.`t2`.`x` and `test`.`t2`.`row_end` > TIMESTAMP/*WITH LOCAL TIME ZONE*/'YYYY-MM-DD hh:ss:mm:.uuuuuu' and `test`.`t2`.`row_start` <= TIMESTAMP/*WITH LOCAL TIME ZONE*/'YYYY-MM-DD hh:ss:mm:.uuuuuu' and `test`.`t1`.`row_end` > TIMESTAMP/*WITH LOCAL TIME ZONE*/'YYYY-MM-DD hh:ss:mm:.uuuuuu' and `test`.`t1`.`row_start` <= TIMESTAMP/*WITH LOCAL TIME ZONE*/'YYYY-MM-DD hh:ss:mm:.uuuuuu'
|
||||
id select_type table type possible_keys key key_len ref rows filtered Extra
|
||||
1 SIMPLE t2 ALL NULL NULL NULL NULL 3 100.00 Using where
|
||||
1 SIMPLE t1 ALL NULL NULL NULL NULL 5 100.00 Using where; Using join buffer (flat, BNL join)
|
||||
Query B:
|
||||
Note 1003 select `test`.`t1`.`x` AS `x`,`test`.`t1`.`y` AS `y1`,`test`.`t2`.`x` AS `x2`,`test`.`t2`.`y` AS `y2` from `test`.`t1` FOR SYSTEM_TIME AS OF TIMESTAMP current_timestamp(6) join `test`.`t2` FOR SYSTEM_TIME AS OF TIMESTAMP current_timestamp(6) where `test`.`t1`.`x` = `test`.`t2`.`x` and `test`.`t2`.`row_end` > <cache>(current_timestamp(6)) and `test`.`t2`.`row_start` <= <cache>(current_timestamp(6)) and `test`.`t1`.`row_end` > <cache>(current_timestamp(6)) and `test`.`t1`.`row_start` <= <cache>(current_timestamp(6))
|
||||
Note 1003 select `test`.`t1`.`x` AS `x`,`test`.`t1`.`y` AS `y1`,`test`.`t2`.`x` AS `x2`,`test`.`t2`.`y` AS `y2` from `test`.`t1` FOR SYSTEM_TIME AS OF TIMESTAMP current_timestamp(6) join `test`.`t2` FOR SYSTEM_TIME AS OF TIMESTAMP current_timestamp(6) where `test`.`t1`.`x` = `test`.`t2`.`x` and `test`.`t2`.`row_end` > TIMESTAMP/*WITH LOCAL TIME ZONE*/'YYYY-MM-DD hh:ss:mm:.uuuuuu' and `test`.`t2`.`row_start` <= TIMESTAMP/*WITH LOCAL TIME ZONE*/'YYYY-MM-DD hh:ss:mm:.uuuuuu' and `test`.`t1`.`row_end` > TIMESTAMP/*WITH LOCAL TIME ZONE*/'YYYY-MM-DD hh:ss:mm:.uuuuuu' and `test`.`t1`.`row_start` <= TIMESTAMP/*WITH LOCAL TIME ZONE*/'YYYY-MM-DD hh:ss:mm:.uuuuuu'
|
||||
Fine result: queries A and B are equal.
|
||||
## LEFT JOIN: t1, t2 versioned
|
||||
select * from (
|
||||
|
@@ -155,21 +155,21 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
|
||||
1 SIMPLE t2 ALL NULL NULL NULL NULL 3 100.00 Using where
|
||||
1 SIMPLE t1 ALL NULL NULL NULL NULL 5 100.00 Using where; Using join buffer (flat, BNL join)
|
||||
Warnings:
|
||||
Note 1003 select `test`.`t1`.`x` AS `IJ2_x1`,`test`.`t1`.`y` AS `y1`,`test`.`t2`.`x` AS `x2`,`test`.`t2`.`y` AS `y2` from `test`.`t1` FOR SYSTEM_TIME AS OF TIMESTAMP @`t0` join `test`.`t2` FOR SYSTEM_TIME AS OF TIMESTAMP @`t0` where `test`.`t1`.`x` = `test`.`t2`.`x` and `test`.`t2`.`row_end` > @`t0` and `test`.`t2`.`row_start` <= @`t0` and `test`.`t1`.`row_end` > @`t0` and `test`.`t1`.`row_start` <= @`t0`
|
||||
Note 1003 select `test`.`t1`.`x` AS `IJ2_x1`,`test`.`t1`.`y` AS `y1`,`test`.`t2`.`x` AS `x2`,`test`.`t2`.`y` AS `y2` from `test`.`t1` FOR SYSTEM_TIME AS OF TIMESTAMP @`t0` join `test`.`t2` FOR SYSTEM_TIME AS OF TIMESTAMP @`t0` where `test`.`t1`.`x` = `test`.`t2`.`x` and `test`.`t2`.`row_end` > TIMESTAMP/*WITH LOCAL TIME ZONE*/'YYYY-MM-DD hh:ss:mm:.uuuuuu' and `test`.`t2`.`row_start` <= TIMESTAMP/*WITH LOCAL TIME ZONE*/'YYYY-MM-DD hh:ss:mm:.uuuuuu' and `test`.`t1`.`row_end` > TIMESTAMP/*WITH LOCAL TIME ZONE*/'YYYY-MM-DD hh:ss:mm:.uuuuuu' and `test`.`t1`.`row_start` <= TIMESTAMP/*WITH LOCAL TIME ZONE*/'YYYY-MM-DD hh:ss:mm:.uuuuuu'
|
||||
explain extended select * from (select t1.x as LJ2_x1, t1.y as y1, t2.x as x2, t2.y as y2 from t1 left join t2 on t1.x = t2.x)
|
||||
for system_time as of timestamp @t0 as t;
|
||||
id select_type table type possible_keys key key_len ref rows filtered Extra
|
||||
1 SIMPLE t1 ALL NULL NULL NULL NULL 5 100.00 Using where
|
||||
1 SIMPLE t2 ALL NULL NULL NULL NULL 3 100.00 Using where; Using join buffer (flat, BNL join)
|
||||
Warnings:
|
||||
Note 1003 select `test`.`t1`.`x` AS `LJ2_x1`,`test`.`t1`.`y` AS `y1`,`test`.`t2`.`x` AS `x2`,`test`.`t2`.`y` AS `y2` from `test`.`t1` FOR SYSTEM_TIME AS OF TIMESTAMP @`t0` left join `test`.`t2` FOR SYSTEM_TIME AS OF TIMESTAMP @`t0` on(`test`.`t2`.`x` = `test`.`t1`.`x` and `test`.`t2`.`row_end` > @`t0` and `test`.`t2`.`row_start` <= @`t0`) where `test`.`t1`.`row_end` > @`t0` and `test`.`t1`.`row_start` <= @`t0`
|
||||
Note 1003 select `test`.`t1`.`x` AS `LJ2_x1`,`test`.`t1`.`y` AS `y1`,`test`.`t2`.`x` AS `x2`,`test`.`t2`.`y` AS `y2` from `test`.`t1` FOR SYSTEM_TIME AS OF TIMESTAMP @`t0` left join `test`.`t2` FOR SYSTEM_TIME AS OF TIMESTAMP @`t0` on(`test`.`t2`.`x` = `test`.`t1`.`x` and `test`.`t2`.`row_end` > TIMESTAMP/*WITH LOCAL TIME ZONE*/'YYYY-MM-DD hh:ss:mm:.uuuuuu' and `test`.`t2`.`row_start` <= TIMESTAMP/*WITH LOCAL TIME ZONE*/'YYYY-MM-DD hh:ss:mm:.uuuuuu') where `test`.`t1`.`row_end` > TIMESTAMP/*WITH LOCAL TIME ZONE*/'YYYY-MM-DD hh:ss:mm:.uuuuuu' and `test`.`t1`.`row_start` <= TIMESTAMP/*WITH LOCAL TIME ZONE*/'YYYY-MM-DD hh:ss:mm:.uuuuuu'
|
||||
explain extended select * from (select t1.x as RJ2_x1, t1.y as y1, t2.x as x2, t2.y as y2 from t1 right join t2 on t1.x = t2.x)
|
||||
for system_time as of timestamp @t0 as t;
|
||||
id select_type table type possible_keys key key_len ref rows filtered Extra
|
||||
1 SIMPLE t2 ALL NULL NULL NULL NULL 3 100.00 Using where
|
||||
1 SIMPLE t1 ALL NULL NULL NULL NULL 5 100.00 Using where; Using join buffer (flat, BNL join)
|
||||
Warnings:
|
||||
Note 1003 select `test`.`t1`.`x` AS `RJ2_x1`,`test`.`t1`.`y` AS `y1`,`test`.`t2`.`x` AS `x2`,`test`.`t2`.`y` AS `y2` from `test`.`t2` FOR SYSTEM_TIME AS OF TIMESTAMP @`t0` left join `test`.`t1` FOR SYSTEM_TIME AS OF TIMESTAMP @`t0` on(`test`.`t1`.`x` = `test`.`t2`.`x` and `test`.`t1`.`row_end` > @`t0` and `test`.`t1`.`row_start` <= @`t0`) where `test`.`t2`.`row_end` > @`t0` and `test`.`t2`.`row_start` <= @`t0`
|
||||
Note 1003 select `test`.`t1`.`x` AS `RJ2_x1`,`test`.`t1`.`y` AS `y1`,`test`.`t2`.`x` AS `x2`,`test`.`t2`.`y` AS `y2` from `test`.`t2` FOR SYSTEM_TIME AS OF TIMESTAMP @`t0` left join `test`.`t1` FOR SYSTEM_TIME AS OF TIMESTAMP @`t0` on(`test`.`t1`.`x` = `test`.`t2`.`x` and `test`.`t1`.`row_end` > TIMESTAMP/*WITH LOCAL TIME ZONE*/'YYYY-MM-DD hh:ss:mm:.uuuuuu' and `test`.`t1`.`row_start` <= TIMESTAMP/*WITH LOCAL TIME ZONE*/'YYYY-MM-DD hh:ss:mm:.uuuuuu') where `test`.`t2`.`row_end` > TIMESTAMP/*WITH LOCAL TIME ZONE*/'YYYY-MM-DD hh:ss:mm:.uuuuuu' and `test`.`t2`.`row_start` <= TIMESTAMP/*WITH LOCAL TIME ZONE*/'YYYY-MM-DD hh:ss:mm:.uuuuuu'
|
||||
select * from (select t1.x as IJ2_x1, t1.y as y1, t2.x as x2, t2.y as y2 from t1 inner join t2 on t1.x = t2.x)
|
||||
for system_time as of timestamp @t0 as t;
|
||||
IJ2_x1 y1 x2 y2
|
||||
|
@@ -5,6 +5,8 @@ if (`SELECT $PS_PROTOCOL != 0`)
|
||||
--source include/have_innodb.inc
|
||||
--source include/default_optimizer_switch.inc
|
||||
|
||||
--let $replace_regex_tsltz6= /TIMESTAMP..WITH LOCAL TIME ZONE..'....-..-.. ..:..:..[.]......'/TIMESTAMP\/*WITH LOCAL TIME ZONE*\/'YYYY-MM-DD hh:ss:mm:.uuuuuu'/
|
||||
|
||||
SET @saved_stats_persistent = @@GLOBAL.innodb_stats_persistent;
|
||||
SET GLOBAL innodb_stats_persistent = OFF;
|
||||
|
||||
@@ -42,6 +44,7 @@ select row_start into @ts_1 from emp where name="jane";
|
||||
|
||||
update emp set mgr=30 where name ="john";
|
||||
|
||||
--replace_regex $replace_regex_tsltz6
|
||||
explain extended
|
||||
with ancestors as (
|
||||
select e.emp_id, e.name, e.mgr, e.salary from emp as e where name = 'bill'
|
||||
@@ -68,6 +71,7 @@ as
|
||||
)
|
||||
select * from ancestors;
|
||||
|
||||
--replace_regex $replace_regex_tsltz6
|
||||
eval explain extended $q;
|
||||
eval $q;
|
||||
|
||||
@@ -86,6 +90,7 @@ as
|
||||
)
|
||||
select * from ancestors for system_time as of timestamp @ts_1;
|
||||
|
||||
--replace_regex $replace_regex_tsltz6
|
||||
eval explain extended $q;
|
||||
eval $q;
|
||||
|
||||
@@ -104,6 +109,7 @@ as
|
||||
)
|
||||
select name from emp where emp_id in (select emp_id from ancestors for system_time as of timestamp @ts_1);
|
||||
|
||||
--replace_regex $replace_regex_tsltz6
|
||||
eval explain extended $q;
|
||||
eval $q;
|
||||
|
||||
|
@@ -1,5 +1,7 @@
|
||||
--source include/default_optimizer_switch.inc
|
||||
|
||||
--let $replace_regex_tsltz6= /TIMESTAMP..WITH LOCAL TIME ZONE..'....-..-.. ..:..:..[.]......'/TIMESTAMP\/*WITH LOCAL TIME ZONE*\/'YYYY-MM-DD hh:ss:mm:.uuuuuu'/
|
||||
|
||||
create table emp
|
||||
(
|
||||
emp_id int,
|
||||
@@ -164,6 +166,7 @@ select * from (
|
||||
select t1.x, t1.y as y1, t2.x as x2, t2.y as y2
|
||||
from t1 join t2 on t1.x = t2.x) for system_time as of now() as t;
|
||||
|
||||
--replace_regex $replace_regex_tsltz6
|
||||
let $a=`show warnings`;
|
||||
--echo Query A:
|
||||
echo $a;
|
||||
@@ -174,6 +177,7 @@ select * from (
|
||||
from t1 for system_time as of now()
|
||||
join t2 for system_time as of now() on t1.x = t2.x) as t;
|
||||
|
||||
--replace_regex $replace_regex_tsltz6
|
||||
let $b=`show warnings`;
|
||||
--echo Query B:
|
||||
echo $b;
|
||||
|
@@ -6,6 +6,8 @@ if (`SELECT $PS_PROTOCOL != 0`)
|
||||
--source suite/versioning/common.inc
|
||||
--source include/default_optimizer_switch.inc
|
||||
|
||||
--let $replace_regex_tsltz6= /TIMESTAMP..WITH LOCAL TIME ZONE..'....-..-.. ..:..:..[.]......'/TIMESTAMP\/*WITH LOCAL TIME ZONE*\/'YYYY-MM-DD hh:ss:mm:.uuuuuu'/
|
||||
|
||||
SET @saved_stats_persistent = @@GLOBAL.innodb_stats_persistent;
|
||||
SET GLOBAL innodb_stats_persistent = OFF;
|
||||
|
||||
@@ -98,11 +100,14 @@ delete from t1;
|
||||
delete from t2;
|
||||
|
||||
#384
|
||||
--replace_regex $replace_regex_tsltz6
|
||||
explain extended select * from (select t1.x as IJ2_x1, t1.y as y1, t2.x as x2, t2.y as y2 from t1 inner join t2 on t1.x = t2.x)
|
||||
for system_time as of timestamp @t0 as t;
|
||||
--replace_regex $replace_regex_tsltz6
|
||||
explain extended select * from (select t1.x as LJ2_x1, t1.y as y1, t2.x as x2, t2.y as y2 from t1 left join t2 on t1.x = t2.x)
|
||||
for system_time as of timestamp @t0 as t;
|
||||
#383
|
||||
--replace_regex $replace_regex_tsltz6
|
||||
explain extended select * from (select t1.x as RJ2_x1, t1.y as y1, t2.x as x2, t2.y as y2 from t1 right join t2 on t1.x = t2.x)
|
||||
for system_time as of timestamp @t0 as t;
|
||||
|
||||
|
11
sql/item.cc
11
sql/item.cc
@@ -7332,6 +7332,17 @@ void Item_datetime_literal::print(String *str, enum_query_type query_type)
|
||||
}
|
||||
|
||||
|
||||
void Item_timestamp_literal::print(String *str, enum_query_type query_type)
|
||||
{
|
||||
str->append(STRING_WITH_LEN("TIMESTAMP/*WITH LOCAL TIME ZONE*/'"));
|
||||
char buf[MAX_DATE_STRING_REP_LENGTH];
|
||||
Datetime dt= m_value.to_datetime(current_thd);
|
||||
int length= my_datetime_to_str(dt.get_mysql_time(), buf, decimals);
|
||||
str->append(buf, length);
|
||||
str->append('\'');
|
||||
}
|
||||
|
||||
|
||||
Item *Item_datetime_literal::clone_item(THD *thd)
|
||||
{
|
||||
return new (thd->mem_root) Item_datetime_literal(thd, &cached_time, decimals);
|
||||
|
18
sql/item.h
18
sql/item.h
@@ -5005,9 +5005,21 @@ class Item_timestamp_literal: public Item_literal
|
||||
public:
|
||||
Item_timestamp_literal(THD *thd)
|
||||
:Item_literal(thd)
|
||||
{ }
|
||||
{
|
||||
collation= DTCollation_numeric();
|
||||
}
|
||||
Item_timestamp_literal(THD *thd,
|
||||
const Timestamp_or_zero_datetime &value,
|
||||
decimal_digits_t dec)
|
||||
:Item_literal(thd),
|
||||
m_value(value)
|
||||
{
|
||||
collation= DTCollation_numeric();
|
||||
decimals= dec;
|
||||
}
|
||||
const Type_handler *type_handler() const override
|
||||
{ return &type_handler_timestamp2; }
|
||||
void print(String *str, enum_query_type query_type) override;
|
||||
int save_in_field(Field *field, bool) override
|
||||
{
|
||||
Timestamp_or_zero_datetime_native native(m_value, decimals);
|
||||
@@ -5039,6 +5051,10 @@ public:
|
||||
{
|
||||
return m_value.to_native(to, decimals);
|
||||
}
|
||||
const Timestamp_or_zero_datetime &value() const
|
||||
{
|
||||
return m_value;
|
||||
}
|
||||
void set_value(const Timestamp_or_zero_datetime &value)
|
||||
{
|
||||
m_value= value;
|
||||
|
@@ -392,6 +392,9 @@ static bool convert_const_to_int(THD *thd, Item_field *field_item,
|
||||
This directly contradicts the manual (number and a string should
|
||||
be compared as doubles), but seems to provide more
|
||||
"intuitive" behavior in some cases (but less intuitive in others).
|
||||
|
||||
This method should be moved to Type_handler::convert_item_for_comparison()
|
||||
eventually.
|
||||
*/
|
||||
void Item_func::convert_const_compared_to_int_field(THD *thd)
|
||||
{
|
||||
@@ -412,6 +415,43 @@ void Item_func::convert_const_compared_to_int_field(THD *thd)
|
||||
}
|
||||
|
||||
|
||||
bool Item_func::aggregate_args2_for_comparison_with_conversion(
|
||||
THD *thd,
|
||||
Type_handler_hybrid_field_type *th)
|
||||
{
|
||||
DBUG_ASSERT(arg_count >= 2);
|
||||
for (bool done= false ; !done ; )
|
||||
{
|
||||
if (th->aggregate_for_comparison(func_name_cstring(), args, 2, false))
|
||||
return true;
|
||||
if (thd->lex->is_ps_or_view_context_analysis())
|
||||
return false;
|
||||
done= true;
|
||||
for (uint subject= 0; subject < 2; subject++)
|
||||
{
|
||||
uint other_side= subject == 0 ? 1 : 0;
|
||||
/* See comment in convert_const_to_int() */
|
||||
if (!args[subject]->with_sum_func() &&
|
||||
args[subject]->can_eval_in_optimize())
|
||||
{
|
||||
Item *item= th->type_handler()->convert_item_for_comparison(thd,
|
||||
args[subject],
|
||||
args[other_side]);
|
||||
if (!item)
|
||||
return true; // An error happened, e.g. EOM
|
||||
if (item != args[subject])
|
||||
{
|
||||
thd->change_item_tree(&args[subject], item);
|
||||
done= false; // Aggregate again, using the replacement item
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Iterate through arguments and compare them to the original arguments
|
||||
in "old_args". If some argument was replaced:
|
||||
@@ -487,7 +527,7 @@ bool Item_bool_rowready_func2::fix_length_and_dec(THD *thd)
|
||||
Item_args old_args(args[0], args[1]);
|
||||
convert_const_compared_to_int_field(thd);
|
||||
Type_handler_hybrid_field_type tmp;
|
||||
if (tmp.aggregate_for_comparison(func_name_cstring(), args, 2, false) ||
|
||||
if (aggregate_args2_for_comparison_with_conversion(thd, &tmp) ||
|
||||
tmp.type_handler()->Item_bool_rowready_func2_fix_length_and_dec(thd,
|
||||
this))
|
||||
{
|
||||
@@ -2804,7 +2844,10 @@ Item_func_nullif::fix_length_and_dec(THD *thd)
|
||||
set_maybe_null();
|
||||
m_arg0= args[0];
|
||||
convert_const_compared_to_int_field(thd);
|
||||
if (cmp.set_cmp_func(thd, this, &args[0], &args[1], true/*set_null*/))
|
||||
Type_handler_hybrid_field_type tmp;
|
||||
if (aggregate_args2_for_comparison_with_conversion(thd, &tmp) ||
|
||||
cmp.set_cmp_func(thd, this, tmp.type_handler(),
|
||||
&args[0], &args[1], true/*set_null*/))
|
||||
return true;
|
||||
/*
|
||||
A special code for EXECUTE..PREPARE.
|
||||
|
@@ -83,6 +83,8 @@ protected:
|
||||
return print_sql_mode_qualified_name(to, query_type, func_name_cstring());
|
||||
}
|
||||
|
||||
bool aggregate_args2_for_comparison_with_conversion(THD *thd,
|
||||
Type_handler_hybrid_field_type *th);
|
||||
public:
|
||||
|
||||
// Print an error message for a builtin-schema qualified function call
|
||||
|
@@ -1207,6 +1207,63 @@ void thd_gmt_sec_to_TIME(MYSQL_THD thd, MYSQL_TIME *ltime, my_time_t t)
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
@brief
|
||||
Convert a non-zero DATETIME to its safe timeval based representation,
|
||||
which guarantees a safe roundtrip DATETIME->timeval->DATETIME,
|
||||
e.g. to optimize:
|
||||
|
||||
WHERE timestamp_arg0 = datetime_arg1
|
||||
|
||||
in the way that we replace "datetime_arg1" to its TIMESTAMP equivalent
|
||||
"timestamp_arg1" and switch from DATETIME comparison to TIMESTAMP comparison:
|
||||
|
||||
WHERE timestamp_arg0 = timestamp_arg1
|
||||
|
||||
This helps to avoid slow TIMESTAMP->DATETIME data type conversion
|
||||
for timestamp_arg0 per row.
|
||||
|
||||
@detail
|
||||
Round trip is possible if the input "YYYY-MM-DD hh:mm:ss" value
|
||||
satisfies the following conditions:
|
||||
|
||||
1. TIME_to_gmt_sec() returns no errors or warnings,
|
||||
which means the input value
|
||||
a. has no zeros in YYYYMMDD
|
||||
b. fits into the TIMESTAMP range
|
||||
c. does not fall into the spring forward gap
|
||||
(because values inside gaps get adjusted to the beginning of the gap)
|
||||
|
||||
2. The my_time_t value returned by TIME_to_gmt_sec() must not be
|
||||
near a DST change or near a leap second, to avoid anomalies:
|
||||
- "YYYY-MM-DD hh:mm:ss" has more than one matching my_time_t values
|
||||
- "YYYY-MM-DD hh:mm:ss" has no matching my_time_t values
|
||||
(e.g. fall into the spring forward gap)
|
||||
|
||||
@param dt The DATETIME value to convert.
|
||||
Must not be zero '0000-00-00 00:00:00.000000'.
|
||||
(The zero value must be handled by the caller).
|
||||
|
||||
@return The conversion result
|
||||
@retval If succeeded, non-NULL Timeval value.
|
||||
@retval Timeval_null value representing SQL NULL if the argument
|
||||
does not have a safe replacement.
|
||||
*/
|
||||
Timeval_null
|
||||
THD::safe_timeval_replacement_for_nonzero_datetime(const Datetime &dt)
|
||||
{
|
||||
used|= THD::TIME_ZONE_USED;
|
||||
DBUG_ASSERT(non_zero_date(dt.get_mysql_time()));
|
||||
uint error= 0;
|
||||
const MYSQL_TIME *ltime= dt.get_mysql_time();
|
||||
my_time_t sec= variables.time_zone->TIME_to_gmt_sec(ltime, &error);
|
||||
if (error /* (1) */ ||
|
||||
!variables.time_zone->is_monotone_continuous_around(sec) /* (2) */)
|
||||
return Timeval_null();
|
||||
return Timeval_null(sec, ltime->second_part);
|
||||
}
|
||||
|
||||
|
||||
#ifdef _WIN32
|
||||
extern "C" my_thread_id next_thread_id_noinline()
|
||||
{
|
||||
|
@@ -4283,6 +4283,8 @@ public:
|
||||
utime_after_query= current_utime();
|
||||
}
|
||||
|
||||
Timeval_null safe_timeval_replacement_for_nonzero_datetime(const Datetime &);
|
||||
|
||||
/**
|
||||
Update server status after execution of a top level statement.
|
||||
Currently only checks if a query was slow, and assigns
|
||||
|
135
sql/sql_type.cc
135
sql/sql_type.cc
@@ -7686,6 +7686,104 @@ Item *Type_handler_row::
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/***************************************************************************/
|
||||
|
||||
/*
|
||||
Check if in a predicate like:
|
||||
|
||||
WHERE timestamp_arg=datetime_arg
|
||||
|
||||
we can replace DATETIME comparison to TIMESTAMP comparison,
|
||||
to avoid slow TIMESTAMP->DATETIME data type conversion per row.
|
||||
|
||||
TIMESTAMP and DATETIME are compared as DATETIME historically.
|
||||
This may be inefficient, because involves a conversion of
|
||||
the TIMESTAMP side to DATETIME per row.
|
||||
The conversion happens in Timezone::gmt_sec_to_TIME().
|
||||
E.g. in case of the SYSTEM timezone, it calls localtime_r(),
|
||||
which is known to be slow.
|
||||
|
||||
It's generally not possible to compare TIMESTAMP and DATETIME
|
||||
as TIMESTAMP without behavior change, because:
|
||||
- DATETIME has a wider range.
|
||||
- Two different TIMESTAMP values can have the same DATETIME value
|
||||
near the "fall back" DST change, as well as for leap seconds.
|
||||
- There are DATETIME gaps during the "spring forward" DST switch.
|
||||
|
||||
However, if the DATETIME side is a constant, then we can compare
|
||||
it to TIMESTAMP as TIMESTAMP in many cases. The DATETIME argument can
|
||||
be converted once to TIMESTAMP, so no data type conversion will
|
||||
happen per row. This is faster for big tables.
|
||||
|
||||
The comparison predicates must satisfy the following conditions:
|
||||
1. There must be a proper data type combination:
|
||||
- other must be of the TIMESTAMP data type
|
||||
- subject must be of the DATETIME data type,
|
||||
or can convert to DATETIME.
|
||||
2. subject must be a constant
|
||||
3. subject must convert to TIMESTAMP safely
|
||||
(without time zone anomalies near its value)
|
||||
*/
|
||||
|
||||
Item *
|
||||
Type_handler_datetime_common::convert_item_for_comparison(
|
||||
THD *thd,
|
||||
Item *subject,
|
||||
const Item *counterpart)
|
||||
const
|
||||
{
|
||||
if (!dynamic_cast<const Type_handler_timestamp_common*>(
|
||||
counterpart->type_handler()) ||
|
||||
!subject->type_handler()->can_return_date())
|
||||
return subject;
|
||||
|
||||
struct Count_handler : public Internal_error_handler
|
||||
{
|
||||
uint hit= 0;
|
||||
bool handle_condition(THD *thd,
|
||||
uint sql_errno,
|
||||
const char *sqlstate,
|
||||
Sql_condition::enum_warning_level *level,
|
||||
const char *msg,
|
||||
Sql_condition **cond_hdl)
|
||||
{
|
||||
hit++;
|
||||
return *level == Sql_condition::WARN_LEVEL_WARN;
|
||||
}
|
||||
} cnt_handler;
|
||||
|
||||
// Suppress and count warnings
|
||||
thd->push_internal_handler(&cnt_handler);
|
||||
Datetime dt(thd, subject, Timestamp::DatetimeOptions(thd));
|
||||
thd->pop_internal_handler();
|
||||
|
||||
if (!dt.is_valid_datetime() || cnt_handler.hit)
|
||||
{
|
||||
/*
|
||||
SQL NULL DATETIME, or a DATETIME with zeros in YYYYMMDD,
|
||||
or warnings during DATETIME evaluation.
|
||||
*/
|
||||
return subject;
|
||||
}
|
||||
|
||||
// '0000-00-00 00:00:00' is a special valid MariaDB TIMESTAMP value
|
||||
if (!non_zero_date(dt.get_mysql_time()))
|
||||
return new (thd->mem_root) Item_timestamp_literal(thd,
|
||||
Timestamp_or_zero_datetime::zero(),
|
||||
subject->datetime_precision(thd));
|
||||
|
||||
const Timeval_null tv(thd->safe_timeval_replacement_for_nonzero_datetime(dt));
|
||||
if (tv.is_null())
|
||||
return subject; // Time zone anomalies found around "dt"
|
||||
|
||||
// Should be safe to convert
|
||||
const Timestamp_or_zero_datetime ts(Timestamp(tv.to_timeval()));
|
||||
return new (thd->mem_root) Item_timestamp_literal(thd,
|
||||
ts,
|
||||
subject->datetime_precision(thd));
|
||||
}
|
||||
|
||||
|
||||
/***************************************************************************/
|
||||
|
||||
static const char* item_name(Item *a, String *str)
|
||||
@@ -8686,6 +8784,43 @@ Type_handler_temporal_result::Item_const_eq(const Item_const *a,
|
||||
b->get_type_all_attributes_from_const()->decimals);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
@brief
|
||||
Check if two costant timestamp values are identical.
|
||||
|
||||
@return
|
||||
true <=> *a and *b are identical
|
||||
*/
|
||||
bool
|
||||
Type_handler_timestamp_common::Item_const_eq(const Item_const *a,
|
||||
const Item_const *b,
|
||||
bool binary_cmp) const
|
||||
{
|
||||
/*
|
||||
In a condition like:
|
||||
WHERE IF(a='2001-01-01 00:00:00',1,0)=IF(a='2001-01-01 00:00:00',1,0);
|
||||
Item_func_eq::fix_length_and_dec() calls get_timestamp_item_for_comparison()
|
||||
which replaces string literals '2001-01-01 00:00:00' with
|
||||
Item_timestamp_literal instances, which later during remove_eq_conds()
|
||||
come to here.
|
||||
|
||||
Note, Item_param bound to TIMESTAMP is not detected here,
|
||||
so trivial conditions of this kind do not get eliminated:
|
||||
DECLARE ts TIMESTAMP DEFAULT (SELECT MAX(ts_col) FROM t1);
|
||||
EXECUTE IMMEDIATE
|
||||
'SELECT * FROM t1 WHERE COALESCE(ts_col,?)<=>COALESCE(ts_col,?)'
|
||||
USING ts, ts;
|
||||
It should be fixed by MDEV-14271.
|
||||
*/
|
||||
const Item_timestamp_literal *ta, *tb;
|
||||
if (!(ta= dynamic_cast<const Item_timestamp_literal*>(a)) ||
|
||||
!(tb= dynamic_cast<const Item_timestamp_literal*>(b)))
|
||||
return false;
|
||||
return !ta->value().cmp(tb->value());
|
||||
}
|
||||
|
||||
|
||||
/***************************************************************************/
|
||||
|
||||
const Type_handler *
|
||||
|
@@ -2837,6 +2837,11 @@ public:
|
||||
class Timestamp_or_zero_datetime: protected Timestamp
|
||||
{
|
||||
bool m_is_zero_datetime;
|
||||
public:
|
||||
static Timestamp_or_zero_datetime zero()
|
||||
{
|
||||
return Timestamp_or_zero_datetime(Timestamp(0, 0), true);
|
||||
}
|
||||
public:
|
||||
Timestamp_or_zero_datetime()
|
||||
:Timestamp(0,0), m_is_zero_datetime(true)
|
||||
@@ -2845,7 +2850,7 @@ public:
|
||||
:Timestamp(native.length() ? Timestamp(native) : Timestamp(0,0)),
|
||||
m_is_zero_datetime(native.length() == 0)
|
||||
{ }
|
||||
Timestamp_or_zero_datetime(const Timestamp &tm, bool is_zero_datetime)
|
||||
Timestamp_or_zero_datetime(const Timestamp &tm, bool is_zero_datetime= false)
|
||||
:Timestamp(tm), m_is_zero_datetime(is_zero_datetime)
|
||||
{ }
|
||||
Timestamp_or_zero_datetime(THD *thd, const MYSQL_TIME *ltime, uint *err_code);
|
||||
@@ -2869,6 +2874,11 @@ public:
|
||||
return 1;
|
||||
return Timestamp::cmp(other);
|
||||
}
|
||||
const Timestamp &to_timestamp() const
|
||||
{
|
||||
DBUG_ASSERT(!is_zero_datetime());
|
||||
return *this;
|
||||
}
|
||||
bool to_TIME(THD *thd, MYSQL_TIME *to, date_mode_t fuzzydate) const;
|
||||
/*
|
||||
Convert to native format:
|
||||
@@ -4206,6 +4216,33 @@ public:
|
||||
virtual Item *make_const_item_for_comparison(THD *thd,
|
||||
Item *src,
|
||||
const Item *cmp) const= 0;
|
||||
/**
|
||||
When aggregating function arguments for comparison
|
||||
(e.g. for =, <, >, <=, >=, NULLIF), in some cases we rewrite
|
||||
arguments. For example, if the predicate
|
||||
timestamp_expr0 = datetime_const_expr1
|
||||
decides to compare arguments as DATETIME,
|
||||
we can try to rewrite datetime_const_expr1 to a TIMESTAMP constant
|
||||
and perform the comparison as TIMESTAMP, which is faster because
|
||||
does not have to perform TIMESTAMP->DATETIME data type conversion per row.
|
||||
|
||||
"this" is the type handler that is used to compare
|
||||
"subject" and "counterpart" (DATETIME in the above example).
|
||||
@param thd the current thread
|
||||
@param subject the comparison side that we want try to rewrite
|
||||
@param counterpart the other comparison side
|
||||
@retval subject, if the subject does not need to be rewritten
|
||||
@retval NULL in case of error (e.g. EOM)
|
||||
@retval Otherwise, a pointer to a new Item which can
|
||||
be used as a replacement for the subject.
|
||||
*/
|
||||
virtual Item *convert_item_for_comparison(THD *thd,
|
||||
Item *subject,
|
||||
const Item *counterpart) const
|
||||
{
|
||||
return subject;
|
||||
}
|
||||
|
||||
virtual Item_cache *Item_get_cache(THD *thd, const Item *item) const= 0;
|
||||
virtual Item *make_constructor_item(THD *thd, List<Item> *args) const
|
||||
{
|
||||
@@ -6524,6 +6561,9 @@ public:
|
||||
}
|
||||
String *print_item_value(THD *thd, Item *item, String *str) const override;
|
||||
Item_cache *Item_get_cache(THD *thd, const Item *item) const override;
|
||||
Item *convert_item_for_comparison(THD *thd,
|
||||
Item *subject,
|
||||
const Item *counterpart) const override;
|
||||
String *Item_func_min_max_val_str(Item_func_min_max *, String *) const override;
|
||||
double Item_func_min_max_val_real(Item_func_min_max *) const override;
|
||||
longlong Item_func_min_max_val_int(Item_func_min_max *) const override;
|
||||
@@ -6695,6 +6735,8 @@ public:
|
||||
my_decimal *Item_func_min_max_val_decimal(Item_func_min_max *,
|
||||
my_decimal *) const override;
|
||||
bool set_comparator_func(THD *thd, Arg_comparator *cmp) const override;
|
||||
bool Item_const_eq(const Item_const *a, const Item_const *b,
|
||||
bool binary_cmp) const override;
|
||||
bool Item_hybrid_func_fix_attributes(THD *thd,
|
||||
const LEX_CSTRING &name,
|
||||
Type_handler_hybrid_field_type *,
|
||||
|
@@ -1035,4 +1035,29 @@ public:
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
A value that's either a Timeval or SQL NULL
|
||||
*/
|
||||
|
||||
class Timeval_null: protected Timeval
|
||||
{
|
||||
bool m_is_null;
|
||||
public:
|
||||
Timeval_null()
|
||||
:Timeval(0, 0),
|
||||
m_is_null(true)
|
||||
{ }
|
||||
Timeval_null(const my_time_t sec, ulong usec)
|
||||
:Timeval(sec, usec),
|
||||
m_is_null(false)
|
||||
{ }
|
||||
const Timeval & to_timeval() const
|
||||
{
|
||||
DBUG_ASSERT(!m_is_null);
|
||||
return *this;
|
||||
}
|
||||
bool is_null() const { return m_is_null; }
|
||||
};
|
||||
|
||||
|
||||
#endif /* STRUCTS_INCLUDED */
|
||||
|
@@ -2426,6 +2426,59 @@ void Time_zone::adjust_leap_second(MYSQL_TIME *t)
|
||||
t->second= 59;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
@brief
|
||||
Check if timestamp<->datetime conversion is guaranteed to be reversible
|
||||
around the given time value.
|
||||
*/
|
||||
|
||||
bool Time_zone::is_monotone_continuous_around(my_time_t sec) const
|
||||
{
|
||||
const my_time_t width= 24 * 60 * 60;
|
||||
/*
|
||||
Let's check that the TIMESTAMP range [sec - width, sec + width]
|
||||
converts back to a DATETIME range [dtmin, dtmax], and the difference
|
||||
(dtmax-dtmin), calculated using DATETIME arithmetics,
|
||||
is also equal to exactly 2*width.
|
||||
|
||||
This should almost guarantee that the TIMESTAMP range around sec
|
||||
is monotone and continuous and thus has no DST changes or leap seconds.
|
||||
|
||||
It's still possible that there are two or more timezone offset changes
|
||||
in the given range. But there are no such time zones according to
|
||||
our knowledge.
|
||||
Note, DST changes and leap seconds do not interfere on a short time_t range:
|
||||
- Leap seconds happen in winter and summer
|
||||
- DST changes happen in spring and fall
|
||||
|
||||
The largest time zone change that ever happened in a single place
|
||||
was 24 hours:
|
||||
- from SST (UTC-11) - the American Samoa Time Zone
|
||||
- to WST (UTC+13) - the Independent State of Samoa Time Zone
|
||||
The Independent State of Samoa used SST until it moved across
|
||||
the International Date Line at the end of 29 December 2011, to WST.
|
||||
It is now 24 hours ahead of American Samoa
|
||||
(and 25 hours in Southern hemisphere summer).
|
||||
Let's use 24 hours as width (48 hours range total).
|
||||
*/
|
||||
|
||||
if (sec < width || sec > TIMESTAMP_MAX_VALUE - width)
|
||||
return false;
|
||||
|
||||
MYSQL_TIME dtmin, dtmax;
|
||||
gmt_sec_to_TIME(&dtmin, sec - width);
|
||||
gmt_sec_to_TIME(&dtmax, sec + width);
|
||||
|
||||
ulonglong seconds;
|
||||
ulong useconds;
|
||||
if (calc_time_diff(&dtmax, &dtmin, 1, &seconds, &useconds))
|
||||
return false; // dtmax is smaller than dtmin, should not happen.
|
||||
if (seconds != (ulonglong) width * 2)
|
||||
return false; // Anomalies found (DST changes or leap seconds)
|
||||
return true;
|
||||
}
|
||||
|
||||
#endif /* !defined(TESTTIME) && !defined(TZINFO2SQL) */
|
||||
|
||||
|
||||
|
@@ -80,6 +80,13 @@ public:
|
||||
*/
|
||||
virtual ~Time_zone() = default;
|
||||
|
||||
/**
|
||||
Check if the time zone does not have any anomalies around "sec", such as:
|
||||
- DST changes (spring forward, fall back)
|
||||
- leap seconds (the 60-th second)
|
||||
*/
|
||||
bool is_monotone_continuous_around(my_time_t sec) const;
|
||||
|
||||
protected:
|
||||
static inline void adjust_leap_second(MYSQL_TIME *t);
|
||||
};
|
||||
|
@@ -257,7 +257,7 @@ select t0.`col_a` `col_a`,t0.`col_dt` `col_dt`,t0.`col_ts` `col_ts`,(unix_timest
|
||||
select t0.`col_a` `col_a`,t0.`col_dt` `col_dt`,t0.`col_ts` `col_ts`,(unix_timestamp(t0.`col_ts`)) `unix_timestamp(col_ts)` from `ts_test_remote`.`tbl_a` t0 where (_latin1'2018-10-28 01:30:00' > t0.`col_ts`)
|
||||
select t0.`col_a` `col_a`,t0.`col_dt` `col_dt`,t0.`col_ts` `col_ts`,(unix_timestamp(t0.`col_ts`)) `unix_timestamp(col_ts)` from `ts_test_remote`.`tbl_a` t0 where (t0.`col_ts` between _latin1'2018-10-28 00:30:00' and _latin1'2018-10-28 01:30:00')
|
||||
select t0.`col_a` `col_a`,t0.`col_dt` `col_dt`,t0.`col_ts` `col_ts`,(unix_timestamp(t0.`col_ts`)) `unix_timestamp(col_ts)` from `ts_test_remote`.`tbl_a` t0 where ((t0.`col_ts` >= _latin1'2018-10-28 00:30:00') and (t0.`col_ts` <= _latin1'2018-10-28 01:30:00'))
|
||||
select t0.`col_a` `col_a`,t0.`col_dt` `col_dt`,t0.`col_ts` `col_ts`,(unix_timestamp(t0.`col_ts`)) `unix_timestamp(col_ts)` from `ts_test_remote`.`tbl_a` t0 where (t0.`col_ts` > '2018-03-25 01:00:00')
|
||||
select t0.`col_a` `col_a`,t0.`col_dt` `col_dt`,t0.`col_ts` `col_ts`,(unix_timestamp(t0.`col_ts`)) `unix_timestamp(col_ts)` from `ts_test_remote`.`tbl_a` t0 where (t0.`col_ts` > _latin1'2018-03-25 01:00:00')
|
||||
select t0.`col_a` `col_a`,t0.`col_dt` `col_dt`,t0.`col_ts` `col_ts`,(unix_timestamp(t0.`col_ts`)) `unix_timestamp(col_ts)` from `ts_test_remote`.`tbl_a` t0 where (t0.`col_ts` > '1970-01-01 00:00:01')
|
||||
SELECT argument FROM mysql.general_log WHERE command_type != 'Execute' AND argument LIKE '%select %'
|
||||
SELECT col_a, col_dt, col_ts, unix_timestamp(col_ts) FROM tbl_a ORDER BY col_a;
|
||||
@@ -344,7 +344,7 @@ select t0.`col_a` `col_a`,t0.`col_dt` `col_dt`,t0.`col_ts` `col_ts`,(unix_timest
|
||||
select t0.`col_a` `col_a`,t0.`col_dt` `col_dt`,t0.`col_ts` `col_ts`,(unix_timestamp(t0.`col_ts`)) `unix_timestamp(col_ts)` from `ts_test_remote`.`tbl_a` t0 where (_latin1'2018-10-28 01:30:00' > t0.`col_ts`)
|
||||
select t0.`col_a` `col_a`,t0.`col_dt` `col_dt`,t0.`col_ts` `col_ts`,(unix_timestamp(t0.`col_ts`)) `unix_timestamp(col_ts)` from `ts_test_remote`.`tbl_a` t0 where (t0.`col_ts` between _latin1'2018-10-28 00:30:00' and _latin1'2018-10-28 01:30:00')
|
||||
select t0.`col_a` `col_a`,t0.`col_dt` `col_dt`,t0.`col_ts` `col_ts`,(unix_timestamp(t0.`col_ts`)) `unix_timestamp(col_ts)` from `ts_test_remote`.`tbl_a` t0 where ((t0.`col_ts` >= _latin1'2018-10-28 00:30:00') and (t0.`col_ts` <= _latin1'2018-10-28 01:30:00'))
|
||||
select t0.`col_a` `col_a`,t0.`col_dt` `col_dt`,t0.`col_ts` `col_ts`,(unix_timestamp(t0.`col_ts`)) `unix_timestamp(col_ts)` from `ts_test_remote`.`tbl_a` t0 where (t0.`col_ts` > '2018-03-25 01:00:00')
|
||||
select t0.`col_a` `col_a`,t0.`col_dt` `col_dt`,t0.`col_ts` `col_ts`,(unix_timestamp(t0.`col_ts`)) `unix_timestamp(col_ts)` from `ts_test_remote`.`tbl_a` t0 where (t0.`col_ts` > _latin1'2018-03-25 01:00:00')
|
||||
select t0.`col_a` `col_a`,t0.`col_dt` `col_dt`,t0.`col_ts` `col_ts`,(unix_timestamp(t0.`col_ts`)) `unix_timestamp(col_ts)` from `ts_test_remote`.`tbl_a` t0 where (t0.`col_ts` > '1970-01-01 00:00:01')
|
||||
SELECT argument FROM mysql.general_log WHERE command_type != 'Execute' AND argument LIKE '%select %'
|
||||
SELECT col_a, col_dt, col_ts, unix_timestamp(col_ts) FROM tbl_a ORDER BY col_a;
|
||||
|
Reference in New Issue
Block a user