List:Commits« Previous MessageNext Message »
From:eugene Date:August 18 2006 12:18am
Subject:bk commit into 5.0 tree (evgen:1.2251) BUG#16861
View as plain text  
Below is the list of changes that have just been committed into a local
5.0 repository of evgen. When evgen 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-08-18 02:18:30+04:00, evgen@stripped +7 -0
  Fixed bug#16861: User defined variable can have a wrong value if a tmp table was
  used.
  
  Sorting by RAND() uses a temporary table in order to get a correct results.
  User defined variable was set during filling the temporary table and later
  on it is substituted with its value from the temporary table. Due to this
  it contains the last value stored in the temporary table.
  
  Now if the result_field is set for the Item_func_set_user_var object it 
  updates variable from the result_field value when being sent to a client.
  
  The Item_func_set_user_var::check() now accepts a use_result_field
  parameter. Depending on its value the result_field or the args[0] is used
  to get current value.
  

  mysql-test/r/user_var.result@stripped, 2006-08-18 02:07:45+04:00, evgen@stripped +9 -0
    Added a test case for bug#16861: User defined variable can have a wrong value if a tmp
table was used.

  mysql-test/t/user_var.test@stripped, 2006-08-18 02:06:56+04:00, evgen@stripped +10 -0
    Added a test case for bug#16861: User defined variable can have a wrong value if a tmp
table was used.

  sql/item_func.cc@stripped, 2006-08-18 02:15:50+04:00, evgen@stripped +30 -12
    Fixed bug#16861: User defined variable can have a wrong value if a tmp table was used.
    Now if the result_field is set for the Item_func_set_user_var object it 
    updates variable from the result_field value when being sent to a client.
    
    The Item_func_set_user_var::check() now accepts a use_result_field
    parameter. Depending on its value the result_field or the args[0] is used
    to get current value.

  sql/item_func.h@stripped, 2006-08-18 02:13:06+04:00, evgen@stripped +4 -2
    Fixed bug#16861: User defined variable can have a wrong value if a tmp table was used.
    Added a new SUSERVAR_FUNC function type.
    Updated the Item_func_set_user_var::check() function declaration.
    Added the Item_func_set_user_var::send() member function.

  sql/set_var.cc@stripped, 2006-08-18 02:10:23+04:00, evgen@stripped +1 -1
    Fixed bug#16861: User defined variable can have a wrong value if a tmp table was used.
    Modified to use updated Item_func_set_user_var::check() function.

  sql/sql_class.cc@stripped, 2006-08-18 02:12:30+04:00, evgen@stripped +1 -1
    Fixed bug#16861: User defined variable can have a wrong value if a tmp table was used.
    Modified to use updated Item_func_set_user_var::check() function.

  sql/sql_select.cc@stripped, 2006-08-18 02:09:47+04:00, evgen@stripped +3 -1
    Fixed bug#16861: User defined variable can have a wrong value if a tmp table was used.
    Now an Item_func_set_user_var object isn't substituted with an Item_field object after
filling a temporary table.

# 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:	evgen
# Host:	sunlight.local
# Root:	/local_work/16861-bug-5.0-mysql

--- 1.297/sql/item_func.cc	2006-08-18 02:18:35 +04:00
+++ 1.298/sql/item_func.cc	2006-08-18 02:18:35 +04:00
@@ -548,7 +548,7 @@
 
 Item *Item_func::get_tmp_table_item(THD *thd)
 {
-  if (!with_sum_func && !const_item())
+  if (!with_sum_func && !const_item() && functype() != SUSERVAR_FUNC)
     return new Item_field(result_field);
   return copy_or_same(thd);
 }
@@ -3719,30 +3719,38 @@
 */
 
 bool
-Item_func_set_user_var::check()
+Item_func_set_user_var::check(bool use_result_field)
 {
   DBUG_ENTER("Item_func_set_user_var::check");
+  if (use_result_field)
+    DBUG_ASSERT(result_field);
 
   switch (cached_result_type) {
   case REAL_RESULT:
   {
-    save_result.vreal= args[0]->val_real();
+    save_result.vreal= use_result_field ? result_field->val_real() :
+                        args[0]->val_real();
     break;
   }
   case INT_RESULT:
   {
-    save_result.vint= args[0]->val_int();
-    unsigned_flag= args[0]->unsigned_flag;
+    save_result.vint= use_result_field ? result_field->val_int() :
+                       args[0]->val_int();
+    unsigned_flag= use_result_field ? ((Field_num*)result_field)->unsigned_flag:
+                    args[0]->unsigned_flag;
     break;
   }
   case STRING_RESULT:
   {
-    save_result.vstr= args[0]->val_str(&value);
+    save_result.vstr= use_result_field ? result_field->val_str(&value) :
+                       args[0]->val_str(&value);
     break;
   }
   case DECIMAL_RESULT:
   {
-    save_result.vdec= args[0]->val_decimal(&decimal_buff);
+    save_result.vdec= use_result_field ?
+                       result_field->val_decimal(&decimal_buff) :
+                       args[0]->val_decimal(&decimal_buff);
     break;
   }
   case ROW_RESULT:
@@ -3828,7 +3836,7 @@
 double Item_func_set_user_var::val_real()
 {
   DBUG_ASSERT(fixed == 1);
-  check();
+  check(0);
   update();					// Store expression
   return entry->val_real(&null_value);
 }
@@ -3836,7 +3844,7 @@
 longlong Item_func_set_user_var::val_int()
 {
   DBUG_ASSERT(fixed == 1);
-  check();
+  check(0);
   update();					// Store expression
   return entry->val_int(&null_value);
 }
@@ -3844,7 +3852,7 @@
 String *Item_func_set_user_var::val_str(String *str)
 {
   DBUG_ASSERT(fixed == 1);
-  check();
+  check(0);
   update();					// Store expression
   return entry->val_str(&null_value, str, decimals);
 }
@@ -3853,7 +3861,7 @@
 my_decimal *Item_func_set_user_var::val_decimal(my_decimal *val)
 {
   DBUG_ASSERT(fixed == 1);
-  check();
+  check(0);
   update();					// Store expression
   return entry->val_decimal(&null_value, val);
 }
@@ -3878,6 +3886,16 @@
   str->append(')');
 }
 
+bool Item_func_set_user_var::send(Protocol *protocol, String *str_arg)
+{
+  if (result_field)
+  {
+    check(1);
+    update();
+    return protocol->store(result_field);
+  }
+  return Item::send(protocol, str_arg);
+}
 
 String *
 Item_func_get_user_var::val_str(String *str)
@@ -4143,7 +4161,7 @@
     Item_func_set_user_var is not fixed after construction, call
     fix_fields().
   */
-  return (!suv || suv->fix_fields(thd, it) || suv->check() || suv->update());
+  return (!suv || suv->fix_fields(thd, it) || suv->check(0) || suv->update());
 }
 
 

--- 1.146/sql/item_func.h	2006-08-18 02:18:35 +04:00
+++ 1.147/sql/item_func.h	2006-08-18 02:18:35 +04:00
@@ -54,7 +54,7 @@
 		  SP_POINTN,SP_GEOMETRYN,SP_INTERIORRINGN,
                   NOT_FUNC, NOT_ALL_FUNC,
                   NOW_FUNC, TRIG_COND_FUNC,
-                  GUSERVAR_FUNC, COLLATE_FUNC,
+                  SUSERVAR_FUNC, GUSERVAR_FUNC, COLLATE_FUNC,
                   EXTRACT_FUNC, CHAR_TYPECAST_FUNC, FUNC_SP, UDF_FUNC };
   enum optimize_type { OPTIMIZE_NONE,OPTIMIZE_KEY,OPTIMIZE_OP, OPTIMIZE_NULL,
                        OPTIMIZE_EQUAL };
@@ -1167,13 +1167,15 @@
   Item_func_set_user_var(LEX_STRING a,Item *b)
     :Item_func(b), cached_result_type(INT_RESULT), name(a)
   {}
+  enum Functype functype() const { return SUSERVAR_FUNC; }
   double val_real();
   longlong val_int();
   String *val_str(String *str);
   my_decimal *val_decimal(my_decimal *);
   bool update_hash(void *ptr, uint length, enum Item_result type,
   		   CHARSET_INFO *cs, Derivation dv, bool unsigned_arg= 0);
-  bool check();
+  bool send(Protocol *protocol, String *str_arg);
+  bool check(bool use_result_field);
   bool update();
   enum Item_result result_type () const { return cached_result_type; }
   bool fix_fields(THD *thd, Item **ref);

--- 1.245/sql/sql_class.cc	2006-08-18 02:18:35 +04:00
+++ 1.246/sql/sql_class.cc	2006-08-18 02:18:35 +04:00
@@ -1883,7 +1883,7 @@
     {
       if ((xx=li++))
       {
-        xx->check();
+        xx->check(0);
 	xx->update();
       }
     }

--- 1.439/sql/sql_select.cc	2006-08-18 02:18:35 +04:00
+++ 1.440/sql/sql_select.cc	2006-08-18 02:18:35 +04:00
@@ -13365,7 +13365,9 @@
   {
     Field *field;
     
-    if (item->with_sum_func && item->type() != Item::SUM_FUNC_ITEM)
+    if ((item->with_sum_func && item->type() != Item::SUM_FUNC_ITEM) ||
+        (item->type() == Item::FUNC_ITEM &&
+         ((Item_func*)item)->functype() == Item_func::SUSERVAR_FUNC))
       item_field= item;
     else
     {

--- 1.161/sql/set_var.cc	2006-08-18 02:18:35 +04:00
+++ 1.162/sql/set_var.cc	2006-08-18 02:18:35 +04:00
@@ -3252,7 +3252,7 @@
     0 can be passed as last argument (reference on item)
   */
   return (user_var_item->fix_fields(thd, (Item**) 0) ||
-	  user_var_item->check()) ? -1 : 0;
+	  user_var_item->check(0)) ? -1 : 0;
 }
 
 

--- 1.39/mysql-test/r/user_var.result	2006-08-18 02:18:35 +04:00
+++ 1.40/mysql-test/r/user_var.result	2006-08-18 02:18:35 +04:00
@@ -292,3 +292,12 @@
 @a
 18446744071710965857
 drop table bigfailure;
+create table t1(f1 int, f2 int);
+insert into t1 values (1,2),(2,3),(3,1);
+select @var:=f2 from t1 group by f1 order by f2 desc limit 1;
+@var:=f2
+3
+select @var;
+@var
+3
+drop table t1;

--- 1.34/mysql-test/t/user_var.test	2006-08-18 02:18:35 +04:00
+++ 1.35/mysql-test/t/user_var.test	2006-08-18 02:18:35 +04:00
@@ -202,3 +202,13 @@
 SELECT @a;
 
 drop table bigfailure;
+
+#
+# Bug#16861: User defined variable can have a wrong value if a tmp table was
+#            used.
+#
+create table t1(f1 int, f2 int);
+insert into t1 values (1,2),(2,3),(3,1);
+select @var:=f2 from t1 group by f1 order by f2 desc limit 1;
+select @var;
+drop table t1;
Thread
bk commit into 5.0 tree (evgen:1.2251) BUG#16861eugene18 Aug