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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: sql_blocks
3
- Version: 1.2025.629
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
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "sql_blocks"
3
- version = "1.2025.0629"
3
+ version = "1.2025.0701"
4
4
  authors = [
5
5
  { name="Julio Cascalles", email="julio.cascalles@outlook.com" },
6
6
  ]
@@ -3,7 +3,7 @@ from setuptools import setup
3
3
 
4
4
  setup(
5
5
  name = 'sql_blocks',
6
- version = '1.2025.0629',
6
+ version = '1.2025.0701',
7
7
  author = 'Júlio Cascalles',
8
8
  author_email = 'julio.cascalles@outlook.com',
9
9
  packages = ['sql_blocks'],
@@ -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
- self.extra = {}
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 __format(self, name: str, main: SQLObject) -> str:
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 += '{}{} {}'.format(
408
+ keywords += '{}{}'.format(
405
409
  '\n\t\t' if self.break_lines else ' ',
406
- obj.cls_to_str(), field if field != '_' else ''
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
- block = KEYWORDS[last_word](word)
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 PARTITION_BY
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.629
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