Commit 63982db9 authored by unknown's avatar unknown
Browse files

Better bugfix for "HAVING when refering to RAND()" (Bug #8216)

Ensure that references in HAVING, ORDER BY or GROUP BY are calculated after fields in SELECT.
This will ensure that any reference to these has a valid value.
Generalized the code for split_sum_func()


BitKeeper/etc/ignore:
  added support-files/ndb-config-2-node.ini
mysql-test/r/group_by.result:
  More complicated test to assure that rand() is only calulated once
mysql-test/r/user_var.result:
  Back to old results :(  (ok but not perfect)
mysql-test/t/group_by.test:
  More complicated test to assure that rand() is only calulated once
sql/item.cc:
  Better bugfix for "HAVING when refering to RAND()"
  This will ensure that when refering to things like RAND() in HAVING through an alias we will not recalculate that rand() value in the HAVING part but use the value in the row
  Generalize split_sum_func()
sql/item.h:
  Better bugfix for "HAVING when refering to RAND()"
  T
sql/item_cmpfunc.cc:
  Better bugfix for "HAVING when refering to RAND()"
  Use generalized split_sum_func2() function
sql/item_func.cc:
  Better bugfix for "HAVING when refering to RAND()"
  Use generalized split_sum_func2() function
sql/item_row.cc:
  Better bugfix for "HAVING when refering to RAND()"
  Use generalized split_sum_func2() function
sql/item_strfunc.cc:
  Better bugfix for "HAVING when refering to RAND()"
  Use generalized split_sum_func2() function
sql/sql_list.h:
  Add functions to concatenate lists
sql/sql_select.cc:
  Better bugfix for "HAVING when refering to RAND()"
  Ensure that references in HAVING, ORDER BY or GROUP BY are calculated after fields in SELECT.
  This will ensure that any reference to these has a valid value.
parent 6a1e7562
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -1007,3 +1007,4 @@ tests/mysql_client_test
libmysqld/examples/mysql_client_test.c
libmysqld/examples/mysql_client_test_embedded
libmysqld/examples/mysqltest_embedded
support-files/ndb-config-2-node.ini
+2 −2
Original line number Diff line number Diff line
@@ -655,9 +655,9 @@ insert into t1 (a,b) values (1,2),(1,3),(2,5);
select a, 0.1*0+1 r2, sum(1) r1 from t1 where a = 1 group  by a having r1>1 and r2=1;
a	r2	r1
1	1.0	2
select a, rand()*0+1 r2, sum(1) r1 from t1 where a = 1 group  by a having r1>1 and r2=1;
select a, round(rand(100)*10) r2, sum(1) r1 from t1 where a = 1 group  by a having r1>1 and r2<=2;
a	r2	r1
1	1	2
1	2	2
select a,sum(b) from t1 where a=1 group by c;
a	sum(b)
1	5
+2 −2
Original line number Diff line number Diff line
@@ -109,8 +109,8 @@ select @a:=0;
select @a, @a:=@a+count(*), count(*), @a from t1 group by i;
@a	@a:=@a+count(*)	count(*)	@a
0	1	1	0
0	3	2	0
0	6	3	0
0	2	2	0
0	3	3	0
select @a:=0;
@a:=0
0
+2 −1
Original line number Diff line number Diff line
@@ -480,7 +480,8 @@ drop table t1;
create table t1 (a integer, b integer, c integer);
insert into t1 (a,b) values (1,2),(1,3),(2,5);
select a, 0.1*0+1 r2, sum(1) r1 from t1 where a = 1 group  by a having r1>1 and r2=1;
select a, rand()*0+1 r2, sum(1) r1 from t1 where a = 1 group  by a having r1>1 and r2=1;
# rand(100)*10 will be < 2 only for the first row (of 6)
select a, round(rand(100)*10) r2, sum(1) r1 from t1 where a = 1 group  by a having r1>1 and r2<=2;
select a,sum(b) from t1 where a=1 group by c;
select a*sum(b) from t1 where a=1 group by c;
select sum(a)*sum(b) from t1 where a=1 group by c;
+52 −0
Original line number Diff line number Diff line
@@ -295,6 +295,58 @@ CHARSET_INFO *Item::default_charset()
}


/*
  Move SUM items out from item tree and replace with reference

  SYNOPSIS
    split_sum_func2()
    thd			Thread handler
    ref_pointer_array	Pointer to array of reference fields
    fields		All fields in select
    ref			Pointer to item

  NOTES
   This is from split_sum_func2() for items that should be split

   All found SUM items are added FIRST in the fields list and
   we replace the item with a reference.

   thd->fatal_error() may be called if we are out of memory
*/


void Item::split_sum_func2(THD *thd, Item **ref_pointer_array,
                           List<Item> &fields, Item **ref)
{
  if (type() != SUM_FUNC_ITEM && with_sum_func)
  {
    /* Will split complicated items and ignore simple ones */
    split_sum_func(thd, ref_pointer_array, fields);
  }
  else if ((type() == SUM_FUNC_ITEM ||
            (used_tables() & ~PARAM_TABLE_BIT)) &&
           type() != REF_ITEM)
  {
    /*
      Replace item with a reference so that we can easily calculate
      it (in case of sum functions) or copy it (in case of fields)

      The test above is to ensure we don't do a reference for things
      that are constants (PARAM_TABLE_BIT is in effect a constant)
      or already referenced (for example an item in HAVING)
    */
    uint el= fields.elements;
    Item *new_item;    
    ref_pointer_array[el]= this;
    if (!(new_item= new Item_ref(ref_pointer_array + el, 0, name)))
      return;                                   // fatal_error is set
    fields.push_front(this);
    ref_pointer_array[el]= this;
    thd->change_item_tree(ref, new_item);
  }
}


/*
   Aggregate two collations together taking
   into account their coercibility (aka derivation):
Loading