MDEV-4863 COALESCE(time_or_datetime) returns wrong results in numeric context
This commit is contained in:
parent
02338228dd
commit
c2b38529a9
@ -1923,3 +1923,112 @@ NULL
|
|||||||
Warnings:
|
Warnings:
|
||||||
Error 1411 Incorrect datetime value: '2020' for function str_to_date
|
Error 1411 Incorrect datetime value: '2020' for function str_to_date
|
||||||
SET TIME_ZONE=DEFAULT;
|
SET TIME_ZONE=DEFAULT;
|
||||||
|
#
|
||||||
|
# MDEV-4863 COALESCE(time_or_datetime) returns wrong results in numeric context
|
||||||
|
#
|
||||||
|
CREATE TABLE t1 (a TIMESTAMP(3));
|
||||||
|
INSERT INTO t1 VALUES ('2001-01-01 10:20:30.999');
|
||||||
|
SELECT CAST(COALESCE(a,a) AS SIGNED) AS c1, CAST(COALESCE(a,a) AS DECIMAL(25,3)) AS c2, ROUND(COALESCE(a,a)) AS c2 FROM t1;
|
||||||
|
c1 c2 c2
|
||||||
|
20010101102030 20010101102030.999 20010101102031
|
||||||
|
DROP TABLE t1;
|
||||||
|
CREATE TABLE t1 (a TIME(3));
|
||||||
|
INSERT INTO t1 VALUES ('10:20:30.999');
|
||||||
|
SELECT CAST(COALESCE(a,a) AS SIGNED) AS c1, CAST(COALESCE(a,a) AS DECIMAL(25,3)) AS c2, ROUND(COALESCE(a,a)) AS c2 FROM t1;
|
||||||
|
c1 c2 c2
|
||||||
|
102030 102030.999 102031
|
||||||
|
DROP TABLE t1;
|
||||||
|
SELECT
|
||||||
|
CAST(COALESCE(DATE('2001-01-01'),TIMESTAMP('2001-01-02 10:20:30')) AS SIGNED) AS c1,
|
||||||
|
CAST(COALESCE(DATE('2001-01-01'),TIMESTAMP('2001-01-02 10:20:30')) AS DECIMAL(25,4)) AS c2,
|
||||||
|
COALESCE(DATE('2001-01-01'),TIMESTAMP('2001-01-02 10:20:30'))+0e0 AS c3,
|
||||||
|
CONCAT(COALESCE(DATE('2001-01-01'),TIMESTAMP('2001-01-02 10:20:30'))) AS c4,
|
||||||
|
TIME(COALESCE(DATE('2001-01-01'),TIMESTAMP('2001-01-02 10:20:30'))) AS c5,
|
||||||
|
DATE(COALESCE(DATE('2001-01-01'),TIMESTAMP('2001-01-02 10:20:30'))) AS c6,
|
||||||
|
TIMESTAMP(COALESCE(DATE('2001-01-01'),TIMESTAMP('2001-01-02 10:20:30'))) AS c7;
|
||||||
|
c1 c2 c3 c4 c5 c6 c7
|
||||||
|
20010101000000 20010101000000.0000 20010101000000 2001-01-01 00:00:00.000000 00:00:00.000000 2001-01-01 2001-01-01 00:00:00.000000
|
||||||
|
SELECT
|
||||||
|
CAST(COALESCE(TIMESTAMP('2001-01-02 10:20:30'),DATE('2001-01-01')) AS SIGNED) AS c1,
|
||||||
|
CAST(COALESCE(TIMESTAMP('2001-01-02 10:20:30'),DATE('2001-01-01')) AS DECIMAL(25,4)) AS c2,
|
||||||
|
COALESCE(TIMESTAMP('2001-01-02 10:20:30'),DATE('2001-01-01'))+0e0 AS c3,
|
||||||
|
CONCAT(COALESCE(TIMESTAMP('2001-01-02 10:20:30'),DATE('2001-01-01'))) AS c4,
|
||||||
|
TIME(COALESCE(TIMESTAMP('2001-01-02 10:20:30'),DATE('2001-01-01'))) AS c5,
|
||||||
|
DATE(COALESCE(TIMESTAMP('2001-01-02 10:20:30'),DATE('2001-01-01'))) AS c6,
|
||||||
|
TIMESTAMP(COALESCE(TIMESTAMP('2001-01-02 10:20:30'),DATE('2001-01-01'))) AS c7;
|
||||||
|
c1 c2 c3 c4 c5 c6 c7
|
||||||
|
20010102102030 20010102102030.0000 20010102102030 2001-01-02 10:20:30.000000 10:20:30.000000 2001-01-02 2001-01-02 10:20:30.000000
|
||||||
|
SELECT
|
||||||
|
CAST(IFNULL(DATE('2001-01-01'),TIMESTAMP('2001-01-02 10:20:30')) AS SIGNED) AS c1,
|
||||||
|
CAST(IFNULL(DATE('2001-01-01'),TIMESTAMP('2001-01-02 10:20:30')) AS DECIMAL(25,4)) AS c2,
|
||||||
|
IFNULL(DATE('2001-01-01'),TIMESTAMP('2001-01-02 10:20:30'))+0e0 AS c3,
|
||||||
|
CONCAT(IFNULL(DATE('2001-01-01'),TIMESTAMP('2001-01-02 10:20:30'))) AS c4,
|
||||||
|
TIME(IFNULL(DATE('2001-01-01'),TIMESTAMP('2001-01-02 10:20:30'))) AS c5,
|
||||||
|
DATE(IFNULL(DATE('2001-01-01'),TIMESTAMP('2001-01-02 10:20:30'))) AS c6,
|
||||||
|
TIMESTAMP(IFNULL(DATE('2001-01-01'),TIMESTAMP('2001-01-02 10:20:30'))) AS c7;
|
||||||
|
c1 c2 c3 c4 c5 c6 c7
|
||||||
|
20010101000000 20010101000000.0000 20010101000000 2001-01-01 00:00:00.000000 00:00:00.000000 2001-01-01 2001-01-01 00:00:00.000000
|
||||||
|
SELECT
|
||||||
|
CAST(IFNULL(TIMESTAMP('2001-01-02 10:20:30'),DATE('2001-01-01')) AS SIGNED) AS c1,
|
||||||
|
CAST(IFNULL(TIMESTAMP('2001-01-02 10:20:30'),DATE('2001-01-01')) AS DECIMAL(25,4)) AS c2,
|
||||||
|
IFNULL(TIMESTAMP('2001-01-02 10:20:30'),DATE('2001-01-01'))+0e0 AS c3,
|
||||||
|
CONCAT(IFNULL(TIMESTAMP('2001-01-02 10:20:30'),DATE('2001-01-01'))) AS c4,
|
||||||
|
TIME(IFNULL(TIMESTAMP('2001-01-02 10:20:30'),DATE('2001-01-01'))) AS c5,
|
||||||
|
DATE(IFNULL(TIMESTAMP('2001-01-02 10:20:30'),DATE('2001-01-01'))) AS c6,
|
||||||
|
TIMESTAMP(IFNULL(TIMESTAMP('2001-01-02 10:20:30'),DATE('2001-01-01'))) AS c7;
|
||||||
|
c1 c2 c3 c4 c5 c6 c7
|
||||||
|
20010102102030 20010102102030.0000 20010102102030 2001-01-02 10:20:30.000000 10:20:30.000000 2001-01-02 2001-01-02 10:20:30.000000
|
||||||
|
SELECT
|
||||||
|
CAST(IF(1,DATE('2001-01-01'),TIMESTAMP('2001-01-02 10:20:30')) AS SIGNED) AS c1,
|
||||||
|
CAST(IF(1,DATE('2001-01-01'),TIMESTAMP('2001-01-02 10:20:30')) AS DECIMAL(25,4)) AS c2,
|
||||||
|
IF(1,DATE('2001-01-01'),TIMESTAMP('2001-01-02 10:20:30'))+0e0 AS c3,
|
||||||
|
CONCAT(IF(1,DATE('2001-01-01'),TIMESTAMP('2001-01-02 10:20:30'))) AS c4,
|
||||||
|
TIME(IF(1,DATE('2001-01-01'),TIMESTAMP('2001-01-02 10:20:30'))) AS c5,
|
||||||
|
DATE(IF(1,DATE('2001-01-01'),TIMESTAMP('2001-01-02 10:20:30'))) AS c6,
|
||||||
|
TIMESTAMP(IF(1,DATE('2001-01-01'),TIMESTAMP('2001-01-02 10:20:30'))) AS c7;
|
||||||
|
c1 c2 c3 c4 c5 c6 c7
|
||||||
|
20010101000000 20010101000000.0000 20010101000000 2001-01-01 00:00:00.000000 00:00:00.000000 2001-01-01 2001-01-01 00:00:00.000000
|
||||||
|
SELECT
|
||||||
|
CAST(IF(0,DATE('2001-01-01'),TIMESTAMP('2001-01-02 10:20:30')) AS SIGNED) AS c1,
|
||||||
|
CAST(IF(0,DATE('2001-01-01'),TIMESTAMP('2001-01-02 10:20:30')) AS DECIMAL(25,4)) AS c2,
|
||||||
|
IF(0,DATE('2001-01-01'),TIMESTAMP('2001-01-02 10:20:30'))+0e0 AS c3,
|
||||||
|
CONCAT(IF(0,DATE('2001-01-01'),TIMESTAMP('2001-01-02 10:20:30'))) AS c4,
|
||||||
|
TIME(IF(0,DATE('2001-01-01'),TIMESTAMP('2001-01-02 10:20:30'))) AS c5,
|
||||||
|
DATE(IF(0,DATE('2001-01-01'),TIMESTAMP('2001-01-02 10:20:30'))) AS c6,
|
||||||
|
TIMESTAMP(IF(0,DATE('2001-01-01'),TIMESTAMP('2001-01-02 10:20:30'))) AS c7;
|
||||||
|
c1 c2 c3 c4 c5 c6 c7
|
||||||
|
20010102102030 20010102102030.0000 20010102102030 2001-01-02 10:20:30.000000 10:20:30.000000 2001-01-02 2001-01-02 10:20:30.000000
|
||||||
|
SELECT
|
||||||
|
CAST(CASE WHEN 1 THEN DATE('2001-01-01') ELSE TIMESTAMP('2001-01-02 10:20:30') END AS SIGNED) AS c1,
|
||||||
|
CAST(CASE WHEN 1 THEN DATE('2001-01-01') ELSE TIMESTAMP('2001-01-02 10:20:30') END AS DECIMAL(25,4)) AS c2,
|
||||||
|
CASE WHEN 1 THEN DATE('2001-01-01') ELSE TIMESTAMP('2001-01-02 10:20:30') END+0e0 AS c3,
|
||||||
|
CONCAT(CASE WHEN 1 THEN DATE('2001-01-01') ELSE TIMESTAMP('2001-01-02 10:20:30') END) AS c4,
|
||||||
|
TIME(CASE WHEN 1 THEN DATE('2001-01-01') ELSE TIMESTAMP('2001-01-02 10:20:30') END) AS c5,
|
||||||
|
DATE(CASE WHEN 1 THEN DATE('2001-01-01') ELSE TIMESTAMP('2001-01-02 10:20:30') END) AS c6,
|
||||||
|
TIMESTAMP(CASE WHEN 1 THEN DATE('2001-01-01') ELSE TIMESTAMP('2001-01-02 10:20:30') END) AS c7;
|
||||||
|
c1 c2 c3 c4 c5 c6 c7
|
||||||
|
20010101000000 20010101000000.0000 20010101000000 2001-01-01 00:00:00.000000 00:00:00.000000 2001-01-01 2001-01-01 00:00:00.000000
|
||||||
|
SELECT
|
||||||
|
CAST(CASE WHEN 0 THEN DATE('2001-01-01') ELSE TIMESTAMP('2001-01-02 10:20:30') END AS SIGNED) AS c1,
|
||||||
|
CAST(CASE WHEN 0 THEN DATE('2001-01-01') ELSE TIMESTAMP('2001-01-02 10:20:30') END AS DECIMAL(25,4)) AS c2,
|
||||||
|
CASE WHEN 0 THEN DATE('2001-01-01') ELSE TIMESTAMP('2001-01-02 10:20:30') END+0e0 AS c3,
|
||||||
|
CONCAT(CASE WHEN 0 THEN DATE('2001-01-01') ELSE TIMESTAMP('2001-01-02 10:20:30') END) AS c4,
|
||||||
|
TIME(CASE WHEN 0 THEN DATE('2001-01-01') ELSE TIMESTAMP('2001-01-02 10:20:30') END) AS c5,
|
||||||
|
DATE(CASE WHEN 0 THEN DATE('2001-01-01') ELSE TIMESTAMP('2001-01-02 10:20:30') END) AS c6,
|
||||||
|
TIMESTAMP(CASE WHEN 0 THEN DATE('2001-01-01') ELSE TIMESTAMP('2001-01-02 10:20:30') END) AS c7;
|
||||||
|
c1 c2 c3 c4 c5 c6 c7
|
||||||
|
20010102102030 20010102102030.0000 20010102102030 2001-01-02 10:20:30.000000 10:20:30.000000 2001-01-02 2001-01-02 10:20:30.000000
|
||||||
|
CREATE TABLE t1 AS SELECT
|
||||||
|
CONCAT(COALESCE(TIME(101010),TIME(101010))) AS c1,
|
||||||
|
CONCAT(IF(0,TIME(101010),TIME(101010))) AS c2,
|
||||||
|
CONCAT(IFNULL(TIME(101010),TIME(101010))) AS c3,
|
||||||
|
CONCAT(CASE WHEN 1 THEN TIME(101010) ELSE TIME(101010) END) AS c4;
|
||||||
|
SHOW CREATE TABLE t1;
|
||||||
|
Table Create Table
|
||||||
|
t1 CREATE TABLE `t1` (
|
||||||
|
`c1` varbinary(10) DEFAULT NULL,
|
||||||
|
`c2` varbinary(10) DEFAULT NULL,
|
||||||
|
`c3` varbinary(10) DEFAULT NULL,
|
||||||
|
`c4` varbinary(10) DEFAULT NULL
|
||||||
|
) ENGINE=MyISAM DEFAULT CHARSET=latin1
|
||||||
|
DROP TABLE t1;
|
||||||
|
@ -657,13 +657,8 @@ create table t1 (d date, t time) engine=myisam;
|
|||||||
insert into t1 values ('2000-12-03','22:55:23'),('2008-05-03','10:19:31');
|
insert into t1 values ('2000-12-03','22:55:23'),('2008-05-03','10:19:31');
|
||||||
select case when d = '2012-12-12' then d else t end as cond, group_concat( d ) from t1 group by cond;
|
select case when d = '2012-12-12' then d else t end as cond, group_concat( d ) from t1 group by cond;
|
||||||
cond group_concat( d )
|
cond group_concat( d )
|
||||||
NULL 2000-12-03
|
0000-00-00 10:19:31 2008-05-03
|
||||||
NULL 2008-05-03
|
0000-00-00 22:55:23 2000-12-03
|
||||||
Warnings:
|
|
||||||
Warning 1292 Incorrect datetime value: '22:55:23'
|
|
||||||
Warning 1292 Incorrect datetime value: '10:19:31'
|
|
||||||
Warning 1292 Incorrect datetime value: '22:55:23'
|
|
||||||
Warning 1292 Incorrect datetime value: '10:19:31'
|
|
||||||
drop table t1;
|
drop table t1;
|
||||||
#
|
#
|
||||||
# Semantics of the condition <non-nullable datetime field> IS NULL
|
# Semantics of the condition <non-nullable datetime field> IS NULL
|
||||||
|
@ -1162,3 +1162,96 @@ SELECT 1 FROM DUAL WHERE SECOND(TIMEDIFF(NULL, '12:12:12'));
|
|||||||
SET TIME_ZONE='+02:00';
|
SET TIME_ZONE='+02:00';
|
||||||
SELECT UNIX_TIMESTAMP(STR_TO_DATE('2020','%Y'));
|
SELECT UNIX_TIMESTAMP(STR_TO_DATE('2020','%Y'));
|
||||||
SET TIME_ZONE=DEFAULT;
|
SET TIME_ZONE=DEFAULT;
|
||||||
|
|
||||||
|
|
||||||
|
--echo #
|
||||||
|
--echo # MDEV-4863 COALESCE(time_or_datetime) returns wrong results in numeric context
|
||||||
|
--echo #
|
||||||
|
CREATE TABLE t1 (a TIMESTAMP(3));
|
||||||
|
INSERT INTO t1 VALUES ('2001-01-01 10:20:30.999');
|
||||||
|
SELECT CAST(COALESCE(a,a) AS SIGNED) AS c1, CAST(COALESCE(a,a) AS DECIMAL(25,3)) AS c2, ROUND(COALESCE(a,a)) AS c2 FROM t1;
|
||||||
|
DROP TABLE t1;
|
||||||
|
CREATE TABLE t1 (a TIME(3));
|
||||||
|
INSERT INTO t1 VALUES ('10:20:30.999');
|
||||||
|
SELECT CAST(COALESCE(a,a) AS SIGNED) AS c1, CAST(COALESCE(a,a) AS DECIMAL(25,3)) AS c2, ROUND(COALESCE(a,a)) AS c2 FROM t1;
|
||||||
|
DROP TABLE t1;
|
||||||
|
|
||||||
|
SELECT
|
||||||
|
CAST(COALESCE(DATE('2001-01-01'),TIMESTAMP('2001-01-02 10:20:30')) AS SIGNED) AS c1,
|
||||||
|
CAST(COALESCE(DATE('2001-01-01'),TIMESTAMP('2001-01-02 10:20:30')) AS DECIMAL(25,4)) AS c2,
|
||||||
|
COALESCE(DATE('2001-01-01'),TIMESTAMP('2001-01-02 10:20:30'))+0e0 AS c3,
|
||||||
|
CONCAT(COALESCE(DATE('2001-01-01'),TIMESTAMP('2001-01-02 10:20:30'))) AS c4,
|
||||||
|
TIME(COALESCE(DATE('2001-01-01'),TIMESTAMP('2001-01-02 10:20:30'))) AS c5,
|
||||||
|
DATE(COALESCE(DATE('2001-01-01'),TIMESTAMP('2001-01-02 10:20:30'))) AS c6,
|
||||||
|
TIMESTAMP(COALESCE(DATE('2001-01-01'),TIMESTAMP('2001-01-02 10:20:30'))) AS c7;
|
||||||
|
|
||||||
|
SELECT
|
||||||
|
CAST(COALESCE(TIMESTAMP('2001-01-02 10:20:30'),DATE('2001-01-01')) AS SIGNED) AS c1,
|
||||||
|
CAST(COALESCE(TIMESTAMP('2001-01-02 10:20:30'),DATE('2001-01-01')) AS DECIMAL(25,4)) AS c2,
|
||||||
|
COALESCE(TIMESTAMP('2001-01-02 10:20:30'),DATE('2001-01-01'))+0e0 AS c3,
|
||||||
|
CONCAT(COALESCE(TIMESTAMP('2001-01-02 10:20:30'),DATE('2001-01-01'))) AS c4,
|
||||||
|
TIME(COALESCE(TIMESTAMP('2001-01-02 10:20:30'),DATE('2001-01-01'))) AS c5,
|
||||||
|
DATE(COALESCE(TIMESTAMP('2001-01-02 10:20:30'),DATE('2001-01-01'))) AS c6,
|
||||||
|
TIMESTAMP(COALESCE(TIMESTAMP('2001-01-02 10:20:30'),DATE('2001-01-01'))) AS c7;
|
||||||
|
|
||||||
|
SELECT
|
||||||
|
CAST(IFNULL(DATE('2001-01-01'),TIMESTAMP('2001-01-02 10:20:30')) AS SIGNED) AS c1,
|
||||||
|
CAST(IFNULL(DATE('2001-01-01'),TIMESTAMP('2001-01-02 10:20:30')) AS DECIMAL(25,4)) AS c2,
|
||||||
|
IFNULL(DATE('2001-01-01'),TIMESTAMP('2001-01-02 10:20:30'))+0e0 AS c3,
|
||||||
|
CONCAT(IFNULL(DATE('2001-01-01'),TIMESTAMP('2001-01-02 10:20:30'))) AS c4,
|
||||||
|
TIME(IFNULL(DATE('2001-01-01'),TIMESTAMP('2001-01-02 10:20:30'))) AS c5,
|
||||||
|
DATE(IFNULL(DATE('2001-01-01'),TIMESTAMP('2001-01-02 10:20:30'))) AS c6,
|
||||||
|
TIMESTAMP(IFNULL(DATE('2001-01-01'),TIMESTAMP('2001-01-02 10:20:30'))) AS c7;
|
||||||
|
|
||||||
|
SELECT
|
||||||
|
CAST(IFNULL(TIMESTAMP('2001-01-02 10:20:30'),DATE('2001-01-01')) AS SIGNED) AS c1,
|
||||||
|
CAST(IFNULL(TIMESTAMP('2001-01-02 10:20:30'),DATE('2001-01-01')) AS DECIMAL(25,4)) AS c2,
|
||||||
|
IFNULL(TIMESTAMP('2001-01-02 10:20:30'),DATE('2001-01-01'))+0e0 AS c3,
|
||||||
|
CONCAT(IFNULL(TIMESTAMP('2001-01-02 10:20:30'),DATE('2001-01-01'))) AS c4,
|
||||||
|
TIME(IFNULL(TIMESTAMP('2001-01-02 10:20:30'),DATE('2001-01-01'))) AS c5,
|
||||||
|
DATE(IFNULL(TIMESTAMP('2001-01-02 10:20:30'),DATE('2001-01-01'))) AS c6,
|
||||||
|
TIMESTAMP(IFNULL(TIMESTAMP('2001-01-02 10:20:30'),DATE('2001-01-01'))) AS c7;
|
||||||
|
|
||||||
|
SELECT
|
||||||
|
CAST(IF(1,DATE('2001-01-01'),TIMESTAMP('2001-01-02 10:20:30')) AS SIGNED) AS c1,
|
||||||
|
CAST(IF(1,DATE('2001-01-01'),TIMESTAMP('2001-01-02 10:20:30')) AS DECIMAL(25,4)) AS c2,
|
||||||
|
IF(1,DATE('2001-01-01'),TIMESTAMP('2001-01-02 10:20:30'))+0e0 AS c3,
|
||||||
|
CONCAT(IF(1,DATE('2001-01-01'),TIMESTAMP('2001-01-02 10:20:30'))) AS c4,
|
||||||
|
TIME(IF(1,DATE('2001-01-01'),TIMESTAMP('2001-01-02 10:20:30'))) AS c5,
|
||||||
|
DATE(IF(1,DATE('2001-01-01'),TIMESTAMP('2001-01-02 10:20:30'))) AS c6,
|
||||||
|
TIMESTAMP(IF(1,DATE('2001-01-01'),TIMESTAMP('2001-01-02 10:20:30'))) AS c7;
|
||||||
|
|
||||||
|
SELECT
|
||||||
|
CAST(IF(0,DATE('2001-01-01'),TIMESTAMP('2001-01-02 10:20:30')) AS SIGNED) AS c1,
|
||||||
|
CAST(IF(0,DATE('2001-01-01'),TIMESTAMP('2001-01-02 10:20:30')) AS DECIMAL(25,4)) AS c2,
|
||||||
|
IF(0,DATE('2001-01-01'),TIMESTAMP('2001-01-02 10:20:30'))+0e0 AS c3,
|
||||||
|
CONCAT(IF(0,DATE('2001-01-01'),TIMESTAMP('2001-01-02 10:20:30'))) AS c4,
|
||||||
|
TIME(IF(0,DATE('2001-01-01'),TIMESTAMP('2001-01-02 10:20:30'))) AS c5,
|
||||||
|
DATE(IF(0,DATE('2001-01-01'),TIMESTAMP('2001-01-02 10:20:30'))) AS c6,
|
||||||
|
TIMESTAMP(IF(0,DATE('2001-01-01'),TIMESTAMP('2001-01-02 10:20:30'))) AS c7;
|
||||||
|
|
||||||
|
SELECT
|
||||||
|
CAST(CASE WHEN 1 THEN DATE('2001-01-01') ELSE TIMESTAMP('2001-01-02 10:20:30') END AS SIGNED) AS c1,
|
||||||
|
CAST(CASE WHEN 1 THEN DATE('2001-01-01') ELSE TIMESTAMP('2001-01-02 10:20:30') END AS DECIMAL(25,4)) AS c2,
|
||||||
|
CASE WHEN 1 THEN DATE('2001-01-01') ELSE TIMESTAMP('2001-01-02 10:20:30') END+0e0 AS c3,
|
||||||
|
CONCAT(CASE WHEN 1 THEN DATE('2001-01-01') ELSE TIMESTAMP('2001-01-02 10:20:30') END) AS c4,
|
||||||
|
TIME(CASE WHEN 1 THEN DATE('2001-01-01') ELSE TIMESTAMP('2001-01-02 10:20:30') END) AS c5,
|
||||||
|
DATE(CASE WHEN 1 THEN DATE('2001-01-01') ELSE TIMESTAMP('2001-01-02 10:20:30') END) AS c6,
|
||||||
|
TIMESTAMP(CASE WHEN 1 THEN DATE('2001-01-01') ELSE TIMESTAMP('2001-01-02 10:20:30') END) AS c7;
|
||||||
|
|
||||||
|
SELECT
|
||||||
|
CAST(CASE WHEN 0 THEN DATE('2001-01-01') ELSE TIMESTAMP('2001-01-02 10:20:30') END AS SIGNED) AS c1,
|
||||||
|
CAST(CASE WHEN 0 THEN DATE('2001-01-01') ELSE TIMESTAMP('2001-01-02 10:20:30') END AS DECIMAL(25,4)) AS c2,
|
||||||
|
CASE WHEN 0 THEN DATE('2001-01-01') ELSE TIMESTAMP('2001-01-02 10:20:30') END+0e0 AS c3,
|
||||||
|
CONCAT(CASE WHEN 0 THEN DATE('2001-01-01') ELSE TIMESTAMP('2001-01-02 10:20:30') END) AS c4,
|
||||||
|
TIME(CASE WHEN 0 THEN DATE('2001-01-01') ELSE TIMESTAMP('2001-01-02 10:20:30') END) AS c5,
|
||||||
|
DATE(CASE WHEN 0 THEN DATE('2001-01-01') ELSE TIMESTAMP('2001-01-02 10:20:30') END) AS c6,
|
||||||
|
TIMESTAMP(CASE WHEN 0 THEN DATE('2001-01-01') ELSE TIMESTAMP('2001-01-02 10:20:30') END) AS c7;
|
||||||
|
|
||||||
|
CREATE TABLE t1 AS SELECT
|
||||||
|
CONCAT(COALESCE(TIME(101010),TIME(101010))) AS c1,
|
||||||
|
CONCAT(IF(0,TIME(101010),TIME(101010))) AS c2,
|
||||||
|
CONCAT(IFNULL(TIME(101010),TIME(101010))) AS c3,
|
||||||
|
CONCAT(CASE WHEN 1 THEN TIME(101010) ELSE TIME(101010) END) AS c4;
|
||||||
|
SHOW CREATE TABLE t1;
|
||||||
|
DROP TABLE t1;
|
||||||
|
13
sql/field.h
13
sql/field.h
@ -52,6 +52,19 @@ inline uint get_set_pack_length(int elements)
|
|||||||
return len > 4 ? 8 : len;
|
return len > 4 ? 8 : len;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Tests if field type is temporal, i.e. represents
|
||||||
|
DATE, TIME, DATETIME or TIMESTAMP types in SQL.
|
||||||
|
|
||||||
|
@param type Field type, as returned by field->type().
|
||||||
|
@retval true If field type is temporal
|
||||||
|
@retval false If field type is not temporal
|
||||||
|
*/
|
||||||
|
inline bool is_temporal_type(enum_field_types type)
|
||||||
|
{
|
||||||
|
return mysql_type_to_time_type(type) != MYSQL_TIMESTAMP_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Virtual_column_info is the class to contain additional
|
Virtual_column_info is the class to contain additional
|
||||||
characteristics that is specific for a virtual/computed
|
characteristics that is specific for a virtual/computed
|
||||||
|
13
sql/item.h
13
sql/item.h
@ -45,6 +45,14 @@ struct TABLE_LIST;
|
|||||||
void item_init(void); /* Init item functions */
|
void item_init(void); /* Init item functions */
|
||||||
class Item_field;
|
class Item_field;
|
||||||
|
|
||||||
|
static inline uint32
|
||||||
|
char_to_byte_length_safe(uint32 char_length_arg, uint32 mbmaxlen_arg)
|
||||||
|
{
|
||||||
|
ulonglong tmp= ((ulonglong) char_length_arg) * mbmaxlen_arg;
|
||||||
|
return (tmp > UINT_MAX32) ? (uint32) UINT_MAX32 : (uint32) tmp;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
"Declared Type Collation"
|
"Declared Type Collation"
|
||||||
A combination of collation and its derivation.
|
A combination of collation and its derivation.
|
||||||
@ -1287,6 +1295,11 @@ public:
|
|||||||
{ return Field::GEOM_GEOMETRY; };
|
{ return Field::GEOM_GEOMETRY; };
|
||||||
String *check_well_formed_result(String *str, bool send_error= 0);
|
String *check_well_formed_result(String *str, bool send_error= 0);
|
||||||
bool eq_by_collation(Item *item, bool binary_cmp, CHARSET_INFO *cs);
|
bool eq_by_collation(Item *item, bool binary_cmp, CHARSET_INFO *cs);
|
||||||
|
void fix_char_length(uint32 max_char_length_arg)
|
||||||
|
{
|
||||||
|
max_length= char_to_byte_length_safe(max_char_length_arg,
|
||||||
|
collation.collation->mbmaxlen);
|
||||||
|
}
|
||||||
Item* set_expr_cache(THD *thd);
|
Item* set_expr_cache(THD *thd);
|
||||||
virtual Item *get_cached_item() { return NULL; }
|
virtual Item *get_cached_item() { return NULL; }
|
||||||
|
|
||||||
|
@ -2374,12 +2374,13 @@ void Item_func_between::print(String *str, enum_query_type query_type)
|
|||||||
void
|
void
|
||||||
Item_func_ifnull::fix_length_and_dec()
|
Item_func_ifnull::fix_length_and_dec()
|
||||||
{
|
{
|
||||||
agg_result_type(&hybrid_type, args, 2);
|
agg_result_type(&cached_result_type, args, 2);
|
||||||
|
cached_field_type= agg_field_type(args, 2);
|
||||||
maybe_null=args[1]->maybe_null;
|
maybe_null=args[1]->maybe_null;
|
||||||
decimals= max(args[0]->decimals, args[1]->decimals);
|
decimals= max(args[0]->decimals, args[1]->decimals);
|
||||||
unsigned_flag= args[0]->unsigned_flag && args[1]->unsigned_flag;
|
unsigned_flag= args[0]->unsigned_flag && args[1]->unsigned_flag;
|
||||||
|
|
||||||
if (hybrid_type == DECIMAL_RESULT || hybrid_type == INT_RESULT)
|
if (cached_result_type == DECIMAL_RESULT || cached_result_type == INT_RESULT)
|
||||||
{
|
{
|
||||||
int len0= args[0]->max_length - args[0]->decimals
|
int len0= args[0]->max_length - args[0]->decimals
|
||||||
- (args[0]->unsigned_flag ? 0 : 1);
|
- (args[0]->unsigned_flag ? 0 : 1);
|
||||||
@ -2392,9 +2393,10 @@ Item_func_ifnull::fix_length_and_dec()
|
|||||||
else
|
else
|
||||||
max_length= max(args[0]->max_length, args[1]->max_length);
|
max_length= max(args[0]->max_length, args[1]->max_length);
|
||||||
|
|
||||||
switch (hybrid_type) {
|
switch (cached_result_type) {
|
||||||
case STRING_RESULT:
|
case STRING_RESULT:
|
||||||
agg_arg_charsets(collation, args, arg_count, MY_COLL_CMP_CONV, 1);
|
if (count_string_result_length(cached_field_type, args, arg_count))
|
||||||
|
return;
|
||||||
break;
|
break;
|
||||||
case DECIMAL_RESULT:
|
case DECIMAL_RESULT:
|
||||||
case REAL_RESULT:
|
case REAL_RESULT:
|
||||||
@ -2407,7 +2409,6 @@ Item_func_ifnull::fix_length_and_dec()
|
|||||||
case IMPOSSIBLE_RESULT:
|
case IMPOSSIBLE_RESULT:
|
||||||
DBUG_ASSERT(0);
|
DBUG_ASSERT(0);
|
||||||
}
|
}
|
||||||
cached_field_type= agg_field_type(args, 2);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -2421,11 +2422,6 @@ uint Item_func_ifnull::decimal_precision() const
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
enum_field_types Item_func_ifnull::field_type() const
|
|
||||||
{
|
|
||||||
return cached_field_type;
|
|
||||||
}
|
|
||||||
|
|
||||||
Field *Item_func_ifnull::tmp_table_field(TABLE *table)
|
Field *Item_func_ifnull::tmp_table_field(TABLE *table)
|
||||||
{
|
{
|
||||||
return tmp_table_field_from_field_type(table, 0);
|
return tmp_table_field_from_field_type(table, 0);
|
||||||
@ -2499,6 +2495,18 @@ Item_func_ifnull::str_op(String *str)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool Item_func_ifnull::date_op(MYSQL_TIME *ltime, uint fuzzydate)
|
||||||
|
{
|
||||||
|
DBUG_ASSERT(fixed == 1);
|
||||||
|
if (!args[0]->get_date(ltime, fuzzydate & ~TIME_FUZZY_DATES))
|
||||||
|
return (null_value= false);
|
||||||
|
if (!args[1]->get_date(ltime, fuzzydate & ~TIME_FUZZY_DATES))
|
||||||
|
return (null_value= false);
|
||||||
|
bzero((char*) ltime,sizeof(*ltime));
|
||||||
|
return null_value= !(fuzzydate & TIME_FUZZY_DATES);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Perform context analysis of an IF item tree.
|
Perform context analysis of an IF item tree.
|
||||||
|
|
||||||
@ -2587,16 +2595,16 @@ Item_func_if::fix_length_and_dec()
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
agg_result_type(&cached_result_type, args+1, 2);
|
agg_result_type(&cached_result_type, args+1, 2);
|
||||||
|
cached_field_type= agg_field_type(args + 1, 2);
|
||||||
if (cached_result_type == STRING_RESULT)
|
if (cached_result_type == STRING_RESULT)
|
||||||
{
|
{
|
||||||
if (agg_arg_charsets(collation, args+1, 2, MY_COLL_ALLOW_CONV, 1))
|
count_string_result_length(cached_field_type, args + 1, 2);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
collation.set(&my_charset_bin); // Number
|
collation.set(&my_charset_bin); // Number
|
||||||
}
|
}
|
||||||
cached_field_type= agg_field_type(args + 1, 2);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((cached_result_type == DECIMAL_RESULT )
|
if ((cached_result_type == DECIMAL_RESULT )
|
||||||
@ -2625,7 +2633,7 @@ uint Item_func_if::decimal_precision() const
|
|||||||
|
|
||||||
|
|
||||||
double
|
double
|
||||||
Item_func_if::val_real()
|
Item_func_if::real_op()
|
||||||
{
|
{
|
||||||
DBUG_ASSERT(fixed == 1);
|
DBUG_ASSERT(fixed == 1);
|
||||||
Item *arg= args[0]->val_bool() ? args[1] : args[2];
|
Item *arg= args[0]->val_bool() ? args[1] : args[2];
|
||||||
@ -2635,7 +2643,7 @@ Item_func_if::val_real()
|
|||||||
}
|
}
|
||||||
|
|
||||||
longlong
|
longlong
|
||||||
Item_func_if::val_int()
|
Item_func_if::int_op()
|
||||||
{
|
{
|
||||||
DBUG_ASSERT(fixed == 1);
|
DBUG_ASSERT(fixed == 1);
|
||||||
Item *arg= args[0]->val_bool() ? args[1] : args[2];
|
Item *arg= args[0]->val_bool() ? args[1] : args[2];
|
||||||
@ -2645,7 +2653,7 @@ Item_func_if::val_int()
|
|||||||
}
|
}
|
||||||
|
|
||||||
String *
|
String *
|
||||||
Item_func_if::val_str(String *str)
|
Item_func_if::str_op(String *str)
|
||||||
{
|
{
|
||||||
DBUG_ASSERT(fixed == 1);
|
DBUG_ASSERT(fixed == 1);
|
||||||
Item *arg= args[0]->val_bool() ? args[1] : args[2];
|
Item *arg= args[0]->val_bool() ? args[1] : args[2];
|
||||||
@ -2658,7 +2666,7 @@ Item_func_if::val_str(String *str)
|
|||||||
|
|
||||||
|
|
||||||
my_decimal *
|
my_decimal *
|
||||||
Item_func_if::val_decimal(my_decimal *decimal_value)
|
Item_func_if::decimal_op(my_decimal *decimal_value)
|
||||||
{
|
{
|
||||||
DBUG_ASSERT(fixed == 1);
|
DBUG_ASSERT(fixed == 1);
|
||||||
Item *arg= args[0]->val_bool() ? args[1] : args[2];
|
Item *arg= args[0]->val_bool() ? args[1] : args[2];
|
||||||
@ -2668,6 +2676,14 @@ Item_func_if::val_decimal(my_decimal *decimal_value)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool Item_func_if::date_op(MYSQL_TIME *ltime, uint fuzzydate)
|
||||||
|
{
|
||||||
|
DBUG_ASSERT(fixed == 1);
|
||||||
|
Item *arg= args[0]->val_bool() ? args[1] : args[2];
|
||||||
|
return (null_value= arg->get_date(ltime, fuzzydate));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
Item_func_nullif::fix_length_and_dec()
|
Item_func_nullif::fix_length_and_dec()
|
||||||
{
|
{
|
||||||
@ -2826,7 +2842,7 @@ Item *Item_func_case::find_item(String *str)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
String *Item_func_case::val_str(String *str)
|
String *Item_func_case::str_op(String *str)
|
||||||
{
|
{
|
||||||
DBUG_ASSERT(fixed == 1);
|
DBUG_ASSERT(fixed == 1);
|
||||||
String *res;
|
String *res;
|
||||||
@ -2844,7 +2860,7 @@ String *Item_func_case::val_str(String *str)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
longlong Item_func_case::val_int()
|
longlong Item_func_case::int_op()
|
||||||
{
|
{
|
||||||
DBUG_ASSERT(fixed == 1);
|
DBUG_ASSERT(fixed == 1);
|
||||||
char buff[MAX_FIELD_WIDTH];
|
char buff[MAX_FIELD_WIDTH];
|
||||||
@ -2862,7 +2878,7 @@ longlong Item_func_case::val_int()
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
double Item_func_case::val_real()
|
double Item_func_case::real_op()
|
||||||
{
|
{
|
||||||
DBUG_ASSERT(fixed == 1);
|
DBUG_ASSERT(fixed == 1);
|
||||||
char buff[MAX_FIELD_WIDTH];
|
char buff[MAX_FIELD_WIDTH];
|
||||||
@ -2881,7 +2897,7 @@ double Item_func_case::val_real()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
my_decimal *Item_func_case::val_decimal(my_decimal *decimal_value)
|
my_decimal *Item_func_case::decimal_op(my_decimal *decimal_value)
|
||||||
{
|
{
|
||||||
DBUG_ASSERT(fixed == 1);
|
DBUG_ASSERT(fixed == 1);
|
||||||
char buff[MAX_FIELD_WIDTH];
|
char buff[MAX_FIELD_WIDTH];
|
||||||
@ -2901,6 +2917,18 @@ my_decimal *Item_func_case::val_decimal(my_decimal *decimal_value)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool Item_func_case::date_op(MYSQL_TIME *ltime, uint fuzzydate)
|
||||||
|
{
|
||||||
|
DBUG_ASSERT(fixed == 1);
|
||||||
|
char buff[MAX_FIELD_WIDTH];
|
||||||
|
String dummy_str(buff, sizeof(buff), default_charset());
|
||||||
|
Item *item= find_item(&dummy_str);
|
||||||
|
if (!item)
|
||||||
|
return (null_value= true);
|
||||||
|
return (null_value= item->get_date(ltime, fuzzydate));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
bool Item_func_case::fix_fields(THD *thd, Item **ref)
|
bool Item_func_case::fix_fields(THD *thd, Item **ref)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
@ -2947,6 +2975,9 @@ void Item_func_case::fix_length_and_dec()
|
|||||||
if (!(agg= (Item**) sql_alloc(sizeof(Item*)*(ncases+1))))
|
if (!(agg= (Item**) sql_alloc(sizeof(Item*)*(ncases+1))))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
if (else_expr_num == -1 || args[else_expr_num]->maybe_null)
|
||||||
|
maybe_null= 1;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Aggregate all THEN and ELSE expression types
|
Aggregate all THEN and ELSE expression types
|
||||||
and collations when string result
|
and collations when string result
|
||||||
@ -2959,13 +2990,29 @@ void Item_func_case::fix_length_and_dec()
|
|||||||
agg[nagg++]= args[else_expr_num];
|
agg[nagg++]= args[else_expr_num];
|
||||||
|
|
||||||
agg_result_type(&cached_result_type, agg, nagg);
|
agg_result_type(&cached_result_type, agg, nagg);
|
||||||
if ((cached_result_type == STRING_RESULT) &&
|
|
||||||
agg_arg_charsets(collation, agg, nagg, MY_COLL_ALLOW_CONV, 1))
|
|
||||||
return;
|
|
||||||
|
|
||||||
cached_field_type= agg_field_type(agg, nagg);
|
cached_field_type= agg_field_type(agg, nagg);
|
||||||
|
|
||||||
|
if (cached_result_type == STRING_RESULT)
|
||||||
|
{
|
||||||
|
if (count_string_result_length(cached_field_type, agg, nagg))
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
max_length= 0;
|
||||||
|
decimals= 0;
|
||||||
|
unsigned_flag= TRUE;
|
||||||
|
for (uint i= 0; i < nagg; i++)
|
||||||
|
agg_num_lengths(agg[i]);
|
||||||
|
if (else_expr_num != -1)
|
||||||
|
agg_num_lengths(args[else_expr_num]);
|
||||||
|
max_length= my_decimal_precision_to_length(max_length + decimals, decimals,
|
||||||
|
unsigned_flag);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Aggregate first expression and all THEN expression types
|
Aggregate first expression and all WHEN expression types
|
||||||
and collations when string comparison
|
and collations when string comparison
|
||||||
*/
|
*/
|
||||||
if (first_expr_num != -1)
|
if (first_expr_num != -1)
|
||||||
@ -3019,29 +3066,6 @@ void Item_func_case::fix_length_and_dec()
|
|||||||
args[i]->cmp_context= item_cmp_type(left_result_type,
|
args[i]->cmp_context= item_cmp_type(left_result_type,
|
||||||
args[i]->result_type());
|
args[i]->result_type());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (else_expr_num == -1 || args[else_expr_num]->maybe_null)
|
|
||||||
maybe_null=1;
|
|
||||||
|
|
||||||
max_length=0;
|
|
||||||
decimals=0;
|
|
||||||
unsigned_flag= TRUE;
|
|
||||||
if (cached_result_type == STRING_RESULT)
|
|
||||||
{
|
|
||||||
for (uint i= 0; i < ncases; i+= 2)
|
|
||||||
agg_str_lengths(args[i + 1]);
|
|
||||||
if (else_expr_num != -1)
|
|
||||||
agg_str_lengths(args[else_expr_num]);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
for (uint i= 0; i < ncases; i+= 2)
|
|
||||||
agg_num_lengths(args[i + 1]);
|
|
||||||
if (else_expr_num != -1)
|
|
||||||
agg_num_lengths(args[else_expr_num]);
|
|
||||||
max_length= my_decimal_precision_to_length(max_length + decimals, decimals,
|
|
||||||
unsigned_flag);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -3149,7 +3173,7 @@ double Item_func_coalesce::real_op()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool Item_func_coalesce::get_date(MYSQL_TIME *ltime,uint fuzzydate)
|
bool Item_func_coalesce::date_op(MYSQL_TIME *ltime,uint fuzzydate)
|
||||||
{
|
{
|
||||||
DBUG_ASSERT(fixed == 1);
|
DBUG_ASSERT(fixed == 1);
|
||||||
null_value= 0;
|
null_value= 0;
|
||||||
@ -3182,20 +3206,11 @@ my_decimal *Item_func_coalesce::decimal_op(my_decimal *decimal_value)
|
|||||||
void Item_func_coalesce::fix_length_and_dec()
|
void Item_func_coalesce::fix_length_and_dec()
|
||||||
{
|
{
|
||||||
cached_field_type= agg_field_type(args, arg_count);
|
cached_field_type= agg_field_type(args, arg_count);
|
||||||
agg_result_type(&hybrid_type, args, arg_count);
|
agg_result_type(&cached_result_type, args, arg_count);
|
||||||
Item_result cmp_type;
|
switch (cached_result_type) {
|
||||||
agg_cmp_type(&cmp_type, args, arg_count);
|
|
||||||
///< @todo let result_type() return TIME_RESULT and remove this special case
|
|
||||||
if (cmp_type == TIME_RESULT)
|
|
||||||
{
|
|
||||||
count_real_length();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
switch (hybrid_type) {
|
|
||||||
case STRING_RESULT:
|
case STRING_RESULT:
|
||||||
count_only_length();
|
if (count_string_result_length(cached_field_type, args, arg_count))
|
||||||
decimals= NOT_FIXED_DEC;
|
return;
|
||||||
agg_arg_charsets(collation, args, arg_count, MY_COLL_ALLOW_CONV, 1);
|
|
||||||
break;
|
break;
|
||||||
case DECIMAL_RESULT:
|
case DECIMAL_RESULT:
|
||||||
count_decimal_length();
|
count_decimal_length();
|
||||||
@ -3204,7 +3219,7 @@ void Item_func_coalesce::fix_length_and_dec()
|
|||||||
count_real_length();
|
count_real_length();
|
||||||
break;
|
break;
|
||||||
case INT_RESULT:
|
case INT_RESULT:
|
||||||
count_only_length();
|
count_only_length(args, arg_count);
|
||||||
decimals= 0;
|
decimals= 0;
|
||||||
break;
|
break;
|
||||||
case ROW_RESULT:
|
case ROW_RESULT:
|
||||||
|
@ -724,24 +724,19 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
class Item_func_coalesce :public Item_func_numhybrid
|
class Item_func_coalesce :public Item_func_hybrid_field_type
|
||||||
{
|
{
|
||||||
protected:
|
|
||||||
enum_field_types cached_field_type;
|
|
||||||
Item_func_coalesce(Item *a, Item *b) :Item_func_numhybrid(a, b) {}
|
|
||||||
public:
|
public:
|
||||||
Item_func_coalesce(List<Item> &list) :Item_func_numhybrid(list) {}
|
Item_func_coalesce(Item *a, Item *b) :Item_func_hybrid_field_type(a, b) {}
|
||||||
|
Item_func_coalesce(List<Item> &list) :Item_func_hybrid_field_type(list) {}
|
||||||
double real_op();
|
double real_op();
|
||||||
longlong int_op();
|
longlong int_op();
|
||||||
String *str_op(String *);
|
String *str_op(String *);
|
||||||
my_decimal *decimal_op(my_decimal *);
|
my_decimal *decimal_op(my_decimal *);
|
||||||
|
bool date_op(MYSQL_TIME *ltime,uint fuzzydate);
|
||||||
void fix_length_and_dec();
|
void fix_length_and_dec();
|
||||||
void find_num_type() {}
|
|
||||||
enum Item_result result_type () const { return hybrid_type; }
|
|
||||||
const char *func_name() const { return "coalesce"; }
|
const char *func_name() const { return "coalesce"; }
|
||||||
table_map not_null_tables() const { return 0; }
|
table_map not_null_tables() const { return 0; }
|
||||||
enum_field_types field_type() const { return cached_field_type; }
|
|
||||||
bool get_date(MYSQL_TIME *ltime,uint fuzzydate);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -755,7 +750,7 @@ public:
|
|||||||
longlong int_op();
|
longlong int_op();
|
||||||
String *str_op(String *str);
|
String *str_op(String *str);
|
||||||
my_decimal *decimal_op(my_decimal *);
|
my_decimal *decimal_op(my_decimal *);
|
||||||
enum_field_types field_type() const;
|
bool date_op(MYSQL_TIME *ltime,uint fuzzydate);
|
||||||
void fix_length_and_dec();
|
void fix_length_and_dec();
|
||||||
void update_used_tables()
|
void update_used_tables()
|
||||||
{
|
{
|
||||||
@ -768,20 +763,17 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
class Item_func_if :public Item_func
|
class Item_func_if :public Item_func_hybrid_field_type
|
||||||
{
|
{
|
||||||
enum Item_result cached_result_type;
|
|
||||||
enum_field_types cached_field_type;
|
|
||||||
public:
|
public:
|
||||||
Item_func_if(Item *a,Item *b,Item *c)
|
Item_func_if(Item *a,Item *b,Item *c)
|
||||||
:Item_func(a,b,c), cached_result_type(INT_RESULT)
|
:Item_func_hybrid_field_type(a,b,c)
|
||||||
{}
|
{}
|
||||||
double val_real();
|
bool date_op(MYSQL_TIME *ltime, uint fuzzydate);
|
||||||
longlong val_int();
|
longlong int_op();
|
||||||
String *val_str(String *str);
|
double real_op();
|
||||||
my_decimal *val_decimal(my_decimal *);
|
my_decimal *decimal_op(my_decimal *);
|
||||||
enum Item_result result_type () const { return cached_result_type; }
|
String *str_op(String *);
|
||||||
enum_field_types field_type() const { return cached_field_type; }
|
|
||||||
bool fix_fields(THD *, Item **);
|
bool fix_fields(THD *, Item **);
|
||||||
void fix_length_and_dec();
|
void fix_length_and_dec();
|
||||||
void update_used_tables()
|
void update_used_tables()
|
||||||
@ -1216,21 +1208,20 @@ public:
|
|||||||
function and only comparators for there result types are used.
|
function and only comparators for there result types are used.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
class Item_func_case :public Item_func
|
class Item_func_case :public Item_func_hybrid_field_type
|
||||||
{
|
{
|
||||||
int first_expr_num, else_expr_num;
|
int first_expr_num, else_expr_num;
|
||||||
enum Item_result cached_result_type, left_result_type;
|
enum Item_result left_result_type;
|
||||||
String tmp_value;
|
String tmp_value;
|
||||||
uint ncases;
|
uint ncases;
|
||||||
Item_result cmp_type;
|
Item_result cmp_type;
|
||||||
DTCollation cmp_collation;
|
DTCollation cmp_collation;
|
||||||
enum_field_types cached_field_type;
|
|
||||||
cmp_item *cmp_items[6]; /* For all result types */
|
cmp_item *cmp_items[6]; /* For all result types */
|
||||||
cmp_item *case_item;
|
cmp_item *case_item;
|
||||||
public:
|
public:
|
||||||
Item_func_case(List<Item> &list, Item *first_expr_arg, Item *else_expr_arg)
|
Item_func_case(List<Item> &list, Item *first_expr_arg, Item *else_expr_arg)
|
||||||
:Item_func(), first_expr_num(-1), else_expr_num(-1),
|
:Item_func_hybrid_field_type(), first_expr_num(-1), else_expr_num(-1),
|
||||||
cached_result_type(INT_RESULT), left_result_type(INT_RESULT), case_item(0)
|
left_result_type(INT_RESULT), case_item(0)
|
||||||
{
|
{
|
||||||
ncases= list.elements;
|
ncases= list.elements;
|
||||||
if (first_expr_arg)
|
if (first_expr_arg)
|
||||||
@ -1246,10 +1237,11 @@ public:
|
|||||||
set_arguments(list);
|
set_arguments(list);
|
||||||
bzero(&cmp_items, sizeof(cmp_items));
|
bzero(&cmp_items, sizeof(cmp_items));
|
||||||
}
|
}
|
||||||
double val_real();
|
double real_op();
|
||||||
longlong val_int();
|
longlong int_op();
|
||||||
String *val_str(String *);
|
String *str_op(String *);
|
||||||
my_decimal *val_decimal(my_decimal *);
|
my_decimal *decimal_op(my_decimal *);
|
||||||
|
bool date_op(MYSQL_TIME *ltime, uint fuzzydate);
|
||||||
bool fix_fields(THD *thd, Item **ref);
|
bool fix_fields(THD *thd, Item **ref);
|
||||||
void fix_length_and_dec();
|
void fix_length_and_dec();
|
||||||
void update_used_tables()
|
void update_used_tables()
|
||||||
@ -1260,8 +1252,6 @@ public:
|
|||||||
}
|
}
|
||||||
uint decimal_precision() const;
|
uint decimal_precision() const;
|
||||||
table_map not_null_tables() const { return 0; }
|
table_map not_null_tables() const { return 0; }
|
||||||
enum Item_result result_type () const { return cached_result_type; }
|
|
||||||
enum_field_types field_type() const { return cached_field_type; }
|
|
||||||
const char *func_name() const { return "case"; }
|
const char *func_name() const { return "case"; }
|
||||||
virtual void print(String *str, enum_query_type query_type);
|
virtual void print(String *str, enum_query_type query_type);
|
||||||
Item *find_item(String *str);
|
Item *find_item(String *str);
|
||||||
|
238
sql/item_func.cc
238
sql/item_func.cc
@ -594,6 +594,30 @@ void Item_func_numhybrid::fix_num_length_and_dec()
|
|||||||
{}
|
{}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
Count max_length and decimals for temporal functions.
|
||||||
|
|
||||||
|
@param item Argument array
|
||||||
|
@param nitems Number of arguments in the array.
|
||||||
|
|
||||||
|
@retval False on success, true on error.
|
||||||
|
*/
|
||||||
|
void Item_func::count_datetime_length(Item **item, uint nitems)
|
||||||
|
{
|
||||||
|
unsigned_flag= 0;
|
||||||
|
decimals= 0;
|
||||||
|
if (field_type() != MYSQL_TYPE_DATE)
|
||||||
|
{
|
||||||
|
for (uint i= 0; i < nitems; i++)
|
||||||
|
set_if_bigger(decimals, item[i]->decimals);
|
||||||
|
}
|
||||||
|
set_if_smaller(decimals, TIME_SECOND_PART_DIGITS);
|
||||||
|
uint len= decimals ? (decimals + 1) : 0;
|
||||||
|
len+= mysql_temporal_int_part_length(field_type());
|
||||||
|
fix_char_length(len);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Set max_length/decimals of function if function is fixed point and
|
Set max_length/decimals of function if function is fixed point and
|
||||||
result length/precision depends on argument ones.
|
result length/precision depends on argument ones.
|
||||||
@ -620,14 +644,14 @@ void Item_func::count_decimal_length()
|
|||||||
Set max_length of if it is maximum length of its arguments.
|
Set max_length of if it is maximum length of its arguments.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void Item_func::count_only_length()
|
void Item_func::count_only_length(Item **item, uint nitems)
|
||||||
{
|
{
|
||||||
max_length= 0;
|
max_length= 0;
|
||||||
unsigned_flag= 0;
|
unsigned_flag= 0;
|
||||||
for (uint i=0 ; i < arg_count ; i++)
|
for (uint i= 0; i < nitems ; i++)
|
||||||
{
|
{
|
||||||
set_if_bigger(max_length, args[i]->max_length);
|
set_if_bigger(max_length, item[i]->max_length);
|
||||||
set_if_bigger(unsigned_flag, args[i]->unsigned_flag);
|
set_if_bigger(unsigned_flag, item[i]->unsigned_flag);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -663,6 +687,30 @@ void Item_func::count_real_length()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
Calculate max_length and decimals for STRING_RESULT functions.
|
||||||
|
|
||||||
|
@param field_type Field type.
|
||||||
|
@param items Argument array.
|
||||||
|
@param nitems Number of arguments.
|
||||||
|
|
||||||
|
@retval False on success, true on error.
|
||||||
|
*/
|
||||||
|
bool Item_func::count_string_result_length(enum_field_types field_type,
|
||||||
|
Item **items, uint nitems)
|
||||||
|
{
|
||||||
|
if (agg_arg_charsets(collation, items, nitems, MY_COLL_ALLOW_CONV, 1))
|
||||||
|
return true;
|
||||||
|
if (is_temporal_type(field_type))
|
||||||
|
count_datetime_length(items, nitems);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
decimals= NOT_FIXED_DEC; // TODO
|
||||||
|
count_only_length(items, nitems);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void Item_func::signal_divide_by_null()
|
void Item_func::signal_divide_by_null()
|
||||||
{
|
{
|
||||||
@ -735,26 +783,26 @@ void Item_num_op::find_num_type(void)
|
|||||||
{
|
{
|
||||||
count_real_length();
|
count_real_length();
|
||||||
max_length= float_length(decimals);
|
max_length= float_length(decimals);
|
||||||
hybrid_type= REAL_RESULT;
|
cached_result_type= REAL_RESULT;
|
||||||
}
|
}
|
||||||
else if (r0 == DECIMAL_RESULT || r1 == DECIMAL_RESULT ||
|
else if (r0 == DECIMAL_RESULT || r1 == DECIMAL_RESULT ||
|
||||||
r0 == TIME_RESULT || r1 == TIME_RESULT)
|
r0 == TIME_RESULT || r1 == TIME_RESULT)
|
||||||
{
|
{
|
||||||
hybrid_type= DECIMAL_RESULT;
|
cached_result_type= DECIMAL_RESULT;
|
||||||
result_precision();
|
result_precision();
|
||||||
fix_decimals();
|
fix_decimals();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
DBUG_ASSERT(r0 == INT_RESULT && r1 == INT_RESULT);
|
DBUG_ASSERT(r0 == INT_RESULT && r1 == INT_RESULT);
|
||||||
hybrid_type=INT_RESULT;
|
cached_result_type=INT_RESULT;
|
||||||
result_precision();
|
result_precision();
|
||||||
decimals= 0;
|
decimals= 0;
|
||||||
}
|
}
|
||||||
DBUG_PRINT("info", ("Type: %s",
|
DBUG_PRINT("info", ("Type: %s",
|
||||||
(hybrid_type == REAL_RESULT ? "REAL_RESULT" :
|
(cached_result_type == REAL_RESULT ? "REAL_RESULT" :
|
||||||
hybrid_type == DECIMAL_RESULT ? "DECIMAL_RESULT" :
|
cached_result_type == DECIMAL_RESULT ? "DECIMAL_RESULT" :
|
||||||
hybrid_type == INT_RESULT ? "INT_RESULT" :
|
cached_result_type == INT_RESULT ? "INT_RESULT" :
|
||||||
"--ILLEGAL!!!--")));
|
"--ILLEGAL!!!--")));
|
||||||
DBUG_VOID_RETURN;
|
DBUG_VOID_RETURN;
|
||||||
}
|
}
|
||||||
@ -770,17 +818,17 @@ void Item_func_num1::find_num_type()
|
|||||||
{
|
{
|
||||||
DBUG_ENTER("Item_func_num1::find_num_type");
|
DBUG_ENTER("Item_func_num1::find_num_type");
|
||||||
DBUG_PRINT("info", ("name %s", func_name()));
|
DBUG_PRINT("info", ("name %s", func_name()));
|
||||||
switch (hybrid_type= args[0]->cast_to_int_type()) {
|
switch (cached_result_type= args[0]->cast_to_int_type()) {
|
||||||
case INT_RESULT:
|
case INT_RESULT:
|
||||||
unsigned_flag= args[0]->unsigned_flag;
|
unsigned_flag= args[0]->unsigned_flag;
|
||||||
break;
|
break;
|
||||||
case STRING_RESULT:
|
case STRING_RESULT:
|
||||||
case REAL_RESULT:
|
case REAL_RESULT:
|
||||||
hybrid_type= REAL_RESULT;
|
cached_result_type= REAL_RESULT;
|
||||||
max_length= float_length(decimals);
|
max_length= float_length(decimals);
|
||||||
break;
|
break;
|
||||||
case TIME_RESULT:
|
case TIME_RESULT:
|
||||||
hybrid_type= DECIMAL_RESULT;
|
cached_result_type= DECIMAL_RESULT;
|
||||||
case DECIMAL_RESULT:
|
case DECIMAL_RESULT:
|
||||||
break;
|
break;
|
||||||
case ROW_RESULT:
|
case ROW_RESULT:
|
||||||
@ -788,9 +836,9 @@ void Item_func_num1::find_num_type()
|
|||||||
DBUG_ASSERT(0);
|
DBUG_ASSERT(0);
|
||||||
}
|
}
|
||||||
DBUG_PRINT("info", ("Type: %s",
|
DBUG_PRINT("info", ("Type: %s",
|
||||||
(hybrid_type == REAL_RESULT ? "REAL_RESULT" :
|
(cached_result_type == REAL_RESULT ? "REAL_RESULT" :
|
||||||
hybrid_type == DECIMAL_RESULT ? "DECIMAL_RESULT" :
|
cached_result_type == DECIMAL_RESULT ? "DECIMAL_RESULT" :
|
||||||
hybrid_type == INT_RESULT ? "INT_RESULT" :
|
cached_result_type == INT_RESULT ? "INT_RESULT" :
|
||||||
"--ILLEGAL!!!--")));
|
"--ILLEGAL!!!--")));
|
||||||
DBUG_VOID_RETURN;
|
DBUG_VOID_RETURN;
|
||||||
}
|
}
|
||||||
@ -810,10 +858,10 @@ void Item_func_numhybrid::fix_length_and_dec()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
String *Item_func_numhybrid::val_str(String *str)
|
String *Item_func_hybrid_result_type::val_str(String *str)
|
||||||
{
|
{
|
||||||
DBUG_ASSERT(fixed == 1);
|
DBUG_ASSERT(fixed == 1);
|
||||||
switch (hybrid_type) {
|
switch (cached_result_type) {
|
||||||
case DECIMAL_RESULT:
|
case DECIMAL_RESULT:
|
||||||
{
|
{
|
||||||
my_decimal decimal_value, *val;
|
my_decimal decimal_value, *val;
|
||||||
@ -840,6 +888,21 @@ String *Item_func_numhybrid::val_str(String *str)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case STRING_RESULT:
|
case STRING_RESULT:
|
||||||
|
if (is_temporal_type(field_type()))
|
||||||
|
{
|
||||||
|
MYSQL_TIME ltime;
|
||||||
|
if (date_op(<ime,
|
||||||
|
field_type() == MYSQL_TYPE_TIME ? TIME_TIME_ONLY : 0) ||
|
||||||
|
str->alloc(MAX_DATE_STRING_REP_LENGTH))
|
||||||
|
{
|
||||||
|
null_value= 1;
|
||||||
|
return (String *) 0;
|
||||||
|
}
|
||||||
|
ltime.time_type= mysql_type_to_time_type(field_type());
|
||||||
|
str->length(my_TIME_to_str(<ime, const_cast<char*>(str->ptr()), decimals));
|
||||||
|
str->set_charset(&my_charset_bin);
|
||||||
|
return str;
|
||||||
|
}
|
||||||
return str_op(&str_value);
|
return str_op(&str_value);
|
||||||
case TIME_RESULT:
|
case TIME_RESULT:
|
||||||
case ROW_RESULT:
|
case ROW_RESULT:
|
||||||
@ -850,10 +913,10 @@ String *Item_func_numhybrid::val_str(String *str)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
double Item_func_numhybrid::val_real()
|
double Item_func_hybrid_result_type::val_real()
|
||||||
{
|
{
|
||||||
DBUG_ASSERT(fixed == 1);
|
DBUG_ASSERT(fixed == 1);
|
||||||
switch (hybrid_type) {
|
switch (cached_result_type) {
|
||||||
case DECIMAL_RESULT:
|
case DECIMAL_RESULT:
|
||||||
{
|
{
|
||||||
my_decimal decimal_value, *val;
|
my_decimal decimal_value, *val;
|
||||||
@ -872,6 +935,18 @@ double Item_func_numhybrid::val_real()
|
|||||||
return real_op();
|
return real_op();
|
||||||
case STRING_RESULT:
|
case STRING_RESULT:
|
||||||
{
|
{
|
||||||
|
if (is_temporal_type(field_type()))
|
||||||
|
{
|
||||||
|
MYSQL_TIME ltime;
|
||||||
|
if (date_op(<ime,
|
||||||
|
field_type() == MYSQL_TYPE_TIME ? TIME_TIME_ONLY : 0 ))
|
||||||
|
{
|
||||||
|
null_value= 1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
ltime.time_type= mysql_type_to_time_type(field_type());
|
||||||
|
return TIME_to_double(<ime);
|
||||||
|
}
|
||||||
char *end_not_used;
|
char *end_not_used;
|
||||||
int err_not_used;
|
int err_not_used;
|
||||||
String *res= str_op(&str_value);
|
String *res= str_op(&str_value);
|
||||||
@ -887,10 +962,10 @@ double Item_func_numhybrid::val_real()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
longlong Item_func_numhybrid::val_int()
|
longlong Item_func_hybrid_result_type::val_int()
|
||||||
{
|
{
|
||||||
DBUG_ASSERT(fixed == 1);
|
DBUG_ASSERT(fixed == 1);
|
||||||
switch (hybrid_type) {
|
switch (cached_result_type) {
|
||||||
case DECIMAL_RESULT:
|
case DECIMAL_RESULT:
|
||||||
{
|
{
|
||||||
my_decimal decimal_value, *val;
|
my_decimal decimal_value, *val;
|
||||||
@ -906,6 +981,18 @@ longlong Item_func_numhybrid::val_int()
|
|||||||
return (longlong) rint(real_op());
|
return (longlong) rint(real_op());
|
||||||
case STRING_RESULT:
|
case STRING_RESULT:
|
||||||
{
|
{
|
||||||
|
if (is_temporal_type(field_type()))
|
||||||
|
{
|
||||||
|
MYSQL_TIME ltime;
|
||||||
|
if (date_op(<ime,
|
||||||
|
field_type() == MYSQL_TYPE_TIME ? TIME_TIME_ONLY : 0))
|
||||||
|
{
|
||||||
|
null_value= 1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
ltime.time_type= mysql_type_to_time_type(field_type());
|
||||||
|
return TIME_to_ulonglong(<ime);
|
||||||
|
}
|
||||||
int err_not_used;
|
int err_not_used;
|
||||||
String *res;
|
String *res;
|
||||||
if (!(res= str_op(&str_value)))
|
if (!(res= str_op(&str_value)))
|
||||||
@ -924,11 +1011,11 @@ longlong Item_func_numhybrid::val_int()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
my_decimal *Item_func_numhybrid::val_decimal(my_decimal *decimal_value)
|
my_decimal *Item_func_hybrid_result_type::val_decimal(my_decimal *decimal_value)
|
||||||
{
|
{
|
||||||
my_decimal *val= decimal_value;
|
my_decimal *val= decimal_value;
|
||||||
DBUG_ASSERT(fixed == 1);
|
DBUG_ASSERT(fixed == 1);
|
||||||
switch (hybrid_type) {
|
switch (cached_result_type) {
|
||||||
case DECIMAL_RESULT:
|
case DECIMAL_RESULT:
|
||||||
val= decimal_op(decimal_value);
|
val= decimal_op(decimal_value);
|
||||||
break;
|
break;
|
||||||
@ -946,6 +1033,19 @@ my_decimal *Item_func_numhybrid::val_decimal(my_decimal *decimal_value)
|
|||||||
}
|
}
|
||||||
case STRING_RESULT:
|
case STRING_RESULT:
|
||||||
{
|
{
|
||||||
|
if (is_temporal_type(field_type()))
|
||||||
|
{
|
||||||
|
MYSQL_TIME ltime;
|
||||||
|
if (date_op(<ime,
|
||||||
|
field_type() == MYSQL_TYPE_TIME ? TIME_TIME_ONLY : 0))
|
||||||
|
{
|
||||||
|
my_decimal_set_zero(decimal_value);
|
||||||
|
null_value= 1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
ltime.time_type= mysql_type_to_time_type(field_type());
|
||||||
|
return date2my_decimal(<ime, decimal_value);
|
||||||
|
}
|
||||||
String *res;
|
String *res;
|
||||||
if (!(res= str_op(&str_value)))
|
if (!(res= str_op(&str_value)))
|
||||||
return NULL;
|
return NULL;
|
||||||
@ -963,6 +1063,62 @@ my_decimal *Item_func_numhybrid::val_decimal(my_decimal *decimal_value)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool Item_func_hybrid_result_type::get_date(MYSQL_TIME *ltime, uint fuzzydate)
|
||||||
|
{
|
||||||
|
DBUG_ASSERT(fixed == 1);
|
||||||
|
switch (cached_result_type) {
|
||||||
|
case DECIMAL_RESULT:
|
||||||
|
{
|
||||||
|
my_decimal value, *res;
|
||||||
|
if (!(res= decimal_op(&value)) ||
|
||||||
|
decimal_to_datetime_with_warn(res, ltime, fuzzydate,
|
||||||
|
field_name_or_null()))
|
||||||
|
goto err;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case INT_RESULT:
|
||||||
|
{
|
||||||
|
longlong value= int_op();
|
||||||
|
if (null_value || int_to_datetime_with_warn(value, ltime, fuzzydate,
|
||||||
|
field_name_or_null()))
|
||||||
|
goto err;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case REAL_RESULT:
|
||||||
|
{
|
||||||
|
double value= real_op();
|
||||||
|
if (null_value || double_to_datetime_with_warn(value, ltime, fuzzydate,
|
||||||
|
field_name_or_null()))
|
||||||
|
goto err;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case STRING_RESULT:
|
||||||
|
{
|
||||||
|
if (is_temporal_type(field_type()))
|
||||||
|
return date_op(ltime, fuzzydate);
|
||||||
|
char buff[40];
|
||||||
|
String tmp(buff,sizeof(buff), &my_charset_bin),*res;
|
||||||
|
if (!(res= str_op(&tmp)) ||
|
||||||
|
str_to_datetime_with_warn(res->ptr(), res->length(),
|
||||||
|
ltime, fuzzydate) <= MYSQL_TIMESTAMP_ERROR)
|
||||||
|
goto err;
|
||||||
|
break;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case ROW_RESULT:
|
||||||
|
case TIME_RESULT:
|
||||||
|
case IMPOSSIBLE_RESULT:
|
||||||
|
DBUG_ASSERT(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (null_value= 0);
|
||||||
|
|
||||||
|
err:
|
||||||
|
bzero(ltime, sizeof(*ltime));
|
||||||
|
return null_value|= !(fuzzydate & TIME_FUZZY_DATES);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void Item_func_signed::print(String *str, enum_query_type query_type)
|
void Item_func_signed::print(String *str, enum_query_type query_type)
|
||||||
{
|
{
|
||||||
str->append(STRING_WITH_LEN("cast("));
|
str->append(STRING_WITH_LEN("cast("));
|
||||||
@ -1471,7 +1627,7 @@ void Item_func_div::fix_length_and_dec()
|
|||||||
DBUG_ENTER("Item_func_div::fix_length_and_dec");
|
DBUG_ENTER("Item_func_div::fix_length_and_dec");
|
||||||
prec_increment= current_thd->variables.div_precincrement;
|
prec_increment= current_thd->variables.div_precincrement;
|
||||||
Item_num_op::fix_length_and_dec();
|
Item_num_op::fix_length_and_dec();
|
||||||
switch (hybrid_type) {
|
switch (cached_result_type) {
|
||||||
case REAL_RESULT:
|
case REAL_RESULT:
|
||||||
{
|
{
|
||||||
decimals=max(args[0]->decimals,args[1]->decimals)+prec_increment;
|
decimals=max(args[0]->decimals,args[1]->decimals)+prec_increment;
|
||||||
@ -1487,7 +1643,7 @@ void Item_func_div::fix_length_and_dec()
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case INT_RESULT:
|
case INT_RESULT:
|
||||||
hybrid_type= DECIMAL_RESULT;
|
cached_result_type= DECIMAL_RESULT;
|
||||||
DBUG_PRINT("info", ("Type changed: DECIMAL_RESULT"));
|
DBUG_PRINT("info", ("Type changed: DECIMAL_RESULT"));
|
||||||
result_precision();
|
result_precision();
|
||||||
break;
|
break;
|
||||||
@ -1670,7 +1826,7 @@ void Item_func_neg::fix_length_and_dec()
|
|||||||
Use val() to get value as arg_type doesn't mean that item is
|
Use val() to get value as arg_type doesn't mean that item is
|
||||||
Item_int or Item_real due to existence of Item_param.
|
Item_int or Item_real due to existence of Item_param.
|
||||||
*/
|
*/
|
||||||
if (hybrid_type == INT_RESULT && args[0]->const_item())
|
if (cached_result_type == INT_RESULT && args[0]->const_item())
|
||||||
{
|
{
|
||||||
longlong val= args[0]->val_int();
|
longlong val= args[0]->val_int();
|
||||||
if ((ulonglong) val >= (ulonglong) LONGLONG_MIN &&
|
if ((ulonglong) val >= (ulonglong) LONGLONG_MIN &&
|
||||||
@ -1681,7 +1837,7 @@ void Item_func_neg::fix_length_and_dec()
|
|||||||
Ensure that result is converted to DECIMAL, as longlong can't hold
|
Ensure that result is converted to DECIMAL, as longlong can't hold
|
||||||
the negated number
|
the negated number
|
||||||
*/
|
*/
|
||||||
hybrid_type= DECIMAL_RESULT;
|
cached_result_type= DECIMAL_RESULT;
|
||||||
DBUG_PRINT("info", ("Type changed: DECIMAL_RESULT"));
|
DBUG_PRINT("info", ("Type changed: DECIMAL_RESULT"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1968,11 +2124,11 @@ void Item_func_int_val::find_num_type()
|
|||||||
{
|
{
|
||||||
DBUG_ENTER("Item_func_int_val::find_num_type");
|
DBUG_ENTER("Item_func_int_val::find_num_type");
|
||||||
DBUG_PRINT("info", ("name %s", func_name()));
|
DBUG_PRINT("info", ("name %s", func_name()));
|
||||||
switch (hybrid_type= args[0]->cast_to_int_type())
|
switch (cached_result_type= args[0]->cast_to_int_type())
|
||||||
{
|
{
|
||||||
case STRING_RESULT:
|
case STRING_RESULT:
|
||||||
case REAL_RESULT:
|
case REAL_RESULT:
|
||||||
hybrid_type= REAL_RESULT;
|
cached_result_type= REAL_RESULT;
|
||||||
max_length= float_length(decimals);
|
max_length= float_length(decimals);
|
||||||
break;
|
break;
|
||||||
case INT_RESULT:
|
case INT_RESULT:
|
||||||
@ -1985,12 +2141,12 @@ void Item_func_int_val::find_num_type()
|
|||||||
if ((args[0]->max_length - args[0]->decimals) >=
|
if ((args[0]->max_length - args[0]->decimals) >=
|
||||||
(DECIMAL_LONGLONG_DIGITS - 2))
|
(DECIMAL_LONGLONG_DIGITS - 2))
|
||||||
{
|
{
|
||||||
hybrid_type= DECIMAL_RESULT;
|
cached_result_type= DECIMAL_RESULT;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
unsigned_flag= args[0]->unsigned_flag;
|
unsigned_flag= args[0]->unsigned_flag;
|
||||||
hybrid_type= INT_RESULT;
|
cached_result_type= INT_RESULT;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case ROW_RESULT:
|
case ROW_RESULT:
|
||||||
@ -1998,9 +2154,9 @@ void Item_func_int_val::find_num_type()
|
|||||||
DBUG_ASSERT(0);
|
DBUG_ASSERT(0);
|
||||||
}
|
}
|
||||||
DBUG_PRINT("info", ("Type: %s",
|
DBUG_PRINT("info", ("Type: %s",
|
||||||
(hybrid_type == REAL_RESULT ? "REAL_RESULT" :
|
(cached_result_type == REAL_RESULT ? "REAL_RESULT" :
|
||||||
hybrid_type == DECIMAL_RESULT ? "DECIMAL_RESULT" :
|
cached_result_type == DECIMAL_RESULT ? "DECIMAL_RESULT" :
|
||||||
hybrid_type == INT_RESULT ? "INT_RESULT" :
|
cached_result_type == INT_RESULT ? "INT_RESULT" :
|
||||||
"--ILLEGAL!!!--")));
|
"--ILLEGAL!!!--")));
|
||||||
|
|
||||||
DBUG_VOID_RETURN;
|
DBUG_VOID_RETURN;
|
||||||
@ -2115,10 +2271,10 @@ void Item_func_round::fix_length_and_dec()
|
|||||||
if (args[0]->result_type() == DECIMAL_RESULT)
|
if (args[0]->result_type() == DECIMAL_RESULT)
|
||||||
{
|
{
|
||||||
max_length++;
|
max_length++;
|
||||||
hybrid_type= DECIMAL_RESULT;
|
cached_result_type= DECIMAL_RESULT;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
hybrid_type= REAL_RESULT;
|
cached_result_type= REAL_RESULT;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2136,14 +2292,14 @@ void Item_func_round::fix_length_and_dec()
|
|||||||
{
|
{
|
||||||
decimals= min(decimals_to_set, NOT_FIXED_DEC);
|
decimals= min(decimals_to_set, NOT_FIXED_DEC);
|
||||||
max_length= float_length(decimals);
|
max_length= float_length(decimals);
|
||||||
hybrid_type= REAL_RESULT;
|
cached_result_type= REAL_RESULT;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (args[0]->result_type()) {
|
switch (args[0]->result_type()) {
|
||||||
case REAL_RESULT:
|
case REAL_RESULT:
|
||||||
case STRING_RESULT:
|
case STRING_RESULT:
|
||||||
hybrid_type= REAL_RESULT;
|
cached_result_type= REAL_RESULT;
|
||||||
decimals= min(decimals_to_set, NOT_FIXED_DEC);
|
decimals= min(decimals_to_set, NOT_FIXED_DEC);
|
||||||
max_length= float_length(decimals);
|
max_length= float_length(decimals);
|
||||||
break;
|
break;
|
||||||
@ -2153,14 +2309,14 @@ void Item_func_round::fix_length_and_dec()
|
|||||||
int length_can_increase= test(!truncate && (val1 < 0) && !val1_unsigned);
|
int length_can_increase= test(!truncate && (val1 < 0) && !val1_unsigned);
|
||||||
max_length= args[0]->max_length + length_can_increase;
|
max_length= args[0]->max_length + length_can_increase;
|
||||||
/* Here we can keep INT_RESULT */
|
/* Here we can keep INT_RESULT */
|
||||||
hybrid_type= INT_RESULT;
|
cached_result_type= INT_RESULT;
|
||||||
decimals= 0;
|
decimals= 0;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
/* fall through */
|
/* fall through */
|
||||||
case DECIMAL_RESULT:
|
case DECIMAL_RESULT:
|
||||||
{
|
{
|
||||||
hybrid_type= DECIMAL_RESULT;
|
cached_result_type= DECIMAL_RESULT;
|
||||||
decimals_to_set= min(DECIMAL_MAX_SCALE, decimals_to_set);
|
decimals_to_set= min(DECIMAL_MAX_SCALE, decimals_to_set);
|
||||||
int decimals_delta= args[0]->decimals - decimals_to_set;
|
int decimals_delta= args[0]->decimals - decimals_to_set;
|
||||||
int precision= args[0]->decimal_precision();
|
int precision= args[0]->decimal_precision();
|
||||||
|
108
sql/item_func.h
108
sql/item_func.h
@ -148,9 +148,12 @@ public:
|
|||||||
void print_op(String *str, enum_query_type query_type);
|
void print_op(String *str, enum_query_type query_type);
|
||||||
void print_args(String *str, uint from, enum_query_type query_type);
|
void print_args(String *str, uint from, enum_query_type query_type);
|
||||||
virtual void fix_num_length_and_dec();
|
virtual void fix_num_length_and_dec();
|
||||||
void count_only_length();
|
void count_only_length(Item **item, uint nitems);
|
||||||
void count_real_length();
|
void count_real_length();
|
||||||
void count_decimal_length();
|
void count_decimal_length();
|
||||||
|
void count_datetime_length(Item **item, uint nitems);
|
||||||
|
bool count_string_result_length(enum_field_types field_type,
|
||||||
|
Item **item, uint nitems);
|
||||||
inline bool get_arg0_date(MYSQL_TIME *ltime, uint fuzzy_date)
|
inline bool get_arg0_date(MYSQL_TIME *ltime, uint fuzzy_date)
|
||||||
{
|
{
|
||||||
return (null_value=args[0]->get_date(ltime, fuzzy_date));
|
return (null_value=args[0]->get_date(ltime, fuzzy_date));
|
||||||
@ -327,38 +330,33 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
class Item_func_numhybrid: public Item_func
|
class Item_func_hybrid_result_type: public Item_func
|
||||||
{
|
{
|
||||||
protected:
|
protected:
|
||||||
Item_result hybrid_type;
|
Item_result cached_result_type;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Item_func_numhybrid() :Item_func(), hybrid_type(REAL_RESULT)
|
Item_func_hybrid_result_type() :Item_func(), cached_result_type(REAL_RESULT)
|
||||||
{}
|
{}
|
||||||
Item_func_numhybrid(Item *a) :Item_func(a), hybrid_type(REAL_RESULT)
|
Item_func_hybrid_result_type(Item *a) :Item_func(a), cached_result_type(REAL_RESULT)
|
||||||
{}
|
{}
|
||||||
Item_func_numhybrid(Item *a,Item *b)
|
Item_func_hybrid_result_type(Item *a,Item *b)
|
||||||
:Item_func(a,b), hybrid_type(REAL_RESULT)
|
:Item_func(a,b), cached_result_type(REAL_RESULT)
|
||||||
{}
|
{}
|
||||||
Item_func_numhybrid(List<Item> &list)
|
Item_func_hybrid_result_type(Item *a,Item *b,Item *c)
|
||||||
:Item_func(list), hybrid_type(REAL_RESULT)
|
:Item_func(a,b,c), cached_result_type(REAL_RESULT)
|
||||||
|
{}
|
||||||
|
Item_func_hybrid_result_type(List<Item> &list)
|
||||||
|
:Item_func(list), cached_result_type(REAL_RESULT)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
enum Item_result result_type () const { return hybrid_type; }
|
enum Item_result result_type () const { return cached_result_type; }
|
||||||
void fix_length_and_dec();
|
|
||||||
void fix_num_length_and_dec();
|
|
||||||
virtual void find_num_type()= 0; /* To be called from fix_length_and_dec */
|
|
||||||
|
|
||||||
inline void fix_decimals()
|
|
||||||
{
|
|
||||||
DBUG_ASSERT(result_type() == DECIMAL_RESULT);
|
|
||||||
if (decimals == NOT_FIXED_DEC)
|
|
||||||
set_if_smaller(decimals, max_length - 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
double val_real();
|
double val_real();
|
||||||
longlong val_int();
|
longlong val_int();
|
||||||
my_decimal *val_decimal(my_decimal *);
|
my_decimal *val_decimal(my_decimal *);
|
||||||
String *val_str(String*str);
|
String *val_str(String*str);
|
||||||
|
bool get_date(MYSQL_TIME *res, uint fuzzy_date);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@brief Performs the operation that this functions implements when the
|
@brief Performs the operation that this functions implements when the
|
||||||
@ -395,9 +393,75 @@ public:
|
|||||||
@return The result of the operation.
|
@return The result of the operation.
|
||||||
*/
|
*/
|
||||||
virtual String *str_op(String *)= 0;
|
virtual String *str_op(String *)= 0;
|
||||||
bool is_null() { update_null_value(); return null_value; }
|
|
||||||
|
/**
|
||||||
|
@brief Performs the operation that this functions implements when
|
||||||
|
field type is a temporal type.
|
||||||
|
@return The result of the operation.
|
||||||
|
*/
|
||||||
|
virtual bool date_op(MYSQL_TIME *res, uint fuzzy_date)= 0;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class Item_func_hybrid_field_type :public Item_func_hybrid_result_type
|
||||||
|
{
|
||||||
|
protected:
|
||||||
|
enum_field_types cached_field_type;
|
||||||
|
public:
|
||||||
|
Item_func_hybrid_field_type()
|
||||||
|
:Item_func_hybrid_result_type(), cached_field_type(MYSQL_TYPE_DOUBLE)
|
||||||
|
{}
|
||||||
|
Item_func_hybrid_field_type(Item *a, Item *b)
|
||||||
|
:Item_func_hybrid_result_type(a, b), cached_field_type(MYSQL_TYPE_DOUBLE)
|
||||||
|
{}
|
||||||
|
Item_func_hybrid_field_type(Item *a, Item *b, Item *c)
|
||||||
|
:Item_func_hybrid_result_type(a, b, c),
|
||||||
|
cached_field_type(MYSQL_TYPE_DOUBLE)
|
||||||
|
{}
|
||||||
|
Item_func_hybrid_field_type(List<Item> &list)
|
||||||
|
:Item_func_hybrid_result_type(list),
|
||||||
|
cached_field_type(MYSQL_TYPE_DOUBLE)
|
||||||
|
{}
|
||||||
|
enum_field_types field_type() const { return cached_field_type; }
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class Item_func_numhybrid: public Item_func_hybrid_result_type
|
||||||
|
{
|
||||||
|
protected:
|
||||||
|
|
||||||
|
inline void fix_decimals()
|
||||||
|
{
|
||||||
|
DBUG_ASSERT(result_type() == DECIMAL_RESULT);
|
||||||
|
if (decimals == NOT_FIXED_DEC)
|
||||||
|
set_if_smaller(decimals, max_length - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
Item_func_numhybrid() :Item_func_hybrid_result_type()
|
||||||
|
{}
|
||||||
|
Item_func_numhybrid(Item *a) :Item_func_hybrid_result_type(a)
|
||||||
|
{}
|
||||||
|
Item_func_numhybrid(Item *a,Item *b)
|
||||||
|
:Item_func_hybrid_result_type(a,b)
|
||||||
|
{}
|
||||||
|
Item_func_numhybrid(Item *a,Item *b,Item *c)
|
||||||
|
:Item_func_hybrid_result_type(a,b,c)
|
||||||
|
{}
|
||||||
|
Item_func_numhybrid(List<Item> &list)
|
||||||
|
:Item_func_hybrid_result_type(list)
|
||||||
|
{}
|
||||||
|
void fix_length_and_dec();
|
||||||
|
void fix_num_length_and_dec();
|
||||||
|
virtual void find_num_type()= 0; /* To be called from fix_length_and_dec */
|
||||||
|
String *str_op(String *str) { DBUG_ASSERT(0); return 0; }
|
||||||
|
bool date_op(MYSQL_TIME *ltime, uint fuzzydate) { DBUG_ASSERT(0); return true; }
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
/* function where type of result detected by first argument */
|
/* function where type of result detected by first argument */
|
||||||
class Item_func_num1: public Item_func_numhybrid
|
class Item_func_num1: public Item_func_numhybrid
|
||||||
{
|
{
|
||||||
@ -407,7 +471,6 @@ public:
|
|||||||
|
|
||||||
void fix_num_length_and_dec();
|
void fix_num_length_and_dec();
|
||||||
void find_num_type();
|
void find_num_type();
|
||||||
String *str_op(String *str) { DBUG_ASSERT(0); return 0; }
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -424,7 +487,6 @@ class Item_num_op :public Item_func_numhybrid
|
|||||||
}
|
}
|
||||||
|
|
||||||
void find_num_type();
|
void find_num_type();
|
||||||
String *str_op(String *str) { DBUG_ASSERT(0); return 0; }
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -372,9 +372,11 @@ public:
|
|||||||
max_length=17 + (decimals ? decimals + 1 : 0);
|
max_length=17 + (decimals ? decimals + 1 : 0);
|
||||||
set_persist_maybe_null(1);
|
set_persist_maybe_null(1);
|
||||||
}
|
}
|
||||||
void find_num_type() { hybrid_type= decimals ? DECIMAL_RESULT : INT_RESULT; }
|
void find_num_type()
|
||||||
|
{ cached_result_type= decimals ? DECIMAL_RESULT : INT_RESULT; }
|
||||||
double real_op() { DBUG_ASSERT(0); return 0; }
|
double real_op() { DBUG_ASSERT(0); return 0; }
|
||||||
String *str_op(String *str) { DBUG_ASSERT(0); return 0; }
|
String *str_op(String *str) { DBUG_ASSERT(0); return 0; }
|
||||||
|
bool date_op(MYSQL_TIME *ltime, uint fuzzydate) { DBUG_ASSERT(0); return true; }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -451,12 +453,8 @@ public:
|
|||||||
{ return save_date_in_field(field); }
|
{ return save_date_in_field(field); }
|
||||||
void fix_length_and_dec()
|
void fix_length_and_dec()
|
||||||
{
|
{
|
||||||
static const uint max_time_type_width[5]=
|
|
||||||
{ MAX_DATETIME_WIDTH, MAX_DATETIME_WIDTH, MAX_DATE_WIDTH,
|
|
||||||
MAX_DATETIME_WIDTH, MIN_TIME_WIDTH };
|
|
||||||
|
|
||||||
set_persist_maybe_null(1);
|
set_persist_maybe_null(1);
|
||||||
max_length= max_time_type_width[mysql_type_to_time_type(field_type())+2];
|
max_length= mysql_temporal_int_part_length(field_type());
|
||||||
if (decimals)
|
if (decimals)
|
||||||
{
|
{
|
||||||
if (decimals == NOT_FIXED_DEC)
|
if (decimals == NOT_FIXED_DEC)
|
||||||
|
@ -930,6 +930,17 @@ mysql_type_to_time_type(enum enum_field_types mysql_type)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static inline uint
|
||||||
|
mysql_temporal_int_part_length(enum enum_field_types mysql_type)
|
||||||
|
{
|
||||||
|
static uint max_time_type_width[5]=
|
||||||
|
{ MAX_DATETIME_WIDTH, MAX_DATETIME_WIDTH, MAX_DATE_WIDTH,
|
||||||
|
MAX_DATETIME_WIDTH, MIN_TIME_WIDTH };
|
||||||
|
return max_time_type_width[mysql_type_to_time_type(mysql_type)+2];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#include "sql_list.h"
|
#include "sql_list.h"
|
||||||
#include "sql_map.h"
|
#include "sql_map.h"
|
||||||
#include "handler.h"
|
#include "handler.h"
|
||||||
|
Loading…
x
Reference in New Issue
Block a user