sql-blocks 1.25.19011745__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 +66 -11
- {sql_blocks-1.25.19011745.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.19011745.dist-info/RECORD +0 -7
- {sql_blocks-1.25.19011745.dist-info → sql_blocks-1.25.26011923.dist-info}/LICENSE +0 -0
- {sql_blocks-1.25.19011745.dist-info → sql_blocks-1.25.26011923.dist-info}/WHEEL +0 -0
- {sql_blocks-1.25.19011745.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)
|
@@ -566,7 +576,7 @@ class Clause:
|
|
566
576
|
found = re.findall(r'^_\d', name)
|
567
577
|
if found:
|
568
578
|
name = found[0].replace('_', '')
|
569
|
-
elif main.alias and not is_function():
|
579
|
+
elif '.' not in name and main.alias and not is_function():
|
570
580
|
name = f'{main.alias}.{name}'
|
571
581
|
return name
|
572
582
|
|
@@ -1008,8 +1018,11 @@ class SQLParser(Parser):
|
|
1008
1018
|
if not key in values:
|
1009
1019
|
continue
|
1010
1020
|
separator = self.class_type.get_separator(key)
|
1021
|
+
cls = {
|
1022
|
+
ORDER_BY: OrderBy, GROUP_BY: GroupBy
|
1023
|
+
}.get(key, Field)
|
1011
1024
|
obj.values[key] = [
|
1012
|
-
|
1025
|
+
cls.format(fld, obj)
|
1013
1026
|
for fld in re.split(separator, values[key])
|
1014
1027
|
if (fld != '*' and len(tables) == 1) or obj.match(fld, key)
|
1015
1028
|
]
|
@@ -1416,6 +1429,47 @@ class NotSelectIN(SelectIN):
|
|
1416
1429
|
condition_class = Not
|
1417
1430
|
|
1418
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
|
+
|
1419
1473
|
class RulePutLimit(Rule):
|
1420
1474
|
@classmethod
|
1421
1475
|
def apply(cls, target: Select):
|
@@ -1554,13 +1608,14 @@ def detect(text: str, join_queries: bool = True) -> Select:
|
|
1554
1608
|
return result
|
1555
1609
|
|
1556
1610
|
|
1557
|
-
if __name__ ==
|
1558
|
-
|
1559
|
-
|
1560
|
-
|
1561
|
-
|
1562
|
-
|
1563
|
-
|
1564
|
-
|
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')
|
1565
1620
|
)
|
1566
|
-
print(
|
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=lPUpYOLHjvx84EVjlydJK03rm7qG1DWotRtqyldKqvo,52020
|
3
|
-
sql_blocks-1.25.19011745.dist-info/LICENSE,sha256=6kbiFSfobTZ7beWiKnHpN902HgBx-Jzgcme0SvKqhKY,1091
|
4
|
-
sql_blocks-1.25.19011745.dist-info/METADATA,sha256=KPw30aPiITpjBHpfWU9yAuTtr8aQ5cW5cdIdzM4iD0k,15031
|
5
|
-
sql_blocks-1.25.19011745.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
|
6
|
-
sql_blocks-1.25.19011745.dist-info/top_level.txt,sha256=57AbUvUjYNy4m1EqDaU3WHeP-uyIAfV0n8GAUp1a1YQ,11
|
7
|
-
sql_blocks-1.25.19011745.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|