sqlglotc 30.17.0__tar.gz → 30.18.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.18.0}/PKG-INFO +3 -3
- {sqlglotc-30.17.0 → sqlglotc-30.18.0}/pyproject.toml +2 -2
- {sqlglotc-30.17.0 → sqlglotc-30.18.0}/sqlglot/executor/table.py +1 -1
- {sqlglotc-30.17.0 → sqlglotc-30.18.0}/sqlglot/expressions/builders.py +9 -4
- {sqlglotc-30.17.0 → sqlglotc-30.18.0}/sqlglot/expressions/constraints.py +4 -0
- {sqlglotc-30.17.0 → sqlglotc-30.18.0}/sqlglot/expressions/ddl.py +1 -1
- {sqlglotc-30.17.0 → sqlglotc-30.18.0}/sqlglot/expressions/json.py +4 -0
- {sqlglotc-30.17.0 → sqlglotc-30.18.0}/sqlglot/expressions/query.py +2 -1
- {sqlglotc-30.17.0 → sqlglotc-30.18.0}/sqlglot/expressions/string.py +2 -1
- {sqlglotc-30.17.0 → sqlglotc-30.18.0}/sqlglot/generator.py +50 -8
- {sqlglotc-30.17.0 → sqlglotc-30.18.0}/sqlglot/generators/clickhouse.py +2 -6
- {sqlglotc-30.17.0 → sqlglotc-30.18.0}/sqlglot/generators/dremio.py +3 -0
- {sqlglotc-30.17.0 → sqlglotc-30.18.0}/sqlglot/generators/duckdb.py +7 -9
- {sqlglotc-30.17.0 → sqlglotc-30.18.0}/sqlglot/generators/hive.py +1 -0
- {sqlglotc-30.17.0 → sqlglotc-30.18.0}/sqlglot/generators/oracle.py +2 -1
- {sqlglotc-30.17.0 → sqlglotc-30.18.0}/sqlglot/generators/postgres.py +8 -4
- {sqlglotc-30.17.0 → sqlglotc-30.18.0}/sqlglot/generators/presto.py +1 -1
- {sqlglotc-30.17.0 → sqlglotc-30.18.0}/sqlglot/generators/python.py +10 -2
- {sqlglotc-30.17.0 → sqlglotc-30.18.0}/sqlglot/generators/snowflake.py +4 -35
- {sqlglotc-30.17.0 → sqlglotc-30.18.0}/sqlglot/generators/sqlite.py +2 -0
- {sqlglotc-30.17.0 → sqlglotc-30.18.0}/sqlglot/generators/teradata.py +2 -3
- {sqlglotc-30.17.0 → sqlglotc-30.18.0}/sqlglot/generators/trino.py +1 -1
- {sqlglotc-30.17.0 → sqlglotc-30.18.0}/sqlglot/generators/tsql.py +11 -1
- {sqlglotc-30.17.0 → sqlglotc-30.18.0}/sqlglot/optimizer/annotate_types.py +29 -15
- {sqlglotc-30.17.0 → sqlglotc-30.18.0}/sqlglot/optimizer/normalize_identifiers.py +33 -11
- {sqlglotc-30.17.0 → sqlglotc-30.18.0}/sqlglot/optimizer/qualify_columns.py +136 -12
- {sqlglotc-30.17.0 → sqlglotc-30.18.0}/sqlglot/optimizer/qualify_tables.py +10 -0
- {sqlglotc-30.17.0 → sqlglotc-30.18.0}/sqlglot/optimizer/resolver.py +2 -3
- {sqlglotc-30.17.0 → sqlglotc-30.18.0}/sqlglot/optimizer/scope.py +8 -4
- {sqlglotc-30.17.0 → sqlglotc-30.18.0}/sqlglot/parser.py +118 -53
- {sqlglotc-30.17.0 → sqlglotc-30.18.0}/sqlglot/parsers/bigquery.py +2 -1
- {sqlglotc-30.17.0 → sqlglotc-30.18.0}/sqlglot/parsers/clickhouse.py +27 -6
- {sqlglotc-30.17.0 → sqlglotc-30.18.0}/sqlglot/parsers/dremio.py +6 -0
- {sqlglotc-30.17.0 → sqlglotc-30.18.0}/sqlglot/parsers/mysql.py +7 -0
- {sqlglotc-30.17.0 → sqlglotc-30.18.0}/sqlglot/parsers/oracle.py +1 -0
- {sqlglotc-30.17.0 → sqlglotc-30.18.0}/sqlglot/parsers/postgres.py +7 -2
- {sqlglotc-30.17.0 → sqlglotc-30.18.0}/sqlglot/parsers/snowflake.py +11 -35
- {sqlglotc-30.17.0 → sqlglotc-30.18.0}/sqlglot/parsers/spark2.py +16 -2
- {sqlglotc-30.17.0 → sqlglotc-30.18.0}/sqlglot/parsers/starrocks.py +3 -0
- {sqlglotc-30.17.0 → sqlglotc-30.18.0}/sqlglot/parsers/teradata.py +1 -1
- {sqlglotc-30.17.0 → sqlglotc-30.18.0}/sqlglot/parsers/tsql.py +3 -1
- {sqlglotc-30.17.0 → sqlglotc-30.18.0/sqlglotc.egg-info}/PKG-INFO +3 -3
- sqlglotc-30.18.0/sqlglotc.egg-info/requires.txt +6 -0
- sqlglotc-30.18.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.18.0}/MANIFEST.in +0 -0
- {sqlglotc-30.17.0 → sqlglotc-30.18.0}/setup.cfg +0 -0
- {sqlglotc-30.17.0 → sqlglotc-30.18.0}/setup.py +0 -0
- {sqlglotc-30.17.0 → sqlglotc-30.18.0}/sqlglot/anonymize.py +0 -0
- {sqlglotc-30.17.0 → sqlglotc-30.18.0}/sqlglot/errors.py +0 -0
- {sqlglotc-30.17.0 → sqlglotc-30.18.0}/sqlglot/expressions/aggregate.py +0 -0
- {sqlglotc-30.17.0 → sqlglotc-30.18.0}/sqlglot/expressions/array.py +0 -0
- {sqlglotc-30.17.0 → sqlglotc-30.18.0}/sqlglot/expressions/core.py +0 -0
- {sqlglotc-30.17.0 → sqlglotc-30.18.0}/sqlglot/expressions/datatypes.py +0 -0
- {sqlglotc-30.17.0 → sqlglotc-30.18.0}/sqlglot/expressions/dml.py +0 -0
- {sqlglotc-30.17.0 → sqlglotc-30.18.0}/sqlglot/expressions/functions.py +0 -0
- {sqlglotc-30.17.0 → sqlglotc-30.18.0}/sqlglot/expressions/math.py +0 -0
- {sqlglotc-30.17.0 → sqlglotc-30.18.0}/sqlglot/expressions/properties.py +0 -0
- {sqlglotc-30.17.0 → sqlglotc-30.18.0}/sqlglot/expressions/temporal.py +0 -0
- {sqlglotc-30.17.0 → sqlglotc-30.18.0}/sqlglot/generators/athena.py +0 -0
- {sqlglotc-30.17.0 → sqlglotc-30.18.0}/sqlglot/generators/bigquery.py +0 -0
- {sqlglotc-30.17.0 → sqlglotc-30.18.0}/sqlglot/generators/databricks.py +0 -0
- {sqlglotc-30.17.0 → sqlglotc-30.18.0}/sqlglot/generators/dax.py +0 -0
- {sqlglotc-30.17.0 → sqlglotc-30.18.0}/sqlglot/generators/doris.py +0 -0
- {sqlglotc-30.17.0 → sqlglotc-30.18.0}/sqlglot/generators/drill.py +0 -0
- {sqlglotc-30.17.0 → sqlglotc-30.18.0}/sqlglot/generators/druid.py +0 -0
- {sqlglotc-30.17.0 → sqlglotc-30.18.0}/sqlglot/generators/dune.py +0 -0
- {sqlglotc-30.17.0 → sqlglotc-30.18.0}/sqlglot/generators/exasol.py +0 -0
- {sqlglotc-30.17.0 → sqlglotc-30.18.0}/sqlglot/generators/fabric.py +0 -0
- {sqlglotc-30.17.0 → sqlglotc-30.18.0}/sqlglot/generators/materialize.py +0 -0
- {sqlglotc-30.17.0 → sqlglotc-30.18.0}/sqlglot/generators/mysql.py +0 -0
- {sqlglotc-30.17.0 → sqlglotc-30.18.0}/sqlglot/generators/prql.py +0 -0
- {sqlglotc-30.17.0 → sqlglotc-30.18.0}/sqlglot/generators/redshift.py +0 -0
- {sqlglotc-30.17.0 → sqlglotc-30.18.0}/sqlglot/generators/risingwave.py +0 -0
- {sqlglotc-30.17.0 → sqlglotc-30.18.0}/sqlglot/generators/singlestore.py +0 -0
- {sqlglotc-30.17.0 → sqlglotc-30.18.0}/sqlglot/generators/solr.py +0 -0
- {sqlglotc-30.17.0 → sqlglotc-30.18.0}/sqlglot/generators/spark.py +0 -0
- {sqlglotc-30.17.0 → sqlglotc-30.18.0}/sqlglot/generators/spark2.py +0 -0
- {sqlglotc-30.17.0 → sqlglotc-30.18.0}/sqlglot/generators/starrocks.py +0 -0
- {sqlglotc-30.17.0 → sqlglotc-30.18.0}/sqlglot/generators/tableau.py +0 -0
- {sqlglotc-30.17.0 → sqlglotc-30.18.0}/sqlglot/helper.py +0 -0
- {sqlglotc-30.17.0 → sqlglotc-30.18.0}/sqlglot/lineage.py +0 -0
- {sqlglotc-30.17.0 → sqlglotc-30.18.0}/sqlglot/optimizer/canonicalize_internal_names.py +0 -0
- {sqlglotc-30.17.0 → sqlglotc-30.18.0}/sqlglot/optimizer/isolate_table_selects.py +0 -0
- {sqlglotc-30.17.0 → sqlglotc-30.18.0}/sqlglot/optimizer/qualify.py +0 -0
- {sqlglotc-30.17.0 → sqlglotc-30.18.0}/sqlglot/optimizer/simplify.py +0 -0
- {sqlglotc-30.17.0 → sqlglotc-30.18.0}/sqlglot/parsers/athena.py +0 -0
- {sqlglotc-30.17.0 → sqlglotc-30.18.0}/sqlglot/parsers/base.py +0 -0
- {sqlglotc-30.17.0 → sqlglotc-30.18.0}/sqlglot/parsers/databricks.py +0 -0
- {sqlglotc-30.17.0 → sqlglotc-30.18.0}/sqlglot/parsers/dax.py +0 -0
- {sqlglotc-30.17.0 → sqlglotc-30.18.0}/sqlglot/parsers/doris.py +0 -0
- {sqlglotc-30.17.0 → sqlglotc-30.18.0}/sqlglot/parsers/drill.py +0 -0
- {sqlglotc-30.17.0 → sqlglotc-30.18.0}/sqlglot/parsers/druid.py +0 -0
- {sqlglotc-30.17.0 → sqlglotc-30.18.0}/sqlglot/parsers/duckdb.py +0 -0
- {sqlglotc-30.17.0 → sqlglotc-30.18.0}/sqlglot/parsers/dune.py +0 -0
- {sqlglotc-30.17.0 → sqlglotc-30.18.0}/sqlglot/parsers/exasol.py +0 -0
- {sqlglotc-30.17.0 → sqlglotc-30.18.0}/sqlglot/parsers/fabric.py +0 -0
- {sqlglotc-30.17.0 → sqlglotc-30.18.0}/sqlglot/parsers/hive.py +0 -0
- {sqlglotc-30.17.0 → sqlglotc-30.18.0}/sqlglot/parsers/materialize.py +0 -0
- {sqlglotc-30.17.0 → sqlglotc-30.18.0}/sqlglot/parsers/presto.py +0 -0
- {sqlglotc-30.17.0 → sqlglotc-30.18.0}/sqlglot/parsers/prql.py +0 -0
- {sqlglotc-30.17.0 → sqlglotc-30.18.0}/sqlglot/parsers/redshift.py +0 -0
- {sqlglotc-30.17.0 → sqlglotc-30.18.0}/sqlglot/parsers/risingwave.py +0 -0
- {sqlglotc-30.17.0 → sqlglotc-30.18.0}/sqlglot/parsers/singlestore.py +0 -0
- {sqlglotc-30.17.0 → sqlglotc-30.18.0}/sqlglot/parsers/solr.py +0 -0
- {sqlglotc-30.17.0 → sqlglotc-30.18.0}/sqlglot/parsers/spark.py +0 -0
- {sqlglotc-30.17.0 → sqlglotc-30.18.0}/sqlglot/parsers/sqlite.py +0 -0
- {sqlglotc-30.17.0 → sqlglotc-30.18.0}/sqlglot/parsers/tableau.py +0 -0
- {sqlglotc-30.17.0 → sqlglotc-30.18.0}/sqlglot/parsers/trino.py +0 -0
- {sqlglotc-30.17.0 → sqlglotc-30.18.0}/sqlglot/schema.py +0 -0
- {sqlglotc-30.17.0 → sqlglotc-30.18.0}/sqlglot/serde.py +0 -0
- {sqlglotc-30.17.0 → sqlglotc-30.18.0}/sqlglot/time.py +0 -0
- {sqlglotc-30.17.0 → sqlglotc-30.18.0}/sqlglot/tokenizer_core.py +0 -0
- {sqlglotc-30.17.0 → sqlglotc-30.18.0}/sqlglot/trie.py +0 -0
- {sqlglotc-30.17.0 → sqlglotc-30.18.0}/sqlglotc.egg-info/SOURCES.txt +0 -0
- {sqlglotc-30.17.0 → sqlglotc-30.18.0}/sqlglotc.egg-info/dependency_links.txt +0 -0
- {sqlglotc-30.17.0 → sqlglotc-30.18.0}/sqlglotc.egg-info/scm_file_list.json +0 -0
- {sqlglotc-30.17.0 → sqlglotc-30.18.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.18.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.18.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
|
]
|
|
@@ -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
|
|
|
@@ -624,6 +624,7 @@ class Group(Expression):
|
|
|
624
624
|
arg_types = {
|
|
625
625
|
"expressions": False,
|
|
626
626
|
"grouping_sets": False,
|
|
627
|
+
"grouping_sets_as_group_by_element": False,
|
|
627
628
|
"cube": False,
|
|
628
629
|
"rollup": False,
|
|
629
630
|
"totals": False,
|
|
@@ -1891,7 +1892,7 @@ class Where(Expression):
|
|
|
1891
1892
|
class Analyze(Expression):
|
|
1892
1893
|
arg_types = {
|
|
1893
1894
|
"kind": False,
|
|
1894
|
-
"
|
|
1895
|
+
"tables": False,
|
|
1895
1896
|
"options": False,
|
|
1896
1897
|
"mode": False,
|
|
1897
1898
|
"partition": False,
|
|
@@ -478,7 +478,8 @@ class RegexpReplace(Expression, Func):
|
|
|
478
478
|
|
|
479
479
|
|
|
480
480
|
class RegexpSplit(Expression, Func):
|
|
481
|
-
|
|
481
|
+
# "mode" is Dremio-specific, appended after "limit" for from_arg_list compat
|
|
482
|
+
arg_types = {"this": True, "expression": True, "limit": False, "mode": False}
|
|
482
483
|
|
|
483
484
|
|
|
484
485
|
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
|
|
|
@@ -850,6 +855,16 @@ class Generator:
|
|
|
850
855
|
|
|
851
856
|
RESPECT_IGNORE_NULLS_UNSUPPORTED_EXPRESSIONS: t.ClassVar[tuple[type[exp.Expr], ...]] = ()
|
|
852
857
|
|
|
858
|
+
MOD_OPERATOR = "%"
|
|
859
|
+
|
|
860
|
+
# Infix operators that bind at least as tightly as %, so a Mod on their right side needs parentheses
|
|
861
|
+
MOD_PAREN_PARENT_TYPES: t.ClassVar[tuple[type[exp.Expr], ...]] = (
|
|
862
|
+
exp.Mul,
|
|
863
|
+
exp.Div,
|
|
864
|
+
exp.IntDiv,
|
|
865
|
+
exp.Mod,
|
|
866
|
+
)
|
|
867
|
+
|
|
853
868
|
SAFE_JSON_PATH_KEY_RE: t.ClassVar = exp.SAFE_IDENTIFIER_RE
|
|
854
869
|
|
|
855
870
|
SENTINEL_LINE_BREAK = "__SQLGLOT__LB__"
|
|
@@ -1826,7 +1841,7 @@ class Generator:
|
|
|
1826
1841
|
return self.prepend_ctes(expression, f"DELETE{hint}{tables}{expression_sql}")
|
|
1827
1842
|
|
|
1828
1843
|
def drop_sql(self, expression: exp.Drop) -> str:
|
|
1829
|
-
|
|
1844
|
+
tables = self.expressions(expression, key="tables", flat=True)
|
|
1830
1845
|
expressions = self.expressions(expression, flat=True)
|
|
1831
1846
|
expressions = f" ({expressions})" if expressions else ""
|
|
1832
1847
|
kind = expression.args["kind"]
|
|
@@ -1848,7 +1863,7 @@ class Generator:
|
|
|
1848
1863
|
purge = " PURGE" if expression.args.get("purge") else ""
|
|
1849
1864
|
sync = " SYNC" if expression.args.get("sync") else ""
|
|
1850
1865
|
force = " FORCE" if expression.args.get("force") else ""
|
|
1851
|
-
return f"DROP{temporary}{materialized}{iceberg} {kind}{concurrently_sql}{exists_sql}{
|
|
1866
|
+
return f"DROP{temporary}{materialized}{iceberg} {kind}{concurrently_sql}{exists_sql}{tables}{on_cluster}{expressions}{cascade}{restrict}{constraints}{purge}{sync}{force}"
|
|
1852
1867
|
|
|
1853
1868
|
def set_operation(self, expression: exp.SetOperation) -> str:
|
|
1854
1869
|
op_type = type(expression)
|
|
@@ -2819,7 +2834,18 @@ class Generator:
|
|
|
2819
2834
|
and groupings
|
|
2820
2835
|
and groupings.strip() not in ("WITH CUBE", "WITH ROLLUP")
|
|
2821
2836
|
):
|
|
2822
|
-
|
|
2837
|
+
add_separator = True
|
|
2838
|
+
|
|
2839
|
+
if grouping_sets and not expression.args.get("grouping_sets_as_group_by_element"):
|
|
2840
|
+
if self.SUPPORTS_GROUPING_SETS_AS_SUFFIX:
|
|
2841
|
+
add_separator = False
|
|
2842
|
+
else:
|
|
2843
|
+
self.unsupported(
|
|
2844
|
+
"GROUPING SETS without a comma after GROUP BY expressions is not supported"
|
|
2845
|
+
)
|
|
2846
|
+
|
|
2847
|
+
if add_separator:
|
|
2848
|
+
group_by = f"{group_by}{self.GROUPINGS_SEP}"
|
|
2823
2849
|
|
|
2824
2850
|
return f"{group_by}{groupings}"
|
|
2825
2851
|
|
|
@@ -4587,7 +4613,15 @@ class Generator:
|
|
|
4587
4613
|
return self.binary(expression, "<=")
|
|
4588
4614
|
|
|
4589
4615
|
def mod_sql(self, expression: exp.Mod) -> str:
|
|
4590
|
-
|
|
4616
|
+
this = self.sql(expression, "this")
|
|
4617
|
+
expr = self.sql(expression, "expression")
|
|
4618
|
+
sql = f"{this} {self.maybe_comment(self.MOD_OPERATOR, comments=expression.comments)} {expr}"
|
|
4619
|
+
|
|
4620
|
+
parent = expression.parent
|
|
4621
|
+
if isinstance(parent, self.MOD_PAREN_PARENT_TYPES) and parent.expression is expression:
|
|
4622
|
+
return f"({sql})"
|
|
4623
|
+
|
|
4624
|
+
return sql
|
|
4591
4625
|
|
|
4592
4626
|
def mul_sql(self, expression: exp.Mul) -> str:
|
|
4593
4627
|
return self.binary(expression, "*")
|
|
@@ -5035,6 +5069,12 @@ class Generator:
|
|
|
5035
5069
|
|
|
5036
5070
|
return self.sql(case)
|
|
5037
5071
|
|
|
5072
|
+
def nthvalue_sql(self, expression: exp.NthValue) -> str:
|
|
5073
|
+
if expression.args.get("from_first") is False:
|
|
5074
|
+
self.unsupported("NTH_VALUE FROM LAST is not supported")
|
|
5075
|
+
|
|
5076
|
+
return self.function_fallback_sql(expression)
|
|
5077
|
+
|
|
5038
5078
|
def comprehension_sql(self, expression: exp.Comprehension) -> str:
|
|
5039
5079
|
this = self.sql(expression, "this")
|
|
5040
5080
|
expr = self.sql(expression, "expression")
|
|
@@ -5395,9 +5435,11 @@ class Generator:
|
|
|
5395
5435
|
|
|
5396
5436
|
if self.IGNORE_NULLS_IN_FUNC and not expression.meta_get("inline"):
|
|
5397
5437
|
if self.IGNORE_NULLS_BEFORE_ORDER:
|
|
5438
|
+
from sqlglot.optimizer.scope import find_all_in_scope
|
|
5439
|
+
|
|
5398
5440
|
# The first modifier here will be the one closest to the AggFunc's arg
|
|
5399
5441
|
mods = sorted(
|
|
5400
|
-
expression
|
|
5442
|
+
find_all_in_scope(expression, exp.HavingMax, exp.Order, exp.Limit),
|
|
5401
5443
|
key=lambda x: (
|
|
5402
5444
|
0
|
|
5403
5445
|
if isinstance(x, exp.HavingMax)
|
|
@@ -6037,8 +6079,8 @@ class Generator:
|
|
|
6037
6079
|
options = f" {options}" if options else ""
|
|
6038
6080
|
kind = self.sql(expression, "kind")
|
|
6039
6081
|
kind = f" {kind}" if kind else ""
|
|
6040
|
-
|
|
6041
|
-
|
|
6082
|
+
tables = self.expressions(expression, key="tables", flat=True)
|
|
6083
|
+
tables = f" {tables}" if tables else ""
|
|
6042
6084
|
mode = self.sql(expression, "mode")
|
|
6043
6085
|
mode = f" {mode}" if mode else ""
|
|
6044
6086
|
properties = self.sql(expression, "properties")
|
|
@@ -6047,7 +6089,7 @@ class Generator:
|
|
|
6047
6089
|
partition = f" {partition}" if partition else ""
|
|
6048
6090
|
inner_expression = self.sql(expression, "expression")
|
|
6049
6091
|
inner_expression = f" {inner_expression}" if inner_expression else ""
|
|
6050
|
-
return f"ANALYZE{options}{kind}{
|
|
6092
|
+
return f"ANALYZE{options}{kind}{tables}{partition}{mode}{inner_expression}{properties}"
|
|
6051
6093
|
|
|
6052
6094
|
def xmltable_sql(self, expression: exp.XMLTable) -> str:
|
|
6053
6095
|
this = self.sql(expression, "this")
|
|
@@ -372,12 +372,8 @@ class ClickHouseGenerator(generator.Generator):
|
|
|
372
372
|
exp.SchemaCommentProperty: lambda self, e: self.naked_property(e),
|
|
373
373
|
exp.Stddev: rename_func("stddevSamp"),
|
|
374
374
|
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
|
-
),
|
|
375
|
+
exp.Lag: rename_func("lag"),
|
|
376
|
+
exp.Lead: rename_func("lead"),
|
|
381
377
|
exp.Levenshtein: unsupported_args("ins_cost", "del_cost", "sub_cost", "max_dist")(
|
|
382
378
|
rename_func("editDistance")
|
|
383
379
|
),
|
|
@@ -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:
|
|
@@ -10,10 +10,10 @@ from sqlglot.dialects.dialect import (
|
|
|
10
10
|
DATETIME_DELTA,
|
|
11
11
|
JSON_EXTRACT_TYPE,
|
|
12
12
|
approx_count_distinct_sql,
|
|
13
|
+
arrow_json_extract_sql,
|
|
13
14
|
array_append_sql,
|
|
14
15
|
array_compact_sql,
|
|
15
16
|
array_concat_sql,
|
|
16
|
-
arrow_json_extract_sql,
|
|
17
17
|
count_if_to_sum,
|
|
18
18
|
date_delta_to_binary_interval_op,
|
|
19
19
|
datestrtodate_sql,
|
|
@@ -2469,13 +2469,6 @@ class DuckDBGenerator(generator.Generator):
|
|
|
2469
2469
|
|
|
2470
2470
|
return self.sql(result)
|
|
2471
2471
|
|
|
2472
|
-
def nthvalue_sql(self, expression: exp.NthValue) -> str:
|
|
2473
|
-
from_first = expression.args.get("from_first", True)
|
|
2474
|
-
if not from_first:
|
|
2475
|
-
self.unsupported("DuckDB's NTH_VALUE doesn't support starting from the end ")
|
|
2476
|
-
|
|
2477
|
-
return self.function_fallback_sql(expression)
|
|
2478
|
-
|
|
2479
2472
|
def randstr_sql(self, expression: exp.Randstr) -> str:
|
|
2480
2473
|
"""
|
|
2481
2474
|
Transpile Snowflake's RANDSTR to DuckDB equivalent using deterministic hash-based random.
|
|
@@ -4720,9 +4713,14 @@ class DuckDBGenerator(generator.Generator):
|
|
|
4720
4713
|
|
|
4721
4714
|
def jsonextractscalar_sql(self, expression: exp.JSONExtractScalar) -> str:
|
|
4722
4715
|
if expression.args.get("scalar_only"):
|
|
4723
|
-
|
|
4716
|
+
json_value = exp.JSONExtractScalar(
|
|
4724
4717
|
this=rename_func("JSON_VALUE")(self, expression), expression="'$'"
|
|
4725
4718
|
)
|
|
4719
|
+
|
|
4720
|
+
# `->>` binds looser than most operators, so the wrap logic needs the parent
|
|
4721
|
+
json_value.parent = expression.parent
|
|
4722
|
+
expression = json_value
|
|
4723
|
+
|
|
4726
4724
|
return _arrow_json_extract_sql(self, expression)
|
|
4727
4725
|
|
|
4728
4726
|
def bitwisenot_sql(self, expression: exp.BitwiseNot) -> str:
|
|
@@ -223,6 +223,7 @@ class HiveGenerator(generator.Generator):
|
|
|
223
223
|
SELECT_KINDS: tuple[str, ...] = ()
|
|
224
224
|
TRY_SUPPORTED = False
|
|
225
225
|
SUPPORTS_UESCAPE = False
|
|
226
|
+
SUPPORTS_GROUPING_SETS_AS_SUFFIX = True
|
|
226
227
|
SUPPORTS_DECODE_CASE = False
|
|
227
228
|
LIMIT_FETCH = "LIMIT"
|
|
228
229
|
TABLESAMPLE_WITH_METHOD = False
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
|
-
|
|
4
3
|
from sqlglot import exp, generator, transforms
|
|
5
4
|
from sqlglot.dialects.dialect import (
|
|
6
5
|
groupconcat_sql,
|
|
7
6
|
no_ilike_sql,
|
|
7
|
+
nth_value_from_sql,
|
|
8
8
|
rename_func,
|
|
9
9
|
strposition_sql,
|
|
10
10
|
trim_sql,
|
|
@@ -77,6 +77,7 @@ class OracleGenerator(generator.Generator):
|
|
|
77
77
|
exp.LogicalOr: rename_func("MAX"),
|
|
78
78
|
exp.LogicalAnd: rename_func("MIN"),
|
|
79
79
|
exp.Mod: rename_func("MOD"),
|
|
80
|
+
exp.NthValue: nth_value_from_sql,
|
|
80
81
|
exp.Rand: rename_func("DBMS_RANDOM.VALUE"),
|
|
81
82
|
exp.Select: transforms.preprocess(
|
|
82
83
|
[
|
|
@@ -7,6 +7,7 @@ from sqlglot.dialects.dialect import (
|
|
|
7
7
|
DATE_ADD_OR_SUB,
|
|
8
8
|
JSON_EXTRACT_TYPE,
|
|
9
9
|
any_value_to_max_sql,
|
|
10
|
+
arrow_json_extract_sql,
|
|
10
11
|
array_append_sql,
|
|
11
12
|
array_concat_sql,
|
|
12
13
|
bool_xor_sql,
|
|
@@ -189,7 +190,11 @@ def _json_extract_sql(
|
|
|
189
190
|
if not isinstance(path, (exp.JSONPath, exp.Variadic)) and not ensure_list(
|
|
190
191
|
expression.args.get("expressions")
|
|
191
192
|
):
|
|
192
|
-
return self
|
|
193
|
+
return arrow_json_extract_sql(self, expression, op=op)
|
|
194
|
+
|
|
195
|
+
# JSON_EXTRACT_PATH requires a key, so use an empty variadic array for the root path
|
|
196
|
+
if len(path.expressions) == 1 and isinstance(path.expressions[0], exp.JSONPathRoot):
|
|
197
|
+
expression.set("expression", exp.Variadic(this=exp.Literal.string("{}")))
|
|
193
198
|
|
|
194
199
|
if expression.args.get("only_json_types"):
|
|
195
200
|
return json_extract_segments(name, quoted_index=False, op=op)(self, expression)
|
|
@@ -347,9 +352,8 @@ class PostgresGenerator(generator.Generator):
|
|
|
347
352
|
),
|
|
348
353
|
exp.JSONExtract: _json_extract_sql("JSON_EXTRACT_PATH", "->"),
|
|
349
354
|
exp.JSONExtractScalar: _json_extract_sql("JSON_EXTRACT_PATH_TEXT", "->>"),
|
|
350
|
-
exp.JSONBExtract: lambda self, e: self
|
|
351
|
-
exp.JSONBExtractScalar: lambda self, e: self
|
|
352
|
-
exp.JSONBContains: lambda self, e: self.binary(e, "?"),
|
|
355
|
+
exp.JSONBExtract: lambda self, e: arrow_json_extract_sql(self, e, op="#>"),
|
|
356
|
+
exp.JSONBExtractScalar: lambda self, e: arrow_json_extract_sql(self, e, op="#>>"),
|
|
353
357
|
exp.ParseJSON: lambda self, e: self.sql(exp.cast(e.this, exp.DType.JSON)),
|
|
354
358
|
exp.JSONPathKey: json_path_key_only_name,
|
|
355
359
|
exp.JSONPathRoot: lambda *_: "",
|
|
@@ -383,7 +383,7 @@ class PrestoGenerator(generator.Generator):
|
|
|
383
383
|
transforms.eliminate_window_clause,
|
|
384
384
|
transforms.eliminate_qualify,
|
|
385
385
|
transforms.eliminate_distinct_on,
|
|
386
|
-
transforms.explode_projection_to_unnest(1),
|
|
386
|
+
transforms.explode_projection_to_unnest(1, unnest_map=True),
|
|
387
387
|
transforms.eliminate_semi_and_anti_joins,
|
|
388
388
|
amend_exploded_column_table,
|
|
389
389
|
]
|
|
@@ -43,7 +43,7 @@ def _case_sql(self, expression):
|
|
|
43
43
|
condition = f"{this} = ({condition})" if this else condition
|
|
44
44
|
chain = f"{true} if {condition} else ({chain})"
|
|
45
45
|
|
|
46
|
-
return chain
|
|
46
|
+
return f"({chain})"
|
|
47
47
|
|
|
48
48
|
|
|
49
49
|
def _lambda_sql(self, e: exp.Lambda) -> str:
|
|
@@ -78,11 +78,18 @@ def _div_sql(self: generator.Generator, e: exp.Div) -> str:
|
|
|
78
78
|
if e.args.get("typed") and not (
|
|
79
79
|
e.this.is_type(*exp.DataType.REAL_TYPES) or e.expression.is_type(*exp.DataType.REAL_TYPES)
|
|
80
80
|
):
|
|
81
|
-
sql = f"
|
|
81
|
+
sql = f"INT({sql})"
|
|
82
82
|
|
|
83
83
|
return sql
|
|
84
84
|
|
|
85
85
|
|
|
86
|
+
def _dpipe_sql(self: generator.Generator, e: exp.DPipe) -> str:
|
|
87
|
+
if e.this.is_type(exp.DataType.Type.ARRAY) or e.expression.is_type(exp.DataType.Type.ARRAY):
|
|
88
|
+
return self.func("ARRAYCONCAT", e.this, e.expression)
|
|
89
|
+
|
|
90
|
+
return self.func("SAFECONCAT" if e.args.get("safe") else "CONCAT", e.this, e.expression)
|
|
91
|
+
|
|
92
|
+
|
|
86
93
|
class PythonGenerator(generator.Generator):
|
|
87
94
|
TRANSFORMS = {
|
|
88
95
|
**{klass: _rename for klass in subclasses(exp.__name__, exp.Binary)},
|
|
@@ -100,6 +107,7 @@ class PythonGenerator(generator.Generator):
|
|
|
100
107
|
),
|
|
101
108
|
exp.Distinct: lambda self, e: f"set({self.sql(e, 'this')})",
|
|
102
109
|
exp.Div: _div_sql,
|
|
110
|
+
exp.DPipe: _dpipe_sql,
|
|
103
111
|
exp.Extract: lambda self, e: f"EXTRACT('{e.name.lower()}', {self.sql(e, 'expression')})",
|
|
104
112
|
exp.ILike: _like_sql,
|
|
105
113
|
exp.In: lambda self, e: self.func("IN", e.this, *e.expressions),
|
|
@@ -17,6 +17,7 @@ from sqlglot.dialects.dialect import (
|
|
|
17
17
|
min_or_least,
|
|
18
18
|
no_make_interval_sql,
|
|
19
19
|
no_timestamp_sql,
|
|
20
|
+
nth_value_from_sql,
|
|
20
21
|
rename_func,
|
|
21
22
|
strposition_sql,
|
|
22
23
|
timestampdiff_sql,
|
|
@@ -96,25 +97,6 @@ def _unqualify_pivot_columns(expression: exp.Expr) -> exp.Expr:
|
|
|
96
97
|
return expression
|
|
97
98
|
|
|
98
99
|
|
|
99
|
-
def _flatten_structured_types_unless_iceberg(expression: exp.Expr) -> exp.Expr:
|
|
100
|
-
assert isinstance(expression, exp.Create)
|
|
101
|
-
|
|
102
|
-
def _flatten_structured_type(expression: exp.Expr) -> exp.Expr:
|
|
103
|
-
if isinstance(expression, exp.DataType) and expression.this in exp.DataType.NESTED_TYPES:
|
|
104
|
-
expression.set("expressions", None)
|
|
105
|
-
return expression
|
|
106
|
-
|
|
107
|
-
props = expression.args.get("properties")
|
|
108
|
-
if isinstance(expression.this, exp.Schema) and not (props and props.find(exp.IcebergProperty)):
|
|
109
|
-
for schema_expression in expression.this.expressions:
|
|
110
|
-
if isinstance(schema_expression, exp.ColumnDef):
|
|
111
|
-
column_type = schema_expression.kind
|
|
112
|
-
if isinstance(column_type, exp.DataType):
|
|
113
|
-
column_type.transform(_flatten_structured_type, copy=False)
|
|
114
|
-
|
|
115
|
-
return expression
|
|
116
|
-
|
|
117
|
-
|
|
118
100
|
def _unnest_generate_date_array(unnest: exp.Unnest) -> None:
|
|
119
101
|
generate_date_array = unnest.expressions[0]
|
|
120
102
|
start = generate_date_array.args.get("start")
|
|
@@ -437,7 +419,6 @@ class SnowflakeGenerator(generator.Generator):
|
|
|
437
419
|
exp.BitwiseNot: rename_func("BITNOT"),
|
|
438
420
|
exp.BitwiseLeftShift: rename_func("BITSHIFTLEFT"),
|
|
439
421
|
exp.BitwiseRightShift: rename_func("BITSHIFTRIGHT"),
|
|
440
|
-
exp.Create: transforms.preprocess([_flatten_structured_types_unless_iceberg]),
|
|
441
422
|
exp.CurrentTimestamp: lambda self, e: (
|
|
442
423
|
self.func("SYSDATE") if e.args.get("sysdate") else self.function_fallback_sql(e)
|
|
443
424
|
),
|
|
@@ -518,6 +499,7 @@ class SnowflakeGenerator(generator.Generator):
|
|
|
518
499
|
exp.MakeInterval: no_make_interval_sql,
|
|
519
500
|
exp.Max: max_or_greatest,
|
|
520
501
|
exp.Min: min_or_least,
|
|
502
|
+
exp.NthValue: nth_value_from_sql,
|
|
521
503
|
exp.ParseJSON: lambda self, e: self.func(
|
|
522
504
|
f"{'TRY_' if e.args.get('safe') else ''}PARSE_JSON", e.this
|
|
523
505
|
),
|
|
@@ -629,19 +611,6 @@ class SnowflakeGenerator(generator.Generator):
|
|
|
629
611
|
nulls_first = None
|
|
630
612
|
return self.func("ARRAY_SORT", expression.this, asc, nulls_first)
|
|
631
613
|
|
|
632
|
-
def nthvalue_sql(self, expression: exp.NthValue) -> str:
|
|
633
|
-
result = self.func("NTH_VALUE", expression.this, expression.args.get("offset"))
|
|
634
|
-
|
|
635
|
-
from_first = expression.args.get("from_first")
|
|
636
|
-
|
|
637
|
-
if from_first is not None:
|
|
638
|
-
if from_first:
|
|
639
|
-
result = result + " FROM FIRST"
|
|
640
|
-
else:
|
|
641
|
-
result = result + " FROM LAST"
|
|
642
|
-
|
|
643
|
-
return result
|
|
644
|
-
|
|
645
614
|
SUPPORTED_JSON_PATH_PARTS = {
|
|
646
615
|
exp.JSONPathKey,
|
|
647
616
|
exp.JSONPathRoot,
|
|
@@ -1179,7 +1148,7 @@ class SnowflakeGenerator(generator.Generator):
|
|
|
1179
1148
|
# Snowflake doesn't support FILTER (WHERE cond), so we rewrite it into an
|
|
1180
1149
|
# equivalent conditional aggregation, i.e. wrap the input values in an IFF
|
|
1181
1150
|
agg = expression.this
|
|
1182
|
-
agg_arg = agg.this
|
|
1151
|
+
agg_arg = seq_get(agg.expressions, 0) if isinstance(agg, exp.Anonymous) else agg.this
|
|
1183
1152
|
cond = expression.expression.this
|
|
1184
1153
|
|
|
1185
1154
|
if isinstance(agg, exp.WithinGroup):
|
|
@@ -1203,7 +1172,7 @@ class SnowflakeGenerator(generator.Generator):
|
|
|
1203
1172
|
# `COUNT(*/t.*) FILTER (WHERE cond)` counts qualifying rows, but a star can't be an IFF
|
|
1204
1173
|
# argument: `IFF(cond, *, NULL)` expands to multiple columns once the table has 2+ of
|
|
1205
1174
|
# them, which Snowflake rejects. Use its native COUNT_IF instead.
|
|
1206
|
-
if isinstance(agg, exp.Count) and agg_arg.is_star:
|
|
1175
|
+
if isinstance(agg, exp.Count) and isinstance(agg_arg, exp.Expression) and agg_arg.is_star:
|
|
1207
1176
|
return self.func("COUNT_IF", cond)
|
|
1208
1177
|
|
|
1209
1178
|
# `DISTINCT` and `ORDER BY` are part of the aggregate's own argument list, so the
|
|
@@ -173,6 +173,7 @@ class SQLiteGenerator(generator.Generator):
|
|
|
173
173
|
exp.LogicalAnd: rename_func("MIN"),
|
|
174
174
|
exp.Pivot: no_pivot_sql,
|
|
175
175
|
exp.Rand: rename_func("RANDOM"),
|
|
176
|
+
exp.RegexpLike: lambda self, e: self.binary(e, "REGEXP"),
|
|
176
177
|
exp.Select: transforms.preprocess(
|
|
177
178
|
[
|
|
178
179
|
_offset_to_limit,
|
|
@@ -372,6 +373,7 @@ class SQLiteGenerator(generator.Generator):
|
|
|
372
373
|
if (
|
|
373
374
|
expression.text("kind").upper() == "RANGE"
|
|
374
375
|
and expression.text("start").upper() == "CURRENT ROW"
|
|
376
|
+
and expression.args.get("end") is None
|
|
375
377
|
):
|
|
376
378
|
return "RANGE CURRENT ROW"
|
|
377
379
|
|
|
@@ -43,6 +43,8 @@ class TeradataGenerator(generator.Generator):
|
|
|
43
43
|
SUPPORTS_DECODE_CASE = False
|
|
44
44
|
|
|
45
45
|
AFTER_HAVING_MODIFIER_TRANSFORMS = generator.AFTER_HAVING_MODIFIER_TRANSFORMS
|
|
46
|
+
MOD_OPERATOR = "MOD"
|
|
47
|
+
MOD_PAREN_PARENT_TYPES = (*generator.Generator.MOD_PAREN_PARENT_TYPES, exp.Pow)
|
|
46
48
|
|
|
47
49
|
LIMIT_IS_TOP = True
|
|
48
50
|
JOIN_HINTS = False
|
|
@@ -127,9 +129,6 @@ class TeradataGenerator(generator.Generator):
|
|
|
127
129
|
sql = f"UPDATE {this}{from_sql} SET {set_sql}{where_sql}"
|
|
128
130
|
return self.prepend_ctes(expression, sql)
|
|
129
131
|
|
|
130
|
-
def mod_sql(self, expression: exp.Mod) -> str:
|
|
131
|
-
return self.binary(expression, "MOD")
|
|
132
|
-
|
|
133
132
|
def rangen_sql(self, expression: exp.RangeN) -> str:
|
|
134
133
|
this = self.sql(expression, "this")
|
|
135
134
|
expressions_sql = self.expressions(expression)
|
|
@@ -34,7 +34,7 @@ class TrinoGenerator(PrestoGenerator):
|
|
|
34
34
|
[
|
|
35
35
|
transforms.eliminate_qualify,
|
|
36
36
|
transforms.eliminate_distinct_on,
|
|
37
|
-
transforms.explode_projection_to_unnest(1),
|
|
37
|
+
transforms.explode_projection_to_unnest(1, unnest_map=True),
|
|
38
38
|
transforms.eliminate_semi_and_anti_joins,
|
|
39
39
|
amend_exploded_column_table,
|
|
40
40
|
]
|
|
@@ -103,7 +103,16 @@ def qualify_derived_table_outputs(expression: exp.Expr) -> exp.Expr:
|
|
|
103
103
|
def _json_extract_sql(
|
|
104
104
|
self: TSQLGenerator, expression: exp.JSONExtract | exp.JSONExtractScalar
|
|
105
105
|
) -> str:
|
|
106
|
+
# JSON_QUERY returns objects and arrays, JSON_VALUE returns scalars. A scalar-only
|
|
107
|
+
# extraction maps to JSON_VALUE; a source that also returns non-scalar values as
|
|
108
|
+
# text (e.g. SQLite's ->>) needs to try both, like a generic JSONExtract does
|
|
109
|
+
if isinstance(expression, exp.JSONExtractScalar) and expression.args.get("scalar_only"):
|
|
110
|
+
return self.func("JSON_VALUE", expression.this, expression.expression)
|
|
111
|
+
|
|
106
112
|
json_query = self.func("JSON_QUERY", expression.this, expression.expression)
|
|
113
|
+
if expression.args.get("json_query"):
|
|
114
|
+
return json_query
|
|
115
|
+
|
|
107
116
|
json_value = self.func("JSON_VALUE", expression.this, expression.expression)
|
|
108
117
|
return self.func("ISNULL", json_query, json_value)
|
|
109
118
|
|
|
@@ -596,7 +605,8 @@ class TSQLGenerator(generator.Generator):
|
|
|
596
605
|
|
|
597
606
|
def drop_sql(self, expression: exp.Drop) -> str:
|
|
598
607
|
if expression.args["kind"] == "VIEW":
|
|
599
|
-
expression.
|
|
608
|
+
for table in expression.args.get("tables") or []:
|
|
609
|
+
table.set("catalog", None)
|
|
600
610
|
return super().drop_sql(expression)
|
|
601
611
|
|
|
602
612
|
def options_modifier(self, expression: exp.Expr) -> str:
|