mirror of
https://github.com/MariaDB/server.git
synced 2025-01-18 04:53:01 +01:00
Bug #7498 User variable SET saves SIGNED BIGINT as UNSIGNED BIGINT
- Add unsigned flag to user_var_entry, used when 'type' is INT_RESULT - Propagate unsigned flag from the query executed by Item_single_row_subselect
This commit is contained in:
parent
332c690273
commit
9ebf7944e3
6 changed files with 88 additions and 11 deletions
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -3408,6 +3408,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:
|
||||
|
@ -3494,6 +3495,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
|
||||
|
@ -3501,7 +3503,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)
|
||||
{
|
||||
|
@ -3549,6 +3552,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;
|
||||
|
@ -3557,7 +3561,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
|
||||
|
@ -3566,7 +3571,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;
|
||||
|
@ -3648,7 +3653,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:
|
||||
str->set(*(longlong*) value, &my_charset_bin);
|
||||
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);
|
||||
|
@ -3719,6 +3727,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:
|
||||
|
@ -3774,7 +3783,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:
|
||||
|
@ -4141,7 +4151,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
|
||||
}
|
||||
|
||||
|
@ -4150,7 +4160,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
|
||||
}
|
||||
|
||||
|
|
|
@ -1154,8 +1154,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
|
||||
|
@ -1166,8 +1164,8 @@ public:
|
|||
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 update_hash(void *ptr, uint length, enum Item_result type,
|
||||
CHARSET_INFO *cs, Derivation dv, bool unsigned_arg= 0);
|
||||
bool check();
|
||||
bool update();
|
||||
enum Item_result result_type () const { return cached_result_type; }
|
||||
|
|
|
@ -1497,6 +1497,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
|
||||
|
|
|
@ -1954,6 +1954,7 @@ class user_var_entry
|
|||
ulong length;
|
||||
query_id_t update_query_id, used_query_id;
|
||||
Item_result type;
|
||||
bool unsigned_flag;
|
||||
|
||||
double val_real(my_bool *null_value);
|
||||
longlong val_int(my_bool *null_value);
|
||||
|
|
Loading…
Reference in a new issue