Skip to content

fix(oracle): support NTH_VALUE FROM FIRST and LAST - #8149

Merged
georgesittas merged 1 commit into
tobymao:mainfrom
aosingh:main
Aug 13, 2026
Merged

fix(oracle): support NTH_VALUE FROM FIRST and LAST#8149
georgesittas merged 1 commit into
tobymao:mainfrom
aosingh:main

Conversation

@aosingh

@aosingh aosingh commented Aug 13, 2026

Copy link
Copy Markdown
Contributor

Summary

Fix Oracle parsing and generation of the optional FROM FIRST / FROM LAST modifier for the NTH_VALUE analytic function.

Oracle supports this syntax:

SELECT NTH_VALUE(1, 1) 
FROM FIRST OVER (ORDER BY 1) AS FIRST_VALUE
FROM DUAL

Before

SQLGlot failed to parse the statement:

File "/project/sqlglot/parser.py", line 2136, in parse
  File "/project/sqlglot/parser.py", line 2256, in _parse
  File "/project/sqlglot/parser.py", line 2223, in _parse_batch_statements
  File "/project/sqlglot/parser.py", line 2386, in _parse_statement
  File "/project/sqlglot/parser.py", line 3991, in _parse_select
  File "/project/sqlglot/parser.py", line 4116, in _parse_select_query
  File "/project/sqlglot/parser.py", line 4452, in _parse_from
  File "/project/sqlglot/parser.py", line 5080, in _parse_table
  File "/project/sqlglot/parser.py", line 4275, in _parse_table_alias
  File "/project/sqlglot/parser.py", line 9707, in _match_r_paren
  File "/project/sqlglot/parser.py", line 2093, in raise_error
sqlglot.errors.ParseError: Expecting ). Line 1, Col: 50.
  SELECT NTH_VALUE(1, 1) FROM FIRST OVER (ORDER BY 1) AS FIRST_VALUE FROM DUAL

After

The Oracle parser recognizes FROM FIRST and FROM LAST immediately after NTH_VALUE(...) and stores the modifier on the existing exp.NthValue.from_first AST argument. The Oracle generator emits the modifier before the OVER clause, preserving the Oracle syntax:

>> sqlglot.parse_one("SELECT NTH_VALUE(1, 1) FROM FIRST OVER (ORDER BY 1) AS FIRST_VALUE FROM DUAL", dialect="oracle")

Select(
  expressions=[
    Alias(
      this=Window(
        this=NthValue(
          this=Literal(this=1, is_string=False),
          offset=Literal(this=1, is_string=False),
          from_first=True),
        order=Order(
          expressions=[
            Ordered(
              this=Literal(this=1, is_string=False),
              nulls_first=False)]),
        over=OVER,
        join_mark=False),
      alias=Identifier(this=FIRST_VALUE, quoted=False))],
  from_=From(
    this=Table(
      this=Identifier(this=DUAL, quoted=False))))

Tests

  python -m unittest tests.dialects.test_oracle
  make test
  make testc

All passed.

@georgesittas
georgesittas merged commit 99b3308 into tobymao:main Aug 13, 2026
8 checks 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