From da7c5e3b857b671a1ac4534ee814d11218098d40 Mon Sep 17 00:00:00 2001 From: Sergei Petrunia Date: Sun, 10 Apr 2016 16:24:04 +0200 Subject: [PATCH] MDEV-9895: Assertion `n_rows > 0' failed in Frame_cursor* get_frame_cursor n=0 in "ROWS 0 PRECEDING" is valid, add handling for it: - Adjust the assert - Bottom bound of 'ROW 0 PRECEDING' is actually looking at the current row, that is, it needs to process partition's first row directly in Frame_n_rows_preceding::next_partition(). - Added testcases --- mysql-test/r/win.result | 61 +++++++++++++++++++++++++++++++++++++++++ mysql-test/t/win.test | 41 +++++++++++++++++++++++++++ sql/sql_window.cc | 10 ++++++- 3 files changed, 111 insertions(+), 1 deletion(-) diff --git a/mysql-test/r/win.result b/mysql-test/r/win.result index c8f182ef0d3..e641ff64433 100644 --- a/mysql-test/r/win.result +++ b/mysql-test/r/win.result @@ -1841,3 +1841,64 @@ insert into t1 values (1),(2); SELECT MAX(i) OVER (PARTITION BY (i)) FROM t1; ERROR 42000: This version of MariaDB doesn't yet support 'This aggregate as window function' drop table t1; +# +# Check the 0 in ROWS 0 PRECEDING +# +create table t1 ( +part_id int, +pk int, +a int +); +insert into t1 values (1, 1, 1); +insert into t1 values (1, 2, 2); +insert into t1 values (1, 3, 4); +insert into t1 values (1, 4, 8); +select +pk, a, +sum(a) over (order by pk rows between 0 preceding and current row) +from t1; +pk a sum(a) over (order by pk rows between 0 preceding and current row) +1 1 1 +2 2 2 +3 4 4 +4 8 8 +select +pk, a, +sum(a) over (order by pk rows between 1 preceding and 0 preceding) +from t1; +pk a sum(a) over (order by pk rows between 1 preceding and 0 preceding) +1 1 1 +2 2 3 +3 4 6 +4 8 12 +insert into t1 values (200, 1, 1); +insert into t1 values (200, 2, 2); +insert into t1 values (200, 3, 4); +insert into t1 values (200, 4, 8); +select +part_id, pk, a, +sum(a) over (partition by part_id order by pk rows between 0 preceding and current row) +from t1; +part_id pk a sum(a) over (partition by part_id order by pk rows between 0 preceding and current row) +1 1 1 1 +1 2 2 2 +1 3 4 4 +1 4 8 8 +200 1 1 1 +200 2 2 2 +200 3 4 4 +200 4 8 8 +select +part_id, pk, a, +sum(a) over (partition by part_id order by pk rows between 1 preceding and 0 preceding) +from t1; +part_id pk a sum(a) over (partition by part_id order by pk rows between 1 preceding and 0 preceding) +1 1 1 1 +1 2 2 3 +1 3 4 6 +1 4 8 12 +200 1 1 1 +200 2 2 3 +200 3 4 6 +200 4 8 12 +drop table t1; diff --git a/mysql-test/t/win.test b/mysql-test/t/win.test index 7dc636a13ed..d7f6cca9261 100644 --- a/mysql-test/t/win.test +++ b/mysql-test/t/win.test @@ -1124,3 +1124,44 @@ insert into t1 values (1),(2); SELECT MAX(i) OVER (PARTITION BY (i)) FROM t1; drop table t1; +--echo # +--echo # Check the 0 in ROWS 0 PRECEDING +--echo # + +create table t1 ( + part_id int, + pk int, + a int +); + +insert into t1 values (1, 1, 1); +insert into t1 values (1, 2, 2); +insert into t1 values (1, 3, 4); +insert into t1 values (1, 4, 8); + +select + pk, a, + sum(a) over (order by pk rows between 0 preceding and current row) +from t1; + +select + pk, a, + sum(a) over (order by pk rows between 1 preceding and 0 preceding) +from t1; + +insert into t1 values (200, 1, 1); +insert into t1 values (200, 2, 2); +insert into t1 values (200, 3, 4); +insert into t1 values (200, 4, 8); +select + part_id, pk, a, + sum(a) over (partition by part_id order by pk rows between 0 preceding and current row) +from t1; + +select + part_id, pk, a, + sum(a) over (partition by part_id order by pk rows between 1 preceding and 0 preceding) +from t1; + +drop table t1; + diff --git a/sql/sql_window.cc b/sql/sql_window.cc index 3753e2499c3..d4de1ac57c6 100644 --- a/sql/sql_window.cc +++ b/sql/sql_window.cc @@ -1279,6 +1279,14 @@ public: - top bound should remove row (#n-3) from the window function. */ n_rows_to_skip= n_rows + (is_top_bound? 1:0) - 1; + + /* Bottom bound "ROWS 0 PRECEDING" is a special case: */ + if (n_rows_to_skip == -1) + { + cursor.get_next(); + item->add(); + n_rows_to_skip= 0; + } } void next_row(Item_sum* item) @@ -1496,7 +1504,7 @@ Frame_cursor *get_frame_cursor(Window_frame *frame, bool is_top_bound) longlong n_rows= bound->offset->val_int(); /* These should be handled in the parser */ DBUG_ASSERT(!bound->offset->null_value); - DBUG_ASSERT(n_rows > 0); + DBUG_ASSERT(n_rows >= 0); if (is_preceding) return new Frame_n_rows_preceding(is_top_bound, n_rows); else