sql-blocks 1.25.109__py3-none-any.whl → 1.25.111__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 +50 -8
- {sql_blocks-1.25.109.dist-info → sql_blocks-1.25.111.dist-info}/METADATA +54 -2
- sql_blocks-1.25.111.dist-info/RECORD +7 -0
- sql_blocks-1.25.109.dist-info/RECORD +0 -7
- {sql_blocks-1.25.109.dist-info → sql_blocks-1.25.111.dist-info}/LICENSE +0 -0
- {sql_blocks-1.25.109.dist-info → sql_blocks-1.25.111.dist-info}/WHEEL +0 -0
- {sql_blocks-1.25.109.dist-info → sql_blocks-1.25.111.dist-info}/top_level.txt +0 -0
sql_blocks/sql_blocks.py
CHANGED
@@ -379,10 +379,9 @@ def quoted(value) -> str:
|
|
379
379
|
|
380
380
|
|
381
381
|
class Position(Enum):
|
382
|
-
Middle =
|
383
|
-
|
384
|
-
EndsWith =
|
385
|
-
RegEx = "REGEXP_LIKE('{}')"
|
382
|
+
Middle = 0
|
383
|
+
StartsWith = 1
|
384
|
+
EndsWith = 2
|
386
385
|
|
387
386
|
|
388
387
|
class Where:
|
@@ -401,7 +400,13 @@ class Where:
|
|
401
400
|
|
402
401
|
@classmethod
|
403
402
|
def contains(cls, content: str, pos: Position = Position.Middle):
|
404
|
-
return cls(
|
403
|
+
return cls(
|
404
|
+
"LIKE '{}{}{}'".format(
|
405
|
+
'%' if pos != Position.StartsWith else '',
|
406
|
+
content,
|
407
|
+
'%' if pos != Position.EndsWith else ''
|
408
|
+
)
|
409
|
+
)
|
405
410
|
|
406
411
|
@classmethod
|
407
412
|
def gt(cls, value):
|
@@ -481,9 +486,8 @@ class Options:
|
|
481
486
|
self.__children: dict = values
|
482
487
|
|
483
488
|
def add(self, logical_separator: str, main: SQLObject):
|
484
|
-
|
485
|
-
|
486
|
-
"""
|
489
|
+
if logical_separator not in ('AND', 'OR'):
|
490
|
+
raise ValueError('`logical_separator` must be AND or OR')
|
487
491
|
conditions: list[str] = []
|
488
492
|
child: Where
|
489
493
|
for field, child in self.__children.items():
|
@@ -1381,6 +1385,31 @@ class RuleDateFuncReplace(Rule):
|
|
1381
1385
|
target.values[WHERE][i] = ' AND '.join(temp.values[WHERE])
|
1382
1386
|
|
1383
1387
|
|
1388
|
+
class RuleReplaceJoinBySubselect(Rule):
|
1389
|
+
@classmethod
|
1390
|
+
def apply(cls, target: Select):
|
1391
|
+
main, *others = Select.parse( str(target) )
|
1392
|
+
modified = False
|
1393
|
+
for query in others:
|
1394
|
+
fk_field, primary_k = ForeignKey.find(main, query)
|
1395
|
+
more_relations = any([
|
1396
|
+
ref[0] == query.table_name for ref in ForeignKey.references
|
1397
|
+
])
|
1398
|
+
invalid = any([
|
1399
|
+
len( query.values.get(SELECT, []) ) > 0,
|
1400
|
+
len( query.values.get(WHERE, []) ) == 0,
|
1401
|
+
not fk_field, more_relations
|
1402
|
+
])
|
1403
|
+
if invalid:
|
1404
|
+
continue
|
1405
|
+
query.__class__ = SubSelect
|
1406
|
+
Field.add(primary_k, query)
|
1407
|
+
query.add(fk_field, main)
|
1408
|
+
modified = True
|
1409
|
+
if modified:
|
1410
|
+
target.values = main.values.copy()
|
1411
|
+
|
1412
|
+
|
1384
1413
|
def parser_class(text: str) -> Parser:
|
1385
1414
|
PARSER_REGEX = [
|
1386
1415
|
(r'select.*from', SQLParser),
|
@@ -1415,3 +1444,16 @@ def detect(text: str) -> Select:
|
|
1415
1444
|
for query in query_list[1:]:
|
1416
1445
|
result += query
|
1417
1446
|
return result
|
1447
|
+
|
1448
|
+
|
1449
|
+
if __name__ == "__main__":
|
1450
|
+
query = Select(
|
1451
|
+
'Installments i', due_date=Field, customer=Select(
|
1452
|
+
'Customer c', id=PrimaryKey,
|
1453
|
+
name=contains('Smith', Position.EndsWith)
|
1454
|
+
)
|
1455
|
+
)
|
1456
|
+
print(query)
|
1457
|
+
print('-----')
|
1458
|
+
query.optimize([RuleReplaceJoinBySubselect])
|
1459
|
+
print(query)
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: sql_blocks
|
3
|
-
Version: 1.25.
|
3
|
+
Version: 1.25.111
|
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
|
@@ -97,8 +97,13 @@ query = Select('Movie m', title=Field,
|
|
97
97
|
genre=eq("Sci-Fi"),
|
98
98
|
awards=contains("Oscar")
|
99
99
|
)
|
100
|
+
AND=Options(
|
101
|
+
..., name=contains(
|
102
|
+
'Chris',
|
103
|
+
Position.StartsWith
|
104
|
+
)
|
105
|
+
)
|
100
106
|
```
|
101
|
-
> Could be AND=Options(...)
|
102
107
|
|
103
108
|
3.4 -- Negative conditions use the _Not_ class instead of _Where_
|
104
109
|
```
|
@@ -363,6 +368,35 @@ m2 = Select(
|
|
363
368
|
|
364
369
|
> The method allows you to select which rules you want to apply in the optimization...Or define your own rules!
|
365
370
|
|
371
|
+
>> NOTE: When a joined table is used only as a filter, it is possible that it can be changed to a sub-query:
|
372
|
+
|
373
|
+
query = Select(
|
374
|
+
'Installments i', due_date=Field, customer=Select(
|
375
|
+
'Customer c', id=PrimaryKey,
|
376
|
+
name=contains('Smith', Position.EndsWith)
|
377
|
+
)
|
378
|
+
)
|
379
|
+
print(query)
|
380
|
+
print('-----')
|
381
|
+
query.optimize([RuleReplaceJoinBySubselect])
|
382
|
+
print(query)
|
383
|
+
```
|
384
|
+
SELECT
|
385
|
+
i.due_date
|
386
|
+
FROM
|
387
|
+
Installments i
|
388
|
+
JOIN Customer c ON (i.customer = c.id)
|
389
|
+
WHERE
|
390
|
+
c.name LIKE '%Smith'
|
391
|
+
-----
|
392
|
+
SELECT
|
393
|
+
i.due_date
|
394
|
+
FROM
|
395
|
+
Installments i
|
396
|
+
WHERE
|
397
|
+
i.customer IN (SELECT c.id FROM Customer c WHERE c.name LIKE '%Smith')
|
398
|
+
```
|
399
|
+
|
366
400
|
---
|
367
401
|
|
368
402
|
### 12 - Adding multiple fields at once
|
@@ -567,3 +601,21 @@ GROUP BY
|
|
567
601
|
ORDER BY
|
568
602
|
customer_count
|
569
603
|
```
|
604
|
+
---
|
605
|
+
### 16 - Function classes
|
606
|
+
You may use this functions:
|
607
|
+
* SubString
|
608
|
+
* Round
|
609
|
+
* DateDiff
|
610
|
+
* Year
|
611
|
+
* Current_Date
|
612
|
+
* Avg
|
613
|
+
* Min
|
614
|
+
* Max
|
615
|
+
* Sum
|
616
|
+
* Count
|
617
|
+
> Some of these functions may vary in syntax depending on the database.
|
618
|
+
For example, if your query is going to run on Oracle, do the following:
|
619
|
+
|
620
|
+
`Function.dialect = Dialect.ORACLE`
|
621
|
+
|
@@ -0,0 +1,7 @@
|
|
1
|
+
sql_blocks/__init__.py,sha256=5ItzGCyqqa6kwY8wvF9kapyHsAiWJ7KEXCcC-OtdXKg,37
|
2
|
+
sql_blocks/sql_blocks.py,sha256=rARGbJxL3Di9mOXRBS4aEFvclO922-dzDOXPy1vSTGg,49018
|
3
|
+
sql_blocks-1.25.111.dist-info/LICENSE,sha256=6kbiFSfobTZ7beWiKnHpN902HgBx-Jzgcme0SvKqhKY,1091
|
4
|
+
sql_blocks-1.25.111.dist-info/METADATA,sha256=Lm7JKPIdZSJT5dkWUc2K7fpY4r0MQ-TeTyv0pbiMy24,14581
|
5
|
+
sql_blocks-1.25.111.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
|
6
|
+
sql_blocks-1.25.111.dist-info/top_level.txt,sha256=57AbUvUjYNy4m1EqDaU3WHeP-uyIAfV0n8GAUp1a1YQ,11
|
7
|
+
sql_blocks-1.25.111.dist-info/RECORD,,
|
@@ -1,7 +0,0 @@
|
|
1
|
-
sql_blocks/__init__.py,sha256=5ItzGCyqqa6kwY8wvF9kapyHsAiWJ7KEXCcC-OtdXKg,37
|
2
|
-
sql_blocks/sql_blocks.py,sha256=OnIlTb03DTgK_U8QBnXQtQ-rKrkSuKNj1hjJiHogmYE,47639
|
3
|
-
sql_blocks-1.25.109.dist-info/LICENSE,sha256=6kbiFSfobTZ7beWiKnHpN902HgBx-Jzgcme0SvKqhKY,1091
|
4
|
-
sql_blocks-1.25.109.dist-info/METADATA,sha256=TRybMQgmXhlz14FxEV6f4rg0-gTPpveyQi3xEYPdZ1w,13425
|
5
|
-
sql_blocks-1.25.109.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
|
6
|
-
sql_blocks-1.25.109.dist-info/top_level.txt,sha256=57AbUvUjYNy4m1EqDaU3WHeP-uyIAfV0n8GAUp1a1YQ,11
|
7
|
-
sql_blocks-1.25.109.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|