sqlglotc 30.17.0__tar.gz → 30.19.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {sqlglotc-30.17.0/sqlglotc.egg-info → sqlglotc-30.19.0}/PKG-INFO +3 -3
- {sqlglotc-30.17.0 → sqlglotc-30.19.0}/pyproject.toml +2 -2
- {sqlglotc-30.17.0 → sqlglotc-30.19.0}/sqlglot/executor/table.py +1 -1
- {sqlglotc-30.17.0 → sqlglotc-30.19.0}/sqlglot/expressions/aggregate.py +6 -0
- {sqlglotc-30.17.0 → sqlglotc-30.19.0}/sqlglot/expressions/array.py +6 -1
- {sqlglotc-30.17.0 → sqlglotc-30.19.0}/sqlglot/expressions/builders.py +9 -4
- {sqlglotc-30.17.0 → sqlglotc-30.19.0}/sqlglot/expressions/constraints.py +4 -0
- {sqlglotc-30.17.0 → sqlglotc-30.19.0}/sqlglot/expressions/core.py +4 -0
- {sqlglotc-30.17.0 → sqlglotc-30.19.0}/sqlglot/expressions/ddl.py +1 -1
- {sqlglotc-30.17.0 → sqlglotc-30.19.0}/sqlglot/expressions/json.py +8 -0
- {sqlglotc-30.17.0 → sqlglotc-30.19.0}/sqlglot/expressions/query.py +21 -5
- {sqlglotc-30.17.0 → sqlglotc-30.19.0}/sqlglot/expressions/string.py +3 -1
- {sqlglotc-30.17.0 → sqlglotc-30.19.0}/sqlglot/generator.py +72 -21
- {sqlglotc-30.17.0 → sqlglotc-30.19.0}/sqlglot/generators/clickhouse.py +12 -6
- {sqlglotc-30.17.0 → sqlglotc-30.19.0}/sqlglot/generators/databricks.py +1 -1
- {sqlglotc-30.17.0 → sqlglotc-30.19.0}/sqlglot/generators/doris.py +15 -0
- {sqlglotc-30.17.0 → sqlglotc-30.19.0}/sqlglot/generators/dremio.py +3 -0
- {sqlglotc-30.17.0 → sqlglotc-30.19.0}/sqlglot/generators/duckdb.py +19 -21
- {sqlglotc-30.17.0 → sqlglotc-30.19.0}/sqlglot/generators/fabric.py +5 -5
- {sqlglotc-30.17.0 → sqlglotc-30.19.0}/sqlglot/generators/hive.py +1 -0
- {sqlglotc-30.17.0 → sqlglotc-30.19.0}/sqlglot/generators/mysql.py +12 -2
- {sqlglotc-30.17.0 → sqlglotc-30.19.0}/sqlglot/generators/oracle.py +2 -1
- {sqlglotc-30.17.0 → sqlglotc-30.19.0}/sqlglot/generators/postgres.py +8 -4
- {sqlglotc-30.17.0 → sqlglotc-30.19.0}/sqlglot/generators/presto.py +1 -1
- {sqlglotc-30.17.0 → sqlglotc-30.19.0}/sqlglot/generators/python.py +20 -3
- {sqlglotc-30.17.0 → sqlglotc-30.19.0}/sqlglot/generators/singlestore.py +11 -0
- {sqlglotc-30.17.0 → sqlglotc-30.19.0}/sqlglot/generators/snowflake.py +4 -35
- {sqlglotc-30.17.0 → sqlglotc-30.19.0}/sqlglot/generators/spark.py +3 -0
- {sqlglotc-30.17.0 → sqlglotc-30.19.0}/sqlglot/generators/sqlite.py +54 -25
- {sqlglotc-30.17.0 → sqlglotc-30.19.0}/sqlglot/generators/teradata.py +3 -3
- {sqlglotc-30.17.0 → sqlglotc-30.19.0}/sqlglot/generators/trino.py +42 -1
- {sqlglotc-30.17.0 → sqlglotc-30.19.0}/sqlglot/generators/tsql.py +72 -4
- {sqlglotc-30.17.0 → sqlglotc-30.19.0}/sqlglot/lineage.py +1 -1
- {sqlglotc-30.17.0 → sqlglotc-30.19.0}/sqlglot/optimizer/annotate_types.py +34 -19
- {sqlglotc-30.17.0 → sqlglotc-30.19.0}/sqlglot/optimizer/canonicalize_internal_names.py +4 -4
- {sqlglotc-30.17.0 → sqlglotc-30.19.0}/sqlglot/optimizer/normalize_identifiers.py +33 -11
- {sqlglotc-30.17.0 → sqlglotc-30.19.0}/sqlglot/optimizer/qualify_columns.py +193 -25
- {sqlglotc-30.17.0 → sqlglotc-30.19.0}/sqlglot/optimizer/qualify_tables.py +10 -0
- {sqlglotc-30.17.0 → sqlglotc-30.19.0}/sqlglot/optimizer/resolver.py +25 -10
- {sqlglotc-30.17.0 → sqlglotc-30.19.0}/sqlglot/optimizer/scope.py +34 -24
- {sqlglotc-30.17.0 → sqlglotc-30.19.0}/sqlglot/optimizer/simplify.py +73 -43
- {sqlglotc-30.17.0 → sqlglotc-30.19.0}/sqlglot/parser.py +160 -82
- {sqlglotc-30.17.0 → sqlglotc-30.19.0}/sqlglot/parsers/bigquery.py +2 -7
- {sqlglotc-30.17.0 → sqlglotc-30.19.0}/sqlglot/parsers/clickhouse.py +27 -6
- {sqlglotc-30.17.0 → sqlglotc-30.19.0}/sqlglot/parsers/dremio.py +6 -0
- {sqlglotc-30.17.0 → sqlglotc-30.19.0}/sqlglot/parsers/hive.py +6 -0
- {sqlglotc-30.17.0 → sqlglotc-30.19.0}/sqlglot/parsers/mysql.py +60 -7
- {sqlglotc-30.17.0 → sqlglotc-30.19.0}/sqlglot/parsers/oracle.py +1 -0
- {sqlglotc-30.17.0 → sqlglotc-30.19.0}/sqlglot/parsers/postgres.py +7 -2
- {sqlglotc-30.17.0 → sqlglotc-30.19.0}/sqlglot/parsers/redshift.py +2 -0
- {sqlglotc-30.17.0 → sqlglotc-30.19.0}/sqlglot/parsers/snowflake.py +18 -37
- {sqlglotc-30.17.0 → sqlglotc-30.19.0}/sqlglot/parsers/spark2.py +16 -2
- {sqlglotc-30.17.0 → sqlglotc-30.19.0}/sqlglot/parsers/sqlite.py +5 -0
- {sqlglotc-30.17.0 → sqlglotc-30.19.0}/sqlglot/parsers/starrocks.py +3 -0
- {sqlglotc-30.17.0 → sqlglotc-30.19.0}/sqlglot/parsers/teradata.py +1 -1
- {sqlglotc-30.17.0 → sqlglotc-30.19.0}/sqlglot/parsers/trino.py +0 -6
- {sqlglotc-30.17.0 → sqlglotc-30.19.0}/sqlglot/parsers/tsql.py +5 -3
- {sqlglotc-30.17.0 → sqlglotc-30.19.0/sqlglotc.egg-info}/PKG-INFO +3 -3
- sqlglotc-30.19.0/sqlglotc.egg-info/requires.txt +6 -0
- sqlglotc-30.19.0/sqlglotc.egg-info/scm_version.json +8 -0
- sqlglotc-30.17.0/sqlglotc.egg-info/requires.txt +0 -6
- sqlglotc-30.17.0/sqlglotc.egg-info/scm_version.json +0 -8
- {sqlglotc-30.17.0 → sqlglotc-30.19.0}/MANIFEST.in +0 -0
- {sqlglotc-30.17.0 → sqlglotc-30.19.0}/setup.cfg +0 -0
- {sqlglotc-30.17.0 → sqlglotc-30.19.0}/setup.py +0 -0
- {sqlglotc-30.17.0 → sqlglotc-30.19.0}/sqlglot/anonymize.py +0 -0
- {sqlglotc-30.17.0 → sqlglotc-30.19.0}/sqlglot/errors.py +0 -0
- {sqlglotc-30.17.0 → sqlglotc-30.19.0}/sqlglot/expressions/datatypes.py +0 -0
- {sqlglotc-30.17.0 → sqlglotc-30.19.0}/sqlglot/expressions/dml.py +0 -0
- {sqlglotc-30.17.0 → sqlglotc-30.19.0}/sqlglot/expressions/functions.py +0 -0
- {sqlglotc-30.17.0 → sqlglotc-30.19.0}/sqlglot/expressions/math.py +0 -0
- {sqlglotc-30.17.0 → sqlglotc-30.19.0}/sqlglot/expressions/properties.py +0 -0
- {sqlglotc-30.17.0 → sqlglotc-30.19.0}/sqlglot/expressions/temporal.py +0 -0
- {sqlglotc-30.17.0 → sqlglotc-30.19.0}/sqlglot/generators/athena.py +0 -0
- {sqlglotc-30.17.0 → sqlglotc-30.19.0}/sqlglot/generators/bigquery.py +0 -0
- {sqlglotc-30.17.0 → sqlglotc-30.19.0}/sqlglot/generators/dax.py +0 -0
- {sqlglotc-30.17.0 → sqlglotc-30.19.0}/sqlglot/generators/drill.py +0 -0
- {sqlglotc-30.17.0 → sqlglotc-30.19.0}/sqlglot/generators/druid.py +0 -0
- {sqlglotc-30.17.0 → sqlglotc-30.19.0}/sqlglot/generators/dune.py +0 -0
- {sqlglotc-30.17.0 → sqlglotc-30.19.0}/sqlglot/generators/exasol.py +0 -0
- {sqlglotc-30.17.0 → sqlglotc-30.19.0}/sqlglot/generators/materialize.py +0 -0
- {sqlglotc-30.17.0 → sqlglotc-30.19.0}/sqlglot/generators/prql.py +0 -0
- {sqlglotc-30.17.0 → sqlglotc-30.19.0}/sqlglot/generators/redshift.py +0 -0
- {sqlglotc-30.17.0 → sqlglotc-30.19.0}/sqlglot/generators/risingwave.py +0 -0
- {sqlglotc-30.17.0 → sqlglotc-30.19.0}/sqlglot/generators/solr.py +0 -0
- {sqlglotc-30.17.0 → sqlglotc-30.19.0}/sqlglot/generators/spark2.py +0 -0
- {sqlglotc-30.17.0 → sqlglotc-30.19.0}/sqlglot/generators/starrocks.py +0 -0
- {sqlglotc-30.17.0 → sqlglotc-30.19.0}/sqlglot/generators/tableau.py +0 -0
- {sqlglotc-30.17.0 → sqlglotc-30.19.0}/sqlglot/helper.py +0 -0
- {sqlglotc-30.17.0 → sqlglotc-30.19.0}/sqlglot/optimizer/isolate_table_selects.py +0 -0
- {sqlglotc-30.17.0 → sqlglotc-30.19.0}/sqlglot/optimizer/qualify.py +0 -0
- {sqlglotc-30.17.0 → sqlglotc-30.19.0}/sqlglot/parsers/athena.py +0 -0
- {sqlglotc-30.17.0 → sqlglotc-30.19.0}/sqlglot/parsers/base.py +0 -0
- {sqlglotc-30.17.0 → sqlglotc-30.19.0}/sqlglot/parsers/databricks.py +0 -0
- {sqlglotc-30.17.0 → sqlglotc-30.19.0}/sqlglot/parsers/dax.py +0 -0
- {sqlglotc-30.17.0 → sqlglotc-30.19.0}/sqlglot/parsers/doris.py +0 -0
- {sqlglotc-30.17.0 → sqlglotc-30.19.0}/sqlglot/parsers/drill.py +0 -0
- {sqlglotc-30.17.0 → sqlglotc-30.19.0}/sqlglot/parsers/druid.py +0 -0
- {sqlglotc-30.17.0 → sqlglotc-30.19.0}/sqlglot/parsers/duckdb.py +0 -0
- {sqlglotc-30.17.0 → sqlglotc-30.19.0}/sqlglot/parsers/dune.py +0 -0
- {sqlglotc-30.17.0 → sqlglotc-30.19.0}/sqlglot/parsers/exasol.py +0 -0
- {sqlglotc-30.17.0 → sqlglotc-30.19.0}/sqlglot/parsers/fabric.py +0 -0
- {sqlglotc-30.17.0 → sqlglotc-30.19.0}/sqlglot/parsers/materialize.py +0 -0
- {sqlglotc-30.17.0 → sqlglotc-30.19.0}/sqlglot/parsers/presto.py +0 -0
- {sqlglotc-30.17.0 → sqlglotc-30.19.0}/sqlglot/parsers/prql.py +0 -0
- {sqlglotc-30.17.0 → sqlglotc-30.19.0}/sqlglot/parsers/risingwave.py +0 -0
- {sqlglotc-30.17.0 → sqlglotc-30.19.0}/sqlglot/parsers/singlestore.py +0 -0
- {sqlglotc-30.17.0 → sqlglotc-30.19.0}/sqlglot/parsers/solr.py +0 -0
- {sqlglotc-30.17.0 → sqlglotc-30.19.0}/sqlglot/parsers/spark.py +0 -0
- {sqlglotc-30.17.0 → sqlglotc-30.19.0}/sqlglot/parsers/tableau.py +0 -0
- {sqlglotc-30.17.0 → sqlglotc-30.19.0}/sqlglot/schema.py +0 -0
- {sqlglotc-30.17.0 → sqlglotc-30.19.0}/sqlglot/serde.py +0 -0
- {sqlglotc-30.17.0 → sqlglotc-30.19.0}/sqlglot/time.py +0 -0
- {sqlglotc-30.17.0 → sqlglotc-30.19.0}/sqlglot/tokenizer_core.py +0 -0
- {sqlglotc-30.17.0 → sqlglotc-30.19.0}/sqlglot/trie.py +0 -0
- {sqlglotc-30.17.0 → sqlglotc-30.19.0}/sqlglotc.egg-info/SOURCES.txt +0 -0
- {sqlglotc-30.17.0 → sqlglotc-30.19.0}/sqlglotc.egg-info/dependency_links.txt +0 -0
- {sqlglotc-30.17.0 → sqlglotc-30.19.0}/sqlglotc.egg-info/scm_file_list.json +0 -0
- {sqlglotc-30.17.0 → sqlglotc-30.19.0}/sqlglotc.egg-info/top_level.txt +0 -0
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: sqlglotc
|
|
3
|
-
Version: 30.
|
|
3
|
+
Version: 30.19.0
|
|
4
4
|
Summary: mypyc-compiled extensions for sqlglot
|
|
5
5
|
Author-email: Toby Mao <toby.mao@gmail.com>
|
|
6
6
|
License-Expression: MIT
|
|
7
7
|
Project-URL: Homepage, https://sqlglot.com/
|
|
8
8
|
Project-URL: Repository, https://github.com/tobymao/sqlglot
|
|
9
9
|
Requires-Python: >=3.10
|
|
10
|
-
Requires-Dist: sqlglot==30.
|
|
10
|
+
Requires-Dist: sqlglot==30.19.0
|
|
11
11
|
Provides-Extra: dev
|
|
12
12
|
Requires-Dist: setuptools>=61.0; extra == "dev"
|
|
13
13
|
Requires-Dist: setuptools_scm; extra == "dev"
|
|
14
|
-
Requires-Dist: sqlglot-mypy>=2.3.0.
|
|
14
|
+
Requires-Dist: sqlglot-mypy>=2.3.0.post2; extra == "dev"
|
|
15
15
|
Dynamic: requires-dist
|
|
@@ -7,7 +7,7 @@ license = "MIT"
|
|
|
7
7
|
requires-python = ">= 3.10"
|
|
8
8
|
|
|
9
9
|
[project.optional-dependencies]
|
|
10
|
-
dev = ["setuptools >= 61.0", "setuptools_scm", "sqlglot-mypy >= 2.3.0.
|
|
10
|
+
dev = ["setuptools >= 61.0", "setuptools_scm", "sqlglot-mypy >= 2.3.0.post2"]
|
|
11
11
|
|
|
12
12
|
[project.urls]
|
|
13
13
|
Homepage = "https://sqlglot.com/"
|
|
@@ -17,7 +17,7 @@ Repository = "https://github.com/tobymao/sqlglot"
|
|
|
17
17
|
requires = [
|
|
18
18
|
"setuptools >= 61.0",
|
|
19
19
|
"setuptools_scm",
|
|
20
|
-
"sqlglot-mypy >= 2.3.0.
|
|
20
|
+
"sqlglot-mypy >= 2.3.0.post2",
|
|
21
21
|
"types-python-dateutil",
|
|
22
22
|
"sqlglot",
|
|
23
23
|
]
|
|
@@ -5,6 +5,12 @@ from __future__ import annotations
|
|
|
5
5
|
from sqlglot.expressions.core import Expression, Func, AggFunc, Binary
|
|
6
6
|
|
|
7
7
|
|
|
8
|
+
class Agg(Expression, AggFunc):
|
|
9
|
+
@property
|
|
10
|
+
def output_name(self) -> str:
|
|
11
|
+
return self.this.name
|
|
12
|
+
|
|
13
|
+
|
|
8
14
|
class AIAgg(Expression, AggFunc):
|
|
9
15
|
arg_types = {"this": True, "expression": True}
|
|
10
16
|
_sql_names = ["AI_AGG"]
|
|
@@ -240,10 +240,15 @@ class Explode(Expression, Func, UDTF):
|
|
|
240
240
|
is_var_len_args = True
|
|
241
241
|
|
|
242
242
|
|
|
243
|
-
class Inline(Expression, Func):
|
|
243
|
+
class Inline(Expression, Func, UDTF):
|
|
244
244
|
pass
|
|
245
245
|
|
|
246
246
|
|
|
247
|
+
class Stack(Expression, Func, UDTF):
|
|
248
|
+
arg_types = {"this": True, "expressions": True}
|
|
249
|
+
is_var_len_args = True
|
|
250
|
+
|
|
251
|
+
|
|
247
252
|
@trait
|
|
248
253
|
class ExplodeOuter(Expr):
|
|
249
254
|
pass
|
|
@@ -495,11 +495,16 @@ def cast(
|
|
|
495
495
|
target_dialect = Dialect.get_or_raise(dialect)
|
|
496
496
|
type_mapping = target_dialect.generator_class.TYPE_MAPPING
|
|
497
497
|
|
|
498
|
-
existing_cast_type
|
|
498
|
+
existing_cast_type = expr.to.this
|
|
499
499
|
new_cast_type: DType = data_type.this
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
500
|
+
# `this` is only a plain type enum for simple types; complex ones such as
|
|
501
|
+
# INTERVAL nest another expression there, so the equivalence check is skipped.
|
|
502
|
+
types_are_equivalent = (
|
|
503
|
+
isinstance(existing_cast_type, DType)
|
|
504
|
+
and isinstance(new_cast_type, DType)
|
|
505
|
+
and type_mapping.get(existing_cast_type, existing_cast_type.value)
|
|
506
|
+
== type_mapping.get(new_cast_type, new_cast_type.value)
|
|
507
|
+
)
|
|
503
508
|
|
|
504
509
|
if expr.is_type(data_type) or types_are_equivalent:
|
|
505
510
|
return expr
|
|
@@ -41,6 +41,10 @@ class ZeroFillColumnConstraint(ColumnConstraint):
|
|
|
41
41
|
arg_types = {}
|
|
42
42
|
|
|
43
43
|
|
|
44
|
+
class BinaryColumnConstraint(ColumnConstraint):
|
|
45
|
+
arg_types = {}
|
|
46
|
+
|
|
47
|
+
|
|
44
48
|
class PeriodForSystemTimeConstraint(Expression, ColumnConstraintKind):
|
|
45
49
|
arg_types = {"this": True, "expression": True}
|
|
46
50
|
|
|
@@ -1828,6 +1828,10 @@ class Identifier(Expression):
|
|
|
1828
1828
|
class DynamicIdentifier(Expression, Func):
|
|
1829
1829
|
arg_types = {"this": True, "expressions": False}
|
|
1830
1830
|
|
|
1831
|
+
@property
|
|
1832
|
+
def name(self) -> str:
|
|
1833
|
+
return self.this.name if self.this else ""
|
|
1834
|
+
|
|
1831
1835
|
|
|
1832
1836
|
class Opclass(Expression):
|
|
1833
1837
|
arg_types = {"this": True, "expression": True}
|
|
@@ -54,6 +54,10 @@ class JSONBContainsAllTopKeys(Expression, Binary, Predicate, Func):
|
|
|
54
54
|
pass
|
|
55
55
|
|
|
56
56
|
|
|
57
|
+
class JSONBContainsTopKey(Expression, Binary, Predicate, Func):
|
|
58
|
+
pass
|
|
59
|
+
|
|
60
|
+
|
|
57
61
|
class JSONBContainsAnyTopKeys(Expression, Binary, Predicate, Func):
|
|
58
62
|
pass
|
|
59
63
|
|
|
@@ -236,6 +240,10 @@ class OpenJSON(Expression, Func):
|
|
|
236
240
|
arg_types = {"this": True, "path": False, "expressions": False}
|
|
237
241
|
|
|
238
242
|
|
|
243
|
+
class FromJson(Expression, Func):
|
|
244
|
+
arg_types = {"this": True, "expression": True, "options": False}
|
|
245
|
+
|
|
246
|
+
|
|
239
247
|
class ParseJSON(Expression, Func):
|
|
240
248
|
# BigQuery, Snowflake have PARSE_JSON, Presto has JSON_PARSE
|
|
241
249
|
# Snowflake also has TRY_PARSE_JSON, which is represented using `safe`
|
|
@@ -12,6 +12,7 @@ from sqlglot.expressions.core import (
|
|
|
12
12
|
Condition,
|
|
13
13
|
Distinct,
|
|
14
14
|
Dot,
|
|
15
|
+
DynamicIdentifier,
|
|
15
16
|
Expr,
|
|
16
17
|
Expression,
|
|
17
18
|
Func,
|
|
@@ -966,9 +967,10 @@ class Table(Expression, Selectable):
|
|
|
966
967
|
|
|
967
968
|
@property
|
|
968
969
|
def name(self) -> str:
|
|
969
|
-
|
|
970
|
+
this = self.this
|
|
971
|
+
if not this or (isinstance(this, Func) and not isinstance(this, DynamicIdentifier)):
|
|
970
972
|
return ""
|
|
971
|
-
return
|
|
973
|
+
return this.name
|
|
972
974
|
|
|
973
975
|
@property
|
|
974
976
|
def db(self) -> str:
|
|
@@ -1018,6 +1020,20 @@ class Table(Expression, Selectable):
|
|
|
1018
1020
|
return col
|
|
1019
1021
|
|
|
1020
1022
|
|
|
1023
|
+
def _is_star(expression: Expr) -> bool:
|
|
1024
|
+
stack = [expression]
|
|
1025
|
+
while stack:
|
|
1026
|
+
node = stack.pop()
|
|
1027
|
+
if isinstance(node, SetOperation):
|
|
1028
|
+
stack.append(node.this)
|
|
1029
|
+
stack.append(node.expression)
|
|
1030
|
+
elif isinstance(node, Subquery):
|
|
1031
|
+
stack.append(node.this)
|
|
1032
|
+
elif node.is_star:
|
|
1033
|
+
return True
|
|
1034
|
+
return False
|
|
1035
|
+
|
|
1036
|
+
|
|
1021
1037
|
class SetOperation(Expression, Query):
|
|
1022
1038
|
arg_types = {
|
|
1023
1039
|
"with_": False,
|
|
@@ -1060,7 +1076,7 @@ class SetOperation(Expression, Query):
|
|
|
1060
1076
|
|
|
1061
1077
|
@property
|
|
1062
1078
|
def is_star(self) -> bool:
|
|
1063
|
-
return self
|
|
1079
|
+
return _is_star(self)
|
|
1064
1080
|
|
|
1065
1081
|
@property
|
|
1066
1082
|
def selects(self) -> list[Expr]:
|
|
@@ -1718,7 +1734,7 @@ class Subquery(Expression, DerivedTable, Query):
|
|
|
1718
1734
|
|
|
1719
1735
|
@property
|
|
1720
1736
|
def is_star(self) -> bool:
|
|
1721
|
-
return self
|
|
1737
|
+
return _is_star(self)
|
|
1722
1738
|
|
|
1723
1739
|
@property
|
|
1724
1740
|
def output_name(self) -> str:
|
|
@@ -1891,7 +1907,7 @@ class Where(Expression):
|
|
|
1891
1907
|
class Analyze(Expression):
|
|
1892
1908
|
arg_types = {
|
|
1893
1909
|
"kind": False,
|
|
1894
|
-
"
|
|
1910
|
+
"tables": False,
|
|
1895
1911
|
"options": False,
|
|
1896
1912
|
"mode": False,
|
|
1897
1913
|
"partition": False,
|
|
@@ -32,6 +32,7 @@ class Concat(Expression, Func):
|
|
|
32
32
|
|
|
33
33
|
|
|
34
34
|
class ConcatWs(Concat):
|
|
35
|
+
arg_types = {**Concat.arg_types, "flatten": False}
|
|
35
36
|
_sql_names = ["CONCAT_WS"]
|
|
36
37
|
|
|
37
38
|
|
|
@@ -478,7 +479,8 @@ class RegexpReplace(Expression, Func):
|
|
|
478
479
|
|
|
479
480
|
|
|
480
481
|
class RegexpSplit(Expression, Func):
|
|
481
|
-
|
|
482
|
+
# "mode" is Dremio-specific, appended after "limit" for from_arg_list compat
|
|
483
|
+
arg_types = {"this": True, "expression": True, "limit": False, "mode": False}
|
|
482
484
|
|
|
483
485
|
|
|
484
486
|
class RegexpSubstr(Expression, Func):
|
|
@@ -147,6 +147,7 @@ class Generator:
|
|
|
147
147
|
exp.AssumeColumnConstraint: lambda self, e: f"ASSUME ({self.sql(e, 'this')})",
|
|
148
148
|
exp.AutoRefreshProperty: lambda self, e: f"AUTO REFRESH {self.sql(e, 'this')}",
|
|
149
149
|
exp.BackupProperty: lambda self, e: f"BACKUP {self.sql(e, 'this')}",
|
|
150
|
+
exp.BinaryColumnConstraint: lambda *_: "BINARY",
|
|
150
151
|
exp.CaseSpecificColumnConstraint: lambda _, e: (
|
|
151
152
|
f"{'NOT ' if e.args.get('not_') else ''}CASESPECIFIC"
|
|
152
153
|
),
|
|
@@ -206,6 +207,7 @@ class Generator:
|
|
|
206
207
|
exp.Int64: lambda self, e: self.sql(exp.cast(e.this, exp.DType.BIGINT)),
|
|
207
208
|
exp.JSONBContainsAnyTopKeys: lambda self, e: self.binary(e, "?|"),
|
|
208
209
|
exp.JSONBContainsAllTopKeys: lambda self, e: self.binary(e, "?&"),
|
|
210
|
+
exp.JSONBContainsTopKey: lambda self, e: self.binary(e, "?"),
|
|
209
211
|
exp.JSONBDeleteAtPath: lambda self, e: self.binary(e, "#-"),
|
|
210
212
|
exp.JSONBPathExists: lambda self, e: self.binary(e, "@?"),
|
|
211
213
|
exp.JSONObject: lambda self, e: self._jsonobject_sql(e),
|
|
@@ -351,6 +353,9 @@ class Generator:
|
|
|
351
353
|
# The separator for grouping sets and rollups
|
|
352
354
|
GROUPINGS_SEP = ","
|
|
353
355
|
|
|
356
|
+
# Whether GROUPING SETS can follow GROUP BY expressions without a comma
|
|
357
|
+
SUPPORTS_GROUPING_SETS_AS_SUFFIX = False
|
|
358
|
+
|
|
354
359
|
# The string used for creating an index on a table
|
|
355
360
|
INDEX_ON = "ON"
|
|
356
361
|
|
|
@@ -530,6 +535,12 @@ class Generator:
|
|
|
530
535
|
# True means limit 1 happens after the set op, False means it it happens on y.
|
|
531
536
|
SET_OP_MODIFIERS = True
|
|
532
537
|
|
|
538
|
+
# Whether a SELECT operand can have a branch-local LIMIT/TOP without parentheses.
|
|
539
|
+
SET_OP_LIMITS = False
|
|
540
|
+
|
|
541
|
+
# Whether set operation operands can be parenthesized without a SELECT wrapper.
|
|
542
|
+
SET_OP_PARENTHESIZED_OPERANDS = True
|
|
543
|
+
|
|
533
544
|
# Whether parameters from COPY statement are wrapped in parentheses
|
|
534
545
|
COPY_PARAMS_ARE_WRAPPED = True
|
|
535
546
|
|
|
@@ -850,6 +861,16 @@ class Generator:
|
|
|
850
861
|
|
|
851
862
|
RESPECT_IGNORE_NULLS_UNSUPPORTED_EXPRESSIONS: t.ClassVar[tuple[type[exp.Expr], ...]] = ()
|
|
852
863
|
|
|
864
|
+
MOD_OPERATOR = "%"
|
|
865
|
+
|
|
866
|
+
# Infix operators that bind at least as tightly as %, so a Mod on their right side needs parentheses
|
|
867
|
+
MOD_PAREN_PARENT_TYPES: t.ClassVar[tuple[type[exp.Expr], ...]] = (
|
|
868
|
+
exp.Mul,
|
|
869
|
+
exp.Div,
|
|
870
|
+
exp.IntDiv,
|
|
871
|
+
exp.Mod,
|
|
872
|
+
)
|
|
873
|
+
|
|
853
874
|
SAFE_JSON_PATH_KEY_RE: t.ClassVar = exp.SAFE_IDENTIFIER_RE
|
|
854
875
|
|
|
855
876
|
SENTINEL_LINE_BREAK = "__SQLGLOT__LB__"
|
|
@@ -1826,7 +1847,7 @@ class Generator:
|
|
|
1826
1847
|
return self.prepend_ctes(expression, f"DELETE{hint}{tables}{expression_sql}")
|
|
1827
1848
|
|
|
1828
1849
|
def drop_sql(self, expression: exp.Drop) -> str:
|
|
1829
|
-
|
|
1850
|
+
tables = self.expressions(expression, key="tables", flat=True)
|
|
1830
1851
|
expressions = self.expressions(expression, flat=True)
|
|
1831
1852
|
expressions = f" ({expressions})" if expressions else ""
|
|
1832
1853
|
kind = expression.args["kind"]
|
|
@@ -1848,7 +1869,7 @@ class Generator:
|
|
|
1848
1869
|
purge = " PURGE" if expression.args.get("purge") else ""
|
|
1849
1870
|
sync = " SYNC" if expression.args.get("sync") else ""
|
|
1850
1871
|
force = " FORCE" if expression.args.get("force") else ""
|
|
1851
|
-
return f"DROP{temporary}{materialized}{iceberg} {kind}{concurrently_sql}{exists_sql}{
|
|
1872
|
+
return f"DROP{temporary}{materialized}{iceberg} {kind}{concurrently_sql}{exists_sql}{tables}{on_cluster}{expressions}{cascade}{restrict}{constraints}{purge}{sync}{force}"
|
|
1852
1873
|
|
|
1853
1874
|
def set_operation(self, expression: exp.SetOperation) -> str:
|
|
1854
1875
|
op_type = type(expression)
|
|
@@ -1887,16 +1908,16 @@ class Generator:
|
|
|
1887
1908
|
if not self.SET_OP_MODIFIERS:
|
|
1888
1909
|
limit = expression.args.get("limit")
|
|
1889
1910
|
order = expression.args.get("order")
|
|
1911
|
+
offset = expression.args.get("offset")
|
|
1890
1912
|
|
|
1891
|
-
if limit or order:
|
|
1913
|
+
if limit or order or offset:
|
|
1892
1914
|
select = self._move_ctes_to_top_level(
|
|
1893
1915
|
exp.subquery(expression, "_l_0", copy=False).select("*", copy=False)
|
|
1894
1916
|
)
|
|
1895
1917
|
|
|
1896
|
-
|
|
1897
|
-
|
|
1898
|
-
|
|
1899
|
-
select = select.order_by(order.pop(), copy=False)
|
|
1918
|
+
for arg in ("limit", "order", "offset"):
|
|
1919
|
+
if value := expression.args.get(arg):
|
|
1920
|
+
select.set(arg, value.pop())
|
|
1900
1921
|
return self.sql(select)
|
|
1901
1922
|
|
|
1902
1923
|
sqls: list[str] = []
|
|
@@ -1914,6 +1935,14 @@ class Generator:
|
|
|
1914
1935
|
)
|
|
1915
1936
|
stack.append(node.this)
|
|
1916
1937
|
else:
|
|
1938
|
+
if (
|
|
1939
|
+
not self.SET_OP_LIMITS
|
|
1940
|
+
and isinstance(node, exp.Select)
|
|
1941
|
+
and node.args.get("limit")
|
|
1942
|
+
):
|
|
1943
|
+
node = node.subquery(copy=False)
|
|
1944
|
+
if not self.SET_OP_PARENTHESIZED_OPERANDS:
|
|
1945
|
+
node = exp.select("*").from_(node, copy=False)
|
|
1917
1946
|
sqls.append(self.sql(node))
|
|
1918
1947
|
|
|
1919
1948
|
this = self.sep().join(sqls)
|
|
@@ -2819,7 +2848,18 @@ class Generator:
|
|
|
2819
2848
|
and groupings
|
|
2820
2849
|
and groupings.strip() not in ("WITH CUBE", "WITH ROLLUP")
|
|
2821
2850
|
):
|
|
2822
|
-
|
|
2851
|
+
add_separator = True
|
|
2852
|
+
|
|
2853
|
+
if grouping_sets:
|
|
2854
|
+
if self.SUPPORTS_GROUPING_SETS_AS_SUFFIX:
|
|
2855
|
+
add_separator = False
|
|
2856
|
+
else:
|
|
2857
|
+
self.unsupported(
|
|
2858
|
+
"GROUPING SETS without a comma after GROUP BY expressions is not supported"
|
|
2859
|
+
)
|
|
2860
|
+
|
|
2861
|
+
if add_separator:
|
|
2862
|
+
group_by = f"{group_by}{self.GROUPINGS_SEP}"
|
|
2823
2863
|
|
|
2824
2864
|
return f"{group_by}{groupings}"
|
|
2825
2865
|
|
|
@@ -3298,8 +3338,8 @@ class Generator:
|
|
|
3298
3338
|
self.sql(expression, "order"),
|
|
3299
3339
|
*self.offset_limit_modifiers(expression, isinstance(limit, exp.Fetch), limit),
|
|
3300
3340
|
*self.after_limit_modifiers(expression),
|
|
3301
|
-
self.options_modifier(expression),
|
|
3302
3341
|
self.sql(expression, "for_"),
|
|
3342
|
+
self.options_modifier(expression),
|
|
3303
3343
|
sep="",
|
|
3304
3344
|
)
|
|
3305
3345
|
|
|
@@ -3796,6 +3836,7 @@ class Generator:
|
|
|
3796
3836
|
path = self.expressions(expression, sep="", flat=True).lstrip(".")
|
|
3797
3837
|
|
|
3798
3838
|
if self.QUOTE_JSON_PATH:
|
|
3839
|
+
path = self.escape_str(path)
|
|
3799
3840
|
path = f"{self.dialect.QUOTE_START}{path}{self.dialect.QUOTE_END}"
|
|
3800
3841
|
|
|
3801
3842
|
return path
|
|
@@ -3814,7 +3855,7 @@ class Generator:
|
|
|
3814
3855
|
|
|
3815
3856
|
if self._quote_json_path_key_using_brackets and self.JSON_PATH_SINGLE_QUOTE_ESCAPE:
|
|
3816
3857
|
escaped = expression.replace("'", "\\'")
|
|
3817
|
-
escaped = f"
|
|
3858
|
+
escaped = f"'{escaped}'"
|
|
3818
3859
|
else:
|
|
3819
3860
|
escaped = expression.replace('"', '\\"')
|
|
3820
3861
|
escaped = f'"{escaped}"'
|
|
@@ -4587,7 +4628,15 @@ class Generator:
|
|
|
4587
4628
|
return self.binary(expression, "<=")
|
|
4588
4629
|
|
|
4589
4630
|
def mod_sql(self, expression: exp.Mod) -> str:
|
|
4590
|
-
|
|
4631
|
+
this = self.sql(expression, "this")
|
|
4632
|
+
expr = self.sql(expression, "expression")
|
|
4633
|
+
sql = f"{this} {self.maybe_comment(self.MOD_OPERATOR, comments=expression.comments)} {expr}"
|
|
4634
|
+
|
|
4635
|
+
parent = expression.parent
|
|
4636
|
+
if isinstance(parent, self.MOD_PAREN_PARENT_TYPES) and parent.expression is expression:
|
|
4637
|
+
return f"({sql})"
|
|
4638
|
+
|
|
4639
|
+
return sql
|
|
4591
4640
|
|
|
4592
4641
|
def mul_sql(self, expression: exp.Mul) -> str:
|
|
4593
4642
|
return self.binary(expression, "*")
|
|
@@ -5035,6 +5084,12 @@ class Generator:
|
|
|
5035
5084
|
|
|
5036
5085
|
return self.sql(case)
|
|
5037
5086
|
|
|
5087
|
+
def nthvalue_sql(self, expression: exp.NthValue) -> str:
|
|
5088
|
+
if expression.args.get("from_first") is False:
|
|
5089
|
+
self.unsupported("NTH_VALUE FROM LAST is not supported")
|
|
5090
|
+
|
|
5091
|
+
return self.function_fallback_sql(expression)
|
|
5092
|
+
|
|
5038
5093
|
def comprehension_sql(self, expression: exp.Comprehension) -> str:
|
|
5039
5094
|
this = self.sql(expression, "this")
|
|
5040
5095
|
expr = self.sql(expression, "expression")
|
|
@@ -5361,12 +5416,6 @@ class Generator:
|
|
|
5361
5416
|
|
|
5362
5417
|
this = self.json_path_part(this)
|
|
5363
5418
|
|
|
5364
|
-
if quoted and self.QUOTE_JSON_PATH:
|
|
5365
|
-
# The whole path is rendered as a single quoted string literal, so the bracketed key
|
|
5366
|
-
# (which may itself contain backslash-escaped quotes, e.g. ["x \"y\"z"]) must be
|
|
5367
|
-
# escaped again for the outer string literal (-> ["x \\"y\\"z"]).
|
|
5368
|
-
this = self.escape_str(this)
|
|
5369
|
-
|
|
5370
5419
|
return (
|
|
5371
5420
|
f"[{this}]"
|
|
5372
5421
|
if self._quote_json_path_key_using_brackets and self.JSON_PATH_BRACKETED_KEY_SUPPORTED
|
|
@@ -5395,9 +5444,11 @@ class Generator:
|
|
|
5395
5444
|
|
|
5396
5445
|
if self.IGNORE_NULLS_IN_FUNC and not expression.meta_get("inline"):
|
|
5397
5446
|
if self.IGNORE_NULLS_BEFORE_ORDER:
|
|
5447
|
+
from sqlglot.optimizer.scope import find_all_in_scope
|
|
5448
|
+
|
|
5398
5449
|
# The first modifier here will be the one closest to the AggFunc's arg
|
|
5399
5450
|
mods = sorted(
|
|
5400
|
-
expression
|
|
5451
|
+
find_all_in_scope(expression, exp.HavingMax, exp.Order, exp.Limit),
|
|
5401
5452
|
key=lambda x: (
|
|
5402
5453
|
0
|
|
5403
5454
|
if isinstance(x, exp.HavingMax)
|
|
@@ -6037,8 +6088,8 @@ class Generator:
|
|
|
6037
6088
|
options = f" {options}" if options else ""
|
|
6038
6089
|
kind = self.sql(expression, "kind")
|
|
6039
6090
|
kind = f" {kind}" if kind else ""
|
|
6040
|
-
|
|
6041
|
-
|
|
6091
|
+
tables = self.expressions(expression, key="tables", flat=True)
|
|
6092
|
+
tables = f" {tables}" if tables else ""
|
|
6042
6093
|
mode = self.sql(expression, "mode")
|
|
6043
6094
|
mode = f" {mode}" if mode else ""
|
|
6044
6095
|
properties = self.sql(expression, "properties")
|
|
@@ -6047,7 +6098,7 @@ class Generator:
|
|
|
6047
6098
|
partition = f" {partition}" if partition else ""
|
|
6048
6099
|
inner_expression = self.sql(expression, "expression")
|
|
6049
6100
|
inner_expression = f" {inner_expression}" if inner_expression else ""
|
|
6050
|
-
return f"ANALYZE{options}{kind}{
|
|
6101
|
+
return f"ANALYZE{options}{kind}{tables}{partition}{mode}{inner_expression}{properties}"
|
|
6051
6102
|
|
|
6052
6103
|
def xmltable_sql(self, expression: exp.XMLTable) -> str:
|
|
6053
6104
|
this = self.sql(expression, "this")
|
|
@@ -186,6 +186,7 @@ class ClickHouseGenerator(generator.Generator):
|
|
|
186
186
|
TABLE_HINTS = False
|
|
187
187
|
GROUPINGS_SEP = ""
|
|
188
188
|
SET_OP_MODIFIERS = False
|
|
189
|
+
SET_OP_LIMITS = True
|
|
189
190
|
ARRAY_SIZE_NAME = "LENGTH"
|
|
190
191
|
WRAP_DERIVED_VALUES = False
|
|
191
192
|
AUTO_REFRESH_BARE_INTERVALS = True
|
|
@@ -372,12 +373,8 @@ class ClickHouseGenerator(generator.Generator):
|
|
|
372
373
|
exp.SchemaCommentProperty: lambda self, e: self.naked_property(e),
|
|
373
374
|
exp.Stddev: rename_func("stddevSamp"),
|
|
374
375
|
exp.Chr: rename_func("CHAR"),
|
|
375
|
-
exp.Lag:
|
|
376
|
-
|
|
377
|
-
),
|
|
378
|
-
exp.Lead: lambda self, e: self.func(
|
|
379
|
-
"leadInFrame", e.this, e.args.get("offset"), e.args.get("default")
|
|
380
|
-
),
|
|
376
|
+
exp.Lag: rename_func("lag"),
|
|
377
|
+
exp.Lead: rename_func("lead"),
|
|
381
378
|
exp.Levenshtein: unsupported_args("ins_cost", "del_cost", "sub_cost", "max_dist")(
|
|
382
379
|
rename_func("editDistance")
|
|
383
380
|
),
|
|
@@ -449,6 +446,15 @@ class ClickHouseGenerator(generator.Generator):
|
|
|
449
446
|
|
|
450
447
|
return self.func("groupConcat", this)
|
|
451
448
|
|
|
449
|
+
def select_sql(self, expression: exp.Select) -> str:
|
|
450
|
+
limit = expression.args.get("limit")
|
|
451
|
+
if isinstance(limit, exp.Fetch) and not expression.args.get("order"):
|
|
452
|
+
count = limit.args.get("count")
|
|
453
|
+
expression.set(
|
|
454
|
+
"limit", exp.Limit(expression=count if count is not None else exp.Literal.number(1))
|
|
455
|
+
)
|
|
456
|
+
return super().select_sql(expression)
|
|
457
|
+
|
|
452
458
|
def offset_sql(self, expression: exp.Offset) -> str:
|
|
453
459
|
offset = super().offset_sql(expression)
|
|
454
460
|
|
|
@@ -97,10 +97,10 @@ class DatabricksGenerator(SparkGenerator):
|
|
|
97
97
|
return f"{self.sql(expression, 'this')} TIMESERIES"
|
|
98
98
|
|
|
99
99
|
def jsonpath_sql(self, expression: exp.JSONPath) -> str:
|
|
100
|
-
expression.set("escape", None)
|
|
101
100
|
path = super().jsonpath_sql(expression)
|
|
102
101
|
|
|
103
102
|
if isinstance(expression.parent, exp.JSONExtractScalar):
|
|
103
|
+
path = self.escape_str(path)
|
|
104
104
|
return f"{self.dialect.QUOTE_START}{path}{self.dialect.QUOTE_END}"
|
|
105
105
|
|
|
106
106
|
return path
|
|
@@ -104,6 +104,7 @@ class DorisGenerator(MySQLGenerator):
|
|
|
104
104
|
"alter",
|
|
105
105
|
"analyze",
|
|
106
106
|
"analyzed",
|
|
107
|
+
"analyzer",
|
|
107
108
|
"and",
|
|
108
109
|
"anti",
|
|
109
110
|
"append",
|
|
@@ -111,6 +112,7 @@ class DorisGenerator(MySQLGenerator):
|
|
|
111
112
|
"array_range",
|
|
112
113
|
"as",
|
|
113
114
|
"asc",
|
|
115
|
+
"asof",
|
|
114
116
|
"at",
|
|
115
117
|
"authors",
|
|
116
118
|
"auto",
|
|
@@ -132,6 +134,7 @@ class DorisGenerator(MySQLGenerator):
|
|
|
132
134
|
"bitxor",
|
|
133
135
|
"blob",
|
|
134
136
|
"boolean",
|
|
137
|
+
"both",
|
|
135
138
|
"brief",
|
|
136
139
|
"broker",
|
|
137
140
|
"buckets",
|
|
@@ -148,6 +151,7 @@ class DorisGenerator(MySQLGenerator):
|
|
|
148
151
|
"catalogs",
|
|
149
152
|
"chain",
|
|
150
153
|
"char",
|
|
154
|
+
"char_filter",
|
|
151
155
|
"character",
|
|
152
156
|
"charset",
|
|
153
157
|
"check",
|
|
@@ -227,6 +231,7 @@ class DorisGenerator(MySQLGenerator):
|
|
|
227
231
|
"drop",
|
|
228
232
|
"dropp",
|
|
229
233
|
"dual",
|
|
234
|
+
"dump",
|
|
230
235
|
"duplicate",
|
|
231
236
|
"dynamic",
|
|
232
237
|
"else",
|
|
@@ -329,8 +334,10 @@ class DorisGenerator(MySQLGenerator):
|
|
|
329
334
|
"largeint",
|
|
330
335
|
"last",
|
|
331
336
|
"lateral",
|
|
337
|
+
"layout",
|
|
332
338
|
"ldap",
|
|
333
339
|
"ldap_admin_password",
|
|
340
|
+
"leading",
|
|
334
341
|
"left",
|
|
335
342
|
"less",
|
|
336
343
|
"level",
|
|
@@ -352,6 +359,7 @@ class DorisGenerator(MySQLGenerator):
|
|
|
352
359
|
"match",
|
|
353
360
|
"match_all",
|
|
354
361
|
"match_any",
|
|
362
|
+
"match_condition",
|
|
355
363
|
"match_phrase",
|
|
356
364
|
"match_phrase_edge",
|
|
357
365
|
"match_phrase_prefix",
|
|
@@ -377,6 +385,7 @@ class DorisGenerator(MySQLGenerator):
|
|
|
377
385
|
"next",
|
|
378
386
|
"ngram_bf",
|
|
379
387
|
"no",
|
|
388
|
+
"no_use_mv",
|
|
380
389
|
"non_nullable",
|
|
381
390
|
"not",
|
|
382
391
|
"null",
|
|
@@ -410,6 +419,7 @@ class DorisGenerator(MySQLGenerator):
|
|
|
410
419
|
"permissive",
|
|
411
420
|
"physical",
|
|
412
421
|
"plan",
|
|
422
|
+
"play",
|
|
413
423
|
"process",
|
|
414
424
|
"plugin",
|
|
415
425
|
"plugins",
|
|
@@ -520,6 +530,9 @@ class DorisGenerator(MySQLGenerator):
|
|
|
520
530
|
"timestampdiff",
|
|
521
531
|
"tinyint",
|
|
522
532
|
"to",
|
|
533
|
+
"token_filter",
|
|
534
|
+
"tokenizer",
|
|
535
|
+
"trailing",
|
|
523
536
|
"transaction",
|
|
524
537
|
"trash",
|
|
525
538
|
"tree",
|
|
@@ -527,6 +540,7 @@ class DorisGenerator(MySQLGenerator):
|
|
|
527
540
|
"trim",
|
|
528
541
|
"true",
|
|
529
542
|
"truncate",
|
|
543
|
+
"try_cast",
|
|
530
544
|
"type",
|
|
531
545
|
"type_cast",
|
|
532
546
|
"types",
|
|
@@ -539,6 +553,7 @@ class DorisGenerator(MySQLGenerator):
|
|
|
539
553
|
"unsigned",
|
|
540
554
|
"update",
|
|
541
555
|
"use",
|
|
556
|
+
"use_mv",
|
|
542
557
|
"user",
|
|
543
558
|
"using",
|
|
544
559
|
"value",
|
|
@@ -70,6 +70,9 @@ class DremioGenerator(generator.Generator):
|
|
|
70
70
|
exp.DateAdd: _date_delta_sql("DATE_ADD"),
|
|
71
71
|
exp.DateSub: _date_delta_sql("DATE_SUB"),
|
|
72
72
|
exp.GenerateSeries: rename_func("ARRAY_GENERATE_RANGE"),
|
|
73
|
+
exp.RegexpSplit: lambda self, e: self.func(
|
|
74
|
+
"REGEXP_SPLIT", e.this, e.expression, e.args.get("mode"), e.args.get("limit")
|
|
75
|
+
),
|
|
73
76
|
}
|
|
74
77
|
|
|
75
78
|
def version_sql(self, expression: exp.Version) -> str:
|