summaryrefslogtreecommitdiffstats
path: root/sqlglot/dialects/duckdb.py
diff options
context:
space:
mode:
Diffstat (limited to 'sqlglot/dialects/duckdb.py')
-rw-r--r--sqlglot/dialects/duckdb.py23
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)