Skip to content

Commit

Permalink
feat(bigquery): Support MAKE_INTERVAL
Browse files Browse the repository at this point in the history
  • Loading branch information
VaggelisD committed Nov 13, 2024
1 parent 858c5b1 commit d8549ae
Show file tree
Hide file tree
Showing 6 changed files with 55 additions and 0 deletions.
21 changes: 21 additions & 0 deletions sqlglot/dialects/bigquery.py
Original file line number Diff line number Diff line change
Expand Up @@ -516,6 +516,7 @@ class Parser(parser.Parser):
FUNCTION_PARSERS = {
**parser.Parser.FUNCTION_PARSERS,
"ARRAY": lambda self: self.expression(exp.Array, expressions=[self._parse_statement()]),
"MAKE_INTERVAL": lambda self: self._parse_make_interval(),
}
FUNCTION_PARSERS.pop("TRIM")

Expand Down Expand Up @@ -746,6 +747,26 @@ def _parse_unnest(self, with_alias: bool = True) -> t.Optional[exp.Unnest]:

return unnest

def _parse_make_interval(self):
expr = exp.MakeInterval()

for arg_key in expr.arg_types:
value = self._parse_lambda()

if not value:
break

# Non-named arguments are filled sequentially, (optionally) followed by named arguments
# that can appear in any order e.g MAKE_INTERVAL(1, minute => 5, day => 2)
if isinstance(value, exp.Kwarg):
arg_key = value.this.name

expr.set(arg_key, value)

self._match(TokenType.COMMA)

return expr

class Generator(generator.Generator):
INTERVAL_ALLOWS_PLURAL_FORM = False
JOIN_HINTS = False
Expand Down
11 changes: 11 additions & 0 deletions sqlglot/dialects/dialect.py
Original file line number Diff line number Diff line change
Expand Up @@ -1724,3 +1724,14 @@ def explode_to_unnest_sql(self: Generator, expression: exp.Lateral) -> str:

def timestampdiff_sql(self: Generator, expression: exp.DatetimeDiff | exp.TimestampDiff) -> str:
return self.func("TIMESTAMPDIFF", expression.unit, expression.expression, expression.this)


def no_make_interval_sql(self: Generator, expression: exp.MakeInterval, sep: str = ", ") -> str:
args = []
for unit, value in expression.args.items():
if isinstance(value, exp.Kwarg):
value = value.expression

args.append(f"{value} {unit}")

return f"INTERVAL '{self.format_args(*args, sep=sep)}'"
2 changes: 2 additions & 0 deletions sqlglot/dialects/duckdb.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
sha256_sql,
build_regexp_extract,
explode_to_unnest_sql,
no_make_interval_sql,
)
from sqlglot.generator import unsupported_args
from sqlglot.helper import seq_get
Expand Down Expand Up @@ -558,6 +559,7 @@ class Generator(generator.Generator):
exp.Lateral: explode_to_unnest_sql,
exp.LogicalOr: rename_func("BOOL_OR"),
exp.LogicalAnd: rename_func("BOOL_AND"),
exp.MakeInterval: lambda self, e: no_make_interval_sql(self, e, sep=" "),
exp.MD5Digest: lambda self, e: self.func("UNHEX", self.func("MD5", e.this)),
exp.MonthsBetween: lambda self, e: self.func(
"DATEDIFF",
Expand Down
2 changes: 2 additions & 0 deletions sqlglot/dialects/snowflake.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
no_safe_divide_sql,
no_timestamp_sql,
timestampdiff_sql,
no_make_interval_sql,
)
from sqlglot.generator import unsupported_args
from sqlglot.helper import flatten, is_float, is_int, seq_get
Expand Down Expand Up @@ -866,6 +867,7 @@ class Generator(generator.Generator):
exp.LogicalAnd: rename_func("BOOLAND_AGG"),
exp.LogicalOr: rename_func("BOOLOR_AGG"),
exp.Map: lambda self, e: var_map_sql(self, e, "OBJECT_CONSTRUCT"),
exp.MakeInterval: no_make_interval_sql,
exp.Max: max_or_greatest,
exp.Min: min_or_least,
exp.ParseJSON: lambda self, e: self.func(
Expand Down
11 changes: 11 additions & 0 deletions sqlglot/expressions.py
Original file line number Diff line number Diff line change
Expand Up @@ -5589,6 +5589,17 @@ class MonthsBetween(Func):
arg_types = {"this": True, "expression": True, "roundoff": False}


class MakeInterval(Func):
arg_types = {
"year": False,
"month": False,
"day": False,
"hour": False,
"minute": False,
"second": False,
}


class LastDay(Func, TimeUnit):
_sql_names = ["LAST_DAY", "LAST_DAY_OF_MONTH"]
arg_types = {"this": True, "unit": False}
Expand Down
8 changes: 8 additions & 0 deletions tests/dialects/test_bigquery.py
Original file line number Diff line number Diff line change
Expand Up @@ -1619,6 +1619,14 @@ def test_bigquery(self):
"snowflake": "SELECT POSITION('@', 'foo@example.com')",
},
)
self.validate_all(
"SELECT ts + MAKE_INTERVAL(1, 2, minute => 5, day => 3)",
write={
"bigquery": "SELECT ts + MAKE_INTERVAL(1, 2, day => 3, minute => 5)",
"duckdb": "SELECT ts + INTERVAL '1 year 2 month 5 minute 3 day'",
"snowflake": "SELECT ts + INTERVAL '1 year, 2 month, 5 minute, 3 day'",
},
)

def test_errors(self):
with self.assertRaises(TokenError):
Expand Down

0 comments on commit d8549ae

Please sign in to comment.