Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
M
MariaDB
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
nexedi
MariaDB
Commits
34eb9838
Commit
34eb9838
authored
Dec 08, 2018
by
Alexander Barkov
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
MDEV-13995 MAX(timestamp) returns a wrong result near DST change
parent
5b3db871
Changes
26
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
26 changed files
with
1850 additions
and
16 deletions
+1850
-16
mysql-test/main/old-mode.result
mysql-test/main/old-mode.result
+41
-0
mysql-test/main/old-mode.test
mysql-test/main/old-mode.test
+29
-0
mysql-test/main/timezone2.result
mysql-test/main/timezone2.result
+189
-0
mysql-test/main/timezone2.test
mysql-test/main/timezone2.test
+167
-0
mysql-test/main/type_timestamp.result
mysql-test/main/type_timestamp.result
+50
-0
mysql-test/main/type_timestamp.test
mysql-test/main/type_timestamp.test
+50
-0
mysql-test/main/type_timestamp_round.result
mysql-test/main/type_timestamp_round.result
+27
-0
mysql-test/main/type_timestamp_round.test
mysql-test/main/type_timestamp_round.test
+22
-0
sql/compat56.h
sql/compat56.h
+9
-0
sql/field.cc
sql/field.cc
+59
-0
sql/field.h
sql/field.h
+19
-0
sql/filesort.cc
sql/filesort.cc
+31
-0
sql/item.cc
sql/item.cc
+122
-0
sql/item.h
sql/item.h
+182
-0
sql/item_cmpfunc.cc
sql/item_cmpfunc.cc
+199
-0
sql/item_cmpfunc.h
sql/item_cmpfunc.h
+41
-0
sql/item_func.cc
sql/item_func.cc
+30
-0
sql/item_func.h
sql/item_func.h
+23
-0
sql/item_subselect.cc
sql/item_subselect.cc
+18
-0
sql/item_subselect.h
sql/item_subselect.h
+1
-0
sql/item_sum.cc
sql/item_sum.cc
+9
-0
sql/item_sum.h
sql/item_sum.h
+1
-0
sql/item_timefunc.cc
sql/item_timefunc.cc
+6
-8
sql/sql_type.cc
sql/sql_type.cc
+325
-7
sql/sql_type.h
sql/sql_type.h
+198
-1
sql/structs.h
sql/structs.h
+2
-0
No files found.
mysql-test/main/old-mode.result
View file @
34eb9838
...
...
@@ -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;
mysql-test/main/old-mode.test
View file @
34eb9838
...
...
@@ -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
;
mysql-test/main/timezone2.result
View file @
34eb9838
...
...
@@ -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
#
mysql-test/main/timezone2.test
View file @
34eb9838
...
...
@@ -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
#
mysql-test/main/type_timestamp.result
View file @
34eb9838
...
...
@@ -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
#
mysql-test/main/type_timestamp.test
View file @
34eb9838
...
...
@@ -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
#
mysql-test/main/type_timestamp_round.result
View file @
34eb9838
...
...
@@ -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;
mysql-test/main/type_timestamp_round.test
View file @
34eb9838
...
...
@@ -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
;
sql/compat56.h
View file @
34eb9838
...
...
@@ -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))
...
...
sql/field.cc
View file @
34eb9838
...
...
@@ -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
)
{
...
...
sql/field.h
View file @
34eb9838
...
...
@@ -790,6 +790,15 @@ class Field: public Value_source
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 @@ class Field: public Value_source
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 @@ class Field_timestamp :public Field_temporal {
{
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 @@ class Field_timestamp :public Field_temporal {
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 @@ class Field_timestamp_hires :public Field_timestamp_with_dec {
{
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 @@ class Field_timestampf :public Field_timestamp_with_dec {
{
return
get_timestamp
(
ptr
,
sec_part
);
}
bool
val_native
(
Native
*
to
);
uint
size_of
()
const
{
return
sizeof
(
*
this
);
}
};
...
...
sql/filesort.cc
View file @
34eb9838
...
...
@@ -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
,
...
...
sql/item.cc
View file @
34eb9838
...
...
@@ -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
,
&
ltime
,
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
)
...
...
sql/item.h
View file @
34eb9838
...
...
@@ -855,6 +855,25 @@ class Item: public Value_source,
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 @@ class Item: public Value_source,
*/
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 @@ class Item_sp_variable :public Item_fixed_hybrid
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 @@ class Item_field :public Item_ident,
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 @@ class Item_param :public Item_basic_value,
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 @@ class Item_bin_string: public Item_hex_hybrid
};
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 @@ class Item_ref :public Item_ident,
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 @@ class Item_direct_ref :public Item_ref
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 @@ class Item_cache_wrapper :public Item_result_field,
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 @@ class Item_direct_view_ref :public Item_direct_ref
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 @@ class Item_ref_null_helper: public Item_ref
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 @@ class Item_cache_date: public Item_cache_temporal
};
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
;
...
...
sql/item_cmpfunc.cc
View file @
34eb9838
...
...
@@ -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
++
;
...
...
sql/item_cmpfunc.h
View file @
34eb9838
...
...
@@ -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 @@ class Arg_comparator: public Sql_alloc
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 @@ class Arg_comparator: public Sql_alloc
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 @@ class Item_func_between :public Item_func_opt_neg
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 @@ class Item_func_coalesce :public Item_func_case_expression
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 @@ class Item_func_ifnull :public Item_func_case_abbreviation2
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 @@ class Item_func_case_abbreviation2_switch: public Item_func_case_abbreviation2
{
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 @@ class Item_func_nullif :public Item_func_case_expression
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 @@ class in_longlong :public in_vector
};
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 @@ class cmp_item_time: public cmp_item_temporal
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 @@ class Item_func_case :public Item_func_case_expression
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"
;
}
...
...
sql/item_func.cc
View file @
34eb9838
...
...
@@ -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
;
...
...
sql/item_func.h
View file @
34eb9838
...
...
@@ -768,6 +768,12 @@ class Item_func_hybrid_field_type: public Item_hybrid_func
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 @@ class Item_func_hybrid_field_type: public Item_hybrid_func
*/
virtual
bool
time_op
(
THD
*
thd
,
MYSQL_TIME
*
res
)
=
0
;
virtual
bool
native_op
(
THD
*
thd
,
Native
*
native
)
=
0
;
};
...
...
@@ -905,6 +912,11 @@ class Item_func_numhybrid: public Item_func_hybrid_field_type
DBUG_ASSERT
(
0
);
return
true
;
}
bool
native_op
(
THD
*
thd
,
Native
*
to
)
{
DBUG_ASSERT
(
0
);
return
true
;
}
};
...
...
@@ -1771,6 +1783,7 @@ class Item_func_min_max :public Item_hybrid_func
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 @@ class Item_func_rollup_const :public Item_func
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 @@ class Item_func_sp :public Item_func,
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 @@ class Item_func_last_value :public Item_func
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
();
}
...
...
sql/item_subselect.cc
View file @
34eb9838
...
...
@@ -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
);
...
...
sql/item_subselect.h
View file @
34eb9838
...
...
@@ -306,6 +306,7 @@ class Item_singlerow_subselect :public Item_subselect
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
);
...
...
sql/item_sum.cc
View file @
34eb9838
...
...
@@ -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"
);
...
...
sql/item_sum.h
View file @
34eb9838
...
...
@@ -1072,6 +1072,7 @@ class Item_sum_hybrid :public Item_sum, public Type_handler_hybrid_field_type
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
();
...
...
sql/item_timefunc.cc
View file @
34eb9838
...
...
@@ -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
;
}
...
...
sql/sql_type.cc
View file @
34eb9838
This diff is collapsed.
Click to expand it.
sql/sql_type.h
View file @
34eb9838
This diff is collapsed.
Click to expand it.
sql/structs.h
View file @
34eb9838
...
...
@@ -847,6 +847,8 @@ class Load_data_outvar
class
Timeval
:
public
timeval
{
protected:
Timeval
()
{
}
public:
Timeval
(
my_time_t
sec
,
ulong
usec
)
{
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment