summaryrefslogtreecommitdiffstats
path: root/sqlglot/dialects/bigquery.py
diff options
context:
space:
mode:
Diffstat (limited to 'sqlglot/dialects/bigquery.py')
-rw-r--r--sqlglot/dialects/bigquery.py36
1 files changed, 29 insertions, 7 deletions
diff --git a/sqlglot/dialects/bigquery.py b/sqlglot/dialects/bigquery.py
index c9d6c79..82162b4 100644
--- a/sqlglot/dialects/bigquery.py
+++ b/sqlglot/dialects/bigquery.py
@@ -163,6 +163,17 @@ def _pushdown_cte_column_names(expression: exp.Expression) -> exp.Expression:
return expression
+def _parse_timestamp(args: t.List) -> exp.StrToTime:
+ this = format_time_lambda(exp.StrToTime, "bigquery")([seq_get(args, 1), seq_get(args, 0)])
+ this.set("zone", seq_get(args, 2))
+ return this
+
+
+def _parse_date(args: t.List) -> exp.Date | exp.DateFromParts:
+ expr_type = exp.DateFromParts if len(args) == 3 else exp.Date
+ return expr_type.from_arg_list(args)
+
+
class BigQuery(Dialect):
UNNEST_COLUMN_ONLY = True
@@ -203,8 +214,10 @@ class BigQuery(Dialect):
while isinstance(parent, exp.Dot):
parent = parent.parent
- if not (isinstance(parent, exp.Table) and parent.db) and not expression.meta.get(
- "is_table"
+ if (
+ not isinstance(parent, exp.UserDefinedFunction)
+ and not (isinstance(parent, exp.Table) and parent.db)
+ and not expression.meta.get("is_table")
):
expression.set("this", expression.this.lower())
@@ -251,6 +264,7 @@ class BigQuery(Dialect):
FUNCTIONS = {
**parser.Parser.FUNCTIONS,
+ "DATE": _parse_date,
"DATE_ADD": parse_date_delta_with_interval(exp.DateAdd),
"DATE_SUB": parse_date_delta_with_interval(exp.DateSub),
"DATE_TRUNC": lambda args: exp.DateTrunc(
@@ -264,9 +278,7 @@ class BigQuery(Dialect):
"PARSE_DATE": lambda args: format_time_lambda(exp.StrToDate, "bigquery")(
[seq_get(args, 1), seq_get(args, 0)]
),
- "PARSE_TIMESTAMP": lambda args: format_time_lambda(exp.StrToTime, "bigquery")(
- [seq_get(args, 1), seq_get(args, 0)]
- ),
+ "PARSE_TIMESTAMP": _parse_timestamp,
"REGEXP_CONTAINS": exp.RegexpLike.from_arg_list,
"REGEXP_EXTRACT": lambda args: exp.RegexpExtract(
this=seq_get(args, 0),
@@ -356,9 +368,11 @@ class BigQuery(Dialect):
EXPLICIT_UNION = True
INTERVAL_ALLOWS_PLURAL_FORM = False
JOIN_HINTS = False
+ QUERY_HINTS = False
TABLE_HINTS = False
LIMIT_FETCH = "LIMIT"
RENAME_TABLE_WITH_DB = False
+ ESCAPE_LINE_BREAK = True
TRANSFORMS = {
**generator.Generator.TRANSFORMS,
@@ -367,6 +381,7 @@ class BigQuery(Dialect):
exp.Cast: transforms.preprocess([transforms.remove_precision_parameterized_types]),
exp.CTE: transforms.preprocess([_pushdown_cte_column_names]),
exp.DateAdd: _date_add_sql("DATE", "ADD"),
+ exp.DateFromParts: rename_func("DATE"),
exp.DateSub: _date_add_sql("DATE", "SUB"),
exp.DatetimeAdd: _date_add_sql("DATETIME", "ADD"),
exp.DatetimeSub: _date_add_sql("DATETIME", "SUB"),
@@ -397,7 +412,9 @@ class BigQuery(Dialect):
]
),
exp.StrToDate: lambda self, e: f"PARSE_DATE({self.format_time(e)}, {self.sql(e, 'this')})",
- exp.StrToTime: lambda self, e: f"PARSE_TIMESTAMP({self.format_time(e)}, {self.sql(e, 'this')})",
+ exp.StrToTime: lambda self, e: self.func(
+ "PARSE_TIMESTAMP", self.format_time(e), e.this, e.args.get("zone")
+ ),
exp.TimeAdd: _date_add_sql("TIME", "ADD"),
exp.TimeSub: _date_add_sql("TIME", "SUB"),
exp.TimestampAdd: _date_add_sql("TIMESTAMP", "ADD"),
@@ -548,10 +565,15 @@ class BigQuery(Dialect):
}
def attimezone_sql(self, expression: exp.AtTimeZone) -> str:
- if not isinstance(expression.parent, exp.Cast):
+ parent = expression.parent
+
+ # BigQuery allows CAST(.. AS {STRING|TIMESTAMP} [FORMAT <fmt> [AT TIME ZONE <tz>]]).
+ # Only the TIMESTAMP one should use the below conversion, when AT TIME ZONE is included.
+ if not isinstance(parent, exp.Cast) or not parent.to.is_type("text"):
return self.func(
"TIMESTAMP", self.func("DATETIME", expression.this, expression.args.get("zone"))
)
+
return super().attimezone_sql(expression)
def trycast_sql(self, expression: exp.TryCast) -> str: