Postgres: parse LIMIT after the row-locking clause#2391
Open
truffle-dev wants to merge 2 commits into
Open
Conversation
PostgreSQL accepts LIMIT/OFFSET both before and after the row-locking clause (FOR UPDATE/FOR SHARE/...), but the parser only consumed LIMIT before the lock loop, so a query like SELECT * FROM t ORDER BY id FOR UPDATE SKIP LOCKED LIMIT 5 failed with "Expected: end of statement, found: LIMIT". Add a supports_limit_after_locking_clause dialect method (off by default, on for Postgres) and parse a trailing LIMIT clause after the locks when no leading one was present.
iffyio
reviewed
Jul 1, 2026
|
|
||
| // PostgreSQL accepts `LIMIT`/`OFFSET` after the row-locking clause | ||
| // (e.g. `... FOR UPDATE SKIP LOCKED LIMIT 5`) as well as before it. | ||
| if limit_clause.is_none() && self.dialect.supports_limit_after_locking_clause() { |
Contributor
There was a problem hiding this comment.
Suggested change
| if limit_clause.is_none() && self.dialect.supports_limit_after_locking_clause() { | |
| if limit_clause.is_none() { |
I think we can skip the dialect flag entirely here, since the FOR UPDATE isn't dialect guarded either?
Author
There was a problem hiding this comment.
Agreed - the lock loop above isn't dialect-guarded, so gating only the trailing limit was inconsistent. Dropped supports_limit_after_locking_clause and its Postgres override and made the condition just limit_clause.is_none(). Full suite (all dialect test files + doctests) and clippy are green. c1c4b70
The row-locking clause (FOR UPDATE/FOR SHARE/...) just above is parsed for every dialect, so gating only the trailing LIMIT/OFFSET behind a dialect flag was inconsistent. Parse it unconditionally instead and remove supports_limit_after_locking_clause.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
PostgreSQL accepts
LIMIT/OFFSETboth before and after the row-locking clause, but the parser only consumedLIMITbefore the lock loop, so:failed with
Expected: end of statement, found: LIMIT.This adds a
supports_limit_after_locking_clausedialect method (off by default, enabled for Postgres) and parses a trailingLIMITclause after the locks when no leading one was present. The AST renders the limit in its canonical position, so the input round-trips to... LIMIT 5 FOR UPDATE SKIP LOCKED.Fixes #2194.