Commit 22a96308 authored by unknown's avatar unknown
Browse files

Merge neptunus.(none):/home/msvensson/mysql/bug7498/my50-bug7498

into  neptunus.(none):/home/msvensson/mysql/mysql-5.0-maint


sql/item_func.cc:
  Auto merged
sql/item_func.h:
  Auto merged
sql/item_subselect.cc:
  Auto merged
sql/sql_class.h:
  Auto merged
parents 63a098f3 f067dfe1
Loading
Loading
Loading
Loading
+36 −0
Original line number Diff line number Diff line
@@ -256,3 +256,39 @@ t1 CREATE TABLE `t1` (
  `@first_var` longtext
) ENGINE=MyISAM DEFAULT CHARSET=latin1
drop table t1;
set @a=18446744071710965857;
select @a;
@a
18446744071710965857
CREATE TABLE `bigfailure` (
`afield` BIGINT UNSIGNED NOT NULL
);
INSERT INTO `bigfailure` VALUES (18446744071710965857);
SELECT * FROM bigfailure;
afield
18446744071710965857
select * from (SELECT afield FROM bigfailure) as b;
afield
18446744071710965857
select * from bigfailure where afield = (SELECT afield FROM bigfailure);
afield
18446744071710965857
select * from bigfailure where afield = 18446744071710965857;
afield
18446744071710965857
select * from bigfailure where afield = 18446744071710965856+1;
afield
18446744071710965857
SET @a := (SELECT afield FROM bigfailure);
SELECT @a;
@a
18446744071710965857
SET @a := (select afield from (SELECT afield FROM bigfailure) as b);
SELECT @a;
@a
18446744071710965857
SET @a := (select * from bigfailure where afield = (SELECT afield FROM bigfailure));
SELECT @a;
@a
18446744071710965857
drop table bigfailure;
+31 −0
Original line number Diff line number Diff line
@@ -171,3 +171,34 @@ set @first_var= cast(NULL as CHAR);
create table t1 select @first_var;
show create table t1;
drop table t1;

#
# Bug #7498 User variable SET saves SIGNED BIGINT as UNSIGNED BIGINT
#

# First part, set user var to large number and select it
set @a=18446744071710965857;
select @a;

# Second part, set user var from large number in table
# then select it
CREATE TABLE `bigfailure` (
  `afield` BIGINT UNSIGNED NOT NULL
);
INSERT INTO `bigfailure` VALUES (18446744071710965857);
SELECT * FROM bigfailure;
select * from (SELECT afield FROM bigfailure) as b;
select * from bigfailure where afield = (SELECT afield FROM bigfailure);
select * from bigfailure where afield = 18446744071710965857;
# This is fixed in 5.0, to be uncommented there
#select * from bigfailure where afield = '18446744071710965857';
select * from bigfailure where afield = 18446744071710965856+1;

SET @a := (SELECT afield FROM bigfailure);
SELECT @a;
SET @a := (select afield from (SELECT afield FROM bigfailure) as b);
SELECT @a;
SET @a := (select * from bigfailure where afield = (SELECT afield FROM bigfailure));
SELECT @a;

drop table bigfailure;
+17 −7
Original line number Diff line number Diff line
@@ -3406,6 +3406,7 @@ static user_var_entry *get_variable(HASH *hash, LEX_STRING &name,
    entry->length=0;
    entry->update_query_id=0;
    entry->collation.set(NULL, DERIVATION_IMPLICIT);
    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:
@@ -3492,6 +3493,7 @@ Item_func_set_user_var::fix_length_and_dec()
    type     - type of new value
    cs       - charset info for new value
    dv       - derivation for new value
    unsigned_arg - indiates if a value of type INT_RESULT is unsigned

  RETURN VALUE
    False - success, True - failure
@@ -3499,7 +3501,8 @@ Item_func_set_user_var::fix_length_and_dec()

static bool
update_hash(user_var_entry *entry, bool set_null, void *ptr, uint length,
            Item_result type, CHARSET_INFO *cs, Derivation dv)
            Item_result type, CHARSET_INFO *cs, Derivation dv,
            bool unsigned_arg)
{
  if (set_null)
  {
@@ -3547,6 +3550,7 @@ update_hash(user_var_entry *entry, bool set_null, void *ptr, uint length,
      ((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;
@@ -3555,7 +3559,8 @@ update_hash(user_var_entry *entry, bool set_null, void *ptr, uint length,

bool
Item_func_set_user_var::update_hash(void *ptr, uint length, Item_result type,
                                    CHARSET_INFO *cs, Derivation dv)
                                    CHARSET_INFO *cs, Derivation dv,
                                    bool unsigned_arg)
{
  /*
    If we set a variable explicitely to NULL then keep the old
@@ -3564,7 +3569,7 @@ Item_func_set_user_var::update_hash(void *ptr, uint length, Item_result type,
  if ((null_value= args[0]->null_value) && null_item)
    type= entry->type;                          // Don't change type of item
  if (::update_hash(entry, (null_value= args[0]->null_value),
                    ptr, length, type, cs, dv))
                    ptr, length, type, cs, dv, unsigned_arg))
  {
    current_thd->fatal_error();     // Probably end of memory
    null_value= 1;
@@ -3646,7 +3651,10 @@ String *user_var_entry::val_str(my_bool *null_value, String *str,
    str->set(*(double*) value, decimals, &my_charset_bin);
    break;
  case INT_RESULT:
    if (!unsigned_flag)
      str->set(*(longlong*) value, &my_charset_bin);
    else
      str->set(*(ulonglong*) value, &my_charset_bin);
    break;
  case DECIMAL_RESULT:
    my_decimal2string(E_DEC_FATAL_ERROR, (my_decimal *)value, 0, 0, 0, str);
@@ -3717,6 +3725,7 @@ Item_func_set_user_var::check()
  case INT_RESULT:
  {
    save_result.vint= args[0]->val_int();
    unsigned_flag= args[0]->unsigned_flag;
    break;
  }
  case STRING_RESULT:
@@ -3772,7 +3781,8 @@ Item_func_set_user_var::update()
  case INT_RESULT:
  {
    res= update_hash((void*) &save_result.vint, sizeof(save_result.vint),
		     INT_RESULT, &my_charset_bin, DERIVATION_IMPLICIT);
		     INT_RESULT, &my_charset_bin, DERIVATION_IMPLICIT,
                     unsigned_flag);
    break;
  }
  case STRING_RESULT:
@@ -4151,7 +4161,7 @@ bool Item_user_var_as_out_param::fix_fields(THD *thd, Item **ref)
void Item_user_var_as_out_param::set_null_value(CHARSET_INFO* cs)
{
  if (::update_hash(entry, TRUE, 0, 0, STRING_RESULT, cs,
                    DERIVATION_IMPLICIT))
                    DERIVATION_IMPLICIT, 0 /* unsigned_arg */))
    current_thd->fatal_error();			// Probably end of memory
}

@@ -4160,7 +4170,7 @@ void Item_user_var_as_out_param::set_value(const char *str, uint length,
                                           CHARSET_INFO* cs)
{
  if (::update_hash(entry, FALSE, (void*)str, length, STRING_RESULT, cs,
                    DERIVATION_IMPLICIT))
                    DERIVATION_IMPLICIT, 0 /* unsigned_arg */))
    current_thd->fatal_error();			// Probably end of memory
}

+2 −4
Original line number Diff line number Diff line
@@ -1157,8 +1157,6 @@ class Item_func_set_user_var :public Item_func
    String *vstr;
    my_decimal *vdec;
  } save_result;
  String save_buff;
  

public:
  LEX_STRING name; // keep it public
@@ -1170,7 +1168,7 @@ class Item_func_set_user_var :public Item_func
  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);
  		   CHARSET_INFO *cs, Derivation dv, bool unsigned_arg= 0);
  bool check();
  bool update();
  enum Item_result result_type () const { return cached_result_type; }
+1 −0
Original line number Diff line number Diff line
@@ -1510,6 +1510,7 @@ static Item_result set_row(List<Item> &item_list, Item *item,
    item->max_length= sel_item->max_length;
    res_type= sel_item->result_type();
    item->decimals= sel_item->decimals;
    item->unsigned_flag= sel_item->unsigned_flag;
    *maybe_null= sel_item->maybe_null;
    if (!(row[i]= Item_cache::get_cache(res_type)))
      return STRING_RESULT; // we should return something
Loading