diff options
Diffstat (limited to 'sql/sql_select.cc')
-rw-r--r-- | sql/sql_select.cc | 17 |
1 files changed, 14 insertions, 3 deletions
diff --git a/sql/sql_select.cc b/sql/sql_select.cc index bf06599b25e..28afec2f688 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -13043,6 +13043,8 @@ void free_underlaid_joins(THD *thd, SELECT_LEX *select) The function replaces occurrences of group by fields in expr by ref objects for these fields unless they are under aggregate functions. + The function also corrects value of the the maybe_null attribute + for the items of all subexpressions containing group by fields. IMPLEMENTATION The function recursively traverses the tree of the expr expression, @@ -13053,6 +13055,9 @@ void free_underlaid_joins(THD *thd, SELECT_LEX *select) This substitution is needed GROUP BY queries with ROLLUP if 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 SELECT a+1 FROM t1 GROUP BY a WITH ROLLUP SELECT SUM(a)+a FROM t1 GROUP BY a WITH ROLLUP @@ -13074,6 +13079,7 @@ static bool change_group_ref(THD *thd, Item_func *expr, ORDER *group_list, arg != arg_end; arg++) { Item *item= *arg; + bool arg_changed= FALSE; if (item->type() == Item::FIELD_ITEM || item->type() == Item::REF_ITEM) { ORDER *group_tmp; @@ -13086,15 +13092,20 @@ static bool change_group_ref(THD *thd, Item_func *expr, ORDER *group_list, item->name))) return 1; // fatal_error is set thd->change_item_tree(arg, new_item); - *changed= TRUE; + arg_changed= TRUE; } } } 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; } + if (arg_changed) + { + expr->maybe_null= 1; + *changed= TRUE; + } } } return 0; @@ -13157,7 +13168,7 @@ bool JOIN::rollup_init() } if (item->type() == Item::FUNC_ITEM) { - bool changed= 0; + bool changed= FALSE; if (change_group_ref(thd, (Item_func *) item, group_list, &changed)) return 1; /* |