1
0
mirror of https://github.com/MariaDB/server.git synced 2025-12-24 11:21:21 +03: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:
unknown
2011-03-24 16:34:06 +02:00
parent 8aaf9197d0
commit ec23949158
11 changed files with 670 additions and 5 deletions

View File

@@ -517,12 +517,49 @@ JOIN::prepare(Item ***rref_pointer_array,
tables_list, &select_lex->leaf_tables,
FALSE, SELECT_ACL, SELECT_ACL))
DBUG_RETURN(-1);
/*
TRUE if the SELECT list mixes elements with and without grouping,
and there is no GROUP BY clause. Mixing non-aggregated fields with
aggregate functions in the SELECT list is a MySQL exptenstion that
is allowed only if the ONLY_FULL_GROUP_BY sql mode is not set.
*/
bool mixed_implicit_grouping= false;
if ((~thd->variables.sql_mode & MODE_ONLY_FULL_GROUP_BY) &&
select_lex->with_sum_func && !group_list)
{
List_iterator_fast <Item> select_it(fields_list);
Item *select_el; /* Element of the SELECT clause, can be an expression. */
bool found_field_elem= false;
bool found_sum_func_elem= false;
while ((select_el= select_it++))
{
if (select_el->with_sum_func)
found_sum_func_elem= true;
if (select_el->with_field)
found_field_elem= true;
if (found_sum_func_elem && found_field_elem)
{
mixed_implicit_grouping= true;
break;
}
}
}
TABLE_LIST *table_ptr;
for (table_ptr= select_lex->leaf_tables;
for (TABLE_LIST *table_ptr= select_lex->leaf_tables;
table_ptr;
table_ptr= table_ptr->next_leaf)
tables++;
{
tables++; /* Count the number of tables in the join. */
/*
If the query uses implicit grouping where the select list contains both
aggregate functions and non-aggregate fields, any non-aggregated field
may produce a NULL value. Set all fields of each table as nullable before
semantic analysis to take into account this change of nullability.
*/
if (mixed_implicit_grouping)
table_ptr->table->maybe_null= 1;
}
if (setup_wild(thd, tables_list, fields_list, &all_fields, wild_num) ||
select_lex->setup_ref_array(thd, og_num) ||