sqlglot 26.27.1__py3-none-any.whl → 26.28.1__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/expressions.py +2 -2
- sqlglot/optimizer/scope.py +5 -2
- sqlglot/parser.py +63 -48
- {sqlglot-26.27.1.dist-info → sqlglot-26.28.1.dist-info}/METADATA +1 -1
- {sqlglot-26.27.1.dist-info → sqlglot-26.28.1.dist-info}/RECORD +9 -9
- {sqlglot-26.27.1.dist-info → sqlglot-26.28.1.dist-info}/WHEEL +0 -0
- {sqlglot-26.27.1.dist-info → sqlglot-26.28.1.dist-info}/licenses/LICENSE +0 -0
- {sqlglot-26.27.1.dist-info → sqlglot-26.28.1.dist-info}/top_level.txt +0 -0
sqlglot/_version.py
CHANGED
sqlglot/expressions.py
CHANGED
@@ -51,8 +51,8 @@ class _Expression(type):
|
|
51
51
|
def __new__(cls, clsname, bases, attrs):
|
52
52
|
klass = super().__new__(cls, clsname, bases, attrs)
|
53
53
|
|
54
|
-
# When an Expression class is created, its key is automatically set
|
55
|
-
# the lowercase version of the class' name.
|
54
|
+
# When an Expression class is created, its key is automatically set
|
55
|
+
# to be the lowercase version of the class' name.
|
56
56
|
klass.key = clsname.lower()
|
57
57
|
|
58
58
|
# This is so that docstrings are not inherited in pdoc
|
sqlglot/optimizer/scope.py
CHANGED
@@ -758,6 +758,8 @@ def _traverse_tables(scope):
|
|
758
758
|
expressions.extend(join.this for join in expression.args.get("joins") or [])
|
759
759
|
continue
|
760
760
|
|
761
|
+
child_scope = None
|
762
|
+
|
761
763
|
for child_scope in _traverse_scope(
|
762
764
|
scope.branch(
|
763
765
|
expression,
|
@@ -775,8 +777,9 @@ def _traverse_tables(scope):
|
|
775
777
|
sources[expression.alias] = child_scope
|
776
778
|
|
777
779
|
# append the final child_scope yielded
|
778
|
-
|
779
|
-
|
780
|
+
if child_scope:
|
781
|
+
scopes.append(child_scope)
|
782
|
+
scope.table_scopes.append(child_scope)
|
780
783
|
|
781
784
|
scope.sources.update(sources)
|
782
785
|
|
sqlglot/parser.py
CHANGED
@@ -932,13 +932,14 @@ class Parser(metaclass=_Parser):
|
|
932
932
|
|
933
933
|
PIPE_SYNTAX_TRANSFORM_PARSERS = {
|
934
934
|
"SELECT": lambda self, query: self._parse_pipe_syntax_select(query),
|
935
|
-
"WHERE": lambda self, query: self.
|
935
|
+
"WHERE": lambda self, query: query.where(self._parse_where(), copy=False),
|
936
936
|
"ORDER BY": lambda self, query: query.order_by(
|
937
937
|
self._parse_order(), append=False, copy=False
|
938
938
|
),
|
939
939
|
"LIMIT": lambda self, query: self._parse_pipe_syntax_limit(query),
|
940
|
-
"OFFSET": lambda self, query: query.offset(self._parse_offset(), copy=False),
|
941
940
|
"AGGREGATE": lambda self, query: self._parse_pipe_syntax_aggregate(query),
|
941
|
+
"PIVOT": lambda self, query: self._parse_pipe_syntax_pivot(query),
|
942
|
+
"UNPIVOT": lambda self, query: self._parse_pipe_syntax_pivot(query),
|
942
943
|
}
|
943
944
|
|
944
945
|
PROPERTY_PARSERS: t.Dict[str, t.Callable] = {
|
@@ -8327,40 +8328,33 @@ class Parser(metaclass=_Parser):
|
|
8327
8328
|
expression.update_positions(token)
|
8328
8329
|
return expression
|
8329
8330
|
|
8330
|
-
def _build_pipe_cte(self, query: exp.Query, expressions: t.List[exp.Expression]) -> exp.
|
8331
|
-
if query.selects:
|
8332
|
-
|
8333
|
-
|
8334
|
-
|
8335
|
-
|
8336
|
-
# For `exp.SetOperation`, generated CTEs are attached to the `with` of its LHS, accessed via `this`
|
8337
|
-
with_ = (
|
8338
|
-
query.args.get("with")
|
8339
|
-
if isinstance(query, exp.Select)
|
8340
|
-
else query.this.args.get("with")
|
8341
|
-
)
|
8342
|
-
ctes = with_.pop() if with_ else None
|
8331
|
+
def _build_pipe_cte(self, query: exp.Query, expressions: t.List[exp.Expression]) -> exp.Select:
|
8332
|
+
if not query.selects:
|
8333
|
+
query = query.select("*", copy=False)
|
8334
|
+
|
8335
|
+
self._pipe_cte_counter += 1
|
8336
|
+
new_cte = f"__tmp{self._pipe_cte_counter}"
|
8343
8337
|
|
8344
|
-
|
8345
|
-
|
8346
|
-
new_select.set("with", ctes)
|
8338
|
+
with_ = query.args.get("with")
|
8339
|
+
ctes = with_.pop() if with_ else None
|
8347
8340
|
|
8348
|
-
|
8341
|
+
new_select = exp.select(*expressions, copy=False).from_(new_cte, copy=False)
|
8342
|
+
if ctes:
|
8343
|
+
new_select.set("with", ctes)
|
8349
8344
|
|
8350
|
-
return
|
8345
|
+
return new_select.with_(new_cte, as_=query, copy=False)
|
8351
8346
|
|
8352
|
-
def _parse_pipe_syntax_select(self, query: exp.
|
8347
|
+
def _parse_pipe_syntax_select(self, query: exp.Select) -> exp.Select:
|
8353
8348
|
select = self._parse_select()
|
8354
|
-
if
|
8355
|
-
return
|
8349
|
+
if not select:
|
8350
|
+
return query
|
8356
8351
|
|
8357
|
-
|
8352
|
+
if not query.selects:
|
8353
|
+
return self._build_pipe_cte(query.select(*select.expressions), [exp.Star()])
|
8358
8354
|
|
8359
|
-
|
8360
|
-
where = self._parse_where()
|
8361
|
-
return query.where(where, copy=False)
|
8355
|
+
return self._build_pipe_cte(query, select.expressions)
|
8362
8356
|
|
8363
|
-
def _parse_pipe_syntax_limit(self, query: exp.
|
8357
|
+
def _parse_pipe_syntax_limit(self, query: exp.Select) -> exp.Select:
|
8364
8358
|
limit = self._parse_limit()
|
8365
8359
|
offset = self._parse_offset()
|
8366
8360
|
if limit:
|
@@ -8371,6 +8365,7 @@ class Parser(metaclass=_Parser):
|
|
8371
8365
|
curr_offset = query.args.get("offset")
|
8372
8366
|
curr_offset = curr_offset.expression.to_py() if curr_offset else 0
|
8373
8367
|
query.offset(exp.Literal.number(curr_offset + offset.expression.to_py()), copy=False)
|
8368
|
+
|
8374
8369
|
return query
|
8375
8370
|
|
8376
8371
|
def _parse_pipe_syntax_aggregate_fields(self) -> t.Optional[exp.Expression]:
|
@@ -8386,8 +8381,8 @@ class Parser(metaclass=_Parser):
|
|
8386
8381
|
return this
|
8387
8382
|
|
8388
8383
|
def _parse_pipe_syntax_aggregate_group_order_by(
|
8389
|
-
self, query: exp.
|
8390
|
-
) -> exp.
|
8384
|
+
self, query: exp.Select, group_by_exists: bool = True
|
8385
|
+
) -> exp.Select:
|
8391
8386
|
expr = self._parse_csv(self._parse_pipe_syntax_aggregate_fields)
|
8392
8387
|
aggregates_or_groups, orders = [], []
|
8393
8388
|
for element in expr:
|
@@ -8400,45 +8395,46 @@ class Parser(metaclass=_Parser):
|
|
8400
8395
|
this = element
|
8401
8396
|
aggregates_or_groups.append(this)
|
8402
8397
|
|
8403
|
-
if group_by_exists
|
8398
|
+
if group_by_exists:
|
8404
8399
|
query = query.select(*aggregates_or_groups, copy=False).group_by(
|
8405
8400
|
*[projection.args.get("alias", projection) for projection in aggregates_or_groups],
|
8406
8401
|
copy=False,
|
8407
8402
|
)
|
8408
8403
|
else:
|
8409
|
-
query = query.select(*aggregates_or_groups,
|
8404
|
+
query = query.select(*aggregates_or_groups, copy=False)
|
8410
8405
|
|
8411
8406
|
if orders:
|
8412
8407
|
return query.order_by(*orders, append=False, copy=False)
|
8413
8408
|
|
8414
8409
|
return query
|
8415
8410
|
|
8416
|
-
def _parse_pipe_syntax_aggregate(self, query: exp.
|
8411
|
+
def _parse_pipe_syntax_aggregate(self, query: exp.Select) -> exp.Select:
|
8417
8412
|
self._match_text_seq("AGGREGATE")
|
8418
8413
|
query = self._parse_pipe_syntax_aggregate_group_order_by(query, group_by_exists=False)
|
8419
8414
|
|
8420
8415
|
if self._match(TokenType.GROUP_BY) or (
|
8421
8416
|
self._match_text_seq("GROUP", "AND") and self._match(TokenType.ORDER_BY)
|
8422
8417
|
):
|
8423
|
-
|
8418
|
+
query = self._parse_pipe_syntax_aggregate_group_order_by(query)
|
8424
8419
|
|
8425
|
-
return query
|
8420
|
+
return self._build_pipe_cte(query, [exp.Star()])
|
8426
8421
|
|
8427
8422
|
def _parse_pipe_syntax_set_operator(
|
8428
8423
|
self, query: t.Optional[exp.Query]
|
8429
|
-
) -> t.Optional[exp.
|
8424
|
+
) -> t.Optional[exp.Select]:
|
8430
8425
|
first_setop = self.parse_set_operation(this=query)
|
8431
8426
|
|
8432
8427
|
if not first_setop or not query:
|
8433
8428
|
return None
|
8434
8429
|
|
8435
|
-
|
8436
|
-
query.select("*", copy=False)
|
8437
|
-
|
8438
|
-
this = first_setop.this.pop()
|
8430
|
+
first_setop.this.pop()
|
8439
8431
|
distinct = first_setop.args.pop("distinct")
|
8440
8432
|
setops = [first_setop.expression.pop(), *self._parse_expressions()]
|
8441
8433
|
|
8434
|
+
query = self._build_pipe_cte(query, [exp.Star()])
|
8435
|
+
with_ = query.args.get("with")
|
8436
|
+
ctes = with_.pop() if with_ else None
|
8437
|
+
|
8442
8438
|
if isinstance(first_setop, exp.Union):
|
8443
8439
|
query = query.union(*setops, distinct=distinct, copy=False, **first_setop.args)
|
8444
8440
|
elif isinstance(first_setop, exp.Except):
|
@@ -8446,22 +8442,41 @@ class Parser(metaclass=_Parser):
|
|
8446
8442
|
else:
|
8447
8443
|
query = query.intersect(*setops, distinct=distinct, copy=False, **first_setop.args)
|
8448
8444
|
|
8449
|
-
|
8450
|
-
|
8451
|
-
)
|
8445
|
+
query.set("with", ctes)
|
8446
|
+
|
8447
|
+
return self._build_pipe_cte(query, [exp.Star()])
|
8448
|
+
|
8449
|
+
def _parse_pipe_syntax_join(self, query: exp.Select) -> t.Optional[exp.Select]:
|
8450
|
+
join = self._parse_join()
|
8451
|
+
if not join:
|
8452
|
+
return None
|
8453
|
+
|
8454
|
+
return query.join(join, copy=False)
|
8452
8455
|
|
8453
|
-
def
|
8456
|
+
def _parse_pipe_syntax_pivot(self, query: exp.Select) -> exp.Select:
|
8457
|
+
pivots = self._parse_pivots()
|
8458
|
+
if not pivots:
|
8459
|
+
return query
|
8460
|
+
|
8461
|
+
from_ = query.args.get("from")
|
8462
|
+
if from_:
|
8463
|
+
from_.this.set("pivots", pivots)
|
8464
|
+
|
8465
|
+
return self._build_pipe_cte(query, [exp.Star()])
|
8466
|
+
|
8467
|
+
def _parse_pipe_syntax_query(self, query: exp.Select) -> t.Optional[exp.Select]:
|
8454
8468
|
while self._match(TokenType.PIPE_GT):
|
8455
8469
|
start = self._curr
|
8456
8470
|
parser = self.PIPE_SYNTAX_TRANSFORM_PARSERS.get(self._curr.text.upper())
|
8457
8471
|
if not parser:
|
8458
|
-
|
8459
|
-
|
8472
|
+
parsed_query = self._parse_pipe_syntax_set_operator(
|
8473
|
+
query
|
8474
|
+
) or self._parse_pipe_syntax_join(query)
|
8475
|
+
if not parsed_query:
|
8460
8476
|
self._retreat(start)
|
8461
8477
|
self.raise_error(f"Unsupported pipe syntax operator: '{start.text.upper()}'.")
|
8462
8478
|
break
|
8463
|
-
|
8464
|
-
query = set_op_query
|
8479
|
+
query = parsed_query
|
8465
8480
|
else:
|
8466
8481
|
query = parser(self, query)
|
8467
8482
|
|
@@ -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=lTxpjPlB8VNbv3452Opk2GFByRI5SLtHItxl9sne84Q,515
|
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=
|
7
|
+
sqlglot/expressions.py,sha256=oE7OmkFEstTWoPqM7yCls2I2JNyia8Spr-jVi3n77-A,242992
|
8
8
|
sqlglot/generator.py,sha256=4iJ0BxkzinmosIhfhb34xjxaFpzw3Zo7fvmknaf5uRs,212432
|
9
9
|
sqlglot/helper.py,sha256=9nZjFVRBtMKFC3EdzpDQ6jkazFO19po6BF8xHiNGZIo,15111
|
10
10
|
sqlglot/jsonpath.py,sha256=dKdI3PNINNGimmSse2IIv-GbPN_3lXncXh_70QH7Lss,7664
|
11
11
|
sqlglot/lineage.py,sha256=kXBDSErmZZluZx_kkrMj4MPEOAbkvcbX1tbOW7Bpl-U,15303
|
12
|
-
sqlglot/parser.py,sha256=
|
12
|
+
sqlglot/parser.py,sha256=TksM9cVq6bbbyM0sgglcOb-p6_1_Xk6EPIS2Buj-048,320530
|
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
|
@@ -69,11 +69,11 @@ sqlglot/optimizer/pushdown_projections.py,sha256=7NoK5NAUVYVhs0YnYyo6WuXfaO-BShS
|
|
69
69
|
sqlglot/optimizer/qualify.py,sha256=oAPfwub7dEkrlCrsptcJWpLya4BgKhN6M5SwIs_86LY,4002
|
70
70
|
sqlglot/optimizer/qualify_columns.py,sha256=X2Iydssan_Fw84cd-mrzqxG3eRfRdpP6HVRofSbfHlg,40515
|
71
71
|
sqlglot/optimizer/qualify_tables.py,sha256=5f5enBAh-bpNB9ewF97W9fx9h1TGXj1Ih5fncvH42sY,6486
|
72
|
-
sqlglot/optimizer/scope.py,sha256=
|
72
|
+
sqlglot/optimizer/scope.py,sha256=lZWJsR1k-vx1VdxOn0yvbF_LcviXbK357WlrgOLXGEs,30123
|
73
73
|
sqlglot/optimizer/simplify.py,sha256=S0Blqg5Mq2KRRWhWz-Eivch9sBjBhg9fRJA6EdBzj2g,50704
|
74
74
|
sqlglot/optimizer/unnest_subqueries.py,sha256=kzWUVDlxs8z9nmRx-8U-pHXPtVZhEIwkKqmKhr2QLvc,10908
|
75
|
-
sqlglot-26.
|
76
|
-
sqlglot-26.
|
77
|
-
sqlglot-26.
|
78
|
-
sqlglot-26.
|
79
|
-
sqlglot-26.
|
75
|
+
sqlglot-26.28.1.dist-info/licenses/LICENSE,sha256=AI3__mHZfOtzY3EluR_pIYBm3_pE7TbVx7qaHxoZ114,1065
|
76
|
+
sqlglot-26.28.1.dist-info/METADATA,sha256=ElrNZkPPdEmAmU1gVJgndWkFCWlhnYqLLkGB4562Bd4,20732
|
77
|
+
sqlglot-26.28.1.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
78
|
+
sqlglot-26.28.1.dist-info/top_level.txt,sha256=5kRskCGA_gVADF9rSfSzPdLHXqvfMusDYeHePfNY2nQ,8
|
79
|
+
sqlglot-26.28.1.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|