sql-blocks 1.25.19011849__py3-none-any.whl → 1.25.26011923__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.
- sql_blocks/sql_blocks.py +62 -20
- {sql_blocks-1.25.19011849.dist-info → sql_blocks-1.25.26011923.dist-info}/METADATA +47 -1
- sql_blocks-1.25.26011923.dist-info/RECORD +7 -0
- sql_blocks-1.25.19011849.dist-info/RECORD +0 -7
- {sql_blocks-1.25.19011849.dist-info → sql_blocks-1.25.26011923.dist-info}/LICENSE +0 -0
- {sql_blocks-1.25.19011849.dist-info → sql_blocks-1.25.26011923.dist-info}/WHEEL +0 -0
- {sql_blocks-1.25.19011849.dist-info → sql_blocks-1.25.26011923.dist-info}/top_level.txt +0 -0
sql_blocks/sql_blocks.py
CHANGED
@@ -470,7 +470,17 @@ class Where:
|
|
470
470
|
values = ','.join(quoted(v) for v in values)
|
471
471
|
return cls(f'IN ({values})')
|
472
472
|
|
473
|
+
@classmethod
|
474
|
+
def formula(cls, formula: str):
|
475
|
+
return cls( ExpressionField(formula) )
|
476
|
+
|
473
477
|
def add(self, name: str, main: SQLObject):
|
478
|
+
if isinstance(self.expr, ExpressionField):
|
479
|
+
self.expr = self.expr.format(name, main)
|
480
|
+
main.values.setdefault(WHERE, []).append('{} {}'.format(
|
481
|
+
self.prefix, self.expr
|
482
|
+
))
|
483
|
+
return
|
474
484
|
func_type = FUNCTION_CLASS.get(name.lower())
|
475
485
|
exists = any(
|
476
486
|
main.is_named_field(fld, SELECT)
|
@@ -1419,6 +1429,47 @@ class NotSelectIN(SelectIN):
|
|
1419
1429
|
condition_class = Not
|
1420
1430
|
|
1421
1431
|
|
1432
|
+
class CTE:
|
1433
|
+
prefix = ''
|
1434
|
+
|
1435
|
+
def __init__(self, name: str, query_list: list[Select]):
|
1436
|
+
self.name = name
|
1437
|
+
for query in query_list:
|
1438
|
+
query.break_lines = False
|
1439
|
+
self.query_list = query_list
|
1440
|
+
|
1441
|
+
def format(self, query: Select) -> str:
|
1442
|
+
LINE_MAX_SIZE = 50
|
1443
|
+
result, line = [], ''
|
1444
|
+
for word in str(query).split(' '):
|
1445
|
+
if len(line) >= LINE_MAX_SIZE and word in KEYWORD:
|
1446
|
+
result.append(line)
|
1447
|
+
line = ''
|
1448
|
+
line += word + ' '
|
1449
|
+
if line:
|
1450
|
+
result.append(line)
|
1451
|
+
return '\n\t'.join(result)
|
1452
|
+
|
1453
|
+
def __str__(self) -> str:
|
1454
|
+
return 'WITH {}{} AS (\n\t{}\n)SELECT * FROM {}'.format(
|
1455
|
+
self.prefix, self.name,
|
1456
|
+
'\nUNION ALL\n\t'.join(
|
1457
|
+
self.format(q) for q in self.query_list
|
1458
|
+
), self.name
|
1459
|
+
)
|
1460
|
+
|
1461
|
+
class Recursive(CTE):
|
1462
|
+
prefix = 'RECURSIVE '
|
1463
|
+
|
1464
|
+
def __str__(self) -> str:
|
1465
|
+
if len(self.query_list) > 1:
|
1466
|
+
alias = self.name[0].lower()
|
1467
|
+
self.query_list[-1].values[FROM].append(f', {self.name} {alias}')
|
1468
|
+
return super().__str__()
|
1469
|
+
|
1470
|
+
|
1471
|
+
# ----- Rules -----
|
1472
|
+
|
1422
1473
|
class RulePutLimit(Rule):
|
1423
1474
|
@classmethod
|
1424
1475
|
def apply(cls, target: Select):
|
@@ -1557,23 +1608,14 @@ def detect(text: str, join_queries: bool = True) -> Select:
|
|
1557
1608
|
return result
|
1558
1609
|
|
1559
1610
|
|
1560
|
-
if __name__ ==
|
1561
|
-
|
1562
|
-
#
|
1563
|
-
#
|
1564
|
-
|
1565
|
-
|
1566
|
-
|
1567
|
-
|
1568
|
-
|
1569
|
-
|
1570
|
-
|
1571
|
-
<- Curso@disciplina(professor, aluno) ->
|
1572
|
-
Aluno(id ^count$qtd_alunos)
|
1573
|
-
''', CypherParser)
|
1574
|
-
query = p + c + a
|
1575
|
-
print(query)
|
1576
|
-
print('------------------')
|
1577
|
-
query.optimize([RuleReplaceJoinBySubselect])
|
1578
|
-
# ==============================================
|
1579
|
-
print(query)
|
1611
|
+
if __name__ == "__main__":
|
1612
|
+
MY_NAME = 'Júlio Cascalles'
|
1613
|
+
# query = Select('SocialMedia s', post=Count, reaction=Sum, user=GroupBy)
|
1614
|
+
# print( CTE('Metrics', [query]) )
|
1615
|
+
q1 = Select(
|
1616
|
+
'SocialMedia me', name=[ eq(MY_NAME), Field ]
|
1617
|
+
)
|
1618
|
+
q2 = Select(
|
1619
|
+
'SocialMedia you', name=Field, id=Where.formula('{af} = n.friend')
|
1620
|
+
)
|
1621
|
+
print( Recursive('Network', [q1, q2]) )
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: sql_blocks
|
3
|
-
Version: 1.25.
|
3
|
+
Version: 1.25.26011923
|
4
4
|
Summary: Allows you to create objects for parts of SQL query commands. Also to combine these objects by joining them, adding or removing parts...
|
5
5
|
Home-page: https://github.com/julio-cascalles/sql_blocks
|
6
6
|
Author: Júlio Cascalles
|
@@ -115,6 +115,16 @@ based_on_book=Not.is_null()
|
|
115
115
|
hash_tag=inside(['space', 'monster', 'gore'])
|
116
116
|
```
|
117
117
|
|
118
|
+
3.6 -- Combining ExpressionField with Where condition:
|
119
|
+
* The **formula** method allows you to write an expression as a condition:
|
120
|
+
```
|
121
|
+
query=Select(
|
122
|
+
'Folks f2',
|
123
|
+
id=Where.formula('({af} = a.father OR {af} = a.mother)')
|
124
|
+
)
|
125
|
+
```
|
126
|
+
> Results: `WHERE...f2.id = a.father OR f2.id = a.mother`
|
127
|
+
|
118
128
|
---
|
119
129
|
### 4 - A field can be two things at the same time:
|
120
130
|
|
@@ -631,3 +641,39 @@ For example, if your query is going to run on Oracle, do the following:
|
|
631
641
|
|
632
642
|
`Function.dialect = Dialect.ORACLE`
|
633
643
|
|
644
|
+
---
|
645
|
+
|
646
|
+
### 17 - CTE and Recursive classes
|
647
|
+
|
648
|
+
* **_CTE class_**
|
649
|
+
```
|
650
|
+
query = Select(
|
651
|
+
'SocialMedia s', post=Count, reaction=Sum, user=GroupBy
|
652
|
+
)
|
653
|
+
print( CTE('Metrics', [query]) )
|
654
|
+
```
|
655
|
+
The result is...
|
656
|
+
```
|
657
|
+
WITH Metrics AS (
|
658
|
+
SELECT Count(s.post), Sum(s.reaction) FROM SocialMedia s GROUP BY user
|
659
|
+
)SELECT * FROM Metrics
|
660
|
+
```
|
661
|
+
|
662
|
+
* **_Recursive class_**
|
663
|
+
```
|
664
|
+
q1 = Select(
|
665
|
+
'SocialMedia me', name=[ eq(MY_NAME), Field ]
|
666
|
+
)
|
667
|
+
q2 = Select(
|
668
|
+
'SocialMedia you' name=Field, id=Where.formula('{af} = n.friend')
|
669
|
+
)
|
670
|
+
print( Recursive('Network', [q1, q2]) )
|
671
|
+
```
|
672
|
+
The result is...
|
673
|
+
```
|
674
|
+
WITH RECURSIVE Network AS (
|
675
|
+
SELECT me.name FROM SocialMedia me WHERE me.name = 'Júlio Cascalles'
|
676
|
+
UNION ALL
|
677
|
+
SELECT you.name FROM SocialMedia you , Network n WHERE you.id = n.friend
|
678
|
+
)SELECT * FROM Network
|
679
|
+
```
|
@@ -0,0 +1,7 @@
|
|
1
|
+
sql_blocks/__init__.py,sha256=5ItzGCyqqa6kwY8wvF9kapyHsAiWJ7KEXCcC-OtdXKg,37
|
2
|
+
sql_blocks/sql_blocks.py,sha256=lVV1Z09JVmwvV0vzKqZVBHpGWpZefD1RsMZy-aIJZSk,53868
|
3
|
+
sql_blocks-1.25.26011923.dist-info/LICENSE,sha256=6kbiFSfobTZ7beWiKnHpN902HgBx-Jzgcme0SvKqhKY,1091
|
4
|
+
sql_blocks-1.25.26011923.dist-info/METADATA,sha256=qvFr99uB0b95uv7MqpvpZaMrH7VrE557bmW4YWFQgnA,16187
|
5
|
+
sql_blocks-1.25.26011923.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
|
6
|
+
sql_blocks-1.25.26011923.dist-info/top_level.txt,sha256=57AbUvUjYNy4m1EqDaU3WHeP-uyIAfV0n8GAUp1a1YQ,11
|
7
|
+
sql_blocks-1.25.26011923.dist-info/RECORD,,
|
@@ -1,7 +0,0 @@
|
|
1
|
-
sql_blocks/__init__.py,sha256=5ItzGCyqqa6kwY8wvF9kapyHsAiWJ7KEXCcC-OtdXKg,37
|
2
|
-
sql_blocks/sql_blocks.py,sha256=nMIOewFh6X7vC0UNKs4mdqz4F_gpCSvtF0oAkocEGHw,52542
|
3
|
-
sql_blocks-1.25.19011849.dist-info/LICENSE,sha256=6kbiFSfobTZ7beWiKnHpN902HgBx-Jzgcme0SvKqhKY,1091
|
4
|
-
sql_blocks-1.25.19011849.dist-info/METADATA,sha256=jp-OY-e66KmW-tXSklUT3l5-01CX0jfCCPJ6iANNpSY,15031
|
5
|
-
sql_blocks-1.25.19011849.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
|
6
|
-
sql_blocks-1.25.19011849.dist-info/top_level.txt,sha256=57AbUvUjYNy4m1EqDaU3WHeP-uyIAfV0n8GAUp1a1YQ,11
|
7
|
-
sql_blocks-1.25.19011849.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|