MDEV-17740 Extend EXTRACT(x AS DAY*) to understand long time intervals
This commit is contained in:
parent
f92d223fe2
commit
d2ba9edd66
@ -79,6 +79,16 @@ extern uchar days_in_month[];
|
||||
/* Useful constants */
|
||||
#define SECONDS_IN_24H 86400L
|
||||
|
||||
/* Limits for the INTERVAL data type */
|
||||
|
||||
/* Number of hours between '0001-01-01 00h' and '9999-12-31 23h' */
|
||||
#define TIME_MAX_INTERVAL_HOUR 87649415
|
||||
#define TIME_MAX_INTERVAL_HOUR_CHAR_LENGTH 8
|
||||
|
||||
/* Number of full days between '0001-01-01' and '9999-12-31'*/
|
||||
#define TIME_MAX_INTERVAL_DAY 3652058 /*87649415/24*/
|
||||
#define TIME_MAX_INTERVAL_DAY_CHAR_LENGTH 7
|
||||
|
||||
/* Limits for the TIME data type */
|
||||
#define TIME_MAX_HOUR 838
|
||||
#define TIME_MAX_MINUTE 59
|
||||
@ -112,7 +122,21 @@ my_bool str_to_DDhhmmssff(const char *str, size_t length, MYSQL_TIME *l_time,
|
||||
ulong max_hour, MYSQL_TIME_STATUS *status);
|
||||
my_bool str_to_datetime_or_date_or_time(const char *str, size_t length,
|
||||
MYSQL_TIME *to, ulonglong flag,
|
||||
MYSQL_TIME_STATUS *status);
|
||||
MYSQL_TIME_STATUS *status,
|
||||
ulong time_max_hour,
|
||||
ulong time_err_hour);
|
||||
my_bool
|
||||
str_to_datetime_or_date_or_interval_hhmmssff(const char *str, size_t length,
|
||||
MYSQL_TIME *to, ulonglong flag,
|
||||
MYSQL_TIME_STATUS *status,
|
||||
ulong time_max_hour,
|
||||
ulong time_err_hour);
|
||||
my_bool
|
||||
str_to_datetime_or_date_or_interval_day(const char *str, size_t length,
|
||||
MYSQL_TIME *to, ulonglong flag,
|
||||
MYSQL_TIME_STATUS *status,
|
||||
ulong time_max_hour,
|
||||
ulong time_err_hour);
|
||||
my_bool str_to_datetime_or_date(const char *str, size_t length, MYSQL_TIME *to,
|
||||
ulonglong flags, MYSQL_TIME_STATUS *status);
|
||||
|
||||
@ -120,7 +144,7 @@ longlong number_to_datetime_or_date(longlong nr, ulong sec_part,
|
||||
MYSQL_TIME *time_res,
|
||||
ulonglong flags, int *was_cut);
|
||||
int number_to_time_only(my_bool neg, ulonglong nr, ulong sec_part,
|
||||
MYSQL_TIME *ltime, int *was_cut);
|
||||
ulong max_hour, MYSQL_TIME *to, int *was_cut);
|
||||
|
||||
ulonglong TIME_to_ulonglong_datetime(const MYSQL_TIME *);
|
||||
ulonglong TIME_to_ulonglong_date(const MYSQL_TIME *);
|
||||
|
@ -3215,7 +3215,8 @@ static void fetch_string_with_conversion(MYSQL_BIND *param, char *value, size_t
|
||||
{
|
||||
MYSQL_TIME *tm= (MYSQL_TIME *)buffer;
|
||||
MYSQL_TIME_STATUS status;
|
||||
str_to_datetime_or_date_or_time(value, length, tm, 0, &status);
|
||||
str_to_datetime_or_date_or_time(value, length, tm, 0, &status,
|
||||
TIME_MAX_HOUR, UINT_MAX32);
|
||||
err= status.warnings;
|
||||
*param->error= MY_TEST(err);
|
||||
break;
|
||||
|
555
mysql-test/main/func_extract.result
Normal file
555
mysql-test/main/func_extract.result
Normal file
@ -0,0 +1,555 @@
|
||||
#
|
||||
# MDEV-17385 MICROSECOND() returns confusing results with an out-of-range TIME-alike argument
|
||||
#
|
||||
CREATE TABLE t1 (v VARCHAR(64), ll BIGINT, t TIME, dt DATETIME, d DATE);
|
||||
CREATE TABLE t2 AS SELECT
|
||||
EXTRACT(DAY FROM t),
|
||||
EXTRACT(DAY_HOUR FROM t),
|
||||
EXTRACT(DAY_MINUTE FROM t),
|
||||
EXTRACT(DAY_SECOND FROM t),
|
||||
EXTRACT(DAY_MICROSECOND FROM t),
|
||||
EXTRACT(DAY FROM d),
|
||||
EXTRACT(DAY_HOUR FROM d),
|
||||
EXTRACT(DAY_MINUTE FROM d),
|
||||
EXTRACT(DAY_SECOND FROM d),
|
||||
EXTRACT(DAY_MICROSECOND FROM d),
|
||||
EXTRACT(DAY FROM v),
|
||||
EXTRACT(DAY_HOUR FROM v),
|
||||
EXTRACT(DAY_MINUTE FROM v),
|
||||
EXTRACT(DAY_SECOND FROM v),
|
||||
EXTRACT(DAY_MICROSECOND FROM v),
|
||||
EXTRACT(DAY FROM ll),
|
||||
EXTRACT(DAY_HOUR FROM ll),
|
||||
EXTRACT(DAY_MINUTE FROM ll),
|
||||
EXTRACT(DAY_SECOND FROM ll),
|
||||
EXTRACT(DAY_MICROSECOND FROM ll)
|
||||
FROM t1;
|
||||
SHOW CREATE TABLE t2;
|
||||
Table Create Table
|
||||
t2 CREATE TABLE `t2` (
|
||||
`EXTRACT(DAY FROM t)` int(3) DEFAULT NULL,
|
||||
`EXTRACT(DAY_HOUR FROM t)` int(5) DEFAULT NULL,
|
||||
`EXTRACT(DAY_MINUTE FROM t)` int(7) DEFAULT NULL,
|
||||
`EXTRACT(DAY_SECOND FROM t)` int(9) DEFAULT NULL,
|
||||
`EXTRACT(DAY_MICROSECOND FROM t)` bigint(15) DEFAULT NULL,
|
||||
`EXTRACT(DAY FROM d)` int(3) DEFAULT NULL,
|
||||
`EXTRACT(DAY_HOUR FROM d)` int(5) DEFAULT NULL,
|
||||
`EXTRACT(DAY_MINUTE FROM d)` int(7) DEFAULT NULL,
|
||||
`EXTRACT(DAY_SECOND FROM d)` int(9) DEFAULT NULL,
|
||||
`EXTRACT(DAY_MICROSECOND FROM d)` bigint(15) DEFAULT NULL,
|
||||
`EXTRACT(DAY FROM v)` int(8) DEFAULT NULL,
|
||||
`EXTRACT(DAY_HOUR FROM v)` int(10) DEFAULT NULL,
|
||||
`EXTRACT(DAY_MINUTE FROM v)` bigint(12) DEFAULT NULL,
|
||||
`EXTRACT(DAY_SECOND FROM v)` bigint(14) DEFAULT NULL,
|
||||
`EXTRACT(DAY_MICROSECOND FROM v)` bigint(20) DEFAULT NULL,
|
||||
`EXTRACT(DAY FROM ll)` int(8) DEFAULT NULL,
|
||||
`EXTRACT(DAY_HOUR FROM ll)` int(10) DEFAULT NULL,
|
||||
`EXTRACT(DAY_MINUTE FROM ll)` bigint(12) DEFAULT NULL,
|
||||
`EXTRACT(DAY_SECOND FROM ll)` bigint(14) DEFAULT NULL,
|
||||
`EXTRACT(DAY_MICROSECOND FROM ll)` bigint(20) DEFAULT NULL
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=latin1
|
||||
DROP TABLE t2;
|
||||
DROP TABLE t1;
|
||||
CREATE TABLE t1 (a VARCHAR(64), b DECIMAL(32,9));
|
||||
INSERT INTO t1 VALUES
|
||||
('9999-12-31 23:59:59.123456', 99991231235959.123456),
|
||||
('2001-01-01 10:20:30.123456', 20010101102030.123456),
|
||||
('4294967296:59:59.123456', 42949672965959.123456),
|
||||
('4294967295:59:59.123456', 42949672955959.123456),
|
||||
('87649416:59:59.123456', 876494165959.123456),
|
||||
('87649415:59:59.123456', 876494155959.123456),
|
||||
('87649414:59:59.123456', 876494145959.123456),
|
||||
('9999:59:59.123456', 99995959.123456),
|
||||
('9999:01:01.123456', 99990101.123456),
|
||||
('9999:01:01', 99990101),
|
||||
('0.999999', 0.999999),
|
||||
('0.99999', 0.99999),
|
||||
('0.9999', 0.9999),
|
||||
('0.999', 0.999),
|
||||
('0.99', 0.99),
|
||||
('0.9', 0.9),
|
||||
('000000',0);
|
||||
# Summary:
|
||||
# Check that FUNC(varchar) and FUNC(decimal) give equal results
|
||||
# Expect empty sets
|
||||
SELECT a, b, EXTRACT(DAY_HOUR FROM a), EXTRACT(DAY_HOUR FROM b) FROM t1 WHERE NOT (EXTRACT(DAY_HOUR FROM a)<=>EXTRACT(DAY_HOUR FROM b));
|
||||
a b EXTRACT(DAY_HOUR FROM a) EXTRACT(DAY_HOUR FROM b)
|
||||
SELECT a, b, EXTRACT(DAY FROM a), EXTRACT(DAY FROM b) FROM t1 WHERE NOT (EXTRACT(DAY FROM a)<=>EXTRACT(DAY FROM b));
|
||||
a b EXTRACT(DAY FROM a) EXTRACT(DAY FROM b)
|
||||
SELECT a, b, EXTRACT(HOUR FROM a), EXTRACT(HOUR FROM b) FROM t1 WHERE NOT (EXTRACT(HOUR FROM a)<=>EXTRACT(HOUR FROM b));
|
||||
a b EXTRACT(HOUR FROM a) EXTRACT(HOUR FROM b)
|
||||
SELECT a, b, EXTRACT(MINUTE FROM a), EXTRACT(MINUTE FROM b) FROM t1 WHERE NOT (EXTRACT(MINUTE FROM a)<=>EXTRACT(MINUTE FROM b));
|
||||
a b EXTRACT(MINUTE FROM a) EXTRACT(MINUTE FROM b)
|
||||
SELECT a, b, EXTRACT(SECOND FROM a), EXTRACT(SECOND FROM b) FROM t1 WHERE NOT (EXTRACT(SECOND FROM a)<=>EXTRACT(SECOND FROM b));
|
||||
a b EXTRACT(SECOND FROM a) EXTRACT(SECOND FROM b)
|
||||
SELECT a, b, EXTRACT(MICROSECOND FROM a), EXTRACT(MICROSECOND FROM b) FROM t1 WHERE NOT (EXTRACT(MICROSECOND FROM a)<=>EXTRACT(MICROSECOND FROM b));
|
||||
a b EXTRACT(MICROSECOND FROM a) EXTRACT(MICROSECOND FROM b)
|
||||
# Detailed results
|
||||
SELECT
|
||||
a,
|
||||
EXTRACT(DAY FROM a) * 24 + EXTRACT(HOUR FROM a) AS dh,
|
||||
EXTRACT(DAY_HOUR FROM a),
|
||||
EXTRACT(DAY FROM a),
|
||||
EXTRACT(HOUR FROM a),
|
||||
EXTRACT(MINUTE FROM a),
|
||||
EXTRACT(SECOND FROM a),
|
||||
EXTRACT(MICROSECOND FROM a)
|
||||
FROM t1;
|
||||
a dh EXTRACT(DAY_HOUR FROM a) EXTRACT(DAY FROM a) EXTRACT(HOUR FROM a) EXTRACT(MINUTE FROM a) EXTRACT(SECOND FROM a) EXTRACT(MICROSECOND FROM a)
|
||||
9999-12-31 23:59:59.123456 767 3123 31 23 59 59 123456
|
||||
2001-01-01 10:20:30.123456 34 110 1 10 20 30 123456
|
||||
4294967296:59:59.123456 NULL NULL NULL NULL NULL NULL NULL
|
||||
4294967295:59:59.123456 NULL NULL NULL NULL NULL NULL NULL
|
||||
87649416:59:59.123456 NULL NULL NULL NULL NULL NULL NULL
|
||||
87649415:59:59.123456 87649415 365205823 3652058 23 59 59 123456
|
||||
87649414:59:59.123456 87649414 365205822 3652058 22 59 59 123456
|
||||
9999:59:59.123456 9999 41615 416 15 59 59 123456
|
||||
9999:01:01.123456 9999 41615 416 15 1 1 123456
|
||||
9999:01:01 9999 41615 416 15 1 1 0
|
||||
0.999999 0 0 0 0 0 0 999999
|
||||
0.99999 0 0 0 0 0 0 999990
|
||||
0.9999 0 0 0 0 0 0 999900
|
||||
0.999 0 0 0 0 0 0 999000
|
||||
0.99 0 0 0 0 0 0 990000
|
||||
0.9 0 0 0 0 0 0 900000
|
||||
000000 0 0 0 0 0 0 0
|
||||
Warnings:
|
||||
Warning 1292 Incorrect interval value: '4294967296:59:59.123456'
|
||||
Warning 1292 Incorrect interval value: '4294967296:59:59.123456'
|
||||
Warning 1292 Incorrect interval value: '4294967296:59:59.123456'
|
||||
Warning 1292 Incorrect interval value: '4294967296:59:59.123456'
|
||||
Warning 1292 Incorrect interval value: '4294967296:59:59.123456'
|
||||
Warning 1292 Incorrect interval value: '4294967296:59:59.123456'
|
||||
Warning 1292 Incorrect interval value: '4294967296:59:59.123456'
|
||||
Warning 1292 Incorrect interval value: '4294967296:59:59.123456'
|
||||
Warning 1292 Incorrect interval value: '4294967295:59:59.123456'
|
||||
Warning 1292 Incorrect interval value: '4294967295:59:59.123456'
|
||||
Warning 1292 Incorrect interval value: '4294967295:59:59.123456'
|
||||
Warning 1292 Incorrect interval value: '4294967295:59:59.123456'
|
||||
Warning 1292 Incorrect interval value: '4294967295:59:59.123456'
|
||||
Warning 1292 Incorrect interval value: '4294967295:59:59.123456'
|
||||
Warning 1292 Incorrect interval value: '4294967295:59:59.123456'
|
||||
Warning 1292 Incorrect interval value: '4294967295:59:59.123456'
|
||||
Warning 1292 Incorrect interval value: '87649416:59:59.123456'
|
||||
Warning 1292 Incorrect interval value: '87649416:59:59.123456'
|
||||
Warning 1292 Incorrect interval value: '87649416:59:59.123456'
|
||||
Warning 1292 Incorrect interval value: '87649416:59:59.123456'
|
||||
Warning 1292 Incorrect interval value: '87649416:59:59.123456'
|
||||
Warning 1292 Incorrect interval value: '87649416:59:59.123456'
|
||||
Warning 1292 Incorrect interval value: '87649416:59:59.123456'
|
||||
Warning 1292 Incorrect interval value: '87649416:59:59.123456'
|
||||
SELECT
|
||||
b,
|
||||
EXTRACT(DAY FROM b) * 24 + EXTRACT(HOUR FROM b) AS dh,
|
||||
EXTRACT(DAY_HOUR FROM b),
|
||||
EXTRACT(DAY FROM b),
|
||||
EXTRACT(HOUR FROM b),
|
||||
EXTRACT(MINUTE FROM b),
|
||||
EXTRACT(SECOND FROM b),
|
||||
EXTRACT(MICROSECOND FROM b)
|
||||
FROM t1;
|
||||
b dh EXTRACT(DAY_HOUR FROM b) EXTRACT(DAY FROM b) EXTRACT(HOUR FROM b) EXTRACT(MINUTE FROM b) EXTRACT(SECOND FROM b) EXTRACT(MICROSECOND FROM b)
|
||||
99991231235959.123456000 767 3123 31 23 59 59 123456
|
||||
20010101102030.123456000 34 110 1 10 20 30 123456
|
||||
42949672965959.123456000 NULL NULL NULL NULL NULL NULL NULL
|
||||
42949672955959.123456000 NULL NULL NULL NULL NULL NULL NULL
|
||||
876494165959.123456000 NULL NULL NULL NULL NULL NULL NULL
|
||||
876494155959.123456000 87649415 365205823 3652058 23 59 59 123456
|
||||
876494145959.123456000 87649414 365205822 3652058 22 59 59 123456
|
||||
99995959.123456000 9999 41615 416 15 59 59 123456
|
||||
99990101.123456000 9999 41615 416 15 1 1 123456
|
||||
99990101.000000000 9999 41615 416 15 1 1 0
|
||||
0.999999000 0 0 0 0 0 0 999999
|
||||
0.999990000 0 0 0 0 0 0 999990
|
||||
0.999900000 0 0 0 0 0 0 999900
|
||||
0.999000000 0 0 0 0 0 0 999000
|
||||
0.990000000 0 0 0 0 0 0 990000
|
||||
0.900000000 0 0 0 0 0 0 900000
|
||||
0.000000000 0 0 0 0 0 0 0
|
||||
Warnings:
|
||||
Warning 1292 Incorrect interval value: '42949672965959.123456000' for column 'b' at row 3
|
||||
Warning 1292 Incorrect interval value: '42949672965959.123456000' for column 'b' at row 3
|
||||
Warning 1292 Incorrect interval value: '42949672965959.123456000' for column 'b' at row 3
|
||||
Warning 1292 Incorrect interval value: '42949672965959.123456000' for column 'b' at row 3
|
||||
Warning 1292 Incorrect interval value: '42949672965959.123456000' for column 'b' at row 3
|
||||
Warning 1292 Incorrect interval value: '42949672965959.123456000' for column 'b' at row 3
|
||||
Warning 1292 Incorrect interval value: '42949672965959.123456000' for column 'b' at row 3
|
||||
Warning 1292 Incorrect interval value: '42949672965959.123456000' for column 'b' at row 3
|
||||
Warning 1292 Incorrect interval value: '42949672955959.123456000' for column 'b' at row 4
|
||||
Warning 1292 Incorrect interval value: '42949672955959.123456000' for column 'b' at row 4
|
||||
Warning 1292 Incorrect interval value: '42949672955959.123456000' for column 'b' at row 4
|
||||
Warning 1292 Incorrect interval value: '42949672955959.123456000' for column 'b' at row 4
|
||||
Warning 1292 Incorrect interval value: '42949672955959.123456000' for column 'b' at row 4
|
||||
Warning 1292 Incorrect interval value: '42949672955959.123456000' for column 'b' at row 4
|
||||
Warning 1292 Incorrect interval value: '42949672955959.123456000' for column 'b' at row 4
|
||||
Warning 1292 Incorrect interval value: '42949672955959.123456000' for column 'b' at row 4
|
||||
Warning 1292 Incorrect interval value: '876494165959.123456000' for column 'b' at row 5
|
||||
Warning 1292 Incorrect interval value: '876494165959.123456000' for column 'b' at row 5
|
||||
Warning 1292 Incorrect interval value: '876494165959.123456000' for column 'b' at row 5
|
||||
Warning 1292 Incorrect interval value: '876494165959.123456000' for column 'b' at row 5
|
||||
Warning 1292 Incorrect interval value: '876494165959.123456000' for column 'b' at row 5
|
||||
Warning 1292 Incorrect interval value: '876494165959.123456000' for column 'b' at row 5
|
||||
Warning 1292 Incorrect interval value: '876494165959.123456000' for column 'b' at row 5
|
||||
Warning 1292 Incorrect interval value: '876494165959.123456000' for column 'b' at row 5
|
||||
DROP TABLE t1;
|
||||
# Special case: DAY + TIME
|
||||
CREATE TABLE t1 (a VARCHAR(64));
|
||||
INSERT INTO t1 VALUES ('9999-01-01');
|
||||
SELECT a,
|
||||
EXTRACT(DAY_HOUR FROM a),
|
||||
EXTRACT(DAY_MINUTE FROM a),
|
||||
EXTRACT(DAY_SECOND FROM a),
|
||||
EXTRACT(DAY_MICROSECOND FROM a),
|
||||
EXTRACT(DAY FROM a),
|
||||
EXTRACT(HOUR FROM a),
|
||||
EXTRACT(MINUTE FROM a),
|
||||
EXTRACT(SECOND FROM a),
|
||||
EXTRACT(MICROSECOND FROM a)
|
||||
FROM t1;
|
||||
a EXTRACT(DAY_HOUR FROM a) EXTRACT(DAY_MINUTE FROM a) EXTRACT(DAY_SECOND FROM a) EXTRACT(DAY_MICROSECOND FROM a) EXTRACT(DAY FROM a) EXTRACT(HOUR FROM a) EXTRACT(MINUTE FROM a) EXTRACT(SECOND FROM a) EXTRACT(MICROSECOND FROM a)
|
||||
9999-01-01 100 10000 1000000 1000000000000 1 0 0 0 0
|
||||
DROP TABLE t1;
|
||||
# Bad values
|
||||
CREATE TABLE t1 (a VARCHAR(64));
|
||||
INSERT INTO t1 VALUES ('');
|
||||
SELECT a,
|
||||
EXTRACT(DAY_HOUR FROM a),
|
||||
EXTRACT(DAY_MINUTE FROM a),
|
||||
EXTRACT(DAY_SECOND FROM a),
|
||||
EXTRACT(DAY_MICROSECOND FROM a),
|
||||
EXTRACT(DAY FROM a),
|
||||
EXTRACT(HOUR FROM a),
|
||||
EXTRACT(MINUTE FROM a),
|
||||
EXTRACT(SECOND FROM a),
|
||||
EXTRACT(MICROSECOND FROM a)
|
||||
FROM t1;
|
||||
a EXTRACT(DAY_HOUR FROM a) EXTRACT(DAY_MINUTE FROM a) EXTRACT(DAY_SECOND FROM a) EXTRACT(DAY_MICROSECOND FROM a) EXTRACT(DAY FROM a) EXTRACT(HOUR FROM a) EXTRACT(MINUTE FROM a) EXTRACT(SECOND FROM a) EXTRACT(MICROSECOND FROM a)
|
||||
NULL NULL NULL NULL NULL NULL NULL NULL NULL
|
||||
Warnings:
|
||||
Warning 1292 Incorrect interval value: ''
|
||||
Warning 1292 Incorrect interval value: ''
|
||||
Warning 1292 Incorrect interval value: ''
|
||||
Warning 1292 Incorrect interval value: ''
|
||||
Warning 1292 Incorrect interval value: ''
|
||||
Warning 1292 Incorrect interval value: ''
|
||||
Warning 1292 Incorrect interval value: ''
|
||||
Warning 1292 Incorrect interval value: ''
|
||||
Warning 1292 Incorrect interval value: ''
|
||||
DROP TABLE t1;
|
||||
# Backward compatibility
|
||||
# This still parses as DATETIME
|
||||
SELECT EXTRACT(YEAR FROM '2001/02/03 10:20:30');
|
||||
EXTRACT(YEAR FROM '2001/02/03 10:20:30')
|
||||
2001
|
||||
SELECT EXTRACT(MONTH FROM '2001/02/03 10:20:30');
|
||||
EXTRACT(MONTH FROM '2001/02/03 10:20:30')
|
||||
2
|
||||
SELECT EXTRACT(DAY FROM '2001/02/03 10:20:30');
|
||||
EXTRACT(DAY FROM '2001/02/03 10:20:30')
|
||||
3
|
||||
SELECT EXTRACT(YEAR FROM '01/02/03 10:20:30');
|
||||
EXTRACT(YEAR FROM '01/02/03 10:20:30')
|
||||
2001
|
||||
SELECT EXTRACT(MONTH FROM '01/02/03 10:20:30');
|
||||
EXTRACT(MONTH FROM '01/02/03 10:20:30')
|
||||
2
|
||||
SELECT EXTRACT(DAY FROM '01/02/03 10:20:30');
|
||||
EXTRACT(DAY FROM '01/02/03 10:20:30')
|
||||
3
|
||||
SELECT EXTRACT(YEAR FROM '01:02:03 10:20:30');
|
||||
EXTRACT(YEAR FROM '01:02:03 10:20:30')
|
||||
2001
|
||||
SELECT EXTRACT(MONTH FROM '01:02:03 10:20:30');
|
||||
EXTRACT(MONTH FROM '01:02:03 10:20:30')
|
||||
2
|
||||
SELECT EXTRACT(DAY FROM '01:02:03 10:20:30');
|
||||
EXTRACT(DAY FROM '01:02:03 10:20:30')
|
||||
3
|
||||
# This still parses as DATETIME and returns NULL
|
||||
SELECT EXTRACT(YEAR FROM "2011-02-32 8:46:06.23434");
|
||||
EXTRACT(YEAR FROM "2011-02-32 8:46:06.23434")
|
||||
NULL
|
||||
Warnings:
|
||||
Warning 1292 Incorrect datetime value: '2011-02-32 8:46:06.23434'
|
||||
SELECT EXTRACT(MONTH FROM "2011-02-32 8:46:06.23434");
|
||||
EXTRACT(MONTH FROM "2011-02-32 8:46:06.23434")
|
||||
NULL
|
||||
Warnings:
|
||||
Warning 1292 Incorrect datetime value: '2011-02-32 8:46:06.23434'
|
||||
SELECT EXTRACT(DAY FROM "2011-02-32 8:46:06.23434");
|
||||
EXTRACT(DAY FROM "2011-02-32 8:46:06.23434")
|
||||
NULL
|
||||
Warnings:
|
||||
Warning 1292 Incorrect interval value: '2011-02-32 8:46:06.23434'
|
||||
SELECT EXTRACT(HOUR FROM "2011-02-32 8:46:06.23434");
|
||||
EXTRACT(HOUR FROM "2011-02-32 8:46:06.23434")
|
||||
NULL
|
||||
Warnings:
|
||||
Warning 1292 Incorrect interval value: '2011-02-32 8:46:06.23434'
|
||||
# This still parses as DATE
|
||||
SELECT EXTRACT(YEAR FROM '2001/02/03');
|
||||
EXTRACT(YEAR FROM '2001/02/03')
|
||||
2001
|
||||
SELECT EXTRACT(MONTH FROM '2001/02/03');
|
||||
EXTRACT(MONTH FROM '2001/02/03')
|
||||
2
|
||||
SELECT EXTRACT(DAY FROM '2001/02/03');
|
||||
EXTRACT(DAY FROM '2001/02/03')
|
||||
3
|
||||
SELECT EXTRACT(YEAR FROM '01/02/03');
|
||||
EXTRACT(YEAR FROM '01/02/03')
|
||||
2001
|
||||
SELECT EXTRACT(MONTH FROM '01/02/03');
|
||||
EXTRACT(MONTH FROM '01/02/03')
|
||||
2
|
||||
SELECT EXTRACT(DAY FROM '01/02/03');
|
||||
EXTRACT(DAY FROM '01/02/03')
|
||||
3
|
||||
SELECT EXTRACT(YEAR FROM '01-02-03');
|
||||
EXTRACT(YEAR FROM '01-02-03')
|
||||
2001
|
||||
SELECT EXTRACT(MONTH FROM '01-02-03');
|
||||
EXTRACT(MONTH FROM '01-02-03')
|
||||
2
|
||||
SELECT EXTRACT(DAY FROM '01-02-03');
|
||||
EXTRACT(DAY FROM '01-02-03')
|
||||
3
|
||||
SELECT EXTRACT(YEAR FROM '1-2-3');
|
||||
EXTRACT(YEAR FROM '1-2-3')
|
||||
1
|
||||
SELECT EXTRACT(MONTH FROM '1-2-3');
|
||||
EXTRACT(MONTH FROM '1-2-3')
|
||||
2
|
||||
SELECT EXTRACT(DAY FROM '1-2-3');
|
||||
EXTRACT(DAY FROM '1-2-3')
|
||||
3
|
||||
SELECT EXTRACT(HOUR FROM '1-2-3');
|
||||
EXTRACT(HOUR FROM '1-2-3')
|
||||
0
|
||||
SELECT EXTRACT(DAY FROM '2024-01-03 garbage /////');
|
||||
EXTRACT(DAY FROM '2024-01-03 garbage /////')
|
||||
3
|
||||
Warnings:
|
||||
Warning 1292 Truncated incorrect date value: '2024-01-03 garbage /////'
|
||||
SELECT EXTRACT(DAY FROM '24-01-03 garbage /////');
|
||||
EXTRACT(DAY FROM '24-01-03 garbage /////')
|
||||
3
|
||||
Warnings:
|
||||
Warning 1292 Truncated incorrect date value: '24-01-03 garbage /////'
|
||||
SELECT EXTRACT(DAY FROM '01-02-03');
|
||||
EXTRACT(DAY FROM '01-02-03')
|
||||
3
|
||||
SELECT EXTRACT(DAY FROM '24:02:03T');
|
||||
EXTRACT(DAY FROM '24:02:03T')
|
||||
3
|
||||
SELECT EXTRACT(DAY FROM '24-02-03');
|
||||
EXTRACT(DAY FROM '24-02-03')
|
||||
3
|
||||
SELECT EXTRACT(DAY FROM '24/02/03');
|
||||
EXTRACT(DAY FROM '24/02/03')
|
||||
3
|
||||
SELECT EXTRACT(DAY FROM '11111');
|
||||
EXTRACT(DAY FROM '11111')
|
||||
1
|
||||
SELECT TIME('2001-01-01T'), TIME('2001-01-01T ');
|
||||
TIME('2001-01-01T') TIME('2001-01-01T ')
|
||||
00:00:00 00:00:00
|
||||
SELECT TIME('2001/01/01T'), TIME('2001/01/01T ');
|
||||
TIME('2001/01/01T') TIME('2001/01/01T ')
|
||||
00:00:00 00:00:00
|
||||
SELECT TIME('2001:01:01T'), TIME('2001:01:01T ');
|
||||
TIME('2001:01:01T') TIME('2001:01:01T ')
|
||||
00:00:00 00:00:00
|
||||
SELECT EXTRACT(DAY FROM '2001-01-01T'), EXTRACT(DAY FROM '2001-01-01T ');
|
||||
EXTRACT(DAY FROM '2001-01-01T') EXTRACT(DAY FROM '2001-01-01T ')
|
||||
1 1
|
||||
SELECT EXTRACT(DAY FROM '2001/01/01T'), EXTRACT(DAY FROM '2001/01/01T ');
|
||||
EXTRACT(DAY FROM '2001/01/01T') EXTRACT(DAY FROM '2001/01/01T ')
|
||||
1 1
|
||||
SELECT EXTRACT(DAY FROM '2001:01:01T'), EXTRACT(DAY FROM '2001:01:01T ');
|
||||
EXTRACT(DAY FROM '2001:01:01T') EXTRACT(DAY FROM '2001:01:01T ')
|
||||
1 1
|
||||
SELECT TIME('2001:01:01T'), TIME('2001:01:01T ');
|
||||
TIME('2001:01:01T') TIME('2001:01:01T ')
|
||||
00:00:00 00:00:00
|
||||
SELECT EXTRACT(HOUR FROM '2001-01-01T'), EXTRACT(HOUR FROM '2001-01-01T ');
|
||||
EXTRACT(HOUR FROM '2001-01-01T') EXTRACT(HOUR FROM '2001-01-01T ')
|
||||
0 0
|
||||
SELECT EXTRACT(HOUR FROM '2001/01/01T'), EXTRACT(HOUR FROM '2001/01/01T ');
|
||||
EXTRACT(HOUR FROM '2001/01/01T') EXTRACT(HOUR FROM '2001/01/01T ')
|
||||
0 0
|
||||
SELECT EXTRACT(HOUR FROM '2001:01:01T'), EXTRACT(HOUR FROM '2001:01:01T ');
|
||||
EXTRACT(HOUR FROM '2001:01:01T') EXTRACT(HOUR FROM '2001:01:01T ')
|
||||
0 0
|
||||
# This still parses as DATE and returns NULL (without trying TIME)
|
||||
SELECT EXTRACT(DAY FROM '100000:02:03T');
|
||||
EXTRACT(DAY FROM '100000:02:03T')
|
||||
NULL
|
||||
Warnings:
|
||||
Warning 1292 Incorrect interval value: '100000:02:03T'
|
||||
SELECT EXTRACT(DAY FROM '100000/02/03');
|
||||
EXTRACT(DAY FROM '100000/02/03')
|
||||
NULL
|
||||
Warnings:
|
||||
Warning 1292 Incorrect interval value: '100000/02/03'
|
||||
SELECT EXTRACT(DAY FROM '100000-02-03');
|
||||
EXTRACT(DAY FROM '100000-02-03')
|
||||
NULL
|
||||
Warnings:
|
||||
Warning 1292 Incorrect interval value: '100000-02-03'
|
||||
SELECT EXTRACT(DAY FROM '1111');
|
||||
EXTRACT(DAY FROM '1111')
|
||||
NULL
|
||||
Warnings:
|
||||
Warning 1292 Incorrect interval value: '1111'
|
||||
SELECT EXTRACT(DAY FROM '111');
|
||||
EXTRACT(DAY FROM '111')
|
||||
NULL
|
||||
Warnings:
|
||||
Warning 1292 Incorrect interval value: '111'
|
||||
SELECT EXTRACT(DAY FROM '11');
|
||||
EXTRACT(DAY FROM '11')
|
||||
NULL
|
||||
Warnings:
|
||||
Warning 1292 Incorrect interval value: '11'
|
||||
SELECT EXTRACT(DAY FROM '1');
|
||||
EXTRACT(DAY FROM '1')
|
||||
NULL
|
||||
Warnings:
|
||||
Warning 1292 Incorrect interval value: '1'
|
||||
# This still parses as TIME
|
||||
SELECT EXTRACT(HOUR FROM '11111');
|
||||
EXTRACT(HOUR FROM '11111')
|
||||
1
|
||||
SELECT EXTRACT(HOUR FROM '1111');
|
||||
EXTRACT(HOUR FROM '1111')
|
||||
0
|
||||
SELECT EXTRACT(HOUR FROM '111');
|
||||
EXTRACT(HOUR FROM '111')
|
||||
0
|
||||
SELECT EXTRACT(HOUR FROM '11');
|
||||
EXTRACT(HOUR FROM '11')
|
||||
0
|
||||
SELECT EXTRACT(HOUR FROM '1');
|
||||
EXTRACT(HOUR FROM '1')
|
||||
0
|
||||
SELECT TIME('01:02:03:');
|
||||
TIME('01:02:03:')
|
||||
01:02:03
|
||||
Warnings:
|
||||
Warning 1292 Truncated incorrect time value: '01:02:03:'
|
||||
SELECT TIME('01:02:03-');
|
||||
TIME('01:02:03-')
|
||||
01:02:03
|
||||
Warnings:
|
||||
Warning 1292 Truncated incorrect time value: '01:02:03-'
|
||||
SELECT TIME('01:02:03;');
|
||||
TIME('01:02:03;')
|
||||
01:02:03
|
||||
Warnings:
|
||||
Warning 1292 Truncated incorrect time value: '01:02:03;'
|
||||
SELECT TIME('01:02:03/');
|
||||
TIME('01:02:03/')
|
||||
01:02:03
|
||||
Warnings:
|
||||
Warning 1292 Truncated incorrect time value: '01:02:03/'
|
||||
SELECT EXTRACT(HOUR FROM '01:02:03:');
|
||||
EXTRACT(HOUR FROM '01:02:03:')
|
||||
1
|
||||
Warnings:
|
||||
Warning 1292 Truncated incorrect time value: '01:02:03:'
|
||||
SELECT EXTRACT(HOUR FROM '01:02:03-');
|
||||
EXTRACT(HOUR FROM '01:02:03-')
|
||||
1
|
||||
Warnings:
|
||||
Warning 1292 Truncated incorrect time value: '01:02:03-'
|
||||
SELECT EXTRACT(HOUR FROM '01:02:03;');
|
||||
EXTRACT(HOUR FROM '01:02:03;')
|
||||
1
|
||||
Warnings:
|
||||
Warning 1292 Truncated incorrect time value: '01:02:03;'
|
||||
SELECT EXTRACT(HOUR FROM '01:02:03/');
|
||||
EXTRACT(HOUR FROM '01:02:03/')
|
||||
1
|
||||
Warnings:
|
||||
Warning 1292 Truncated incorrect time value: '01:02:03/'
|
||||
# Backward compatibility preserved for YEAR and MONTH only
|
||||
# (behavior has changed for DAY, see below)
|
||||
SELECT EXTRACT(YEAR FROM '01:02:03');
|
||||
EXTRACT(YEAR FROM '01:02:03')
|
||||
2001
|
||||
SELECT EXTRACT(MONTH FROM '01:02:03');
|
||||
EXTRACT(MONTH FROM '01:02:03')
|
||||
2
|
||||
SELECT EXTRACT(YEAR FROM '24:01:03 garbage /////');
|
||||
EXTRACT(YEAR FROM '24:01:03 garbage /////')
|
||||
2024
|
||||
Warnings:
|
||||
Warning 1292 Truncated incorrect date value: '24:01:03 garbage /////'
|
||||
SELECT EXTRACT(MONTH FROM '24:01:03 garbage /////');
|
||||
EXTRACT(MONTH FROM '24:01:03 garbage /////')
|
||||
1
|
||||
Warnings:
|
||||
Warning 1292 Truncated incorrect date value: '24:01:03 garbage /////'
|
||||
# This still parses as TIME 00:20:01
|
||||
SELECT TIME('2001/01/01');
|
||||
TIME('2001/01/01')
|
||||
00:20:01
|
||||
Warnings:
|
||||
Warning 1292 Truncated incorrect time value: '2001/01/01'
|
||||
SELECT TIME('2001-01-01');
|
||||
TIME('2001-01-01')
|
||||
00:20:01
|
||||
Warnings:
|
||||
Warning 1292 Truncated incorrect time value: '2001-01-01'
|
||||
# This still parses as TIME and overflows to '838:59:59'
|
||||
SELECT TIME('2001:01:01');
|
||||
TIME('2001:01:01')
|
||||
838:59:59
|
||||
Warnings:
|
||||
Warning 1292 Truncated incorrect time value: '2001:01:01'
|
||||
# This used to parse as DATE, now parses as TIME interval
|
||||
CREATE TABLE t1 (a VARCHAR(64));
|
||||
INSERT INTO t1 VALUES
|
||||
('2024:01:03 garbage /////'),
|
||||
('24:01:03 garbage /////'),
|
||||
('01:01:03 garbage /////'),
|
||||
('2024:02:03'),
|
||||
('100000:02:03'),
|
||||
('24:02:03'),
|
||||
('01:02:03'),
|
||||
('01:02:03:'),
|
||||
('01:02:03-'),
|
||||
('01:02:03;'),
|
||||
('01:02:03/'),
|
||||
('20 10:20:30');
|
||||
SELECT EXTRACT(DAY FROM a), EXTRACT(DAY_SECOND FROM a), a FROM t1;
|
||||
EXTRACT(DAY FROM a) EXTRACT(DAY_SECOND FROM a) a
|
||||
84 84080103 2024:01:03 garbage /////
|
||||
1 1000103 24:01:03 garbage /////
|
||||
0 10103 01:01:03 garbage /////
|
||||
84 84080203 2024:02:03
|
||||
4166 4166160203 100000:02:03
|
||||
1 1000203 24:02:03
|
||||
0 10203 01:02:03
|
||||
0 10203 01:02:03:
|
||||
0 10203 01:02:03-
|
||||
0 10203 01:02:03;
|
||||
0 10203 01:02:03/
|
||||
20 20102030 20 10:20:30
|
||||
Warnings:
|
||||
Warning 1292 Truncated incorrect time value: '2024:01:03 garbage /////'
|
||||
Warning 1292 Truncated incorrect time value: '2024:01:03 garbage /////'
|
||||
Warning 1292 Truncated incorrect time value: '24:01:03 garbage /////'
|
||||
Warning 1292 Truncated incorrect time value: '24:01:03 garbage /////'
|
||||
Warning 1292 Truncated incorrect time value: '01:01:03 garbage /////'
|
||||
Warning 1292 Truncated incorrect time value: '01:01:03 garbage /////'
|
||||
Warning 1292 Truncated incorrect time value: '01:02:03:'
|
||||
Warning 1292 Truncated incorrect time value: '01:02:03:'
|
||||
Warning 1292 Truncated incorrect time value: '01:02:03-'
|
||||
Warning 1292 Truncated incorrect time value: '01:02:03-'
|
||||
Warning 1292 Truncated incorrect time value: '01:02:03;'
|
||||
Warning 1292 Truncated incorrect time value: '01:02:03;'
|
||||
Warning 1292 Truncated incorrect time value: '01:02:03/'
|
||||
Warning 1292 Truncated incorrect time value: '01:02:03/'
|
||||
DROP TABLE t1;
|
250
mysql-test/main/func_extract.test
Normal file
250
mysql-test/main/func_extract.test
Normal file
@ -0,0 +1,250 @@
|
||||
--echo #
|
||||
--echo # MDEV-17385 MICROSECOND() returns confusing results with an out-of-range TIME-alike argument
|
||||
--echo #
|
||||
|
||||
CREATE TABLE t1 (v VARCHAR(64), ll BIGINT, t TIME, dt DATETIME, d DATE);
|
||||
CREATE TABLE t2 AS SELECT
|
||||
EXTRACT(DAY FROM t),
|
||||
EXTRACT(DAY_HOUR FROM t),
|
||||
EXTRACT(DAY_MINUTE FROM t),
|
||||
EXTRACT(DAY_SECOND FROM t),
|
||||
EXTRACT(DAY_MICROSECOND FROM t),
|
||||
EXTRACT(DAY FROM d),
|
||||
EXTRACT(DAY_HOUR FROM d),
|
||||
EXTRACT(DAY_MINUTE FROM d),
|
||||
EXTRACT(DAY_SECOND FROM d),
|
||||
EXTRACT(DAY_MICROSECOND FROM d),
|
||||
EXTRACT(DAY FROM v),
|
||||
EXTRACT(DAY_HOUR FROM v),
|
||||
EXTRACT(DAY_MINUTE FROM v),
|
||||
EXTRACT(DAY_SECOND FROM v),
|
||||
EXTRACT(DAY_MICROSECOND FROM v),
|
||||
EXTRACT(DAY FROM ll),
|
||||
EXTRACT(DAY_HOUR FROM ll),
|
||||
EXTRACT(DAY_MINUTE FROM ll),
|
||||
EXTRACT(DAY_SECOND FROM ll),
|
||||
EXTRACT(DAY_MICROSECOND FROM ll)
|
||||
FROM t1;
|
||||
SHOW CREATE TABLE t2;
|
||||
DROP TABLE t2;
|
||||
DROP TABLE t1;
|
||||
|
||||
|
||||
CREATE TABLE t1 (a VARCHAR(64), b DECIMAL(32,9));
|
||||
INSERT INTO t1 VALUES
|
||||
('9999-12-31 23:59:59.123456', 99991231235959.123456),
|
||||
('2001-01-01 10:20:30.123456', 20010101102030.123456),
|
||||
('4294967296:59:59.123456', 42949672965959.123456),
|
||||
('4294967295:59:59.123456', 42949672955959.123456),
|
||||
('87649416:59:59.123456', 876494165959.123456),
|
||||
('87649415:59:59.123456', 876494155959.123456),
|
||||
('87649414:59:59.123456', 876494145959.123456),
|
||||
('9999:59:59.123456', 99995959.123456),
|
||||
('9999:01:01.123456', 99990101.123456),
|
||||
('9999:01:01', 99990101),
|
||||
('0.999999', 0.999999),
|
||||
('0.99999', 0.99999),
|
||||
('0.9999', 0.9999),
|
||||
('0.999', 0.999),
|
||||
('0.99', 0.99),
|
||||
('0.9', 0.9),
|
||||
('000000',0);
|
||||
|
||||
--echo # Summary:
|
||||
--echo # Check that FUNC(varchar) and FUNC(decimal) give equal results
|
||||
--echo # Expect empty sets
|
||||
--disable_warnings
|
||||
SELECT a, b, EXTRACT(DAY_HOUR FROM a), EXTRACT(DAY_HOUR FROM b) FROM t1 WHERE NOT (EXTRACT(DAY_HOUR FROM a)<=>EXTRACT(DAY_HOUR FROM b));
|
||||
SELECT a, b, EXTRACT(DAY FROM a), EXTRACT(DAY FROM b) FROM t1 WHERE NOT (EXTRACT(DAY FROM a)<=>EXTRACT(DAY FROM b));
|
||||
SELECT a, b, EXTRACT(HOUR FROM a), EXTRACT(HOUR FROM b) FROM t1 WHERE NOT (EXTRACT(HOUR FROM a)<=>EXTRACT(HOUR FROM b));
|
||||
SELECT a, b, EXTRACT(MINUTE FROM a), EXTRACT(MINUTE FROM b) FROM t1 WHERE NOT (EXTRACT(MINUTE FROM a)<=>EXTRACT(MINUTE FROM b));
|
||||
SELECT a, b, EXTRACT(SECOND FROM a), EXTRACT(SECOND FROM b) FROM t1 WHERE NOT (EXTRACT(SECOND FROM a)<=>EXTRACT(SECOND FROM b));
|
||||
SELECT a, b, EXTRACT(MICROSECOND FROM a), EXTRACT(MICROSECOND FROM b) FROM t1 WHERE NOT (EXTRACT(MICROSECOND FROM a)<=>EXTRACT(MICROSECOND FROM b));
|
||||
--enable_warnings
|
||||
|
||||
--echo # Detailed results
|
||||
SELECT
|
||||
a,
|
||||
EXTRACT(DAY FROM a) * 24 + EXTRACT(HOUR FROM a) AS dh,
|
||||
EXTRACT(DAY_HOUR FROM a),
|
||||
EXTRACT(DAY FROM a),
|
||||
EXTRACT(HOUR FROM a),
|
||||
EXTRACT(MINUTE FROM a),
|
||||
EXTRACT(SECOND FROM a),
|
||||
EXTRACT(MICROSECOND FROM a)
|
||||
FROM t1;
|
||||
SELECT
|
||||
b,
|
||||
EXTRACT(DAY FROM b) * 24 + EXTRACT(HOUR FROM b) AS dh,
|
||||
EXTRACT(DAY_HOUR FROM b),
|
||||
EXTRACT(DAY FROM b),
|
||||
EXTRACT(HOUR FROM b),
|
||||
EXTRACT(MINUTE FROM b),
|
||||
EXTRACT(SECOND FROM b),
|
||||
EXTRACT(MICROSECOND FROM b)
|
||||
FROM t1;
|
||||
DROP TABLE t1;
|
||||
|
||||
--echo # Special case: DAY + TIME
|
||||
CREATE TABLE t1 (a VARCHAR(64));
|
||||
INSERT INTO t1 VALUES ('9999-01-01');
|
||||
SELECT a,
|
||||
EXTRACT(DAY_HOUR FROM a),
|
||||
EXTRACT(DAY_MINUTE FROM a),
|
||||
EXTRACT(DAY_SECOND FROM a),
|
||||
EXTRACT(DAY_MICROSECOND FROM a),
|
||||
EXTRACT(DAY FROM a),
|
||||
EXTRACT(HOUR FROM a),
|
||||
EXTRACT(MINUTE FROM a),
|
||||
EXTRACT(SECOND FROM a),
|
||||
EXTRACT(MICROSECOND FROM a)
|
||||
FROM t1;
|
||||
DROP TABLE t1;
|
||||
|
||||
--echo # Bad values
|
||||
CREATE TABLE t1 (a VARCHAR(64));
|
||||
INSERT INTO t1 VALUES ('');
|
||||
SELECT a,
|
||||
EXTRACT(DAY_HOUR FROM a),
|
||||
EXTRACT(DAY_MINUTE FROM a),
|
||||
EXTRACT(DAY_SECOND FROM a),
|
||||
EXTRACT(DAY_MICROSECOND FROM a),
|
||||
EXTRACT(DAY FROM a),
|
||||
EXTRACT(HOUR FROM a),
|
||||
EXTRACT(MINUTE FROM a),
|
||||
EXTRACT(SECOND FROM a),
|
||||
EXTRACT(MICROSECOND FROM a)
|
||||
FROM t1;
|
||||
DROP TABLE t1;
|
||||
|
||||
|
||||
--echo # Backward compatibility
|
||||
|
||||
--echo # This still parses as DATETIME
|
||||
SELECT EXTRACT(YEAR FROM '2001/02/03 10:20:30');
|
||||
SELECT EXTRACT(MONTH FROM '2001/02/03 10:20:30');
|
||||
SELECT EXTRACT(DAY FROM '2001/02/03 10:20:30');
|
||||
|
||||
SELECT EXTRACT(YEAR FROM '01/02/03 10:20:30');
|
||||
SELECT EXTRACT(MONTH FROM '01/02/03 10:20:30');
|
||||
SELECT EXTRACT(DAY FROM '01/02/03 10:20:30');
|
||||
|
||||
SELECT EXTRACT(YEAR FROM '01:02:03 10:20:30');
|
||||
SELECT EXTRACT(MONTH FROM '01:02:03 10:20:30');
|
||||
SELECT EXTRACT(DAY FROM '01:02:03 10:20:30');
|
||||
|
||||
--echo # This still parses as DATETIME and returns NULL
|
||||
|
||||
SELECT EXTRACT(YEAR FROM "2011-02-32 8:46:06.23434");
|
||||
SELECT EXTRACT(MONTH FROM "2011-02-32 8:46:06.23434");
|
||||
SELECT EXTRACT(DAY FROM "2011-02-32 8:46:06.23434");
|
||||
SELECT EXTRACT(HOUR FROM "2011-02-32 8:46:06.23434");
|
||||
|
||||
--echo # This still parses as DATE
|
||||
|
||||
SELECT EXTRACT(YEAR FROM '2001/02/03');
|
||||
SELECT EXTRACT(MONTH FROM '2001/02/03');
|
||||
SELECT EXTRACT(DAY FROM '2001/02/03');
|
||||
|
||||
SELECT EXTRACT(YEAR FROM '01/02/03');
|
||||
SELECT EXTRACT(MONTH FROM '01/02/03');
|
||||
SELECT EXTRACT(DAY FROM '01/02/03');
|
||||
|
||||
SELECT EXTRACT(YEAR FROM '01-02-03');
|
||||
SELECT EXTRACT(MONTH FROM '01-02-03');
|
||||
SELECT EXTRACT(DAY FROM '01-02-03');
|
||||
|
||||
SELECT EXTRACT(YEAR FROM '1-2-3');
|
||||
SELECT EXTRACT(MONTH FROM '1-2-3');
|
||||
SELECT EXTRACT(DAY FROM '1-2-3');
|
||||
SELECT EXTRACT(HOUR FROM '1-2-3');
|
||||
|
||||
SELECT EXTRACT(DAY FROM '2024-01-03 garbage /////');
|
||||
SELECT EXTRACT(DAY FROM '24-01-03 garbage /////');
|
||||
SELECT EXTRACT(DAY FROM '01-02-03');
|
||||
|
||||
SELECT EXTRACT(DAY FROM '24:02:03T');
|
||||
SELECT EXTRACT(DAY FROM '24-02-03');
|
||||
SELECT EXTRACT(DAY FROM '24/02/03');
|
||||
|
||||
SELECT EXTRACT(DAY FROM '11111');
|
||||
|
||||
SELECT TIME('2001-01-01T'), TIME('2001-01-01T ');
|
||||
SELECT TIME('2001/01/01T'), TIME('2001/01/01T ');
|
||||
SELECT TIME('2001:01:01T'), TIME('2001:01:01T ');
|
||||
|
||||
SELECT EXTRACT(DAY FROM '2001-01-01T'), EXTRACT(DAY FROM '2001-01-01T ');
|
||||
SELECT EXTRACT(DAY FROM '2001/01/01T'), EXTRACT(DAY FROM '2001/01/01T ');
|
||||
SELECT EXTRACT(DAY FROM '2001:01:01T'), EXTRACT(DAY FROM '2001:01:01T ');
|
||||
|
||||
|
||||
SELECT TIME('2001:01:01T'), TIME('2001:01:01T ');
|
||||
SELECT EXTRACT(HOUR FROM '2001-01-01T'), EXTRACT(HOUR FROM '2001-01-01T ');
|
||||
SELECT EXTRACT(HOUR FROM '2001/01/01T'), EXTRACT(HOUR FROM '2001/01/01T ');
|
||||
SELECT EXTRACT(HOUR FROM '2001:01:01T'), EXTRACT(HOUR FROM '2001:01:01T ');
|
||||
|
||||
--echo # This still parses as DATE and returns NULL (without trying TIME)
|
||||
SELECT EXTRACT(DAY FROM '100000:02:03T');
|
||||
SELECT EXTRACT(DAY FROM '100000/02/03');
|
||||
SELECT EXTRACT(DAY FROM '100000-02-03');
|
||||
|
||||
SELECT EXTRACT(DAY FROM '1111');
|
||||
SELECT EXTRACT(DAY FROM '111');
|
||||
SELECT EXTRACT(DAY FROM '11');
|
||||
SELECT EXTRACT(DAY FROM '1');
|
||||
|
||||
|
||||
--echo # This still parses as TIME
|
||||
|
||||
SELECT EXTRACT(HOUR FROM '11111');
|
||||
SELECT EXTRACT(HOUR FROM '1111');
|
||||
SELECT EXTRACT(HOUR FROM '111');
|
||||
SELECT EXTRACT(HOUR FROM '11');
|
||||
SELECT EXTRACT(HOUR FROM '1');
|
||||
|
||||
SELECT TIME('01:02:03:');
|
||||
SELECT TIME('01:02:03-');
|
||||
SELECT TIME('01:02:03;');
|
||||
SELECT TIME('01:02:03/');
|
||||
|
||||
SELECT EXTRACT(HOUR FROM '01:02:03:');
|
||||
SELECT EXTRACT(HOUR FROM '01:02:03-');
|
||||
SELECT EXTRACT(HOUR FROM '01:02:03;');
|
||||
SELECT EXTRACT(HOUR FROM '01:02:03/');
|
||||
|
||||
--echo # Backward compatibility preserved for YEAR and MONTH only
|
||||
--echo # (behavior has changed for DAY, see below)
|
||||
SELECT EXTRACT(YEAR FROM '01:02:03');
|
||||
SELECT EXTRACT(MONTH FROM '01:02:03');
|
||||
|
||||
SELECT EXTRACT(YEAR FROM '24:01:03 garbage /////');
|
||||
SELECT EXTRACT(MONTH FROM '24:01:03 garbage /////');
|
||||
|
||||
--echo # This still parses as TIME 00:20:01
|
||||
|
||||
SELECT TIME('2001/01/01');
|
||||
SELECT TIME('2001-01-01');
|
||||
|
||||
--echo # This still parses as TIME and overflows to '838:59:59'
|
||||
SELECT TIME('2001:01:01');
|
||||
|
||||
|
||||
--echo # This used to parse as DATE, now parses as TIME interval
|
||||
|
||||
CREATE TABLE t1 (a VARCHAR(64));
|
||||
INSERT INTO t1 VALUES
|
||||
('2024:01:03 garbage /////'),
|
||||
('24:01:03 garbage /////'),
|
||||
('01:01:03 garbage /////'),
|
||||
('2024:02:03'),
|
||||
('100000:02:03'),
|
||||
('24:02:03'),
|
||||
('01:02:03'),
|
||||
('01:02:03:'),
|
||||
('01:02:03-'),
|
||||
('01:02:03;'),
|
||||
('01:02:03/'),
|
||||
('20 10:20:30');
|
||||
|
||||
SELECT EXTRACT(DAY FROM a), EXTRACT(DAY_SECOND FROM a), a FROM t1;
|
||||
DROP TABLE t1;
|
@ -367,9 +367,7 @@ extract(DAY_MINUTE FROM "02 10:11:12")
|
||||
21011
|
||||
select extract(DAY_SECOND FROM "225 10:11:12");
|
||||
extract(DAY_SECOND FROM "225 10:11:12")
|
||||
34225959
|
||||
Warnings:
|
||||
Warning 1292 Truncated incorrect time value: '225 10:11:12'
|
||||
225101112
|
||||
select extract(HOUR FROM "1999-01-02 10:11:12");
|
||||
extract(HOUR FROM "1999-01-02 10:11:12")
|
||||
10
|
||||
@ -1033,9 +1031,7 @@ Note 1105 Cast to unsigned converted negative integer to it's positive complemen
|
||||
Warning 1292 Truncated incorrect time value: '18446744073709551615:00:00'
|
||||
SELECT EXTRACT(HOUR FROM '10000:02:03');
|
||||
EXTRACT(HOUR FROM '10000:02:03')
|
||||
22
|
||||
Warnings:
|
||||
Warning 1292 Truncated incorrect time value: '10000:02:03'
|
||||
16
|
||||
CREATE TABLE t1(f1 TIME);
|
||||
INSERT IGNORE INTO t1 VALUES('916:00:00 a');
|
||||
Warnings:
|
||||
|
@ -17,10 +17,7 @@ Warnings:
|
||||
Warning 1292 Incorrect datetime value: '0'
|
||||
select extract(hour from '100000:02:03'), extract(hour from '100000:02:03 ');
|
||||
extract(hour from '100000:02:03') extract(hour from '100000:02:03 ')
|
||||
NULL NULL
|
||||
Warnings:
|
||||
Warning 1292 Incorrect time value: '100000:02:03'
|
||||
Warning 1292 Incorrect time value: '100000:02:03 '
|
||||
16 16
|
||||
#
|
||||
# backward compatibility craziness
|
||||
#
|
||||
|
@ -262,12 +262,25 @@ static void get_microseconds(ulong *val, MYSQL_TIME_STATUS *status,
|
||||
|
||||
|
||||
static int check_time_range_internal(MYSQL_TIME *ltime,
|
||||
ulong max_hour, uint dec,
|
||||
int *warning);
|
||||
ulong max_hour, ulong err_hour,
|
||||
uint dec, int *warning);
|
||||
|
||||
int check_time_range(MYSQL_TIME *ltime, uint dec, int *warning)
|
||||
{
|
||||
return check_time_range_internal(ltime, TIME_MAX_HOUR, dec, warning);
|
||||
return check_time_range_internal(ltime, TIME_MAX_HOUR, UINT_MAX32,
|
||||
dec, warning);
|
||||
}
|
||||
|
||||
|
||||
static my_bool
|
||||
set_neg(my_bool neg, MYSQL_TIME_STATUS *st, MYSQL_TIME *ltime)
|
||||
{
|
||||
if ((ltime->neg= neg) && ltime->time_type != MYSQL_TIMESTAMP_TIME)
|
||||
{
|
||||
st->warnings|= MYSQL_TIME_WARN_OUT_OF_RANGE;
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
@ -351,20 +364,51 @@ static my_bool find_body(my_bool *neg, const char *str, size_t length,
|
||||
}
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint count_punct;
|
||||
uint count_colon;
|
||||
uint count_iso_date_time_separator;
|
||||
} MYSQL_TIME_USED_CHAR_STATISTICS;
|
||||
|
||||
|
||||
static void
|
||||
mysql_time_used_char_statistics_init(MYSQL_TIME_USED_CHAR_STATISTICS *to,
|
||||
const char *str, const char *end)
|
||||
{
|
||||
const char *s;
|
||||
bzero((void *) to, sizeof(MYSQL_TIME_USED_CHAR_STATISTICS));
|
||||
for (s= str; s < end; s++)
|
||||
{
|
||||
if (my_ispunct(&my_charset_latin1, *s))
|
||||
to->count_punct++;
|
||||
if (*s == ':')
|
||||
to->count_colon++;
|
||||
if (*s == 'T')
|
||||
to->count_iso_date_time_separator++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static my_bool
|
||||
is_datetime_body_candidate(const char *str, size_t length)
|
||||
is_datetime_body_candidate(const char *str, size_t length,
|
||||
my_bool allow_dates_delimited,
|
||||
my_bool allow_dates_numeric)
|
||||
{
|
||||
static uint min_date_length= 5; /* '1-1-1' -> '0001-01-01' */
|
||||
uint pos;
|
||||
uint pos, count_punct= 0;
|
||||
uint date_time_separator_length= MY_TEST(!allow_dates_delimited);
|
||||
if (length >= 12)
|
||||
return TRUE;
|
||||
/*
|
||||
The shortest possible DATE is '1-1-1', which is 5 characters.
|
||||
To make a full datetime it should be at least followed by a space or a 'T'.
|
||||
To make a date it should be just not less that 5 characters.
|
||||
*/
|
||||
if (length < min_date_length + 1/* DATE/TIME separator */)
|
||||
if (length < min_date_length + date_time_separator_length &&
|
||||
!allow_dates_numeric)
|
||||
return FALSE;
|
||||
for (pos= min_date_length; pos < length; pos++)
|
||||
for (pos= 0; pos < length; pos++)
|
||||
{
|
||||
if (str[pos] == 'T') /* Date/time separator */
|
||||
return TRUE;
|
||||
@ -381,21 +425,23 @@ is_datetime_body_candidate(const char *str, size_t length)
|
||||
TIME('111 11') -> 838:59:59 = 111 days 11 hours with overflow
|
||||
TIME('1111 11') -> 838:59:59 = 1111 days 11 hours with overflow
|
||||
*/
|
||||
for (pos= 0 ; pos < min_date_length; pos++)
|
||||
{
|
||||
if (my_ispunct(&my_charset_latin1, str[pos])) /* Can be a DATE */
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
return count_punct > 0; /* Can be a DATE if already had separators*/
|
||||
}
|
||||
if (my_ispunct(&my_charset_latin1, str[pos]))
|
||||
{
|
||||
if (allow_dates_delimited && str[pos] != ':')
|
||||
return TRUE;
|
||||
count_punct++;
|
||||
}
|
||||
}
|
||||
return FALSE;
|
||||
return allow_dates_numeric && count_punct == 0;
|
||||
}
|
||||
|
||||
|
||||
static my_bool
|
||||
str_to_DDhhmmssff_internal(my_bool neg, const char *str, size_t length,
|
||||
MYSQL_TIME *l_time, ulong max_hour,
|
||||
MYSQL_TIME *l_time,
|
||||
ulong max_hour, ulong err_hour,
|
||||
MYSQL_TIME_STATUS *status,
|
||||
const char **endptr);
|
||||
|
||||
@ -452,14 +498,18 @@ static my_bool
|
||||
str_to_datetime_or_date_body(const char *str, size_t length, MYSQL_TIME *l_time,
|
||||
ulonglong flags,
|
||||
my_bool punct_is_date_time_separator,
|
||||
MYSQL_TIME_STATUS *status)
|
||||
MYSQL_TIME_STATUS *status,
|
||||
uint *number_of_fields,
|
||||
const char **endptr)
|
||||
{
|
||||
const char *end=str+length, *pos;
|
||||
uint number_of_fields= 0, digits, year_length, not_zero_date;
|
||||
uint digits, year_length, not_zero_date;
|
||||
int warn= 0;
|
||||
DBUG_ENTER("str_to_datetime_or_date_body");
|
||||
DBUG_ASSERT(C_FLAGS_OK(flags));
|
||||
bzero(l_time, sizeof(*l_time));
|
||||
*number_of_fields= 0;
|
||||
*endptr= str;
|
||||
|
||||
/*
|
||||
Calculate number of digits in first part.
|
||||
@ -487,40 +537,41 @@ str_to_datetime_or_date_body(const char *str, size_t length, MYSQL_TIME *l_time,
|
||||
(only numbers like [YY]YYMMDD[T][hhmmss[.uuuuuu]])
|
||||
*/
|
||||
year_length= (digits == 4 || digits == 8 || digits >= 14) ? 4 : 2;
|
||||
if (get_digits(&l_time->year, &number_of_fields, &str, end, year_length)
|
||||
|| get_digits(&l_time->month, &number_of_fields, &str, end, 2)
|
||||
|| get_digits(&l_time->day, &number_of_fields, &str, end, 2)
|
||||
if (get_digits(&l_time->year, number_of_fields, &str, end, year_length)
|
||||
|| get_digits(&l_time->month, number_of_fields, &str, end, 2)
|
||||
|| get_digits(&l_time->day, number_of_fields, &str, end, 2)
|
||||
|| get_maybe_T(&str, end)
|
||||
|| get_digits(&l_time->hour, &number_of_fields, &str, end, 2)
|
||||
|| get_digits(&l_time->minute, &number_of_fields, &str, end, 2)
|
||||
|| get_digits(&l_time->second, &number_of_fields, &str, end, 2))
|
||||
|| get_digits(&l_time->hour, number_of_fields, &str, end, 2)
|
||||
|| get_digits(&l_time->minute, number_of_fields, &str, end, 2)
|
||||
|| get_digits(&l_time->second, number_of_fields, &str, end, 2))
|
||||
warn|= MYSQL_TIME_WARN_TRUNCATED;
|
||||
}
|
||||
else
|
||||
{
|
||||
const char *start= str;
|
||||
if (get_number(&l_time->year, &number_of_fields, &str, end))
|
||||
if (get_number(&l_time->year, number_of_fields, &str, end))
|
||||
warn|= MYSQL_TIME_WARN_TRUNCATED;
|
||||
year_length= (uint)(str - start);
|
||||
|
||||
if (!warn &&
|
||||
(get_punct(&str, end)
|
||||
|| get_number(&l_time->month, &number_of_fields, &str, end)
|
||||
|| get_number(&l_time->month, number_of_fields, &str, end)
|
||||
|| get_punct(&str, end)
|
||||
|| get_number(&l_time->day, &number_of_fields, &str, end)
|
||||
|| get_date_time_separator(&number_of_fields,
|
||||
|| get_number(&l_time->day, number_of_fields, &str, end)
|
||||
|| get_date_time_separator(number_of_fields,
|
||||
punct_is_date_time_separator, &str, end)
|
||||
|| get_number(&l_time->hour, &number_of_fields, &str, end)
|
||||
|| get_number(&l_time->hour, number_of_fields, &str, end)
|
||||
|| get_punct(&str, end)
|
||||
|| get_number(&l_time->minute, &number_of_fields, &str, end)
|
||||
|| get_number(&l_time->minute, number_of_fields, &str, end)
|
||||
|| get_punct(&str, end)
|
||||
|| get_number(&l_time->second, &number_of_fields, &str, end)))
|
||||
|| get_number(&l_time->second, number_of_fields, &str, end)))
|
||||
warn|= MYSQL_TIME_WARN_TRUNCATED;
|
||||
}
|
||||
status->warnings|= warn;
|
||||
|
||||
*endptr= str;
|
||||
/* we're ok if date part is correct. even if the rest is truncated */
|
||||
if (number_of_fields < 3)
|
||||
if (*number_of_fields < 3)
|
||||
{
|
||||
l_time->time_type= MYSQL_TIMESTAMP_NONE;
|
||||
status->warnings|= MYSQL_TIME_WARN_TRUNCATED;
|
||||
@ -531,7 +582,8 @@ str_to_datetime_or_date_body(const char *str, size_t length, MYSQL_TIME *l_time,
|
||||
{
|
||||
str++;
|
||||
get_microseconds(&l_time->second_part, status,
|
||||
&number_of_fields, &str, end);
|
||||
number_of_fields, &str, end);
|
||||
*endptr= str;
|
||||
}
|
||||
|
||||
not_zero_date = l_time->year || l_time->month || l_time->day ||
|
||||
@ -551,7 +603,7 @@ str_to_datetime_or_date_body(const char *str, size_t length, MYSQL_TIME *l_time,
|
||||
if (check_date(l_time, not_zero_date, flags, &status->warnings))
|
||||
goto err;
|
||||
|
||||
l_time->time_type= (number_of_fields <= 3 ?
|
||||
l_time->time_type= (*number_of_fields <= 3 ?
|
||||
MYSQL_TIMESTAMP_DATE : MYSQL_TIMESTAMP_DATETIME);
|
||||
|
||||
if (str != end)
|
||||
@ -594,27 +646,104 @@ err:
|
||||
TRUE on error
|
||||
*/
|
||||
|
||||
static
|
||||
my_bool str_to_datetime_or_date_or_time_body(const char *str, size_t length,
|
||||
MYSQL_TIME *l_time,
|
||||
ulonglong fuzzydate,
|
||||
MYSQL_TIME_STATUS *status)
|
||||
static my_bool
|
||||
str_to_datetime_or_date_or_time_body(const char *str, size_t length,
|
||||
MYSQL_TIME *l_time,
|
||||
ulonglong fuzzydate,
|
||||
MYSQL_TIME_STATUS *status,
|
||||
ulong time_max_hour,
|
||||
ulong time_err_hour,
|
||||
my_bool allow_dates_delimited,
|
||||
my_bool allow_dates_numeric)
|
||||
{
|
||||
const char *endptr;
|
||||
DBUG_ASSERT(C_FLAGS_OK(fuzzydate));
|
||||
|
||||
/* Check first if this is a full TIMESTAMP */
|
||||
if (is_datetime_body_candidate(str, length))
|
||||
if (is_datetime_body_candidate(str, length,
|
||||
allow_dates_delimited,
|
||||
allow_dates_numeric))
|
||||
{ /* Probably full timestamp */
|
||||
int warn_copy= status->warnings; /* could already be set by find_body() */
|
||||
(void) str_to_datetime_or_date_body(str, length, l_time,
|
||||
fuzzydate, FALSE, status);
|
||||
if (l_time->time_type >= MYSQL_TIMESTAMP_ERROR)
|
||||
return l_time->time_type == MYSQL_TIMESTAMP_ERROR;
|
||||
uint number_of_fields;
|
||||
(void) str_to_datetime_or_date_body(str, length, l_time, fuzzydate,
|
||||
FALSE, status,
|
||||
&number_of_fields, &endptr);
|
||||
DBUG_ASSERT(endptr >= str);
|
||||
DBUG_ASSERT(endptr <= str + length);
|
||||
switch (l_time->time_type) {
|
||||
case MYSQL_TIMESTAMP_DATETIME:
|
||||
return FALSE;
|
||||
case MYSQL_TIMESTAMP_DATE:
|
||||
{
|
||||
/*
|
||||
Successfully parsed as DATE, but it can also be a TIME:
|
||||
'24:02:03' - continue and parse as TIME
|
||||
'24:02:03 garbage /////' - continue and parse as TIME
|
||||
'24:02:03T' - return DATE
|
||||
'24-02-03' - return DATE
|
||||
'24/02/03' - return DATE
|
||||
'11111' - return DATE
|
||||
*/
|
||||
MYSQL_TIME_USED_CHAR_STATISTICS used_chars;
|
||||
mysql_time_used_char_statistics_init(&used_chars, str, endptr);
|
||||
if (used_chars.count_iso_date_time_separator || !used_chars.count_colon)
|
||||
return FALSE;
|
||||
}
|
||||
break;
|
||||
case MYSQL_TIMESTAMP_ERROR:
|
||||
{
|
||||
MYSQL_TIME_USED_CHAR_STATISTICS used_chars;
|
||||
/*
|
||||
Check if it parsed as DATETIME but then failed as out of range:
|
||||
'2011-02-32 8:46:06.23434' - return error
|
||||
*/
|
||||
if (number_of_fields > 3)
|
||||
return TRUE;
|
||||
/*
|
||||
Check if it parsed as DATE but then failed as out of range:
|
||||
'100000:02:03' - continue and parse as TIME
|
||||
'100000:02:03T' - return error
|
||||
'100000/02/03' - return error
|
||||
'100000-02-03' - return error
|
||||
*/
|
||||
mysql_time_used_char_statistics_init(&used_chars, str, endptr);
|
||||
if (used_chars.count_iso_date_time_separator || !used_chars.count_colon)
|
||||
return TRUE;
|
||||
}
|
||||
break;
|
||||
case MYSQL_TIMESTAMP_NONE:
|
||||
{
|
||||
if (allow_dates_numeric && endptr >= str + length)
|
||||
{
|
||||
/*
|
||||
For backward compatibility this parses as DATE and fails:
|
||||
EXTRACT(DAY FROM '1111') -- return error
|
||||
EXTRACT(DAY FROM '1') -- return error
|
||||
*/
|
||||
MYSQL_TIME_USED_CHAR_STATISTICS used_chars;
|
||||
mysql_time_used_char_statistics_init(&used_chars, str, endptr);
|
||||
if (!used_chars.count_iso_date_time_separator &&
|
||||
!used_chars.count_colon &&
|
||||
!used_chars.count_punct)
|
||||
return TRUE;
|
||||
}
|
||||
/*
|
||||
- '256 10:30:30' - continue and parse as TIME
|
||||
- '4294967296:59:59.123456456' - continue and parse as TIME
|
||||
*/
|
||||
}
|
||||
break;
|
||||
case MYSQL_TIMESTAMP_TIME:
|
||||
DBUG_ASSERT(0);
|
||||
break;
|
||||
}
|
||||
my_time_status_init(status);
|
||||
status->warnings= warn_copy;
|
||||
}
|
||||
|
||||
if (!str_to_DDhhmmssff_internal(FALSE, str, length, l_time, TIME_MAX_HOUR,
|
||||
if (!str_to_DDhhmmssff_internal(FALSE, str, length, l_time,
|
||||
time_max_hour, time_err_hour,
|
||||
status, &endptr))
|
||||
return FALSE;
|
||||
|
||||
@ -640,10 +769,11 @@ my_bool str_to_DDhhmmssff(const char *str, size_t length, MYSQL_TIME *ltime,
|
||||
return TRUE;
|
||||
|
||||
/* Reject anything that might be parsed as a full TIMESTAMP */
|
||||
if (is_datetime_body_candidate(str, length))
|
||||
if (is_datetime_body_candidate(str, length, FALSE, FALSE))
|
||||
{
|
||||
(void) str_to_datetime_or_date_body(str, length, ltime,
|
||||
0, FALSE, status);
|
||||
uint number_of_fields;
|
||||
(void) str_to_datetime_or_date_body(str, length, ltime, 0, FALSE,
|
||||
status, &number_of_fields, &endptr);
|
||||
if (ltime->time_type > MYSQL_TIMESTAMP_ERROR)
|
||||
{
|
||||
status->warnings|= MYSQL_TIME_WARN_TRUNCATED;
|
||||
@ -659,7 +789,7 @@ my_bool str_to_DDhhmmssff(const char *str, size_t length, MYSQL_TIME *ltime,
|
||||
will scan only '2001'.
|
||||
*/
|
||||
if (str_to_DDhhmmssff_internal(neg, str, length, ltime, max_hour,
|
||||
status, &endptr) ||
|
||||
UINT_MAX32, status, &endptr) ||
|
||||
(endptr < str + length && endptr[0] == '-'))
|
||||
return TRUE;
|
||||
return FALSE;
|
||||
@ -668,29 +798,63 @@ my_bool str_to_DDhhmmssff(const char *str, size_t length, MYSQL_TIME *ltime,
|
||||
|
||||
my_bool
|
||||
str_to_datetime_or_date_or_time(const char *str, size_t length,
|
||||
MYSQL_TIME *l_time,
|
||||
ulonglong fuzzydate,
|
||||
MYSQL_TIME_STATUS *status)
|
||||
MYSQL_TIME *to, ulonglong mode,
|
||||
MYSQL_TIME_STATUS *status,
|
||||
ulong time_max_hour,
|
||||
ulong time_err_hour)
|
||||
{
|
||||
my_bool neg, rc;
|
||||
DBUG_ASSERT(C_FLAGS_OK(fuzzydate));
|
||||
my_bool neg;
|
||||
DBUG_ASSERT(C_FLAGS_OK(mode));
|
||||
my_time_status_init(status);
|
||||
return
|
||||
find_body(&neg, str, length, to, &status->warnings, &str, &length) ||
|
||||
str_to_datetime_or_date_or_time_body(str, length, to, mode, status,
|
||||
time_max_hour, time_err_hour,
|
||||
FALSE, FALSE) ||
|
||||
set_neg(neg, status, to);
|
||||
}
|
||||
|
||||
|
||||
my_bool
|
||||
str_to_datetime_or_date_or_interval_hhmmssff(const char *str, size_t length,
|
||||
MYSQL_TIME *to, ulonglong mode,
|
||||
MYSQL_TIME_STATUS *status,
|
||||
ulong time_max_hour,
|
||||
ulong time_err_hour)
|
||||
{
|
||||
my_bool neg;
|
||||
DBUG_ASSERT(C_FLAGS_OK(mode));
|
||||
my_time_status_init(status);
|
||||
return
|
||||
find_body(&neg, str, length, to, &status->warnings, &str, &length) ||
|
||||
str_to_datetime_or_date_or_time_body(str, length, to, mode, status,
|
||||
time_max_hour, time_err_hour,
|
||||
TRUE, FALSE) ||
|
||||
set_neg(neg, status, to);
|
||||
}
|
||||
|
||||
|
||||
my_bool
|
||||
str_to_datetime_or_date_or_interval_day(const char *str, size_t length,
|
||||
MYSQL_TIME *to, ulonglong mode,
|
||||
MYSQL_TIME_STATUS *status,
|
||||
ulong time_max_hour,
|
||||
ulong time_err_hour)
|
||||
{
|
||||
my_bool neg;
|
||||
DBUG_ASSERT(C_FLAGS_OK(mode));
|
||||
my_time_status_init(status);
|
||||
if (find_body(&neg, str, length, l_time, &status->warnings, &str, &length))
|
||||
return TRUE;
|
||||
/*
|
||||
QQ: Perhaps we should modify xxx_body() to return endptr.
|
||||
If endptr points to '-', return an error.
|
||||
For backward compatibility we allow to parse non-delimited
|
||||
values as DATE rather than as TIME:
|
||||
EXTRACT(DAY FROM '11111')
|
||||
*/
|
||||
rc= str_to_datetime_or_date_or_time_body(str, length, l_time,
|
||||
fuzzydate, status);
|
||||
if (rc)
|
||||
return rc;
|
||||
if ((l_time->neg= neg) && l_time->time_type != MYSQL_TIMESTAMP_TIME)
|
||||
{
|
||||
status->warnings|= MYSQL_TIME_WARN_OUT_OF_RANGE;
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
return
|
||||
find_body(&neg, str, length, to, &status->warnings, &str, &length) ||
|
||||
str_to_datetime_or_date_or_time_body(str, length, to, mode, status,
|
||||
time_max_hour, time_err_hour,
|
||||
TRUE, TRUE) ||
|
||||
set_neg(neg, status, to);
|
||||
}
|
||||
|
||||
|
||||
@ -698,20 +862,16 @@ my_bool
|
||||
str_to_datetime_or_date(const char *str, size_t length, MYSQL_TIME *l_time,
|
||||
ulonglong flags, MYSQL_TIME_STATUS *status)
|
||||
{
|
||||
my_bool neg, rc;
|
||||
my_bool neg;
|
||||
uint number_of_fields;
|
||||
const char *endptr;
|
||||
DBUG_ASSERT(C_FLAGS_OK(flags));
|
||||
my_time_status_init(status);
|
||||
if (find_body(&neg, str, length, l_time, &status->warnings, &str, &length))
|
||||
return TRUE;
|
||||
rc= str_to_datetime_or_date_body(str, length, l_time, flags, TRUE, status);
|
||||
if (rc)
|
||||
return rc;
|
||||
if ((l_time->neg= neg))
|
||||
{
|
||||
status->warnings|= MYSQL_TIME_WARN_OUT_OF_RANGE;
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
return
|
||||
find_body(&neg, str, length, l_time, &status->warnings, &str, &length) ||
|
||||
str_to_datetime_or_date_body(str, length, l_time, flags, TRUE,
|
||||
status, &number_of_fields, &endptr) ||
|
||||
set_neg(neg, status, l_time);
|
||||
}
|
||||
|
||||
|
||||
@ -738,7 +898,8 @@ str_to_datetime_or_date(const char *str, size_t length, MYSQL_TIME *l_time,
|
||||
*/
|
||||
static my_bool
|
||||
str_to_DDhhmmssff_internal(my_bool neg, const char *str, size_t length,
|
||||
MYSQL_TIME *l_time, ulong max_hour,
|
||||
MYSQL_TIME *l_time,
|
||||
ulong max_hour, ulong err_hour,
|
||||
MYSQL_TIME_STATUS *status, const char **endptr)
|
||||
{
|
||||
ulong date[5];
|
||||
@ -891,7 +1052,8 @@ fractional:
|
||||
*endptr= str;
|
||||
|
||||
/* Check if the value is valid and fits into MYSQL_TIME range */
|
||||
if (check_time_range_internal(l_time, max_hour, 6, &status->warnings))
|
||||
if (check_time_range_internal(l_time, max_hour, err_hour,
|
||||
6, &status->warnings))
|
||||
return TRUE;
|
||||
|
||||
/* Check if there is garbage at end of the MYSQL_TIME specification */
|
||||
@ -911,7 +1073,9 @@ err:
|
||||
SYNOPSIS:
|
||||
check_time_range_internal()
|
||||
time pointer to MYSQL_TIME value
|
||||
ulong max_hour - maximum allowed hour value
|
||||
ulong max_hour - maximum allowed hour value. if the hour is greater,
|
||||
cut the time value to 'max_hour:59:59.999999'
|
||||
ulong err_hour - if hour is greater than this value, return an error
|
||||
uint dec
|
||||
warning set MYSQL_TIME_WARN_OUT_OF_RANGE flag if the value is out of range
|
||||
|
||||
@ -926,13 +1090,15 @@ err:
|
||||
*/
|
||||
|
||||
int check_time_range_internal(struct st_mysql_time *my_time,
|
||||
ulong max_hour, uint dec, int *warning)
|
||||
ulong max_hour, ulong err_hour,
|
||||
uint dec, int *warning)
|
||||
{
|
||||
ulonglong hour;
|
||||
static ulong max_sec_part[TIME_SECOND_PART_DIGITS+1]= {000000, 900000, 990000,
|
||||
999000, 999900, 999990, 999999};
|
||||
|
||||
if (my_time->minute >= 60 || my_time->second >= 60)
|
||||
if (my_time->minute >= 60 || my_time->second >= 60 ||
|
||||
my_time->hour > err_hour)
|
||||
{
|
||||
*warning|= MYSQL_TIME_WARN_TRUNCATED;
|
||||
return 1;
|
||||
@ -1581,17 +1747,19 @@ longlong number_to_datetime_or_date(longlong nr, ulong sec_part,
|
||||
-1 time value is invalid
|
||||
*/
|
||||
int number_to_time_only(my_bool neg, ulonglong nr, ulong sec_part,
|
||||
MYSQL_TIME *ltime, int *was_cut)
|
||||
ulong max_hour, MYSQL_TIME *ltime, int *was_cut)
|
||||
{
|
||||
static const ulonglong TIME_MAX_mmss= TIME_MAX_MINUTE*100 + TIME_MAX_SECOND;
|
||||
ulonglong time_max_value= max_hour * 10000ULL + TIME_MAX_mmss;
|
||||
*was_cut= 0;
|
||||
ltime->year= ltime->month= ltime->day= 0;
|
||||
ltime->time_type= MYSQL_TIMESTAMP_TIME;
|
||||
|
||||
ltime->neg= neg;
|
||||
|
||||
if (nr > TIME_MAX_VALUE)
|
||||
if (nr > time_max_value)
|
||||
{
|
||||
nr= TIME_MAX_VALUE;
|
||||
nr= time_max_value;
|
||||
sec_part= TIME_MAX_SECOND_PART;
|
||||
*was_cut= MYSQL_TIME_WARN_OUT_OF_RANGE;
|
||||
}
|
||||
|
@ -2092,16 +2092,18 @@ void Item_extract::print(String *str, enum_query_type query_type)
|
||||
bool Item_extract::fix_length_and_dec()
|
||||
{
|
||||
maybe_null=1; // If wrong date
|
||||
uint32 daylen= args[0]->cmp_type() == TIME_RESULT ? 2 :
|
||||
TIME_MAX_INTERVAL_DAY_CHAR_LENGTH;
|
||||
switch (int_type) {
|
||||
case INTERVAL_YEAR: set_date_length(4); break; // YYYY
|
||||
case INTERVAL_YEAR_MONTH: set_date_length(6); break; // YYYYMM
|
||||
case INTERVAL_QUARTER: set_date_length(2); break; // 1..4
|
||||
case INTERVAL_MONTH: set_date_length(2); break; // MM
|
||||
case INTERVAL_WEEK: set_date_length(2); break; // 0..52
|
||||
case INTERVAL_DAY: set_day_length(2); break; // DD
|
||||
case INTERVAL_DAY_HOUR: set_time_length(4); break; // DDhh
|
||||
case INTERVAL_DAY_MINUTE: set_time_length(6); break; // DDhhmm
|
||||
case INTERVAL_DAY_SECOND: set_time_length(8); break; // DDhhmmss
|
||||
case INTERVAL_DAY: set_day_length(daylen); break; // DD
|
||||
case INTERVAL_DAY_HOUR: set_day_length(daylen+2); break; // DDhh
|
||||
case INTERVAL_DAY_MINUTE: set_day_length(daylen+4); break; // DDhhmm
|
||||
case INTERVAL_DAY_SECOND: set_day_length(daylen+6); break; // DDhhmmss
|
||||
case INTERVAL_HOUR: set_time_length(2); break; // hh
|
||||
case INTERVAL_HOUR_MINUTE: set_time_length(4); break; // hhmm
|
||||
case INTERVAL_HOUR_SECOND: set_time_length(6); break; // hhmmss
|
||||
@ -2109,7 +2111,7 @@ bool Item_extract::fix_length_and_dec()
|
||||
case INTERVAL_MINUTE_SECOND: set_time_length(4); break; // mmss
|
||||
case INTERVAL_SECOND: set_time_length(2); break; // ss
|
||||
case INTERVAL_MICROSECOND: set_time_length(6); break; // ffffff
|
||||
case INTERVAL_DAY_MICROSECOND: set_time_length(14); break; // DDhhmmssffffff
|
||||
case INTERVAL_DAY_MICROSECOND: set_time_length(daylen+12); break; // DDhhmmssffffff
|
||||
case INTERVAL_HOUR_MICROSECOND: set_time_length(12); break; // hhmmssffffff
|
||||
case INTERVAL_MINUTE_MICROSECOND: set_time_length(10); break; // mmssffffff
|
||||
case INTERVAL_SECOND_MICROSECOND: set_time_length(8); break; // ssffffff
|
||||
|
@ -993,12 +993,12 @@ class Item_extract :public Item_int_func,
|
||||
EXTRACT(DAY FROM '-24:00:00') -> -1
|
||||
*/
|
||||
set_handler(handler_by_length(max_length= length + 1/*sign*/, 11));
|
||||
m_date_mode= date_mode_t(0);
|
||||
m_date_mode= TIME_INTERVAL_DAY;
|
||||
}
|
||||
void set_time_length(uint32 length)
|
||||
{
|
||||
set_handler(handler_by_length(max_length= length + 1/*sign*/, 11));
|
||||
m_date_mode= TIME_TIME_ONLY;
|
||||
m_date_mode= TIME_INTERVAL_hhmmssff;
|
||||
}
|
||||
public:
|
||||
const interval_type int_type; // keep it public
|
||||
|
@ -37,11 +37,13 @@ public:
|
||||
FUZZY_DATES is used for the result will only be used for comparison
|
||||
purposes. Conversion is as relaxed as possible.
|
||||
*/
|
||||
FUZZY_DATES= 1U,
|
||||
TIME_ONLY= 4U,
|
||||
NO_ZERO_IN_DATE= (1UL << 23), // MODE_NO_ZERO_IN_DATE
|
||||
NO_ZERO_DATE= (1UL << 24), // MODE_NO_ZERO_DATE
|
||||
INVALID_DATES= (1UL << 25) // MODE_INVALID_DATES
|
||||
FUZZY_DATES= 1U,
|
||||
TIME_ONLY= 4U,
|
||||
INTERVAL_hhmmssff= 8U,
|
||||
INTERVAL_DAY= 16U,
|
||||
NO_ZERO_IN_DATE= (1UL << 23), // MODE_NO_ZERO_IN_DATE
|
||||
NO_ZERO_DATE= (1UL << 24), // MODE_NO_ZERO_DATE
|
||||
INVALID_DATES= (1UL << 25) // MODE_INVALID_DATES
|
||||
};
|
||||
|
||||
private:
|
||||
@ -98,6 +100,8 @@ public:
|
||||
const date_mode_t
|
||||
TIME_FUZZY_DATES (date_mode_t::value_t::FUZZY_DATES),
|
||||
TIME_TIME_ONLY (date_mode_t::value_t::TIME_ONLY),
|
||||
TIME_INTERVAL_hhmmssff (date_mode_t::value_t::INTERVAL_hhmmssff),
|
||||
TIME_INTERVAL_DAY (date_mode_t::value_t::INTERVAL_DAY),
|
||||
TIME_NO_ZERO_IN_DATE (date_mode_t::value_t::NO_ZERO_IN_DATE),
|
||||
TIME_NO_ZERO_DATE (date_mode_t::value_t::NO_ZERO_DATE),
|
||||
TIME_INVALID_DATES (date_mode_t::value_t::INVALID_DATES);
|
||||
|
@ -371,18 +371,14 @@ public:
|
||||
};
|
||||
|
||||
|
||||
/* Character set-aware version of str_to_datetime_or_date_or_time() */
|
||||
bool Temporal::str_to_datetime_or_date_or_time(MYSQL_TIME_STATUS *status,
|
||||
/* Character set-aware version of ascii_to_datetime_or_date_or_time() */
|
||||
bool Temporal::str_to_datetime_or_date_or_time(MYSQL_TIME_STATUS *st,
|
||||
const char *str, size_t length,
|
||||
CHARSET_INFO *cs,
|
||||
date_mode_t fuzzydate)
|
||||
{
|
||||
TemporalAsciiBuffer tmp(str, length, cs);
|
||||
bool rc= ::str_to_datetime_or_date_or_time(tmp.str, tmp.length, this,
|
||||
ulonglong(fuzzydate & TIME_MODE_FOR_XXX_TO_DATE),
|
||||
status);
|
||||
DBUG_ASSERT(status->warnings || !rc);
|
||||
return rc;
|
||||
return ascii_to_datetime_or_date_or_time(st, tmp.str, tmp.length, fuzzydate);
|
||||
}
|
||||
|
||||
|
||||
@ -393,11 +389,17 @@ bool Temporal::str_to_datetime_or_date(MYSQL_TIME_STATUS *status,
|
||||
date_mode_t flags)
|
||||
{
|
||||
TemporalAsciiBuffer tmp(str, length, cs);
|
||||
bool rc= ::str_to_datetime_or_date(tmp.str, tmp.length, this,
|
||||
ulonglong(flags & TIME_MODE_FOR_XXX_TO_DATE),
|
||||
status);
|
||||
DBUG_ASSERT(status->warnings || !rc);
|
||||
return rc;
|
||||
return ascii_to_datetime_or_date(status, tmp.str, tmp.length, flags);
|
||||
}
|
||||
|
||||
|
||||
/* Character set-aware version of ascii_to_temporal() */
|
||||
bool Temporal::str_to_temporal(MYSQL_TIME_STATUS *status,
|
||||
const char *str, size_t length, CHARSET_INFO *cs,
|
||||
date_mode_t flags)
|
||||
{
|
||||
TemporalAsciiBuffer tmp(str, length, cs);
|
||||
return ascii_to_temporal(status, tmp.str, tmp.length, flags);
|
||||
}
|
||||
|
||||
|
||||
|
@ -181,9 +181,7 @@ void Temporal::make_from_str(THD *thd, Warn *warn,
|
||||
push_warning(thd, Sql_condition::WARN_LEVEL_NOTE,
|
||||
ER_YES, ErrConvString(str, length,cs).ptr()););
|
||||
|
||||
if (fuzzydate & TIME_TIME_ONLY ?
|
||||
str_to_datetime_or_date_or_time(warn, str, length, cs, fuzzydate) :
|
||||
str_to_datetime_or_date(warn, str, length, cs, fuzzydate))
|
||||
if (str_to_temporal(warn, str, length, cs, fuzzydate))
|
||||
make_fuzzy_date(&warn->warnings, fuzzydate);
|
||||
if (warn->warnings)
|
||||
warn->set_str(str, length, &my_charset_bin);
|
||||
@ -232,8 +230,11 @@ void Sec6::make_truncated_warning(THD *thd, const char *type_str) const
|
||||
bool Sec6::convert_to_mysql_time(THD *thd, int *warn, MYSQL_TIME *ltime,
|
||||
date_mode_t fuzzydate) const
|
||||
{
|
||||
bool is_time= bool(fuzzydate & TIME_TIME_ONLY);
|
||||
bool rc= is_time ? to_time(ltime, warn) : to_datetime(ltime, fuzzydate, warn);
|
||||
bool rc= fuzzydate & (TIME_INTERVAL_hhmmssff | TIME_INTERVAL_DAY) ?
|
||||
to_datetime_or_to_interval_hhmmssff(ltime, warn) :
|
||||
fuzzydate & TIME_TIME_ONLY ?
|
||||
to_datetime_or_time(ltime, warn, fuzzydate) :
|
||||
to_datetime_or_date(ltime, warn, fuzzydate);
|
||||
DBUG_ASSERT(*warn || !rc);
|
||||
if (truncated())
|
||||
*warn|= MYSQL_TIME_WARN_TRUNCATED;
|
||||
|
116
sql/sql_type.h
116
sql/sql_type.h
@ -264,21 +264,59 @@ public:
|
||||
MYSQL_TIME *ltime,
|
||||
date_mode_t fuzzydate) const;
|
||||
|
||||
// Convert a number in format hhhmmss.ff to TIME'hhh:mm:ss.ff'
|
||||
bool to_time(MYSQL_TIME *to, int *warn) const
|
||||
protected:
|
||||
|
||||
bool to_interval_hhmmssff_only(MYSQL_TIME *to, int *warn) const
|
||||
{
|
||||
bool rc= (m_sec > 9999999 && m_sec <= 99991231235959ULL && !neg()) ?
|
||||
number_to_datetime_or_date(m_sec, m_usec, to,
|
||||
C_TIME_INVALID_DATES, warn) < 0 :
|
||||
number_to_time_only(m_neg, m_sec, m_usec, to, warn);
|
||||
return number_to_time_only(m_neg, m_sec, m_usec,
|
||||
TIME_MAX_INTERVAL_HOUR, to, warn);
|
||||
}
|
||||
bool to_datetime_or_to_interval_hhmmssff(MYSQL_TIME *to, int *warn) const
|
||||
{
|
||||
/*
|
||||
Convert a number to a time interval.
|
||||
The following formats are understood:
|
||||
- 0 <= x <= 999999995959 - parse as hhhhmmss
|
||||
- 999999995959 < x <= 99991231235959 - parse as YYYYMMDDhhmmss
|
||||
(YYMMDDhhmmss) (YYYYMMDDhhmmss)
|
||||
|
||||
Note, these formats are NOT understood:
|
||||
- YYMMDD - overlaps with INTERVAL range
|
||||
- YYYYMMDD - overlaps with INTERVAL range
|
||||
- YYMMDDhhmmss - overlaps with INTERVAL range, partially
|
||||
(see TIME_MAX_INTERVAL_HOUR)
|
||||
|
||||
If we ever need wider intervals, this code switching between
|
||||
full datetime and interval-only should be rewised.
|
||||
*/
|
||||
DBUG_ASSERT(TIME_MAX_INTERVAL_HOUR <= 999999995959);
|
||||
/* (YYMMDDhhmmss) */
|
||||
if (m_sec > 999999995959ULL &&
|
||||
m_sec <= 99991231235959ULL && m_neg == 0)
|
||||
return to_datetime_or_date(to, warn, TIME_INVALID_DATES);
|
||||
if (m_sec / 10000 > TIME_MAX_INTERVAL_HOUR)
|
||||
{
|
||||
*warn= MYSQL_TIME_WARN_OUT_OF_RANGE;
|
||||
return true;
|
||||
}
|
||||
return to_interval_hhmmssff_only(to, warn);
|
||||
}
|
||||
public:
|
||||
// [-][DD]hhhmmss.ff, YYMMDDhhmmss.ff, YYYYMMDDhhmmss.ff
|
||||
bool to_datetime_or_time(MYSQL_TIME *to, int *warn, date_mode_t mode) const
|
||||
{
|
||||
bool rc= m_sec > 9999999 && m_sec <= 99991231235959ULL && !m_neg ?
|
||||
::number_to_datetime_or_date(m_sec, m_usec, to,
|
||||
ulonglong(mode & TIME_MODE_FOR_XXX_TO_DATE), warn) < 0 :
|
||||
::number_to_time_only(m_neg, m_sec, m_usec, TIME_MAX_HOUR, to, warn);
|
||||
DBUG_ASSERT(*warn || !rc);
|
||||
return rc;
|
||||
}
|
||||
/*
|
||||
Convert a number in format YYYYMMDDhhmmss.ff to
|
||||
Convert a number in formats YYYYMMDDhhmmss.ff or YYMMDDhhmmss.ff to
|
||||
TIMESTAMP'YYYY-MM-DD hh:mm:ss.ff'
|
||||
*/
|
||||
bool to_datetime(MYSQL_TIME *to, date_mode_t flags, int *warn) const
|
||||
bool to_datetime_or_date(MYSQL_TIME *to, int *warn, date_mode_t flags) const
|
||||
{
|
||||
if (m_neg)
|
||||
{
|
||||
@ -458,6 +496,8 @@ public:
|
||||
timestamp_type tstype, const char *name)
|
||||
{
|
||||
const char *typestr= tstype >= 0 ? type_name_by_timestamp_type(tstype) :
|
||||
mode & (TIME_INTERVAL_hhmmssff | TIME_INTERVAL_DAY) ?
|
||||
"interval" :
|
||||
mode & TIME_TIME_ONLY ? "time" : "datetime";
|
||||
Temporal::push_conversion_warnings(thd, totally_useless_value, warnings, typestr,
|
||||
name, ptr());
|
||||
@ -579,6 +619,60 @@ protected:
|
||||
if (warn->warnings)
|
||||
warn->set_decimal(nr);
|
||||
}
|
||||
bool ascii_to_temporal(MYSQL_TIME_STATUS *st,
|
||||
const char *str, size_t length,
|
||||
date_mode_t mode)
|
||||
{
|
||||
if (mode & (TIME_INTERVAL_hhmmssff | TIME_INTERVAL_DAY))
|
||||
return ascii_to_datetime_or_date_or_interval_DDhhmmssff(st, str, length,
|
||||
mode);
|
||||
if (mode & TIME_TIME_ONLY)
|
||||
return ascii_to_datetime_or_date_or_time(st, str, length, mode);
|
||||
return ascii_to_datetime_or_date(st, str, length, mode);
|
||||
}
|
||||
bool ascii_to_datetime_or_date_or_interval_DDhhmmssff(MYSQL_TIME_STATUS *st,
|
||||
const char *str,
|
||||
size_t length,
|
||||
date_mode_t mode)
|
||||
{
|
||||
longlong cflags= ulonglong(mode & TIME_MODE_FOR_XXX_TO_DATE);
|
||||
bool rc= mode & TIME_INTERVAL_DAY ?
|
||||
::str_to_datetime_or_date_or_interval_day(str, length, this, cflags, st,
|
||||
TIME_MAX_INTERVAL_HOUR,
|
||||
TIME_MAX_INTERVAL_HOUR) :
|
||||
::str_to_datetime_or_date_or_interval_hhmmssff(str, length, this,
|
||||
cflags, st,
|
||||
TIME_MAX_INTERVAL_HOUR,
|
||||
TIME_MAX_INTERVAL_HOUR);
|
||||
DBUG_ASSERT(!rc || st->warnings);
|
||||
return rc;
|
||||
}
|
||||
bool ascii_to_datetime_or_date_or_time(MYSQL_TIME_STATUS *status,
|
||||
const char *str, size_t length,
|
||||
date_mode_t fuzzydate)
|
||||
{
|
||||
ulonglong cflags= ulonglong(fuzzydate & TIME_MODE_FOR_XXX_TO_DATE);
|
||||
bool rc= ::str_to_datetime_or_date_or_time(str, length, this,
|
||||
cflags, status,
|
||||
TIME_MAX_HOUR, UINT_MAX32);
|
||||
DBUG_ASSERT(!rc || status->warnings);
|
||||
return rc;
|
||||
}
|
||||
bool ascii_to_datetime_or_date(MYSQL_TIME_STATUS *status,
|
||||
const char *str, size_t length,
|
||||
date_mode_t fuzzydate)
|
||||
{
|
||||
DBUG_ASSERT(bool(fuzzydate & TIME_TIME_ONLY) == false);
|
||||
bool rc= ::str_to_datetime_or_date(str, length, this,
|
||||
ulonglong(fuzzydate & TIME_MODE_FOR_XXX_TO_DATE),
|
||||
status);
|
||||
DBUG_ASSERT(!rc || status->warnings);
|
||||
return rc;
|
||||
}
|
||||
// Character set aware versions for string conversion routines
|
||||
bool str_to_temporal(MYSQL_TIME_STATUS *st,
|
||||
const char *str, size_t length,
|
||||
CHARSET_INFO *cs, date_mode_t fuzzydate);
|
||||
bool str_to_datetime_or_date_or_time(MYSQL_TIME_STATUS *st,
|
||||
const char *str, size_t length,
|
||||
CHARSET_INFO *cs, date_mode_t fuzzydate);
|
||||
@ -858,7 +952,7 @@ public:
|
||||
*/
|
||||
static uint max_useful_hour()
|
||||
{
|
||||
return 87649415;
|
||||
return TIME_MAX_INTERVAL_HOUR;
|
||||
}
|
||||
public:
|
||||
Interval_DDhhmmssff(THD *thd, Status *st, bool push_warnings,
|
||||
@ -1120,7 +1214,7 @@ public:
|
||||
}
|
||||
Time(THD *thd, int *warn, const Sec6 &nr, const Options opt)
|
||||
{
|
||||
if (nr.to_time(this, warn))
|
||||
if (nr.to_datetime_or_time(this, warn, TIME_INVALID_DATES))
|
||||
time_type= MYSQL_TIMESTAMP_NONE;
|
||||
xxx_to_time_result_to_valid_value(thd, warn, opt);
|
||||
}
|
||||
@ -1305,7 +1399,7 @@ protected:
|
||||
Temporal_with_date(int *warn, const Sec6 &nr, date_mode_t flags)
|
||||
{
|
||||
DBUG_ASSERT(bool(flags & TIME_TIME_ONLY) == false);
|
||||
if (nr.to_datetime(this, flags, warn))
|
||||
if (nr.to_datetime_or_date(this, warn, flags))
|
||||
time_type= MYSQL_TIMESTAMP_NONE;
|
||||
}
|
||||
Temporal_with_date(MYSQL_TIME_STATUS *status,
|
||||
|
Loading…
x
Reference in New Issue
Block a user