Skip to content

Commit 6aa7498

Browse files
MDEV-31744: Assertion with COUNT(*) OVER (ORDER BY const RANGE BETWEEN...)
When the query uses several Window Functions: SELECT WIN_FUNC1() OVER (ORDER BY 'const', col1), WIN_FUNC2() OVER (ORDER BY col1 RANGE BETWEEN CURRENT ROW AND 5 FOLLOWING) compare_window_funcs_by_window_specs() will try to get the Window Specs to reuse the ORDER BY lists. If the lists produce the same order (like above) Window Spec of the WIN_FUNC2 will reuse the ORDER BY list of WIN_FUNC1. However, WIN_FUNC2 has a RANGE-type window frame. It expects to get ORDER BY list with one element, which it will use to compute frame bounds. Proving it with ORDER BY list from WIN_FUNC1 ('const', col1) was caused an assertion failure The fix is to: Use the original ORDER BY list when constructing RANGE-type frames Fix an apparent typo bug in compare_window_funcs_by_window_specs(): assignment win_spec1->save_order_list= win_spec2->order_list; Saved the order list from the wrong spec. Instead, take one from win_spec1.
1 parent 7ccc7c3 commit 6aa7498

File tree

4 files changed

+169
-4
lines changed

4 files changed

+169
-4
lines changed

mysql-test/main/win.result

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4745,3 +4745,53 @@ DROP TABLE t1, t2;
47454745
#
47464746
# End of 10.6 tests
47474747
#
4748+
#
4749+
# MDEV-31744: Assertion `order_list->elements == 1' failure
4750+
# during Frame_range_n_bottom object creation
4751+
#
4752+
CREATE TABLE t1 (a int, b int, c int, d int) ENGINE=MyISAM;
4753+
INSERT INTO t1 VALUES (1,1,1,1);
4754+
CREATE VIEW v1 AS SELECT * FROM t1;
4755+
SELECT
4756+
LEAD(a) OVER (ORDER BY b, c) AS c1,
4757+
COUNT(*) OVER (ORDER BY d RANGE BETWEEN CURRENT ROW AND 5 FOLLOWING) AS c2
4758+
FROM v1;
4759+
c1 c2
4760+
NULL 1
4761+
#
4762+
# test similar query as above for Frame_range_n_top
4763+
#
4764+
SELECT
4765+
LEAD(a) OVER (ORDER BY b, c) AS c1,
4766+
COUNT(*) OVER (ORDER BY d RANGE BETWEEN 5 PRECEDING AND CURRENT ROW) AS c2
4767+
FROM v1;
4768+
c1 c2
4769+
NULL 1
4770+
DROP TABLE t1;
4771+
DROP VIEW v1;
4772+
#
4773+
# test queries as above but on the table instead of view
4774+
#
4775+
CREATE TABLE t1 (a int) ENGINE=MyISAM;
4776+
INSERT INTO t1 values (1), (2);
4777+
SELECT
4778+
COUNT(*) OVER (ORDER BY 'abc', a) AS c1,
4779+
COUNT(*) OVER (ORDER BY a RANGE BETWEEN CURRENT ROW AND 5 FOLLOWING) AS c2
4780+
from t1;
4781+
c1 c2
4782+
1 2
4783+
2 1
4784+
#
4785+
# similar query on table with Frame_range_n_top
4786+
#
4787+
SELECT
4788+
COUNT(*) OVER (ORDER BY 'abc', a) AS c1,
4789+
COUNT(*) OVER (ORDER BY a RANGE BETWEEN 5 PRECEDING AND CURRENT ROW) AS c2
4790+
from t1;
4791+
c1 c2
4792+
1 1
4793+
2 2
4794+
DROP TABLE t1;
4795+
#
4796+
# End of 10.11 tests
4797+
#

mysql-test/main/win.test

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3058,3 +3058,56 @@ DROP TABLE t1, t2;
30583058
--echo #
30593059
--echo # End of 10.6 tests
30603060
--echo #
3061+
3062+
--echo #
3063+
--echo # MDEV-31744: Assertion `order_list->elements == 1' failure
3064+
--echo # during Frame_range_n_bottom object creation
3065+
--echo #
3066+
3067+
CREATE TABLE t1 (a int, b int, c int, d int) ENGINE=MyISAM;
3068+
INSERT INTO t1 VALUES (1,1,1,1);
3069+
CREATE VIEW v1 AS SELECT * FROM t1;
3070+
3071+
SELECT
3072+
LEAD(a) OVER (ORDER BY b, c) AS c1,
3073+
COUNT(*) OVER (ORDER BY d RANGE BETWEEN CURRENT ROW AND 5 FOLLOWING) AS c2
3074+
FROM v1;
3075+
3076+
--echo #
3077+
--echo # test similar query as above for Frame_range_n_top
3078+
--echo #
3079+
3080+
SELECT
3081+
LEAD(a) OVER (ORDER BY b, c) AS c1,
3082+
COUNT(*) OVER (ORDER BY d RANGE BETWEEN 5 PRECEDING AND CURRENT ROW) AS c2
3083+
FROM v1;
3084+
3085+
DROP TABLE t1;
3086+
DROP VIEW v1;
3087+
3088+
--echo #
3089+
--echo # test queries as above but on the table instead of view
3090+
--echo #
3091+
3092+
CREATE TABLE t1 (a int) ENGINE=MyISAM;
3093+
INSERT INTO t1 values (1), (2);
3094+
3095+
SELECT
3096+
COUNT(*) OVER (ORDER BY 'abc', a) AS c1,
3097+
COUNT(*) OVER (ORDER BY a RANGE BETWEEN CURRENT ROW AND 5 FOLLOWING) AS c2
3098+
from t1;
3099+
3100+
--echo #
3101+
--echo # similar query on table with Frame_range_n_top
3102+
--echo #
3103+
3104+
SELECT
3105+
COUNT(*) OVER (ORDER BY 'abc', a) AS c1,
3106+
COUNT(*) OVER (ORDER BY a RANGE BETWEEN 5 PRECEDING AND CURRENT ROW) AS c2
3107+
from t1;
3108+
3109+
DROP TABLE t1;
3110+
3111+
--echo #
3112+
--echo # End of 10.11 tests
3113+
--echo #

mysql-test/suite/encryption/r/tempfiles_encrypted.result

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4752,6 +4752,56 @@ DROP TABLE t1, t2;
47524752
# End of 10.6 tests
47534753
#
47544754
#
4755+
# MDEV-31744: Assertion `order_list->elements == 1' failure
4756+
# during Frame_range_n_bottom object creation
4757+
#
4758+
CREATE TABLE t1 (a int, b int, c int, d int) ENGINE=MyISAM;
4759+
INSERT INTO t1 VALUES (1,1,1,1);
4760+
CREATE VIEW v1 AS SELECT * FROM t1;
4761+
SELECT
4762+
LEAD(a) OVER (ORDER BY b, c) AS c1,
4763+
COUNT(*) OVER (ORDER BY d RANGE BETWEEN CURRENT ROW AND 5 FOLLOWING) AS c2
4764+
FROM v1;
4765+
c1 c2
4766+
NULL 1
4767+
#
4768+
# test similar query as above for Frame_range_n_top
4769+
#
4770+
SELECT
4771+
LEAD(a) OVER (ORDER BY b, c) AS c1,
4772+
COUNT(*) OVER (ORDER BY d RANGE BETWEEN 5 PRECEDING AND CURRENT ROW) AS c2
4773+
FROM v1;
4774+
c1 c2
4775+
NULL 1
4776+
DROP TABLE t1;
4777+
DROP VIEW v1;
4778+
#
4779+
# test queries as above but on the table instead of view
4780+
#
4781+
CREATE TABLE t1 (a int) ENGINE=MyISAM;
4782+
INSERT INTO t1 values (1), (2);
4783+
SELECT
4784+
COUNT(*) OVER (ORDER BY 'abc', a) AS c1,
4785+
COUNT(*) OVER (ORDER BY a RANGE BETWEEN CURRENT ROW AND 5 FOLLOWING) AS c2
4786+
from t1;
4787+
c1 c2
4788+
1 2
4789+
2 1
4790+
#
4791+
# similar query on table with Frame_range_n_top
4792+
#
4793+
SELECT
4794+
COUNT(*) OVER (ORDER BY 'abc', a) AS c1,
4795+
COUNT(*) OVER (ORDER BY a RANGE BETWEEN 5 PRECEDING AND CURRENT ROW) AS c2
4796+
from t1;
4797+
c1 c2
4798+
1 1
4799+
2 2
4800+
DROP TABLE t1;
4801+
#
4802+
# End of 10.11 tests
4803+
#
4804+
#
47554805
# MDEV-23867: select crash in compute_window_func
47564806
#
47574807
set @save_sort_buffer_size=@@sort_buffer_size;

sql/sql_window.cc

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -665,12 +665,12 @@ int compare_window_funcs_by_window_specs(Item_window_func *win_func1,
665665
*/
666666
if (!win_spec1->name() && win_spec2->name())
667667
{
668-
win_spec1->save_order_list= win_spec2->order_list;
668+
win_spec1->save_order_list= win_spec1->order_list;
669669
win_spec1->order_list= win_spec2->order_list;
670670
}
671671
else
672672
{
673-
win_spec1->save_order_list= win_spec2->order_list;
673+
win_spec2->save_order_list= win_spec2->order_list;
674674
win_spec2->order_list= win_spec1->order_list;
675675
}
676676

@@ -2490,13 +2490,25 @@ Frame_cursor *get_frame_cursor(THD *thd, Window_spec *spec, bool is_top_bound)
24902490
}
24912491
else
24922492
{
2493+
/*
2494+
compare_window_funcs_by_window_specs() will try to get the
2495+
Window Specs to reuse the ORDER BY lists.
2496+
RANGE-type window frame expects a single ORDER BY element,
2497+
and if the list from a different window spec having more than 1
2498+
ORDER BY element is used, then an ASSERT is raised.
2499+
2500+
So, use the original ORDER BY list when constructing
2501+
RANGE-type frames.
2502+
*/
2503+
SQL_I_List<ORDER> *order_list=
2504+
spec->save_order_list ? spec->save_order_list : spec->order_list;
24932505
if (is_top_bound)
24942506
return new Frame_range_n_top(
2495-
thd, spec->partition_list, spec->order_list,
2507+
thd, spec->partition_list, order_list,
24962508
is_preceding, bound->offset);
24972509

24982510
return new Frame_range_n_bottom(thd,
2499-
spec->partition_list, spec->order_list,
2511+
spec->partition_list, order_list,
25002512
is_preceding, bound->offset);
25012513
}
25022514
}

0 commit comments

Comments
 (0)