Skip to content

Commit

Permalink
Feat(tsql, oracle): add support for NEXT VALUE FOR clause (#1521)
Browse files Browse the repository at this point in the history
  • Loading branch information
georgesittas authored May 2, 2023
1 parent c3db2b8 commit 20cacba
Show file tree
Hide file tree
Showing 5 changed files with 21 additions and 1 deletion.
6 changes: 6 additions & 0 deletions sqlglot/expressions.py
Original file line number Diff line number Diff line change
Expand Up @@ -4075,6 +4075,12 @@ class When(Func):
arg_types = {"matched": True, "source": False, "condition": False, "then": True}


# https://docs.oracle.com/javadb/10.8.3.0/ref/rrefsqljnextvaluefor.html
# https://learn.microsoft.com/en-us/sql/t-sql/functions/next-value-for-transact-sql?view=sql-server-ver16
class NextValueFor(Func):
arg_types = {"this": True, "order": False}


def _norm_arg(arg):
return arg.lower() if type(arg) is str else arg

Expand Down
5 changes: 5 additions & 0 deletions sqlglot/generator.py
Original file line number Diff line number Diff line change
Expand Up @@ -1629,6 +1629,11 @@ def constraint_sql(self, expression: exp.Constraint) -> str:
expressions = self.expressions(expression, flat=True)
return f"CONSTRAINT {this} {expressions}"

def nextvaluefor_sql(self, expression: exp.NextValueFor) -> str:
order = expression.args.get("order")
order = f" OVER ({self.order_sql(order, flat=True)})" if order else ""
return f"NEXT VALUE FOR {self.sql(expression, 'this')}{order}"

def extract_sql(self, expression: exp.Extract) -> str:
this = self.sql(expression, "this")
expression_sql = self.sql(expression, "expression")
Expand Down
7 changes: 6 additions & 1 deletion sqlglot/parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -685,9 +685,14 @@ class Parser(metaclass=_Parser):
SCHEMA_UNNAMED_CONSTRAINTS = {"CHECK", "FOREIGN KEY", "LIKE", "PRIMARY KEY", "UNIQUE"}

NO_PAREN_FUNCTION_PARSERS = {
TokenType.ANY: lambda self: self.expression(exp.Any, this=self._parse_bitwise()),
TokenType.CASE: lambda self: self._parse_case(),
TokenType.IF: lambda self: self._parse_if(),
TokenType.ANY: lambda self: self.expression(exp.Any, this=self._parse_bitwise()),
TokenType.NEXT_VALUE_FOR: lambda self: self.expression(
exp.NextValueFor,
this=self._parse_column(),
order=self._match(TokenType.OVER) and self._parse_wrapped(self._parse_order),
),
}

FUNCTION_PARSERS: t.Dict[str, t.Callable] = {
Expand Down
2 changes: 2 additions & 0 deletions sqlglot/tokens.py
Original file line number Diff line number Diff line change
Expand Up @@ -232,6 +232,7 @@ class TokenType(AutoName):
MOD = auto()
NATURAL = auto()
NEXT = auto()
NEXT_VALUE_FOR = auto()
NO_ACTION = auto()
NOTNULL = auto()
NULL = auto()
Expand Down Expand Up @@ -573,6 +574,7 @@ class Tokenizer(metaclass=_Tokenizer):
"MERGE": TokenType.MERGE,
"NATURAL": TokenType.NATURAL,
"NEXT": TokenType.NEXT,
"NEXT VALUE FOR": TokenType.NEXT_VALUE_FOR,
"NO ACTION": TokenType.NO_ACTION,
"NOT": TokenType.NOT,
"NOTNULL": TokenType.NOTNULL,
Expand Down
2 changes: 2 additions & 0 deletions tests/fixtures/identity.sql
Original file line number Diff line number Diff line change
Expand Up @@ -818,3 +818,5 @@ JSON_OBJECT('x': NULL, 'y': 1 ABSENT ON NULL WITH UNIQUE KEYS)
JSON_OBJECT('x': 1 RETURNING VARCHAR(100))
JSON_OBJECT('x': 1 RETURNING VARBINARY FORMAT JSON ENCODING UTF8)
SELECT if.x
SELECT NEXT VALUE FOR db.schema.sequence_name
SELECT NEXT VALUE FOR db.schema.sequence_name OVER (ORDER BY foo), col

0 comments on commit 20cacba

Please sign in to comment.