From b514dbe37920a8ac73db7205c78c691ffb3cf030 Mon Sep 17 00:00:00 2001 From: Abhishek Singh Date: Wed, 12 Aug 2026 22:02:06 -0700 Subject: [PATCH] support nth_value analytic function for oracle --- sqlglot/generators/oracle.py | 8 +++++++- sqlglot/parsers/oracle.py | 8 ++++++++ tests/dialects/test_oracle.py | 6 ++++++ 3 files changed, 21 insertions(+), 1 deletion(-) diff --git a/sqlglot/generators/oracle.py b/sqlglot/generators/oracle.py index 53fdf0ecf6..2134db1228 100644 --- a/sqlglot/generators/oracle.py +++ b/sqlglot/generators/oracle.py @@ -1,6 +1,5 @@ from __future__ import annotations - from sqlglot import exp, generator, transforms from sqlglot.dialects.dialect import ( groupconcat_sql, @@ -111,6 +110,13 @@ class OracleGenerator(generator.Generator): exp.VolatileProperty: exp.Properties.Location.UNSUPPORTED, } + def nthvalue_sql(self, expression: exp.NthValue) -> str: + result = self.func("NTH_VALUE", expression.this, expression.args.get("offset")) + from_first = expression.args.get("from_first") + if from_first is not None: + result = result + (" FROM FIRST" if from_first else " FROM LAST") + return result + def currenttimestamp_sql(self, expression: exp.CurrentTimestamp) -> str: if expression.args.get("sysdate"): return "SYSDATE" diff --git a/sqlglot/parsers/oracle.py b/sqlglot/parsers/oracle.py index f7b9769ef7..fe98b4a4d8 100644 --- a/sqlglot/parsers/oracle.py +++ b/sqlglot/parsers/oracle.py @@ -61,6 +61,14 @@ class OracleParser(parser.Parser): "TO_NUMBER": lambda self: self._parse_to_number(), } + def _parse_window(self, this: exp.Expr | None, alias: bool = False) -> exp.Expr | None: + if isinstance(this, exp.NthValue): + if self._match_text_seq("FROM", "FIRST"): + this.set("from_first", True) + elif self._match_text_seq("FROM", "LAST"): + this.set("from_first", False) + return super()._parse_window(this, alias) + PROPERTY_PARSERS = { **parser.Parser.PROPERTY_PARSERS, "GLOBAL": lambda self: ( diff --git a/tests/dialects/test_oracle.py b/tests/dialects/test_oracle.py index 3da291d526..ac407635ae 100644 --- a/tests/dialects/test_oracle.py +++ b/tests/dialects/test_oracle.py @@ -8,6 +8,12 @@ class TestOracle(Validator): def test_oracle(self): self.validate_identity("1 /* /* */", "1 /* / * */") + self.validate_identity( + "SELECT NTH_VALUE(1, 1) FROM FIRST OVER (ORDER BY 1) AS FIRST_VALUE FROM DUAL" + ) + self.validate_identity( + "SELECT NTH_VALUE(1, 1) FROM LAST OVER (ORDER BY 1) AS LAST_VALUE FROM DUAL" + ) self.validate_all( "SELECT CONNECT_BY_ROOT x y", write={