diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-27 02:50:25 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-27 02:50:25 +0000 |
commit | cf49728f719975144a958f23ba5f3336fb81ae55 (patch) | |
tree | 78aa5446e86cc5623808508ee167c9a476754939 /sqlglot/dialects/clickhouse.py | |
parent | Releasing debian version 23.10.0-1. (diff) | |
download | sqlglot-cf49728f719975144a958f23ba5f3336fb81ae55.tar.xz sqlglot-cf49728f719975144a958f23ba5f3336fb81ae55.zip |
Merging upstream version 23.12.1.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'sqlglot/dialects/clickhouse.py')
-rw-r--r-- | sqlglot/dialects/clickhouse.py | 100 |
1 files changed, 66 insertions, 34 deletions
diff --git a/sqlglot/dialects/clickhouse.py b/sqlglot/dialects/clickhouse.py index 34ee529..67e28d0 100644 --- a/sqlglot/dialects/clickhouse.py +++ b/sqlglot/dialects/clickhouse.py @@ -6,6 +6,7 @@ from sqlglot import exp, generator, parser, tokens, transforms from sqlglot.dialects.dialect import ( Dialect, arg_max_or_min_no_count, + build_formatted_time, date_delta_sql, inline_array_sql, json_extract_segments, @@ -19,6 +20,16 @@ from sqlglot.helper import is_int, seq_get from sqlglot.tokens import Token, TokenType +def _build_date_format(args: t.List) -> exp.TimeToStr: + expr = build_formatted_time(exp.TimeToStr, "clickhouse")(args) + + timezone = seq_get(args, 2) + if timezone: + expr.set("timezone", timezone) + + return expr + + def _lower_func(sql: str) -> str: index = sql.index("(") return sql[:index].lower() + sql[index:] @@ -124,6 +135,8 @@ class ClickHouse(Dialect): "DATEDIFF": lambda args: exp.DateDiff( this=seq_get(args, 2), expression=seq_get(args, 1), unit=seq_get(args, 0) ), + "DATE_FORMAT": _build_date_format, + "FORMATDATETIME": _build_date_format, "JSONEXTRACTSTRING": build_json_extract_path( exp.JSONExtractScalar, zero_based_indexing=False ), @@ -241,6 +254,14 @@ class ClickHouse(Dialect): "sparkBar", "sumCount", "largestTriangleThreeBuckets", + "histogram", + "sequenceMatch", + "sequenceCount", + "windowFunnel", + "retention", + "uniqUpTo", + "sequenceNextNode", + "exponentialTimeDecayedAvg", } AGG_FUNCTIONS_SUFFIXES = [ @@ -383,6 +404,7 @@ class ClickHouse(Dialect): alias_tokens: t.Optional[t.Collection[TokenType]] = None, parse_bracket: bool = False, is_db_reference: bool = False, + parse_partition: bool = False, ) -> t.Optional[exp.Expression]: this = super()._parse_table( schema=schema, @@ -447,46 +469,53 @@ class ClickHouse(Dialect): functions: t.Optional[t.Dict[str, t.Callable]] = None, anonymous: bool = False, optional_parens: bool = True, + any_token: bool = False, ) -> t.Optional[exp.Expression]: - func = super()._parse_function( - functions=functions, anonymous=anonymous, optional_parens=optional_parens + expr = super()._parse_function( + functions=functions, + anonymous=anonymous, + optional_parens=optional_parens, + any_token=any_token, + ) + + func = expr.this if isinstance(expr, exp.Window) else expr + + # Aggregate functions can be split in 2 parts: <func_name><suffix> + parts = ( + self.AGG_FUNC_MAPPING.get(func.this) if isinstance(func, exp.Anonymous) else None ) - if isinstance(func, exp.Anonymous): - parts = self.AGG_FUNC_MAPPING.get(func.this) + if parts: params = self._parse_func_params(func) + kwargs = { + "this": func.this, + "expressions": func.expressions, + } + if parts[1]: + kwargs["parts"] = parts + exp_class = exp.CombinedParameterizedAgg if params else exp.CombinedAggFunc + else: + exp_class = exp.ParameterizedAgg if params else exp.AnonymousAggFunc + + kwargs["exp_class"] = exp_class if params: - if parts and parts[1]: - return self.expression( - exp.CombinedParameterizedAgg, - this=func.this, - expressions=func.expressions, - params=params, - parts=parts, - ) - return self.expression( - exp.ParameterizedAgg, - this=func.this, - expressions=func.expressions, - params=params, - ) - - if parts: - if parts[1]: - return self.expression( - exp.CombinedAggFunc, - this=func.this, - expressions=func.expressions, - parts=parts, - ) - return self.expression( - exp.AnonymousAggFunc, - this=func.this, - expressions=func.expressions, - ) - - return func + kwargs["params"] = params + + func = self.expression(**kwargs) + + if isinstance(expr, exp.Window): + # The window's func was parsed as Anonymous in base parser, fix its + # type to be CH style CombinedAnonymousAggFunc / AnonymousAggFunc + expr.set("this", func) + elif params: + # Params have blocked super()._parse_function() from parsing the following window + # (if that exists) as they're standing between the function call and the window spec + expr = self._parse_window(func) + else: + expr = func + + return expr def _parse_func_params( self, this: t.Optional[exp.Func] = None @@ -653,6 +682,9 @@ class ClickHouse(Dialect): exp.StrPosition: lambda self, e: self.func( "position", e.this, e.args.get("substr"), e.args.get("position") ), + exp.TimeToStr: lambda self, e: self.func( + "DATE_FORMAT", e.this, self.format_time(e), e.args.get("timezone") + ), exp.VarMap: lambda self, e: _lower_func(var_map_sql(self, e)), exp.Xor: lambda self, e: self.func("xor", e.this, e.expression, *e.expressions), } |