Commit bd414485 authored by Ramil Kalimullin's avatar Ramil Kalimullin

Fix for bug#42009: SELECT into variable gives different results to direct SELECT

Problem: storing "SELECT ... INTO @var ..." results in variables we used val_xxx()
methods which returned results of the current row. 
So, in some cases (e.g. SELECT DISTINCT, GROUP BY or HAVING) we got data
from the first row of a new group (where we evaluate a clause) instead of
data from the last row of the previous group.

Fix: use val_xxx_result() counterparts to get proper results.


mysql-test/r/distinct.result:
  Fix for bug#42009: SELECT into variable gives different results to direct SELECT
    - results adjusted.
mysql-test/r/user_var.result:
  Fix for bug#42009: SELECT into variable gives different results to direct SELECT
    - test result.
mysql-test/t/user_var.test:
  Fix for bug#42009: SELECT into variable gives different results to direct SELECT
    - test case.
sql/item_func.cc:
  Fix for bug#42009: SELECT into variable gives different results to direct SELECT
    - Item_func_set_user_var::save_item_result() added to evaluate and store 
      an item's result into a user variable.
sql/item_func.h:
  Fix for bug#42009: SELECT into variable gives different results to direct SELECT
    - Item_func_set_user_var::save_item_result() added to evaluate and store 
      an item's result into a user variable.
sql/sql_class.cc:
  Fix for bug#42009: SELECT into variable gives different results to direct SELECT
    - use Item_func_set_user_var::save_item_result() to store results into user 
      variables.
parent fb20a7d6
...@@ -629,21 +629,21 @@ SELECT DISTINCT @v5:= fruit_id, @v6:= fruit_name INTO @v7, @v8 FROM t1 WHERE ...@@ -629,21 +629,21 @@ SELECT DISTINCT @v5:= fruit_id, @v6:= fruit_name INTO @v7, @v8 FROM t1 WHERE
fruit_name = 'APPLE'; fruit_name = 'APPLE';
SELECT @v5, @v6, @v7, @v8; SELECT @v5, @v6, @v7, @v8;
@v5 @v6 @v7 @v8 @v5 @v6 @v7 @v8
3 PEAR 3 PEAR 2 APPLE 2 APPLE
SELECT DISTINCT @v5 + fruit_id, CONCAT(@v6, fruit_name) INTO @v9, @v10 FROM t1 SELECT DISTINCT @v5 + fruit_id, CONCAT(@v6, fruit_name) INTO @v9, @v10 FROM t1
WHERE fruit_name = 'APPLE'; WHERE fruit_name = 'APPLE';
SELECT @v5, @v6, @v7, @v8, @v9, @v10; SELECT @v5, @v6, @v7, @v8, @v9, @v10;
@v5 @v6 @v7 @v8 @v9 @v10 @v5 @v6 @v7 @v8 @v9 @v10
3 PEAR 3 PEAR 5 PEARAPPLE 2 APPLE 2 APPLE 4 APPLEAPPLE
SELECT DISTINCT @v11:= @v5 + fruit_id, @v12:= CONCAT(@v6, fruit_name) INTO SELECT DISTINCT @v11:= @v5 + fruit_id, @v12:= CONCAT(@v6, fruit_name) INTO
@v13, @v14 FROM t1 WHERE fruit_name = 'APPLE'; @v13, @v14 FROM t1 WHERE fruit_name = 'APPLE';
SELECT @v11, @v12, @v13, @v14; SELECT @v11, @v12, @v13, @v14;
@v11 @v12 @v13 @v14 @v11 @v12 @v13 @v14
6 PEARPEAR 6 PEARPEAR 4 APPLEAPPLE 4 APPLEAPPLE
SELECT DISTINCT @v13, @v14 INTO @v15, @v16 FROM t1 WHERE fruit_name = 'APPLE'; SELECT DISTINCT @v13, @v14 INTO @v15, @v16 FROM t1 WHERE fruit_name = 'APPLE';
SELECT @v15, @v16; SELECT @v15, @v16;
@v15 @v16 @v15 @v16
6 PEARPEAR 4 APPLEAPPLE
SELECT DISTINCT 2 + 2, 'Bob' INTO @v17, @v18 FROM t1 WHERE fruit_name = SELECT DISTINCT 2 + 2, 'Bob' INTO @v17, @v18 FROM t1 WHERE fruit_name =
'APPLE'; 'APPLE';
SELECT @v17, @v18; SELECT @v17, @v18;
......
...@@ -353,3 +353,14 @@ select @a:=f4, count(f4) from t1 group by 1 desc; ...@@ -353,3 +353,14 @@ select @a:=f4, count(f4) from t1 group by 1 desc;
2.6 1 2.6 1
1.6 4 1.6 4
drop table t1; drop table t1;
CREATE TABLE t1(a INT, b INT);
INSERT INTO t1 VALUES (0, 0), (2, 1), (2, 3), (1, 1), (30, 20);
SELECT a, b INTO @a, @b FROM t1 WHERE a=2 AND b=3 GROUP BY a, b;
SELECT @a, @b;
@a @b
2 3
SELECT a, b FROM t1 WHERE a=2 AND b=3 GROUP BY a, b;
a b
2 3
DROP TABLE t1;
End of 5.0 tests
...@@ -237,3 +237,15 @@ select @a:=f2, count(f2) from t1 group by 1 desc; ...@@ -237,3 +237,15 @@ select @a:=f2, count(f2) from t1 group by 1 desc;
select @a:=f3, count(f3) from t1 group by 1 desc; select @a:=f3, count(f3) from t1 group by 1 desc;
select @a:=f4, count(f4) from t1 group by 1 desc; select @a:=f4, count(f4) from t1 group by 1 desc;
drop table t1; drop table t1;
#
# Bug#42009: SELECT into variable gives different results to direct SELECT
#
CREATE TABLE t1(a INT, b INT);
INSERT INTO t1 VALUES (0, 0), (2, 1), (2, 3), (1, 1), (30, 20);
SELECT a, b INTO @a, @b FROM t1 WHERE a=2 AND b=3 GROUP BY a, b;
SELECT @a, @b;
SELECT a, b FROM t1 WHERE a=2 AND b=3 GROUP BY a, b;
DROP TABLE t1;
--echo End of 5.0 tests
...@@ -4147,6 +4147,41 @@ Item_func_set_user_var::check(bool use_result_field) ...@@ -4147,6 +4147,41 @@ Item_func_set_user_var::check(bool use_result_field)
} }
/**
@brief Evaluate and store item's result.
This function is invoked on "SELECT ... INTO @var ...".
@param item An item to get value from.
*/
void Item_func_set_user_var::save_item_result(Item *item)
{
DBUG_ENTER("Item_func_set_user_var::save_item_result");
switch (cached_result_type) {
case REAL_RESULT:
save_result.vreal= item->val_result();
break;
case INT_RESULT:
save_result.vint= item->val_int_result();
unsigned_flag= item->unsigned_flag;
break;
case STRING_RESULT:
save_result.vstr= item->str_result(&value);
break;
case DECIMAL_RESULT:
save_result.vdec= item->val_decimal_result(&decimal_buff);
break;
case ROW_RESULT:
default:
// Should never happen
DBUG_ASSERT(0);
break;
}
DBUG_VOID_RETURN;
}
/* /*
This functions is invoked on SET @variable or @variable:= expression. This functions is invoked on SET @variable or @variable:= expression.
......
...@@ -1308,6 +1308,7 @@ class Item_func_set_user_var :public Item_func ...@@ -1308,6 +1308,7 @@ class Item_func_set_user_var :public Item_func
bool send(Protocol *protocol, String *str_arg); bool send(Protocol *protocol, String *str_arg);
void make_field(Send_field *tmp_field); void make_field(Send_field *tmp_field);
bool check(bool use_result_field); bool check(bool use_result_field);
void save_item_result(Item *item);
bool update(); bool update();
enum Item_result result_type () const { return cached_result_type; } enum Item_result result_type () const { return cached_result_type; }
bool fix_fields(THD *thd, Item **ref); bool fix_fields(THD *thd, Item **ref);
......
...@@ -2041,7 +2041,7 @@ bool select_dumpvar::send_data(List<Item> &items) ...@@ -2041,7 +2041,7 @@ bool select_dumpvar::send_data(List<Item> &items)
{ {
Item_func_set_user_var *suv= new Item_func_set_user_var(mv->s, item); Item_func_set_user_var *suv= new Item_func_set_user_var(mv->s, item);
suv->fix_fields(thd, 0); suv->fix_fields(thd, 0);
suv->check(0); suv->save_item_result(item);
suv->update(); suv->update();
} }
} }
......
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