diff options
Diffstat (limited to 'sqlglot/dialects/duckdb.py')
-rw-r--r-- | sqlglot/dialects/duckdb.py | 23 |
1 files changed, 18 insertions, 5 deletions
diff --git a/sqlglot/dialects/duckdb.py b/sqlglot/dialects/duckdb.py index 219b1aa..5428e86 100644 --- a/sqlglot/dialects/duckdb.py +++ b/sqlglot/dialects/duckdb.py @@ -11,6 +11,7 @@ from sqlglot.dialects.dialect import ( binary_from_function, date_trunc_to_time, datestrtodate_sql, + encode_decode_sql, format_time_lambda, no_comment_column_constraint_sql, no_properties_sql, @@ -32,14 +33,14 @@ from sqlglot.tokens import TokenType def _ts_or_ds_add_sql(self: generator.Generator, expression: exp.TsOrDsAdd) -> str: this = self.sql(expression, "this") unit = self.sql(expression, "unit").strip("'") or "DAY" - return f"CAST({this} AS DATE) + {self.sql(exp.Interval(this=expression.expression, unit=unit))}" + return f"CAST({this} AS DATE) + {self.sql(exp.Interval(this=expression.expression.copy(), unit=unit))}" def _date_delta_sql(self: generator.Generator, expression: exp.DateAdd | exp.DateSub) -> str: this = self.sql(expression, "this") unit = self.sql(expression, "unit").strip("'") or "DAY" op = "+" if isinstance(expression, exp.DateAdd) else "-" - return f"{this} {op} {self.sql(exp.Interval(this=expression.expression, unit=unit))}" + return f"{this} {op} {self.sql(exp.Interval(this=expression.expression.copy(), unit=unit))}" # BigQuery -> DuckDB conversion for the DATE function @@ -167,6 +168,16 @@ class DuckDB(Dialect): "XOR": binary_from_function(exp.BitwiseXor), } + FUNCTION_PARSERS = { + **parser.Parser.FUNCTION_PARSERS, + "DECODE": lambda self: self.expression( + exp.Decode, this=self._parse_conjunction(), charset=exp.Literal.string("utf-8") + ), + "ENCODE": lambda self: self.expression( + exp.Encode, this=self._parse_conjunction(), charset=exp.Literal.string("utf-8") + ), + } + TYPE_TOKENS = { *parser.Parser.TYPE_TOKENS, TokenType.UBIGINT, @@ -215,7 +226,9 @@ class DuckDB(Dialect): ), exp.DateStrToDate: datestrtodate_sql, exp.DateToDi: lambda self, e: f"CAST(STRFTIME({self.sql(e, 'this')}, {DuckDB.DATEINT_FORMAT}) AS INT)", + exp.Decode: lambda self, e: encode_decode_sql(self, e, "DECODE", replace=False), exp.DiToDate: lambda self, e: f"CAST(STRPTIME(CAST({self.sql(e, 'this')} AS TEXT), {DuckDB.DATEINT_FORMAT}) AS DATE)", + exp.Encode: lambda self, e: encode_decode_sql(self, e, "ENCODE", replace=False), exp.Explode: rename_func("UNNEST"), exp.IntDiv: lambda self, e: self.binary(e, "//"), exp.JSONExtract: arrow_json_extract_sql, @@ -228,8 +241,8 @@ class DuckDB(Dialect): exp.MonthsBetween: lambda self, e: self.func( "DATEDIFF", "'month'", - exp.cast(e.expression, "timestamp"), - exp.cast(e.this, "timestamp"), + exp.cast(e.expression, "timestamp", copy=True), + exp.cast(e.this, "timestamp", copy=True), ), exp.Properties: no_properties_sql, exp.RegexpExtract: regexp_extract_sql, @@ -290,7 +303,7 @@ class DuckDB(Dialect): multiplier = 90 if multiplier: - return f"({multiplier} * {super().interval_sql(exp.Interval(this=expression.this, unit=exp.var('day')))})" + return f"({multiplier} * {super().interval_sql(exp.Interval(this=expression.this.copy(), unit=exp.var('day')))})" return super().interval_sql(expression) |