sql-blocks 1.20250713__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
  )
@@ -945,15 +950,16 @@ class OrderBy(Clause):
945
950
 
946
951
  @classmethod
947
952
  def format(cls, name: str, main: SQLObject) -> str:
948
- if cls.ascending(name):
949
- cls.sort = SortType.ASC
950
- else:
953
+ # if cls.ascending(name):
954
+ # cls.sort = SortType.ASC
955
+ # else:
956
+ if not cls.ascending(name):
951
957
  cls.sort = SortType.DESC
952
958
  return super().format(name, main)
953
959
 
954
960
  @classmethod
955
961
  def cls_to_str(cls, field: str='') -> str:
956
- return f"{ORDER_BY} {field}"
962
+ return f"{ORDER_BY} {field}{cls.sort.value}"
957
963
 
958
964
  class Partition:
959
965
  @classmethod
@@ -1064,7 +1070,8 @@ class QueryLanguage:
1064
1070
  return self.join_with_tabs(values, ' AND ')
1065
1071
 
1066
1072
  def sort_by(self, values: list) -> str:
1067
- if OrderBy.sort == SortType.DESC and OrderBy.ascending(values[-1]):
1073
+ is_ascending = OrderBy.ascending(values[-1]) if values else False
1074
+ if OrderBy.sort == SortType.DESC and is_ascending:
1068
1075
  values[-1] += ' DESC'
1069
1076
  return self.join_with_tabs(values, ',')
1070
1077
 
@@ -2190,7 +2197,8 @@ class Recursive(CTE):
2190
2197
  MAIN_TAG = '__main__'
2191
2198
 
2192
2199
  class CTEFactory:
2193
- def __init__(self, txt: str):
2200
+
2201
+ def __init__(self, txt: str, template: str = ''):
2194
2202
  """
2195
2203
  SQL syntax:
2196
2204
  ---
@@ -2203,30 +2211,28 @@ class CTEFactory:
2203
2211
  Table1(field, `function$`field`:alias`, `group@`) <- Table2(field)
2204
2212
  `...`MainTable(field)
2205
2213
  """
2214
+ if template:
2215
+ for table in re.findall(r'[#](\w+)', txt):
2216
+ txt = txt.replace(f'#{table}', template.format(t=table))
2206
2217
  if parser_class(txt) == CypherParser:
2207
- txt, main_script = txt.split('...')
2218
+ txt, *main_script = txt.split('...')
2208
2219
  query_list = Select.parse(txt, CypherParser)
2209
2220
  if main_script:
2210
- main_script = ''.join(main_script)
2211
- if '(*)' in main_script:
2212
- field_list = [
2213
- re.split(
2214
- r'\bas\b|\bAS\b', field
2215
- )[-1].strip()
2216
- for query in query_list
2217
- for field in query.values.get(SELECT, [])
2218
- ]
2219
- main_script = main_script.replace('(*)', '({}, *)'.format(
2220
- ','.join(field_list)
2221
- ))
2221
+ main_script = self.replace_wildcards(
2222
+ ''.join(main_script), query_list
2223
+ )
2222
2224
  self.main = detect(main_script)
2223
2225
  alias = self.main.table_name
2224
2226
  else:
2225
2227
  alias = '_'.join(query.table_name for query in query_list)
2226
2228
  self.main = Select(alias)
2227
2229
  self.main.break_lines = False
2228
- query = join_queries(query_list)
2229
- 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)]
2230
2236
  return
2231
2237
  summary = self.extract_subqueries(txt)
2232
2238
  self.main = detect( summary.pop(MAIN_TAG) )
@@ -2244,6 +2250,21 @@ class CTEFactory:
2244
2250
  result = ',\n'.join(lines) + '\n' + str(self.main)
2245
2251
  CTE.show_query = True
2246
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
2247
2268
 
2248
2269
  @staticmethod
2249
2270
  def extract_subqueries(txt: str) -> dict:
@@ -2280,7 +2301,7 @@ class CTEFactory:
2280
2301
  query_list = [
2281
2302
  clean_subquery( expr.split() )
2282
2303
  for expr in re.split(
2283
- r'\bUNION\b', txt[start: end], re.IGNORECASE
2304
+ r'\bUNION\b', txt[start: end], flags=re.IGNORECASE
2284
2305
  )
2285
2306
  ]
2286
2307
  result[MAIN_TAG] += f' {alias} {alias}'
@@ -2397,8 +2418,8 @@ def parser_class(text: str) -> Parser:
2397
2418
  PARSER_REGEX = [
2398
2419
  (r'select.*from', SQLParser),
2399
2420
  (r'[.](find|aggregate)[(]', MongoParser),
2400
- (r'[(\[]\w*[:]\w+', Neo4JParser),
2401
- (r'^\w+[@]*\w*[(]', CypherParser)
2421
+ (r'\bmatch\b\s*[(]', Neo4JParser),
2422
+ (r'^\w+\S+[(]', CypherParser),
2402
2423
  ]
2403
2424
  text = Parser.remove_spaces(text)
2404
2425
  for regex, class_type in PARSER_REGEX:
@@ -2436,9 +2457,28 @@ def detect(text: str, join_method = join_queries, format: str='') -> Select | li
2436
2457
  return result
2437
2458
  # ===========================================================================================//
2438
2459
 
2460
+
2439
2461
  if __name__ == "__main__":
2462
+ OrderBy.sort = SortType.DESC
2440
2463
  cte = CTEFactory(
2441
- "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@)"
2442
2482
  # ^^^ ^^^ ^^^
2443
2483
  # | | | ^^^ ^^^
2444
2484
  # | | | | |
@@ -2450,6 +2490,6 @@ if __name__ == "__main__":
2450
2490
  # | |
2451
2491
  # +--- The Sales table |
2452
2492
  # Also groups by vendor´s name ------------------+
2453
- "...Annual_Sales_per_Vendor(*) -> Goal(year, target)"
2493
+ # "...Annual_Sales_per_Vendor(*) -> Goal(^year, target)"
2454
2494
  )
2455
2495
  print(cte)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: sql_blocks
3
- Version: 1.20250713
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=h5toXPu_0Nw9VaifIXAVlLBOKAv1Oz2Iw2kQSVEbk4Y,84392
3
- sql_blocks-1.20250713.dist-info/LICENSE,sha256=6kbiFSfobTZ7beWiKnHpN902HgBx-Jzgcme0SvKqhKY,1091
4
- sql_blocks-1.20250713.dist-info/METADATA,sha256=OnjjmdmJU39ADp7D1IS6FmC020iIqguDP1MbkKCdJtg,25388
5
- sql_blocks-1.20250713.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
6
- sql_blocks-1.20250713.dist-info/top_level.txt,sha256=57AbUvUjYNy4m1EqDaU3WHeP-uyIAfV0n8GAUp1a1YQ,11
7
- sql_blocks-1.20250713.dist-info/RECORD,,