Skip to content

Support ADQL-2.1 OFFSET clause (Postgres and Oracle) - #268

Merged
pdowler merged 2 commits into
opencadc:mainfrom
jesusjuansalgado:adql21-offset-clause
Oct 8, 2026
Merged

pdowler merged 2 commits into
opencadc:mainfrom
jesusjuansalgado:adql21-offset-clause

Conversation

@jesusjuansalgado

Copy link
Copy Markdown
Contributor

Summary

  • AdqlQuery rejected any query containing a bare OFFSET clause as invalid ADQL keyword: LIMIT, because a Limit AST node carrying only an offset was indistinguishable from one carrying a real LIMIT/TOP-derived row count (both defaulted rowCount to 0).
  • Fixing only that check would have been incomplete: QuerySelectDeParser separately treated rowCount == 0 as a signal for an explicit TOP 0, which would have silently collapsed an offset-only query into LIMIT 0 — returning zero rows instead of skipping the requested number, with no error raised.
  • Added an explicit rowCountSet flag to Limit (cadc-jsqlparser-compat) so "no row cap was ever established" is distinguishable from "a row cap of exactly 0 was established", and used it in both the validator and the deparser.
  • OracleQuerySelectDeParser inherited the fixed base deparseLimit, which would have emitted the bare OFFSET n form Postgres/MySQL accept — invalid for Oracle, which requires the ANSI OFFSET n ROWS form. Gave it its own override.

Test plan

  • cadc-adql unit tests: bare OFFSET, OFFSET without ORDER BY, TOP n ... OFFSET m combined, and the MySQL-style LIMIT offset,row_count form still correctly rejected (uses the LIMIT keyword).
  • cadc-tap-server-oracle unit tests: offset-only emits OFFSET n ROWS; TOP n ... OFFSET m combined still correctly wraps in the ROWNUM subselect with the offset preserved inside it.
  • Full existing test suites for cadc-adql and cadc-tap-server-oracle pass (the 7 pre-existing failures in TapSchemaReadAccessConverterTest reproduce identically against unmodified main, confirmed by running the same suite without this change).
  • End-to-end check against a real local PostgreSQL instance: generated SQL for TOP, bare OFFSET, TOP+OFFSET combined, and OFFSET past the end of the result set were executed directly, and all returned the correct rows.

🤖 Generated with Claude Code

jesusjuansalgado and others added 2 commits September 29, 2026 12:15
AdqlQuery rejected any query with a bare OFFSET clause as an "invalid
ADQL keyword: LIMIT", since a Limit AST node with no LIMIT keyword
looked identical to one with rowCount defaulted to 0. Fixing just that
check would have been incomplete: QuerySelectDeParser separately used
rowCount == 0 as a proxy for an explicit "TOP 0", which would have
collapsed an offset-only query to "LIMIT 0" -- silently returning zero
rows instead of skipping the requested number.

Add an explicit rowCountSet flag to Limit so "no row cap was ever
given" is distinguishable from "TOP 0 was given", and use it in both
places. Also give OracleQuerySelectDeParser its own deparseLimit
override, since Oracle needs ANSI "OFFSET n ROWS" rather than the bare
"OFFSET n" Postgres/MySQL accept.

Verified against a real PostgreSQL instance: TOP, bare OFFSET, TOP+OFFSET
combined, and OFFSET past the end of the result set all return the
correct rows, while a literal LIMIT keyword is still rejected.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…oracle

Each module in this repo is released independently and consumed by
downstream modules via a Maven version-range coordinate, not a local
project reference. CI installs each module to the runner's local Maven
repo in sequence, but when a changed module keeps its old version
number, Gradle's range resolution treats that version as available in
both mavenCentral() and mavenLocal() and prefers mavenCentral() (listed
first), silently ignoring the freshly-built local artifact. That's what
broke the previous commit's CI run: cadc-adql compiled against the old,
unpatched cadc-jsqlparser-compat:0.6.6 from Maven Central instead of the
locally-installed one with isRowCountSet().

Bumping the version of every module whose code changed here removes the
ambiguity, verified against a clean-cache simulation of the CI sequence.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@jesusjuansalgado

jesusjuansalgado commented Sep 30, 2026 •

Copy link
Copy Markdown
Contributor Author

I have tried to correct the pipeline error (although I am not very familiar, and I am not sure how to trigger it again) (only allowed to be triggered by maintainers, I think). Please feel free to amend anything that is not aligned with your pipeline or code standards

@pdowler

pdowler commented Oct 1, 2026 •

Copy link
Copy Markdown
Member

I think pipeline has to run successfully once and then once I merge this then pipeline will trigger automatically in future.

I think the versions bumps were the correct fix because mavenCentral is higher priority than mavenLocal.

@pdowler
pdowler merged commit c68f019 into opencadc:main Oct 8, 2026
1 check passed
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.

2 participants