Commit 49346467 authored by evgen@moonbone.local's avatar evgen@moonbone.local

Bug#28494: Grouping by Item_func_set_user_var produces incorrect result.

This is an additional fix.
Item::val_xxx methods are supposed to use original data source and
Item::val_xxx_result methods to use the item's result field. But for the
Item_func_set_user_var class val_xxx_result methods were mapped to val_xxx
methods. This leads, in particular, to producing bad sort keys and thus
wrong order of the result set of queries with group by/order by clauses.

The set of val_xxx_result methods is added to the Item_func_set_user_var
class. It's the same as the val_xxx set of method but uses the result_field
to return a value.
parent 72a64f08
...@@ -318,9 +318,17 @@ SHOW COUNT(*) ERRORS; ...@@ -318,9 +318,17 @@ SHOW COUNT(*) ERRORS;
@@session.error_count @@session.error_count
1 1
create table t1(f1 int); create table t1(f1 int);
insert into t1 values(1),(1),(2); insert into t1 values(1),(1),(2),(3),(4),(1),(3),(1);
select @a:=f1, count(f1) from t1 group by 1; select @a:=f1, count(f1) from t1 group by 1 desc;
@a:=f1 count(f1) @a:=f1 count(f1)
1 2 4 1
3 2
2 1 2 1
1 4
select @a:=f1, count(f1) from t1 group by 1 asc;
@a:=f1 count(f1)
1 4
2 1
3 2
4 1
drop table t1; drop table t1;
...@@ -227,6 +227,7 @@ SHOW COUNT(*) ERRORS; ...@@ -227,6 +227,7 @@ SHOW COUNT(*) ERRORS;
# Bug#28494: Grouping by Item_func_set_user_var produces incorrect result. # Bug#28494: Grouping by Item_func_set_user_var produces incorrect result.
# #
create table t1(f1 int); create table t1(f1 int);
insert into t1 values(1),(1),(2); insert into t1 values(1),(1),(2),(3),(4),(1),(3),(1);
select @a:=f1, count(f1) from t1 group by 1; select @a:=f1, count(f1) from t1 group by 1 desc;
select @a:=f1, count(f1) from t1 group by 1 asc;
drop table t1; drop table t1;
...@@ -4208,6 +4208,40 @@ my_decimal *Item_func_set_user_var::val_decimal(my_decimal *val) ...@@ -4208,6 +4208,40 @@ my_decimal *Item_func_set_user_var::val_decimal(my_decimal *val)
} }
double Item_func_set_user_var::val_real_result()
{
DBUG_ASSERT(fixed == 1);
check(TRUE);
update(); // Store expression
return entry->val_real(&null_value);
}
longlong Item_func_set_user_var::val_int_result()
{
DBUG_ASSERT(fixed == 1);
check(TRUE);
update(); // Store expression
return entry->val_int(&null_value);
}
String *Item_func_set_user_var::val_str_result(String *str)
{
DBUG_ASSERT(fixed == 1);
check(TRUE);
update(); // Store expression
return entry->val_str(&null_value, str, decimals);
}
my_decimal *Item_func_set_user_var::val_decimal_result(my_decimal *val)
{
DBUG_ASSERT(fixed == 1);
check(TRUE);
update(); // Store expression
return entry->val_decimal(&null_value, val);
}
void Item_func_set_user_var::print(String *str) void Item_func_set_user_var::print(String *str)
{ {
str->append(STRING_WITH_LEN("(@")); str->append(STRING_WITH_LEN("(@"));
......
...@@ -1208,6 +1208,10 @@ public: ...@@ -1208,6 +1208,10 @@ public:
longlong val_int(); longlong val_int();
String *val_str(String *str); String *val_str(String *str);
my_decimal *val_decimal(my_decimal *); my_decimal *val_decimal(my_decimal *);
double val_real_result();
longlong val_int_result();
String *val_str_result(String *str);
my_decimal *val_decimal_result(my_decimal *);
bool update_hash(void *ptr, uint length, enum Item_result type, bool update_hash(void *ptr, uint length, enum Item_result type,
CHARSET_INFO *cs, Derivation dv, bool unsigned_arg); CHARSET_INFO *cs, Derivation dv, bool unsigned_arg);
bool send(Protocol *protocol, String *str_arg); bool send(Protocol *protocol, String *str_arg);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment