MySQL Lists are EOL. Please join:

List:Commits« Previous MessageNext Message »
From:kpettersson Date:November 13 2006 7:08pm
Subject:bk commit into 5.0 tree (Kristofer.Pettersson:1.2298) BUG#16546
View as plain text  
Below is the list of changes that have just been committed into a local
5.0 repository of Kristofer Pettersson. When Kristofer Pettersson does a push these changes will
be propagated to the main repository and, within 24 hours after the
push, to the public repository.
For information on how to access the public repository
see http://dev.mysql.com/doc/mysql/en/installing-source-tree.html

ChangeSet@stripped, 2006-11-13 20:07:42+01:00, Kristofer.Pettersson@naruto. +6 -0
  Bug#16546 DATETIME+0 not always coerced the same way
  There was a difference between how a DATETIME/DATE-cast and a
  DATETIME/DATE resolve the same numerical operations.
  - Added checks to determine if a numberic operation is working
    on a DATETIME or DATE field and change result set to a
    my_decimal object rather than a double. 

  sql/item.cc@stripped, 2006-11-13 20:06:19+01:00, Kristofer.Pettersson@naruto. +2 -1
    - Move global into class context.

  sql/item.h@stripped, 2006-11-13 20:06:20+01:00, Kristofer.Pettersson@naruto. +6 -0
    - Added pointer to current statement context.

  sql/item_func.cc@stripped, 2006-11-13 20:06:21+01:00, Kristofer.Pettersson@naruto. +25 -6
    - Changed result type for numeric operations involing DATE and DATETIME
      fields.

  sql/item_timefunc.cc@stripped, 2006-11-13 20:06:22+01:00, Kristofer.Pettersson@naruto. +142 -0
    - Added function override to catch decimal operation on the now
      function.

  sql/item_timefunc.h@stripped, 2006-11-13 20:06:22+01:00, Kristofer.Pettersson@naruto. +6 -2
    - Added function overrides for val_decimal.
    - Added limit to number of decimals for the cast function on a date
      and datetime.
    - 

  sql/sql_class.h@stripped, 2006-11-13 20:06:23+01:00, Kristofer.Pettersson@naruto. +6 -0
    - Clarified interface to the mem_root.

# This is a BitKeeper patch.  What follows are the unified diffs for the
# set of deltas contained in the patch.  The rest of the patch, the part
# that BitKeeper cares about, is below these diffs.
# User:	Kristofer.Pettersson
# Host:	naruto.
# Root:	C:/cpp/bug16546/my50-bug16546

--- 1.235/sql/item.cc	2006-11-13 20:08:05 +01:00
+++ 1.236/sql/item.cc	2006-11-13 20:08:05 +01:00
@@ -308,7 +308,7 @@ Item::Item():
   cmp_context= (Item_result)-1;
 
   /* Put item in free list so that we can free all items at end */
-  THD *thd= current_thd;
+  this->thd= current_thd;
   next= thd->free_list;
   thd->free_list= this;
   /*
@@ -349,6 +349,7 @@ Item::Item(THD *thd, Item *item):
 {
   next= thd->free_list;				// Put in free list
   thd->free_list= this;
+  this->thd = thd;
 }
 
 

--- 1.209/sql/item.h	2006-11-13 20:08:06 +01:00
+++ 1.210/sql/item.h	2006-11-13 20:08:06 +01:00
@@ -451,6 +451,12 @@ public:
 
   enum traverse_order { POSTFIX, PREFIX };
   
+  /*
+    A pointer to the statement context which instantiated this
+    Item.
+  */
+  THD *thd;
+
   /* Reuse size, only used by SP local variable assignment, otherwize 0 */
   uint rsize;
 

--- 1.305/sql/item_func.cc	2006-11-13 20:08:06 +01:00
+++ 1.306/sql/item_func.cc	2006-11-13 20:08:06 +01:00
@@ -650,11 +650,13 @@ bool Item_func_connection_id::fix_fields
 
 
 /*
-  Check arguments here to determine result's type for a numeric
+  @brief Check arguments here to determine result's type for a numeric
   function of two arguments.
 
-  SYNOPSIS
-    Item_num_op::find_num_type()
+  @note We change behavior of the numeric operation based on parameter
+  type, but because of the SQL language we always aim to project the
+  result onto a real number space and request each parameter object to
+  give us a scalar projection of it's current value.
 */
 
 void Item_num_op::find_num_type(void)
@@ -668,9 +670,26 @@ void Item_num_op::find_num_type(void)
   if (r0 == REAL_RESULT || r1 == REAL_RESULT ||
       r0 == STRING_RESULT || r1 ==STRING_RESULT)
   {
-    count_real_length();
-    max_length= float_length(decimals);
-    hybrid_type= REAL_RESULT;
+    /*
+      If either field is a datetime we want to cast this operator
+      into returning a my_decimal object and not a regular floating
+      point value because of the amount of significant numbers 
+      needed.
+    */
+    enum_field_types f0= args[0]->field_type();
+    enum_field_types f1= args[1]->field_type();
+    if( f0 == MYSQL_TYPE_DATETIME || f1 == MYSQL_TYPE_DATETIME 
+      || f0 == MYSQL_TYPE_DATE || f1 == MYSQL_TYPE_DATE)
+    {
+      hybrid_type= DECIMAL_RESULT;
+      result_precision();
+    } 
+    else
+    {
+      count_real_length();
+      max_length= float_length(decimals);
+      hybrid_type= REAL_RESULT;
+    }
   }
   else if (r0 == DECIMAL_RESULT || r1 == DECIMAL_RESULT)
   {

--- 1.124/sql/item_timefunc.cc	2006-11-13 20:08:06 +01:00
+++ 1.125/sql/item_timefunc.cc	2006-11-13 20:08:06 +01:00
@@ -1445,6 +1445,36 @@ String *Item_func_now::val_str(String *s
   return &str_value;
 }
 
+/*
+  @note Can't call parent Item_func_date because we have no where to
+  store the result.
+ */
+my_decimal *Item_func_now::val_decimal(my_decimal *decimal_value)
+{
+  DBUG_ASSERT(fixed == 1);
+  
+  
+  MEM_ROOT *stmt_mem_root = this->thd->get_mem_root();
+  CHARSET_INFO *my_charset = this->default_charset();
+  String *datetime_str = new (stmt_mem_root) String("",0,my_charset);
+  
+  /* 
+    Construct the datetime representation as a string.
+    TODO add microseconds
+  */
+  char buffer[25];
+  my_sprintf(buffer,(buffer,"%04u%02u%02u%02u%02u%02u",
+    ltime.year,ltime.month,ltime.day,ltime.hour,ltime.minute,ltime.second));
+  datetime_str->append(buffer);
+  
+  (void)str2my_decimal(E_DEC_FATAL_ERROR, (char*) datetime_str->ptr(),
+                datetime_str->length(), datetime_str->charset(), decimal_value);
+
+  delete datetime_str;
+
+  return decimal_value;
+
+}
 
 void Item_func_now::fix_length_and_dec()
 {
@@ -2491,6 +2521,64 @@ longlong Item_datetime_typecast::val_int
   return TIME_to_ulonglong_datetime(&ltime);
 }
 
+double Item_datetime_typecast::val_real() 
+{
+  return (double)val_int();
+}
+
+/*
+  @brief Returns the decimal representation of a datetime value.
+
+  @param decimal_value A pointer to an instantiated my_decimal 
+  object containing the resulting decimal value.
+
+  @detail The decimal representation of a datetime is because of
+  historical reasons the same as the internal format 
+  YYYYMMDDhhmmss.uuuuuu expressed as a real number.
+  
+  @note This should possibly benefit from a refactoring of behavior
+  into returning the representation of seconds after epoch.
+
+  @return A pointer to the modified my_decimal object.
+
+  @see Item::find_num_type (FIXME!)
+*/
+my_decimal *Item_datetime_typecast::val_decimal(my_decimal *decimal_value)
+{
+  DBUG_ASSERT(fixed == 1);
+  TIME ltime;
+    
+  MEM_ROOT *stmt_mem_root = this->thd->get_mem_root();
+  CHARSET_INFO *my_charset = this->default_charset();
+  String *datetime_str = new (stmt_mem_root) String("",0,my_charset);
+
+  if (get_arg0_date(&ltime,1))
+  {
+    null_value= 1;
+    (void)str2my_decimal(E_DEC_FATAL_ERROR, datetime_str->ptr(),
+               datetime_str->length(), datetime_str->charset(), decimal_value);
+    /*
+       This will return decimal 0.0 but FIXME! will contain an error code
+    */
+    return decimal_value;
+  }
+  
+  /* 
+    Construct the datetime representation as a string.
+    TODO add microseconds
+  */
+  char buffer[25];
+  my_sprintf(buffer,(buffer,"%04u%02u%02u%02u%02u%02u",
+    ltime.year,ltime.month,ltime.day,ltime.hour,ltime.minute,ltime.second));
+  datetime_str->append(buffer);
+  
+  (void)str2my_decimal(E_DEC_FATAL_ERROR, (char*) datetime_str->ptr(),
+                datetime_str->length(), datetime_str->charset(), decimal_value);
+
+  delete datetime_str;
+
+  return decimal_value;
+}
 
 bool Item_time_typecast::get_time(TIME *ltime)
 {
@@ -2538,6 +2626,60 @@ bool Item_date_typecast::get_date(TIME *
   ltime->hour= ltime->minute= ltime->second= ltime->second_part= 0;
   ltime->time_type= MYSQL_TIMESTAMP_DATE;
   return res;
+}
+
+/*
+  @brief Returns the decimal representation of a datetime value.
+
+  @param decimal_value A pointer to an instantiated my_decimal 
+  object containing the resulting decimal value.
+
+  @detail The decimal representation of a datetime is because of
+  historical reasons the same as the internal format 
+  YYYYMMDDhhmmss.uuuuuu expressed as a real number.
+  
+  @note This should possibly benefit from a refactoring of behavior
+  into returning the representation of seconds after epoch.
+
+  @return A pointer to the modified my_decimal object.
+
+  @see Item::find_num_type (FIXME!)
+*/
+my_decimal *Item_date_typecast::val_decimal(my_decimal *decimal_value)
+{
+  DBUG_ASSERT(fixed == 1);
+  TIME ltime;
+    
+  MEM_ROOT *stmt_mem_root = this->thd->get_mem_root();
+  CHARSET_INFO *my_charset = this->default_charset();
+  String *date_str = new (stmt_mem_root) String("",0,my_charset);
+
+  if (get_arg0_date(&ltime,1))
+  {
+    null_value= 1;
+    (void)str2my_decimal(E_DEC_FATAL_ERROR, date_str->ptr(),
+               date_str->length(), date_str->charset(), decimal_value);
+    /*
+       This will return decimal 0.0 but FIXME! will contain an error code
+    */
+    return decimal_value;
+  }
+  
+  /* 
+    Construct the datetime representation as a string.
+    TODO add microseconds
+  */
+  char buffer[25];
+  my_sprintf(buffer,(buffer,"%04u%02u%02u%",
+    ltime.year,ltime.month,ltime.day));
+  date_str->append(buffer);
+  
+  (void)str2my_decimal(E_DEC_FATAL_ERROR, (char*) date_str->ptr(),
+                date_str->length(), date_str->charset(), decimal_value);
+
+  delete date_str;
+
+  return decimal_value;
 }
 
 

--- 1.68/sql/item_timefunc.h	2006-11-13 20:08:06 +01:00
+++ 1.69/sql/item_timefunc.h	2006-11-13 20:08:06 +01:00
@@ -467,6 +467,7 @@ public:
   String *val_str(String *str);
   void fix_length_and_dec();
   bool get_date(TIME *res, uint fuzzy_date);
+  my_decimal *val_decimal(my_decimal *decimal_value);
   virtual void store_now_in_TIME(TIME *now_time)=0;
 };
 
@@ -741,7 +742,7 @@ public:
 class Item_date_typecast :public Item_typecast_maybe_null
 {
 public:
-  Item_date_typecast(Item *a) :Item_typecast_maybe_null(a) {}
+  Item_date_typecast(Item *a) :Item_typecast_maybe_null(a) { this->decimals= DATETIME_DEC; }
   const char *func_name() const { return "cast_as_date"; }
   String *val_str(String *str);
   bool get_date(TIME *ltime, uint fuzzy_date);
@@ -759,6 +760,7 @@ public:
   }
   bool result_as_longlong() { return TRUE; }
   longlong val_int();
+  my_decimal *val_decimal(my_decimal *decimal_value);
 };
 
 
@@ -783,7 +785,7 @@ public:
 class Item_datetime_typecast :public Item_typecast_maybe_null
 {
 public:
-  Item_datetime_typecast(Item *a) :Item_typecast_maybe_null(a) {}
+  Item_datetime_typecast(Item *a) :Item_typecast_maybe_null(a) { this->decimals= DATETIME_DEC; }
   const char *func_name() const { return "cast_as_datetime"; }
   String *val_str(String *str);
   const char *cast_type() const { return "datetime"; }
@@ -794,6 +796,8 @@ public:
   }
   bool result_as_longlong() { return TRUE; }
   longlong val_int();
+  double val_real();
+  my_decimal *Item_datetime_typecast::val_decimal(my_decimal *my_decimal);
 };
 
 class Item_func_makedate :public Item_str_func

--- 1.300/sql/sql_class.h	2006-11-13 20:08:07 +01:00
+++ 1.301/sql/sql_class.h	2006-11-13 20:08:07 +01:00
@@ -677,6 +677,7 @@ public:
   */
   Item *free_list;
   MEM_ROOT *mem_root;                   // Pointer to current memroot
+  MEM_ROOT *get_mem_root() { return mem_root; }
 #ifndef DBUG_OFF
   bool is_backup_arena; /* True if this arena is used for backup. */
 #endif
@@ -827,6 +828,11 @@ public:
   void restore_backup_statement(Statement *stmt, Statement *backup);
   /* return class type */
   virtual Type type() const;
+
+  /*
+    @brief return the mem root used by this statement.
+  */
+  MEM_ROOT *get_statement_mem_root() { return &main_mem_root; }
 };
 
 


Thread
bk commit into 5.0 tree (Kristofer.Pettersson:1.2298) BUG#16546kpettersson13 Nov