Skip to content

fix: parse PostgreSQL SELECT with more than one locking clause - #2927

Merged
manticore-projects merged 1 commit into
JSQLParser:masterfrom
DylanMerigaud:fix/2926-multiple-locking-clauses
Nov 14, 2026
Merged

manticore-projects merged 1 commit into
JSQLParser:masterfrom
DylanMerigaud:fix/2926-multiple-locking-clauses

Conversation

@DylanMerigaud

Copy link
Copy Markdown
Contributor

Fixes #2926.

PostgreSQL accepts several locking clauses in one SELECT, so each table can get its own lock strength, for example FOR UPDATE OF t FOR SHARE OF u. PlainSelect() read one FOR ... clause, so the issue's query stopped at the second FOR.

What changes:

  • New production AdditionalForUpdateClause(). After the first locking clause, PlainSelect() now reads any number of further clauses, each one FOR UPDATE, FOR SHARE, FOR NO KEY UPDATE or FOR KEY SHARE, with an optional OF table list, WAIT n, NOWAIT or SKIP LOCKED. Each becomes a ForUpdateClause. FOR READ ONLY and FOR FETCH ONLY are not accepted as a second clause.
  • Select gets getAdditionalForUpdateClauses(), setAdditionalForUpdateClauses() and addAdditionalForUpdateClause(). The first clause stays where it was: getForMode(), getForUpdateTables(), getWait(), isNoWait(), isSkipLocked() and getForUpdate() still describe only the first one, and the new list is null when there is a single clause, so a query that parsed before builds the same object.
  • Select.appendTo() and SelectDeParser print the additional clauses right after the first one.
  • SelectValidator checks the mode, the OF tables, WAIT, NOWAIT and SKIP LOCKED of each additional clause with the same features it uses for the first one.

Tests:

  • ForUpdateTest.testPostgresMultipleLockingClausesIssue2926: the issue's query parses and round trips; the first clause is UPDATE OF t, the additional one is SHARE OF u.
  • ForUpdateTest.testPostgresMultipleLockingClausesWithOptions: four clauses mixing the four modes, an OF list of two tables, a clause without OF, NOWAIT and SKIP LOCKED.
  • ForUpdateTest.testSingleLockingClauseHasNoAdditionalClauses: one clause leaves the list null.
  • SelectValidatorTest.testValidationMultipleLockingClauses: the issue's form validates for PostgreSQL, and a second FOR NO KEY UPDATE is reported as selectForNoKeyUpdate for Oracle.

PostgreSQL accepts several locking clauses in one SELECT, such as
FOR UPDATE OF t FOR SHARE OF u. After the first clause, PlainSelect now
reads further FOR UPDATE, FOR SHARE, FOR NO KEY UPDATE and FOR KEY SHARE
clauses, each with its optional OF list, WAIT, NOWAIT or SKIP LOCKED,
into Select.getAdditionalForUpdateClauses(). The first clause keeps its
existing getters. toString, the deparser and the validator handle the
additional clauses.

Fixes JSQLParser#2926

Signed-off-by: Dylan Merigaud <dylanmerigaud@gmail.com>
@manticore-projects
manticore-projects merged commit f925239 into JSQLParser:master Nov 14, 2026
10 checks passed
@manticore-projects

Copy link
Copy Markdown
Contributor

Thank you!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[BUG] JSQLParser : PostgreSQL : Multiple locking clauses (FOR UPDATE OF ... FOR SHARE OF ...) fail to parse

2 participants