sql-blocks 1.20250714__py3-none-any.whl → 1.20250715__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
@@ -202,9 +202,14 @@ class NamedField:
202
202
  self.class_type = class_type
203
203
 
204
204
  def add(self, name: str, main: SQLObject):
205
+ def is_literal() -> bool:
206
+ if re.search(r'^[\'"].*', name):
207
+ return True
208
+ return False
205
209
  main.values.setdefault(SELECT, []).append(
206
210
  '{} as {}'.format(
207
- self.class_type.format(name, main),
211
+ name if is_literal()
212
+ else self.class_type.format(name, main),
208
213
  self.alias # --- field alias
209
214
  )
210
215
  )
@@ -2192,7 +2197,8 @@ class Recursive(CTE):
2192
2197
  MAIN_TAG = '__main__'
2193
2198
 
2194
2199
  class CTEFactory:
2195
- def __init__(self, txt: str):
2200
+
2201
+ def __init__(self, txt: str, template: str = ''):
2196
2202
  """
2197
2203
  SQL syntax:
2198
2204
  ---
@@ -2205,30 +2211,28 @@ class CTEFactory:
2205
2211
  Table1(field, `function$`field`:alias`, `group@`) <- Table2(field)
2206
2212
  `...`MainTable(field)
2207
2213
  """
2214
+ if template:
2215
+ for table in re.findall(r'[#](\w+)', txt):
2216
+ txt = txt.replace(f'#{table}', template.format(t=table))
2208
2217
  if parser_class(txt) == CypherParser:
2209
- txt, main_script = txt.split('...')
2218
+ txt, *main_script = txt.split('...')
2210
2219
  query_list = Select.parse(txt, CypherParser)
2211
2220
  if main_script:
2212
- main_script = ''.join(main_script)
2213
- if '(*)' in main_script:
2214
- field_list = [
2215
- re.split(
2216
- r'\bas\b|\bAS\b', field
2217
- )[-1].strip()
2218
- for query in query_list
2219
- for field in query.values.get(SELECT, [])
2220
- ]
2221
- main_script = main_script.replace('(*)', '({}, *)'.format(
2222
- ','.join(field_list)
2223
- ))
2221
+ main_script = self.replace_wildcards(
2222
+ ''.join(main_script), query_list
2223
+ )
2224
2224
  self.main = detect(main_script)
2225
2225
  alias = self.main.table_name
2226
2226
  else:
2227
2227
  alias = '_'.join(query.table_name for query in query_list)
2228
2228
  self.main = Select(alias)
2229
2229
  self.main.break_lines = False
2230
- query = join_queries(query_list)
2231
- self.cte_list = [CTE(alias, [query])]
2230
+ related_tables = any([
2231
+ query.join_type.value for query in query_list
2232
+ ])
2233
+ if related_tables:
2234
+ query_list = [ join_queries(query_list) ]
2235
+ self.cte_list = [CTE(alias, query_list)]
2232
2236
  return
2233
2237
  summary = self.extract_subqueries(txt)
2234
2238
  self.main = detect( summary.pop(MAIN_TAG) )
@@ -2246,6 +2250,21 @@ class CTEFactory:
2246
2250
  result = ',\n'.join(lines) + '\n' + str(self.main)
2247
2251
  CTE.show_query = True
2248
2252
  return result
2253
+
2254
+ @staticmethod
2255
+ def replace_wildcards(txt: str, query_list: list) -> str:
2256
+ if '(*)' in txt:
2257
+ field_list = [
2258
+ re.split(
2259
+ r'\bas\b|\bAS\b', field
2260
+ )[-1].strip()
2261
+ for query in query_list
2262
+ for field in query.values.get(SELECT, [])
2263
+ ]
2264
+ return txt.replace('(*)', '({}, *)'.format(
2265
+ ','.join( set(field_list) )
2266
+ ))
2267
+ return txt
2249
2268
 
2250
2269
  @staticmethod
2251
2270
  def extract_subqueries(txt: str) -> dict:
@@ -2282,7 +2301,7 @@ class CTEFactory:
2282
2301
  query_list = [
2283
2302
  clean_subquery( expr.split() )
2284
2303
  for expr in re.split(
2285
- r'\bUNION\b', txt[start: end], re.IGNORECASE
2304
+ r'\bUNION\b', txt[start: end], flags=re.IGNORECASE
2286
2305
  )
2287
2306
  ]
2288
2307
  result[MAIN_TAG] += f' {alias} {alias}'
@@ -2399,8 +2418,8 @@ def parser_class(text: str) -> Parser:
2399
2418
  PARSER_REGEX = [
2400
2419
  (r'select.*from', SQLParser),
2401
2420
  (r'[.](find|aggregate)[(]', MongoParser),
2402
- (r'[(\[]\w*[:]\w+', Neo4JParser),
2403
- (r'^\w+[@]*\w*[(]', CypherParser)
2421
+ (r'\bmatch\b\s*[(]', Neo4JParser),
2422
+ (r'^\w+\S+[(]', CypherParser),
2404
2423
  ]
2405
2424
  text = Parser.remove_spaces(text)
2406
2425
  for regex, class_type in PARSER_REGEX:
@@ -2442,7 +2461,24 @@ def detect(text: str, join_method = join_queries, format: str='') -> Select | li
2442
2461
  if __name__ == "__main__":
2443
2462
  OrderBy.sort = SortType.DESC
2444
2463
  cte = CTEFactory(
2445
- "Sales(year$ref_date:ref_year@, sum$quantity:qty_sold, vendor) <- Vendor(id, name:vendors_name@)"
2464
+ # "#Customer#Employee#Supplier...People_by_Type(*)",
2465
+ # template = '{t}("{t[0]}":ptype, nome:person_name)'
2466
+ """
2467
+ SELECT u001.name, agg_sales.total
2468
+ FROM (
2469
+ SELECT * FROM Users u
2470
+ WHERE u.status = 'active'
2471
+ ) AS u001
2472
+ JOIN (
2473
+ SELECT s.user_id, Sum(s.value) as total
2474
+ FROM Sales s
2475
+ GROUP BY s.user_id
2476
+ )
2477
+ As agg_sales
2478
+ ON u001.id = agg_sales.user_id
2479
+ ORDER BY u001.name
2480
+ """
2481
+ # "Sales(year$ref_date:ref_year@, sum$quantity:qty_sold, vendor) <- Vendor(id, name:vendors_name@)"
2446
2482
  # ^^^ ^^^ ^^^
2447
2483
  # | | | ^^^ ^^^
2448
2484
  # | | | | |
@@ -2454,6 +2490,6 @@ if __name__ == "__main__":
2454
2490
  # | |
2455
2491
  # +--- The Sales table |
2456
2492
  # Also groups by vendor´s name ------------------+
2457
- "...Annual_Sales_per_Vendor(*) -> Goal(^year, target)"
2493
+ # "...Annual_Sales_per_Vendor(*) -> Goal(^year, target)"
2458
2494
  )
2459
2495
  print(cte)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: sql_blocks
3
- Version: 1.20250714
3
+ Version: 1.20250715
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=LNdU9qK7eROrpCzggnPxOOlTSKkuU-mVYJLNsZNjvdY,85746
3
+ sql_blocks-1.20250715.dist-info/LICENSE,sha256=6kbiFSfobTZ7beWiKnHpN902HgBx-Jzgcme0SvKqhKY,1091
4
+ sql_blocks-1.20250715.dist-info/METADATA,sha256=pVsle1pwP1elpLwRZtpcXjL5uIi2iTiysunYaBj4N3I,25388
5
+ sql_blocks-1.20250715.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
6
+ sql_blocks-1.20250715.dist-info/top_level.txt,sha256=57AbUvUjYNy4m1EqDaU3WHeP-uyIAfV0n8GAUp1a1YQ,11
7
+ sql_blocks-1.20250715.dist-info/RECORD,,
@@ -1,7 +0,0 @@
1
- sql_blocks/__init__.py,sha256=5ItzGCyqqa6kwY8wvF9kapyHsAiWJ7KEXCcC-OtdXKg,37
2
- sql_blocks/sql_blocks.py,sha256=wYBE0XgHwsWQM0Wng5w03HtGMJ5aAqIoHpr0sAvlH-A,84546
3
- sql_blocks-1.20250714.dist-info/LICENSE,sha256=6kbiFSfobTZ7beWiKnHpN902HgBx-Jzgcme0SvKqhKY,1091
4
- sql_blocks-1.20250714.dist-info/METADATA,sha256=CPrPfsQDAQcGlGZ2z9ajGXsj_u7UHwlZia9kDqSgvrc,25388
5
- sql_blocks-1.20250714.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
6
- sql_blocks-1.20250714.dist-info/top_level.txt,sha256=57AbUvUjYNy4m1EqDaU3WHeP-uyIAfV0n8GAUp1a1YQ,11
7
- sql_blocks-1.20250714.dist-info/RECORD,,