List:Commits« Previous MessageNext Message »
From:Alexander Barkov Date:November 3 2011 9:35am
Subject:bzr push into mysql-trunk branch (alexander.barkov:3547 to 3548) WL#946
View as plain text  
 3548 Alexander Barkov	2011-11-03
      WL#946 clean-ups
      - Introducing new class MYSQL_TIME_cache.
      - minor other improvements

    modified:
      sql/field.cc
      sql/item_timefunc.cc
      sql/item_timefunc.h
      sql/sql_class.h
      sql/sql_time.cc
      sql/tztime.h
 3547 Alexander Barkov	2011-11-02
      WL#946 clean-ups

    modified:
      mysys/my_getsystime.c
      sql/item_timefunc.h
=== modified file 'sql/field.cc'
--- a/sql/field.cc	2011-11-01 11:52:24 +0000
+++ b/sql/field.cc	2011-11-03 09:33:45 +0000
@@ -5344,7 +5344,6 @@ bool Field_timestamp::get_date_internal(
   ASSERT_COLUMN_MARKED_FOR_READ;
   uint32 temp;
   THD  *thd= table ? table->in_use : current_thd;
-  thd->time_zone_used= 1;
 #ifdef WORDS_BIGENDIAN
   if (table && table->s->db_low_byte_first)
     temp= uint4korr(ptr);
@@ -5353,7 +5352,7 @@ bool Field_timestamp::get_date_internal(
     longget(temp, ptr);
   if (!temp)
     return true;
-  thd->variables.time_zone->gmt_sec_to_TIME(ltime, (my_time_t) temp);
+  thd->time_zone()->gmt_sec_to_TIME(ltime, (my_time_t) temp);
   return false;
 }
 
@@ -5564,11 +5563,9 @@ Field_timestampf::get_date_internal(MYSQ
   THD *thd= table ? table->in_use : current_thd;
   struct timeval tm;
   my_timestamp_from_binary(&tm, ptr, dec);
-  thd->time_zone_used= 1;
   if (tm.tv_sec == 0)
     return true;
-  thd->variables.time_zone->gmt_sec_to_TIME(ltime, (my_time_t) tm.tv_sec);
-  ltime->second_part= tm.tv_usec;
+  thd->time_zone()->gmt_sec_to_TIME(ltime, tm);
   return false;
 }
 

=== modified file 'sql/item_timefunc.cc'
--- a/sql/item_timefunc.cc	2011-11-02 11:21:10 +0000
+++ b/sql/item_timefunc.cc	2011-11-03 09:33:45 +0000
@@ -1028,16 +1028,14 @@ bool Item_date_literal::eq(const Item *i
   return
     item->basic_const_item() && type() == item->type() &&
     func_name() == ((Item_func *) item)->func_name() &&
-    ctime_as_temporal == ((Item_date_literal *) item)->ctime_as_temporal;
+    cached_time.eq(((Item_date_literal *) item)->cached_time);
 }
 
 
 void Item_date_literal::print(String *str, enum_query_type query_type)
 {
-  char buff[MAX_DATE_STRING_REP_LENGTH];
   str->append("DATE'");
-  my_date_to_str(&ctime, buff);
-  str->append(buff);
+  str->append(cached_time.cptr());
   str->append('\'');
 }
 
@@ -1047,16 +1045,14 @@ bool Item_datetime_literal::eq(const Ite
   return
     item->basic_const_item() && type() == item->type() &&
     func_name() == ((Item_func *) item)->func_name() &&
-    ctime_as_temporal == ((Item_datetime_literal *) item)->ctime_as_temporal;
+    cached_time.eq(((Item_datetime_literal *) item)->cached_time);
 }
 
 
 void Item_datetime_literal::print(String *str, enum_query_type query_type)
 {
-  char buff[MAX_DATE_STRING_REP_LENGTH];
   str->append("TIMESTAMP'");
-  my_datetime_to_str(&ctime, buff, decimals);
-  str->append(buff);
+  str->append(cached_time.cptr());
   str->append('\'');
 }
 
@@ -1066,16 +1062,14 @@ bool Item_time_literal::eq(const Item *i
   return
     item->basic_const_item() && type() == item->type() &&
     func_name() == ((Item_func *) item)->func_name() &&
-    ctime_as_temporal == ((Item_time_literal *) item)->ctime_as_temporal;
+    cached_time.eq(((Item_time_literal *) item)->cached_time);
 }
 
 
 void Item_time_literal::print(String *str, enum_query_type query_type)
 {
-  char buff[MAX_DATE_STRING_REP_LENGTH];
   str->append("TIME'");
-  my_time_to_str(&ctime, buff, decimals);
-  str->append(buff);
+  str->append(cached_time.cptr());
   str->append('\'');
 }
 
@@ -1804,191 +1798,194 @@ bool Item_func_from_days::get_date(MYSQL
 }
 
 
-void Item_func_curdate::fix_length_and_dec()
+/**
+  Set time and time_packed from a TIME value.
+*/
+void MYSQL_TIME_cache::set_time(MYSQL_TIME *ltime, uint8 dec_arg)
 {
-  Item_date_func::fix_length_and_dec();
-
-  store_now_in_TIME(&ctime);
-  
-  /* We don't need to set second_part and neg because they already 0 */
-  ctime.hour= ctime.minute= ctime.second= 0;
-  ctime.time_type= MYSQL_TIMESTAMP_DATE;
-  ctime_as_longlong= (longlong) TIME_to_longlong_date_packed(&ctime);
+  DBUG_ASSERT(ltime->time_type == MYSQL_TIMESTAMP_TIME);
+  time= *ltime;
+  time_packed= TIME_to_longlong_time_packed(&time);
+  dec= dec_arg;
 }
 
 
-String *Item_func_curdate::val_str(String *str)
+/**
+  Set time and time_packed from a DATE value.
+*/
+void MYSQL_TIME_cache::set_date(MYSQL_TIME *ltime)
 {
-  DBUG_ASSERT(fixed == 1);
-  if (str->alloc(MAX_DATE_STRING_REP_LENGTH))
-  {
-    null_value= 1;
-    return (String *) 0;
-  }
-  make_date((DATE_TIME_FORMAT *) 0, &ctime, str);
-  return str;
+  DBUG_ASSERT(ltime->time_type == MYSQL_TIMESTAMP_DATE);
+  time= *ltime;
+  time_packed= TIME_to_longlong_date_packed(&time);
 }
 
 
 /**
-    Converts current time in my_time_t to MYSQL_TIME represenatation for local
-    time zone. Defines time zone (local) used for whole CURDATE function.
+  Set time and time_packed from a DATETIME value.
 */
-void Item_func_curdate_local::store_now_in_TIME(MYSQL_TIME *now_time)
+void MYSQL_TIME_cache::set_datetime(MYSQL_TIME *ltime, uint8 dec_arg)
 {
-  THD *thd= current_thd;
-  thd->variables.time_zone->gmt_sec_to_TIME(now_time, 
-                                            (my_time_t) thd->query_start());
-  thd->time_zone_used= 1;
+  DBUG_ASSERT(ltime->time_type == MYSQL_TIMESTAMP_DATETIME);
+  time= *ltime;
+  time_packed= TIME_to_longlong_datetime_packed(&time);
+  dec= dec_arg;
 }
 
 
 /**
-    Converts current time in my_time_t to MYSQL_TIME represenatation for UTC
-    time zone. Defines time zone (UTC) used for whole UTC_DATE function.
+  Set time and time_packed according to DATETIME value
+  in "struct timeval" representation and its time zone.
 */
-void Item_func_curdate_utc::store_now_in_TIME(MYSQL_TIME *now_time)
+void MYSQL_TIME_cache::set_datetime(struct timeval tv, uint8 dec_arg,
+                                    Time_zone *tz)
 {
-  my_tz_UTC->gmt_sec_to_TIME(now_time, 
-                             (my_time_t) (current_thd->query_start()));
-  /* 
-    We are not flagging this query as using time zone, since it uses fixed
-    UTC-SYSTEM time-zone.
-  */
+  tz->gmt_sec_to_TIME(&time, tv);
+  time_packed= TIME_to_longlong_datetime_packed(&time);
+  dec= dec_arg;
 }
 
 
-bool Item_func_curdate::get_date(MYSQL_TIME *res,
-				 uint fuzzy_date __attribute__((unused)))
+/**
+  Set time and time_packed according to DATE value
+  in "struct timeval" representation and its time zone.
+*/
+void MYSQL_TIME_cache::set_date(struct timeval tv, Time_zone *tz)
 {
-  *res= ctime;
-  return 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);
 }
 
 
-String *Item_func_curtime::val_str(String *str)
+/**
+  Set time and time_packed according to TIME value
+  in "struct timeval" representation and its time zone.
+*/
+void MYSQL_TIME_cache::set_time(struct timeval tv, uint8 dec_arg,
+                                Time_zone *tz)
 {
-  DBUG_ASSERT(fixed == 1);
-  str_value.set(buff, buff_length, &my_charset_latin1);
-  return &str_value;
+  tz->gmt_sec_to_TIME(&time, tv);
+  datetime_to_time(&time);
+  time_packed= TIME_to_longlong_time_packed(&time);
+  dec= dec_arg;
 }
 
 
-bool Item_func_curtime::get_time(MYSQL_TIME *ltime)
+/**
+  Cache string representation from the cached MYSQL_TIME representation.
+  If string representation has already been cached, then nothing happens.
+*/
+void MYSQL_TIME_cache::cache_string()
 {
-  *ltime= ctime;
-  return false;
+  DBUG_ASSERT(time.time_type != MYSQL_TIMESTAMP_NONE);
+  if (!string_length)
+    string_length= my_TIME_to_str(&time, string_buff, decimals());
 }
 
 
-void Item_func_curtime::fix_length_and_dec()
+/**
+  Cache string representation (if needed) and return it as C string.
+*/
+const char *MYSQL_TIME_cache::cptr()
 {
-  if (check_precision())
-    return;
-  store_now_in_TIME(&ctime);
-  ctime_as_temporal= TIME_to_longlong_time_packed(&ctime);
-  buff_length= (uint) my_time_to_str(&ctime, buff, decimals);
-  fix_length_and_charset_datetime(buff_length);
+  cache_string();
+  return string_buff;
 }
 
 
-void Item_func_curtime::store_now_in_TIME_tz(THD *thd, Time_zone *tz,
-                                             MYSQL_TIME *now_time)
+/**
+  Cache string representation (if needed) and return it as String.
+*/
+String *MYSQL_TIME_cache::val_str(String *str)
 {
-  struct timeval tv= thd->query_start_timeval_trunc(decimals);
-  tz->gmt_sec_to_TIME(now_time, (my_time_t) tv.tv_sec);
-  now_time->second_part= tv.tv_usec;
-  datetime_to_time(now_time);
+  cache_string();
+  str->set(string_buff, string_length, &my_charset_latin1);
+  return str;
 }
 
-/**
-    Converts current time in my_time_t to MYSQL_TIME represenatation for local
-    time zone. Defines time zone (local) used for whole CURTIME function.
-*/
-void Item_func_curtime_local::store_now_in_TIME(MYSQL_TIME *now_time)
+
+/* CURDATE() and UTC_DATE() */
+void Item_func_curdate::fix_length_and_dec()
 {
   THD *thd= current_thd;
-  store_now_in_TIME_tz(thd, thd->variables.time_zone, now_time);
-  thd->time_zone_used= 1;
+  Item_date_func::fix_length_and_dec();
+  cached_time.set_date(thd->query_start_timeval_trunc(decimals), time_zone());
 }
 
 
-/**
-    Converts current time in my_time_t to MYSQL_TIME represenatation for UTC
-    time zone. Defines time zone (UTC) used for whole UTC_TIME function.
-*/
-void Item_func_curtime_utc::store_now_in_TIME(MYSQL_TIME *now_time)
+Time_zone *Item_func_curdate_local::time_zone()
 {
-  store_now_in_TIME_tz(current_thd, my_tz_UTC, now_time);
-  /* 
-    We are not flagging this query as using time zone, since it uses fixed
-    UTC-SYSTEM time-zone.
-  */
+  return current_thd->time_zone();
 }
 
 
-String *Item_func_now::val_str(String *str)
+Time_zone *Item_func_curdate_utc::time_zone()
 {
-  DBUG_ASSERT(fixed == 1);
-  str_value.set(buff, buff_length, &my_charset_numeric);
-  return &str_value;
+  return my_tz_UTC;
 }
 
 
-void Item_func_now::fix_length_and_dec()
+/* CURTIME() and UTC_TIME() */
+void Item_func_curtime::fix_length_and_dec()
 {
   if (check_precision())
     return;
-  store_now_in_TIME(&ctime);
-  ctime_as_longlong= (longlong) TIME_to_longlong_datetime_packed(&ctime);
-  buff_length= (uint) my_datetime_to_str(&ctime, buff, decimals);
-  fix_length_and_charset_datetime(buff_length);
+  THD *thd= current_thd;
+  cached_time.set_time(thd->query_start_timeval_trunc(decimals), decimals,
+                       time_zone());
+  /*
+    We use 8 instead of MAX_TIME_WIDTH (which is 10) becase:
+    - there is no sign 
+    - hour is in the 2-digit range
+  */
+  fix_length_and_dec_and_charset_datetime(8, decimals);
 }
 
 
-/**
-    Converts current time in my_time_t to MYSQL_TIME represenatation for local
-    time zone. Defines time zone (local) used for whole NOW function.
-*/
-void Item_func_now_local::store_now_in_TIME(MYSQL_TIME *now_time)
+Time_zone *Item_func_curtime_local::time_zone()
 {
-  THD *thd= current_thd;
-  struct timeval tv= thd->query_start_timeval_trunc(decimals);
-  thd->variables.time_zone->gmt_sec_to_TIME(now_time, (my_time_t) tv.tv_sec);
-  now_time->second_part= tv.tv_usec;
-  thd->time_zone_used= 1;
+  return current_thd->time_zone();
 }
 
 
-/**
-    Converts current time in my_time_t to MYSQL_TIME represenatation for UTC
-    time zone. Defines time zone (UTC) used for whole UTC_TIMESTAMP function.
-*/
-void Item_func_now_utc::store_now_in_TIME(MYSQL_TIME *now_time)
+Time_zone *Item_func_curtime_utc::time_zone()
+{
+  return my_tz_UTC;
+}
+
+
+/* NOW() and UTC_TIMESTAMP () */
+
+void Item_func_now::fix_length_and_dec()
 {
+  if (check_precision())
+    return;
   THD *thd= current_thd;
-  struct timeval tv= thd->query_start_timeval_trunc(decimals);
-  my_tz_UTC->gmt_sec_to_TIME(now_time, (my_time_t) thd->query_start());
-  now_time->second_part= tv.tv_usec;
-  /* 
-    We are not flagging this query as using time zone, since it uses fixed
-    UTC-SYSTEM time-zone.
-  */
+  cached_time.set_datetime(thd->query_start_timeval_trunc(decimals), decimals,
+                           time_zone());
+  fix_length_and_dec_and_charset_datetime(MAX_DATETIME_WIDTH, decimals);
 }
 
 
-bool Item_func_now::get_date(MYSQL_TIME *res,
-                             uint fuzzy_date __attribute__((unused)))
+Time_zone *Item_func_now_local::time_zone()
 {
-  *res= ctime;
-  return 0;
+  return current_thd->time_zone();
+}
+
+
+Time_zone *Item_func_now_utc::time_zone()
+{
+  return my_tz_UTC;
 }
 
 
 int Item_func_now::save_in_field(Field *to, bool no_conversions)
 {
   to->set_notnull();
-  return to->store_time(&ctime, decimals);
+  return to->store_time(cached_time.get_TIME(), decimals);
 }
 
 
@@ -2001,14 +1998,13 @@ bool Item_func_sysdate_local::get_date(M
 {
   THD *thd= current_thd;
   ulonglong tmp= my_micro_time();
-  thd->variables.time_zone->gmt_sec_to_TIME(now_time,
-                                            (my_time_t) (tmp / 1000000));
+  thd->time_zone()->gmt_sec_to_TIME(now_time,
+                                    (my_time_t) (tmp / 1000000));
   if (decimals)
   {
     now_time->second_part= tmp % 1000000;
     my_datetime_trunc(now_time, decimals);
   }
-  thd->time_zone_used= 1;
   return false;
 }
 

=== modified file 'sql/item_timefunc.h'
--- a/sql/item_timefunc.h	2011-11-02 14:05:10 +0000
+++ b/sql/item_timefunc.h	2011-11-03 09:33:45 +0000
@@ -658,17 +658,100 @@ public:
 
 
 /**
+  Cache for MYSQL_TIME value with various representations.
+  
+  - MYSQL_TIME representation (time) is initialized during set_XXX().
+  - Packed representation (time_packed) is also initialized during set_XXX().
+  - String representation (string_buff) is not initialized during set_XXX(),
+    It's initialized only if val_str() or cptr() are called.
+*/
+class MYSQL_TIME_cache
+{
+  MYSQL_TIME time;                              // MYSQL_TIME representation
+  longlong time_packed;                         // packed representation
+  char string_buff[MAX_DATE_STRING_REP_LENGTH]; // string representation
+  uint string_length;                           // length of string
+  uint8 dec;                                    // Number of decimals
+  void cache_string(); // Store string representation to string_buff
+public:
+  MYSQL_TIME_cache()
+  {
+    time.time_type= MYSQL_TIMESTAMP_NONE;
+    string_length= 0;
+    string_buff[0]= '\0';
+    dec= 0;
+  }
+  // Initialize time and time_packed from MYSQL_TIME parameter.
+  void set_date(MYSQL_TIME *ltime);
+  void set_time(MYSQL_TIME *ltime, uint8 dec_arg);
+  void set_datetime(MYSQL_TIME *ltime, uint8 dec_arg);
+  // Initialize time and time_packed from "struct timeval" and time zone.
+  void set_date(struct timeval tv, Time_zone *tz);
+  void set_time(struct timeval tv, uint8 dec_arg, Time_zone *tz);
+  void set_datetime(struct timeval tv, uint8 dec_arg, Time_zone *tz);
+
+  /**
+    Test if cached value is equal to another MYSQL_TIME_cache value.
+  */
+  bool eq(const MYSQL_TIME_cache &tm) const
+  {
+    return val_packed() == tm.val_packed();
+  }
+
+  /**
+    Return number of decimal digits.
+  */
+  uint8 decimals() const
+  {
+    DBUG_ASSERT(time.time_type != MYSQL_TIMESTAMP_NONE);
+    return dec;
+  }
+
+  /**
+    Return packed representation.
+  */
+  longlong val_packed() const
+  {
+    DBUG_ASSERT(time.time_type != MYSQL_TIMESTAMP_NONE);
+    return time_packed;
+  }
+  /**
+    Store MYSQL_TIME representation into the given MYSQL_TIME variable.
+  */
+  void get_TIME(MYSQL_TIME *ltime) const
+  {
+    DBUG_ASSERT(time.time_type != MYSQL_TIMESTAMP_NONE);
+    *ltime= time;
+  }
+  /**
+    Return pointer to MYSQL_TIME representation.
+  */
+  MYSQL_TIME *get_TIME()
+  {
+    DBUG_ASSERT(time.time_type != MYSQL_TIMESTAMP_NONE);
+    return &time;
+  }
+  /**
+    Store string representation into String.
+  */
+  String *val_str(String *str);
+  /**
+    Return C string representation.
+  */
+  const char *cptr();
+};
+
+
+/**
   DATE'2010-01-01'
 */
 class Item_date_literal :public Item_date_func
 {
-  MYSQL_TIME ctime;           // Date value
-  longlong ctime_as_temporal; // Cached packed representation of ctime
+  MYSQL_TIME_cache cached_time;
 public:
   Item_date_literal(MYSQL_TIME *ltime) :Item_date_func()
   {
-    ctime= *ltime;
-    ctime_as_temporal= TIME_to_longlong_date_packed(&ctime);
+    cached_time.set_date(ltime);
     fix_length_and_dec();
     fixed= 1;
   }
@@ -677,14 +760,19 @@ public:
   longlong val_date_temporal()
   {
     DBUG_ASSERT(fixed);
-    return ctime_as_temporal;
+    return cached_time.val_packed();
   }
   bool get_date(MYSQL_TIME *ltime, uint fuzzy_date)
   {
     DBUG_ASSERT(fixed);
-    *ltime= ctime;
+    cached_time.get_TIME(ltime);
     return false;
   }
+  String *val_str(String *str)
+  {
+    DBUG_ASSERT(fixed);
+    return cached_time.val_str(str);
+  }
   void fix_length_and_dec()
   {
     fix_length_and_dec_and_charset_datetime(MAX_DATE_WIDTH, 0);
@@ -711,14 +799,12 @@ public:
 */
 class Item_time_literal :public Item_time_func
 {
-  MYSQL_TIME ctime;           // Time value
-  longlong ctime_as_temporal; // Cached packed representation of ctime
+  MYSQL_TIME_cache cached_time;
 public:
   Item_time_literal(MYSQL_TIME *ltime, uint dec_arg) :Item_time_func()
   {
-    ctime= *ltime;
-    ctime_as_temporal= TIME_to_longlong_time_packed(&ctime);
     decimals= min(dec_arg, DATETIME_MAX_DECIMALS);
+    cached_time.set_time(ltime, decimals);
     fix_length_and_dec();
     fixed= 1;
   }
@@ -727,14 +813,19 @@ public:
   longlong val_time_temporal()
   {
     DBUG_ASSERT(fixed);
-    return ctime_as_temporal;
+    return cached_time.val_packed();
   }
   bool get_time(MYSQL_TIME *ltime)
   {
     DBUG_ASSERT(fixed);
-    *ltime= ctime;
+    cached_time.get_TIME(ltime);
     return false;
   }
+  String *val_str(String *str)
+  {
+    DBUG_ASSERT(fixed);
+    return cached_time.val_str(str);
+  }
   void fix_length_and_dec()
   {
     fix_length_and_dec_and_charset_datetime(MAX_TIME_WIDTH, decimals);
@@ -761,14 +852,12 @@ public:
 */
 class Item_datetime_literal :public Item_datetime_func
 {
-  MYSQL_TIME ctime;            // Datetime value
-  longlong ctime_as_temporal;  // Cached packed representation of ctime
+  MYSQL_TIME_cache cached_time;
 public:
   Item_datetime_literal(MYSQL_TIME *ltime, uint dec_arg) :Item_datetime_func()
   {
-    ctime= *ltime;
-    ctime_as_temporal= TIME_to_longlong_datetime_packed(&ctime);
     decimals= min(dec_arg, DATETIME_MAX_DECIMALS);
+    cached_time.set_datetime(ltime, decimals);
     fix_length_and_dec();
     fixed= 1;
   }
@@ -777,14 +866,19 @@ public:
   longlong val_date_temporal()
   {
     DBUG_ASSERT(fixed);
-    return ctime_as_temporal;
+    return cached_time.val_packed();
   }
   bool get_date(MYSQL_TIME *ltime, uint fuzzy_date)
   {
     DBUG_ASSERT(fixed);
-    *ltime= ctime;
+    cached_time.get_TIME(ltime);
     return false;
   }
+  String *val_str(String *str)
+  {
+    DBUG_ASSERT(fixed);
+    return cached_time.val_str(str);
+  }
   void fix_length_and_dec()
   {
     fix_length_and_dec_and_charset_datetime(MAX_DATETIME_WIDTH, decimals);
@@ -810,35 +904,36 @@ public:
 
 class Item_func_curtime :public Item_time_func
 {
-  char buff[9*2+32];
-  uint buff_length;
-  MYSQL_TIME ctime;            // TIME value
-  longlong ctime_as_temporal;  // Cached packed representation of ctime
-protected:
-  void store_now_in_TIME_tz(THD *thd, Time_zone *tz, MYSQL_TIME *now_time);
-  /* 
-    Abstract method that defines which time zone is used for conversion.
-    Converts time current time in my_time_t representation to broken-down
-    MYSQL_TIME representation using UTC-SYSTEM or per-thread time zone.
-  */
-  virtual void store_now_in_TIME(MYSQL_TIME *now_time)=0;
+  MYSQL_TIME_cache cached_time; // Initialized in fix_length_and_dec
+protected:
+  // Abstract method that defines which time zone is used for conversion.
+  virtual Time_zone *time_zone()= 0;
 public:
   Item_func_curtime(uint8 dec_arg) :Item_time_func() { decimals= dec_arg; }
+  void fix_length_and_dec();
   longlong val_time_temporal()
   {
     DBUG_ASSERT(fixed == 1);
-    return ctime_as_temporal;
+    return cached_time.val_packed();
+  }
+  bool get_time(MYSQL_TIME *ltime)
+  {
+    DBUG_ASSERT(fixed == 1);
+    cached_time.get_TIME(ltime);
+    return false;
+  }
+  String *val_str(String *str)
+  {
+    DBUG_ASSERT(fixed == 1);
+    return cached_time.val_str(&str_value);
   }
-  String *val_str(String *str);
-  void fix_length_and_dec();
-  bool get_time(MYSQL_TIME *ltime);
 };
 
 
 class Item_func_curtime_local :public Item_func_curtime
 {
 protected:
-  virtual void store_now_in_TIME(MYSQL_TIME *now_time);
+  Time_zone *time_zone();
 public:
   Item_func_curtime_local(ulong dec_arg) :Item_func_curtime(dec_arg) {}
   const char *func_name() const { return "curtime"; }
@@ -848,7 +943,7 @@ public:
 class Item_func_curtime_utc :public Item_func_curtime
 {
 protected:
-  virtual void store_now_in_TIME(MYSQL_TIME *now_time);
+  Time_zone *time_zone();
 public:
   Item_func_curtime_utc(ulong dec_arg) :Item_func_curtime(dec_arg) {}
   const char *func_name() const { return "utc_time"; }
@@ -859,27 +954,35 @@ public:
 
 class Item_func_curdate :public Item_date_func
 {
-  MYSQL_TIME ctime;           // Initialized in fix_length_and_dec
-  longlong ctime_as_longlong; // Initialized in fix_length_and_dec
+  MYSQL_TIME_cache cached_time; // Initialized in fix_length_and_dec
 protected:
-  virtual void store_now_in_TIME(MYSQL_TIME *now_time)=0;
+  virtual Time_zone *time_zone()= 0;
 public:
   Item_func_curdate() :Item_date_func() {}
+  void fix_length_and_dec();
   longlong val_date_temporal()
   {
     DBUG_ASSERT(fixed == 1);
-    return (ctime_as_longlong) ;
+    return cached_time.val_packed();
+  }
+  bool get_date(MYSQL_TIME *res, uint fuzzy_date)
+  {
+    DBUG_ASSERT(fixed == 1);
+    cached_time.get_TIME(res);
+    return false;
+  }
+  String *val_str(String *str)
+  {
+    DBUG_ASSERT(fixed == 1);
+    return cached_time.val_str(&str_value);
   }
-  String *val_str(String *str);
-  void fix_length_and_dec();
-  bool get_date(MYSQL_TIME *res, uint fuzzy_date);
 };
 
 
 class Item_func_curdate_local :public Item_func_curdate
 {
 protected:
-  void store_now_in_TIME(MYSQL_TIME *now_time);
+  Time_zone *time_zone();
 public:
   Item_func_curdate_local() :Item_func_curdate() {}
   const char *func_name() const { return "curdate"; }
@@ -889,7 +992,7 @@ public:
 class Item_func_curdate_utc :public Item_func_curdate
 {
 protected:
-  void store_now_in_TIME(MYSQL_TIME *now_time);
+  Time_zone *time_zone();
 public:
   Item_func_curdate_utc() :Item_func_curdate() {}
   const char *func_name() const { return "utc_date"; }
@@ -900,30 +1003,36 @@ public:
 
 class Item_func_now :public Item_datetime_func
 {
+  MYSQL_TIME_cache cached_time; 
 protected:
-  MYSQL_TIME ctime;           // Datetime value
-  longlong ctime_as_longlong; // Cached packed representation of ctime
-  char buff[20*2+32];	// +32 to make my_snprintf_{8bit|ucs2} happy
-  uint buff_length;
-  virtual void store_now_in_TIME(MYSQL_TIME *now_time)=0;
+  virtual Time_zone *time_zone()= 0;
 public:
   Item_func_now(uint8 dec_arg) :Item_datetime_func() { decimals= dec_arg; }
+  void fix_length_and_dec();
+  int save_in_field(Field *to, bool no_conversions);
   longlong val_date_temporal()
   {
     DBUG_ASSERT(fixed == 1);
-    return ctime_as_longlong;
+    return cached_time.val_packed();
+  }
+  bool get_date(MYSQL_TIME *res, uint fuzzy_date)
+  {
+    DBUG_ASSERT(fixed == 1);
+    cached_time.get_TIME(res);
+    return false;
+  }
+  String *val_str(String *str)
+  {
+    DBUG_ASSERT(fixed == 1);
+    return cached_time.val_str(&str_value);
   }
-  int save_in_field(Field *to, bool no_conversions);
-  String *val_str(String *str);
-  void fix_length_and_dec();
-  bool get_date(MYSQL_TIME *res, uint fuzzy_date);
 };
 
 
 class Item_func_now_local :public Item_func_now
 {
 protected:
-  virtual void store_now_in_TIME(MYSQL_TIME *now_time);
+  Time_zone *time_zone();
 public:
   Item_func_now_local(ulong dec_arg) :Item_func_now(dec_arg) {}
   const char *func_name() const { return "now"; }
@@ -934,7 +1043,7 @@ public:
 class Item_func_now_utc :public Item_func_now
 {
 protected:
-  virtual void store_now_in_TIME(MYSQL_TIME *now_time);
+  Time_zone *time_zone();
 public:
   Item_func_now_utc(ulong dec_arg) :Item_func_now(dec_arg) {}
   const char *func_name() const { return "utc_timestamp"; }

=== modified file 'sql/sql_class.h'
--- a/sql/sql_class.h	2011-11-02 11:21:10 +0000
+++ b/sql/sql_class.h	2011-11-03 09:33:45 +0000
@@ -2709,6 +2709,11 @@ public:
     return variables.sql_mode &
       (MODE_NO_ZERO_IN_DATE | MODE_NO_ZERO_DATE | MODE_INVALID_DATES);
   }
+  inline Time_zone *time_zone()
+  {
+    time_zone_used= 1;
+    return variables.time_zone;
+  }
   inline time_t query_start()
   {
     query_start_used= 1;

=== modified file 'sql/sql_time.cc'
--- a/sql/sql_time.cc	2011-11-02 11:21:10 +0000
+++ b/sql/sql_time.cc	2011-11-03 09:33:45 +0000
@@ -625,9 +625,8 @@ my_time_t TIME_to_timestamp(THD *thd, co
   my_time_t timestamp;
 
   *in_dst_time_gap= 0;
-  thd->time_zone_used= 1;
 
-  timestamp= thd->variables.time_zone->TIME_to_gmt_sec(t, in_dst_time_gap);
+  timestamp= thd->time_zone()->TIME_to_gmt_sec(t, in_dst_time_gap);
   if (timestamp)
   {
     return timestamp;

=== modified file 'sql/tztime.h'
--- a/sql/tztime.h	2011-06-30 15:50:45 +0000
+++ b/sql/tztime.h	2011-11-03 09:33:45 +0000
@@ -52,6 +52,15 @@ public:
   */
   virtual void   gmt_sec_to_TIME(MYSQL_TIME *tmp, my_time_t t) const = 0;
   /**
+    Comverts "struct timeval" to local time in
+    broken down MYSQL_TIME represendation.
+  */
+  void gmt_sec_to_TIME(MYSQL_TIME *tmp, struct timeval tv)
+  {
+    gmt_sec_to_TIME(tmp, (my_time_t) tv.tv_sec);
+    tmp->second_part= tv.tv_usec;
+  }
+  /**
     Because of constness of String returned by get_name() time zone name 
     have to be already zeroended to be able to use String::ptr() instead
     of c_ptr().

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