List:Commits« Previous MessageNext Message »
From:Alexander Barkov Date:November 7 2011 12:04pm
Subject:bzr push into mysql-trunk branch (alexander.barkov:3550 to 3552) WL#946
View as plain text  
 3552 Alexander Barkov	2011-11-07
      WL#946: more clean-ups in MYSQL_TIME_cache:
      now set_XXX() functions automatically reset string representation.
      This is needed because in case of prepared statements
      fix_length_and_dec() is called twice: at prepare time and at execute time.
      We need to clean string representation when set_XXX() is called from the
      execute time fix_length_and_dec().

    modified:
      sql/item_timefunc.cc
      sql/item_timefunc.h
      unittest/gunit/item-t.cc
 3551 Alexander Barkov	2011-11-07
      WL#946: Bug#13354645 CRASH IN ITEM_TEMPORAL_HYBRID_FUNC

    modified:
      mysql-test/r/type_temporal_fractional.result
      mysql-test/t/type_temporal_fractional.test
      sql/item_timefunc.cc
      sql/sql_time.h
 3550 Alexander Barkov	2011-11-07
      WL#946 Improvements in MYSQL_TIME_cache.

    modified:
      sql/item_timefunc.cc
      sql/item_timefunc.h
      unittest/gunit/item-t.cc
=== modified file 'mysql-test/r/type_temporal_fractional.result'
--- a/mysql-test/r/type_temporal_fractional.result	2011-11-02 06:13:46 +0000
+++ b/mysql-test/r/type_temporal_fractional.result	2011-11-07 11:50:35 +0000
@@ -15969,3 +15969,54 @@ FROM t1
 WHERE col_datetime_3_not_null_key NOT IN
 (LEAST( DATE('0000-00-00 00:00:00'), CURDATE()), col_time_2_key);
 DROP TABLE t1;
+SET timestamp=UNIX_TIMESTAMP('2001-11-07 15:13:00');
+CREATE TABLE t1 (
+col_time_3_not_null time(3) NOT NULL,
+col_datetime_4_not_null_key datetime(4) NOT NULL,
+col_datetime_key datetime DEFAULT NULL,
+col_time_1_key time(1) DEFAULT NULL,
+col_time_5 time(5) DEFAULT NULL,
+col_timestamp_6_not_null_key timestamp(6) NULL DEFAULT '0000-00-00 00:00:00.000000',
+pk datetime(6) NOT NULL DEFAULT '0000-00-00 00:00:00.000000',
+PRIMARY KEY (pk),
+KEY col_datetime_4_not_null_key (col_datetime_4_not_null_key),
+KEY col_datetime_key (col_datetime_key),
+KEY col_time_1_key (col_time_1_key),
+KEY col_timestamp_6_not_null_key (col_timestamp_6_not_null_key));
+INSERT INTO t1 VALUES ('12:52:24.022','0000-00-00 00:00:00.0000','2003-05-24 00:00:00','00:20:09.0','15:11:20.03463','0000-00-00 00:00:00.000000','2011-11-07 12:01:35.111932');
+INSERT INTO t1 VALUES ('18:52:49.043','2000-10-13 00:00:00.0000','2005-07-22 00:00:00',NULL,'08:19:02.03845','2000-09-20 03:26:09.009008','2011-11-07 12:01:36.111932');
+INSERT INTO t1 VALUES ('23:46:05.010','2005-12-27 04:06:15.0087','0000-00-00 00:00:00','23:40:13.0','08:30:24.03114','0000-00-00 00:00:00.000000','2011-11-07 12:01:37.111932');
+INSERT INTO t1 VALUES ('00:20:05.000','2009-06-01 08:01:58.0532','2007-03-26 12:18:48','00:20:03.0','20:32:22.04519','2000-08-19 21:00:00.000000','2011-11-07 12:01:38.111932');
+INSERT INTO t1 VALUES ('00:20:05.000','2002-05-01 00:00:00.0000','0000-00-00 00:00:00','04:31:10.0','00:20:04.00000','0000-00-00 00:00:00.000000','2011-11-07 12:01:39.111932');
+INSERT INTO t1 VALUES ('00:20:06.000','2007-07-25 22:20:58.0023','0000-00-00 00:00:00','00:23:16.1',NULL,'2008-03-19 16:17:15.042024','2011-11-07 12:01:40.111932');
+INSERT INTO t1 VALUES ('02:55:32.040','0000-00-00 00:00:00.0000',NULL,'00:20:02.0','08:45:57.00998','2009-06-25 10:21:16.011345','2011-11-07 12:01:41.111932');
+INSERT INTO t1 VALUES ('00:20:06.000','2009-01-07 01:12:15.0324','2000-05-26 00:00:00','17:41:45.1','00:20:07.00000','0000-00-00 00:00:00.000000','2011-11-07 12:01:42.111932');
+INSERT INTO t1 VALUES ('12:01:30.061','2009-04-01 00:00:00.0000','2001-05-08 05:31:04','07:43:41.1','11:12:29.03251','2009-12-22 17:45:46.040987','2011-11-07 12:01:43.111932');
+INSERT INTO t1 VALUES ('00:16:22.057','2005-05-10 00:18:58.0345',NULL,'02:24:15.0',NULL,'2008-02-14 20:55:46.023678','2011-11-07 12:01:44.111932');
+INSERT INTO t1 VALUES ('06:54:17.018','2002-12-27 12:28:03.0382','0000-00-00 00:00:00','19:19:54.0','01:42:30.03406','0000-00-00 00:00:00.000000','2011-11-07 12:01:45.111932');
+INSERT INTO t1 VALUES ('00:20:04.000','2007-03-11 00:00:00.0000','0000-00-00 00:00:00',NULL,'13:12:03.05778','2005-02-19 02:31:13.046418','2011-11-07 12:01:46.111932');
+INSERT INTO t1 VALUES ('00:20:01.000','2009-08-13 00:00:00.0000','0000-00-00 00:00:00','00:20:02.0',NULL,'2008-05-21 10:53:59.004633','2011-11-07 12:01:47.111932');
+INSERT INTO t1 VALUES ('02:44:13.025','2001-07-02 14:06:37.0411','2009-04-01 00:43:45','00:20:07.0','16:15:02.01279','2004-07-28 17:34:20.031118','2011-11-07 12:01:48.111932');
+INSERT INTO t1 VALUES ('14:51:02.019','2006-02-24 04:12:05.0014','0000-00-00 00:00:00','00:20:08.0','00:20:09.00000','2001-04-25 21:00:00.000000','2011-11-07 12:01:49.111932');
+SELECT
+col_timestamp_6_not_null_key AS c1,
+col_datetime_key AS c2,
+UTC_DATE() AS c3 
+FROM t1
+WHERE col_time_1_key BETWEEN
+TIMESTAMPADD(MONTH, 38 ,CONVERT_TZ( DATE(MAKEDATE(207, 38 )), '+00:00','+04:00'))
+AND LOCALTIMESTAMP()
+ORDER BY col_datetime_4_not_null_key , col_time_5 , col_time_3_not_null;
+c1	c2	c3
+2009-06-25 10:21:16.011345	NULL	2001-11-07
+0000-00-00 00:00:00.000000	2003-05-24 00:00:00	2001-11-07
+2004-07-28 17:34:20.031118	2009-04-01 00:43:45	2001-11-07
+0000-00-00 00:00:00.000000	0000-00-00 00:00:00	2001-11-07
+2008-02-14 20:55:46.023678	NULL	2001-11-07
+2001-04-25 21:00:00.000000	0000-00-00 00:00:00	2001-11-07
+2008-03-19 16:17:15.042024	0000-00-00 00:00:00	2001-11-07
+2009-12-22 17:45:46.040987	2001-05-08 05:31:04	2001-11-07
+2000-08-19 21:00:00.000000	2007-03-26 12:18:48	2001-11-07
+2008-05-21 10:53:59.004633	0000-00-00 00:00:00	2001-11-07
+DROP TABLE t1;
+SET timestamp=DEFAULT;

=== modified file 'mysql-test/t/type_temporal_fractional.test'
--- a/mysql-test/t/type_temporal_fractional.test	2011-11-02 06:13:46 +0000
+++ b/mysql-test/t/type_temporal_fractional.test	2011-11-07 11:50:35 +0000
@@ -6765,6 +6765,49 @@ WHERE col_datetime_3_not_null_key NOT IN
 --enable_result_log
 DROP TABLE t1;
 
+#
+# Bug#13354645 CRASH IN ITEM_TEMPORAL_HYBRID_FUNC
+#
+SET timestamp=UNIX_TIMESTAMP('2001-11-07 15:13:00');
+CREATE TABLE t1 (
+  col_time_3_not_null time(3) NOT NULL,
+  col_datetime_4_not_null_key datetime(4) NOT NULL,
+  col_datetime_key datetime DEFAULT NULL,
+  col_time_1_key time(1) DEFAULT NULL,
+  col_time_5 time(5) DEFAULT NULL,
+  col_timestamp_6_not_null_key timestamp(6) NULL DEFAULT '0000-00-00 00:00:00.000000',
+  pk datetime(6) NOT NULL DEFAULT '0000-00-00 00:00:00.000000',
+  PRIMARY KEY (pk),
+  KEY col_datetime_4_not_null_key (col_datetime_4_not_null_key),
+  KEY col_datetime_key (col_datetime_key),
+  KEY col_time_1_key (col_time_1_key),
+  KEY col_timestamp_6_not_null_key (col_timestamp_6_not_null_key));
+INSERT INTO t1 VALUES ('12:52:24.022','0000-00-00 00:00:00.0000','2003-05-24 00:00:00','00:20:09.0','15:11:20.03463','0000-00-00 00:00:00.000000','2011-11-07 12:01:35.111932');
+INSERT INTO t1 VALUES ('18:52:49.043','2000-10-13 00:00:00.0000','2005-07-22 00:00:00',NULL,'08:19:02.03845','2000-09-20 03:26:09.009008','2011-11-07 12:01:36.111932');
+INSERT INTO t1 VALUES ('23:46:05.010','2005-12-27 04:06:15.0087','0000-00-00 00:00:00','23:40:13.0','08:30:24.03114','0000-00-00 00:00:00.000000','2011-11-07 12:01:37.111932');
+INSERT INTO t1 VALUES ('00:20:05.000','2009-06-01 08:01:58.0532','2007-03-26 12:18:48','00:20:03.0','20:32:22.04519','2000-08-19 21:00:00.000000','2011-11-07 12:01:38.111932');
+INSERT INTO t1 VALUES ('00:20:05.000','2002-05-01 00:00:00.0000','0000-00-00 00:00:00','04:31:10.0','00:20:04.00000','0000-00-00 00:00:00.000000','2011-11-07 12:01:39.111932');
+INSERT INTO t1 VALUES ('00:20:06.000','2007-07-25 22:20:58.0023','0000-00-00 00:00:00','00:23:16.1',NULL,'2008-03-19 16:17:15.042024','2011-11-07 12:01:40.111932');
+INSERT INTO t1 VALUES ('02:55:32.040','0000-00-00 00:00:00.0000',NULL,'00:20:02.0','08:45:57.00998','2009-06-25 10:21:16.011345','2011-11-07 12:01:41.111932');
+INSERT INTO t1 VALUES ('00:20:06.000','2009-01-07 01:12:15.0324','2000-05-26 00:00:00','17:41:45.1','00:20:07.00000','0000-00-00 00:00:00.000000','2011-11-07 12:01:42.111932');
+INSERT INTO t1 VALUES ('12:01:30.061','2009-04-01 00:00:00.0000','2001-05-08 05:31:04','07:43:41.1','11:12:29.03251','2009-12-22 17:45:46.040987','2011-11-07 12:01:43.111932');
+INSERT INTO t1 VALUES ('00:16:22.057','2005-05-10 00:18:58.0345',NULL,'02:24:15.0',NULL,'2008-02-14 20:55:46.023678','2011-11-07 12:01:44.111932');
+INSERT INTO t1 VALUES ('06:54:17.018','2002-12-27 12:28:03.0382','0000-00-00 00:00:00','19:19:54.0','01:42:30.03406','0000-00-00 00:00:00.000000','2011-11-07 12:01:45.111932');
+INSERT INTO t1 VALUES ('00:20:04.000','2007-03-11 00:00:00.0000','0000-00-00 00:00:00',NULL,'13:12:03.05778','2005-02-19 02:31:13.046418','2011-11-07 12:01:46.111932');
+INSERT INTO t1 VALUES ('00:20:01.000','2009-08-13 00:00:00.0000','0000-00-00 00:00:00','00:20:02.0',NULL,'2008-05-21 10:53:59.004633','2011-11-07 12:01:47.111932');
+INSERT INTO t1 VALUES ('02:44:13.025','2001-07-02 14:06:37.0411','2009-04-01 00:43:45','00:20:07.0','16:15:02.01279','2004-07-28 17:34:20.031118','2011-11-07 12:01:48.111932');
+INSERT INTO t1 VALUES ('14:51:02.019','2006-02-24 04:12:05.0014','0000-00-00 00:00:00','00:20:08.0','00:20:09.00000','2001-04-25 21:00:00.000000','2011-11-07 12:01:49.111932');
+SELECT
+  col_timestamp_6_not_null_key AS c1,
+  col_datetime_key AS c2,
+  UTC_DATE() AS c3 
+FROM t1
+WHERE col_time_1_key BETWEEN
+  TIMESTAMPADD(MONTH, 38 ,CONVERT_TZ( DATE(MAKEDATE(207, 38 )), '+00:00','+04:00'))
+  AND LOCALTIMESTAMP()
+ORDER BY col_datetime_4_not_null_key , col_time_5 , col_time_3_not_null;
+DROP TABLE t1;
+SET timestamp=DEFAULT;
 
 ## TS-TODO: SELECT CAST('00:00:00' AS DATETIME) -> should it use curdate?
 ## TS-TODO: Item::get_date() works via string for DECIMAL_RESULT/FLOAT_RESULT: select cast(20110512154559.616 as date)

=== modified file 'sql/item_timefunc.cc'
--- a/sql/item_timefunc.cc	2011-11-07 07:44:22 +0000
+++ b/sql/item_timefunc.cc	2011-11-07 12:02:15 +0000
@@ -1800,62 +1800,64 @@ bool Item_func_from_days::get_date(MYSQL
 
 void MYSQL_TIME_cache::set_time(MYSQL_TIME *ltime, uint8 dec_arg)
 {
-  DBUG_ASSERT(string_buff[0] == '\0' && string_length == 0);
   DBUG_ASSERT(ltime->time_type == MYSQL_TIMESTAMP_TIME);
   time= *ltime;
   time_packed= TIME_to_longlong_time_packed(&time);
   dec= dec_arg;
+  reset_string();
 }
 
 
 void MYSQL_TIME_cache::set_date(MYSQL_TIME *ltime)
 {
-  DBUG_ASSERT(string_buff[0] == '\0' && string_length == 0);
   DBUG_ASSERT(ltime->time_type == MYSQL_TIMESTAMP_DATE);
   time= *ltime;
   time_packed= TIME_to_longlong_date_packed(&time);
+  dec= 0;
+  reset_string();
 }
 
 
 void MYSQL_TIME_cache::set_datetime(MYSQL_TIME *ltime, uint8 dec_arg)
 {
-  DBUG_ASSERT(string_buff[0] == '\0' && string_length == 0);
   DBUG_ASSERT(ltime->time_type == MYSQL_TIMESTAMP_DATETIME);
   time= *ltime;
   time_packed= TIME_to_longlong_datetime_packed(&time);
   dec= dec_arg;
+  reset_string();
 }
 
 
 void MYSQL_TIME_cache::set_datetime(struct timeval tv, uint8 dec_arg,
                                     Time_zone *tz)
 {
-  DBUG_ASSERT(string_buff[0] == '\0' && string_length == 0);
   tz->gmt_sec_to_TIME(&time, tv);
   time_packed= TIME_to_longlong_datetime_packed(&time);
   dec= dec_arg;
+  reset_string();
 }
 
 
 void MYSQL_TIME_cache::set_date(struct timeval tv, Time_zone *tz)
 {
-  DBUG_ASSERT(string_buff[0] == '\0' && string_length == 0);
   tz->gmt_sec_to_TIME(&time, (my_time_t) tv.tv_sec);
   time.time_type= MYSQL_TIMESTAMP_DATE;
   /* We don't need to set second_part and neg because they are already 0 */
   time.hour= time.minute= time.second= 0;
   time_packed= TIME_to_longlong_date_packed(&time);
+  dec= 0;
+  reset_string();
 }
 
 
 void MYSQL_TIME_cache::set_time(struct timeval tv, uint8 dec_arg,
                                 Time_zone *tz)
 {
-  DBUG_ASSERT(string_buff[0] == '\0' && string_length == 0);
   tz->gmt_sec_to_TIME(&time, tv);
   datetime_to_time(&time);
   time_packed= TIME_to_longlong_time_packed(&time);
   dec= dec_arg;
+  reset_string();
 }
 
 
@@ -2373,6 +2375,17 @@ bool Item_date_add_interval::get_date_in
   if (date_sub_interval)
     interval.neg = !interval.neg;
 
+  /*
+    Make sure we return proper time_type.
+    It's important for val_str().
+  */
+  if (cached_field_type == MYSQL_TYPE_DATE &&
+      ltime->time_type == MYSQL_TIMESTAMP_DATETIME)
+    datetime_to_date(ltime);
+  else if (cached_field_type == MYSQL_TYPE_DATETIME &&
+           ltime->time_type == MYSQL_TIMESTAMP_DATE)
+    date_to_datetime(ltime);
+
   if ((null_value= date_add_interval(ltime, int_type, interval)))
     return true;
   return false;

=== modified file 'sql/item_timefunc.h'
--- a/sql/item_timefunc.h	2011-11-07 07:44:22 +0000
+++ b/sql/item_timefunc.h	2011-11-07 12:02:15 +0000
@@ -677,11 +677,13 @@ class MYSQL_TIME_cache
     If string representation has already been cached, then nothing happens.
   */
   void cache_string();
-public:
-
-  MYSQL_TIME_cache()
+  /**
+    Reset string representation.
+  */
+  void reset_string()
   {
-    reset();
+    string_length= 0;
+    string_buff[0]= '\0';
   }
   /**
     Reset all members.
@@ -690,10 +692,15 @@ public:
   {
     time.time_type= MYSQL_TIMESTAMP_NONE;
     time_packed= 0;
-    string_length= 0;
-    string_buff[0]= '\0';
+    reset_string();
     dec= 0;
   }
+public:
+
+  MYSQL_TIME_cache()
+  {
+    reset();
+  }
   /**
     Set time and time_packed from a DATE value.
   */

=== modified file 'sql/sql_time.h'
--- a/sql/sql_time.h	2011-11-02 11:21:10 +0000
+++ b/sql/sql_time.h	2011-11-07 11:50:35 +0000
@@ -53,6 +53,15 @@ inline void datetime_to_time(MYSQL_TIME 
   ltime->year= ltime->month= ltime->day= 0;
   ltime->time_type= MYSQL_TIMESTAMP_TIME;
 }
+inline void datetime_to_date(MYSQL_TIME *ltime)
+{
+  ltime->hour= ltime->minute= ltime->second= ltime->second_part= 0;
+  ltime->time_type= MYSQL_TIMESTAMP_DATE;
+}
+inline void date_to_datetime(MYSQL_TIME *ltime)
+{
+  ltime->time_type= MYSQL_TIMESTAMP_DATETIME;
+}
 void make_truncated_value_warning(THD *thd,
                                   Sql_condition::enum_warning_level level,
                                   ErrConvString val,

=== modified file 'unittest/gunit/item-t.cc'
--- a/unittest/gunit/item-t.cc	2011-11-07 07:44:22 +0000
+++ b/unittest/gunit/item-t.cc	2011-11-07 12:02:15 +0000
@@ -414,7 +414,6 @@ TEST_F(ItemTest, MYSQL_TIME_cache)
   str= cache.val_str(&str_buff);
   EXPECT_STREQ("2011-11-07 10:20:30.123456", str->c_ptr_safe());
   EXPECT_STREQ("2011-11-07 10:20:30.123456", cache.cptr());
-  cache.reset();
   cache.set_datetime(&datetime6, 6);
   // Now call the other way around: cptr() then val_str()
   EXPECT_STREQ("2011-11-07 10:20:30.123456", cache.cptr());
@@ -446,7 +445,6 @@ TEST_F(ItemTest, MYSQL_TIME_cache)
      Testing DATETIME(6).
      Initializing from "struct timeval".
   */
-  cache.reset();
   cache.set_datetime(tv6, 6, my_tz_UTC);
   EXPECT_EQ(1840440237558456896LL, cache.val_packed());
   EXPECT_EQ(6, cache.decimals());
@@ -458,7 +456,6 @@ TEST_F(ItemTest, MYSQL_TIME_cache)
     Testing TIME(6).
     Initializing from MYSQL_TIME.
   */
-  cache.reset();
   cache.set_time(&time6, 6);
   EXPECT_EQ(709173043776LL, cache.val_packed());
   EXPECT_EQ(6, cache.decimals());
@@ -471,7 +468,6 @@ TEST_F(ItemTest, MYSQL_TIME_cache)
     Testing TIME(6).
     Initializing from "struct timeval".
   */
-  cache.reset();
   cache.set_time(tv6, 6, my_tz_UTC);
   EXPECT_EQ(709173043776LL, cache.val_packed());
   EXPECT_EQ(6, cache.decimals());
@@ -482,7 +478,6 @@ TEST_F(ItemTest, MYSQL_TIME_cache)
   /*
     Testing DATETIME(5)
   */
-  cache.reset();
   MYSQL_TIME datetime5=
   { 2011, 11, 7, 10, 20, 30, 123450, 0, MYSQL_TIMESTAMP_DATETIME };
   cache.set_datetime(&datetime5, 5);
@@ -492,7 +487,6 @@ TEST_F(ItemTest, MYSQL_TIME_cache)
   str= cache.val_str(&str_buff);
   EXPECT_STREQ("2011-11-07 10:20:30.12345", str->c_ptr_safe());
   EXPECT_STREQ("2011-11-07 10:20:30.12345", cache.cptr());
-  cache.reset();
   cache.set_datetime(&datetime5, 5);
   /* Now call the other way around: cptr() then val_str() */
   EXPECT_STREQ("2011-11-07 10:20:30.12345", cache.cptr());
@@ -502,7 +496,6 @@ TEST_F(ItemTest, MYSQL_TIME_cache)
     Testing DATE.
     Initializing from MYSQL_TIME.
   */
-  cache.reset();
   MYSQL_TIME date=
   { 2011, 11, 7, 0, 0, 0, 0, 0, MYSQL_TIMESTAMP_DATE };
   cache.set_date(&date);
@@ -516,7 +509,6 @@ TEST_F(ItemTest, MYSQL_TIME_cache)
     Testing DATE.
     Initializing from "struct tm".
   */
-  cache.reset();
   cache.set_date(tv6, my_tz_UTC);
   EXPECT_EQ(1840439528385413120LL, cache.val_packed());
   EXPECT_EQ(0, cache.decimals());

No bundle (reason: useless for push emails).
Thread
bzr push into mysql-trunk branch (alexander.barkov:3550 to 3552) WL#946Alexander Barkov11 Nov