From cfb47ddde2bbbdc3065ed2b959bd4719247fbd30 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Wed, 23 Nov 2022 00:58:07 +0100 Subject: [PATCH] MDEV-30066 (limit + offset) union all (...) limit = incorrect result select_union_direct::send_data() only sends a record when the LIMIT ... OFFSET clause of the individual select won't skip it. Thus, select_union_direct::send_data() should not do any actions related to a sending a record if the offset of a select isn't reached yet --- mysql-test/main/union.result | 15 +++++++++++++++ mysql-test/main/union.test | 9 +++++++++ sql/sql_union.cc | 13 ++++++++----- 3 files changed, 32 insertions(+), 5 deletions(-) diff --git a/mysql-test/main/union.result b/mysql-test/main/union.result index bf65bbd44d1..8d9d9752e1d 100644 --- a/mysql-test/main/union.result +++ b/mysql-test/main/union.result @@ -2748,5 +2748,20 @@ a b c d 3 4 2 197 drop table t1,t2; # +# MDEV-30066 (limit + offset) union all (...) limit = incorrect result +# +create table t1(id int primary key auto_increment, c1 int); +insert into t1(c1) values(1),(2),(3); +(select * from t1 where c1>=1 order by c1 desc limit 2,1) union all (select * from t1 where c1>1 order by c1 desc); +id c1 +1 1 +2 2 +3 3 +(select * from t1 where c1>=1 order by c1 desc limit 2,1) union all (select * from t1 where c1>1 order by c1 desc) limit 2; +id c1 +1 1 +2 2 +drop table t1; +# # End of 10.3 tests # diff --git a/mysql-test/main/union.test b/mysql-test/main/union.test index eff3cfd260b..ba9ee278228 100644 --- a/mysql-test/main/union.test +++ b/mysql-test/main/union.test @@ -1982,6 +1982,15 @@ union (select 0 as a, 99 as b, drop table t1,t2; +--echo # +--echo # MDEV-30066 (limit + offset) union all (...) limit = incorrect result +--echo # +create table t1(id int primary key auto_increment, c1 int); +insert into t1(c1) values(1),(2),(3); +(select * from t1 where c1>=1 order by c1 desc limit 2,1) union all (select * from t1 where c1>1 order by c1 desc); +(select * from t1 where c1>=1 order by c1 desc limit 2,1) union all (select * from t1 where c1>1 order by c1 desc) limit 2; +drop table t1; + --echo # --echo # End of 10.3 tests --echo # diff --git a/sql/sql_union.cc b/sql/sql_union.cc index e831e2a479c..902e25d084e 100644 --- a/sql/sql_union.cc +++ b/sql/sql_union.cc @@ -551,14 +551,17 @@ int select_union_direct::send_data(List &items) { if (!limit) return false; - limit--; - if (offset) + if (!unit->offset_limit_cnt) { - offset--; - return false; + limit--; + if (offset) + { + offset--; + return false; + } + send_records++; } - send_records++; fill_record(thd, table, table->field, items, true, false); if (unlikely(thd->is_error())) return true; /* purecov: inspected */