sqlglotc 30.20.0__tar.gz → 30.22.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.20.0/sqlglotc.egg-info → sqlglotc-30.22.0}/PKG-INFO +3 -3
- {sqlglotc-30.20.0 → sqlglotc-30.22.0}/pyproject.toml +2 -2
- {sqlglotc-30.20.0 → sqlglotc-30.22.0}/setup.py +0 -1
- {sqlglotc-30.20.0 → sqlglotc-30.22.0}/sqlglot/expressions/array.py +15 -1
- {sqlglotc-30.20.0 → sqlglotc-30.22.0}/sqlglot/expressions/builders.py +1 -1
- {sqlglotc-30.20.0 → sqlglotc-30.22.0}/sqlglot/expressions/ddl.py +1 -1
- {sqlglotc-30.20.0 → sqlglotc-30.22.0}/sqlglot/expressions/properties.py +3 -5
- {sqlglotc-30.20.0 → sqlglotc-30.22.0}/sqlglot/expressions/query.py +41 -3
- {sqlglotc-30.20.0 → sqlglotc-30.22.0}/sqlglot/expressions/string.py +4 -0
- {sqlglotc-30.20.0 → sqlglotc-30.22.0}/sqlglot/generator.py +150 -34
- {sqlglotc-30.20.0 → sqlglotc-30.22.0}/sqlglot/generators/athena.py +1 -1
- {sqlglotc-30.20.0 → sqlglotc-30.22.0}/sqlglot/generators/bigquery.py +4 -2
- {sqlglotc-30.20.0 → sqlglotc-30.22.0}/sqlglot/generators/clickhouse.py +21 -0
- {sqlglotc-30.20.0 → sqlglotc-30.22.0}/sqlglot/generators/doris.py +1 -0
- {sqlglotc-30.20.0 → sqlglotc-30.22.0}/sqlglot/generators/dremio.py +1 -0
- {sqlglotc-30.20.0 → sqlglotc-30.22.0}/sqlglot/generators/drill.py +7 -0
- {sqlglotc-30.20.0 → sqlglotc-30.22.0}/sqlglot/generators/duckdb.py +76 -9
- {sqlglotc-30.20.0 → sqlglotc-30.22.0}/sqlglot/generators/hive.py +1 -0
- {sqlglotc-30.20.0 → sqlglotc-30.22.0}/sqlglot/generators/materialize.py +6 -1
- {sqlglotc-30.20.0 → sqlglotc-30.22.0}/sqlglot/generators/mysql.py +25 -1
- {sqlglotc-30.20.0 → sqlglotc-30.22.0}/sqlglot/generators/oracle.py +1 -0
- {sqlglotc-30.20.0 → sqlglotc-30.22.0}/sqlglot/generators/postgres.py +15 -1
- {sqlglotc-30.20.0 → sqlglotc-30.22.0}/sqlglot/generators/presto.py +9 -0
- {sqlglotc-30.20.0 → sqlglotc-30.22.0}/sqlglot/generators/redshift.py +8 -0
- {sqlglotc-30.20.0 → sqlglotc-30.22.0}/sqlglot/generators/risingwave.py +2 -1
- {sqlglotc-30.20.0 → sqlglotc-30.22.0}/sqlglot/generators/singlestore.py +11 -2
- {sqlglotc-30.20.0 → sqlglotc-30.22.0}/sqlglot/generators/snowflake.py +5 -48
- {sqlglotc-30.20.0 → sqlglotc-30.22.0}/sqlglot/generators/spark.py +3 -3
- {sqlglotc-30.20.0 → sqlglotc-30.22.0}/sqlglot/generators/spark2.py +10 -0
- {sqlglotc-30.20.0 → sqlglotc-30.22.0}/sqlglot/generators/sqlite.py +2 -1
- {sqlglotc-30.20.0 → sqlglotc-30.22.0}/sqlglot/generators/starrocks.py +8 -0
- {sqlglotc-30.20.0 → sqlglotc-30.22.0}/sqlglot/generators/trino.py +1 -0
- {sqlglotc-30.20.0 → sqlglotc-30.22.0}/sqlglot/generators/tsql.py +12 -4
- {sqlglotc-30.20.0 → sqlglotc-30.22.0}/sqlglot/lineage.py +19 -6
- {sqlglotc-30.20.0 → sqlglotc-30.22.0}/sqlglot/optimizer/canonicalize_internal_names.py +6 -4
- {sqlglotc-30.20.0 → sqlglotc-30.22.0}/sqlglot/optimizer/qualify.py +0 -3
- {sqlglotc-30.20.0 → sqlglotc-30.22.0}/sqlglot/optimizer/qualify_columns.py +132 -40
- {sqlglotc-30.20.0 → sqlglotc-30.22.0}/sqlglot/optimizer/qualify_tables.py +32 -8
- {sqlglotc-30.20.0 → sqlglotc-30.22.0}/sqlglot/optimizer/resolver.py +46 -38
- {sqlglotc-30.20.0 → sqlglotc-30.22.0}/sqlglot/optimizer/scope.py +31 -13
- {sqlglotc-30.20.0 → sqlglotc-30.22.0}/sqlglot/optimizer/simplify.py +10 -3
- {sqlglotc-30.20.0 → sqlglotc-30.22.0}/sqlglot/parser.py +251 -79
- {sqlglotc-30.20.0 → sqlglotc-30.22.0}/sqlglot/parsers/athena.py +5 -2
- {sqlglotc-30.20.0 → sqlglotc-30.22.0}/sqlglot/parsers/clickhouse.py +14 -0
- {sqlglotc-30.20.0 → sqlglotc-30.22.0}/sqlglot/parsers/doris.py +3 -0
- {sqlglotc-30.20.0 → sqlglotc-30.22.0}/sqlglot/parsers/duckdb.py +3 -2
- {sqlglotc-30.20.0 → sqlglotc-30.22.0}/sqlglot/parsers/hive.py +37 -1
- {sqlglotc-30.20.0 → sqlglotc-30.22.0}/sqlglot/parsers/mysql.py +30 -5
- {sqlglotc-30.20.0 → sqlglotc-30.22.0}/sqlglot/parsers/postgres.py +3 -0
- {sqlglotc-30.20.0 → sqlglotc-30.22.0}/sqlglot/parsers/snowflake.py +11 -0
- {sqlglotc-30.20.0 → sqlglotc-30.22.0}/sqlglot/parsers/spark.py +6 -0
- {sqlglotc-30.20.0 → sqlglotc-30.22.0}/sqlglot/parsers/spark2.py +8 -1
- {sqlglotc-30.20.0 → sqlglotc-30.22.0}/sqlglot/parsers/starrocks.py +3 -0
- {sqlglotc-30.20.0 → sqlglotc-30.22.0}/sqlglot/parsers/trino.py +25 -0
- {sqlglotc-30.20.0 → sqlglotc-30.22.0}/sqlglot/parsers/tsql.py +72 -2
- {sqlglotc-30.20.0 → sqlglotc-30.22.0}/sqlglot/tokenizer_core.py +207 -22
- {sqlglotc-30.20.0 → sqlglotc-30.22.0/sqlglotc.egg-info}/PKG-INFO +3 -3
- {sqlglotc-30.20.0 → sqlglotc-30.22.0}/sqlglotc.egg-info/SOURCES.txt +0 -1
- sqlglotc-30.22.0/sqlglotc.egg-info/requires.txt +6 -0
- sqlglotc-30.22.0/sqlglotc.egg-info/scm_version.json +8 -0
- sqlglotc-30.20.0/sqlglot/schema.py +0 -813
- sqlglotc-30.20.0/sqlglotc.egg-info/requires.txt +0 -6
- sqlglotc-30.20.0/sqlglotc.egg-info/scm_version.json +0 -8
- {sqlglotc-30.20.0 → sqlglotc-30.22.0}/MANIFEST.in +0 -0
- {sqlglotc-30.20.0 → sqlglotc-30.22.0}/setup.cfg +0 -0
- {sqlglotc-30.20.0 → sqlglotc-30.22.0}/sqlglot/anonymize.py +0 -0
- {sqlglotc-30.20.0 → sqlglotc-30.22.0}/sqlglot/errors.py +0 -0
- {sqlglotc-30.20.0 → sqlglotc-30.22.0}/sqlglot/executor/table.py +0 -0
- {sqlglotc-30.20.0 → sqlglotc-30.22.0}/sqlglot/expressions/aggregate.py +0 -0
- {sqlglotc-30.20.0 → sqlglotc-30.22.0}/sqlglot/expressions/constraints.py +0 -0
- {sqlglotc-30.20.0 → sqlglotc-30.22.0}/sqlglot/expressions/core.py +0 -0
- {sqlglotc-30.20.0 → sqlglotc-30.22.0}/sqlglot/expressions/datatypes.py +0 -0
- {sqlglotc-30.20.0 → sqlglotc-30.22.0}/sqlglot/expressions/dml.py +0 -0
- {sqlglotc-30.20.0 → sqlglotc-30.22.0}/sqlglot/expressions/functions.py +0 -0
- {sqlglotc-30.20.0 → sqlglotc-30.22.0}/sqlglot/expressions/json.py +0 -0
- {sqlglotc-30.20.0 → sqlglotc-30.22.0}/sqlglot/expressions/math.py +0 -0
- {sqlglotc-30.20.0 → sqlglotc-30.22.0}/sqlglot/expressions/temporal.py +0 -0
- {sqlglotc-30.20.0 → sqlglotc-30.22.0}/sqlglot/generators/databricks.py +0 -0
- {sqlglotc-30.20.0 → sqlglotc-30.22.0}/sqlglot/generators/dax.py +0 -0
- {sqlglotc-30.20.0 → sqlglotc-30.22.0}/sqlglot/generators/druid.py +0 -0
- {sqlglotc-30.20.0 → sqlglotc-30.22.0}/sqlglot/generators/dune.py +0 -0
- {sqlglotc-30.20.0 → sqlglotc-30.22.0}/sqlglot/generators/exasol.py +0 -0
- {sqlglotc-30.20.0 → sqlglotc-30.22.0}/sqlglot/generators/fabric.py +0 -0
- {sqlglotc-30.20.0 → sqlglotc-30.22.0}/sqlglot/generators/prql.py +0 -0
- {sqlglotc-30.20.0 → sqlglotc-30.22.0}/sqlglot/generators/python.py +0 -0
- {sqlglotc-30.20.0 → sqlglotc-30.22.0}/sqlglot/generators/solr.py +0 -0
- {sqlglotc-30.20.0 → sqlglotc-30.22.0}/sqlglot/generators/tableau.py +0 -0
- {sqlglotc-30.20.0 → sqlglotc-30.22.0}/sqlglot/generators/teradata.py +0 -0
- {sqlglotc-30.20.0 → sqlglotc-30.22.0}/sqlglot/helper.py +0 -0
- {sqlglotc-30.20.0 → sqlglotc-30.22.0}/sqlglot/optimizer/annotate_types.py +0 -0
- {sqlglotc-30.20.0 → sqlglotc-30.22.0}/sqlglot/optimizer/isolate_table_selects.py +0 -0
- {sqlglotc-30.20.0 → sqlglotc-30.22.0}/sqlglot/optimizer/normalize_identifiers.py +0 -0
- {sqlglotc-30.20.0 → sqlglotc-30.22.0}/sqlglot/parsers/base.py +0 -0
- {sqlglotc-30.20.0 → sqlglotc-30.22.0}/sqlglot/parsers/bigquery.py +0 -0
- {sqlglotc-30.20.0 → sqlglotc-30.22.0}/sqlglot/parsers/databricks.py +0 -0
- {sqlglotc-30.20.0 → sqlglotc-30.22.0}/sqlglot/parsers/dax.py +0 -0
- {sqlglotc-30.20.0 → sqlglotc-30.22.0}/sqlglot/parsers/dremio.py +0 -0
- {sqlglotc-30.20.0 → sqlglotc-30.22.0}/sqlglot/parsers/drill.py +0 -0
- {sqlglotc-30.20.0 → sqlglotc-30.22.0}/sqlglot/parsers/druid.py +0 -0
- {sqlglotc-30.20.0 → sqlglotc-30.22.0}/sqlglot/parsers/dune.py +0 -0
- {sqlglotc-30.20.0 → sqlglotc-30.22.0}/sqlglot/parsers/exasol.py +0 -0
- {sqlglotc-30.20.0 → sqlglotc-30.22.0}/sqlglot/parsers/fabric.py +0 -0
- {sqlglotc-30.20.0 → sqlglotc-30.22.0}/sqlglot/parsers/materialize.py +0 -0
- {sqlglotc-30.20.0 → sqlglotc-30.22.0}/sqlglot/parsers/oracle.py +0 -0
- {sqlglotc-30.20.0 → sqlglotc-30.22.0}/sqlglot/parsers/presto.py +0 -0
- {sqlglotc-30.20.0 → sqlglotc-30.22.0}/sqlglot/parsers/prql.py +0 -0
- {sqlglotc-30.20.0 → sqlglotc-30.22.0}/sqlglot/parsers/redshift.py +0 -0
- {sqlglotc-30.20.0 → sqlglotc-30.22.0}/sqlglot/parsers/risingwave.py +0 -0
- {sqlglotc-30.20.0 → sqlglotc-30.22.0}/sqlglot/parsers/singlestore.py +0 -0
- {sqlglotc-30.20.0 → sqlglotc-30.22.0}/sqlglot/parsers/solr.py +0 -0
- {sqlglotc-30.20.0 → sqlglotc-30.22.0}/sqlglot/parsers/sqlite.py +0 -0
- {sqlglotc-30.20.0 → sqlglotc-30.22.0}/sqlglot/parsers/tableau.py +0 -0
- {sqlglotc-30.20.0 → sqlglotc-30.22.0}/sqlglot/parsers/teradata.py +0 -0
- {sqlglotc-30.20.0 → sqlglotc-30.22.0}/sqlglot/serde.py +0 -0
- {sqlglotc-30.20.0 → sqlglotc-30.22.0}/sqlglot/time.py +0 -0
- {sqlglotc-30.20.0 → sqlglotc-30.22.0}/sqlglot/trie.py +0 -0
- {sqlglotc-30.20.0 → sqlglotc-30.22.0}/sqlglotc.egg-info/dependency_links.txt +0 -0
- {sqlglotc-30.20.0 → sqlglotc-30.22.0}/sqlglotc.egg-info/scm_file_list.json +0 -0
- {sqlglotc-30.20.0 → sqlglotc-30.22.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.22.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.22.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:
|
|
14
|
+
Requires-Dist: mypy>=2.4.0; 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", "
|
|
10
|
+
dev = ["setuptools >= 61.0", "setuptools_scm", "mypy >= 2.4.0"]
|
|
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
|
-
"
|
|
20
|
+
"mypy >= 2.4.0",
|
|
21
21
|
"types-python-dateutil",
|
|
22
22
|
"sqlglot",
|
|
23
23
|
]
|
|
@@ -23,6 +23,7 @@ class Array(Expression, Func):
|
|
|
23
23
|
"expressions": False,
|
|
24
24
|
"bracket_notation": False,
|
|
25
25
|
"struct_name_inheritance": False,
|
|
26
|
+
"value_constructor": False,
|
|
26
27
|
}
|
|
27
28
|
is_var_len_args = True
|
|
28
29
|
|
|
@@ -84,7 +85,16 @@ class ArrayReverse(Expression, Func):
|
|
|
84
85
|
|
|
85
86
|
|
|
86
87
|
class ArraySlice(Expression, Func):
|
|
87
|
-
|
|
88
|
+
"""Slice by end index, or by length when is_length is set."""
|
|
89
|
+
|
|
90
|
+
arg_types = {
|
|
91
|
+
"this": True,
|
|
92
|
+
"start": True,
|
|
93
|
+
"end": False,
|
|
94
|
+
"step": False,
|
|
95
|
+
"zero_based": False,
|
|
96
|
+
"is_length": False,
|
|
97
|
+
}
|
|
88
98
|
|
|
89
99
|
|
|
90
100
|
class ArraySort(Expression, Func):
|
|
@@ -244,6 +254,10 @@ class Inline(Expression, Func, UDTF):
|
|
|
244
254
|
pass
|
|
245
255
|
|
|
246
256
|
|
|
257
|
+
class SplitToTable(Expression, Func, UDTF):
|
|
258
|
+
arg_types = {"this": True, "expression": True}
|
|
259
|
+
|
|
260
|
+
|
|
247
261
|
class Stack(Expression, Func, UDTF):
|
|
248
262
|
arg_types = {"this": True, "expressions": True}
|
|
249
263
|
is_var_len_args = True
|
|
@@ -624,7 +624,9 @@ class Properties(Expression):
|
|
|
624
624
|
"INCLUDE": IncludeProperty,
|
|
625
625
|
}
|
|
626
626
|
|
|
627
|
-
PROPERTY_TO_NAME: t.ClassVar[dict[type[Property], str]] = {
|
|
627
|
+
PROPERTY_TO_NAME: t.ClassVar[dict[type[Property], str]] = {
|
|
628
|
+
v: k for k, v in NAME_TO_PROPERTY.items()
|
|
629
|
+
}
|
|
628
630
|
|
|
629
631
|
# CREATE property locations
|
|
630
632
|
# Form: schema specified
|
|
@@ -652,7 +654,3 @@ class Properties(Expression):
|
|
|
652
654
|
expressions.append(Property(this=Literal.string(key), value=convert(value)))
|
|
653
655
|
|
|
654
656
|
return cls(expressions=expressions)
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
# TODO (mypyc)
|
|
658
|
-
Properties.PROPERTY_TO_NAME = {v: k for k, v in Properties.NAME_TO_PROPERTY.items()}
|
|
@@ -19,6 +19,7 @@ from sqlglot.expressions.core import (
|
|
|
19
19
|
Hint,
|
|
20
20
|
Identifier,
|
|
21
21
|
In,
|
|
22
|
+
Var,
|
|
22
23
|
_apply_builder,
|
|
23
24
|
_apply_child_list_builder,
|
|
24
25
|
_apply_list_builder,
|
|
@@ -441,11 +442,24 @@ class QueryBand(Expression):
|
|
|
441
442
|
|
|
442
443
|
|
|
443
444
|
class RecursiveWithSearch(Expression):
|
|
444
|
-
arg_types = {
|
|
445
|
+
arg_types = {
|
|
446
|
+
"kind": True,
|
|
447
|
+
"this": True,
|
|
448
|
+
"expression": True,
|
|
449
|
+
"to": False,
|
|
450
|
+
"default": False,
|
|
451
|
+
"using": False,
|
|
452
|
+
}
|
|
445
453
|
|
|
446
454
|
|
|
447
455
|
class With(Expression):
|
|
448
|
-
arg_types = {
|
|
456
|
+
arg_types = {
|
|
457
|
+
"expressions": False,
|
|
458
|
+
"recursive": False,
|
|
459
|
+
"search": False,
|
|
460
|
+
"cycle": False,
|
|
461
|
+
"udfs": False,
|
|
462
|
+
}
|
|
449
463
|
|
|
450
464
|
@property
|
|
451
465
|
def recursive(self) -> bool:
|
|
@@ -572,7 +586,7 @@ class ConditionalInsert(Expression):
|
|
|
572
586
|
|
|
573
587
|
|
|
574
588
|
class MultitableInserts(Expression):
|
|
575
|
-
arg_types = {"expressions": True, "kind":
|
|
589
|
+
arg_types = {"with_": False, "expressions": True, "kind": False, "source": True}
|
|
576
590
|
|
|
577
591
|
|
|
578
592
|
class OnCondition(Expression):
|
|
@@ -657,6 +671,11 @@ class Limit(Expression):
|
|
|
657
671
|
"expressions": False,
|
|
658
672
|
}
|
|
659
673
|
|
|
674
|
+
@property
|
|
675
|
+
def is_limit_all(self) -> bool:
|
|
676
|
+
limit_expression = self.args.get("expression")
|
|
677
|
+
return isinstance(limit_expression, Var) and limit_expression.name.upper() == "ALL"
|
|
678
|
+
|
|
660
679
|
|
|
661
680
|
class LimitOptions(Expression):
|
|
662
681
|
arg_types = {
|
|
@@ -804,6 +823,19 @@ class Lateral(Expression, UDTF):
|
|
|
804
823
|
"ordinality": False,
|
|
805
824
|
}
|
|
806
825
|
|
|
826
|
+
@property
|
|
827
|
+
def selects(self) -> list[Expr]:
|
|
828
|
+
from sqlglot.expressions.array import Unnest
|
|
829
|
+
|
|
830
|
+
columns = super().selects
|
|
831
|
+
|
|
832
|
+
# UNNEST ... WITH ORDINALITY stores the ordinality column's name in Unnest.offset
|
|
833
|
+
offset = self.this.args.get("offset") if isinstance(self.this, Unnest) else None
|
|
834
|
+
if isinstance(offset, Identifier):
|
|
835
|
+
columns = columns + [offset]
|
|
836
|
+
|
|
837
|
+
return columns
|
|
838
|
+
|
|
807
839
|
|
|
808
840
|
class TableFromRows(Expression, UDTF):
|
|
809
841
|
arg_types = {
|
|
@@ -941,6 +973,12 @@ class Get(Expression):
|
|
|
941
973
|
arg_types = {"this": True, "target": True, "properties": False}
|
|
942
974
|
|
|
943
975
|
|
|
976
|
+
class ListStage(Expression):
|
|
977
|
+
"""Lists files in a Snowflake stage or Git repository clone."""
|
|
978
|
+
|
|
979
|
+
arg_types = {"this": True, "pattern": False}
|
|
980
|
+
|
|
981
|
+
|
|
944
982
|
class Table(Expression, Selectable):
|
|
945
983
|
arg_types = {
|
|
946
984
|
"this": False,
|
|
@@ -25,6 +25,8 @@ if t.TYPE_CHECKING:
|
|
|
25
25
|
|
|
26
26
|
logger = logging.getLogger("sqlglot")
|
|
27
27
|
|
|
28
|
+
_HIGH_BYTE_RE = re.compile(r"[\x80-\xff]")
|
|
29
|
+
|
|
28
30
|
ESCAPED_UNICODE_RE = re.compile(r"\\(\d+)")
|
|
29
31
|
UNSUPPORTED_TEMPLATE = "Argument '{}' is not supported for expression '{}' when targeting {}."
|
|
30
32
|
|
|
@@ -380,6 +382,12 @@ class Generator:
|
|
|
380
382
|
# Whether comparing against booleans (e.g. x IS TRUE) is supported
|
|
381
383
|
IS_BOOL_ALLOWED = True
|
|
382
384
|
|
|
385
|
+
# Whether casting a fractional number to an integer rounds it instead of truncating it
|
|
386
|
+
CAST_TO_INT_ROUNDS = False
|
|
387
|
+
|
|
388
|
+
# Whether the native integer division operator returns NULL for a zero divisor instead of raising
|
|
389
|
+
SAFE_INT_DIVISION = False
|
|
390
|
+
|
|
383
391
|
# Whether to include the "SET" keyword in the "INSERT ... ON DUPLICATE KEY UPDATE" statement
|
|
384
392
|
DUPLICATE_KEY_UPDATE_WITH_SET = True
|
|
385
393
|
|
|
@@ -565,6 +573,9 @@ class Generator:
|
|
|
565
573
|
# The HEX function name
|
|
566
574
|
HEX_FUNC = "HEX"
|
|
567
575
|
|
|
576
|
+
# Function that constructs a binary value from a hex-encoded byte string.
|
|
577
|
+
BYTE_STRING_FUNCTION = ""
|
|
578
|
+
|
|
568
579
|
# The keywords to use when prefixing & separating WITH based properties
|
|
569
580
|
WITH_PROPERTIES_PREFIX = "WITH"
|
|
570
581
|
|
|
@@ -871,6 +882,10 @@ class Generator:
|
|
|
871
882
|
exp.Mod,
|
|
872
883
|
)
|
|
873
884
|
|
|
885
|
+
# ALTER options that follow the others without a comma, e.g. MySQL's
|
|
886
|
+
# ENGINE=InnoDB PARTITION BY LIST (...) or StarRocks' PARTITION BY ... DISTRIBUTED BY ...
|
|
887
|
+
ALTER_PARTITION_OPTIONS: t.ClassVar[tuple[type[exp.Expr], ...]] = ()
|
|
888
|
+
|
|
874
889
|
SAFE_JSON_PATH_KEY_RE: t.ClassVar = exp.SAFE_IDENTIFIER_RE
|
|
875
890
|
|
|
876
891
|
SENTINEL_LINE_BREAK = "__SQLGLOT__LB__"
|
|
@@ -892,6 +907,7 @@ class Generator:
|
|
|
892
907
|
"_escaped_quote_end",
|
|
893
908
|
"_escaped_byte_quote_end",
|
|
894
909
|
"_escaped_identifier_end",
|
|
910
|
+
"_identifier_escaped_sequences",
|
|
895
911
|
"_next_name",
|
|
896
912
|
"_identifier_start",
|
|
897
913
|
"_identifier_end",
|
|
@@ -944,6 +960,7 @@ class Generator:
|
|
|
944
960
|
else ""
|
|
945
961
|
)
|
|
946
962
|
self._escaped_identifier_end = self.dialect.IDENTIFIER_END * 2
|
|
963
|
+
self._identifier_escaped_sequences = self.dialect.IDENTIFIER_ESCAPED_SEQUENCES
|
|
947
964
|
|
|
948
965
|
self._next_name = name_sequence("_t")
|
|
949
966
|
|
|
@@ -1569,8 +1586,10 @@ class Generator:
|
|
|
1569
1586
|
)
|
|
1570
1587
|
search = self.sql(expression, "search")
|
|
1571
1588
|
search = f" {search}" if search else ""
|
|
1589
|
+
cycle = self.sql(expression, "cycle")
|
|
1590
|
+
cycle = f" {cycle}" if cycle else ""
|
|
1572
1591
|
|
|
1573
|
-
sql = f"WITH {recursive}{sql}{search}" if sql else ""
|
|
1592
|
+
sql = f"WITH {recursive}{sql}{search}{cycle}" if sql else ""
|
|
1574
1593
|
return f"{udfs} {sql}" if udfs and sql else f"{udfs}{sql}"
|
|
1575
1594
|
|
|
1576
1595
|
def cte_sql(self, expression: exp.CTE) -> str:
|
|
@@ -1642,15 +1661,23 @@ class Generator:
|
|
|
1642
1661
|
|
|
1643
1662
|
def bytestring_sql(self, expression: exp.ByteString) -> str:
|
|
1644
1663
|
this = self.sql(expression, "this")
|
|
1664
|
+
is_bytes = bool(expression.args.get("is_bytes"))
|
|
1665
|
+
if is_bytes and self.BYTE_STRING_FUNCTION:
|
|
1666
|
+
# Hex digits can be quoted directly without escaping.
|
|
1667
|
+
return self.func(self.BYTE_STRING_FUNCTION, f"'{this.encode('latin-1').hex()}'")
|
|
1668
|
+
|
|
1645
1669
|
if self.dialect.BYTE_START:
|
|
1646
1670
|
escaped_byte_string = self.escape_str(
|
|
1647
1671
|
this,
|
|
1648
|
-
escape_backslash=
|
|
1672
|
+
escape_backslash=bool(
|
|
1673
|
+
self.dialect.tokenizer_class.NUMERIC_ESCAPES
|
|
1674
|
+
or self.dialect.tokenizer_class.DROP_UNKNOWN_ESCAPES
|
|
1675
|
+
),
|
|
1649
1676
|
delimiter=self.dialect.BYTE_END,
|
|
1650
1677
|
escaped_delimiter=self._escaped_byte_quote_end,
|
|
1651
1678
|
is_byte_string=True,
|
|
1679
|
+
is_bytes=is_bytes,
|
|
1652
1680
|
)
|
|
1653
|
-
is_bytes = expression.args.get("is_bytes", False)
|
|
1654
1681
|
delimited_byte_string = (
|
|
1655
1682
|
f"{self.dialect.BYTE_START}{escaped_byte_string}{self.dialect.BYTE_END}"
|
|
1656
1683
|
)
|
|
@@ -1787,7 +1814,8 @@ class Generator:
|
|
|
1787
1814
|
if type_value == exp.DType.USERDEFINED and expression.args.get("kind"):
|
|
1788
1815
|
type_sql = self.sql(expression, "kind")
|
|
1789
1816
|
elif type_value == exp.DType.CHARACTER_SET:
|
|
1790
|
-
|
|
1817
|
+
char = f"CHAR({interior})" if interior else "CHAR"
|
|
1818
|
+
return f"{char} CHARACTER SET {self.sql(expression, 'kind')}"
|
|
1791
1819
|
else:
|
|
1792
1820
|
type_sql = (
|
|
1793
1821
|
self.TYPE_MAPPING.get(type_value, type_value.value)
|
|
@@ -2031,6 +2059,9 @@ class Generator:
|
|
|
2031
2059
|
lower = text.lower()
|
|
2032
2060
|
quoted = expression.quoted
|
|
2033
2061
|
text = lower if self.normalize and not quoted else text
|
|
2062
|
+
if self._identifier_escaped_sequences:
|
|
2063
|
+
for char, escaped in self._identifier_escaped_sequences.items():
|
|
2064
|
+
text = text.replace(char, escaped)
|
|
2034
2065
|
text = text.replace(self._identifier_end, self._escaped_identifier_end)
|
|
2035
2066
|
if (
|
|
2036
2067
|
quoted
|
|
@@ -2959,7 +2990,20 @@ class Generator:
|
|
|
2959
2990
|
op_sql = self.seg(f"LATERAL VIEW{' OUTER' if expression.args.get('outer') else ''}")
|
|
2960
2991
|
return f"{op_sql}{self.sep()}{this}{table}{columns}"
|
|
2961
2992
|
|
|
2962
|
-
|
|
2993
|
+
table_alias = expression.args.get("alias")
|
|
2994
|
+
offset = expression.this.args.get("offset")
|
|
2995
|
+
|
|
2996
|
+
if (
|
|
2997
|
+
self.UNNEST_WITH_ORDINALITY
|
|
2998
|
+
and table_alias
|
|
2999
|
+
and isinstance(expression.this, exp.Unnest)
|
|
3000
|
+
and isinstance(offset, exp.Identifier)
|
|
3001
|
+
):
|
|
3002
|
+
# UNNEST ... WITH ORDINALITY stores the ordinality column's name in Unnest.offset
|
|
3003
|
+
table_alias = table_alias.copy()
|
|
3004
|
+
table_alias.append("columns", offset.copy())
|
|
3005
|
+
|
|
3006
|
+
alias = self.sql(table_alias)
|
|
2963
3007
|
alias = f" AS {alias}" if alias else ""
|
|
2964
3008
|
|
|
2965
3009
|
ordinality = expression.args.get("ordinality") or ""
|
|
@@ -2972,6 +3016,9 @@ class Generator:
|
|
|
2972
3016
|
def limit_sql(self, expression: exp.Limit, top: bool = False) -> str:
|
|
2973
3017
|
this = self.sql(expression, "this")
|
|
2974
3018
|
|
|
3019
|
+
if expression.is_limit_all and not self.dialect.SUPPORTS_LIMIT_ALL:
|
|
3020
|
+
return this
|
|
3021
|
+
|
|
2975
3022
|
args = [
|
|
2976
3023
|
self._simplify_unless_literal(e) if self.LIMIT_ONLY_LITERALS else e
|
|
2977
3024
|
for e in (expression.args.get(k) for k in ("offset", "expression"))
|
|
@@ -3059,6 +3106,7 @@ class Generator:
|
|
|
3059
3106
|
delimiter: str | None = None,
|
|
3060
3107
|
escaped_delimiter: str | None = None,
|
|
3061
3108
|
is_byte_string: bool = False,
|
|
3109
|
+
is_bytes: bool = False,
|
|
3062
3110
|
) -> str:
|
|
3063
3111
|
if is_byte_string:
|
|
3064
3112
|
supports_escape_sequences = self.dialect.BYTE_STRINGS_SUPPORT_ESCAPED_SEQUENCES
|
|
@@ -3071,6 +3119,10 @@ class Generator:
|
|
|
3071
3119
|
for ch in text
|
|
3072
3120
|
)
|
|
3073
3121
|
|
|
3122
|
+
if is_bytes and "x" in self.dialect.tokenizer_class.NUMERIC_ESCAPES:
|
|
3123
|
+
# Escape high bytes so they aren't re-encoded as UTF-8 characters.
|
|
3124
|
+
text = _HIGH_BYTE_RE.sub(lambda m: f"\\x{ord(m.group()):02x}", text)
|
|
3125
|
+
|
|
3074
3126
|
delimiter = delimiter or self.dialect.QUOTE_END
|
|
3075
3127
|
escaped_delimiter = escaped_delimiter or self._escaped_quote_end
|
|
3076
3128
|
|
|
@@ -3171,7 +3223,9 @@ class Generator:
|
|
|
3171
3223
|
if not (isinstance(this, exp.Column) and not this.table):
|
|
3172
3224
|
return None
|
|
3173
3225
|
|
|
3174
|
-
|
|
3226
|
+
# Only a query's own ORDER BY can reference its projection aliases
|
|
3227
|
+
order = expression.parent
|
|
3228
|
+
ancestor = order.parent if isinstance(order, exp.Order) else None
|
|
3175
3229
|
if not isinstance(ancestor, exp.Select):
|
|
3176
3230
|
return None
|
|
3177
3231
|
|
|
@@ -3321,7 +3375,9 @@ class Generator:
|
|
|
3321
3375
|
limit = exp.Limit(
|
|
3322
3376
|
expression=exp.maybe_copy(count) if count is not None else exp.Literal.number(1)
|
|
3323
3377
|
)
|
|
3324
|
-
elif
|
|
3378
|
+
elif (
|
|
3379
|
+
self.LIMIT_FETCH == "FETCH" and isinstance(limit, exp.Limit) and not limit.is_limit_all
|
|
3380
|
+
):
|
|
3325
3381
|
limit = exp.Fetch(direction="FIRST", count=exp.maybe_copy(limit.expression))
|
|
3326
3382
|
|
|
3327
3383
|
return csv(
|
|
@@ -4371,10 +4427,12 @@ class Generator:
|
|
|
4371
4427
|
return f"SET {exprs}"
|
|
4372
4428
|
|
|
4373
4429
|
def alter_sql(self, expression: exp.Alter) -> str:
|
|
4374
|
-
actions = expression.
|
|
4430
|
+
actions = expression.actions
|
|
4375
4431
|
|
|
4376
|
-
if
|
|
4377
|
-
|
|
4432
|
+
if (
|
|
4433
|
+
not self.dialect.ALTER_TABLE_ADD_REQUIRED_FOR_EACH_COLUMN
|
|
4434
|
+
and actions
|
|
4435
|
+
and isinstance(actions[0], exp.ColumnDef)
|
|
4378
4436
|
):
|
|
4379
4437
|
actions_sql = self.expressions(expression, key="actions", flat=True)
|
|
4380
4438
|
actions_sql = f"ADD {actions_sql}"
|
|
@@ -4401,8 +4459,18 @@ class Generator:
|
|
|
4401
4459
|
on_cluster = self.sql(expression, "cluster")
|
|
4402
4460
|
on_cluster = f" {on_cluster}" if on_cluster else ""
|
|
4403
4461
|
only = " ONLY" if expression.args.get("only") else ""
|
|
4404
|
-
options =
|
|
4405
|
-
|
|
4462
|
+
options = expression.args.get("options") or []
|
|
4463
|
+
options_sql = self.expressions(
|
|
4464
|
+
sqls=[o for o in options if not isinstance(o, self.ALTER_PARTITION_OPTIONS)]
|
|
4465
|
+
)
|
|
4466
|
+
options_sql = f", {options_sql}" if options_sql and actions_sql else options_sql
|
|
4467
|
+
partitions_sql = self.expressions(
|
|
4468
|
+
sqls=[o for o in options if isinstance(o, self.ALTER_PARTITION_OPTIONS)],
|
|
4469
|
+
sep=" ",
|
|
4470
|
+
flat=True,
|
|
4471
|
+
)
|
|
4472
|
+
if partitions_sql and (actions_sql or options_sql):
|
|
4473
|
+
partitions_sql = f" {partitions_sql}"
|
|
4406
4474
|
kind = self.sql(expression, "kind")
|
|
4407
4475
|
not_valid = " NOT VALID" if expression.args.get("not_valid") else ""
|
|
4408
4476
|
check = " WITH CHECK" if expression.args.get("check") else ""
|
|
@@ -4414,7 +4482,7 @@ class Generator:
|
|
|
4414
4482
|
this = self.sql(expression, "this")
|
|
4415
4483
|
this = f" {this}" if this else ""
|
|
4416
4484
|
|
|
4417
|
-
return f"ALTER {iceberg}{kind}{exists}{only}{this}{on_cluster}{check}{self.sep()}{actions_sql}{not_valid}{
|
|
4485
|
+
return f"ALTER {iceberg}{kind}{exists}{only}{this}{on_cluster}{check}{self.sep()}{actions_sql}{not_valid}{options_sql}{partitions_sql}{cascade}"
|
|
4418
4486
|
|
|
4419
4487
|
def altersession_sql(self, expression: exp.AlterSession) -> str:
|
|
4420
4488
|
items_sql = self.expressions(expression, flat=True)
|
|
@@ -4477,12 +4545,14 @@ class Generator:
|
|
|
4477
4545
|
return f"{this_sql} HAVING {kind} {expression_sql}"
|
|
4478
4546
|
|
|
4479
4547
|
def intdiv_sql(self, expression: exp.IntDiv) -> str:
|
|
4480
|
-
return self.
|
|
4481
|
-
|
|
4482
|
-
|
|
4483
|
-
|
|
4484
|
-
|
|
4485
|
-
|
|
4548
|
+
return self._truncated_div_sql(expression.this, expression.expression)
|
|
4549
|
+
|
|
4550
|
+
def _truncated_div_sql(self, this: exp.Expr, divisor: exp.Expr) -> str:
|
|
4551
|
+
div: exp.Expr = exp.Div(this=this, expression=divisor)
|
|
4552
|
+
if self.CAST_TO_INT_ROUNDS:
|
|
4553
|
+
div = exp.Trunc(this=div)
|
|
4554
|
+
|
|
4555
|
+
return self.sql(exp.Cast(this=div, to=exp.DataType(this=exp.DType.BIGINT)))
|
|
4486
4556
|
|
|
4487
4557
|
def dpipe_sql(self, expression: exp.DPipe) -> str:
|
|
4488
4558
|
if self.dialect.STRICT_STRING_CONCAT and expression.args.get("safe"):
|
|
@@ -4501,12 +4571,14 @@ class Generator:
|
|
|
4501
4571
|
|
|
4502
4572
|
elif not self.dialect.TYPED_DIVISION and expression.args.get("typed"):
|
|
4503
4573
|
if l.is_type(*exp.DataType.INTEGER_TYPES) and r.is_type(*exp.DataType.INTEGER_TYPES):
|
|
4504
|
-
|
|
4505
|
-
|
|
4506
|
-
|
|
4507
|
-
|
|
4508
|
-
)
|
|
4509
|
-
)
|
|
4574
|
+
# Native integer division depends on the target's operand types, which may differ
|
|
4575
|
+
# from the source's (e.g. FLOOR(int) is DOUBLE in DuckDB), unless the operands are
|
|
4576
|
+
# integer literals or casts
|
|
4577
|
+
if all(e.is_int or isinstance(e, exp.Cast) for e in (l, r)) and (
|
|
4578
|
+
expression.args.get("safe") or not self.SAFE_INT_DIVISION
|
|
4579
|
+
):
|
|
4580
|
+
return self.sql(exp.IntDiv(this=l, expression=r))
|
|
4581
|
+
return self._truncated_div_sql(l, r)
|
|
4510
4582
|
|
|
4511
4583
|
return self.binary(expression, "/")
|
|
4512
4584
|
|
|
@@ -4727,12 +4799,11 @@ class Generator:
|
|
|
4727
4799
|
elif arg_value is not None:
|
|
4728
4800
|
args.append(arg_value)
|
|
4729
4801
|
|
|
4730
|
-
|
|
4731
|
-
name = expression.meta_get("name") or expression.sql_name()
|
|
4732
|
-
else:
|
|
4733
|
-
name = expression.sql_name()
|
|
4802
|
+
return self.func(self.function_name(expression), *args)
|
|
4734
4803
|
|
|
4735
|
-
|
|
4804
|
+
def function_name(self, expression: exp.Func) -> str:
|
|
4805
|
+
name_key = self.dialect.ORIGINAL_NAME_META_KEY
|
|
4806
|
+
return (expression.meta_get(name_key) if name_key else None) or expression.sql_name()
|
|
4736
4807
|
|
|
4737
4808
|
def func(
|
|
4738
4809
|
self,
|
|
@@ -5309,6 +5380,28 @@ class Generator:
|
|
|
5309
5380
|
sqlglot.dialects.dialect.unit_to_str(expression),
|
|
5310
5381
|
)
|
|
5311
5382
|
|
|
5383
|
+
def arrayinsert_sql(self, expression: exp.ArrayInsert, index_offset: int = 0) -> str:
|
|
5384
|
+
this = expression.this
|
|
5385
|
+
position = expression.args["position"]
|
|
5386
|
+
offset = index_offset - (expression.args.get("offset") or 0)
|
|
5387
|
+
|
|
5388
|
+
if offset:
|
|
5389
|
+
if position.is_int:
|
|
5390
|
+
value = position.to_py()
|
|
5391
|
+
if value >= 0:
|
|
5392
|
+
position = exp.Literal.number(value + offset)
|
|
5393
|
+
elif offset < 0 and value == -1:
|
|
5394
|
+
# 1-based -1 appends, which a 0-based position can only express as the size
|
|
5395
|
+
position = exp.ArraySize(this=this.copy())
|
|
5396
|
+
else:
|
|
5397
|
+
# Negative positions count from the end, so they shift in the opposite
|
|
5398
|
+
# direction, e.g. 0-based -1 (before the last element) is 1-based -2
|
|
5399
|
+
position = exp.Literal.number(value - offset)
|
|
5400
|
+
else:
|
|
5401
|
+
self.unsupported("ARRAY_INSERT position can only be converted if it's a literal")
|
|
5402
|
+
|
|
5403
|
+
return self.func("ARRAY_INSERT", this, position, expression.expression)
|
|
5404
|
+
|
|
5312
5405
|
def arrayany_sql(self, expression: exp.ArrayAny) -> str:
|
|
5313
5406
|
if self.CAN_IMPLEMENT_ARRAY_ANY:
|
|
5314
5407
|
filtered = exp.ArrayFilter(this=expression.this, expression=expression.expression)
|
|
@@ -5710,9 +5803,18 @@ class Generator:
|
|
|
5710
5803
|
|
|
5711
5804
|
def multitableinserts_sql(self, expression: exp.MultitableInserts) -> str:
|
|
5712
5805
|
kind = self.sql(expression, "kind")
|
|
5713
|
-
|
|
5714
|
-
|
|
5715
|
-
|
|
5806
|
+
source = self.sql(expression, "source")
|
|
5807
|
+
|
|
5808
|
+
if kind:
|
|
5809
|
+
expressions = self.seg(self.expressions(expression, sep=" "))
|
|
5810
|
+
sql = f"INSERT {kind}{expressions}{self.seg(source)}"
|
|
5811
|
+
else:
|
|
5812
|
+
# If kind isn't present, we have Hive's FROM-first form:
|
|
5813
|
+
# FROM x INSERT ... SELECT ... [INSERT ... SELECT ...]
|
|
5814
|
+
inserts = self.sep().join(self.sql(e) for e in expression.expressions)
|
|
5815
|
+
sql = f"FROM {source}{self.seg(inserts)}"
|
|
5816
|
+
|
|
5817
|
+
return self.prepend_ctes(expression, sql)
|
|
5716
5818
|
|
|
5717
5819
|
def oncondition_sql(self, expression: exp.OnCondition) -> str:
|
|
5718
5820
|
# Static options like "NULL ON ERROR" are stored as strings, in contrast to "DEFAULT <expr> ON ERROR"
|
|
@@ -6148,12 +6250,16 @@ class Generator:
|
|
|
6148
6250
|
kind = self.sql(expression, "kind")
|
|
6149
6251
|
this = self.sql(expression, "this")
|
|
6150
6252
|
set = self.sql(expression, "expression")
|
|
6253
|
+
to = self.sql(expression, "to")
|
|
6254
|
+
to = f" TO {to}" if to else ""
|
|
6255
|
+
default = self.sql(expression, "default")
|
|
6256
|
+
default = f" DEFAULT {default}" if default else ""
|
|
6151
6257
|
using = self.sql(expression, "using")
|
|
6152
6258
|
using = f" USING {using}" if using else ""
|
|
6153
6259
|
|
|
6154
6260
|
kind_sql = kind if kind == "CYCLE" else f"SEARCH {kind} FIRST BY"
|
|
6155
6261
|
|
|
6156
|
-
return f"{kind_sql} {this} SET {set}{using}"
|
|
6262
|
+
return f"{kind_sql} {this} SET {set}{to}{default}{using}"
|
|
6157
6263
|
|
|
6158
6264
|
def parameterizedagg_sql(self, expression: exp.ParameterizedAgg) -> str:
|
|
6159
6265
|
params = self.expressions(expression, key="params", flat=True)
|
|
@@ -6176,6 +6282,11 @@ class Generator:
|
|
|
6176
6282
|
self.unsupported("Unsupported INSTALL statement")
|
|
6177
6283
|
return ""
|
|
6178
6284
|
|
|
6285
|
+
def liststage_sql(self, expression: exp.ListStage) -> str:
|
|
6286
|
+
pattern = self.sql(expression, "pattern")
|
|
6287
|
+
pattern = f" PATTERN = {pattern}" if pattern else ""
|
|
6288
|
+
return f"LIST {self.sql(expression, 'this')}{pattern}"
|
|
6289
|
+
|
|
6179
6290
|
def get_put_sql(self, expression: exp.Put | exp.Get) -> str:
|
|
6180
6291
|
# Snowflake GET/PUT statements:
|
|
6181
6292
|
# PUT <file> <internalStage> <properties>
|
|
@@ -6354,6 +6465,11 @@ class Generator:
|
|
|
6354
6465
|
using = f" USING {charset}" if charset else ""
|
|
6355
6466
|
return self.func(name, this + using)
|
|
6356
6467
|
|
|
6468
|
+
def weightstring_sql(self, expression: exp.WeightString) -> str:
|
|
6469
|
+
to = self.sql(expression, "to")
|
|
6470
|
+
to = f" AS {to}" if to else ""
|
|
6471
|
+
return self.func("WEIGHT_STRING", f"{self.sql(expression, 'this')}{to}")
|
|
6472
|
+
|
|
6357
6473
|
def block_sql(self, expression: exp.Block) -> str:
|
|
6358
6474
|
expressions = self.expressions(expression, sep="; ", flat=True)
|
|
6359
6475
|
begin = "BEGIN " if expression.args.get("begin") else ""
|
|
@@ -15,6 +15,7 @@ from sqlglot.dialects.dialect import (
|
|
|
15
15
|
inline_array_unless_query,
|
|
16
16
|
max_or_greatest,
|
|
17
17
|
min_or_least,
|
|
18
|
+
no_filter_sql,
|
|
18
19
|
no_ilike_sql,
|
|
19
20
|
regexp_replace_sql,
|
|
20
21
|
rename_func,
|
|
@@ -229,8 +230,7 @@ def _levenshtein_sql(self: BigQueryGenerator, expression: exp.Levenshtein) -> st
|
|
|
229
230
|
|
|
230
231
|
|
|
231
232
|
def _json_extract_sql(self: BigQueryGenerator, expression: JSON_EXTRACT_TYPE) -> str:
|
|
232
|
-
|
|
233
|
-
upper = name.upper()
|
|
233
|
+
upper = self.function_name(expression).upper()
|
|
234
234
|
|
|
235
235
|
dquote_escaping = upper in DQUOTES_ESCAPING_JSON_FUNCTIONS
|
|
236
236
|
|
|
@@ -257,6 +257,7 @@ class BigQueryGenerator(generator.Generator):
|
|
|
257
257
|
RENAME_TABLE_WITH_DB = False
|
|
258
258
|
NVL2_SUPPORTED = False
|
|
259
259
|
UNNEST_WITH_ORDINALITY = False
|
|
260
|
+
CAST_TO_INT_ROUNDS = True
|
|
260
261
|
COLLATE_IS_FUNC = True
|
|
261
262
|
LIMIT_ONLY_LITERALS = True
|
|
262
263
|
SUPPORTS_TABLE_ALIAS_COLUMNS = False
|
|
@@ -335,6 +336,7 @@ class BigQueryGenerator(generator.Generator):
|
|
|
335
336
|
exp.DatetimeAdd: date_add_interval_sql("DATETIME", "ADD"),
|
|
336
337
|
exp.DatetimeSub: date_add_interval_sql("DATETIME", "SUB"),
|
|
337
338
|
exp.DateFromUnixDate: rename_func("DATE_FROM_UNIX_DATE"),
|
|
339
|
+
exp.Filter: no_filter_sql,
|
|
338
340
|
exp.FromTimeZone: lambda self, e: self.func(
|
|
339
341
|
"DATETIME", self.func("TIMESTAMP", e.this, e.args.get("zone")), "'UTC'"
|
|
340
342
|
),
|