CURRENT ROW frame start for RANGE frame

This commit is contained in:
Alexander Kuzmenkov 2021-02-03 17:22:37 +03:00
parent 7c55ecf67d
commit 35754abb4a
4 changed files with 71 additions and 12 deletions

View File

@ -295,18 +295,14 @@ void WindowTransform::advanceFrameStartChoose()
frame_started = true;
return;
case WindowFrame::BoundaryType::Current:
switch (window_description.frame.type)
{
case WindowFrame::FrameType::Rows:
// CURRENT ROW
frame_start = current_row;
frame_started = true;
return;
default:
// Fallthrough to the "not implemented" error.
break;
}
break;
// CURRENT ROW differs between frame types only in how the peer
// groups are accounted.
assert(partition_start <= peer_group_start);
assert(peer_group_start < partition_end);
assert(peer_group_start <= current_row);
frame_start = peer_group_start;
frame_started = true;
return;
case WindowFrame::BoundaryType::Offset:
switch (window_description.frame.type)
{
@ -651,6 +647,13 @@ void WindowTransform::appendChunk(Chunk & chunk)
// current_row, frame_start, frame_end,
// frame_started, frame_ended);
// We now know that the current row is valid, so we can update the
// peer group start.
if (!arePeers(peer_group_start, current_row))
{
peer_group_start = current_row;
}
// Advance the frame start.
advanceFrameStart();
@ -703,6 +706,8 @@ void WindowTransform::appendChunk(Chunk & chunk)
writeOutCurrentRow();
// Move to the next row. The frame will have to be recalculated.
// The peer group start is updated at the beginning of the loop,
// because current_row might now be past-the-end.
advanceRowNumber(current_row);
first_not_ready_row = current_row;
frame_ended = false;
@ -738,6 +743,7 @@ void WindowTransform::appendChunk(Chunk & chunk)
prev_frame_start = partition_start;
prev_frame_end = partition_start;
assert(current_row == partition_start);
peer_group_start = partition_start;
// fmt::print(stderr, "reinitialize agg data at start of {}\n",
// new_partition_start);
@ -925,6 +931,7 @@ void WindowTransform::work()
assert(next_output_block_number >= first_block_number);
assert(frame_start.block >= first_block_number);
assert(current_row.block >= first_block_number);
assert(peer_group_start.block >= first_block_number);
}
}

View File

@ -257,6 +257,10 @@ public:
// The row for which we are now computing the window functions.
RowNumber current_row;
// The start of current peer group, needed for CURRENT ROW frame start.
// For ROWS frame, always equal to the current row, and for RANGE and GROUP
// frames may be earlier.
RowNumber peer_group_start;
// The frame is [frame_start, frame_end) if frame_ended && frame_started,
// and unknown otherwise. Note that when we move to the next row, both the

View File

@ -568,3 +568,42 @@ SELECT number, max(number) OVER (PARTITION BY intDiv(number, 7) ORDER BY number
-- a corner case
select count() over ();
1
-- RANGE CURRENT ROW frame start
select number, p, o,
count(*) over (partition by p order by o
range between current row and unbounded following)
from (select number, intDiv(number, 5) p, mod(number, 3) o
from numbers(31))
order by p, o, number
settings max_block_size = 2;
0 0 0 5
3 0 0 5
1 0 1 3
4 0 1 3
2 0 2 1
6 1 0 5
9 1 0 5
7 1 1 3
5 1 2 2
8 1 2 2
12 2 0 5
10 2 1 4
13 2 1 4
11 2 2 2
14 2 2 2
15 3 0 5
18 3 0 5
16 3 1 3
19 3 1 3
17 3 2 1
21 4 0 5
24 4 0 5
22 4 1 3
20 4 2 2
23 4 2 2
27 5 0 5
25 5 1 4
28 5 1 4
26 5 2 2
29 5 2 2
30 6 0 1

View File

@ -182,3 +182,12 @@ SELECT number, max(number) OVER (PARTITION BY intDiv(number, 7) ORDER BY number
-- a corner case
select count() over ();
-- RANGE CURRENT ROW frame start
select number, p, o,
count(*) over (partition by p order by o
range between current row and unbounded following)
from (select number, intDiv(number, 5) p, mod(number, 3) o
from numbers(31))
order by p, o, number
settings max_block_size = 2;