Commit 3a23139a authored by unknown's avatar unknown
Browse files

Merge epotemkin@bk-internal.mysql.com:/home/bk/mysql-5.0-opt

into  sunlight.local:/local_work/16861-bug-5.0-mysql


sql/sql_select.cc:
  Auto merged
parents 8776a1e1 c623e54f
Loading
Loading
Loading
Loading
+9 −0
Original line number Diff line number Diff line
@@ -292,3 +292,12 @@ SELECT @a;
@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;
+10 −0
Original line number Diff line number Diff line
@@ -202,3 +202,13 @@ SET @a := (select * from bigfailure where afield = (SELECT afield FROM bigfailur
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;
+30 −12
Original line number Diff line number Diff line
@@ -548,7 +548,7 @@ void Item_func::signal_divide_by_null()

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 @@ my_decimal *user_var_entry::val_decimal(my_bool *null_value, my_decimal *val)
*/

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 @@ Item_func_set_user_var::update()
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 @@ double Item_func_set_user_var::val_real()
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 @@ longlong Item_func_set_user_var::val_int()
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 @@ String *Item_func_set_user_var::val_str(String *str)
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 @@ void Item_func_set_user_var::print_as_stmt(String *str)
  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 @@ bool Item_func_get_user_var::set_value(THD *thd,
    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());
}


+4 −2
Original line number Diff line number Diff line
@@ -54,7 +54,7 @@ class Item_func :public Item_result_field
		  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 @@ class Item_func_set_user_var :public Item_func
  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 −1
Original line number Diff line number Diff line
@@ -3252,7 +3252,7 @@ int set_var_user::check(THD *thd)
    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;
}


Loading