sql-blocks 1.2025.625__py3-none-any.whl → 1.2025.628__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 CHANGED
@@ -330,16 +330,21 @@ class DateDiff(Function):
330
330
  append_param = True
331
331
 
332
332
  def __str__(self) -> str:
333
- def is_field_or_func(name: str) -> bool:
333
+ def is_field_or_func(obj) -> bool:
334
+ if not isinstance(obj, str):
335
+ return True
334
336
  candidate = re.sub(
335
- '[()]', '', name.split('.')[-1]
337
+ '[()]', '', obj.split('.')[-1]
336
338
  )
339
+ print(f'---------------> #{candidate=}#')
337
340
  return candidate.isidentifier()
341
+ self.params = [
342
+ p if is_field_or_func(p) else f"'{p}'"
343
+ for p in self.params
344
+ ]
338
345
  if self.dialect != Dialect.SQL_SERVER:
339
- params = [str(p) for p in self.params]
340
346
  return ' - '.join(
341
- p if is_field_or_func(p) else f"'{p}'"
342
- for p in params
347
+ str(p) for p in self.params
343
348
  ) # <==== Date subtract
344
349
  return super().__str__()
345
350
 
@@ -654,6 +659,8 @@ class Not(Where):
654
659
 
655
660
 
656
661
  class Case:
662
+ break_lines = True
663
+
657
664
  def __init__(self, field: str):
658
665
  self.__conditions = {}
659
666
  self.default = None
@@ -680,16 +687,24 @@ class Case:
680
687
  return self
681
688
 
682
689
  def format(self, name: str, field: str='') -> str:
690
+ TABULATION = '\t\t' if self.break_lines else ' '
691
+ LINE_BREAK = '\n' if self.break_lines else ' '
683
692
  default = self.default
684
693
  if not field:
685
694
  field = self.field
686
- return 'CASE \n{}\n\tEND AS {}'.format(
687
- '\n'.join(
688
- f'\t\tWHEN {field} {cond.content} THEN {res}'
695
+ return 'CASE{brk}{cond}{df}{tab}END{alias}'.format(
696
+ brk=LINE_BREAK,
697
+ cond=LINE_BREAK.join(
698
+ f'{TABULATION}WHEN {field} {cond.content} THEN {res}'
689
699
  for res, cond in self.__conditions.items()
690
- ) + (f'\n\t\tELSE {default}' if default else ''),
691
- name
700
+ ),
701
+ df=f'{LINE_BREAK}{TABULATION}ELSE {default}' if not default is None else '',
702
+ tab='\n\t' if self.break_lines else ' ',
703
+ alias=f' AS {name}' if name else ''
692
704
  )
705
+
706
+ def __str__(self):
707
+ return self.format('', self.field)
693
708
 
694
709
  def add(self, name: str, main: SQLObject):
695
710
  main.values.setdefault(SELECT, []).append(
@@ -2009,7 +2024,7 @@ class CTE(Select):
2009
2024
  # ---------------------------------------------------------
2010
2025
  return 'WITH {}{} AS (\n {}\n){}'.format(
2011
2026
  self.prefix, self.table_name,
2012
- '\nUNION ALL\n '.join(
2027
+ '\n\tUNION ALL\n '.join(
2013
2028
  justify(q) for q in self.query_list
2014
2029
  ), super().__str__() if self.show_query else ''
2015
2030
  )
@@ -2081,18 +2096,33 @@ class CTEFactory:
2081
2096
  self.cte_list = [
2082
2097
  CTE(alias, [
2083
2098
  Select.parse(query)[0]
2099
+ for query in elements
2084
2100
  ])
2085
- for alias, query in summary.items()
2101
+ for alias, elements in summary.items()
2086
2102
  ]
2087
2103
 
2088
2104
  def __str__(self):
2089
2105
  CTE.show_query = False
2090
2106
  lines = [str(cte) for cte in self.cte_list]
2091
- return ',\n'.join(lines) + '\n' + str(self.main)
2107
+ result = ',\n'.join(lines) + '\n' + str(self.main)
2108
+ CTE.show_query = True
2109
+ return result
2092
2110
 
2093
2111
  @staticmethod
2094
- def extract_subqueries(txt: str) -> dict:
2112
+ def extract_subqueries(txt: str) -> dict:
2095
2113
  result = {}
2114
+ # ---------------------------------------------------
2115
+ def clean_subquery(source: list) -> str:
2116
+ while source:
2117
+ if source[0].upper() == 'SELECT':
2118
+ break
2119
+ word = source.pop(0)
2120
+ if word.upper() in ('FROM', 'JOIN'):
2121
+ result[MAIN_TAG] += f' {word}'
2122
+ return ' '.join(source)
2123
+ def balanced_parentheses(expr: str) -> bool:
2124
+ return expr.count('(') == expr.count(')')
2125
+ # ---------------------------------------------------
2096
2126
  for found in re.finditer(r'(FROM|JOIN)\s*[(]\s*SELECT', txt, re.IGNORECASE):
2097
2127
  start = found.start()
2098
2128
  alias = ''
@@ -2102,16 +2132,23 @@ class CTEFactory:
2102
2132
  if not found:
2103
2133
  break
2104
2134
  end = found.end() + pos
2105
- elements = txt[start: end].split()
2106
- if '(' not in elements[-3]:
2107
- _, alias = elements[-2:]
2135
+ last = end
2136
+ if balanced_parentheses(txt[start: end]):
2137
+ pos += found.start()
2138
+ alias = re.findall(r'\s*(\w+)$', txt[pos: end])[0]
2139
+ end = pos
2108
2140
  pos = end
2109
- first_word = elements.pop(0)
2110
2141
  if not result:
2111
2142
  result[MAIN_TAG] = txt[:start]
2112
- result[MAIN_TAG] += f' {first_word} {alias} {alias}'
2113
- result[alias] = ' '.join(elements[1: -3])
2114
- result[MAIN_TAG] += txt[end:]
2143
+ query_list = [
2144
+ clean_subquery( expr.split() )
2145
+ for expr in re.split(
2146
+ r'\bUNION\b', txt[start: end], re.IGNORECASE
2147
+ )
2148
+ ]
2149
+ result[MAIN_TAG] += f' {alias} {alias}'
2150
+ result[alias] = query_list
2151
+ result[MAIN_TAG] += txt[last:]
2115
2152
  return result
2116
2153
 
2117
2154
 
@@ -2259,3 +2296,12 @@ def detect(text: str, join_queries: bool = True, format: str='') -> Select | lis
2259
2296
  result += query
2260
2297
  return result
2261
2298
  # ===========================================================================================//
2299
+
2300
+ if __name__ == "__main__":
2301
+
2302
+ print(
2303
+ Select(
2304
+ 'Emprestimo e',
2305
+ _=Sum(Case('atraso').when(gt(60), 25).when(lt(15), 5).else_value(10)).As('multa', OrderBy)
2306
+ )
2307
+ )
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: sql_blocks
3
- Version: 1.2025.625
3
+ Version: 1.2025.628
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
@@ -0,0 +1,7 @@
1
+ sql_blocks/__init__.py,sha256=5ItzGCyqqa6kwY8wvF9kapyHsAiWJ7KEXCcC-OtdXKg,37
2
+ sql_blocks/sql_blocks.py,sha256=gbihrdYwzwGUMDO2pXSeIOmxxaOX9A-hXoz-qZv_4Ls,78290
3
+ sql_blocks-1.2025.628.dist-info/LICENSE,sha256=6kbiFSfobTZ7beWiKnHpN902HgBx-Jzgcme0SvKqhKY,1091
4
+ sql_blocks-1.2025.628.dist-info/METADATA,sha256=mhDyYy5hxk3A-I7CKjekvhTBizZVXpkUA5RtKMHcIks,23328
5
+ sql_blocks-1.2025.628.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
6
+ sql_blocks-1.2025.628.dist-info/top_level.txt,sha256=57AbUvUjYNy4m1EqDaU3WHeP-uyIAfV0n8GAUp1a1YQ,11
7
+ sql_blocks-1.2025.628.dist-info/RECORD,,
@@ -1,7 +0,0 @@
1
- sql_blocks/__init__.py,sha256=5ItzGCyqqa6kwY8wvF9kapyHsAiWJ7KEXCcC-OtdXKg,37
2
- sql_blocks/sql_blocks.py,sha256=J7zEJ5JNRxI3F-7TIypb0myb5OgdE5Stv4boZCTVBLM,76610
3
- sql_blocks-1.2025.625.dist-info/LICENSE,sha256=6kbiFSfobTZ7beWiKnHpN902HgBx-Jzgcme0SvKqhKY,1091
4
- sql_blocks-1.2025.625.dist-info/METADATA,sha256=I6KTi5S_usvCjJEQl6lm8LG4DaxHhX0NlGRwhHpKBT8,23328
5
- sql_blocks-1.2025.625.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
6
- sql_blocks-1.2025.625.dist-info/top_level.txt,sha256=57AbUvUjYNy4m1EqDaU3WHeP-uyIAfV0n8GAUp1a1YQ,11
7
- sql_blocks-1.2025.625.dist-info/RECORD,,