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 +58 -22
- {sql_blocks-1.20250714.dist-info → sql_blocks-1.20250715.dist-info}/METADATA +1 -1
- sql_blocks-1.20250715.dist-info/RECORD +7 -0
- sql_blocks-1.20250714.dist-info/RECORD +0 -7
- {sql_blocks-1.20250714.dist-info → sql_blocks-1.20250715.dist-info}/LICENSE +0 -0
- {sql_blocks-1.20250714.dist-info → sql_blocks-1.20250715.dist-info}/WHEEL +0 -0
- {sql_blocks-1.20250714.dist-info → sql_blocks-1.20250715.dist-info}/top_level.txt +0 -0
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
|
-
|
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
|
-
|
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 =
|
2213
|
-
|
2214
|
-
|
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
|
-
|
2231
|
-
|
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'
|
2403
|
-
(r'^\w+[
|
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
|
-
"
|
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.
|
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,,
|
File without changes
|
File without changes
|
File without changes
|