sqlglot 27.18.0__py3-none-any.whl → 27.20.0__py3-none-any.whl
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.
- sqlglot/_version.py +2 -2
- sqlglot/dialects/bigquery.py +25 -9
- sqlglot/dialects/snowflake.py +31 -0
- sqlglot/dialects/sqlite.py +9 -0
- sqlglot/dialects/starrocks.py +3 -0
- sqlglot/expressions.py +92 -25
- sqlglot/generator.py +3 -0
- sqlglot/helper.py +0 -18
- sqlglot/parser.py +3 -1
- {sqlglot-27.18.0.dist-info → sqlglot-27.20.0.dist-info}/METADATA +3 -1
- {sqlglot-27.18.0.dist-info → sqlglot-27.20.0.dist-info}/RECORD +14 -14
- {sqlglot-27.18.0.dist-info → sqlglot-27.20.0.dist-info}/WHEEL +0 -0
- {sqlglot-27.18.0.dist-info → sqlglot-27.20.0.dist-info}/licenses/LICENSE +0 -0
- {sqlglot-27.18.0.dist-info → sqlglot-27.20.0.dist-info}/top_level.txt +0 -0
sqlglot/_version.py
CHANGED
|
@@ -28,7 +28,7 @@ version_tuple: VERSION_TUPLE
|
|
|
28
28
|
commit_id: COMMIT_ID
|
|
29
29
|
__commit_id__: COMMIT_ID
|
|
30
30
|
|
|
31
|
-
__version__ = version = '27.
|
|
32
|
-
__version_tuple__ = version_tuple = (27,
|
|
31
|
+
__version__ = version = '27.20.0'
|
|
32
|
+
__version_tuple__ = version_tuple = (27, 20, 0)
|
|
33
33
|
|
|
34
34
|
__commit_id__ = commit_id = None
|
sqlglot/dialects/bigquery.py
CHANGED
|
@@ -754,15 +754,31 @@ class BigQuery(Dialect):
|
|
|
754
754
|
SUPPORTS_IMPLICIT_UNNEST = True
|
|
755
755
|
JOINS_HAVE_EQUAL_PRECEDENCE = True
|
|
756
756
|
|
|
757
|
-
# BigQuery does not allow ASC/DESC to be used as an identifier
|
|
758
|
-
ID_VAR_TOKENS =
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
757
|
+
# BigQuery does not allow ASC/DESC to be used as an identifier, allows GRANT as an identifier
|
|
758
|
+
ID_VAR_TOKENS = {
|
|
759
|
+
*parser.Parser.ID_VAR_TOKENS,
|
|
760
|
+
TokenType.GRANT,
|
|
761
|
+
} - {TokenType.ASC, TokenType.DESC}
|
|
762
|
+
|
|
763
|
+
ALIAS_TOKENS = {
|
|
764
|
+
*parser.Parser.ALIAS_TOKENS,
|
|
765
|
+
TokenType.GRANT,
|
|
766
|
+
} - {TokenType.ASC, TokenType.DESC}
|
|
767
|
+
|
|
768
|
+
TABLE_ALIAS_TOKENS = {
|
|
769
|
+
*parser.Parser.TABLE_ALIAS_TOKENS,
|
|
770
|
+
TokenType.GRANT,
|
|
771
|
+
} - {TokenType.ASC, TokenType.DESC}
|
|
772
|
+
|
|
773
|
+
COMMENT_TABLE_ALIAS_TOKENS = {
|
|
774
|
+
*parser.Parser.COMMENT_TABLE_ALIAS_TOKENS,
|
|
775
|
+
TokenType.GRANT,
|
|
776
|
+
} - {TokenType.ASC, TokenType.DESC}
|
|
777
|
+
|
|
778
|
+
UPDATE_ALIAS_TOKENS = {
|
|
779
|
+
*parser.Parser.UPDATE_ALIAS_TOKENS,
|
|
780
|
+
TokenType.GRANT,
|
|
781
|
+
} - {TokenType.ASC, TokenType.DESC}
|
|
766
782
|
|
|
767
783
|
FUNCTIONS = {
|
|
768
784
|
**parser.Parser.FUNCTIONS,
|
sqlglot/dialects/snowflake.py
CHANGED
|
@@ -532,14 +532,18 @@ class Snowflake(Dialect):
|
|
|
532
532
|
exp.DataType.Type.INT: {
|
|
533
533
|
*Dialect.TYPE_TO_EXPRESSIONS[exp.DataType.Type.INT],
|
|
534
534
|
exp.Ascii,
|
|
535
|
+
exp.ByteLength,
|
|
535
536
|
exp.Length,
|
|
537
|
+
exp.RtrimmedLength,
|
|
536
538
|
exp.BitLength,
|
|
537
539
|
exp.Levenshtein,
|
|
538
540
|
exp.JarowinklerSimilarity,
|
|
541
|
+
exp.StrPosition,
|
|
539
542
|
},
|
|
540
543
|
exp.DataType.Type.VARCHAR: {
|
|
541
544
|
*Dialect.TYPE_TO_EXPRESSIONS[exp.DataType.Type.VARCHAR],
|
|
542
545
|
exp.Base64DecodeString,
|
|
546
|
+
exp.TryBase64DecodeString,
|
|
543
547
|
exp.Base64Encode,
|
|
544
548
|
exp.DecompressString,
|
|
545
549
|
exp.MD5,
|
|
@@ -550,6 +554,7 @@ class Snowflake(Dialect):
|
|
|
550
554
|
exp.Collate,
|
|
551
555
|
exp.Collation,
|
|
552
556
|
exp.HexDecodeString,
|
|
557
|
+
exp.TryHexDecodeString,
|
|
553
558
|
exp.HexEncode,
|
|
554
559
|
exp.Initcap,
|
|
555
560
|
exp.RegexpExtract,
|
|
@@ -558,12 +563,16 @@ class Snowflake(Dialect):
|
|
|
558
563
|
exp.Replace,
|
|
559
564
|
exp.SHA,
|
|
560
565
|
exp.SHA2,
|
|
566
|
+
exp.Soundex,
|
|
561
567
|
exp.Space,
|
|
568
|
+
exp.SplitPart,
|
|
562
569
|
exp.Uuid,
|
|
563
570
|
},
|
|
564
571
|
exp.DataType.Type.BINARY: {
|
|
565
572
|
*Dialect.TYPE_TO_EXPRESSIONS[exp.DataType.Type.BINARY],
|
|
566
573
|
exp.Base64DecodeBinary,
|
|
574
|
+
exp.TryBase64DecodeBinary,
|
|
575
|
+
exp.TryHexDecodeBinary,
|
|
567
576
|
exp.Compress,
|
|
568
577
|
exp.DecompressBinary,
|
|
569
578
|
exp.MD5Digest,
|
|
@@ -579,6 +588,13 @@ class Snowflake(Dialect):
|
|
|
579
588
|
exp.DataType.Type.ARRAY: {
|
|
580
589
|
exp.Split,
|
|
581
590
|
},
|
|
591
|
+
exp.DataType.Type.OBJECT: {
|
|
592
|
+
exp.ParseUrl,
|
|
593
|
+
exp.ParseIp,
|
|
594
|
+
},
|
|
595
|
+
exp.DataType.Type.DECIMAL: {
|
|
596
|
+
exp.RegexpCount,
|
|
597
|
+
},
|
|
582
598
|
}
|
|
583
599
|
|
|
584
600
|
ANNOTATORS = {
|
|
@@ -600,6 +616,9 @@ class Snowflake(Dialect):
|
|
|
600
616
|
},
|
|
601
617
|
exp.ConcatWs: lambda self, e: self._annotate_by_args(e, "expressions"),
|
|
602
618
|
exp.Reverse: _annotate_reverse,
|
|
619
|
+
exp.RegexpCount: lambda self, e: self._annotate_with_type(
|
|
620
|
+
e, exp.DataType.build("NUMBER", dialect="snowflake")
|
|
621
|
+
),
|
|
603
622
|
}
|
|
604
623
|
|
|
605
624
|
TIME_MAPPING = {
|
|
@@ -732,6 +751,9 @@ class Snowflake(Dialect):
|
|
|
732
751
|
"NULLIFZERO": _build_if_from_nullifzero,
|
|
733
752
|
"OBJECT_CONSTRUCT": _build_object_construct,
|
|
734
753
|
"OCTET_LENGTH": exp.ByteLength.from_arg_list,
|
|
754
|
+
"PARSE_URL": lambda args: exp.ParseUrl(
|
|
755
|
+
this=seq_get(args, 0), permissive=seq_get(args, 1)
|
|
756
|
+
),
|
|
735
757
|
"REGEXP_EXTRACT_ALL": _build_regexp_extract(exp.RegexpExtractAll),
|
|
736
758
|
"REGEXP_REPLACE": _build_regexp_replace,
|
|
737
759
|
"REGEXP_SUBSTR": _build_regexp_extract(exp.RegexpExtract),
|
|
@@ -783,6 +805,7 @@ class Snowflake(Dialect):
|
|
|
783
805
|
FUNCTION_PARSERS = {
|
|
784
806
|
**parser.Parser.FUNCTION_PARSERS,
|
|
785
807
|
"DATE_PART": lambda self: self._parse_date_part(),
|
|
808
|
+
"DIRECTORY": lambda self: self._parse_directory(),
|
|
786
809
|
"OBJECT_CONSTRUCT_KEEP_NULL": lambda self: self._parse_json_object(),
|
|
787
810
|
"LISTAGG": lambda self: self._parse_string_agg(),
|
|
788
811
|
"SEMANTIC_VIEW": lambda self: self._parse_semantic_view(),
|
|
@@ -892,6 +915,14 @@ class Snowflake(Dialect):
|
|
|
892
915
|
),
|
|
893
916
|
}
|
|
894
917
|
|
|
918
|
+
def _parse_directory(self) -> exp.DirectoryStage:
|
|
919
|
+
table = self._parse_table_parts()
|
|
920
|
+
|
|
921
|
+
if isinstance(table, exp.Table):
|
|
922
|
+
table = table.this
|
|
923
|
+
|
|
924
|
+
return self.expression(exp.DirectoryStage, this=table)
|
|
925
|
+
|
|
895
926
|
def _parse_use(self) -> exp.Use:
|
|
896
927
|
if self._match_text_seq("SECONDARY", "ROLES"):
|
|
897
928
|
this = self._match_texts(("ALL", "NONE")) and exp.var(self._prev.text.upper())
|
sqlglot/dialects/sqlite.py
CHANGED
|
@@ -342,3 +342,12 @@ class SQLite(Dialect):
|
|
|
342
342
|
|
|
343
343
|
def respectnulls_sql(self, expression: exp.RespectNulls) -> str:
|
|
344
344
|
return self.sql(expression.this)
|
|
345
|
+
|
|
346
|
+
def windowspec_sql(self, expression: exp.WindowSpec) -> str:
|
|
347
|
+
if (
|
|
348
|
+
expression.text("kind").upper() == "RANGE"
|
|
349
|
+
and expression.text("start").upper() == "CURRENT ROW"
|
|
350
|
+
):
|
|
351
|
+
return "RANGE CURRENT ROW"
|
|
352
|
+
|
|
353
|
+
return super().windowspec_sql(expression)
|
sqlglot/dialects/starrocks.py
CHANGED
|
@@ -32,6 +32,7 @@ def st_distance_sphere(self, expression: exp.StDistance) -> str:
|
|
|
32
32
|
|
|
33
33
|
class StarRocks(MySQL):
|
|
34
34
|
STRICT_JSON_PATH_SYNTAX = False
|
|
35
|
+
INDEX_OFFSET = 1
|
|
35
36
|
|
|
36
37
|
class Tokenizer(MySQL.Tokenizer):
|
|
37
38
|
KEYWORDS = {
|
|
@@ -49,6 +50,7 @@ class StarRocks(MySQL):
|
|
|
49
50
|
"DATE_DIFF": lambda args: exp.DateDiff(
|
|
50
51
|
this=seq_get(args, 1), expression=seq_get(args, 2), unit=seq_get(args, 0)
|
|
51
52
|
),
|
|
53
|
+
"ARRAY_FLATTEN": exp.Flatten.from_arg_list,
|
|
52
54
|
"REGEXP": exp.RegexpLike.from_arg_list,
|
|
53
55
|
}
|
|
54
56
|
|
|
@@ -152,6 +154,7 @@ class StarRocks(MySQL):
|
|
|
152
154
|
exp.DateDiff: lambda self, e: self.func(
|
|
153
155
|
"DATE_DIFF", unit_to_str(e), e.this, e.expression
|
|
154
156
|
),
|
|
157
|
+
exp.Flatten: rename_func("ARRAY_FLATTEN"),
|
|
155
158
|
exp.JSONExtractScalar: arrow_json_extract_sql,
|
|
156
159
|
exp.JSONExtract: arrow_json_extract_sql,
|
|
157
160
|
exp.Property: property_sql,
|
sqlglot/expressions.py
CHANGED
|
@@ -120,19 +120,43 @@ class Expression(metaclass=_Expression):
|
|
|
120
120
|
def __eq__(self, other) -> bool:
|
|
121
121
|
return type(self) is type(other) and hash(self) == hash(other)
|
|
122
122
|
|
|
123
|
-
@property
|
|
124
|
-
def hashable_args(self) -> t.Any:
|
|
125
|
-
return frozenset(
|
|
126
|
-
(k, tuple(_norm_arg(a) for a in v) if type(v) is list else _norm_arg(v))
|
|
127
|
-
for k, v in self.args.items()
|
|
128
|
-
if not (v is None or v is False or (type(v) is list and not v))
|
|
129
|
-
)
|
|
130
|
-
|
|
131
123
|
def __hash__(self) -> int:
|
|
132
|
-
if self._hash is
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
124
|
+
if self._hash is None:
|
|
125
|
+
nodes = []
|
|
126
|
+
queue = deque([self])
|
|
127
|
+
|
|
128
|
+
while queue:
|
|
129
|
+
node = queue.popleft()
|
|
130
|
+
nodes.append(node)
|
|
131
|
+
|
|
132
|
+
for v in node.iter_expressions():
|
|
133
|
+
if v._hash is None:
|
|
134
|
+
queue.append(v)
|
|
135
|
+
|
|
136
|
+
for node in reversed(nodes):
|
|
137
|
+
hash_ = hash(node.key)
|
|
138
|
+
t = type(node)
|
|
139
|
+
|
|
140
|
+
if t is Literal or t is Identifier:
|
|
141
|
+
for k, v in sorted(node.args.items()):
|
|
142
|
+
if v:
|
|
143
|
+
hash_ = hash((hash_, k, v))
|
|
144
|
+
else:
|
|
145
|
+
for k, v in sorted(node.args.items()):
|
|
146
|
+
t = type(v)
|
|
147
|
+
|
|
148
|
+
if t is list:
|
|
149
|
+
for x in v:
|
|
150
|
+
if x is not None and x is not False:
|
|
151
|
+
hash_ = hash((hash_, k, x.lower() if type(x) is str else x))
|
|
152
|
+
else:
|
|
153
|
+
hash_ = hash((hash_, k))
|
|
154
|
+
elif v is not None and v is not False:
|
|
155
|
+
hash_ = hash((hash_, k, v.lower() if t is str else v))
|
|
156
|
+
|
|
157
|
+
node._hash = hash_
|
|
158
|
+
assert self._hash
|
|
159
|
+
return self._hash
|
|
136
160
|
|
|
137
161
|
def __reduce__(self) -> t.Tuple[t.Callable, t.Tuple[t.List[t.Dict[str, t.Any]]]]:
|
|
138
162
|
from sqlglot.serde import dump, load
|
|
@@ -369,6 +393,12 @@ class Expression(metaclass=_Expression):
|
|
|
369
393
|
overwrite: assuming an index is given, this determines whether to overwrite the
|
|
370
394
|
list entry instead of only inserting a new value (i.e., like list.insert).
|
|
371
395
|
"""
|
|
396
|
+
expression: t.Optional[Expression] = self
|
|
397
|
+
|
|
398
|
+
while expression and expression._hash is not None:
|
|
399
|
+
expression._hash = None
|
|
400
|
+
expression = expression.parent
|
|
401
|
+
|
|
372
402
|
if index is not None:
|
|
373
403
|
expressions = self.args.get(arg_key) or []
|
|
374
404
|
|
|
@@ -2235,10 +2265,14 @@ class Prior(Expression):
|
|
|
2235
2265
|
|
|
2236
2266
|
|
|
2237
2267
|
class Directory(Expression):
|
|
2238
|
-
# https://spark.apache.org/docs/3.0.0-preview/sql-ref-syntax-dml-insert-overwrite-directory-hive.html
|
|
2239
2268
|
arg_types = {"this": True, "local": False, "row_format": False}
|
|
2240
2269
|
|
|
2241
2270
|
|
|
2271
|
+
# https://docs.snowflake.com/en/user-guide/data-load-dirtables-query
|
|
2272
|
+
class DirectoryStage(Expression):
|
|
2273
|
+
pass
|
|
2274
|
+
|
|
2275
|
+
|
|
2242
2276
|
class ForeignKey(Expression):
|
|
2243
2277
|
arg_types = {
|
|
2244
2278
|
"expressions": False,
|
|
@@ -2298,10 +2332,6 @@ class Identifier(Expression):
|
|
|
2298
2332
|
def quoted(self) -> bool:
|
|
2299
2333
|
return bool(self.args.get("quoted"))
|
|
2300
2334
|
|
|
2301
|
-
@property
|
|
2302
|
-
def hashable_args(self) -> t.Any:
|
|
2303
|
-
return (self.this, self.quoted)
|
|
2304
|
-
|
|
2305
2335
|
@property
|
|
2306
2336
|
def output_name(self) -> str:
|
|
2307
2337
|
return self.name
|
|
@@ -2536,10 +2566,6 @@ class LimitOptions(Expression):
|
|
|
2536
2566
|
class Literal(Condition):
|
|
2537
2567
|
arg_types = {"this": True, "is_string": True}
|
|
2538
2568
|
|
|
2539
|
-
@property
|
|
2540
|
-
def hashable_args(self) -> t.Any:
|
|
2541
|
-
return (self.this, self.args.get("is_string"))
|
|
2542
|
-
|
|
2543
2569
|
@classmethod
|
|
2544
2570
|
def number(cls, number) -> Literal:
|
|
2545
2571
|
return cls(this=str(number), is_string=False)
|
|
@@ -6427,14 +6453,36 @@ class Base64DecodeBinary(Func):
|
|
|
6427
6453
|
arg_types = {"this": True, "alphabet": False}
|
|
6428
6454
|
|
|
6429
6455
|
|
|
6456
|
+
# https://docs.snowflake.com/en/sql-reference/functions/base64_decode_string
|
|
6430
6457
|
class Base64DecodeString(Func):
|
|
6431
6458
|
arg_types = {"this": True, "alphabet": False}
|
|
6432
6459
|
|
|
6433
6460
|
|
|
6461
|
+
# https://docs.snowflake.com/en/sql-reference/functions/base64_encode
|
|
6434
6462
|
class Base64Encode(Func):
|
|
6435
6463
|
arg_types = {"this": True, "max_line_length": False, "alphabet": False}
|
|
6436
6464
|
|
|
6437
6465
|
|
|
6466
|
+
# https://docs.snowflake.com/en/sql-reference/functions/try_base64_decode_binary
|
|
6467
|
+
class TryBase64DecodeBinary(Func):
|
|
6468
|
+
arg_types = {"this": True, "alphabet": False}
|
|
6469
|
+
|
|
6470
|
+
|
|
6471
|
+
# https://docs.snowflake.com/en/sql-reference/functions/try_base64_decode_string
|
|
6472
|
+
class TryBase64DecodeString(Func):
|
|
6473
|
+
arg_types = {"this": True, "alphabet": False}
|
|
6474
|
+
|
|
6475
|
+
|
|
6476
|
+
# https://docs.snowflake.com/en/sql-reference/functions/try_hex_decode_binary
|
|
6477
|
+
class TryHexDecodeBinary(Func):
|
|
6478
|
+
pass
|
|
6479
|
+
|
|
6480
|
+
|
|
6481
|
+
# https://docs.snowflake.com/en/sql-reference/functions/try_hex_decode_string
|
|
6482
|
+
class TryHexDecodeString(Func):
|
|
6483
|
+
pass
|
|
6484
|
+
|
|
6485
|
+
|
|
6438
6486
|
# https://trino.io/docs/current/functions/datetime.html#from_iso8601_timestamp
|
|
6439
6487
|
class FromISO8601Timestamp(Func):
|
|
6440
6488
|
_sql_names = ["FROM_ISO8601_TIMESTAMP"]
|
|
@@ -6888,6 +6936,16 @@ class ParseJSON(Func):
|
|
|
6888
6936
|
arg_types = {"this": True, "expression": False, "safe": False}
|
|
6889
6937
|
|
|
6890
6938
|
|
|
6939
|
+
# Snowflake: https://docs.snowflake.com/en/sql-reference/functions/parse_url
|
|
6940
|
+
# Databricks: https://docs.databricks.com/aws/en/sql/language-manual/functions/parse_url
|
|
6941
|
+
class ParseUrl(Func):
|
|
6942
|
+
arg_types = {"this": True, "part_to_extract": False, "key": False, "permissive": False}
|
|
6943
|
+
|
|
6944
|
+
|
|
6945
|
+
class ParseIp(Func):
|
|
6946
|
+
arg_types = {"this": True, "type": True, "permissive": False}
|
|
6947
|
+
|
|
6948
|
+
|
|
6891
6949
|
class ParseTime(Func):
|
|
6892
6950
|
arg_types = {"this": True, "format": True}
|
|
6893
6951
|
|
|
@@ -6918,6 +6976,10 @@ class Length(Func):
|
|
|
6918
6976
|
_sql_names = ["LENGTH", "LEN", "CHAR_LENGTH", "CHARACTER_LENGTH"]
|
|
6919
6977
|
|
|
6920
6978
|
|
|
6979
|
+
class RtrimmedLength(Func):
|
|
6980
|
+
pass
|
|
6981
|
+
|
|
6982
|
+
|
|
6921
6983
|
class BitLength(Func):
|
|
6922
6984
|
pass
|
|
6923
6985
|
|
|
@@ -7235,6 +7297,15 @@ class RegexpSplit(Func):
|
|
|
7235
7297
|
arg_types = {"this": True, "expression": True, "limit": False}
|
|
7236
7298
|
|
|
7237
7299
|
|
|
7300
|
+
class RegexpCount(Func):
|
|
7301
|
+
arg_types = {
|
|
7302
|
+
"this": True,
|
|
7303
|
+
"expression": True,
|
|
7304
|
+
"position": False,
|
|
7305
|
+
"parameters": False,
|
|
7306
|
+
}
|
|
7307
|
+
|
|
7308
|
+
|
|
7238
7309
|
class Repeat(Func):
|
|
7239
7310
|
arg_types = {"this": True, "times": True}
|
|
7240
7311
|
|
|
@@ -7698,10 +7769,6 @@ class TableColumn(Expression):
|
|
|
7698
7769
|
pass
|
|
7699
7770
|
|
|
7700
7771
|
|
|
7701
|
-
def _norm_arg(arg):
|
|
7702
|
-
return arg.lower() if type(arg) is str else arg
|
|
7703
|
-
|
|
7704
|
-
|
|
7705
7772
|
ALL_FUNCTIONS = subclasses(__name__, Func, (AggFunc, Anonymous, Func))
|
|
7706
7773
|
FUNCTION_BY_NAME = {name: func for func in ALL_FUNCTIONS for name in func.sql_names()}
|
|
7707
7774
|
|
sqlglot/generator.py
CHANGED
|
@@ -5334,3 +5334,6 @@ class Generator(metaclass=_Generator):
|
|
|
5334
5334
|
def modelattribute_sql(self, expression: exp.ModelAttribute) -> str:
|
|
5335
5335
|
self.unsupported("The model!attribute syntax is not supported")
|
|
5336
5336
|
return ""
|
|
5337
|
+
|
|
5338
|
+
def directorystage_sql(self, expression: exp.DirectoryStage) -> str:
|
|
5339
|
+
return self.func("DIRECTORY", expression.this)
|
sqlglot/helper.py
CHANGED
|
@@ -226,31 +226,13 @@ def while_changing(expression: Expression, func: t.Callable[[Expression], E]) ->
|
|
|
226
226
|
Returns:
|
|
227
227
|
The transformed expression.
|
|
228
228
|
"""
|
|
229
|
-
end_hash: t.Optional[int] = None
|
|
230
229
|
|
|
231
230
|
while True:
|
|
232
|
-
# No need to walk the AST– we've already cached the hashes in the previous iteration
|
|
233
|
-
if end_hash is None:
|
|
234
|
-
for n in reversed(tuple(expression.walk())):
|
|
235
|
-
n._hash = hash(n)
|
|
236
|
-
|
|
237
231
|
start_hash = hash(expression)
|
|
238
232
|
expression = func(expression)
|
|
239
|
-
|
|
240
|
-
expression_nodes = tuple(expression.walk())
|
|
241
|
-
|
|
242
|
-
# Uncache previous caches so we can recompute them
|
|
243
|
-
for n in reversed(expression_nodes):
|
|
244
|
-
n._hash = None
|
|
245
|
-
n._hash = hash(n)
|
|
246
|
-
|
|
247
233
|
end_hash = hash(expression)
|
|
248
234
|
|
|
249
235
|
if start_hash == end_hash:
|
|
250
|
-
# ... and reset the hash so we don't risk it becoming out of date if a mutation happens
|
|
251
|
-
for n in expression_nodes:
|
|
252
|
-
n._hash = None
|
|
253
|
-
|
|
254
236
|
break
|
|
255
237
|
|
|
256
238
|
return expression
|
sqlglot/parser.py
CHANGED
|
@@ -809,6 +809,8 @@ class Parser(metaclass=_Parser):
|
|
|
809
809
|
exp.DataType: lambda self: self._parse_types(allow_identifiers=False, schema=True),
|
|
810
810
|
exp.Expression: lambda self: self._parse_expression(),
|
|
811
811
|
exp.From: lambda self: self._parse_from(joins=True),
|
|
812
|
+
exp.GrantPrincipal: lambda self: self._parse_grant_principal(),
|
|
813
|
+
exp.GrantPrivilege: lambda self: self._parse_grant_privilege(),
|
|
812
814
|
exp.Group: lambda self: self._parse_group(),
|
|
813
815
|
exp.Having: lambda self: self._parse_having(),
|
|
814
816
|
exp.Hint: lambda self: self._parse_hint_body(),
|
|
@@ -1409,7 +1411,7 @@ class Parser(metaclass=_Parser):
|
|
|
1409
1411
|
|
|
1410
1412
|
VIEW_ATTRIBUTES = {"ENCRYPTION", "SCHEMABINDING", "VIEW_METADATA"}
|
|
1411
1413
|
|
|
1412
|
-
WINDOW_ALIAS_TOKENS = ID_VAR_TOKENS - {TokenType.ROWS}
|
|
1414
|
+
WINDOW_ALIAS_TOKENS = ID_VAR_TOKENS - {TokenType.RANGE, TokenType.ROWS}
|
|
1413
1415
|
WINDOW_BEFORE_PAREN_TOKENS = {TokenType.OVER}
|
|
1414
1416
|
WINDOW_SIDES = {"FOLLOWING", "PRECEDING"}
|
|
1415
1417
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: sqlglot
|
|
3
|
-
Version: 27.
|
|
3
|
+
Version: 27.20.0
|
|
4
4
|
Summary: An easily customizable SQL parser and transpiler
|
|
5
5
|
Author-email: Toby Mao <toby.mao@gmail.com>
|
|
6
6
|
License-Expression: MIT
|
|
@@ -89,12 +89,14 @@ pip3 install "sqlglot[rs]"
|
|
|
89
89
|
Or with a local checkout:
|
|
90
90
|
|
|
91
91
|
```
|
|
92
|
+
# Optionally prefix with UV=1 to use uv for the installation
|
|
92
93
|
make install
|
|
93
94
|
```
|
|
94
95
|
|
|
95
96
|
Requirements for development (optional):
|
|
96
97
|
|
|
97
98
|
```
|
|
99
|
+
# Optionally prefix with UV=1 to use uv for the installation
|
|
98
100
|
make install-dev
|
|
99
101
|
```
|
|
100
102
|
|
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
sqlglot/__init__.py,sha256=za08rtdPh2v7dOpGdNomttlIVGgTrKja7rPd6sQwaTg,5391
|
|
2
2
|
sqlglot/__main__.py,sha256=022c173KqxsiABWTEpUIq_tJUxuNiW7a7ABsxBXqvu8,2069
|
|
3
3
|
sqlglot/_typing.py,sha256=-1HPyr3w5COlSJWqlgt8jhFk2dyMvBuvVBqIX1wyVCM,642
|
|
4
|
-
sqlglot/_version.py,sha256=
|
|
4
|
+
sqlglot/_version.py,sha256=W-gB5oTd5rWsYZXOhmfTMtDc_wY3Dl-VUjAJOtLX5qo,708
|
|
5
5
|
sqlglot/diff.py,sha256=PtOllQMQa1Sw1-V2Y8eypmDqGujXYPaTOp_WLsWkAWk,17314
|
|
6
6
|
sqlglot/errors.py,sha256=QNKMr-pzLUDR-tuMmn_GK6iMHUIVdb_YSJ_BhGEvuso,2126
|
|
7
|
-
sqlglot/expressions.py,sha256=
|
|
8
|
-
sqlglot/generator.py,sha256=
|
|
9
|
-
sqlglot/helper.py,sha256=
|
|
7
|
+
sqlglot/expressions.py,sha256=jQs1lR1Nh5nmXYEjaYVakXgMijNgaWmh1fsOOZ10imE,260181
|
|
8
|
+
sqlglot/generator.py,sha256=KyFuqWQpawTj3rWV7ONKO4euqVTzV8aFU3desDu8fso,226565
|
|
9
|
+
sqlglot/helper.py,sha256=OOt5_Mbmnl4Uy6WO6v7DR1iLPcb3v6ITybpq6usf3jw,14471
|
|
10
10
|
sqlglot/jsonpath.py,sha256=SQgaxzaEYBN7At9dkTK4N1Spk6xHxvHL6QtCIP6iM30,7905
|
|
11
11
|
sqlglot/lineage.py,sha256=Qj5ykuDNcATppb9vOjoIKBqRVLbu3OMPiZk9f3iyv40,15312
|
|
12
|
-
sqlglot/parser.py,sha256=
|
|
12
|
+
sqlglot/parser.py,sha256=bVpU72Ace-vGXkiqoojKXFGRpXxProri31Q3WP1TQuE,337453
|
|
13
13
|
sqlglot/planner.py,sha256=ql7Li-bWJRcyXzNaZy_n6bQ6B2ZfunEIB8Ztv2xaxq4,14634
|
|
14
14
|
sqlglot/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
15
15
|
sqlglot/schema.py,sha256=13H2qKQs27EKdTpDLOvcNnSTDAUbYNKjWtJs4aQCSOA,20509
|
|
@@ -20,7 +20,7 @@ sqlglot/transforms.py,sha256=utNDsCBsA7hPUK3-aby3DDgiY_XVMAKQqeoLm1EyihI,41218
|
|
|
20
20
|
sqlglot/trie.py,sha256=v27uXMrHfqrXlJ6GmeTSMovsB_3o0ctnlKhdNt7W6fI,2245
|
|
21
21
|
sqlglot/dialects/__init__.py,sha256=g3HRtyb32r3LooiHKTzuUNB0_rBO_RauuOegp42gB48,3811
|
|
22
22
|
sqlglot/dialects/athena.py,sha256=ofArmayYLev4qZQ15GM8mevG04qqR5WGFb2ZcuYm6x4,10966
|
|
23
|
-
sqlglot/dialects/bigquery.py,sha256=
|
|
23
|
+
sqlglot/dialects/bigquery.py,sha256=m3Tk_rieNds4i-t0v-dELB5MvLfIvJY3ozuU6FItXJ8,72758
|
|
24
24
|
sqlglot/dialects/clickhouse.py,sha256=6kx1cm0YhtHbg5kvcY64Hau2KdeC7Y26SVlVHGLyPEA,58579
|
|
25
25
|
sqlglot/dialects/databricks.py,sha256=H4QTq7gg6tJylKc_YWsGp6049KydoI_wlQUHM7iCJtI,4753
|
|
26
26
|
sqlglot/dialects/dialect.py,sha256=KfBctpr7VdrCdHrP1Tk7CqAml53tRq9x-aDAkaN-9l0,73540
|
|
@@ -42,12 +42,12 @@ sqlglot/dialects/prql.py,sha256=fwN-SPEGx-drwf1K0U2MByN-PkW3C_rOgQ3xeJeychg,7908
|
|
|
42
42
|
sqlglot/dialects/redshift.py,sha256=FIwtP3yEg-way9pa32kxCJc6IaFkHVIvgYKZA-Ilmi0,15919
|
|
43
43
|
sqlglot/dialects/risingwave.py,sha256=BqWwW1iT_OIVMwfRamaww79snnBwIgCfr22Go-ggO68,3289
|
|
44
44
|
sqlglot/dialects/singlestore.py,sha256=0QqNYOucNklPQuyeGcsisLI97qPGx_RfWKOFarJz2qw,61711
|
|
45
|
-
sqlglot/dialects/snowflake.py,sha256=
|
|
45
|
+
sqlglot/dialects/snowflake.py,sha256=_SXsdDPNopi78MT7R_YHZHoY6WDB_tZ6pVvk5VcJaYQ,79485
|
|
46
46
|
sqlglot/dialects/solr.py,sha256=pydnl4ml-3M1Fc4ALm6cMVO9h-5EtqZxPZH_91Nz1Ss,617
|
|
47
47
|
sqlglot/dialects/spark.py,sha256=PzyhkelDzbCMgJ3RVHD6yyzLIFp9NdZfwVas5IymowM,10147
|
|
48
48
|
sqlglot/dialects/spark2.py,sha256=qz36FT9k4iuiqboRpyG4VpKGkPR0P2fifmqgZ9gNUEU,14851
|
|
49
|
-
sqlglot/dialects/sqlite.py,sha256=
|
|
50
|
-
sqlglot/dialects/starrocks.py,sha256
|
|
49
|
+
sqlglot/dialects/sqlite.py,sha256=FuEDDyKZeeWVblknhFSMX7dNoS-ci5ktXpSXZeBK5xA,13592
|
|
50
|
+
sqlglot/dialects/starrocks.py,sha256=-NWQa2gJbiMMfLauX-Jy9ciJ5DUzUOk2QkPbhglz5W4,11446
|
|
51
51
|
sqlglot/dialects/tableau.py,sha256=oIawDzUITxGCWaEMB8OaNMPWhbC3U-2y09pYPm4eazc,2190
|
|
52
52
|
sqlglot/dialects/teradata.py,sha256=7LxCcRwP0Idd_OnCzA57NCdheVjHcKC2aFAKG5N49IU,18202
|
|
53
53
|
sqlglot/dialects/trino.py,sha256=Z7prRhCxIBh0KCxIQpWmVOIGHCJM9Xl5oRlqySxln4Y,4350
|
|
@@ -77,8 +77,8 @@ sqlglot/optimizer/qualify_tables.py,sha256=dA4ZazL7ShQh2JgBwpHuG-4c5lBw1TNzCnuN7
|
|
|
77
77
|
sqlglot/optimizer/scope.py,sha256=UOTrbwqcTc5iRQf0WStgYWXpE24w6riZy-tJYA18yTw,31229
|
|
78
78
|
sqlglot/optimizer/simplify.py,sha256=27IYsqbz1kyMlURSfRkm_ADSQJg-4805AOMFOjKKytU,51049
|
|
79
79
|
sqlglot/optimizer/unnest_subqueries.py,sha256=kzWUVDlxs8z9nmRx-8U-pHXPtVZhEIwkKqmKhr2QLvc,10908
|
|
80
|
-
sqlglot-27.
|
|
81
|
-
sqlglot-27.
|
|
82
|
-
sqlglot-27.
|
|
83
|
-
sqlglot-27.
|
|
84
|
-
sqlglot-27.
|
|
80
|
+
sqlglot-27.20.0.dist-info/licenses/LICENSE,sha256=p1Yk0B4oa0l8Rh-_dYyy75d8spjPd_vTloXfz4FWxys,1065
|
|
81
|
+
sqlglot-27.20.0.dist-info/METADATA,sha256=nO_Q85ybayInmXwdQV_wFMHF4kQSA0ujLlWo-H5r0I8,20825
|
|
82
|
+
sqlglot-27.20.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
83
|
+
sqlglot-27.20.0.dist-info/top_level.txt,sha256=5kRskCGA_gVADF9rSfSzPdLHXqvfMusDYeHePfNY2nQ,8
|
|
84
|
+
sqlglot-27.20.0.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|