diff options
Diffstat (limited to 'sqlglot/dialects/bigquery.py')
-rw-r--r-- | sqlglot/dialects/bigquery.py | 36 |
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: |