MDEV-16991 Rounding vs truncation for TIME, DATETIME, TIMESTAMP
This commit is contained in:
parent
27f3329ff6
commit
4447a02cf1
@ -108,12 +108,14 @@ typedef struct st_mysql_time_status
|
||||
{
|
||||
int warnings;
|
||||
uint precision;
|
||||
uint nanoseconds;
|
||||
} MYSQL_TIME_STATUS;
|
||||
|
||||
static inline void my_time_status_init(MYSQL_TIME_STATUS *status)
|
||||
{
|
||||
status->warnings= 0;
|
||||
status->precision= 0;
|
||||
status->nanoseconds= 0;
|
||||
}
|
||||
|
||||
my_bool check_date(const MYSQL_TIME *ltime, my_bool not_zero_date,
|
||||
|
1374
mysql-test/main/func_time_round.result
Normal file
1374
mysql-test/main/func_time_round.result
Normal file
File diff suppressed because it is too large
Load Diff
461
mysql-test/main/func_time_round.test
Normal file
461
mysql-test/main/func_time_round.test
Normal file
@ -0,0 +1,461 @@
|
||||
SET sql_mode=IF(@@version LIKE '%MariaDB%', 'TIME_ROUND_FRACTIONAL', '');
|
||||
SET @default_sql_mode=@@sql_mode;
|
||||
|
||||
CREATE TABLE t1_datetime_in_varchar (id SERIAL, a VARCHAR(64));
|
||||
INSERT INTO t1_datetime_in_varchar (a) VALUES
|
||||
('2000-12-31 23:59:59'),
|
||||
('2000-12-31 23:59:59.9'),
|
||||
('2000-12-31 23:59:59.99'),
|
||||
('2000-12-31 23:59:59.999'),
|
||||
('2000-12-31 23:59:59.9999'),
|
||||
('2000-12-31 23:59:59.99999'),
|
||||
('2000-12-31 23:59:59.999999'),
|
||||
('2000-12-31 23:59:59.9999999');
|
||||
|
||||
CREATE TABLE t1_datetime_in_decimal (id SERIAL, a DECIMAL(38,10));
|
||||
INSERT INTO t1_datetime_in_decimal (a) VALUES
|
||||
(20001231235959),
|
||||
(20001231235959.9),
|
||||
(20001231235959.99),
|
||||
(20001231235959.999),
|
||||
(20001231235959.9999),
|
||||
(20001231235959.99999),
|
||||
(20001231235959.999999),
|
||||
(20001231235959.9999999);
|
||||
|
||||
|
||||
CREATE TABLE t1_time_in_varchar (id SERIAL, a VARCHAR(64));
|
||||
INSERT INTO t1_time_in_varchar (a) VALUES
|
||||
('00:00:00'),
|
||||
('00:00:00.9'),
|
||||
('00:00:00.99'),
|
||||
('00:00:00.999'),
|
||||
('00:00:00.9999'),
|
||||
('00:00:00.99999'),
|
||||
('00:00:00.999999'),
|
||||
('00:00:00.9999999');
|
||||
INSERT INTO t1_time_in_varchar (a) VALUES
|
||||
('837:59:59.9999999'),
|
||||
('838:59:59'),
|
||||
('838:59:59.9'),
|
||||
('838:59:59.99'),
|
||||
('838:59:59.999'),
|
||||
('838:59:59.9999'),
|
||||
('838:59:59.99999'),
|
||||
('838:59:59.999999'),
|
||||
('838:59:59.9999999'),
|
||||
('839:59:59.9999999'),
|
||||
('87649414:59:59.999999'),
|
||||
('87649414:59:59.9999999'),
|
||||
('87649415:59:59.999999'),
|
||||
('87649415:59:59.9999999');
|
||||
|
||||
|
||||
CREATE TABLE t1_time_in_decimal (id SERIAL, a DECIMAL(38,10));
|
||||
INSERT INTO t1_time_in_decimal (a) VALUES
|
||||
(0),
|
||||
(0.9),
|
||||
(0.99),
|
||||
(0.999),
|
||||
(0.9999),
|
||||
(0.99999),
|
||||
(0.999999),
|
||||
(0.9999999);
|
||||
INSERT INTO t1_time_in_decimal (a) VALUES
|
||||
(8375959.9999999),
|
||||
(8385959),
|
||||
(8385959.9),
|
||||
(8385959.99),
|
||||
(8385959.999),
|
||||
(8385959.9999),
|
||||
(8385959.99999),
|
||||
(8385959.999999),
|
||||
(8385959.9999999),
|
||||
(8395959.9999999),
|
||||
(876494145959.999999),
|
||||
(876494145959.9999999),
|
||||
(876494155959.999999),
|
||||
(876494155959.9999999);
|
||||
|
||||
--echo #
|
||||
--echo # TIME: LEAST/GREATEST
|
||||
--echo #
|
||||
|
||||
SELECT GREATEST(TIME'00:00:00', a) FROM t1_time_in_varchar;
|
||||
SELECT GREATEST(TIME'00:00:00', a) FROM t1_time_in_decimal;
|
||||
|
||||
SELECT GREATEST(TIME'00:00:00', '00:00:00.0000004');
|
||||
SELECT GREATEST(TIME'00:00:00', 0.0000004);
|
||||
|
||||
SELECT GREATEST(TIME'00:00:00', '00:00:00.0000005');
|
||||
SELECT GREATEST(TIME'00:00:00', 0.0000005);
|
||||
|
||||
|
||||
--echo #
|
||||
--echo # Functions with a single TIME input, conversion from DATETIME-in-VARCHAR
|
||||
--echo #
|
||||
|
||||
SELECT SECOND(a), CAST(a AS TIME(6)), a FROM t1_datetime_in_varchar ORDER BY id;
|
||||
SELECT MINUTE(a), CAST(a AS TIME(6)), a FROM t1_datetime_in_varchar ORDER BY id;
|
||||
SELECT HOUR(a), CAST(a AS TIME(6)), a FROM t1_datetime_in_varchar ORDER BY id;
|
||||
|
||||
SELECT EXTRACT(SECOND FROM a), CAST(a AS TIME(6)), a FROM t1_datetime_in_varchar ORDER BY id;
|
||||
SELECT EXTRACT(MINUTE FROM a), CAST(a AS TIME(6)), a FROM t1_datetime_in_varchar ORDER BY id;
|
||||
SELECT EXTRACT(HOUR FROM a), CAST(a AS TIME(6)), a FROM t1_datetime_in_varchar ORDER BY id;
|
||||
|
||||
SELECT TIME_TO_SEC(a), CAST(a AS TIME(6)), a FROM t1_datetime_in_varchar ORDER BY id;
|
||||
|
||||
|
||||
--echo #
|
||||
--echo # Functions with a single TIME input, conversion from DATETIME-in-DECIMAL
|
||||
--echo #
|
||||
|
||||
|
||||
SELECT SECOND(a), CAST(a AS TIME(6)), a FROM t1_datetime_in_decimal ORDER BY id;
|
||||
SELECT MINUTE(a), CAST(a AS TIME(6)), a FROM t1_datetime_in_decimal ORDER BY id;
|
||||
SELECT HOUR(a), CAST(a AS TIME(6)), a FROM t1_datetime_in_decimal ORDER BY id;
|
||||
|
||||
SELECT EXTRACT(SECOND FROM a), CAST(a AS TIME(6)), a FROM t1_datetime_in_decimal ORDER BY id;
|
||||
SELECT EXTRACT(MINUTE FROM a), CAST(a AS TIME(6)), a FROM t1_datetime_in_decimal ORDER BY id;
|
||||
SELECT EXTRACT(HOUR FROM a), CAST(a AS TIME(6)), a FROM t1_datetime_in_decimal ORDER BY id;
|
||||
|
||||
SELECT TIME_TO_SEC(a), CAST(a AS TIME(6)), a FROM t1_datetime_in_decimal ORDER BY id;
|
||||
|
||||
|
||||
--echo #
|
||||
--echo # Functions with a single TIME interval input, conversion from TIME-interval-in-VARCHAR
|
||||
--echo #
|
||||
|
||||
SELECT
|
||||
EXTRACT(DAY FROM a),
|
||||
EXTRACT(HOUR FROM a),
|
||||
EXTRACT(MINUTE FROM a),
|
||||
EXTRACT(SECOND FROM a),
|
||||
EXTRACT(MICROSECOND FROM a),
|
||||
CAST(a AS INTERVAL DAY_SECOND(6)),
|
||||
a
|
||||
FROM t1_time_in_varchar ORDER BY id;
|
||||
|
||||
SELECT
|
||||
TIME_TO_SEC(a),
|
||||
CAST(a AS TIME(6)),
|
||||
a
|
||||
FROM t1_time_in_varchar ORDER BY id;
|
||||
|
||||
--echo #
|
||||
--echo # Functions with a single TIME interval input, conversion from TIME-interval-in-DECIMAL
|
||||
--echo #
|
||||
|
||||
SELECT
|
||||
EXTRACT(DAY FROM a),
|
||||
EXTRACT(HOUR FROM a),
|
||||
EXTRACT(MINUTE FROM a),
|
||||
EXTRACT(SECOND FROM a),
|
||||
EXTRACT(MICROSECOND FROM a),
|
||||
CAST(a AS INTERVAL DAY_SECOND(6)),
|
||||
a
|
||||
FROM t1_time_in_decimal ORDER BY id;
|
||||
|
||||
SELECT
|
||||
TIME_TO_SEC(a),
|
||||
CAST(a AS TIME(6)),
|
||||
a
|
||||
FROM t1_time_in_decimal ORDER BY id;
|
||||
|
||||
|
||||
--echo #
|
||||
--echo # Functions with a single DATE input, conversion from DATETIME-in-VARCHAR
|
||||
--echo #
|
||||
|
||||
SELECT QUARTER(a), CAST(a AS DATE), a FROM t1_datetime_in_varchar ORDER BY id;
|
||||
SELECT DAY(a), CAST(a AS DATE), a FROM t1_datetime_in_varchar ORDER BY id;
|
||||
SELECT MONTH(a), CAST(a AS DATE), a FROM t1_datetime_in_varchar ORDER BY id;
|
||||
SELECT YEAR(a), CAST(a AS DATE), a FROM t1_datetime_in_varchar ORDER BY id;
|
||||
|
||||
SELECT DAYNAME(a), CAST(a AS DATE), a FROM t1_datetime_in_varchar ORDER BY id;
|
||||
SELECT MONTHNAME(a), CAST(a AS DATE), a FROM t1_datetime_in_varchar ORDER BY id;
|
||||
|
||||
SELECT LAST_DAY(a), CAST(a AS DATE), a FROM t1_datetime_in_varchar ORDER BY id;
|
||||
SELECT TO_DAYS(a), CAST(a AS DATE), a FROM t1_datetime_in_varchar ORDER BY id;
|
||||
SELECT DAYOFYEAR(a), CAST(a AS DATE), a FROM t1_datetime_in_varchar ORDER BY id;
|
||||
|
||||
|
||||
CREATE TABLE t1 (a VARCHAR(32));
|
||||
INSERT INTO t1 VALUES
|
||||
('2002-01-05 23:59:59'),
|
||||
('2002-01-05 23:59:59.999999'),
|
||||
('2002-01-05 23:59:59.9999999');
|
||||
SELECT YEARWEEK(a), a FROM t1;
|
||||
SELECT WEEK(a), a FROM t1;
|
||||
SELECT WEEKDAY(a), a FROM t1;
|
||||
DROP TABLE t1;
|
||||
|
||||
CREATE TABLE t1 (a DECIMAL(32,9));
|
||||
INSERT INTO t1 VALUES
|
||||
(20020105235959),
|
||||
(20020105235959.999999),
|
||||
(20020105235959.9999999);
|
||||
SELECT YEARWEEK(a), a FROM t1;
|
||||
SELECT WEEK(a), a FROM t1;
|
||||
SELECT WEEKDAY(a), a FROM t1;
|
||||
DROP TABLE t1;
|
||||
|
||||
--echo #
|
||||
--echo # Functions with a single DATE input, conversion from DATETIME-in-DECIMAL
|
||||
--echo #
|
||||
|
||||
SELECT QUARTER(a), CAST(a AS DATE), a FROM t1_datetime_in_decimal ORDER BY id;
|
||||
SELECT DAY(a), CAST(a AS DATE), a FROM t1_datetime_in_decimal ORDER BY id;
|
||||
SELECT MONTH(a), CAST(a AS DATE), a FROM t1_datetime_in_decimal ORDER BY id;
|
||||
SELECT YEAR(a), CAST(a AS DATE), a FROM t1_datetime_in_decimal ORDER BY id;
|
||||
|
||||
SELECT DAYNAME(a), CAST(a AS DATE), a FROM t1_datetime_in_decimal ORDER BY id;
|
||||
SELECT MONTHNAME(a), CAST(a AS DATE), a FROM t1_datetime_in_decimal ORDER BY id;
|
||||
SELECT YEARWEEK(a), CAST(a AS DATE), a FROM t1_datetime_in_decimal ORDER BY id;
|
||||
|
||||
SELECT LAST_DAY(a), CAST(a AS DATE), a FROM t1_datetime_in_decimal ORDER BY id;
|
||||
SELECT TO_DAYS(a), CAST(a AS DATE), a FROM t1_datetime_in_decimal ORDER BY id;
|
||||
SELECT DAYOFYEAR(a), CAST(a AS DATE), a FROM t1_datetime_in_decimal ORDER BY id;
|
||||
SELECT DAYOFMONTH(a), CAST(a AS DATE), a FROM t1_datetime_in_decimal ORDER BY id;
|
||||
|
||||
|
||||
--echo #
|
||||
--echo # Functions with a single DATETIME input, conversion from DATETIME-in-VARCHAR
|
||||
--echo #
|
||||
|
||||
SELECT TO_SECONDS(a), CAST(a AS DATETIME(6)), a FROM t1_datetime_in_varchar ORDER BY id;
|
||||
|
||||
SET time_zone='+00:00';
|
||||
SELECT UNIX_TIMESTAMP(a), CAST(a AS DATETIME(6)), a FROM t1_datetime_in_varchar ORDER BY id;
|
||||
SET time_zone=DEFAULT;
|
||||
|
||||
SELECT CONVERT_TZ(a, '+00:00','+00:00'), CAST(a AS DATETIME(6)), a FROM t1_datetime_in_varchar ORDER BY id;
|
||||
|
||||
|
||||
--echo #
|
||||
--echo # Functions with a single DATETIME input, conversion from DATETIME-in-DECIMAL
|
||||
--echo #
|
||||
|
||||
SELECT TO_SECONDS(a), CAST(a AS DATETIME(6)), a FROM t1_datetime_in_decimal ORDER BY id;
|
||||
|
||||
SET time_zone='+00:00';
|
||||
SELECT UNIX_TIMESTAMP(a), CAST(a AS DATETIME(6)), a FROM t1_datetime_in_decimal ORDER BY id;
|
||||
SET time_zone=DEFAULT;
|
||||
|
||||
SELECT CONVERT_TZ(a, '+00:00','+00:00'), CAST(a AS DATETIME(6)), a FROM t1_datetime_in_decimal ORDER BY id;
|
||||
|
||||
DROP TABLE t1_datetime_in_varchar;
|
||||
DROP TABLE t1_datetime_in_decimal;
|
||||
DROP TABLE t1_time_in_varchar;
|
||||
DROP TABLE t1_time_in_decimal;
|
||||
|
||||
|
||||
--echo #
|
||||
--echo # Functions that construct DATETIME
|
||||
--echo #
|
||||
|
||||
SET time_zone='+00:00';
|
||||
CREATE TABLE t1_unix_timestamp (id SERIAL, a DECIMAL(30,10));
|
||||
INSERT INTO t1_unix_timestamp (a) VALUES
|
||||
(980639999),
|
||||
(980639999.9),
|
||||
(980639999.999999),
|
||||
(980639999.9999999),
|
||||
(2147483647),
|
||||
(2147483647.9),
|
||||
(2147483647.999999),
|
||||
(2147483647.9999999);
|
||||
SELECT a, FROM_UNIXTIME(a) FROM t1_unix_timestamp ORDER BY id;
|
||||
DROP TABLE t1_unix_timestamp;
|
||||
SET time_zone=DEFAULT;
|
||||
|
||||
|
||||
--echo #
|
||||
--echo # Functions that construct TIME
|
||||
--echo #
|
||||
|
||||
CREATE TABLE t1_sec (id SERIAL, a DECIMAL(38,10));
|
||||
INSERT INTO t1_sec (a) VALUES
|
||||
(59),
|
||||
(59.9),
|
||||
(59.999999),
|
||||
(59.9999999),
|
||||
(3020398),
|
||||
(3020398.999999),
|
||||
(3020398.9999999),
|
||||
(3020399),
|
||||
(3020399.999999),
|
||||
(3020399.9999999),
|
||||
(9223372036854775807),
|
||||
(9223372036854775807.9),
|
||||
(9223372036854775807.999999),
|
||||
(9223372036854775807.9999999),
|
||||
(18446744073709551615),
|
||||
(18446744073709551615.9),
|
||||
(18446744073709551615.999999),
|
||||
(18446744073709551615.9999999);
|
||||
SELECT a, SEC_TO_TIME(a) FROM t1_sec ORDER BY id;
|
||||
DROP TABLE t1_sec;
|
||||
|
||||
|
||||
CREATE TABLE t1_sec (id SERIAL, a DECIMAL(38,10));
|
||||
INSERT INTO t1_sec (a) VALUES
|
||||
(0),
|
||||
(0.9),
|
||||
(0.999999),
|
||||
(0.9999999);
|
||||
SELECT a, MAKETIME(0, 0, a) FROM t1_sec ORDER BY id;
|
||||
DROP TABLE t1_sec;
|
||||
|
||||
|
||||
CREATE TABLE t1 (a VARCHAR(64));
|
||||
INSERT INTO t1 VALUES
|
||||
('2017-12-31 23:59:59'),
|
||||
('2017-12-31 23:59:59.9'),
|
||||
('2017-12-31 23:59:59.999999'),
|
||||
('2017-12-31 23:59:59.9999999');
|
||||
--vertical_results
|
||||
SELECT
|
||||
'----',
|
||||
a,
|
||||
DATE_FORMAT(a, '%Y') AS yyyy,
|
||||
DATE_FORMAT(a, '%Y-%m-%d') AS d,
|
||||
DATE_FORMAT(a, '%H:%i:%s') AS t0,
|
||||
DATE_FORMAT(a, '%H:%i:%s.%f') AS t6,
|
||||
DATE_FORMAT(a, '%Y-%m-%d %H:%i:%s') AS dt0,
|
||||
DATE_FORMAT(a, '%Y-%m-%d %H:%i:%s.%f') AS dt6
|
||||
FROM t1;
|
||||
--horizontal_results
|
||||
DROP TABLE t1;
|
||||
|
||||
CREATE TABLE t1 (a DECIMAL(32,9));
|
||||
INSERT INTO t1 VALUES
|
||||
(20171231235959),
|
||||
(20171231235959.9),
|
||||
(20171231235959.999999),
|
||||
(20171231235959.9999999);
|
||||
--vertical_results
|
||||
SELECT
|
||||
'----',
|
||||
a,
|
||||
DATE_FORMAT(a, '%Y') AS yyyy,
|
||||
DATE_FORMAT(a, '%Y-%m-%d') AS d,
|
||||
DATE_FORMAT(a, '%H:%i:%s') AS t0,
|
||||
DATE_FORMAT(a, '%H:%i:%s.%f') AS t6,
|
||||
DATE_FORMAT(a, '%Y-%m-%d %H:%i:%s') AS dt0,
|
||||
DATE_FORMAT(a, '%Y-%m-%d %H:%i:%s.%f') AS dt6
|
||||
FROM t1;
|
||||
--horizontal_results
|
||||
DROP TABLE t1;
|
||||
|
||||
|
||||
--echo #
|
||||
--echo # Functions with two temporal parameters that round nanoseconds in both parameters in MySQL
|
||||
--echo #
|
||||
|
||||
CREATE TABLE t1 (a VARCHAR(64));
|
||||
CREATE TABLE t2 (a VARCHAR(64));
|
||||
INSERT INTO t1 VALUES
|
||||
('2017-12-31 23:59:59'),
|
||||
('2017-12-31 23:59:59.9'),
|
||||
('2017-12-31 23:59:59.999999'),
|
||||
('2017-12-31 23:59:59.9999999');
|
||||
INSERT INTO t2 VALUES
|
||||
('00:00:00'),
|
||||
('00:00:00.9'),
|
||||
('00:00:00.999999'),
|
||||
('00:00:00.9999999');
|
||||
|
||||
SELECT TIMESTAMP(t1.a, t2.a), t1.a, t2.a FROM t1,t2 ORDER BY t1.a, t2.a;
|
||||
SELECT ADDTIME(t1.a, t2.a), t1.a, t2.a FROM t1,t2 ORDER BY t1.a, t2.a;
|
||||
|
||||
DROP TABLE t1, t2;
|
||||
|
||||
|
||||
CREATE TABLE t1 (a VARCHAR(64));
|
||||
CREATE TABLE t2 (a VARCHAR(64));
|
||||
INSERT INTO t1 VALUES
|
||||
('23:59:59'),
|
||||
('23:59:59.9'),
|
||||
('23:59:59.999999'),
|
||||
('23:59:59.9999999');
|
||||
INSERT INTO t2 VALUES
|
||||
('00:00:00'),
|
||||
('00:00:00.9'),
|
||||
('00:00:00.999999'),
|
||||
('00:00:00.9999999');
|
||||
SELECT TIMEDIFF(t1.a, t2.a), t1.a, t2.a FROM t1,t2 ORDER BY t1.a, t2.a;
|
||||
DROP TABLE t1, t2;
|
||||
|
||||
|
||||
CREATE TABLE t1 (a VARCHAR(64));
|
||||
CREATE TABLE t2 (a VARCHAR(64));
|
||||
INSERT INTO t1 VALUES
|
||||
('2001-12-31 23:59:59'),
|
||||
('2001-12-31 23:59:59.9'),
|
||||
('2001-12-31 23:59:59.999999'),
|
||||
('2001-12-31 23:59:59.9999999');
|
||||
INSERT INTO t2 VALUES
|
||||
('2001-12-31 23:59:59'),
|
||||
('2001-12-31 23:59:59.9'),
|
||||
('2001-12-31 23:59:59.999999'),
|
||||
('2001-12-31 23:59:59.9999999');
|
||||
SELECT TIMESTAMPDIFF(MICROSECOND,t1.a, t2.a), t1.a, t2.a FROM t1,t2 ORDER BY t1.a, t2.a;
|
||||
DROP TABLE t1, t2;
|
||||
|
||||
CREATE TABLE t1 (a VARCHAR(64));
|
||||
CREATE TABLE t2 (a VARCHAR(64));
|
||||
INSERT INTO t1 VALUES
|
||||
('23:59:59'),
|
||||
('23:59:59.9'),
|
||||
('23:59:59.999999'),
|
||||
('23:59:59.9999999');
|
||||
INSERT INTO t2 VALUES
|
||||
('00:00:00'),
|
||||
('00:00:00.9'),
|
||||
('00:00:00.999999'),
|
||||
('00:00:00.9999999');
|
||||
SELECT TIMEDIFF(t1.a, t2.a), t1.a, t2.a FROM t1,t2 ORDER BY t1.a, t2.a;
|
||||
DROP TABLE t1, t2;
|
||||
|
||||
|
||||
--echo #
|
||||
--echo # STR_TO_DATE behaviour is questionable in MySQL 5.6 (MySQL Bug #92474)
|
||||
--echo #
|
||||
|
||||
--echo # It truncates nanoseconds, but this may change in the future.
|
||||
CREATE TABLE t1 (a VARCHAR(64));
|
||||
INSERT INTO t1 VALUES
|
||||
('2017-12-31 23:59:59'),
|
||||
('2017-12-31 23:59:59.9'),
|
||||
('2017-12-31 23:59:59.999999'),
|
||||
('2017-12-31 23:59:59.9999999');
|
||||
|
||||
SELECT
|
||||
a,
|
||||
STR_TO_DATE(a, '%Y-%m-%d %H:%i:%s') AS c0,
|
||||
STR_TO_DATE(a, '%Y-%m-%d %H:%i:%s.%f') AS c6
|
||||
FROM t1;
|
||||
DROP TABLE t1;
|
||||
|
||||
|
||||
--echo #
|
||||
--echo # DATE_ADD behaviour is questionable in MySQL 5.6 (MySQL Bug#92473)
|
||||
--echo # It rounds nanoseconds in the first argument, but truncates nanoseconds in the second argument.
|
||||
--echo # This may change in the future, to round both arguments.
|
||||
--echo #
|
||||
|
||||
CREATE TABLE t1 (a VARCHAR(64));
|
||||
INSERT INTO t1 VALUES
|
||||
('2017-12-31 23:59:59'),
|
||||
('2017-12-31 23:59:59.9'),
|
||||
('2017-12-31 23:59:59.999999'),
|
||||
('2017-12-31 23:59:59.9999999');
|
||||
CREATE TABLE t2 (b DECIMAL(32,9));
|
||||
INSERT INTO t2 VALUES
|
||||
(0),
|
||||
(0.9),
|
||||
(0.999999),
|
||||
(0.9999999);
|
||||
SELECT a, b, DATE_ADD(a, INTERVAL b SECOND) FROM t1,t2 ORDER BY a,b;
|
||||
DROP TABLE t1, t2;
|
@ -664,7 +664,7 @@ proc body longblob
|
||||
proc definer char(141)
|
||||
proc created timestamp
|
||||
proc modified timestamp
|
||||
proc sql_mode set('REAL_AS_FLOAT','PIPES_AS_CONCAT','ANSI_QUOTES','IGNORE_SPACE','IGNORE_BAD_TABLE_OPTIONS','ONLY_FULL_GROUP_BY','NO_UNSIGNED_SUBTRACTION','NO_DIR_IN_CREATE','POSTGRESQL','ORACLE','MSSQL','DB2','MAXDB','NO_KEY_OPTIONS','NO_TABLE_OPTIONS','NO_FIELD_OPTIONS','MYSQL323','MYSQL40','ANSI','NO_AUTO_VALUE_ON_ZERO','NO_BACKSLASH_ESCAPES','STRICT_TRANS_TABLES','STRICT_ALL_TABLES','NO_ZERO_IN_DATE','NO_ZERO_DATE','INVALID_DATES','ERROR_FOR_DIVISION_BY_ZERO','TRADITIONAL','NO_AUTO_CREATE_USER','HIGH_NOT_PRECEDENCE','NO_ENGINE_SUBSTITUTION','PAD_CHAR_TO_FULL_LENGTH','EMPTY_STRING_IS_NULL','SIMULTANEOUS_ASSIGNMENT')
|
||||
proc sql_mode set('REAL_AS_FLOAT','PIPES_AS_CONCAT','ANSI_QUOTES','IGNORE_SPACE','IGNORE_BAD_TABLE_OPTIONS','ONLY_FULL_GROUP_BY','NO_UNSIGNED_SUBTRACTION','NO_DIR_IN_CREATE','POSTGRESQL','ORACLE','MSSQL','DB2','MAXDB','NO_KEY_OPTIONS','NO_TABLE_OPTIONS','NO_FIELD_OPTIONS','MYSQL323','MYSQL40','ANSI','NO_AUTO_VALUE_ON_ZERO','NO_BACKSLASH_ESCAPES','STRICT_TRANS_TABLES','STRICT_ALL_TABLES','NO_ZERO_IN_DATE','NO_ZERO_DATE','INVALID_DATES','ERROR_FOR_DIVISION_BY_ZERO','TRADITIONAL','NO_AUTO_CREATE_USER','HIGH_NOT_PRECEDENCE','NO_ENGINE_SUBSTITUTION','PAD_CHAR_TO_FULL_LENGTH','EMPTY_STRING_IS_NULL','SIMULTANEOUS_ASSIGNMENT','TIME_ROUND_FRACTIONAL')
|
||||
proc comment text
|
||||
proc character_set_client char(32)
|
||||
proc collation_connection char(32)
|
||||
|
@ -1209,7 +1209,8 @@ The following specify which files/extra groups are read (specified before remain
|
||||
ERROR_FOR_DIVISION_BY_ZERO, TRADITIONAL,
|
||||
NO_AUTO_CREATE_USER, HIGH_NOT_PRECEDENCE,
|
||||
NO_ENGINE_SUBSTITUTION, PAD_CHAR_TO_FULL_LENGTH,
|
||||
EMPTY_STRING_IS_NULL, SIMULTANEOUS_ASSIGNMENT
|
||||
EMPTY_STRING_IS_NULL, SIMULTANEOUS_ASSIGNMENT,
|
||||
TIME_ROUND_FRACTIONAL
|
||||
--sql-safe-updates If set to 1, UPDATEs and DELETEs need either a key in the
|
||||
WHERE clause, or a LIMIT clause, or else they will
|
||||
aborted. Prevents the common mistake of accidentally
|
||||
|
@ -476,10 +476,14 @@ select @@sql_mode;
|
||||
@@sql_mode
|
||||
REAL_AS_FLOAT,PIPES_AS_CONCAT,ANSI_QUOTES,IGNORE_SPACE,NO_TABLE_OPTIONS,ANSI
|
||||
set sql_mode=2147483648*2*2*2;
|
||||
ERROR 42000: Variable 'sql_mode' can't be set to the value of '17179869184'
|
||||
select @@sql_mode;
|
||||
@@sql_mode
|
||||
REAL_AS_FLOAT,PIPES_AS_CONCAT,ANSI_QUOTES,IGNORE_SPACE,NO_TABLE_OPTIONS,ANSI
|
||||
TIME_ROUND_FRACTIONAL
|
||||
set sql_mode=2147483648*2*2*2*2;
|
||||
ERROR 42000: Variable 'sql_mode' can't be set to the value of '34359738368'
|
||||
select @@sql_mode;
|
||||
@@sql_mode
|
||||
TIME_ROUND_FRACTIONAL
|
||||
set sql_mode=PAD_CHAR_TO_FULL_LENGTH;
|
||||
create table t1 (a int auto_increment primary key, b char(5));
|
||||
insert into t1 (b) values('a'),('b\t'),('c ');
|
||||
|
@ -263,8 +263,10 @@ set sql_mode=4194304;
|
||||
select @@sql_mode;
|
||||
set sql_mode=16384+(65536*4);
|
||||
select @@sql_mode;
|
||||
set sql_mode=2147483648*2*2*2;
|
||||
select @@sql_mode;
|
||||
--error 1231
|
||||
set sql_mode=2147483648*2*2*2; # that mode does not exist
|
||||
set sql_mode=2147483648*2*2*2*2; # that mode does not exist
|
||||
select @@sql_mode;
|
||||
|
||||
#
|
||||
|
@ -191,7 +191,7 @@ proc CREATE TABLE `proc` (
|
||||
`definer` char(141) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL DEFAULT '',
|
||||
`created` timestamp NOT NULL DEFAULT current_timestamp() ON UPDATE current_timestamp(),
|
||||
`modified` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',
|
||||
`sql_mode` set('REAL_AS_FLOAT','PIPES_AS_CONCAT','ANSI_QUOTES','IGNORE_SPACE','IGNORE_BAD_TABLE_OPTIONS','ONLY_FULL_GROUP_BY','NO_UNSIGNED_SUBTRACTION','NO_DIR_IN_CREATE','POSTGRESQL','ORACLE','MSSQL','DB2','MAXDB','NO_KEY_OPTIONS','NO_TABLE_OPTIONS','NO_FIELD_OPTIONS','MYSQL323','MYSQL40','ANSI','NO_AUTO_VALUE_ON_ZERO','NO_BACKSLASH_ESCAPES','STRICT_TRANS_TABLES','STRICT_ALL_TABLES','NO_ZERO_IN_DATE','NO_ZERO_DATE','INVALID_DATES','ERROR_FOR_DIVISION_BY_ZERO','TRADITIONAL','NO_AUTO_CREATE_USER','HIGH_NOT_PRECEDENCE','NO_ENGINE_SUBSTITUTION','PAD_CHAR_TO_FULL_LENGTH','EMPTY_STRING_IS_NULL','SIMULTANEOUS_ASSIGNMENT') NOT NULL DEFAULT '',
|
||||
`sql_mode` set('REAL_AS_FLOAT','PIPES_AS_CONCAT','ANSI_QUOTES','IGNORE_SPACE','IGNORE_BAD_TABLE_OPTIONS','ONLY_FULL_GROUP_BY','NO_UNSIGNED_SUBTRACTION','NO_DIR_IN_CREATE','POSTGRESQL','ORACLE','MSSQL','DB2','MAXDB','NO_KEY_OPTIONS','NO_TABLE_OPTIONS','NO_FIELD_OPTIONS','MYSQL323','MYSQL40','ANSI','NO_AUTO_VALUE_ON_ZERO','NO_BACKSLASH_ESCAPES','STRICT_TRANS_TABLES','STRICT_ALL_TABLES','NO_ZERO_IN_DATE','NO_ZERO_DATE','INVALID_DATES','ERROR_FOR_DIVISION_BY_ZERO','TRADITIONAL','NO_AUTO_CREATE_USER','HIGH_NOT_PRECEDENCE','NO_ENGINE_SUBSTITUTION','PAD_CHAR_TO_FULL_LENGTH','EMPTY_STRING_IS_NULL','SIMULTANEOUS_ASSIGNMENT','TIME_ROUND_FRACTIONAL') NOT NULL DEFAULT '',
|
||||
`comment` text CHARACTER SET utf8 COLLATE utf8_bin NOT NULL,
|
||||
`character_set_client` char(32) CHARACTER SET utf8 COLLATE utf8_bin DEFAULT NULL,
|
||||
`collation_connection` char(32) CHARACTER SET utf8 COLLATE utf8_bin DEFAULT NULL,
|
||||
@ -217,7 +217,7 @@ event CREATE TABLE `event` (
|
||||
`ends` datetime DEFAULT NULL,
|
||||
`status` enum('ENABLED','DISABLED','SLAVESIDE_DISABLED') NOT NULL DEFAULT 'ENABLED',
|
||||
`on_completion` enum('DROP','PRESERVE') NOT NULL DEFAULT 'DROP',
|
||||
`sql_mode` set('REAL_AS_FLOAT','PIPES_AS_CONCAT','ANSI_QUOTES','IGNORE_SPACE','IGNORE_BAD_TABLE_OPTIONS','ONLY_FULL_GROUP_BY','NO_UNSIGNED_SUBTRACTION','NO_DIR_IN_CREATE','POSTGRESQL','ORACLE','MSSQL','DB2','MAXDB','NO_KEY_OPTIONS','NO_TABLE_OPTIONS','NO_FIELD_OPTIONS','MYSQL323','MYSQL40','ANSI','NO_AUTO_VALUE_ON_ZERO','NO_BACKSLASH_ESCAPES','STRICT_TRANS_TABLES','STRICT_ALL_TABLES','NO_ZERO_IN_DATE','NO_ZERO_DATE','INVALID_DATES','ERROR_FOR_DIVISION_BY_ZERO','TRADITIONAL','NO_AUTO_CREATE_USER','HIGH_NOT_PRECEDENCE','NO_ENGINE_SUBSTITUTION','PAD_CHAR_TO_FULL_LENGTH','EMPTY_STRING_IS_NULL','SIMULTANEOUS_ASSIGNMENT') NOT NULL DEFAULT '',
|
||||
`sql_mode` set('REAL_AS_FLOAT','PIPES_AS_CONCAT','ANSI_QUOTES','IGNORE_SPACE','IGNORE_BAD_TABLE_OPTIONS','ONLY_FULL_GROUP_BY','NO_UNSIGNED_SUBTRACTION','NO_DIR_IN_CREATE','POSTGRESQL','ORACLE','MSSQL','DB2','MAXDB','NO_KEY_OPTIONS','NO_TABLE_OPTIONS','NO_FIELD_OPTIONS','MYSQL323','MYSQL40','ANSI','NO_AUTO_VALUE_ON_ZERO','NO_BACKSLASH_ESCAPES','STRICT_TRANS_TABLES','STRICT_ALL_TABLES','NO_ZERO_IN_DATE','NO_ZERO_DATE','INVALID_DATES','ERROR_FOR_DIVISION_BY_ZERO','TRADITIONAL','NO_AUTO_CREATE_USER','HIGH_NOT_PRECEDENCE','NO_ENGINE_SUBSTITUTION','PAD_CHAR_TO_FULL_LENGTH','EMPTY_STRING_IS_NULL','SIMULTANEOUS_ASSIGNMENT','TIME_ROUND_FRACTIONAL') NOT NULL DEFAULT '',
|
||||
`comment` char(64) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL DEFAULT '',
|
||||
`originator` int(10) unsigned NOT NULL,
|
||||
`time_zone` char(64) CHARACTER SET latin1 NOT NULL DEFAULT 'SYSTEM',
|
||||
|
@ -192,7 +192,7 @@ proc CREATE TABLE `proc` (
|
||||
`definer` char(141) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL DEFAULT '',
|
||||
`created` timestamp NOT NULL DEFAULT current_timestamp() ON UPDATE current_timestamp(),
|
||||
`modified` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',
|
||||
`sql_mode` set('REAL_AS_FLOAT','PIPES_AS_CONCAT','ANSI_QUOTES','IGNORE_SPACE','IGNORE_BAD_TABLE_OPTIONS','ONLY_FULL_GROUP_BY','NO_UNSIGNED_SUBTRACTION','NO_DIR_IN_CREATE','POSTGRESQL','ORACLE','MSSQL','DB2','MAXDB','NO_KEY_OPTIONS','NO_TABLE_OPTIONS','NO_FIELD_OPTIONS','MYSQL323','MYSQL40','ANSI','NO_AUTO_VALUE_ON_ZERO','NO_BACKSLASH_ESCAPES','STRICT_TRANS_TABLES','STRICT_ALL_TABLES','NO_ZERO_IN_DATE','NO_ZERO_DATE','INVALID_DATES','ERROR_FOR_DIVISION_BY_ZERO','TRADITIONAL','NO_AUTO_CREATE_USER','HIGH_NOT_PRECEDENCE','NO_ENGINE_SUBSTITUTION','PAD_CHAR_TO_FULL_LENGTH','EMPTY_STRING_IS_NULL','SIMULTANEOUS_ASSIGNMENT') NOT NULL DEFAULT '',
|
||||
`sql_mode` set('REAL_AS_FLOAT','PIPES_AS_CONCAT','ANSI_QUOTES','IGNORE_SPACE','IGNORE_BAD_TABLE_OPTIONS','ONLY_FULL_GROUP_BY','NO_UNSIGNED_SUBTRACTION','NO_DIR_IN_CREATE','POSTGRESQL','ORACLE','MSSQL','DB2','MAXDB','NO_KEY_OPTIONS','NO_TABLE_OPTIONS','NO_FIELD_OPTIONS','MYSQL323','MYSQL40','ANSI','NO_AUTO_VALUE_ON_ZERO','NO_BACKSLASH_ESCAPES','STRICT_TRANS_TABLES','STRICT_ALL_TABLES','NO_ZERO_IN_DATE','NO_ZERO_DATE','INVALID_DATES','ERROR_FOR_DIVISION_BY_ZERO','TRADITIONAL','NO_AUTO_CREATE_USER','HIGH_NOT_PRECEDENCE','NO_ENGINE_SUBSTITUTION','PAD_CHAR_TO_FULL_LENGTH','EMPTY_STRING_IS_NULL','SIMULTANEOUS_ASSIGNMENT','TIME_ROUND_FRACTIONAL') NOT NULL DEFAULT '',
|
||||
`comment` text CHARACTER SET utf8 COLLATE utf8_bin NOT NULL,
|
||||
`character_set_client` char(32) CHARACTER SET utf8 COLLATE utf8_bin DEFAULT NULL,
|
||||
`collation_connection` char(32) CHARACTER SET utf8 COLLATE utf8_bin DEFAULT NULL,
|
||||
@ -218,7 +218,7 @@ event CREATE TABLE `event` (
|
||||
`ends` datetime DEFAULT NULL,
|
||||
`status` enum('ENABLED','DISABLED','SLAVESIDE_DISABLED') NOT NULL DEFAULT 'ENABLED',
|
||||
`on_completion` enum('DROP','PRESERVE') NOT NULL DEFAULT 'DROP',
|
||||
`sql_mode` set('REAL_AS_FLOAT','PIPES_AS_CONCAT','ANSI_QUOTES','IGNORE_SPACE','IGNORE_BAD_TABLE_OPTIONS','ONLY_FULL_GROUP_BY','NO_UNSIGNED_SUBTRACTION','NO_DIR_IN_CREATE','POSTGRESQL','ORACLE','MSSQL','DB2','MAXDB','NO_KEY_OPTIONS','NO_TABLE_OPTIONS','NO_FIELD_OPTIONS','MYSQL323','MYSQL40','ANSI','NO_AUTO_VALUE_ON_ZERO','NO_BACKSLASH_ESCAPES','STRICT_TRANS_TABLES','STRICT_ALL_TABLES','NO_ZERO_IN_DATE','NO_ZERO_DATE','INVALID_DATES','ERROR_FOR_DIVISION_BY_ZERO','TRADITIONAL','NO_AUTO_CREATE_USER','HIGH_NOT_PRECEDENCE','NO_ENGINE_SUBSTITUTION','PAD_CHAR_TO_FULL_LENGTH','EMPTY_STRING_IS_NULL','SIMULTANEOUS_ASSIGNMENT') NOT NULL DEFAULT '',
|
||||
`sql_mode` set('REAL_AS_FLOAT','PIPES_AS_CONCAT','ANSI_QUOTES','IGNORE_SPACE','IGNORE_BAD_TABLE_OPTIONS','ONLY_FULL_GROUP_BY','NO_UNSIGNED_SUBTRACTION','NO_DIR_IN_CREATE','POSTGRESQL','ORACLE','MSSQL','DB2','MAXDB','NO_KEY_OPTIONS','NO_TABLE_OPTIONS','NO_FIELD_OPTIONS','MYSQL323','MYSQL40','ANSI','NO_AUTO_VALUE_ON_ZERO','NO_BACKSLASH_ESCAPES','STRICT_TRANS_TABLES','STRICT_ALL_TABLES','NO_ZERO_IN_DATE','NO_ZERO_DATE','INVALID_DATES','ERROR_FOR_DIVISION_BY_ZERO','TRADITIONAL','NO_AUTO_CREATE_USER','HIGH_NOT_PRECEDENCE','NO_ENGINE_SUBSTITUTION','PAD_CHAR_TO_FULL_LENGTH','EMPTY_STRING_IS_NULL','SIMULTANEOUS_ASSIGNMENT','TIME_ROUND_FRACTIONAL') NOT NULL DEFAULT '',
|
||||
`comment` char(64) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL DEFAULT '',
|
||||
`originator` int(10) unsigned NOT NULL,
|
||||
`time_zone` char(64) CHARACTER SET latin1 NOT NULL DEFAULT 'SYSTEM',
|
||||
|
@ -192,7 +192,7 @@ proc CREATE TABLE `proc` (
|
||||
`definer` char(141) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL DEFAULT '',
|
||||
`created` timestamp NOT NULL DEFAULT current_timestamp() ON UPDATE current_timestamp(),
|
||||
`modified` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',
|
||||
`sql_mode` set('REAL_AS_FLOAT','PIPES_AS_CONCAT','ANSI_QUOTES','IGNORE_SPACE','IGNORE_BAD_TABLE_OPTIONS','ONLY_FULL_GROUP_BY','NO_UNSIGNED_SUBTRACTION','NO_DIR_IN_CREATE','POSTGRESQL','ORACLE','MSSQL','DB2','MAXDB','NO_KEY_OPTIONS','NO_TABLE_OPTIONS','NO_FIELD_OPTIONS','MYSQL323','MYSQL40','ANSI','NO_AUTO_VALUE_ON_ZERO','NO_BACKSLASH_ESCAPES','STRICT_TRANS_TABLES','STRICT_ALL_TABLES','NO_ZERO_IN_DATE','NO_ZERO_DATE','INVALID_DATES','ERROR_FOR_DIVISION_BY_ZERO','TRADITIONAL','NO_AUTO_CREATE_USER','HIGH_NOT_PRECEDENCE','NO_ENGINE_SUBSTITUTION','PAD_CHAR_TO_FULL_LENGTH','EMPTY_STRING_IS_NULL','SIMULTANEOUS_ASSIGNMENT') NOT NULL DEFAULT '',
|
||||
`sql_mode` set('REAL_AS_FLOAT','PIPES_AS_CONCAT','ANSI_QUOTES','IGNORE_SPACE','IGNORE_BAD_TABLE_OPTIONS','ONLY_FULL_GROUP_BY','NO_UNSIGNED_SUBTRACTION','NO_DIR_IN_CREATE','POSTGRESQL','ORACLE','MSSQL','DB2','MAXDB','NO_KEY_OPTIONS','NO_TABLE_OPTIONS','NO_FIELD_OPTIONS','MYSQL323','MYSQL40','ANSI','NO_AUTO_VALUE_ON_ZERO','NO_BACKSLASH_ESCAPES','STRICT_TRANS_TABLES','STRICT_ALL_TABLES','NO_ZERO_IN_DATE','NO_ZERO_DATE','INVALID_DATES','ERROR_FOR_DIVISION_BY_ZERO','TRADITIONAL','NO_AUTO_CREATE_USER','HIGH_NOT_PRECEDENCE','NO_ENGINE_SUBSTITUTION','PAD_CHAR_TO_FULL_LENGTH','EMPTY_STRING_IS_NULL','SIMULTANEOUS_ASSIGNMENT','TIME_ROUND_FRACTIONAL') NOT NULL DEFAULT '',
|
||||
`comment` text CHARACTER SET utf8 COLLATE utf8_bin NOT NULL,
|
||||
`character_set_client` char(32) CHARACTER SET utf8 COLLATE utf8_bin DEFAULT NULL,
|
||||
`collation_connection` char(32) CHARACTER SET utf8 COLLATE utf8_bin DEFAULT NULL,
|
||||
@ -218,7 +218,7 @@ event CREATE TABLE `event` (
|
||||
`ends` datetime DEFAULT NULL,
|
||||
`status` enum('ENABLED','DISABLED','SLAVESIDE_DISABLED') NOT NULL DEFAULT 'ENABLED',
|
||||
`on_completion` enum('DROP','PRESERVE') NOT NULL DEFAULT 'DROP',
|
||||
`sql_mode` set('REAL_AS_FLOAT','PIPES_AS_CONCAT','ANSI_QUOTES','IGNORE_SPACE','IGNORE_BAD_TABLE_OPTIONS','ONLY_FULL_GROUP_BY','NO_UNSIGNED_SUBTRACTION','NO_DIR_IN_CREATE','POSTGRESQL','ORACLE','MSSQL','DB2','MAXDB','NO_KEY_OPTIONS','NO_TABLE_OPTIONS','NO_FIELD_OPTIONS','MYSQL323','MYSQL40','ANSI','NO_AUTO_VALUE_ON_ZERO','NO_BACKSLASH_ESCAPES','STRICT_TRANS_TABLES','STRICT_ALL_TABLES','NO_ZERO_IN_DATE','NO_ZERO_DATE','INVALID_DATES','ERROR_FOR_DIVISION_BY_ZERO','TRADITIONAL','NO_AUTO_CREATE_USER','HIGH_NOT_PRECEDENCE','NO_ENGINE_SUBSTITUTION','PAD_CHAR_TO_FULL_LENGTH','EMPTY_STRING_IS_NULL','SIMULTANEOUS_ASSIGNMENT') NOT NULL DEFAULT '',
|
||||
`sql_mode` set('REAL_AS_FLOAT','PIPES_AS_CONCAT','ANSI_QUOTES','IGNORE_SPACE','IGNORE_BAD_TABLE_OPTIONS','ONLY_FULL_GROUP_BY','NO_UNSIGNED_SUBTRACTION','NO_DIR_IN_CREATE','POSTGRESQL','ORACLE','MSSQL','DB2','MAXDB','NO_KEY_OPTIONS','NO_TABLE_OPTIONS','NO_FIELD_OPTIONS','MYSQL323','MYSQL40','ANSI','NO_AUTO_VALUE_ON_ZERO','NO_BACKSLASH_ESCAPES','STRICT_TRANS_TABLES','STRICT_ALL_TABLES','NO_ZERO_IN_DATE','NO_ZERO_DATE','INVALID_DATES','ERROR_FOR_DIVISION_BY_ZERO','TRADITIONAL','NO_AUTO_CREATE_USER','HIGH_NOT_PRECEDENCE','NO_ENGINE_SUBSTITUTION','PAD_CHAR_TO_FULL_LENGTH','EMPTY_STRING_IS_NULL','SIMULTANEOUS_ASSIGNMENT','TIME_ROUND_FRACTIONAL') NOT NULL DEFAULT '',
|
||||
`comment` char(64) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL DEFAULT '',
|
||||
`originator` int(10) unsigned NOT NULL,
|
||||
`time_zone` char(64) CHARACTER SET latin1 NOT NULL DEFAULT 'SYSTEM',
|
||||
|
@ -192,7 +192,7 @@ proc CREATE TABLE `proc` (
|
||||
`definer` char(141) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL DEFAULT '',
|
||||
`created` timestamp NOT NULL DEFAULT current_timestamp() ON UPDATE current_timestamp(),
|
||||
`modified` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',
|
||||
`sql_mode` set('REAL_AS_FLOAT','PIPES_AS_CONCAT','ANSI_QUOTES','IGNORE_SPACE','IGNORE_BAD_TABLE_OPTIONS','ONLY_FULL_GROUP_BY','NO_UNSIGNED_SUBTRACTION','NO_DIR_IN_CREATE','POSTGRESQL','ORACLE','MSSQL','DB2','MAXDB','NO_KEY_OPTIONS','NO_TABLE_OPTIONS','NO_FIELD_OPTIONS','MYSQL323','MYSQL40','ANSI','NO_AUTO_VALUE_ON_ZERO','NO_BACKSLASH_ESCAPES','STRICT_TRANS_TABLES','STRICT_ALL_TABLES','NO_ZERO_IN_DATE','NO_ZERO_DATE','INVALID_DATES','ERROR_FOR_DIVISION_BY_ZERO','TRADITIONAL','NO_AUTO_CREATE_USER','HIGH_NOT_PRECEDENCE','NO_ENGINE_SUBSTITUTION','PAD_CHAR_TO_FULL_LENGTH','EMPTY_STRING_IS_NULL','SIMULTANEOUS_ASSIGNMENT') NOT NULL DEFAULT '',
|
||||
`sql_mode` set('REAL_AS_FLOAT','PIPES_AS_CONCAT','ANSI_QUOTES','IGNORE_SPACE','IGNORE_BAD_TABLE_OPTIONS','ONLY_FULL_GROUP_BY','NO_UNSIGNED_SUBTRACTION','NO_DIR_IN_CREATE','POSTGRESQL','ORACLE','MSSQL','DB2','MAXDB','NO_KEY_OPTIONS','NO_TABLE_OPTIONS','NO_FIELD_OPTIONS','MYSQL323','MYSQL40','ANSI','NO_AUTO_VALUE_ON_ZERO','NO_BACKSLASH_ESCAPES','STRICT_TRANS_TABLES','STRICT_ALL_TABLES','NO_ZERO_IN_DATE','NO_ZERO_DATE','INVALID_DATES','ERROR_FOR_DIVISION_BY_ZERO','TRADITIONAL','NO_AUTO_CREATE_USER','HIGH_NOT_PRECEDENCE','NO_ENGINE_SUBSTITUTION','PAD_CHAR_TO_FULL_LENGTH','EMPTY_STRING_IS_NULL','SIMULTANEOUS_ASSIGNMENT','TIME_ROUND_FRACTIONAL') NOT NULL DEFAULT '',
|
||||
`comment` text CHARACTER SET utf8 COLLATE utf8_bin NOT NULL,
|
||||
`character_set_client` char(32) CHARACTER SET utf8 COLLATE utf8_bin DEFAULT NULL,
|
||||
`collation_connection` char(32) CHARACTER SET utf8 COLLATE utf8_bin DEFAULT NULL,
|
||||
@ -218,7 +218,7 @@ event CREATE TABLE `event` (
|
||||
`ends` datetime DEFAULT NULL,
|
||||
`status` enum('ENABLED','DISABLED','SLAVESIDE_DISABLED') NOT NULL DEFAULT 'ENABLED',
|
||||
`on_completion` enum('DROP','PRESERVE') NOT NULL DEFAULT 'DROP',
|
||||
`sql_mode` set('REAL_AS_FLOAT','PIPES_AS_CONCAT','ANSI_QUOTES','IGNORE_SPACE','IGNORE_BAD_TABLE_OPTIONS','ONLY_FULL_GROUP_BY','NO_UNSIGNED_SUBTRACTION','NO_DIR_IN_CREATE','POSTGRESQL','ORACLE','MSSQL','DB2','MAXDB','NO_KEY_OPTIONS','NO_TABLE_OPTIONS','NO_FIELD_OPTIONS','MYSQL323','MYSQL40','ANSI','NO_AUTO_VALUE_ON_ZERO','NO_BACKSLASH_ESCAPES','STRICT_TRANS_TABLES','STRICT_ALL_TABLES','NO_ZERO_IN_DATE','NO_ZERO_DATE','INVALID_DATES','ERROR_FOR_DIVISION_BY_ZERO','TRADITIONAL','NO_AUTO_CREATE_USER','HIGH_NOT_PRECEDENCE','NO_ENGINE_SUBSTITUTION','PAD_CHAR_TO_FULL_LENGTH','EMPTY_STRING_IS_NULL','SIMULTANEOUS_ASSIGNMENT') NOT NULL DEFAULT '',
|
||||
`sql_mode` set('REAL_AS_FLOAT','PIPES_AS_CONCAT','ANSI_QUOTES','IGNORE_SPACE','IGNORE_BAD_TABLE_OPTIONS','ONLY_FULL_GROUP_BY','NO_UNSIGNED_SUBTRACTION','NO_DIR_IN_CREATE','POSTGRESQL','ORACLE','MSSQL','DB2','MAXDB','NO_KEY_OPTIONS','NO_TABLE_OPTIONS','NO_FIELD_OPTIONS','MYSQL323','MYSQL40','ANSI','NO_AUTO_VALUE_ON_ZERO','NO_BACKSLASH_ESCAPES','STRICT_TRANS_TABLES','STRICT_ALL_TABLES','NO_ZERO_IN_DATE','NO_ZERO_DATE','INVALID_DATES','ERROR_FOR_DIVISION_BY_ZERO','TRADITIONAL','NO_AUTO_CREATE_USER','HIGH_NOT_PRECEDENCE','NO_ENGINE_SUBSTITUTION','PAD_CHAR_TO_FULL_LENGTH','EMPTY_STRING_IS_NULL','SIMULTANEOUS_ASSIGNMENT','TIME_ROUND_FRACTIONAL') NOT NULL DEFAULT '',
|
||||
`comment` char(64) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL DEFAULT '',
|
||||
`originator` int(10) unsigned NOT NULL,
|
||||
`time_zone` char(64) CHARACTER SET latin1 NOT NULL DEFAULT 'SYSTEM',
|
||||
|
174
mysql-test/main/type_date_round.result
Normal file
174
mysql-test/main/type_date_round.result
Normal file
@ -0,0 +1,174 @@
|
||||
SET sql_mode=IF(@@version LIKE '%MariaDB%', 'TIME_ROUND_FRACTIONAL', '');
|
||||
SET @default_sql_mode=@@sql_mode;
|
||||
#
|
||||
# DATE: SET
|
||||
#
|
||||
CREATE TABLE t1 (a DATE, b DATETIME(4));
|
||||
INSERT INTO t1 VALUES(NULL,'2000-12-31 23:59:59.9999');
|
||||
UPDATE t1 SET a=b;
|
||||
Warnings:
|
||||
Note 1265 Data truncated for column 'a' at row 1
|
||||
SELECT a FROM t1;
|
||||
a
|
||||
2000-12-31
|
||||
DROP TABLE t1;
|
||||
CREATE TABLE t1 (a DATE, b VARCHAR(64));
|
||||
INSERT INTO t1 VALUES(NULL,'2000-12-31 23:59:59.9999');
|
||||
INSERT INTO t1 VALUES(NULL,'2000-12-31 23:59:59.9999999');
|
||||
UPDATE t1 SET a=b;
|
||||
Warnings:
|
||||
Note 1265 Data truncated for column 'a' at row 1
|
||||
Note 1265 Data truncated for column 'a' at row 2
|
||||
SELECT a FROM t1;
|
||||
a
|
||||
2000-12-31
|
||||
2000-12-31
|
||||
DROP TABLE t1;
|
||||
CREATE TABLE t1 (a DATE, b DECIMAL(38,10));
|
||||
INSERT INTO t1 VALUES(NULL,20001231235959.9999);
|
||||
INSERT INTO t1 VALUES(NULL,20001231235959.9999999);
|
||||
UPDATE t1 SET a=b;
|
||||
Warnings:
|
||||
Note 1265 Data truncated for column 'a' at row 1
|
||||
Note 1265 Data truncated for column 'a' at row 2
|
||||
SELECT a FROM t1;
|
||||
a
|
||||
2000-12-31
|
||||
2000-12-31
|
||||
DROP TABLE t1;
|
||||
#
|
||||
# DATE: ALTER
|
||||
#
|
||||
CREATE TABLE t1 (a DATETIME(4));
|
||||
INSERT INTO t1 VALUES('2000-12-31 23:59:59.9999');
|
||||
ALTER TABLE t1 MODIFY a DATE;
|
||||
Warnings:
|
||||
Note 1265 Data truncated for column 'a' at row 1
|
||||
SELECT a FROM t1;
|
||||
a
|
||||
2000-12-31
|
||||
DROP TABLE t1;
|
||||
CREATE TABLE t1 (a VARCHAR(64));
|
||||
INSERT INTO t1 VALUES('2000-12-31 23:59:59.9999');
|
||||
INSERT INTO t1 VALUES('2000-12-31 23:59:59.9999999');
|
||||
ALTER TABLE t1 MODIFY a DATE;
|
||||
Warnings:
|
||||
Note 1265 Data truncated for column 'a' at row 1
|
||||
Note 1292 Truncated incorrect datetime value: '2000-12-31 23:59:59.9999999'
|
||||
Note 1265 Data truncated for column 'a' at row 2
|
||||
SELECT a FROM t1;
|
||||
a
|
||||
2000-12-31
|
||||
2000-12-31
|
||||
DROP TABLE t1;
|
||||
CREATE TABLE t1 (a DECIMAL(38,10));
|
||||
INSERT INTO t1 VALUES(20001231235959.9999);
|
||||
INSERT INTO t1 VALUES(20001231235959.9999999);
|
||||
ALTER TABLE t1 MODIFY a DATE;
|
||||
Warnings:
|
||||
Note 1265 Data truncated for column 'a' at row 1
|
||||
Note 1265 Data truncated for column 'a' at row 2
|
||||
SELECT a FROM t1;
|
||||
a
|
||||
2000-12-31
|
||||
2000-12-31
|
||||
DROP TABLE t1;
|
||||
#
|
||||
# DATE: CAST
|
||||
#
|
||||
CREATE TABLE t1 (a DATETIME(4));
|
||||
INSERT INTO t1 VALUES('2000-12-31 23:59:59.9999');
|
||||
SELECT a, CAST(a AS DATE) FROM t1;
|
||||
a CAST(a AS DATE)
|
||||
2000-12-31 23:59:59.9999 2000-12-31
|
||||
DROP TABLE t1;
|
||||
CREATE TABLE t1 (a VARCHAR(64));
|
||||
INSERT INTO t1 VALUES('2000-12-31 23:59:59.9999');
|
||||
INSERT INTO t1 VALUES('2000-12-31 23:59:59.9999999');
|
||||
SELECT a, CAST(a AS DATE) FROM t1;
|
||||
a CAST(a AS DATE)
|
||||
2000-12-31 23:59:59.9999 2000-12-31
|
||||
2000-12-31 23:59:59.9999999 2000-12-31
|
||||
Warnings:
|
||||
Note 1292 Truncated incorrect datetime value: '2000-12-31 23:59:59.9999999'
|
||||
DROP TABLE t1;
|
||||
CREATE TABLE t1 (a DECIMAL(38,10));
|
||||
INSERT INTO t1 VALUES(20001231235959.9999);
|
||||
INSERT INTO t1 VALUES(20001231235959.9999999);
|
||||
SELECT a, CAST(a AS DATE) FROM t1;
|
||||
a CAST(a AS DATE)
|
||||
20001231235959.9999000000 2000-12-31
|
||||
20001231235959.9999999000 2000-12-31
|
||||
DROP TABLE t1;
|
||||
#
|
||||
# Equal field propagation
|
||||
#
|
||||
CREATE TABLE t1 (a DATE);
|
||||
INSERT INTO t1 VALUES (20010101);
|
||||
INSERT INTO t1 VALUES (20010102);
|
||||
SELECT * FROM t1 WHERE a= 20010101235959.9999999;
|
||||
a
|
||||
2001-01-02
|
||||
SELECT * FROM t1 WHERE a='2001-01-01 23:59:59.9999999';
|
||||
a
|
||||
2001-01-02
|
||||
Warnings:
|
||||
Note 1292 Truncated incorrect datetime value: '2001-01-01 23:59:59.9999999'
|
||||
SELECT * FROM t1 WHERE a='2001-01-01 23:59:59.9999999' AND a>='2001-01-01 23:59:59.9999999';
|
||||
a
|
||||
2001-01-02
|
||||
Warnings:
|
||||
Note 1292 Truncated incorrect datetime value: '2001-01-01 23:59:59.9999999'
|
||||
Note 1292 Truncated incorrect datetime value: '2001-01-01 23:59:59.9999999'
|
||||
SELECT * FROM t1 WHERE a='2001-01-01 23:59:59.9999999' AND CONCAT(a)='2001-01-02';
|
||||
a
|
||||
2001-01-02
|
||||
Warnings:
|
||||
Note 1292 Truncated incorrect datetime value: '2001-01-01 23:59:59.9999999'
|
||||
EXPLAIN EXTENDED SELECT * FROM t1 WHERE a='2001-01-01 23:59:59.9999999' AND a>='2001-01-01 23:59:59.9999999';
|
||||
id select_type table type possible_keys key key_len ref rows filtered Extra
|
||||
1 SIMPLE t1 ALL NULL NULL NULL NULL 2 100.00 Using where
|
||||
Warnings:
|
||||
Note 1292 Truncated incorrect datetime value: '2001-01-01 23:59:59.9999999'
|
||||
Note 1292 Truncated incorrect datetime value: '2001-01-01 23:59:59.9999999'
|
||||
Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = DATE'2001-01-02'
|
||||
EXPLAIN EXTENDED SELECT * FROM t1 WHERE a='2001-01-01 23:59:59.9999999' AND CONCAT(a)='2001-01-02';
|
||||
id select_type table type possible_keys key key_len ref rows filtered Extra
|
||||
1 SIMPLE t1 ALL NULL NULL NULL NULL 2 100.00 Using where
|
||||
Warnings:
|
||||
Note 1292 Truncated incorrect datetime value: '2001-01-01 23:59:59.9999999'
|
||||
Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = DATE'2001-01-02'
|
||||
DROP TABLE t1;
|
||||
#
|
||||
# Comparing non-temporal to DATE
|
||||
#
|
||||
# Although conversion from non-temporal to DATE (e.g. on SET) does not round,
|
||||
# comparison between non-temporal to DATE is performed as DATETIME.
|
||||
# So rounding does happen here.
|
||||
CREATE TABLE t1 (a VARCHAR(64));
|
||||
INSERT t1 VALUES ('2001-01-01 23:59:59.9999999');
|
||||
SELECT * FROM t1 WHERE a=DATE'2001-01-02';
|
||||
a
|
||||
2001-01-01 23:59:59.9999999
|
||||
Warnings:
|
||||
Note 1292 Truncated incorrect datetime value: '2001-01-01 23:59:59.9999999'
|
||||
SELECT * FROM t1 WHERE CONCAT(a)=DATE'2001-01-02';
|
||||
a
|
||||
2001-01-01 23:59:59.9999999
|
||||
Warnings:
|
||||
Note 1292 Truncated incorrect datetime value: '2001-01-01 23:59:59.9999999'
|
||||
SELECT * FROM t1 WHERE COALESCE(a)=DATE'2001-01-02';
|
||||
a
|
||||
2001-01-01 23:59:59.9999999
|
||||
Warnings:
|
||||
Note 1292 Truncated incorrect datetime value: '2001-01-01 23:59:59.9999999'
|
||||
DROP TABLE t1;
|
||||
CREATE TABLE t1 (a DECIMAL(32,7));
|
||||
INSERT t1 VALUES (20010101235959.9999999);
|
||||
SELECT * FROM t1 WHERE a=DATE'2001-01-02';
|
||||
a
|
||||
20010101235959.9999999
|
||||
SELECT * FROM t1 WHERE COALESCE(a)=DATE'2001-01-02';
|
||||
a
|
||||
20010101235959.9999999
|
||||
DROP TABLE t1;
|
113
mysql-test/main/type_date_round.test
Normal file
113
mysql-test/main/type_date_round.test
Normal file
@ -0,0 +1,113 @@
|
||||
SET sql_mode=IF(@@version LIKE '%MariaDB%', 'TIME_ROUND_FRACTIONAL', '');
|
||||
SET @default_sql_mode=@@sql_mode;
|
||||
|
||||
--echo #
|
||||
--echo # DATE: SET
|
||||
--echo #
|
||||
|
||||
CREATE TABLE t1 (a DATE, b DATETIME(4));
|
||||
INSERT INTO t1 VALUES(NULL,'2000-12-31 23:59:59.9999');
|
||||
UPDATE t1 SET a=b;
|
||||
SELECT a FROM t1;
|
||||
DROP TABLE t1;
|
||||
|
||||
CREATE TABLE t1 (a DATE, b VARCHAR(64));
|
||||
INSERT INTO t1 VALUES(NULL,'2000-12-31 23:59:59.9999');
|
||||
INSERT INTO t1 VALUES(NULL,'2000-12-31 23:59:59.9999999');
|
||||
UPDATE t1 SET a=b;
|
||||
SELECT a FROM t1;
|
||||
DROP TABLE t1;
|
||||
|
||||
CREATE TABLE t1 (a DATE, b DECIMAL(38,10));
|
||||
INSERT INTO t1 VALUES(NULL,20001231235959.9999);
|
||||
INSERT INTO t1 VALUES(NULL,20001231235959.9999999);
|
||||
UPDATE t1 SET a=b;
|
||||
SELECT a FROM t1;
|
||||
DROP TABLE t1;
|
||||
|
||||
--echo #
|
||||
--echo # DATE: ALTER
|
||||
--echo #
|
||||
|
||||
CREATE TABLE t1 (a DATETIME(4));
|
||||
INSERT INTO t1 VALUES('2000-12-31 23:59:59.9999');
|
||||
ALTER TABLE t1 MODIFY a DATE;
|
||||
SELECT a FROM t1;
|
||||
DROP TABLE t1;
|
||||
|
||||
CREATE TABLE t1 (a VARCHAR(64));
|
||||
INSERT INTO t1 VALUES('2000-12-31 23:59:59.9999');
|
||||
INSERT INTO t1 VALUES('2000-12-31 23:59:59.9999999');
|
||||
ALTER TABLE t1 MODIFY a DATE;
|
||||
SELECT a FROM t1;
|
||||
DROP TABLE t1;
|
||||
|
||||
CREATE TABLE t1 (a DECIMAL(38,10));
|
||||
INSERT INTO t1 VALUES(20001231235959.9999);
|
||||
INSERT INTO t1 VALUES(20001231235959.9999999);
|
||||
ALTER TABLE t1 MODIFY a DATE;
|
||||
SELECT a FROM t1;
|
||||
DROP TABLE t1;
|
||||
|
||||
--echo #
|
||||
--echo # DATE: CAST
|
||||
--echo #
|
||||
|
||||
CREATE TABLE t1 (a DATETIME(4));
|
||||
INSERT INTO t1 VALUES('2000-12-31 23:59:59.9999');
|
||||
SELECT a, CAST(a AS DATE) FROM t1;
|
||||
DROP TABLE t1;
|
||||
|
||||
# This truncates microseconds but rounds nanoseconds (MySQL Bug #92475)
|
||||
CREATE TABLE t1 (a VARCHAR(64));
|
||||
INSERT INTO t1 VALUES('2000-12-31 23:59:59.9999');
|
||||
INSERT INTO t1 VALUES('2000-12-31 23:59:59.9999999');
|
||||
SELECT a, CAST(a AS DATE) FROM t1;
|
||||
DROP TABLE t1;
|
||||
|
||||
# This truncates microseconds but rounds nanoseconds (MySQL Bug #92475)
|
||||
CREATE TABLE t1 (a DECIMAL(38,10));
|
||||
INSERT INTO t1 VALUES(20001231235959.9999);
|
||||
INSERT INTO t1 VALUES(20001231235959.9999999);
|
||||
SELECT a, CAST(a AS DATE) FROM t1;
|
||||
DROP TABLE t1;
|
||||
|
||||
|
||||
--echo #
|
||||
--echo # Equal field propagation
|
||||
--echo #
|
||||
|
||||
CREATE TABLE t1 (a DATE);
|
||||
INSERT INTO t1 VALUES (20010101);
|
||||
INSERT INTO t1 VALUES (20010102);
|
||||
# DATE is compared to non-temporal as DATETIME
|
||||
# In the below queries nanoseconds should round to microseconds
|
||||
SELECT * FROM t1 WHERE a= 20010101235959.9999999;
|
||||
SELECT * FROM t1 WHERE a='2001-01-01 23:59:59.9999999';
|
||||
SELECT * FROM t1 WHERE a='2001-01-01 23:59:59.9999999' AND a>='2001-01-01 23:59:59.9999999';
|
||||
SELECT * FROM t1 WHERE a='2001-01-01 23:59:59.9999999' AND CONCAT(a)='2001-01-02';
|
||||
EXPLAIN EXTENDED SELECT * FROM t1 WHERE a='2001-01-01 23:59:59.9999999' AND a>='2001-01-01 23:59:59.9999999';
|
||||
EXPLAIN EXTENDED SELECT * FROM t1 WHERE a='2001-01-01 23:59:59.9999999' AND CONCAT(a)='2001-01-02';
|
||||
DROP TABLE t1;
|
||||
|
||||
|
||||
--echo #
|
||||
--echo # Comparing non-temporal to DATE
|
||||
--echo #
|
||||
|
||||
--echo # Although conversion from non-temporal to DATE (e.g. on SET) does not round,
|
||||
--echo # comparison between non-temporal to DATE is performed as DATETIME.
|
||||
--echo # So rounding does happen here.
|
||||
|
||||
CREATE TABLE t1 (a VARCHAR(64));
|
||||
INSERT t1 VALUES ('2001-01-01 23:59:59.9999999');
|
||||
SELECT * FROM t1 WHERE a=DATE'2001-01-02';
|
||||
SELECT * FROM t1 WHERE CONCAT(a)=DATE'2001-01-02';
|
||||
SELECT * FROM t1 WHERE COALESCE(a)=DATE'2001-01-02';
|
||||
DROP TABLE t1;
|
||||
|
||||
CREATE TABLE t1 (a DECIMAL(32,7));
|
||||
INSERT t1 VALUES (20010101235959.9999999);
|
||||
SELECT * FROM t1 WHERE a=DATE'2001-01-02';
|
||||
SELECT * FROM t1 WHERE COALESCE(a)=DATE'2001-01-02';
|
||||
DROP TABLE t1;
|
205
mysql-test/main/type_datetime_round.result
Normal file
205
mysql-test/main/type_datetime_round.result
Normal file
@ -0,0 +1,205 @@
|
||||
SET sql_mode=IF(@@version LIKE '%MariaDB%', 'TIME_ROUND_FRACTIONAL', '');
|
||||
SET @default_sql_mode=@@sql_mode;
|
||||
#
|
||||
# DATETIME: SET
|
||||
#
|
||||
CREATE TABLE t1 (a DATETIME(3), b DATETIME(4));
|
||||
INSERT INTO t1 VALUES(NULL,'2000-12-31 23:59:59.9999');
|
||||
UPDATE t1 SET a=b;
|
||||
SELECT a FROM t1;
|
||||
a
|
||||
2001-01-01 00:00:00.000
|
||||
DROP TABLE t1;
|
||||
CREATE TABLE t1 (a DATETIME(3), b VARCHAR(64));
|
||||
INSERT INTO t1 VALUES(NULL,'2000-12-31 23:59:59.9999');
|
||||
INSERT INTO t1 VALUES(NULL,'2000-12-31 23:59:59.9999999');
|
||||
UPDATE t1 SET a=b;
|
||||
Warnings:
|
||||
Note 1265 Data truncated for column 'a' at row 2
|
||||
SELECT a FROM t1;
|
||||
a
|
||||
2001-01-01 00:00:00.000
|
||||
2001-01-01 00:00:00.000
|
||||
DROP TABLE t1;
|
||||
CREATE TABLE t1 (a DATETIME(3), b DECIMAL(38,10));
|
||||
INSERT INTO t1 VALUES(NULL,20001231235959.9999);
|
||||
INSERT INTO t1 VALUES(NULL,20001231235959.9999999);
|
||||
UPDATE t1 SET a=b;
|
||||
SELECT a FROM t1;
|
||||
a
|
||||
2001-01-01 00:00:00.000
|
||||
2001-01-01 00:00:00.000
|
||||
DROP TABLE t1;
|
||||
#
|
||||
# DATETIME: ALTER
|
||||
#
|
||||
CREATE TABLE t1 (a DATETIME(4));
|
||||
INSERT INTO t1 VALUES('2000-12-31 23:59:59.9999');
|
||||
ALTER TABLE t1 MODIFY a DATETIME(3);
|
||||
SELECT a FROM t1;
|
||||
a
|
||||
2001-01-01 00:00:00.000
|
||||
DROP TABLE t1;
|
||||
CREATE TABLE t1 (a VARCHAR(64));
|
||||
INSERT INTO t1 VALUES('2000-12-31 23:59:59.9999');
|
||||
INSERT INTO t1 VALUES('2000-12-31 23:59:59.9999999');
|
||||
ALTER TABLE t1 MODIFY a DATETIME(3);
|
||||
Warnings:
|
||||
Note 1292 Truncated incorrect datetime value: '2000-12-31 23:59:59.9999999'
|
||||
SELECT a FROM t1;
|
||||
a
|
||||
2001-01-01 00:00:00.000
|
||||
2001-01-01 00:00:00.000
|
||||
DROP TABLE t1;
|
||||
CREATE TABLE t1 (a DECIMAL(38,10));
|
||||
INSERT INTO t1 VALUES(20001231235959.9999);
|
||||
INSERT INTO t1 VALUES(20001231235959.9999999);
|
||||
ALTER TABLE t1 MODIFY a DATETIME(3);
|
||||
SELECT a FROM t1;
|
||||
a
|
||||
2001-01-01 00:00:00.000
|
||||
2001-01-01 00:00:00.000
|
||||
DROP TABLE t1;
|
||||
#
|
||||
# Corner case:
|
||||
# ALTER DATETIME to a shorter DATETIME
|
||||
# All values round, maximum possible value truncates.
|
||||
#
|
||||
SET time_zone='+00:00';
|
||||
CREATE TABLE t1 (ID INT, a DATETIME(6), comment VARCHAR(64));
|
||||
INSERT INTO t1 VALUES (0, '9999-12-30 23:59:58.999999', 'Should round');
|
||||
INSERT INTO t1 VALUES (1, '9999-12-31 22:59:59.999999', 'Should round');
|
||||
INSERT INTO t1 VALUES (2, '9999-12-31 23:59:58.999999', 'Should round');
|
||||
INSERT INTO t1 VALUES (3, '9999-12-31 23:59:59.999999', 'Should truncate');
|
||||
ALTER TABLE t1 MODIFY a DATETIME(5);
|
||||
Warnings:
|
||||
Warning 1264 Out of range value for column 'a' at row 4
|
||||
SELECT * FROM t1;
|
||||
ID a comment
|
||||
0 9999-12-30 23:59:59.00000 Should round
|
||||
1 9999-12-31 23:00:00.00000 Should round
|
||||
2 9999-12-31 23:59:59.00000 Should round
|
||||
3 9999-12-31 23:59:59.99999 Should truncate
|
||||
DROP TABLE t1;
|
||||
SET time_zone=DEFAULT;
|
||||
#
|
||||
# NOW
|
||||
#
|
||||
SET time_zone='+00:00';
|
||||
SET timestamp=UNIX_TIMESTAMP('2010-12-31 23:59:59.999999');
|
||||
CREATE OR REPLACE TABLE t1 (id SERIAL, a DATETIME(4));
|
||||
INSERT INTO t1 (a) VALUES (now(6));
|
||||
INSERT INTO t1 (a) VALUES (CURRENT_TIMESTAMP(6));
|
||||
INSERT INTO t1 (a) VALUES (CURRENT_TIME(6));
|
||||
SELECT * FROM t1;
|
||||
id a
|
||||
1 2011-01-01 00:00:00.0000
|
||||
2 2011-01-01 00:00:00.0000
|
||||
3 2011-01-01 00:00:00.0000
|
||||
DROP TABLE t1;
|
||||
SET timestamp=DEFAULT;
|
||||
SET time_zone=DEFAULT;
|
||||
#
|
||||
# DATETIME: CAST
|
||||
#
|
||||
CREATE TABLE t1 (a DATETIME(4));
|
||||
INSERT INTO t1 VALUES('2000-12-31 23:59:59.9999');
|
||||
SELECT a, CAST(a AS DATETIME(3)) FROM t1;
|
||||
a CAST(a AS DATETIME(3))
|
||||
2000-12-31 23:59:59.9999 2001-01-01 00:00:00.000
|
||||
DROP TABLE t1;
|
||||
CREATE TABLE t1 (a VARCHAR(64));
|
||||
INSERT INTO t1 VALUES('2000-12-31 23:59:59.9999');
|
||||
INSERT INTO t1 VALUES('2000-12-31 23:59:59.9999999');
|
||||
SELECT a, CAST(a AS DATETIME(3)) FROM t1;
|
||||
a CAST(a AS DATETIME(3))
|
||||
2000-12-31 23:59:59.9999 2001-01-01 00:00:00.000
|
||||
2000-12-31 23:59:59.9999999 2001-01-01 00:00:00.000
|
||||
Warnings:
|
||||
Note 1292 Truncated incorrect datetime value: '2000-12-31 23:59:59.9999999'
|
||||
DROP TABLE t1;
|
||||
CREATE TABLE t1 (a DECIMAL(38,10));
|
||||
INSERT INTO t1 VALUES(20001231235959.9999);
|
||||
INSERT INTO t1 VALUES(20001231235959.9999999);
|
||||
SELECT a, CAST(a AS DATETIME(3)) FROM t1;
|
||||
a CAST(a AS DATETIME(3))
|
||||
20001231235959.9999000000 2001-01-01 00:00:00.000
|
||||
20001231235959.9999999000 2001-01-01 00:00:00.000
|
||||
DROP TABLE t1;
|
||||
#
|
||||
# Equal field propagation
|
||||
#
|
||||
CREATE TABLE t1 (a DATETIME(6));
|
||||
INSERT INTO t1 VALUES (20010101235959.999999);
|
||||
INSERT INTO t1 VALUES (20010101235959.9999999);
|
||||
SELECT * FROM t1 WHERE a=20010101235959.9999999;
|
||||
a
|
||||
2001-01-02 00:00:00.000000
|
||||
SELECT * FROM t1 WHERE a='20010101235959.9999999';
|
||||
a
|
||||
2001-01-02 00:00:00.000000
|
||||
Warnings:
|
||||
Note 1292 Truncated incorrect datetime value: '20010101235959.9999999'
|
||||
SELECT * FROM t1 WHERE a='20010101235959.9999999' AND a>='20010101235959.9999999';
|
||||
a
|
||||
2001-01-02 00:00:00.000000
|
||||
Warnings:
|
||||
Note 1292 Truncated incorrect datetime value: '20010101235959.9999999'
|
||||
Note 1292 Truncated incorrect datetime value: '20010101235959.9999999'
|
||||
SELECT * FROM t1 WHERE a='20010101235959.9999999' AND CONCAT(a)='2001-01-02 00:00:00.000000';
|
||||
a
|
||||
2001-01-02 00:00:00.000000
|
||||
Warnings:
|
||||
Note 1292 Truncated incorrect datetime value: '20010101235959.9999999'
|
||||
EXPLAIN EXTENDED SELECT * FROM t1 WHERE a='20010101235959.9999999' AND a>='20010101235959.9999999';
|
||||
id select_type table type possible_keys key key_len ref rows filtered Extra
|
||||
1 SIMPLE t1 ALL NULL NULL NULL NULL 2 100.00 Using where
|
||||
Warnings:
|
||||
Note 1292 Truncated incorrect datetime value: '20010101235959.9999999'
|
||||
Note 1292 Truncated incorrect datetime value: '20010101235959.9999999'
|
||||
Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = TIMESTAMP'2001-01-02 00:00:00'
|
||||
EXPLAIN EXTENDED SELECT * FROM t1 WHERE a='20010101235959.9999999' AND CONCAT(a)='2001-01-02 00:00:00.000000';
|
||||
id select_type table type possible_keys key key_len ref rows filtered Extra
|
||||
1 SIMPLE t1 ALL NULL NULL NULL NULL 2 100.00 Using where
|
||||
Warnings:
|
||||
Note 1292 Truncated incorrect datetime value: '20010101235959.9999999'
|
||||
Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = TIMESTAMP'2001-01-02 00:00:00'
|
||||
DROP TABLE t1;
|
||||
#
|
||||
# Comparing non-temporal to DATETIME
|
||||
#
|
||||
CREATE TABLE t1 (a VARCHAR(64));
|
||||
INSERT t1 VALUES ('2001-01-01 23:59:59.9999999');
|
||||
SELECT * FROM t1 WHERE a=TIMESTAMP'2001-01-02 00:00:00';
|
||||
a
|
||||
2001-01-01 23:59:59.9999999
|
||||
Warnings:
|
||||
Note 1292 Truncated incorrect datetime value: '2001-01-01 23:59:59.9999999'
|
||||
SELECT * FROM t1 WHERE CONCAT(a)=TIMESTAMP'2001-01-02 00:00:00';
|
||||
a
|
||||
2001-01-01 23:59:59.9999999
|
||||
Warnings:
|
||||
Note 1292 Truncated incorrect datetime value: '2001-01-01 23:59:59.9999999'
|
||||
SELECT * FROM t1 WHERE COALESCE(a)=TIMESTAMP'2001-01-02 00:00:00';
|
||||
a
|
||||
2001-01-01 23:59:59.9999999
|
||||
Warnings:
|
||||
Note 1292 Truncated incorrect datetime value: '2001-01-01 23:59:59.9999999'
|
||||
DROP TABLE t1;
|
||||
CREATE TABLE t1 (a DECIMAL(32,7));
|
||||
INSERT t1 VALUES (20010101235959.9999999);
|
||||
SELECT * FROM t1 WHERE a=TIMESTAMP'2001-01-02 00:00:00';
|
||||
a
|
||||
20010101235959.9999999
|
||||
SELECT * FROM t1 WHERE COALESCE(a)=TIMESTAMP'2001-01-02 00:00:00';
|
||||
a
|
||||
20010101235959.9999999
|
||||
DROP TABLE t1;
|
||||
#
|
||||
# Literal corner case
|
||||
#
|
||||
SELECT TIMESTAMP'9999-12-31 23:59:59.999999';
|
||||
TIMESTAMP'9999-12-31 23:59:59.999999'
|
||||
9999-12-31 23:59:59.999999
|
||||
SELECT TIME'9999-12-31 23:59:59.9999999';
|
||||
ERROR HY000: Incorrect TIME value: '9999-12-31 23:59:59.9999999'
|
147
mysql-test/main/type_datetime_round.test
Normal file
147
mysql-test/main/type_datetime_round.test
Normal file
@ -0,0 +1,147 @@
|
||||
SET sql_mode=IF(@@version LIKE '%MariaDB%', 'TIME_ROUND_FRACTIONAL', '');
|
||||
SET @default_sql_mode=@@sql_mode;
|
||||
|
||||
--echo #
|
||||
--echo # DATETIME: SET
|
||||
--echo #
|
||||
|
||||
CREATE TABLE t1 (a DATETIME(3), b DATETIME(4));
|
||||
INSERT INTO t1 VALUES(NULL,'2000-12-31 23:59:59.9999');
|
||||
UPDATE t1 SET a=b;
|
||||
SELECT a FROM t1;
|
||||
DROP TABLE t1;
|
||||
|
||||
CREATE TABLE t1 (a DATETIME(3), b VARCHAR(64));
|
||||
INSERT INTO t1 VALUES(NULL,'2000-12-31 23:59:59.9999');
|
||||
INSERT INTO t1 VALUES(NULL,'2000-12-31 23:59:59.9999999');
|
||||
UPDATE t1 SET a=b;
|
||||
SELECT a FROM t1;
|
||||
DROP TABLE t1;
|
||||
|
||||
CREATE TABLE t1 (a DATETIME(3), b DECIMAL(38,10));
|
||||
INSERT INTO t1 VALUES(NULL,20001231235959.9999);
|
||||
INSERT INTO t1 VALUES(NULL,20001231235959.9999999);
|
||||
UPDATE t1 SET a=b;
|
||||
SELECT a FROM t1;
|
||||
DROP TABLE t1;
|
||||
|
||||
--echo #
|
||||
--echo # DATETIME: ALTER
|
||||
--echo #
|
||||
|
||||
CREATE TABLE t1 (a DATETIME(4));
|
||||
INSERT INTO t1 VALUES('2000-12-31 23:59:59.9999');
|
||||
ALTER TABLE t1 MODIFY a DATETIME(3);
|
||||
SELECT a FROM t1;
|
||||
DROP TABLE t1;
|
||||
|
||||
CREATE TABLE t1 (a VARCHAR(64));
|
||||
INSERT INTO t1 VALUES('2000-12-31 23:59:59.9999');
|
||||
INSERT INTO t1 VALUES('2000-12-31 23:59:59.9999999');
|
||||
ALTER TABLE t1 MODIFY a DATETIME(3);
|
||||
SELECT a FROM t1;
|
||||
DROP TABLE t1;
|
||||
|
||||
CREATE TABLE t1 (a DECIMAL(38,10));
|
||||
INSERT INTO t1 VALUES(20001231235959.9999);
|
||||
INSERT INTO t1 VALUES(20001231235959.9999999);
|
||||
ALTER TABLE t1 MODIFY a DATETIME(3);
|
||||
SELECT a FROM t1;
|
||||
DROP TABLE t1;
|
||||
|
||||
|
||||
--echo #
|
||||
--echo # Corner case:
|
||||
--echo # ALTER DATETIME to a shorter DATETIME
|
||||
--echo # All values round, maximum possible value truncates.
|
||||
--echo #
|
||||
|
||||
SET time_zone='+00:00';
|
||||
CREATE TABLE t1 (ID INT, a DATETIME(6), comment VARCHAR(64));
|
||||
INSERT INTO t1 VALUES (0, '9999-12-30 23:59:58.999999', 'Should round');
|
||||
INSERT INTO t1 VALUES (1, '9999-12-31 22:59:59.999999', 'Should round');
|
||||
INSERT INTO t1 VALUES (2, '9999-12-31 23:59:58.999999', 'Should round');
|
||||
INSERT INTO t1 VALUES (3, '9999-12-31 23:59:59.999999', 'Should truncate');
|
||||
ALTER TABLE t1 MODIFY a DATETIME(5);
|
||||
SELECT * FROM t1;
|
||||
DROP TABLE t1;
|
||||
SET time_zone=DEFAULT;
|
||||
|
||||
|
||||
--echo #
|
||||
--echo # NOW
|
||||
--echo #
|
||||
|
||||
SET time_zone='+00:00';
|
||||
SET timestamp=UNIX_TIMESTAMP('2010-12-31 23:59:59.999999');
|
||||
CREATE OR REPLACE TABLE t1 (id SERIAL, a DATETIME(4));
|
||||
INSERT INTO t1 (a) VALUES (now(6));
|
||||
INSERT INTO t1 (a) VALUES (CURRENT_TIMESTAMP(6));
|
||||
INSERT INTO t1 (a) VALUES (CURRENT_TIME(6));
|
||||
SELECT * FROM t1;
|
||||
DROP TABLE t1;
|
||||
SET timestamp=DEFAULT;
|
||||
SET time_zone=DEFAULT;
|
||||
|
||||
|
||||
--echo #
|
||||
--echo # DATETIME: CAST
|
||||
--echo #
|
||||
|
||||
CREATE TABLE t1 (a DATETIME(4));
|
||||
INSERT INTO t1 VALUES('2000-12-31 23:59:59.9999');
|
||||
SELECT a, CAST(a AS DATETIME(3)) FROM t1;
|
||||
DROP TABLE t1;
|
||||
|
||||
CREATE TABLE t1 (a VARCHAR(64));
|
||||
INSERT INTO t1 VALUES('2000-12-31 23:59:59.9999');
|
||||
INSERT INTO t1 VALUES('2000-12-31 23:59:59.9999999');
|
||||
SELECT a, CAST(a AS DATETIME(3)) FROM t1;
|
||||
DROP TABLE t1;
|
||||
|
||||
CREATE TABLE t1 (a DECIMAL(38,10));
|
||||
INSERT INTO t1 VALUES(20001231235959.9999);
|
||||
INSERT INTO t1 VALUES(20001231235959.9999999);
|
||||
SELECT a, CAST(a AS DATETIME(3)) FROM t1;
|
||||
DROP TABLE t1;
|
||||
|
||||
|
||||
--echo #
|
||||
--echo # Equal field propagation
|
||||
--echo #
|
||||
|
||||
CREATE TABLE t1 (a DATETIME(6));
|
||||
INSERT INTO t1 VALUES (20010101235959.999999);
|
||||
INSERT INTO t1 VALUES (20010101235959.9999999);
|
||||
SELECT * FROM t1 WHERE a=20010101235959.9999999;
|
||||
SELECT * FROM t1 WHERE a='20010101235959.9999999';
|
||||
SELECT * FROM t1 WHERE a='20010101235959.9999999' AND a>='20010101235959.9999999';
|
||||
SELECT * FROM t1 WHERE a='20010101235959.9999999' AND CONCAT(a)='2001-01-02 00:00:00.000000';
|
||||
EXPLAIN EXTENDED SELECT * FROM t1 WHERE a='20010101235959.9999999' AND a>='20010101235959.9999999';
|
||||
EXPLAIN EXTENDED SELECT * FROM t1 WHERE a='20010101235959.9999999' AND CONCAT(a)='2001-01-02 00:00:00.000000';
|
||||
DROP TABLE t1;
|
||||
|
||||
--echo #
|
||||
--echo # Comparing non-temporal to DATETIME
|
||||
--echo #
|
||||
|
||||
CREATE TABLE t1 (a VARCHAR(64));
|
||||
INSERT t1 VALUES ('2001-01-01 23:59:59.9999999');
|
||||
SELECT * FROM t1 WHERE a=TIMESTAMP'2001-01-02 00:00:00';
|
||||
SELECT * FROM t1 WHERE CONCAT(a)=TIMESTAMP'2001-01-02 00:00:00';
|
||||
SELECT * FROM t1 WHERE COALESCE(a)=TIMESTAMP'2001-01-02 00:00:00';
|
||||
DROP TABLE t1;
|
||||
|
||||
CREATE TABLE t1 (a DECIMAL(32,7));
|
||||
INSERT t1 VALUES (20010101235959.9999999);
|
||||
SELECT * FROM t1 WHERE a=TIMESTAMP'2001-01-02 00:00:00';
|
||||
SELECT * FROM t1 WHERE COALESCE(a)=TIMESTAMP'2001-01-02 00:00:00';
|
||||
DROP TABLE t1;
|
||||
|
||||
--echo #
|
||||
--echo # Literal corner case
|
||||
--echo #
|
||||
|
||||
SELECT TIMESTAMP'9999-12-31 23:59:59.999999';
|
||||
--error ER_WRONG_VALUE
|
||||
SELECT TIME'9999-12-31 23:59:59.9999999';
|
260
mysql-test/main/type_time_round.result
Normal file
260
mysql-test/main/type_time_round.result
Normal file
@ -0,0 +1,260 @@
|
||||
SET sql_mode=IF(@@version LIKE '%MariaDB%', 'TIME_ROUND_FRACTIONAL', '');
|
||||
SET @default_sql_mode=@@sql_mode;
|
||||
#
|
||||
# TIME: SET
|
||||
#
|
||||
CREATE TABLE t1 (a TIME(3), b TIME(4));
|
||||
INSERT INTO t1 VALUES(NULL,'00:00:00.9999');
|
||||
UPDATE t1 SET a=b;
|
||||
SELECT a FROM t1;
|
||||
a
|
||||
00:00:01.000
|
||||
DROP TABLE t1;
|
||||
CREATE TABLE t1 (a TIME(3), b VARCHAR(64));
|
||||
INSERT INTO t1 VALUES(NULL,'00:00:00.9999');
|
||||
INSERT INTO t1 VALUES(NULL,'00:00:00.9999999');
|
||||
UPDATE t1 SET a=b;
|
||||
Warnings:
|
||||
Note 1265 Data truncated for column 'a' at row 2
|
||||
SELECT a FROM t1;
|
||||
a
|
||||
00:00:01.000
|
||||
00:00:01.000
|
||||
DROP TABLE t1;
|
||||
CREATE TABLE t1 (a TIME(3), b DECIMAL(38,10));
|
||||
INSERT INTO t1 VALUES(NULL,0.9999);
|
||||
INSERT INTO t1 VALUES(NULL,0.9999999);
|
||||
UPDATE t1 SET a=b;
|
||||
SELECT a FROM t1;
|
||||
a
|
||||
00:00:01.000
|
||||
00:00:01.000
|
||||
DROP TABLE t1;
|
||||
CREATE TABLE t1 (a TIME(3), b DOUBLE);
|
||||
INSERT INTO t1 VALUES(NULL,0.9999);
|
||||
INSERT INTO t1 VALUES(NULL,0.9999999);
|
||||
UPDATE t1 SET a=b;
|
||||
SELECT a FROM t1;
|
||||
a
|
||||
00:00:01.000
|
||||
00:00:01.000
|
||||
DROP TABLE t1;
|
||||
CREATE TABLE t1 (a TIME(6), b VARCHAR(64));
|
||||
INSERT INTO t1 VALUES(NULL,'00:00:00.9999999');
|
||||
UPDATE t1 SET a=b;
|
||||
Warnings:
|
||||
Note 1265 Data truncated for column 'a' at row 1
|
||||
SELECT a FROM t1;
|
||||
a
|
||||
00:00:01.000000
|
||||
DROP TABLE t1;
|
||||
CREATE TABLE t1 (a TIME(6), b DECIMAL(38,10));
|
||||
INSERT INTO t1 VALUES(NULL,0.9999999);
|
||||
UPDATE t1 SET a=b;
|
||||
SELECT a FROM t1;
|
||||
a
|
||||
00:00:01.000000
|
||||
DROP TABLE t1;
|
||||
CREATE TABLE t1 (a TIME(6), b DOUBLE);
|
||||
INSERT INTO t1 VALUES(NULL,0.9999999);
|
||||
UPDATE t1 SET a=b;
|
||||
SELECT a FROM t1;
|
||||
a
|
||||
00:00:01.000000
|
||||
DROP TABLE t1;
|
||||
#
|
||||
# TIME: ALTER
|
||||
#
|
||||
CREATE TABLE t1 (a TIME(4));
|
||||
INSERT INTO t1 VALUES('00:00:00.9999');
|
||||
ALTER TABLE t1 MODIFY a TIME(3);
|
||||
SELECT a FROM t1;
|
||||
a
|
||||
00:00:01.000
|
||||
DROP TABLE t1;
|
||||
CREATE TABLE t1 (a VARCHAR(64));
|
||||
INSERT INTO t1 VALUES('00:00:00.9999');
|
||||
INSERT INTO t1 VALUES('00:00:00.9999999');
|
||||
ALTER TABLE t1 MODIFY a TIME(3);
|
||||
Warnings:
|
||||
Note 1292 Truncated incorrect time value: '00:00:00.9999999'
|
||||
SELECT a FROM t1;
|
||||
a
|
||||
00:00:01.000
|
||||
00:00:01.000
|
||||
DROP TABLE t1;
|
||||
CREATE TABLE t1 (a DECIMAL(38,10));
|
||||
INSERT INTO t1 VALUES(0.9999);
|
||||
INSERT INTO t1 VALUES(0.9999999);
|
||||
ALTER TABLE t1 MODIFY a TIME(3);
|
||||
SELECT a FROM t1;
|
||||
a
|
||||
00:00:01.000
|
||||
00:00:01.000
|
||||
DROP TABLE t1;
|
||||
CREATE TABLE t1 (a DOUBLE);
|
||||
INSERT INTO t1 VALUES(0.9999);
|
||||
INSERT INTO t1 VALUES(0.9999999);
|
||||
ALTER TABLE t1 MODIFY a TIME(3);
|
||||
Warnings:
|
||||
Note 1265 Data truncated for column 'a' at row 2
|
||||
SELECT a FROM t1;
|
||||
a
|
||||
00:00:01.000
|
||||
00:00:01.000
|
||||
DROP TABLE t1;
|
||||
#
|
||||
# TIME: CAST
|
||||
#
|
||||
CREATE TABLE t1 (a TIME(4));
|
||||
INSERT INTO t1 VALUES('00:00:00.9999');
|
||||
SELECT a, CAST(a AS TIME(3)) FROM t1;
|
||||
a CAST(a AS TIME(3))
|
||||
00:00:00.9999 00:00:01.000
|
||||
DROP TABLE t1;
|
||||
CREATE TABLE t1 (a VARCHAR(64));
|
||||
INSERT INTO t1 VALUES('00:00:00.9999');
|
||||
INSERT INTO t1 VALUES('00:00:00.9999999');
|
||||
SELECT a, CAST(a AS TIME(3)) FROM t1;
|
||||
a CAST(a AS TIME(3))
|
||||
00:00:00.9999 00:00:01.000
|
||||
00:00:00.9999999 00:00:01.000
|
||||
Warnings:
|
||||
Note 1292 Truncated incorrect time value: '00:00:00.9999999'
|
||||
DROP TABLE t1;
|
||||
CREATE TABLE t1 (a DECIMAL(38,10));
|
||||
INSERT INTO t1 VALUES(0.9999);
|
||||
INSERT INTO t1 VALUES(0.9999999);
|
||||
SELECT a, CAST(a AS TIME(3)) FROM t1;
|
||||
a CAST(a AS TIME(3))
|
||||
0.9999000000 00:00:01.000
|
||||
0.9999999000 00:00:01.000
|
||||
DROP TABLE t1;
|
||||
CREATE TABLE t1 (a DOUBLE);
|
||||
INSERT INTO t1 VALUES(0.9999);
|
||||
INSERT INTO t1 VALUES(0.9999999);
|
||||
SELECT a, CAST(a AS TIME(3)) FROM t1;
|
||||
a CAST(a AS TIME(3))
|
||||
0.9999 00:00:01.000
|
||||
0.9999999 00:00:01.000
|
||||
DROP TABLE t1;
|
||||
CREATE TABLE t1 (a VARCHAR(64));
|
||||
INSERT INTO t1 VALUES('00:00:00.9999999');
|
||||
SELECT a, CAST(a AS TIME(6)) FROM t1;
|
||||
a CAST(a AS TIME(6))
|
||||
00:00:00.9999999 00:00:01.000000
|
||||
Warnings:
|
||||
Note 1292 Truncated incorrect time value: '00:00:00.9999999'
|
||||
DROP TABLE t1;
|
||||
CREATE TABLE t1 (a DECIMAL(38,10));
|
||||
INSERT INTO t1 VALUES(0.9999999);
|
||||
SELECT a, CAST(a AS TIME(6)) FROM t1;
|
||||
a CAST(a AS TIME(6))
|
||||
0.9999999000 00:00:01.000000
|
||||
DROP TABLE t1;
|
||||
CREATE TABLE t1 (a DOUBLE);
|
||||
INSERT INTO t1 VALUES(0.9999999);
|
||||
SELECT a, CAST(a AS TIME(6)) FROM t1;
|
||||
a CAST(a AS TIME(6))
|
||||
0.9999999 00:00:01.000000
|
||||
DROP TABLE t1;
|
||||
#
|
||||
# NOW
|
||||
#
|
||||
SET time_zone='+00:00';
|
||||
SET timestamp=UNIX_TIMESTAMP('2010-12-31 23:59:59.999999');
|
||||
CREATE OR REPLACE TABLE t1 (id SERIAL, a TIME(4));
|
||||
INSERT INTO t1 (a) VALUES (now(6));
|
||||
Warnings:
|
||||
Note 1265 Data truncated for column 'a' at row 1
|
||||
INSERT INTO t1 (a) VALUES (CURRENT_TIMESTAMP(6));
|
||||
Warnings:
|
||||
Note 1265 Data truncated for column 'a' at row 1
|
||||
INSERT INTO t1 (a) VALUES (CURRENT_TIME(6));
|
||||
SELECT * FROM t1;
|
||||
id a
|
||||
1 24:00:00.0000
|
||||
2 24:00:00.0000
|
||||
3 24:00:00.0000
|
||||
DROP TABLE t1;
|
||||
SET timestamp=DEFAULT;
|
||||
SET time_zone=DEFAULT;
|
||||
#
|
||||
# Equal field propagation
|
||||
#
|
||||
CREATE TABLE t1 (a TIME(6));
|
||||
INSERT INTO t1 VALUES (0.999999);
|
||||
INSERT INTO t1 VALUES (0.9999999);
|
||||
SELECT * FROM t1 WHERE a=0.9999999;
|
||||
a
|
||||
00:00:01.000000
|
||||
SELECT * FROM t1 WHERE a='0.9999999';
|
||||
a
|
||||
00:00:01.000000
|
||||
Warnings:
|
||||
Note 1292 Truncated incorrect time value: '0.9999999'
|
||||
SELECT * FROM t1 WHERE a='0.9999999' AND a>='0.9999999';
|
||||
a
|
||||
00:00:01.000000
|
||||
Warnings:
|
||||
Note 1292 Truncated incorrect time value: '0.9999999'
|
||||
Note 1292 Truncated incorrect time value: '0.9999999'
|
||||
SELECT * FROM t1 WHERE a='0.9999999' AND CONCAT(a)='00:00:01.000000';
|
||||
a
|
||||
00:00:01.000000
|
||||
Warnings:
|
||||
Note 1292 Truncated incorrect time value: '0.9999999'
|
||||
EXPLAIN EXTENDED SELECT * FROM t1 WHERE a='0.9999999' AND a>='0.9999999';
|
||||
id select_type table type possible_keys key key_len ref rows filtered Extra
|
||||
1 SIMPLE t1 ALL NULL NULL NULL NULL 2 100.00 Using where
|
||||
Warnings:
|
||||
Note 1292 Truncated incorrect time value: '0.9999999'
|
||||
Note 1292 Truncated incorrect time value: '0.9999999'
|
||||
Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = TIME'00:00:01'
|
||||
EXPLAIN EXTENDED SELECT * FROM t1 WHERE a='0.9999999' AND CONCAT(a)='00:00:01.000000';
|
||||
id select_type table type possible_keys key key_len ref rows filtered Extra
|
||||
1 SIMPLE t1 ALL NULL NULL NULL NULL 2 100.00 Using where
|
||||
Warnings:
|
||||
Note 1292 Truncated incorrect time value: '0.9999999'
|
||||
Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = TIME'00:00:01'
|
||||
DROP TABLE t1;
|
||||
#
|
||||
# Comparing non-temporal to TIME
|
||||
#
|
||||
CREATE TABLE t1 (a VARCHAR(64));
|
||||
INSERT t1 VALUES ('22:59:59.9999999');
|
||||
SELECT * FROM t1 WHERE a=TIME'23:00:00';
|
||||
a
|
||||
22:59:59.9999999
|
||||
Warnings:
|
||||
Note 1292 Truncated incorrect time value: '22:59:59.9999999'
|
||||
SELECT * FROM t1 WHERE CONCAT(a)=TIME'23:00:00';
|
||||
a
|
||||
22:59:59.9999999
|
||||
Warnings:
|
||||
Note 1292 Truncated incorrect time value: '22:59:59.9999999'
|
||||
SELECT * FROM t1 WHERE COALESCE(a)=TIME'23:00:00';
|
||||
a
|
||||
22:59:59.9999999
|
||||
Warnings:
|
||||
Note 1292 Truncated incorrect time value: '22:59:59.9999999'
|
||||
DROP TABLE t1;
|
||||
CREATE TABLE t1 (a DECIMAL(32,7));
|
||||
INSERT t1 VALUES (225959.9999999);
|
||||
SELECT * FROM t1 WHERE a=TIME'23:00:00';
|
||||
a
|
||||
225959.9999999
|
||||
SELECT * FROM t1 WHERE COALESCE(a)=TIME'23:00:00';
|
||||
a
|
||||
225959.9999999
|
||||
DROP TABLE t1;
|
||||
#
|
||||
# Literal corner case
|
||||
#
|
||||
SELECT TIME'838:59:59.999999';
|
||||
TIME'838:59:59.999999'
|
||||
838:59:59.999999
|
||||
SELECT TIME'838:59:59.9999999';
|
||||
ERROR HY000: Incorrect TIME value: '838:59:59.9999999'
|
||||
SELECT TIME'839:00:00';
|
||||
ERROR HY000: Incorrect TIME value: '839:00:00'
|
184
mysql-test/main/type_time_round.test
Normal file
184
mysql-test/main/type_time_round.test
Normal file
@ -0,0 +1,184 @@
|
||||
SET sql_mode=IF(@@version LIKE '%MariaDB%', 'TIME_ROUND_FRACTIONAL', '');
|
||||
SET @default_sql_mode=@@sql_mode;
|
||||
|
||||
--echo #
|
||||
--echo # TIME: SET
|
||||
--echo #
|
||||
|
||||
CREATE TABLE t1 (a TIME(3), b TIME(4));
|
||||
INSERT INTO t1 VALUES(NULL,'00:00:00.9999');
|
||||
UPDATE t1 SET a=b;
|
||||
SELECT a FROM t1;
|
||||
DROP TABLE t1;
|
||||
|
||||
CREATE TABLE t1 (a TIME(3), b VARCHAR(64));
|
||||
INSERT INTO t1 VALUES(NULL,'00:00:00.9999');
|
||||
INSERT INTO t1 VALUES(NULL,'00:00:00.9999999');
|
||||
UPDATE t1 SET a=b;
|
||||
SELECT a FROM t1;
|
||||
DROP TABLE t1;
|
||||
|
||||
CREATE TABLE t1 (a TIME(3), b DECIMAL(38,10));
|
||||
INSERT INTO t1 VALUES(NULL,0.9999);
|
||||
INSERT INTO t1 VALUES(NULL,0.9999999);
|
||||
UPDATE t1 SET a=b;
|
||||
SELECT a FROM t1;
|
||||
DROP TABLE t1;
|
||||
|
||||
CREATE TABLE t1 (a TIME(3), b DOUBLE);
|
||||
INSERT INTO t1 VALUES(NULL,0.9999);
|
||||
INSERT INTO t1 VALUES(NULL,0.9999999);
|
||||
UPDATE t1 SET a=b;
|
||||
SELECT a FROM t1;
|
||||
DROP TABLE t1;
|
||||
|
||||
CREATE TABLE t1 (a TIME(6), b VARCHAR(64));
|
||||
INSERT INTO t1 VALUES(NULL,'00:00:00.9999999');
|
||||
UPDATE t1 SET a=b;
|
||||
SELECT a FROM t1;
|
||||
DROP TABLE t1;
|
||||
|
||||
CREATE TABLE t1 (a TIME(6), b DECIMAL(38,10));
|
||||
INSERT INTO t1 VALUES(NULL,0.9999999);
|
||||
UPDATE t1 SET a=b;
|
||||
SELECT a FROM t1;
|
||||
DROP TABLE t1;
|
||||
|
||||
CREATE TABLE t1 (a TIME(6), b DOUBLE);
|
||||
INSERT INTO t1 VALUES(NULL,0.9999999);
|
||||
UPDATE t1 SET a=b;
|
||||
SELECT a FROM t1;
|
||||
DROP TABLE t1;
|
||||
|
||||
--echo #
|
||||
--echo # TIME: ALTER
|
||||
--echo #
|
||||
|
||||
CREATE TABLE t1 (a TIME(4));
|
||||
INSERT INTO t1 VALUES('00:00:00.9999');
|
||||
ALTER TABLE t1 MODIFY a TIME(3);
|
||||
SELECT a FROM t1;
|
||||
DROP TABLE t1;
|
||||
|
||||
CREATE TABLE t1 (a VARCHAR(64));
|
||||
INSERT INTO t1 VALUES('00:00:00.9999');
|
||||
INSERT INTO t1 VALUES('00:00:00.9999999');
|
||||
ALTER TABLE t1 MODIFY a TIME(3);
|
||||
SELECT a FROM t1;
|
||||
DROP TABLE t1;
|
||||
|
||||
CREATE TABLE t1 (a DECIMAL(38,10));
|
||||
INSERT INTO t1 VALUES(0.9999);
|
||||
INSERT INTO t1 VALUES(0.9999999);
|
||||
ALTER TABLE t1 MODIFY a TIME(3);
|
||||
SELECT a FROM t1;
|
||||
DROP TABLE t1;
|
||||
|
||||
CREATE TABLE t1 (a DOUBLE);
|
||||
INSERT INTO t1 VALUES(0.9999);
|
||||
INSERT INTO t1 VALUES(0.9999999);
|
||||
ALTER TABLE t1 MODIFY a TIME(3);
|
||||
SELECT a FROM t1;
|
||||
DROP TABLE t1;
|
||||
|
||||
--echo #
|
||||
--echo # TIME: CAST
|
||||
--echo #
|
||||
|
||||
CREATE TABLE t1 (a TIME(4));
|
||||
INSERT INTO t1 VALUES('00:00:00.9999');
|
||||
SELECT a, CAST(a AS TIME(3)) FROM t1;
|
||||
DROP TABLE t1;
|
||||
|
||||
CREATE TABLE t1 (a VARCHAR(64));
|
||||
INSERT INTO t1 VALUES('00:00:00.9999');
|
||||
INSERT INTO t1 VALUES('00:00:00.9999999');
|
||||
SELECT a, CAST(a AS TIME(3)) FROM t1;
|
||||
DROP TABLE t1;
|
||||
|
||||
CREATE TABLE t1 (a DECIMAL(38,10));
|
||||
INSERT INTO t1 VALUES(0.9999);
|
||||
INSERT INTO t1 VALUES(0.9999999);
|
||||
SELECT a, CAST(a AS TIME(3)) FROM t1;
|
||||
DROP TABLE t1;
|
||||
|
||||
CREATE TABLE t1 (a DOUBLE);
|
||||
INSERT INTO t1 VALUES(0.9999);
|
||||
INSERT INTO t1 VALUES(0.9999999);
|
||||
SELECT a, CAST(a AS TIME(3)) FROM t1;
|
||||
DROP TABLE t1;
|
||||
|
||||
CREATE TABLE t1 (a VARCHAR(64));
|
||||
INSERT INTO t1 VALUES('00:00:00.9999999');
|
||||
SELECT a, CAST(a AS TIME(6)) FROM t1;
|
||||
DROP TABLE t1;
|
||||
|
||||
CREATE TABLE t1 (a DECIMAL(38,10));
|
||||
INSERT INTO t1 VALUES(0.9999999);
|
||||
SELECT a, CAST(a AS TIME(6)) FROM t1;
|
||||
DROP TABLE t1;
|
||||
|
||||
CREATE TABLE t1 (a DOUBLE);
|
||||
INSERT INTO t1 VALUES(0.9999999);
|
||||
SELECT a, CAST(a AS TIME(6)) FROM t1;
|
||||
DROP TABLE t1;
|
||||
|
||||
|
||||
--echo #
|
||||
--echo # NOW
|
||||
--echo #
|
||||
|
||||
SET time_zone='+00:00';
|
||||
SET timestamp=UNIX_TIMESTAMP('2010-12-31 23:59:59.999999');
|
||||
CREATE OR REPLACE TABLE t1 (id SERIAL, a TIME(4));
|
||||
INSERT INTO t1 (a) VALUES (now(6));
|
||||
INSERT INTO t1 (a) VALUES (CURRENT_TIMESTAMP(6));
|
||||
INSERT INTO t1 (a) VALUES (CURRENT_TIME(6));
|
||||
SELECT * FROM t1;
|
||||
DROP TABLE t1;
|
||||
SET timestamp=DEFAULT;
|
||||
SET time_zone=DEFAULT;
|
||||
|
||||
|
||||
--echo #
|
||||
--echo # Equal field propagation
|
||||
--echo #
|
||||
|
||||
CREATE TABLE t1 (a TIME(6));
|
||||
INSERT INTO t1 VALUES (0.999999);
|
||||
INSERT INTO t1 VALUES (0.9999999);
|
||||
SELECT * FROM t1 WHERE a=0.9999999;
|
||||
SELECT * FROM t1 WHERE a='0.9999999';
|
||||
SELECT * FROM t1 WHERE a='0.9999999' AND a>='0.9999999';
|
||||
SELECT * FROM t1 WHERE a='0.9999999' AND CONCAT(a)='00:00:01.000000';
|
||||
EXPLAIN EXTENDED SELECT * FROM t1 WHERE a='0.9999999' AND a>='0.9999999';
|
||||
EXPLAIN EXTENDED SELECT * FROM t1 WHERE a='0.9999999' AND CONCAT(a)='00:00:01.000000';
|
||||
DROP TABLE t1;
|
||||
|
||||
|
||||
--echo #
|
||||
--echo # Comparing non-temporal to TIME
|
||||
--echo #
|
||||
|
||||
CREATE TABLE t1 (a VARCHAR(64));
|
||||
INSERT t1 VALUES ('22:59:59.9999999');
|
||||
SELECT * FROM t1 WHERE a=TIME'23:00:00';
|
||||
SELECT * FROM t1 WHERE CONCAT(a)=TIME'23:00:00';
|
||||
SELECT * FROM t1 WHERE COALESCE(a)=TIME'23:00:00';
|
||||
DROP TABLE t1;
|
||||
|
||||
CREATE TABLE t1 (a DECIMAL(32,7));
|
||||
INSERT t1 VALUES (225959.9999999);
|
||||
SELECT * FROM t1 WHERE a=TIME'23:00:00';
|
||||
SELECT * FROM t1 WHERE COALESCE(a)=TIME'23:00:00';
|
||||
DROP TABLE t1;
|
||||
|
||||
--echo #
|
||||
--echo # Literal corner case
|
||||
--echo #
|
||||
|
||||
SELECT TIME'838:59:59.999999';
|
||||
--error ER_WRONG_VALUE
|
||||
SELECT TIME'838:59:59.9999999';
|
||||
--error ER_WRONG_VALUE
|
||||
SELECT TIME'839:00:00';
|
164
mysql-test/main/type_timestamp_round.result
Normal file
164
mysql-test/main/type_timestamp_round.result
Normal file
@ -0,0 +1,164 @@
|
||||
SET sql_mode=IF(@@version LIKE '%MariaDB%', 'TIME_ROUND_FRACTIONAL', '');
|
||||
SET @default_sql_mode=@@sql_mode;
|
||||
#
|
||||
# TIMESTAMP: SET
|
||||
#
|
||||
CREATE TABLE t1 (a TIMESTAMP(3) NULL DEFAULT NULL, b TIMESTAMP(4) NULL DEFAULT NULL);
|
||||
INSERT INTO t1 VALUES(NULL,'2000-12-31 23:59:59.9999');
|
||||
UPDATE t1 SET a=b;
|
||||
SELECT a FROM t1;
|
||||
a
|
||||
2001-01-01 00:00:00.000
|
||||
DROP TABLE t1;
|
||||
CREATE TABLE t1 (a TIMESTAMP(3) NULL DEFAULT NULL, b VARCHAR(64));
|
||||
INSERT INTO t1 VALUES(NULL,'2000-12-31 23:59:59.9999');
|
||||
INSERT INTO t1 VALUES(NULL,'2000-12-31 23:59:59.9999999');
|
||||
UPDATE t1 SET a=b;
|
||||
Warnings:
|
||||
Note 1265 Data truncated for column 'a' at row 2
|
||||
SELECT a FROM t1;
|
||||
a
|
||||
2001-01-01 00:00:00.000
|
||||
2001-01-01 00:00:00.000
|
||||
DROP TABLE t1;
|
||||
CREATE TABLE t1 (a TIMESTAMP(3) NULL DEFAULT NULL, b DECIMAL(38,10));
|
||||
INSERT INTO t1 VALUES(NULL,20001231235959.9999);
|
||||
INSERT INTO t1 VALUES(NULL,20001231235959.9999999);
|
||||
UPDATE t1 SET a=b;
|
||||
SELECT a FROM t1;
|
||||
a
|
||||
2001-01-01 00:00:00.000
|
||||
2001-01-01 00:00:00.000
|
||||
DROP TABLE t1;
|
||||
#
|
||||
# TIMESTAMP: ALTER
|
||||
#
|
||||
CREATE TABLE t1 (a TIMESTAMP(4) NULL DEFAULT NULL);
|
||||
INSERT INTO t1 VALUES('2000-12-31 23:59:59.9999');
|
||||
ALTER TABLE t1 MODIFY a TIMESTAMP(3) NULL DEFAULT NULL;
|
||||
SELECT a FROM t1;
|
||||
a
|
||||
2001-01-01 00:00:00.000
|
||||
DROP TABLE t1;
|
||||
CREATE TABLE t1 (a VARCHAR(64));
|
||||
INSERT INTO t1 VALUES('2000-12-31 23:59:59.9999');
|
||||
INSERT INTO t1 VALUES('2000-12-31 23:59:59.9999999');
|
||||
ALTER TABLE t1 MODIFY a TIMESTAMP(3) NULL DEFAULT NULL;
|
||||
Warnings:
|
||||
Note 1292 Truncated incorrect datetime value: '2000-12-31 23:59:59.9999999'
|
||||
SELECT a FROM t1;
|
||||
a
|
||||
2001-01-01 00:00:00.000
|
||||
2001-01-01 00:00:00.000
|
||||
DROP TABLE t1;
|
||||
CREATE TABLE t1 (a DECIMAL(38,10));
|
||||
INSERT INTO t1 VALUES(20001231235959.9999);
|
||||
INSERT INTO t1 VALUES(20001231235959.9999999);
|
||||
ALTER TABLE t1 MODIFY a TIMESTAMP(3) NULL DEFAULT NULL;
|
||||
SELECT a FROM t1;
|
||||
a
|
||||
2001-01-01 00:00:00.000
|
||||
2001-01-01 00:00:00.000
|
||||
DROP TABLE t1;
|
||||
#
|
||||
# Corner case:
|
||||
# ALTER TIMESTAMP to a shorter TIMESTAMP
|
||||
# All values round, maximum possible value truncates.
|
||||
#
|
||||
SET time_zone='+00:00';
|
||||
CREATE TABLE t1 (ID INT, a TIMESTAMP(6), comment VARCHAR(64));
|
||||
INSERT INTO t1 VALUES (0, '2038-01-18 23:59:59.999999', 'Should round');
|
||||
INSERT INTO t1 VALUES (1, '2038-01-19 03:14:06.999999', 'Should round');
|
||||
INSERT INTO t1 VALUES (2, '2038-01-19 03:14:07.999999', 'Should truncate');
|
||||
ALTER TABLE t1 MODIFY a TIMESTAMP(5);
|
||||
Warnings:
|
||||
Warning 1264 Out of range value for column 'a' at row 3
|
||||
SELECT * FROM t1;
|
||||
ID a comment
|
||||
0 2038-01-19 00:00:00.00000 Should round
|
||||
1 2038-01-19 03:14:07.00000 Should round
|
||||
2 2038-01-19 03:14:07.99999 Should truncate
|
||||
DROP TABLE t1;
|
||||
SET time_zone=DEFAULT;
|
||||
#
|
||||
# NOW
|
||||
#
|
||||
SET time_zone='+00:00';
|
||||
SET timestamp=UNIX_TIMESTAMP('2010-12-31 23:59:59.999999');
|
||||
CREATE OR REPLACE TABLE t1 (id SERIAL, a TIMESTAMP(4));
|
||||
INSERT INTO t1 (a) VALUES (now(6));
|
||||
INSERT INTO t1 (a) VALUES (CURRENT_TIMESTAMP(6));
|
||||
INSERT INTO t1 (a) VALUES (CURRENT_TIME(6));
|
||||
SELECT * FROM t1;
|
||||
id a
|
||||
1 2011-01-01 00:00:00.0000
|
||||
2 2011-01-01 00:00:00.0000
|
||||
3 2011-01-01 00:00:00.0000
|
||||
DROP TABLE t1;
|
||||
SET timestamp=DEFAULT;
|
||||
SET time_zone=DEFAULT;
|
||||
#
|
||||
# DATETIME to TIMESTAMP conversion with DST change
|
||||
#
|
||||
SET sql_mode=IF(@@version LIKE '%MariaDB%',
|
||||
'STRICT_ALL_TABLES,TIME_ROUND_FRACTIONAL',
|
||||
'STRICT_ALL_TABLES');
|
||||
SET time_zone='Europe/Moscow';
|
||||
CREATE TABLE t1 (a TIMESTAMP);
|
||||
INSERT INTO t1 VALUES ('2010-03-28 01:59:59.0' /* Winter time */);
|
||||
INSERT INTO t1 VALUES ('2010-03-28 01:59:59.9' /* Rounds to the DST gap */);
|
||||
ERROR 22007: Incorrect datetime value: '2010-03-28 01:59:59.9' for column 'a' at row 1
|
||||
SELECT * FROM t1;
|
||||
a
|
||||
2010-03-28 01:59:59
|
||||
DROP TABLE t1;
|
||||
SET time_zone=DEFAULT;
|
||||
SET sql_mode=@default_sql_mode;
|
||||
SET sql_mode=IF(@@version LIKE '%MariaDB%','TIME_ROUND_FRACTIONAL','');
|
||||
SET time_zone='Europe/Moscow';
|
||||
CREATE TABLE t1 (a TIMESTAMP);
|
||||
INSERT INTO t1 VALUES ('2010-03-28 01:59:59.0' /* Winter time */);
|
||||
INSERT INTO t1 VALUES ('2010-03-28 01:59:59.9' /* Rounds to the DST gap, then gets fixed to the first second of the summer time */);
|
||||
Warnings:
|
||||
Warning 1299 Invalid TIMESTAMP value in column 'a' at row 1
|
||||
SELECT a, UNIX_TIMESTAMP(a) FROM t1;
|
||||
a UNIX_TIMESTAMP(a)
|
||||
2010-03-28 01:59:59 1269730799
|
||||
2010-03-28 03:00:00 1269730800
|
||||
DROP TABLE t1;
|
||||
SET time_zone=DEFAULT;
|
||||
SET sql_mode=@default_sql_mode;
|
||||
#
|
||||
# Comparing non-temporal to TIMESTAMP
|
||||
#
|
||||
CREATE TABLE t1 (a VARCHAR(64));
|
||||
INSERT t1 VALUES ('2001-01-01 23:59:59.9999999');
|
||||
CREATE TABLE t2 (a TIMESTAMP);
|
||||
INSERT INTO t2 VALUES ('2001-01-02 00:00:00');
|
||||
SELECT * FROM t1,t2 WHERE t1.a=t2.a;
|
||||
a a
|
||||
2001-01-01 23:59:59.9999999 2001-01-02 00:00:00
|
||||
Warnings:
|
||||
Note 1292 Truncated incorrect datetime value: '2001-01-01 23:59:59.9999999'
|
||||
SELECT * FROM t1,t2 WHERE CONCAT(t1.a)=t2.a;
|
||||
a a
|
||||
2001-01-01 23:59:59.9999999 2001-01-02 00:00:00
|
||||
Warnings:
|
||||
Note 1292 Truncated incorrect datetime value: '2001-01-01 23:59:59.9999999'
|
||||
SELECT * FROM t1,t2 WHERE COALESCE(t1.a)=t2.a;
|
||||
a a
|
||||
2001-01-01 23:59:59.9999999 2001-01-02 00:00:00
|
||||
Warnings:
|
||||
Note 1292 Truncated incorrect datetime value: '2001-01-01 23:59:59.9999999'
|
||||
DROP TABLE t1,t2;
|
||||
CREATE TABLE t1 (a DECIMAL(32,7));
|
||||
INSERT t1 VALUES (20010101235959.9999999);
|
||||
CREATE TABLE t2 (a TIMESTAMP);
|
||||
INSERT INTO t2 VALUES ('2001-01-02 00:00:00');
|
||||
SELECT * FROM t1,t2 WHERE t1.a=t2.a;
|
||||
a a
|
||||
20010101235959.9999999 2001-01-02 00:00:00
|
||||
SELECT * FROM t1,t2 WHERE COALESCE(t1.a)=t2.a;
|
||||
a a
|
||||
20010101235959.9999999 2001-01-02 00:00:00
|
||||
DROP TABLE t1,t2;
|
138
mysql-test/main/type_timestamp_round.test
Normal file
138
mysql-test/main/type_timestamp_round.test
Normal file
@ -0,0 +1,138 @@
|
||||
SET sql_mode=IF(@@version LIKE '%MariaDB%', 'TIME_ROUND_FRACTIONAL', '');
|
||||
SET @default_sql_mode=@@sql_mode;
|
||||
|
||||
--echo #
|
||||
--echo # TIMESTAMP: SET
|
||||
--echo #
|
||||
|
||||
CREATE TABLE t1 (a TIMESTAMP(3) NULL DEFAULT NULL, b TIMESTAMP(4) NULL DEFAULT NULL);
|
||||
INSERT INTO t1 VALUES(NULL,'2000-12-31 23:59:59.9999');
|
||||
UPDATE t1 SET a=b;
|
||||
SELECT a FROM t1;
|
||||
DROP TABLE t1;
|
||||
|
||||
CREATE TABLE t1 (a TIMESTAMP(3) NULL DEFAULT NULL, b VARCHAR(64));
|
||||
INSERT INTO t1 VALUES(NULL,'2000-12-31 23:59:59.9999');
|
||||
INSERT INTO t1 VALUES(NULL,'2000-12-31 23:59:59.9999999');
|
||||
UPDATE t1 SET a=b;
|
||||
SELECT a FROM t1;
|
||||
DROP TABLE t1;
|
||||
|
||||
CREATE TABLE t1 (a TIMESTAMP(3) NULL DEFAULT NULL, b DECIMAL(38,10));
|
||||
INSERT INTO t1 VALUES(NULL,20001231235959.9999);
|
||||
INSERT INTO t1 VALUES(NULL,20001231235959.9999999);
|
||||
UPDATE t1 SET a=b;
|
||||
SELECT a FROM t1;
|
||||
DROP TABLE t1;
|
||||
|
||||
--echo #
|
||||
--echo # TIMESTAMP: ALTER
|
||||
--echo #
|
||||
|
||||
CREATE TABLE t1 (a TIMESTAMP(4) NULL DEFAULT NULL);
|
||||
INSERT INTO t1 VALUES('2000-12-31 23:59:59.9999');
|
||||
ALTER TABLE t1 MODIFY a TIMESTAMP(3) NULL DEFAULT NULL;
|
||||
SELECT a FROM t1;
|
||||
DROP TABLE t1;
|
||||
|
||||
CREATE TABLE t1 (a VARCHAR(64));
|
||||
INSERT INTO t1 VALUES('2000-12-31 23:59:59.9999');
|
||||
INSERT INTO t1 VALUES('2000-12-31 23:59:59.9999999');
|
||||
ALTER TABLE t1 MODIFY a TIMESTAMP(3) NULL DEFAULT NULL;
|
||||
SELECT a FROM t1;
|
||||
DROP TABLE t1;
|
||||
|
||||
CREATE TABLE t1 (a DECIMAL(38,10));
|
||||
INSERT INTO t1 VALUES(20001231235959.9999);
|
||||
INSERT INTO t1 VALUES(20001231235959.9999999);
|
||||
ALTER TABLE t1 MODIFY a TIMESTAMP(3) NULL DEFAULT NULL;
|
||||
SELECT a FROM t1;
|
||||
DROP TABLE t1;
|
||||
|
||||
|
||||
--echo #
|
||||
--echo # Corner case:
|
||||
--echo # ALTER TIMESTAMP to a shorter TIMESTAMP
|
||||
--echo # All values round, maximum possible value truncates.
|
||||
--echo #
|
||||
|
||||
SET time_zone='+00:00';
|
||||
CREATE TABLE t1 (ID INT, a TIMESTAMP(6), comment VARCHAR(64));
|
||||
INSERT INTO t1 VALUES (0, '2038-01-18 23:59:59.999999', 'Should round');
|
||||
INSERT INTO t1 VALUES (1, '2038-01-19 03:14:06.999999', 'Should round');
|
||||
INSERT INTO t1 VALUES (2, '2038-01-19 03:14:07.999999', 'Should truncate');
|
||||
ALTER TABLE t1 MODIFY a TIMESTAMP(5);
|
||||
SELECT * FROM t1;
|
||||
DROP TABLE t1;
|
||||
SET time_zone=DEFAULT;
|
||||
|
||||
--echo #
|
||||
--echo # NOW
|
||||
--echo #
|
||||
|
||||
SET time_zone='+00:00';
|
||||
SET timestamp=UNIX_TIMESTAMP('2010-12-31 23:59:59.999999');
|
||||
CREATE OR REPLACE TABLE t1 (id SERIAL, a TIMESTAMP(4));
|
||||
INSERT INTO t1 (a) VALUES (now(6));
|
||||
INSERT INTO t1 (a) VALUES (CURRENT_TIMESTAMP(6));
|
||||
INSERT INTO t1 (a) VALUES (CURRENT_TIME(6));
|
||||
SELECT * FROM t1;
|
||||
DROP TABLE t1;
|
||||
SET timestamp=DEFAULT;
|
||||
SET time_zone=DEFAULT;
|
||||
|
||||
|
||||
--echo #
|
||||
--echo # DATETIME to TIMESTAMP conversion with DST change
|
||||
--echo #
|
||||
|
||||
--disable_warnings
|
||||
SET sql_mode=IF(@@version LIKE '%MariaDB%',
|
||||
'STRICT_ALL_TABLES,TIME_ROUND_FRACTIONAL',
|
||||
'STRICT_ALL_TABLES');
|
||||
--enable_warnings
|
||||
SET time_zone='Europe/Moscow';
|
||||
CREATE TABLE t1 (a TIMESTAMP);
|
||||
INSERT INTO t1 VALUES ('2010-03-28 01:59:59.0' /* Winter time */);
|
||||
--error ER_TRUNCATED_WRONG_VALUE
|
||||
INSERT INTO t1 VALUES ('2010-03-28 01:59:59.9' /* Rounds to the DST gap */);
|
||||
SELECT * FROM t1;
|
||||
DROP TABLE t1;
|
||||
SET time_zone=DEFAULT;
|
||||
--disable_warnings
|
||||
SET sql_mode=@default_sql_mode;
|
||||
--enable_warnings
|
||||
|
||||
SET sql_mode=IF(@@version LIKE '%MariaDB%','TIME_ROUND_FRACTIONAL','');
|
||||
SET time_zone='Europe/Moscow';
|
||||
CREATE TABLE t1 (a TIMESTAMP);
|
||||
INSERT INTO t1 VALUES ('2010-03-28 01:59:59.0' /* Winter time */);
|
||||
INSERT INTO t1 VALUES ('2010-03-28 01:59:59.9' /* Rounds to the DST gap, then gets fixed to the first second of the summer time */);
|
||||
SELECT a, UNIX_TIMESTAMP(a) FROM t1;
|
||||
DROP TABLE t1;
|
||||
SET time_zone=DEFAULT;
|
||||
--disable_warnings
|
||||
SET sql_mode=@default_sql_mode;
|
||||
--enable_warnings
|
||||
|
||||
|
||||
--echo #
|
||||
--echo # Comparing non-temporal to TIMESTAMP
|
||||
--echo #
|
||||
|
||||
CREATE TABLE t1 (a VARCHAR(64));
|
||||
INSERT t1 VALUES ('2001-01-01 23:59:59.9999999');
|
||||
CREATE TABLE t2 (a TIMESTAMP);
|
||||
INSERT INTO t2 VALUES ('2001-01-02 00:00:00');
|
||||
SELECT * FROM t1,t2 WHERE t1.a=t2.a;
|
||||
SELECT * FROM t1,t2 WHERE CONCAT(t1.a)=t2.a;
|
||||
SELECT * FROM t1,t2 WHERE COALESCE(t1.a)=t2.a;
|
||||
DROP TABLE t1,t2;
|
||||
|
||||
CREATE TABLE t1 (a DECIMAL(32,7));
|
||||
INSERT t1 VALUES (20010101235959.9999999);
|
||||
CREATE TABLE t2 (a TIMESTAMP);
|
||||
INSERT INTO t2 VALUES ('2001-01-02 00:00:00');
|
||||
SELECT * FROM t1,t2 WHERE t1.a=t2.a;
|
||||
SELECT * FROM t1,t2 WHERE COALESCE(t1.a)=t2.a;
|
||||
DROP TABLE t1,t2;
|
@ -61,7 +61,7 @@ def mysql event modified 9 '0000-00-00 00:00:00' NO timestamp NULL NULL NULL NUL
|
||||
def mysql event name 2 '' NO char 64 192 NULL NULL NULL utf8 utf8_general_ci char(64) PRI select,insert,update,references NEVER NULL
|
||||
def mysql event on_completion 14 'DROP' NO enum 8 24 NULL NULL NULL utf8 utf8_general_ci enum('DROP','PRESERVE') select,insert,update,references NEVER NULL
|
||||
def mysql event originator 17 NULL NO int NULL NULL 10 0 NULL NULL NULL int(10) unsigned select,insert,update,references NEVER NULL
|
||||
def mysql event sql_mode 15 '' NO set 539 1617 NULL NULL NULL utf8 utf8_general_ci set('REAL_AS_FLOAT','PIPES_AS_CONCAT','ANSI_QUOTES','IGNORE_SPACE','IGNORE_BAD_TABLE_OPTIONS','ONLY_FULL_GROUP_BY','NO_UNSIGNED_SUBTRACTION','NO_DIR_IN_CREATE','POSTGRESQL','ORACLE','MSSQL','DB2','MAXDB','NO_KEY_OPTIONS','NO_TABLE_OPTIONS','NO_FIELD_OPTIONS','MYSQL323','MYSQL40','ANSI','NO_AUTO_VALUE_ON_ZERO','NO_BACKSLASH_ESCAPES','STRICT_TRANS_TABLES','STRICT_ALL_TABLES','NO_ZERO_IN_DATE','NO_ZERO_DATE','INVALID_DATES','ERROR_FOR_DIVISION_BY_ZERO','TRADITIONAL','NO_AUTO_CREATE_USER','HIGH_NOT_PRECEDENCE','NO_ENGINE_SUBSTITUTION','PAD_CHAR_TO_FULL_LENGTH','EMPTY_STRING_IS_NULL','SIMULTANEOUS_ASSIGNMENT') select,insert,update,references NEVER NULL
|
||||
def mysql event sql_mode 15 '' NO set 561 1683 NULL NULL NULL utf8 utf8_general_ci set('REAL_AS_FLOAT','PIPES_AS_CONCAT','ANSI_QUOTES','IGNORE_SPACE','IGNORE_BAD_TABLE_OPTIONS','ONLY_FULL_GROUP_BY','NO_UNSIGNED_SUBTRACTION','NO_DIR_IN_CREATE','POSTGRESQL','ORACLE','MSSQL','DB2','MAXDB','NO_KEY_OPTIONS','NO_TABLE_OPTIONS','NO_FIELD_OPTIONS','MYSQL323','MYSQL40','ANSI','NO_AUTO_VALUE_ON_ZERO','NO_BACKSLASH_ESCAPES','STRICT_TRANS_TABLES','STRICT_ALL_TABLES','NO_ZERO_IN_DATE','NO_ZERO_DATE','INVALID_DATES','ERROR_FOR_DIVISION_BY_ZERO','TRADITIONAL','NO_AUTO_CREATE_USER','HIGH_NOT_PRECEDENCE','NO_ENGINE_SUBSTITUTION','PAD_CHAR_TO_FULL_LENGTH','EMPTY_STRING_IS_NULL','SIMULTANEOUS_ASSIGNMENT','TIME_ROUND_FRACTIONAL') select,insert,update,references NEVER NULL
|
||||
def mysql event starts 11 NULL YES datetime NULL NULL NULL NULL 0 NULL NULL datetime select,insert,update,references NEVER NULL
|
||||
def mysql event status 13 'ENABLED' NO enum 18 54 NULL NULL NULL utf8 utf8_general_ci enum('ENABLED','DISABLED','SLAVESIDE_DISABLED') select,insert,update,references NEVER NULL
|
||||
def mysql event time_zone 18 'SYSTEM' NO char 64 64 NULL NULL NULL latin1 latin1_swedish_ci char(64) select,insert,update,references NEVER NULL
|
||||
@ -133,7 +133,7 @@ def mysql proc returns 10 NULL NO longblob 4294967295 4294967295 NULL NULL NULL
|
||||
def mysql proc security_type 8 'DEFINER' NO enum 7 21 NULL NULL NULL utf8 utf8_general_ci enum('INVOKER','DEFINER') select,insert,update,references NEVER NULL
|
||||
def mysql proc specific_name 4 '' NO char 64 192 NULL NULL NULL utf8 utf8_general_ci char(64) select,insert,update,references NEVER NULL
|
||||
def mysql proc sql_data_access 6 'CONTAINS_SQL' NO enum 17 51 NULL NULL NULL utf8 utf8_general_ci enum('CONTAINS_SQL','NO_SQL','READS_SQL_DATA','MODIFIES_SQL_DATA') select,insert,update,references NEVER NULL
|
||||
def mysql proc sql_mode 15 '' NO set 539 1617 NULL NULL NULL utf8 utf8_general_ci set('REAL_AS_FLOAT','PIPES_AS_CONCAT','ANSI_QUOTES','IGNORE_SPACE','IGNORE_BAD_TABLE_OPTIONS','ONLY_FULL_GROUP_BY','NO_UNSIGNED_SUBTRACTION','NO_DIR_IN_CREATE','POSTGRESQL','ORACLE','MSSQL','DB2','MAXDB','NO_KEY_OPTIONS','NO_TABLE_OPTIONS','NO_FIELD_OPTIONS','MYSQL323','MYSQL40','ANSI','NO_AUTO_VALUE_ON_ZERO','NO_BACKSLASH_ESCAPES','STRICT_TRANS_TABLES','STRICT_ALL_TABLES','NO_ZERO_IN_DATE','NO_ZERO_DATE','INVALID_DATES','ERROR_FOR_DIVISION_BY_ZERO','TRADITIONAL','NO_AUTO_CREATE_USER','HIGH_NOT_PRECEDENCE','NO_ENGINE_SUBSTITUTION','PAD_CHAR_TO_FULL_LENGTH','EMPTY_STRING_IS_NULL','SIMULTANEOUS_ASSIGNMENT') select,insert,update,references NEVER NULL
|
||||
def mysql proc sql_mode 15 '' NO set 561 1683 NULL NULL NULL utf8 utf8_general_ci set('REAL_AS_FLOAT','PIPES_AS_CONCAT','ANSI_QUOTES','IGNORE_SPACE','IGNORE_BAD_TABLE_OPTIONS','ONLY_FULL_GROUP_BY','NO_UNSIGNED_SUBTRACTION','NO_DIR_IN_CREATE','POSTGRESQL','ORACLE','MSSQL','DB2','MAXDB','NO_KEY_OPTIONS','NO_TABLE_OPTIONS','NO_FIELD_OPTIONS','MYSQL323','MYSQL40','ANSI','NO_AUTO_VALUE_ON_ZERO','NO_BACKSLASH_ESCAPES','STRICT_TRANS_TABLES','STRICT_ALL_TABLES','NO_ZERO_IN_DATE','NO_ZERO_DATE','INVALID_DATES','ERROR_FOR_DIVISION_BY_ZERO','TRADITIONAL','NO_AUTO_CREATE_USER','HIGH_NOT_PRECEDENCE','NO_ENGINE_SUBSTITUTION','PAD_CHAR_TO_FULL_LENGTH','EMPTY_STRING_IS_NULL','SIMULTANEOUS_ASSIGNMENT','TIME_ROUND_FRACTIONAL') select,insert,update,references NEVER NULL
|
||||
def mysql proc type 3 NULL NO enum 12 36 NULL NULL NULL utf8 utf8_general_ci enum('FUNCTION','PROCEDURE','PACKAGE','PACKAGE BODY') PRI select,insert,update,references NEVER NULL
|
||||
def mysql procs_priv Db 2 '' NO char 64 192 NULL NULL NULL utf8 utf8_bin char(64) PRI select,insert,update,references NEVER NULL
|
||||
def mysql procs_priv Grantor 6 '' NO char 141 423 NULL NULL NULL utf8 utf8_bin char(141) MUL select,insert,update,references NEVER NULL
|
||||
@ -380,7 +380,7 @@ NULL mysql event starts datetime NULL NULL NULL NULL datetime
|
||||
NULL mysql event ends datetime NULL NULL NULL NULL datetime
|
||||
3.0000 mysql event status enum 18 54 utf8 utf8_general_ci enum('ENABLED','DISABLED','SLAVESIDE_DISABLED')
|
||||
3.0000 mysql event on_completion enum 8 24 utf8 utf8_general_ci enum('DROP','PRESERVE')
|
||||
3.0000 mysql event sql_mode set 539 1617 utf8 utf8_general_ci set('REAL_AS_FLOAT','PIPES_AS_CONCAT','ANSI_QUOTES','IGNORE_SPACE','IGNORE_BAD_TABLE_OPTIONS','ONLY_FULL_GROUP_BY','NO_UNSIGNED_SUBTRACTION','NO_DIR_IN_CREATE','POSTGRESQL','ORACLE','MSSQL','DB2','MAXDB','NO_KEY_OPTIONS','NO_TABLE_OPTIONS','NO_FIELD_OPTIONS','MYSQL323','MYSQL40','ANSI','NO_AUTO_VALUE_ON_ZERO','NO_BACKSLASH_ESCAPES','STRICT_TRANS_TABLES','STRICT_ALL_TABLES','NO_ZERO_IN_DATE','NO_ZERO_DATE','INVALID_DATES','ERROR_FOR_DIVISION_BY_ZERO','TRADITIONAL','NO_AUTO_CREATE_USER','HIGH_NOT_PRECEDENCE','NO_ENGINE_SUBSTITUTION','PAD_CHAR_TO_FULL_LENGTH','EMPTY_STRING_IS_NULL','SIMULTANEOUS_ASSIGNMENT')
|
||||
3.0000 mysql event sql_mode set 561 1683 utf8 utf8_general_ci set('REAL_AS_FLOAT','PIPES_AS_CONCAT','ANSI_QUOTES','IGNORE_SPACE','IGNORE_BAD_TABLE_OPTIONS','ONLY_FULL_GROUP_BY','NO_UNSIGNED_SUBTRACTION','NO_DIR_IN_CREATE','POSTGRESQL','ORACLE','MSSQL','DB2','MAXDB','NO_KEY_OPTIONS','NO_TABLE_OPTIONS','NO_FIELD_OPTIONS','MYSQL323','MYSQL40','ANSI','NO_AUTO_VALUE_ON_ZERO','NO_BACKSLASH_ESCAPES','STRICT_TRANS_TABLES','STRICT_ALL_TABLES','NO_ZERO_IN_DATE','NO_ZERO_DATE','INVALID_DATES','ERROR_FOR_DIVISION_BY_ZERO','TRADITIONAL','NO_AUTO_CREATE_USER','HIGH_NOT_PRECEDENCE','NO_ENGINE_SUBSTITUTION','PAD_CHAR_TO_FULL_LENGTH','EMPTY_STRING_IS_NULL','SIMULTANEOUS_ASSIGNMENT','TIME_ROUND_FRACTIONAL')
|
||||
3.0000 mysql event comment char 64 192 utf8 utf8_bin char(64)
|
||||
NULL mysql event originator int NULL NULL NULL NULL int(10) unsigned
|
||||
1.0000 mysql event time_zone char 64 64 latin1 latin1_swedish_ci char(64)
|
||||
@ -451,7 +451,7 @@ NULL mysql innodb_table_stats sum_of_other_index_sizes bigint NULL NULL NULL NUL
|
||||
3.0000 mysql proc definer char 141 423 utf8 utf8_bin char(141)
|
||||
NULL mysql proc created timestamp NULL NULL NULL NULL timestamp
|
||||
NULL mysql proc modified timestamp NULL NULL NULL NULL timestamp
|
||||
3.0000 mysql proc sql_mode set 539 1617 utf8 utf8_general_ci set('REAL_AS_FLOAT','PIPES_AS_CONCAT','ANSI_QUOTES','IGNORE_SPACE','IGNORE_BAD_TABLE_OPTIONS','ONLY_FULL_GROUP_BY','NO_UNSIGNED_SUBTRACTION','NO_DIR_IN_CREATE','POSTGRESQL','ORACLE','MSSQL','DB2','MAXDB','NO_KEY_OPTIONS','NO_TABLE_OPTIONS','NO_FIELD_OPTIONS','MYSQL323','MYSQL40','ANSI','NO_AUTO_VALUE_ON_ZERO','NO_BACKSLASH_ESCAPES','STRICT_TRANS_TABLES','STRICT_ALL_TABLES','NO_ZERO_IN_DATE','NO_ZERO_DATE','INVALID_DATES','ERROR_FOR_DIVISION_BY_ZERO','TRADITIONAL','NO_AUTO_CREATE_USER','HIGH_NOT_PRECEDENCE','NO_ENGINE_SUBSTITUTION','PAD_CHAR_TO_FULL_LENGTH','EMPTY_STRING_IS_NULL','SIMULTANEOUS_ASSIGNMENT')
|
||||
3.0000 mysql proc sql_mode set 561 1683 utf8 utf8_general_ci set('REAL_AS_FLOAT','PIPES_AS_CONCAT','ANSI_QUOTES','IGNORE_SPACE','IGNORE_BAD_TABLE_OPTIONS','ONLY_FULL_GROUP_BY','NO_UNSIGNED_SUBTRACTION','NO_DIR_IN_CREATE','POSTGRESQL','ORACLE','MSSQL','DB2','MAXDB','NO_KEY_OPTIONS','NO_TABLE_OPTIONS','NO_FIELD_OPTIONS','MYSQL323','MYSQL40','ANSI','NO_AUTO_VALUE_ON_ZERO','NO_BACKSLASH_ESCAPES','STRICT_TRANS_TABLES','STRICT_ALL_TABLES','NO_ZERO_IN_DATE','NO_ZERO_DATE','INVALID_DATES','ERROR_FOR_DIVISION_BY_ZERO','TRADITIONAL','NO_AUTO_CREATE_USER','HIGH_NOT_PRECEDENCE','NO_ENGINE_SUBSTITUTION','PAD_CHAR_TO_FULL_LENGTH','EMPTY_STRING_IS_NULL','SIMULTANEOUS_ASSIGNMENT','TIME_ROUND_FRACTIONAL')
|
||||
1.0000 mysql proc comment text 65535 65535 utf8 utf8_bin text
|
||||
3.0000 mysql proc character_set_client char 32 96 utf8 utf8_bin char(32)
|
||||
3.0000 mysql proc collation_connection char 32 96 utf8 utf8_bin char(32)
|
||||
|
50
mysql-test/suite/rpl/r/rpl_temporal_round.result
Normal file
50
mysql-test/suite/rpl/r/rpl_temporal_round.result
Normal file
@ -0,0 +1,50 @@
|
||||
include/master-slave.inc
|
||||
[connection master]
|
||||
SET sql_mode=TIME_ROUND_FRACTIONAL;
|
||||
SET time_zone='+00:00';
|
||||
SET timestamp=UNIX_TIMESTAMP('2010-12-31 23:59:59.999999');
|
||||
CREATE TABLE t1 (id SERIAL, a TIMESTAMP(4));
|
||||
INSERT INTO t1 (a) VALUES (now(6));
|
||||
INSERT INTO t1 (a) VALUES ('2011-01-01 23:59:59.999999');
|
||||
CREATE TABLE t2 (id SERIAL, a DATETIME(4));
|
||||
INSERT INTO t2 (a) VALUES (now(6));
|
||||
INSERT INTO t2 (a) VALUES ('2011-01-01 23:59:59.999999');
|
||||
CREATE TABLE t3 (id SERIAL, a TIME(4));
|
||||
INSERT INTO t3 (a) VALUES (now(6));
|
||||
Warnings:
|
||||
Note 1265 Data truncated for column 'a' at row 1
|
||||
INSERT INTO t3 (a) VALUES ('2011-01-01 23:59:59.999999');
|
||||
Warnings:
|
||||
Note 1265 Data truncated for column 'a' at row 1
|
||||
SELECT * FROM t1;
|
||||
id a
|
||||
1 2011-01-01 00:00:00.0000
|
||||
2 2011-01-02 00:00:00.0000
|
||||
SELECT * FROM t2;
|
||||
id a
|
||||
1 2011-01-01 00:00:00.0000
|
||||
2 2011-01-02 00:00:00.0000
|
||||
SELECT * FROM t3;
|
||||
id a
|
||||
1 24:00:00.0000
|
||||
2 24:00:00.0000
|
||||
connection slave;
|
||||
connection slave;
|
||||
SET time_zone='+00:00';
|
||||
SELECT * FROM t1;
|
||||
id a
|
||||
1 2011-01-01 00:00:00.0000
|
||||
2 2011-01-02 00:00:00.0000
|
||||
SELECT * FROM t2;
|
||||
id a
|
||||
1 2011-01-01 00:00:00.0000
|
||||
2 2011-01-02 00:00:00.0000
|
||||
SELECT * FROM t3;
|
||||
id a
|
||||
1 24:00:00.0000
|
||||
2 24:00:00.0000
|
||||
connection master;
|
||||
DROP TABLE t1;
|
||||
DROP TABLE t2;
|
||||
DROP TABLE t3;
|
||||
include/rpl_end.inc
|
35
mysql-test/suite/rpl/t/rpl_temporal_round.test
Normal file
35
mysql-test/suite/rpl/t/rpl_temporal_round.test
Normal file
@ -0,0 +1,35 @@
|
||||
--source include/master-slave.inc
|
||||
|
||||
SET sql_mode=TIME_ROUND_FRACTIONAL;
|
||||
SET time_zone='+00:00';
|
||||
SET timestamp=UNIX_TIMESTAMP('2010-12-31 23:59:59.999999');
|
||||
|
||||
CREATE TABLE t1 (id SERIAL, a TIMESTAMP(4));
|
||||
INSERT INTO t1 (a) VALUES (now(6));
|
||||
INSERT INTO t1 (a) VALUES ('2011-01-01 23:59:59.999999');
|
||||
|
||||
CREATE TABLE t2 (id SERIAL, a DATETIME(4));
|
||||
INSERT INTO t2 (a) VALUES (now(6));
|
||||
INSERT INTO t2 (a) VALUES ('2011-01-01 23:59:59.999999');
|
||||
|
||||
CREATE TABLE t3 (id SERIAL, a TIME(4));
|
||||
INSERT INTO t3 (a) VALUES (now(6));
|
||||
INSERT INTO t3 (a) VALUES ('2011-01-01 23:59:59.999999');
|
||||
|
||||
SELECT * FROM t1;
|
||||
SELECT * FROM t2;
|
||||
SELECT * FROM t3;
|
||||
|
||||
sync_slave_with_master;
|
||||
connection slave;
|
||||
SET time_zone='+00:00';
|
||||
SELECT * FROM t1;
|
||||
SELECT * FROM t2;
|
||||
SELECT * FROM t3;
|
||||
|
||||
connection master;
|
||||
DROP TABLE t1;
|
||||
DROP TABLE t2;
|
||||
DROP TABLE t3;
|
||||
|
||||
--source include/rpl_end.inc
|
@ -367,7 +367,15 @@ SELECT @@global.sql_mode;
|
||||
@@global.sql_mode
|
||||
REAL_AS_FLOAT,PIPES_AS_CONCAT,ANSI_QUOTES,IGNORE_SPACE,IGNORE_BAD_TABLE_OPTIONS,ONLY_FULL_GROUP_BY,NO_UNSIGNED_SUBTRACTION,NO_DIR_IN_CREATE,POSTGRESQL,ORACLE,MSSQL,DB2,MAXDB,NO_KEY_OPTIONS,NO_TABLE_OPTIONS,NO_FIELD_OPTIONS,MYSQL323,MYSQL40,ANSI,NO_AUTO_VALUE_ON_ZERO,NO_BACKSLASH_ESCAPES,STRICT_TRANS_TABLES,STRICT_ALL_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ALLOW_INVALID_DATES,ERROR_FOR_DIVISION_BY_ZERO,TRADITIONAL,NO_AUTO_CREATE_USER,HIGH_NOT_PRECEDENCE,NO_ENGINE_SUBSTITUTION,PAD_CHAR_TO_FULL_LENGTH,EMPTY_STRING_IS_NULL,SIMULTANEOUS_ASSIGNMENT
|
||||
SET @@global.sql_mode = 17179869184;
|
||||
ERROR 42000: Variable 'sql_mode' can't be set to the value of '17179869184'
|
||||
SELECT @@global.sql_mode;
|
||||
@@global.sql_mode
|
||||
TIME_ROUND_FRACTIONAL
|
||||
SET @@global.sql_mode = 34359738367;
|
||||
SELECT @@global.sql_mode;
|
||||
@@global.sql_mode
|
||||
REAL_AS_FLOAT,PIPES_AS_CONCAT,ANSI_QUOTES,IGNORE_SPACE,IGNORE_BAD_TABLE_OPTIONS,ONLY_FULL_GROUP_BY,NO_UNSIGNED_SUBTRACTION,NO_DIR_IN_CREATE,POSTGRESQL,ORACLE,MSSQL,DB2,MAXDB,NO_KEY_OPTIONS,NO_TABLE_OPTIONS,NO_FIELD_OPTIONS,MYSQL323,MYSQL40,ANSI,NO_AUTO_VALUE_ON_ZERO,NO_BACKSLASH_ESCAPES,STRICT_TRANS_TABLES,STRICT_ALL_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ALLOW_INVALID_DATES,ERROR_FOR_DIVISION_BY_ZERO,TRADITIONAL,NO_AUTO_CREATE_USER,HIGH_NOT_PRECEDENCE,NO_ENGINE_SUBSTITUTION,PAD_CHAR_TO_FULL_LENGTH,EMPTY_STRING_IS_NULL,SIMULTANEOUS_ASSIGNMENT,TIME_ROUND_FRACTIONAL
|
||||
SET @@global.sql_mode = 34359738368;
|
||||
ERROR 42000: Variable 'sql_mode' can't be set to the value of '34359738368'
|
||||
SET @@global.sql_mode = 0.4;
|
||||
ERROR 42000: Incorrect argument type to variable 'sql_mode'
|
||||
'#---------------------FN_DYNVARS_152_08----------------------#'
|
||||
|
@ -4755,7 +4755,7 @@ VARIABLE_COMMENT Sets the sql mode
|
||||
NUMERIC_MIN_VALUE NULL
|
||||
NUMERIC_MAX_VALUE NULL
|
||||
NUMERIC_BLOCK_SIZE NULL
|
||||
ENUM_VALUE_LIST REAL_AS_FLOAT,PIPES_AS_CONCAT,ANSI_QUOTES,IGNORE_SPACE,IGNORE_BAD_TABLE_OPTIONS,ONLY_FULL_GROUP_BY,NO_UNSIGNED_SUBTRACTION,NO_DIR_IN_CREATE,POSTGRESQL,ORACLE,MSSQL,DB2,MAXDB,NO_KEY_OPTIONS,NO_TABLE_OPTIONS,NO_FIELD_OPTIONS,MYSQL323,MYSQL40,ANSI,NO_AUTO_VALUE_ON_ZERO,NO_BACKSLASH_ESCAPES,STRICT_TRANS_TABLES,STRICT_ALL_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ALLOW_INVALID_DATES,ERROR_FOR_DIVISION_BY_ZERO,TRADITIONAL,NO_AUTO_CREATE_USER,HIGH_NOT_PRECEDENCE,NO_ENGINE_SUBSTITUTION,PAD_CHAR_TO_FULL_LENGTH,EMPTY_STRING_IS_NULL,SIMULTANEOUS_ASSIGNMENT
|
||||
ENUM_VALUE_LIST REAL_AS_FLOAT,PIPES_AS_CONCAT,ANSI_QUOTES,IGNORE_SPACE,IGNORE_BAD_TABLE_OPTIONS,ONLY_FULL_GROUP_BY,NO_UNSIGNED_SUBTRACTION,NO_DIR_IN_CREATE,POSTGRESQL,ORACLE,MSSQL,DB2,MAXDB,NO_KEY_OPTIONS,NO_TABLE_OPTIONS,NO_FIELD_OPTIONS,MYSQL323,MYSQL40,ANSI,NO_AUTO_VALUE_ON_ZERO,NO_BACKSLASH_ESCAPES,STRICT_TRANS_TABLES,STRICT_ALL_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ALLOW_INVALID_DATES,ERROR_FOR_DIVISION_BY_ZERO,TRADITIONAL,NO_AUTO_CREATE_USER,HIGH_NOT_PRECEDENCE,NO_ENGINE_SUBSTITUTION,PAD_CHAR_TO_FULL_LENGTH,EMPTY_STRING_IS_NULL,SIMULTANEOUS_ASSIGNMENT,TIME_ROUND_FRACTIONAL
|
||||
READ_ONLY NO
|
||||
COMMAND_LINE_ARGUMENT REQUIRED
|
||||
VARIABLE_NAME SQL_NOTES
|
||||
|
@ -310,8 +310,14 @@ SELECT @@global.sql_mode;
|
||||
SET @@global.sql_mode = 17179869183;
|
||||
SELECT @@global.sql_mode;
|
||||
|
||||
--Error ER_WRONG_VALUE_FOR_VAR
|
||||
SET @@global.sql_mode = 17179869184;
|
||||
SELECT @@global.sql_mode;
|
||||
|
||||
SET @@global.sql_mode = 34359738367;
|
||||
SELECT @@global.sql_mode;
|
||||
|
||||
--Error ER_WRONG_VALUE_FOR_VAR
|
||||
SET @@global.sql_mode = 34359738368;
|
||||
|
||||
# use of decimal values
|
||||
|
||||
|
@ -130,3 +130,14 @@ show status like "Feature_system_versioning";
|
||||
Variable_name Value
|
||||
Feature_system_versioning 2
|
||||
drop table t;
|
||||
#
|
||||
# MDEV-16991 Rounding vs truncation for TIME, DATETIME, TIMESTAMP
|
||||
#
|
||||
SET sql_mode=TIME_ROUND_FRACTIONAL;
|
||||
SET @@global.system_versioning_asof= timestamp'2001-12-31 23:59:59.9999999';
|
||||
Warnings:
|
||||
Note 1292 Truncated incorrect datetime value: '2001-12-31 23:59:59.9999999'
|
||||
SELECT @@global.system_versioning_asof;
|
||||
@@global.system_versioning_asof
|
||||
2002-01-01 00:00:00.000000
|
||||
SET @@global.system_versioning_asof= DEFAULT;
|
||||
|
@ -87,3 +87,13 @@ select * from t for system_time between '0-0-0' and current_timestamp(6);
|
||||
show status like "Feature_system_versioning";
|
||||
|
||||
drop table t;
|
||||
|
||||
|
||||
--echo #
|
||||
--echo # MDEV-16991 Rounding vs truncation for TIME, DATETIME, TIMESTAMP
|
||||
--echo #
|
||||
|
||||
SET sql_mode=TIME_ROUND_FRACTIONAL;
|
||||
SET @@global.system_versioning_asof= timestamp'2001-12-31 23:59:59.9999999';
|
||||
SELECT @@global.system_versioning_asof;
|
||||
SET @@global.system_versioning_asof= DEFAULT;
|
||||
|
@ -80,7 +80,7 @@ CREATE TABLE IF NOT EXISTS time_zone_transition_type ( Time_zone_id int unsign
|
||||
|
||||
CREATE TABLE IF NOT EXISTS time_zone_leap_second ( Transition_time bigint signed NOT NULL, Correction int signed NOT NULL, PRIMARY KEY TranTime (Transition_time) ) engine=Aria transactional=1 CHARACTER SET utf8 comment='Leap seconds information for time zones';
|
||||
|
||||
CREATE TABLE IF NOT EXISTS proc (db char(64) collate utf8_bin DEFAULT '' NOT NULL, name char(64) DEFAULT '' NOT NULL, type enum('FUNCTION','PROCEDURE','PACKAGE','PACKAGE BODY') NOT NULL, specific_name char(64) DEFAULT '' NOT NULL, language enum('SQL') DEFAULT 'SQL' NOT NULL, sql_data_access enum( 'CONTAINS_SQL', 'NO_SQL', 'READS_SQL_DATA', 'MODIFIES_SQL_DATA') DEFAULT 'CONTAINS_SQL' NOT NULL, is_deterministic enum('YES','NO') DEFAULT 'NO' NOT NULL, security_type enum('INVOKER','DEFINER') DEFAULT 'DEFINER' NOT NULL, param_list blob NOT NULL, returns longblob NOT NULL, body longblob NOT NULL, definer char(141) collate utf8_bin DEFAULT '' NOT NULL, created timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, modified timestamp NOT NULL DEFAULT '0000-00-00 00:00:00', sql_mode set( 'REAL_AS_FLOAT', 'PIPES_AS_CONCAT', 'ANSI_QUOTES', 'IGNORE_SPACE', 'IGNORE_BAD_TABLE_OPTIONS', 'ONLY_FULL_GROUP_BY', 'NO_UNSIGNED_SUBTRACTION', 'NO_DIR_IN_CREATE', 'POSTGRESQL', 'ORACLE', 'MSSQL', 'DB2', 'MAXDB', 'NO_KEY_OPTIONS', 'NO_TABLE_OPTIONS', 'NO_FIELD_OPTIONS', 'MYSQL323', 'MYSQL40', 'ANSI', 'NO_AUTO_VALUE_ON_ZERO', 'NO_BACKSLASH_ESCAPES', 'STRICT_TRANS_TABLES', 'STRICT_ALL_TABLES', 'NO_ZERO_IN_DATE', 'NO_ZERO_DATE', 'INVALID_DATES', 'ERROR_FOR_DIVISION_BY_ZERO', 'TRADITIONAL', 'NO_AUTO_CREATE_USER', 'HIGH_NOT_PRECEDENCE', 'NO_ENGINE_SUBSTITUTION', 'PAD_CHAR_TO_FULL_LENGTH', 'EMPTY_STRING_IS_NULL', 'SIMULTANEOUS_ASSIGNMENT') DEFAULT '' NOT NULL, comment text collate utf8_bin NOT NULL, character_set_client char(32) collate utf8_bin, collation_connection char(32) collate utf8_bin, db_collation char(32) collate utf8_bin, body_utf8 longblob, aggregate enum('NONE', 'GROUP') DEFAULT 'NONE' NOT NULL, PRIMARY KEY (db,name,type)) engine=Aria transactional=1 character set utf8 comment='Stored Procedures';
|
||||
CREATE TABLE IF NOT EXISTS proc (db char(64) collate utf8_bin DEFAULT '' NOT NULL, name char(64) DEFAULT '' NOT NULL, type enum('FUNCTION','PROCEDURE','PACKAGE','PACKAGE BODY') NOT NULL, specific_name char(64) DEFAULT '' NOT NULL, language enum('SQL') DEFAULT 'SQL' NOT NULL, sql_data_access enum( 'CONTAINS_SQL', 'NO_SQL', 'READS_SQL_DATA', 'MODIFIES_SQL_DATA') DEFAULT 'CONTAINS_SQL' NOT NULL, is_deterministic enum('YES','NO') DEFAULT 'NO' NOT NULL, security_type enum('INVOKER','DEFINER') DEFAULT 'DEFINER' NOT NULL, param_list blob NOT NULL, returns longblob NOT NULL, body longblob NOT NULL, definer char(141) collate utf8_bin DEFAULT '' NOT NULL, created timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, modified timestamp NOT NULL DEFAULT '0000-00-00 00:00:00', sql_mode set( 'REAL_AS_FLOAT', 'PIPES_AS_CONCAT', 'ANSI_QUOTES', 'IGNORE_SPACE', 'IGNORE_BAD_TABLE_OPTIONS', 'ONLY_FULL_GROUP_BY', 'NO_UNSIGNED_SUBTRACTION', 'NO_DIR_IN_CREATE', 'POSTGRESQL', 'ORACLE', 'MSSQL', 'DB2', 'MAXDB', 'NO_KEY_OPTIONS', 'NO_TABLE_OPTIONS', 'NO_FIELD_OPTIONS', 'MYSQL323', 'MYSQL40', 'ANSI', 'NO_AUTO_VALUE_ON_ZERO', 'NO_BACKSLASH_ESCAPES', 'STRICT_TRANS_TABLES', 'STRICT_ALL_TABLES', 'NO_ZERO_IN_DATE', 'NO_ZERO_DATE', 'INVALID_DATES', 'ERROR_FOR_DIVISION_BY_ZERO', 'TRADITIONAL', 'NO_AUTO_CREATE_USER', 'HIGH_NOT_PRECEDENCE', 'NO_ENGINE_SUBSTITUTION', 'PAD_CHAR_TO_FULL_LENGTH', 'EMPTY_STRING_IS_NULL', 'SIMULTANEOUS_ASSIGNMENT', 'TIME_ROUND_FRACTIONAL') DEFAULT '' NOT NULL, comment text collate utf8_bin NOT NULL, character_set_client char(32) collate utf8_bin, collation_connection char(32) collate utf8_bin, db_collation char(32) collate utf8_bin, body_utf8 longblob, aggregate enum('NONE', 'GROUP') DEFAULT 'NONE' NOT NULL, PRIMARY KEY (db,name,type)) engine=Aria transactional=1 character set utf8 comment='Stored Procedures';
|
||||
|
||||
CREATE TABLE IF NOT EXISTS procs_priv ( Host char(60) binary DEFAULT '' NOT NULL, Db char(64) binary DEFAULT '' NOT NULL, User char(80) binary DEFAULT '' NOT NULL, Routine_name char(64) COLLATE utf8_general_ci DEFAULT '' NOT NULL, Routine_type enum('FUNCTION','PROCEDURE','PACKAGE','PACKAGE BODY') NOT NULL, Grantor char(141) DEFAULT '' NOT NULL, Proc_priv set('Execute','Alter Routine','Grant') COLLATE utf8_general_ci DEFAULT '' NOT NULL, Timestamp timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, PRIMARY KEY (Host,Db,User,Routine_name,Routine_type), KEY Grantor (Grantor) ) engine=Aria transactional=1 CHARACTER SET utf8 COLLATE utf8_bin comment='Procedure privileges';
|
||||
|
||||
@ -101,7 +101,7 @@ PREPARE stmt FROM @str;
|
||||
EXECUTE stmt;
|
||||
DROP PREPARE stmt;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS event ( db char(64) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL default '', name char(64) CHARACTER SET utf8 NOT NULL default '', body longblob NOT NULL, definer char(141) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL default '', execute_at DATETIME default NULL, interval_value int(11) default NULL, interval_field ENUM('YEAR','QUARTER','MONTH','DAY','HOUR','MINUTE','WEEK','SECOND','MICROSECOND','YEAR_MONTH','DAY_HOUR','DAY_MINUTE','DAY_SECOND','HOUR_MINUTE','HOUR_SECOND','MINUTE_SECOND','DAY_MICROSECOND','HOUR_MICROSECOND','MINUTE_MICROSECOND','SECOND_MICROSECOND') default NULL, created TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, modified TIMESTAMP NOT NULL DEFAULT '0000-00-00 00:00:00', last_executed DATETIME default NULL, starts DATETIME default NULL, ends DATETIME default NULL, status ENUM('ENABLED','DISABLED','SLAVESIDE_DISABLED') NOT NULL default 'ENABLED', on_completion ENUM('DROP','PRESERVE') NOT NULL default 'DROP', sql_mode set('REAL_AS_FLOAT','PIPES_AS_CONCAT','ANSI_QUOTES','IGNORE_SPACE','IGNORE_BAD_TABLE_OPTIONS','ONLY_FULL_GROUP_BY','NO_UNSIGNED_SUBTRACTION','NO_DIR_IN_CREATE','POSTGRESQL','ORACLE','MSSQL','DB2','MAXDB','NO_KEY_OPTIONS','NO_TABLE_OPTIONS','NO_FIELD_OPTIONS','MYSQL323','MYSQL40','ANSI','NO_AUTO_VALUE_ON_ZERO','NO_BACKSLASH_ESCAPES','STRICT_TRANS_TABLES','STRICT_ALL_TABLES','NO_ZERO_IN_DATE','NO_ZERO_DATE','INVALID_DATES','ERROR_FOR_DIVISION_BY_ZERO','TRADITIONAL','NO_AUTO_CREATE_USER','HIGH_NOT_PRECEDENCE','NO_ENGINE_SUBSTITUTION','PAD_CHAR_TO_FULL_LENGTH','EMPTY_STRING_IS_NULL','SIMULTANEOUS_ASSIGNMENT') DEFAULT '' NOT NULL, comment char(64) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL default '', originator INTEGER UNSIGNED NOT NULL, time_zone char(64) CHARACTER SET latin1 NOT NULL DEFAULT 'SYSTEM', character_set_client char(32) collate utf8_bin, collation_connection char(32) collate utf8_bin, db_collation char(32) collate utf8_bin, body_utf8 longblob, PRIMARY KEY (db, name) ) engine=Aria transactional=1 DEFAULT CHARSET=utf8 COMMENT 'Events';
|
||||
CREATE TABLE IF NOT EXISTS event ( db char(64) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL default '', name char(64) CHARACTER SET utf8 NOT NULL default '', body longblob NOT NULL, definer char(141) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL default '', execute_at DATETIME default NULL, interval_value int(11) default NULL, interval_field ENUM('YEAR','QUARTER','MONTH','DAY','HOUR','MINUTE','WEEK','SECOND','MICROSECOND','YEAR_MONTH','DAY_HOUR','DAY_MINUTE','DAY_SECOND','HOUR_MINUTE','HOUR_SECOND','MINUTE_SECOND','DAY_MICROSECOND','HOUR_MICROSECOND','MINUTE_MICROSECOND','SECOND_MICROSECOND') default NULL, created TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, modified TIMESTAMP NOT NULL DEFAULT '0000-00-00 00:00:00', last_executed DATETIME default NULL, starts DATETIME default NULL, ends DATETIME default NULL, status ENUM('ENABLED','DISABLED','SLAVESIDE_DISABLED') NOT NULL default 'ENABLED', on_completion ENUM('DROP','PRESERVE') NOT NULL default 'DROP', sql_mode set('REAL_AS_FLOAT','PIPES_AS_CONCAT','ANSI_QUOTES','IGNORE_SPACE','IGNORE_BAD_TABLE_OPTIONS','ONLY_FULL_GROUP_BY','NO_UNSIGNED_SUBTRACTION','NO_DIR_IN_CREATE','POSTGRESQL','ORACLE','MSSQL','DB2','MAXDB','NO_KEY_OPTIONS','NO_TABLE_OPTIONS','NO_FIELD_OPTIONS','MYSQL323','MYSQL40','ANSI','NO_AUTO_VALUE_ON_ZERO','NO_BACKSLASH_ESCAPES','STRICT_TRANS_TABLES','STRICT_ALL_TABLES','NO_ZERO_IN_DATE','NO_ZERO_DATE','INVALID_DATES','ERROR_FOR_DIVISION_BY_ZERO','TRADITIONAL','NO_AUTO_CREATE_USER','HIGH_NOT_PRECEDENCE','NO_ENGINE_SUBSTITUTION','PAD_CHAR_TO_FULL_LENGTH','EMPTY_STRING_IS_NULL','SIMULTANEOUS_ASSIGNMENT','TIME_ROUND_FRACTIONAL') DEFAULT '' NOT NULL, comment char(64) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL default '', originator INTEGER UNSIGNED NOT NULL, time_zone char(64) CHARACTER SET latin1 NOT NULL DEFAULT 'SYSTEM', character_set_client char(32) collate utf8_bin, collation_connection char(32) collate utf8_bin, db_collation char(32) collate utf8_bin, body_utf8 longblob, PRIMARY KEY (db, name) ) engine=Aria transactional=1 DEFAULT CHARSET=utf8 COMMENT 'Events';
|
||||
|
||||
SET @create_innodb_table_stats="CREATE TABLE IF NOT EXISTS innodb_table_stats (
|
||||
database_name VARCHAR(64) NOT NULL,
|
||||
|
@ -417,7 +417,8 @@ ALTER TABLE proc MODIFY name char(64) DEFAULT '' NOT NULL,
|
||||
'NO_ENGINE_SUBSTITUTION',
|
||||
'PAD_CHAR_TO_FULL_LENGTH',
|
||||
'EMPTY_STRING_IS_NULL',
|
||||
'SIMULTANEOUS_ASSIGNMENT'
|
||||
'SIMULTANEOUS_ASSIGNMENT',
|
||||
'TIME_ROUND_FRACTIONAL'
|
||||
) DEFAULT '' NOT NULL,
|
||||
DEFAULT CHARACTER SET utf8;
|
||||
|
||||
@ -553,7 +554,8 @@ ALTER TABLE event MODIFY sql_mode
|
||||
'NO_ENGINE_SUBSTITUTION',
|
||||
'PAD_CHAR_TO_FULL_LENGTH',
|
||||
'EMPTY_STRING_IS_NULL',
|
||||
'SIMULTANEOUS_ASSIGNMENT'
|
||||
'SIMULTANEOUS_ASSIGNMENT',
|
||||
'TIME_ROUND_FRACTIONAL'
|
||||
) DEFAULT '' NOT NULL AFTER on_completion;
|
||||
ALTER TABLE event MODIFY name char(64) CHARACTER SET utf8 NOT NULL default '';
|
||||
|
||||
|
@ -256,6 +256,14 @@ static void get_microseconds(ulong *val, MYSQL_TIME_STATUS *status,
|
||||
*val= (ulong) (tmp * log_10_int[6 - (*str - start)]);
|
||||
else
|
||||
*val= tmp;
|
||||
if (str[0] < end && my_isdigit(&my_charset_latin1, str[0][0]))
|
||||
{
|
||||
/*
|
||||
We don't need the exact nanoseconds value.
|
||||
Knowing the first digit is enough for rounding.
|
||||
*/
|
||||
status->nanoseconds= 100 * (uint)(str[0][0] - '0');
|
||||
}
|
||||
if (skip_digits(str, end))
|
||||
status->warnings|= MYSQL_TIME_NOTE_TRUNCATED;
|
||||
}
|
||||
|
@ -479,14 +479,24 @@ Event_queue_element::load_from_row(THD *thd, TABLE *table)
|
||||
uint not_used;
|
||||
if (!starts_null)
|
||||
{
|
||||
table->field[ET_FIELD_STARTS]->get_date(&time, TIME_NO_ZERO_DATE);
|
||||
/*
|
||||
The expected data type for these columns in mysql.events:
|
||||
starts, ends, execute_at, last_executed
|
||||
is DATETIME. No nanosecond truncation should normally be needed,
|
||||
unless the DBA changes them, e.g. to VARCHAR, DECIMAL, etc.
|
||||
For this unexpected case let's use the default round mode,
|
||||
according to the current session settings.
|
||||
*/
|
||||
table->field[ET_FIELD_STARTS]->get_date(&time, TIME_NO_ZERO_DATE |
|
||||
thd->temporal_round_mode());
|
||||
starts= my_tz_OFFSET0->TIME_to_gmt_sec(&time,¬_used);
|
||||
}
|
||||
|
||||
ends_null= table->field[ET_FIELD_ENDS]->is_null();
|
||||
if (!ends_null)
|
||||
{
|
||||
table->field[ET_FIELD_ENDS]->get_date(&time, TIME_NO_ZERO_DATE);
|
||||
table->field[ET_FIELD_ENDS]->get_date(&time, TIME_NO_ZERO_DATE |
|
||||
thd->temporal_round_mode());
|
||||
ends= my_tz_OFFSET0->TIME_to_gmt_sec(&time,¬_used);
|
||||
}
|
||||
|
||||
@ -502,8 +512,8 @@ Event_queue_element::load_from_row(THD *thd, TABLE *table)
|
||||
DBUG_ASSERT(!(starts_null && ends_null && !expression && execute_at_null));
|
||||
if (!expression && !execute_at_null)
|
||||
{
|
||||
if (table->field[ET_FIELD_EXECUTE_AT]->get_date(&time,
|
||||
TIME_NO_ZERO_DATE))
|
||||
if (table->field[ET_FIELD_EXECUTE_AT]->get_date(&time, TIME_NO_ZERO_DATE |
|
||||
thd->temporal_round_mode()))
|
||||
DBUG_RETURN(TRUE);
|
||||
execute_at= my_tz_OFFSET0->TIME_to_gmt_sec(&time,¬_used);
|
||||
}
|
||||
@ -535,8 +545,8 @@ Event_queue_element::load_from_row(THD *thd, TABLE *table)
|
||||
|
||||
if (!table->field[ET_FIELD_LAST_EXECUTED]->is_null())
|
||||
{
|
||||
table->field[ET_FIELD_LAST_EXECUTED]->get_date(&time,
|
||||
TIME_NO_ZERO_DATE);
|
||||
table->field[ET_FIELD_LAST_EXECUTED]->get_date(&time, TIME_NO_ZERO_DATE |
|
||||
thd->temporal_round_mode());
|
||||
last_executed= my_tz_OFFSET0->TIME_to_gmt_sec(&time,¬_used);
|
||||
}
|
||||
|
||||
|
@ -216,7 +216,13 @@ Event_parse_data::init_execute_at(THD *thd)
|
||||
(starts_null && ends_null)));
|
||||
DBUG_ASSERT(starts_null && ends_null);
|
||||
|
||||
if (item_execute_at->get_date(thd, <ime, TIME_NO_ZERO_DATE))
|
||||
/*
|
||||
The expected data type is DATETIME. No nanoseconds truncation should
|
||||
normally be needed. Using the default rounding mode.
|
||||
See more comments in event_data_object.cc.
|
||||
*/
|
||||
if (item_execute_at->get_date(thd, <ime, TIME_NO_ZERO_DATE |
|
||||
thd->temporal_round_mode()))
|
||||
goto wrong_value;
|
||||
|
||||
ltime_utc= TIME_to_timestamp(thd,<ime,¬_used);
|
||||
@ -378,7 +384,8 @@ Event_parse_data::init_starts(THD *thd)
|
||||
if (item_starts->fix_fields(thd, &item_starts))
|
||||
goto wrong_value;
|
||||
|
||||
if (item_starts->get_date(thd, <ime, TIME_NO_ZERO_DATE))
|
||||
if (item_starts->get_date(thd, <ime, TIME_NO_ZERO_DATE |
|
||||
thd->temporal_round_mode()))
|
||||
goto wrong_value;
|
||||
|
||||
ltime_utc= TIME_to_timestamp(thd, <ime, ¬_used);
|
||||
@ -433,7 +440,8 @@ Event_parse_data::init_ends(THD *thd)
|
||||
goto error_bad_params;
|
||||
|
||||
DBUG_PRINT("info", ("convert to TIME"));
|
||||
if (item_ends->get_date(thd, <ime, TIME_NO_ZERO_DATE))
|
||||
if (item_ends->get_date(thd, <ime, TIME_NO_ZERO_DATE |
|
||||
thd->temporal_round_mode()))
|
||||
goto error_bad_params;
|
||||
|
||||
ltime_utc= TIME_to_timestamp(thd, <ime, ¬_used);
|
||||
|
149
sql/field.cc
149
sql/field.cc
@ -5084,10 +5084,11 @@ int Field_timestamp::store_TIME_with_warning(THD *thd, const Datetime *dt,
|
||||
}
|
||||
|
||||
|
||||
date_mode_t Field_timestamp::sql_mode_for_timestamp(THD *thd) const
|
||||
date_conv_mode_t Timestamp::sql_mode_for_timestamp(THD *thd)
|
||||
{
|
||||
// We don't want to store invalid or fuzzy datetime values in TIMESTAMP
|
||||
return date_mode_t((thd->variables.sql_mode & MODE_NO_ZERO_DATE) | MODE_NO_ZERO_IN_DATE);
|
||||
return date_conv_mode_t((thd->variables.sql_mode & MODE_NO_ZERO_DATE) |
|
||||
MODE_NO_ZERO_IN_DATE);
|
||||
}
|
||||
|
||||
|
||||
@ -5096,7 +5097,7 @@ int Field_timestamp::store_time_dec(const MYSQL_TIME *ltime, uint dec)
|
||||
int warn;
|
||||
ErrConvTime str(ltime);
|
||||
THD *thd= get_thd();
|
||||
Datetime dt(thd, &warn, ltime, sql_mode_for_timestamp(thd), decimals());
|
||||
Datetime dt(thd, &warn, ltime, Timestamp::DatetimeOptions(thd), decimals());
|
||||
return store_TIME_with_warning(thd, &dt, &str, warn);
|
||||
}
|
||||
|
||||
@ -5106,7 +5107,7 @@ int Field_timestamp::store(const char *from,size_t len,CHARSET_INFO *cs)
|
||||
ErrConvString str(from, len, cs);
|
||||
THD *thd= get_thd();
|
||||
MYSQL_TIME_STATUS st;
|
||||
Datetime dt(&st, from, len, cs, sql_mode_for_timestamp(thd), decimals());
|
||||
Datetime dt(thd, &st, from, len, cs, Timestamp::DatetimeOptions(thd), decimals());
|
||||
return store_TIME_with_warning(thd, &dt, &str, st.warnings);
|
||||
}
|
||||
|
||||
@ -5116,7 +5117,7 @@ int Field_timestamp::store(double nr)
|
||||
int error;
|
||||
ErrConvDouble str(nr);
|
||||
THD *thd= get_thd();
|
||||
Datetime dt(&error, nr, sql_mode_for_timestamp(thd), decimals());
|
||||
Datetime dt(thd, &error, nr, Timestamp::DatetimeOptions(thd), decimals());
|
||||
return store_TIME_with_warning(thd, &dt, &str, error);
|
||||
}
|
||||
|
||||
@ -5127,14 +5128,29 @@ int Field_timestamp::store(longlong nr, bool unsigned_val)
|
||||
Longlong_hybrid tmp(nr, unsigned_val);
|
||||
ErrConvInteger str(tmp);
|
||||
THD *thd= get_thd();
|
||||
Datetime dt(&error, tmp, sql_mode_for_timestamp(thd));
|
||||
Datetime dt(thd, &error, tmp, Timestamp::DatetimeOptions(thd));
|
||||
return store_TIME_with_warning(thd, &dt, &str, error);
|
||||
}
|
||||
|
||||
|
||||
int Field_timestamp::store_timestamp(my_time_t ts, ulong sec_part)
|
||||
{
|
||||
store_TIMESTAMP(Timestamp(ts, sec_part).trunc(decimals()));
|
||||
int warn= 0;
|
||||
time_round_mode_t mode= Datetime::default_round_mode(get_thd());
|
||||
store_TIMESTAMP(Timestamp(ts, sec_part).round(decimals(), mode, &warn));
|
||||
if (warn)
|
||||
{
|
||||
/*
|
||||
We're here if rounding would overflow outside of the supported TIMESTAMP
|
||||
range, so truncation happened instead:
|
||||
CREATE TABLE t1 (a TIMESTAMP(6));
|
||||
INSERT INTO t1 VALUES ('maximum-possible-timestamp.999999');
|
||||
ALTER TABLE t1 MODIFY a TIMESTAMP(5);
|
||||
SELECT * FROM t1; --> 'maximum-possible-timestamp.99999' (5 digits)
|
||||
Raise a warning, like DATETIME does for '9999-12-31 23:59:59.999999'.
|
||||
*/
|
||||
set_warning(Sql_condition::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
|
||||
}
|
||||
if (ts == 0 && sec_part == 0 &&
|
||||
get_thd()->variables.sql_mode & (ulonglong) TIME_NO_ZERO_DATE)
|
||||
{
|
||||
@ -5157,7 +5173,7 @@ double Field_timestamp::val_real(void)
|
||||
longlong Field_timestamp::val_int(void)
|
||||
{
|
||||
MYSQL_TIME ltime;
|
||||
if (get_date(<ime, TIME_NO_ZERO_DATE))
|
||||
if (get_date(<ime, Datetime::Options(TIME_NO_ZERO_DATE, get_thd())))
|
||||
return 0;
|
||||
|
||||
return ltime.year * 10000000000LL + ltime.month * 100000000LL +
|
||||
@ -5177,7 +5193,7 @@ String *Field_timestamp::val_str(String *val_buffer, String *val_ptr)
|
||||
to= (char*) val_buffer->ptr();
|
||||
val_buffer->length(field_length);
|
||||
|
||||
if (get_date(<ime, TIME_NO_ZERO_DATE))
|
||||
if (get_date(<ime, Datetime::Options(TIME_NO_ZERO_DATE, get_thd())))
|
||||
{ /* Zero time is "000000" */
|
||||
val_ptr->set(zero_timestamp, field_length, &my_charset_numeric);
|
||||
return val_ptr;
|
||||
@ -5407,7 +5423,7 @@ my_time_t Field_timestamp_hires::get_timestamp(const uchar *pos,
|
||||
double Field_timestamp_with_dec::val_real(void)
|
||||
{
|
||||
MYSQL_TIME ltime;
|
||||
if (get_date(<ime, TIME_NO_ZERO_DATE))
|
||||
if (get_date(<ime, Datetime::Options(TIME_NO_ZERO_DATE, get_thd())))
|
||||
return 0;
|
||||
|
||||
return ltime.year * 1e10 + ltime.month * 1e8 +
|
||||
@ -5427,7 +5443,7 @@ int Field_timestamp::store_decimal(const my_decimal *d)
|
||||
int error;
|
||||
THD *thd= get_thd();
|
||||
ErrConvDecimal str(d);
|
||||
Datetime dt(&error, d, sql_mode_for_timestamp(thd), decimals());
|
||||
Datetime dt(thd, &error, d, Timestamp::DatetimeOptions(thd), decimals());
|
||||
return store_TIME_with_warning(thd, &dt, &str, error);
|
||||
}
|
||||
|
||||
@ -5570,7 +5586,8 @@ int Field_datetime::store(const char *from, size_t len, CHARSET_INFO *cs)
|
||||
{
|
||||
MYSQL_TIME_STATUS st;
|
||||
ErrConvString str(from, len, cs);
|
||||
Datetime dt(&st, from, len, cs, sql_mode_for_dates(get_thd()), decimals());
|
||||
THD *thd= get_thd();
|
||||
Datetime dt(thd, &st, from, len, cs, Datetime::Options(thd), decimals());
|
||||
return store_TIME_with_warning(&dt, &str, st.warnings);
|
||||
}
|
||||
|
||||
@ -5578,7 +5595,8 @@ int Field_datetime::store(double nr)
|
||||
{
|
||||
int error;
|
||||
ErrConvDouble str(nr);
|
||||
Datetime dt(&error, nr, sql_mode_for_dates(get_thd()), decimals());
|
||||
THD *thd= get_thd();
|
||||
Datetime dt(thd, &error, nr, Datetime::Options(thd), decimals());
|
||||
return store_TIME_with_warning(&dt, &str, error);
|
||||
}
|
||||
|
||||
@ -5588,7 +5606,8 @@ int Field_datetime::store(longlong nr, bool unsigned_val)
|
||||
int error;
|
||||
Longlong_hybrid tmp(nr, unsigned_val);
|
||||
ErrConvInteger str(tmp);
|
||||
Datetime dt(&error, tmp, sql_mode_for_dates(get_thd()));
|
||||
THD *thd= get_thd();
|
||||
Datetime dt(thd, &error, tmp, Datetime::Options(thd));
|
||||
return store_TIME_with_warning(&dt, &str, error);
|
||||
}
|
||||
|
||||
@ -5597,7 +5616,7 @@ int Field_datetime::store_time_dec(const MYSQL_TIME *ltime, uint dec)
|
||||
int error;
|
||||
ErrConvTime str(ltime);
|
||||
THD *thd= get_thd();
|
||||
Datetime dt(thd, &error, ltime, sql_mode_for_dates(thd), decimals());
|
||||
Datetime dt(thd, &error, ltime, Datetime::Options(thd), decimals());
|
||||
return store_TIME_with_warning(&dt, &str, error);
|
||||
}
|
||||
|
||||
@ -5606,7 +5625,8 @@ int Field_datetime::store_decimal(const my_decimal *d)
|
||||
{
|
||||
int error;
|
||||
ErrConvDecimal str(d);
|
||||
Datetime tm(&error, d, sql_mode_for_dates(get_thd()), decimals());
|
||||
THD *thd= get_thd();
|
||||
Datetime tm(thd, &error, d, Datetime::Options(thd), decimals());
|
||||
return store_TIME_with_warning(&tm, &str, error);
|
||||
}
|
||||
|
||||
@ -5617,7 +5637,7 @@ Field_temporal_with_date::validate_value_in_record(THD *thd,
|
||||
{
|
||||
DBUG_ASSERT(!is_null_in_record(record));
|
||||
MYSQL_TIME ltime;
|
||||
return get_TIME(<ime, ptr_in_record(record), sql_mode_for_dates(thd));
|
||||
return get_TIME(<ime, ptr_in_record(record), Datetime::Options(thd));
|
||||
}
|
||||
|
||||
|
||||
@ -5657,7 +5677,8 @@ Item *Field_temporal::get_equal_const_item_datetime(THD *thd,
|
||||
const_item->field_type() != MYSQL_TYPE_TIMESTAMP) ||
|
||||
const_item->decimals != decimals())
|
||||
{
|
||||
Datetime dt(thd, const_item, date_mode_t(0));
|
||||
Datetime::Options opt(TIME_CONV_NONE, thd);
|
||||
Datetime dt(thd, const_item, opt, decimals());
|
||||
if (!dt.is_valid_datetime())
|
||||
return NULL;
|
||||
/*
|
||||
@ -5672,7 +5693,7 @@ Item *Field_temporal::get_equal_const_item_datetime(THD *thd,
|
||||
case ANY_SUBST:
|
||||
if (!is_temporal_type_with_date(const_item->field_type()))
|
||||
{
|
||||
Datetime dt(thd, const_item, Datetime::comparison_flags_for_get_date());
|
||||
Datetime dt(thd, const_item, Datetime::Options_cmp(thd));
|
||||
if (!dt.is_valid_datetime())
|
||||
return NULL;
|
||||
return new (thd->mem_root)
|
||||
@ -5724,7 +5745,17 @@ int Field_time::store(const char *from,size_t len,CHARSET_INFO *cs)
|
||||
ErrConvString str(from, len, cs);
|
||||
MYSQL_TIME_STATUS st;
|
||||
THD *thd= get_thd();
|
||||
Time tm(thd, &st, from, len, cs, sql_mode_for_dates(thd), decimals());
|
||||
/*
|
||||
Unlike number-to-time conversion, we need to additionally pass
|
||||
MODE_NO_ZERO_DATE here (if it presents in the current sql_mode):
|
||||
SET sql_mode='STRICT_ALL_TABLES,NO_ZERO_DATE';
|
||||
INSERT INTO t1 VALUES ('0000-00-00 00:00:00'); -- error
|
||||
INSERT INTO t1 VALUES (0); -- ok
|
||||
In the first INSERT we have a zero date.
|
||||
In the second INSERT we don't have a zero date (it is just a zero time).
|
||||
*/
|
||||
Time::Options opt(sql_mode_for_dates(thd), thd);
|
||||
Time tm(thd, &st, from, len, cs, opt, decimals());
|
||||
return store_TIME_with_warning(&tm, &str, st.warnings);
|
||||
}
|
||||
|
||||
@ -5733,7 +5764,7 @@ int Field_time::store_time_dec(const MYSQL_TIME *ltime, uint dec)
|
||||
{
|
||||
ErrConvTime str(ltime);
|
||||
int warn;
|
||||
Time tm(&warn, ltime, curdays, decimals());
|
||||
Time tm(&warn, ltime, curdays, Time::Options(get_thd()), decimals());
|
||||
return store_TIME_with_warning(&tm, &str, warn);
|
||||
}
|
||||
|
||||
@ -5742,7 +5773,7 @@ int Field_time::store(double nr)
|
||||
{
|
||||
ErrConvDouble str(nr);
|
||||
int was_cut;
|
||||
Time tm(get_thd(), &was_cut, nr, Time::Options(), decimals());
|
||||
Time tm(get_thd(), &was_cut, nr, Time::Options(get_thd()), decimals());
|
||||
return store_TIME_with_warning(&tm, &str, was_cut);
|
||||
}
|
||||
|
||||
@ -5752,8 +5783,14 @@ int Field_time::store(longlong nr, bool unsigned_val)
|
||||
Longlong_hybrid tmp(nr, unsigned_val);
|
||||
ErrConvInteger str(tmp);
|
||||
int was_cut;
|
||||
// Need fractional digit truncation if nr overflows to '838:59:59.999999'
|
||||
Time tm(get_thd(), &was_cut, tmp, Time::Options(), decimals());
|
||||
THD *thd= get_thd();
|
||||
/*
|
||||
Need fractional digit truncation if nr overflows to '838:59:59.999999'.
|
||||
The constructor used below will always truncate (never round).
|
||||
We don't need to care to overwrite the default session rounding mode
|
||||
from HALF_UP to TRUNCATE.
|
||||
*/
|
||||
Time tm(thd, &was_cut, tmp, Time::Options(thd), decimals());
|
||||
return store_TIME_with_warning(&tm, &str, was_cut);
|
||||
}
|
||||
|
||||
@ -5805,7 +5842,7 @@ String *Field_time::val_str(String *str,
|
||||
{
|
||||
ASSERT_COLUMN_MARKED_FOR_READ;
|
||||
MYSQL_TIME ltime;
|
||||
get_date(<ime, TIME_TIME_ONLY);
|
||||
get_date(<ime, Datetime::Options(TIME_TIME_ONLY, get_thd()));
|
||||
str->alloc(field_length + 1);
|
||||
str->length(my_time_to_str(<ime, const_cast<char*>(str->ptr()), decimals()));
|
||||
str->set_charset(&my_charset_numeric);
|
||||
@ -5815,7 +5852,8 @@ String *Field_time::val_str(String *str,
|
||||
|
||||
bool Field_time::check_zero_in_date_with_warn(date_mode_t fuzzydate)
|
||||
{
|
||||
if (!(fuzzydate & TIME_TIME_ONLY) && (fuzzydate & TIME_NO_ZERO_IN_DATE))
|
||||
date_conv_mode_t tmp= date_conv_mode_t(fuzzydate);
|
||||
if (!(tmp & TIME_TIME_ONLY) && (tmp & TIME_NO_ZERO_IN_DATE))
|
||||
{
|
||||
THD *thd= get_thd();
|
||||
push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN,
|
||||
@ -5860,7 +5898,7 @@ bool Field_time::get_date(MYSQL_TIME *ltime, date_mode_t fuzzydate)
|
||||
bool Field_time::send_binary(Protocol *protocol)
|
||||
{
|
||||
MYSQL_TIME ltime;
|
||||
get_date(<ime, TIME_TIME_ONLY);
|
||||
get_date(<ime, Time::Options(TIME_TIME_ONLY, get_thd()));
|
||||
return protocol->store_time(<ime, decimals());
|
||||
}
|
||||
|
||||
@ -5911,7 +5949,7 @@ int Field_time::store_decimal(const my_decimal *d)
|
||||
{
|
||||
ErrConvDecimal str(d);
|
||||
int was_cut;
|
||||
Time tm(get_thd(), &was_cut, d, Time::Options(), decimals());
|
||||
Time tm(get_thd(), &was_cut, d, Time::Options(get_thd()), decimals());
|
||||
return store_TIME_with_warning(&tm, &str, was_cut);
|
||||
}
|
||||
|
||||
@ -5971,8 +6009,7 @@ Item *Field_time::get_equal_const_item(THD *thd, const Context &ctx,
|
||||
if (const_item->field_type() != MYSQL_TYPE_TIME)
|
||||
{
|
||||
// Get the value of const_item with conversion from DATETIME to TIME
|
||||
Time tm(get_thd(), const_item,
|
||||
Time::Options(Time::comparison_flags_for_get_date(), mode));
|
||||
Time tm(get_thd(), const_item, Time::Options_cmp(thd, mode));
|
||||
if (!tm.is_valid_time())
|
||||
return NULL;
|
||||
/*
|
||||
@ -5996,10 +6033,6 @@ Item *Field_time::get_equal_const_item(THD *thd, const Context &ctx,
|
||||
if (const_item->field_type() != MYSQL_TYPE_TIME ||
|
||||
const_item->decimals != decimals())
|
||||
{
|
||||
Time tm(get_thd(), const_item,
|
||||
Time::Options(TIME_TIME_ONLY, mode));
|
||||
if (!tm.is_valid_time())
|
||||
return NULL;
|
||||
/*
|
||||
Note, the value returned in "ltime" can have more fractional
|
||||
digits that decimals(). The Item_time_literal constructor will
|
||||
@ -6014,6 +6047,10 @@ Item *Field_time::get_equal_const_item(THD *thd, const Context &ctx,
|
||||
The optimized WHERE will return with "Impossible WHERE", without
|
||||
having to do the full table scan.
|
||||
*/
|
||||
Time tm(thd, const_item, Time::Options(TIME_TIME_ONLY, thd, mode),
|
||||
decimals());
|
||||
if (!tm.is_valid_time())
|
||||
return NULL;
|
||||
return new (thd->mem_root) Item_time_literal(thd, tm.get_mysql_time(),
|
||||
decimals());
|
||||
}
|
||||
@ -6027,7 +6064,7 @@ longlong Field_time_with_dec::val_int(void)
|
||||
{
|
||||
ASSERT_COLUMN_MARKED_FOR_READ;
|
||||
MYSQL_TIME ltime;
|
||||
get_date(<ime, TIME_TIME_ONLY);
|
||||
get_date(<ime, Time::Options(TIME_TIME_ONLY, get_thd()));
|
||||
longlong val= TIME_to_ulonglong_time(<ime);
|
||||
return ltime.neg ? -val : val;
|
||||
}
|
||||
@ -6036,7 +6073,7 @@ double Field_time_with_dec::val_real(void)
|
||||
{
|
||||
ASSERT_COLUMN_MARKED_FOR_READ;
|
||||
MYSQL_TIME ltime;
|
||||
get_date(<ime, TIME_TIME_ONLY);
|
||||
get_date(<ime, Time::Options(TIME_TIME_ONLY, get_thd()));
|
||||
return TIME_to_double(<ime);
|
||||
}
|
||||
|
||||
@ -6268,7 +6305,8 @@ int Field_date_common::store(const char *from, size_t len, CHARSET_INFO *cs)
|
||||
{
|
||||
MYSQL_TIME_STATUS st;
|
||||
ErrConvString str(from, len, cs);
|
||||
Datetime dt(&st, from, len, cs, sql_mode_for_dates(get_thd()));
|
||||
THD *thd= get_thd();
|
||||
Datetime dt(thd, &st, from, len, cs, Date::Options(thd), 0);
|
||||
return store_TIME_with_warning(&dt, &str, st.warnings);
|
||||
}
|
||||
|
||||
@ -6276,7 +6314,8 @@ int Field_date_common::store(double nr)
|
||||
{
|
||||
int error;
|
||||
ErrConvDouble str(nr);
|
||||
Datetime dt(&error, nr, sql_mode_for_dates(get_thd()));
|
||||
THD *thd= get_thd();
|
||||
Datetime dt(thd, &error, nr, Date::Options(thd), 0);
|
||||
return store_TIME_with_warning(&dt, &str, error);
|
||||
}
|
||||
|
||||
@ -6285,7 +6324,8 @@ int Field_date_common::store(longlong nr, bool unsigned_val)
|
||||
int error;
|
||||
Longlong_hybrid tmp(nr, unsigned_val);
|
||||
ErrConvInteger str(tmp);
|
||||
Datetime dt(&error, tmp, sql_mode_for_dates(get_thd()));
|
||||
THD *thd= get_thd();
|
||||
Datetime dt(thd, &error, tmp, Date::Options(thd));
|
||||
return store_TIME_with_warning(&dt, &str, error);
|
||||
}
|
||||
|
||||
@ -6294,7 +6334,7 @@ int Field_date_common::store_time_dec(const MYSQL_TIME *ltime, uint dec)
|
||||
int error;
|
||||
ErrConvTime str(ltime);
|
||||
THD *thd= get_thd();
|
||||
Datetime dt(thd, &error, ltime, sql_mode_for_dates(thd));
|
||||
Datetime dt(thd, &error, ltime, Date::Options(thd), 0);
|
||||
return store_TIME_with_warning(&dt, &str, error);
|
||||
}
|
||||
|
||||
@ -6302,7 +6342,8 @@ int Field_date_common::store_decimal(const my_decimal *d)
|
||||
{
|
||||
int error;
|
||||
ErrConvDecimal str(d);
|
||||
Datetime tm(&error, d, sql_mode_for_dates(get_thd()));
|
||||
THD *thd= get_thd();
|
||||
Datetime tm(thd, &error, d, Date::Options(thd), 0);
|
||||
return store_TIME_with_warning(&tm, &str, error);
|
||||
}
|
||||
|
||||
@ -6512,8 +6553,14 @@ Item *Field_newdate::get_equal_const_item(THD *thd, const Context &ctx,
|
||||
case ANY_SUBST:
|
||||
if (!is_temporal_type_with_date(const_item->field_type()))
|
||||
{
|
||||
// Get the value of const_item with conversion from TIME to DATETIME
|
||||
Datetime dt(thd, const_item, Datetime::comparison_flags_for_get_date());
|
||||
/*
|
||||
DATE is compared to DATETIME-alike non-temporal values
|
||||
(such as VARCHAR, DECIMAL) as DATETIME, e.g.:
|
||||
WHERE date_column=20010101235959.0000009
|
||||
So here we convert the constant to DATETIME normally.
|
||||
In case if TIME_ROUND_FRACTIONAL is enabled, nanoseconds will round.
|
||||
*/
|
||||
Datetime dt(thd, const_item, Datetime::Options_cmp(thd));
|
||||
if (!dt.is_valid_datetime())
|
||||
return NULL;
|
||||
/*
|
||||
@ -6540,10 +6587,17 @@ Item *Field_newdate::get_equal_const_item(THD *thd, const Context &ctx,
|
||||
case IDENTITY_SUBST:
|
||||
if (const_item->field_type() != MYSQL_TYPE_DATE)
|
||||
{
|
||||
Date d(thd, const_item, date_mode_t(0));
|
||||
if (!d.is_valid_date())
|
||||
/*
|
||||
DATE is compared to non-temporal as DATETIME.
|
||||
We need to convert to DATETIME first, taking into account the
|
||||
current session rounding mode (even though this is IDENTITY_SUBSTS!),
|
||||
then convert the result to DATE.
|
||||
*/
|
||||
Datetime dt(thd, const_item, Datetime::Options(TIME_CONV_NONE, thd));
|
||||
if (!dt.is_valid_datetime())
|
||||
return NULL;
|
||||
return new (thd->mem_root) Item_date_literal(thd, d.get_mysql_time());
|
||||
return new (thd->mem_root)
|
||||
Item_date_literal(thd, Date(&dt).get_mysql_time());
|
||||
}
|
||||
break;
|
||||
}
|
||||
@ -6693,7 +6747,8 @@ int Field_datetime::set_time()
|
||||
{
|
||||
THD *thd= table->in_use;
|
||||
set_notnull();
|
||||
store_datetime(Datetime(thd, thd->query_start_timeval(), decimals()));
|
||||
// Here we always truncate (not round), no matter what sql_mode is
|
||||
store_datetime(Datetime(thd, thd->query_start_timeval()).trunc(decimals()));
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
16
sql/field.h
16
sql/field.h
@ -1346,7 +1346,6 @@ public:
|
||||
void copy_from_tmp(int offset);
|
||||
uint fill_cache_field(struct st_cache_field *copy);
|
||||
virtual bool get_date(MYSQL_TIME *ltime, date_mode_t fuzzydate);
|
||||
bool get_time(MYSQL_TIME *ltime) { return get_date(ltime, TIME_TIME_ONLY); }
|
||||
virtual TYPELIB *get_typelib() const { return NULL; }
|
||||
virtual CHARSET_INFO *charset(void) const { return &my_charset_bin; }
|
||||
virtual CHARSET_INFO *charset_for_protocol(void) const
|
||||
@ -2643,7 +2642,8 @@ public:
|
||||
int save_in_field(Field *to)
|
||||
{
|
||||
MYSQL_TIME ltime;
|
||||
if (get_date(<ime, date_mode_t(0)))
|
||||
// For temporal types no truncation needed. Rounding mode is not important.
|
||||
if (get_date(<ime, TIME_CONV_NONE | TIME_FRAC_NONE))
|
||||
return to->reset();
|
||||
return to->store_time_dec(<ime, decimals());
|
||||
}
|
||||
@ -2721,7 +2721,6 @@ public:
|
||||
|
||||
class Field_timestamp :public Field_temporal {
|
||||
protected:
|
||||
date_mode_t sql_mode_for_timestamp(THD *thd) const;
|
||||
int store_TIME_with_warning(THD *, const Datetime *,
|
||||
const ErrConv *, int warn);
|
||||
virtual void store_TIMEVAL(const timeval &tv)
|
||||
@ -2771,10 +2770,15 @@ public:
|
||||
{
|
||||
return get_timestamp(ptr, sec_part);
|
||||
}
|
||||
// This is used by storage/perfschema
|
||||
void store_TIME(my_time_t timestamp, ulong sec_part)
|
||||
/*
|
||||
This method is used by storage/perfschema and
|
||||
Item_func_now_local::save_in_field().
|
||||
*/
|
||||
void store_TIME(my_time_t ts, ulong sec_part)
|
||||
{
|
||||
store_TIMESTAMP(Timestamp(timestamp, sec_part).trunc(decimals()));
|
||||
int warn;
|
||||
time_round_mode_t mode= Datetime::default_round_mode(get_thd());
|
||||
store_TIMESTAMP(Timestamp(ts, sec_part).round(decimals(), mode, &warn));
|
||||
}
|
||||
bool get_date(MYSQL_TIME *ltime, date_mode_t fuzzydate);
|
||||
uchar *pack(uchar *to, const uchar *from,
|
||||
|
@ -438,19 +438,19 @@ void Field::do_field_temporal(Copy_field *copy, date_mode_t fuzzydate)
|
||||
|
||||
void Field::do_field_datetime(Copy_field *copy)
|
||||
{
|
||||
return do_field_temporal(copy, date_mode_t(0));
|
||||
return do_field_temporal(copy, Datetime::Options(TIME_CONV_NONE, current_thd));
|
||||
}
|
||||
|
||||
|
||||
void Field::do_field_date(Copy_field *copy)
|
||||
{
|
||||
return do_field_temporal(copy, date_mode_t(0));
|
||||
return do_field_temporal(copy, Date::Options(TIME_CONV_NONE));
|
||||
}
|
||||
|
||||
|
||||
void Field_time::do_field_time(Copy_field *copy)
|
||||
{
|
||||
return do_field_temporal(copy, TIME_TIME_ONLY);
|
||||
return do_field_temporal(copy, Time::Options(current_thd));
|
||||
}
|
||||
|
||||
|
||||
|
@ -1051,7 +1051,10 @@ Type_handler_temporal_result::make_sort_key(uchar *to, Item *item,
|
||||
Sort_param *param) const
|
||||
{
|
||||
MYSQL_TIME buf;
|
||||
if (item->get_date_result(current_thd, &buf, TIME_INVALID_DATES))
|
||||
// This is a temporal type. No nanoseconds. Rounding mode is not important.
|
||||
DBUG_ASSERT(item->cmp_type() == TIME_RESULT);
|
||||
static const Temporal::Options opt(TIME_INVALID_DATES, TIME_FRAC_NONE);
|
||||
if (item->get_date_result(current_thd, &buf, opt))
|
||||
{
|
||||
DBUG_ASSERT(item->maybe_null);
|
||||
DBUG_ASSERT(item->null_value);
|
||||
|
11
sql/item.cc
11
sql/item.cc
@ -118,12 +118,12 @@ void Item::push_note_converted_to_positive_complement(THD *thd)
|
||||
longlong Item::val_datetime_packed_result(THD *thd)
|
||||
{
|
||||
MYSQL_TIME ltime, tmp;
|
||||
if (get_date_result(thd, <ime, Datetime::comparison_flags_for_get_date()))
|
||||
if (get_date_result(thd, <ime, Datetime::Options_cmp(thd)))
|
||||
return 0;
|
||||
if (ltime.time_type != MYSQL_TIMESTAMP_TIME)
|
||||
return pack_time(<ime);
|
||||
if ((null_value= time_to_datetime_with_warn(thd, <ime,
|
||||
&tmp, date_mode_t(0))))
|
||||
if ((null_value= time_to_datetime_with_warn(thd, <ime, &tmp,
|
||||
TIME_CONV_NONE)))
|
||||
return 0;
|
||||
return pack_time(&tmp);
|
||||
}
|
||||
@ -305,7 +305,7 @@ int Item::save_date_in_field(Field *field, bool no_conversions)
|
||||
{
|
||||
MYSQL_TIME ltime;
|
||||
THD *thd= field->table->in_use;
|
||||
if (get_date(thd, <ime, sql_mode_for_dates(thd)))
|
||||
if (get_date(thd, <ime, Datetime::Options(thd)))
|
||||
return set_field_to_null_with_conversions(field, no_conversions);
|
||||
field->set_notnull();
|
||||
return field->store_time_dec(<ime, decimals);
|
||||
@ -9732,7 +9732,8 @@ bool Item_cache_temporal::get_date(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzz
|
||||
int Item_cache_temporal::save_in_field(Field *field, bool no_conversions)
|
||||
{
|
||||
MYSQL_TIME ltime;
|
||||
if (get_date(field->get_thd(), <ime, date_mode_t(0)))
|
||||
// This is a temporal type. No nanoseconds, so round mode is not important.
|
||||
if (get_date(field->get_thd(), <ime, TIME_CONV_NONE | TIME_FRAC_NONE))
|
||||
return set_field_to_null_with_conversions(field, no_conversions);
|
||||
field->set_notnull();
|
||||
int error= field->store_time_dec(<ime, decimals);
|
||||
|
20
sql/item.h
20
sql/item.h
@ -1636,28 +1636,28 @@ public:
|
||||
bool get_date_from_real(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate);
|
||||
bool get_date_from_string(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate);
|
||||
bool get_time(THD *thd, MYSQL_TIME *ltime)
|
||||
{ return get_date(thd, ltime, Time::flags_for_get_date()); }
|
||||
{ return get_date(thd, ltime, Time::Options(thd)); }
|
||||
// Get a DATE or DATETIME value in numeric packed format for comparison
|
||||
virtual longlong val_datetime_packed(THD *thd)
|
||||
{
|
||||
date_mode_t fuzzydate= Datetime::comparison_flags_for_get_date();
|
||||
return Datetime(current_thd, this, fuzzydate).to_packed();
|
||||
return Datetime(thd, this, Datetime::Options_cmp(thd)).to_packed();
|
||||
}
|
||||
// Get a TIME value in numeric packed format for comparison
|
||||
virtual longlong val_time_packed(THD *thd)
|
||||
{
|
||||
return Time(thd, this, Time::comparison_flags_for_get_date()).to_packed();
|
||||
return Time(thd, this, Time::Options_cmp(thd)).to_packed();
|
||||
}
|
||||
longlong val_datetime_packed_result(THD *thd);
|
||||
longlong val_time_packed_result(THD *thd)
|
||||
{
|
||||
MYSQL_TIME ltime;
|
||||
date_mode_t fuzzydate= Time::comparison_flags_for_get_date();
|
||||
return get_date_result(thd, <ime, fuzzydate) ? 0 : pack_time(<ime);
|
||||
return get_date_result(thd, <ime, Time::Options_cmp(thd)) ? 0 :
|
||||
pack_time(<ime);
|
||||
}
|
||||
|
||||
virtual bool get_date_result(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate)
|
||||
{ return get_date(thd, ltime,fuzzydate); }
|
||||
|
||||
/*
|
||||
The method allows to determine nullness of a complex expression
|
||||
without fully evaluating it, instead of calling val/result*() then
|
||||
@ -6441,8 +6441,8 @@ public:
|
||||
Item *make_literal(THD *);
|
||||
longlong val_datetime_packed(THD *thd)
|
||||
{
|
||||
date_mode_t fuzzy= Datetime::comparison_flags_for_get_date();
|
||||
return has_value() ? Datetime(thd, this, fuzzy).to_packed() : 0;
|
||||
Datetime::Options_cmp opt(thd);
|
||||
return has_value() ? Datetime(thd, this, opt).to_packed() : 0;
|
||||
}
|
||||
longlong val_time_packed(THD *thd)
|
||||
{
|
||||
@ -6481,7 +6481,7 @@ public:
|
||||
}
|
||||
longlong val_time_packed(THD *thd)
|
||||
{
|
||||
return Time(thd, this, Time::comparison_flags_for_get_date()).to_packed();
|
||||
return Time(thd, this, Time::Options_cmp(thd)).to_packed();
|
||||
}
|
||||
longlong val_int()
|
||||
{
|
||||
@ -6516,7 +6516,7 @@ public:
|
||||
}
|
||||
longlong val_time_packed(THD *thd)
|
||||
{
|
||||
return Time(thd, this, Time::comparison_flags_for_get_date()).to_packed();
|
||||
return Time(thd, this, Time::Options_cmp(thd)).to_packed();
|
||||
}
|
||||
longlong val_int() { return has_value() ? Date(this).to_longlong() : 0; }
|
||||
double val_real() { return has_value() ? Date(this).to_double() : 0; }
|
||||
|
@ -2312,7 +2312,8 @@ bool Item_func_ifnull::date_op(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydat
|
||||
DBUG_ASSERT(fixed == 1);
|
||||
for (uint i= 0; i < 2; i++)
|
||||
{
|
||||
Datetime dt(thd, args[i], fuzzydate & ~TIME_FUZZY_DATES);
|
||||
Datetime_truncation_not_needed dt(thd, args[i],
|
||||
fuzzydate & ~TIME_FUZZY_DATES);
|
||||
if (!(dt.copy_to_mysql_time(ltime, mysql_timestamp_type())))
|
||||
return (null_value= false);
|
||||
}
|
||||
@ -2812,7 +2813,7 @@ Item_func_nullif::date_op(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate)
|
||||
DBUG_ASSERT(fixed == 1);
|
||||
if (!compare())
|
||||
return (null_value= true);
|
||||
Datetime dt(thd, args[2], fuzzydate);
|
||||
Datetime_truncation_not_needed dt(thd, args[2], fuzzydate);
|
||||
return (null_value= dt.copy_to_mysql_time(ltime, mysql_timestamp_type()));
|
||||
}
|
||||
|
||||
@ -2987,7 +2988,7 @@ bool Item_func_case::date_op(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate)
|
||||
Item *item= find_item();
|
||||
if (!item)
|
||||
return (null_value= true);
|
||||
Datetime dt(thd, item, fuzzydate);
|
||||
Datetime_truncation_not_needed dt(thd, item, fuzzydate);
|
||||
return (null_value= dt.copy_to_mysql_time(ltime, mysql_timestamp_type()));
|
||||
}
|
||||
|
||||
@ -3339,7 +3340,8 @@ bool Item_func_coalesce::date_op(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzyd
|
||||
DBUG_ASSERT(fixed == 1);
|
||||
for (uint i= 0; i < arg_count; i++)
|
||||
{
|
||||
Datetime dt(thd, args[i], fuzzydate & ~TIME_FUZZY_DATES);
|
||||
Datetime_truncation_not_needed dt(thd, args[i],
|
||||
fuzzydate & ~TIME_FUZZY_DATES);
|
||||
if (!dt.copy_to_mysql_time(ltime, mysql_timestamp_type()))
|
||||
return (null_value= false);
|
||||
}
|
||||
|
@ -1127,7 +1127,7 @@ public:
|
||||
|
||||
bool date_op(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate)
|
||||
{
|
||||
Datetime dt(thd, find_item(), fuzzydate);
|
||||
Datetime_truncation_not_needed dt(thd, find_item(), fuzzydate);
|
||||
return (null_value= dt.copy_to_mysql_time(ltime, mysql_timestamp_type()));
|
||||
}
|
||||
bool time_op(THD *thd, MYSQL_TIME *ltime)
|
||||
|
@ -2610,13 +2610,13 @@ bool Item_func_min_max::get_time_native(THD *thd, MYSQL_TIME *ltime)
|
||||
{
|
||||
DBUG_ASSERT(fixed == 1);
|
||||
|
||||
Time value(thd, args[0], Time::Options(), decimals);
|
||||
Time value(thd, args[0], Time::Options(thd), decimals);
|
||||
if (!value.is_valid_time())
|
||||
return (null_value= true);
|
||||
|
||||
for (uint i= 1; i < arg_count ; i++)
|
||||
{
|
||||
Time tmp(thd, args[i], Time::Options(), decimals);
|
||||
Time tmp(thd, args[i], Time::Options(thd), decimals);
|
||||
if (!tmp.is_valid_time())
|
||||
return (null_value= true);
|
||||
|
||||
|
@ -4544,7 +4544,7 @@ bool Item_func_dyncol_create::prepare_arguments(THD *thd, bool force_names_arg)
|
||||
case DYN_COL_DATETIME:
|
||||
case DYN_COL_DATE:
|
||||
args[valpos]->get_date(thd, &vals[i].x.time_value,
|
||||
sql_mode_for_dates(thd));
|
||||
Datetime::Options(thd));
|
||||
break;
|
||||
case DYN_COL_TIME:
|
||||
args[valpos]->get_time(thd, &vals[i].x.time_value);
|
||||
|
@ -131,7 +131,7 @@ static bool extract_date_time(THD *thd, DATE_TIME_FORMAT *format,
|
||||
timestamp_type cached_timestamp_type,
|
||||
const char **sub_pattern_end,
|
||||
const char *date_time_type,
|
||||
date_mode_t fuzzydate)
|
||||
date_conv_mode_t fuzzydate)
|
||||
{
|
||||
int weekday= 0, yearday= 0, daypart= 0;
|
||||
int week_number= -1;
|
||||
@ -808,8 +808,9 @@ longlong Item_func_period_diff::val_int()
|
||||
longlong Item_func_to_days::val_int()
|
||||
{
|
||||
DBUG_ASSERT(fixed == 1);
|
||||
Date d(current_thd, args[0], TIME_NO_ZERO_DATE | TIME_NO_ZERO_IN_DATE);
|
||||
return (null_value= !d.is_valid_date()) ? 0 : d.daynr();
|
||||
THD *thd= current_thd;
|
||||
Datetime d(thd, args[0], Datetime::Options(TIME_NO_ZEROS, thd));
|
||||
return (null_value= !d.is_valid_datetime()) ? 0 : d.daynr();
|
||||
}
|
||||
|
||||
|
||||
@ -817,14 +818,15 @@ longlong Item_func_to_seconds::val_int_endpoint(bool left_endp,
|
||||
bool *incl_endp)
|
||||
{
|
||||
DBUG_ASSERT(fixed == 1);
|
||||
Datetime dt(current_thd, args[0], TIME_FUZZY_DATES);
|
||||
// val_int_endpoint() is called only if args[0] is a temporal Item_field
|
||||
Datetime_from_temporal dt(current_thd, args[0], TIME_FUZZY_DATES);
|
||||
if ((null_value= !dt.is_valid_datetime()))
|
||||
{
|
||||
/* got NULL, leave the incl_endp intact */
|
||||
return LONGLONG_MIN;
|
||||
}
|
||||
/* Set to NULL if invalid date, but keep the value */
|
||||
null_value= dt.check_date(TIME_NO_ZERO_IN_DATE | TIME_NO_ZERO_DATE);
|
||||
null_value= dt.check_date(TIME_NO_ZEROS);
|
||||
/*
|
||||
Even if the evaluation return NULL, seconds is useful for pruning
|
||||
*/
|
||||
@ -835,7 +837,11 @@ longlong Item_func_to_seconds::val_int()
|
||||
{
|
||||
DBUG_ASSERT(fixed == 1);
|
||||
THD *thd= current_thd;
|
||||
Datetime dt(thd, args[0], TIME_NO_ZERO_DATE | TIME_NO_ZERO_IN_DATE);
|
||||
/*
|
||||
Unlike val_int_endpoint(), we cannot use Datetime_from_temporal here.
|
||||
The argument can be of a non-temporal data type.
|
||||
*/
|
||||
Datetime dt(thd, args[0], Datetime::Options(TIME_NO_ZEROS, thd));
|
||||
return (null_value= !dt.is_valid_datetime()) ? 0 : dt.to_seconds();
|
||||
}
|
||||
|
||||
@ -880,7 +886,8 @@ enum_monotonicity_info Item_func_to_seconds::get_monotonicity_info() const
|
||||
longlong Item_func_to_days::val_int_endpoint(bool left_endp, bool *incl_endp)
|
||||
{
|
||||
DBUG_ASSERT(fixed == 1);
|
||||
Datetime dt(current_thd, args[0], date_mode_t(0));
|
||||
// val_int_endpoint() is only called if args[0] is a temporal Item_field
|
||||
Datetime_from_temporal dt(current_thd, args[0], TIME_CONV_NONE);
|
||||
longlong res;
|
||||
if ((null_value= !dt.is_valid_datetime()))
|
||||
{
|
||||
@ -889,7 +896,7 @@ longlong Item_func_to_days::val_int_endpoint(bool left_endp, bool *incl_endp)
|
||||
}
|
||||
res= (longlong) dt.daynr();
|
||||
/* Set to NULL if invalid date, but keep the value */
|
||||
null_value= dt.check_date(TIME_NO_ZERO_IN_DATE | TIME_NO_ZERO_DATE);
|
||||
null_value= dt.check_date(TIME_NO_ZEROS);
|
||||
if (null_value)
|
||||
{
|
||||
/*
|
||||
@ -933,22 +940,25 @@ longlong Item_func_to_days::val_int_endpoint(bool left_endp, bool *incl_endp)
|
||||
longlong Item_func_dayofyear::val_int()
|
||||
{
|
||||
DBUG_ASSERT(fixed == 1);
|
||||
Date d(current_thd, args[0], TIME_NO_ZERO_IN_DATE | TIME_NO_ZERO_DATE);
|
||||
return (null_value= !d.is_valid_date()) ? 0 : d.dayofyear();
|
||||
THD *thd= current_thd;
|
||||
Datetime d(thd, args[0], Datetime::Options(TIME_NO_ZEROS, thd));
|
||||
return (null_value= !d.is_valid_datetime()) ? 0 : d.dayofyear();
|
||||
}
|
||||
|
||||
longlong Item_func_dayofmonth::val_int()
|
||||
{
|
||||
DBUG_ASSERT(fixed == 1);
|
||||
Date d(current_thd, args[0], date_mode_t(0));
|
||||
return (null_value= !d.is_valid_date()) ? 0 : d.get_mysql_time()->day;
|
||||
THD *thd= current_thd;
|
||||
Datetime d(thd, args[0], Datetime::Options(TIME_CONV_NONE, thd));
|
||||
return (null_value= !d.is_valid_datetime()) ? 0 : d.get_mysql_time()->day;
|
||||
}
|
||||
|
||||
longlong Item_func_month::val_int()
|
||||
{
|
||||
DBUG_ASSERT(fixed == 1);
|
||||
Date d(current_thd, args[0], date_mode_t(0));
|
||||
return (null_value= !d.is_valid_date()) ? 0 : d.get_mysql_time()->month;
|
||||
THD *thd= current_thd;
|
||||
Datetime d(thd, args[0], Datetime::Options(TIME_CONV_NONE, thd));
|
||||
return (null_value= !d.is_valid_datetime()) ? 0 : d.get_mysql_time()->month;
|
||||
}
|
||||
|
||||
|
||||
@ -970,9 +980,9 @@ String* Item_func_monthname::val_str(String* str)
|
||||
DBUG_ASSERT(fixed == 1);
|
||||
const char *month_name;
|
||||
uint err;
|
||||
Date d(current_thd, args[0], date_mode_t(0));
|
||||
|
||||
if ((null_value= (!d.is_valid_date() || !d.get_mysql_time()->month)))
|
||||
THD *thd= current_thd;
|
||||
Datetime d(thd, args[0], Datetime::Options(TIME_CONV_NONE, thd));
|
||||
if ((null_value= (!d.is_valid_datetime() || !d.get_mysql_time()->month)))
|
||||
return (String *) 0;
|
||||
|
||||
month_name= locale->month_names->type_names[d.get_mysql_time()->month - 1];
|
||||
@ -989,21 +999,24 @@ String* Item_func_monthname::val_str(String* str)
|
||||
longlong Item_func_quarter::val_int()
|
||||
{
|
||||
DBUG_ASSERT(fixed == 1);
|
||||
Date d(current_thd, args[0], date_mode_t(0));
|
||||
return (null_value= !d.is_valid_date()) ? 0 : d.quarter();
|
||||
THD *thd= current_thd;
|
||||
Datetime d(thd, args[0], Datetime::Options(TIME_CONV_NONE, thd));
|
||||
return (null_value= !d.is_valid_datetime()) ? 0 : d.quarter();
|
||||
}
|
||||
|
||||
longlong Item_func_hour::val_int()
|
||||
{
|
||||
DBUG_ASSERT(fixed == 1);
|
||||
Time tm(current_thd, args[0], Time::Options_for_cast());
|
||||
THD *thd= current_thd;
|
||||
Time tm(thd, args[0], Time::Options_for_cast(thd));
|
||||
return (null_value= !tm.is_valid_time()) ? 0 : tm.get_mysql_time()->hour;
|
||||
}
|
||||
|
||||
longlong Item_func_minute::val_int()
|
||||
{
|
||||
DBUG_ASSERT(fixed == 1);
|
||||
Time tm(current_thd, args[0], Time::Options_for_cast());
|
||||
THD *thd= current_thd;
|
||||
Time tm(thd, args[0], Time::Options_for_cast(thd));
|
||||
return (null_value= !tm.is_valid_time()) ? 0 : tm.get_mysql_time()->minute;
|
||||
}
|
||||
|
||||
@ -1013,7 +1026,8 @@ longlong Item_func_minute::val_int()
|
||||
longlong Item_func_second::val_int()
|
||||
{
|
||||
DBUG_ASSERT(fixed == 1);
|
||||
Time tm(current_thd, args[0], Time::Options_for_cast());
|
||||
THD *thd= current_thd;
|
||||
Time tm(thd, args[0], Time::Options_for_cast(thd));
|
||||
return (null_value= !tm.is_valid_time()) ? 0 : tm.get_mysql_time()->second;
|
||||
}
|
||||
|
||||
@ -1062,8 +1076,8 @@ longlong Item_func_week::val_int()
|
||||
DBUG_ASSERT(fixed == 1);
|
||||
uint week_format;
|
||||
THD *thd= current_thd;
|
||||
Date d(thd, args[0], TIME_NO_ZERO_DATE | TIME_NO_ZERO_IN_DATE);
|
||||
if ((null_value= !d.is_valid_date()))
|
||||
Datetime d(thd, args[0], Datetime::Options(TIME_NO_ZEROS, thd));
|
||||
if ((null_value= !d.is_valid_datetime()))
|
||||
return 0;
|
||||
if (arg_count > 1)
|
||||
week_format= (uint)args[1]->val_int();
|
||||
@ -1076,8 +1090,9 @@ longlong Item_func_week::val_int()
|
||||
longlong Item_func_yearweek::val_int()
|
||||
{
|
||||
DBUG_ASSERT(fixed == 1);
|
||||
Date d(current_thd, args[0], TIME_NO_ZERO_DATE | TIME_NO_ZERO_IN_DATE);
|
||||
return (null_value= !d.is_valid_date()) ? 0 :
|
||||
THD *thd= current_thd;
|
||||
Datetime d(thd, args[0], Datetime::Options(TIME_NO_ZEROS, thd));
|
||||
return (null_value= !d.is_valid_datetime()) ? 0 :
|
||||
d.yearweek((week_mode((uint) args[1]->val_int()) | WEEK_YEAR));
|
||||
}
|
||||
|
||||
@ -1085,8 +1100,9 @@ longlong Item_func_yearweek::val_int()
|
||||
longlong Item_func_weekday::val_int()
|
||||
{
|
||||
DBUG_ASSERT(fixed == 1);
|
||||
Date d(current_thd, args[0], TIME_NO_ZERO_DATE | TIME_NO_ZERO_IN_DATE);
|
||||
return ((null_value= !d.is_valid_date())) ? 0 :
|
||||
THD *thd= current_thd;
|
||||
Datetime d(thd, args[0], Datetime::Options(TIME_NO_ZEROS, thd));
|
||||
return ((null_value= !d.is_valid_datetime())) ? 0 :
|
||||
calc_weekday(d.daynr(), odbc_type) + MY_TEST(odbc_type);
|
||||
}
|
||||
|
||||
@ -1123,8 +1139,9 @@ String* Item_func_dayname::val_str(String* str)
|
||||
longlong Item_func_year::val_int()
|
||||
{
|
||||
DBUG_ASSERT(fixed == 1);
|
||||
Date d(current_thd, args[0], date_mode_t(0));
|
||||
return (null_value= !d.is_valid_date()) ? 0 : d.get_mysql_time()->year;
|
||||
THD *thd= current_thd;
|
||||
Datetime d(thd, args[0], Datetime::Options(TIME_CONV_NONE, thd));
|
||||
return (null_value= !d.is_valid_datetime()) ? 0 : d.get_mysql_time()->year;
|
||||
}
|
||||
|
||||
|
||||
@ -1155,7 +1172,8 @@ enum_monotonicity_info Item_func_year::get_monotonicity_info() const
|
||||
longlong Item_func_year::val_int_endpoint(bool left_endp, bool *incl_endp)
|
||||
{
|
||||
DBUG_ASSERT(fixed == 1);
|
||||
Datetime dt(current_thd, args[0], date_mode_t(0));
|
||||
// val_int_endpoint() is cally only if args[0] is a temporal Item_field
|
||||
Datetime_from_temporal dt(current_thd, args[0], TIME_CONV_NONE);
|
||||
if ((null_value= !dt.is_valid_datetime()))
|
||||
{
|
||||
/* got NULL, leave the incl_endp intact */
|
||||
@ -1200,7 +1218,7 @@ bool Item_func_unix_timestamp::get_timestamp_value(my_time_t *seconds,
|
||||
}
|
||||
|
||||
THD *thd= current_thd;
|
||||
Datetime dt(thd, args[0], TIME_NO_ZERO_IN_DATE);
|
||||
Datetime dt(thd, args[0], Datetime::Options(TIME_NO_ZERO_IN_DATE, thd));
|
||||
if ((null_value= !dt.is_valid_datetime()))
|
||||
return true;
|
||||
|
||||
@ -1264,7 +1282,8 @@ longlong Item_func_unix_timestamp::val_int_endpoint(bool left_endp, bool *incl_e
|
||||
longlong Item_func_time_to_sec::int_op()
|
||||
{
|
||||
DBUG_ASSERT(fixed == 1);
|
||||
Time tm(current_thd, args[0], Time::Options_for_cast());
|
||||
THD *thd= current_thd;
|
||||
Time tm(thd, args[0], Time::Options_for_cast(thd));
|
||||
return ((null_value= !tm.is_valid_time())) ? 0 : tm.to_seconds();
|
||||
}
|
||||
|
||||
@ -1272,7 +1291,8 @@ longlong Item_func_time_to_sec::int_op()
|
||||
my_decimal *Item_func_time_to_sec::decimal_op(my_decimal* buf)
|
||||
{
|
||||
DBUG_ASSERT(fixed == 1);
|
||||
Time tm(current_thd, args[0], Time::Options_for_cast());
|
||||
THD *thd= current_thd;
|
||||
Time tm(thd, args[0], Time::Options_for_cast(thd));
|
||||
if ((null_value= !tm.is_valid_time()))
|
||||
return 0;
|
||||
const MYSQL_TIME *ltime= tm.get_mysql_time();
|
||||
@ -1621,9 +1641,8 @@ int Item_func_now_local::save_in_field(Field *field, bool no_conversions)
|
||||
{
|
||||
THD *thd= field->get_thd();
|
||||
my_time_t ts= thd->query_start();
|
||||
uint dec= MY_MIN(decimals, field->decimals());
|
||||
ulong sec_part= dec ? thd->query_start_sec_part() : 0;
|
||||
sec_part-= my_time_fraction_remainder(sec_part, dec);
|
||||
ulong sec_part= decimals ? thd->query_start_sec_part() : 0;
|
||||
sec_part-= my_time_fraction_remainder(sec_part, decimals);
|
||||
field->set_notnull();
|
||||
((Field_timestamp*)field)->store_TIME(ts, sec_part);
|
||||
return 0;
|
||||
@ -1698,9 +1717,10 @@ bool Item_func_sysdate_local::get_date(THD *thd, MYSQL_TIME *res,
|
||||
bool Item_func_sec_to_time::get_date(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate)
|
||||
{
|
||||
DBUG_ASSERT(fixed == 1);
|
||||
VSec6 sec(thd, args[0], "seconds", LONGLONG_MAX);
|
||||
VSec9 sec(thd, args[0], "seconds", LONGLONG_MAX);
|
||||
if ((null_value= sec.is_null()))
|
||||
return true;
|
||||
sec.round(decimals, thd->temporal_round_mode());
|
||||
if (sec.sec_to_time(ltime, decimals) && !sec.truncated())
|
||||
sec.make_truncated_warning(thd, "seconds");
|
||||
return false;
|
||||
@ -1858,10 +1878,10 @@ String *Item_func_date_format::val_str(String *str)
|
||||
uint size;
|
||||
const MY_LOCALE *lc= 0;
|
||||
DBUG_ASSERT(fixed == 1);
|
||||
|
||||
if ((null_value= args[0]->get_date(current_thd, &l_time,
|
||||
is_time_format ? TIME_TIME_ONLY :
|
||||
date_mode_t(0))))
|
||||
date_conv_mode_t mode= is_time_format ? TIME_TIME_ONLY : TIME_CONV_NONE;
|
||||
THD *thd= current_thd;
|
||||
if ((null_value= args[0]->get_date(thd, &l_time,
|
||||
Temporal::Options(mode, thd))))
|
||||
return 0;
|
||||
|
||||
if (!(format = args[1]->val_str(str)) || !format->length())
|
||||
@ -1918,12 +1938,16 @@ bool Item_func_from_unixtime::get_date(THD *thd, MYSQL_TIME *ltime,
|
||||
bzero((char *)ltime, sizeof(*ltime));
|
||||
ltime->time_type= MYSQL_TIMESTAMP_TIME;
|
||||
|
||||
VSec6 sec(thd, args[0], "unixtime", TIMESTAMP_MAX_VALUE);
|
||||
VSec9 sec(thd, args[0], "unixtime", TIMESTAMP_MAX_VALUE);
|
||||
DBUG_ASSERT(sec.sec() <= TIMESTAMP_MAX_VALUE);
|
||||
|
||||
if (sec.is_null() || sec.truncated() || sec.neg())
|
||||
return (null_value= 1);
|
||||
|
||||
sec.round(MY_MIN(decimals, TIME_SECOND_PART_DIGITS), thd->temporal_round_mode());
|
||||
if (sec.sec() > TIMESTAMP_MAX_VALUE)
|
||||
return (null_value= true); // Went out of range after rounding
|
||||
|
||||
tz->gmt_sec_to_TIME(ltime, (my_time_t) sec.sec());
|
||||
ltime->second_part= sec.usec();
|
||||
|
||||
@ -1952,7 +1976,8 @@ bool Item_func_convert_tz::get_date(THD *thd, MYSQL_TIME *ltime,
|
||||
if ((null_value= (from_tz == 0 || to_tz == 0)))
|
||||
return true;
|
||||
|
||||
Datetime *dt= new(ltime) Datetime(thd, args[0], TIME_NO_ZERO_DATE | TIME_NO_ZERO_IN_DATE);
|
||||
Datetime::Options opt(TIME_NO_ZEROS, thd);
|
||||
Datetime *dt= new(ltime) Datetime(thd, args[0], opt);
|
||||
if ((null_value= !dt->is_valid_datetime()))
|
||||
return true;
|
||||
|
||||
@ -2133,7 +2158,8 @@ uint Extract_source::week(THD *thd) const
|
||||
longlong Item_extract::val_int()
|
||||
{
|
||||
DBUG_ASSERT(fixed == 1);
|
||||
Extract_source dt(current_thd, args[0], m_date_mode);
|
||||
THD *thd= current_thd;
|
||||
Extract_source dt(thd, args[0], m_date_mode);
|
||||
if ((null_value= !dt.is_valid_extract_source()))
|
||||
return 0;
|
||||
switch (int_type) {
|
||||
@ -2141,7 +2167,7 @@ longlong Item_extract::val_int()
|
||||
case INTERVAL_YEAR_MONTH: return dt.year_month();
|
||||
case INTERVAL_QUARTER: return dt.quarter();
|
||||
case INTERVAL_MONTH: return dt.month();
|
||||
case INTERVAL_WEEK: return dt.week(current_thd);
|
||||
case INTERVAL_WEEK: return dt.week(thd);
|
||||
case INTERVAL_DAY: return dt.day();
|
||||
case INTERVAL_DAY_HOUR: return dt.day_hour();
|
||||
case INTERVAL_DAY_MINUTE: return dt.day_minute();
|
||||
@ -2420,7 +2446,7 @@ void Item_char_typecast::fix_length_and_dec_internal(CHARSET_INFO *from_cs)
|
||||
|
||||
bool Item_time_typecast::get_date(THD *thd, MYSQL_TIME *to, date_mode_t mode)
|
||||
{
|
||||
Time *tm= new(to) Time(thd, args[0], Time::Options_for_cast(mode),
|
||||
Time *tm= new(to) Time(thd, args[0], Time::Options_for_cast(mode, thd),
|
||||
MY_MIN(decimals, TIME_SECOND_PART_DIGITS));
|
||||
return (null_value= !tm->is_valid_time());
|
||||
}
|
||||
@ -2429,7 +2455,8 @@ bool Item_time_typecast::get_date(THD *thd, MYSQL_TIME *to, date_mode_t mode)
|
||||
bool Item_date_typecast::get_date(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate)
|
||||
{
|
||||
date_mode_t tmp= (fuzzydate | sql_mode_for_dates(thd)) & ~TIME_TIME_ONLY;
|
||||
Date *d= new(ltime) Date(thd, args[0], tmp);
|
||||
// Force truncation
|
||||
Date *d= new(ltime) Date(thd, args[0], Date::Options(date_conv_mode_t(tmp)));
|
||||
return (null_value= !d->is_valid_date());
|
||||
}
|
||||
|
||||
@ -2437,7 +2464,9 @@ bool Item_date_typecast::get_date(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzy
|
||||
bool Item_datetime_typecast::get_date(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate)
|
||||
{
|
||||
date_mode_t tmp= (fuzzydate | sql_mode_for_dates(thd)) & ~TIME_TIME_ONLY;
|
||||
Datetime *dt= new(ltime) Datetime(thd, args[0], tmp,
|
||||
// Force rounding if the current sql_mode says so
|
||||
Datetime::Options opt(date_conv_mode_t(tmp), thd);
|
||||
Datetime *dt= new(ltime) Datetime(thd, args[0], opt,
|
||||
MY_MIN(decimals, TIME_SECOND_PART_DIGITS));
|
||||
return (null_value= !dt->is_valid_datetime());
|
||||
}
|
||||
@ -2558,6 +2587,7 @@ bool Item_func_timediff::get_date(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzy
|
||||
return (null_value= adjust_time_range_with_warn(thd, ltime, decimals));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
MAKETIME(h,m,s) is a time function that calculates a time value
|
||||
from the total number of hours, minutes, and seconds.
|
||||
@ -2569,7 +2599,7 @@ bool Item_func_maketime::get_date(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzy
|
||||
DBUG_ASSERT(fixed == 1);
|
||||
Longlong_hybrid hour(args[0]->val_int(), args[0]->unsigned_flag);
|
||||
longlong minute= args[1]->val_int();
|
||||
VSec6 sec(thd, args[2], "seconds", 59);
|
||||
VSec9 sec(thd, args[2], "seconds", 59);
|
||||
|
||||
DBUG_ASSERT(sec.sec() <= 59);
|
||||
if (args[0]->null_value || args[1]->null_value || sec.is_null() ||
|
||||
@ -2577,7 +2607,8 @@ bool Item_func_maketime::get_date(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzy
|
||||
return (null_value= 1);
|
||||
|
||||
int warn;
|
||||
new(ltime) Time(&warn, hour.neg(), hour.abs(), (uint) minute, sec);
|
||||
new(ltime) Time(&warn, hour.neg(), hour.abs(), (uint) minute, sec,
|
||||
thd->temporal_round_mode(), decimals);
|
||||
if (warn)
|
||||
{
|
||||
// use check_time_range() to set ltime to the max value depending on dec
|
||||
@ -2607,7 +2638,8 @@ bool Item_func_maketime::get_date(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzy
|
||||
longlong Item_func_microsecond::val_int()
|
||||
{
|
||||
DBUG_ASSERT(fixed == 1);
|
||||
Time tm(current_thd, args[0], Time::Options_for_cast());
|
||||
THD *thd= current_thd;
|
||||
Time tm(thd, args[0], Time::Options_for_cast(thd));
|
||||
return ((null_value= !tm.is_valid_time())) ?
|
||||
0 : tm.get_mysql_time()->second_part;
|
||||
}
|
||||
@ -2621,12 +2653,12 @@ longlong Item_func_timestamp_diff::val_int()
|
||||
long months= 0;
|
||||
int neg= 1;
|
||||
THD *thd= current_thd;
|
||||
date_mode_t fuzzydate= TIME_NO_ZERO_DATE | TIME_NO_ZERO_IN_DATE;
|
||||
Datetime::Options opt(TIME_NO_ZEROS, thd);
|
||||
|
||||
null_value= 0;
|
||||
|
||||
if (Datetime(thd, args[0], fuzzydate).copy_to_mysql_time(<ime1) ||
|
||||
Datetime(thd, args[1], fuzzydate).copy_to_mysql_time(<ime2))
|
||||
if (Datetime(thd, args[0], opt).copy_to_mysql_time(<ime1) ||
|
||||
Datetime(thd, args[1], opt).copy_to_mysql_time(<ime2))
|
||||
goto null_date;
|
||||
|
||||
if (calc_time_diff(<ime2,<ime1, 1,
|
||||
@ -2935,7 +2967,8 @@ bool Item_func_str_to_date::get_date_common(THD *thd, MYSQL_TIME *ltime,
|
||||
date_time_format.format.length= format->length();
|
||||
if (extract_date_time(thd, &date_time_format, val->ptr(), val->length(),
|
||||
ltime, tstype, 0, "datetime",
|
||||
fuzzydate | sql_mode_for_dates(thd)))
|
||||
date_conv_mode_t(fuzzydate) |
|
||||
sql_mode_for_dates(thd)))
|
||||
return (null_value=1);
|
||||
return (null_value= 0);
|
||||
}
|
||||
@ -2943,8 +2976,10 @@ bool Item_func_str_to_date::get_date_common(THD *thd, MYSQL_TIME *ltime,
|
||||
|
||||
bool Item_func_last_day::get_date(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate)
|
||||
{
|
||||
Date *d= new(ltime) Date(thd, args[0], fuzzydate & ~TIME_TIME_ONLY);
|
||||
if ((null_value= (!d->is_valid_date() || ltime->month == 0)))
|
||||
Datetime::Options opt(date_conv_mode_t(fuzzydate & ~TIME_TIME_ONLY),
|
||||
time_round_mode_t(fuzzydate));
|
||||
Datetime *d= new(ltime) Datetime(thd, args[0], opt);
|
||||
if ((null_value= (!d->is_valid_datetime() || ltime->month == 0)))
|
||||
return true;
|
||||
uint month_idx= ltime->month-1;
|
||||
ltime->day= days_in_month[month_idx];
|
||||
|
@ -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= TIME_INTERVAL_DAY;
|
||||
m_date_mode= Temporal::Options(TIME_INTERVAL_DAY, current_thd);
|
||||
}
|
||||
void set_time_length(uint32 length)
|
||||
{
|
||||
set_handler(handler_by_length(max_length= length + 1/*sign*/, 11));
|
||||
m_date_mode= TIME_INTERVAL_hhmmssff;
|
||||
m_date_mode= Temporal::Options(TIME_INTERVAL_hhmmssff, current_thd);
|
||||
}
|
||||
public:
|
||||
const interval_type int_type; // keep it public
|
||||
@ -1117,7 +1117,7 @@ public:
|
||||
{ }
|
||||
String *val_str(String *to)
|
||||
{
|
||||
Interval_DDhhmmssff it(current_thd, args[0]);
|
||||
Interval_DDhhmmssff it(current_thd, args[0], m_fsp);
|
||||
null_value= !it.is_valid_interval_DDhhmmssff();
|
||||
return it.to_string(to, m_fsp);
|
||||
}
|
||||
@ -1222,7 +1222,7 @@ public:
|
||||
}
|
||||
bool get_date(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate)
|
||||
{
|
||||
Datetime dt(thd, args[0], date_mode_t(0));
|
||||
Datetime dt(thd, args[0], Datetime::Options(TIME_CONV_NONE, thd));
|
||||
if (!dt.is_valid_datetime())
|
||||
return null_value= true;
|
||||
Interval_DDhhmmssff it(thd, args[1]);
|
||||
@ -1461,7 +1461,8 @@ public:
|
||||
bool get_date(THD *thd, Item_handled_func *item,
|
||||
MYSQL_TIME *to, date_mode_t fuzzy) const
|
||||
{
|
||||
Datetime dt(thd, item->arguments()[0], date_mode_t(0));
|
||||
Datetime::Options opt(TIME_CONV_NONE, thd);
|
||||
Datetime dt(thd, item->arguments()[0], opt);
|
||||
if (!dt.is_valid_datetime() ||
|
||||
dt.check_date_with_warn(thd, TIME_NO_ZERO_DATE | TIME_NO_ZERO_IN_DATE))
|
||||
return (item->null_value= true);
|
||||
@ -1489,7 +1490,11 @@ public:
|
||||
bool get_date(THD *thd, Item_handled_func *item,
|
||||
MYSQL_TIME *to, date_mode_t fuzzy) const
|
||||
{
|
||||
Date d(thd, item->arguments()[0], date_mode_t(0));
|
||||
/*
|
||||
The first argument is known to be of the DATE data type (not DATETIME).
|
||||
We don't need rounding here.
|
||||
*/
|
||||
Date d(thd, item->arguments()[0], TIME_CONV_NONE);
|
||||
if (!d.is_valid_date() ||
|
||||
d.check_date_with_warn(thd, TIME_NO_ZERO_DATE | TIME_NO_ZERO_IN_DATE))
|
||||
return (item->null_value= true);
|
||||
@ -1542,10 +1547,10 @@ public:
|
||||
bool get_date(THD *thd, Item_handled_func *item,
|
||||
MYSQL_TIME *to, date_mode_t fuzzy) const
|
||||
{
|
||||
if (item->arguments()[0]->get_date(thd, to, date_mode_t(0)) ||
|
||||
if (item->arguments()[0]->
|
||||
get_date(thd, to, Datetime::Options(TIME_CONV_NONE, thd)) ||
|
||||
(to->time_type != MYSQL_TIMESTAMP_TIME &&
|
||||
check_date_with_warn(thd, to, TIME_NO_ZERO_DATE | TIME_NO_ZERO_IN_DATE,
|
||||
MYSQL_TIMESTAMP_ERROR)))
|
||||
check_date_with_warn(thd, to, TIME_NO_ZEROS, MYSQL_TIMESTAMP_ERROR)))
|
||||
return (item->null_value= true);
|
||||
return (item->null_value= add(thd, item->arguments()[1],
|
||||
int_type(item), sub(item), to));
|
||||
@ -1581,7 +1586,8 @@ public:
|
||||
MYSQL_TIME *to, date_mode_t fuzzy) const
|
||||
{
|
||||
DBUG_ASSERT(item->is_fixed());
|
||||
Datetime dt(thd, item->arguments()[0], date_mode_t(0));
|
||||
Datetime::Options opt(TIME_CONV_NONE, thd);
|
||||
Datetime dt(thd, item->arguments()[0], opt);
|
||||
if (!dt.is_valid_datetime())
|
||||
return item->null_value= true;
|
||||
Interval_DDhhmmssff it(thd, item->arguments()[1]);
|
||||
@ -1650,7 +1656,8 @@ public:
|
||||
{
|
||||
DBUG_ASSERT(item->is_fixed());
|
||||
// Detect a proper timestamp type based on the argument values
|
||||
Temporal_hybrid l_time1(thd, item->arguments()[0], TIME_TIME_ONLY);
|
||||
Temporal_hybrid l_time1(thd, item->arguments()[0],
|
||||
Temporal::Options(TIME_TIME_ONLY, thd));
|
||||
if (!l_time1.is_valid_temporal())
|
||||
return (item->null_value= true);
|
||||
Interval_DDhhmmssff l_time2(thd, item->arguments()[1]);
|
||||
|
@ -142,7 +142,9 @@ Item_func_trt_id::val_int()
|
||||
else
|
||||
{
|
||||
MYSQL_TIME commit_ts;
|
||||
if (args[0]->get_date(current_thd, &commit_ts, date_mode_t(0)))
|
||||
THD *thd= current_thd;
|
||||
Datetime::Options opt(TIME_CONV_NONE, thd);
|
||||
if (args[0]->get_date(thd, &commit_ts, opt))
|
||||
{
|
||||
null_value= true;
|
||||
return 0;
|
||||
|
@ -268,7 +268,8 @@ int str2my_decimal(uint mask, const char *from, size_t length,
|
||||
integer part cannot be larger that 1e18 (otherwise it's an overflow).
|
||||
fractional part is microseconds.
|
||||
*/
|
||||
bool my_decimal2seconds(const my_decimal *d, ulonglong *sec, ulong *microsec)
|
||||
bool my_decimal2seconds(const my_decimal *d, ulonglong *sec,
|
||||
ulong *microsec, ulong *nanosec)
|
||||
{
|
||||
int pos;
|
||||
|
||||
@ -286,6 +287,7 @@ bool my_decimal2seconds(const my_decimal *d, ulonglong *sec, ulong *microsec)
|
||||
}
|
||||
|
||||
*microsec= d->frac ? static_cast<longlong>(d->buf[pos+1]) / (DIG_BASE/1000000) : 0;
|
||||
*nanosec= d->frac ? static_cast<longlong>(d->buf[pos+1]) % (DIG_BASE/1000000) : 0;
|
||||
|
||||
if (pos > 1)
|
||||
{
|
||||
|
@ -362,7 +362,8 @@ inline bool str_set_decimal(const my_decimal *val, String *str,
|
||||
}
|
||||
|
||||
|
||||
bool my_decimal2seconds(const my_decimal *d, ulonglong *sec, ulong *microsec);
|
||||
bool my_decimal2seconds(const my_decimal *d, ulonglong *sec,
|
||||
ulong *microsec, ulong *nanosec);
|
||||
|
||||
my_decimal *seconds2my_decimal(bool sign, ulonglong sec, ulong microsec,
|
||||
my_decimal *d);
|
||||
|
@ -200,7 +200,8 @@ TABLE_FIELD_TYPE proc_table_fields[MYSQL_PROC_FIELD_COUNT] =
|
||||
"'STRICT_ALL_TABLES','NO_ZERO_IN_DATE','NO_ZERO_DATE','INVALID_DATES',"
|
||||
"'ERROR_FOR_DIVISION_BY_ZERO','TRADITIONAL','NO_AUTO_CREATE_USER',"
|
||||
"'HIGH_NOT_PRECEDENCE','NO_ENGINE_SUBSTITUTION','PAD_CHAR_TO_FULL_LENGTH',"
|
||||
"'EMPTY_STRING_IS_NULL','SIMULTANEOUS_ASSIGNMENT')") },
|
||||
"'EMPTY_STRING_IS_NULL','SIMULTANEOUS_ASSIGNMENT',"
|
||||
"'TIME_ROUND_FRACTIONAL')") },
|
||||
{ NULL, 0 }
|
||||
},
|
||||
{
|
||||
|
@ -26,13 +26,15 @@ typedef int64 query_id_t;
|
||||
|
||||
/*
|
||||
"fuzzydate" with strict data type control.
|
||||
Represents a mixture of *only* data type conversion flags, without rounding.
|
||||
Please keep "explicit" in constructors and conversion methods.
|
||||
*/
|
||||
class date_mode_t
|
||||
class date_conv_mode_t
|
||||
{
|
||||
public:
|
||||
enum value_t
|
||||
{
|
||||
CONV_NONE= 0U,
|
||||
/*
|
||||
FUZZY_DATES is used for the result will only be used for comparison
|
||||
purposes. Conversion is as relaxed as possible.
|
||||
@ -41,15 +43,159 @@ public:
|
||||
TIME_ONLY= 4U,
|
||||
INTERVAL_hhmmssff= 8U,
|
||||
INTERVAL_DAY= 16U,
|
||||
RANGE0_LAST= INTERVAL_DAY,
|
||||
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
|
||||
};
|
||||
|
||||
/*
|
||||
BIT-OR for all known values. Let's have a separate enum for it.
|
||||
- We don't put this value "value_t", to avoid handling it in switch().
|
||||
- We don't put this value as a static const inside the class,
|
||||
because "gdb" would display it every time when we do "print"
|
||||
for a time_round_mode_t value.
|
||||
- We can't put into into a function returning this value, because
|
||||
it's not allowed to use functions in static_assert.
|
||||
*/
|
||||
enum known_values_t
|
||||
{
|
||||
KNOWN_MODES= FUZZY_DATES |
|
||||
TIME_ONLY | INTERVAL_hhmmssff | INTERVAL_DAY |
|
||||
NO_ZERO_IN_DATE | NO_ZERO_DATE | INVALID_DATES
|
||||
};
|
||||
private:
|
||||
value_t m_mode;
|
||||
public:
|
||||
|
||||
// Constructors
|
||||
explicit date_conv_mode_t(ulonglong fuzzydate)
|
||||
:m_mode((value_t) fuzzydate)
|
||||
{ }
|
||||
|
||||
// Conversion operators
|
||||
explicit operator ulonglong() const
|
||||
{
|
||||
return m_mode;
|
||||
}
|
||||
explicit operator bool() const
|
||||
{
|
||||
return m_mode != 0;
|
||||
}
|
||||
|
||||
// Unary operators
|
||||
ulonglong operator~() const
|
||||
{
|
||||
return ~m_mode;
|
||||
}
|
||||
|
||||
// Dyadic bitwise operators
|
||||
date_conv_mode_t operator&(const date_conv_mode_t &other) const
|
||||
{
|
||||
return date_conv_mode_t(m_mode & other.m_mode);
|
||||
}
|
||||
date_conv_mode_t operator&(const ulonglong other) const
|
||||
{
|
||||
return date_conv_mode_t(m_mode & other);
|
||||
}
|
||||
|
||||
date_conv_mode_t operator|(const date_conv_mode_t &other) const
|
||||
{
|
||||
return date_conv_mode_t(m_mode | other.m_mode);
|
||||
}
|
||||
|
||||
// Dyadic bitwise assignment operators
|
||||
date_conv_mode_t &operator&=(const date_conv_mode_t &other)
|
||||
{
|
||||
m_mode= value_t(m_mode & other.m_mode);
|
||||
return *this;
|
||||
}
|
||||
|
||||
date_conv_mode_t &operator|=(const date_conv_mode_t &other)
|
||||
{
|
||||
m_mode= value_t(m_mode | other.m_mode);
|
||||
return *this;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
Fractional rounding mode for temporal data types.
|
||||
*/
|
||||
class time_round_mode_t
|
||||
{
|
||||
public:
|
||||
enum value_t
|
||||
{
|
||||
/*
|
||||
Use FRAC_NONE when the value needs no rounding nor truncation,
|
||||
because it is already known not to haveany fractional digits outside
|
||||
of the requested precision.
|
||||
*/
|
||||
FRAC_NONE= 0,
|
||||
FRAC_TRUNCATE= date_conv_mode_t::RANGE0_LAST << 1, // 32
|
||||
FRAC_ROUND= date_conv_mode_t::RANGE0_LAST << 2 // 64
|
||||
};
|
||||
// BIT-OR for all known values. See comments in time_conv_mode_t.
|
||||
enum known_values_t
|
||||
{
|
||||
KNOWN_MODES= FRAC_TRUNCATE | FRAC_ROUND
|
||||
};
|
||||
private:
|
||||
value_t m_mode;
|
||||
public:
|
||||
// Constructors
|
||||
explicit time_round_mode_t(ulonglong mode)
|
||||
:m_mode((value_t) mode)
|
||||
{
|
||||
DBUG_ASSERT(mode == FRAC_NONE ||
|
||||
mode == FRAC_TRUNCATE ||
|
||||
mode == FRAC_ROUND);
|
||||
}
|
||||
// Conversion operators
|
||||
explicit operator ulonglong() const
|
||||
{
|
||||
return m_mode;
|
||||
}
|
||||
value_t mode() const
|
||||
{
|
||||
return m_mode;
|
||||
}
|
||||
// Comparison operators
|
||||
bool operator==(const time_round_mode_t &other)
|
||||
{
|
||||
return m_mode == other.m_mode;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
"fuzzydate" with strict data type control.
|
||||
Used as a parameter to get_date() and represents a mixture of:
|
||||
- data type conversion flags
|
||||
- fractional second rounding flags
|
||||
Please keep "explicit" in constructors and conversion methods.
|
||||
*/
|
||||
class date_mode_t
|
||||
{
|
||||
public:
|
||||
enum value_t
|
||||
{
|
||||
CONV_NONE= date_conv_mode_t::CONV_NONE, // 0
|
||||
FUZZY_DATES= date_conv_mode_t::FUZZY_DATES, // 1
|
||||
TIME_ONLY= date_conv_mode_t::TIME_ONLY, // 4
|
||||
INTERVAL_hhmmssff= date_conv_mode_t::INTERVAL_hhmmssff, // 8
|
||||
INTERVAL_DAY= date_conv_mode_t::INTERVAL_DAY, // 16
|
||||
FRAC_TRUNCATE= time_round_mode_t::FRAC_TRUNCATE, // 32
|
||||
FRAC_ROUND= time_round_mode_t::FRAC_ROUND, // 64
|
||||
NO_ZERO_IN_DATE= date_conv_mode_t::NO_ZERO_IN_DATE, // (1UL << 23)
|
||||
NO_ZERO_DATE= date_conv_mode_t::NO_ZERO_DATE, // (1UL << 24)
|
||||
INVALID_DATES= date_conv_mode_t::INVALID_DATES, // (1UL << 25)
|
||||
};
|
||||
protected:
|
||||
value_t m_mode;
|
||||
public:
|
||||
|
||||
// Constructors
|
||||
explicit date_mode_t(ulonglong fuzzydate)
|
||||
:m_mode((value_t) fuzzydate)
|
||||
@ -64,11 +210,22 @@ public:
|
||||
{
|
||||
return m_mode != 0;
|
||||
}
|
||||
|
||||
// Unary operators
|
||||
date_mode_t operator~() const
|
||||
explicit operator date_conv_mode_t() const
|
||||
{
|
||||
return date_mode_t(~m_mode);
|
||||
return date_conv_mode_t(ulonglong(m_mode) & date_conv_mode_t::KNOWN_MODES);
|
||||
}
|
||||
explicit operator time_round_mode_t() const
|
||||
{
|
||||
return time_round_mode_t(ulonglong(m_mode) & time_round_mode_t::KNOWN_MODES);
|
||||
}
|
||||
// Unary operators
|
||||
ulonglong operator~() const
|
||||
{
|
||||
return ~m_mode;
|
||||
}
|
||||
bool operator!() const
|
||||
{
|
||||
return !m_mode;
|
||||
}
|
||||
|
||||
// Dyadic bitwise operators
|
||||
@ -76,6 +233,10 @@ public:
|
||||
{
|
||||
return date_mode_t(m_mode & other.m_mode);
|
||||
}
|
||||
date_mode_t operator&(ulonglong other) const
|
||||
{
|
||||
return date_mode_t(m_mode & other);
|
||||
}
|
||||
|
||||
date_mode_t operator|(const date_mode_t &other) const
|
||||
{
|
||||
@ -94,22 +255,81 @@ public:
|
||||
m_mode= value_t(m_mode | other.m_mode);
|
||||
return *this;
|
||||
}
|
||||
|
||||
date_mode_t &operator|=(const date_conv_mode_t &other)
|
||||
{
|
||||
m_mode= value_t(m_mode | ulonglong(other));
|
||||
return *this;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
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);
|
||||
// Bitwise OR out-of-class operators for data type mixtures
|
||||
static inline date_mode_t operator|(const date_mode_t &a,
|
||||
const date_conv_mode_t &b)
|
||||
{
|
||||
return date_mode_t(ulonglong(a) | ulonglong(b));
|
||||
}
|
||||
|
||||
static inline date_mode_t operator|(const date_conv_mode_t &a,
|
||||
const time_round_mode_t &b)
|
||||
{
|
||||
return date_mode_t(ulonglong(a) | ulonglong(b));
|
||||
}
|
||||
|
||||
|
||||
static inline date_mode_t operator|(const date_conv_mode_t &a,
|
||||
const date_mode_t &b)
|
||||
{
|
||||
return date_mode_t(ulonglong(a) | ulonglong(b));
|
||||
}
|
||||
|
||||
|
||||
// Bitwise AND out-of-class operators for data type mixtures
|
||||
static inline date_conv_mode_t operator&(const date_mode_t &a,
|
||||
const date_conv_mode_t &b)
|
||||
{
|
||||
return date_conv_mode_t(ulonglong(a) & ulonglong(b));
|
||||
}
|
||||
|
||||
static inline date_conv_mode_t operator&(const date_conv_mode_t &a,
|
||||
const date_mode_t &b)
|
||||
{
|
||||
return date_conv_mode_t(ulonglong(a) & ulonglong(b));
|
||||
}
|
||||
|
||||
static inline date_conv_mode_t operator&(sql_mode_t &a,
|
||||
const date_conv_mode_t &b)
|
||||
{
|
||||
return date_conv_mode_t(a & ulonglong(b));
|
||||
}
|
||||
|
||||
|
||||
static const date_conv_mode_t
|
||||
TIME_CONV_NONE (date_conv_mode_t::CONV_NONE),
|
||||
TIME_FUZZY_DATES (date_conv_mode_t::FUZZY_DATES),
|
||||
TIME_TIME_ONLY (date_conv_mode_t::TIME_ONLY),
|
||||
TIME_INTERVAL_hhmmssff (date_conv_mode_t::INTERVAL_hhmmssff),
|
||||
TIME_INTERVAL_DAY (date_conv_mode_t::INTERVAL_DAY),
|
||||
TIME_NO_ZERO_IN_DATE (date_conv_mode_t::NO_ZERO_IN_DATE),
|
||||
TIME_NO_ZERO_DATE (date_conv_mode_t::NO_ZERO_DATE),
|
||||
TIME_INVALID_DATES (date_conv_mode_t::INVALID_DATES);
|
||||
|
||||
// An often used combination
|
||||
static const date_conv_mode_t
|
||||
TIME_NO_ZEROS (date_conv_mode_t::NO_ZERO_DATE|
|
||||
date_conv_mode_t::NO_ZERO_IN_DATE);
|
||||
|
||||
// Flags understood by str_to_xxx, number_to_xxx, check_date
|
||||
static const date_mode_t
|
||||
static const date_conv_mode_t
|
||||
TIME_MODE_FOR_XXX_TO_DATE (date_mode_t::NO_ZERO_IN_DATE |
|
||||
date_mode_t::NO_ZERO_DATE |
|
||||
date_mode_t::INVALID_DATES);
|
||||
|
||||
static const time_round_mode_t
|
||||
TIME_FRAC_NONE (time_round_mode_t::FRAC_NONE),
|
||||
TIME_FRAC_TRUNCATE (time_round_mode_t::FRAC_TRUNCATE),
|
||||
TIME_FRAC_ROUND (time_round_mode_t::FRAC_ROUND);
|
||||
|
||||
|
||||
#endif
|
||||
|
@ -158,6 +158,7 @@ enum enum_binlog_row_image {
|
||||
#define MODE_PAD_CHAR_TO_FULL_LENGTH (1ULL << 31)
|
||||
#define MODE_EMPTY_STRING_IS_NULL (1ULL << 32)
|
||||
#define MODE_SIMULTANEOUS_ASSIGNMENT (1ULL << 33)
|
||||
#define MODE_TIME_ROUND_FRACTIONAL (1ULL << 34)
|
||||
|
||||
/* Bits for different old style modes */
|
||||
#define OLD_MODE_NO_DUP_KEY_WARNINGS_WITH_IGNORE (1 << 0)
|
||||
@ -3419,6 +3420,11 @@ public:
|
||||
{
|
||||
return Timeval(query_start(), query_start_sec_part());
|
||||
}
|
||||
time_round_mode_t temporal_round_mode() const
|
||||
{
|
||||
return variables.sql_mode & MODE_TIME_ROUND_FRACTIONAL ?
|
||||
TIME_FRAC_ROUND : TIME_FRAC_TRUNCATE;
|
||||
}
|
||||
|
||||
private:
|
||||
struct {
|
||||
@ -4957,13 +4963,17 @@ my_eof(THD *thd)
|
||||
(A)->variables.sql_log_bin_off= 0;}
|
||||
|
||||
|
||||
inline date_mode_t sql_mode_for_dates(THD *thd)
|
||||
inline date_conv_mode_t sql_mode_for_dates(THD *thd)
|
||||
{
|
||||
static_assert((date_conv_mode_t::KNOWN_MODES &
|
||||
time_round_mode_t::KNOWN_MODES) == 0,
|
||||
"date_conv_mode_t and time_round_mode_t must use different "
|
||||
"bit values");
|
||||
static_assert(MODE_NO_ZERO_DATE == date_mode_t::NO_ZERO_DATE &&
|
||||
MODE_NO_ZERO_IN_DATE == date_mode_t::NO_ZERO_IN_DATE &&
|
||||
MODE_INVALID_DATES == date_mode_t::INVALID_DATES,
|
||||
"sql_mode_t and date_mode_t values must be equal");
|
||||
return date_mode_t(thd->variables.sql_mode &
|
||||
return date_conv_mode_t(thd->variables.sql_mode &
|
||||
(MODE_NO_ZERO_DATE | MODE_NO_ZERO_IN_DATE | MODE_INVALID_DATES));
|
||||
}
|
||||
|
||||
|
@ -8217,6 +8217,7 @@ static int get_part_iter_for_interval_via_mapping(partition_info *part_info,
|
||||
field->type() == MYSQL_TYPE_DATETIME))
|
||||
{
|
||||
/* Monotonic, but return NULL for dates with zeros in month/day. */
|
||||
DBUG_ASSERT(field->cmp_type() == TIME_RESULT); // No rounding/truncation
|
||||
zero_in_start_date= field->get_date(&start_date, date_mode_t(0));
|
||||
DBUG_PRINT("info", ("zero start %u %04d-%02d-%02d",
|
||||
zero_in_start_date, start_date.year,
|
||||
@ -8241,6 +8242,7 @@ static int get_part_iter_for_interval_via_mapping(partition_info *part_info,
|
||||
!part_info->part_expr->null_value)
|
||||
{
|
||||
MYSQL_TIME end_date;
|
||||
DBUG_ASSERT(field->cmp_type() == TIME_RESULT); // No rounding/truncation
|
||||
bool zero_in_end_date= field->get_date(&end_date, date_mode_t(0));
|
||||
/*
|
||||
This is an optimization for TO_DAYS()/TO_SECONDS() to avoid scanning
|
||||
|
@ -289,8 +289,8 @@ ulong convert_month_to_period(ulong month)
|
||||
|
||||
|
||||
bool
|
||||
check_date_with_warn(THD *thd, const MYSQL_TIME *ltime, date_mode_t fuzzydate,
|
||||
timestamp_type ts_type)
|
||||
check_date_with_warn(THD *thd, const MYSQL_TIME *ltime,
|
||||
date_conv_mode_t fuzzydate, timestamp_type ts_type)
|
||||
{
|
||||
int unused;
|
||||
if (check_date(ltime, fuzzydate, &unused))
|
||||
@ -372,34 +372,37 @@ public:
|
||||
|
||||
|
||||
/* 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,
|
||||
bool Temporal::str_to_datetime_or_date_or_time(THD *thd, MYSQL_TIME_STATUS *st,
|
||||
const char *str, size_t length,
|
||||
CHARSET_INFO *cs,
|
||||
date_mode_t fuzzydate)
|
||||
{
|
||||
TemporalAsciiBuffer tmp(str, length, cs);
|
||||
return ascii_to_datetime_or_date_or_time(st, tmp.str, tmp.length, fuzzydate);
|
||||
return ascii_to_datetime_or_date_or_time(st, tmp.str, tmp.length, fuzzydate)||
|
||||
add_nanoseconds(thd, &st->warnings, fuzzydate, st->nanoseconds);
|
||||
}
|
||||
|
||||
|
||||
/* Character set-aware version of str_to_datetime_or_date() */
|
||||
bool Temporal::str_to_datetime_or_date(MYSQL_TIME_STATUS *status,
|
||||
bool Temporal::str_to_datetime_or_date(THD *thd, 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_datetime_or_date(status, tmp.str, tmp.length, flags);
|
||||
return ascii_to_datetime_or_date(status, tmp.str, tmp.length, flags) ||
|
||||
add_nanoseconds(thd, &status->warnings, flags, status->nanoseconds);
|
||||
}
|
||||
|
||||
|
||||
/* Character set-aware version of ascii_to_temporal() */
|
||||
bool Temporal::str_to_temporal(MYSQL_TIME_STATUS *status,
|
||||
bool Temporal::str_to_temporal(THD *thd, 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);
|
||||
return ascii_to_temporal(status, tmp.str, tmp.length, flags) ||
|
||||
add_nanoseconds(thd, &status->warnings, flags, status->nanoseconds);
|
||||
}
|
||||
|
||||
|
||||
@ -1307,7 +1310,7 @@ time_to_datetime(THD *thd, const MYSQL_TIME *from, MYSQL_TIME *to)
|
||||
bool
|
||||
time_to_datetime_with_warn(THD *thd,
|
||||
const MYSQL_TIME *from, MYSQL_TIME *to,
|
||||
date_mode_t fuzzydate)
|
||||
date_conv_mode_t fuzzydate)
|
||||
{
|
||||
int warn= 0;
|
||||
DBUG_ASSERT(from->time_type == MYSQL_TIMESTAMP_TIME);
|
||||
|
@ -57,7 +57,7 @@ bool int_to_datetime_with_warn(THD *thd, const Longlong_hybrid &nr,
|
||||
bool time_to_datetime(THD *thd, const MYSQL_TIME *tm, MYSQL_TIME *dt);
|
||||
bool time_to_datetime_with_warn(THD *thd,
|
||||
const MYSQL_TIME *tm, MYSQL_TIME *dt,
|
||||
date_mode_t fuzzydate);
|
||||
date_conv_mode_t fuzzydate);
|
||||
|
||||
inline void datetime_to_date(MYSQL_TIME *ltime)
|
||||
{
|
||||
@ -166,13 +166,20 @@ non_zero_date(const MYSQL_TIME *ltime)
|
||||
non_zero_hhmmssuu(ltime));
|
||||
}
|
||||
static inline bool
|
||||
check_date(const MYSQL_TIME *ltime, date_mode_t flags, int *was_cut)
|
||||
check_date(const MYSQL_TIME *ltime, date_conv_mode_t flags, int *was_cut)
|
||||
{
|
||||
return check_date(ltime, non_zero_date(ltime),
|
||||
ulonglong(flags & TIME_MODE_FOR_XXX_TO_DATE), was_cut);
|
||||
}
|
||||
bool check_date_with_warn(THD *thd, const MYSQL_TIME *ltime, date_mode_t fuzzy_date,
|
||||
timestamp_type ts_type);
|
||||
bool check_date_with_warn(THD *thd, const MYSQL_TIME *ltime,
|
||||
date_conv_mode_t fuzzy_date, timestamp_type ts_type);
|
||||
static inline bool
|
||||
check_date_with_warn(THD *thd, const MYSQL_TIME *ltime,
|
||||
date_mode_t fuzzydate, timestamp_type ts_type)
|
||||
{
|
||||
return check_date_with_warn(thd, ltime, date_conv_mode_t(fuzzydate), ts_type);
|
||||
}
|
||||
|
||||
bool adjust_time_range_with_warn(THD *thd, MYSQL_TIME *ltime, uint dec);
|
||||
|
||||
longlong pack_time(const MYSQL_TIME *my_time);
|
||||
|
282
sql/sql_type.cc
282
sql/sql_type.cc
@ -156,12 +156,24 @@ VDec_op::VDec_op(Item_func_hybrid_field_type *item)
|
||||
}
|
||||
|
||||
|
||||
date_mode_t Temporal::sql_mode_for_dates(THD *thd)
|
||||
date_conv_mode_t Temporal::sql_mode_for_dates(THD *thd)
|
||||
{
|
||||
return ::sql_mode_for_dates(thd);
|
||||
}
|
||||
|
||||
|
||||
time_round_mode_t Temporal::default_round_mode(THD *thd)
|
||||
{
|
||||
return thd->temporal_round_mode();
|
||||
}
|
||||
|
||||
|
||||
time_round_mode_t Timestamp::default_round_mode(THD *thd)
|
||||
{
|
||||
return thd->temporal_round_mode();
|
||||
}
|
||||
|
||||
|
||||
my_decimal *Temporal::to_decimal(my_decimal *to) const
|
||||
{
|
||||
return date2my_decimal(this, to);
|
||||
@ -183,8 +195,8 @@ 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 (str_to_temporal(warn, str, length, cs, fuzzydate))
|
||||
make_fuzzy_date(&warn->warnings, fuzzydate);
|
||||
if (str_to_temporal(thd, warn, str, length, cs, fuzzydate))
|
||||
make_fuzzy_date(&warn->warnings, date_conv_mode_t(fuzzydate));
|
||||
if (warn->warnings)
|
||||
warn->set_str(str, length, &my_charset_bin);
|
||||
}
|
||||
@ -197,14 +209,14 @@ Temporal_hybrid::Temporal_hybrid(THD *thd, Item *item, date_mode_t fuzzydate)
|
||||
}
|
||||
|
||||
|
||||
void Sec6::make_from_decimal(const my_decimal *d)
|
||||
void Sec6::make_from_decimal(const my_decimal *d, ulong *nanoseconds)
|
||||
{
|
||||
m_neg= my_decimal2seconds(d, &m_sec, &m_usec);
|
||||
m_neg= my_decimal2seconds(d, &m_sec, &m_usec, nanoseconds);
|
||||
m_truncated= (m_sec >= LONGLONG_MAX);
|
||||
}
|
||||
|
||||
|
||||
void Sec6::make_from_double(double nr)
|
||||
void Sec6::make_from_double(double nr, ulong *nanoseconds)
|
||||
{
|
||||
if ((m_neg= nr < 0))
|
||||
nr= -nr;
|
||||
@ -216,7 +228,9 @@ void Sec6::make_from_double(double nr)
|
||||
else
|
||||
{
|
||||
m_sec= (ulonglong) nr;
|
||||
m_usec= (ulong) ((nr - floor(nr)) * 1000000);
|
||||
m_usec= (ulong) ((nr - floor(nr)) * 1000000000);
|
||||
*nanoseconds= m_usec % 1000;
|
||||
m_usec/= 1000;
|
||||
}
|
||||
}
|
||||
|
||||
@ -235,8 +249,8 @@ bool Sec6::convert_to_mysql_time(THD *thd, int *warn, MYSQL_TIME *ltime,
|
||||
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);
|
||||
to_datetime_or_time(ltime, warn, date_conv_mode_t(fuzzydate)) :
|
||||
to_datetime_or_date(ltime, warn, date_conv_mode_t(fuzzydate));
|
||||
DBUG_ASSERT(*warn || !rc);
|
||||
if (truncated())
|
||||
*warn|= MYSQL_TIME_WARN_TRUNCATED;
|
||||
@ -259,7 +273,7 @@ void Temporal::push_conversion_warnings(THD *thd, bool totally_useless_value, in
|
||||
}
|
||||
|
||||
|
||||
VSec6::VSec6(THD *thd, Item *item, const char *type_str, ulonglong limit)
|
||||
VSec9::VSec9(THD *thd, Item *item, const char *type_str, ulonglong limit)
|
||||
{
|
||||
if (item->decimals == 0)
|
||||
{ // optimize for an important special case
|
||||
@ -277,7 +291,7 @@ VSec6::VSec6(THD *thd, Item *item, const char *type_str, ulonglong limit)
|
||||
else if (item->cmp_type() == REAL_RESULT)
|
||||
{
|
||||
double nr= item->val_real();
|
||||
make_from_double(nr);
|
||||
make_from_double(nr, &m_nsec);
|
||||
m_is_null= item->null_value;
|
||||
if (!m_is_null && m_sec > limit)
|
||||
{
|
||||
@ -293,7 +307,7 @@ VSec6::VSec6(THD *thd, Item *item, const char *type_str, ulonglong limit)
|
||||
else
|
||||
{
|
||||
VDec tmp(item);
|
||||
(m_is_null= tmp.is_null()) ? reset() : make_from_decimal(tmp.ptr());
|
||||
(m_is_null= tmp.is_null()) ? reset() : make_from_decimal(tmp.ptr(), &m_nsec);
|
||||
if (!m_is_null && m_sec > limit)
|
||||
{
|
||||
m_sec= limit;
|
||||
@ -352,7 +366,8 @@ const LEX_CSTRING Interval_DDhhmmssff::m_type_name=
|
||||
|
||||
Interval_DDhhmmssff::Interval_DDhhmmssff(THD *thd, Status *st,
|
||||
bool push_warnings,
|
||||
Item *item, ulong max_hour)
|
||||
Item *item, ulong max_hour,
|
||||
time_round_mode_t mode, uint dec)
|
||||
{
|
||||
switch (item->cmp_type()) {
|
||||
case ROW_RESULT:
|
||||
@ -361,7 +376,8 @@ Interval_DDhhmmssff::Interval_DDhhmmssff(THD *thd, Status *st,
|
||||
break;
|
||||
case TIME_RESULT:
|
||||
{
|
||||
if (item->get_date(thd, this, TIME_TIME_ONLY))
|
||||
// Rounding mode is not important here
|
||||
if (item->get_date(thd, this, Options(TIME_TIME_ONLY, TIME_FRAC_NONE)))
|
||||
time_type= MYSQL_TIMESTAMP_NONE;
|
||||
else if (time_type != MYSQL_TIMESTAMP_TIME)
|
||||
{
|
||||
@ -392,6 +408,8 @@ Interval_DDhhmmssff::Interval_DDhhmmssff(THD *thd, Status *st,
|
||||
}
|
||||
else
|
||||
{
|
||||
if (mode == TIME_FRAC_ROUND)
|
||||
time_round_or_set_max(dec, &st->warnings, max_hour, st->nanoseconds);
|
||||
if (hour > max_hour)
|
||||
{
|
||||
st->warnings|= MYSQL_TIME_WARN_OUT_OF_RANGE;
|
||||
@ -450,7 +468,8 @@ uint Interval_DDhhmmssff::fsp(THD *thd, Item *item)
|
||||
if (!item->const_item() || item->is_expensive())
|
||||
return TIME_SECOND_PART_DIGITS;
|
||||
Status st;
|
||||
Interval_DDhhmmssff it(thd, &st, false/*no warnings*/, item, UINT_MAX32);
|
||||
Interval_DDhhmmssff it(thd, &st, false/*no warnings*/, item, UINT_MAX32,
|
||||
TIME_FRAC_TRUNCATE, TIME_SECOND_PART_DIGITS);
|
||||
return it.is_valid_interval_DDhhmmssff() ? st.precision :
|
||||
TIME_SECOND_PART_DIGITS;
|
||||
}
|
||||
@ -459,13 +478,101 @@ uint Interval_DDhhmmssff::fsp(THD *thd, Item *item)
|
||||
void Time::make_from_item(THD *thd, int *warn, Item *item, const Options opt)
|
||||
{
|
||||
*warn= 0;
|
||||
if (item->get_date(thd, this, opt.get_date_flags()))
|
||||
if (item->get_date(thd, this, opt))
|
||||
time_type= MYSQL_TIMESTAMP_NONE;
|
||||
else
|
||||
valid_MYSQL_TIME_to_valid_value(thd, warn, opt);
|
||||
}
|
||||
|
||||
|
||||
static uint msec_round_add[7]=
|
||||
{
|
||||
500000000,
|
||||
50000000,
|
||||
5000000,
|
||||
500000,
|
||||
50000,
|
||||
5000,
|
||||
0
|
||||
};
|
||||
|
||||
|
||||
Sec9 & Sec9::round(uint dec)
|
||||
{
|
||||
DBUG_ASSERT(dec <= TIME_SECOND_PART_DIGITS);
|
||||
if (Sec6::add_nanoseconds(m_nsec + msec_round_add[dec]))
|
||||
m_sec++;
|
||||
m_nsec= 0;
|
||||
Sec6::trunc(dec);
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
void Timestamp::round_or_set_max(uint dec, int *warn)
|
||||
{
|
||||
DBUG_ASSERT(dec <= TIME_SECOND_PART_DIGITS);
|
||||
if (add_nanoseconds_usec(msec_round_add[dec]) &&
|
||||
tv_sec++ >= TIMESTAMP_MAX_VALUE)
|
||||
{
|
||||
tv_sec= TIMESTAMP_MAX_VALUE;
|
||||
tv_usec= TIME_MAX_SECOND_PART;
|
||||
*warn|= MYSQL_TIME_WARN_OUT_OF_RANGE;
|
||||
}
|
||||
my_timeval_trunc(this, dec);
|
||||
}
|
||||
|
||||
|
||||
bool Temporal::add_nanoseconds_with_round(THD *thd, int *warn,
|
||||
date_conv_mode_t mode,
|
||||
ulong nsec)
|
||||
{
|
||||
switch (time_type) {
|
||||
case MYSQL_TIMESTAMP_TIME:
|
||||
{
|
||||
ulong max_hour= (mode & (TIME_INTERVAL_DAY | TIME_INTERVAL_hhmmssff)) ?
|
||||
TIME_MAX_INTERVAL_HOUR : TIME_MAX_HOUR;
|
||||
time_round_or_set_max(6, warn, max_hour, nsec);
|
||||
return false;
|
||||
}
|
||||
case MYSQL_TIMESTAMP_DATETIME:
|
||||
return datetime_round_or_invalidate(thd, 6, warn, nsec);
|
||||
case MYSQL_TIMESTAMP_DATE:
|
||||
return false;
|
||||
case MYSQL_TIMESTAMP_NONE:
|
||||
return false;
|
||||
case MYSQL_TIMESTAMP_ERROR:
|
||||
break;
|
||||
}
|
||||
DBUG_ASSERT(0);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
void Temporal::time_round_or_set_max(uint dec, int *warn,
|
||||
ulong max_hour, ulong nsec)
|
||||
{
|
||||
DBUG_ASSERT(dec <= TIME_SECOND_PART_DIGITS);
|
||||
if (add_nanoseconds_mmssff(nsec) && ++hour > max_hour)
|
||||
{
|
||||
time_hhmmssff_set_max(max_hour);
|
||||
*warn|= MYSQL_TIME_WARN_OUT_OF_RANGE;
|
||||
}
|
||||
my_time_trunc(this, dec);
|
||||
}
|
||||
|
||||
|
||||
void Time::round_or_set_max(uint dec, int *warn, ulong nsec)
|
||||
{
|
||||
Temporal::time_round_or_set_max(dec, warn, TIME_MAX_HOUR, nsec);
|
||||
DBUG_ASSERT(is_valid_time_slow());
|
||||
}
|
||||
|
||||
|
||||
void Time::round_or_set_max(uint dec, int *warn)
|
||||
{
|
||||
round_or_set_max(dec, warn, msec_round_add[dec]);
|
||||
}
|
||||
|
||||
/**
|
||||
Create from a DATETIME by subtracting a given number of days,
|
||||
implementing an optimized version of calc_time_diff().
|
||||
@ -586,9 +693,10 @@ Time::Time(int *warn, bool neg, ulonglong hour, uint minute, const Sec6 &second)
|
||||
}
|
||||
|
||||
|
||||
void Temporal_with_date::make_from_item(THD *thd, Item *item, date_mode_t flags)
|
||||
void Temporal_with_date::make_from_item(THD *thd, Item *item,
|
||||
date_mode_t fuzzydate)
|
||||
{
|
||||
flags&= ~TIME_TIME_ONLY;
|
||||
date_conv_mode_t flags= date_conv_mode_t(fuzzydate) & ~TIME_TIME_ONLY;
|
||||
/*
|
||||
Some TIME type items return error when trying to do get_date()
|
||||
without TIME_TIME_ONLY set (e.g. Item_field for Field_time).
|
||||
@ -596,10 +704,11 @@ void Temporal_with_date::make_from_item(THD *thd, Item *item, date_mode_t flags)
|
||||
In the legacy time->datetime conversion mode we do not add TIME_TIME_ONLY
|
||||
and leave it to get_date() to check date.
|
||||
*/
|
||||
date_mode_t time_flag= (item->field_type() == MYSQL_TYPE_TIME &&
|
||||
date_conv_mode_t time_flag= (item->field_type() == MYSQL_TYPE_TIME &&
|
||||
!(thd->variables.old_behavior & OLD_MODE_ZERO_DATE_TIME_CAST)) ?
|
||||
TIME_TIME_ONLY : date_mode_t(0);
|
||||
if (item->get_date(thd, this, flags | time_flag))
|
||||
TIME_TIME_ONLY : TIME_CONV_NONE;
|
||||
Options opt(flags | time_flag, time_round_mode_t(fuzzydate));
|
||||
if (item->get_date(thd, this, opt))
|
||||
time_type= MYSQL_TIMESTAMP_NONE;
|
||||
else if (time_type == MYSQL_TIMESTAMP_TIME)
|
||||
{
|
||||
@ -612,22 +721,17 @@ void Temporal_with_date::make_from_item(THD *thd, Item *item, date_mode_t flags)
|
||||
}
|
||||
|
||||
|
||||
void Temporal_with_date::make_from_item(THD *thd, Item *item)
|
||||
void Temporal_with_date::check_date_or_invalidate(int *warn,
|
||||
date_conv_mode_t flags)
|
||||
{
|
||||
return make_from_item(thd, item, sql_mode_for_dates(thd));
|
||||
}
|
||||
|
||||
|
||||
void Temporal_with_date::check_date_or_invalidate(int *warn, date_mode_t flags)
|
||||
{
|
||||
if (check_date(this, pack_time(this) != 0,
|
||||
ulonglong(flags & TIME_MODE_FOR_XXX_TO_DATE), warn))
|
||||
if (::check_date(this, pack_time(this) != 0,
|
||||
ulonglong(flags & TIME_MODE_FOR_XXX_TO_DATE), warn))
|
||||
time_type= MYSQL_TIMESTAMP_NONE;
|
||||
}
|
||||
|
||||
|
||||
void Datetime::make_from_time(THD *thd, int *warn, const MYSQL_TIME *from,
|
||||
date_mode_t flags)
|
||||
date_conv_mode_t flags)
|
||||
{
|
||||
DBUG_ASSERT(from->time_type == MYSQL_TIMESTAMP_TIME);
|
||||
if (time_to_datetime(thd, from, this))
|
||||
@ -641,7 +745,7 @@ void Datetime::make_from_time(THD *thd, int *warn, const MYSQL_TIME *from,
|
||||
|
||||
|
||||
void Datetime::make_from_datetime(THD *thd, int *warn, const MYSQL_TIME *from,
|
||||
date_mode_t flags)
|
||||
date_conv_mode_t flags)
|
||||
{
|
||||
DBUG_ASSERT(from->time_type == MYSQL_TIMESTAMP_DATE ||
|
||||
from->time_type == MYSQL_TIMESTAMP_DATETIME);
|
||||
@ -667,7 +771,7 @@ Datetime::Datetime(THD *thd, const timeval &tv)
|
||||
|
||||
|
||||
Datetime::Datetime(THD *thd, int *warn, const MYSQL_TIME *from,
|
||||
date_mode_t flags)
|
||||
date_conv_mode_t flags)
|
||||
{
|
||||
DBUG_ASSERT(bool(flags & TIME_TIME_ONLY) == false);
|
||||
switch (from->time_type) {
|
||||
@ -687,6 +791,82 @@ Datetime::Datetime(THD *thd, int *warn, const MYSQL_TIME *from,
|
||||
}
|
||||
|
||||
|
||||
bool Temporal::datetime_add_nanoseconds_or_invalidate(THD *thd, int *warn, ulong nsec)
|
||||
{
|
||||
if (!add_nanoseconds_mmssff(nsec))
|
||||
return false;
|
||||
/*
|
||||
Overflow happened on minutes. Now we need to add 1 hour to the value.
|
||||
Catch a special case for the maximum possible date and hour==23, to
|
||||
truncate '9999-12-31 23:59:59.9999999' (with 7 fractional digits)
|
||||
to '9999-12-31 23:59:59.999999' (with 6 fractional digits),
|
||||
with a warning, instead of returning an error, so this statement:
|
||||
INSERT INTO (datetime_column) VALUES ('9999-12-31 23:59:59.9999999');
|
||||
inserts a value truncated to 6 fractional digits, instead of zero
|
||||
date '0000-00-00 00:00:00.000000'.
|
||||
*/
|
||||
if (year == 9999 && month == 12 && day == 31 && hour == 23)
|
||||
{
|
||||
minute= 59;
|
||||
second= 59;
|
||||
second_part= 999999;
|
||||
*warn= MYSQL_TIME_WARN_OUT_OF_RANGE;
|
||||
return false;
|
||||
}
|
||||
INTERVAL interval;
|
||||
memset(&interval, 0, sizeof(interval));
|
||||
interval.hour= 1;
|
||||
/* date_add_interval cannot handle bad dates */
|
||||
if (check_date(TIME_NO_ZERO_IN_DATE | TIME_NO_ZERO_DATE, warn) ||
|
||||
date_add_interval(thd, this, INTERVAL_HOUR, interval))
|
||||
{
|
||||
make_from_out_of_range(warn);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool Temporal::datetime_round_or_invalidate(THD *thd, uint dec, int *warn, ulong nsec)
|
||||
{
|
||||
DBUG_ASSERT(dec <= TIME_SECOND_PART_DIGITS);
|
||||
if (datetime_add_nanoseconds_or_invalidate(thd, warn, nsec))
|
||||
return true;
|
||||
my_time_trunc(this, dec);
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
|
||||
bool Datetime::round_or_invalidate(THD *thd, uint dec, int *warn)
|
||||
{
|
||||
return round_or_invalidate(thd, dec, warn, msec_round_add[dec]);
|
||||
}
|
||||
|
||||
|
||||
Datetime_from_temporal::Datetime_from_temporal(THD *thd, Item *temporal,
|
||||
date_conv_mode_t fuzzydate)
|
||||
:Datetime(thd, temporal, Options(fuzzydate, TIME_FRAC_NONE))
|
||||
{
|
||||
// Exact rounding mode does not matter
|
||||
DBUG_ASSERT(temporal->cmp_type() == TIME_RESULT);
|
||||
}
|
||||
|
||||
|
||||
Datetime_truncation_not_needed::Datetime_truncation_not_needed(THD *thd, Item *item,
|
||||
date_conv_mode_t mode)
|
||||
:Datetime(thd, item, Options(mode, TIME_FRAC_NONE))
|
||||
{
|
||||
/*
|
||||
The called Datetime() constructor only would truncate nanoseconds if they
|
||||
existed (but we know there were no nanoseconds). Here we assert that there
|
||||
are also no microsecond digits outside of the scale specified in "dec".
|
||||
*/
|
||||
DBUG_ASSERT(!is_valid_datetime() || fraction_remainder(item->decimals) == 0);
|
||||
}
|
||||
|
||||
/********************************************************************/
|
||||
|
||||
uint Type_std_attributes::count_max_decimals(Item **item, uint nitems)
|
||||
{
|
||||
uint res= 0;
|
||||
@ -3151,14 +3331,16 @@ void Type_handler_row::Item_update_null_value(Item *item) const
|
||||
void Type_handler_time_common::Item_update_null_value(Item *item) const
|
||||
{
|
||||
MYSQL_TIME ltime;
|
||||
(void) item->get_date(current_thd, <ime, TIME_TIME_ONLY);
|
||||
THD *thd= current_thd;
|
||||
(void) item->get_date(thd, <ime, Time::Options(TIME_TIME_ONLY, thd));
|
||||
}
|
||||
|
||||
|
||||
void Type_handler_temporal_with_date::Item_update_null_value(Item *item) const
|
||||
{
|
||||
MYSQL_TIME ltime;
|
||||
(void) item->get_date(current_thd, <ime, sql_mode_for_dates(current_thd));
|
||||
THD *thd= current_thd;
|
||||
(void) item->get_date(thd, <ime, Datetime::Options(thd));
|
||||
}
|
||||
|
||||
|
||||
@ -5013,7 +5195,7 @@ bool Type_handler_temporal_result::
|
||||
*/
|
||||
return func->get_date_native(thd, ltime,
|
||||
fuzzydate & TIME_TIME_ONLY ?
|
||||
sql_mode_for_dates(thd) :
|
||||
Datetime::Options(thd) :
|
||||
fuzzydate);
|
||||
}
|
||||
|
||||
@ -5847,14 +6029,15 @@ uint Type_handler_string_result::Item_temporal_precision(THD *thd, Item *item,
|
||||
String *tmp;
|
||||
MYSQL_TIME_STATUS status;
|
||||
DBUG_ASSERT(item->is_fixed());
|
||||
// Nanosecond rounding is not needed here, for performance purposes
|
||||
if ((tmp= item->val_str(&buf)) &&
|
||||
(is_time ?
|
||||
Time(thd, &status, tmp->ptr(), tmp->length(), tmp->charset(),
|
||||
Time::Options(TIME_TIME_ONLY,
|
||||
Time::Options(TIME_TIME_ONLY, TIME_FRAC_TRUNCATE,
|
||||
Time::DATETIME_TO_TIME_YYYYMMDD_TRUNCATE)).
|
||||
is_valid_time() :
|
||||
Datetime(&status, tmp->ptr(), tmp->length(), tmp->charset(),
|
||||
TIME_FUZZY_DATES).
|
||||
Datetime(thd, &status, tmp->ptr(), tmp->length(), tmp->charset(),
|
||||
Datetime::Options(TIME_FUZZY_DATES, TIME_FRAC_TRUNCATE)).
|
||||
is_valid_datetime()))
|
||||
return MY_MIN(status.precision, TIME_SECOND_PART_DIGITS);
|
||||
return MY_MIN(item->decimals, TIME_SECOND_PART_DIGITS);
|
||||
@ -6104,7 +6287,8 @@ bool Type_handler_temporal_with_date::
|
||||
Item_save_in_value(THD *thd, Item *item, st_value *value) const
|
||||
{
|
||||
value->m_type= DYN_COL_DATETIME;
|
||||
item->get_date(thd, &value->value.m_time, sql_mode_for_dates(thd));
|
||||
item->get_date(thd, &value->value.m_time,
|
||||
Datetime::Options(thd, TIME_FRAC_NONE));
|
||||
return check_null(item, value);
|
||||
}
|
||||
|
||||
@ -6298,7 +6482,7 @@ bool Type_handler::
|
||||
Item_send_datetime(Item *item, Protocol *protocol, st_value *buf) const
|
||||
{
|
||||
item->get_date(protocol->thd, &buf->value.m_time,
|
||||
sql_mode_for_dates(protocol->thd));
|
||||
Datetime::Options(protocol->thd));
|
||||
if (!item->null_value)
|
||||
return protocol->store(&buf->value.m_time, item->decimals);
|
||||
return protocol->store_null();
|
||||
@ -6309,7 +6493,7 @@ bool Type_handler::
|
||||
Item_send_date(Item *item, Protocol *protocol, st_value *buf) const
|
||||
{
|
||||
item->get_date(protocol->thd, &buf->value.m_time,
|
||||
sql_mode_for_dates(protocol->thd));
|
||||
Date::Options(protocol->thd));
|
||||
if (!item->null_value)
|
||||
return protocol->store_date(&buf->value.m_time);
|
||||
return protocol->store_null();
|
||||
@ -7502,8 +7686,8 @@ int Type_handler_temporal_with_date::stored_field_cmp_to_item(THD *thd,
|
||||
Item *item) const
|
||||
{
|
||||
MYSQL_TIME field_time, item_time, item_time2, *item_time_cmp= &item_time;
|
||||
field->get_date(&field_time, TIME_INVALID_DATES);
|
||||
item->get_date(thd, &item_time, TIME_INVALID_DATES);
|
||||
field->get_date(&field_time, Datetime::Options(TIME_INVALID_DATES, thd));
|
||||
item->get_date(thd, &item_time, Datetime::Options(TIME_INVALID_DATES, thd));
|
||||
if (item_time.time_type == MYSQL_TIMESTAMP_TIME &&
|
||||
time_to_datetime(thd, &item_time, item_time_cmp= &item_time2))
|
||||
return 1;
|
||||
@ -7516,8 +7700,8 @@ int Type_handler_time_common::stored_field_cmp_to_item(THD *thd,
|
||||
Item *item) const
|
||||
{
|
||||
MYSQL_TIME field_time, item_time;
|
||||
field->get_time(&field_time);
|
||||
item->get_time(thd, &item_time);
|
||||
field->get_date(&field_time, Time::Options(thd));
|
||||
item->get_date(thd, &item_time, Time::Options(thd));
|
||||
return my_time_compare(&field_time, &item_time);
|
||||
}
|
||||
|
||||
@ -7612,7 +7796,7 @@ Type_handler_date_common::create_literal_item(THD *thd,
|
||||
{
|
||||
Temporal::Warn st;
|
||||
Item_literal *item= NULL;
|
||||
Temporal_hybrid tmp(thd, &st, str, length, cs, sql_mode_for_dates(thd));
|
||||
Temporal_hybrid tmp(thd, &st, str, length, cs, Temporal_hybrid::Options(thd));
|
||||
if (tmp.is_valid_temporal() &&
|
||||
tmp.get_mysql_time()->time_type == MYSQL_TIMESTAMP_DATE &&
|
||||
!have_important_literal_warnings(&st))
|
||||
@ -7632,7 +7816,7 @@ Type_handler_temporal_with_date::create_literal_item(THD *thd,
|
||||
{
|
||||
Temporal::Warn st;
|
||||
Item_literal *item= NULL;
|
||||
Temporal_hybrid tmp(thd, &st, str, length, cs, sql_mode_for_dates(thd));
|
||||
Temporal_hybrid tmp(thd, &st, str, length, cs, Temporal_hybrid::Options(thd));
|
||||
if (tmp.is_valid_temporal() &&
|
||||
tmp.get_mysql_time()->time_type == MYSQL_TIMESTAMP_DATETIME &&
|
||||
!have_important_literal_warnings(&st))
|
||||
@ -7653,7 +7837,7 @@ Type_handler_time_common::create_literal_item(THD *thd,
|
||||
{
|
||||
MYSQL_TIME_STATUS st;
|
||||
Item_literal *item= NULL;
|
||||
Time::Options opt(TIME_TIME_ONLY, Time::DATETIME_TO_TIME_DISALLOW);
|
||||
Time::Options opt(TIME_TIME_ONLY, thd, Time::DATETIME_TO_TIME_DISALLOW);
|
||||
Time tmp(thd, &st, str, length, cs, opt);
|
||||
if (tmp.is_valid_time() &&
|
||||
!have_important_literal_warnings(&st))
|
||||
|
687
sql/sql_type.h
687
sql/sql_type.h
File diff suppressed because it is too large
Load Diff
@ -3353,6 +3353,7 @@ static const char *sql_mode_names[]=
|
||||
"ALLOW_INVALID_DATES", "ERROR_FOR_DIVISION_BY_ZERO", "TRADITIONAL",
|
||||
"NO_AUTO_CREATE_USER", "HIGH_NOT_PRECEDENCE", "NO_ENGINE_SUBSTITUTION",
|
||||
"PAD_CHAR_TO_FULL_LENGTH", "EMPTY_STRING_IS_NULL", "SIMULTANEOUS_ASSIGNMENT",
|
||||
"TIME_ROUND_FRACTIONAL",
|
||||
0
|
||||
};
|
||||
|
||||
|
@ -2659,7 +2659,8 @@ public:
|
||||
if (!Sys_var_enum::do_check(thd, var))
|
||||
return false;
|
||||
MYSQL_TIME ltime;
|
||||
bool res= var->value->get_date(thd, <ime, date_mode_t(0));
|
||||
Datetime::Options opt(TIME_CONV_NONE, thd);
|
||||
bool res= var->value->get_date(thd, <ime, opt);
|
||||
if (!res)
|
||||
{
|
||||
var->save_result.ulonglong_value= SYSTEM_TIME_AS_OF;
|
||||
@ -2676,7 +2677,9 @@ private:
|
||||
{
|
||||
if (var->value)
|
||||
{
|
||||
res= var->value->get_date(current_thd, &out.ltime, date_mode_t(0));
|
||||
THD *thd= current_thd;
|
||||
Datetime::Options opt(TIME_CONV_NONE, thd);
|
||||
res= var->value->get_date(thd, &out.ltime, opt);
|
||||
}
|
||||
else // set DEFAULT from global var
|
||||
{
|
||||
|
@ -10576,7 +10576,7 @@ int ha_mroonga::generic_store_bulk_time(Field *field, grn_obj *buf)
|
||||
bool truncated = false;
|
||||
Field_time *time_field = (Field_time *)field;
|
||||
MYSQL_TIME mysql_time;
|
||||
time_field->get_time(&mysql_time);
|
||||
time_field->get_date(&mysql_time, Time::Options(current_thd));
|
||||
mrn::TimeConverter time_converter;
|
||||
long long int time = time_converter.mysql_time_to_grn_time(&mysql_time,
|
||||
&truncated);
|
||||
@ -10596,7 +10596,7 @@ int ha_mroonga::generic_store_bulk_datetime(Field *field, grn_obj *buf)
|
||||
bool truncated = false;
|
||||
Field_datetime *datetime_field = (Field_datetime *)field;
|
||||
MYSQL_TIME mysql_time;
|
||||
datetime_field->get_time(&mysql_time);
|
||||
datetime_field->get_date(&mysql_time, Time::Options(current_thd));
|
||||
mrn::TimeConverter time_converter;
|
||||
long long int time = time_converter.mysql_time_to_grn_time(&mysql_time,
|
||||
&truncated);
|
||||
@ -10657,7 +10657,7 @@ int ha_mroonga::generic_store_bulk_datetime2(Field *field, grn_obj *buf)
|
||||
bool truncated = false;
|
||||
Field_datetimef *datetimef_field = (Field_datetimef *)field;
|
||||
MYSQL_TIME mysql_time;
|
||||
datetimef_field->get_time(&mysql_time);
|
||||
datetimef_field->get_date(&mysql_time, Time::Options(current_thd));
|
||||
mrn::TimeConverter time_converter;
|
||||
long long int time = time_converter.mysql_time_to_grn_time(&mysql_time,
|
||||
&truncated);
|
||||
@ -10682,7 +10682,7 @@ int ha_mroonga::generic_store_bulk_time2(Field *field, grn_obj *buf)
|
||||
int error = 0;
|
||||
bool truncated = false;
|
||||
MYSQL_TIME mysql_time;
|
||||
field->get_time(&mysql_time);
|
||||
field->get_date(&mysql_time, Time::Options(current_thd));
|
||||
mrn::TimeConverter time_converter;
|
||||
long long int time = time_converter.mysql_time_to_grn_time(&mysql_time,
|
||||
&truncated);
|
||||
@ -10707,7 +10707,7 @@ int ha_mroonga::generic_store_bulk_new_date(Field *field, grn_obj *buf)
|
||||
bool truncated = false;
|
||||
Field_newdate *newdate_field = (Field_newdate *)field;
|
||||
MYSQL_TIME mysql_date;
|
||||
newdate_field->get_time(&mysql_date);
|
||||
newdate_field->get_date(&mysql_date, Time::Options(current_thd));
|
||||
mrn::TimeConverter time_converter;
|
||||
long long int time = time_converter.mysql_time_to_grn_time(&mysql_date,
|
||||
&truncated);
|
||||
@ -11617,14 +11617,14 @@ int ha_mroonga::storage_encode_key_timestamp(Field *field, const uchar *key,
|
||||
} else {
|
||||
Field_timestamp_hires *timestamp_hires_field =
|
||||
(Field_timestamp_hires *)field;
|
||||
uint fuzzy_date = 0;
|
||||
uchar *ptr_backup = field->ptr;
|
||||
uchar *null_ptr_backup = field->null_ptr;
|
||||
TABLE *table_backup = field->table;
|
||||
field->ptr = (uchar *)key;
|
||||
field->null_ptr = (uchar *)(key - 1);
|
||||
field->table = table;
|
||||
timestamp_hires_field->get_date(&mysql_time, date_mode_t(fuzzy_date));
|
||||
Temporal::Options opt(TIME_CONV_NONE, current_thd);
|
||||
timestamp_hires_field->get_date(&mysql_time, opt);
|
||||
field->ptr = ptr_backup;
|
||||
field->null_ptr = null_ptr_backup;
|
||||
field->table = table_backup;
|
||||
@ -11675,12 +11675,12 @@ int ha_mroonga::storage_encode_key_time(Field *field, const uchar *key,
|
||||
mysql_time.time_type = MYSQL_TIMESTAMP_TIME;
|
||||
} else {
|
||||
Field_time_hires *time_hires_field = (Field_time_hires *)field;
|
||||
uint fuzzy_date = 0;
|
||||
uchar *ptr_backup = field->ptr;
|
||||
uchar *null_ptr_backup = field->null_ptr;
|
||||
field->ptr = (uchar *)key;
|
||||
field->null_ptr = (uchar *)(key - 1);
|
||||
time_hires_field->get_date(&mysql_time, date_mode_t(fuzzy_date));
|
||||
Temporal::Options opt(TIME_CONV_NONE, current_thd);
|
||||
time_hires_field->get_date(&mysql_time, opt);
|
||||
field->ptr = ptr_backup;
|
||||
field->null_ptr = null_ptr_backup;
|
||||
}
|
||||
@ -11749,12 +11749,12 @@ int ha_mroonga::storage_encode_key_datetime(Field *field, const uchar *key,
|
||||
if (field->decimals() > 0) {
|
||||
Field_datetime_hires *datetime_hires_field = (Field_datetime_hires *)field;
|
||||
MYSQL_TIME mysql_time;
|
||||
uint fuzzy_date = 0;
|
||||
uchar *ptr_backup = field->ptr;
|
||||
uchar *null_ptr_backup = field->null_ptr;
|
||||
field->ptr = (uchar *)key;
|
||||
field->null_ptr = (uchar *)(key - 1);
|
||||
datetime_hires_field->get_date(&mysql_time, date_mode_t(fuzzy_date));
|
||||
Temporal::Options opt(TIME_CONV_NONE, current_thd);
|
||||
datetime_hires_field->get_date(&mysql_time, opt);
|
||||
field->ptr = ptr_backup;
|
||||
field->null_ptr = null_ptr_backup;
|
||||
mrn::TimeConverter time_converter;
|
||||
|
@ -258,8 +258,11 @@ namespace mrn {
|
||||
Item *real_value_item = value_item->real_item();
|
||||
switch (field_item->field->type()) {
|
||||
case MYSQL_TYPE_TIME:
|
||||
error = real_value_item->get_time(current_thd, mysql_time);
|
||||
{
|
||||
THD *thd= current_thd;
|
||||
error= real_value_item->get_date(thd, mysql_time, Time::Options(thd));
|
||||
break;
|
||||
}
|
||||
case MYSQL_TYPE_YEAR:
|
||||
mysql_time->year = static_cast<int>(value_item->val_int());
|
||||
mysql_time->month = 1;
|
||||
@ -273,9 +276,13 @@ namespace mrn {
|
||||
error = false;
|
||||
break;
|
||||
default:
|
||||
error = real_value_item->get_date(current_thd, mysql_time, TIME_FUZZY_DATES);
|
||||
{
|
||||
THD *thd= current_thd;
|
||||
Datetime::Options opt(TIME_FUZZY_DATES, thd);
|
||||
error = real_value_item->get_date(thd, mysql_time, opt);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
DBUG_RETURN(error);
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user