Fix window function expressions such as win_func() <operator> expr.
The problem was found in 2 places.
First, when we have complex expressions containing window functions, we
can only compute their final value _after_ we have computed the window
function's values. These values must be stored within the temporary
table that we are using, before sending them off.
This is done by performing an extra copy_funcs call before the final
end_send() call.
Second, such expressions need to have their inner arguments,
changed such that the references within those arguments point to fields within
the temporary table.
Ex: sum(t.a) over (order by t.b) + sum(t.a) over (order by t.b)
Before this fix, t.a pointed to the original table's a field. In order
to compute the sum function's value correctly, it needs to point to the
copy of this field inside the temp table.
This is done by calling split_sum_func for each argument in the
expression in turn.
The win.test results have also been updated as they contained wrong
values for such a use case.
When running with --ps protocol, window functions cleanup method may
be called twice. Enforce proper cleanup by setting pointers to NULL
after deletion. This prevents double deletion on second cleanup.
Perform only one table scan for each window function present. We do this
by keeping keeping cursors for each window function frame bound and
running them for each function for every row.
When ordering by a column and partitioning by another, we must reset the
peer_tracker for dense_rank, regardless if the value for the order
column changes or not.
Example:
select a, b, dense_rank() over (partition by b order by a)
a | b | dense_rank
----------------------
1 | p1 | 1
2 | p1 | 2
2 | p2 | 1 // Here, without this fix we returned 0.
2 | p2 | 2 // And 1 here.
The bug was caused by a weird behaviour in test_if_group_changed, not
returning true when testing for the first time after initializing
the Cached_item list.
- When window functions are present, JOIN::simple_order should be set
to FALSE. (Otherwise, the optimizer may attempt to do a "pre-sorting"
on the first join_tab. Which can work in some cases, but generally
isn't)
- filesort tries to only read table fields that it requires. Window
function requires its temp.table field. In order to pass this info
to filesort, added an implementation of Item_window_func::
register_field_in_read_map.
- Make Item_XXX::cleanup() clean List<Cached_item> orderby_fields.
(Items survive across PS re-executions. Cached_item don't, because
they keep pointers to fix_field'ed items, etc)
- Move List<Cached_item> out into Group_bound_tracker.
Item_func_or_sum.
Implemented method update_used_tables for class Item_findow_func.
Added the flag Item::with_window_func.
Made sure that window functions could be used only in SELECT list
and ORDER BY clause.
Added test cases that checked different illegal placements of
window functions.
1. Item_windowfunc must check the nullness of the field if it returns the
value from the result_field.
2. The decimal value must come from the window_func instead of the
result_field when not fetching values from the result_field.
Added a more extensive test case that highlights if these bugs occur.
The 2 select statements check behaviour for decimal and real typed
fields respectively.
Query result had 0 where it should have had NULLs:
- Make Item_window_func::val* functions honor NULL-handling conventions:
1. set null_value to indicate whether we've returned a NULL value
2. val_str and val_decimal should return NULL pointer when they're
returning SQL NULL value.
Fix assertion failure when sending results to network.
- The assert was due to window func returing SQL NULL despite having
maybe_null=false
- Fixed by settting Item_window_func::maybe_null correctly in fix_fields
- Item_sum_count::remove() should check if the argument's value is NULL.
- Window Function item must have its Item_window_func::split_sum_func
called,
- and it must call split_sum_func for aggregate's arguments (see the
comment near Item_window_func::split_sum_func for explanation why)
- Add temporary code: clone_read_record() clones READ_RECORD structure,
as long as it is used for reading filesort() result that fits into
memory.
- Add frame bounds for ROWS-type frames. ROWS n PRECEDING|FOLLOWING,
ROWS UNBOUNDED PRECEDING|FOLLOWING, CURRENT ROW are supported.
- Add Item_sum_count::remove() which allows "streaming" computation
of COUNT() over a moving frame.