mirror of
https://github.com/MariaDB/server.git
synced 2026-05-10 17:14:30 +02:00
MDEV-13995 MAX(timestamp) returns a wrong result near DST change
This commit is contained in:
parent
5b3db87134
commit
34eb98387f
26 changed files with 1850 additions and 16 deletions
|
|
@ -180,3 +180,44 @@ a unix_timestamp(a)
|
||||||
2010-10-31 02:25:26 1288481126
|
2010-10-31 02:25:26 1288481126
|
||||||
drop table t1, t2;
|
drop table t1, t2;
|
||||||
set time_zone=DEFAULT;
|
set time_zone=DEFAULT;
|
||||||
|
#
|
||||||
|
# MDEV-13995 MAX(timestamp) returns a wrong result near DST change
|
||||||
|
#
|
||||||
|
SET global mysql56_temporal_format=false;
|
||||||
|
SET time_zone='+00:00';
|
||||||
|
CREATE TABLE t1 (a TIMESTAMP(0));
|
||||||
|
INSERT INTO t1 VALUES (FROM_UNIXTIME(1288477526) /*summer time in Moscow*/);
|
||||||
|
INSERT INTO t1 VALUES (FROM_UNIXTIME(1288477526+3599) /*winter time in Moscow*/);
|
||||||
|
SET time_zone='Europe/Moscow';
|
||||||
|
SELECT a, COALESCE(a), UNIX_TIMESTAMP(a) FROM t1;
|
||||||
|
a COALESCE(a) UNIX_TIMESTAMP(a)
|
||||||
|
2010-10-31 02:25:26 2010-10-31 02:25:26 1288477526
|
||||||
|
2010-10-31 02:25:25 2010-10-31 02:25:25 1288481125
|
||||||
|
SELECT MIN(a), UNIX_TIMESTAMP(MIN(a)) AS a FROM t1;
|
||||||
|
MIN(a) a
|
||||||
|
2010-10-31 02:25:26 1288477526
|
||||||
|
SELECT MAX(a), UNIX_TIMESTAMP(MAX(a)) AS a FROM t1;
|
||||||
|
MAX(a) a
|
||||||
|
2010-10-31 02:25:25 1288481125
|
||||||
|
SELECT t1.a, UNIX_TIMESTAMP(t1.a), t2.a, UNIX_TIMESTAMP(t2.a) FROM t1 t1, t1 t2 WHERE t1.a=t2.a;
|
||||||
|
a UNIX_TIMESTAMP(t1.a) a UNIX_TIMESTAMP(t2.a)
|
||||||
|
2010-10-31 02:25:26 1288477526 2010-10-31 02:25:26 1288477526
|
||||||
|
2010-10-31 02:25:25 1288481125 2010-10-31 02:25:25 1288481125
|
||||||
|
ALTER TABLE t1 MODIFY a TIMESTAMP(1);
|
||||||
|
SELECT a, COALESCE(a), UNIX_TIMESTAMP(a) FROM t1;
|
||||||
|
a COALESCE(a) UNIX_TIMESTAMP(a)
|
||||||
|
2010-10-31 02:25:26.0 2010-10-31 02:25:26.0 1288477526.0
|
||||||
|
2010-10-31 02:25:25.0 2010-10-31 02:25:25.0 1288481125.0
|
||||||
|
SELECT MIN(a), UNIX_TIMESTAMP(MIN(a)) AS a FROM t1;
|
||||||
|
MIN(a) a
|
||||||
|
2010-10-31 02:25:26.0 1288477526.0
|
||||||
|
SELECT MAX(a), UNIX_TIMESTAMP(MAX(a)) AS a FROM t1;
|
||||||
|
MAX(a) a
|
||||||
|
2010-10-31 02:25:25.0 1288481125.0
|
||||||
|
SELECT t1.a, UNIX_TIMESTAMP(t1.a), t2.a, UNIX_TIMESTAMP(t2.a) FROM t1 t1, t1 t2 WHERE t1.a=t2.a;
|
||||||
|
a UNIX_TIMESTAMP(t1.a) a UNIX_TIMESTAMP(t2.a)
|
||||||
|
2010-10-31 02:25:26.0 1288477526.0 2010-10-31 02:25:26.0 1288477526.0
|
||||||
|
2010-10-31 02:25:25.0 1288481125.0 2010-10-31 02:25:25.0 1288481125.0
|
||||||
|
DROP TABLE t1;
|
||||||
|
SET time_zone=DEFAULT;
|
||||||
|
SET global mysql56_temporal_format=true;
|
||||||
|
|
|
||||||
|
|
@ -119,3 +119,32 @@ insert t2 select a from t1;
|
||||||
select a, unix_timestamp(a) from t2;
|
select a, unix_timestamp(a) from t2;
|
||||||
drop table t1, t2;
|
drop table t1, t2;
|
||||||
set time_zone=DEFAULT;
|
set time_zone=DEFAULT;
|
||||||
|
|
||||||
|
|
||||||
|
--echo #
|
||||||
|
--echo # MDEV-13995 MAX(timestamp) returns a wrong result near DST change
|
||||||
|
--echo #
|
||||||
|
|
||||||
|
# This tests:
|
||||||
|
# Field_timestamp::val_native()
|
||||||
|
# Field_timestamp_hires::val_native()
|
||||||
|
# Type_handler_timestamp_common::type_handler_for_native_format()
|
||||||
|
|
||||||
|
SET global mysql56_temporal_format=false;
|
||||||
|
SET time_zone='+00:00';
|
||||||
|
CREATE TABLE t1 (a TIMESTAMP(0));
|
||||||
|
INSERT INTO t1 VALUES (FROM_UNIXTIME(1288477526) /*summer time in Moscow*/);
|
||||||
|
INSERT INTO t1 VALUES (FROM_UNIXTIME(1288477526+3599) /*winter time in Moscow*/);
|
||||||
|
SET time_zone='Europe/Moscow';
|
||||||
|
SELECT a, COALESCE(a), UNIX_TIMESTAMP(a) FROM t1;
|
||||||
|
SELECT MIN(a), UNIX_TIMESTAMP(MIN(a)) AS a FROM t1;
|
||||||
|
SELECT MAX(a), UNIX_TIMESTAMP(MAX(a)) AS a FROM t1;
|
||||||
|
SELECT t1.a, UNIX_TIMESTAMP(t1.a), t2.a, UNIX_TIMESTAMP(t2.a) FROM t1 t1, t1 t2 WHERE t1.a=t2.a;
|
||||||
|
ALTER TABLE t1 MODIFY a TIMESTAMP(1);
|
||||||
|
SELECT a, COALESCE(a), UNIX_TIMESTAMP(a) FROM t1;
|
||||||
|
SELECT MIN(a), UNIX_TIMESTAMP(MIN(a)) AS a FROM t1;
|
||||||
|
SELECT MAX(a), UNIX_TIMESTAMP(MAX(a)) AS a FROM t1;
|
||||||
|
SELECT t1.a, UNIX_TIMESTAMP(t1.a), t2.a, UNIX_TIMESTAMP(t2.a) FROM t1 t1, t1 t2 WHERE t1.a=t2.a;
|
||||||
|
DROP TABLE t1;
|
||||||
|
SET time_zone=DEFAULT;
|
||||||
|
SET global mysql56_temporal_format=true;
|
||||||
|
|
|
||||||
|
|
@ -353,5 +353,194 @@ Warning 1292 Truncated incorrect datetime value: '00:00:00'
|
||||||
SET old_mode=DEFAULT;
|
SET old_mode=DEFAULT;
|
||||||
SET timestamp=DEFAULT;
|
SET timestamp=DEFAULT;
|
||||||
#
|
#
|
||||||
|
# MDEV-13995 MAX(timestamp) returns a wrong result near DST change
|
||||||
|
#
|
||||||
|
SET time_zone='+00:00';
|
||||||
|
CREATE TABLE t1 (a TIMESTAMP);
|
||||||
|
INSERT INTO t1 VALUES (FROM_UNIXTIME(1288477526) /*summer time in Moscow*/);
|
||||||
|
INSERT INTO t1 VALUES (FROM_UNIXTIME(1288477526+3599) /*winter time in Moscow*/);
|
||||||
|
SET time_zone='Europe/Moscow';
|
||||||
|
SELECT a, UNIX_TIMESTAMP(a) FROM t1;
|
||||||
|
a UNIX_TIMESTAMP(a)
|
||||||
|
2010-10-31 02:25:26 1288477526
|
||||||
|
2010-10-31 02:25:25 1288481125
|
||||||
|
SELECT UNIX_TIMESTAMP(MAX(a)) AS a FROM t1;
|
||||||
|
a
|
||||||
|
1288481125
|
||||||
|
CREATE TABLE t2 (a TIMESTAMP);
|
||||||
|
INSERT INTO t2 SELECT MAX(a) AS a FROM t1;
|
||||||
|
SELECT a, UNIX_TIMESTAMP(a) FROM t2;
|
||||||
|
a UNIX_TIMESTAMP(a)
|
||||||
|
2010-10-31 02:25:25 1288481125
|
||||||
|
DROP TABLE t2;
|
||||||
|
DROP TABLE t1;
|
||||||
|
SET time_zone='+00:00';
|
||||||
|
CREATE TABLE t1 (a TIMESTAMP);
|
||||||
|
CREATE TABLE t2 (a TIMESTAMP);
|
||||||
|
INSERT INTO t1 VALUES (FROM_UNIXTIME(1288477526) /*summer time in Moscow*/);
|
||||||
|
INSERT INTO t2 VALUES (FROM_UNIXTIME(1288477526+3599) /*winter time in Moscow*/);
|
||||||
|
SET time_zone='Europe/Moscow';
|
||||||
|
SELECT UNIX_TIMESTAMP(t1.a), UNIX_TIMESTAMP(t2.a) FROM t1,t2;
|
||||||
|
UNIX_TIMESTAMP(t1.a) UNIX_TIMESTAMP(t2.a)
|
||||||
|
1288477526 1288481125
|
||||||
|
SELECT * FROM t1,t2 WHERE t1.a < t2.a;
|
||||||
|
a a
|
||||||
|
2010-10-31 02:25:26 2010-10-31 02:25:25
|
||||||
|
DROP TABLE t1,t2;
|
||||||
|
BEGIN NOT ATOMIC
|
||||||
|
DECLARE a,b TIMESTAMP;
|
||||||
|
SET time_zone='+00:00';
|
||||||
|
SET a=FROM_UNIXTIME(1288477526);
|
||||||
|
SET b=FROM_UNIXTIME(1288481125);
|
||||||
|
SELECT a < b;
|
||||||
|
SET time_zone='Europe/Moscow';
|
||||||
|
SELECT a < b;
|
||||||
|
END;
|
||||||
|
$$
|
||||||
|
a < b
|
||||||
|
1
|
||||||
|
a < b
|
||||||
|
1
|
||||||
|
CREATE OR REPLACE FUNCTION f1(uts INT) RETURNS TIMESTAMP
|
||||||
|
BEGIN
|
||||||
|
DECLARE ts TIMESTAMP;
|
||||||
|
DECLARE tz VARCHAR(64) DEFAULT @@time_zone;
|
||||||
|
SET time_zone='+00:00';
|
||||||
|
SET ts=FROM_UNIXTIME(uts);
|
||||||
|
SET time_zone=tz;
|
||||||
|
RETURN ts;
|
||||||
|
END;
|
||||||
|
$$
|
||||||
|
SET time_zone='+00:00';
|
||||||
|
SELECT f1(1288477526) < f1(1288481125);
|
||||||
|
f1(1288477526) < f1(1288481125)
|
||||||
|
1
|
||||||
|
SET time_zone='Europe/Moscow';
|
||||||
|
SELECT f1(1288477526) < f1(1288481125);
|
||||||
|
f1(1288477526) < f1(1288481125)
|
||||||
|
1
|
||||||
|
DROP FUNCTION f1;
|
||||||
|
CREATE TABLE t1 (a TIMESTAMP,b TIMESTAMP);
|
||||||
|
SET time_zone='+00:00';
|
||||||
|
INSERT INTO t1 VALUES (FROM_UNIXTIME(1288477526) /*summer time in Mowcow*/,
|
||||||
|
FROM_UNIXTIME(1288481125) /*winter time in Moscow*/);
|
||||||
|
SELECT *, LEAST(a,b) FROM t1;
|
||||||
|
a b LEAST(a,b)
|
||||||
|
2010-10-30 22:25:26 2010-10-30 23:25:25 2010-10-30 22:25:26
|
||||||
|
SET time_zone='Europe/Moscow';
|
||||||
|
SELECT *, LEAST(a,b) FROM t1;
|
||||||
|
a b LEAST(a,b)
|
||||||
|
2010-10-31 02:25:26 2010-10-31 02:25:25 2010-10-31 02:25:26
|
||||||
|
SELECT UNIX_TIMESTAMP(a), UNIX_TIMESTAMP(b), UNIX_TIMESTAMP(LEAST(a,b)) FROM t1;
|
||||||
|
UNIX_TIMESTAMP(a) UNIX_TIMESTAMP(b) UNIX_TIMESTAMP(LEAST(a,b))
|
||||||
|
1288477526 1288481125 1288477526
|
||||||
|
DROP TABLE t1;
|
||||||
|
CREATE TABLE t1 (a TIMESTAMP,b TIMESTAMP,c TIMESTAMP);
|
||||||
|
SET time_zone='+00:00';
|
||||||
|
INSERT INTO t1 VALUES (
|
||||||
|
FROM_UNIXTIME(1288477526) /*summer time in Moscow*/,
|
||||||
|
FROM_UNIXTIME(1288481125) /*winter time in Moscow*/,
|
||||||
|
FROM_UNIXTIME(1288481126) /*winter time in Moscow*/);
|
||||||
|
SELECT b BETWEEN a AND c FROM t1;
|
||||||
|
b BETWEEN a AND c
|
||||||
|
1
|
||||||
|
SET time_zone='Europe/Moscow';
|
||||||
|
SELECT b BETWEEN a AND c FROM t1;
|
||||||
|
b BETWEEN a AND c
|
||||||
|
1
|
||||||
|
DROP TABLE t1;
|
||||||
|
SET time_zone='+00:00';
|
||||||
|
CREATE TABLE t1 (a TIMESTAMP);
|
||||||
|
INSERT INTO t1 VALUES (FROM_UNIXTIME(1288477526) /*summer time in Mowcow*/);
|
||||||
|
INSERT INTO t1 VALUES (FROM_UNIXTIME(1288481125) /*winter time in Moscow*/);
|
||||||
|
SELECT a, UNIX_TIMESTAMP(a) FROM t1 ORDER BY a;
|
||||||
|
a UNIX_TIMESTAMP(a)
|
||||||
|
2010-10-30 22:25:26 1288477526
|
||||||
|
2010-10-30 23:25:25 1288481125
|
||||||
|
SELECT COALESCE(a) AS a, UNIX_TIMESTAMP(a) FROM t1 ORDER BY a;
|
||||||
|
a UNIX_TIMESTAMP(a)
|
||||||
|
2010-10-30 22:25:26 1288477526
|
||||||
|
2010-10-30 23:25:25 1288481125
|
||||||
|
SET time_zone='Europe/Moscow';
|
||||||
|
SELECT a, UNIX_TIMESTAMP(a) FROM t1 ORDER BY a;
|
||||||
|
a UNIX_TIMESTAMP(a)
|
||||||
|
2010-10-31 02:25:26 1288477526
|
||||||
|
2010-10-31 02:25:25 1288481125
|
||||||
|
SELECT COALESCE(a) AS a, UNIX_TIMESTAMP(a) FROM t1 ORDER BY a;
|
||||||
|
a UNIX_TIMESTAMP(a)
|
||||||
|
2010-10-31 02:25:26 1288477526
|
||||||
|
2010-10-31 02:25:25 1288481125
|
||||||
|
DROP TABLE t1;
|
||||||
|
SET time_zone='+00:00';
|
||||||
|
CREATE TABLE t1 (a TIMESTAMP);
|
||||||
|
INSERT INTO t1 VALUES (FROM_UNIXTIME(1288477526) /*summer time in Mowcow*/);
|
||||||
|
INSERT INTO t1 VALUES (FROM_UNIXTIME(1288481126) /*winter time in Moscow*/);
|
||||||
|
SET time_zone='Europe/Moscow';
|
||||||
|
SELECT a, UNIX_TIMESTAMP(a) FROM t1 GROUP BY a;
|
||||||
|
a UNIX_TIMESTAMP(a)
|
||||||
|
2010-10-31 02:25:26 1288477526
|
||||||
|
2010-10-31 02:25:26 1288481126
|
||||||
|
DROP TABLE t1;
|
||||||
|
SET time_zone='+00:00';
|
||||||
|
CREATE TABLE t1 (a TIMESTAMP, b TIMESTAMP);
|
||||||
|
INSERT INTO t1 VALUES (FROM_UNIXTIME(1288477526),FROM_UNIXTIME(1288481126));
|
||||||
|
SELECT UNIX_TIMESTAMP(a),UNIX_TIMESTAMP(b),CASE a WHEN b THEN 'eq' ELSE 'ne' END AS x FROM t1;
|
||||||
|
UNIX_TIMESTAMP(a) UNIX_TIMESTAMP(b) x
|
||||||
|
1288477526 1288481126 ne
|
||||||
|
SET time_zone='Europe/Moscow';
|
||||||
|
SELECT UNIX_TIMESTAMP(a),UNIX_TIMESTAMP(b),CASE a WHEN b THEN 'eq' ELSE 'ne' END AS x FROM t1;
|
||||||
|
UNIX_TIMESTAMP(a) UNIX_TIMESTAMP(b) x
|
||||||
|
1288477526 1288481126 ne
|
||||||
|
DROP TABLE t1;
|
||||||
|
SET time_zone='+00:00';
|
||||||
|
CREATE TABLE t1 (a TIMESTAMP, b TIMESTAMP,c TIMESTAMP);
|
||||||
|
INSERT INTO t1 VALUES (FROM_UNIXTIME(1288477526),FROM_UNIXTIME(1288481126),FROM_UNIXTIME(1288481127));
|
||||||
|
SELECT UNIX_TIMESTAMP(a),UNIX_TIMESTAMP(b),a IN (b,c) AS x FROM t1;
|
||||||
|
UNIX_TIMESTAMP(a) UNIX_TIMESTAMP(b) x
|
||||||
|
1288477526 1288481126 0
|
||||||
|
SET time_zone='Europe/Moscow';
|
||||||
|
SELECT UNIX_TIMESTAMP(a),UNIX_TIMESTAMP(b),a IN (b,c) AS x FROM t1;
|
||||||
|
UNIX_TIMESTAMP(a) UNIX_TIMESTAMP(b) x
|
||||||
|
1288477526 1288481126 0
|
||||||
|
DROP TABLE t1;
|
||||||
|
SET time_zone='+00:00';
|
||||||
|
CREATE TABLE t1 (a TIMESTAMP, b TIMESTAMP);
|
||||||
|
INSERT INTO t1 VALUES (FROM_UNIXTIME(1288477526),FROM_UNIXTIME(1288481126));
|
||||||
|
SELECT * FROM t1 WHERE a = (SELECT MAX(b) FROM t1);
|
||||||
|
a b
|
||||||
|
SELECT * FROM t1 WHERE a = (SELECT MIN(b) FROM t1);
|
||||||
|
a b
|
||||||
|
SELECT * FROM t1 WHERE a IN ((SELECT MAX(b) FROM t1), (SELECT MIN(b) FROM t1));
|
||||||
|
a b
|
||||||
|
SET time_zone='Europe/Moscow';
|
||||||
|
SELECT * FROM t1 WHERE a = (SELECT MAX(b) FROM t1);
|
||||||
|
a b
|
||||||
|
SELECT * FROM t1 WHERE a = (SELECT MIN(b) FROM t1);
|
||||||
|
a b
|
||||||
|
SELECT * FROM t1 WHERE a IN ((SELECT MAX(b) FROM t1), (SELECT MIN(b) FROM t1));
|
||||||
|
a b
|
||||||
|
DROP TABLE t1;
|
||||||
|
SET time_zone='+00:00';
|
||||||
|
CREATE TABLE t1 (a TIMESTAMP, b TIMESTAMP);
|
||||||
|
INSERT INTO t1 VALUES (FROM_UNIXTIME(1100000000),FROM_UNIXTIME(1200000000));
|
||||||
|
INSERT INTO t1 VALUES (FROM_UNIXTIME(1100000001),FROM_UNIXTIME(1200000001));
|
||||||
|
INSERT INTO t1 VALUES (FROM_UNIXTIME(1288477526),FROM_UNIXTIME(1288481126));
|
||||||
|
INSERT INTO t1 VALUES (FROM_UNIXTIME(1300000000),FROM_UNIXTIME(1400000000));
|
||||||
|
INSERT INTO t1 VALUES (FROM_UNIXTIME(1300000001),FROM_UNIXTIME(1400000001));
|
||||||
|
SELECT * FROM t1 WHERE a = (SELECT MAX(b) FROM t1);
|
||||||
|
a b
|
||||||
|
SELECT * FROM t1 WHERE a = (SELECT MIN(b) FROM t1);
|
||||||
|
a b
|
||||||
|
SELECT * FROM t1 WHERE a IN ((SELECT MAX(b) FROM t1), (SELECT MIN(b) FROM t1));
|
||||||
|
a b
|
||||||
|
SET time_zone='Europe/Moscow';
|
||||||
|
SELECT * FROM t1 WHERE a = (SELECT MAX(b) FROM t1);
|
||||||
|
a b
|
||||||
|
SELECT * FROM t1 WHERE a = (SELECT MIN(b) FROM t1);
|
||||||
|
a b
|
||||||
|
SELECT * FROM t1 WHERE a IN ((SELECT MAX(b) FROM t1), (SELECT MIN(b) FROM t1));
|
||||||
|
a b
|
||||||
|
DROP TABLE t1;
|
||||||
|
#
|
||||||
# End of 10.4 tests
|
# End of 10.4 tests
|
||||||
#
|
#
|
||||||
|
|
|
||||||
|
|
@ -324,6 +324,173 @@ SELECT CONVERT_TZ(TIME('2010-01-01 00:00:00'),'+00:00','+7:5');
|
||||||
SET old_mode=DEFAULT;
|
SET old_mode=DEFAULT;
|
||||||
SET timestamp=DEFAULT;
|
SET timestamp=DEFAULT;
|
||||||
|
|
||||||
|
--echo #
|
||||||
|
--echo # MDEV-13995 MAX(timestamp) returns a wrong result near DST change
|
||||||
|
--echo #
|
||||||
|
|
||||||
|
# MAX()
|
||||||
|
SET time_zone='+00:00';
|
||||||
|
CREATE TABLE t1 (a TIMESTAMP);
|
||||||
|
INSERT INTO t1 VALUES (FROM_UNIXTIME(1288477526) /*summer time in Moscow*/);
|
||||||
|
INSERT INTO t1 VALUES (FROM_UNIXTIME(1288477526+3599) /*winter time in Moscow*/);
|
||||||
|
SET time_zone='Europe/Moscow';
|
||||||
|
SELECT a, UNIX_TIMESTAMP(a) FROM t1;
|
||||||
|
SELECT UNIX_TIMESTAMP(MAX(a)) AS a FROM t1;
|
||||||
|
CREATE TABLE t2 (a TIMESTAMP);
|
||||||
|
INSERT INTO t2 SELECT MAX(a) AS a FROM t1;
|
||||||
|
SELECT a, UNIX_TIMESTAMP(a) FROM t2;
|
||||||
|
DROP TABLE t2;
|
||||||
|
DROP TABLE t1;
|
||||||
|
|
||||||
|
|
||||||
|
# Comparison
|
||||||
|
SET time_zone='+00:00';
|
||||||
|
CREATE TABLE t1 (a TIMESTAMP);
|
||||||
|
CREATE TABLE t2 (a TIMESTAMP);
|
||||||
|
INSERT INTO t1 VALUES (FROM_UNIXTIME(1288477526) /*summer time in Moscow*/);
|
||||||
|
INSERT INTO t2 VALUES (FROM_UNIXTIME(1288477526+3599) /*winter time in Moscow*/);
|
||||||
|
SET time_zone='Europe/Moscow';
|
||||||
|
SELECT UNIX_TIMESTAMP(t1.a), UNIX_TIMESTAMP(t2.a) FROM t1,t2;
|
||||||
|
SELECT * FROM t1,t2 WHERE t1.a < t2.a;
|
||||||
|
DROP TABLE t1,t2;
|
||||||
|
|
||||||
|
|
||||||
|
# SP variable comparison
|
||||||
|
DELIMITER $$;
|
||||||
|
BEGIN NOT ATOMIC
|
||||||
|
DECLARE a,b TIMESTAMP;
|
||||||
|
SET time_zone='+00:00';
|
||||||
|
SET a=FROM_UNIXTIME(1288477526);
|
||||||
|
SET b=FROM_UNIXTIME(1288481125);
|
||||||
|
SELECT a < b;
|
||||||
|
SET time_zone='Europe/Moscow';
|
||||||
|
SELECT a < b;
|
||||||
|
END;
|
||||||
|
$$
|
||||||
|
DELIMITER ;$$
|
||||||
|
|
||||||
|
|
||||||
|
# SP function comparison
|
||||||
|
DELIMITER $$;
|
||||||
|
CREATE OR REPLACE FUNCTION f1(uts INT) RETURNS TIMESTAMP
|
||||||
|
BEGIN
|
||||||
|
DECLARE ts TIMESTAMP;
|
||||||
|
DECLARE tz VARCHAR(64) DEFAULT @@time_zone;
|
||||||
|
SET time_zone='+00:00';
|
||||||
|
SET ts=FROM_UNIXTIME(uts);
|
||||||
|
SET time_zone=tz;
|
||||||
|
RETURN ts;
|
||||||
|
END;
|
||||||
|
$$
|
||||||
|
DELIMITER ;$$
|
||||||
|
SET time_zone='+00:00';
|
||||||
|
SELECT f1(1288477526) < f1(1288481125);
|
||||||
|
SET time_zone='Europe/Moscow';
|
||||||
|
SELECT f1(1288477526) < f1(1288481125);
|
||||||
|
DROP FUNCTION f1;
|
||||||
|
|
||||||
|
|
||||||
|
# LEAST()
|
||||||
|
CREATE TABLE t1 (a TIMESTAMP,b TIMESTAMP);
|
||||||
|
SET time_zone='+00:00';
|
||||||
|
INSERT INTO t1 VALUES (FROM_UNIXTIME(1288477526) /*summer time in Mowcow*/,
|
||||||
|
FROM_UNIXTIME(1288481125) /*winter time in Moscow*/);
|
||||||
|
SELECT *, LEAST(a,b) FROM t1;
|
||||||
|
SET time_zone='Europe/Moscow';
|
||||||
|
SELECT *, LEAST(a,b) FROM t1;
|
||||||
|
SELECT UNIX_TIMESTAMP(a), UNIX_TIMESTAMP(b), UNIX_TIMESTAMP(LEAST(a,b)) FROM t1;
|
||||||
|
DROP TABLE t1;
|
||||||
|
|
||||||
|
|
||||||
|
# BETWEEN
|
||||||
|
CREATE TABLE t1 (a TIMESTAMP,b TIMESTAMP,c TIMESTAMP);
|
||||||
|
SET time_zone='+00:00';
|
||||||
|
INSERT INTO t1 VALUES (
|
||||||
|
FROM_UNIXTIME(1288477526) /*summer time in Moscow*/,
|
||||||
|
FROM_UNIXTIME(1288481125) /*winter time in Moscow*/,
|
||||||
|
FROM_UNIXTIME(1288481126) /*winter time in Moscow*/);
|
||||||
|
SELECT b BETWEEN a AND c FROM t1;
|
||||||
|
SET time_zone='Europe/Moscow';
|
||||||
|
SELECT b BETWEEN a AND c FROM t1;
|
||||||
|
DROP TABLE t1;
|
||||||
|
|
||||||
|
|
||||||
|
# ORDER BY
|
||||||
|
SET time_zone='+00:00';
|
||||||
|
CREATE TABLE t1 (a TIMESTAMP);
|
||||||
|
INSERT INTO t1 VALUES (FROM_UNIXTIME(1288477526) /*summer time in Mowcow*/);
|
||||||
|
INSERT INTO t1 VALUES (FROM_UNIXTIME(1288481125) /*winter time in Moscow*/);
|
||||||
|
SELECT a, UNIX_TIMESTAMP(a) FROM t1 ORDER BY a;
|
||||||
|
SELECT COALESCE(a) AS a, UNIX_TIMESTAMP(a) FROM t1 ORDER BY a;
|
||||||
|
SET time_zone='Europe/Moscow';
|
||||||
|
SELECT a, UNIX_TIMESTAMP(a) FROM t1 ORDER BY a;
|
||||||
|
SELECT COALESCE(a) AS a, UNIX_TIMESTAMP(a) FROM t1 ORDER BY a;
|
||||||
|
DROP TABLE t1;
|
||||||
|
|
||||||
|
|
||||||
|
# GROUP BY
|
||||||
|
SET time_zone='+00:00';
|
||||||
|
CREATE TABLE t1 (a TIMESTAMP);
|
||||||
|
INSERT INTO t1 VALUES (FROM_UNIXTIME(1288477526) /*summer time in Mowcow*/);
|
||||||
|
INSERT INTO t1 VALUES (FROM_UNIXTIME(1288481126) /*winter time in Moscow*/);
|
||||||
|
SET time_zone='Europe/Moscow';
|
||||||
|
SELECT a, UNIX_TIMESTAMP(a) FROM t1 GROUP BY a;
|
||||||
|
DROP TABLE t1;
|
||||||
|
|
||||||
|
|
||||||
|
# CASE
|
||||||
|
SET time_zone='+00:00';
|
||||||
|
CREATE TABLE t1 (a TIMESTAMP, b TIMESTAMP);
|
||||||
|
INSERT INTO t1 VALUES (FROM_UNIXTIME(1288477526),FROM_UNIXTIME(1288481126));
|
||||||
|
SELECT UNIX_TIMESTAMP(a),UNIX_TIMESTAMP(b),CASE a WHEN b THEN 'eq' ELSE 'ne' END AS x FROM t1;
|
||||||
|
SET time_zone='Europe/Moscow';
|
||||||
|
SELECT UNIX_TIMESTAMP(a),UNIX_TIMESTAMP(b),CASE a WHEN b THEN 'eq' ELSE 'ne' END AS x FROM t1;
|
||||||
|
DROP TABLE t1;
|
||||||
|
|
||||||
|
|
||||||
|
# IN
|
||||||
|
SET time_zone='+00:00';
|
||||||
|
CREATE TABLE t1 (a TIMESTAMP, b TIMESTAMP,c TIMESTAMP);
|
||||||
|
INSERT INTO t1 VALUES (FROM_UNIXTIME(1288477526),FROM_UNIXTIME(1288481126),FROM_UNIXTIME(1288481127));
|
||||||
|
SELECT UNIX_TIMESTAMP(a),UNIX_TIMESTAMP(b),a IN (b,c) AS x FROM t1;
|
||||||
|
SET time_zone='Europe/Moscow';
|
||||||
|
SELECT UNIX_TIMESTAMP(a),UNIX_TIMESTAMP(b),a IN (b,c) AS x FROM t1;
|
||||||
|
DROP TABLE t1;
|
||||||
|
|
||||||
|
# Comparison and IN in combination with a subquery (with one row)
|
||||||
|
|
||||||
|
SET time_zone='+00:00';
|
||||||
|
CREATE TABLE t1 (a TIMESTAMP, b TIMESTAMP);
|
||||||
|
INSERT INTO t1 VALUES (FROM_UNIXTIME(1288477526),FROM_UNIXTIME(1288481126));
|
||||||
|
SELECT * FROM t1 WHERE a = (SELECT MAX(b) FROM t1);
|
||||||
|
SELECT * FROM t1 WHERE a = (SELECT MIN(b) FROM t1);
|
||||||
|
SELECT * FROM t1 WHERE a IN ((SELECT MAX(b) FROM t1), (SELECT MIN(b) FROM t1));
|
||||||
|
|
||||||
|
SET time_zone='Europe/Moscow';
|
||||||
|
SELECT * FROM t1 WHERE a = (SELECT MAX(b) FROM t1);
|
||||||
|
SELECT * FROM t1 WHERE a = (SELECT MIN(b) FROM t1);
|
||||||
|
SELECT * FROM t1 WHERE a IN ((SELECT MAX(b) FROM t1), (SELECT MIN(b) FROM t1));
|
||||||
|
DROP TABLE t1;
|
||||||
|
|
||||||
|
# Comparison and IN in combinarion with a subquery (with multiple rows)
|
||||||
|
SET time_zone='+00:00';
|
||||||
|
CREATE TABLE t1 (a TIMESTAMP, b TIMESTAMP);
|
||||||
|
INSERT INTO t1 VALUES (FROM_UNIXTIME(1100000000),FROM_UNIXTIME(1200000000));
|
||||||
|
INSERT INTO t1 VALUES (FROM_UNIXTIME(1100000001),FROM_UNIXTIME(1200000001));
|
||||||
|
INSERT INTO t1 VALUES (FROM_UNIXTIME(1288477526),FROM_UNIXTIME(1288481126));
|
||||||
|
INSERT INTO t1 VALUES (FROM_UNIXTIME(1300000000),FROM_UNIXTIME(1400000000));
|
||||||
|
INSERT INTO t1 VALUES (FROM_UNIXTIME(1300000001),FROM_UNIXTIME(1400000001));
|
||||||
|
SELECT * FROM t1 WHERE a = (SELECT MAX(b) FROM t1);
|
||||||
|
SELECT * FROM t1 WHERE a = (SELECT MIN(b) FROM t1);
|
||||||
|
SELECT * FROM t1 WHERE a IN ((SELECT MAX(b) FROM t1), (SELECT MIN(b) FROM t1));
|
||||||
|
|
||||||
|
SET time_zone='Europe/Moscow';
|
||||||
|
SELECT * FROM t1 WHERE a = (SELECT MAX(b) FROM t1);
|
||||||
|
SELECT * FROM t1 WHERE a = (SELECT MIN(b) FROM t1);
|
||||||
|
SELECT * FROM t1 WHERE a IN ((SELECT MAX(b) FROM t1), (SELECT MIN(b) FROM t1));
|
||||||
|
DROP TABLE t1;
|
||||||
|
|
||||||
|
|
||||||
--echo #
|
--echo #
|
||||||
--echo # End of 10.4 tests
|
--echo # End of 10.4 tests
|
||||||
--echo #
|
--echo #
|
||||||
|
|
|
||||||
|
|
@ -1068,5 +1068,55 @@ DROP PROCEDURE p1;
|
||||||
SET timestamp=DEFAULT;
|
SET timestamp=DEFAULT;
|
||||||
SET time_zone=DEFAULT;
|
SET time_zone=DEFAULT;
|
||||||
#
|
#
|
||||||
|
# MDEV-13995 MAX(timestamp) returns a wrong result near DST change
|
||||||
|
#
|
||||||
|
# Testing Item_func_rollup_const::val_native()
|
||||||
|
# There is a bug in the below output (MDEV-16612)
|
||||||
|
# Please remove this comment when MDEV-16612 is fixed and results are re-recorded
|
||||||
|
CREATE TABLE t1 (id INT);
|
||||||
|
INSERT INTO t1 VALUES (1),(2);
|
||||||
|
BEGIN NOT ATOMIC
|
||||||
|
DECLARE v TIMESTAMP DEFAULT '2001-01-01 10:20:30'; -- "v" will be wrapped into Item_func_rollup_const
|
||||||
|
SELECT id, v AS v, COUNT(*) FROM t1 GROUP BY id,v WITH ROLLUP;
|
||||||
|
END;
|
||||||
|
$$
|
||||||
|
id v COUNT(*)
|
||||||
|
1 2001-01-01 10:20:30 1
|
||||||
|
1 2001-01-01 10:20:30 1
|
||||||
|
2 2001-01-01 10:20:30 1
|
||||||
|
2 2001-01-01 10:20:30 1
|
||||||
|
NULL 2001-01-01 10:20:30 2
|
||||||
|
DROP TABLE t1;
|
||||||
|
#
|
||||||
|
# Testing Type_handler_timestamp_common::Item_save_in_field()
|
||||||
|
# "txt" is expected to have three fractional digits
|
||||||
|
SET time_zone='+00:00';
|
||||||
|
SET timestamp=UNIX_TIMESTAMP('2001-01-01 10:20:30.123456');
|
||||||
|
CREATE TABLE t1 (ts1 TIMESTAMP(1) NOT NULL, ts2 TIMESTAMP(3) NOT NULL, txt TEXT);
|
||||||
|
INSERT INTO t1 VALUES ('0000-00-00 00:00:00', '0000-00-00 00:00:00',COALESCE(ts1,ts2));
|
||||||
|
INSERT INTO t1 VALUES (NOW(),NOW(),COALESCE(ts1,ts2));
|
||||||
|
INSERT INTO t1 VALUES (NOW(1),NOW(3),COALESCE(ts1,ts2));
|
||||||
|
SELECT * FROM t1;
|
||||||
|
ts1 ts2 txt
|
||||||
|
0000-00-00 00:00:00.0 0000-00-00 00:00:00.000 0000-00-00 00:00:00.000
|
||||||
|
2001-01-01 10:20:30.0 2001-01-01 10:20:30.000 2001-01-01 10:20:30.000
|
||||||
|
2001-01-01 10:20:30.1 2001-01-01 10:20:30.123 2001-01-01 10:20:30.100
|
||||||
|
DROP TABLE t1;
|
||||||
|
SET timestamp=DEFAULT;
|
||||||
|
SET time_zone=DEFAULT;
|
||||||
|
#
|
||||||
|
# Testing Field_timestamp::store_native
|
||||||
|
#
|
||||||
|
SET sql_mode='';
|
||||||
|
CREATE TABLE t1 (a TIMESTAMP, b TIMESTAMP);
|
||||||
|
INSERT INTO t1 VALUES ('0000-00-00 00:00:00','0000-00-00 00:00:00');
|
||||||
|
SET sql_mode='STRICT_ALL_TABLES,NO_ZERO_DATE';
|
||||||
|
UPDATE t1 SET a=b;
|
||||||
|
ERROR 22007: Incorrect datetime value: '0000-00-00 00:00:00' for column 'a' at row 1
|
||||||
|
UPDATE t1 SET a=COALESCE(b);
|
||||||
|
ERROR 22007: Incorrect datetime value: '0000-00-00 00:00:00' for column 'a' at row 1
|
||||||
|
DROP TABLE t1;
|
||||||
|
SET sql_mode=DEFAULT;
|
||||||
|
#
|
||||||
# End of 10.4 tests
|
# End of 10.4 tests
|
||||||
#
|
#
|
||||||
|
|
|
||||||
|
|
@ -660,6 +660,56 @@ DROP PROCEDURE p1;
|
||||||
SET timestamp=DEFAULT;
|
SET timestamp=DEFAULT;
|
||||||
SET time_zone=DEFAULT;
|
SET time_zone=DEFAULT;
|
||||||
|
|
||||||
|
--echo #
|
||||||
|
--echo # MDEV-13995 MAX(timestamp) returns a wrong result near DST change
|
||||||
|
--echo #
|
||||||
|
|
||||||
|
--echo # Testing Item_func_rollup_const::val_native()
|
||||||
|
|
||||||
|
--echo # There is a bug in the below output (MDEV-16612)
|
||||||
|
--echo # Please remove this comment when MDEV-16612 is fixed and results are re-recorded
|
||||||
|
|
||||||
|
CREATE TABLE t1 (id INT);
|
||||||
|
INSERT INTO t1 VALUES (1),(2);
|
||||||
|
DELIMITER $$;
|
||||||
|
BEGIN NOT ATOMIC
|
||||||
|
DECLARE v TIMESTAMP DEFAULT '2001-01-01 10:20:30'; -- "v" will be wrapped into Item_func_rollup_const
|
||||||
|
SELECT id, v AS v, COUNT(*) FROM t1 GROUP BY id,v WITH ROLLUP;
|
||||||
|
END;
|
||||||
|
$$
|
||||||
|
DELIMITER ;$$
|
||||||
|
DROP TABLE t1;
|
||||||
|
|
||||||
|
--echo #
|
||||||
|
--echo # Testing Type_handler_timestamp_common::Item_save_in_field()
|
||||||
|
--echo # "txt" is expected to have three fractional digits
|
||||||
|
SET time_zone='+00:00';
|
||||||
|
SET timestamp=UNIX_TIMESTAMP('2001-01-01 10:20:30.123456');
|
||||||
|
CREATE TABLE t1 (ts1 TIMESTAMP(1) NOT NULL, ts2 TIMESTAMP(3) NOT NULL, txt TEXT);
|
||||||
|
INSERT INTO t1 VALUES ('0000-00-00 00:00:00', '0000-00-00 00:00:00',COALESCE(ts1,ts2));
|
||||||
|
INSERT INTO t1 VALUES (NOW(),NOW(),COALESCE(ts1,ts2));
|
||||||
|
INSERT INTO t1 VALUES (NOW(1),NOW(3),COALESCE(ts1,ts2));
|
||||||
|
SELECT * FROM t1;
|
||||||
|
DROP TABLE t1;
|
||||||
|
SET timestamp=DEFAULT;
|
||||||
|
SET time_zone=DEFAULT;
|
||||||
|
|
||||||
|
--echo #
|
||||||
|
--echo # Testing Field_timestamp::store_native
|
||||||
|
--echo #
|
||||||
|
|
||||||
|
SET sql_mode='';
|
||||||
|
CREATE TABLE t1 (a TIMESTAMP, b TIMESTAMP);
|
||||||
|
INSERT INTO t1 VALUES ('0000-00-00 00:00:00','0000-00-00 00:00:00');
|
||||||
|
SET sql_mode='STRICT_ALL_TABLES,NO_ZERO_DATE';
|
||||||
|
--error ER_TRUNCATED_WRONG_VALUE
|
||||||
|
UPDATE t1 SET a=b;
|
||||||
|
--error ER_TRUNCATED_WRONG_VALUE
|
||||||
|
UPDATE t1 SET a=COALESCE(b);
|
||||||
|
DROP TABLE t1;
|
||||||
|
SET sql_mode=DEFAULT;
|
||||||
|
|
||||||
|
|
||||||
--echo #
|
--echo #
|
||||||
--echo # End of 10.4 tests
|
--echo # End of 10.4 tests
|
||||||
--echo #
|
--echo #
|
||||||
|
|
|
||||||
|
|
@ -162,3 +162,30 @@ SELECT * FROM t1,t2 WHERE COALESCE(t1.a)=t2.a;
|
||||||
a a
|
a a
|
||||||
20010101235959.9999999 2001-01-02 00:00:00
|
20010101235959.9999999 2001-01-02 00:00:00
|
||||||
DROP TABLE t1,t2;
|
DROP TABLE t1,t2;
|
||||||
|
#
|
||||||
|
# MDEV-13995 MAX(timestamp) returns a wrong result near DST change
|
||||||
|
#
|
||||||
|
# Test Field_timestamp::store_native()
|
||||||
|
#
|
||||||
|
SET sql_mode=@default_sql_mode;
|
||||||
|
SET time_zone='+00:00';
|
||||||
|
CREATE TABLE t1 (ts0 TIMESTAMP, ts1 TIMESTAMP(1));
|
||||||
|
INSERT INTO t1 VALUES ('2001-01-01 10:20:30', '2001-01-01 10:20:30.9');
|
||||||
|
SELECT * FROM t1;
|
||||||
|
ts0 ts1
|
||||||
|
2001-01-01 10:20:30 2001-01-01 10:20:30.9
|
||||||
|
# This should round
|
||||||
|
UPDATE t1 SET ts0=COALESCE(ts1);
|
||||||
|
SELECT * FROM t1;
|
||||||
|
ts0 ts1
|
||||||
|
2001-01-01 10:20:31 2001-01-01 10:20:30.9
|
||||||
|
# Corner case
|
||||||
|
UPDATE t1 SET ts1=FROM_UNIXTIME(2147483647.9);
|
||||||
|
UPDATE t1 SET ts0=COALESCE(ts1);
|
||||||
|
Warnings:
|
||||||
|
Warning 1264 Out of range value for column 'ts0' at row 1
|
||||||
|
SELECT * FROM t1;
|
||||||
|
ts0 ts1
|
||||||
|
2038-01-19 03:14:07 2038-01-19 03:14:07.9
|
||||||
|
DROP TABLE t1;
|
||||||
|
SET time_zone=DEFAULT;
|
||||||
|
|
|
||||||
|
|
@ -136,3 +136,25 @@ INSERT INTO t2 VALUES ('2001-01-02 00:00:00');
|
||||||
SELECT * FROM t1,t2 WHERE t1.a=t2.a;
|
SELECT * FROM t1,t2 WHERE t1.a=t2.a;
|
||||||
SELECT * FROM t1,t2 WHERE COALESCE(t1.a)=t2.a;
|
SELECT * FROM t1,t2 WHERE COALESCE(t1.a)=t2.a;
|
||||||
DROP TABLE t1,t2;
|
DROP TABLE t1,t2;
|
||||||
|
|
||||||
|
|
||||||
|
--echo #
|
||||||
|
--echo # MDEV-13995 MAX(timestamp) returns a wrong result near DST change
|
||||||
|
--echo #
|
||||||
|
--echo # Test Field_timestamp::store_native()
|
||||||
|
--echo #
|
||||||
|
|
||||||
|
SET sql_mode=@default_sql_mode;
|
||||||
|
SET time_zone='+00:00';
|
||||||
|
CREATE TABLE t1 (ts0 TIMESTAMP, ts1 TIMESTAMP(1));
|
||||||
|
INSERT INTO t1 VALUES ('2001-01-01 10:20:30', '2001-01-01 10:20:30.9');
|
||||||
|
SELECT * FROM t1;
|
||||||
|
--echo # This should round
|
||||||
|
UPDATE t1 SET ts0=COALESCE(ts1);
|
||||||
|
SELECT * FROM t1;
|
||||||
|
--echo # Corner case
|
||||||
|
UPDATE t1 SET ts1=FROM_UNIXTIME(2147483647.9);
|
||||||
|
UPDATE t1 SET ts0=COALESCE(ts1);
|
||||||
|
SELECT * FROM t1;
|
||||||
|
DROP TABLE t1;
|
||||||
|
SET time_zone=DEFAULT;
|
||||||
|
|
|
||||||
|
|
@ -19,6 +19,15 @@
|
||||||
|
|
||||||
|
|
||||||
/** MySQL56 routines and macros **/
|
/** MySQL56 routines and macros **/
|
||||||
|
|
||||||
|
/*
|
||||||
|
Buffer size for a native TIMESTAMP representation, for use with NativBuffer.
|
||||||
|
4 bytes for seconds
|
||||||
|
3 bytes for microseconds
|
||||||
|
1 byte for the trailing '\0' (class Native reserves extra 1 byte for '\0')
|
||||||
|
*/
|
||||||
|
#define STRING_BUFFER_TIMESTAMP_BINARY_SIZE 8 /* 4 + 3 + 1 */
|
||||||
|
|
||||||
#define MY_PACKED_TIME_GET_INT_PART(x) ((x) >> 24)
|
#define MY_PACKED_TIME_GET_INT_PART(x) ((x) >> 24)
|
||||||
#define MY_PACKED_TIME_GET_FRAC_PART(x) ((x) % (1LL << 24))
|
#define MY_PACKED_TIME_GET_FRAC_PART(x) ((x) % (1LL << 24))
|
||||||
#define MY_PACKED_TIME_MAKE(i, f) ((((longlong) (i)) << 24) + (f))
|
#define MY_PACKED_TIME_MAKE(i, f) ((((longlong) (i)) << 24) + (f))
|
||||||
|
|
|
||||||
59
sql/field.cc
59
sql/field.cc
|
|
@ -5023,6 +5023,15 @@ my_time_t Field_timestamp::get_timestamp(const uchar *pos,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool Field_timestamp::val_native(Native *to)
|
||||||
|
{
|
||||||
|
ASSERT_COLUMN_MARKED_FOR_READ;
|
||||||
|
my_time_t sec= (my_time_t) sint4korr(ptr);
|
||||||
|
return Timestamp_or_zero_datetime(Timestamp(sec, 0), sec == 0).
|
||||||
|
to_native(to, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
int Field_timestamp::store_TIME_with_warning(THD *thd, const Datetime *dt,
|
int Field_timestamp::store_TIME_with_warning(THD *thd, const Datetime *dt,
|
||||||
const ErrConv *str, int was_cut)
|
const ErrConv *str, int was_cut)
|
||||||
{
|
{
|
||||||
|
|
@ -5143,6 +5152,14 @@ int Field_timestamp::store_timestamp_dec(const timeval &ts, uint dec)
|
||||||
}
|
}
|
||||||
if (ts.tv_sec == 0 && ts.tv_usec == 0 &&
|
if (ts.tv_sec == 0 && ts.tv_usec == 0 &&
|
||||||
get_thd()->variables.sql_mode & (ulonglong) TIME_NO_ZERO_DATE)
|
get_thd()->variables.sql_mode & (ulonglong) TIME_NO_ZERO_DATE)
|
||||||
|
return zero_time_stored_return_code_with_warning();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int Field_timestamp::zero_time_stored_return_code_with_warning()
|
||||||
|
{
|
||||||
|
if (get_thd()->variables.sql_mode & (ulonglong) TIME_NO_ZERO_DATE)
|
||||||
{
|
{
|
||||||
ErrConvString s(
|
ErrConvString s(
|
||||||
STRING_WITH_LEN("0000-00-00 00:00:00.000000") - (decimals() ? 6 - decimals() : 7),
|
STRING_WITH_LEN("0000-00-00 00:00:00.000000") - (decimals() ? 6 - decimals() : 7),
|
||||||
|
|
@ -5151,6 +5168,23 @@ int Field_timestamp::store_timestamp_dec(const timeval &ts, uint dec)
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int Field_timestamp::store_native(const Native &value)
|
||||||
|
{
|
||||||
|
if (!value.length()) // Zero datetime
|
||||||
|
{
|
||||||
|
reset();
|
||||||
|
return zero_time_stored_return_code_with_warning();
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
The exact second precision is not important here.
|
||||||
|
Field_timestamp*::store_timestamp_dec() do not use the "dec" parameter.
|
||||||
|
Passing TIME_SECOND_PART_DIGITS is OK.
|
||||||
|
*/
|
||||||
|
return store_timestamp_dec(Timestamp(value).tv(), TIME_SECOND_PART_DIGITS);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -5410,6 +5444,18 @@ my_time_t Field_timestamp_hires::get_timestamp(const uchar *pos,
|
||||||
return mi_uint4korr(pos);
|
return mi_uint4korr(pos);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool Field_timestamp_hires::val_native(Native *to)
|
||||||
|
{
|
||||||
|
ASSERT_COLUMN_MARKED_FOR_READ;
|
||||||
|
struct timeval tm;
|
||||||
|
tm.tv_sec= mi_uint4korr(ptr);
|
||||||
|
tm.tv_usec= (ulong) sec_part_unshift(read_bigendian(ptr+4, sec_part_bytes(dec)), dec);
|
||||||
|
return Timestamp_or_zero_datetime(Timestamp(tm), tm.tv_sec == 0).
|
||||||
|
to_native(to, dec);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
double Field_timestamp_with_dec::val_real(void)
|
double Field_timestamp_with_dec::val_real(void)
|
||||||
{
|
{
|
||||||
MYSQL_TIME ltime;
|
MYSQL_TIME ltime;
|
||||||
|
|
@ -5516,6 +5562,19 @@ my_time_t Field_timestampf::get_timestamp(const uchar *pos,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool Field_timestampf::val_native(Native *to)
|
||||||
|
{
|
||||||
|
ASSERT_COLUMN_MARKED_FOR_READ;
|
||||||
|
// Check if it's '0000-00-00 00:00:00' rather than a real timestamp
|
||||||
|
if (ptr[0] == 0 && ptr[1] == 0 && ptr[2] == 0 && ptr[3] == 0)
|
||||||
|
{
|
||||||
|
to->length(0);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return Field::val_native(to);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************/
|
/*************************************************************/
|
||||||
uint Field_temporal::is_equal(Create_field *new_field)
|
uint Field_temporal::is_equal(Create_field *new_field)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
19
sql/field.h
19
sql/field.h
|
|
@ -790,6 +790,15 @@ public:
|
||||||
return store_timestamp_dec(Timeval(timestamp, sec_part),
|
return store_timestamp_dec(Timeval(timestamp, sec_part),
|
||||||
TIME_SECOND_PART_DIGITS);
|
TIME_SECOND_PART_DIGITS);
|
||||||
}
|
}
|
||||||
|
/**
|
||||||
|
Store a value represented in native format
|
||||||
|
*/
|
||||||
|
virtual int store_native(const Native &value)
|
||||||
|
{
|
||||||
|
DBUG_ASSERT(0);
|
||||||
|
reset();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
int store_time(const MYSQL_TIME *ltime)
|
int store_time(const MYSQL_TIME *ltime)
|
||||||
{ return store_time_dec(ltime, TIME_SECOND_PART_DIGITS); }
|
{ return store_time_dec(ltime, TIME_SECOND_PART_DIGITS); }
|
||||||
int store(const char *to, size_t length, CHARSET_INFO *cs,
|
int store(const char *to, size_t length, CHARSET_INFO *cs,
|
||||||
|
|
@ -836,6 +845,11 @@ public:
|
||||||
This trickery is used to decrease a number of malloc calls.
|
This trickery is used to decrease a number of malloc calls.
|
||||||
*/
|
*/
|
||||||
virtual String *val_str(String*,String *)=0;
|
virtual String *val_str(String*,String *)=0;
|
||||||
|
virtual bool val_native(Native *to)
|
||||||
|
{
|
||||||
|
DBUG_ASSERT(!is_null());
|
||||||
|
return to->copy((const char *) ptr, pack_length());
|
||||||
|
}
|
||||||
String *val_int_as_str(String *val_buffer, bool unsigned_flag);
|
String *val_int_as_str(String *val_buffer, bool unsigned_flag);
|
||||||
/*
|
/*
|
||||||
Return the field value as a LEX_CSTRING, without padding to full length
|
Return the field value as a LEX_CSTRING, without padding to full length
|
||||||
|
|
@ -2735,6 +2749,7 @@ protected:
|
||||||
{
|
{
|
||||||
store_TIMEVAL(ts.tv());
|
store_TIMEVAL(ts.tv());
|
||||||
}
|
}
|
||||||
|
int zero_time_stored_return_code_with_warning();
|
||||||
public:
|
public:
|
||||||
Field_timestamp(uchar *ptr_arg, uint32 len_arg,
|
Field_timestamp(uchar *ptr_arg, uint32 len_arg,
|
||||||
uchar *null_ptr_arg, uchar null_bit_arg,
|
uchar *null_ptr_arg, uchar null_bit_arg,
|
||||||
|
|
@ -2785,6 +2800,8 @@ public:
|
||||||
store_TIMESTAMP(Timestamp(ts, sec_part).round(decimals(), mode, &warn));
|
store_TIMESTAMP(Timestamp(ts, sec_part).round(decimals(), mode, &warn));
|
||||||
}
|
}
|
||||||
bool get_date(MYSQL_TIME *ltime, date_mode_t fuzzydate);
|
bool get_date(MYSQL_TIME *ltime, date_mode_t fuzzydate);
|
||||||
|
int store_native(const Native &value);
|
||||||
|
bool val_native(Native *to);
|
||||||
uchar *pack(uchar *to, const uchar *from,
|
uchar *pack(uchar *to, const uchar *from,
|
||||||
uint max_length __attribute__((unused)))
|
uint max_length __attribute__((unused)))
|
||||||
{
|
{
|
||||||
|
|
@ -2864,6 +2881,7 @@ public:
|
||||||
{
|
{
|
||||||
DBUG_ASSERT(dec);
|
DBUG_ASSERT(dec);
|
||||||
}
|
}
|
||||||
|
bool val_native(Native *to);
|
||||||
my_time_t get_timestamp(const uchar *pos, ulong *sec_part) const;
|
my_time_t get_timestamp(const uchar *pos, ulong *sec_part) const;
|
||||||
int cmp(const uchar *,const uchar *);
|
int cmp(const uchar *,const uchar *);
|
||||||
uint32 pack_length() const { return 4 + sec_part_bytes(dec); }
|
uint32 pack_length() const { return 4 + sec_part_bytes(dec); }
|
||||||
|
|
@ -2914,6 +2932,7 @@ public:
|
||||||
{
|
{
|
||||||
return get_timestamp(ptr, sec_part);
|
return get_timestamp(ptr, sec_part);
|
||||||
}
|
}
|
||||||
|
bool val_native(Native *to);
|
||||||
uint size_of() const { return sizeof(*this); }
|
uint size_of() const { return sizeof(*this); }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1067,6 +1067,28 @@ Type_handler_temporal_result::make_sort_key(uchar *to, Item *item,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
Type_handler_timestamp_common::make_sort_key(uchar *to, Item *item,
|
||||||
|
const SORT_FIELD_ATTR *sort_field,
|
||||||
|
Sort_param *param) const
|
||||||
|
{
|
||||||
|
uint binlen= my_timestamp_binary_length(item->decimals);
|
||||||
|
Timestamp_or_zero_datetime_native_null native(current_thd, item);
|
||||||
|
if (native.is_null() || native.is_zero_datetime())
|
||||||
|
{
|
||||||
|
// NULL or '0000-00-00 00:00:00'
|
||||||
|
bzero(to, item->maybe_null ? binlen + 1 : binlen);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
DBUG_ASSERT(native.length() == binlen);
|
||||||
|
if (item->maybe_null)
|
||||||
|
*to++= 1;
|
||||||
|
memcpy((char *) to, native.ptr(), binlen);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
Type_handler::make_sort_key_longlong(uchar *to,
|
Type_handler::make_sort_key_longlong(uchar *to,
|
||||||
bool maybe_null,
|
bool maybe_null,
|
||||||
|
|
@ -1873,6 +1895,15 @@ Type_handler_temporal_result::sortlength(THD *thd,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
Type_handler_timestamp_common::sortlength(THD *thd,
|
||||||
|
const Type_std_attributes *item,
|
||||||
|
SORT_FIELD_ATTR *sortorder) const
|
||||||
|
{
|
||||||
|
sortorder->length= my_timestamp_binary_length(item->decimals);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
Type_handler_int_result::sortlength(THD *thd,
|
Type_handler_int_result::sortlength(THD *thd,
|
||||||
const Type_std_attributes *item,
|
const Type_std_attributes *item,
|
||||||
|
|
|
||||||
122
sql/item.cc
122
sql/item.cc
|
|
@ -1526,6 +1526,12 @@ String *Item_sp_variable::val_str(String *sp)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool Item_sp_variable::val_native(THD *thd, Native *to)
|
||||||
|
{
|
||||||
|
return val_native_from_item(thd, this_item(), to);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
my_decimal *Item_sp_variable::val_decimal(my_decimal *decimal_value)
|
my_decimal *Item_sp_variable::val_decimal(my_decimal *decimal_value)
|
||||||
{
|
{
|
||||||
DBUG_ASSERT(fixed);
|
DBUG_ASSERT(fixed);
|
||||||
|
|
@ -3178,6 +3184,18 @@ bool Item_field::get_date_result(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzyd
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool Item_field::val_native(THD *thd, Native *to)
|
||||||
|
{
|
||||||
|
return val_native_from_field(field, to);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool Item_field::val_native_result(THD *thd, Native *to)
|
||||||
|
{
|
||||||
|
return val_native_from_field(result_field, to);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void Item_field::save_result(Field *to)
|
void Item_field::save_result(Field *to)
|
||||||
{
|
{
|
||||||
save_field_in_field(result_field, &null_value, to, TRUE);
|
save_field_in_field(result_field, &null_value, to, TRUE);
|
||||||
|
|
@ -4843,6 +4861,12 @@ String* Item_ref_null_helper::val_str(String* s)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool Item_ref_null_helper::val_native(THD *thd, Native *to)
|
||||||
|
{
|
||||||
|
return (owner->was_null|= val_native_from_item(thd, *ref, to));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
bool Item_ref_null_helper::get_date(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate)
|
bool Item_ref_null_helper::get_date(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate)
|
||||||
{
|
{
|
||||||
return (owner->was_null|= null_value= (*ref)->get_date_result(thd, ltime, fuzzydate));
|
return (owner->was_null|= null_value= (*ref)->get_date_result(thd, ltime, fuzzydate));
|
||||||
|
|
@ -8103,6 +8127,14 @@ String *Item_ref::str_result(String* str)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool Item_ref::val_native_result(THD *thd, Native *to)
|
||||||
|
{
|
||||||
|
return result_field ?
|
||||||
|
val_native_from_field(result_field, to) :
|
||||||
|
val_native(thd, to);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
my_decimal *Item_ref::val_decimal_result(my_decimal *decimal_value)
|
my_decimal *Item_ref::val_decimal_result(my_decimal *decimal_value)
|
||||||
{
|
{
|
||||||
if (result_field)
|
if (result_field)
|
||||||
|
|
@ -8197,6 +8229,12 @@ bool Item_ref::get_date(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool Item_ref::val_native(THD *thd, Native *to)
|
||||||
|
{
|
||||||
|
return val_native_from_item(thd, *ref, to);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
my_decimal *Item_ref::val_decimal(my_decimal *decimal_value)
|
my_decimal *Item_ref::val_decimal(my_decimal *decimal_value)
|
||||||
{
|
{
|
||||||
my_decimal *val= (*ref)->val_decimal_result(decimal_value);
|
my_decimal *val= (*ref)->val_decimal_result(decimal_value);
|
||||||
|
|
@ -8334,6 +8372,12 @@ bool Item_direct_ref::get_date(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydat
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool Item_direct_ref::val_native(THD *thd, Native *to)
|
||||||
|
{
|
||||||
|
return val_native_from_item(thd, *ref, to);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
Item_cache_wrapper::~Item_cache_wrapper()
|
Item_cache_wrapper::~Item_cache_wrapper()
|
||||||
{
|
{
|
||||||
DBUG_ASSERT(expr_cache == 0);
|
DBUG_ASSERT(expr_cache == 0);
|
||||||
|
|
@ -8622,6 +8666,28 @@ String *Item_cache_wrapper::val_str(String* str)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
Get the native value of the possibly cached item
|
||||||
|
*/
|
||||||
|
|
||||||
|
bool Item_cache_wrapper::val_native(THD *thd, Native* to)
|
||||||
|
{
|
||||||
|
Item *cached_value;
|
||||||
|
DBUG_ENTER("Item_cache_wrapper::val_native");
|
||||||
|
if (!expr_cache)
|
||||||
|
DBUG_RETURN(val_native_from_item(thd, orig_item, to));
|
||||||
|
|
||||||
|
if ((cached_value= check_cache()))
|
||||||
|
DBUG_RETURN(val_native_from_item(thd, cached_value, to));
|
||||||
|
|
||||||
|
cache();
|
||||||
|
if ((null_value= expr_value->null_value))
|
||||||
|
DBUG_RETURN(true);
|
||||||
|
DBUG_RETURN(expr_value->val_native(thd, to));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Get the decimal value of the possibly cached item
|
Get the decimal value of the possibly cached item
|
||||||
*/
|
*/
|
||||||
|
|
@ -9794,6 +9860,62 @@ Item *Item_cache_time::make_literal(THD *thd)
|
||||||
return new (thd->mem_root) Item_time_literal(thd, <ime, decimals);
|
return new (thd->mem_root) Item_time_literal(thd, <ime, decimals);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int Item_cache_timestamp::save_in_field(Field *field, bool no_conversions)
|
||||||
|
{
|
||||||
|
if (!has_value())
|
||||||
|
return set_field_to_null_with_conversions(field, no_conversions);
|
||||||
|
return m_native.save_in_field(field, decimals);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool Item_cache_timestamp::val_native(THD *thd, Native *to)
|
||||||
|
{
|
||||||
|
if (!has_value())
|
||||||
|
{
|
||||||
|
null_value= true;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return null_value= to->copy(m_native);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Datetime Item_cache_timestamp::to_datetime(THD *thd)
|
||||||
|
{
|
||||||
|
DBUG_ASSERT(is_fixed() == 1);
|
||||||
|
if (!has_value())
|
||||||
|
{
|
||||||
|
null_value= true;
|
||||||
|
return Datetime();
|
||||||
|
}
|
||||||
|
return Datetime(thd, Timestamp_or_zero_datetime(m_native).tv());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool Item_cache_timestamp::get_date(THD *thd, MYSQL_TIME *ltime,
|
||||||
|
date_mode_t fuzzydate)
|
||||||
|
{
|
||||||
|
if (!has_value())
|
||||||
|
{
|
||||||
|
set_zero_time(ltime, MYSQL_TIMESTAMP_DATETIME);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
Timestamp_or_zero_datetime tm(m_native);
|
||||||
|
return (null_value= tm.to_TIME(thd, ltime, fuzzydate));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool Item_cache_timestamp::cache_value()
|
||||||
|
{
|
||||||
|
if (!example)
|
||||||
|
return false;
|
||||||
|
value_cached= true;
|
||||||
|
null_value= example->val_native_with_conversion_result(current_thd, &m_native,
|
||||||
|
type_handler());
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
bool Item_cache_real::cache_value()
|
bool Item_cache_real::cache_value()
|
||||||
{
|
{
|
||||||
if (!example)
|
if (!example)
|
||||||
|
|
|
||||||
182
sql/item.h
182
sql/item.h
|
|
@ -855,6 +855,25 @@ protected:
|
||||||
res= NULL;
|
res= NULL;
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
bool val_native_from_item(THD *thd, Item *item, Native *to)
|
||||||
|
{
|
||||||
|
DBUG_ASSERT(is_fixed());
|
||||||
|
null_value= item->val_native(thd, to);
|
||||||
|
DBUG_ASSERT(null_value == item->null_value);
|
||||||
|
return null_value;
|
||||||
|
}
|
||||||
|
bool val_native_from_field(Field *field, Native *to)
|
||||||
|
{
|
||||||
|
if ((null_value= field->is_null()))
|
||||||
|
return true;
|
||||||
|
return (null_value= field->val_native(to));
|
||||||
|
}
|
||||||
|
bool val_native_with_conversion_from_item(THD *thd, Item *item, Native *to,
|
||||||
|
const Type_handler *handler)
|
||||||
|
{
|
||||||
|
DBUG_ASSERT(is_fixed());
|
||||||
|
return null_value= item->val_native_with_conversion(thd, to, handler);
|
||||||
|
}
|
||||||
my_decimal *val_decimal_from_item(Item *item, my_decimal *decimal_value)
|
my_decimal *val_decimal_from_item(Item *item, my_decimal *decimal_value)
|
||||||
{
|
{
|
||||||
DBUG_ASSERT(is_fixed());
|
DBUG_ASSERT(is_fixed());
|
||||||
|
|
@ -1276,6 +1295,60 @@ public:
|
||||||
*/
|
*/
|
||||||
virtual String *val_str(String *str)=0;
|
virtual String *val_str(String *str)=0;
|
||||||
|
|
||||||
|
|
||||||
|
bool val_native_with_conversion(THD *thd, Native *to, const Type_handler *th)
|
||||||
|
{
|
||||||
|
return th->Item_val_native_with_conversion(thd, this, to);
|
||||||
|
}
|
||||||
|
bool val_native_with_conversion_result(THD *thd, Native *to,
|
||||||
|
const Type_handler *th)
|
||||||
|
{
|
||||||
|
return th->Item_val_native_with_conversion_result(thd, this, to);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual bool val_native(THD *thd, Native *to)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
The default implementation for the Items that do not need native format:
|
||||||
|
- Item_basic_value
|
||||||
|
- Item_ident_for_show
|
||||||
|
- Item_copy
|
||||||
|
- Item_exists_subselect
|
||||||
|
- Item_sum_field
|
||||||
|
- Item_sum_or_func (default implementation)
|
||||||
|
- Item_proc
|
||||||
|
- Item_type_holder (as val_xxx() are never called for it);
|
||||||
|
- TODO: Item_name_const will need val_native() in the future,
|
||||||
|
when we add this syntax:
|
||||||
|
TIMESTAMP WITH LOCAL TIMEZONE'2001-01-01 00:00:00'
|
||||||
|
|
||||||
|
These hybrid Item types override val_native():
|
||||||
|
- Item_field
|
||||||
|
- Item_param
|
||||||
|
- Item_sp_variable
|
||||||
|
- Item_ref
|
||||||
|
- Item_cache_wrapper
|
||||||
|
- Item_direct_ref
|
||||||
|
- Item_direct_view_ref
|
||||||
|
- Item_ref_null_helper
|
||||||
|
- Item_sum_or_func
|
||||||
|
Note, these hybrid type Item_sum_or_func descendants
|
||||||
|
override the default implementation:
|
||||||
|
* Item_sum_hybrid
|
||||||
|
* Item_func_hybrid_field_type
|
||||||
|
* Item_func_min_max
|
||||||
|
* Item_func_sp
|
||||||
|
* Item_func_last_value
|
||||||
|
* Item_func_rollup_const
|
||||||
|
*/
|
||||||
|
DBUG_ASSERT(0);
|
||||||
|
return null_value= true;
|
||||||
|
}
|
||||||
|
virtual bool val_native_result(THD *thd, Native *to)
|
||||||
|
{
|
||||||
|
return val_native(thd, to);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Returns string representation of this item in ASCII format.
|
Returns string representation of this item in ASCII format.
|
||||||
|
|
||||||
|
|
@ -2689,6 +2762,7 @@ public:
|
||||||
String *val_str(String *sp);
|
String *val_str(String *sp);
|
||||||
my_decimal *val_decimal(my_decimal *decimal_value);
|
my_decimal *val_decimal(my_decimal *decimal_value);
|
||||||
bool get_date(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate);
|
bool get_date(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate);
|
||||||
|
bool val_native(THD *thd, Native *to);
|
||||||
bool is_null();
|
bool is_null();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
@ -3229,6 +3303,8 @@ public:
|
||||||
void save_result(Field *to);
|
void save_result(Field *to);
|
||||||
double val_result();
|
double val_result();
|
||||||
longlong val_int_result();
|
longlong val_int_result();
|
||||||
|
bool val_native(THD *thd, Native *to);
|
||||||
|
bool val_native_result(THD *thd, Native *to);
|
||||||
String *str_result(String* tmp);
|
String *str_result(String* tmp);
|
||||||
my_decimal *val_decimal_result(my_decimal *);
|
my_decimal *val_decimal_result(my_decimal *);
|
||||||
bool val_bool_result();
|
bool val_bool_result();
|
||||||
|
|
@ -3815,6 +3891,11 @@ public:
|
||||||
return can_return_value() ? value.val_str(str, this) : NULL;
|
return can_return_value() ? value.val_str(str, this) : NULL;
|
||||||
}
|
}
|
||||||
bool get_date(THD *thd, MYSQL_TIME *tm, date_mode_t fuzzydate);
|
bool get_date(THD *thd, MYSQL_TIME *tm, date_mode_t fuzzydate);
|
||||||
|
bool val_native(THD *thd, Native *to)
|
||||||
|
{
|
||||||
|
return Item_param::type_handler()->Item_param_val_native(thd, this, to);
|
||||||
|
}
|
||||||
|
|
||||||
int save_in_field(Field *field, bool no_conversions);
|
int save_in_field(Field *field, bool no_conversions);
|
||||||
|
|
||||||
void set_default();
|
void set_default();
|
||||||
|
|
@ -4614,6 +4695,54 @@ public:
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class Item_timestamp_literal: public Item_literal
|
||||||
|
{
|
||||||
|
Timestamp_or_zero_datetime m_value;
|
||||||
|
public:
|
||||||
|
Item_timestamp_literal(THD *thd)
|
||||||
|
:Item_literal(thd)
|
||||||
|
{ }
|
||||||
|
const Type_handler *type_handler() const { return &type_handler_timestamp2; }
|
||||||
|
int save_in_field(Field *field, bool no_conversions)
|
||||||
|
{
|
||||||
|
Timestamp_or_zero_datetime_native native(m_value, decimals);
|
||||||
|
return native.save_in_field(field, decimals);
|
||||||
|
}
|
||||||
|
longlong val_int()
|
||||||
|
{
|
||||||
|
return m_value.to_datetime(current_thd).to_longlong();
|
||||||
|
}
|
||||||
|
double val_real()
|
||||||
|
{
|
||||||
|
return m_value.to_datetime(current_thd).to_double();
|
||||||
|
}
|
||||||
|
String *val_str(String *to)
|
||||||
|
{
|
||||||
|
return m_value.to_datetime(current_thd).to_string(to, decimals);
|
||||||
|
}
|
||||||
|
my_decimal *val_decimal(my_decimal *to)
|
||||||
|
{
|
||||||
|
return m_value.to_datetime(current_thd).to_decimal(to);
|
||||||
|
}
|
||||||
|
bool get_date(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate)
|
||||||
|
{
|
||||||
|
bool res= m_value.to_TIME(thd, ltime, fuzzydate);
|
||||||
|
DBUG_ASSERT(!res);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
bool val_native(THD *thd, Native *to)
|
||||||
|
{
|
||||||
|
return m_value.to_native(to, decimals);
|
||||||
|
}
|
||||||
|
void set_value(const Timestamp_or_zero_datetime &value)
|
||||||
|
{
|
||||||
|
m_value= value;
|
||||||
|
}
|
||||||
|
Item *get_copy(THD *thd)
|
||||||
|
{ return get_item_copy<Item_timestamp_literal>(thd, this); }
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
class Item_temporal_literal :public Item_literal
|
class Item_temporal_literal :public Item_literal
|
||||||
{
|
{
|
||||||
protected:
|
protected:
|
||||||
|
|
@ -5062,11 +5191,13 @@ public:
|
||||||
my_decimal *val_decimal(my_decimal *);
|
my_decimal *val_decimal(my_decimal *);
|
||||||
bool val_bool();
|
bool val_bool();
|
||||||
String *val_str(String* tmp);
|
String *val_str(String* tmp);
|
||||||
|
bool val_native(THD *thd, Native *to);
|
||||||
bool is_null();
|
bool is_null();
|
||||||
bool get_date(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate);
|
bool get_date(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate);
|
||||||
double val_result();
|
double val_result();
|
||||||
longlong val_int_result();
|
longlong val_int_result();
|
||||||
String *str_result(String* tmp);
|
String *str_result(String* tmp);
|
||||||
|
bool val_native_result(THD *thd, Native *to);
|
||||||
my_decimal *val_decimal_result(my_decimal *);
|
my_decimal *val_decimal_result(my_decimal *);
|
||||||
bool val_bool_result();
|
bool val_bool_result();
|
||||||
bool is_null_result();
|
bool is_null_result();
|
||||||
|
|
@ -5271,6 +5402,7 @@ public:
|
||||||
double val_real();
|
double val_real();
|
||||||
longlong val_int();
|
longlong val_int();
|
||||||
String *val_str(String* tmp);
|
String *val_str(String* tmp);
|
||||||
|
bool val_native(THD *thd, Native *to);
|
||||||
my_decimal *val_decimal(my_decimal *);
|
my_decimal *val_decimal(my_decimal *);
|
||||||
bool val_bool();
|
bool val_bool();
|
||||||
bool is_null();
|
bool is_null();
|
||||||
|
|
@ -5367,6 +5499,7 @@ public:
|
||||||
double val_real();
|
double val_real();
|
||||||
longlong val_int();
|
longlong val_int();
|
||||||
String *val_str(String* tmp);
|
String *val_str(String* tmp);
|
||||||
|
bool val_native(THD *thd, Native *to);
|
||||||
my_decimal *val_decimal(my_decimal *);
|
my_decimal *val_decimal(my_decimal *);
|
||||||
bool val_bool();
|
bool val_bool();
|
||||||
bool is_null();
|
bool is_null();
|
||||||
|
|
@ -5563,6 +5696,12 @@ public:
|
||||||
else
|
else
|
||||||
return Item_direct_ref::val_str(tmp);
|
return Item_direct_ref::val_str(tmp);
|
||||||
}
|
}
|
||||||
|
bool val_native(THD *thd, Native *to)
|
||||||
|
{
|
||||||
|
if (check_null_ref())
|
||||||
|
return true;
|
||||||
|
return Item_direct_ref::val_native(thd, to);
|
||||||
|
}
|
||||||
my_decimal *val_decimal(my_decimal *tmp)
|
my_decimal *val_decimal(my_decimal *tmp)
|
||||||
{
|
{
|
||||||
if (check_null_ref())
|
if (check_null_ref())
|
||||||
|
|
@ -5708,6 +5847,7 @@ public:
|
||||||
my_decimal *val_decimal(my_decimal *);
|
my_decimal *val_decimal(my_decimal *);
|
||||||
bool val_bool();
|
bool val_bool();
|
||||||
bool get_date(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate);
|
bool get_date(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate);
|
||||||
|
bool val_native(THD *thd, Native *to);
|
||||||
virtual void print(String *str, enum_query_type query_type);
|
virtual void print(String *str, enum_query_type query_type);
|
||||||
table_map used_tables() const;
|
table_map used_tables() const;
|
||||||
Item *get_copy(THD *thd)
|
Item *get_copy(THD *thd)
|
||||||
|
|
@ -6531,6 +6671,48 @@ public:
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class Item_cache_timestamp: public Item_cache
|
||||||
|
{
|
||||||
|
Timestamp_or_zero_datetime_native m_native;
|
||||||
|
Datetime to_datetime(THD *thd);
|
||||||
|
public:
|
||||||
|
Item_cache_timestamp(THD *thd)
|
||||||
|
:Item_cache(thd, &type_handler_timestamp2) { }
|
||||||
|
Item *get_copy(THD *thd)
|
||||||
|
{ return get_item_copy<Item_cache_timestamp>(thd, this); }
|
||||||
|
bool cache_value();
|
||||||
|
String* val_str(String *to)
|
||||||
|
{
|
||||||
|
return to_datetime(current_thd).to_string(to, decimals);
|
||||||
|
}
|
||||||
|
my_decimal *val_decimal(my_decimal *to)
|
||||||
|
{
|
||||||
|
return to_datetime(current_thd).to_decimal(to);
|
||||||
|
}
|
||||||
|
longlong val_int()
|
||||||
|
{
|
||||||
|
return to_datetime(current_thd).to_longlong();
|
||||||
|
}
|
||||||
|
double val_real()
|
||||||
|
{
|
||||||
|
return to_datetime(current_thd).to_double();
|
||||||
|
}
|
||||||
|
longlong val_datetime_packed(THD *thd)
|
||||||
|
{
|
||||||
|
DBUG_ASSERT(0);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
longlong val_time_packed(THD *thd)
|
||||||
|
{
|
||||||
|
DBUG_ASSERT(0);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
bool get_date(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate);
|
||||||
|
int save_in_field(Field *field, bool no_conversions);
|
||||||
|
bool val_native(THD *thd, Native *to);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
class Item_cache_real: public Item_cache
|
class Item_cache_real: public Item_cache
|
||||||
{
|
{
|
||||||
double value;
|
double value;
|
||||||
|
|
|
||||||
|
|
@ -567,6 +567,18 @@ bool Arg_comparator::set_cmp_func_datetime()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool Arg_comparator::set_cmp_func_native()
|
||||||
|
{
|
||||||
|
THD *thd= current_thd;
|
||||||
|
m_compare_collation= &my_charset_numeric;
|
||||||
|
func= is_owner_equal_func() ? &Arg_comparator::compare_e_native :
|
||||||
|
&Arg_comparator::compare_native;
|
||||||
|
a= cache_converted_constant(thd, a, &a_cache, compare_type_handler());
|
||||||
|
b= cache_converted_constant(thd, b, &b_cache, compare_type_handler());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
bool Arg_comparator::set_cmp_func_int()
|
bool Arg_comparator::set_cmp_func_int()
|
||||||
{
|
{
|
||||||
THD *thd= current_thd;
|
THD *thd= current_thd;
|
||||||
|
|
@ -770,6 +782,39 @@ int Arg_comparator::compare_e_string()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int Arg_comparator::compare_native()
|
||||||
|
{
|
||||||
|
THD *thd= current_thd;
|
||||||
|
if (!(*a)->val_native_with_conversion(thd, &m_native1,
|
||||||
|
compare_type_handler()))
|
||||||
|
{
|
||||||
|
if (!(*b)->val_native_with_conversion(thd, &m_native2,
|
||||||
|
compare_type_handler()))
|
||||||
|
{
|
||||||
|
if (set_null)
|
||||||
|
owner->null_value= 0;
|
||||||
|
return compare_type_handler()->cmp_native(m_native1, m_native2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (set_null)
|
||||||
|
owner->null_value= 1;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int Arg_comparator::compare_e_native()
|
||||||
|
{
|
||||||
|
THD *thd= current_thd;
|
||||||
|
bool res1= (*a)->val_native_with_conversion(thd, &m_native1,
|
||||||
|
compare_type_handler());
|
||||||
|
bool res2= (*b)->val_native_with_conversion(thd, &m_native2,
|
||||||
|
compare_type_handler());
|
||||||
|
if (res1 || res2)
|
||||||
|
return MY_TEST(res1 == res2);
|
||||||
|
return MY_TEST(compare_type_handler()->cmp_native(m_native1, m_native2) == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
int Arg_comparator::compare_real()
|
int Arg_comparator::compare_real()
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
|
|
@ -2121,6 +2166,29 @@ longlong Item_func_between::val_int_cmp_time()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
longlong Item_func_between::val_int_cmp_native()
|
||||||
|
{
|
||||||
|
THD *thd= current_thd;
|
||||||
|
const Type_handler *h= m_comparator.type_handler();
|
||||||
|
NativeBuffer<STRING_BUFFER_USUAL_SIZE> value, a, b;
|
||||||
|
if (val_native_with_conversion_from_item(thd, args[0], &value, h))
|
||||||
|
return 0;
|
||||||
|
bool ra= args[1]->val_native_with_conversion(thd, &a, h);
|
||||||
|
bool rb= args[2]->val_native_with_conversion(thd, &b, h);
|
||||||
|
if (!ra && !rb)
|
||||||
|
return (longlong)
|
||||||
|
((h->cmp_native(value, a) >= 0 &&
|
||||||
|
h->cmp_native(value, b) <= 0) != negated);
|
||||||
|
if (ra && rb)
|
||||||
|
null_value= true;
|
||||||
|
else if (ra)
|
||||||
|
null_value= h->cmp_native(value, b) <= 0;
|
||||||
|
else
|
||||||
|
null_value= h->cmp_native(value, a) >= 0;
|
||||||
|
return (longlong) (!null_value && negated);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
longlong Item_func_between::val_int_cmp_string()
|
longlong Item_func_between::val_int_cmp_string()
|
||||||
{
|
{
|
||||||
String *value,*a,*b;
|
String *value,*a,*b;
|
||||||
|
|
@ -2306,6 +2374,15 @@ Item_func_ifnull::str_op(String *str)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool Item_func_ifnull::native_op(THD *thd, Native *to)
|
||||||
|
{
|
||||||
|
DBUG_ASSERT(fixed == 1);
|
||||||
|
if (!val_native_with_conversion_from_item(thd, args[0], to, type_handler()))
|
||||||
|
return false;
|
||||||
|
return val_native_with_conversion_from_item(thd, args[1], to, type_handler());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
bool Item_func_ifnull::date_op(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate)
|
bool Item_func_ifnull::date_op(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate)
|
||||||
{
|
{
|
||||||
DBUG_ASSERT(fixed == 1);
|
DBUG_ASSERT(fixed == 1);
|
||||||
|
|
@ -2828,6 +2905,16 @@ Item_func_nullif::time_op(THD *thd, MYSQL_TIME *ltime)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool
|
||||||
|
Item_func_nullif::native_op(THD *thd, Native *to)
|
||||||
|
{
|
||||||
|
DBUG_ASSERT(fixed == 1);
|
||||||
|
if (!compare())
|
||||||
|
return (null_value= true);
|
||||||
|
return val_native_with_conversion_from_item(thd, args[2], to, type_handler());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
bool
|
bool
|
||||||
Item_func_nullif::is_null()
|
Item_func_nullif::is_null()
|
||||||
{
|
{
|
||||||
|
|
@ -3002,6 +3089,16 @@ bool Item_func_case::time_op(THD *thd, MYSQL_TIME *ltime)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool Item_func_case::native_op(THD *thd, Native *to)
|
||||||
|
{
|
||||||
|
DBUG_ASSERT(fixed == 1);
|
||||||
|
Item *item= find_item();
|
||||||
|
if (!item)
|
||||||
|
return (null_value= true);
|
||||||
|
return val_native_with_conversion_from_item(thd, item, to, type_handler());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
bool Item_func_case::fix_fields(THD *thd, Item **ref)
|
bool Item_func_case::fix_fields(THD *thd, Item **ref)
|
||||||
{
|
{
|
||||||
bool res= Item_func::fix_fields(thd, ref);
|
bool res= Item_func::fix_fields(thd, ref);
|
||||||
|
|
@ -3360,6 +3457,18 @@ bool Item_func_coalesce::time_op(THD *thd, MYSQL_TIME *ltime)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool Item_func_coalesce::native_op(THD *thd, Native *to)
|
||||||
|
{
|
||||||
|
DBUG_ASSERT(fixed == 1);
|
||||||
|
for (uint i= 0; i < arg_count; i++)
|
||||||
|
{
|
||||||
|
if (!val_native_with_conversion_from_item(thd, args[i], to, type_handler()))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return (null_value= true);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
my_decimal *Item_func_coalesce::decimal_op(my_decimal *decimal_value)
|
my_decimal *Item_func_coalesce::decimal_op(my_decimal *decimal_value)
|
||||||
{
|
{
|
||||||
DBUG_ASSERT(fixed == 1);
|
DBUG_ASSERT(fixed == 1);
|
||||||
|
|
@ -3637,6 +3746,53 @@ Item *in_longlong::create_item(THD *thd)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int cmp_timestamp(void *cmp_arg,
|
||||||
|
Timestamp_or_zero_datetime *a,
|
||||||
|
Timestamp_or_zero_datetime *b)
|
||||||
|
{
|
||||||
|
return a->cmp(*b);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
in_timestamp::in_timestamp(THD *thd, uint elements)
|
||||||
|
:in_vector(thd, elements, sizeof(Value), (qsort2_cmp) cmp_timestamp, 0)
|
||||||
|
{}
|
||||||
|
|
||||||
|
|
||||||
|
void in_timestamp::set(uint pos, Item *item)
|
||||||
|
{
|
||||||
|
Timestamp_or_zero_datetime *buff= &((Timestamp_or_zero_datetime *) base)[pos];
|
||||||
|
Timestamp_or_zero_datetime_native_null native(current_thd, item, true);
|
||||||
|
if (native.is_null())
|
||||||
|
*buff= Timestamp_or_zero_datetime();
|
||||||
|
else
|
||||||
|
*buff= Timestamp_or_zero_datetime(native);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
uchar *in_timestamp::get_value(Item *item)
|
||||||
|
{
|
||||||
|
Timestamp_or_zero_datetime_native_null native(current_thd, item, true);
|
||||||
|
if (native.is_null())
|
||||||
|
return 0;
|
||||||
|
tmp= Timestamp_or_zero_datetime(native);
|
||||||
|
return (uchar*) &tmp;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Item *in_timestamp::create_item(THD *thd)
|
||||||
|
{
|
||||||
|
return new (thd->mem_root) Item_timestamp_literal(thd);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void in_timestamp::value_to_item(uint pos, Item *item)
|
||||||
|
{
|
||||||
|
const Timestamp_or_zero_datetime &buff= (((Timestamp_or_zero_datetime*) base)[pos]);
|
||||||
|
static_cast<Item_timestamp_literal*>(item)->set_value(buff);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void in_datetime::set(uint pos,Item *item)
|
void in_datetime::set(uint pos,Item *item)
|
||||||
{
|
{
|
||||||
struct packed_longlong *buff= &((packed_longlong*) base)[pos];
|
struct packed_longlong *buff= &((packed_longlong*) base)[pos];
|
||||||
|
|
@ -4044,6 +4200,49 @@ cmp_item *cmp_item_time::make_same()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void cmp_item_timestamp::store_value(Item *item)
|
||||||
|
{
|
||||||
|
item->val_native_with_conversion(current_thd, &m_native,
|
||||||
|
&type_handler_timestamp2);
|
||||||
|
m_null_value= item->null_value;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int cmp_item_timestamp::cmp_not_null(const Value *val)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
This method will be implemented when we add this syntax:
|
||||||
|
SELECT TIMESTAMP WITH LOCAL TIME ZONE '2001-01-01 10:20:30'
|
||||||
|
For now TIMESTAMP is compared to non-TIMESTAMP using DATETIME.
|
||||||
|
*/
|
||||||
|
DBUG_ASSERT(0);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int cmp_item_timestamp::cmp(Item *arg)
|
||||||
|
{
|
||||||
|
THD *thd= current_thd;
|
||||||
|
Timestamp_or_zero_datetime_native_null tmp(thd, arg, true);
|
||||||
|
return m_null_value || tmp.is_null() ? UNKNOWN :
|
||||||
|
type_handler_timestamp2.cmp_native(m_native, tmp) != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int cmp_item_timestamp::compare(cmp_item *arg)
|
||||||
|
{
|
||||||
|
cmp_item_timestamp *tmp= static_cast<cmp_item_timestamp*>(arg);
|
||||||
|
return type_handler_timestamp2.cmp_native(m_native, tmp->m_native);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
cmp_item* cmp_item_timestamp::make_same()
|
||||||
|
{
|
||||||
|
return new cmp_item_timestamp();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
bool Item_func_in::count_sargable_conds(void *arg)
|
bool Item_func_in::count_sargable_conds(void *arg)
|
||||||
{
|
{
|
||||||
((SELECT_LEX*) arg)->cond_count++;
|
((SELECT_LEX*) arg)->cond_count++;
|
||||||
|
|
|
||||||
|
|
@ -68,6 +68,7 @@ class Arg_comparator: public Sql_alloc
|
||||||
if (val1 == val2) return 0;
|
if (val1 == val2) return 0;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
NativeBuffer<STRING_BUFFER_USUAL_SIZE> m_native1, m_native2;
|
||||||
public:
|
public:
|
||||||
/* Allow owner function to use string buffers. */
|
/* Allow owner function to use string buffers. */
|
||||||
String value1, value2;
|
String value1, value2;
|
||||||
|
|
@ -89,6 +90,7 @@ public:
|
||||||
bool set_cmp_func_string();
|
bool set_cmp_func_string();
|
||||||
bool set_cmp_func_time();
|
bool set_cmp_func_time();
|
||||||
bool set_cmp_func_datetime();
|
bool set_cmp_func_datetime();
|
||||||
|
bool set_cmp_func_native();
|
||||||
bool set_cmp_func_int();
|
bool set_cmp_func_int();
|
||||||
bool set_cmp_func_real();
|
bool set_cmp_func_real();
|
||||||
bool set_cmp_func_decimal();
|
bool set_cmp_func_decimal();
|
||||||
|
|
@ -121,6 +123,8 @@ public:
|
||||||
int compare_e_datetime();
|
int compare_e_datetime();
|
||||||
int compare_time();
|
int compare_time();
|
||||||
int compare_e_time();
|
int compare_e_time();
|
||||||
|
int compare_native();
|
||||||
|
int compare_e_native();
|
||||||
int compare_json_str_basic(Item *j, Item *s);
|
int compare_json_str_basic(Item *j, Item *s);
|
||||||
int compare_json_str();
|
int compare_json_str();
|
||||||
int compare_str_json();
|
int compare_str_json();
|
||||||
|
|
@ -935,6 +939,7 @@ public:
|
||||||
longlong val_int_cmp_string();
|
longlong val_int_cmp_string();
|
||||||
longlong val_int_cmp_datetime();
|
longlong val_int_cmp_datetime();
|
||||||
longlong val_int_cmp_time();
|
longlong val_int_cmp_time();
|
||||||
|
longlong val_int_cmp_native();
|
||||||
longlong val_int_cmp_int();
|
longlong val_int_cmp_int();
|
||||||
longlong val_int_cmp_real();
|
longlong val_int_cmp_real();
|
||||||
longlong val_int_cmp_decimal();
|
longlong val_int_cmp_decimal();
|
||||||
|
|
@ -1013,6 +1018,7 @@ public:
|
||||||
my_decimal *decimal_op(my_decimal *);
|
my_decimal *decimal_op(my_decimal *);
|
||||||
bool date_op(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate);
|
bool date_op(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate);
|
||||||
bool time_op(THD *thd, MYSQL_TIME *ltime);
|
bool time_op(THD *thd, MYSQL_TIME *ltime);
|
||||||
|
bool native_op(THD *thd, Native *to);
|
||||||
bool fix_length_and_dec()
|
bool fix_length_and_dec()
|
||||||
{
|
{
|
||||||
if (aggregate_for_result(func_name(), args, arg_count, true))
|
if (aggregate_for_result(func_name(), args, arg_count, true))
|
||||||
|
|
@ -1092,6 +1098,7 @@ public:
|
||||||
my_decimal *decimal_op(my_decimal *);
|
my_decimal *decimal_op(my_decimal *);
|
||||||
bool date_op(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate);
|
bool date_op(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate);
|
||||||
bool time_op(THD *thd, MYSQL_TIME *ltime);
|
bool time_op(THD *thd, MYSQL_TIME *ltime);
|
||||||
|
bool native_op(THD *thd, Native *to);
|
||||||
bool fix_length_and_dec()
|
bool fix_length_and_dec()
|
||||||
{
|
{
|
||||||
if (Item_func_case_abbreviation2::fix_length_and_dec2(args))
|
if (Item_func_case_abbreviation2::fix_length_and_dec2(args))
|
||||||
|
|
@ -1150,6 +1157,11 @@ public:
|
||||||
{
|
{
|
||||||
return val_str_from_item(find_item(), str);
|
return val_str_from_item(find_item(), str);
|
||||||
}
|
}
|
||||||
|
bool native_op(THD *thd, Native *to)
|
||||||
|
{
|
||||||
|
return val_native_with_conversion_from_item(thd, find_item(), to,
|
||||||
|
type_handler());
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -1249,6 +1261,7 @@ public:
|
||||||
longlong int_op();
|
longlong int_op();
|
||||||
String *str_op(String *str);
|
String *str_op(String *str);
|
||||||
my_decimal *decimal_op(my_decimal *);
|
my_decimal *decimal_op(my_decimal *);
|
||||||
|
bool native_op(THD *thd, Native *to);
|
||||||
bool fix_length_and_dec();
|
bool fix_length_and_dec();
|
||||||
bool walk(Item_processor processor, bool walk_subquery, void *arg);
|
bool walk(Item_processor processor, bool walk_subquery, void *arg);
|
||||||
const char *func_name() const { return "nullif"; }
|
const char *func_name() const { return "nullif"; }
|
||||||
|
|
@ -1412,6 +1425,19 @@ public:
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class in_timestamp :public in_vector
|
||||||
|
{
|
||||||
|
Timestamp_or_zero_datetime tmp;
|
||||||
|
public:
|
||||||
|
in_timestamp(THD *thd, uint elements);
|
||||||
|
void set(uint pos,Item *item);
|
||||||
|
uchar *get_value(Item *item);
|
||||||
|
Item* create_item(THD *thd);
|
||||||
|
void value_to_item(uint pos, Item *item);
|
||||||
|
const Type_handler *type_handler() const { return &type_handler_timestamp2; }
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Class to represent a vector of constant DATE/DATETIME values.
|
Class to represent a vector of constant DATE/DATETIME values.
|
||||||
*/
|
*/
|
||||||
|
|
@ -1666,6 +1692,20 @@ public:
|
||||||
cmp_item *make_same();
|
cmp_item *make_same();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class cmp_item_timestamp: public cmp_item_scalar
|
||||||
|
{
|
||||||
|
Timestamp_or_zero_datetime_native m_native;
|
||||||
|
public:
|
||||||
|
cmp_item_timestamp() :cmp_item_scalar() { }
|
||||||
|
void store_value(Item *item);
|
||||||
|
int cmp_not_null(const Value *val);
|
||||||
|
int cmp(Item *arg);
|
||||||
|
int compare(cmp_item *ci);
|
||||||
|
cmp_item *make_same();
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
class cmp_item_real : public cmp_item_scalar
|
class cmp_item_real : public cmp_item_scalar
|
||||||
{
|
{
|
||||||
double value;
|
double value;
|
||||||
|
|
@ -2132,6 +2172,7 @@ public:
|
||||||
my_decimal *decimal_op(my_decimal *);
|
my_decimal *decimal_op(my_decimal *);
|
||||||
bool date_op(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate);
|
bool date_op(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate);
|
||||||
bool time_op(THD *thd, MYSQL_TIME *ltime);
|
bool time_op(THD *thd, MYSQL_TIME *ltime);
|
||||||
|
bool native_op(THD *thd, Native *to);
|
||||||
bool fix_fields(THD *thd, Item **ref);
|
bool fix_fields(THD *thd, Item **ref);
|
||||||
table_map not_null_tables() const { return 0; }
|
table_map not_null_tables() const { return 0; }
|
||||||
const char *func_name() const { return "case"; }
|
const char *func_name() const { return "case"; }
|
||||||
|
|
|
||||||
|
|
@ -2730,6 +2730,28 @@ my_decimal *Item_func_min_max::val_decimal_native(my_decimal *dec)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool Item_func_min_max::val_native(THD *thd, Native *native)
|
||||||
|
{
|
||||||
|
DBUG_ASSERT(fixed == 1);
|
||||||
|
const Type_handler *handler= Item_hybrid_func::type_handler();
|
||||||
|
NativeBuffer<STRING_BUFFER_USUAL_SIZE> cur;
|
||||||
|
for (uint i= 0; i < arg_count; i++)
|
||||||
|
{
|
||||||
|
if (val_native_with_conversion_from_item(thd, args[i],
|
||||||
|
i == 0 ? native : &cur,
|
||||||
|
handler))
|
||||||
|
return true;
|
||||||
|
if (i > 0)
|
||||||
|
{
|
||||||
|
int cmp= handler->cmp_native(*native, cur);
|
||||||
|
if ((cmp_sign < 0 ? cmp : -cmp) < 0 && native->copy(cur))
|
||||||
|
return null_value= true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null_value= false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
longlong Item_func_bit_length::val_int()
|
longlong Item_func_bit_length::val_int()
|
||||||
{
|
{
|
||||||
DBUG_ASSERT(fixed == 1);
|
DBUG_ASSERT(fixed == 1);
|
||||||
|
|
@ -6453,6 +6475,14 @@ String *Item_func_last_value::val_str(String *str)
|
||||||
return tmp;
|
return tmp;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool Item_func_last_value::val_native(THD *thd, Native *to)
|
||||||
|
{
|
||||||
|
evaluate_sideeffects();
|
||||||
|
return val_native_from_item(thd, last_value, to);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
longlong Item_func_last_value::val_int()
|
longlong Item_func_last_value::val_int()
|
||||||
{
|
{
|
||||||
longlong tmp;
|
longlong tmp;
|
||||||
|
|
|
||||||
|
|
@ -768,6 +768,12 @@ public:
|
||||||
Item_func_hybrid_field_type_get_date_with_warn(thd, this, to, mode);
|
Item_func_hybrid_field_type_get_date_with_warn(thd, this, to, mode);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool val_native(THD *thd, Native *to)
|
||||||
|
{
|
||||||
|
DBUG_ASSERT(fixed);
|
||||||
|
return native_op(thd, to);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@brief Performs the operation that this functions implements when the
|
@brief Performs the operation that this functions implements when the
|
||||||
result type is INT.
|
result type is INT.
|
||||||
|
|
@ -838,6 +844,7 @@ public:
|
||||||
*/
|
*/
|
||||||
virtual bool time_op(THD *thd, MYSQL_TIME *res)= 0;
|
virtual bool time_op(THD *thd, MYSQL_TIME *res)= 0;
|
||||||
|
|
||||||
|
virtual bool native_op(THD *thd, Native *native)= 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -905,6 +912,11 @@ public:
|
||||||
DBUG_ASSERT(0);
|
DBUG_ASSERT(0);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
bool native_op(THD *thd, Native *to)
|
||||||
|
{
|
||||||
|
DBUG_ASSERT(0);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -1771,6 +1783,7 @@ public:
|
||||||
return Item_func_min_max::type_handler()->
|
return Item_func_min_max::type_handler()->
|
||||||
Item_func_min_max_get_date(thd, this, res, fuzzydate);
|
Item_func_min_max_get_date(thd, this, res, fuzzydate);
|
||||||
}
|
}
|
||||||
|
bool val_native(THD *thd, Native *to);
|
||||||
void aggregate_attributes_real(Item **items, uint nitems)
|
void aggregate_attributes_real(Item **items, uint nitems)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
|
|
@ -1834,6 +1847,8 @@ public:
|
||||||
double val_real() { return val_real_from_item(args[0]); }
|
double val_real() { return val_real_from_item(args[0]); }
|
||||||
longlong val_int() { return val_int_from_item(args[0]); }
|
longlong val_int() { return val_int_from_item(args[0]); }
|
||||||
String *val_str(String *str) { return val_str_from_item(args[0], str); }
|
String *val_str(String *str) { return val_str_from_item(args[0], str); }
|
||||||
|
bool val_native(THD *thd, Native *to)
|
||||||
|
{ return val_native_from_item(thd, args[0], to); }
|
||||||
my_decimal *val_decimal(my_decimal *dec)
|
my_decimal *val_decimal(my_decimal *dec)
|
||||||
{ return val_decimal_from_item(args[0], dec); }
|
{ return val_decimal_from_item(args[0], dec); }
|
||||||
bool get_date(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate)
|
bool get_date(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate)
|
||||||
|
|
@ -3153,6 +3168,13 @@ public:
|
||||||
return str;
|
return str;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool val_native(THD *thd, Native *to)
|
||||||
|
{
|
||||||
|
if (execute())
|
||||||
|
return true;
|
||||||
|
return null_value= sp_result_field->val_native(to);
|
||||||
|
}
|
||||||
|
|
||||||
void update_null_value()
|
void update_null_value()
|
||||||
{
|
{
|
||||||
execute();
|
execute();
|
||||||
|
|
@ -3282,6 +3304,7 @@ public:
|
||||||
String *val_str(String *);
|
String *val_str(String *);
|
||||||
my_decimal *val_decimal(my_decimal *);
|
my_decimal *val_decimal(my_decimal *);
|
||||||
bool get_date(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate);
|
bool get_date(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate);
|
||||||
|
bool val_native(THD *thd, Native *);
|
||||||
bool fix_length_and_dec();
|
bool fix_length_and_dec();
|
||||||
const char *func_name() const { return "last_value"; }
|
const char *func_name() const { return "last_value"; }
|
||||||
const Type_handler *type_handler() const { return last_value->type_handler(); }
|
const Type_handler *type_handler() const { return last_value->type_handler(); }
|
||||||
|
|
|
||||||
|
|
@ -1352,6 +1352,24 @@ String *Item_singlerow_subselect::val_str(String *str)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool Item_singlerow_subselect::val_native(THD *thd, Native *to)
|
||||||
|
{
|
||||||
|
DBUG_ASSERT(fixed == 1);
|
||||||
|
if (forced_const)
|
||||||
|
return value->val_native(thd, to);
|
||||||
|
if (!exec() && !value->null_value)
|
||||||
|
{
|
||||||
|
null_value= false;
|
||||||
|
return value->val_native(thd, to);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
reset();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
my_decimal *Item_singlerow_subselect::val_decimal(my_decimal *decimal_value)
|
my_decimal *Item_singlerow_subselect::val_decimal(my_decimal *decimal_value)
|
||||||
{
|
{
|
||||||
DBUG_ASSERT(fixed == 1);
|
DBUG_ASSERT(fixed == 1);
|
||||||
|
|
|
||||||
|
|
@ -306,6 +306,7 @@ public:
|
||||||
double val_real();
|
double val_real();
|
||||||
longlong val_int ();
|
longlong val_int ();
|
||||||
String *val_str (String *);
|
String *val_str (String *);
|
||||||
|
bool val_native(THD *thd, Native *);
|
||||||
my_decimal *val_decimal(my_decimal *);
|
my_decimal *val_decimal(my_decimal *);
|
||||||
bool val_bool();
|
bool val_bool();
|
||||||
bool get_date(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate);
|
bool get_date(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate);
|
||||||
|
|
|
||||||
|
|
@ -2381,6 +2381,15 @@ Item_sum_hybrid::val_str(String *str)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool Item_sum_hybrid::val_native(THD *thd, Native *to)
|
||||||
|
{
|
||||||
|
DBUG_ASSERT(fixed == 1);
|
||||||
|
if (null_value)
|
||||||
|
return true;
|
||||||
|
return val_native_from_item(thd, value, to);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void Item_sum_hybrid::cleanup()
|
void Item_sum_hybrid::cleanup()
|
||||||
{
|
{
|
||||||
DBUG_ENTER("Item_sum_hybrid::cleanup");
|
DBUG_ENTER("Item_sum_hybrid::cleanup");
|
||||||
|
|
|
||||||
|
|
@ -1072,6 +1072,7 @@ protected:
|
||||||
bool get_date(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate);
|
bool get_date(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate);
|
||||||
void reset_field();
|
void reset_field();
|
||||||
String *val_str(String *);
|
String *val_str(String *);
|
||||||
|
bool val_native(THD *thd, Native *);
|
||||||
const Type_handler *real_type_handler() const
|
const Type_handler *real_type_handler() const
|
||||||
{
|
{
|
||||||
return get_arg(0)->real_type_handler();
|
return get_arg(0)->real_type_handler();
|
||||||
|
|
|
||||||
|
|
@ -1217,15 +1217,13 @@ bool Item_func_unix_timestamp::get_timestamp_value(my_time_t *seconds,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
THD *thd= current_thd;
|
Timestamp_or_zero_datetime_native_null native(current_thd, args[0], true);
|
||||||
Datetime dt(thd, args[0], Datetime::Options(TIME_NO_ZERO_IN_DATE, thd));
|
if ((null_value= native.is_null() || native.is_zero_datetime()))
|
||||||
if ((null_value= !dt.is_valid_datetime()))
|
|
||||||
return true;
|
return true;
|
||||||
|
Timestamp_or_zero_datetime tm(native);
|
||||||
uint error_code;
|
*seconds= tm.tv().tv_sec;
|
||||||
*seconds= TIME_to_timestamp(thd, dt.get_mysql_time(), &error_code);
|
*second_part= tm.tv().tv_usec;
|
||||||
*second_part= dt.get_mysql_time()->second_part;
|
return false;
|
||||||
return (null_value= (error_code == ER_WARN_DATA_OUT_OF_RANGE));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
332
sql/sql_type.cc
332
sql/sql_type.cc
|
|
@ -209,6 +209,104 @@ Temporal_hybrid::Temporal_hybrid(THD *thd, Item *item, date_mode_t fuzzydate)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
uint Timestamp::binary_length_to_precision(uint length)
|
||||||
|
{
|
||||||
|
switch (length) {
|
||||||
|
case 4: return 0;
|
||||||
|
case 5: return 2;
|
||||||
|
case 6: return 4;
|
||||||
|
case 7: return 6;
|
||||||
|
}
|
||||||
|
DBUG_ASSERT(0);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Timestamp::Timestamp(const Native &native)
|
||||||
|
{
|
||||||
|
DBUG_ASSERT(native.length() >= 4 && native.length() <= 7);
|
||||||
|
uint dec= binary_length_to_precision(native.length());
|
||||||
|
my_timestamp_from_binary(this, (const uchar *) native.ptr(), dec);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool Timestamp::to_native(Native *to, uint decimals) const
|
||||||
|
{
|
||||||
|
uint len= my_timestamp_binary_length(decimals);
|
||||||
|
if (to->reserve(len))
|
||||||
|
return true;
|
||||||
|
my_timestamp_to_binary(this, (uchar *) to->ptr(), decimals);
|
||||||
|
to->length(len);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool Timestamp::to_TIME(THD *thd, MYSQL_TIME *to, date_mode_t fuzzydate) const
|
||||||
|
{
|
||||||
|
return thd->timestamp_to_TIME(to, tv_sec, tv_usec, fuzzydate);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Timestamp::Timestamp(THD *thd, const MYSQL_TIME *ltime, uint *error_code)
|
||||||
|
:Timeval(TIME_to_timestamp(thd, ltime, error_code), ltime->second_part)
|
||||||
|
{ }
|
||||||
|
|
||||||
|
|
||||||
|
Timestamp_or_zero_datetime::Timestamp_or_zero_datetime(THD *thd,
|
||||||
|
const MYSQL_TIME *ltime,
|
||||||
|
uint *error_code)
|
||||||
|
:Timestamp(thd, ltime, error_code),
|
||||||
|
m_is_zero_datetime(*error_code == ER_WARN_DATA_OUT_OF_RANGE)
|
||||||
|
{
|
||||||
|
if (m_is_zero_datetime)
|
||||||
|
{
|
||||||
|
if (!non_zero_date(ltime))
|
||||||
|
*error_code= 0; // ltime was '0000-00-00 00:00:00'
|
||||||
|
}
|
||||||
|
else if (*error_code == ER_WARN_INVALID_TIMESTAMP)
|
||||||
|
*error_code= 0; // ltime fell into spring time gap, adjusted.
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool Timestamp_or_zero_datetime::to_TIME(THD *thd, MYSQL_TIME *to,
|
||||||
|
date_mode_t fuzzydate) const
|
||||||
|
{
|
||||||
|
if (m_is_zero_datetime)
|
||||||
|
{
|
||||||
|
set_zero_time(to, MYSQL_TIMESTAMP_DATETIME);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return Timestamp::to_TIME(thd, to, fuzzydate);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool Timestamp_or_zero_datetime::to_native(Native *to, uint decimals) const
|
||||||
|
{
|
||||||
|
if (m_is_zero_datetime)
|
||||||
|
{
|
||||||
|
to->length(0);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return Timestamp::to_native(to, decimals);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int Timestamp_or_zero_datetime_native::save_in_field(Field *field,
|
||||||
|
uint decimals) const
|
||||||
|
{
|
||||||
|
field->set_notnull();
|
||||||
|
if (field->type_handler()->type_handler_for_native_format() ==
|
||||||
|
&type_handler_timestamp2)
|
||||||
|
return field->store_native(*this);
|
||||||
|
if (is_zero_datetime())
|
||||||
|
{
|
||||||
|
static Datetime zero(Datetime::zero());
|
||||||
|
return field->store_time_dec(zero.get_mysql_time(), decimals);
|
||||||
|
}
|
||||||
|
return field->store_timestamp_dec(Timestamp(*this).tv(), decimals);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void Sec6::make_from_decimal(const my_decimal *d, ulong *nanoseconds)
|
void Sec6::make_from_decimal(const my_decimal *d, ulong *nanoseconds)
|
||||||
{
|
{
|
||||||
m_neg= my_decimal2seconds(d, &m_sec, &m_usec, nanoseconds);
|
m_neg= my_decimal2seconds(d, &m_sec, &m_usec, nanoseconds);
|
||||||
|
|
@ -1272,7 +1370,7 @@ const Type_handler *Type_handler_datetime_common::type_handler_for_comparison()
|
||||||
|
|
||||||
const Type_handler *Type_handler_timestamp_common::type_handler_for_comparison() const
|
const Type_handler *Type_handler_timestamp_common::type_handler_for_comparison() const
|
||||||
{
|
{
|
||||||
return &type_handler_datetime;
|
return &type_handler_timestamp;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -1281,6 +1379,15 @@ const Type_handler *Type_handler_row::type_handler_for_comparison() const
|
||||||
return &type_handler_row;
|
return &type_handler_row;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/***************************************************************************/
|
||||||
|
|
||||||
|
const Type_handler *
|
||||||
|
Type_handler_timestamp_common::type_handler_for_native_format() const
|
||||||
|
{
|
||||||
|
return &type_handler_timestamp2;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/***************************************************************************/
|
/***************************************************************************/
|
||||||
|
|
||||||
const Type_handler *Type_handler_typelib::type_handler_for_item_field() const
|
const Type_handler *Type_handler_typelib::type_handler_for_item_field() const
|
||||||
|
|
@ -1457,6 +1564,16 @@ Type_handler_hybrid_field_type::aggregate_for_comparison(const Type_handler *h)
|
||||||
*/
|
*/
|
||||||
if (b == TIME_RESULT)
|
if (b == TIME_RESULT)
|
||||||
m_type_handler= h; // Temporal types bit non-temporal types
|
m_type_handler= h; // Temporal types bit non-temporal types
|
||||||
|
/*
|
||||||
|
Compare TIMESTAMP to a non-temporal type as DATETIME.
|
||||||
|
This is needed to make queries with fuzzy dates work:
|
||||||
|
SELECT * FROM t1
|
||||||
|
WHERE
|
||||||
|
ts BETWEEN '0000-00-00' AND '2010-00-01 00:00:00';
|
||||||
|
*/
|
||||||
|
if (m_type_handler->type_handler_for_native_format() ==
|
||||||
|
&type_handler_timestamp2)
|
||||||
|
m_type_handler= &type_handler_datetime;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
@ -1540,7 +1657,19 @@ Type_handler_hybrid_field_type::aggregate_for_min_max(const Type_handler *h)
|
||||||
}
|
}
|
||||||
else if (a == TIME_RESULT || b == TIME_RESULT)
|
else if (a == TIME_RESULT || b == TIME_RESULT)
|
||||||
{
|
{
|
||||||
if ((a == TIME_RESULT) + (b == TIME_RESULT) == 1)
|
if ((m_type_handler->type_handler_for_native_format() ==
|
||||||
|
&type_handler_timestamp2) +
|
||||||
|
(h->type_handler_for_native_format() ==
|
||||||
|
&type_handler_timestamp2) == 1)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
Handle LEAST(TIMESTAMP, non-TIMESTAMP) as DATETIME,
|
||||||
|
to make sure fuzzy dates work in this context:
|
||||||
|
LEAST('2001-00-00', timestamp_field)
|
||||||
|
*/
|
||||||
|
m_type_handler= &type_handler_datetime2;
|
||||||
|
}
|
||||||
|
else if ((a == TIME_RESULT) + (b == TIME_RESULT) == 1)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
We're here if there's only one temporal data type:
|
We're here if there's only one temporal data type:
|
||||||
|
|
@ -3395,6 +3524,18 @@ int Type_handler_temporal_with_date::Item_save_in_field(Item *item,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int Type_handler_timestamp_common::Item_save_in_field(Item *item,
|
||||||
|
Field *field,
|
||||||
|
bool no_conversions)
|
||||||
|
const
|
||||||
|
{
|
||||||
|
Timestamp_or_zero_datetime_native_null tmp(field->table->in_use, item, true);
|
||||||
|
if (tmp.is_null())
|
||||||
|
return set_field_to_null_with_conversions(field, no_conversions);
|
||||||
|
return tmp.save_in_field(field, item->decimals);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
int Type_handler_string_result::Item_save_in_field(Item *item, Field *field,
|
int Type_handler_string_result::Item_save_in_field(Item *item, Field *field,
|
||||||
bool no_conversions) const
|
bool no_conversions) const
|
||||||
{
|
{
|
||||||
|
|
@ -3461,6 +3602,12 @@ Type_handler_temporal_with_date::set_comparator_func(Arg_comparator *cmp) const
|
||||||
return cmp->set_cmp_func_datetime();
|
return cmp->set_cmp_func_datetime();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
Type_handler_timestamp_common::set_comparator_func(Arg_comparator *cmp) const
|
||||||
|
{
|
||||||
|
return cmp->set_cmp_func_native();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************************/
|
/*************************************************************************/
|
||||||
|
|
||||||
|
|
@ -3596,7 +3743,7 @@ Type_handler_string_result::Item_get_cache(THD *thd, const Item *item) const
|
||||||
Item_cache *
|
Item_cache *
|
||||||
Type_handler_timestamp_common::Item_get_cache(THD *thd, const Item *item) const
|
Type_handler_timestamp_common::Item_get_cache(THD *thd, const Item *item) const
|
||||||
{
|
{
|
||||||
return new (thd->mem_root) Item_cache_datetime(thd);
|
return new (thd->mem_root) Item_cache_timestamp(thd);
|
||||||
}
|
}
|
||||||
|
|
||||||
Item_cache *
|
Item_cache *
|
||||||
|
|
@ -4763,6 +4910,12 @@ longlong Type_handler_time_common::
|
||||||
return func->val_int_cmp_time();
|
return func->val_int_cmp_time();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
longlong Type_handler_timestamp_common::
|
||||||
|
Item_func_between_val_int(Item_func_between *func) const
|
||||||
|
{
|
||||||
|
return func->val_int_cmp_native();
|
||||||
|
}
|
||||||
|
|
||||||
longlong Type_handler_int_result::
|
longlong Type_handler_int_result::
|
||||||
Item_func_between_val_int(Item_func_between *func) const
|
Item_func_between_val_int(Item_func_between *func) const
|
||||||
{
|
{
|
||||||
|
|
@ -4826,6 +4979,12 @@ cmp_item *Type_handler_temporal_with_date::make_cmp_item(THD *thd,
|
||||||
return new (thd->mem_root) cmp_item_datetime;
|
return new (thd->mem_root) cmp_item_datetime;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cmp_item *Type_handler_timestamp_common::make_cmp_item(THD *thd,
|
||||||
|
CHARSET_INFO *cs) const
|
||||||
|
{
|
||||||
|
return new (thd->mem_root) cmp_item_timestamp;
|
||||||
|
}
|
||||||
|
|
||||||
/***************************************************************************/
|
/***************************************************************************/
|
||||||
|
|
||||||
static int srtcmp_in(CHARSET_INFO *cs, const String *x,const String *y)
|
static int srtcmp_in(CHARSET_INFO *cs, const String *x,const String *y)
|
||||||
|
|
@ -4886,6 +5045,15 @@ Type_handler_temporal_with_date::make_in_vector(THD *thd,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
in_vector *
|
||||||
|
Type_handler_timestamp_common::make_in_vector(THD *thd,
|
||||||
|
const Item_func_in *func,
|
||||||
|
uint nargs) const
|
||||||
|
{
|
||||||
|
return new (thd->mem_root) in_timestamp(thd, nargs);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
in_vector *Type_handler_row::make_in_vector(THD *thd,
|
in_vector *Type_handler_row::make_in_vector(THD *thd,
|
||||||
const Item_func_in *func,
|
const Item_func_in *func,
|
||||||
uint nargs) const
|
uint nargs) const
|
||||||
|
|
@ -5004,7 +5172,9 @@ String *Type_handler_datetime_common::
|
||||||
String *Type_handler_timestamp_common::
|
String *Type_handler_timestamp_common::
|
||||||
Item_func_min_max_val_str(Item_func_min_max *func, String *str) const
|
Item_func_min_max_val_str(Item_func_min_max *func, String *str) const
|
||||||
{
|
{
|
||||||
return Datetime(func).to_string(str, func->decimals);
|
THD *thd= current_thd;
|
||||||
|
return Timestamp_or_zero_datetime_native_null(thd, func).
|
||||||
|
to_datetime(thd).to_string(str, func->decimals);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -5056,10 +5226,13 @@ double Type_handler_datetime_common::
|
||||||
return Datetime(current_thd, func).to_double();
|
return Datetime(current_thd, func).to_double();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
double Type_handler_timestamp_common::
|
double Type_handler_timestamp_common::
|
||||||
Item_func_min_max_val_real(Item_func_min_max *func) const
|
Item_func_min_max_val_real(Item_func_min_max *func) const
|
||||||
{
|
{
|
||||||
return Datetime(current_thd, func).to_double();
|
THD *thd= current_thd;
|
||||||
|
return Timestamp_or_zero_datetime_native_null(thd, func).
|
||||||
|
to_datetime(thd).to_double();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -5101,7 +5274,9 @@ longlong Type_handler_datetime_common::
|
||||||
longlong Type_handler_timestamp_common::
|
longlong Type_handler_timestamp_common::
|
||||||
Item_func_min_max_val_int(Item_func_min_max *func) const
|
Item_func_min_max_val_int(Item_func_min_max *func) const
|
||||||
{
|
{
|
||||||
return Datetime(current_thd, func).to_longlong();
|
THD *thd= current_thd;
|
||||||
|
return Timestamp_or_zero_datetime_native_null(thd, func).
|
||||||
|
to_datetime(thd).to_longlong();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -5156,7 +5331,9 @@ my_decimal *Type_handler_timestamp_common::
|
||||||
Item_func_min_max_val_decimal(Item_func_min_max *func,
|
Item_func_min_max_val_decimal(Item_func_min_max *func,
|
||||||
my_decimal *dec) const
|
my_decimal *dec) const
|
||||||
{
|
{
|
||||||
return Datetime(current_thd, func).to_decimal(dec);
|
THD *thd= current_thd;
|
||||||
|
return Timestamp_or_zero_datetime_native_null(thd, func).
|
||||||
|
to_datetime(thd).to_decimal(dec);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -5208,6 +5385,15 @@ bool Type_handler_time_common::
|
||||||
return func->get_time_native(thd, ltime);
|
return func->get_time_native(thd, ltime);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool Type_handler_timestamp_common::
|
||||||
|
Item_func_min_max_get_date(THD *thd, Item_func_min_max *func,
|
||||||
|
MYSQL_TIME *ltime, date_mode_t fuzzydate) const
|
||||||
|
{
|
||||||
|
return Timestamp_or_zero_datetime_native_null(thd, func).
|
||||||
|
to_datetime(thd).copy_to_mysql_time(ltime);
|
||||||
|
}
|
||||||
|
|
||||||
/***************************************************************************/
|
/***************************************************************************/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -6480,6 +6666,18 @@ bool Type_handler::
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool Type_handler::Item_send_timestamp(Item *item,
|
||||||
|
Protocol *protocol,
|
||||||
|
st_value *buf) const
|
||||||
|
{
|
||||||
|
Timestamp_or_zero_datetime_native_null native(protocol->thd, item);
|
||||||
|
if (native.is_null())
|
||||||
|
return protocol->store_null();
|
||||||
|
native.to_TIME(protocol->thd, &buf->value.m_time);
|
||||||
|
return protocol->store(&buf->value.m_time, item->decimals);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
bool Type_handler::
|
bool Type_handler::
|
||||||
Item_send_datetime(Item *item, Protocol *protocol, st_value *buf) const
|
Item_send_datetime(Item *item, Protocol *protocol, st_value *buf) const
|
||||||
{
|
{
|
||||||
|
|
@ -7628,6 +7826,16 @@ bool Type_handler_temporal_with_date::Item_eq_value(THD *thd,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool Type_handler_timestamp_common::Item_eq_value(THD *thd,
|
||||||
|
const Type_cmp_attributes *attr,
|
||||||
|
Item *a, Item *b) const
|
||||||
|
{
|
||||||
|
Timestamp_or_zero_datetime_native_null na(thd, a, true);
|
||||||
|
Timestamp_or_zero_datetime_native_null nb(thd, b, true);
|
||||||
|
return !na.is_null() && !nb.is_null() && !cmp_native(na, nb);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
bool Type_handler_string_result::Item_eq_value(THD *thd,
|
bool Type_handler_string_result::Item_eq_value(THD *thd,
|
||||||
const Type_cmp_attributes *attr,
|
const Type_cmp_attributes *attr,
|
||||||
Item *a, Item *b) const
|
Item *a, Item *b) const
|
||||||
|
|
@ -7845,3 +8053,113 @@ Type_handler_time_common::create_literal_item(THD *thd,
|
||||||
literal_warn(thd, item, str, length, cs, &st, "TIME", send_error);
|
literal_warn(thd, item, str, length, cs, &st, "TIME", send_error);
|
||||||
return item;
|
return item;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool Type_handler_timestamp_common::TIME_to_native(THD *thd,
|
||||||
|
const MYSQL_TIME *ltime,
|
||||||
|
Native *to,
|
||||||
|
uint decimals) const
|
||||||
|
{
|
||||||
|
uint error_code;
|
||||||
|
Timestamp_or_zero_datetime tm(thd, ltime, &error_code);
|
||||||
|
if (error_code)
|
||||||
|
return true;
|
||||||
|
tm.trunc(decimals);
|
||||||
|
return tm.to_native(to, decimals);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool
|
||||||
|
Type_handler_timestamp_common::Item_val_native_with_conversion(THD *thd,
|
||||||
|
Item *item,
|
||||||
|
Native *to) const
|
||||||
|
{
|
||||||
|
MYSQL_TIME ltime;
|
||||||
|
if (item->type_handler()->type_handler_for_native_format() ==
|
||||||
|
&type_handler_timestamp2)
|
||||||
|
return item->val_native(thd, to);
|
||||||
|
return
|
||||||
|
item->get_date(thd, <ime, Datetime::Options(TIME_NO_ZERO_IN_DATE, thd)) ||
|
||||||
|
TIME_to_native(thd, <ime, to, item->datetime_precision(thd));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool
|
||||||
|
Type_handler_timestamp_common::Item_val_native_with_conversion_result(THD *thd,
|
||||||
|
Item *item,
|
||||||
|
Native *to)
|
||||||
|
const
|
||||||
|
{
|
||||||
|
MYSQL_TIME ltime;
|
||||||
|
if (item->type_handler()->type_handler_for_native_format() ==
|
||||||
|
&type_handler_timestamp2)
|
||||||
|
return item->val_native_result(thd, to);
|
||||||
|
return
|
||||||
|
item->get_date_result(thd, <ime,
|
||||||
|
Datetime::Options(TIME_NO_ZERO_IN_DATE, thd)) ||
|
||||||
|
TIME_to_native(thd, <ime, to, item->datetime_precision(thd));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int Type_handler_timestamp_common::cmp_native(const Native &a,
|
||||||
|
const Native &b) const
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
Optimize a simple case:
|
||||||
|
Either both timeatamp values have the same fractional precision,
|
||||||
|
or both values are zero datetime '0000-00-00 00:00:00.000000',
|
||||||
|
*/
|
||||||
|
if (a.length() == b.length())
|
||||||
|
return memcmp(a.ptr(), b.ptr(), a.length());
|
||||||
|
return Timestamp_or_zero_datetime(a).cmp(Timestamp_or_zero_datetime(b));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Timestamp_or_zero_datetime_native_null::
|
||||||
|
Timestamp_or_zero_datetime_native_null(THD *thd, Item *item, bool conv)
|
||||||
|
:Null_flag(false)
|
||||||
|
{
|
||||||
|
DBUG_ASSERT(item->type_handler()->type_handler_for_native_format() ==
|
||||||
|
&type_handler_timestamp2 || conv);
|
||||||
|
if (conv ?
|
||||||
|
type_handler_timestamp2.Item_val_native_with_conversion(thd, item, this) :
|
||||||
|
item->val_native(thd, this))
|
||||||
|
Null_flag::operator=(true);
|
||||||
|
// If no conversion, then is_null() should be equal to item->null_value
|
||||||
|
DBUG_ASSERT(is_null() == item->null_value || conv);
|
||||||
|
/*
|
||||||
|
is_null() can be true together with item->null_value==false, which means
|
||||||
|
a non-NULL item was evaluated, but then the conversion to TIMESTAMP failed.
|
||||||
|
But is_null() can never be false if item->null_value==true.
|
||||||
|
*/
|
||||||
|
DBUG_ASSERT(is_null() >= item->null_value);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool
|
||||||
|
Type_handler::Item_param_val_native(THD *thd,
|
||||||
|
Item_param *item,
|
||||||
|
Native *to) const
|
||||||
|
{
|
||||||
|
DBUG_ASSERT(0); // TODO-TYPE: MDEV-14271
|
||||||
|
return item->null_value= true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool
|
||||||
|
Type_handler_timestamp_common::Item_param_val_native(THD *thd,
|
||||||
|
Item_param *item,
|
||||||
|
Native *to) const
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
The below code may not run well in corner cases.
|
||||||
|
This will be fixed under terms of MDEV-14271.
|
||||||
|
Item_param should:
|
||||||
|
- either remember @@time_zone at bind time
|
||||||
|
- or store TIMESTAMP in my_time_t format, rather than in MYSQL_TIME format.
|
||||||
|
*/
|
||||||
|
MYSQL_TIME ltime;
|
||||||
|
return
|
||||||
|
item->get_date(thd, <ime, Datetime::Options(TIME_NO_ZERO_IN_DATE, thd)) ||
|
||||||
|
TIME_to_native(thd, <ime, to, item->datetime_precision(thd));
|
||||||
|
}
|
||||||
|
|
|
||||||
199
sql/sql_type.h
199
sql/sql_type.h
|
|
@ -25,6 +25,7 @@
|
||||||
#include "sql_array.h"
|
#include "sql_array.h"
|
||||||
#include "sql_const.h"
|
#include "sql_const.h"
|
||||||
#include "sql_time.h"
|
#include "sql_time.h"
|
||||||
|
#include "compat56.h"
|
||||||
|
|
||||||
class Field;
|
class Field;
|
||||||
class Column_definition;
|
class Column_definition;
|
||||||
|
|
@ -90,6 +91,25 @@ enum scalar_comparison_op
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class Native: public Binary_string
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Native(char *str, size_t len)
|
||||||
|
:Binary_string(str, len)
|
||||||
|
{ }
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
template<size_t buff_sz>
|
||||||
|
class NativeBuffer: public Native
|
||||||
|
{
|
||||||
|
char buff[buff_sz];
|
||||||
|
public:
|
||||||
|
NativeBuffer() : Native(buff, buff_sz) { length(0); }
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class Dec_ptr
|
class Dec_ptr
|
||||||
{
|
{
|
||||||
protected:
|
protected:
|
||||||
|
|
@ -1925,7 +1945,16 @@ public:
|
||||||
{ }
|
{ }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static Datetime zero()
|
||||||
|
{
|
||||||
|
int warn;
|
||||||
|
static Longlong_hybrid nr(0, false);
|
||||||
|
return Datetime(&warn, nr, date_mode_t(0));
|
||||||
|
}
|
||||||
public:
|
public:
|
||||||
|
Datetime() // NULL value
|
||||||
|
:Temporal_with_date()
|
||||||
|
{ }
|
||||||
Datetime(THD *thd, Item *item, date_mode_t fuzzydate)
|
Datetime(THD *thd, Item *item, date_mode_t fuzzydate)
|
||||||
:Temporal_with_date(thd, item, fuzzydate)
|
:Temporal_with_date(thd, item, fuzzydate)
|
||||||
{
|
{
|
||||||
|
|
@ -2204,6 +2233,7 @@ public:
|
||||||
|
|
||||||
class Timestamp: protected Timeval
|
class Timestamp: protected Timeval
|
||||||
{
|
{
|
||||||
|
static uint binary_length_to_precision(uint length);
|
||||||
protected:
|
protected:
|
||||||
void round_or_set_max(uint dec, int *warn);
|
void round_or_set_max(uint dec, int *warn);
|
||||||
bool add_nanoseconds_usec(uint nanoseconds)
|
bool add_nanoseconds_usec(uint nanoseconds)
|
||||||
|
|
@ -2237,7 +2267,18 @@ public:
|
||||||
explicit Timestamp(const timeval &tv)
|
explicit Timestamp(const timeval &tv)
|
||||||
:Timeval(tv)
|
:Timeval(tv)
|
||||||
{ }
|
{ }
|
||||||
|
explicit Timestamp(const Native &native);
|
||||||
|
Timestamp(THD *thd, const MYSQL_TIME *ltime, uint *error_code);
|
||||||
const struct timeval &tv() const { return *this; }
|
const struct timeval &tv() const { return *this; }
|
||||||
|
int cmp(const Timestamp &other) const
|
||||||
|
{
|
||||||
|
return tv_sec < other.tv_sec ? -1 :
|
||||||
|
tv_sec > other.tv_sec ? +1 :
|
||||||
|
tv_usec < other.tv_usec ? -1 :
|
||||||
|
tv_usec > other.tv_usec ? +1 : 0;
|
||||||
|
}
|
||||||
|
bool to_TIME(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate) const;
|
||||||
|
bool to_native(Native *to, uint decimals) const;
|
||||||
long fraction_remainder(uint dec) const
|
long fraction_remainder(uint dec) const
|
||||||
{
|
{
|
||||||
return my_time_fraction_remainder(tv_usec, dec);
|
return my_time_fraction_remainder(tv_usec, dec);
|
||||||
|
|
@ -2273,6 +2314,117 @@ public:
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
A helper class to store MariaDB TIMESTAMP values, which can be:
|
||||||
|
- real TIMESTAMP (seconds and microseconds since epoch), or
|
||||||
|
- zero datetime '0000-00-00 00:00:00.000000'
|
||||||
|
*/
|
||||||
|
class Timestamp_or_zero_datetime: public Timestamp
|
||||||
|
{
|
||||||
|
bool m_is_zero_datetime;
|
||||||
|
public:
|
||||||
|
Timestamp_or_zero_datetime()
|
||||||
|
:Timestamp(0,0), m_is_zero_datetime(true)
|
||||||
|
{ }
|
||||||
|
Timestamp_or_zero_datetime(const Native &native)
|
||||||
|
: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(tm), m_is_zero_datetime(is_zero_datetime)
|
||||||
|
{ }
|
||||||
|
Timestamp_or_zero_datetime(THD *thd, const MYSQL_TIME *ltime, uint *err_code);
|
||||||
|
Datetime to_datetime(THD *thd) const
|
||||||
|
{
|
||||||
|
return Datetime(thd, *this);
|
||||||
|
}
|
||||||
|
bool is_zero_datetime() const { return m_is_zero_datetime; }
|
||||||
|
const struct timeval &tv() const
|
||||||
|
{
|
||||||
|
DBUG_ASSERT(!is_zero_datetime());
|
||||||
|
return Timestamp::tv();
|
||||||
|
}
|
||||||
|
void trunc(uint decimals)
|
||||||
|
{
|
||||||
|
if (!is_zero_datetime())
|
||||||
|
Timestamp::trunc(decimals);
|
||||||
|
}
|
||||||
|
int cmp(const Timestamp_or_zero_datetime &other) const
|
||||||
|
{
|
||||||
|
if (is_zero_datetime())
|
||||||
|
return other.is_zero_datetime() ? 0 : -1;
|
||||||
|
if (other.is_zero_datetime())
|
||||||
|
return 1;
|
||||||
|
return Timestamp::cmp(other);
|
||||||
|
}
|
||||||
|
bool to_TIME(THD *thd, MYSQL_TIME *to, date_mode_t fuzzydate) const;
|
||||||
|
/*
|
||||||
|
Convert to native format:
|
||||||
|
- Real timestamps are encoded in the same way how Field_timestamp2 stores
|
||||||
|
values (big endian seconds followed by big endian microseconds)
|
||||||
|
- Zero datetime '0000-00-00 00:00:00.000000' is encoded as empty string.
|
||||||
|
Two native values are binary comparable.
|
||||||
|
*/
|
||||||
|
bool to_native(Native *to, uint decimals) const;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
A helper class to store non-null MariaDB TIMESTAMP values in
|
||||||
|
the native binary encoded representation.
|
||||||
|
*/
|
||||||
|
class Timestamp_or_zero_datetime_native:
|
||||||
|
public NativeBuffer<STRING_BUFFER_TIMESTAMP_BINARY_SIZE>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Timestamp_or_zero_datetime_native() { }
|
||||||
|
Timestamp_or_zero_datetime_native(const Timestamp_or_zero_datetime &ts,
|
||||||
|
uint decimals)
|
||||||
|
{
|
||||||
|
if (ts.to_native(this, decimals))
|
||||||
|
length(0); // safety
|
||||||
|
}
|
||||||
|
int save_in_field(Field *field, uint decimals) const;
|
||||||
|
bool is_zero_datetime() const
|
||||||
|
{
|
||||||
|
return length() == 0;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
A helper class to store nullable MariaDB TIMESTAMP values in
|
||||||
|
the native binary encoded representation.
|
||||||
|
*/
|
||||||
|
class Timestamp_or_zero_datetime_native_null: public Timestamp_or_zero_datetime_native,
|
||||||
|
public Null_flag
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
// With optional data type conversion
|
||||||
|
Timestamp_or_zero_datetime_native_null(THD *thd, Item *item, bool conv);
|
||||||
|
// Without data type conversion: item is known to be of the TIMESTAMP type
|
||||||
|
Timestamp_or_zero_datetime_native_null(THD *thd, Item *item)
|
||||||
|
:Timestamp_or_zero_datetime_native_null(thd, item, false)
|
||||||
|
{ }
|
||||||
|
Datetime to_datetime(THD *thd) const
|
||||||
|
{
|
||||||
|
return is_null() ? Datetime() :
|
||||||
|
Datetime(thd, Timestamp_or_zero_datetime(*this).tv());
|
||||||
|
}
|
||||||
|
void to_TIME(THD *thd, MYSQL_TIME *to)
|
||||||
|
{
|
||||||
|
DBUG_ASSERT(!is_null());
|
||||||
|
Datetime::Options opt(TIME_CONV_NONE, TIME_FRAC_NONE);
|
||||||
|
Timestamp_or_zero_datetime(*this).to_TIME(thd, to, opt);
|
||||||
|
}
|
||||||
|
bool is_zero_datetime() const
|
||||||
|
{
|
||||||
|
DBUG_ASSERT(!is_null());
|
||||||
|
return Timestamp_or_zero_datetime_native::is_zero_datetime();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Flags for collation aggregation modes, used in TDCollation::agg():
|
Flags for collation aggregation modes, used in TDCollation::agg():
|
||||||
|
|
||||||
|
|
@ -2905,6 +3057,7 @@ protected:
|
||||||
bool Item_send_double(Item *item, Protocol *protocol, st_value *buf) const;
|
bool Item_send_double(Item *item, Protocol *protocol, st_value *buf) const;
|
||||||
bool Item_send_time(Item *item, Protocol *protocol, st_value *buf) const;
|
bool Item_send_time(Item *item, Protocol *protocol, st_value *buf) const;
|
||||||
bool Item_send_date(Item *item, Protocol *protocol, st_value *buf) const;
|
bool Item_send_date(Item *item, Protocol *protocol, st_value *buf) const;
|
||||||
|
bool Item_send_timestamp(Item *item, Protocol *protocol, st_value *buf) const;
|
||||||
bool Item_send_datetime(Item *item, Protocol *protocol, st_value *buf) const;
|
bool Item_send_datetime(Item *item, Protocol *protocol, st_value *buf) const;
|
||||||
bool Column_definition_prepare_stage2_legacy(Column_definition *c,
|
bool Column_definition_prepare_stage2_legacy(Column_definition *c,
|
||||||
enum_field_types type)
|
enum_field_types type)
|
||||||
|
|
@ -3026,6 +3179,10 @@ public:
|
||||||
*/
|
*/
|
||||||
virtual bool is_param_long_data_type() const { return false; }
|
virtual bool is_param_long_data_type() const { return false; }
|
||||||
virtual const Type_handler *type_handler_for_comparison() const= 0;
|
virtual const Type_handler *type_handler_for_comparison() const= 0;
|
||||||
|
virtual const Type_handler *type_handler_for_native_format() const
|
||||||
|
{
|
||||||
|
return this;
|
||||||
|
}
|
||||||
virtual const Type_handler *type_handler_for_item_field() const
|
virtual const Type_handler *type_handler_for_item_field() const
|
||||||
{
|
{
|
||||||
return this;
|
return this;
|
||||||
|
|
@ -3208,6 +3365,9 @@ public:
|
||||||
Item_param *param,
|
Item_param *param,
|
||||||
const Type_all_attributes *attr,
|
const Type_all_attributes *attr,
|
||||||
const st_value *value) const= 0;
|
const st_value *value) const= 0;
|
||||||
|
virtual bool Item_param_val_native(THD *thd,
|
||||||
|
Item_param *item,
|
||||||
|
Native *to) const;
|
||||||
virtual bool Item_send(Item *item, Protocol *p, st_value *buf) const= 0;
|
virtual bool Item_send(Item *item, Protocol *p, st_value *buf) const= 0;
|
||||||
virtual int Item_save_in_field(Item *item, Field *field,
|
virtual int Item_save_in_field(Item *item, Field *field,
|
||||||
bool no_conversions) const= 0;
|
bool no_conversions) const= 0;
|
||||||
|
|
@ -3310,6 +3470,11 @@ public:
|
||||||
DBUG_ASSERT(0);
|
DBUG_ASSERT(0);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
virtual int cmp_native(const Native &a, const Native &b) const
|
||||||
|
{
|
||||||
|
DBUG_ASSERT(0);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
virtual bool set_comparator_func(Arg_comparator *cmp) const= 0;
|
virtual bool set_comparator_func(Arg_comparator *cmp) const= 0;
|
||||||
virtual bool Item_const_eq(const Item_const *a, const Item_const *b,
|
virtual bool Item_const_eq(const Item_const *a, const Item_const *b,
|
||||||
bool binary_cmp) const
|
bool binary_cmp) const
|
||||||
|
|
@ -3334,6 +3499,17 @@ public:
|
||||||
virtual
|
virtual
|
||||||
bool Item_sum_variance_fix_length_and_dec(Item_sum_variance *) const= 0;
|
bool Item_sum_variance_fix_length_and_dec(Item_sum_variance *) const= 0;
|
||||||
|
|
||||||
|
virtual bool Item_val_native_with_conversion(THD *thd, Item *item,
|
||||||
|
Native *to) const
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
virtual bool Item_val_native_with_conversion_result(THD *thd, Item *item,
|
||||||
|
Native *to) const
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
virtual bool Item_val_bool(Item *item) const= 0;
|
virtual bool Item_val_bool(Item *item) const= 0;
|
||||||
virtual void Item_get_date(THD *thd, Item *item,
|
virtual void Item_get_date(THD *thd, Item *item,
|
||||||
Temporal::Warn *buff, MYSQL_TIME *ltime,
|
Temporal::Warn *buff, MYSQL_TIME *ltime,
|
||||||
|
|
@ -5187,10 +5363,13 @@ public:
|
||||||
class Type_handler_timestamp_common: public Type_handler_temporal_with_date
|
class Type_handler_timestamp_common: public Type_handler_temporal_with_date
|
||||||
{
|
{
|
||||||
static const Name m_name_timestamp;
|
static const Name m_name_timestamp;
|
||||||
|
protected:
|
||||||
|
bool TIME_to_native(THD *, const MYSQL_TIME *from, Native *to, uint dec) const;
|
||||||
public:
|
public:
|
||||||
virtual ~Type_handler_timestamp_common() {}
|
virtual ~Type_handler_timestamp_common() {}
|
||||||
const Name name() const { return m_name_timestamp; }
|
const Name name() const { return m_name_timestamp; }
|
||||||
const Type_handler *type_handler_for_comparison() const;
|
const Type_handler *type_handler_for_comparison() const;
|
||||||
|
const Type_handler *type_handler_for_native_format() const;
|
||||||
enum_field_types field_type() const { return MYSQL_TYPE_TIMESTAMP; }
|
enum_field_types field_type() const { return MYSQL_TYPE_TIMESTAMP; }
|
||||||
enum_mysql_timestamp_type mysql_timestamp_type() const
|
enum_mysql_timestamp_type mysql_timestamp_type() const
|
||||||
{
|
{
|
||||||
|
|
@ -5201,6 +5380,20 @@ public:
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
void Column_definition_implicit_upgrade(Column_definition *c) const;
|
void Column_definition_implicit_upgrade(Column_definition *c) const;
|
||||||
|
bool Item_eq_value(THD *thd, const Type_cmp_attributes *attr,
|
||||||
|
Item *a, Item *b) const;
|
||||||
|
bool Item_val_native_with_conversion(THD *thd, Item *, Native *to) const;
|
||||||
|
bool Item_val_native_with_conversion_result(THD *thd, Item *, Native *to) const;
|
||||||
|
bool Item_param_val_native(THD *thd, Item_param *item, Native *to) const;
|
||||||
|
int cmp_native(const Native &a, const Native &b) const;
|
||||||
|
longlong Item_func_between_val_int(Item_func_between *func) const;
|
||||||
|
cmp_item *make_cmp_item(THD *thd, CHARSET_INFO *cs) const;
|
||||||
|
in_vector *make_in_vector(THD *thd, const Item_func_in *f, uint nargs) const;
|
||||||
|
void make_sort_key(uchar *to, Item *item, const SORT_FIELD_ATTR *sort_field,
|
||||||
|
Sort_param *param) const;
|
||||||
|
void sortlength(THD *thd,
|
||||||
|
const Type_std_attributes *item,
|
||||||
|
SORT_FIELD_ATTR *attr) const;
|
||||||
bool Column_definition_fix_attributes(Column_definition *c) const;
|
bool Column_definition_fix_attributes(Column_definition *c) const;
|
||||||
uint Item_decimal_scale(const Item *item) const
|
uint Item_decimal_scale(const Item *item) const
|
||||||
{
|
{
|
||||||
|
|
@ -5213,8 +5406,9 @@ public:
|
||||||
}
|
}
|
||||||
bool Item_send(Item *item, Protocol *protocol, st_value *buf) const
|
bool Item_send(Item *item, Protocol *protocol, st_value *buf) const
|
||||||
{
|
{
|
||||||
return Item_send_datetime(item, protocol, buf);
|
return Item_send_timestamp(item, protocol, buf);
|
||||||
}
|
}
|
||||||
|
int Item_save_in_field(Item *item, Field *field, bool no_conversions) const;
|
||||||
String *print_item_value(THD *thd, Item *item, String *str) const;
|
String *print_item_value(THD *thd, Item *item, String *str) const;
|
||||||
Item_cache *Item_get_cache(THD *thd, const Item *item) const;
|
Item_cache *Item_get_cache(THD *thd, const Item *item) const;
|
||||||
String *Item_func_min_max_val_str(Item_func_min_max *, String *) const;
|
String *Item_func_min_max_val_str(Item_func_min_max *, String *) const;
|
||||||
|
|
@ -5222,6 +5416,7 @@ public:
|
||||||
longlong Item_func_min_max_val_int(Item_func_min_max *) const;
|
longlong Item_func_min_max_val_int(Item_func_min_max *) const;
|
||||||
my_decimal *Item_func_min_max_val_decimal(Item_func_min_max *,
|
my_decimal *Item_func_min_max_val_decimal(Item_func_min_max *,
|
||||||
my_decimal *) const;
|
my_decimal *) const;
|
||||||
|
bool set_comparator_func(Arg_comparator *cmp) const;
|
||||||
bool Item_hybrid_func_fix_attributes(THD *thd,
|
bool Item_hybrid_func_fix_attributes(THD *thd,
|
||||||
const char *name,
|
const char *name,
|
||||||
Type_handler_hybrid_field_type *,
|
Type_handler_hybrid_field_type *,
|
||||||
|
|
@ -5229,6 +5424,8 @@ public:
|
||||||
Item **items, uint nitems) const;
|
Item **items, uint nitems) const;
|
||||||
void Item_param_set_param_func(Item_param *param,
|
void Item_param_set_param_func(Item_param *param,
|
||||||
uchar **pos, ulong len) const;
|
uchar **pos, ulong len) const;
|
||||||
|
bool Item_func_min_max_get_date(THD *thd, Item_func_min_max*,
|
||||||
|
MYSQL_TIME *, date_mode_t fuzzydate) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -847,6 +847,8 @@ public:
|
||||||
|
|
||||||
class Timeval: public timeval
|
class Timeval: public timeval
|
||||||
{
|
{
|
||||||
|
protected:
|
||||||
|
Timeval() { }
|
||||||
public:
|
public:
|
||||||
Timeval(my_time_t sec, ulong usec)
|
Timeval(my_time_t sec, ulong usec)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue