sqlglotc 30.12.0__tar.gz → 30.13.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.12.0/sqlglotc.egg-info → sqlglotc-30.13.0}/PKG-INFO +3 -3
- {sqlglotc-30.12.0 → sqlglotc-30.13.0}/pyproject.toml +2 -2
- {sqlglotc-30.12.0 → sqlglotc-30.13.0}/setup.py +7 -0
- {sqlglotc-30.12.0 → sqlglotc-30.13.0}/sqlglot/expressions/aggregate.py +5 -4
- {sqlglotc-30.12.0 → sqlglotc-30.13.0}/sqlglot/expressions/constraints.py +5 -0
- {sqlglotc-30.12.0 → sqlglotc-30.13.0}/sqlglot/expressions/ddl.py +1 -1
- {sqlglotc-30.12.0 → sqlglotc-30.13.0}/sqlglot/expressions/math.py +4 -0
- {sqlglotc-30.12.0 → sqlglotc-30.13.0}/sqlglot/expressions/string.py +11 -0
- {sqlglotc-30.12.0 → sqlglotc-30.13.0}/sqlglot/expressions/temporal.py +14 -3
- {sqlglotc-30.12.0 → sqlglotc-30.13.0}/sqlglot/generator.py +27 -15
- {sqlglotc-30.12.0 → sqlglotc-30.13.0}/sqlglot/generators/bigquery.py +30 -0
- {sqlglotc-30.12.0 → sqlglotc-30.13.0}/sqlglot/generators/databricks.py +13 -0
- sqlglotc-30.13.0/sqlglot/generators/dax.py +7 -0
- {sqlglotc-30.12.0 → sqlglotc-30.13.0}/sqlglot/generators/dremio.py +8 -0
- {sqlglotc-30.12.0 → sqlglotc-30.13.0}/sqlglot/generators/drill.py +17 -1
- {sqlglotc-30.12.0 → sqlglotc-30.13.0}/sqlglot/generators/duckdb.py +29 -59
- {sqlglotc-30.12.0 → sqlglotc-30.13.0}/sqlglot/generators/hive.py +78 -27
- {sqlglotc-30.12.0 → sqlglotc-30.13.0}/sqlglot/generators/oracle.py +1 -0
- {sqlglotc-30.12.0 → sqlglotc-30.13.0}/sqlglot/generators/postgres.py +8 -2
- {sqlglotc-30.12.0 → sqlglotc-30.13.0}/sqlglot/generators/presto.py +64 -5
- {sqlglotc-30.12.0 → sqlglotc-30.13.0}/sqlglot/generators/snowflake.py +57 -1
- {sqlglotc-30.12.0 → sqlglotc-30.13.0}/sqlglot/generators/spark.py +0 -1
- {sqlglotc-30.12.0 → sqlglotc-30.13.0}/sqlglot/generators/spark2.py +23 -0
- {sqlglotc-30.12.0 → sqlglotc-30.13.0}/sqlglot/generators/sqlite.py +6 -1
- {sqlglotc-30.12.0 → sqlglotc-30.13.0}/sqlglot/generators/trino.py +1 -0
- {sqlglotc-30.12.0 → sqlglotc-30.13.0}/sqlglot/generators/tsql.py +5 -2
- {sqlglotc-30.12.0 → sqlglotc-30.13.0}/sqlglot/optimizer/annotate_types.py +22 -8
- {sqlglotc-30.12.0 → sqlglotc-30.13.0}/sqlglot/optimizer/canonicalize_internal_names.py +19 -6
- {sqlglotc-30.12.0 → sqlglotc-30.13.0}/sqlglot/optimizer/qualify_columns.py +84 -22
- {sqlglotc-30.12.0 → sqlglotc-30.13.0}/sqlglot/optimizer/resolver.py +23 -10
- {sqlglotc-30.12.0 → sqlglotc-30.13.0}/sqlglot/optimizer/scope.py +4 -2
- {sqlglotc-30.12.0 → sqlglotc-30.13.0}/sqlglot/optimizer/simplify.py +2 -5
- {sqlglotc-30.12.0 → sqlglotc-30.13.0}/sqlglot/parser.py +114 -51
- {sqlglotc-30.12.0 → sqlglotc-30.13.0}/sqlglot/parsers/bigquery.py +32 -18
- {sqlglotc-30.12.0 → sqlglotc-30.13.0}/sqlglot/parsers/clickhouse.py +10 -1
- {sqlglotc-30.12.0 → sqlglotc-30.13.0}/sqlglot/parsers/databricks.py +15 -0
- sqlglotc-30.13.0/sqlglot/parsers/dax.py +48 -0
- {sqlglotc-30.12.0 → sqlglotc-30.13.0}/sqlglot/parsers/drill.py +8 -0
- {sqlglotc-30.12.0 → sqlglotc-30.13.0}/sqlglot/parsers/duckdb.py +4 -0
- {sqlglotc-30.12.0 → sqlglotc-30.13.0}/sqlglot/parsers/exasol.py +1 -1
- {sqlglotc-30.12.0 → sqlglotc-30.13.0}/sqlglot/parsers/hive.py +2 -18
- {sqlglotc-30.12.0 → sqlglotc-30.13.0}/sqlglot/parsers/mysql.py +3 -0
- {sqlglotc-30.12.0 → sqlglotc-30.13.0}/sqlglot/parsers/oracle.py +5 -2
- {sqlglotc-30.12.0 → sqlglotc-30.13.0}/sqlglot/parsers/presto.py +6 -2
- {sqlglotc-30.12.0 → sqlglotc-30.13.0}/sqlglot/parsers/snowflake.py +5 -4
- {sqlglotc-30.12.0 → sqlglotc-30.13.0}/sqlglot/parsers/spark2.py +1 -1
- {sqlglotc-30.12.0 → sqlglotc-30.13.0}/sqlglot/parsers/tsql.py +10 -0
- {sqlglotc-30.12.0 → sqlglotc-30.13.0}/sqlglot/time.py +23 -23
- {sqlglotc-30.12.0 → sqlglotc-30.13.0}/sqlglot/tokenizer_core.py +12 -3
- {sqlglotc-30.12.0 → sqlglotc-30.13.0/sqlglotc.egg-info}/PKG-INFO +3 -3
- {sqlglotc-30.12.0 → sqlglotc-30.13.0}/sqlglotc.egg-info/SOURCES.txt +2 -0
- sqlglotc-30.13.0/sqlglotc.egg-info/requires.txt +6 -0
- {sqlglotc-30.12.0 → sqlglotc-30.13.0}/sqlglotc.egg-info/scm_file_list.json +2 -2
- sqlglotc-30.13.0/sqlglotc.egg-info/scm_version.json +8 -0
- sqlglotc-30.12.0/sqlglotc.egg-info/requires.txt +0 -6
- sqlglotc-30.12.0/sqlglotc.egg-info/scm_version.json +0 -8
- {sqlglotc-30.12.0 → sqlglotc-30.13.0}/MANIFEST.in +0 -0
- {sqlglotc-30.12.0 → sqlglotc-30.13.0}/setup.cfg +0 -0
- {sqlglotc-30.12.0 → sqlglotc-30.13.0}/sqlglot/errors.py +0 -0
- {sqlglotc-30.12.0 → sqlglotc-30.13.0}/sqlglot/executor/table.py +0 -0
- {sqlglotc-30.12.0 → sqlglotc-30.13.0}/sqlglot/expressions/array.py +0 -0
- {sqlglotc-30.12.0 → sqlglotc-30.13.0}/sqlglot/expressions/builders.py +0 -0
- {sqlglotc-30.12.0 → sqlglotc-30.13.0}/sqlglot/expressions/core.py +0 -0
- {sqlglotc-30.12.0 → sqlglotc-30.13.0}/sqlglot/expressions/datatypes.py +0 -0
- {sqlglotc-30.12.0 → sqlglotc-30.13.0}/sqlglot/expressions/dml.py +0 -0
- {sqlglotc-30.12.0 → sqlglotc-30.13.0}/sqlglot/expressions/functions.py +0 -0
- {sqlglotc-30.12.0 → sqlglotc-30.13.0}/sqlglot/expressions/json.py +0 -0
- {sqlglotc-30.12.0 → sqlglotc-30.13.0}/sqlglot/expressions/properties.py +0 -0
- {sqlglotc-30.12.0 → sqlglotc-30.13.0}/sqlglot/expressions/query.py +0 -0
- {sqlglotc-30.12.0 → sqlglotc-30.13.0}/sqlglot/generators/athena.py +0 -0
- {sqlglotc-30.12.0 → sqlglotc-30.13.0}/sqlglot/generators/clickhouse.py +0 -0
- {sqlglotc-30.12.0 → sqlglotc-30.13.0}/sqlglot/generators/doris.py +0 -0
- {sqlglotc-30.12.0 → sqlglotc-30.13.0}/sqlglot/generators/druid.py +0 -0
- {sqlglotc-30.12.0 → sqlglotc-30.13.0}/sqlglot/generators/dune.py +0 -0
- {sqlglotc-30.12.0 → sqlglotc-30.13.0}/sqlglot/generators/exasol.py +0 -0
- {sqlglotc-30.12.0 → sqlglotc-30.13.0}/sqlglot/generators/fabric.py +0 -0
- {sqlglotc-30.12.0 → sqlglotc-30.13.0}/sqlglot/generators/materialize.py +0 -0
- {sqlglotc-30.12.0 → sqlglotc-30.13.0}/sqlglot/generators/mysql.py +0 -0
- {sqlglotc-30.12.0 → sqlglotc-30.13.0}/sqlglot/generators/prql.py +0 -0
- {sqlglotc-30.12.0 → sqlglotc-30.13.0}/sqlglot/generators/python.py +0 -0
- {sqlglotc-30.12.0 → sqlglotc-30.13.0}/sqlglot/generators/redshift.py +0 -0
- {sqlglotc-30.12.0 → sqlglotc-30.13.0}/sqlglot/generators/risingwave.py +0 -0
- {sqlglotc-30.12.0 → sqlglotc-30.13.0}/sqlglot/generators/singlestore.py +0 -0
- {sqlglotc-30.12.0 → sqlglotc-30.13.0}/sqlglot/generators/solr.py +0 -0
- {sqlglotc-30.12.0 → sqlglotc-30.13.0}/sqlglot/generators/starrocks.py +0 -0
- {sqlglotc-30.12.0 → sqlglotc-30.13.0}/sqlglot/generators/tableau.py +0 -0
- {sqlglotc-30.12.0 → sqlglotc-30.13.0}/sqlglot/generators/teradata.py +0 -0
- {sqlglotc-30.12.0 → sqlglotc-30.13.0}/sqlglot/helper.py +0 -0
- {sqlglotc-30.12.0 → sqlglotc-30.13.0}/sqlglot/lineage.py +0 -0
- {sqlglotc-30.12.0 → sqlglotc-30.13.0}/sqlglot/optimizer/isolate_table_selects.py +0 -0
- {sqlglotc-30.12.0 → sqlglotc-30.13.0}/sqlglot/optimizer/normalize_identifiers.py +0 -0
- {sqlglotc-30.12.0 → sqlglotc-30.13.0}/sqlglot/optimizer/qualify.py +0 -0
- {sqlglotc-30.12.0 → sqlglotc-30.13.0}/sqlglot/optimizer/qualify_tables.py +0 -0
- {sqlglotc-30.12.0 → sqlglotc-30.13.0}/sqlglot/parsers/athena.py +0 -0
- {sqlglotc-30.12.0 → sqlglotc-30.13.0}/sqlglot/parsers/base.py +0 -0
- {sqlglotc-30.12.0 → sqlglotc-30.13.0}/sqlglot/parsers/doris.py +0 -0
- {sqlglotc-30.12.0 → sqlglotc-30.13.0}/sqlglot/parsers/dremio.py +0 -0
- {sqlglotc-30.12.0 → sqlglotc-30.13.0}/sqlglot/parsers/druid.py +0 -0
- {sqlglotc-30.12.0 → sqlglotc-30.13.0}/sqlglot/parsers/dune.py +0 -0
- {sqlglotc-30.12.0 → sqlglotc-30.13.0}/sqlglot/parsers/fabric.py +0 -0
- {sqlglotc-30.12.0 → sqlglotc-30.13.0}/sqlglot/parsers/materialize.py +0 -0
- {sqlglotc-30.12.0 → sqlglotc-30.13.0}/sqlglot/parsers/postgres.py +0 -0
- {sqlglotc-30.12.0 → sqlglotc-30.13.0}/sqlglot/parsers/prql.py +0 -0
- {sqlglotc-30.12.0 → sqlglotc-30.13.0}/sqlglot/parsers/redshift.py +0 -0
- {sqlglotc-30.12.0 → sqlglotc-30.13.0}/sqlglot/parsers/risingwave.py +0 -0
- {sqlglotc-30.12.0 → sqlglotc-30.13.0}/sqlglot/parsers/singlestore.py +0 -0
- {sqlglotc-30.12.0 → sqlglotc-30.13.0}/sqlglot/parsers/solr.py +0 -0
- {sqlglotc-30.12.0 → sqlglotc-30.13.0}/sqlglot/parsers/spark.py +0 -0
- {sqlglotc-30.12.0 → sqlglotc-30.13.0}/sqlglot/parsers/sqlite.py +0 -0
- {sqlglotc-30.12.0 → sqlglotc-30.13.0}/sqlglot/parsers/starrocks.py +0 -0
- {sqlglotc-30.12.0 → sqlglotc-30.13.0}/sqlglot/parsers/tableau.py +0 -0
- {sqlglotc-30.12.0 → sqlglotc-30.13.0}/sqlglot/parsers/teradata.py +0 -0
- {sqlglotc-30.12.0 → sqlglotc-30.13.0}/sqlglot/parsers/trino.py +0 -0
- {sqlglotc-30.12.0 → sqlglotc-30.13.0}/sqlglot/schema.py +0 -0
- {sqlglotc-30.12.0 → sqlglotc-30.13.0}/sqlglot/serde.py +0 -0
- {sqlglotc-30.12.0 → sqlglotc-30.13.0}/sqlglot/trie.py +0 -0
- {sqlglotc-30.12.0 → sqlglotc-30.13.0}/sqlglotc.egg-info/dependency_links.txt +0 -0
- {sqlglotc-30.12.0 → sqlglotc-30.13.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.13.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.13.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.1.0.
|
|
14
|
+
Requires-Dist: sqlglot-mypy>=2.1.0.post9; 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.1.0.
|
|
10
|
+
dev = ["setuptools >= 61.0", "setuptools_scm", "sqlglot-mypy >= 2.1.0.post9"]
|
|
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.1.0.
|
|
20
|
+
"sqlglot-mypy >= 2.1.0.post9",
|
|
21
21
|
"types-python-dateutil",
|
|
22
22
|
"sqlglot",
|
|
23
23
|
]
|
|
@@ -90,6 +90,13 @@ def _source_paths():
|
|
|
90
90
|
|
|
91
91
|
|
|
92
92
|
class build_ext(_build_ext):
|
|
93
|
+
def finalize_options(self):
|
|
94
|
+
super().finalize_options()
|
|
95
|
+
# Compile in parallel by default; builds driven by pip (wheel/sdist installs)
|
|
96
|
+
# have no way to pass -j. An explicit -j on the command line still wins.
|
|
97
|
+
if self.parallel is None:
|
|
98
|
+
self.parallel = os.cpu_count() or 1
|
|
99
|
+
|
|
93
100
|
def copy_extensions_to_source(self):
|
|
94
101
|
"""For editable installs, put sqlglot.* .so files in the sqlglot source dir."""
|
|
95
102
|
for ext in self.extensions:
|
|
@@ -102,6 +102,7 @@ class Count(Expression, AggFunc):
|
|
|
102
102
|
|
|
103
103
|
class CountIf(Expression, AggFunc):
|
|
104
104
|
_sql_names = ["COUNT_IF", "COUNTIF"]
|
|
105
|
+
arg_types = {"this": True, "zero_on_all_null": False}
|
|
105
106
|
|
|
106
107
|
|
|
107
108
|
class CovarPop(Expression, AggFunc):
|
|
@@ -255,19 +256,19 @@ class RegrAvgy(Expression, AggFunc):
|
|
|
255
256
|
|
|
256
257
|
|
|
257
258
|
class RegrCount(Expression, AggFunc):
|
|
258
|
-
arg_types = {"this": True, "expression":
|
|
259
|
+
arg_types = {"this": True, "expression": False}
|
|
259
260
|
|
|
260
261
|
|
|
261
262
|
class RegrIntercept(Expression, AggFunc):
|
|
262
|
-
arg_types = {"this": True, "expression":
|
|
263
|
+
arg_types = {"this": True, "expression": False}
|
|
263
264
|
|
|
264
265
|
|
|
265
266
|
class RegrR2(Expression, AggFunc):
|
|
266
|
-
arg_types = {"this": True, "expression":
|
|
267
|
+
arg_types = {"this": True, "expression": False}
|
|
267
268
|
|
|
268
269
|
|
|
269
270
|
class RegrSlope(Expression, AggFunc):
|
|
270
|
-
arg_types = {"this": True, "expression":
|
|
271
|
+
arg_types = {"this": True, "expression": False}
|
|
271
272
|
|
|
272
273
|
|
|
273
274
|
class RegrSxx(Expression, AggFunc):
|
|
@@ -220,6 +220,11 @@ class PrimaryKey(Expression):
|
|
|
220
220
|
arg_types = {"this": False, "expressions": True, "options": False, "include": False}
|
|
221
221
|
|
|
222
222
|
|
|
223
|
+
# https://docs.databricks.com/aws/en/sql/language-manual/sql-ref-syntax-ddl-create-table-constraint
|
|
224
|
+
class TimeseriesKey(Expression):
|
|
225
|
+
pass
|
|
226
|
+
|
|
227
|
+
|
|
223
228
|
class IndexParameters(Expression):
|
|
224
229
|
arg_types = {
|
|
225
230
|
"using": False,
|
|
@@ -477,6 +477,17 @@ class RegexpSplit(Expression, Func):
|
|
|
477
477
|
arg_types = {"this": True, "expression": True, "limit": False}
|
|
478
478
|
|
|
479
479
|
|
|
480
|
+
class RegexpSubstr(Expression, Func):
|
|
481
|
+
arg_types = {
|
|
482
|
+
"this": True,
|
|
483
|
+
"expression": True,
|
|
484
|
+
"position": False,
|
|
485
|
+
"occurrence": False,
|
|
486
|
+
"parameters": False,
|
|
487
|
+
"group": False,
|
|
488
|
+
}
|
|
489
|
+
|
|
490
|
+
|
|
480
491
|
# Hashing / cryptographic
|
|
481
492
|
|
|
482
493
|
|
|
@@ -106,7 +106,7 @@ class DatetimeAdd(Expression, Func, IntervalOp):
|
|
|
106
106
|
|
|
107
107
|
|
|
108
108
|
class DatetimeDiff(Expression, Func, TimeUnit):
|
|
109
|
-
arg_types = {"this": True, "expression": True, "unit": False}
|
|
109
|
+
arg_types = {"this": True, "expression": True, "unit": False, "date_part_boundary": False}
|
|
110
110
|
|
|
111
111
|
|
|
112
112
|
class DatetimeSub(Expression, Func, IntervalOp):
|
|
@@ -441,6 +441,10 @@ class FromISO8601Date(Expression, Func):
|
|
|
441
441
|
_sql_names = ["FROM_ISO8601_DATE"]
|
|
442
442
|
|
|
443
443
|
|
|
444
|
+
class FromISO8601TimestampNanos(Expression, Func):
|
|
445
|
+
_sql_names = ["FROM_ISO8601_TIMESTAMP_NANOS"]
|
|
446
|
+
|
|
447
|
+
|
|
444
448
|
class ParseDatetime(Expression, Func):
|
|
445
449
|
arg_types = {"this": True, "format": False, "zone": False, "default_year": False}
|
|
446
450
|
|
|
@@ -450,11 +454,18 @@ class ParseTime(Expression, Func):
|
|
|
450
454
|
|
|
451
455
|
|
|
452
456
|
class StrToDate(Expression, Func):
|
|
453
|
-
arg_types = {"this": True, "format": False, "safe": False}
|
|
457
|
+
arg_types = {"this": True, "format": False, "safe": False, "default_year": False}
|
|
454
458
|
|
|
455
459
|
|
|
456
460
|
class StrToTime(Expression, Func):
|
|
457
|
-
arg_types = {
|
|
461
|
+
arg_types = {
|
|
462
|
+
"this": True,
|
|
463
|
+
"format": True,
|
|
464
|
+
"zone": False,
|
|
465
|
+
"safe": False,
|
|
466
|
+
"target_type": False,
|
|
467
|
+
"default_year": False,
|
|
468
|
+
}
|
|
458
469
|
|
|
459
470
|
|
|
460
471
|
class StrToUnix(Expression, Func):
|
|
@@ -402,9 +402,6 @@ class Generator:
|
|
|
402
402
|
# UNNEST WITH ORDINALITY (presto) instead of UNNEST WITH OFFSET (bigquery)
|
|
403
403
|
UNNEST_WITH_ORDINALITY = True
|
|
404
404
|
|
|
405
|
-
# Whether FILTER (WHERE cond) can be used for conditional aggregation
|
|
406
|
-
AGGREGATE_FILTER_SUPPORTED = True
|
|
407
|
-
|
|
408
405
|
# Whether JOIN sides (LEFT, RIGHT) are supported in conjunction with SEMI/ANTI join kinds
|
|
409
406
|
SEMI_ANTI_JOIN_WITH_SIDE = True
|
|
410
407
|
|
|
@@ -429,6 +426,9 @@ class Generator:
|
|
|
429
426
|
# The keyword to use when specifying the seed of a sample clause
|
|
430
427
|
TABLESAMPLE_SEED_KEYWORD = "SEED"
|
|
431
428
|
|
|
429
|
+
# Whether the historical data clause (AT ... / BEFORE ...) is generated after the table alias
|
|
430
|
+
HISTORICAL_DATA_POST_ALIAS = False
|
|
431
|
+
|
|
432
432
|
# Whether COLLATE is a function instead of a binary operator
|
|
433
433
|
COLLATE_IS_FUNC = False
|
|
434
434
|
|
|
@@ -1905,16 +1905,9 @@ class Generator:
|
|
|
1905
1905
|
return f"{percent}{rows}{with_ties}"
|
|
1906
1906
|
|
|
1907
1907
|
def filter_sql(self, expression: exp.Filter) -> str:
|
|
1908
|
-
|
|
1909
|
-
|
|
1910
|
-
|
|
1911
|
-
return f"{this} FILTER({where})"
|
|
1912
|
-
|
|
1913
|
-
agg = expression.this
|
|
1914
|
-
agg_arg = agg.this
|
|
1915
|
-
cond = expression.expression.this
|
|
1916
|
-
agg_arg.replace(exp.If(this=cond.copy(), true=agg_arg.copy()))
|
|
1917
|
-
return self.sql(agg)
|
|
1908
|
+
this = self.sql(expression, "this")
|
|
1909
|
+
where = self.sql(expression, "expression").strip()
|
|
1910
|
+
return f"{this} FILTER({where})"
|
|
1918
1911
|
|
|
1919
1912
|
def hint_sql(self, expression: exp.Hint) -> str:
|
|
1920
1913
|
if not self.QUERY_HINTS:
|
|
@@ -2433,7 +2426,10 @@ class Generator:
|
|
|
2433
2426
|
|
|
2434
2427
|
when = self.sql(expression, "when")
|
|
2435
2428
|
if when:
|
|
2436
|
-
|
|
2429
|
+
if self.HISTORICAL_DATA_POST_ALIAS:
|
|
2430
|
+
alias = f"{alias} {when}"
|
|
2431
|
+
else:
|
|
2432
|
+
table = f"{table} {when}"
|
|
2437
2433
|
|
|
2438
2434
|
changes = self.sql(expression, "changes")
|
|
2439
2435
|
changes = f" {changes}" if changes else ""
|
|
@@ -3243,7 +3239,12 @@ class Generator:
|
|
|
3243
3239
|
limit = expression.args.get("limit")
|
|
3244
3240
|
|
|
3245
3241
|
if self.LIMIT_FETCH == "LIMIT" and isinstance(limit, exp.Fetch):
|
|
3246
|
-
|
|
3242
|
+
count = limit.args.get("count")
|
|
3243
|
+
# "FETCH FIRST ROWS ONLY" without a count means one row per the SQL
|
|
3244
|
+
# standard; emitting a bare "LIMIT" here would produce invalid SQL.
|
|
3245
|
+
limit = exp.Limit(
|
|
3246
|
+
expression=exp.maybe_copy(count) if count is not None else exp.Literal.number(1)
|
|
3247
|
+
)
|
|
3247
3248
|
elif self.LIMIT_FETCH == "FETCH" and isinstance(limit, exp.Limit):
|
|
3248
3249
|
limit = exp.Fetch(direction="FIRST", count=exp.maybe_copy(limit.expression))
|
|
3249
3250
|
|
|
@@ -3723,6 +3724,10 @@ class Generator:
|
|
|
3723
3724
|
options = f" {options}" if options else ""
|
|
3724
3725
|
return f"PRIMARY KEY{this} ({expressions}){include}{options}"
|
|
3725
3726
|
|
|
3727
|
+
def timeserieskey_sql(self, expression: exp.TimeseriesKey) -> str:
|
|
3728
|
+
self.unsupported("TIMESERIES primary key columns are not supported")
|
|
3729
|
+
return self.sql(expression, "this")
|
|
3730
|
+
|
|
3726
3731
|
def if_sql(self, expression: exp.If) -> str:
|
|
3727
3732
|
return self.case_sql(exp.Case(ifs=[expression], default=expression.args.get("false")))
|
|
3728
3733
|
|
|
@@ -4008,6 +4013,9 @@ class Generator:
|
|
|
4008
4013
|
def fromiso8601timestamp_sql(self, expression: exp.FromISO8601Timestamp) -> str:
|
|
4009
4014
|
return self.sql(exp.cast(expression.this, exp.DType.TIMESTAMPTZ))
|
|
4010
4015
|
|
|
4016
|
+
def fromiso8601timestampnanos_sql(self, expression: exp.FromISO8601TimestampNanos) -> str:
|
|
4017
|
+
return self.sql(exp.cast(expression.this, exp.DType.TIMESTAMPTZ))
|
|
4018
|
+
|
|
4011
4019
|
def add_sql(self, expression: exp.Add) -> str:
|
|
4012
4020
|
return self.binary(expression, "+")
|
|
4013
4021
|
|
|
@@ -4087,6 +4095,10 @@ class Generator:
|
|
|
4087
4095
|
def strtotime_sql(self, expression: exp.StrToTime) -> str:
|
|
4088
4096
|
return self.func("STR_TO_TIME", expression.this, expression.args.get("format"))
|
|
4089
4097
|
|
|
4098
|
+
# Base implementation that excludes the safe and default_year metadata args
|
|
4099
|
+
def strtodate_sql(self, expression: exp.StrToDate) -> str:
|
|
4100
|
+
return self.func("STR_TO_DATE", expression.this, expression.args.get("format"))
|
|
4101
|
+
|
|
4090
4102
|
def parsedatetime_sql(self, expression: exp.ParseDatetime) -> str:
|
|
4091
4103
|
return self.func(
|
|
4092
4104
|
"PARSE_DATETIME",
|
|
@@ -137,6 +137,34 @@ def _pushdown_cte_column_names(expression: exp.Expr) -> exp.Expr:
|
|
|
137
137
|
return expression
|
|
138
138
|
|
|
139
139
|
|
|
140
|
+
def _unnest_explode_generate_series(expression: exp.Expr) -> exp.Expr:
|
|
141
|
+
"""
|
|
142
|
+
Rewrites exploding GENERATE_SERIES projections into table references, e.g.
|
|
143
|
+
|
|
144
|
+
SELECT GENERATE_SERIES(1, 2) AS x -> SELECT x FROM GENERATE_SERIES(1, 2) AS x
|
|
145
|
+
SELECT y, GENERATE_SERIES(1, 2) AS x FROM t -> SELECT y, x FROM t CROSS JOIN GENERATE_SERIES(1, 2) AS x
|
|
146
|
+
|
|
147
|
+
since BigQuery can't explode in the projection and must unnest it in the FROM clause instead.
|
|
148
|
+
The resulting table reference is unnested downstream by `transforms.unnest_generate_series`.
|
|
149
|
+
"""
|
|
150
|
+
if isinstance(expression, exp.Select):
|
|
151
|
+
for projection in expression.selects:
|
|
152
|
+
if isinstance(series := projection.unalias(), exp.ExplodingGenerateSeries):
|
|
153
|
+
column_name = projection.output_name or "_gen_series_value"
|
|
154
|
+
|
|
155
|
+
projection.replace(exp.column(column_name))
|
|
156
|
+
table = exp.Table(
|
|
157
|
+
this=series, alias=exp.TableAlias(this=exp.to_identifier(column_name))
|
|
158
|
+
)
|
|
159
|
+
|
|
160
|
+
if expression.args.get("from_"):
|
|
161
|
+
expression.join(table, copy=False, join_type="CROSS")
|
|
162
|
+
else:
|
|
163
|
+
expression.set("from_", exp.From(this=table))
|
|
164
|
+
|
|
165
|
+
return expression
|
|
166
|
+
|
|
167
|
+
|
|
140
168
|
def _array_contains_sql(self: BigQueryGenerator, expression: exp.ArrayContains) -> str:
|
|
141
169
|
return self.sql(
|
|
142
170
|
exp.Exists(
|
|
@@ -358,6 +386,7 @@ class BigQueryGenerator(generator.Generator):
|
|
|
358
386
|
exp.ParseDatetime: lambda self, e: self.func("PARSE_DATETIME", self.format_time(e), e.this),
|
|
359
387
|
exp.Select: transforms.preprocess(
|
|
360
388
|
[
|
|
389
|
+
_unnest_explode_generate_series,
|
|
361
390
|
transforms.explode_projection_to_unnest(),
|
|
362
391
|
transforms.unqualify_unnest,
|
|
363
392
|
transforms.eliminate_distinct_on,
|
|
@@ -379,6 +408,7 @@ class BigQueryGenerator(generator.Generator):
|
|
|
379
408
|
exp.StrToDate: _str_to_datetime_sql,
|
|
380
409
|
exp.StrToTime: _str_to_datetime_sql,
|
|
381
410
|
exp.SessionUser: lambda *_: "SESSION_USER()",
|
|
411
|
+
exp.Table: transforms.preprocess([transforms.unnest_generate_series]),
|
|
382
412
|
exp.TimeAdd: date_add_interval_sql("TIME", "ADD"),
|
|
383
413
|
exp.TimeFromParts: rename_func("TIME"),
|
|
384
414
|
exp.TimestampFromParts: rename_func("DATETIME"),
|
|
@@ -57,6 +57,9 @@ class DatabricksGenerator(SparkGenerator):
|
|
|
57
57
|
exp.CurrentCatalog: lambda *_: "CURRENT_CATALOG()",
|
|
58
58
|
exp.RegexpLike: None,
|
|
59
59
|
exp.TryCast: None,
|
|
60
|
+
exp.RegrAvgx: lambda self, e: self._regr_sql(e),
|
|
61
|
+
exp.RegrSxx: lambda self, e: self._regr_sql(e),
|
|
62
|
+
exp.RegrSyy: lambda self, e: self._regr_sql(e),
|
|
60
63
|
}.items()
|
|
61
64
|
if v is not None
|
|
62
65
|
}
|
|
@@ -90,6 +93,9 @@ class DatabricksGenerator(SparkGenerator):
|
|
|
90
93
|
|
|
91
94
|
return super().columndef_sql(expression, sep)
|
|
92
95
|
|
|
96
|
+
def timeserieskey_sql(self, expression: exp.TimeseriesKey) -> str:
|
|
97
|
+
return f"{self.sql(expression, 'this')} TIMESERIES"
|
|
98
|
+
|
|
93
99
|
def jsonpath_sql(self, expression: exp.JSONPath) -> str:
|
|
94
100
|
expression.set("escape", None)
|
|
95
101
|
path = super().jsonpath_sql(expression)
|
|
@@ -109,6 +115,13 @@ class DatabricksGenerator(SparkGenerator):
|
|
|
109
115
|
|
|
110
116
|
return self.func("UNIFORM", expression.this, expression.expression, seed)
|
|
111
117
|
|
|
118
|
+
def _regr_sql(self, expression: exp.RegrAvgx | exp.RegrSxx | exp.RegrSyy) -> str:
|
|
119
|
+
name = expression.sql_name()
|
|
120
|
+
x = expression.expression
|
|
121
|
+
if isinstance(x, exp.Distinct):
|
|
122
|
+
return self.func(name, exp.Distinct(expressions=[expression.this]), *x.expressions)
|
|
123
|
+
return self.func(name, expression.this, x)
|
|
124
|
+
|
|
112
125
|
def clusterproperty_sql(self, expression):
|
|
113
126
|
this = self.sql(expression, "this") or f"({self.expressions(expression, flat=True)})"
|
|
114
127
|
return f"CLUSTER BY {this}"
|
|
@@ -72,6 +72,14 @@ class DremioGenerator(generator.Generator):
|
|
|
72
72
|
exp.GenerateSeries: rename_func("ARRAY_GENERATE_RANGE"),
|
|
73
73
|
}
|
|
74
74
|
|
|
75
|
+
def version_sql(self, expression: exp.Version) -> str:
|
|
76
|
+
if expression.text("kind") == "AS OF":
|
|
77
|
+
this = "SNAPSHOT" if expression.name == "VERSION" else expression.name
|
|
78
|
+
return f"AT {this} {self.sql(expression, 'expression')}"
|
|
79
|
+
|
|
80
|
+
self.unsupported("Range time travel is not supported in Dremio")
|
|
81
|
+
return super().version_sql(expression)
|
|
82
|
+
|
|
75
83
|
def datatype_sql(self, expression: exp.DataType) -> str:
|
|
76
84
|
"""
|
|
77
85
|
Reject time-zone-aware TIMESTAMPs, which Dremio does not accept
|
|
@@ -29,6 +29,7 @@ class DrillGenerator(generator.Generator):
|
|
|
29
29
|
TRY_SUPPORTED = False
|
|
30
30
|
SUPPORTS_UESCAPE = False
|
|
31
31
|
SUPPORTS_DECODE_CASE = False
|
|
32
|
+
SUPPORTS_LIKE_QUANTIFIERS = False
|
|
32
33
|
|
|
33
34
|
AFTER_HAVING_MODIFIER_TRANSFORMS = generator.AFTER_HAVING_MODIFIER_TRANSFORMS
|
|
34
35
|
|
|
@@ -76,7 +77,6 @@ class DrillGenerator(generator.Generator):
|
|
|
76
77
|
exp.If: lambda self, e: (
|
|
77
78
|
f"`IF`({self.format_args(e.this, e.args.get('true'), e.args.get('false'))})"
|
|
78
79
|
),
|
|
79
|
-
exp.ILike: lambda self, e: self.binary(e, "`ILIKE`"),
|
|
80
80
|
exp.Levenshtein: unsupported_args("ins_cost", "del_cost", "sub_cost", "max_dist")(
|
|
81
81
|
rename_func("LEVENSHTEIN_DISTANCE")
|
|
82
82
|
),
|
|
@@ -104,6 +104,22 @@ class DrillGenerator(generator.Generator):
|
|
|
104
104
|
),
|
|
105
105
|
}
|
|
106
106
|
|
|
107
|
+
def ilike_sql(self, expression: exp.ILike) -> str:
|
|
108
|
+
if isinstance(expression.expression, (exp.All, exp.Any)):
|
|
109
|
+
return super().ilike_sql(expression)
|
|
110
|
+
return self._ilike_func_sql(expression)
|
|
111
|
+
|
|
112
|
+
def escape_sql(self, expression: exp.Escape) -> str:
|
|
113
|
+
# Drill takes the escape character as ILIKE's third argument instead of an ESCAPE clause
|
|
114
|
+
this = expression.this
|
|
115
|
+
if isinstance(this, exp.ILike) and not isinstance(this.expression, (exp.All, exp.Any)):
|
|
116
|
+
return self._ilike_func_sql(this, expression.expression)
|
|
117
|
+
return super().escape_sql(expression)
|
|
118
|
+
|
|
119
|
+
def _ilike_func_sql(self, expression: exp.ILike, escape: exp.Expr | None = None) -> str:
|
|
120
|
+
ilike = self.func("ILIKE", expression.this, expression.expression, escape)
|
|
121
|
+
return f"NOT {ilike}" if expression.args.get("negate") else ilike
|
|
122
|
+
|
|
107
123
|
|
|
108
124
|
def _drill_dateint_format() -> str:
|
|
109
125
|
from sqlglot.dialects.drill import Drill
|
|
@@ -32,9 +32,10 @@ from sqlglot.dialects.dialect import (
|
|
|
32
32
|
rename_func,
|
|
33
33
|
remove_from_array_using_filter,
|
|
34
34
|
strposition_sql,
|
|
35
|
-
str_to_time_sql,
|
|
36
35
|
timestrtotime_sql,
|
|
37
36
|
unit_to_str,
|
|
37
|
+
week_unit_to_dow,
|
|
38
|
+
WEEK_START_DAY_TO_DOW,
|
|
38
39
|
)
|
|
39
40
|
from sqlglot.generator import unsupported_args
|
|
40
41
|
from sqlglot.helper import find_new_name, is_date_unit, seq_get
|
|
@@ -69,18 +70,6 @@ WS_CONTROL_CHARS_TO_DUCK = {
|
|
|
69
70
|
"\u001f": 31,
|
|
70
71
|
}
|
|
71
72
|
|
|
72
|
-
# Days of week to ISO 8601 day-of-week numbers
|
|
73
|
-
# ISO 8601 standard: Monday=1, Tuesday=2, Wednesday=3, Thursday=4, Friday=5, Saturday=6, Sunday=7
|
|
74
|
-
WEEK_START_DAY_TO_DOW = {
|
|
75
|
-
"MONDAY": 1,
|
|
76
|
-
"TUESDAY": 2,
|
|
77
|
-
"WEDNESDAY": 3,
|
|
78
|
-
"THURSDAY": 4,
|
|
79
|
-
"FRIDAY": 5,
|
|
80
|
-
"SATURDAY": 6,
|
|
81
|
-
"SUNDAY": 7,
|
|
82
|
-
}
|
|
83
|
-
|
|
84
73
|
MAX_BIT_POSITION = exp.Literal.number(32768)
|
|
85
74
|
|
|
86
75
|
# cs/as/ps are Snowflake defaults; DuckDB already behaves the same way, so they are safe to drop.
|
|
@@ -906,33 +895,6 @@ def _implicit_datetime_cast(
|
|
|
906
895
|
return arg
|
|
907
896
|
|
|
908
897
|
|
|
909
|
-
def _week_unit_to_dow(unit: exp.Expr | None) -> int | None:
|
|
910
|
-
"""
|
|
911
|
-
Compute the Monday-based day shift to align DATE_DIFF('WEEK', ...) coming
|
|
912
|
-
from other dialects, e.g BigQuery's WEEK(<day>) or ISOWEEK unit parts.
|
|
913
|
-
|
|
914
|
-
Args:
|
|
915
|
-
unit: The unit expression (Var for ISOWEEK or WeekStart)
|
|
916
|
-
|
|
917
|
-
Returns:
|
|
918
|
-
The ISO 8601 day number (Monday=1, Sunday=7 etc) or None if not a week unit or if day is dynamic (not a constant).
|
|
919
|
-
|
|
920
|
-
Examples:
|
|
921
|
-
"WEEK(SUNDAY)" -> 7
|
|
922
|
-
"WEEK(MONDAY)" -> 1
|
|
923
|
-
"ISOWEEK" -> 1
|
|
924
|
-
"""
|
|
925
|
-
# Handle plain Var expressions for ISOWEEK only
|
|
926
|
-
if isinstance(unit, exp.Var) and unit.name.upper() in "ISOWEEK":
|
|
927
|
-
return 1
|
|
928
|
-
|
|
929
|
-
# Handle WeekStart expressions with explicit day
|
|
930
|
-
if isinstance(unit, exp.WeekStart):
|
|
931
|
-
return WEEK_START_DAY_TO_DOW.get(unit.name.upper())
|
|
932
|
-
|
|
933
|
-
return None
|
|
934
|
-
|
|
935
|
-
|
|
936
898
|
def _build_week_trunc_expression(
|
|
937
899
|
date_expr: exp.Expr,
|
|
938
900
|
start_dow: int,
|
|
@@ -989,7 +951,7 @@ def _date_diff_sql(self: DuckDBGenerator, expression: exp.DateDiff | exp.Datetim
|
|
|
989
951
|
date_part_boundary = expression.args.get("date_part_boundary")
|
|
990
952
|
|
|
991
953
|
# Extract week start day; returns None if day is dynamic (column/placeholder)
|
|
992
|
-
week_start =
|
|
954
|
+
week_start = week_unit_to_dow(unit)
|
|
993
955
|
if date_part_boundary and week_start and this and expr:
|
|
994
956
|
expression.set("unit", exp.Literal.string("WEEK"))
|
|
995
957
|
|
|
@@ -1606,6 +1568,7 @@ class DuckDBGenerator(generator.Generator):
|
|
|
1606
1568
|
ARRAY_SIZE_DIM_REQUIRED: bool | None = False
|
|
1607
1569
|
NORMALIZE_EXTRACT_DATE_PARTS = True
|
|
1608
1570
|
SUPPORTS_LIKE_QUANTIFIERS = False
|
|
1571
|
+
HISTORICAL_DATA_POST_ALIAS = True
|
|
1609
1572
|
SET_ASSIGNMENT_REQUIRES_VARIABLE_KEYWORD = True
|
|
1610
1573
|
|
|
1611
1574
|
TRANSFORMS = {
|
|
@@ -2751,14 +2714,13 @@ class DuckDBGenerator(generator.Generator):
|
|
|
2751
2714
|
exp.DType.TIMESTAMPTZ,
|
|
2752
2715
|
)
|
|
2753
2716
|
|
|
2717
|
+
value, formatted_time = self._strptime_default_year(expression)
|
|
2718
|
+
|
|
2754
2719
|
if expression.args.get("safe"):
|
|
2755
|
-
formatted_time = self.format_time(expression)
|
|
2756
2720
|
cast_type = exp.DType.TIMESTAMPTZ if needs_tz else exp.DType.TIMESTAMP
|
|
2757
|
-
return self.sql(
|
|
2758
|
-
exp.cast(self.func("TRY_STRPTIME", expression.this, formatted_time), cast_type)
|
|
2759
|
-
)
|
|
2721
|
+
return self.sql(exp.cast(self.func("TRY_STRPTIME", value, formatted_time), cast_type))
|
|
2760
2722
|
|
|
2761
|
-
base_sql =
|
|
2723
|
+
base_sql = self.func("STRPTIME", value, formatted_time)
|
|
2762
2724
|
if needs_tz:
|
|
2763
2725
|
return self.sql(
|
|
2764
2726
|
exp.cast(
|
|
@@ -2769,27 +2731,30 @@ class DuckDBGenerator(generator.Generator):
|
|
|
2769
2731
|
return base_sql
|
|
2770
2732
|
|
|
2771
2733
|
def strtodate_sql(self, expression: exp.StrToDate) -> str:
|
|
2772
|
-
formatted_time = self.
|
|
2734
|
+
value, formatted_time = self._strptime_default_year(expression)
|
|
2773
2735
|
function_name = "STRPTIME" if not expression.args.get("safe") else "TRY_STRPTIME"
|
|
2774
2736
|
return self.sql(
|
|
2775
2737
|
exp.cast(
|
|
2776
|
-
self.func(function_name,
|
|
2738
|
+
self.func(function_name, value, formatted_time),
|
|
2777
2739
|
exp.DataType(this=exp.DType.DATE),
|
|
2778
2740
|
)
|
|
2779
2741
|
)
|
|
2780
2742
|
|
|
2781
|
-
def
|
|
2782
|
-
|
|
2743
|
+
def _strptime_default_year(
|
|
2744
|
+
self, expression: exp.StrToTime | exp.StrToDate | exp.ParseDatetime
|
|
2745
|
+
) -> tuple[exp.ExpOrStr, exp.ExpOrStr | None]:
|
|
2746
|
+
value: exp.ExpOrStr = expression.this
|
|
2747
|
+
formatted_time: exp.ExpOrStr | None = self.format_time(expression)
|
|
2783
2748
|
|
|
2784
|
-
default_year
|
|
2785
|
-
|
|
2786
|
-
|
|
2787
|
-
fmt_prefix = exp.Literal.string("%Y ")
|
|
2788
|
-
value = exp.DPipe(this=year_str, expression=expression.this)
|
|
2789
|
-
fmt = exp.DPipe(this=fmt_prefix, expression=formatted_time)
|
|
2790
|
-
return self.func("STRPTIME", value, fmt)
|
|
2749
|
+
if default_year := expression.args.get("default_year"):
|
|
2750
|
+
value = exp.DPipe(this=exp.Literal.string(f"{default_year.name} "), expression=value)
|
|
2751
|
+
formatted_time = exp.DPipe(this=exp.Literal.string("%Y "), expression=formatted_time)
|
|
2791
2752
|
|
|
2792
|
-
return
|
|
2753
|
+
return value, formatted_time
|
|
2754
|
+
|
|
2755
|
+
def parsedatetime_sql(self, expression: exp.ParseDatetime) -> str:
|
|
2756
|
+
value, formatted_time = self._strptime_default_year(expression)
|
|
2757
|
+
return self.func("STRPTIME", value, formatted_time)
|
|
2793
2758
|
|
|
2794
2759
|
def parsetime_sql(self, expression: exp.ParseTime) -> str:
|
|
2795
2760
|
formatted_time = self.format_time(expression)
|
|
@@ -3152,6 +3117,11 @@ class DuckDBGenerator(generator.Generator):
|
|
|
3152
3117
|
|
|
3153
3118
|
def countif_sql(self, expression: exp.CountIf) -> str:
|
|
3154
3119
|
if self.dialect.version >= (1, 2):
|
|
3120
|
+
this = expression.this
|
|
3121
|
+
if expression.args.get("zero_on_all_null") and not isinstance(this, exp.Distinct):
|
|
3122
|
+
# DuckDB >= 1.2's COUNT_IF returns NULL when the condition is NULL on all rows,
|
|
3123
|
+
# so we wrap the condition in IS TRUE to preserve count-like semantics
|
|
3124
|
+
expression = exp.CountIf(this=exp.paren(this).is_(exp.true()))
|
|
3155
3125
|
return self.function_fallback_sql(expression)
|
|
3156
3126
|
|
|
3157
3127
|
# https://github.com/tobymao/sqlglot/pull/4749
|
|
@@ -4383,7 +4353,7 @@ class DuckDBGenerator(generator.Generator):
|
|
|
4383
4353
|
unit = expression.args.get("unit")
|
|
4384
4354
|
date = expression.this
|
|
4385
4355
|
|
|
4386
|
-
week_start =
|
|
4356
|
+
week_start = week_unit_to_dow(unit)
|
|
4387
4357
|
unit = unit_to_str(expression)
|
|
4388
4358
|
|
|
4389
4359
|
if week_start:
|