MDEV-16991 Rounding vs truncation for TIME, DATETIME, TIMESTAMP

This commit is contained in:
Alexander Barkov 2018-11-23 19:04:42 +04:00
parent 27f3329ff6
commit 4447a02cf1
59 changed files with 4774 additions and 398 deletions

View File

@ -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,

File diff suppressed because it is too large Load Diff

View 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;

View File

@ -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)

View File

@ -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

View File

@ -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 ');

View File

@ -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;
#

View File

@ -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',

View File

@ -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',

View File

@ -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',

View File

@ -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',

View 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;

View 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;

View 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'

View 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';

View 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'

View 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';

View 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;

View 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;

View File

@ -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)

View 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

View 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

View File

@ -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----------------------#'

View File

@ -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

View File

@ -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

View File

@ -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;

View File

@ -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;

View File

@ -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,

View File

@ -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 '';

View File

@ -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;
}

View File

@ -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,&not_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,&not_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,&not_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,&not_used);
}

View File

@ -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, &ltime, 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, &ltime, TIME_NO_ZERO_DATE |
thd->temporal_round_mode()))
goto wrong_value;
ltime_utc= TIME_to_timestamp(thd,&ltime,&not_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, &ltime, TIME_NO_ZERO_DATE))
if (item_starts->get_date(thd, &ltime, TIME_NO_ZERO_DATE |
thd->temporal_round_mode()))
goto wrong_value;
ltime_utc= TIME_to_timestamp(thd, &ltime, &not_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, &ltime, TIME_NO_ZERO_DATE))
if (item_ends->get_date(thd, &ltime, TIME_NO_ZERO_DATE |
thd->temporal_round_mode()))
goto error_bad_params;
ltime_utc= TIME_to_timestamp(thd, &ltime, &not_used);

View File

@ -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(&ltime, TIME_NO_ZERO_DATE))
if (get_date(&ltime, 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(&ltime, TIME_NO_ZERO_DATE))
if (get_date(&ltime, 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(&ltime, TIME_NO_ZERO_DATE))
if (get_date(&ltime, 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(&ltime, ptr_in_record(record), sql_mode_for_dates(thd));
return get_TIME(&ltime, 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(&ltime, TIME_TIME_ONLY);
get_date(&ltime, Datetime::Options(TIME_TIME_ONLY, get_thd()));
str->alloc(field_length + 1);
str->length(my_time_to_str(&ltime, 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(&ltime, TIME_TIME_ONLY);
get_date(&ltime, Time::Options(TIME_TIME_ONLY, get_thd()));
return protocol->store_time(&ltime, 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(&ltime, TIME_TIME_ONLY);
get_date(&ltime, Time::Options(TIME_TIME_ONLY, get_thd()));
longlong val= TIME_to_ulonglong_time(&ltime);
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(&ltime, TIME_TIME_ONLY);
get_date(&ltime, Time::Options(TIME_TIME_ONLY, get_thd()));
return TIME_to_double(&ltime);
}
@ -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;
}

View File

@ -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(&ltime, date_mode_t(0)))
// For temporal types no truncation needed. Rounding mode is not important.
if (get_date(&ltime, TIME_CONV_NONE | TIME_FRAC_NONE))
return to->reset();
return to->store_time_dec(&ltime, 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,

View File

@ -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));
}

View File

@ -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);

View File

@ -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, &ltime, Datetime::comparison_flags_for_get_date()))
if (get_date_result(thd, &ltime, Datetime::Options_cmp(thd)))
return 0;
if (ltime.time_type != MYSQL_TIMESTAMP_TIME)
return pack_time(&ltime);
if ((null_value= time_to_datetime_with_warn(thd, &ltime,
&tmp, date_mode_t(0))))
if ((null_value= time_to_datetime_with_warn(thd, &ltime, &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, &ltime, sql_mode_for_dates(thd)))
if (get_date(thd, &ltime, Datetime::Options(thd)))
return set_field_to_null_with_conversions(field, no_conversions);
field->set_notnull();
return field->store_time_dec(&ltime, 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(), &ltime, date_mode_t(0)))
// This is a temporal type. No nanoseconds, so round mode is not important.
if (get_date(field->get_thd(), &ltime, 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(&ltime, decimals);

View File

@ -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, &ltime, fuzzydate) ? 0 : pack_time(&ltime);
return get_date_result(thd, &ltime, Time::Options_cmp(thd)) ? 0 :
pack_time(&ltime);
}
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; }

View File

@ -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);
}

View File

@ -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)

View File

@ -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);

View File

@ -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);

View File

@ -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(&ltime1) ||
Datetime(thd, args[1], fuzzydate).copy_to_mysql_time(&ltime2))
if (Datetime(thd, args[0], opt).copy_to_mysql_time(&ltime1) ||
Datetime(thd, args[1], opt).copy_to_mysql_time(&ltime2))
goto null_date;
if (calc_time_diff(&ltime2,&ltime1, 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];

View File

@ -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]);

View File

@ -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;

View File

@ -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)
{

View File

@ -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);

View File

@ -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 }
},
{

View File

@ -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

View File

@ -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));
}

View File

@ -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

View File

@ -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);

View File

@ -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);

View File

@ -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, &ltime, TIME_TIME_ONLY);
THD *thd= current_thd;
(void) item->get_date(thd, &ltime, 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, &ltime, sql_mode_for_dates(current_thd));
THD *thd= current_thd;
(void) item->get_date(thd, &ltime, 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))

File diff suppressed because it is too large Load Diff

View File

@ -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
};

View File

@ -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, &ltime, date_mode_t(0));
Datetime::Options opt(TIME_CONV_NONE, thd);
bool res= var->value->get_date(thd, &ltime, 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
{

View File

@ -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;

View File

@ -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);
}