summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--mysql-test/r/type_time.result24
-rw-r--r--mysql-test/t/type_time.test14
-rw-r--r--sql-common/my_time.c28
3 files changed, 60 insertions, 6 deletions
diff --git a/mysql-test/r/type_time.result b/mysql-test/r/type_time.result
index 442435b0459..deb60a95f21 100644
--- a/mysql-test/r/type_time.result
+++ b/mysql-test/r/type_time.result
@@ -85,3 +85,27 @@ sec_to_time(time_to_sec(t))
13:00:00
09:00:00
drop table t1;
+SELECT CAST(235959.123456 AS TIME);
+CAST(235959.123456 AS TIME)
+23:59:59.123456
+SELECT CAST(0.235959123456e+6 AS TIME);
+CAST(0.235959123456e+6 AS TIME)
+23:59:59.123456
+SELECT CAST(235959123456e-6 AS TIME);
+CAST(235959123456e-6 AS TIME)
+23:59:59.123456
+SELECT CAST(235959.1234567 AS TIME);
+CAST(235959.1234567 AS TIME)
+23:59:59.123456
+Warnings:
+Warning 1292 Truncated incorrect time value: '235959.1234567'
+SELECT CAST(0.2359591234567e6 AS TIME);
+CAST(0.2359591234567e6 AS TIME)
+23:59:59.123456
+Warnings:
+Warning 1292 Truncated incorrect time value: '235959.1234567'
+SELECT CAST(0.2359591234567e+30 AS TIME);
+CAST(0.2359591234567e+30 AS TIME)
+NULL
+Warnings:
+Warning 1292 Truncated incorrect time value: '2.359591234567e+29'
diff --git a/mysql-test/t/type_time.test b/mysql-test/t/type_time.test
index 7ae3f65f7cc..9abfe914335 100644
--- a/mysql-test/t/type_time.test
+++ b/mysql-test/t/type_time.test
@@ -21,4 +21,18 @@ select t, time_to_sec(t),sec_to_time(time_to_sec(t)) from t1;
select sec_to_time(time_to_sec(t)) from t1;
drop table t1;
+#
+# BUG #12440: Incorrect processing of time values containing
+# long fraction part and/or large exponent part.
+#
+# These must return normal result:
+SELECT CAST(235959.123456 AS TIME);
+SELECT CAST(0.235959123456e+6 AS TIME);
+SELECT CAST(235959123456e-6 AS TIME);
+# These must cut fraction part and produce warning:
+SELECT CAST(235959.1234567 AS TIME);
+SELECT CAST(0.2359591234567e6 AS TIME);
+# This must return NULL and produce warning:
+SELECT CAST(0.2359591234567e+30 AS TIME);
+
# End of 4.1 tests
diff --git a/sql-common/my_time.c b/sql-common/my_time.c
index 72809ee9b4b..c9d39260761 100644
--- a/sql-common/my_time.c
+++ b/sql-common/my_time.c
@@ -575,18 +575,34 @@ fractional:
/* Get fractional second part */
if ((end-str) >= 2 && *str == '.' && my_isdigit(&my_charset_latin1,str[1]))
{
- uint field_length=5;
+ int field_length= 5;
str++; value=(uint) (uchar) (*str - '0');
- while (++str != end &&
- my_isdigit(&my_charset_latin1,str[0]) &&
- field_length--)
- value=value*10 + (uint) (uchar) (*str - '0');
- if (field_length)
+ while (++str != end && my_isdigit(&my_charset_latin1, *str))
+ {
+ if (field_length-- > 0)
+ value= value*10 + (uint) (uchar) (*str - '0');
+ }
+ if (field_length > 0)
value*= (long) log_10_int[field_length];
+ else if (field_length < 0)
+ *was_cut= 1;
date[4]=value;
}
else
date[4]=0;
+
+ /* Check for exponent part: E<gigit> | E<sign><digit> */
+ /* (may occur as result of %g formatting of time value) */
+ if ((end - str) > 1 &&
+ (*str == 'e' || *str == 'E') &&
+ (my_isdigit(&my_charset_latin1, str[1]) ||
+ ((str[1] == '-' || str[1] == '+') &&
+ (end - str) > 2 &&
+ my_isdigit(&my_charset_latin1, str[2]))))
+ {
+ *was_cut= 1;
+ return 1;
+ }
if (internal_format_positions[7] != 255)
{