List:Commits« Previous MessageNext Message »
From:Alexander Barkov Date:August 15 2012 11:57am
Subject:bzr push into mysql-trunk branch (alexander.barkov:4230 to 4231)
View as plain text  
 4231 Alexander Barkov	2012-08-15 [merge]
      Merging from 5.6.

    modified:
      sql/binlog.cc
      sql/item.cc
      sql/item_func.cc
      sql/log_event.h
      sql/rpl_master.cc
      sql/sql_class.cc
      sql/sql_class.h
      sql/sql_prepare.cc
 4230 Martin Hansson	2012-08-15
      Bug#13985071: DEPRECATE INSERT DELAYED
      
      Follow-up patch. There is now a deprecation message when using system
      variables that are part of the INSERT DELAYED feature. The variables
      are also flagged as deprecated when running mysqld --help.

    modified:
      mysql-test/r/delayed.result
      mysql-test/r/mysqld--help-notwin.result
      mysql-test/r/mysqld--help-win.result
      mysql-test/r/variables.result
      mysql-test/suite/rpl/r/rpl_bug31076.result
      mysql-test/suite/sys_vars/r/delayed_insert_limit_basic_32.result
      mysql-test/suite/sys_vars/r/delayed_insert_limit_basic_64.result
      mysql-test/suite/sys_vars/r/delayed_insert_limit_func.result
      mysql-test/suite/sys_vars/r/delayed_insert_timeout_basic.result
      mysql-test/suite/sys_vars/r/delayed_queue_size_basic_32.result
      mysql-test/suite/sys_vars/r/delayed_queue_size_basic_64.result
      mysql-test/suite/sys_vars/r/max_delayed_threads_basic.result
      mysql-test/suite/sys_vars/r/max_insert_delayed_threads_basic.result
      mysql-test/t/delayed.test
      sql/sys_vars.cc
=== modified file 'sql/binlog.cc'
--- a/sql/binlog.cc	2012-07-24 11:18:33 +0000
+++ b/sql/binlog.cc	2012-08-15 11:04:29 +0000
@@ -4732,8 +4732,9 @@ bool MYSQL_BIN_LOG::write_event(Log_even
             if (user_var_event->unsigned_flag)
               flags|= User_var_log_event::UNSIGNED_F;
 
-            User_var_log_event e(thd, user_var_event->user_var_event->name.str,
-                                 user_var_event->user_var_event->name.length,
+            User_var_log_event e(thd,
+                                 user_var_event->user_var_event->entry_name.ptr(),
+                                 user_var_event->user_var_event->entry_name.length(),
                                  user_var_event->value,
                                  user_var_event->length,
                                  user_var_event->type,

=== modified file 'sql/item.cc'
--- a/sql/item.cc	2012-08-09 12:30:01 +0000
+++ b/sql/item.cc	2012-08-15 11:04:29 +0000
@@ -3579,9 +3579,9 @@ bool Item_param::set_longdata(const char
 bool Item_param::set_from_user_var(THD *thd, const user_var_entry *entry)
 {
   DBUG_ENTER("Item_param::set_from_user_var");
-  if (entry && entry->value)
+  if (entry && entry->ptr())
   {
-    item_result_type= entry->type;
+    item_result_type= entry->type();
     unsigned_flag= entry->unsigned_flag;
     if (limit_clause_param)
     {
@@ -3592,11 +3592,11 @@ bool Item_param::set_from_user_var(THD *
     }
     switch (item_result_type) {
     case REAL_RESULT:
-      set_double(*(double*)entry->value);
+      set_double(*(double*) entry->ptr());
       item_type= Item::REAL_ITEM;
       break;
     case INT_RESULT:
-      set_int(*(longlong*)entry->value, MY_INT64_NUM_DECIMAL_DIGITS);
+      set_int(*(longlong*) entry->ptr(), MY_INT64_NUM_DECIMAL_DIGITS);
       item_type= Item::INT_ITEM;
       break;
     case STRING_RESULT:
@@ -3621,13 +3621,13 @@ bool Item_param::set_from_user_var(THD *
       */
       item_type= Item::STRING_ITEM;
 
-      if (set_str((const char *)entry->value, entry->length))
+      if (set_str((const char *) entry->ptr(), entry->length()))
         DBUG_RETURN(1);
       break;
     }
     case DECIMAL_RESULT:
     {
-      const my_decimal *ent_value= (const my_decimal *)entry->value;
+      const my_decimal *ent_value= (const my_decimal *) entry->ptr();
       my_decimal2decimal(ent_value, &decimal_value);
       state= DECIMAL_VALUE;
       decimals= ent_value->frac;

=== modified file 'sql/item_func.cc'
--- a/sql/item_func.cc	2012-08-07 13:37:23 +0000
+++ b/sql/item_func.cc	2012-08-15 10:38:01 +0000
@@ -4550,9 +4550,7 @@ longlong Item_func_sleep::val_int()
 }
 
 
-#define extra_size sizeof(double)
-
-static user_var_entry *get_variable(HASH *hash, Name_string &name,
+static user_var_entry *get_variable(HASH *hash, const Name_string &name,
 				    bool create_if_not_exists)
 {
   user_var_entry *entry;
@@ -4561,32 +4559,10 @@ static user_var_entry *get_variable(HASH
                                                  name.length())) &&
       create_if_not_exists)
   {
-    uint size=ALIGN_SIZE(sizeof(user_var_entry))+name.length()+1+extra_size;
     if (!my_hash_inited(hash))
       return 0;
-    if (!(entry = (user_var_entry*) my_malloc(size,MYF(MY_WME | ME_FATALERROR))))
+    if (!(entry= user_var_entry::create(name)))
       return 0;
-    entry->name.str=(char*) entry+ ALIGN_SIZE(sizeof(user_var_entry))+
-      extra_size;
-    entry->name.length= name.length();
-    entry->value=0;
-    entry->length=0;
-    entry->update_query_id=0;
-    entry->collation.set(NULL, DERIVATION_IMPLICIT, 0);
-    entry->unsigned_flag= 0;
-    /*
-      If we are here, we were called from a SET or a query which sets a
-      variable. Imagine it is this:
-      INSERT INTO t SELECT @a:=10, @a:=@a+1.
-      Then when we have a Item_func_get_user_var (because of the @a+1) so we
-      think we have to write the value of @a to the binlog. But before that,
-      we have a Item_func_set_user_var to create @a (@a:=10), in this we mark
-      the variable as "already logged" (line below) so that it won't be logged
-      by Item_func_get_user_var (because that's not necessary).
-    */
-    entry->used_query_id=current_thd->query_id;
-    entry->type=STRING_RESULT;
-    name.strcpy(entry->name.str);
     if (my_hash_insert(hash,(uchar*) entry))
     {
       my_free(entry);
@@ -4699,11 +4675,60 @@ bool Item_func_set_user_var::register_fi
 }
 
 
+bool user_var_entry::realloc(uint length)
+{
+  if (length <= extra_size)
+  {
+    /* Enough space to store value in value struct */
+    free_value();
+    m_ptr= internal_buffer_ptr();
+  }
+  else
+  {
+    /* Allocate an external buffer */
+    if (m_length != length)
+    {
+      if (m_ptr == internal_buffer_ptr())
+        m_ptr= 0;
+      if (!(m_ptr= (char*) my_realloc(m_ptr, length,
+                                      MYF(MY_ALLOW_ZERO_PTR | MY_WME |
+                                      ME_FATALERROR))))
+        return true;
+    }
+  }
+  return false;
+}
+
+
+/**
+  Set value to user variable.
+  @param ptr            pointer to buffer with new value
+  @param length         length of new value
+  @param type           type of new value
+
+  @retval  false   on success
+  @retval  true    on allocation error
+
+*/
+bool user_var_entry::store(void *from, uint length, Item_result type)
+{
+  // Store strings with end \0
+  if (realloc(length + test(type == STRING_RESULT)))
+    return true;
+  if (type == STRING_RESULT)
+    m_ptr[length]= 0;     // Store end \0
+  memmove(m_ptr, from, length);
+  if (type == DECIMAL_RESULT)
+    ((my_decimal*) m_ptr)->fix_buffer_pointer();
+  m_length= length;
+  m_type= type;
+  return false;
+}
+
+
 /**
   Set value to user variable.
 
-  @param entry          pointer to structure representing variable
-  @param set_null       should we set NULL value ?
   @param ptr            pointer to buffer with new value
   @param length         length of new value
   @param type           type of new value
@@ -4719,63 +4744,15 @@ bool Item_func_set_user_var::register_fi
     true    failure
 */
 
-static bool
-update_hash(user_var_entry *entry, bool set_null, void *ptr, uint length,
-            Item_result type, const CHARSET_INFO *cs, Derivation dv,
-            bool unsigned_arg)
-{
-  if (set_null)
-  {
-    char *pos= (char*) entry+ ALIGN_SIZE(sizeof(user_var_entry));
-    if (entry->value && entry->value != pos)
-      my_free(entry->value);
-    entry->value= 0;
-    entry->length= 0;
-  }
-  else
-  {
-    if (type == STRING_RESULT)
-      length++;					// Store strings with end \0
-    if (length <= extra_size)
-    {
-      /* Save value in value struct */
-      char *pos= (char*) entry+ ALIGN_SIZE(sizeof(user_var_entry));
-      if (entry->value != pos)
-      {
-	if (entry->value)
-	  my_free(entry->value);
-	entry->value=pos;
-      }
-    }
-    else
-    {
-      /* Allocate variable */
-      if (entry->length != length)
-      {
-	char *pos= (char*) entry+ ALIGN_SIZE(sizeof(user_var_entry));
-	if (entry->value == pos)
-	  entry->value=0;
-        entry->value= (char*) my_realloc(entry->value, length,
-                                         MYF(MY_ALLOW_ZERO_PTR | MY_WME |
-                                             ME_FATALERROR));
-        if (!entry->value)
-	  return 1;
-      }
-    }
-    if (type == STRING_RESULT)
-    {
-      length--;					// Fix length change above
-      entry->value[length]= 0;			// Store end \0
-    }
-    memmove(entry->value, ptr, length);
-    if (type == DECIMAL_RESULT)
-      ((my_decimal*)entry->value)->fix_buffer_pointer();
-    entry->length= length;
-    entry->collation.set(cs, dv);
-    entry->unsigned_flag= unsigned_arg;
-  }
-  entry->type=type;
-  return 0;
+bool user_var_entry::store(void *ptr, uint length, Item_result type,
+                           const CHARSET_INFO *cs, Derivation dv,
+                           bool unsigned_arg)
+{
+  if (store(ptr, length, type))
+    return true;
+  collation.set(cs, dv);
+  unsigned_flag= unsigned_arg;
+  return false;
 }
 
 
@@ -4795,9 +4772,10 @@ Item_func_set_user_var::update_hash(void
   else
     null_value= args[0]->null_value;
   if (null_value && null_item)
-    res_type= entry->type;                      // Don't change type of item
-  if (::update_hash(entry, null_value,
-                    ptr, length, res_type, cs, dv, unsigned_arg))
+    res_type= entry->type();                    // Don't change type of item
+  if (null_value)
+    entry->set_null_value(res_type);
+  else if (entry->store(ptr, length, res_type, cs, dv, unsigned_arg))
   {
     null_value= 1;
     return 1;
@@ -4810,22 +4788,22 @@ Item_func_set_user_var::update_hash(void
 
 double user_var_entry::val_real(my_bool *null_value)
 {
-  if ((*null_value= (value == 0)))
+  if ((*null_value= (m_ptr == 0)))
     return 0.0;
 
-  switch (type) {
+  switch (m_type) {
   case REAL_RESULT:
-    return *(double*) value;
+    return *(double*) m_ptr;
   case INT_RESULT:
-    return (double) *(longlong*) value;
+    return (double) *(longlong*) m_ptr;
   case DECIMAL_RESULT:
   {
     double result;
-    my_decimal2double(E_DEC_FATAL_ERROR, (my_decimal *)value, &result);
+    my_decimal2double(E_DEC_FATAL_ERROR, (my_decimal *) m_ptr, &result);
     return result;
   }
   case STRING_RESULT:
-    return my_atof(value);                      // This is null terminated
+    return my_atof(m_ptr);                    // This is null terminated
   case ROW_RESULT:
     DBUG_ASSERT(1);				// Impossible
     break;
@@ -4838,24 +4816,24 @@ double user_var_entry::val_real(my_bool
 
 longlong user_var_entry::val_int(my_bool *null_value) const
 {
-  if ((*null_value= (value == 0)))
+  if ((*null_value= (m_ptr == 0)))
     return LL(0);
 
-  switch (type) {
+  switch (m_type) {
   case REAL_RESULT:
-    return (longlong) *(double*) value;
+    return (longlong) *(double*) m_ptr;
   case INT_RESULT:
-    return *(longlong*) value;
+    return *(longlong*) m_ptr;
   case DECIMAL_RESULT:
   {
     longlong result;
-    my_decimal2int(E_DEC_FATAL_ERROR, (my_decimal *)value, 0, &result);
+    my_decimal2int(E_DEC_FATAL_ERROR, (my_decimal *) m_ptr, 0, &result);
     return result;
   }
   case STRING_RESULT:
   {
     int error;
-    return my_strtoll10(value, (char**) 0, &error);// String is null terminated
+    return my_strtoll10(m_ptr, (char**) 0, &error);// String is null terminated
   }
   case ROW_RESULT:
     DBUG_ASSERT(1);				// Impossible
@@ -4870,24 +4848,24 @@ longlong user_var_entry::val_int(my_bool
 String *user_var_entry::val_str(my_bool *null_value, String *str,
 				uint decimals)
 {
-  if ((*null_value= (value == 0)))
+  if ((*null_value= (m_ptr == 0)))
     return (String*) 0;
 
-  switch (type) {
+  switch (m_type) {
   case REAL_RESULT:
-    str->set_real(*(double*) value, decimals, collation.collation);
+    str->set_real(*(double*) m_ptr, decimals, collation.collation);
     break;
   case INT_RESULT:
     if (!unsigned_flag)
-      str->set(*(longlong*) value, collation.collation);
+      str->set(*(longlong*) m_ptr, collation.collation);
     else
-      str->set(*(ulonglong*) value, collation.collation);
+      str->set(*(ulonglong*) m_ptr, collation.collation);
     break;
   case DECIMAL_RESULT:
-    str_set_decimal((my_decimal *) value, str, collation.collation);
+    str_set_decimal((my_decimal *) m_ptr, str, collation.collation);
     break;
   case STRING_RESULT:
-    if (str->copy(value, length, collation.collation))
+    if (str->copy(m_ptr, m_length, collation.collation))
       str= 0;					// EOM error
   case ROW_RESULT:
     DBUG_ASSERT(1);				// Impossible
@@ -4900,21 +4878,22 @@ String *user_var_entry::val_str(my_bool
 
 my_decimal *user_var_entry::val_decimal(my_bool *null_value, my_decimal *val)
 {
-  if ((*null_value= (value == 0)))
+  if ((*null_value= (m_ptr == 0)))
     return 0;
 
-  switch (type) {
+  switch (m_type) {
   case REAL_RESULT:
-    double2my_decimal(E_DEC_FATAL_ERROR, *(double*) value, val);
+    double2my_decimal(E_DEC_FATAL_ERROR, *(double*) m_ptr, val);
     break;
   case INT_RESULT:
-    int2my_decimal(E_DEC_FATAL_ERROR, *(longlong*) value, 0, val);
+    int2my_decimal(E_DEC_FATAL_ERROR, *(longlong*) m_ptr, 0, val);
     break;
   case DECIMAL_RESULT:
-    my_decimal2decimal((my_decimal *) value, val);
+    my_decimal2decimal((my_decimal *) m_ptr, val);
     break;
   case STRING_RESULT:
-    str2my_decimal(E_DEC_FATAL_ERROR, value, length, collation.collation, val);
+    str2my_decimal(E_DEC_FATAL_ERROR, m_ptr, m_length,
+                   collation.collation, val);
     break;
   case ROW_RESULT:
     DBUG_ASSERT(1);				// Impossible
@@ -5453,7 +5432,7 @@ get_var_with_binlog(THD *thd, enum_sql_c
     may need to be valid after current [SP] statement execution pool is
     destroyed.
   */
-  size= ALIGN_SIZE(sizeof(BINLOG_USER_VAR_EVENT)) + var_entry->length;
+  size= ALIGN_SIZE(sizeof(BINLOG_USER_VAR_EVENT)) + var_entry->length();
   if (!(user_var_event= (BINLOG_USER_VAR_EVENT *)
         alloc_root(thd->user_var_events_alloc, size)))
     goto err;
@@ -5461,10 +5440,10 @@ get_var_with_binlog(THD *thd, enum_sql_c
   user_var_event->value= (char*) user_var_event +
     ALIGN_SIZE(sizeof(BINLOG_USER_VAR_EVENT));
   user_var_event->user_var_event= var_entry;
-  user_var_event->type= var_entry->type;
+  user_var_event->type= var_entry->type();
   user_var_event->charset_number= var_entry->collation.collation->number;
   user_var_event->unsigned_flag= var_entry->unsigned_flag;
-  if (!var_entry->value)
+  if (!var_entry->ptr())
   {
     /* NULL value*/
     user_var_event->length= 0;
@@ -5472,9 +5451,9 @@ get_var_with_binlog(THD *thd, enum_sql_c
   }
   else
   {
-    user_var_event->length= var_entry->length;
-    memcpy(user_var_event->value, var_entry->value,
-           var_entry->length);
+    user_var_event->length= var_entry->length();
+    memcpy(user_var_event->value, var_entry->ptr(),
+           var_entry->length());
   }
   /* Mark that this variable has been used by this query */
   var_entry->used_query_id= thd->query_id;
@@ -5506,9 +5485,9 @@ void Item_func_get_user_var::fix_length_
   */
   if (!error && var_entry)
   {
-    m_cached_result_type= var_entry->type;
+    m_cached_result_type= var_entry->type();
     unsigned_flag= var_entry->unsigned_flag;
-    max_length= var_entry->length;
+    max_length= var_entry->length();
 
     collation.set(var_entry->collation);
     switch(m_cached_result_type) {
@@ -5595,7 +5574,7 @@ bool Item_user_var_as_out_param::fix_fie
   if (Item::fix_fields(thd, ref) ||
       !(entry= get_variable(&thd->user_vars, name, 1)))
     return TRUE;
-  entry->type= STRING_RESULT;
+  entry->set_type(STRING_RESULT);
   /*
     Let us set the same collation which is used for loading
     of fields in LOAD DATA INFILE.
@@ -5611,16 +5590,15 @@ bool Item_user_var_as_out_param::fix_fie
 
 void Item_user_var_as_out_param::set_null_value(const CHARSET_INFO* cs)
 {
-  ::update_hash(entry, TRUE, 0, 0, STRING_RESULT, cs,
-                DERIVATION_IMPLICIT, 0 /* unsigned_arg */);
+  entry->set_null_value(STRING_RESULT);
 }
 
 
 void Item_user_var_as_out_param::set_value(const char *str, uint length,
                                            const CHARSET_INFO* cs)
 {
-  ::update_hash(entry, FALSE, (void*)str, length, STRING_RESULT, cs,
-                DERIVATION_IMPLICIT, 0 /* unsigned_arg */);
+  entry->store((void*) str, length, STRING_RESULT, cs,
+               DERIVATION_IMPLICIT, 0 /* unsigned_arg */);
 }
 
 

=== modified file 'sql/log_event.h'
--- a/sql/log_event.h	2012-08-14 08:57:19 +0000
+++ b/sql/log_event.h	2012-08-15 10:38:01 +0000
@@ -2882,7 +2882,7 @@ public:
     UNDEF_F= 0,
     UNSIGNED_F= 1
   };
-  char *name;
+  const char *name;
   uint name_len;
   char *val;
   ulong val_len;
@@ -2892,7 +2892,7 @@ public:
   uchar flags;
 #ifdef MYSQL_SERVER
   bool deferred;
-  User_var_log_event(THD* thd_arg, char *name_arg, uint name_len_arg,
+  User_var_log_event(THD* thd_arg, const char *name_arg, uint name_len_arg,
                      char *val_arg, ulong val_len_arg, Item_result type_arg,
 		     uint charset_number_arg, uchar flags_arg,
                      enum_event_cache_type cache_type_arg,

=== modified file 'sql/rpl_master.cc'
--- a/sql/rpl_master.cc	2012-06-25 09:28:20 +0000
+++ b/sql/rpl_master.cc	2012-08-15 10:38:01 +0000
@@ -313,10 +313,10 @@ static uint8 get_binlog_checksum_value_a
   }
   else
   {
-    DBUG_ASSERT(entry->type == STRING_RESULT);
+    DBUG_ASSERT(entry->type() == STRING_RESULT);
     String str;
     uint dummy_errors;
-    str.copy(entry->value, entry->length, &my_charset_bin, &my_charset_bin,
+    str.copy(entry->ptr(), entry->length(), &my_charset_bin, &my_charset_bin,
              &dummy_errors);
     ret= (uint8) find_type ((char*) str.ptr(), &binlog_checksum_typelib, 1) - 1;
     DBUG_ASSERT(ret <= BINLOG_CHECKSUM_ALG_CRC32); // while it's just on CRC32 alg
@@ -1611,9 +1611,9 @@ String *get_slave_uuid(THD *thd, String
     return NULL;
   user_var_entry *entry=
     (user_var_entry*) my_hash_search(&thd->user_vars, name, sizeof(name)-1);
-  if (entry && entry->length > 0)
+  if (entry && entry->length() > 0)
   {
-    value->copy(entry->value, entry->length, NULL);
+    value->copy(entry->ptr(), entry->length(), NULL);
     return value;
   }
   else

=== modified file 'sql/sql_class.cc'
--- a/sql/sql_class.cc	2012-08-02 08:15:19 +0000
+++ b/sql/sql_class.cc	2012-08-15 11:04:29 +0000
@@ -85,16 +85,13 @@ const char * const THD::DEFAULT_WHERE= "
 extern "C" uchar *get_var_key(user_var_entry *entry, size_t *length,
                               my_bool not_used __attribute__((unused)))
 {
-  *length= entry->name.length;
-  return (uchar*) entry->name.str;
+  *length= entry->entry_name.length();
+  return (uchar*) entry->entry_name.ptr();
 }
 
 extern "C" void free_user_var(user_var_entry *entry)
 {
-  char *pos= (char*) entry+ALIGN_SIZE(sizeof(*entry));
-  if (entry->value && entry->value != pos)
-    my_free(entry->value);
-  my_free(entry);
+  entry->destroy();
 }
 
 bool Key_part_spec::operator==(const Key_part_spec& other) const

=== modified file 'sql/sql_class.h'
--- a/sql/sql_class.h	2012-08-09 07:55:37 +0000
+++ b/sql/sql_class.h	2012-08-15 11:04:29 +0000
@@ -4572,20 +4572,181 @@ public:
 // this is needed for user_vars hash
 class user_var_entry
 {
- public:
+  static const size_t extra_size= sizeof(double);
+  char *m_ptr;          // Value
+  ulong m_length;       // Value length
+  Item_result m_type;   // Value type
+
+  void reset_value()
+  { m_ptr= NULL; m_length= 0; }
+  void set_value(char *value, ulong length)
+  { m_ptr= value; m_length= length; }
+
+  /**
+    Position inside a user_var_entry where small values are stored:
+    double values, longlong values and string values with length
+    up to extra_size (should be 8 bytes on all platforms).
+    String values with length longer than 8 are stored in a separate
+    memory buffer, which is allocated when needed using the method realloc().
+  */
+  char *internal_buffer_ptr() const
+  { return (char *) this + ALIGN_SIZE(sizeof(user_var_entry)); }
+
+  /**
+    Position inside a user_var_entry where a null-terminates array
+    of characters representing the variable name is stored.
+  */
+  char *name_ptr() const
+  { return internal_buffer_ptr() + extra_size; }
+
+  /**
+    Initialize m_ptr to the internal buffer (if the value is small enough),
+    or allocate a separate buffer.
+    @param length - length of the value to be stored.
+  */
+  bool realloc(uint length);
+
+  /**
+    Check if m_ptr point to an external buffer previously alloced by realloc().
+    @retval true  - an external buffer is alloced.
+    @retval false - m_ptr is null, or points to the internal buffer.
+  */
+  bool alloced()
+  { return m_ptr && m_ptr != internal_buffer_ptr(); }
+
+  /**
+    Free the external value buffer, if it's allocated.
+  */
+  void free_value()
+  {
+    if (alloced())
+      my_free(m_ptr);
+  }
+
+  /**
+    Copy the array of characters from the given name into the internal
+    name buffer and initialize entry_name to point to it.
+  */
+  void copy_name(const Simple_cstring &name)
+  {
+    name.strcpy(name_ptr());
+    entry_name= Name_string(name_ptr(), name.length());
+  }
+
+  /**
+    Initialize all members
+    @param name - Name of the user_var_entry instance.
+  */
+  void init(const Simple_cstring &name)
+  {
+    copy_name(name);
+    reset_value();
+    update_query_id= 0;
+    collation.set(NULL, DERIVATION_IMPLICIT, 0);
+    unsigned_flag= 0;
+    /*
+      If we are here, we were called from a SET or a query which sets a
+      variable. Imagine it is this:
+      INSERT INTO t SELECT @a:=10, @a:=@a+1.
+      Then when we have a Item_func_get_user_var (because of the @a+1) so we
+      think we have to write the value of @a to the binlog. But before that,
+      we have a Item_func_set_user_var to create @a (@a:=10), in this we mark
+      the variable as "already logged" (line below) so that it won't be logged
+      by Item_func_get_user_var (because that's not necessary).
+    */
+    used_query_id= current_thd->query_id;
+    set_type(STRING_RESULT);
+  }
+
+  /**
+    Store a value of the given type into a user_var_entry instance.
+    @param from    Value
+    @param length  Size of the value
+    @param type    type
+    @return
+    @retval        false on success
+    @retval        true on memory allocation error
+  */
+  bool store(void *from, uint length, Item_result type);
+
+public:
   user_var_entry() {}                         /* Remove gcc warning */
-  LEX_STRING name;
-  char *value;
-  ulong length;
+
+  Simple_cstring entry_name;  // Variable name
+  DTCollation collation;      // Collation with attributes
   query_id_t update_query_id, used_query_id;
-  Item_result type;
-  bool unsigned_flag;
+  bool unsigned_flag;         // true if unsigned, false if signed
+
+  /**
+    Store a value of the given type and attributes (collation, sign)
+    into a user_var_entry instance.
+    @param from         Value
+    @param length       Size of the value
+    @param type         type
+    @param cs           Character set and collation of the value
+    @param dv           Collationd erivation of the value
+    @param unsigned_arg Signess of the value
+    @return
+    @retval        false on success
+    @retval        true on memory allocation error
+  */
+  bool store(void *from, uint length, Item_result type,
+             const CHARSET_INFO *cs, Derivation dv, bool unsigned_arg);
+  /**
+    Set type of to the given value.
+    @param type  Data type.
+  */
+  void set_type(Item_result type) { m_type= type; }
+  /**
+    Set value to NULL
+    @param type  Data type.
+  */
+
+  void set_null_value(Item_result type)
+  {
+    free_value();
+    reset_value();
+    set_type(type);
+  }
+
+  /**
+    Allocate and initialize a user variable instance.
+    @param namec  Name of the variable.
+    @return
+    @retval  Address of the allocated and initialized user_var_entry instance.
+    @retval  NULL on allocation error.
+  */
+  static user_var_entry *create(const Name_string &name)
+  {
+    user_var_entry *entry;
+    uint size= ALIGN_SIZE(sizeof(user_var_entry)) +
+               (name.length() + 1) + extra_size;
+    if (!(entry= (user_var_entry*) my_malloc(size, MYF(MY_WME |
+                                                       ME_FATALERROR))))
+      return NULL;
+    entry->init(name);
+    return entry;
+  }
+
+  /**
+    Free all memory used by a user_var_entry instance
+    previously created by create().
+  */
+  void destroy()
+  {
+    free_value();  // Free the external value buffer
+    my_free(this); // Free the instance itself
+  }
 
+  /* Routines to access the value and its type */
+  const char *ptr() const { return m_ptr; }
+  ulong length() const { return m_length; }
+  Item_result type() const { return m_type; }
+  /* Item-alike routines to access the value */
   double val_real(my_bool *null_value);
   longlong val_int(my_bool *null_value) const;
   String *val_str(my_bool *null_value, String *str, uint decimals);
   my_decimal *val_decimal(my_bool *null_value, my_decimal *result);
-  DTCollation collation;
 };
 
 /*

=== modified file 'sql/sql_prepare.cc'
--- a/sql/sql_prepare.cc	2012-07-26 18:46:34 +0000
+++ b/sql/sql_prepare.cc	2012-08-15 10:38:01 +0000
@@ -2321,7 +2321,7 @@ static const char *get_dynamic_sql_strin
          (user_var_entry*)my_hash_search(&thd->user_vars,
                                          (uchar*)lex->prepared_stmt_code.str,
                                          lex->prepared_stmt_code.length))
-        && entry->value)
+        && entry->ptr())
     {
       my_bool is_var_null;
       var_value= entry->val_str(&is_var_null, &str, NOT_FIXED_DEC);

No bundle (reason: useless for push emails).
Thread
bzr push into mysql-trunk branch (alexander.barkov:4230 to 4231) Alexander Barkov15 Aug