summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorunknown <igor@olga.mysql.com>2007-04-29 18:32:59 -0700
committerunknown <igor@olga.mysql.com>2007-04-29 18:32:59 -0700
commit532f2e84160e14b8f1a9104ec673af778e8950a6 (patch)
tree4f41906a0d61ce1b1e7d1ceb6ce8830dfded7627
parentba967f5b43dd1bb0f303bdeee55aeb630ea829a7 (diff)
parentc004ad09444b8b3be367b6620aa4f0716684bdc3 (diff)
downloadmariadb-git-532f2e84160e14b8f1a9104ec673af778e8950a6.tar.gz
Merge olga.mysql.com:/home/igor/mysql-4.1-opt
into olga.mysql.com:/home/igor/dev-opt/mysql-5.0-opt-bug24856 sql/item_func.h: Auto merged sql/sql_select.cc: Auto merged mysql-test/r/olap.result: Manual merge. mysql-test/t/olap.test: Manual merge.
-rw-r--r--mysql-test/r/olap.result60
-rw-r--r--mysql-test/t/olap.test22
-rw-r--r--sql/item_func.h25
-rw-r--r--sql/sql_select.cc28
4 files changed, 131 insertions, 4 deletions
diff --git a/mysql-test/r/olap.result b/mysql-test/r/olap.result
index 91cd15295c3..fe6253611e8 100644
--- a/mysql-test/r/olap.result
+++ b/mysql-test/r/olap.result
@@ -607,6 +607,66 @@ x a sum(b)
2006-07-01 NULL 11
NULL NULL 11
drop table t1;
+CREATE TABLE t1 (a int, b int);
+INSERT INTO t1
+VALUES (2,10),(3,30),(2,40),(1,10),(2,30),(1,20),(2,10);
+SELECT a, SUM(b) FROM t1 GROUP BY a WITH ROLLUP;
+a SUM(b)
+1 30
+2 90
+3 30
+NULL 150
+SELECT DISTINCT a, SUM(b) FROM t1 GROUP BY a WITH ROLLUP;
+a SUM(b)
+1 30
+2 90
+3 30
+NULL 150
+SELECT a, b, COUNT(*) FROM t1 GROUP BY a,b WITH ROLLUP;
+a b COUNT(*)
+1 10 1
+1 20 1
+1 NULL 2
+2 10 2
+2 30 1
+2 40 1
+2 NULL 4
+3 30 1
+3 NULL 1
+NULL NULL 7
+SELECT DISTINCT a, b, COUNT(*) FROM t1 GROUP BY a,b WITH ROLLUP;
+a b COUNT(*)
+1 10 1
+1 20 1
+1 NULL 2
+2 10 2
+2 30 1
+2 40 1
+2 NULL 4
+3 30 1
+3 NULL 1
+NULL NULL 7
+SELECT 'x', a, SUM(b) FROM t1 GROUP BY 1,2 WITH ROLLUP;
+x a SUM(b)
+x 1 30
+x 2 90
+x 3 30
+x NULL 150
+NULL NULL 150
+SELECT DISTINCT 'x', a, SUM(b) FROM t1 GROUP BY 1,2 WITH ROLLUP;
+x a SUM(b)
+x 1 30
+x 2 90
+x 3 30
+x NULL 150
+NULL NULL 150
+SELECT DISTINCT 'x', a, SUM(b) FROM t1 GROUP BY 1,2 WITH ROLLUP;
+x a SUM(b)
+x 1 30
+x 2 90
+x 3 30
+x NULL 150
+NULL NULL 150
CREATE TABLE t1(id int, type char(1));
INSERT INTO t1 VALUES
(1,"A"),(2,"C"),(3,"A"),(4,"A"),(5,"B"),
diff --git a/mysql-test/t/olap.test b/mysql-test/t/olap.test
index e6cbfe3166c..05934bff492 100644
--- a/mysql-test/t/olap.test
+++ b/mysql-test/t/olap.test
@@ -292,6 +292,25 @@ select left(a,10), a, sum(b) from t1 group by 1,2 with rollup;
select left(a,10) x, a, sum(b) from t1 group by x,a with rollup;
drop table t1;
+#
+# Bug #24856: ROLLUP by const item in a query with DISTINCT
+#
+
+CREATE TABLE t1 (a int, b int);
+INSERT INTO t1
+ VALUES (2,10),(3,30),(2,40),(1,10),(2,30),(1,20),(2,10);
+
+SELECT a, SUM(b) FROM t1 GROUP BY a WITH ROLLUP;
+SELECT DISTINCT a, SUM(b) FROM t1 GROUP BY a WITH ROLLUP;
+SELECT a, b, COUNT(*) FROM t1 GROUP BY a,b WITH ROLLUP;
+SELECT DISTINCT a, b, COUNT(*) FROM t1 GROUP BY a,b WITH ROLLUP;
+
+SELECT 'x', a, SUM(b) FROM t1 GROUP BY 1,2 WITH ROLLUP;
+SELECT DISTINCT 'x', a, SUM(b) FROM t1 GROUP BY 1,2 WITH ROLLUP;
+SELECT DISTINCT 'x', a, SUM(b) FROM t1 GROUP BY 1,2 WITH ROLLUP;
+
+DROP TABLE t1;
+
# End of 4.1 tests
#
@@ -339,6 +358,3 @@ SELECT * FROM (SELECT a, SUM(a) FROM t1 GROUP BY a WITH ROLLUP) as t;
DROP TABLE t1;
-
-
-
diff --git a/sql/item_func.h b/sql/item_func.h
index 635a409e0a2..cdf397c82ed 100644
--- a/sql/item_func.h
+++ b/sql/item_func.h
@@ -719,6 +719,31 @@ public:
};
+/*
+ Objects of this class are used for ROLLUP queries to wrap up
+ each constant item referred to in GROUP BY list.
+*/
+
+class Item_func_rollup_const :public Item_func
+{
+public:
+ Item_func_rollup_const(Item *a) :Item_func(a)
+ { name= a->name; }
+ double val() { return args[0]->val(); }
+ longlong val_int() { return args[0]->val_int(); }
+ String *val_str(String *str) { return args[0]->val_str(str); }
+ const char *func_name() const { return "rollup_const"; }
+ bool const_item() const { return 0; }
+ Item_result result_type() const { return args[0]->result_type(); }
+ void fix_length_and_dec()
+ {
+ collation= args[0]->collation;
+ max_length= args[0]->max_length;
+ decimals=args[0]->decimals;
+ }
+};
+
+
class Item_func_length :public Item_int_func
{
String value;
diff --git a/sql/sql_select.cc b/sql/sql_select.cc
index b4d9e8b007e..4545ff62f31 100644
--- a/sql/sql_select.cc
+++ b/sql/sql_select.cc
@@ -14540,7 +14540,7 @@ bool JOIN::rollup_init()
for (j=0 ; j < fields_list.elements ; j++)
rollup.fields[i].push_back(rollup.null_items[i]);
}
- List_iterator_fast<Item> it(all_fields);
+ List_iterator<Item> it(all_fields);
Item *item;
while ((item= it++))
{
@@ -14553,6 +14553,32 @@ bool JOIN::rollup_init()
{
item->maybe_null= 1;
found_in_group= 1;
+ if (item->const_item())
+ {
+ /*
+ For ROLLUP queries each constant item referenced in GROUP BY list
+ is wrapped up into an Item_func object yielding the same value
+ as the constant item. The objects of the wrapper class are never
+ considered as constant items and besides they inherit all
+ properties of the Item_result_field class.
+ This wrapping allows us to ensure writing constant items
+ into temporary tables whenever the result of the ROLLUP
+ operation has to be written into a temporary table, e.g. when
+ ROLLUP is used together with DISTINCT in the SELECT list.
+ Usually when creating temporary tables for a intermidiate
+ result we do not include fields for constant expressions.
+ */
+ Item* new_item= new Item_func_rollup_const(item);
+ if (!new_item)
+ return 1;
+ new_item->fix_fields(thd,0, (Item **) 0);
+ thd->change_item_tree(it.ref(), new_item);
+ for (ORDER *tmp= group_tmp; tmp; tmp= tmp->next)
+ {
+ if (*tmp->item == item)
+ thd->change_item_tree(tmp->item, new_item);
+ }
+ }
}
}
if (item->type() == Item::FUNC_ITEM && !found_in_group)