Commit 19192328 authored by igor@rurik.mysql.com's avatar igor@rurik.mysql.com

sql_select.cc:

  Fixed bug #12885.
  Forced inheritence of the maybe_null flag for the expressions
  containing GROUP BY attributes in selects with ROLLUP.
olap.test, olap.result:
  Added test case for bug #12885.
parent 98a52fa9
...@@ -516,3 +516,16 @@ a b c count ...@@ -516,3 +516,16 @@ a b c count
1 NULL NULL 2 1 NULL NULL 2
NULL NULL NULL 2 NULL NULL NULL 2
DROP TABLE t1; DROP TABLE t1;
CREATE TABLE t1 (a int(11) NOT NULL);
INSERT INTO t1 VALUES (1),(2);
SELECT * FROM (SELECT a, a + 1, COUNT(*) FROM t1 GROUP BY a WITH ROLLUP) t;
a a + 1 COUNT(*)
1 2 1
2 3 1
NULL NULL 2
SELECT * FROM (SELECT a, LENGTH(a), COUNT(*) FROM t1 GROUP BY a WITH ROLLUP) t;
a LENGTH(a) COUNT(*)
1 1 1
2 1 1
NULL NULL 2
DROP TABLE t1;
...@@ -250,4 +250,17 @@ SELECT a, b, a AS c, COUNT(*) AS count FROM t1 GROUP BY a, b, c WITH ROLLUP; ...@@ -250,4 +250,17 @@ SELECT a, b, a AS c, COUNT(*) AS count FROM t1 GROUP BY a, b, c WITH ROLLUP;
DROP TABLE t1; DROP TABLE t1;
#
# Bug #11885: derived table specified by a subquery with
# ROLLUP over expressions on not nullable group by attributes
#
CREATE TABLE t1 (a int(11) NOT NULL);
INSERT INTO t1 VALUES (1),(2);
SELECT * FROM (SELECT a, a + 1, COUNT(*) FROM t1 GROUP BY a WITH ROLLUP) t;
SELECT * FROM (SELECT a, LENGTH(a), COUNT(*) FROM t1 GROUP BY a WITH ROLLUP) t;
DROP TABLE t1;
# End of 4.1 tests # End of 4.1 tests
...@@ -9277,6 +9277,8 @@ void free_underlaid_joins(THD *thd, SELECT_LEX *select) ...@@ -9277,6 +9277,8 @@ void free_underlaid_joins(THD *thd, SELECT_LEX *select)
The function replaces occurrences of group by fields in expr The function replaces occurrences of group by fields in expr
by ref objects for these fields unless they are under aggregate by ref objects for these fields unless they are under aggregate
functions. functions.
The function also corrects value of the the maybe_null attribute
for the items of all subexpressions containing group by fields.
IMPLEMENTATION IMPLEMENTATION
The function recursively traverses the tree of the expr expression, The function recursively traverses the tree of the expr expression,
...@@ -9287,6 +9289,9 @@ void free_underlaid_joins(THD *thd, SELECT_LEX *select) ...@@ -9287,6 +9289,9 @@ void free_underlaid_joins(THD *thd, SELECT_LEX *select)
This substitution is needed GROUP BY queries with ROLLUP if This substitution is needed GROUP BY queries with ROLLUP if
SELECT list contains expressions over group by attributes. SELECT list contains expressions over group by attributes.
TODO: Some functions are not null-preserving. For those functions
updating of the maybe_null attribute is an overkill.
EXAMPLES EXAMPLES
SELECT a+1 FROM t1 GROUP BY a WITH ROLLUP SELECT a+1 FROM t1 GROUP BY a WITH ROLLUP
SELECT SUM(a)+a FROM t1 GROUP BY a WITH ROLLUP SELECT SUM(a)+a FROM t1 GROUP BY a WITH ROLLUP
...@@ -9307,6 +9312,7 @@ static bool change_group_ref(THD *thd, Item_func *expr, ORDER *group_list, ...@@ -9307,6 +9312,7 @@ static bool change_group_ref(THD *thd, Item_func *expr, ORDER *group_list,
arg != arg_end; arg++) arg != arg_end; arg++)
{ {
Item *item= *arg; Item *item= *arg;
bool arg_changed= FALSE;
if (item->type() == Item::FIELD_ITEM || item->type() == Item::REF_ITEM) if (item->type() == Item::FIELD_ITEM || item->type() == Item::REF_ITEM)
{ {
ORDER *group_tmp; ORDER *group_tmp;
...@@ -9318,15 +9324,20 @@ static bool change_group_ref(THD *thd, Item_func *expr, ORDER *group_list, ...@@ -9318,15 +9324,20 @@ static bool change_group_ref(THD *thd, Item_func *expr, ORDER *group_list,
if(!(new_item= new Item_ref(group_tmp->item, 0, item->name))) if(!(new_item= new Item_ref(group_tmp->item, 0, item->name)))
return 1; // fatal_error is set return 1; // fatal_error is set
thd->change_item_tree(arg, new_item); thd->change_item_tree(arg, new_item);
*changed= TRUE; arg_changed= TRUE;
} }
} }
} }
else if (item->type() == Item::FUNC_ITEM) else if (item->type() == Item::FUNC_ITEM)
{ {
if (change_group_ref(thd, (Item_func *) item, group_list, changed)) if (change_group_ref(thd, (Item_func *) item, group_list, &arg_changed))
return 1; return 1;
} }
if (arg_changed)
{
expr->maybe_null= 1;
*changed= TRUE;
}
} }
} }
return 0; return 0;
...@@ -9389,7 +9400,7 @@ bool JOIN::rollup_init() ...@@ -9389,7 +9400,7 @@ bool JOIN::rollup_init()
} }
if (item->type() == Item::FUNC_ITEM) if (item->type() == Item::FUNC_ITEM)
{ {
bool changed= 0; bool changed= FALSE;
if (change_group_ref(thd, (Item_func *) item, group_list, &changed)) if (change_group_ref(thd, (Item_func *) item, group_list, &changed))
return 1; return 1;
/* /*
......
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