summaryrefslogtreecommitdiffstats
path: root/sqlglot/dialects/duckdb.py
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-08 08:11:53 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-08 08:12:02 +0000
commit8d36f5966675e23bee7026ba37ae0647fbf47300 (patch)
treedf4227bbb3b07cb70df87237bcff03c8efd7822d /sqlglot/dialects/duckdb.py
parentReleasing debian version 22.2.0-1. (diff)
downloadsqlglot-8d36f5966675e23bee7026ba37ae0647fbf47300.tar.xz
sqlglot-8d36f5966675e23bee7026ba37ae0647fbf47300.zip
Merging upstream version 23.7.0.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'sqlglot/dialects/duckdb.py')
-rw-r--r--sqlglot/dialects/duckdb.py42
1 files changed, 35 insertions, 7 deletions
diff --git a/sqlglot/dialects/duckdb.py b/sqlglot/dialects/duckdb.py
index f74dc97..6a1d07a 100644
--- a/sqlglot/dialects/duckdb.py
+++ b/sqlglot/dialects/duckdb.py
@@ -26,6 +26,7 @@ from sqlglot.dialects.dialect import (
str_to_time_sql,
timestamptrunc_sql,
timestrtotime_sql,
+ unit_to_var,
)
from sqlglot.helper import flatten, seq_get
from sqlglot.tokens import TokenType
@@ -33,15 +34,16 @@ from sqlglot.tokens import TokenType
def _ts_or_ds_add_sql(self: DuckDB.Generator, expression: exp.TsOrDsAdd) -> str:
this = self.sql(expression, "this")
- unit = self.sql(expression, "unit").strip("'") or "DAY"
- interval = self.sql(exp.Interval(this=expression.expression, unit=unit))
+ interval = self.sql(exp.Interval(this=expression.expression, unit=unit_to_var(expression)))
return f"CAST({this} AS {self.sql(expression.return_type)}) + {interval}"
-def _date_delta_sql(self: DuckDB.Generator, expression: exp.DateAdd | exp.DateSub) -> str:
+def _date_delta_sql(
+ self: DuckDB.Generator, expression: exp.DateAdd | exp.DateSub | exp.TimeAdd
+) -> str:
this = self.sql(expression, "this")
- unit = self.sql(expression, "unit").strip("'") or "DAY"
- op = "+" if isinstance(expression, exp.DateAdd) else "-"
+ unit = unit_to_var(expression)
+ op = "+" if isinstance(expression, (exp.DateAdd, exp.TimeAdd)) else "-"
return f"{this} {op} {self.sql(exp.Interval(this=expression.expression, unit=unit))}"
@@ -186,6 +188,11 @@ class DuckDB(Dialect):
return super().to_json_path(path)
class Tokenizer(tokens.Tokenizer):
+ HEREDOC_STRINGS = ["$"]
+
+ HEREDOC_TAG_IS_IDENTIFIER = True
+ HEREDOC_STRING_ALTERNATIVE = TokenType.PARAMETER
+
KEYWORDS = {
**tokens.Tokenizer.KEYWORDS,
"//": TokenType.DIV,
@@ -199,6 +206,7 @@ class DuckDB(Dialect):
"LOGICAL": TokenType.BOOLEAN,
"ONLY": TokenType.ONLY,
"PIVOT_WIDER": TokenType.PIVOT,
+ "POSITIONAL": TokenType.POSITIONAL,
"SIGNED": TokenType.INT,
"STRING": TokenType.VARCHAR,
"UBIGINT": TokenType.UBIGINT,
@@ -227,8 +235,8 @@ class DuckDB(Dialect):
FUNCTIONS = {
**parser.Parser.FUNCTIONS,
"ARRAY_HAS": exp.ArrayContains.from_arg_list,
- "ARRAY_SORT": exp.SortArray.from_arg_list,
"ARRAY_REVERSE_SORT": _build_sort_array_desc,
+ "ARRAY_SORT": exp.SortArray.from_arg_list,
"DATEDIFF": _build_date_diff,
"DATE_DIFF": _build_date_diff,
"DATE_TRUNC": date_trunc_to_time,
@@ -285,6 +293,11 @@ class DuckDB(Dialect):
FUNCTION_PARSERS = parser.Parser.FUNCTION_PARSERS.copy()
FUNCTION_PARSERS.pop("DECODE")
+ NO_PAREN_FUNCTION_PARSERS = {
+ **parser.Parser.NO_PAREN_FUNCTION_PARSERS,
+ "MAP": lambda self: self._parse_map(),
+ }
+
TABLE_ALIAS_TOKENS = parser.Parser.TABLE_ALIAS_TOKENS - {
TokenType.SEMI,
TokenType.ANTI,
@@ -299,6 +312,13 @@ class DuckDB(Dialect):
),
}
+ def _parse_map(self) -> exp.ToMap | exp.Map:
+ if self._match(TokenType.L_BRACE, advance=False):
+ return self.expression(exp.ToMap, this=self._parse_bracket())
+
+ args = self._parse_wrapped_csv(self._parse_conjunction)
+ return self.expression(exp.Map, keys=seq_get(args, 0), values=seq_get(args, 1))
+
def _parse_types(
self, check_func: bool = False, schema: bool = False, allow_identifiers: bool = True
) -> t.Optional[exp.Expression]:
@@ -345,6 +365,7 @@ class DuckDB(Dialect):
SUPPORTS_CREATE_TABLE_LIKE = False
MULTI_ARG_DISTINCT = False
CAN_IMPLEMENT_ARRAY_ANY = True
+ SUPPORTS_TO_NUMBER = False
TRANSFORMS = {
**generator.Generator.TRANSFORMS,
@@ -425,6 +446,7 @@ class DuckDB(Dialect):
"EPOCH", self.func("STRPTIME", e.this, self.format_time(e))
),
exp.Struct: _struct_sql,
+ exp.TimeAdd: _date_delta_sql,
exp.Timestamp: no_timestamp_sql,
exp.TimestampDiff: lambda self, e: self.func(
"DATE_DIFF", exp.Literal.string(e.unit), e.expression, e.this
@@ -478,7 +500,7 @@ class DuckDB(Dialect):
STAR_MAPPING = {**generator.Generator.STAR_MAPPING, "except": "EXCLUDE"}
- UNWRAPPED_INTERVAL_VALUES = (exp.Column, exp.Literal, exp.Paren)
+ UNWRAPPED_INTERVAL_VALUES = (exp.Literal, exp.Paren)
# DuckDB doesn't generally support CREATE TABLE .. properties
# https://duckdb.org/docs/sql/statements/create_table.html
@@ -569,3 +591,9 @@ class DuckDB(Dialect):
return rename_func("RANGE")(self, expression)
return super().generateseries_sql(expression)
+
+ def bracket_sql(self, expression: exp.Bracket) -> str:
+ if isinstance(expression.this, exp.Array):
+ expression.this.replace(exp.paren(expression.this))
+
+ return super().bracket_sql(expression)