Skip to content

Commit 170206e

Browse files
committed
Error out if SKIP LOCKED and WITH TIES are both specified
Both bugs #16676[1] and #17141[2] illustrate that the combination of SKIP LOCKED and FETCH FIRST WITH TIES break expectations when it comes to rows returned to other sessions accessing the same row. Since this situation is detectable from the syntax and hard to fix otherwise, forbid for now, with the potential to fix in the future. [1] https://postgr.es/m/16676-fd62c3c835880da6@postgresql.org [2] https://postgr.es/m/17141-913d78b9675aac8e@postgresql.org Backpatch-through: 13, where WITH TIES was introduced Author: David Christensen <david.christensen@crunchydata.com> Discussion: https://postgr.es/m/CAOxo6XLPccCKru3xPMaYDpa+AXyPeWFs+SskrrL+HKwDjJnLhg@mail.gmail.com
1 parent 7adbe18 commit 170206e

File tree

5 files changed

+29
-2
lines changed

5 files changed

+29
-2
lines changed

doc/src/sgml/ref/select.sgml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1454,7 +1454,8 @@ FETCH { FIRST | NEXT } [ <replaceable class="parameter">count</replaceable> ] {
14541454
The <literal>WITH TIES</literal> option is used to return any additional
14551455
rows that tie for the last place in the result set according to
14561456
the <literal>ORDER BY</literal> clause; <literal>ORDER BY</literal>
1457-
is mandatory in this case.
1457+
is mandatory in this case, and <literal>SKIP LOCKED</literal> is
1458+
not allowed.
14581459
<literal>ROW</literal> and <literal>ROWS</literal> as well as
14591460
<literal>FIRST</literal> and <literal>NEXT</literal> are noise
14601461
words that don't influence the effects of these clauses.

src/backend/commands/matview.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -185,7 +185,8 @@ ExecRefreshMatView(RefreshMatViewStmt *stmt, const char *queryString,
185185
if (concurrent && stmt->skipData)
186186
ereport(ERROR,
187187
(errcode(ERRCODE_SYNTAX_ERROR),
188-
errmsg("CONCURRENTLY and WITH NO DATA options cannot be used together")));
188+
errmsg("%s and %s options cannot be used together",
189+
"CONCURRENTLY", "WITH NO DATA")));
189190

190191
/*
191192
* Check that everything is correct for a refresh. Problems at this point

src/backend/parser/gram.y

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16163,6 +16163,21 @@ insertSelectOptions(SelectStmt *stmt,
1616316163
ereport(ERROR,
1616416164
(errcode(ERRCODE_SYNTAX_ERROR),
1616516165
errmsg("WITH TIES cannot be specified without ORDER BY clause")));
16166+
if (limitClause->limitOption == LIMIT_OPTION_WITH_TIES && stmt->lockingClause)
16167+
{
16168+
ListCell *lc;
16169+
16170+
foreach(lc, stmt->lockingClause)
16171+
{
16172+
LockingClause *lock = lfirst_node(LockingClause, lc);
16173+
16174+
if (lock->waitPolicy == LockWaitSkip)
16175+
ereport(ERROR,
16176+
(errcode(ERRCODE_SYNTAX_ERROR),
16177+
errmsg("%s and %s options cannot be used together",
16178+
"SKIP LOCKED", "WITH TIES")));
16179+
}
16180+
}
1616616181
stmt->limitOption = limitClause->limitOption;
1616716182
}
1616816183
if (withClause)

src/test/regress/expected/limit.out

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -619,6 +619,11 @@ SELECT thousand
619619
0
620620
(2 rows)
621621

622+
-- SKIP LOCKED and WITH TIES are incompatible
623+
SELECT thousand
624+
FROM onek WHERE thousand < 5
625+
ORDER BY thousand FETCH FIRST 1 ROW WITH TIES FOR UPDATE SKIP LOCKED;
626+
ERROR: SKIP LOCKED and WITH TIES options cannot be used together
622627
-- should fail
623628
SELECT ''::text AS two, unique1, unique2, stringu1
624629
FROM onek WHERE unique1 > 50

src/test/regress/sql/limit.sql

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -173,6 +173,11 @@ SELECT thousand
173173
FROM onek WHERE thousand < 5
174174
ORDER BY thousand FETCH FIRST 2 ROW ONLY;
175175

176+
-- SKIP LOCKED and WITH TIES are incompatible
177+
SELECT thousand
178+
FROM onek WHERE thousand < 5
179+
ORDER BY thousand FETCH FIRST 1 ROW WITH TIES FOR UPDATE SKIP LOCKED;
180+
176181
-- should fail
177182
SELECT ''::text AS two, unique1, unique2, stringu1
178183
FROM onek WHERE unique1 > 50

0 commit comments

Comments
 (0)