List:Commits« Previous MessageNext Message »
From:Ramil Kalimullin Date:December 16 2011 4:58pm
Subject:bzr push into mysql-trunk branch (ramil:3674 to 3675) Bug#13450867
View as plain text  
 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#13450867Ramil Kalimullin16 Dec