3675 Ramil Kalimullin 2011-12-16
Fix for BUG#13450867: CRASH ON UPDATE A TIME COLUMN
sec_to_time() changed to deal with FSP.
modified:
mysql-test/r/type_temporal_fractional.result
mysql-test/t/type_temporal_fractional.test
sql/item_timefunc.cc
3674 Vasil Dimov 2011-12-16
Fix Bug#12429443 PERSISTENT STATISTICS GIVE LESS ACCURATE ESTIMATES
FOR DATE COLUMNS
Further tune the estimation formula for number of distinct records:
* Introduce a ratio which is 1 for unique keys and <1 for non-uniq keys
(see R in the patch)
* Avoid counting one record twice - as last on some page and first on
subsequent page. This has biggest impact on pages with just two distinct
records on them - then the number of distinct records could have been
estimated to be two times bigger than actual.
This reverts parts of vasil.dimov@stripped
because total_recs is needed again in dict_stats_analyze_index_for_n_prefix().
modified:
storage/innobase/dict/dict0stats.cc
=== modified file 'mysql-test/r/type_temporal_fractional.result'
--- a/mysql-test/r/type_temporal_fractional.result 2011-11-21 15:17:51 +0000
+++ b/mysql-test/r/type_temporal_fractional.result 2011-12-16 16:57:46 +0000
@@ -4022,7 +4022,7 @@ a a + INTERVAL 1 HOUR a - INTERVAL 1 HOU
SELECT a, a + INTERVAL 1 SECOND, a - INTERVAL 1 SECOND FROM t1;
a a + INTERVAL 1 SECOND a - INTERVAL 1 SECOND
-10:00:00.100000 -09:59:59.100000 -10:00:01.100000
-00:00:00.100000 00:00:01.100000 00:00:00.900000
+00:00:00.100000 00:00:01.100000 -00:00:00.900000
10:00:00.100000 10:00:01.100000 09:59:59.100000
SELECT a, a + INTERVAL 1.1 SECOND, a - INTERVAL 1.1 SECOND FROM t1;
a a + INTERVAL 1.1 SECOND a - INTERVAL 1.1 SECOND
@@ -16937,3 +16937,50 @@ SELECT c_time AS c1 FROM t1
WHERE c_timestamp NOT IN (NULL, '0000-00-00 00:00:00');
c1
DROP TABLE t1;
+#
+# BUG#13450867 - CRASH ON UPDATE A TIME COLUMN
+#
+CREATE TABLE t1 (a TIME(6), b TIME(6), c TIME(6), d TIME(6));
+INSERT INTO t1 VALUES
+('-838:59:59.999999', '-838:59:59.000001',
+'838:59:59.999999', '838:59:59.000001');
+Warnings:
+Warning 1264 Out of range value for column 'a' at row 1
+Warning 1264 Out of range value for column 'b' at row 1
+Warning 1264 Out of range value for column 'c' at row 1
+Warning 1264 Out of range value for column 'd' at row 1
+SELECT * FROM t1;
+a b c d
+-838:59:59.000000 -838:59:59.000000 838:59:59.000000 838:59:59.000000
+UPDATE t1 SET
+a= a - INTERVAL 999999 MICROSECOND, b= b - INTERVAL 1 MICROSECOND,
+c= c + INTERVAL 999999 MICROSECOND, d= d + INTERVAL 1 MICROSECOND;
+Warnings:
+Warning 1441 Datetime function: time field overflow
+Warning 1441 Datetime function: time field overflow
+Warning 1441 Datetime function: time field overflow
+Warning 1441 Datetime function: time field overflow
+SELECT * FROM t1;
+a b c d
+NULL NULL NULL NULL
+DROP TABLE t1;
+SELECT SEC_TO_TIME(3200399.999999);
+SEC_TO_TIME(3200399.999999)
+838:59:59.000000
+Warnings:
+Warning 1292 Truncated incorrect time value: '3200399.999999'
+SELECT SEC_TO_TIME(3200399.000001);
+SEC_TO_TIME(3200399.000001)
+838:59:59.000000
+Warnings:
+Warning 1292 Truncated incorrect time value: '3200399.000001'
+SELECT SEC_TO_TIME(-3200399.999999);
+SEC_TO_TIME(-3200399.999999)
+-838:59:59.000000
+Warnings:
+Warning 1292 Truncated incorrect time value: '-3200399.999999'
+SELECT SEC_TO_TIME(-3200399.000001);
+SEC_TO_TIME(-3200399.000001)
+-838:59:59.000000
+Warnings:
+Warning 1292 Truncated incorrect time value: '-3200399.000001'
=== modified file 'mysql-test/t/type_temporal_fractional.test'
--- a/mysql-test/t/type_temporal_fractional.test 2011-11-21 15:17:51 +0000
+++ b/mysql-test/t/type_temporal_fractional.test 2011-12-16 16:57:46 +0000
@@ -7468,3 +7468,23 @@ DROP TABLE t1;
## alter session set nls_timestamp_format='YYYY-MM-DD HH24:MI:SS.FF';
##select * from t1 where a=b;
##2011-04-09 15:36:32.225000 2011-04-09 15:36:32.225
+
+
+--echo #
+--echo # BUG#13450867 - CRASH ON UPDATE A TIME COLUMN
+--echo #
+CREATE TABLE t1 (a TIME(6), b TIME(6), c TIME(6), d TIME(6));
+INSERT INTO t1 VALUES
+ ('-838:59:59.999999', '-838:59:59.000001',
+ '838:59:59.999999', '838:59:59.000001');
+SELECT * FROM t1;
+UPDATE t1 SET
+ a= a - INTERVAL 999999 MICROSECOND, b= b - INTERVAL 1 MICROSECOND,
+ c= c + INTERVAL 999999 MICROSECOND, d= d + INTERVAL 1 MICROSECOND;
+SELECT * FROM t1;
+DROP TABLE t1;
+
+SELECT SEC_TO_TIME(3200399.999999);
+SELECT SEC_TO_TIME(3200399.000001);
+SELECT SEC_TO_TIME(-3200399.999999);
+SELECT SEC_TO_TIME(-3200399.000001);
=== modified file 'sql/item_timefunc.cc'
--- a/sql/item_timefunc.cc 2011-11-21 11:58:25 +0000
+++ b/sql/item_timefunc.cc 2011-12-16 16:57:46 +0000
@@ -79,59 +79,51 @@ adjust_time_range_with_warn(MYSQL_TIME *
/*
- Convert seconds to MYSQL_TIME value with overflow checking
+ Convert seconds to MYSQL_TIME value with overflow checking.
SYNOPSIS:
sec_to_time()
seconds number of seconds
- unsigned_flag 1, if 'seconds' is unsigned, 0, otherwise
ltime output MYSQL_TIME value
- send_warn whether to send a generic warning on truncation
DESCRIPTION
If the 'seconds' argument is inside MYSQL_TIME data range, convert it to a
corresponding value.
- Otherwise, truncate the resulting value to the nearest endpoint, and
- produce a warning message.
+ Otherwise, truncate the resulting value to the nearest endpoint.
RETURN
1 if the value was truncated during conversion
0 otherwise
*/
-static bool sec_to_time(longlong seconds, bool unsigned_flag,
- MYSQL_TIME *ltime, bool send_warn)
+static bool sec_to_time(lldiv_t seconds, MYSQL_TIME *ltime)
{
- uint sec;
+ int warning= 0;
set_zero_time(ltime, MYSQL_TIMESTAMP_TIME);
- if (seconds < 0)
+ if (seconds.quot < 0 || seconds.rem < 0)
{
- if (unsigned_flag)
- goto overflow;
ltime->neg= 1;
- if (seconds < -3020399)
- goto overflow;
- seconds= -seconds;
+ seconds.quot= -seconds.quot;
+ seconds.rem= -seconds.rem;
}
- else if (seconds > 3020399)
- goto overflow;
- sec= (uint) ((ulonglong) seconds % 3600);
- ltime->hour= (uint) (seconds/3600);
- ltime->minute= sec/60;
- ltime->second= sec % 60;
-
- return 0;
+ if (seconds.quot > TIME_MAX_VALUE_SECONDS)
+ {
+ set_max_hhmmss(ltime);
+ return true;
+ }
-overflow:
- set_max_hhmmss(ltime);
+ ltime->hour= (uint) (seconds.quot / 3600);
+ uint sec= (uint) (seconds.quot % 3600);
+ ltime->minute= sec / 60;
+ ltime->second= sec % 60;
+ ltime->second_part= (uint) (seconds.rem / 1000);
+
+ adjust_time_range(ltime, &warning);
- if (send_warn)
- make_truncated_value_warning(ErrConvString(seconds, unsigned_flag),
- MYSQL_TIMESTAMP_TIME);
- return 1;
+ return warning ? true : false;
}
@@ -1927,13 +1919,9 @@ bool Item_func_sec_to_time::get_time(MYS
make_truncated_value_warning(ErrConvString(val), MYSQL_TIMESTAMP_TIME);
return false;
}
- sec_to_time(seconds.quot, 0, ltime, true);
- /*
- Both negative seconds.quot and negative seconds.rem
- affect ltime->neg, hence "|=" to combine them.
- */
- ltime->neg|= seconds.rem < 0;
- ltime->second_part= (seconds.rem < 0 ? -seconds.rem : seconds.rem) / 1000;
+ if (sec_to_time(seconds, ltime))
+ make_truncated_value_warning(ErrConvString(val),
+ MYSQL_TIMESTAMP_TIME);
return false;
}
@@ -2335,8 +2323,11 @@ bool Item_date_add_interval::get_time_in
interval.second_part) *
(interval.neg ? -1 : 1);
longlong diff= usec1 + usec2;
+ lldiv_t seconds;
+ seconds.quot= diff / 1000000;
+ seconds.rem= diff % 1000000 * 1000; /* time->second_part= lldiv.rem / 1000 */
if ((null_value= (interval.year || interval.month ||
- sec_to_time(diff / 1000000, 0, ltime, false))))
+ sec_to_time(seconds, ltime))))
{
push_warning_printf(current_thd, Sql_condition::WARN_LEVEL_WARN,
ER_DATETIME_FUNCTION_OVERFLOW,
@@ -2344,8 +2335,6 @@ bool Item_date_add_interval::get_time_in
"time");
return true;
}
- ltime->second_part= (diff % 1000000) * (diff < 0 ? -1 : 1);
- ltime->time_type= MYSQL_TIMESTAMP_TIME;
return false;
}
No bundle (reason: useless for push emails).
| Thread |
|---|
| • bzr push into mysql-trunk branch (ramil:3674 to 3675) Bug#13450867 | Ramil Kalimullin | 16 Dec |