Skip to content

Commit f69fe33

Browse files
Dag WanvikChaithra Gopalareddy
authored andcommitted
Bug#31361748 ASSERTION `W->FRAME_BUFFER()->S->DB_TYPE()->DB_TYPE ==
DB_TYPE_INNODB || CNT <= 1 || (W->LAST_ROW_OUTPUT() == 0 && W->FRAME()->M_FROM->M_BORDER_TYPE == WBT_VALUE_FOLLOWING) || FOR_NTH_VALUE' FAILED. Problem: Only seen in debug mode with RANGE frame. While evaluating the previous row, we had a frame containing no rows. While evaluating the current row (mysql#3 in the minimal repro given in added test), we find that all possible rows falls *before* the frame boundaries, so we still have a frame containing no rows. In this case, we could move the possible boundaries [first_rowno_in_range_frame, last_rowno_in_range_frame] one row forward for the set of rows that will fit in the frame when evaluating the next (last) row, but we didn't update them to reflect this. In production code, this will lead to reading more rows than strictly necessary when evaluating the frame rows for the next current row, which is not optimal, but will work. In the debug code, we assert when we need to read more than one row to position correctly in the frame buffer, hence the issue. Solution: Update m_first_rowno_in_range_frame and m_last_rowno_in_range_frame also in this case. Reviewed by: Chaithra Gopalareddy <[email protected]>
1 parent 21f618c commit f69fe33

File tree

3 files changed

+82
-0
lines changed

3 files changed

+82
-0
lines changed

mysql-test/r/window_functions.result

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9430,6 +9430,51 @@ a SUM(a) OVER (ROWS BETWEEN
94309430
4 NULL
94319431
DROP TABLE t;
94329432
#
9433+
# Bug#31361748 ASSERTION `W->FRAME_BUFFER()->S->DB_TYPE()->DB_TYPE..
9434+
#
9435+
# Minimal repro
9436+
CREATE TABLE t(a INT);
9437+
INSERT INTO t VALUES (3), (10), (100), (103);
9438+
SELECT a, COUNT(a) OVER (ORDER BY a RANGE
9439+
BETWEEN 4 FOLLOWING AND 6 FOLLOWING)
9440+
FROM t;
9441+
a COUNT(a) OVER (ORDER BY a RANGE
9442+
BETWEEN 4 FOLLOWING AND 6 FOLLOWING)
9443+
3 0
9444+
10 0
9445+
100 0
9446+
103 0
9447+
DROP TABLE t;
9448+
# Original repro
9449+
CREATE TABLE t (a INT,b INT);
9450+
INSERT INTO t(a) VALUES(2147483647),(0),(-2),(-1),(0);
9451+
INSERT INTO t(a) VALUES(5430600),(0),(-91),(2147483647),(0);
9452+
INSERT INTO t(a) VALUES(-1),(0),(-26164),(37583),(-1),(79);
9453+
SELECT LAST_VALUE(b) RESPECT NULLS
9454+
OVER (PARTITION BY b ORDER BY a
9455+
RANGE BETWEEN 253 FOLLOWING AND 118 FOLLOWING)
9456+
FROM t;
9457+
LAST_VALUE(b) RESPECT NULLS
9458+
OVER (PARTITION BY b ORDER BY a
9459+
RANGE BETWEEN 253 FOLLOWING AND 118 FOLLOWING)
9460+
NULL
9461+
NULL
9462+
NULL
9463+
NULL
9464+
NULL
9465+
NULL
9466+
NULL
9467+
NULL
9468+
NULL
9469+
NULL
9470+
NULL
9471+
NULL
9472+
NULL
9473+
NULL
9474+
NULL
9475+
NULL
9476+
DROP TABLE t;
9477+
#
94339478
# Bug#31393719: SIGFPE, ARITHMETIC EXCEPTION IN ITEM_NTILE::VAL_INT
94349479
#
94359480
DO NTILE(MAX(NOT 1)) OVER();

mysql-test/t/window_functions.test

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4172,6 +4172,28 @@ FROM t;
41724172

41734173
DROP TABLE t;
41744174

4175+
--echo #
4176+
--echo # Bug#31361748 ASSERTION `W->FRAME_BUFFER()->S->DB_TYPE()->DB_TYPE..
4177+
--echo #
4178+
4179+
--echo # Minimal repro
4180+
CREATE TABLE t(a INT);
4181+
INSERT INTO t VALUES (3), (10), (100), (103);
4182+
SELECT a, COUNT(a) OVER (ORDER BY a RANGE
4183+
BETWEEN 4 FOLLOWING AND 6 FOLLOWING)
4184+
FROM t;
4185+
DROP TABLE t;
4186+
4187+
--echo # Original repro
4188+
CREATE TABLE t (a INT,b INT);
4189+
INSERT INTO t(a) VALUES(2147483647),(0),(-2),(-1),(0);
4190+
INSERT INTO t(a) VALUES(5430600),(0),(-91),(2147483647),(0);
4191+
INSERT INTO t(a) VALUES(-1),(0),(-26164),(37583),(-1),(79);
4192+
SELECT LAST_VALUE(b) RESPECT NULLS
4193+
OVER (PARTITION BY b ORDER BY a
4194+
RANGE BETWEEN 253 FOLLOWING AND 118 FOLLOWING)
4195+
FROM t;
4196+
DROP TABLE t;
41754197

41764198
# Local Variables:
41774199
# mode: sql

sql/sql_executor.cc

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5890,6 +5890,8 @@ bool process_buffered_windowing_record(THD *thd, Temp_table_param *param,
58905890
row. Now evaluate over any new rows within range of the current row.
58915891
*/
58925892
const int64 first = w.last_rowno_in_range_frame() + 1;
5893+
const bool empty =
5894+
w.last_rowno_in_range_frame() < w.first_rowno_in_range_frame();
58935895
bool row_added = false;
58945896

58955897
for (rowno = first; rowno <= upper; rowno++) {
@@ -5933,6 +5935,19 @@ bool process_buffered_windowing_record(THD *thd, Temp_table_param *param,
59335935
row_added = true;
59345936
}
59355937

5938+
if (w.before_frame() && empty) {
5939+
DBUG_ASSERT(!row_added && !found_first);
5940+
// This row's value is too low to fit in frame. We already had an empty
5941+
// set of frame rows when evaluating for the previous row, and the set
5942+
// is still empty. So, we can move the possible boundaries for the
5943+
// set of frame rows for the next row to be evaluated one row ahead.
5944+
// We need only update last_rowno_in_range_frame here, first_row
5945+
// no_in_range_frame will be adjusted below to be one higher, cf.
5946+
// "maintain invariant" comment.
5947+
w.set_last_rowno_in_range_frame(
5948+
min(w.last_rowno_in_range_frame() + 1, upper));
5949+
}
5950+
59365951
if (rowno > upper && row_added)
59375952
w.set_last_rowno_in_range_frame(rowno - 1);
59385953

0 commit comments

Comments
 (0)