mirror of
https://github.com/MariaDB/server.git
synced 2025-07-29 05:21:33 +03:00
MDEV-6768 Wrong result with aggregate with join with no result set
When a query does implicit grouping and join operation produces an empty result set, a NULL-complemented row combination is generated. However, constant table fields still show non-NULL values. What happens in the is that end_send_group() is called with a const row but without any rows matching the WHERE clause. This last part is shown by 'join->first_record' not being set. This causes item->no_rows_in_result() to be called for all items to reset all sum functions to their initial state. However fields are not set to NULL. The used fix is to produce NULL-complemented records for constant tables as well. Also, reset the constant table's records back in case we're in a subquery which may get re-executed. An alternative fix would have item->no_rows_in_result() also work with Item_field objects. There is some other issues with the code: - join->no_rows_in_result_called is used but never set. - Tables that are used with group functions are not properly marked as maybe_null, which is required if the table rows should be regarded as null-complemented (not existing). - The code that tries to detect if mixed_implicit_grouping should be set didn't take into account all usage of fields and sum functions. - Item_func::restore_to_before_no_rows_in_result() called the wrong function. - join->clear() does not use a table_map argument to clear_tables(), which caused it to ignore constant tables. - unclear_tables() does not correctly restore status to what is was before clear_tables(). Main bug fix was to always use a table_map argument to clear_tables() and always use join->clear() and clear_tables() together with unclear_tables(). Other fixes: - Fixed Item_func::restore_to_before_no_rows_in_result() - Set 'join->no_rows_in_result_called' when no_rows_in_result_set() is called. - Removed not used argument from setup_end_select_func(). - More code comments - Ensure that end_send_group() modifies the same fields as are in the result set. - Changed return_zero_rows() to use pointers instead of references, similar to the rest of the code. Reviewer: Sergei Petrunia <sergey@mariadb.com>
This commit is contained in:
@ -227,7 +227,7 @@ enum sj_strategy_enum
|
||||
|
||||
typedef enum_nested_loop_state
|
||||
(*Next_select_func)(JOIN *, struct st_join_table *, bool);
|
||||
Next_select_func setup_end_select_func(JOIN *join, JOIN_TAB *tab);
|
||||
Next_select_func setup_end_select_func(JOIN *join);
|
||||
int rr_sequential(READ_RECORD *info);
|
||||
int rr_sequential_and_unpack(READ_RECORD *info);
|
||||
Item *remove_pushed_top_conjuncts(THD *thd, Item *cond);
|
||||
@ -1767,7 +1767,8 @@ public:
|
||||
void join_free();
|
||||
/** Cleanup this JOIN, possibly for reuse */
|
||||
void cleanup(bool full);
|
||||
void clear();
|
||||
void clear(table_map *cleared_tables);
|
||||
void inline clear_sum_funcs();
|
||||
bool send_row_on_empty_set()
|
||||
{
|
||||
return (do_send_rows && implicit_grouping && !group_optimized_away &&
|
||||
|
Reference in New Issue
Block a user