Commit 5b3b53ce authored by Alexander Barkov's avatar Alexander Barkov

MDEV-23311 CEILING() and FLOOR() convert temporal input to numbers, unlike ROUND() and TRUNCATE()

Fixing functions CEILING and FLOOR to return
- TIME for TIME input
- DATETIME for DATETIME and TIMESTAMP input
parent 69cf6302
......@@ -233,9 +233,16 @@ static inline long my_time_fraction_remainder(long nr, uint decimals)
DBUG_ASSERT(decimals <= TIME_SECOND_PART_DIGITS);
return nr % (long) log_10_int[TIME_SECOND_PART_DIGITS - decimals];
}
static inline void my_datetime_trunc(MYSQL_TIME *ltime, uint decimals)
{
ltime->second_part-= my_time_fraction_remainder(ltime->second_part, decimals);
}
static inline void my_time_trunc(MYSQL_TIME *ltime, uint decimals)
{
ltime->second_part-= my_time_fraction_remainder(ltime->second_part, decimals);
if (!ltime->second_part && ltime->neg &&
!ltime->hour && !ltime->minute && !ltime->second)
ltime->neg= FALSE;
}
static inline void my_timeval_trunc(struct timeval *tv, uint decimals)
{
......
......@@ -900,5 +900,170 @@ f
NULL
DROP TABLE t1;
#
# MDEV-23311 CEILING() and FLOOR() convert temporal input to numbers, unlike ROUND() and TRUNCATE()
#
CREATE TABLE t1 AS SELECT
FLOOR(TIMESTAMP'2001-01-01 00:00:00.999999'),
CEILING(TIMESTAMP'2001-01-01 00:00:00.999999');
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
`FLOOR(TIMESTAMP'2001-01-01 00:00:00.999999')` datetime DEFAULT NULL,
`CEILING(TIMESTAMP'2001-01-01 00:00:00.999999')` datetime DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
DROP TABLE t1;
CREATE TABLE t1 (a DATETIME(6));
INSERT INTO t1 VALUES ('9999-12-31 23:59:59.999999');
INSERT INTO t1 VALUES ('9999-12-31 23:59:59.99999');
INSERT INTO t1 VALUES ('9999-12-31 23:59:59.9999');
INSERT INTO t1 VALUES ('9999-12-31 23:59:59.999');
INSERT INTO t1 VALUES ('9999-12-31 23:59:59.99');
INSERT INTO t1 VALUES ('9999-12-31 23:59:59.9');
INSERT INTO t1 VALUES ('9999-12-31 23:59:59.1');
INSERT INTO t1 VALUES ('9999-12-31 23:59:59.0');
INSERT INTO t1 VALUES ('9999-12-30 23:59:59.999999');
INSERT INTO t1 VALUES ('9999-12-30 23:59:59.99999');
INSERT INTO t1 VALUES ('9999-12-30 23:59:59.9999');
INSERT INTO t1 VALUES ('9999-12-30 23:59:59.999');
INSERT INTO t1 VALUES ('9999-12-30 23:59:59.99');
INSERT INTO t1 VALUES ('9999-12-30 23:59:59.9');
INSERT INTO t1 VALUES ('9999-12-30 23:59:59.1');
INSERT INTO t1 VALUES ('9999-12-30 23:59:59.0');
INSERT INTO t1 VALUES ('0999-12-31 23:59:59.999999');
INSERT INTO t1 VALUES ('0999-12-31 23:59:59.99999');
INSERT INTO t1 VALUES ('0999-12-31 23:59:59.9999');
INSERT INTO t1 VALUES ('0999-12-31 23:59:59.999');
INSERT INTO t1 VALUES ('0999-12-31 23:59:59.99');
INSERT INTO t1 VALUES ('0999-12-31 23:59:59.9');
INSERT INTO t1 VALUES ('0999-12-31 23:59:59.1');
INSERT INTO t1 VALUES ('0999-12-31 23:59:59.0');
INSERT INTO t1 VALUES ('0001-12-31 23:59:59.999999');
INSERT INTO t1 VALUES ('0001-12-31 23:59:59.99999');
INSERT INTO t1 VALUES ('0001-12-31 23:59:59.9999');
INSERT INTO t1 VALUES ('0001-12-31 23:59:59.999');
INSERT INTO t1 VALUES ('0001-12-31 23:59:59.99');
INSERT INTO t1 VALUES ('0001-12-31 23:59:59.9');
INSERT INTO t1 VALUES ('0001-12-31 23:59:59.1');
INSERT INTO t1 VALUES ('0001-12-31 23:59:59.0');
CREATE FUNCTION FLOOR_SP(a DATETIME(6)) RETURNS DATETIME
BEGIN
RETURN
CASE
WHEN EXTRACT(MICROSECOND FROM a)=0 THEN a
ELSE TRUNCATE(a,0)
END;
END;
$$
CREATE FUNCTION CEILING_SP(a DATETIME(6)) RETURNS DATETIME
BEGIN
RETURN
CASE
WHEN TRUNCATE(a,0)=TIMESTAMP'9999-12-31 23:59:59' THEN a
WHEN EXTRACT(MICROSECOND FROM a)=0 THEN a
ELSE TRUNCATE(a,0)+INTERVAL 1 SECOND
END;
END;
$$
SELECT a, FLOOR(a), FLOOR_SP(a), FLOOR(a)=FLOOR_SP(a) FROM t1 ORDER BY a;
a FLOOR(a) FLOOR_SP(a) FLOOR(a)=FLOOR_SP(a)
0001-12-31 23:59:59.000000 0001-12-31 23:59:59 0001-12-31 23:59:59 1
0001-12-31 23:59:59.100000 0001-12-31 23:59:59 0001-12-31 23:59:59 1
0001-12-31 23:59:59.900000 0001-12-31 23:59:59 0001-12-31 23:59:59 1
0001-12-31 23:59:59.990000 0001-12-31 23:59:59 0001-12-31 23:59:59 1
0001-12-31 23:59:59.999000 0001-12-31 23:59:59 0001-12-31 23:59:59 1
0001-12-31 23:59:59.999900 0001-12-31 23:59:59 0001-12-31 23:59:59 1
0001-12-31 23:59:59.999990 0001-12-31 23:59:59 0001-12-31 23:59:59 1
0001-12-31 23:59:59.999999 0001-12-31 23:59:59 0001-12-31 23:59:59 1
0999-12-31 23:59:59.000000 0999-12-31 23:59:59 0999-12-31 23:59:59 1
0999-12-31 23:59:59.100000 0999-12-31 23:59:59 0999-12-31 23:59:59 1
0999-12-31 23:59:59.900000 0999-12-31 23:59:59 0999-12-31 23:59:59 1
0999-12-31 23:59:59.990000 0999-12-31 23:59:59 0999-12-31 23:59:59 1
0999-12-31 23:59:59.999000 0999-12-31 23:59:59 0999-12-31 23:59:59 1
0999-12-31 23:59:59.999900 0999-12-31 23:59:59 0999-12-31 23:59:59 1
0999-12-31 23:59:59.999990 0999-12-31 23:59:59 0999-12-31 23:59:59 1
0999-12-31 23:59:59.999999 0999-12-31 23:59:59 0999-12-31 23:59:59 1
9999-12-30 23:59:59.000000 9999-12-30 23:59:59 9999-12-30 23:59:59 1
9999-12-30 23:59:59.100000 9999-12-30 23:59:59 9999-12-30 23:59:59 1
9999-12-30 23:59:59.900000 9999-12-30 23:59:59 9999-12-30 23:59:59 1
9999-12-30 23:59:59.990000 9999-12-30 23:59:59 9999-12-30 23:59:59 1
9999-12-30 23:59:59.999000 9999-12-30 23:59:59 9999-12-30 23:59:59 1
9999-12-30 23:59:59.999900 9999-12-30 23:59:59 9999-12-30 23:59:59 1
9999-12-30 23:59:59.999990 9999-12-30 23:59:59 9999-12-30 23:59:59 1
9999-12-30 23:59:59.999999 9999-12-30 23:59:59 9999-12-30 23:59:59 1
9999-12-31 23:59:59.000000 9999-12-31 23:59:59 9999-12-31 23:59:59 1
9999-12-31 23:59:59.100000 9999-12-31 23:59:59 9999-12-31 23:59:59 1
9999-12-31 23:59:59.900000 9999-12-31 23:59:59 9999-12-31 23:59:59 1
9999-12-31 23:59:59.990000 9999-12-31 23:59:59 9999-12-31 23:59:59 1
9999-12-31 23:59:59.999000 9999-12-31 23:59:59 9999-12-31 23:59:59 1
9999-12-31 23:59:59.999900 9999-12-31 23:59:59 9999-12-31 23:59:59 1
9999-12-31 23:59:59.999990 9999-12-31 23:59:59 9999-12-31 23:59:59 1
9999-12-31 23:59:59.999999 9999-12-31 23:59:59 9999-12-31 23:59:59 1
SELECT a, CEILING(a), CEILING_SP(a), CEILING(a)=CEILING_SP(a) FROM t1 ORDER BY a;
a CEILING(a) CEILING_SP(a) CEILING(a)=CEILING_SP(a)
0001-12-31 23:59:59.000000 0001-12-31 23:59:59 0001-12-31 23:59:59 1
0001-12-31 23:59:59.100000 0002-01-01 00:00:00 0002-01-01 00:00:00 1
0001-12-31 23:59:59.900000 0002-01-01 00:00:00 0002-01-01 00:00:00 1
0001-12-31 23:59:59.990000 0002-01-01 00:00:00 0002-01-01 00:00:00 1
0001-12-31 23:59:59.999000 0002-01-01 00:00:00 0002-01-01 00:00:00 1
0001-12-31 23:59:59.999900 0002-01-01 00:00:00 0002-01-01 00:00:00 1
0001-12-31 23:59:59.999990 0002-01-01 00:00:00 0002-01-01 00:00:00 1
0001-12-31 23:59:59.999999 0002-01-01 00:00:00 0002-01-01 00:00:00 1
0999-12-31 23:59:59.000000 0999-12-31 23:59:59 0999-12-31 23:59:59 1
0999-12-31 23:59:59.100000 1000-01-01 00:00:00 1000-01-01 00:00:00 1
0999-12-31 23:59:59.900000 1000-01-01 00:00:00 1000-01-01 00:00:00 1
0999-12-31 23:59:59.990000 1000-01-01 00:00:00 1000-01-01 00:00:00 1
0999-12-31 23:59:59.999000 1000-01-01 00:00:00 1000-01-01 00:00:00 1
0999-12-31 23:59:59.999900 1000-01-01 00:00:00 1000-01-01 00:00:00 1
0999-12-31 23:59:59.999990 1000-01-01 00:00:00 1000-01-01 00:00:00 1
0999-12-31 23:59:59.999999 1000-01-01 00:00:00 1000-01-01 00:00:00 1
9999-12-30 23:59:59.000000 9999-12-30 23:59:59 9999-12-30 23:59:59 1
9999-12-30 23:59:59.100000 9999-12-31 00:00:00 9999-12-31 00:00:00 1
9999-12-30 23:59:59.900000 9999-12-31 00:00:00 9999-12-31 00:00:00 1
9999-12-30 23:59:59.990000 9999-12-31 00:00:00 9999-12-31 00:00:00 1
9999-12-30 23:59:59.999000 9999-12-31 00:00:00 9999-12-31 00:00:00 1
9999-12-30 23:59:59.999900 9999-12-31 00:00:00 9999-12-31 00:00:00 1
9999-12-30 23:59:59.999990 9999-12-31 00:00:00 9999-12-31 00:00:00 1
9999-12-30 23:59:59.999999 9999-12-31 00:00:00 9999-12-31 00:00:00 1
9999-12-31 23:59:59.000000 9999-12-31 23:59:59 9999-12-31 23:59:59 1
9999-12-31 23:59:59.100000 9999-12-31 23:59:59 9999-12-31 23:59:59 1
9999-12-31 23:59:59.900000 9999-12-31 23:59:59 9999-12-31 23:59:59 1
9999-12-31 23:59:59.990000 9999-12-31 23:59:59 9999-12-31 23:59:59 1
9999-12-31 23:59:59.999000 9999-12-31 23:59:59 9999-12-31 23:59:59 1
9999-12-31 23:59:59.999900 9999-12-31 23:59:59 9999-12-31 23:59:59 1
9999-12-31 23:59:59.999990 9999-12-31 23:59:59 9999-12-31 23:59:59 1
9999-12-31 23:59:59.999999 9999-12-31 23:59:59 9999-12-31 23:59:59 1
DROP FUNCTION FLOOR_SP;
DROP FUNCTION CEILING_SP;
DROP TABLE t1;
CREATE TABLE t1 (a DATETIME(6));
INSERT INTO t1 VALUES ('0000-00-00 23:59:59.999999');
INSERT INTO t1 VALUES ('0000-00-01 23:59:59.999999');
INSERT INTO t1 VALUES ('0000-01-01 23:59:59.999999');
INSERT INTO t1 VALUES ('0001-00-00 23:59:59.999999');
SELECT a, FLOOR(a), CEILING(a) FROM t1;
a FLOOR(a) CEILING(a)
0000-00-00 23:59:59.999999 0000-00-00 23:59:59 NULL
0000-00-01 23:59:59.999999 0000-00-01 23:59:59 NULL
0000-01-01 23:59:59.999999 0000-01-01 23:59:59 NULL
0001-00-00 23:59:59.999999 0001-00-00 23:59:59 NULL
Warnings:
Warning 1411 Incorrect date value: '0000-00-00' for function round(datetime)
Warning 1411 Incorrect date value: '0000-00-01' for function round(datetime)
Warning 1411 Incorrect date value: '0000-01-01' for function round(datetime)
Warning 1411 Incorrect date value: '0001-00-00' for function round(datetime)
DROP TABLE t1;
SET sql_mode=ALLOW_INVALID_DATES;
CREATE TABLE t1 (a DATETIME(6));
INSERT INTO t1 VALUES ('2001-02-28 23:59:59.999999');
INSERT INTO t1 VALUES ('2001-02-29 23:59:59.999999');
SELECT a, FLOOR(a), CEILING(a) FROM t1;
a FLOOR(a) CEILING(a)
2001-02-28 23:59:59.999999 2001-02-28 23:59:59 2001-03-01 00:00:00
2001-02-29 23:59:59.999999 2001-02-29 23:59:59 NULL
Warnings:
Warning 1411 Incorrect date value: '2001-02-29' for function round(datetime)
DROP TABLE t1;
SET sql_mode=DEFAULT;
#
# End of 10.4 tests
#
......@@ -156,6 +156,104 @@ SELECT ROUND(a) AS f FROM t1 GROUP BY a WITH ROLLUP;
DROP TABLE t1;
--echo #
--echo # MDEV-23311 CEILING() and FLOOR() convert temporal input to numbers, unlike ROUND() and TRUNCATE()
--echo #
CREATE TABLE t1 AS SELECT
FLOOR(TIMESTAMP'2001-01-01 00:00:00.999999'),
CEILING(TIMESTAMP'2001-01-01 00:00:00.999999');
SHOW CREATE TABLE t1;
DROP TABLE t1;
CREATE TABLE t1 (a DATETIME(6));
INSERT INTO t1 VALUES ('9999-12-31 23:59:59.999999');
INSERT INTO t1 VALUES ('9999-12-31 23:59:59.99999');
INSERT INTO t1 VALUES ('9999-12-31 23:59:59.9999');
INSERT INTO t1 VALUES ('9999-12-31 23:59:59.999');
INSERT INTO t1 VALUES ('9999-12-31 23:59:59.99');
INSERT INTO t1 VALUES ('9999-12-31 23:59:59.9');
INSERT INTO t1 VALUES ('9999-12-31 23:59:59.1');
INSERT INTO t1 VALUES ('9999-12-31 23:59:59.0');
INSERT INTO t1 VALUES ('9999-12-30 23:59:59.999999');
INSERT INTO t1 VALUES ('9999-12-30 23:59:59.99999');
INSERT INTO t1 VALUES ('9999-12-30 23:59:59.9999');
INSERT INTO t1 VALUES ('9999-12-30 23:59:59.999');
INSERT INTO t1 VALUES ('9999-12-30 23:59:59.99');
INSERT INTO t1 VALUES ('9999-12-30 23:59:59.9');
INSERT INTO t1 VALUES ('9999-12-30 23:59:59.1');
INSERT INTO t1 VALUES ('9999-12-30 23:59:59.0');
INSERT INTO t1 VALUES ('0999-12-31 23:59:59.999999');
INSERT INTO t1 VALUES ('0999-12-31 23:59:59.99999');
INSERT INTO t1 VALUES ('0999-12-31 23:59:59.9999');
INSERT INTO t1 VALUES ('0999-12-31 23:59:59.999');
INSERT INTO t1 VALUES ('0999-12-31 23:59:59.99');
INSERT INTO t1 VALUES ('0999-12-31 23:59:59.9');
INSERT INTO t1 VALUES ('0999-12-31 23:59:59.1');
INSERT INTO t1 VALUES ('0999-12-31 23:59:59.0');
INSERT INTO t1 VALUES ('0001-12-31 23:59:59.999999');
INSERT INTO t1 VALUES ('0001-12-31 23:59:59.99999');
INSERT INTO t1 VALUES ('0001-12-31 23:59:59.9999');
INSERT INTO t1 VALUES ('0001-12-31 23:59:59.999');
INSERT INTO t1 VALUES ('0001-12-31 23:59:59.99');
INSERT INTO t1 VALUES ('0001-12-31 23:59:59.9');
INSERT INTO t1 VALUES ('0001-12-31 23:59:59.1');
INSERT INTO t1 VALUES ('0001-12-31 23:59:59.0');
DELIMITER $$;
CREATE FUNCTION FLOOR_SP(a DATETIME(6)) RETURNS DATETIME
BEGIN
RETURN
CASE
WHEN EXTRACT(MICROSECOND FROM a)=0 THEN a
ELSE TRUNCATE(a,0)
END;
END;
$$
DELIMITER ;$$
DELIMITER $$;
CREATE FUNCTION CEILING_SP(a DATETIME(6)) RETURNS DATETIME
BEGIN
RETURN
CASE
WHEN TRUNCATE(a,0)=TIMESTAMP'9999-12-31 23:59:59' THEN a
WHEN EXTRACT(MICROSECOND FROM a)=0 THEN a
ELSE TRUNCATE(a,0)+INTERVAL 1 SECOND
END;
END;
$$
DELIMITER ;$$
SELECT a, FLOOR(a), FLOOR_SP(a), FLOOR(a)=FLOOR_SP(a) FROM t1 ORDER BY a;
SELECT a, CEILING(a), CEILING_SP(a), CEILING(a)=CEILING_SP(a) FROM t1 ORDER BY a;
DROP FUNCTION FLOOR_SP;
DROP FUNCTION CEILING_SP;
DROP TABLE t1;
CREATE TABLE t1 (a DATETIME(6));
INSERT INTO t1 VALUES ('0000-00-00 23:59:59.999999');
INSERT INTO t1 VALUES ('0000-00-01 23:59:59.999999');
INSERT INTO t1 VALUES ('0000-01-01 23:59:59.999999');
INSERT INTO t1 VALUES ('0001-00-00 23:59:59.999999');
SELECT a, FLOOR(a), CEILING(a) FROM t1;
DROP TABLE t1;
SET sql_mode=ALLOW_INVALID_DATES;
CREATE TABLE t1 (a DATETIME(6));
INSERT INTO t1 VALUES ('2001-02-28 23:59:59.999999');
INSERT INTO t1 VALUES ('2001-02-29 23:59:59.999999');
SELECT a, FLOOR(a), CEILING(a) FROM t1;
DROP TABLE t1;
SET sql_mode=DEFAULT;
--echo #
--echo # End of 10.4 tests
--echo #
......@@ -670,3 +670,240 @@ a ROUND(a,-6)
838:59:59.999999 838:59:59
DROP TABLE t1;
SET time_zone=DEFAULT;
#
# MDEV-23311 CEILING() and FLOOR() convert temporal input to numbers, unlike ROUND() and TRUNCATE()
#
CREATE TABLE t1 AS SELECT
FLOOR(TIME'00:00:00.999999'),
CEILING(TIME'00:00:00.999999');
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
`FLOOR(TIME'00:00:00.999999')` time NOT NULL,
`CEILING(TIME'00:00:00.999999')` time NOT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
DROP TABLE t1;
CREATE TABLE t1 (a TIME(6));
INSERT INTO t1 VALUES ('838:59:59.999999');
INSERT INTO t1 VALUES ('838:59:59.99999');
INSERT INTO t1 VALUES ('838:59:59.9999');
INSERT INTO t1 VALUES ('838:59:59.999');
INSERT INTO t1 VALUES ('838:59:59.99');
INSERT INTO t1 VALUES ('838:59:59.9');
INSERT INTO t1 VALUES ('838:59:59.1');
INSERT INTO t1 VALUES ('838:59:59.0');
INSERT INTO t1 VALUES ('837:59:59.999999');
INSERT INTO t1 VALUES ('837:59:59.99999');
INSERT INTO t1 VALUES ('837:59:59.9999');
INSERT INTO t1 VALUES ('837:59:59.999');
INSERT INTO t1 VALUES ('837:59:59.99');
INSERT INTO t1 VALUES ('837:59:59.9');
INSERT INTO t1 VALUES ('837:59:59.1');
INSERT INTO t1 VALUES ('837:59:59.0');
INSERT INTO t1 VALUES ('23:59:59.999999');
INSERT INTO t1 VALUES ('23:59:59.99999');
INSERT INTO t1 VALUES ('23:59:59.9999');
INSERT INTO t1 VALUES ('23:59:59.999');
INSERT INTO t1 VALUES ('23:59:59.99');
INSERT INTO t1 VALUES ('23:59:59.9');
INSERT INTO t1 VALUES ('23:59:59.1');
INSERT INTO t1 VALUES ('23:59:59.0');
INSERT INTO t1 VALUES ('00:00:00.999999');
INSERT INTO t1 VALUES ('00:00:00.99999');
INSERT INTO t1 VALUES ('00:00:00.9999');
INSERT INTO t1 VALUES ('00:00:00.999');
INSERT INTO t1 VALUES ('00:00:00.99');
INSERT INTO t1 VALUES ('00:00:00.9');
INSERT INTO t1 VALUES ('00:00:00.1');
INSERT INTO t1 VALUES ('00:00:00.0');
INSERT INTO t1 VALUES ('-00:00:00.999999');
INSERT INTO t1 VALUES ('-00:00:00.99999');
INSERT INTO t1 VALUES ('-00:00:00.9999');
INSERT INTO t1 VALUES ('-00:00:00.999');
INSERT INTO t1 VALUES ('-00:00:00.99');
INSERT INTO t1 VALUES ('-00:00:00.9');
INSERT INTO t1 VALUES ('-00:00:00.1');
INSERT INTO t1 VALUES ('-00:00:00.0');
INSERT INTO t1 VALUES ('-23:59:59.999999');
INSERT INTO t1 VALUES ('-23:59:59.99999');
INSERT INTO t1 VALUES ('-23:59:59.9999');
INSERT INTO t1 VALUES ('-23:59:59.999');
INSERT INTO t1 VALUES ('-23:59:59.99');
INSERT INTO t1 VALUES ('-23:59:59.9');
INSERT INTO t1 VALUES ('-23:59:59.1');
INSERT INTO t1 VALUES ('-23:59:59.0');
INSERT INTO t1 VALUES ('-837:59:59.999999');
INSERT INTO t1 VALUES ('-837:59:59.99999');
INSERT INTO t1 VALUES ('-837:59:59.9999');
INSERT INTO t1 VALUES ('-837:59:59.999');
INSERT INTO t1 VALUES ('-837:59:59.99');
INSERT INTO t1 VALUES ('-837:59:59.9');
INSERT INTO t1 VALUES ('-837:59:59.1');
INSERT INTO t1 VALUES ('-837:59:59.0');
INSERT INTO t1 VALUES ('-838:59:59.999999');
INSERT INTO t1 VALUES ('-838:59:59.99999');
INSERT INTO t1 VALUES ('-838:59:59.9999');
INSERT INTO t1 VALUES ('-838:59:59.999');
INSERT INTO t1 VALUES ('-838:59:59.99');
INSERT INTO t1 VALUES ('-838:59:59.9');
INSERT INTO t1 VALUES ('-838:59:59.1');
INSERT INTO t1 VALUES ('-838:59:59.0');
CREATE FUNCTION FLOOR_SP(a TIME(6)) RETURNS TIME
BEGIN
RETURN
CASE
WHEN TRUNCATE(a,0)=TIME'838:59:59' THEN a
WHEN TRUNCATE(a,0)=TIME'-838:59:59' THEN a
WHEN a=TRUNCATE(a,0) THEN a -- no fractional digits
WHEN a<0 THEN TRUNCATE(a,0)-INTERVAL 1 SECOND -- negative values
WHEN a>0 THEN TRUNCATE(a,0) -- positive values
END;
END;
$$
CREATE FUNCTION CEILING_SP(a TIME(6)) RETURNS TIME
BEGIN
RETURN
CASE
WHEN TRUNCATE(a,0)=TIME'838:59:59' THEN a
WHEN TRUNCATE(a,0)=TIME'-838:59:59' THEN a
WHEN a=TRUNCATE(a,0) THEN a -- no fractional digits
WHEN a<0 THEN TRUNCATE(a,0) -- negative values
WHEN a>0 THEN TRUNCATE(a,0)+INTERVAL 1 SECOND -- positive values
END;
END;
$$
SELECT a, FLOOR(a), FLOOR_SP(a), FLOOR(a)=FLOOR_SP(a) FROM t1 ORDER BY a;
a FLOOR(a) FLOOR_SP(a) FLOOR(a)=FLOOR_SP(a)
-838:59:59.999999 -838:59:59 -838:59:59 1
-838:59:59.999990 -838:59:59 -838:59:59 1
-838:59:59.999900 -838:59:59 -838:59:59 1
-838:59:59.999000 -838:59:59 -838:59:59 1
-838:59:59.990000 -838:59:59 -838:59:59 1
-838:59:59.900000 -838:59:59 -838:59:59 1
-838:59:59.100000 -838:59:59 -838:59:59 1
-838:59:59.000000 -838:59:59 -838:59:59 1
-837:59:59.999999 -838:00:00 -838:00:00 1
-837:59:59.999990 -838:00:00 -838:00:00 1
-837:59:59.999900 -838:00:00 -838:00:00 1
-837:59:59.999000 -838:00:00 -838:00:00 1
-837:59:59.990000 -838:00:00 -838:00:00 1
-837:59:59.900000 -838:00:00 -838:00:00 1
-837:59:59.100000 -838:00:00 -838:00:00 1
-837:59:59.000000 -837:59:59 -837:59:59 1
-23:59:59.999999 -24:00:00 -24:00:00 1
-23:59:59.999990 -24:00:00 -24:00:00 1
-23:59:59.999900 -24:00:00 -24:00:00 1
-23:59:59.999000 -24:00:00 -24:00:00 1
-23:59:59.990000 -24:00:00 -24:00:00 1
-23:59:59.900000 -24:00:00 -24:00:00 1
-23:59:59.100000 -24:00:00 -24:00:00 1
-23:59:59.000000 -23:59:59 -23:59:59 1
-00:00:00.999999 -00:00:01 -00:00:01 1
-00:00:00.999990 -00:00:01 -00:00:01 1
-00:00:00.999900 -00:00:01 -00:00:01 1
-00:00:00.999000 -00:00:01 -00:00:01 1
-00:00:00.990000 -00:00:01 -00:00:01 1
-00:00:00.900000 -00:00:01 -00:00:01 1
-00:00:00.100000 -00:00:01 -00:00:01 1
00:00:00.000000 00:00:00 00:00:00 1
00:00:00.000000 00:00:00 00:00:00 1
00:00:00.100000 00:00:00 00:00:00 1
00:00:00.900000 00:00:00 00:00:00 1
00:00:00.990000 00:00:00 00:00:00 1
00:00:00.999000 00:00:00 00:00:00 1
00:00:00.999900 00:00:00 00:00:00 1
00:00:00.999990 00:00:00 00:00:00 1
00:00:00.999999 00:00:00 00:00:00 1
23:59:59.000000 23:59:59 23:59:59 1
23:59:59.100000 23:59:59 23:59:59 1
23:59:59.900000 23:59:59 23:59:59 1
23:59:59.990000 23:59:59 23:59:59 1
23:59:59.999000 23:59:59 23:59:59 1
23:59:59.999900 23:59:59 23:59:59 1
23:59:59.999990 23:59:59 23:59:59 1
23:59:59.999999 23:59:59 23:59:59 1
837:59:59.000000 837:59:59 837:59:59 1
837:59:59.100000 837:59:59 837:59:59 1
837:59:59.900000 837:59:59 837:59:59 1
837:59:59.990000 837:59:59 837:59:59 1
837:59:59.999000 837:59:59 837:59:59 1
837:59:59.999900 837:59:59 837:59:59 1
837:59:59.999990 837:59:59 837:59:59 1
837:59:59.999999 837:59:59 837:59:59 1
838:59:59.000000 838:59:59 838:59:59 1
838:59:59.100000 838:59:59 838:59:59 1
838:59:59.900000 838:59:59 838:59:59 1
838:59:59.990000 838:59:59 838:59:59 1
838:59:59.999000 838:59:59 838:59:59 1
838:59:59.999900 838:59:59 838:59:59 1
838:59:59.999990 838:59:59 838:59:59 1
838:59:59.999999 838:59:59 838:59:59 1
SELECT a, CEILING(a), CEILING_SP(a), CEILING(a)=CEILING_SP(a) FROM t1 ORDER BY a;
a CEILING(a) CEILING_SP(a) CEILING(a)=CEILING_SP(a)
-838:59:59.999999 -838:59:59 -838:59:59 1
-838:59:59.999990 -838:59:59 -838:59:59 1
-838:59:59.999900 -838:59:59 -838:59:59 1
-838:59:59.999000 -838:59:59 -838:59:59 1
-838:59:59.990000 -838:59:59 -838:59:59 1
-838:59:59.900000 -838:59:59 -838:59:59 1
-838:59:59.100000 -838:59:59 -838:59:59 1
-838:59:59.000000 -838:59:59 -838:59:59 1
-837:59:59.999999 -837:59:59 -837:59:59 1
-837:59:59.999990 -837:59:59 -837:59:59 1
-837:59:59.999900 -837:59:59 -837:59:59 1
-837:59:59.999000 -837:59:59 -837:59:59 1
-837:59:59.990000 -837:59:59 -837:59:59 1
-837:59:59.900000 -837:59:59 -837:59:59 1
-837:59:59.100000 -837:59:59 -837:59:59 1
-837:59:59.000000 -837:59:59 -837:59:59 1
-23:59:59.999999 -23:59:59 -23:59:59 1
-23:59:59.999990 -23:59:59 -23:59:59 1
-23:59:59.999900 -23:59:59 -23:59:59 1
-23:59:59.999000 -23:59:59 -23:59:59 1
-23:59:59.990000 -23:59:59 -23:59:59 1
-23:59:59.900000 -23:59:59 -23:59:59 1
-23:59:59.100000 -23:59:59 -23:59:59 1
-23:59:59.000000 -23:59:59 -23:59:59 1
-00:00:00.999999 00:00:00 00:00:00 1
-00:00:00.999990 00:00:00 00:00:00 1
-00:00:00.999900 00:00:00 00:00:00 1
-00:00:00.999000 00:00:00 00:00:00 1
-00:00:00.990000 00:00:00 00:00:00 1
-00:00:00.900000 00:00:00 00:00:00 1
-00:00:00.100000 00:00:00 00:00:00 1
00:00:00.000000 00:00:00 00:00:00 1
00:00:00.000000 00:00:00 00:00:00 1
00:00:00.100000 00:00:01 00:00:01 1
00:00:00.900000 00:00:01 00:00:01 1
00:00:00.990000 00:00:01 00:00:01 1
00:00:00.999000 00:00:01 00:00:01 1
00:00:00.999900 00:00:01 00:00:01 1
00:00:00.999990 00:00:01 00:00:01 1
00:00:00.999999 00:00:01 00:00:01 1
23:59:59.000000 23:59:59 23:59:59 1
23:59:59.100000 24:00:00 24:00:00 1
23:59:59.900000 24:00:00 24:00:00 1
23:59:59.990000 24:00:00 24:00:00 1
23:59:59.999000 24:00:00 24:00:00 1
23:59:59.999900 24:00:00 24:00:00 1
23:59:59.999990 24:00:00 24:00:00 1
23:59:59.999999 24:00:00 24:00:00 1
837:59:59.000000 837:59:59 837:59:59 1
837:59:59.100000 838:00:00 838:00:00 1
837:59:59.900000 838:00:00 838:00:00 1
837:59:59.990000 838:00:00 838:00:00 1
837:59:59.999000 838:00:00 838:00:00 1
837:59:59.999900 838:00:00 838:00:00 1
837:59:59.999990 838:00:00 838:00:00 1
837:59:59.999999 838:00:00 838:00:00 1
838:59:59.000000 838:59:59 838:59:59 1
838:59:59.100000 838:59:59 838:59:59 1
838:59:59.900000 838:59:59 838:59:59 1
838:59:59.990000 838:59:59 838:59:59 1
838:59:59.999000 838:59:59 838:59:59 1
838:59:59.999900 838:59:59 838:59:59 1
838:59:59.999990 838:59:59 838:59:59 1
838:59:59.999999 838:59:59 838:59:59 1
DROP FUNCTION FLOOR_SP;
DROP FUNCTION CEILING_SP;
DROP TABLE t1;
......@@ -73,3 +73,126 @@ SELECT a, ROUND(a,-6) FROM t1;
DROP TABLE t1;
SET time_zone=DEFAULT;
--echo #
--echo # MDEV-23311 CEILING() and FLOOR() convert temporal input to numbers, unlike ROUND() and TRUNCATE()
--echo #
CREATE TABLE t1 AS SELECT
FLOOR(TIME'00:00:00.999999'),
CEILING(TIME'00:00:00.999999');
SHOW CREATE TABLE t1;
DROP TABLE t1;
CREATE TABLE t1 (a TIME(6));
INSERT INTO t1 VALUES ('838:59:59.999999');
INSERT INTO t1 VALUES ('838:59:59.99999');
INSERT INTO t1 VALUES ('838:59:59.9999');
INSERT INTO t1 VALUES ('838:59:59.999');
INSERT INTO t1 VALUES ('838:59:59.99');
INSERT INTO t1 VALUES ('838:59:59.9');
INSERT INTO t1 VALUES ('838:59:59.1');
INSERT INTO t1 VALUES ('838:59:59.0');
INSERT INTO t1 VALUES ('837:59:59.999999');
INSERT INTO t1 VALUES ('837:59:59.99999');
INSERT INTO t1 VALUES ('837:59:59.9999');
INSERT INTO t1 VALUES ('837:59:59.999');
INSERT INTO t1 VALUES ('837:59:59.99');
INSERT INTO t1 VALUES ('837:59:59.9');
INSERT INTO t1 VALUES ('837:59:59.1');
INSERT INTO t1 VALUES ('837:59:59.0');
INSERT INTO t1 VALUES ('23:59:59.999999');
INSERT INTO t1 VALUES ('23:59:59.99999');
INSERT INTO t1 VALUES ('23:59:59.9999');
INSERT INTO t1 VALUES ('23:59:59.999');
INSERT INTO t1 VALUES ('23:59:59.99');
INSERT INTO t1 VALUES ('23:59:59.9');
INSERT INTO t1 VALUES ('23:59:59.1');
INSERT INTO t1 VALUES ('23:59:59.0');
INSERT INTO t1 VALUES ('00:00:00.999999');
INSERT INTO t1 VALUES ('00:00:00.99999');
INSERT INTO t1 VALUES ('00:00:00.9999');
INSERT INTO t1 VALUES ('00:00:00.999');
INSERT INTO t1 VALUES ('00:00:00.99');
INSERT INTO t1 VALUES ('00:00:00.9');
INSERT INTO t1 VALUES ('00:00:00.1');
INSERT INTO t1 VALUES ('00:00:00.0');
INSERT INTO t1 VALUES ('-00:00:00.999999');
INSERT INTO t1 VALUES ('-00:00:00.99999');
INSERT INTO t1 VALUES ('-00:00:00.9999');
INSERT INTO t1 VALUES ('-00:00:00.999');
INSERT INTO t1 VALUES ('-00:00:00.99');
INSERT INTO t1 VALUES ('-00:00:00.9');
INSERT INTO t1 VALUES ('-00:00:00.1');
INSERT INTO t1 VALUES ('-00:00:00.0');
INSERT INTO t1 VALUES ('-23:59:59.999999');
INSERT INTO t1 VALUES ('-23:59:59.99999');
INSERT INTO t1 VALUES ('-23:59:59.9999');
INSERT INTO t1 VALUES ('-23:59:59.999');
INSERT INTO t1 VALUES ('-23:59:59.99');
INSERT INTO t1 VALUES ('-23:59:59.9');
INSERT INTO t1 VALUES ('-23:59:59.1');
INSERT INTO t1 VALUES ('-23:59:59.0');
INSERT INTO t1 VALUES ('-837:59:59.999999');
INSERT INTO t1 VALUES ('-837:59:59.99999');
INSERT INTO t1 VALUES ('-837:59:59.9999');
INSERT INTO t1 VALUES ('-837:59:59.999');
INSERT INTO t1 VALUES ('-837:59:59.99');
INSERT INTO t1 VALUES ('-837:59:59.9');
INSERT INTO t1 VALUES ('-837:59:59.1');
INSERT INTO t1 VALUES ('-837:59:59.0');
INSERT INTO t1 VALUES ('-838:59:59.999999');
INSERT INTO t1 VALUES ('-838:59:59.99999');
INSERT INTO t1 VALUES ('-838:59:59.9999');
INSERT INTO t1 VALUES ('-838:59:59.999');
INSERT INTO t1 VALUES ('-838:59:59.99');
INSERT INTO t1 VALUES ('-838:59:59.9');
INSERT INTO t1 VALUES ('-838:59:59.1');
INSERT INTO t1 VALUES ('-838:59:59.0');
DELIMITER $$;
CREATE FUNCTION FLOOR_SP(a TIME(6)) RETURNS TIME
BEGIN
RETURN
CASE
WHEN TRUNCATE(a,0)=TIME'838:59:59' THEN a
WHEN TRUNCATE(a,0)=TIME'-838:59:59' THEN a
WHEN a=TRUNCATE(a,0) THEN a -- no fractional digits
WHEN a<0 THEN TRUNCATE(a,0)-INTERVAL 1 SECOND -- negative values
WHEN a>0 THEN TRUNCATE(a,0) -- positive values
END;
END;
$$
DELIMITER ;$$
DELIMITER $$;
CREATE FUNCTION CEILING_SP(a TIME(6)) RETURNS TIME
BEGIN
RETURN
CASE
WHEN TRUNCATE(a,0)=TIME'838:59:59' THEN a
WHEN TRUNCATE(a,0)=TIME'-838:59:59' THEN a
WHEN a=TRUNCATE(a,0) THEN a -- no fractional digits
WHEN a<0 THEN TRUNCATE(a,0) -- negative values
WHEN a>0 THEN TRUNCATE(a,0)+INTERVAL 1 SECOND -- positive values
END;
END;
$$
DELIMITER ;$$
SELECT a, FLOOR(a), FLOOR_SP(a), FLOOR(a)=FLOOR_SP(a) FROM t1 ORDER BY a;
SELECT a, CEILING(a), CEILING_SP(a), CEILING(a)=CEILING_SP(a) FROM t1 ORDER BY a;
DROP FUNCTION FLOOR_SP;
DROP FUNCTION CEILING_SP;
DROP TABLE t1;
......@@ -626,5 +626,17 @@ a ROUND(a,-6)
DROP TABLE t1;
SET time_zone=DEFAULT;
#
# MDEV-23311 CEILING() and FLOOR() convert temporal input to numbers, unlike ROUND() and TRUNCATE()
#
CREATE TABLE t1 (a TIMESTAMP NOT NULL);
CREATE TABLE t2 AS SELECT FLOOR(a), CEILING(a) FROM t1;
SHOW CREATE TABLE t2;
Table Create Table
t2 CREATE TABLE `t2` (
`FLOOR(a)` datetime DEFAULT NULL,
`CEILING(a)` datetime DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
DROP TABLE t1, t2;
#
# End of 10.4 tests
#
......@@ -107,6 +107,16 @@ DROP TABLE t1;
SET time_zone=DEFAULT;
--echo #
--echo # MDEV-23311 CEILING() and FLOOR() convert temporal input to numbers, unlike ROUND() and TRUNCATE()
--echo #
CREATE TABLE t1 (a TIMESTAMP NOT NULL);
CREATE TABLE t2 AS SELECT FLOOR(a), CEILING(a) FROM t1;
SHOW CREATE TABLE t2;
DROP TABLE t1, t2;
--echo #
--echo # End of 10.4 tests
--echo #
......@@ -2218,8 +2218,7 @@ bool Item_func_int_val::fix_length_and_dec()
{
DBUG_ENTER("Item_func_int_val::fix_length_and_dec");
DBUG_PRINT("info", ("name %s", func_name()));
if (args[0]->cast_to_int_type_handler()->
Item_func_int_val_fix_length_and_dec(this))
if (args[0]->type_handler()->Item_func_int_val_fix_length_and_dec(this))
DBUG_RETURN(TRUE);
DBUG_PRINT("info", ("Type: %s", type_handler()->name().ptr()));
DBUG_RETURN(FALSE);
......@@ -2262,6 +2261,28 @@ my_decimal *Item_func_ceiling::decimal_op(my_decimal *decimal_value)
}
bool Item_func_ceiling::date_op(THD *thd, MYSQL_TIME *to, date_mode_t fuzzydate)
{
Datetime::Options opt(thd, TIME_FRAC_TRUNCATE);
Datetime *tm= new (to) Datetime(thd, args[0], opt);
tm->ceiling(thd);
null_value= !tm->is_valid_datetime();
DBUG_ASSERT(maybe_null || !null_value);
return null_value;
}
bool Item_func_ceiling::time_op(THD *thd, MYSQL_TIME *to)
{
static const Time::Options_for_round opt;
Time *tm= new (to) Time(thd, args[0], opt);
tm->ceiling();
null_value= !tm->is_valid_time();
DBUG_ASSERT(maybe_null || !null_value);
return null_value;
}
longlong Item_func_floor::int_op()
{
switch (args[0]->result_type()) {
......@@ -2302,6 +2323,28 @@ my_decimal *Item_func_floor::decimal_op(my_decimal *decimal_value)
}
bool Item_func_floor::date_op(THD *thd, MYSQL_TIME *to, date_mode_t fuzzydate)
{
// DATETIME is not negative, so FLOOR means just truncation
Datetime::Options opt(thd, TIME_FRAC_TRUNCATE);
Datetime *tm= new (to) Datetime(thd, args[0], opt, 0);
null_value= !tm->is_valid_datetime();
DBUG_ASSERT(maybe_null || !null_value);
return null_value;
}
bool Item_func_floor::time_op(THD *thd, MYSQL_TIME *to)
{
static const Time::Options_for_round opt;
Time *tm= new (to) Time(thd, args[0], opt);
tm->floor();
null_value= !tm->is_valid_time();
DBUG_ASSERT(maybe_null || !null_value);
return null_value;
}
void Item_func_round::fix_length_and_dec_decimal(uint decimals_to_set)
{
int decimals_delta= args[0]->decimals - decimals_to_set;
......@@ -2540,9 +2583,7 @@ bool Item_func_round::time_op(THD *thd, MYSQL_TIME *to)
{
DBUG_ASSERT(args[0]->type_handler()->mysql_timestamp_type() ==
MYSQL_TIMESTAMP_TIME);
Time::Options opt(Time::default_flags_for_get_date(),
truncate ? TIME_FRAC_TRUNCATE : TIME_FRAC_ROUND,
Time::DATETIME_TO_TIME_DISALLOW);
Time::Options_for_round opt(truncate ? TIME_FRAC_TRUNCATE : TIME_FRAC_ROUND);
Longlong_hybrid_null dec= args[1]->to_longlong_hybrid_null();
Time *tm= new (to) Time(thd, args[0], opt,
dec.to_uint(TIME_SECOND_PART_DIGITS));
......
......@@ -1666,13 +1666,32 @@ class Item_func_cot :public Item_dec_func
};
class Item_func_int_val :public Item_func_num1
class Item_func_int_val :public Item_func_hybrid_field_type
{
public:
Item_func_int_val(THD *thd, Item *a): Item_func_num1(thd, a) {}
Item_func_int_val(THD *thd, Item *a): Item_func_hybrid_field_type(thd, a) {}
bool check_partition_func_processor(void *int_arg) { return FALSE; }
bool check_vcol_func_processor(void *arg) { return FALSE; }
void fix_length_and_dec_double();
void fix_length_and_dec_int_or_decimal();
void fix_length_and_dec_time()
{
fix_attributes_time(0);
set_handler(&type_handler_time2);
}
void fix_length_and_dec_datetime()
{
fix_attributes_datetime(0);
set_handler(&type_handler_datetime2);
maybe_null= true; // E.g. CEILING(TIMESTAMP'0000-01-01 23:59:59.9')
}
bool fix_length_and_dec();
String *str_op(String *str) { DBUG_ASSERT(0); return 0; }
bool native_op(THD *thd, Native *to)
{
DBUG_ASSERT(0);
return true;
}
};
......@@ -1684,6 +1703,8 @@ class Item_func_ceiling :public Item_func_int_val
longlong int_op();
double real_op();
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);
Item *get_copy(THD *thd)
{ return get_item_copy<Item_func_ceiling>(thd, this); }
};
......@@ -1697,6 +1718,8 @@ class Item_func_floor :public Item_func_int_val
longlong int_op();
double real_op();
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);
Item *get_copy(THD *thd)
{ return get_item_copy<Item_func_floor>(thd, this); }
};
......
......@@ -1580,7 +1580,7 @@ static void set_sec_part(ulong sec_part, MYSQL_TIME *ltime, Item *item)
{
ltime->second_part= sec_part;
if (item->decimals < TIME_SECOND_PART_DIGITS)
my_time_trunc(ltime, item->decimals);
my_datetime_trunc(ltime, item->decimals);
}
}
......
......@@ -1524,7 +1524,7 @@ bool Protocol_binary::store(MYSQL_TIME *tm, int decimals)
DBUG_ASSERT(decimals == AUTO_SEC_PART_DIGITS ||
(decimals >= 0 && decimals <= TIME_SECOND_PART_DIGITS));
if (decimals != AUTO_SEC_PART_DIGITS)
my_time_trunc(tm, decimals);
my_datetime_trunc(tm, decimals);
int4store(pos+7, tm->second_part);
if (tm->second_part)
length=11;
......
......@@ -5330,7 +5330,7 @@ bool Protocol_local::store(const char *str, size_t length,
bool Protocol_local::store(MYSQL_TIME *time, int decimals)
{
if (decimals != AUTO_SEC_PART_DIGITS)
my_time_trunc(time, decimals);
my_datetime_trunc(time, decimals);
return store_column(time, sizeof(MYSQL_TIME));
}
......
......@@ -980,7 +980,7 @@ bool Temporal::datetime_round_or_invalidate(THD *thd, uint dec, int *warn, ulong
DBUG_ASSERT(dec <= TIME_SECOND_PART_DIGITS);
if (datetime_add_nanoseconds_or_invalidate(thd, warn, nsec))
return true;
my_time_trunc(this, dec);
my_datetime_trunc(this, dec);
return false;
}
......@@ -5732,6 +5732,22 @@ bool Type_handler_int_result::
}
bool Type_handler_typelib::
Item_func_int_val_fix_length_and_dec(Item_func_int_val *item) const
{
item->fix_length_and_dec_int_or_decimal();
return false;
}
bool Type_handler_hex_hybrid::
Item_func_int_val_fix_length_and_dec(Item_func_int_val *item) const
{
item->fix_length_and_dec_int_or_decimal();
return false;
}
bool Type_handler_real_result::
Item_func_int_val_fix_length_and_dec(Item_func_int_val *item) const
{
......@@ -5756,6 +5772,30 @@ bool Type_handler_temporal_result::
}
bool Type_handler_time_common::
Item_func_int_val_fix_length_and_dec(Item_func_int_val *item) const
{
item->fix_length_and_dec_time();
return false;
}
bool Type_handler_datetime_common::
Item_func_int_val_fix_length_and_dec(Item_func_int_val *item) const
{
item->fix_length_and_dec_datetime();
return false;
}
bool Type_handler_timestamp_common::
Item_func_int_val_fix_length_and_dec(Item_func_int_val *item) const
{
item->fix_length_and_dec_datetime();
return false;
}
bool Type_handler_string_result::
Item_func_int_val_fix_length_and_dec(Item_func_int_val *item) const
{
......
......@@ -1358,6 +1358,14 @@ class Time: public Temporal
{ }
};
class Options_for_round: public Options
{
public:
Options_for_round(time_round_mode_t round_mode= TIME_FRAC_TRUNCATE)
:Options(Time::default_flags_for_get_date(), round_mode,
Time::DATETIME_TO_TIME_DISALLOW)
{ }
};
class Options_cmp: public Options
{
public:
......@@ -1709,6 +1717,40 @@ class Time: public Temporal
DBUG_ASSERT(is_valid_value_slow());
return *this;
}
Time &ceiling(int *warn)
{
if (is_valid_time())
{
if (neg)
my_time_trunc(this, 0);
else if (second_part)
round_or_set_max(0, warn, 999999999);
}
DBUG_ASSERT(is_valid_value_slow());
return *this;
}
Time &ceiling()
{
int warn= 0;
return ceiling(&warn);
}
Time &floor(int *warn)
{
if (is_valid_time())
{
if (!neg)
my_time_trunc(this, 0);
else if (second_part)
round_or_set_max(0, warn, 999999999);
}
DBUG_ASSERT(is_valid_value_slow());
return *this;
}
Time &floor()
{
int warn= 0;
return floor(&warn);
}
Time &round(uint dec, int *warn)
{
if (is_valid_time())
......@@ -2276,10 +2318,22 @@ class Datetime: public Temporal_with_date
Datetime &trunc(uint dec)
{
if (is_valid_datetime())
my_time_trunc(this, dec);
my_datetime_trunc(this, dec);
DBUG_ASSERT(is_valid_value_slow());
return *this;
}
Datetime &ceiling(THD *thd, int *warn)
{
if (is_valid_datetime() && second_part)
round_or_invalidate(thd, 0, warn, 999999999);
DBUG_ASSERT(is_valid_value_slow());
return *this;
}
Datetime &ceiling(THD *thd)
{
int warn= 0;
return ceiling(thd, &warn);
}
Datetime &round(THD *thd, uint dec, int *warn)
{
if (is_valid_datetime())
......@@ -5305,6 +5359,7 @@ class Type_handler_time_common: public Type_handler_temporal_result
MYSQL_TIME *, date_mode_t fuzzydate) const;
longlong Item_func_between_val_int(Item_func_between *func) const;
bool Item_func_round_fix_length_and_dec(Item_func_round *) const;
bool Item_func_int_val_fix_length_and_dec(Item_func_int_val *) const;
Item *make_const_item_for_comparison(THD *, Item *src, const Item *cmp) const;
bool set_comparator_func(Arg_comparator *cmp) const;
cmp_item *make_cmp_item(THD *thd, CHARSET_INFO *cs) const;
......@@ -5532,6 +5587,7 @@ class Type_handler_datetime_common: public Type_handler_temporal_with_date
my_decimal *Item_func_min_max_val_decimal(Item_func_min_max *,
my_decimal *) const;
bool Item_func_round_fix_length_and_dec(Item_func_round *) const;
bool Item_func_int_val_fix_length_and_dec(Item_func_int_val *) const;
bool Item_hybrid_func_fix_attributes(THD *thd,
const char *name,
Type_handler_hybrid_field_type *,
......@@ -5634,6 +5690,7 @@ class Type_handler_timestamp_common: public Type_handler_temporal_with_date
int cmp_native(const Native &a, const Native &b) const;
longlong Item_func_between_val_int(Item_func_between *func) const;
bool Item_func_round_fix_length_and_dec(Item_func_round *) const;
bool Item_func_int_val_fix_length_and_dec(Item_func_int_val *) const;
cmp_item *make_cmp_item(THD *thd, CHARSET_INFO *cs) const;
in_vector *make_in_vector(THD *thd, const Item_func_in *f, uint nargs) const;
void make_sort_key(uchar *to, Item *item, const SORT_FIELD_ATTR *sort_field,
......@@ -5977,6 +6034,7 @@ class Type_handler_hex_hybrid: public Type_handler_varchar
const Name name() const { return m_name_hex_hybrid; }
const Type_handler *cast_to_int_type_handler() const;
const Type_handler *type_handler_for_system_time() const;
bool Item_func_int_val_fix_length_and_dec(Item_func_int_val *) const;
};
......@@ -6212,6 +6270,7 @@ class Type_handler_typelib: public Type_handler_general_purpose_string
enum_field_types field_type() const { return MYSQL_TYPE_STRING; }
const Type_handler *type_handler_for_item_field() const;
const Type_handler *cast_to_int_type_handler() const;
bool Item_func_int_val_fix_length_and_dec(Item_func_int_val *) const;
bool Item_hybrid_func_fix_attributes(THD *thd,
const char *name,
Type_handler_hybrid_field_type *,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment