sql-blocks 1.2025.629__tar.gz → 1.2025.701__tar.gz
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-1.2025.629/sql_blocks.egg-info → sql_blocks-1.2025.701}/PKG-INFO +24 -2
- {sql_blocks-1.2025.629 → sql_blocks-1.2025.701}/README.md +23 -1
- {sql_blocks-1.2025.629 → sql_blocks-1.2025.701}/pyproject.toml +1 -1
- {sql_blocks-1.2025.629 → sql_blocks-1.2025.701}/setup.py +1 -1
- {sql_blocks-1.2025.629 → sql_blocks-1.2025.701}/sql_blocks/sql_blocks.py +83 -39
- {sql_blocks-1.2025.629 → sql_blocks-1.2025.701/sql_blocks.egg-info}/PKG-INFO +24 -2
- {sql_blocks-1.2025.629 → sql_blocks-1.2025.701}/LICENSE +0 -0
- {sql_blocks-1.2025.629 → sql_blocks-1.2025.701}/setup.cfg +0 -0
- {sql_blocks-1.2025.629 → sql_blocks-1.2025.701}/sql_blocks/__init__.py +0 -0
- {sql_blocks-1.2025.629 → sql_blocks-1.2025.701}/sql_blocks.egg-info/SOURCES.txt +0 -0
- {sql_blocks-1.2025.629 → sql_blocks-1.2025.701}/sql_blocks.egg-info/dependency_links.txt +0 -0
- {sql_blocks-1.2025.629 → sql_blocks-1.2025.701}/sql_blocks.egg-info/top_level.txt +0 -0
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: sql_blocks
|
3
|
-
Version: 1.2025.
|
3
|
+
Version: 1.2025.701
|
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
|
@@ -415,7 +415,7 @@ m2 = Select(
|
|
415
415
|
)
|
416
416
|
)
|
417
417
|
|
418
|
-
10.1 - If the labels used in the CASE are based on ranges of values in sequence, you can use the **Range class**:
|
418
|
+
* 10.1 - If the labels used in the CASE are based on ranges of values in sequence, you can use the **Range class**:
|
419
419
|
|
420
420
|
query = Select(
|
421
421
|
'People p',
|
@@ -440,6 +440,28 @@ is equivalent to...
|
|
440
440
|
FROM
|
441
441
|
People p
|
442
442
|
```
|
443
|
+
|
444
|
+
* 10.2 `If` class
|
445
|
+
|
446
|
+
Usefull to conditional Sum, Avg, Count...
|
447
|
+
|
448
|
+
**Example:**
|
449
|
+
|
450
|
+
Select('Emprestimo',
|
451
|
+
taxa=If('atraso', gt(0), Sum)
|
452
|
+
)
|
453
|
+
|
454
|
+
results...
|
455
|
+
```
|
456
|
+
SELECT
|
457
|
+
Sum(CASE
|
458
|
+
WHEN atraso > 0 THEN taxa
|
459
|
+
ELSE 0
|
460
|
+
END)
|
461
|
+
FROM
|
462
|
+
Emprestimo
|
463
|
+
```
|
464
|
+
|
443
465
|
---
|
444
466
|
|
445
467
|
### 11 - optimize method
|
@@ -400,7 +400,7 @@ m2 = Select(
|
|
400
400
|
)
|
401
401
|
)
|
402
402
|
|
403
|
-
10.1 - If the labels used in the CASE are based on ranges of values in sequence, you can use the **Range class**:
|
403
|
+
* 10.1 - If the labels used in the CASE are based on ranges of values in sequence, you can use the **Range class**:
|
404
404
|
|
405
405
|
query = Select(
|
406
406
|
'People p',
|
@@ -425,6 +425,28 @@ is equivalent to...
|
|
425
425
|
FROM
|
426
426
|
People p
|
427
427
|
```
|
428
|
+
|
429
|
+
* 10.2 `If` class
|
430
|
+
|
431
|
+
Usefull to conditional Sum, Avg, Count...
|
432
|
+
|
433
|
+
**Example:**
|
434
|
+
|
435
|
+
Select('Emprestimo',
|
436
|
+
taxa=If('atraso', gt(0), Sum)
|
437
|
+
)
|
438
|
+
|
439
|
+
results...
|
440
|
+
```
|
441
|
+
SELECT
|
442
|
+
Sum(CASE
|
443
|
+
WHEN atraso > 0 THEN taxa
|
444
|
+
ELSE 0
|
445
|
+
END)
|
446
|
+
FROM
|
447
|
+
Emprestimo
|
448
|
+
```
|
449
|
+
|
428
450
|
---
|
429
451
|
|
430
452
|
### 11 - optimize method
|
@@ -210,6 +210,34 @@ class NamedField:
|
|
210
210
|
)
|
211
211
|
|
212
212
|
|
213
|
+
class Code:
|
214
|
+
def __init__(self):
|
215
|
+
# --- Replace class method by instance method: ------
|
216
|
+
self.add = self.__add
|
217
|
+
# -----------------------------------------------------
|
218
|
+
self.field_class = Field
|
219
|
+
self.extra = {}
|
220
|
+
|
221
|
+
def As(self, field_alias: str, modifiers=None):
|
222
|
+
if modifiers:
|
223
|
+
self.extra[field_alias] = TO_LIST(modifiers)
|
224
|
+
self.field_class = NamedField(field_alias)
|
225
|
+
return self
|
226
|
+
|
227
|
+
def format(self, name: str, main: SQLObject) -> str:
|
228
|
+
raise NotImplementedError('Use child classes instead of this one')
|
229
|
+
|
230
|
+
def __add(self, name: str, main: SQLObject):
|
231
|
+
name = self.format(name, main)
|
232
|
+
self.field_class.add(name, main)
|
233
|
+
if self.extra:
|
234
|
+
main.__call__(**self.extra)
|
235
|
+
|
236
|
+
@classmethod
|
237
|
+
def add(cls, name: str, main: SQLObject):
|
238
|
+
cls().__add(name, main)
|
239
|
+
|
240
|
+
|
213
241
|
class Dialect(Enum):
|
214
242
|
ANSI = 0
|
215
243
|
SQL_SERVER = 1
|
@@ -220,7 +248,7 @@ class Dialect(Enum):
|
|
220
248
|
SQL_TYPES = 'CHAR INT DATE FLOAT ANY'.split()
|
221
249
|
CHAR, INT, DATE, FLOAT, ANY = SQL_TYPES
|
222
250
|
|
223
|
-
class Function:
|
251
|
+
class Function(Code):
|
224
252
|
dialect = Dialect.ANSI
|
225
253
|
inputs = None
|
226
254
|
output = None
|
@@ -241,24 +269,13 @@ class Function:
|
|
241
269
|
if unfriendly:
|
242
270
|
return Cast(func, main_param)
|
243
271
|
return param
|
244
|
-
# --- Replace class methods by instance methods: ------
|
245
|
-
self.add = self.__add
|
246
|
-
self.format = self.__format
|
247
|
-
# -----------------------------------------------------
|
248
272
|
self.params = [set_func_types(p) for p in params]
|
249
|
-
self.field_class = Field
|
250
273
|
self.pattern = self.get_pattern()
|
251
|
-
|
274
|
+
super().__init__()
|
252
275
|
|
253
276
|
def get_pattern(self) -> str:
|
254
277
|
return '{func_name}({params})'
|
255
278
|
|
256
|
-
def As(self, field_alias: str, modifiers=None):
|
257
|
-
if modifiers:
|
258
|
-
self.extra[field_alias] = TO_LIST(modifiers)
|
259
|
-
self.field_class = NamedField(field_alias)
|
260
|
-
return self
|
261
|
-
|
262
279
|
def __str__(self) -> str:
|
263
280
|
return self.pattern.format(
|
264
281
|
func_name=self.__class__.__name__,
|
@@ -288,24 +305,11 @@ class Function:
|
|
288
305
|
else:
|
289
306
|
self.params = new_params + self.params
|
290
307
|
|
291
|
-
def
|
308
|
+
def format(self, name: str, main: SQLObject) -> str:
|
292
309
|
if name not in '*_':
|
293
310
|
self.set_main_param(name, main)
|
294
311
|
return str(self)
|
295
312
|
|
296
|
-
@classmethod
|
297
|
-
def format(cls, name: str, main: SQLObject):
|
298
|
-
return cls().__format(name, main)
|
299
|
-
|
300
|
-
def __add(self, name: str, main: SQLObject):
|
301
|
-
name = self.format(name, main)
|
302
|
-
self.field_class.add(name, main)
|
303
|
-
if self.extra:
|
304
|
-
main.__call__(**self.extra)
|
305
|
-
|
306
|
-
@classmethod
|
307
|
-
def add(cls, name: str, main: SQLObject):
|
308
|
-
cls().__add(name, main)
|
309
313
|
|
310
314
|
|
311
315
|
# ---- String Functions: ---------------------------------
|
@@ -395,15 +399,15 @@ class Frame:
|
|
395
399
|
keywords = ''
|
396
400
|
for field, obj in args.items():
|
397
401
|
is_valid = any([
|
398
|
-
obj is OrderBy,
|
402
|
+
obj is OrderBy, obj is DescOrderBy,
|
399
403
|
obj is Partition,
|
400
404
|
isinstance(obj, Rows),
|
401
405
|
])
|
402
406
|
if not is_valid:
|
403
407
|
continue
|
404
|
-
keywords += '{}{}
|
408
|
+
keywords += '{}{}'.format(
|
405
409
|
'\n\t\t' if self.break_lines else ' ',
|
406
|
-
obj.cls_to_str(
|
410
|
+
obj.cls_to_str(field if field != '_' else '')
|
407
411
|
)
|
408
412
|
if keywords and self.break_lines:
|
409
413
|
keywords += '\n\t'
|
@@ -750,7 +754,10 @@ class Case:
|
|
750
754
|
while tokens:
|
751
755
|
word = tokens.pop(0)
|
752
756
|
if last_word in KEYWORDS:
|
753
|
-
|
757
|
+
try:
|
758
|
+
block = KEYWORDS[last_word](word)
|
759
|
+
except:
|
760
|
+
break
|
754
761
|
result += block.fields
|
755
762
|
block.fields = []
|
756
763
|
elif word not in RESERVED_WORDS:
|
@@ -759,6 +766,27 @@ class Case:
|
|
759
766
|
return result
|
760
767
|
|
761
768
|
|
769
|
+
class If(Code, Frame):
|
770
|
+
"""
|
771
|
+
Behaves like an aggregation function
|
772
|
+
"""
|
773
|
+
def __init__(self, field: str, condition: Where, func_class: Function):
|
774
|
+
self.field = field
|
775
|
+
self.condition = condition
|
776
|
+
self.func_class = func_class
|
777
|
+
super().__init__()
|
778
|
+
|
779
|
+
def format(self, name: str, main: SQLObject) -> str:
|
780
|
+
return '{func}({param}){over}'.format(
|
781
|
+
func=self.func_class.__name__,
|
782
|
+
param=Case(self.field).when(self.condition, f'={name}').else_value(0),
|
783
|
+
over=self.pattern
|
784
|
+
)
|
785
|
+
|
786
|
+
def get_pattern(self) -> str:
|
787
|
+
return ''
|
788
|
+
|
789
|
+
|
762
790
|
class Options:
|
763
791
|
def __init__(self, **values):
|
764
792
|
self.__children: dict = values
|
@@ -857,7 +885,7 @@ class Rows:
|
|
857
885
|
def __init__(self, *rows: list[Row]):
|
858
886
|
self.rows = rows
|
859
887
|
|
860
|
-
def cls_to_str(self) -> str:
|
888
|
+
def cls_to_str(self, field: str='') -> str:
|
861
889
|
return 'ROWS {}{}'.format(
|
862
890
|
'BETWEEN ' if len(self.rows) > 1 else '',
|
863
891
|
' AND '.join(str(row) for row in self.rows)
|
@@ -870,6 +898,11 @@ class DescOrderBy:
|
|
870
898
|
name = Clause.format(name, main)
|
871
899
|
main.values.setdefault(ORDER_BY, []).append(name + SortType.DESC.value)
|
872
900
|
|
901
|
+
@classmethod
|
902
|
+
def cls_to_str(cls, field: str='') -> str:
|
903
|
+
return f"{ORDER_BY} {field} DESC"
|
904
|
+
|
905
|
+
|
873
906
|
class OrderBy(Clause):
|
874
907
|
sort: SortType = SortType.ASC
|
875
908
|
DESC = DescOrderBy
|
@@ -894,14 +927,13 @@ class OrderBy(Clause):
|
|
894
927
|
return super().format(name, main)
|
895
928
|
|
896
929
|
@classmethod
|
897
|
-
def cls_to_str(cls) -> str:
|
898
|
-
return ORDER_BY
|
930
|
+
def cls_to_str(cls, field: str='') -> str:
|
931
|
+
return f"{ORDER_BY} {field}"
|
899
932
|
|
900
|
-
PARTITION_BY = 'PARTITION BY'
|
901
933
|
class Partition:
|
902
934
|
@classmethod
|
903
|
-
def cls_to_str(cls) -> str:
|
904
|
-
return
|
935
|
+
def cls_to_str(cls, field: str) -> str:
|
936
|
+
return f'PARTITION BY {field}'
|
905
937
|
|
906
938
|
|
907
939
|
class GroupBy(Clause):
|
@@ -918,7 +950,7 @@ class Having:
|
|
918
950
|
|
919
951
|
def add(self, name: str, main:SQLObject):
|
920
952
|
main.values[GROUP_BY][-1] += ' HAVING {} {}'.format(
|
921
|
-
self.function.format(name, main), self.condition.content
|
953
|
+
self.function().format(name, main), self.condition.content
|
922
954
|
)
|
923
955
|
|
924
956
|
@classmethod
|
@@ -2297,4 +2329,16 @@ def detect(text: str, join_queries: bool = True, format: str='') -> Select | lis
|
|
2297
2329
|
for query in query_list[1:]:
|
2298
2330
|
result += query
|
2299
2331
|
return result
|
2300
|
-
# ===========================================================================================//
|
2332
|
+
# ===========================================================================================//
|
2333
|
+
|
2334
|
+
if __name__ == "__main__":
|
2335
|
+
query = Select(
|
2336
|
+
'Emprestimos e',
|
2337
|
+
taxa=If('atraso', gt(0), Sum).over(
|
2338
|
+
mes_ano=OrderBy.DESC,
|
2339
|
+
_=Rows(Current(), Following(5)),
|
2340
|
+
# _=Rows(Preceding(3), Following()),
|
2341
|
+
# _=Rows( Preceding(3) ),
|
2342
|
+
).As('multa')
|
2343
|
+
)
|
2344
|
+
print(query)
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: sql_blocks
|
3
|
-
Version: 1.2025.
|
3
|
+
Version: 1.2025.701
|
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
|
@@ -415,7 +415,7 @@ m2 = Select(
|
|
415
415
|
)
|
416
416
|
)
|
417
417
|
|
418
|
-
10.1 - If the labels used in the CASE are based on ranges of values in sequence, you can use the **Range class**:
|
418
|
+
* 10.1 - If the labels used in the CASE are based on ranges of values in sequence, you can use the **Range class**:
|
419
419
|
|
420
420
|
query = Select(
|
421
421
|
'People p',
|
@@ -440,6 +440,28 @@ is equivalent to...
|
|
440
440
|
FROM
|
441
441
|
People p
|
442
442
|
```
|
443
|
+
|
444
|
+
* 10.2 `If` class
|
445
|
+
|
446
|
+
Usefull to conditional Sum, Avg, Count...
|
447
|
+
|
448
|
+
**Example:**
|
449
|
+
|
450
|
+
Select('Emprestimo',
|
451
|
+
taxa=If('atraso', gt(0), Sum)
|
452
|
+
)
|
453
|
+
|
454
|
+
results...
|
455
|
+
```
|
456
|
+
SELECT
|
457
|
+
Sum(CASE
|
458
|
+
WHEN atraso > 0 THEN taxa
|
459
|
+
ELSE 0
|
460
|
+
END)
|
461
|
+
FROM
|
462
|
+
Emprestimo
|
463
|
+
```
|
464
|
+
|
443
465
|
---
|
444
466
|
|
445
467
|
### 11 - optimize method
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|