summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/my_global.h1
-rw-r--r--include/my_time.h9
-rw-r--r--mysql-test/r/cast.result16
-rw-r--r--mysql-test/r/dyncol.result31
-rw-r--r--mysql-test/r/func_time.result12
-rw-r--r--mysql-test/r/type_datetime.result9
-rw-r--r--mysql-test/r/type_time.result28
-rw-r--r--mysql-test/r/type_time_hires.result14
-rw-r--r--mysql-test/t/dyncol.test7
-rw-r--r--mysql-test/t/func_time.test5
-rw-r--r--mysql-test/t/type_datetime.test8
-rw-r--r--mysql-test/t/type_time.test17
-rw-r--r--sql-common/my_time.c12
-rw-r--r--sql/field.cc27
-rw-r--r--sql/item.cc4
-rw-r--r--sql/item_func.cc4
-rw-r--r--sql/item_strfunc.cc6
-rw-r--r--sql/item_timefunc.cc12
-rw-r--r--sql/mysql_priv.h11
-rw-r--r--sql/time.cc12
20 files changed, 194 insertions, 51 deletions
diff --git a/include/my_global.h b/include/my_global.h
index 41ab8bc518d..b924c47e86e 100644
--- a/include/my_global.h
+++ b/include/my_global.h
@@ -630,6 +630,7 @@ typedef unsigned short ushort;
#define sgn(a) (((a) < 0) ? -1 : ((a) > 0) ? 1 : 0)
#define swap_variables(t, a, b) { t dummy; dummy= a; a= b; b= dummy; }
#define test(a) ((a) ? 1 : 0)
+#define MY_TEST(a) ((a) ? 1 : 0)
#define set_if_bigger(a,b) do { if ((a) < (b)) (a)=(b); } while(0)
#define set_if_smaller(a,b) do { if ((a) > (b)) (a)=(b); } while(0)
#define set_bits(type, bit_count) (sizeof(type)*8 <= (bit_count) ? ~(type) 0 : ((((type) 1) << (bit_count)) - (type) 1))
diff --git a/include/my_time.h b/include/my_time.h
index 4d8ea0c2eda..f3fd1f1b638 100644
--- a/include/my_time.h
+++ b/include/my_time.h
@@ -82,6 +82,13 @@ typedef long my_time_t;
#define MYSQL_TIME_WARN_TRUNCATED 1
#define MYSQL_TIME_WARN_OUT_OF_RANGE 2
+#define MYSQL_TIME_NOTE_TRUNCATED 16
+
+#define MYSQL_TIME_WARN_WARNINGS (MYSQL_TIME_WARN_TRUNCATED|MYSQL_TIME_WARN_OUT_OF_RANGE)
+#define MYSQL_TIME_WARN_NOTES (MYSQL_TIME_NOTE_TRUNCATED)
+
+#define MYSQL_TIME_WARN_HAVE_WARNINGS(x) MY_TEST((x) & MYSQL_TIME_WARN_WARNINGS)
+#define MYSQL_TIME_WARN_HAVE_NOTES(x) MY_TEST((x) & MYSQL_TIME_WARN_NOTES)
/* Limits for the TIME data type */
#define TIME_MAX_HOUR 838
@@ -115,7 +122,7 @@ longlong double_to_datetime(double nr, MYSQL_TIME *ltime, uint flags, int *cut)
ltime, flags, cut);
}
-int number_to_time(my_bool neg, longlong nr, ulong sec_part,
+int number_to_time(my_bool neg, ulonglong nr, ulong sec_part,
MYSQL_TIME *ltime, int *was_cut);
ulonglong TIME_to_ulonglong_datetime(const MYSQL_TIME *);
ulonglong TIME_to_ulonglong_date(const MYSQL_TIME *);
diff --git a/mysql-test/r/cast.result b/mysql-test/r/cast.result
index 94715e28518..e79f514c9c3 100644
--- a/mysql-test/r/cast.result
+++ b/mysql-test/r/cast.result
@@ -77,7 +77,7 @@ cast(cast(20010203101112.121314 as double) as datetime)
2001-02-03 10:11:12
select cast(cast(010203101112.12 as double) as datetime);
cast(cast(010203101112.12 as double) as datetime)
-0001-02-03 10:11:12
+2001-02-03 10:11:12
select cast(cast(20010203101112.121314 as decimal(32,6)) as datetime);
cast(cast(20010203101112.121314 as decimal(32,6)) as datetime)
2001-02-03 10:11:12
@@ -86,10 +86,10 @@ cast(20010203101112.121314 as datetime)
2001-02-03 10:11:12
select cast(110203101112.121314 as datetime);
cast(110203101112.121314 as datetime)
-0011-02-03 10:11:12
+2011-02-03 10:11:12
select cast(cast(010203101112.12 as double) as datetime);
cast(cast(010203101112.12 as double) as datetime)
-0001-02-03 10:11:12
+2001-02-03 10:11:12
select cast("2011-02-03 10:11:12.123456" as datetime);
cast("2011-02-03 10:11:12.123456" as datetime)
2011-02-03 10:11:12
@@ -110,7 +110,7 @@ cast(cast(20010203101112.5 as double) as datetime(1))
2001-02-03 10:11:12.5
select cast(cast(010203101112.12 as double) as datetime(2));
cast(cast(010203101112.12 as double) as datetime(2))
-0001-02-03 10:11:12.12
+2001-02-03 10:11:12.12
select cast(cast(20010203101112.121314 as decimal(32,6)) as datetime(6));
cast(cast(20010203101112.121314 as decimal(32,6)) as datetime(6))
2001-02-03 10:11:12.121314
@@ -119,10 +119,10 @@ cast(20010203101112.121314 as datetime(6))
2001-02-03 10:11:12.121314
select cast(110203101112.121314 as datetime(6));
cast(110203101112.121314 as datetime(6))
-0011-02-03 10:11:12.121314
+2011-02-03 10:11:12.121314
select cast(cast(010203101112.12 as double) as datetime(6));
cast(cast(010203101112.12 as double) as datetime(6))
-0001-02-03 10:11:12.120000
+2001-02-03 10:11:12.120000
select cast("2011-02-03 10:11:12.123456" as time);
cast("2011-02-03 10:11:12.123456" as time)
10:11:12
@@ -265,7 +265,7 @@ Warnings:
Warning 1264 Out of range value for column 'cast(-1000 as double(5,2))' at row 1
select cast(010203101112.121314 as datetime);
cast(010203101112.121314 as datetime)
-0001-02-03 10:11:12
+2001-02-03 10:11:12
select cast(120010203101112.121314 as datetime);
cast(120010203101112.121314 as datetime)
NULL
@@ -326,7 +326,7 @@ cast(cast(120010203101112.121314 as double) as datetime)
NULL
select cast(cast(1.1 as double) as datetime);
cast(cast(1.1 as double) as datetime)
-0000-00-00 00:00:01
+NULL
select cast(cast(-1.1 as double) as datetime);
cast(cast(-1.1 as double) as datetime)
NULL
diff --git a/mysql-test/r/dyncol.result b/mysql-test/r/dyncol.result
index 1b06bd06162..28ae1957564 100644
--- a/mysql-test/r/dyncol.result
+++ b/mysql-test/r/dyncol.result
@@ -1001,29 +1001,29 @@ Warnings:
Warning 1292 Truncated incorrect time value: '1223.5aa'
select column_get(column_create(1, 18446744073709551615 AS unsigned int), 1 as time);
column_get(column_create(1, 18446744073709551615 AS unsigned int), 1 as time)
-NULL
+838:59:59
Warnings:
-Warning 1292 Incorrect datetime value: '1.84467440737096e+19'
+Warning 1292 Truncated incorrect time value: '1.84467440737096e+19'
select column_get(column_create(1, 9223372036854775807 AS int), 1 as time);
column_get(column_create(1, 9223372036854775807 AS int), 1 as time)
-NULL
+838:59:59
Warnings:
-Warning 1292 Incorrect datetime value: '9223372036854775807'
+Warning 1292 Truncated incorrect time value: '9223372036854775807'
select column_get(column_create(1, -9223372036854775808 AS int), 1 as time);
column_get(column_create(1, -9223372036854775808 AS int), 1 as time)
-NULL
+-838:59:59
Warnings:
-Warning 1292 Incorrect datetime value: '-9223372036854775808'
+Warning 1292 Truncated incorrect time value: '-9223372036854775808'
select column_get(column_create(1, 99999999999999999999999999999 AS decimal(32,10)), 1 as time);
column_get(column_create(1, 99999999999999999999999999999 AS decimal(32,10)), 1 as time)
-NULL
+838:59:59
Warnings:
-Warning 1292 Incorrect datetime value: '99999999999999999999999999999'
+Warning 1292 Truncated incorrect time value: '99999999999999999999999999999'
select column_get(column_create(1, 99999999999999999999999999999 AS double), 1 as time);
column_get(column_create(1, 99999999999999999999999999999 AS double), 1 as time)
-NULL
+838:59:59
Warnings:
-Warning 1292 Incorrect datetime value: '1e+29'
+Warning 1292 Truncated incorrect time value: '1e+29'
select column_get(column_create(1, "2011-02-32 8:46:06.23434" AS CHAR), 1 as time);
column_get(column_create(1, "2011-02-32 8:46:06.23434" AS CHAR), 1 as time)
NULL
@@ -1425,5 +1425,16 @@ Warning 1265 Data truncated for column 'dyncol' at row 1
SELECT COLUMN_ADD( dyncol, 7, '22:22:22', 8, REPEAT('x',270) AS CHAR ) FROM t1;
DROP table t1;
#
+# MDEV-4858 Wrong results for a huge unsigned value inserted into a TIME column
+#
+SELECT
+column_get(column_create(1, -999999999999999 AS int), 1 AS TIME) AS t1,
+column_get(column_create(1, -9223372036854775808 AS int), 1 AS TIME) AS t2;
+t1 t2
+-838:59:59 -838:59:59
+Warnings:
+Warning 1292 Truncated incorrect time value: '-999999999999999'
+Warning 1292 Truncated incorrect time value: '-9223372036854775808'
+#
# end of 5.3 tests
#
diff --git a/mysql-test/r/func_time.result b/mysql-test/r/func_time.result
index ac336418823..c52f512aa70 100644
--- a/mysql-test/r/func_time.result
+++ b/mysql-test/r/func_time.result
@@ -1101,9 +1101,9 @@ NULL
select isnull(week(now() + 0)), isnull(week(now() + 0.2)),
week(20061108), week(20061108.01), week(20061108085411.000002);
isnull(week(now() + 0)) isnull(week(now() + 0.2)) week(20061108) week(20061108.01) week(20061108085411.000002)
-0 0 45 NULL 45
+0 0 45 45 45
Warnings:
-Warning 1292 Incorrect datetime value: '20061108.01'
+Warning 1292 Truncated incorrect datetime value: '20061108.01'
End of 4.1 tests
explain extended select timestampdiff(SQL_TSI_WEEK, '2001-02-01', '2001-05-01') as a1,
timestampdiff(SQL_TSI_FRAC_SECOND, '2001-02-01 12:59:59.120000', '2001-05-01 12:58:58.119999') as a2;
@@ -2381,3 +2381,11 @@ SELECT 1 FROM t1 GROUP BY MONTHNAME(0) WITH ROLLUP;
1
1
DROP TABLE t1;
+#
+# MDEV-6099 Bad results for DATE_ADD(.., INTERVAL 2000000000000000000.0 SECOND)
+#
+SELECT DATE_ADD('2001-01-01 10:20:30',INTERVAL 250000000000.0 SECOND) AS c1, DATE_ADD('2001-01-01 10:20:30',INTERVAL 2000000000000000000.0 SECOND) AS c2;
+c1 c2
+9923-03-10 22:47:10.0 NULL
+Warnings:
+Warning 1292 Truncated incorrect DECIMAL value: '2000000000000000000.0'
diff --git a/mysql-test/r/type_datetime.result b/mysql-test/r/type_datetime.result
index d20506288ad..33d94069980 100644
--- a/mysql-test/r/type_datetime.result
+++ b/mysql-test/r/type_datetime.result
@@ -724,4 +724,13 @@ call test5041();
dt
0000-01-02 08:20:30
drop procedure test5041;
+#
+# MDEV-6097 Inconsistent results for CAST(int,decimal,double AS DATETIME)
+#
+SELECT
+CAST(010203101112 AS DATETIME(1)) AS c1,
+CAST(010203101112.2 AS DATETIME(1)) AS c2,
+CAST(010203101112.2+0e0 AS DATETIME(1)) AS c3;
+c1 c2 c3
+2001-02-03 10:11:12.0 2001-02-03 10:11:12.2 2001-02-03 10:11:12.1
End of 5.3 tests
diff --git a/mysql-test/r/type_time.result b/mysql-test/r/type_time.result
index 26e42d3b3b2..56b35e04502 100644
--- a/mysql-test/r/type_time.result
+++ b/mysql-test/r/type_time.result
@@ -298,5 +298,33 @@ Field Type Null Key Default Extra
MAX(t1)+1 decimal(22,1) YES NULL
DROP TABLE t2,t1;
#
+# MDEV-4858 Wrong results for a huge unsigned value inserted into a TIME column
+#
+SET sql_mode=traditional;
+CREATE TABLE t1 (a TIME(6));
+INSERT INTO t1 VALUES (CAST(0xFFFFFFFF00000000 AS UNSIGNED));
+ERROR 22007: Incorrect time value: '18446744069414584320' for column 'a' at row 1
+SET sql_mode=DEFAULT;
+INSERT INTO t1 VALUES (CAST(0xFFFFFFFF00000000 AS UNSIGNED));
+Warnings:
+Warning 1264 Out of range value for column 'a' at row 1
+SELECT * FROM t1;
+a
+838:59:59.999999
+DROP TABLE t1;
+SELECT TIME'00:00:00'> CAST(0xFFFFFFFF00000000 AS UNSIGNED);
+TIME'00:00:00'> CAST(0xFFFFFFFF00000000 AS UNSIGNED)
+0
+Warnings:
+Warning 1292 Truncated incorrect DOUBLE value: '00:00:00'
+#
+# MDEV-6100 No warning on CAST(9000000 AS TIME)
+#
+SELECT CAST(9000000 AS TIME);
+CAST(9000000 AS TIME)
+838:59:59
+Warnings:
+Warning 1292 Truncated incorrect time value: '9000000'
+#
# End of 5.3 tests
#
diff --git a/mysql-test/r/type_time_hires.result b/mysql-test/r/type_time_hires.result
index bf54434a04c..7fbb5079d5a 100644
--- a/mysql-test/r/type_time_hires.result
+++ b/mysql-test/r/type_time_hires.result
@@ -16,46 +16,46 @@ Warnings:
Warning 1265 Data truncated for column 'a' at row 1
insert t1 values (99991231235959e1);
Warnings:
-Warning 1265 Data truncated for column 'a' at row 1
+Warning 1264 Out of range value for column 'a' at row 1
select * from t1;
a
-00:00:00.000
00:20:03.123
01:02:03.456
03:04:05.789
15:47:11.123
+838:59:59.999
select truncate(a, 6) from t1;
truncate(a, 6)
-0.000000
2003.123000
10203.456000
30405.789062
154711.123000
+8385959.999000
select a DIV 1 from t1;
a DIV 1
-0
2003
10203
30405
154711
+8385959
select group_concat(distinct a) from t1;
group_concat(distinct a)
-00:00:00.000,00:20:03.123,01:02:03.456,03:04:05.789,15:47:11.123
+00:20:03.123,01:02:03.456,03:04:05.789,15:47:11.123,838:59:59.999
alter table t1 engine=innodb;
select * from t1 order by a;
a
-00:00:00.000
00:20:03.123
01:02:03.456
03:04:05.789
15:47:11.123
+838:59:59.999
select * from t1 order by a+0;
a
-00:00:00.000
00:20:03.123
01:02:03.456
03:04:05.789
15:47:11.123
+838:59:59.999
drop table t1;
create table t1 (a time(4)) engine=innodb;
insert t1 values ('2010-12-11 01:02:03.456789');
diff --git a/mysql-test/t/dyncol.test b/mysql-test/t/dyncol.test
index 914bf9151b3..de4e150130a 100644
--- a/mysql-test/t/dyncol.test
+++ b/mysql-test/t/dyncol.test
@@ -623,6 +623,13 @@ SELECT COLUMN_ADD( dyncol, 7, '22:22:22', 8, REPEAT('x',270) AS CHAR ) FROM t1;
DROP table t1;
--echo #
+--echo # MDEV-4858 Wrong results for a huge unsigned value inserted into a TIME column
+--echo #
+SELECT
+ column_get(column_create(1, -999999999999999 AS int), 1 AS TIME) AS t1,
+ column_get(column_create(1, -9223372036854775808 AS int), 1 AS TIME) AS t2;
+
+--echo #
--echo # end of 5.3 tests
--echo #
diff --git a/mysql-test/t/func_time.test b/mysql-test/t/func_time.test
index 4205a70ee56..52dbf3471ac 100644
--- a/mysql-test/t/func_time.test
+++ b/mysql-test/t/func_time.test
@@ -1437,3 +1437,8 @@ CREATE TABLE t1 (i INT);
INSERT INTO t1 VALUES (1),(2);
SELECT 1 FROM t1 GROUP BY MONTHNAME(0) WITH ROLLUP;
DROP TABLE t1;
+
+--echo #
+--echo # MDEV-6099 Bad results for DATE_ADD(.., INTERVAL 2000000000000000000.0 SECOND)
+--echo #
+SELECT DATE_ADD('2001-01-01 10:20:30',INTERVAL 250000000000.0 SECOND) AS c1, DATE_ADD('2001-01-01 10:20:30',INTERVAL 2000000000000000000.0 SECOND) AS c2;
diff --git a/mysql-test/t/type_datetime.test b/mysql-test/t/type_datetime.test
index 2fdc33ab079..d249039293c 100644
--- a/mysql-test/t/type_datetime.test
+++ b/mysql-test/t/type_datetime.test
@@ -519,6 +519,14 @@ DELIMITER ;|
call test5041();
drop procedure test5041;
+--echo #
+--echo # MDEV-6097 Inconsistent results for CAST(int,decimal,double AS DATETIME)
+--echo #
+SELECT
+ CAST(010203101112 AS DATETIME(1)) AS c1,
+ CAST(010203101112.2 AS DATETIME(1)) AS c2,
+ CAST(010203101112.2+0e0 AS DATETIME(1)) AS c3;
+
--echo End of 5.3 tests
diff --git a/mysql-test/t/type_time.test b/mysql-test/t/type_time.test
index 724e25625af..07fae572a7d 100644
--- a/mysql-test/t/type_time.test
+++ b/mysql-test/t/type_time.test
@@ -201,6 +201,23 @@ SELECT * FROM t2;
SHOW COLUMNS FROM t2;
DROP TABLE t2,t1;
+--echo #
+--echo # MDEV-4858 Wrong results for a huge unsigned value inserted into a TIME column
+--echo #
+SET sql_mode=traditional;
+CREATE TABLE t1 (a TIME(6));
+--error ER_TRUNCATED_WRONG_VALUE
+INSERT INTO t1 VALUES (CAST(0xFFFFFFFF00000000 AS UNSIGNED));
+SET sql_mode=DEFAULT;
+INSERT INTO t1 VALUES (CAST(0xFFFFFFFF00000000 AS UNSIGNED));
+SELECT * FROM t1;
+DROP TABLE t1;
+SELECT TIME'00:00:00'> CAST(0xFFFFFFFF00000000 AS UNSIGNED);
+
+--echo #
+--echo # MDEV-6100 No warning on CAST(9000000 AS TIME)
+--echo #
+SELECT CAST(9000000 AS TIME);
--echo #
--echo # End of 5.3 tests
diff --git a/sql-common/my_time.c b/sql-common/my_time.c
index 1f058f89bb7..17d031168c6 100644
--- a/sql-common/my_time.c
+++ b/sql-common/my_time.c
@@ -1226,7 +1226,7 @@ longlong number_to_datetime(longlong nr, ulong sec_part, MYSQL_TIME *time_res,
*was_cut= 0;
time_res->time_type=MYSQL_TIMESTAMP_DATE;
- if (nr == 0 || nr >= 10000101000000LL || sec_part)
+ if (nr == 0 || nr >= 10000101000000LL)
{
time_res->time_type=MYSQL_TIMESTAMP_DATETIME;
goto ok;
@@ -1284,7 +1284,11 @@ longlong number_to_datetime(longlong nr, ulong sec_part, MYSQL_TIME *time_res,
time_res->minute <= 59 && time_res->second <= 59 &&
sec_part <= TIME_MAX_SECOND_PART &&
!check_date(time_res, nr || sec_part, flags, was_cut))
+ {
+ if (time_res->time_type == MYSQL_TIMESTAMP_DATE && sec_part != 0)
+ *was_cut= MYSQL_TIME_NOTE_TRUNCATED;
return nr;
+ }
/* Don't want to have was_cut get set if NO_ZERO_DATE was violated. */
if (nr || !(flags & TIME_NO_ZERO_DATE))
@@ -1318,10 +1322,10 @@ longlong number_to_datetime(longlong nr, ulong sec_part, MYSQL_TIME *time_res,
0 time value is valid, but was possibly truncated
-1 time value is invalid
*/
-int number_to_time(my_bool neg, longlong nr, ulong sec_part,
+int number_to_time(my_bool neg, ulonglong nr, ulong sec_part,
MYSQL_TIME *ltime, int *was_cut)
{
- if (nr > 9999999 && neg == 0)
+ if (nr > 9999999 && nr < 99991231235959ULL && neg == 0)
{
if (number_to_datetime(nr, sec_part, ltime,
TIME_INVALID_DATES, was_cut) < 0)
@@ -1329,7 +1333,7 @@ int number_to_time(my_bool neg, longlong nr, ulong sec_part,
ltime->year= ltime->month= ltime->day= 0;
ltime->time_type= MYSQL_TIMESTAMP_TIME;
- *was_cut= MYSQL_TIME_WARN_TRUNCATED;
+ *was_cut= MYSQL_TIME_NOTE_TRUNCATED;
return 0;
}
diff --git a/sql/field.cc b/sql/field.cc
index 78d39a79194..4452f881fb7 100644
--- a/sql/field.cc
+++ b/sql/field.cc
@@ -4664,7 +4664,7 @@ int Field_timestamp::store(longlong nr, bool unsigned_val)
{
MYSQL_TIME l_time;
int error;
- Lazy_string_num str(nr);
+ Lazy_string_num str(nr, unsigned_val);
THD *thd= table->in_use;
/* We don't want to store invalid or fuzzy datetime values in TIMESTAMP */
@@ -5067,6 +5067,17 @@ int Field_temporal::store_TIME_with_warning(MYSQL_TIME *ltime,
ASSERT_COLUMN_MARKED_FOR_WRITE_OR_COMPUTED;
+#if MARIADB_VERSION_ID < 1000000
+ /*
+ Check if the YYYYMMDD part was truncated.
+ Translate a note into a warning.
+ In MariaDB-10.0 we have a better warnings/notes handling,
+ so this code is not needed.
+ */
+ if (was_cut & MYSQL_TIME_NOTE_TRUNCATED)
+ was_cut|= MYSQL_TIME_WARN_TRUNCATED;
+#endif
+
if (was_cut == 0 &&
have_smth_to_conv == 0 &&
temporal_type() != MYSQL_TIMESTAMP_TIME) // special case: zero date
@@ -5157,7 +5168,7 @@ int Field_temporal::store(longlong nr, bool unsigned_val)
MYSQL_TIME ltime;
longlong tmp;
THD *thd= table->in_use;
- Lazy_string_num str(nr);
+ Lazy_string_num str(nr, unsigned_val);
tmp= number_to_datetime(nr, 0, &ltime, (thd->variables.sql_mode &
(MODE_NO_ZERO_IN_DATE |
@@ -5255,7 +5266,7 @@ int Field_time::store(double nr)
bool neg= nr < 0;
if (neg)
nr= -nr;
- int have_smth_to_conv= !number_to_time(neg, (longlong)nr,
+ int have_smth_to_conv= !number_to_time(neg, (ulonglong) nr,
(ulong)((nr - floor(nr)) * TIME_SECOND_PART_FACTOR),
&ltime, &was_cut);
@@ -5266,9 +5277,12 @@ int Field_time::store(double nr)
int Field_time::store(longlong nr, bool unsigned_val)
{
MYSQL_TIME ltime;
- Lazy_string_num str(nr);
+ Lazy_string_num str(nr, unsigned_val);
int was_cut;
- int have_smth_to_conv= !number_to_time(nr < 0, nr < 0 ? -nr : nr,
+ if (nr < 0 && unsigned_val)
+ nr= 99991231235959LL + 1;
+ int have_smth_to_conv= !number_to_time(nr < 0,
+ (ulonglong) (nr < 0 ? -nr : nr),
0, &ltime, &was_cut);
return store_TIME_with_warning(&ltime, &str, was_cut, have_smth_to_conv);
@@ -5633,7 +5647,8 @@ bool Field_year::get_date(MYSQL_TIME *ltime,uint fuzzydate)
int tmp= (int) ptr[0];
if (tmp || field_length != 4)
tmp+= 1900;
- return int_to_datetime_with_warn(tmp * 10000, ltime, fuzzydate, field_name);
+ return int_to_datetime_with_warn(false, tmp * 10000,
+ ltime, fuzzydate, field_name);
}
diff --git a/sql/item.cc b/sql/item.cc
index a45a7500f1c..3a1913bd4a1 100644
--- a/sql/item.cc
+++ b/sql/item.cc
@@ -1228,6 +1228,7 @@ bool Item::get_date(MYSQL_TIME *ltime,uint fuzzydate)
case INT_RESULT:
{
longlong value= val_int();
+ bool neg= !unsigned_flag && value < 0;
if (field_type() == MYSQL_TYPE_YEAR)
{
if (max_length == 2)
@@ -1239,7 +1240,8 @@ bool Item::get_date(MYSQL_TIME *ltime,uint fuzzydate)
}
value*= 10000; /* make it YYYYMMHH */
}
- if (null_value || int_to_datetime_with_warn(value, ltime, fuzzydate,
+ if (null_value || int_to_datetime_with_warn(neg, neg ? -value : value,
+ ltime, fuzzydate,
field_name_or_null()))
goto err;
break;
diff --git a/sql/item_func.cc b/sql/item_func.cc
index a4f713a16b0..fc69fa711c2 100644
--- a/sql/item_func.cc
+++ b/sql/item_func.cc
@@ -1088,7 +1088,9 @@ bool Item_func_hybrid_result_type::get_date(MYSQL_TIME *ltime, uint fuzzydate)
case INT_RESULT:
{
longlong value= int_op();
- if (null_value || int_to_datetime_with_warn(value, ltime, fuzzydate,
+ bool neg= !unsigned_flag && value < 0;
+ if (null_value || int_to_datetime_with_warn(neg, neg ? -value : value,
+ ltime, fuzzydate,
field_name_or_null()))
goto err;
break;
diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc
index 4044ee3cd19..4a58ad339e2 100644
--- a/sql/item_strfunc.cc
+++ b/sql/item_strfunc.cc
@@ -4149,8 +4149,10 @@ bool Item_dyncol_get::get_date(MYSQL_TIME *ltime, uint fuzzy_date)
case DYN_COL_UINT:
if (signed_value || val.x.ulong_value <= LONGLONG_MAX)
{
- if (int_to_datetime_with_warn(val.x.ulong_value, ltime, fuzzy_date,
- 0 /* TODO */))
+ bool neg= val.x.ulong_value > LONGLONG_MAX;
+ if (int_to_datetime_with_warn(neg, neg ? -val.x.ulong_value :
+ val.x.ulong_value,
+ ltime, fuzzy_date, 0 /* TODO */))
goto null;
return 0;
}
diff --git a/sql/item_timefunc.cc b/sql/item_timefunc.cc
index fbc7bc36842..bb93fc08faa 100644
--- a/sql/item_timefunc.cc
+++ b/sql/item_timefunc.cc
@@ -1206,6 +1206,18 @@ bool get_interval_value(Item *args,interval_type int_type,
if (!(val= args->val_decimal(&decimal_value)))
return true;
interval->neg= my_decimal2seconds(val, &second, &second_part);
+ if (second == LONGLONG_MAX)
+ {
+ char buff[DECIMAL_MAX_STR_LENGTH];
+ int length= sizeof(buff);
+ decimal2string(val, buff, &length, 0, 0, 0);
+ push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN,
+ ER_TRUNCATED_WRONG_VALUE,
+ ER(ER_TRUNCATED_WRONG_VALUE), "DECIMAL",
+ buff);
+ return true;
+ }
+
interval->second= second;
interval->second_part= second_part;
return false;
diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h
index 2f04f02064c..0a64f654863 100644
--- a/sql/mysql_priv.h
+++ b/sql/mysql_priv.h
@@ -876,10 +876,13 @@ public:
class Lazy_string_num : public Lazy_string
{
- longlong num;
+ longlong m_value;
+ bool m_unsigned;
public:
- Lazy_string_num(longlong num_arg) : Lazy_string(), num(num_arg) {}
- void copy_to(String *dst) const { dst->set(num, &my_charset_bin); }
+ Lazy_string_num(longlong num_arg, bool unsigned_flag= false) :
+ Lazy_string(), m_value(num_arg), m_unsigned(unsigned_flag) {}
+ void copy_to(String *dst) const
+ { dst->set_int(m_value, m_unsigned, &my_charset_bin); }
};
class Lazy_string_decimal: public Lazy_string
@@ -2540,7 +2543,7 @@ bool double_to_datetime_with_warn(double value, MYSQL_TIME *ltime,
ulong fuzzydate, const char *field_name);
bool decimal_to_datetime_with_warn(const my_decimal *value, MYSQL_TIME *ltime,
ulong fuzzydate, const char *field_name);
-bool int_to_datetime_with_warn(longlong value, MYSQL_TIME *ltime,
+bool int_to_datetime_with_warn(bool neg, ulonglong value, MYSQL_TIME *ltime,
ulong fuzzydate, const char *field_name);
static inline void make_truncated_value_warning(THD *thd,
diff --git a/sql/time.cc b/sql/time.cc
index b91ddad6cd4..ab36db40bfe 100644
--- a/sql/time.cc
+++ b/sql/time.cc
@@ -291,20 +291,23 @@ static bool number_to_time_with_warn(bool neg, ulonglong nr, ulong sec_part,
int was_cut;
longlong res;
enum_field_types f_type;
+ bool have_warnings;
if (fuzzydate & TIME_TIME_ONLY)
{
fuzzydate= TIME_TIME_ONLY; // clear other flags
f_type= MYSQL_TYPE_TIME;
res= number_to_time(neg, nr, sec_part, ltime, &was_cut);
+ have_warnings= MYSQL_TIME_WARN_HAVE_WARNINGS(was_cut);
}
else
{
f_type= MYSQL_TYPE_DATETIME;
res= neg ? -1 : number_to_datetime(nr, sec_part, ltime, fuzzydate, &was_cut);
+ have_warnings= was_cut && (fuzzydate & TIME_NO_ZERO_IN_DATE);
}
- if (res < 0 || (was_cut && (fuzzydate & TIME_NO_ZERO_IN_DATE)))
+ if (res < 0 || have_warnings)
{
make_truncated_value_warning(current_thd,
MYSQL_ERROR::WARN_LEVEL_WARN, str,
@@ -347,12 +350,11 @@ bool decimal_to_datetime_with_warn(const my_decimal *value, MYSQL_TIME *ltime,
}
-bool int_to_datetime_with_warn(longlong value, MYSQL_TIME *ltime,
+bool int_to_datetime_with_warn(bool neg, ulonglong value, MYSQL_TIME *ltime,
ulong fuzzydate, const char *field_name)
{
- const Lazy_string_num str(value);
- bool neg= value < 0;
- return number_to_time_with_warn(neg, neg ? -value : value, 0, ltime,
+ const Lazy_string_num str(neg ? -value : value, !neg);
+ return number_to_time_with_warn(neg, value, 0, ltime,
fuzzydate, &str, field_name);
}