sql-blocks 1.25.113__py3-none-any.whl → 1.25.1801__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 +69 -24
- {sql_blocks-1.25.113.dist-info → sql_blocks-1.25.1801.dist-info}/METADATA +9 -3
- sql_blocks-1.25.1801.dist-info/RECORD +7 -0
- sql_blocks-1.25.113.dist-info/RECORD +0 -7
- {sql_blocks-1.25.113.dist-info → sql_blocks-1.25.1801.dist-info}/LICENSE +0 -0
- {sql_blocks-1.25.113.dist-info → sql_blocks-1.25.1801.dist-info}/WHEEL +0 -0
- {sql_blocks-1.25.113.dist-info → sql_blocks-1.25.1801.dist-info}/top_level.txt +0 -0
sql_blocks/sql_blocks.py
CHANGED
@@ -121,7 +121,8 @@ class SQLObject:
|
|
121
121
|
|
122
122
|
SQL_CONST_SYSDATE = 'SYSDATE'
|
123
123
|
SQL_CONST_CURR_DATE = 'Current_date'
|
124
|
-
|
124
|
+
SQL_ROW_NUM = 'ROWNUM'
|
125
|
+
SQL_CONSTS = [SQL_CONST_SYSDATE, SQL_CONST_CURR_DATE, SQL_ROW_NUM]
|
125
126
|
|
126
127
|
|
127
128
|
class Field:
|
@@ -282,14 +283,15 @@ class Frame:
|
|
282
283
|
keywords = ''
|
283
284
|
for field, obj in args.items():
|
284
285
|
is_valid = any([
|
285
|
-
obj is
|
286
|
-
|
286
|
+
obj is OrderBy,
|
287
|
+
obj is Partition,
|
288
|
+
isinstance(obj, Rows),
|
287
289
|
])
|
288
290
|
if not is_valid:
|
289
291
|
continue
|
290
292
|
keywords += '{}{} {}'.format(
|
291
293
|
'\n\t\t' if self.break_lines else ' ',
|
292
|
-
obj.cls_to_str(), field
|
294
|
+
obj.cls_to_str(), field if field != '_' else ''
|
293
295
|
)
|
294
296
|
if keywords and self.break_lines:
|
295
297
|
keywords += '\n\t'
|
@@ -561,6 +563,34 @@ class SortType(Enum):
|
|
561
563
|
ASC = ''
|
562
564
|
DESC = ' DESC'
|
563
565
|
|
566
|
+
class Row:
|
567
|
+
def __init__(self, value: int=0):
|
568
|
+
self.value = value
|
569
|
+
|
570
|
+
def __str__(self) -> str:
|
571
|
+
return '{} {}'.format(
|
572
|
+
'UNBOUNDED' if self.value == 0 else self.value,
|
573
|
+
self.__class__.__name__.upper()
|
574
|
+
)
|
575
|
+
|
576
|
+
class Preceding(Row):
|
577
|
+
...
|
578
|
+
class Following(Row):
|
579
|
+
...
|
580
|
+
class Current(Row):
|
581
|
+
def __str__(self) -> str:
|
582
|
+
return 'CURRENT ROW'
|
583
|
+
|
584
|
+
class Rows:
|
585
|
+
def __init__(self, *rows: list[Row]):
|
586
|
+
self.rows = rows
|
587
|
+
|
588
|
+
def cls_to_str(self) -> str:
|
589
|
+
return 'ROWS {}{}'.format(
|
590
|
+
'BETWEEN ' if len(self.rows) > 1 else '',
|
591
|
+
' AND '.join(str(row) for row in self.rows)
|
592
|
+
)
|
593
|
+
|
564
594
|
|
565
595
|
class OrderBy(Clause):
|
566
596
|
sort: SortType = SortType.ASC
|
@@ -625,7 +655,7 @@ class Rule:
|
|
625
655
|
...
|
626
656
|
|
627
657
|
class QueryLanguage:
|
628
|
-
pattern = '{select}{_from}{where}{group_by}{order_by}'
|
658
|
+
pattern = '{select}{_from}{where}{group_by}{order_by}{limit}'
|
629
659
|
has_default = {key: bool(key == SELECT) for key in KEYWORD}
|
630
660
|
|
631
661
|
@staticmethod
|
@@ -653,13 +683,16 @@ class QueryLanguage:
|
|
653
683
|
def set_group(self, values: list) -> str:
|
654
684
|
return self.join_with_tabs(values, ',')
|
655
685
|
|
686
|
+
def set_limit(self, values: list) -> str:
|
687
|
+
return self.join_with_tabs(values, ' ')
|
688
|
+
|
656
689
|
def __init__(self, target: 'Select'):
|
657
|
-
self.KEYWORDS = [SELECT, FROM, WHERE, GROUP_BY, ORDER_BY]
|
690
|
+
self.KEYWORDS = [SELECT, FROM, WHERE, GROUP_BY, ORDER_BY, LIMIT]
|
658
691
|
self.TABULATION = '\n\t' if target.break_lines else ' '
|
659
692
|
self.LINE_BREAK = '\n' if target.break_lines else ' '
|
660
693
|
self.TOKEN_METHODS = {
|
661
694
|
SELECT: self.add_field, FROM: self.get_tables,
|
662
|
-
WHERE: self.extract_conditions,
|
695
|
+
WHERE: self.extract_conditions, LIMIT: self.set_limit,
|
663
696
|
ORDER_BY: self.sort_by, GROUP_BY: self.set_group,
|
664
697
|
}
|
665
698
|
self.result = {}
|
@@ -1308,10 +1341,21 @@ class Select(SQLObject):
|
|
1308
1341
|
return True
|
1309
1342
|
|
1310
1343
|
def limit(self, row_count: int=100, offset: int=0):
|
1311
|
-
|
1312
|
-
|
1313
|
-
|
1314
|
-
|
1344
|
+
if Function.dialect == Dialect.SQL_SERVER:
|
1345
|
+
fields = self.values.get(SELECT)
|
1346
|
+
if fields:
|
1347
|
+
fields[0] = f'SELECT TOP({row_count}) {fields[0]}'
|
1348
|
+
else:
|
1349
|
+
self.values[SELECT] = [f'SELECT TOP({row_count}) *']
|
1350
|
+
return self
|
1351
|
+
if Function.dialect == Dialect.ORACLE:
|
1352
|
+
Where.gte(row_count).add(SQL_ROW_NUM, self)
|
1353
|
+
if offset > 0:
|
1354
|
+
Where.lte(row_count+offset).add(SQL_ROW_NUM, self)
|
1355
|
+
return self
|
1356
|
+
self.values[LIMIT] = ['{}{}'.format(
|
1357
|
+
row_count, f' OFFSET {offset}' if offset > 0 else ''
|
1358
|
+
)]
|
1315
1359
|
return self
|
1316
1360
|
|
1317
1361
|
def match(self, field: str, key: str) -> bool:
|
@@ -1475,7 +1519,7 @@ def parser_class(text: str) -> Parser:
|
|
1475
1519
|
return None
|
1476
1520
|
|
1477
1521
|
|
1478
|
-
def detect(text: str) -> Select:
|
1522
|
+
def detect(text: str, join_queries: bool = True) -> Select:
|
1479
1523
|
from collections import Counter
|
1480
1524
|
parser = parser_class(text)
|
1481
1525
|
if not parser:
|
@@ -1491,6 +1535,8 @@ def detect(text: str) -> Select:
|
|
1491
1535
|
text = text[:begin] + new_name + '(' + text[end:]
|
1492
1536
|
count -= 1
|
1493
1537
|
query_list = Select.parse(text, parser)
|
1538
|
+
if not join_queries:
|
1539
|
+
return query_list
|
1494
1540
|
result = query_list[0]
|
1495
1541
|
for query in query_list[1:]:
|
1496
1542
|
result += query
|
@@ -1498,15 +1544,14 @@ def detect(text: str) -> Select:
|
|
1498
1544
|
|
1499
1545
|
|
1500
1546
|
if __name__ == '__main__':
|
1501
|
-
|
1502
|
-
|
1503
|
-
|
1504
|
-
|
1505
|
-
|
1506
|
-
|
1507
|
-
|
1508
|
-
|
1509
|
-
|
1510
|
-
|
1511
|
-
|
1512
|
-
print('#######################################')
|
1547
|
+
for dialect in Dialect:
|
1548
|
+
Function.dialect = dialect
|
1549
|
+
print(f'--------------{dialect.name}--------------')
|
1550
|
+
query = Select(
|
1551
|
+
'Installments',
|
1552
|
+
_=DateDiff(
|
1553
|
+
Current_Date(),
|
1554
|
+
'due_date'
|
1555
|
+
).As('elapsed_time')
|
1556
|
+
).limit(10)
|
1557
|
+
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.1801
|
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
|
@@ -554,12 +554,18 @@ It consists of the inverse process of parsing: From a Select object, it returns
|
|
554
554
|
---
|
555
555
|
### 14 - Window Function
|
556
556
|
|
557
|
-
Aggregation functions (Avg, Min, Max, Sum, Count) have the **over** method...
|
557
|
+
Aggregation functions (Avg, Min, Max, Sum, Count) -- or Window functions (Lead, Lag, Row_Number, Rank) -- have the **over** method...
|
558
558
|
|
559
559
|
query=Select(
|
560
560
|
'Enrollment e',
|
561
561
|
payment=Sum().over(
|
562
|
-
|
562
|
+
student_id=Partition, due_date=OrderBy,
|
563
|
+
# _=Rows(Current(), Following(5)),
|
564
|
+
# ^^^-------> ROWS BETWEEN CURRENT ROW AND 5 FOLLOWING
|
565
|
+
# _=Rows(Preceding(3), Following()),
|
566
|
+
# ^^^-------> ROWS BETWEEN 3 PRECEDING AND UNBOUNDED FOLLOWING
|
567
|
+
# _=Rows(Preceding(3))
|
568
|
+
# ^^^-------> ROWS 3 PRECEDING
|
563
569
|
).As('sum_per_student')
|
564
570
|
)
|
565
571
|
|
@@ -0,0 +1,7 @@
|
|
1
|
+
sql_blocks/__init__.py,sha256=5ItzGCyqqa6kwY8wvF9kapyHsAiWJ7KEXCcC-OtdXKg,37
|
2
|
+
sql_blocks/sql_blocks.py,sha256=iFS3drlQaazFkbBBFIH58RPZt4Lhe6R2Xqi_Ujef7Bg,51893
|
3
|
+
sql_blocks-1.25.1801.dist-info/LICENSE,sha256=6kbiFSfobTZ7beWiKnHpN902HgBx-Jzgcme0SvKqhKY,1091
|
4
|
+
sql_blocks-1.25.1801.dist-info/METADATA,sha256=WnwFnhle4YXNyeC6dBVAnQmUqJiboT1CDhbvRHOmEQY,15027
|
5
|
+
sql_blocks-1.25.1801.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
|
6
|
+
sql_blocks-1.25.1801.dist-info/top_level.txt,sha256=57AbUvUjYNy4m1EqDaU3WHeP-uyIAfV0n8GAUp1a1YQ,11
|
7
|
+
sql_blocks-1.25.1801.dist-info/RECORD,,
|
@@ -1,7 +0,0 @@
|
|
1
|
-
sql_blocks/__init__.py,sha256=5ItzGCyqqa6kwY8wvF9kapyHsAiWJ7KEXCcC-OtdXKg,37
|
2
|
-
sql_blocks/sql_blocks.py,sha256=Saj3MqmF0OHY60bhc_aSl8fL-PhXM2apmiPiE6KspOc,50553
|
3
|
-
sql_blocks-1.25.113.dist-info/LICENSE,sha256=6kbiFSfobTZ7beWiKnHpN902HgBx-Jzgcme0SvKqhKY,1091
|
4
|
-
sql_blocks-1.25.113.dist-info/METADATA,sha256=td1IZl9O3m2U0rWFk6gyecqWnkr0cMDW94PfeqhzP8Y,14638
|
5
|
-
sql_blocks-1.25.113.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
|
6
|
-
sql_blocks-1.25.113.dist-info/top_level.txt,sha256=57AbUvUjYNy4m1EqDaU3WHeP-uyIAfV0n8GAUp1a1YQ,11
|
7
|
-
sql_blocks-1.25.113.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|