Commit 6858d534 authored by Igor Babaev's avatar Igor Babaev

MDEV-17201 dropped anchor rows with non-null recursion query

The function st_select_lex_unit::exec_recursive() missed resetting of
select_limit_cnt and offset_limit_cnt before execution of union parts.
As a result recursive CTEs specified by UNIONs whose SELECTs contained
LIMIT/OFFSET could return wrong sets of records.
parent 65474d92
......@@ -3393,3 +3393,51 @@ select * from cte1, cte2 where cte1.c1 = 3;
c1 c2
drop procedure p;
drop table t1,t2;
#
# MDEV-17201: recursive part with LIMIT
#
CREATE TABLE purchases (
id int unsigned NOT NULL AUTO_INCREMENT,
pdate date NOT NULL,
quantity int unsigned NOT NULL,
p_id int unsigned NOT NULL,
PRIMARY KEY (id)
);
INSERT INTO purchases(pdate, quantity, p_id) VALUES
('2014-11-01',5 ,1),('2014-11-03', 3 ,1),
('2014-11-01',2 ,2),('2014-11-03', 4 ,2);
CREATE TABLE expired (
edate date NOT NULL,
quantity int unsigned NOT NULL,
p_id int unsigned NOT NULL,
PRIMARY KEY (edate,p_id)
);
INSERT INTO expired VALUES ('2014-11-12', 5 ,1),('2014-11-08', 1 ,2);
WITH RECURSIVE expired_map AS (
SELECT edate AS expired_date,
CAST(NULL AS date) AS purchase_date,
0 AS quantity,
e.p_id,
(SELECT MAX(id)+1 FROM purchases p
WHERE pdate <= edate AND p.p_id =p_id) AS purchase_processed,
quantity AS unresolved
FROM expired e
UNION
( SELECT expired_date,
pdate,
IF(p.quantity < m.unresolved, p.quantity, m.unresolved),
p.p_id,
p.id,
IF(p.quantity < m.unresolved, m.unresolved - p.quantity, 0)
FROM purchases p JOIN expired_map m ON p.p_id = m.p_id
WHERE p.id < m.purchase_processed AND m.unresolved > 0
ORDER BY p.id DESC
LIMIT 1
)
)
SELECT * FROM expired_map;
expired_date purchase_date quantity p_id purchase_processed unresolved
2014-11-12 NULL 0 1 5 5
2014-11-08 NULL 0 2 5 1
2014-11-08 2014-11-03 1 2 4 0
DROP TABLE purchases, expired;
......@@ -2390,3 +2390,53 @@ eval $q3;
drop procedure p;
drop table t1,t2;
--echo #
--echo # MDEV-17201: recursive part with LIMIT
--echo #
CREATE TABLE purchases (
id int unsigned NOT NULL AUTO_INCREMENT,
pdate date NOT NULL,
quantity int unsigned NOT NULL,
p_id int unsigned NOT NULL,
PRIMARY KEY (id)
);
INSERT INTO purchases(pdate, quantity, p_id) VALUES
('2014-11-01',5 ,1),('2014-11-03', 3 ,1),
('2014-11-01',2 ,2),('2014-11-03', 4 ,2);
CREATE TABLE expired (
edate date NOT NULL,
quantity int unsigned NOT NULL,
p_id int unsigned NOT NULL,
PRIMARY KEY (edate,p_id)
);
INSERT INTO expired VALUES ('2014-11-12', 5 ,1),('2014-11-08', 1 ,2);
WITH RECURSIVE expired_map AS (
SELECT edate AS expired_date,
CAST(NULL AS date) AS purchase_date,
0 AS quantity,
e.p_id,
(SELECT MAX(id)+1 FROM purchases p
WHERE pdate <= edate AND p.p_id =p_id) AS purchase_processed,
quantity AS unresolved
FROM expired e
UNION
( SELECT expired_date,
pdate,
IF(p.quantity < m.unresolved, p.quantity, m.unresolved),
p.p_id,
p.id,
IF(p.quantity < m.unresolved, m.unresolved - p.quantity, 0)
FROM purchases p JOIN expired_map m ON p.p_id = m.p_id
WHERE p.id < m.purchase_processed AND m.unresolved > 0
ORDER BY p.id DESC
LIMIT 1
)
)
SELECT * FROM expired_map;
DROP TABLE purchases, expired;
......@@ -1274,6 +1274,7 @@ bool st_select_lex_unit::exec_recursive()
for (st_select_lex *sl= start ; sl != end; sl= sl->next_select())
{
thd->lex->current_select= sl;
set_limit(sl);
sl->join->exec();
saved_error= sl->join->error;
if (!saved_error)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment