mirror of
https://github.com/MariaDB/server.git
synced 2025-01-16 03:52:35 +01: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
|
||||
drop table t1, t2;
|
||||
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;
|
||||
drop table t1, t2;
|
||||
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 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
|
||||
#
|
||||
|
|
|
@ -324,6 +324,173 @@ SELECT CONVERT_TZ(TIME('2010-01-01 00:00:00'),'+00:00','+7:5');
|
|||
SET old_mode=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 # End of 10.4 tests
|
||||
--echo #
|
||||
|
|
|
@ -1068,5 +1068,55 @@ DROP PROCEDURE p1;
|
|||
SET timestamp=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
|
||||
#
|
||||
|
|
|
@ -660,6 +660,56 @@ DROP PROCEDURE p1;
|
|||
SET timestamp=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 # End of 10.4 tests
|
||||
--echo #
|
||||
|
|
|
@ -162,3 +162,30 @@ SELECT * FROM t1,t2 WHERE COALESCE(t1.a)=t2.a;
|
|||
a a
|
||||
20010101235959.9999999 2001-01-02 00:00:00
|
||||
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 COALESCE(t1.a)=t2.a;
|
||||
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 **/
|
||||
|
||||
/*
|
||||
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_FRAC_PART(x) ((x) % (1LL << 24))
|
||||
#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,
|
||||
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 &&
|
||||
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(
|
||||
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 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);
|
||||
}
|
||||
|
||||
|
||||
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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
|
|
19
sql/field.h
19
sql/field.h
|
@ -790,6 +790,15 @@ public:
|
|||
return store_timestamp_dec(Timeval(timestamp, sec_part),
|
||||
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)
|
||||
{ return store_time_dec(ltime, TIME_SECOND_PART_DIGITS); }
|
||||
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.
|
||||
*/
|
||||
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);
|
||||
/*
|
||||
Return the field value as a LEX_CSTRING, without padding to full length
|
||||
|
@ -2735,6 +2749,7 @@ protected:
|
|||
{
|
||||
store_TIMEVAL(ts.tv());
|
||||
}
|
||||
int zero_time_stored_return_code_with_warning();
|
||||
public:
|
||||
Field_timestamp(uchar *ptr_arg, uint32 len_arg,
|
||||
uchar *null_ptr_arg, uchar null_bit_arg,
|
||||
|
@ -2785,6 +2800,8 @@ public:
|
|||
store_TIMESTAMP(Timestamp(ts, sec_part).round(decimals(), mode, &warn));
|
||||
}
|
||||
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,
|
||||
uint max_length __attribute__((unused)))
|
||||
{
|
||||
|
@ -2864,6 +2881,7 @@ public:
|
|||
{
|
||||
DBUG_ASSERT(dec);
|
||||
}
|
||||
bool val_native(Native *to);
|
||||
my_time_t get_timestamp(const uchar *pos, ulong *sec_part) const;
|
||||
int cmp(const uchar *,const uchar *);
|
||||
uint32 pack_length() const { return 4 + sec_part_bytes(dec); }
|
||||
|
@ -2914,6 +2932,7 @@ public:
|
|||
{
|
||||
return get_timestamp(ptr, sec_part);
|
||||
}
|
||||
bool val_native(Native *to);
|
||||
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
|
||||
Type_handler::make_sort_key_longlong(uchar *to,
|
||||
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
|
||||
Type_handler_int_result::sortlength(THD *thd,
|
||||
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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
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 *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()
|
||||
{
|
||||
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
|
||||
*/
|
||||
|
@ -9794,6 +9860,62 @@ Item *Item_cache_time::make_literal(THD *thd)
|
|||
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()
|
||||
{
|
||||
if (!example)
|
||||
|
|
182
sql/item.h
182
sql/item.h
|
@ -855,6 +855,25 @@ protected:
|
|||
res= NULL;
|
||||
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)
|
||||
{
|
||||
DBUG_ASSERT(is_fixed());
|
||||
|
@ -1276,6 +1295,60 @@ public:
|
|||
*/
|
||||
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.
|
||||
|
||||
|
@ -2689,6 +2762,7 @@ public:
|
|||
String *val_str(String *sp);
|
||||
my_decimal *val_decimal(my_decimal *decimal_value);
|
||||
bool get_date(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate);
|
||||
bool val_native(THD *thd, Native *to);
|
||||
bool is_null();
|
||||
|
||||
public:
|
||||
|
@ -3229,6 +3303,8 @@ public:
|
|||
void save_result(Field *to);
|
||||
double val_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);
|
||||
my_decimal *val_decimal_result(my_decimal *);
|
||||
bool val_bool_result();
|
||||
|
@ -3815,6 +3891,11 @@ public:
|
|||
return can_return_value() ? value.val_str(str, this) : NULL;
|
||||
}
|
||||
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);
|
||||
|
||||
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
|
||||
{
|
||||
protected:
|
||||
|
@ -5062,11 +5191,13 @@ public:
|
|||
my_decimal *val_decimal(my_decimal *);
|
||||
bool val_bool();
|
||||
String *val_str(String* tmp);
|
||||
bool val_native(THD *thd, Native *to);
|
||||
bool is_null();
|
||||
bool get_date(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate);
|
||||
double val_result();
|
||||
longlong val_int_result();
|
||||
String *str_result(String* tmp);
|
||||
bool val_native_result(THD *thd, Native *to);
|
||||
my_decimal *val_decimal_result(my_decimal *);
|
||||
bool val_bool_result();
|
||||
bool is_null_result();
|
||||
|
@ -5271,6 +5402,7 @@ public:
|
|||
double val_real();
|
||||
longlong val_int();
|
||||
String *val_str(String* tmp);
|
||||
bool val_native(THD *thd, Native *to);
|
||||
my_decimal *val_decimal(my_decimal *);
|
||||
bool val_bool();
|
||||
bool is_null();
|
||||
|
@ -5367,6 +5499,7 @@ public:
|
|||
double val_real();
|
||||
longlong val_int();
|
||||
String *val_str(String* tmp);
|
||||
bool val_native(THD *thd, Native *to);
|
||||
my_decimal *val_decimal(my_decimal *);
|
||||
bool val_bool();
|
||||
bool is_null();
|
||||
|
@ -5563,6 +5696,12 @@ public:
|
|||
else
|
||||
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)
|
||||
{
|
||||
if (check_null_ref())
|
||||
|
@ -5708,6 +5847,7 @@ public:
|
|||
my_decimal *val_decimal(my_decimal *);
|
||||
bool val_bool();
|
||||
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);
|
||||
table_map used_tables() const;
|
||||
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
|
||||
{
|
||||
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()
|
||||
{
|
||||
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()
|
||||
{
|
||||
/*
|
||||
|
@ -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()
|
||||
{
|
||||
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)
|
||||
{
|
||||
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
|
||||
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 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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
((SELECT_LEX*) arg)->cond_count++;
|
||||
|
|
|
@ -68,6 +68,7 @@ class Arg_comparator: public Sql_alloc
|
|||
if (val1 == val2) return 0;
|
||||
return 1;
|
||||
}
|
||||
NativeBuffer<STRING_BUFFER_USUAL_SIZE> m_native1, m_native2;
|
||||
public:
|
||||
/* Allow owner function to use string buffers. */
|
||||
String value1, value2;
|
||||
|
@ -89,6 +90,7 @@ public:
|
|||
bool set_cmp_func_string();
|
||||
bool set_cmp_func_time();
|
||||
bool set_cmp_func_datetime();
|
||||
bool set_cmp_func_native();
|
||||
bool set_cmp_func_int();
|
||||
bool set_cmp_func_real();
|
||||
bool set_cmp_func_decimal();
|
||||
|
@ -121,6 +123,8 @@ public:
|
|||
int compare_e_datetime();
|
||||
int compare_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();
|
||||
int compare_str_json();
|
||||
|
@ -935,6 +939,7 @@ public:
|
|||
longlong val_int_cmp_string();
|
||||
longlong val_int_cmp_datetime();
|
||||
longlong val_int_cmp_time();
|
||||
longlong val_int_cmp_native();
|
||||
longlong val_int_cmp_int();
|
||||
longlong val_int_cmp_real();
|
||||
longlong val_int_cmp_decimal();
|
||||
|
@ -1013,6 +1018,7 @@ public:
|
|||
my_decimal *decimal_op(my_decimal *);
|
||||
bool date_op(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate);
|
||||
bool time_op(THD *thd, MYSQL_TIME *ltime);
|
||||
bool native_op(THD *thd, Native *to);
|
||||
bool fix_length_and_dec()
|
||||
{
|
||||
if (aggregate_for_result(func_name(), args, arg_count, true))
|
||||
|
@ -1092,6 +1098,7 @@ public:
|
|||
my_decimal *decimal_op(my_decimal *);
|
||||
bool date_op(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate);
|
||||
bool time_op(THD *thd, MYSQL_TIME *ltime);
|
||||
bool native_op(THD *thd, Native *to);
|
||||
bool fix_length_and_dec()
|
||||
{
|
||||
if (Item_func_case_abbreviation2::fix_length_and_dec2(args))
|
||||
|
@ -1150,6 +1157,11 @@ public:
|
|||
{
|
||||
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();
|
||||
String *str_op(String *str);
|
||||
my_decimal *decimal_op(my_decimal *);
|
||||
bool native_op(THD *thd, Native *to);
|
||||
bool fix_length_and_dec();
|
||||
bool walk(Item_processor processor, bool walk_subquery, void *arg);
|
||||
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.
|
||||
*/
|
||||
|
@ -1666,6 +1692,20 @@ public:
|
|||
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
|
||||
{
|
||||
double value;
|
||||
|
@ -2132,6 +2172,7 @@ public:
|
|||
my_decimal *decimal_op(my_decimal *);
|
||||
bool date_op(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate);
|
||||
bool time_op(THD *thd, MYSQL_TIME *ltime);
|
||||
bool native_op(THD *thd, Native *to);
|
||||
bool fix_fields(THD *thd, Item **ref);
|
||||
table_map not_null_tables() const { return 0; }
|
||||
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()
|
||||
{
|
||||
DBUG_ASSERT(fixed == 1);
|
||||
|
@ -6453,6 +6475,14 @@ String *Item_func_last_value::val_str(String *str)
|
|||
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 tmp;
|
||||
|
|
|
@ -768,6 +768,12 @@ public:
|
|||
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
|
||||
result type is INT.
|
||||
|
@ -838,6 +844,7 @@ public:
|
|||
*/
|
||||
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);
|
||||
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()->
|
||||
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)
|
||||
{
|
||||
/*
|
||||
|
@ -1834,6 +1847,8 @@ public:
|
|||
double val_real() { return val_real_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); }
|
||||
bool val_native(THD *thd, Native *to)
|
||||
{ return val_native_from_item(thd, args[0], to); }
|
||||
my_decimal *val_decimal(my_decimal *dec)
|
||||
{ return val_decimal_from_item(args[0], dec); }
|
||||
bool get_date(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate)
|
||||
|
@ -3153,6 +3168,13 @@ public:
|
|||
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()
|
||||
{
|
||||
execute();
|
||||
|
@ -3282,6 +3304,7 @@ public:
|
|||
String *val_str(String *);
|
||||
my_decimal *val_decimal(my_decimal *);
|
||||
bool get_date(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate);
|
||||
bool val_native(THD *thd, Native *);
|
||||
bool fix_length_and_dec();
|
||||
const char *func_name() const { return "last_value"; }
|
||||
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)
|
||||
{
|
||||
DBUG_ASSERT(fixed == 1);
|
||||
|
|
|
@ -306,6 +306,7 @@ public:
|
|||
double val_real();
|
||||
longlong val_int ();
|
||||
String *val_str (String *);
|
||||
bool val_native(THD *thd, Native *);
|
||||
my_decimal *val_decimal(my_decimal *);
|
||||
bool val_bool();
|
||||
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()
|
||||
{
|
||||
DBUG_ENTER("Item_sum_hybrid::cleanup");
|
||||
|
|
|
@ -1072,6 +1072,7 @@ protected:
|
|||
bool get_date(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate);
|
||||
void reset_field();
|
||||
String *val_str(String *);
|
||||
bool val_native(THD *thd, Native *);
|
||||
const Type_handler *real_type_handler() const
|
||||
{
|
||||
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;
|
||||
Datetime dt(thd, args[0], Datetime::Options(TIME_NO_ZERO_IN_DATE, thd));
|
||||
if ((null_value= !dt.is_valid_datetime()))
|
||||
Timestamp_or_zero_datetime_native_null native(current_thd, args[0], true);
|
||||
if ((null_value= native.is_null() || native.is_zero_datetime()))
|
||||
return true;
|
||||
|
||||
uint error_code;
|
||||
*seconds= TIME_to_timestamp(thd, dt.get_mysql_time(), &error_code);
|
||||
*second_part= dt.get_mysql_time()->second_part;
|
||||
return (null_value= (error_code == ER_WARN_DATA_OUT_OF_RANGE));
|
||||
Timestamp_or_zero_datetime tm(native);
|
||||
*seconds= tm.tv().tv_sec;
|
||||
*second_part= tm.tv().tv_usec;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
|
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)
|
||||
{
|
||||
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
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
/***************************************************************************/
|
||||
|
||||
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
|
||||
|
@ -1457,6 +1564,16 @@ Type_handler_hybrid_field_type::aggregate_for_comparison(const Type_handler *h)
|
|||
*/
|
||||
if (b == TIME_RESULT)
|
||||
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
|
||||
{
|
||||
|
@ -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)
|
||||
{
|
||||
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:
|
||||
|
@ -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,
|
||||
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();
|
||||
}
|
||||
|
||||
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 *
|
||||
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 *
|
||||
|
@ -4763,6 +4910,12 @@ longlong Type_handler_time_common::
|
|||
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::
|
||||
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;
|
||||
}
|
||||
|
||||
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)
|
||||
|
@ -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,
|
||||
const Item_func_in *func,
|
||||
uint nargs) const
|
||||
|
@ -5004,7 +5172,9 @@ String *Type_handler_datetime_common::
|
|||
String *Type_handler_timestamp_common::
|
||||
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();
|
||||
}
|
||||
|
||||
|
||||
double Type_handler_timestamp_common::
|
||||
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::
|
||||
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,
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
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::
|
||||
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,
|
||||
const Type_cmp_attributes *attr,
|
||||
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);
|
||||
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_const.h"
|
||||
#include "sql_time.h"
|
||||
#include "compat56.h"
|
||||
|
||||
class Field;
|
||||
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
|
||||
{
|
||||
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:
|
||||
Datetime() // NULL value
|
||||
:Temporal_with_date()
|
||||
{ }
|
||||
Datetime(THD *thd, Item *item, date_mode_t fuzzydate)
|
||||
:Temporal_with_date(thd, item, fuzzydate)
|
||||
{
|
||||
|
@ -2204,6 +2233,7 @@ public:
|
|||
|
||||
class Timestamp: protected Timeval
|
||||
{
|
||||
static uint binary_length_to_precision(uint length);
|
||||
protected:
|
||||
void round_or_set_max(uint dec, int *warn);
|
||||
bool add_nanoseconds_usec(uint nanoseconds)
|
||||
|
@ -2237,7 +2267,18 @@ public:
|
|||
explicit Timestamp(const 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; }
|
||||
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
|
||||
{
|
||||
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():
|
||||
|
||||
|
@ -2905,6 +3057,7 @@ protected:
|
|||
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_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 Column_definition_prepare_stage2_legacy(Column_definition *c,
|
||||
enum_field_types type)
|
||||
|
@ -3026,6 +3179,10 @@ public:
|
|||
*/
|
||||
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_native_format() const
|
||||
{
|
||||
return this;
|
||||
}
|
||||
virtual const Type_handler *type_handler_for_item_field() const
|
||||
{
|
||||
return this;
|
||||
|
@ -3208,6 +3365,9 @@ public:
|
|||
Item_param *param,
|
||||
const Type_all_attributes *attr,
|
||||
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 int Item_save_in_field(Item *item, Field *field,
|
||||
bool no_conversions) const= 0;
|
||||
|
@ -3310,6 +3470,11 @@ public:
|
|||
DBUG_ASSERT(0);
|
||||
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 Item_const_eq(const Item_const *a, const Item_const *b,
|
||||
bool binary_cmp) const
|
||||
|
@ -3334,6 +3499,17 @@ public:
|
|||
virtual
|
||||
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 void Item_get_date(THD *thd, Item *item,
|
||||
Temporal::Warn *buff, MYSQL_TIME *ltime,
|
||||
|
@ -5187,10 +5363,13 @@ public:
|
|||
class Type_handler_timestamp_common: public Type_handler_temporal_with_date
|
||||
{
|
||||
static const Name m_name_timestamp;
|
||||
protected:
|
||||
bool TIME_to_native(THD *, const MYSQL_TIME *from, Native *to, uint dec) const;
|
||||
public:
|
||||
virtual ~Type_handler_timestamp_common() {}
|
||||
const Name name() const { return m_name_timestamp; }
|
||||
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_mysql_timestamp_type mysql_timestamp_type() const
|
||||
{
|
||||
|
@ -5201,6 +5380,20 @@ public:
|
|||
return true;
|
||||
}
|
||||
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;
|
||||
uint Item_decimal_scale(const Item *item) const
|
||||
{
|
||||
|
@ -5213,8 +5406,9 @@ public:
|
|||
}
|
||||
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;
|
||||
Item_cache *Item_get_cache(THD *thd, const Item *item) 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;
|
||||
my_decimal *Item_func_min_max_val_decimal(Item_func_min_max *,
|
||||
my_decimal *) const;
|
||||
bool set_comparator_func(Arg_comparator *cmp) const;
|
||||
bool Item_hybrid_func_fix_attributes(THD *thd,
|
||||
const char *name,
|
||||
Type_handler_hybrid_field_type *,
|
||||
|
@ -5229,6 +5424,8 @@ public:
|
|||
Item **items, uint nitems) const;
|
||||
void Item_param_set_param_func(Item_param *param,
|
||||
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
|
||||
{
|
||||
protected:
|
||||
Timeval() { }
|
||||
public:
|
||||
Timeval(my_time_t sec, ulong usec)
|
||||
{
|
||||
|
|
Loading…
Reference in a new issue