Skip to content

Commit 530cb08

Browse files
author
Dag Wanvik
committed
Bug#35340987 [backport] Prepared SELECT returns different results on consecutive executions.
This patch also solves: Bug#35380604 issue with window functions in stored procedures Bug#35846873 Segmentation fault in /mysql-8.0.34/sql/item.cc:2811 Bug#35846585 Arithmetic exception in /mysql-8.0.34/sql/item_sum.cc:5032 A regression from Bug#35060385 Item::update_used_tables should also update the PROP_SUBQUERY which fully re-calculates m_accum_properties for an Item_func, starting with 0. In the repro, we have a prepared statement which gives the wrong result in the second execute. We have an equality expression in the select list, one argument of which is a window function. During optimize, we find ourselves in this situation: Item_ref::update_used_tables (Item_aggregate_ref to w.f.) Item_func::update_used_tables (equality function) ReplaceMaterializedTable CreateFrameBufferTable make_tmp_tables_info : But make_tmp_tables_info changes the slice for the window function with this call: set_ref_item_slice(widx). So Item_ref's m_ref_item then points to a field in a window tmp table, not the window function, so we lose the PROP_WINDOW_FUNCTION property for the aggregate reference and hence also the equality function, which leads to error in the second execute of the prepared statement: since optimize now finds the equality function now contains no window function it is evaluated too early: during a call of copy_funcs from BufferingWindowIterator::Read instead of during a call of copy_funcs from process_buffered_windowing_record. The solution is always (re)compute update_used_tables for the function fields in make_tmp_tables_info if windows are present, i.e. before we start relying on the correct values of the PROP_WINDOW_FUNCTION property for the (next) execution. Change-Id: I43617988424ea3fc17c0cca5d5e5e40a86b46b8c
1 parent f798c85 commit 530cb08

File tree

3 files changed

+106
-0
lines changed

3 files changed

+106
-0
lines changed

mysql-test/r/window_functions_bugs.result

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1718,3 +1718,58 @@ Warnings:
17181718
Warning 1292 Truncated incorrect INTEGER value: 'it'
17191719
SET SQL_MODE=default;
17201720
DROP TABLE t1;
1721+
#
1722+
# Bug#35340987 Prepared SELECT returns different results on
1723+
# consecutive executions.
1724+
#
1725+
CREATE TABLE t(i INT);
1726+
INSERT INTO t(i) VALUES (100), (101);
1727+
PREPARE stmt1 FROM "
1728+
SELECT a.i, (LAST_VALUE(a.i) OVER outer_window) = a.i AS result
1729+
FROM (SELECT LAG(i) OVER inner_window AS i_lag,
1730+
i AS i
1731+
FROM t
1732+
WINDOW inner_window AS (ORDER BY i) ) AS a
1733+
WINDOW outer_window AS (ORDER BY a.i)";
1734+
EXECUTE stmt1;
1735+
i result
1736+
100 1
1737+
101 1
1738+
EXECUTE stmt1;
1739+
i result
1740+
100 1
1741+
101 1
1742+
DROP PREPARE stmt1;
1743+
DROP TABLE t;
1744+
#
1745+
# Bug#35380604 issue with window functions in stored procedures
1746+
#
1747+
CREATE TABLE table1(id INT);
1748+
INSERT INTO table1 VALUES(1),(2),(3),(4),(5),(6);
1749+
CREATE PROCEDURE test2()
1750+
BEGIN
1751+
SELECT COUNT(*) OVER (ROWS BETWEEN 5 PRECEDING AND 5 FOLLOWING) AS a,
1752+
COUNT(*) OVER (ROWS BETWEEN 5 PRECEDING AND 5 FOLLOWING) + 1 AS "a+1",
1753+
COUNT(*) OVER (ROWS BETWEEN 5 PRECEDING AND 5 FOLLOWING) - 1 AS "a-1",
1754+
COUNT(*) OVER () AS b,
1755+
COUNT(*) OVER () + 1 AS "b+1",
1756+
COUNT(*) OVER () - 1 AS "b-1" FROM table1 ;
1757+
END $
1758+
CALL test2();
1759+
a a+1 a-1 b b+1 b-1
1760+
6 7 5 6 7 5
1761+
6 7 5 6 7 5
1762+
6 7 5 6 7 5
1763+
6 7 5 6 7 5
1764+
6 7 5 6 7 5
1765+
6 7 5 6 7 5
1766+
CALL test2();
1767+
a a+1 a-1 b b+1 b-1
1768+
6 7 5 6 7 5
1769+
6 7 5 6 7 5
1770+
6 7 5 6 7 5
1771+
6 7 5 6 7 5
1772+
6 7 5 6 7 5
1773+
6 7 5 6 7 5
1774+
DROP PROCEDURE test2;
1775+
DROP TABLE table1;

mysql-test/t/window_functions_bugs.test

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1179,3 +1179,47 @@ ORDER BY ( EXPORT_SET( c2,
11791179
SET SQL_MODE=default;
11801180

11811181
DROP TABLE t1;
1182+
1183+
--echo #
1184+
--echo # Bug#35340987 Prepared SELECT returns different results on
1185+
--echo # consecutive executions.
1186+
--echo #
1187+
CREATE TABLE t(i INT);
1188+
INSERT INTO t(i) VALUES (100), (101);
1189+
1190+
PREPARE stmt1 FROM "
1191+
SELECT a.i, (LAST_VALUE(a.i) OVER outer_window) = a.i AS result
1192+
FROM (SELECT LAG(i) OVER inner_window AS i_lag,
1193+
i AS i
1194+
FROM t
1195+
WINDOW inner_window AS (ORDER BY i) ) AS a
1196+
WINDOW outer_window AS (ORDER BY a.i)";
1197+
1198+
EXECUTE stmt1;
1199+
EXECUTE stmt1;
1200+
1201+
DROP PREPARE stmt1;
1202+
DROP TABLE t;
1203+
1204+
--echo #
1205+
--echo # Bug#35380604 issue with window functions in stored procedures
1206+
--echo #
1207+
CREATE TABLE table1(id INT);
1208+
INSERT INTO table1 VALUES(1),(2),(3),(4),(5),(6);
1209+
DELIMITER $;
1210+
CREATE PROCEDURE test2()
1211+
BEGIN
1212+
SELECT COUNT(*) OVER (ROWS BETWEEN 5 PRECEDING AND 5 FOLLOWING) AS a,
1213+
COUNT(*) OVER (ROWS BETWEEN 5 PRECEDING AND 5 FOLLOWING) + 1 AS "a+1",
1214+
COUNT(*) OVER (ROWS BETWEEN 5 PRECEDING AND 5 FOLLOWING) - 1 AS "a-1",
1215+
COUNT(*) OVER () AS b,
1216+
COUNT(*) OVER () + 1 AS "b+1",
1217+
COUNT(*) OVER () - 1 AS "b-1" FROM table1 ;
1218+
END $
1219+
DELIMITER ;$
1220+
1221+
CALL test2();
1222+
CALL test2();
1223+
1224+
DROP PROCEDURE test2;
1225+
DROP TABLE table1;

sql/sql_select.cc

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4390,6 +4390,13 @@ bool JOIN::make_tmp_tables_info() {
43904390

43914391
DBUG_TRACE;
43924392

4393+
// This is necessary to undo effects of any previous execute's call to
4394+
// CreateFramebufferTable->ReplaceMaterializedItems's calls of
4395+
// update_used_tables: loses PROP_WINDOW_FUNCTION needed here in next
4396+
// execution round
4397+
if (m_windows.elements > 0)
4398+
for (auto f : *fields) f->update_used_tables();
4399+
43934400
/*
43944401
In this function, we may change having_cond into a condition on a
43954402
temporary sort/group table, so we have to assign having_for_explain now:

0 commit comments

Comments
 (0)