sqlglot 27.27.0__py3-none-any.whl → 28.4.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/__init__.py +1 -0
- sqlglot/__main__.py +6 -4
- sqlglot/_version.py +2 -2
- sqlglot/dialects/bigquery.py +118 -279
- sqlglot/dialects/clickhouse.py +73 -5
- sqlglot/dialects/databricks.py +38 -1
- sqlglot/dialects/dialect.py +354 -275
- sqlglot/dialects/dremio.py +4 -1
- sqlglot/dialects/duckdb.py +754 -25
- sqlglot/dialects/exasol.py +243 -10
- sqlglot/dialects/hive.py +8 -8
- sqlglot/dialects/mysql.py +14 -4
- sqlglot/dialects/oracle.py +29 -0
- sqlglot/dialects/postgres.py +60 -26
- sqlglot/dialects/presto.py +47 -16
- sqlglot/dialects/redshift.py +16 -0
- sqlglot/dialects/risingwave.py +3 -0
- sqlglot/dialects/singlestore.py +12 -3
- sqlglot/dialects/snowflake.py +239 -218
- sqlglot/dialects/spark.py +15 -4
- sqlglot/dialects/spark2.py +11 -48
- sqlglot/dialects/sqlite.py +10 -0
- sqlglot/dialects/starrocks.py +3 -0
- sqlglot/dialects/teradata.py +5 -8
- sqlglot/dialects/trino.py +6 -0
- sqlglot/dialects/tsql.py +61 -22
- sqlglot/diff.py +4 -2
- sqlglot/errors.py +69 -0
- sqlglot/executor/__init__.py +5 -10
- sqlglot/executor/python.py +1 -29
- sqlglot/expressions.py +637 -100
- sqlglot/generator.py +160 -43
- sqlglot/helper.py +2 -44
- sqlglot/lineage.py +10 -4
- sqlglot/optimizer/annotate_types.py +247 -140
- sqlglot/optimizer/canonicalize.py +6 -1
- sqlglot/optimizer/eliminate_joins.py +1 -1
- sqlglot/optimizer/eliminate_subqueries.py +2 -2
- sqlglot/optimizer/merge_subqueries.py +5 -5
- sqlglot/optimizer/normalize.py +20 -13
- sqlglot/optimizer/normalize_identifiers.py +17 -3
- sqlglot/optimizer/optimizer.py +4 -0
- sqlglot/optimizer/pushdown_predicates.py +1 -1
- sqlglot/optimizer/qualify.py +18 -10
- sqlglot/optimizer/qualify_columns.py +122 -275
- sqlglot/optimizer/qualify_tables.py +128 -76
- sqlglot/optimizer/resolver.py +374 -0
- sqlglot/optimizer/scope.py +27 -16
- sqlglot/optimizer/simplify.py +1075 -959
- sqlglot/optimizer/unnest_subqueries.py +12 -2
- sqlglot/parser.py +296 -170
- sqlglot/planner.py +2 -2
- sqlglot/schema.py +15 -4
- sqlglot/tokens.py +42 -7
- sqlglot/transforms.py +77 -22
- sqlglot/typing/__init__.py +316 -0
- sqlglot/typing/bigquery.py +376 -0
- sqlglot/typing/hive.py +12 -0
- sqlglot/typing/presto.py +24 -0
- sqlglot/typing/snowflake.py +505 -0
- sqlglot/typing/spark2.py +58 -0
- sqlglot/typing/tsql.py +9 -0
- {sqlglot-27.27.0.dist-info → sqlglot-28.4.0.dist-info}/METADATA +2 -2
- sqlglot-28.4.0.dist-info/RECORD +92 -0
- sqlglot-27.27.0.dist-info/RECORD +0 -84
- {sqlglot-27.27.0.dist-info → sqlglot-28.4.0.dist-info}/WHEEL +0 -0
- {sqlglot-27.27.0.dist-info → sqlglot-28.4.0.dist-info}/licenses/LICENSE +0 -0
- {sqlglot-27.27.0.dist-info → sqlglot-28.4.0.dist-info}/top_level.txt +0 -0
sqlglot/parser.py
CHANGED
|
@@ -7,7 +7,14 @@ import typing as t
|
|
|
7
7
|
from collections import defaultdict
|
|
8
8
|
|
|
9
9
|
from sqlglot import exp
|
|
10
|
-
from sqlglot.errors import
|
|
10
|
+
from sqlglot.errors import (
|
|
11
|
+
ErrorLevel,
|
|
12
|
+
ParseError,
|
|
13
|
+
TokenError,
|
|
14
|
+
concat_messages,
|
|
15
|
+
highlight_sql,
|
|
16
|
+
merge_errors,
|
|
17
|
+
)
|
|
11
18
|
from sqlglot.helper import apply_index_offset, ensure_list, seq_get
|
|
12
19
|
from sqlglot.time import format_time
|
|
13
20
|
from sqlglot.tokens import Token, Tokenizer, TokenType
|
|
@@ -97,6 +104,8 @@ def build_extract_json_with_path(expr_type: t.Type[E]) -> t.Callable[[t.List, Di
|
|
|
97
104
|
)
|
|
98
105
|
if len(args) > 2 and expr_type is exp.JSONExtract:
|
|
99
106
|
expression.set("expressions", args[2:])
|
|
107
|
+
if expr_type is exp.JSONExtractScalar:
|
|
108
|
+
expression.set("scalar_only", dialect.JSON_EXTRACT_SCALAR_SCALAR_ONLY)
|
|
100
109
|
|
|
101
110
|
return expression
|
|
102
111
|
|
|
@@ -226,7 +235,12 @@ class Parser(metaclass=_Parser):
|
|
|
226
235
|
end=seq_get(args, 1),
|
|
227
236
|
step=seq_get(args, 2) or exp.Interval(this=exp.Literal.string(1), unit=exp.var("DAY")),
|
|
228
237
|
),
|
|
238
|
+
"GENERATE_UUID": lambda args, dialect: exp.Uuid(
|
|
239
|
+
is_string=dialect.UUID_IS_STRING_TYPE or None
|
|
240
|
+
),
|
|
229
241
|
"GLOB": lambda args: exp.Glob(this=seq_get(args, 1), expression=seq_get(args, 0)),
|
|
242
|
+
"GREATEST": lambda args: exp.Greatest(this=seq_get(args, 0), expressions=args[1:]),
|
|
243
|
+
"LEAST": lambda args: exp.Least(this=seq_get(args, 0), expressions=args[1:]),
|
|
230
244
|
"HEX": build_hex,
|
|
231
245
|
"JSON_EXTRACT": build_extract_json_with_path(exp.JSONExtract),
|
|
232
246
|
"JSON_EXTRACT_SCALAR": build_extract_json_with_path(exp.JSONExtractScalar),
|
|
@@ -265,6 +279,7 @@ class Parser(metaclass=_Parser):
|
|
|
265
279
|
),
|
|
266
280
|
"UNNEST": lambda args: exp.Unnest(expressions=ensure_list(seq_get(args, 0))),
|
|
267
281
|
"UPPER": build_upper,
|
|
282
|
+
"UUID": lambda args, dialect: exp.Uuid(is_string=dialect.UUID_IS_STRING_TYPE or None),
|
|
268
283
|
"VAR_MAP": build_var_map,
|
|
269
284
|
}
|
|
270
285
|
|
|
@@ -274,9 +289,13 @@ class Parser(metaclass=_Parser):
|
|
|
274
289
|
TokenType.CURRENT_TIME: exp.CurrentTime,
|
|
275
290
|
TokenType.CURRENT_TIMESTAMP: exp.CurrentTimestamp,
|
|
276
291
|
TokenType.CURRENT_USER: exp.CurrentUser,
|
|
292
|
+
TokenType.LOCALTIME: exp.Localtime,
|
|
293
|
+
TokenType.LOCALTIMESTAMP: exp.Localtimestamp,
|
|
294
|
+
TokenType.CURRENT_ROLE: exp.CurrentRole,
|
|
277
295
|
}
|
|
278
296
|
|
|
279
297
|
STRUCT_TYPE_TOKENS = {
|
|
298
|
+
TokenType.FILE,
|
|
280
299
|
TokenType.NESTED,
|
|
281
300
|
TokenType.OBJECT,
|
|
282
301
|
TokenType.STRUCT,
|
|
@@ -316,6 +335,7 @@ class Parser(metaclass=_Parser):
|
|
|
316
335
|
TokenType.UINT,
|
|
317
336
|
TokenType.BIGINT,
|
|
318
337
|
TokenType.UBIGINT,
|
|
338
|
+
TokenType.BIGNUM,
|
|
319
339
|
TokenType.INT128,
|
|
320
340
|
TokenType.UINT128,
|
|
321
341
|
TokenType.INT256,
|
|
@@ -346,6 +366,7 @@ class Parser(metaclass=_Parser):
|
|
|
346
366
|
TokenType.TINYTEXT,
|
|
347
367
|
TokenType.TIME,
|
|
348
368
|
TokenType.TIMETZ,
|
|
369
|
+
TokenType.TIME_NS,
|
|
349
370
|
TokenType.TIMESTAMP,
|
|
350
371
|
TokenType.TIMESTAMP_S,
|
|
351
372
|
TokenType.TIMESTAMP_MS,
|
|
@@ -376,6 +397,7 @@ class Parser(metaclass=_Parser):
|
|
|
376
397
|
TokenType.DECIMAL64,
|
|
377
398
|
TokenType.DECIMAL128,
|
|
378
399
|
TokenType.DECIMAL256,
|
|
400
|
+
TokenType.DECFLOAT,
|
|
379
401
|
TokenType.UDECIMAL,
|
|
380
402
|
TokenType.BIGDECIMAL,
|
|
381
403
|
TokenType.UUID,
|
|
@@ -485,6 +507,7 @@ class Parser(metaclass=_Parser):
|
|
|
485
507
|
# Tokens that can represent identifiers
|
|
486
508
|
ID_VAR_TOKENS = {
|
|
487
509
|
TokenType.ALL,
|
|
510
|
+
TokenType.ANALYZE,
|
|
488
511
|
TokenType.ATTACH,
|
|
489
512
|
TokenType.VAR,
|
|
490
513
|
TokenType.ANTI,
|
|
@@ -532,12 +555,14 @@ class Parser(metaclass=_Parser):
|
|
|
532
555
|
TokenType.LIMIT,
|
|
533
556
|
TokenType.LOAD,
|
|
534
557
|
TokenType.LOCK,
|
|
558
|
+
TokenType.MATCH,
|
|
535
559
|
TokenType.MERGE,
|
|
536
560
|
TokenType.NATURAL,
|
|
537
561
|
TokenType.NEXT,
|
|
538
562
|
TokenType.OFFSET,
|
|
539
563
|
TokenType.OPERATOR,
|
|
540
564
|
TokenType.ORDINALITY,
|
|
565
|
+
TokenType.OVER,
|
|
541
566
|
TokenType.OVERLAPS,
|
|
542
567
|
TokenType.OVERWRITE,
|
|
543
568
|
TokenType.PARTITION,
|
|
@@ -614,6 +639,7 @@ class Parser(metaclass=_Parser):
|
|
|
614
639
|
TokenType.CURRENT_TIMESTAMP,
|
|
615
640
|
TokenType.CURRENT_TIME,
|
|
616
641
|
TokenType.CURRENT_USER,
|
|
642
|
+
TokenType.CURRENT_CATALOG,
|
|
617
643
|
TokenType.FILTER,
|
|
618
644
|
TokenType.FIRST,
|
|
619
645
|
TokenType.FORMAT,
|
|
@@ -625,6 +651,8 @@ class Parser(metaclass=_Parser):
|
|
|
625
651
|
TokenType.ILIKE,
|
|
626
652
|
TokenType.INSERT,
|
|
627
653
|
TokenType.LIKE,
|
|
654
|
+
TokenType.LOCALTIME,
|
|
655
|
+
TokenType.LOCALTIMESTAMP,
|
|
628
656
|
TokenType.MERGE,
|
|
629
657
|
TokenType.NEXT,
|
|
630
658
|
TokenType.OFFSET,
|
|
@@ -633,6 +661,7 @@ class Parser(metaclass=_Parser):
|
|
|
633
661
|
TokenType.REPLACE,
|
|
634
662
|
TokenType.RLIKE,
|
|
635
663
|
TokenType.ROW,
|
|
664
|
+
TokenType.SESSION_USER,
|
|
636
665
|
TokenType.UNNEST,
|
|
637
666
|
TokenType.VAR,
|
|
638
667
|
TokenType.LEFT,
|
|
@@ -746,7 +775,7 @@ class Parser(metaclass=_Parser):
|
|
|
746
775
|
TokenType.ARROW: lambda self, expressions: self.expression(
|
|
747
776
|
exp.Lambda,
|
|
748
777
|
this=self._replace_lambda(
|
|
749
|
-
self.
|
|
778
|
+
self._parse_disjunction(),
|
|
750
779
|
expressions,
|
|
751
780
|
),
|
|
752
781
|
expressions=expressions,
|
|
@@ -754,7 +783,7 @@ class Parser(metaclass=_Parser):
|
|
|
754
783
|
TokenType.FARROW: lambda self, expressions: self.expression(
|
|
755
784
|
exp.Kwarg,
|
|
756
785
|
this=exp.var(expressions[0].name),
|
|
757
|
-
expression=self.
|
|
786
|
+
expression=self._parse_disjunction(),
|
|
758
787
|
),
|
|
759
788
|
}
|
|
760
789
|
|
|
@@ -779,6 +808,7 @@ class Parser(metaclass=_Parser):
|
|
|
779
808
|
this=this,
|
|
780
809
|
expression=self.dialect.to_json_path(path),
|
|
781
810
|
only_json_types=self.JSON_ARROWS_REQUIRE_JSON_TYPE,
|
|
811
|
+
scalar_only=self.dialect.JSON_EXTRACT_SCALAR_SCALAR_ONLY,
|
|
782
812
|
),
|
|
783
813
|
TokenType.HASH_ARROW: lambda self, this, path: self.expression(
|
|
784
814
|
exp.JSONBExtract,
|
|
@@ -806,7 +836,7 @@ class Parser(metaclass=_Parser):
|
|
|
806
836
|
exp.Cluster: lambda self: self._parse_sort(exp.Cluster, TokenType.CLUSTER_BY),
|
|
807
837
|
exp.Column: lambda self: self._parse_column(),
|
|
808
838
|
exp.ColumnDef: lambda self: self._parse_column_def(self._parse_column()),
|
|
809
|
-
exp.Condition: lambda self: self.
|
|
839
|
+
exp.Condition: lambda self: self._parse_disjunction(),
|
|
810
840
|
exp.DataType: lambda self: self._parse_types(allow_identifiers=False, schema=True),
|
|
811
841
|
exp.Expression: lambda self: self._parse_expression(),
|
|
812
842
|
exp.From: lambda self: self._parse_from(joins=True),
|
|
@@ -881,33 +911,33 @@ class Parser(metaclass=_Parser):
|
|
|
881
911
|
}
|
|
882
912
|
|
|
883
913
|
STRING_PARSERS = {
|
|
884
|
-
TokenType.HEREDOC_STRING: lambda self, token: self.expression(
|
|
885
|
-
|
|
886
|
-
),
|
|
887
|
-
TokenType.NATIONAL_STRING: lambda self, token: self.expression(
|
|
888
|
-
exp.National, this=token.text
|
|
889
|
-
),
|
|
890
|
-
TokenType.RAW_STRING: lambda self, token: self.expression(exp.RawString, this=token.text),
|
|
914
|
+
TokenType.HEREDOC_STRING: lambda self, token: self.expression(exp.RawString, token=token),
|
|
915
|
+
TokenType.NATIONAL_STRING: lambda self, token: self.expression(exp.National, token=token),
|
|
916
|
+
TokenType.RAW_STRING: lambda self, token: self.expression(exp.RawString, token=token),
|
|
891
917
|
TokenType.STRING: lambda self, token: self.expression(
|
|
892
|
-
exp.Literal,
|
|
918
|
+
exp.Literal, token=token, is_string=True
|
|
893
919
|
),
|
|
894
920
|
TokenType.UNICODE_STRING: lambda self, token: self.expression(
|
|
895
921
|
exp.UnicodeString,
|
|
896
|
-
|
|
922
|
+
token=token,
|
|
897
923
|
escape=self._match_text_seq("UESCAPE") and self._parse_string(),
|
|
898
924
|
),
|
|
899
925
|
}
|
|
900
926
|
|
|
901
927
|
NUMERIC_PARSERS = {
|
|
902
|
-
TokenType.BIT_STRING: lambda self, token: self.expression(exp.BitString,
|
|
903
|
-
TokenType.BYTE_STRING: lambda self, token: self.expression(
|
|
928
|
+
TokenType.BIT_STRING: lambda self, token: self.expression(exp.BitString, token=token),
|
|
929
|
+
TokenType.BYTE_STRING: lambda self, token: self.expression(
|
|
930
|
+
exp.ByteString,
|
|
931
|
+
token=token,
|
|
932
|
+
is_bytes=self.dialect.BYTE_STRING_IS_BYTES_TYPE or None,
|
|
933
|
+
),
|
|
904
934
|
TokenType.HEX_STRING: lambda self, token: self.expression(
|
|
905
935
|
exp.HexString,
|
|
906
|
-
|
|
936
|
+
token=token,
|
|
907
937
|
is_integer=self.dialect.HEX_STRING_IS_INTEGER_TYPE or None,
|
|
908
938
|
),
|
|
909
939
|
TokenType.NUMBER: lambda self, token: self.expression(
|
|
910
|
-
exp.Literal,
|
|
940
|
+
exp.Literal, token=token, is_string=False
|
|
911
941
|
),
|
|
912
942
|
}
|
|
913
943
|
|
|
@@ -1243,6 +1273,7 @@ class Parser(metaclass=_Parser):
|
|
|
1243
1273
|
"EXTRACT": lambda self: self._parse_extract(),
|
|
1244
1274
|
"FLOOR": lambda self: self._parse_ceil_floor(exp.Floor),
|
|
1245
1275
|
"GAP_FILL": lambda self: self._parse_gap_fill(),
|
|
1276
|
+
"INITCAP": lambda self: self._parse_initcap(),
|
|
1246
1277
|
"JSON_OBJECT": lambda self: self._parse_json_object(),
|
|
1247
1278
|
"JSON_OBJECTAGG": lambda self: self._parse_json_object(agg=True),
|
|
1248
1279
|
"JSON_TABLE": lambda self: self._parse_json_table(),
|
|
@@ -1442,6 +1473,8 @@ class Parser(metaclass=_Parser):
|
|
|
1442
1473
|
# The style options for the DESCRIBE statement
|
|
1443
1474
|
DESCRIBE_STYLES = {"ANALYZE", "EXTENDED", "FORMATTED", "HISTORY"}
|
|
1444
1475
|
|
|
1476
|
+
SET_ASSIGNMENT_DELIMITERS = {"=", ":=", "TO"}
|
|
1477
|
+
|
|
1445
1478
|
# The style options for the ANALYZE statement
|
|
1446
1479
|
ANALYZE_STYLES = {
|
|
1447
1480
|
"BUFFER_USAGE_LIMIT",
|
|
@@ -1473,7 +1506,7 @@ class Parser(metaclass=_Parser):
|
|
|
1473
1506
|
|
|
1474
1507
|
RECURSIVE_CTE_SEARCH_KIND = {"BREADTH", "DEPTH", "CYCLE"}
|
|
1475
1508
|
|
|
1476
|
-
MODIFIABLES = (exp.Query, exp.Table, exp.TableFromRows)
|
|
1509
|
+
MODIFIABLES = (exp.Query, exp.Table, exp.TableFromRows, exp.Values)
|
|
1477
1510
|
|
|
1478
1511
|
STRICT_CAST = True
|
|
1479
1512
|
|
|
@@ -1716,15 +1749,15 @@ class Parser(metaclass=_Parser):
|
|
|
1716
1749
|
error level setting.
|
|
1717
1750
|
"""
|
|
1718
1751
|
token = token or self._curr or self._prev or Token.string("")
|
|
1719
|
-
|
|
1720
|
-
|
|
1721
|
-
|
|
1722
|
-
|
|
1723
|
-
|
|
1752
|
+
formatted_sql, start_context, highlight, end_context = highlight_sql(
|
|
1753
|
+
sql=self.sql,
|
|
1754
|
+
positions=[(token.start, token.end)],
|
|
1755
|
+
context_length=self.error_message_context,
|
|
1756
|
+
)
|
|
1757
|
+
formatted_message = f"{message}. Line {token.line}, Col: {token.col}.\n {formatted_sql}"
|
|
1724
1758
|
|
|
1725
1759
|
error = ParseError.new(
|
|
1726
|
-
|
|
1727
|
-
f" {start_context}\033[4m{highlight}\033[0m{end_context}",
|
|
1760
|
+
formatted_message,
|
|
1728
1761
|
description=message,
|
|
1729
1762
|
line=token.line,
|
|
1730
1763
|
col=token.col,
|
|
@@ -1739,7 +1772,11 @@ class Parser(metaclass=_Parser):
|
|
|
1739
1772
|
self.errors.append(error)
|
|
1740
1773
|
|
|
1741
1774
|
def expression(
|
|
1742
|
-
self,
|
|
1775
|
+
self,
|
|
1776
|
+
exp_class: t.Type[E],
|
|
1777
|
+
token: t.Optional[Token] = None,
|
|
1778
|
+
comments: t.Optional[t.List[str]] = None,
|
|
1779
|
+
**kwargs,
|
|
1743
1780
|
) -> E:
|
|
1744
1781
|
"""
|
|
1745
1782
|
Creates a new, validated Expression.
|
|
@@ -1752,7 +1789,11 @@ class Parser(metaclass=_Parser):
|
|
|
1752
1789
|
Returns:
|
|
1753
1790
|
The target expression.
|
|
1754
1791
|
"""
|
|
1755
|
-
|
|
1792
|
+
if token:
|
|
1793
|
+
instance = exp_class(this=token.text, **kwargs)
|
|
1794
|
+
instance.update_positions(token)
|
|
1795
|
+
else:
|
|
1796
|
+
instance = exp_class(**kwargs)
|
|
1756
1797
|
instance.add_comments(comments) if comments else self._add_comments(instance)
|
|
1757
1798
|
return self.validate_expression(instance)
|
|
1758
1799
|
|
|
@@ -2246,7 +2287,10 @@ class Parser(metaclass=_Parser):
|
|
|
2246
2287
|
return self._parse_sortkey(compound=True)
|
|
2247
2288
|
|
|
2248
2289
|
if self._match_text_seq("SQL", "SECURITY"):
|
|
2249
|
-
return self.expression(
|
|
2290
|
+
return self.expression(
|
|
2291
|
+
exp.SqlSecurityProperty,
|
|
2292
|
+
this=self._match_texts(("DEFINER", "INVOKER")) and self._prev.text.upper(),
|
|
2293
|
+
)
|
|
2250
2294
|
|
|
2251
2295
|
index = self._index
|
|
2252
2296
|
|
|
@@ -2365,10 +2409,8 @@ class Parser(metaclass=_Parser):
|
|
|
2365
2409
|
self._match(TokenType.EQ)
|
|
2366
2410
|
prop = self.expression(
|
|
2367
2411
|
exp.WithSystemVersioningProperty,
|
|
2368
|
-
|
|
2369
|
-
|
|
2370
|
-
"with": with_,
|
|
2371
|
-
},
|
|
2412
|
+
on=True,
|
|
2413
|
+
with_=with_,
|
|
2372
2414
|
)
|
|
2373
2415
|
|
|
2374
2416
|
if self._match_text_seq("OFF"):
|
|
@@ -2683,7 +2725,7 @@ class Parser(metaclass=_Parser):
|
|
|
2683
2725
|
|
|
2684
2726
|
def _parse_partition_by(self) -> t.List[exp.Expression]:
|
|
2685
2727
|
if self._match(TokenType.PARTITION_BY):
|
|
2686
|
-
return self._parse_csv(self.
|
|
2728
|
+
return self._parse_csv(self._parse_disjunction)
|
|
2687
2729
|
return []
|
|
2688
2730
|
|
|
2689
2731
|
def _parse_partition_bound_spec(self) -> exp.PartitionBoundSpec:
|
|
@@ -2941,15 +2983,9 @@ class Parser(metaclass=_Parser):
|
|
|
2941
2983
|
self._match(TokenType.TABLE)
|
|
2942
2984
|
is_function = self._match(TokenType.FUNCTION)
|
|
2943
2985
|
|
|
2944
|
-
this = (
|
|
2945
|
-
self._parse_table(schema=True, parse_partition=True)
|
|
2946
|
-
if not is_function
|
|
2947
|
-
else self._parse_function()
|
|
2948
|
-
)
|
|
2949
|
-
if isinstance(this, exp.Table) and self._match(TokenType.ALIAS, advance=False):
|
|
2950
|
-
this.set("alias", self._parse_table_alias())
|
|
2986
|
+
this = self._parse_function() if is_function else self._parse_insert_table()
|
|
2951
2987
|
|
|
2952
|
-
returning = self._parse_returning()
|
|
2988
|
+
returning = self._parse_returning() # TSQL allows RETURNING before source
|
|
2953
2989
|
|
|
2954
2990
|
return self.expression(
|
|
2955
2991
|
exp.Insert,
|
|
@@ -2960,7 +2996,8 @@ class Parser(metaclass=_Parser):
|
|
|
2960
2996
|
stored=self._match_text_seq("STORED") and self._parse_stored(),
|
|
2961
2997
|
by_name=self._match_text_seq("BY", "NAME"),
|
|
2962
2998
|
exists=self._parse_exists(),
|
|
2963
|
-
where=self._match_pair(TokenType.REPLACE, TokenType.WHERE)
|
|
2999
|
+
where=self._match_pair(TokenType.REPLACE, TokenType.WHERE)
|
|
3000
|
+
and self._parse_disjunction(),
|
|
2964
3001
|
partition=self._match(TokenType.PARTITION_BY) and self._parse_partitioned_by(),
|
|
2965
3002
|
settings=self._match_text_seq("SETTINGS") and self._parse_settings_property(),
|
|
2966
3003
|
default=self._match_text_seq("DEFAULT", "VALUES"),
|
|
@@ -2973,6 +3010,12 @@ class Parser(metaclass=_Parser):
|
|
|
2973
3010
|
source=self._match(TokenType.TABLE) and self._parse_table(),
|
|
2974
3011
|
)
|
|
2975
3012
|
|
|
3013
|
+
def _parse_insert_table(self) -> t.Optional[exp.Expression]:
|
|
3014
|
+
this = self._parse_table(schema=True, parse_partition=True)
|
|
3015
|
+
if isinstance(this, exp.Table) and self._match(TokenType.ALIAS, advance=False):
|
|
3016
|
+
this.set("alias", self._parse_table_alias())
|
|
3017
|
+
return this
|
|
3018
|
+
|
|
2976
3019
|
def _parse_kill(self) -> exp.Kill:
|
|
2977
3020
|
kind = exp.var(self._prev.text) if self._match_texts(("CONNECTION", "QUERY")) else None
|
|
2978
3021
|
|
|
@@ -3039,10 +3082,8 @@ class Parser(metaclass=_Parser):
|
|
|
3039
3082
|
return None
|
|
3040
3083
|
return self.expression(
|
|
3041
3084
|
exp.SerdeProperties,
|
|
3042
|
-
|
|
3043
|
-
|
|
3044
|
-
"with": with_,
|
|
3045
|
-
},
|
|
3085
|
+
expressions=self._parse_wrapped_properties(),
|
|
3086
|
+
with_=with_,
|
|
3046
3087
|
)
|
|
3047
3088
|
|
|
3048
3089
|
def _parse_row_format(
|
|
@@ -3117,6 +3158,7 @@ class Parser(metaclass=_Parser):
|
|
|
3117
3158
|
cluster=self._match(TokenType.ON) and self._parse_on_property(),
|
|
3118
3159
|
where=self._parse_where(),
|
|
3119
3160
|
returning=returning or self._parse_returning(),
|
|
3161
|
+
order=self._parse_order(),
|
|
3120
3162
|
limit=self._parse_limit(),
|
|
3121
3163
|
)
|
|
3122
3164
|
|
|
@@ -3130,7 +3172,7 @@ class Parser(metaclass=_Parser):
|
|
|
3130
3172
|
elif self._match(TokenType.RETURNING, advance=False):
|
|
3131
3173
|
kwargs["returning"] = self._parse_returning()
|
|
3132
3174
|
elif self._match(TokenType.FROM, advance=False):
|
|
3133
|
-
kwargs["
|
|
3175
|
+
kwargs["from_"] = self._parse_from(joins=True)
|
|
3134
3176
|
elif self._match(TokenType.WHERE, advance=False):
|
|
3135
3177
|
kwargs["where"] = self._parse_where()
|
|
3136
3178
|
elif self._match(TokenType.ORDER_BY, advance=False):
|
|
@@ -3187,7 +3229,7 @@ class Parser(metaclass=_Parser):
|
|
|
3187
3229
|
return self.expression(
|
|
3188
3230
|
exp.Partition,
|
|
3189
3231
|
subpartition=self._prev.text.upper() == "SUBPARTITION",
|
|
3190
|
-
expressions=self._parse_wrapped_csv(self.
|
|
3232
|
+
expressions=self._parse_wrapped_csv(self._parse_disjunction),
|
|
3191
3233
|
)
|
|
3192
3234
|
|
|
3193
3235
|
def _parse_value(self, values: bool = True) -> t.Optional[exp.Tuple]:
|
|
@@ -3220,11 +3262,12 @@ class Parser(metaclass=_Parser):
|
|
|
3220
3262
|
# Support parentheses for duckdb FROM-first syntax
|
|
3221
3263
|
select = self._parse_select(from_=from_)
|
|
3222
3264
|
if select:
|
|
3223
|
-
if not select.args.get("
|
|
3224
|
-
select.set("
|
|
3265
|
+
if not select.args.get("from_"):
|
|
3266
|
+
select.set("from_", from_)
|
|
3225
3267
|
this = select
|
|
3226
3268
|
else:
|
|
3227
3269
|
this = exp.select("*").from_(t.cast(exp.From, from_))
|
|
3270
|
+
this = self._parse_query_modifiers(self._parse_set_operations(this))
|
|
3228
3271
|
else:
|
|
3229
3272
|
this = (
|
|
3230
3273
|
self._parse_table(consume_pipe=True)
|
|
@@ -3283,8 +3326,11 @@ class Parser(metaclass=_Parser):
|
|
|
3283
3326
|
self.raise_error("Failed to parse any statement following CTE")
|
|
3284
3327
|
return cte
|
|
3285
3328
|
|
|
3286
|
-
|
|
3287
|
-
this.
|
|
3329
|
+
while isinstance(this, exp.Subquery) and this.is_wrapper:
|
|
3330
|
+
this = this.this
|
|
3331
|
+
|
|
3332
|
+
if "with_" in this.arg_types:
|
|
3333
|
+
this.set("with_", cte)
|
|
3288
3334
|
else:
|
|
3289
3335
|
self.raise_error(f"{this.key} does not support CTE")
|
|
3290
3336
|
this = cte
|
|
@@ -3293,7 +3339,7 @@ class Parser(metaclass=_Parser):
|
|
|
3293
3339
|
|
|
3294
3340
|
# duckdb supports leading with FROM x
|
|
3295
3341
|
from_ = (
|
|
3296
|
-
self._parse_from(consume_pipe=True)
|
|
3342
|
+
self._parse_from(joins=True, consume_pipe=True)
|
|
3297
3343
|
if self._match(TokenType.FROM, advance=False)
|
|
3298
3344
|
else None
|
|
3299
3345
|
)
|
|
@@ -3350,7 +3396,7 @@ class Parser(metaclass=_Parser):
|
|
|
3350
3396
|
from_ = self._parse_from()
|
|
3351
3397
|
|
|
3352
3398
|
if from_:
|
|
3353
|
-
this.set("
|
|
3399
|
+
this.set("from_", from_)
|
|
3354
3400
|
|
|
3355
3401
|
this = self._parse_query_modifiers(this)
|
|
3356
3402
|
elif (table or nested) and self._match(TokenType.L_PAREN):
|
|
@@ -3370,12 +3416,6 @@ class Parser(metaclass=_Parser):
|
|
|
3370
3416
|
return self.expression(exp.Summarize, this=this, table=table)
|
|
3371
3417
|
elif self._match(TokenType.DESCRIBE):
|
|
3372
3418
|
this = self._parse_describe()
|
|
3373
|
-
elif self._match_text_seq("STREAM"):
|
|
3374
|
-
this = self._parse_function()
|
|
3375
|
-
if this:
|
|
3376
|
-
this = self.expression(exp.Stream, this=this)
|
|
3377
|
-
else:
|
|
3378
|
-
self._retreat(self._index - 1)
|
|
3379
3419
|
else:
|
|
3380
3420
|
this = None
|
|
3381
3421
|
|
|
@@ -3522,7 +3562,7 @@ class Parser(metaclass=_Parser):
|
|
|
3522
3562
|
def _implicit_unnests_to_explicit(self, this: E) -> E:
|
|
3523
3563
|
from sqlglot.optimizer.normalize_identifiers import normalize_identifiers as _norm
|
|
3524
3564
|
|
|
3525
|
-
refs = {_norm(this.args["
|
|
3565
|
+
refs = {_norm(this.args["from_"].this.copy(), dialect=self.dialect).alias_or_name}
|
|
3526
3566
|
for i, join in enumerate(this.args.get("joins") or []):
|
|
3527
3567
|
table = join.this
|
|
3528
3568
|
normalized_table = table.copy()
|
|
@@ -3587,7 +3627,7 @@ class Parser(metaclass=_Parser):
|
|
|
3587
3627
|
continue
|
|
3588
3628
|
break
|
|
3589
3629
|
|
|
3590
|
-
if self.SUPPORTS_IMPLICIT_UNNEST and this and this.args.get("
|
|
3630
|
+
if self.SUPPORTS_IMPLICIT_UNNEST and this and this.args.get("from_"):
|
|
3591
3631
|
this = self._implicit_unnests_to_explicit(this)
|
|
3592
3632
|
|
|
3593
3633
|
return this
|
|
@@ -3807,6 +3847,16 @@ class Parser(metaclass=_Parser):
|
|
|
3807
3847
|
ordinality=ordinality,
|
|
3808
3848
|
)
|
|
3809
3849
|
|
|
3850
|
+
def _parse_stream(self) -> t.Optional[exp.Stream]:
|
|
3851
|
+
index = self._index
|
|
3852
|
+
if self._match_text_seq("STREAM"):
|
|
3853
|
+
this = self._try_parse(self._parse_table)
|
|
3854
|
+
if this:
|
|
3855
|
+
return self.expression(exp.Stream, this=this)
|
|
3856
|
+
|
|
3857
|
+
self._retreat(index)
|
|
3858
|
+
return None
|
|
3859
|
+
|
|
3810
3860
|
def _parse_join_parts(
|
|
3811
3861
|
self,
|
|
3812
3862
|
) -> t.Tuple[t.Optional[Token], t.Optional[Token], t.Optional[Token]]:
|
|
@@ -3862,11 +3912,11 @@ class Parser(metaclass=_Parser):
|
|
|
3862
3912
|
)
|
|
3863
3913
|
|
|
3864
3914
|
if method:
|
|
3865
|
-
kwargs["method"] = method.text
|
|
3915
|
+
kwargs["method"] = method.text.upper()
|
|
3866
3916
|
if side:
|
|
3867
|
-
kwargs["side"] = side.text
|
|
3917
|
+
kwargs["side"] = side.text.upper()
|
|
3868
3918
|
if kind:
|
|
3869
|
-
kwargs["kind"] = kind.text
|
|
3919
|
+
kwargs["kind"] = kind.text.upper()
|
|
3870
3920
|
if hint:
|
|
3871
3921
|
kwargs["hint"] = hint
|
|
3872
3922
|
|
|
@@ -3874,7 +3924,7 @@ class Parser(metaclass=_Parser):
|
|
|
3874
3924
|
kwargs["match_condition"] = self._parse_wrapped(self._parse_comparison)
|
|
3875
3925
|
|
|
3876
3926
|
if self._match(TokenType.ON):
|
|
3877
|
-
kwargs["on"] = self.
|
|
3927
|
+
kwargs["on"] = self._parse_disjunction()
|
|
3878
3928
|
elif self._match(TokenType.USING):
|
|
3879
3929
|
kwargs["using"] = self._parse_using_identifiers()
|
|
3880
3930
|
elif (
|
|
@@ -3887,7 +3937,7 @@ class Parser(metaclass=_Parser):
|
|
|
3887
3937
|
joins: t.Optional[list] = list(self._parse_joins())
|
|
3888
3938
|
|
|
3889
3939
|
if joins and self._match(TokenType.ON):
|
|
3890
|
-
kwargs["on"] = self.
|
|
3940
|
+
kwargs["on"] = self._parse_disjunction()
|
|
3891
3941
|
elif joins and self._match(TokenType.USING):
|
|
3892
3942
|
kwargs["using"] = self._parse_using_identifiers()
|
|
3893
3943
|
else:
|
|
@@ -3913,7 +3963,7 @@ class Parser(metaclass=_Parser):
|
|
|
3913
3963
|
return self.expression(exp.Join, comments=comments, **kwargs)
|
|
3914
3964
|
|
|
3915
3965
|
def _parse_opclass(self) -> t.Optional[exp.Expression]:
|
|
3916
|
-
this = self.
|
|
3966
|
+
this = self._parse_disjunction()
|
|
3917
3967
|
|
|
3918
3968
|
if self._match_texts(self.OPCLASS_FOLLOW_KEYWORDS, advance=False):
|
|
3919
3969
|
return this
|
|
@@ -4099,6 +4149,10 @@ class Parser(metaclass=_Parser):
|
|
|
4099
4149
|
parse_partition: bool = False,
|
|
4100
4150
|
consume_pipe: bool = False,
|
|
4101
4151
|
) -> t.Optional[exp.Expression]:
|
|
4152
|
+
stream = self._parse_stream()
|
|
4153
|
+
if stream:
|
|
4154
|
+
return stream
|
|
4155
|
+
|
|
4102
4156
|
lateral = self._parse_lateral()
|
|
4103
4157
|
if lateral:
|
|
4104
4158
|
return lateral
|
|
@@ -4161,6 +4215,11 @@ class Parser(metaclass=_Parser):
|
|
|
4161
4215
|
if alias:
|
|
4162
4216
|
this.set("alias", alias)
|
|
4163
4217
|
|
|
4218
|
+
if self._match(TokenType.INDEXED_BY):
|
|
4219
|
+
this.set("indexed", self._parse_table_parts())
|
|
4220
|
+
elif self._match_text_seq("NOT", "INDEXED"):
|
|
4221
|
+
this.set("indexed", False)
|
|
4222
|
+
|
|
4164
4223
|
if isinstance(this, exp.Table) and self._match_text_seq("AT"):
|
|
4165
4224
|
return self.expression(
|
|
4166
4225
|
exp.AtIndex, this=this.to_column(copy=False), expression=self._parse_id_var()
|
|
@@ -4400,7 +4459,7 @@ class Parser(metaclass=_Parser):
|
|
|
4400
4459
|
expressions = self._match(TokenType.ON) and self._parse_csv(_parse_on)
|
|
4401
4460
|
into = self._parse_unpivot_columns()
|
|
4402
4461
|
using = self._match(TokenType.USING) and self._parse_csv(
|
|
4403
|
-
lambda: self._parse_alias(self.
|
|
4462
|
+
lambda: self._parse_alias(self._parse_column())
|
|
4404
4463
|
)
|
|
4405
4464
|
group = self._parse_group()
|
|
4406
4465
|
|
|
@@ -4429,16 +4488,18 @@ class Parser(metaclass=_Parser):
|
|
|
4429
4488
|
|
|
4430
4489
|
value = self._parse_column()
|
|
4431
4490
|
|
|
4432
|
-
if not self.
|
|
4433
|
-
self.raise_error("Expecting IN
|
|
4491
|
+
if not self._match(TokenType.IN):
|
|
4492
|
+
self.raise_error("Expecting IN")
|
|
4434
4493
|
|
|
4435
|
-
if self._match(TokenType.
|
|
4436
|
-
|
|
4437
|
-
|
|
4438
|
-
|
|
4494
|
+
if self._match(TokenType.L_PAREN):
|
|
4495
|
+
if self._match(TokenType.ANY):
|
|
4496
|
+
exprs: t.List[exp.Expression] = ensure_list(exp.PivotAny(this=self._parse_order()))
|
|
4497
|
+
else:
|
|
4498
|
+
exprs = self._parse_csv(_parse_aliased_expression)
|
|
4499
|
+
self._match_r_paren()
|
|
4500
|
+
return self.expression(exp.In, this=value, expressions=exprs)
|
|
4439
4501
|
|
|
4440
|
-
self.
|
|
4441
|
-
return self.expression(exp.In, this=value, expressions=exprs)
|
|
4502
|
+
return self.expression(exp.In, this=value, field=self._parse_id_var())
|
|
4442
4503
|
|
|
4443
4504
|
def _parse_pivot_aggregation(self) -> t.Optional[exp.Expression]:
|
|
4444
4505
|
func = self._parse_function()
|
|
@@ -4558,7 +4619,7 @@ class Parser(metaclass=_Parser):
|
|
|
4558
4619
|
return None
|
|
4559
4620
|
|
|
4560
4621
|
return self.expression(
|
|
4561
|
-
exp.PreWhere, comments=self._prev_comments, this=self.
|
|
4622
|
+
exp.PreWhere, comments=self._prev_comments, this=self._parse_disjunction()
|
|
4562
4623
|
)
|
|
4563
4624
|
|
|
4564
4625
|
def _parse_where(self, skip_where_token: bool = False) -> t.Optional[exp.Where]:
|
|
@@ -4566,7 +4627,7 @@ class Parser(metaclass=_Parser):
|
|
|
4566
4627
|
return None
|
|
4567
4628
|
|
|
4568
4629
|
return self.expression(
|
|
4569
|
-
exp.Where, comments=self._prev_comments, this=self.
|
|
4630
|
+
exp.Where, comments=self._prev_comments, this=self._parse_disjunction()
|
|
4570
4631
|
)
|
|
4571
4632
|
|
|
4572
4633
|
def _parse_group(self, skip_group_by_token: bool = False) -> t.Optional[exp.Group]:
|
|
@@ -4591,7 +4652,7 @@ class Parser(metaclass=_Parser):
|
|
|
4591
4652
|
self._parse_csv(
|
|
4592
4653
|
lambda: None
|
|
4593
4654
|
if self._match_set((TokenType.CUBE, TokenType.ROLLUP), advance=False)
|
|
4594
|
-
else self.
|
|
4655
|
+
else self._parse_disjunction()
|
|
4595
4656
|
)
|
|
4596
4657
|
)
|
|
4597
4658
|
|
|
@@ -4624,7 +4685,7 @@ class Parser(metaclass=_Parser):
|
|
|
4624
4685
|
return None
|
|
4625
4686
|
|
|
4626
4687
|
return self.expression(
|
|
4627
|
-
kind, expressions=[] if with_prefix else self._parse_wrapped_csv(self.
|
|
4688
|
+
kind, expressions=[] if with_prefix else self._parse_wrapped_csv(self._parse_bitwise)
|
|
4628
4689
|
)
|
|
4629
4690
|
|
|
4630
4691
|
def _parse_grouping_sets(self) -> t.Optional[exp.GroupingSets]:
|
|
@@ -4641,19 +4702,19 @@ class Parser(metaclass=_Parser):
|
|
|
4641
4702
|
if not skip_having_token and not self._match(TokenType.HAVING):
|
|
4642
4703
|
return None
|
|
4643
4704
|
return self.expression(
|
|
4644
|
-
exp.Having, comments=self._prev_comments, this=self.
|
|
4705
|
+
exp.Having, comments=self._prev_comments, this=self._parse_disjunction()
|
|
4645
4706
|
)
|
|
4646
4707
|
|
|
4647
4708
|
def _parse_qualify(self) -> t.Optional[exp.Qualify]:
|
|
4648
4709
|
if not self._match(TokenType.QUALIFY):
|
|
4649
4710
|
return None
|
|
4650
|
-
return self.expression(exp.Qualify, this=self.
|
|
4711
|
+
return self.expression(exp.Qualify, this=self._parse_disjunction())
|
|
4651
4712
|
|
|
4652
4713
|
def _parse_connect_with_prior(self) -> t.Optional[exp.Expression]:
|
|
4653
4714
|
self.NO_PAREN_FUNCTION_PARSERS["PRIOR"] = lambda self: self.expression(
|
|
4654
4715
|
exp.Prior, this=self._parse_bitwise()
|
|
4655
4716
|
)
|
|
4656
|
-
connect = self.
|
|
4717
|
+
connect = self._parse_disjunction()
|
|
4657
4718
|
self.NO_PAREN_FUNCTION_PARSERS.pop("PRIOR")
|
|
4658
4719
|
return connect
|
|
4659
4720
|
|
|
@@ -4661,7 +4722,7 @@ class Parser(metaclass=_Parser):
|
|
|
4661
4722
|
if skip_start_token:
|
|
4662
4723
|
start = None
|
|
4663
4724
|
elif self._match(TokenType.START_WITH):
|
|
4664
|
-
start = self.
|
|
4725
|
+
start = self._parse_disjunction()
|
|
4665
4726
|
else:
|
|
4666
4727
|
return None
|
|
4667
4728
|
|
|
@@ -4670,14 +4731,14 @@ class Parser(metaclass=_Parser):
|
|
|
4670
4731
|
connect = self._parse_connect_with_prior()
|
|
4671
4732
|
|
|
4672
4733
|
if not start and self._match(TokenType.START_WITH):
|
|
4673
|
-
start = self.
|
|
4734
|
+
start = self._parse_disjunction()
|
|
4674
4735
|
|
|
4675
4736
|
return self.expression(exp.Connect, start=start, connect=connect, nocycle=nocycle)
|
|
4676
4737
|
|
|
4677
4738
|
def _parse_name_as_expression(self) -> t.Optional[exp.Expression]:
|
|
4678
4739
|
this = self._parse_id_var(any_token=True)
|
|
4679
4740
|
if self._match(TokenType.ALIAS):
|
|
4680
|
-
this = self.expression(exp.Alias, alias=this, this=self.
|
|
4741
|
+
this = self.expression(exp.Alias, alias=this, this=self._parse_disjunction())
|
|
4681
4742
|
return this
|
|
4682
4743
|
|
|
4683
4744
|
def _parse_interpolate(self) -> t.Optional[t.List[exp.Expression]]:
|
|
@@ -4711,7 +4772,7 @@ class Parser(metaclass=_Parser):
|
|
|
4711
4772
|
def _parse_ordered(
|
|
4712
4773
|
self, parse_method: t.Optional[t.Callable] = None
|
|
4713
4774
|
) -> t.Optional[exp.Ordered]:
|
|
4714
|
-
this = parse_method() if parse_method else self.
|
|
4775
|
+
this = parse_method() if parse_method else self._parse_disjunction()
|
|
4715
4776
|
if not this:
|
|
4716
4777
|
return None
|
|
4717
4778
|
|
|
@@ -4740,12 +4801,10 @@ class Parser(metaclass=_Parser):
|
|
|
4740
4801
|
if self._match_text_seq("WITH", "FILL"):
|
|
4741
4802
|
with_fill = self.expression(
|
|
4742
4803
|
exp.WithFill,
|
|
4743
|
-
|
|
4744
|
-
|
|
4745
|
-
|
|
4746
|
-
|
|
4747
|
-
"interpolate": self._parse_interpolate(),
|
|
4748
|
-
},
|
|
4804
|
+
from_=self._match(TokenType.FROM) and self._parse_bitwise(),
|
|
4805
|
+
to=self._match_text_seq("TO") and self._parse_bitwise(),
|
|
4806
|
+
step=self._match_text_seq("STEP") and self._parse_bitwise(),
|
|
4807
|
+
interpolate=self._parse_interpolate(),
|
|
4749
4808
|
)
|
|
4750
4809
|
else:
|
|
4751
4810
|
with_fill = None
|
|
@@ -4784,8 +4843,13 @@ class Parser(metaclass=_Parser):
|
|
|
4784
4843
|
# Parsing LIMIT x% (i.e x PERCENT) as a term leads to an error, since
|
|
4785
4844
|
# we try to build an exp.Mod expr. For that matter, we backtrack and instead
|
|
4786
4845
|
# consume the factor plus parse the percentage separately
|
|
4787
|
-
|
|
4788
|
-
|
|
4846
|
+
index = self._index
|
|
4847
|
+
expression = self._try_parse(self._parse_term)
|
|
4848
|
+
if isinstance(expression, exp.Mod):
|
|
4849
|
+
self._retreat(index)
|
|
4850
|
+
expression = self._parse_factor()
|
|
4851
|
+
elif not expression:
|
|
4852
|
+
expression = self._parse_factor()
|
|
4789
4853
|
limit_options = self._parse_limit_options()
|
|
4790
4854
|
|
|
4791
4855
|
if self._match(TokenType.COMMA):
|
|
@@ -5009,7 +5073,7 @@ class Parser(metaclass=_Parser):
|
|
|
5009
5073
|
return this
|
|
5010
5074
|
|
|
5011
5075
|
this = expression
|
|
5012
|
-
elif self._match(TokenType.ISNULL):
|
|
5076
|
+
elif self._match(TokenType.ISNULL) or (negate and self._match(TokenType.NULL)):
|
|
5013
5077
|
this = self.expression(exp.Is, this=this, expression=exp.Null())
|
|
5014
5078
|
|
|
5015
5079
|
# Postgres supports ISNULL and NOTNULL for conditions.
|
|
@@ -5053,10 +5117,13 @@ class Parser(metaclass=_Parser):
|
|
|
5053
5117
|
unique = self._match(TokenType.UNIQUE)
|
|
5054
5118
|
self._match_text_seq("KEYS")
|
|
5055
5119
|
expression: t.Optional[exp.Expression] = self.expression(
|
|
5056
|
-
exp.JSON,
|
|
5120
|
+
exp.JSON,
|
|
5121
|
+
this=kind,
|
|
5122
|
+
with_=_with,
|
|
5123
|
+
unique=unique,
|
|
5057
5124
|
)
|
|
5058
5125
|
else:
|
|
5059
|
-
expression = self.
|
|
5126
|
+
expression = self._parse_null() or self._parse_bitwise()
|
|
5060
5127
|
if not expression:
|
|
5061
5128
|
self._retreat(index)
|
|
5062
5129
|
return None
|
|
@@ -5113,7 +5180,9 @@ class Parser(metaclass=_Parser):
|
|
|
5113
5180
|
def _parse_escape(self, this: t.Optional[exp.Expression]) -> t.Optional[exp.Expression]:
|
|
5114
5181
|
if not self._match(TokenType.ESCAPE):
|
|
5115
5182
|
return this
|
|
5116
|
-
return self.expression(
|
|
5183
|
+
return self.expression(
|
|
5184
|
+
exp.Escape, this=this, expression=self._parse_string() or self._parse_null()
|
|
5185
|
+
)
|
|
5117
5186
|
|
|
5118
5187
|
def _parse_interval(self, match_interval: bool = True) -> t.Optional[exp.Add | exp.Interval]:
|
|
5119
5188
|
index = self._index
|
|
@@ -5261,7 +5330,7 @@ class Parser(metaclass=_Parser):
|
|
|
5261
5330
|
|
|
5262
5331
|
def _parse_factor(self) -> t.Optional[exp.Expression]:
|
|
5263
5332
|
parse_method = self._parse_exponent if self.EXPONENT else self._parse_unary
|
|
5264
|
-
this = parse_method()
|
|
5333
|
+
this = self._parse_at_time_zone(parse_method())
|
|
5265
5334
|
|
|
5266
5335
|
while self._match_set(self.FACTOR):
|
|
5267
5336
|
klass = self.FACTOR[self._prev.token_type]
|
|
@@ -5286,14 +5355,14 @@ class Parser(metaclass=_Parser):
|
|
|
5286
5355
|
def _parse_unary(self) -> t.Optional[exp.Expression]:
|
|
5287
5356
|
if self._match_set(self.UNARY_PARSERS):
|
|
5288
5357
|
return self.UNARY_PARSERS[self._prev.token_type](self)
|
|
5289
|
-
return self.
|
|
5358
|
+
return self._parse_type()
|
|
5290
5359
|
|
|
5291
5360
|
def _parse_type(
|
|
5292
5361
|
self, parse_interval: bool = True, fallback_to_identifier: bool = False
|
|
5293
5362
|
) -> t.Optional[exp.Expression]:
|
|
5294
5363
|
interval = parse_interval and self._parse_interval()
|
|
5295
5364
|
if interval:
|
|
5296
|
-
return interval
|
|
5365
|
+
return self._parse_column_ops(interval)
|
|
5297
5366
|
|
|
5298
5367
|
index = self._index
|
|
5299
5368
|
data_type = self._parse_types(check_func=True, allow_identifiers=False)
|
|
@@ -5499,7 +5568,7 @@ class Parser(metaclass=_Parser):
|
|
|
5499
5568
|
self.raise_error("Expecting >")
|
|
5500
5569
|
|
|
5501
5570
|
if self._match_set((TokenType.L_BRACKET, TokenType.L_PAREN)):
|
|
5502
|
-
values = self._parse_csv(self.
|
|
5571
|
+
values = self._parse_csv(self._parse_disjunction)
|
|
5503
5572
|
if not values and is_struct:
|
|
5504
5573
|
values = None
|
|
5505
5574
|
self._retreat(self._index - 1)
|
|
@@ -5591,12 +5660,14 @@ class Parser(metaclass=_Parser):
|
|
|
5591
5660
|
break
|
|
5592
5661
|
|
|
5593
5662
|
matched_array = False
|
|
5594
|
-
values = self._parse_csv(self.
|
|
5663
|
+
values = self._parse_csv(self._parse_disjunction) or None
|
|
5595
5664
|
if (
|
|
5596
5665
|
values
|
|
5597
5666
|
and not schema
|
|
5598
5667
|
and (
|
|
5599
|
-
not self.dialect.SUPPORTS_FIXED_SIZE_ARRAYS
|
|
5668
|
+
not self.dialect.SUPPORTS_FIXED_SIZE_ARRAYS
|
|
5669
|
+
or datatype_token == TokenType.ARRAY
|
|
5670
|
+
or not self._match(TokenType.R_BRACKET, advance=False)
|
|
5600
5671
|
)
|
|
5601
5672
|
):
|
|
5602
5673
|
# Retreating here means that we should not parse the following values as part of the data type, e.g. in DuckDB
|
|
@@ -5654,7 +5725,9 @@ class Parser(metaclass=_Parser):
|
|
|
5654
5725
|
def _parse_at_time_zone(self, this: t.Optional[exp.Expression]) -> t.Optional[exp.Expression]:
|
|
5655
5726
|
if not self._match_text_seq("AT", "TIME", "ZONE"):
|
|
5656
5727
|
return this
|
|
5657
|
-
return self.
|
|
5728
|
+
return self._parse_at_time_zone(
|
|
5729
|
+
self.expression(exp.AtTimeZone, this=this, zone=self._parse_unary())
|
|
5730
|
+
)
|
|
5658
5731
|
|
|
5659
5732
|
def _parse_column(self) -> t.Optional[exp.Expression]:
|
|
5660
5733
|
this = self._parse_column_reference()
|
|
@@ -5814,7 +5887,7 @@ class Parser(metaclass=_Parser):
|
|
|
5814
5887
|
this = self.expression(exp.Tuple)
|
|
5815
5888
|
elif isinstance(this, exp.UNWRAPPED_QUERIES):
|
|
5816
5889
|
this = self._parse_subquery(this=this, parse_alias=False)
|
|
5817
|
-
elif isinstance(this, exp.Subquery):
|
|
5890
|
+
elif isinstance(this, (exp.Subquery, exp.Values)):
|
|
5818
5891
|
this = self._parse_subquery(
|
|
5819
5892
|
this=self._parse_query_modifiers(self._parse_set_operations(this)),
|
|
5820
5893
|
parse_alias=False,
|
|
@@ -5845,7 +5918,9 @@ class Parser(metaclass=_Parser):
|
|
|
5845
5918
|
expressions.append(exp.Literal.string(self._prev.text))
|
|
5846
5919
|
|
|
5847
5920
|
if len(expressions) > 1:
|
|
5848
|
-
return self.expression(
|
|
5921
|
+
return self.expression(
|
|
5922
|
+
exp.Concat, expressions=expressions, coalesce=self.dialect.CONCAT_COALESCE
|
|
5923
|
+
)
|
|
5849
5924
|
|
|
5850
5925
|
return primary
|
|
5851
5926
|
|
|
@@ -6061,7 +6136,7 @@ class Parser(metaclass=_Parser):
|
|
|
6061
6136
|
def _parse_introducer(self, token: Token) -> exp.Introducer | exp.Identifier:
|
|
6062
6137
|
literal = self._parse_primary()
|
|
6063
6138
|
if literal:
|
|
6064
|
-
return self.expression(exp.Introducer,
|
|
6139
|
+
return self.expression(exp.Introducer, token=token, expression=literal)
|
|
6065
6140
|
|
|
6066
6141
|
return self._identifier_expression(token)
|
|
6067
6142
|
|
|
@@ -6100,7 +6175,7 @@ class Parser(metaclass=_Parser):
|
|
|
6100
6175
|
|
|
6101
6176
|
if self._match(TokenType.DISTINCT):
|
|
6102
6177
|
this = self.expression(
|
|
6103
|
-
exp.Distinct, expressions=self._parse_csv(self.
|
|
6178
|
+
exp.Distinct, expressions=self._parse_csv(self._parse_disjunction)
|
|
6104
6179
|
)
|
|
6105
6180
|
else:
|
|
6106
6181
|
this = self._parse_select_or_expression(alias=alias)
|
|
@@ -6148,7 +6223,7 @@ class Parser(metaclass=_Parser):
|
|
|
6148
6223
|
):
|
|
6149
6224
|
persisted = self._prev.text.upper() == "MATERIALIZED"
|
|
6150
6225
|
constraint_kind = exp.ComputedColumnConstraint(
|
|
6151
|
-
this=self.
|
|
6226
|
+
this=self._parse_disjunction(),
|
|
6152
6227
|
persisted=persisted or self._match_text_seq("PERSISTED"),
|
|
6153
6228
|
data_type=exp.Var(this="AUTO")
|
|
6154
6229
|
if self._match_text_seq("AUTO")
|
|
@@ -6463,6 +6538,14 @@ class Parser(metaclass=_Parser):
|
|
|
6463
6538
|
and self._prev.token_type == TokenType.DESC
|
|
6464
6539
|
)
|
|
6465
6540
|
|
|
6541
|
+
this = None
|
|
6542
|
+
if (
|
|
6543
|
+
self._curr.text.upper() not in self.CONSTRAINT_PARSERS
|
|
6544
|
+
and self._next
|
|
6545
|
+
and self._next.token_type == TokenType.L_PAREN
|
|
6546
|
+
):
|
|
6547
|
+
this = self._parse_id_var()
|
|
6548
|
+
|
|
6466
6549
|
if not in_props and not self._match(TokenType.L_PAREN, advance=False):
|
|
6467
6550
|
return self.expression(
|
|
6468
6551
|
exp.PrimaryKeyColumnConstraint,
|
|
@@ -6476,13 +6559,14 @@ class Parser(metaclass=_Parser):
|
|
|
6476
6559
|
|
|
6477
6560
|
return self.expression(
|
|
6478
6561
|
exp.PrimaryKey,
|
|
6562
|
+
this=this,
|
|
6479
6563
|
expressions=expressions,
|
|
6480
6564
|
include=self._parse_index_params(),
|
|
6481
6565
|
options=self._parse_key_constraint_options(),
|
|
6482
6566
|
)
|
|
6483
6567
|
|
|
6484
6568
|
def _parse_bracket_key_value(self, is_map: bool = False) -> t.Optional[exp.Expression]:
|
|
6485
|
-
return self._parse_slice(self._parse_alias(self.
|
|
6569
|
+
return self._parse_slice(self._parse_alias(self._parse_disjunction(), explicit=True))
|
|
6486
6570
|
|
|
6487
6571
|
def _parse_odbc_datetime_literal(self) -> exp.Expression:
|
|
6488
6572
|
"""
|
|
@@ -6562,9 +6646,16 @@ class Parser(metaclass=_Parser):
|
|
|
6562
6646
|
return self._parse_bracket(this)
|
|
6563
6647
|
|
|
6564
6648
|
def _parse_slice(self, this: t.Optional[exp.Expression]) -> t.Optional[exp.Expression]:
|
|
6565
|
-
if self._match(TokenType.COLON):
|
|
6566
|
-
return
|
|
6567
|
-
|
|
6649
|
+
if not self._match(TokenType.COLON):
|
|
6650
|
+
return this
|
|
6651
|
+
|
|
6652
|
+
if self._match_pair(TokenType.DASH, TokenType.COLON, advance=False):
|
|
6653
|
+
self._advance()
|
|
6654
|
+
end: t.Optional[exp.Expression] = -exp.Literal.number("1")
|
|
6655
|
+
else:
|
|
6656
|
+
end = self._parse_unary()
|
|
6657
|
+
step = self._parse_unary() if self._match(TokenType.COLON) else None
|
|
6658
|
+
return self.expression(exp.Slice, this=this, expression=end, step=step)
|
|
6568
6659
|
|
|
6569
6660
|
def _parse_case(self) -> t.Optional[exp.Expression]:
|
|
6570
6661
|
if self._match(TokenType.DOT, advance=False):
|
|
@@ -6576,16 +6667,16 @@ class Parser(metaclass=_Parser):
|
|
|
6576
6667
|
default = None
|
|
6577
6668
|
|
|
6578
6669
|
comments = self._prev_comments
|
|
6579
|
-
expression = self.
|
|
6670
|
+
expression = self._parse_disjunction()
|
|
6580
6671
|
|
|
6581
6672
|
while self._match(TokenType.WHEN):
|
|
6582
|
-
this = self.
|
|
6673
|
+
this = self._parse_disjunction()
|
|
6583
6674
|
self._match(TokenType.THEN)
|
|
6584
|
-
then = self.
|
|
6675
|
+
then = self._parse_disjunction()
|
|
6585
6676
|
ifs.append(self.expression(exp.If, this=this, true=then))
|
|
6586
6677
|
|
|
6587
6678
|
if self._match(TokenType.ELSE):
|
|
6588
|
-
default = self.
|
|
6679
|
+
default = self._parse_disjunction()
|
|
6589
6680
|
|
|
6590
6681
|
if not self._match(TokenType.END):
|
|
6591
6682
|
if isinstance(default, exp.Interval) and default.this.sql().upper() == "END":
|
|
@@ -6610,15 +6701,15 @@ class Parser(metaclass=_Parser):
|
|
|
6610
6701
|
if self.NO_PAREN_IF_COMMANDS and index == 0:
|
|
6611
6702
|
return self._parse_as_command(self._prev)
|
|
6612
6703
|
|
|
6613
|
-
condition = self.
|
|
6704
|
+
condition = self._parse_disjunction()
|
|
6614
6705
|
|
|
6615
6706
|
if not condition:
|
|
6616
6707
|
self._retreat(index)
|
|
6617
6708
|
return None
|
|
6618
6709
|
|
|
6619
6710
|
self._match(TokenType.THEN)
|
|
6620
|
-
true = self.
|
|
6621
|
-
false = self.
|
|
6711
|
+
true = self._parse_disjunction()
|
|
6712
|
+
false = self._parse_disjunction() if self._match(TokenType.ELSE) else None
|
|
6622
6713
|
self._match(TokenType.END)
|
|
6623
6714
|
this = self.expression(exp.If, this=condition, true=true, false=false)
|
|
6624
6715
|
|
|
@@ -6657,7 +6748,7 @@ class Parser(metaclass=_Parser):
|
|
|
6657
6748
|
return self.validate_expression(gap_fill, args)
|
|
6658
6749
|
|
|
6659
6750
|
def _parse_cast(self, strict: bool, safe: t.Optional[bool] = None) -> exp.Expression:
|
|
6660
|
-
this = self.
|
|
6751
|
+
this = self._parse_disjunction()
|
|
6661
6752
|
|
|
6662
6753
|
if not self._match(TokenType.ALIAS):
|
|
6663
6754
|
if self._match(TokenType.COMMA):
|
|
@@ -6717,12 +6808,12 @@ class Parser(metaclass=_Parser):
|
|
|
6717
6808
|
def _parse_string_agg(self) -> exp.GroupConcat:
|
|
6718
6809
|
if self._match(TokenType.DISTINCT):
|
|
6719
6810
|
args: t.List[t.Optional[exp.Expression]] = [
|
|
6720
|
-
self.expression(exp.Distinct, expressions=[self.
|
|
6811
|
+
self.expression(exp.Distinct, expressions=[self._parse_disjunction()])
|
|
6721
6812
|
]
|
|
6722
6813
|
if self._match(TokenType.COMMA):
|
|
6723
|
-
args.extend(self._parse_csv(self.
|
|
6814
|
+
args.extend(self._parse_csv(self._parse_disjunction))
|
|
6724
6815
|
else:
|
|
6725
|
-
args = self._parse_csv(self.
|
|
6816
|
+
args = self._parse_csv(self._parse_disjunction) # type: ignore
|
|
6726
6817
|
|
|
6727
6818
|
if self._match_text_seq("ON", "OVERFLOW"):
|
|
6728
6819
|
# trino: LISTAGG(expression [, separator] [ON OVERFLOW overflow_behavior])
|
|
@@ -6827,7 +6918,7 @@ class Parser(metaclass=_Parser):
|
|
|
6827
6918
|
return namespaces
|
|
6828
6919
|
|
|
6829
6920
|
def _parse_decode(self) -> t.Optional[exp.Decode | exp.DecodeCase]:
|
|
6830
|
-
args = self._parse_csv(self.
|
|
6921
|
+
args = self._parse_csv(self._parse_disjunction)
|
|
6831
6922
|
|
|
6832
6923
|
if len(args) < 3:
|
|
6833
6924
|
return self.expression(exp.Decode, this=seq_get(args, 0), charset=seq_get(args, 1))
|
|
@@ -7253,7 +7344,7 @@ class Parser(metaclass=_Parser):
|
|
|
7253
7344
|
"value": (
|
|
7254
7345
|
(self._match_text_seq("UNBOUNDED") and "UNBOUNDED")
|
|
7255
7346
|
or (self._match_text_seq("CURRENT", "ROW") and "CURRENT ROW")
|
|
7256
|
-
or self.
|
|
7347
|
+
or self._parse_bitwise()
|
|
7257
7348
|
),
|
|
7258
7349
|
"side": self._match_texts(self.WINDOW_SIDES) and self._prev.text,
|
|
7259
7350
|
}
|
|
@@ -7396,7 +7487,7 @@ class Parser(metaclass=_Parser):
|
|
|
7396
7487
|
if self._match(TokenType.L_PAREN, advance=False):
|
|
7397
7488
|
return self._parse_wrapped_csv(self._parse_expression)
|
|
7398
7489
|
|
|
7399
|
-
expression = self._parse_alias(self.
|
|
7490
|
+
expression = self._parse_alias(self._parse_disjunction(), explicit=True)
|
|
7400
7491
|
return [expression] if expression else None
|
|
7401
7492
|
|
|
7402
7493
|
def _parse_csv(
|
|
@@ -7505,9 +7596,19 @@ class Parser(metaclass=_Parser):
|
|
|
7505
7596
|
|
|
7506
7597
|
return self.expression(exp.Commit, chain=chain)
|
|
7507
7598
|
|
|
7508
|
-
def _parse_refresh(self) -> exp.Refresh:
|
|
7509
|
-
self._match(TokenType.TABLE)
|
|
7510
|
-
|
|
7599
|
+
def _parse_refresh(self) -> exp.Refresh | exp.Command:
|
|
7600
|
+
if self._match(TokenType.TABLE):
|
|
7601
|
+
kind = "TABLE"
|
|
7602
|
+
elif self._match_text_seq("MATERIALIZED", "VIEW"):
|
|
7603
|
+
kind = "MATERIALIZED VIEW"
|
|
7604
|
+
else:
|
|
7605
|
+
kind = ""
|
|
7606
|
+
|
|
7607
|
+
this = self._parse_string() or self._parse_table()
|
|
7608
|
+
if not kind and not isinstance(this, exp.Literal):
|
|
7609
|
+
return self._parse_as_command(self._prev)
|
|
7610
|
+
|
|
7611
|
+
return self.expression(exp.Refresh, this=this, kind=kind)
|
|
7511
7612
|
|
|
7512
7613
|
def _parse_column_def_with_exists(self):
|
|
7513
7614
|
start = self._index
|
|
@@ -7604,7 +7705,7 @@ class Parser(metaclass=_Parser):
|
|
|
7604
7705
|
if self._match_pair(TokenType.DROP, TokenType.DEFAULT):
|
|
7605
7706
|
return self.expression(exp.AlterColumn, this=column, drop=True)
|
|
7606
7707
|
if self._match_pair(TokenType.SET, TokenType.DEFAULT):
|
|
7607
|
-
return self.expression(exp.AlterColumn, this=column, default=self.
|
|
7708
|
+
return self.expression(exp.AlterColumn, this=column, default=self._parse_disjunction())
|
|
7608
7709
|
if self._match(TokenType.COMMENT):
|
|
7609
7710
|
return self.expression(exp.AlterColumn, this=column, comment=self._parse_string())
|
|
7610
7711
|
if self._match_text_seq("DROP", "NOT", "NULL"):
|
|
@@ -7633,7 +7734,7 @@ class Parser(metaclass=_Parser):
|
|
|
7633
7734
|
this=column,
|
|
7634
7735
|
dtype=self._parse_types(),
|
|
7635
7736
|
collate=self._match(TokenType.COLLATE) and self._parse_term(),
|
|
7636
|
-
using=self._match(TokenType.USING) and self.
|
|
7737
|
+
using=self._match(TokenType.USING) and self._parse_disjunction(),
|
|
7637
7738
|
)
|
|
7638
7739
|
|
|
7639
7740
|
def _parse_alter_diststyle(self) -> exp.AlterDistStyle:
|
|
@@ -7960,14 +8061,12 @@ class Parser(metaclass=_Parser):
|
|
|
7960
8061
|
self._match(TokenType.USING)
|
|
7961
8062
|
using = self._parse_table()
|
|
7962
8063
|
|
|
7963
|
-
self._match(TokenType.ON)
|
|
7964
|
-
on = self._parse_assignment()
|
|
7965
|
-
|
|
7966
8064
|
return self.expression(
|
|
7967
8065
|
exp.Merge,
|
|
7968
8066
|
this=target,
|
|
7969
8067
|
using=using,
|
|
7970
|
-
on=
|
|
8068
|
+
on=self._match(TokenType.ON) and self._parse_disjunction(),
|
|
8069
|
+
using_cond=self._match(TokenType.USING) and self._parse_using_identifiers(),
|
|
7971
8070
|
whens=self._parse_when_matched(),
|
|
7972
8071
|
returning=self._parse_returning(),
|
|
7973
8072
|
)
|
|
@@ -7983,7 +8082,7 @@ class Parser(metaclass=_Parser):
|
|
|
7983
8082
|
if self._match_text_seq("BY", "TARGET")
|
|
7984
8083
|
else self._match_text_seq("BY", "SOURCE")
|
|
7985
8084
|
)
|
|
7986
|
-
condition = self.
|
|
8085
|
+
condition = self._parse_disjunction() if self._match(TokenType.AND) else None
|
|
7987
8086
|
|
|
7988
8087
|
self._match(TokenType.THEN)
|
|
7989
8088
|
|
|
@@ -8040,7 +8139,7 @@ class Parser(metaclass=_Parser):
|
|
|
8040
8139
|
return self._parse_set_transaction(global_=kind == "GLOBAL")
|
|
8041
8140
|
|
|
8042
8141
|
left = self._parse_primary() or self._parse_column()
|
|
8043
|
-
assignment_delimiter = self._match_texts(
|
|
8142
|
+
assignment_delimiter = self._match_texts(self.SET_ASSIGNMENT_DELIMITERS)
|
|
8044
8143
|
|
|
8045
8144
|
if not left or (self.SET_REQUIRES_ASSIGNMENT_DELIMITER and not assignment_delimiter):
|
|
8046
8145
|
self._retreat(index)
|
|
@@ -8062,7 +8161,7 @@ class Parser(metaclass=_Parser):
|
|
|
8062
8161
|
exp.SetItem,
|
|
8063
8162
|
expressions=characteristics,
|
|
8064
8163
|
kind="TRANSACTION",
|
|
8065
|
-
|
|
8164
|
+
global_=global_,
|
|
8066
8165
|
)
|
|
8067
8166
|
|
|
8068
8167
|
def _parse_set_item(self) -> t.Optional[exp.Expression]:
|
|
@@ -8160,15 +8259,18 @@ class Parser(metaclass=_Parser):
|
|
|
8160
8259
|
) -> t.Optional[exp.Comprehension]:
|
|
8161
8260
|
index = self._index
|
|
8162
8261
|
expression = self._parse_column()
|
|
8262
|
+
position = self._match(TokenType.COMMA) and self._parse_column()
|
|
8263
|
+
|
|
8163
8264
|
if not self._match(TokenType.IN):
|
|
8164
8265
|
self._retreat(index - 1)
|
|
8165
8266
|
return None
|
|
8166
8267
|
iterator = self._parse_column()
|
|
8167
|
-
condition = self.
|
|
8268
|
+
condition = self._parse_disjunction() if self._match_text_seq("IF") else None
|
|
8168
8269
|
return self.expression(
|
|
8169
8270
|
exp.Comprehension,
|
|
8170
8271
|
this=this,
|
|
8171
8272
|
expression=expression,
|
|
8273
|
+
position=position,
|
|
8172
8274
|
iterator=iterator,
|
|
8173
8275
|
condition=condition,
|
|
8174
8276
|
)
|
|
@@ -8443,8 +8545,15 @@ class Parser(metaclass=_Parser):
|
|
|
8443
8545
|
elif prev == "FILE_FORMAT":
|
|
8444
8546
|
# T-SQL's external file format case
|
|
8445
8547
|
param.set("expression", self._parse_field())
|
|
8548
|
+
elif (
|
|
8549
|
+
prev == "FORMAT"
|
|
8550
|
+
and self._prev.token_type == TokenType.ALIAS
|
|
8551
|
+
and self._match_texts(("AVRO", "JSON"))
|
|
8552
|
+
):
|
|
8553
|
+
param.set("this", exp.var(f"FORMAT AS {self._prev.text.upper()}"))
|
|
8554
|
+
param.set("expression", self._parse_field())
|
|
8446
8555
|
else:
|
|
8447
|
-
param.set("expression", self._parse_unquoted_field())
|
|
8556
|
+
param.set("expression", self._parse_unquoted_field() or self._parse_bracket())
|
|
8448
8557
|
|
|
8449
8558
|
options.append(param)
|
|
8450
8559
|
self._match(sep)
|
|
@@ -8465,7 +8574,10 @@ class Parser(metaclass=_Parser):
|
|
|
8465
8574
|
if self._match_text_seq("ENCRYPTION"):
|
|
8466
8575
|
expr.set("encryption", self._parse_wrapped_options())
|
|
8467
8576
|
if self._match_text_seq("IAM_ROLE"):
|
|
8468
|
-
expr.set(
|
|
8577
|
+
expr.set(
|
|
8578
|
+
"iam_role",
|
|
8579
|
+
exp.var(self._prev.text) if self._match(TokenType.DEFAULT) else self._parse_field(),
|
|
8580
|
+
)
|
|
8469
8581
|
if self._match_text_seq("REGION"):
|
|
8470
8582
|
expr.set("region", self._parse_field())
|
|
8471
8583
|
|
|
@@ -8542,11 +8654,9 @@ class Parser(metaclass=_Parser):
|
|
|
8542
8654
|
|
|
8543
8655
|
return self.expression(
|
|
8544
8656
|
exp.Star,
|
|
8545
|
-
|
|
8546
|
-
|
|
8547
|
-
|
|
8548
|
-
"rename": self._parse_star_op("RENAME"),
|
|
8549
|
-
},
|
|
8657
|
+
except_=self._parse_star_op("EXCEPT", "EXCLUDE"),
|
|
8658
|
+
replace=self._parse_star_op("REPLACE"),
|
|
8659
|
+
rename=self._parse_star_op("RENAME"),
|
|
8550
8660
|
).update_positions(star_token)
|
|
8551
8661
|
|
|
8552
8662
|
def _parse_grant_privilege(self) -> t.Optional[exp.GrantPrivilege]:
|
|
@@ -8644,14 +8754,17 @@ class Parser(metaclass=_Parser):
|
|
|
8644
8754
|
)
|
|
8645
8755
|
|
|
8646
8756
|
def _parse_overlay(self) -> exp.Overlay:
|
|
8757
|
+
def _parse_overlay_arg(text: str) -> t.Optional[exp.Expression]:
|
|
8758
|
+
return (
|
|
8759
|
+
self._match(TokenType.COMMA) or self._match_text_seq(text)
|
|
8760
|
+
) and self._parse_bitwise()
|
|
8761
|
+
|
|
8647
8762
|
return self.expression(
|
|
8648
8763
|
exp.Overlay,
|
|
8649
|
-
|
|
8650
|
-
|
|
8651
|
-
|
|
8652
|
-
|
|
8653
|
-
"for": self._match_text_seq("FOR") and self._parse_bitwise(),
|
|
8654
|
-
},
|
|
8764
|
+
this=self._parse_bitwise(),
|
|
8765
|
+
expression=_parse_overlay_arg("PLACING"),
|
|
8766
|
+
from_=_parse_overlay_arg("FROM"),
|
|
8767
|
+
for_=_parse_overlay_arg("FOR"),
|
|
8655
8768
|
)
|
|
8656
8769
|
|
|
8657
8770
|
def _parse_format_name(self) -> exp.Property:
|
|
@@ -8679,10 +8792,7 @@ class Parser(metaclass=_Parser):
|
|
|
8679
8792
|
def _identifier_expression(
|
|
8680
8793
|
self, token: t.Optional[Token] = None, **kwargs: t.Any
|
|
8681
8794
|
) -> exp.Identifier:
|
|
8682
|
-
|
|
8683
|
-
expression = self.expression(exp.Identifier, this=token.text, **kwargs)
|
|
8684
|
-
expression.update_positions(token)
|
|
8685
|
-
return expression
|
|
8795
|
+
return self.expression(exp.Identifier, token=token or self._prev, **kwargs)
|
|
8686
8796
|
|
|
8687
8797
|
def _build_pipe_cte(
|
|
8688
8798
|
self,
|
|
@@ -8697,12 +8807,12 @@ class Parser(metaclass=_Parser):
|
|
|
8697
8807
|
self._pipe_cte_counter += 1
|
|
8698
8808
|
new_cte = f"__tmp{self._pipe_cte_counter}"
|
|
8699
8809
|
|
|
8700
|
-
with_ = query.args.get("
|
|
8810
|
+
with_ = query.args.get("with_")
|
|
8701
8811
|
ctes = with_.pop() if with_ else None
|
|
8702
8812
|
|
|
8703
8813
|
new_select = exp.select(*expressions, copy=False).from_(new_cte, copy=False)
|
|
8704
8814
|
if ctes:
|
|
8705
|
-
new_select.set("
|
|
8815
|
+
new_select.set("with_", ctes)
|
|
8706
8816
|
|
|
8707
8817
|
return new_select.with_(new_cte, as_=query, copy=False)
|
|
8708
8818
|
|
|
@@ -8730,7 +8840,7 @@ class Parser(metaclass=_Parser):
|
|
|
8730
8840
|
return query
|
|
8731
8841
|
|
|
8732
8842
|
def _parse_pipe_syntax_aggregate_fields(self) -> t.Optional[exp.Expression]:
|
|
8733
|
-
this = self.
|
|
8843
|
+
this = self._parse_disjunction()
|
|
8734
8844
|
if self._match_text_seq("GROUP", "AND", advance=False):
|
|
8735
8845
|
return this
|
|
8736
8846
|
|
|
@@ -8797,7 +8907,7 @@ class Parser(metaclass=_Parser):
|
|
|
8797
8907
|
]
|
|
8798
8908
|
|
|
8799
8909
|
query = self._build_pipe_cte(query=query, expressions=[exp.Star()])
|
|
8800
|
-
with_ = query.args.get("
|
|
8910
|
+
with_ = query.args.get("with_")
|
|
8801
8911
|
ctes = with_.pop() if with_ else None
|
|
8802
8912
|
|
|
8803
8913
|
if isinstance(first_setop, exp.Union):
|
|
@@ -8807,7 +8917,7 @@ class Parser(metaclass=_Parser):
|
|
|
8807
8917
|
else:
|
|
8808
8918
|
query = query.intersect(*setops, copy=False, **first_setop.args)
|
|
8809
8919
|
|
|
8810
|
-
query.set("
|
|
8920
|
+
query.set("with_", ctes)
|
|
8811
8921
|
|
|
8812
8922
|
return self._build_pipe_cte(query=query, expressions=[exp.Star()])
|
|
8813
8923
|
|
|
@@ -8826,7 +8936,7 @@ class Parser(metaclass=_Parser):
|
|
|
8826
8936
|
if not pivots:
|
|
8827
8937
|
return query
|
|
8828
8938
|
|
|
8829
|
-
from_ = query.args.get("
|
|
8939
|
+
from_ = query.args.get("from_")
|
|
8830
8940
|
if from_:
|
|
8831
8941
|
from_.this.set("pivots", pivots)
|
|
8832
8942
|
|
|
@@ -8840,7 +8950,7 @@ class Parser(metaclass=_Parser):
|
|
|
8840
8950
|
def _parse_pipe_syntax_tablesample(self, query: exp.Select) -> exp.Select:
|
|
8841
8951
|
sample = self._parse_table_sample()
|
|
8842
8952
|
|
|
8843
|
-
with_ = query.args.get("
|
|
8953
|
+
with_ = query.args.get("with_")
|
|
8844
8954
|
if with_:
|
|
8845
8955
|
with_.expressions[-1].this.set("sample", sample)
|
|
8846
8956
|
else:
|
|
@@ -8852,7 +8962,7 @@ class Parser(metaclass=_Parser):
|
|
|
8852
8962
|
if isinstance(query, exp.Subquery):
|
|
8853
8963
|
query = exp.select("*").from_(query, copy=False)
|
|
8854
8964
|
|
|
8855
|
-
if not query.args.get("
|
|
8965
|
+
if not query.args.get("from_"):
|
|
8856
8966
|
query = exp.select("*").from_(query.subquery(copy=False), copy=False)
|
|
8857
8967
|
|
|
8858
8968
|
while self._match(TokenType.PIPE_GT):
|
|
@@ -8925,13 +9035,20 @@ class Parser(metaclass=_Parser):
|
|
|
8925
9035
|
) -> exp.Expression:
|
|
8926
9036
|
if isinstance(node, exp.Distinct) and len(node.expressions) > 1:
|
|
8927
9037
|
concat_exprs = [
|
|
8928
|
-
self.expression(
|
|
9038
|
+
self.expression(
|
|
9039
|
+
exp.Concat,
|
|
9040
|
+
expressions=node.expressions,
|
|
9041
|
+
safe=True,
|
|
9042
|
+
coalesce=self.dialect.CONCAT_COALESCE,
|
|
9043
|
+
)
|
|
8929
9044
|
]
|
|
8930
9045
|
node.set("expressions", concat_exprs)
|
|
8931
9046
|
return node
|
|
8932
9047
|
if len(exprs) == 1:
|
|
8933
9048
|
return exprs[0]
|
|
8934
|
-
return self.expression(
|
|
9049
|
+
return self.expression(
|
|
9050
|
+
exp.Concat, expressions=args, safe=True, coalesce=self.dialect.CONCAT_COALESCE
|
|
9051
|
+
)
|
|
8935
9052
|
|
|
8936
9053
|
args = self._parse_csv(self._parse_lambda)
|
|
8937
9054
|
|
|
@@ -8951,3 +9068,12 @@ class Parser(metaclass=_Parser):
|
|
|
8951
9068
|
separator = self._parse_field() if self._match(TokenType.SEPARATOR) else None
|
|
8952
9069
|
|
|
8953
9070
|
return self.expression(exp.GroupConcat, this=this, separator=separator)
|
|
9071
|
+
|
|
9072
|
+
def _parse_initcap(self) -> exp.Initcap:
|
|
9073
|
+
expr = exp.Initcap.from_arg_list(self._parse_function_args())
|
|
9074
|
+
|
|
9075
|
+
# attach dialect's default delimiters
|
|
9076
|
+
if expr.args.get("expression") is None:
|
|
9077
|
+
expr.set("expression", exp.Literal.string(self.dialect.INITCAP_DEFAULT_DELIMITER_CHARS))
|
|
9078
|
+
|
|
9079
|
+
return expr
|