mirror of
https://github.com/MariaDB/server.git
synced 2026-04-30 04:05:32 +02:00
Fix LP BUG#715738
Analysis: A query with implicit grouping is one with aggregate functions and no GROUP BY clause. MariaDB inherits from MySQL an SQL extenstion that allows mixing aggregate functions with non-aggregate fields. If a query with such mixed select clause produces an empty result set, the meaning of aggregate functions is well defined - either NULL (MIN, MAX, etc.), or 0 (count(*)). However the non-aggregated fields must also have some value, and the only reasonable value in the case of empty result is NULL. The cause of the many wrong results was that if a field is declared as non-nullable (e.g. because it is a PK or NOT NULL), the semantic analysis and the optimization phases treat this field as non-nullable, and generate all related query plan elements based on this assumption. Later during execution, these incorrectly configured/generated query plan elements result in a wrong result because the selected fields are not null due to the not-null assumption during optimization. Solution: Detect before the context analysys phase that a query uses implicit grouping with mixed aggregates/non-aggregates, and set all fields as nullable. The parser already walks the SELECT clause, and already sets Item::with_sum_func for Items that reference aggreagate functions. The patch adds a symmetric Item::with_field so that all Items that reference an Item_field are marked during their construction at parse time in the same way as with aggregate function use.
This commit is contained in:
parent
8aaf9197d0
commit
ec23949158
11 changed files with 670 additions and 5 deletions
|
|
@ -79,6 +79,7 @@ void Item_func::set_arguments(List<Item> &list)
|
|||
{
|
||||
*(save_args++)= item;
|
||||
with_sum_func|=item->with_sum_func;
|
||||
with_field|= item->with_field;
|
||||
}
|
||||
}
|
||||
list.empty(); // Fields are used
|
||||
|
|
@ -129,6 +130,7 @@ Item_func::Item_func(THD *thd, Item_func *item)
|
|||
Sets as a side effect the following class variables:
|
||||
maybe_null Set if any argument may return NULL
|
||||
with_sum_func Set if any of the arguments contains a sum function
|
||||
with_field Set if any of the arguments contains or is a field
|
||||
used_tables_cache Set to union of the tables used by arguments
|
||||
|
||||
str_value.charset If this is a string function, set this to the
|
||||
|
|
@ -198,6 +200,7 @@ Item_func::fix_fields(THD *thd, Item **ref)
|
|||
maybe_null=1;
|
||||
|
||||
with_sum_func= with_sum_func || item->with_sum_func;
|
||||
with_field= with_field || item->with_field;
|
||||
used_tables_cache|= item->used_tables();
|
||||
not_null_tables_cache|= item->not_null_tables();
|
||||
const_item_cache&= item->const_item();
|
||||
|
|
@ -2939,6 +2942,7 @@ udf_handler::fix_fields(THD *thd, Item_result_field *func,
|
|||
if (item->maybe_null)
|
||||
func->maybe_null=1;
|
||||
func->with_sum_func= func->with_sum_func || item->with_sum_func;
|
||||
func->with_field= func->with_field || item->with_field;
|
||||
used_tables_cache|=item->used_tables();
|
||||
const_item_cache&=item->const_item();
|
||||
f_args.arg_type[i]=item->result_type();
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue