sql-code-graph 1.34.2__py3-none-any.whl → 1.34.4__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_code_graph-1.34.2.dist-info → sql_code_graph-1.34.4.dist-info}/METADATA +1 -1
- {sql_code_graph-1.34.2.dist-info → sql_code_graph-1.34.4.dist-info}/RECORD +9 -9
- sqlcg/__init__.py +1 -1
- sqlcg/cli/commands/analyze.py +25 -3
- sqlcg/core/queries.py +1 -0
- sqlcg/core/queries.sql +23 -0
- sqlcg/indexer/indexer.py +14 -0
- {sql_code_graph-1.34.2.dist-info → sql_code_graph-1.34.4.dist-info}/WHEEL +0 -0
- {sql_code_graph-1.34.2.dist-info → sql_code_graph-1.34.4.dist-info}/entry_points.txt +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: sql-code-graph
|
|
3
|
-
Version: 1.34.
|
|
3
|
+
Version: 1.34.4
|
|
4
4
|
Summary: SQL code graph analyzer and lineage tracer
|
|
5
5
|
Project-URL: Homepage, https://github.com/Warhorze/sql-code-graph
|
|
6
6
|
Project-URL: Repository, https://github.com/Warhorze/sql-code-graph
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
sqlcg/__init__.py,sha256=
|
|
1
|
+
sqlcg/__init__.py,sha256=jFojpr6ZojswTJKMfPZEdxqOfiqZPTpuB2Cb9aa1RM0,116
|
|
2
2
|
sqlcg/__main__.py,sha256=1YoFLcqEgTwYq1J3TbUwpkdG0zeeLIf2fJvwWI-CLFU,109
|
|
3
3
|
sqlcg/cli/__init__.py,sha256=W8fD0LpMq2xm_5WKGNMvJh2WBL1ho5E8hUeAqXQYT1g,28
|
|
4
4
|
sqlcg/cli/coverage.py,sha256=Xm9ITzZDHv2mJ70Q5jCacVuhDStVrE3gq12_-Ypvtd8,43823
|
|
5
5
|
sqlcg/cli/main.py,sha256=tlFvl-l9hWfZBP9dO2svZXvLDbh7T5731CFyctuVqDI,2485
|
|
6
6
|
sqlcg/cli/commands/__init__.py,sha256=oSHtr6VD-jNubOjuCQyZj2tBppjMEpQDh-IGQ8of9eA,30
|
|
7
|
-
sqlcg/cli/commands/analyze.py,sha256=
|
|
7
|
+
sqlcg/cli/commands/analyze.py,sha256=lC7QeBKljWVpKQ-x8BOF5Ok6y4jd329U1aBGrp159OA,31046
|
|
8
8
|
sqlcg/cli/commands/catalog.py,sha256=xCIWp_9xcDPHIMUB0xrZR3-G0WMvKbfq4yMwe2sDT2g,12670
|
|
9
9
|
sqlcg/cli/commands/db.py,sha256=QEDPs0boeFe8ETE8BWe7I2JLSXROUI571SHXMTUqxh8,7982
|
|
10
10
|
sqlcg/cli/commands/find.py,sha256=uMdG08bU-AvB9RqsTKPfdVnJet7b3Ebj0xbsjqTclYA,2678
|
|
@@ -25,15 +25,15 @@ sqlcg/core/graph_db.py,sha256=3iZ1J32cEn7_cVhNA1tLiNuJHCyatN4F40HXLLfmwHY,10815
|
|
|
25
25
|
sqlcg/core/jobs.py,sha256=Je-fCdSKRgiSsv1W8SgNAlp36a7t7-pJZ-qKPbka9OE,3298
|
|
26
26
|
sqlcg/core/noise_match.py,sha256=8jxMBum0HB7wnVyS8hHaklO279QOSNKDmPtv-0RujD8,4781
|
|
27
27
|
sqlcg/core/queries.cypher,sha256=cvPOVe5GUOzJN4bxUvDxNI--xIIP8gm42TR-gUnea4U,4685
|
|
28
|
-
sqlcg/core/queries.py,sha256=
|
|
29
|
-
sqlcg/core/queries.sql,sha256
|
|
28
|
+
sqlcg/core/queries.py,sha256=QwQsjI2YJPipfw69k9iSu1jpeiOIPPtkegO4TVmAVaY,3703
|
|
29
|
+
sqlcg/core/queries.sql,sha256=-ZoMnNt-i2kojMHLAUHvQhCZURIgI9zkfh8J8QJo1iE,16863
|
|
30
30
|
sqlcg/core/schema.cypher,sha256=StaJqIzOLwF2X9HYvfHSdGiYGFb_YkiHubPrTu-Qpmg,2898
|
|
31
31
|
sqlcg/core/schema.py,sha256=pVGzf__czAddmz-fsXgXqq2DTxN9EKom5RvIHLctIPU,1519
|
|
32
32
|
sqlcg/indexer/__init__.py,sha256=Wh20Unz2OHs1oIyWLrpurPAasF0BET2g4iXtNk7mh2U,56
|
|
33
33
|
sqlcg/indexer/dbt_adapter.py,sha256=EB5x1WU5Z9d-I97ADDj88S_hG1C4z4nbrv8JUCzXfy8,686
|
|
34
34
|
sqlcg/indexer/error_classify.py,sha256=-sp8cRmuOBHu_CxnCtaXf34YxHFYwIFNjIrn4LaEv6M,7142
|
|
35
35
|
sqlcg/indexer/git_delta.py,sha256=zYdH5q-jV7w_ne8Oxdywsy0N3rwUjpd5RjEDurlrMSA,5026
|
|
36
|
-
sqlcg/indexer/indexer.py,sha256=
|
|
36
|
+
sqlcg/indexer/indexer.py,sha256=u6fIhgLfBs9fKJoAyO4hJrm9152YMe08EHycncctQx8,102697
|
|
37
37
|
sqlcg/indexer/pool.py,sha256=iMmCQtpDRKBTQBep2_EUq9THcsE18Zgk0hdaFB_CwiA,19006
|
|
38
38
|
sqlcg/indexer/walker.py,sha256=Cft6JiJtdBFy0HR6L9pJdr5Fg0eRR3XBW1OMtM2apto,1947
|
|
39
39
|
sqlcg/indexer/watcher.py,sha256=mJQq1LASRLKKwhz0WhCUWPLLqyPR2_-FD_8efYU6gE8,8442
|
|
@@ -65,7 +65,7 @@ sqlcg/utils/__init__.py,sha256=--iqt5ThTXmT8Wz7da8hs3n0zDfYPl8P-z5OgRJ_77E,154
|
|
|
65
65
|
sqlcg/utils/hashing.py,sha256=H25-sYfxHKb3_IERFnHyAIYNiXN470Oqo5sJT_D3YOA,438
|
|
66
66
|
sqlcg/utils/ignore.py,sha256=6__DfiYgynI2b8nH52O2BzI1EZcZ_LRazhqEOJVGGcE,1955
|
|
67
67
|
sqlcg/utils/logging.py,sha256=u0fCmYsLj9o81vawm3xZTHaw68GQYVm7JxG-gP81u8A,840
|
|
68
|
-
sql_code_graph-1.34.
|
|
69
|
-
sql_code_graph-1.34.
|
|
70
|
-
sql_code_graph-1.34.
|
|
71
|
-
sql_code_graph-1.34.
|
|
68
|
+
sql_code_graph-1.34.4.dist-info/METADATA,sha256=tzuVGUb49jlzRUkFgV28LwMdvIR0h83TsN9zpFHFA0A,17791
|
|
69
|
+
sql_code_graph-1.34.4.dist-info/WHEEL,sha256=mffPy8wBnZQn2VnJUU5jE99KsxaSfiyMHV9Yt0aLVxs,87
|
|
70
|
+
sql_code_graph-1.34.4.dist-info/entry_points.txt,sha256=Wfe49sVzV9p4eVFGo5RxcV-frr3HOP0yzzst8JBxQLQ,46
|
|
71
|
+
sql_code_graph-1.34.4.dist-info/RECORD,,
|
sqlcg/__init__.py
CHANGED
sqlcg/cli/commands/analyze.py
CHANGED
|
@@ -8,7 +8,10 @@ import typer
|
|
|
8
8
|
from rich.console import Console
|
|
9
9
|
from rich.table import Table
|
|
10
10
|
|
|
11
|
-
from sqlcg.core.queries import
|
|
11
|
+
from sqlcg.core.queries import (
|
|
12
|
+
GET_TABLE_EXTERNAL_CONSUMERS_QUERY,
|
|
13
|
+
IMPACT_CONSUMERS_VIA_LINEAGE_QUERY,
|
|
14
|
+
)
|
|
12
15
|
from sqlcg.server.read_client import resolved_repo_root, run_read_routed
|
|
13
16
|
|
|
14
17
|
if TYPE_CHECKING:
|
|
@@ -312,8 +315,16 @@ def impact( # noqa: B008
|
|
|
312
315
|
table: str = typer.Argument(..., help="Table name to analyze"), # noqa: B008
|
|
313
316
|
raw: bool = typer.Option(False, "--raw", help="Disable noise filtering on results"), # noqa: B008
|
|
314
317
|
) -> None:
|
|
315
|
-
"""Show all queries impacted by a table.
|
|
316
|
-
|
|
318
|
+
"""Show all queries impacted by a table.
|
|
319
|
+
|
|
320
|
+
One-hop "who reads this table" — the union of direct SELECTS_FROM consumers
|
|
321
|
+
and consumers that read the table only via COLUMN_LINEAGE / STAR_SOURCE
|
|
322
|
+
(CTE-wrapped / promoted-intermediate reads, e.g. the live DWH node
|
|
323
|
+
``ba.all_rows_in_selection``). Bug #6 fix: brings ``impact`` to the same
|
|
324
|
+
one-hop consumer completeness ``find_table_usages`` already has. Stays
|
|
325
|
+
one-hop (NOT transitive — that is ``downstream``'s job).
|
|
326
|
+
"""
|
|
327
|
+
direct = run_read_routed(
|
|
317
328
|
"SELECT DISTINCT q.id AS id, q.kind AS kind, q.target_table AS target"
|
|
318
329
|
' FROM "SqlTable" t'
|
|
319
330
|
' JOIN "SELECTS_FROM" sf ON sf.dst_key = t.qualified'
|
|
@@ -321,6 +332,17 @@ def impact( # noqa: B008
|
|
|
321
332
|
" WHERE t.qualified = ? LIMIT 100",
|
|
322
333
|
{"t": table},
|
|
323
334
|
)
|
|
335
|
+
# Consumers reachable only via COLUMN_LINEAGE / STAR_SOURCE. Two "?" both
|
|
336
|
+
# bound to the qualified table name: _params_list returns list(values()) in
|
|
337
|
+
# insertion order, so the ordered dict {"t":..., "t2":...} binds correctly.
|
|
338
|
+
via = run_read_routed(
|
|
339
|
+
IMPACT_CONSUMERS_VIA_LINEAGE_QUERY,
|
|
340
|
+
{"t": table, "t2": table},
|
|
341
|
+
)
|
|
342
|
+
seen = {r["id"] for r in direct}
|
|
343
|
+
results = direct + [r for r in via if r["id"] not in seen]
|
|
344
|
+
# Preserve the existing 100-row bound on the merged consumer set.
|
|
345
|
+
results = results[:100]
|
|
324
346
|
if not raw:
|
|
325
347
|
from sqlcg.server.noise_filter import NoiseFilter
|
|
326
348
|
|
sqlcg/core/queries.py
CHANGED
|
@@ -72,3 +72,4 @@ GET_TABLES_EXTERNAL_CONSUMERS_BATCH_QUERY = _Q["GET_TABLES_EXTERNAL_CONSUMERS_BA
|
|
|
72
72
|
COUNT_EXTERNAL_CONSUMERS_QUERY = _Q["COUNT_EXTERNAL_CONSUMERS"]
|
|
73
73
|
GET_TABLE_READS_ADJACENCY_QUERY = _Q["GET_TABLE_READS_ADJACENCY"]
|
|
74
74
|
GET_PRODUCER_TABLES_QUERY = _Q["GET_PRODUCER_TABLES"]
|
|
75
|
+
IMPACT_CONSUMERS_VIA_LINEAGE_QUERY = _Q["IMPACT_CONSUMERS_VIA_LINEAGE"]
|
sqlcg/core/queries.sql
CHANGED
|
@@ -413,3 +413,26 @@ WHERE t.name = ?
|
|
|
413
413
|
SELECT DISTINCT target_table AS producer_table
|
|
414
414
|
FROM "SqlQuery"
|
|
415
415
|
WHERE target_table <> '' AND target_table IS NOT NULL
|
|
416
|
+
|
|
417
|
+
-- IMPACT_CONSUMERS_VIA_LINEAGE
|
|
418
|
+
-- Bug #6: consumers that read a table only via COLUMN_LINEAGE or STAR_SOURCE
|
|
419
|
+
-- (CTE-wrapped / promoted-intermediate reads that emit no top-level SELECTS_FROM
|
|
420
|
+
-- edge, e.g. the live DWH cross-file-promoted node ba.all_rows_in_selection:
|
|
421
|
+
-- kind='table', non-namespaced, 0 SELECTS_FROM in-edges, 55 COLUMN_LINEAGE
|
|
422
|
+
-- out-edges). Returns the same (id, kind, target) shape as the SELECTS_FROM-only
|
|
423
|
+
-- impact query in analyze.py:impact() so the two result sets merge + dedup on q.id.
|
|
424
|
+
-- Both branches key on the QUALIFIED table name (impact() keys on t.qualified):
|
|
425
|
+
-- COLUMN_LINEAGE branch -> src.table_qualified; STAR_SOURCE branch -> ss.dst_key.
|
|
426
|
+
-- The STAR_SOURCE branch closes the STAR-only-consumer gap (FIND_TABLE_USAGES
|
|
427
|
+
-- itself still lacks it — out of scope, separate follow-up).
|
|
428
|
+
-- params: [table_qualified, table_qualified] (same value bound to BOTH ?)
|
|
429
|
+
SELECT DISTINCT q.id AS id, q.kind AS kind, q.target_table AS target
|
|
430
|
+
FROM "SqlColumn" src
|
|
431
|
+
JOIN "COLUMN_LINEAGE" cl ON cl.src_key = src.id
|
|
432
|
+
JOIN "SqlQuery" q ON q.id = cl.query_id
|
|
433
|
+
WHERE src.table_qualified = ?
|
|
434
|
+
UNION
|
|
435
|
+
SELECT DISTINCT q.id AS id, q.kind AS kind, q.target_table AS target
|
|
436
|
+
FROM "STAR_SOURCE" ss
|
|
437
|
+
JOIN "SqlQuery" q ON q.id = ss.src_key
|
|
438
|
+
WHERE ss.dst_key = ?
|
sqlcg/indexer/indexer.py
CHANGED
|
@@ -896,6 +896,20 @@ class Indexer:
|
|
|
896
896
|
if profile:
|
|
897
897
|
_t_catalog_end = time.perf_counter()
|
|
898
898
|
|
|
899
|
+
# Bug #4 (PR-4): re-run the star expansion AFTER the catalog is applied.
|
|
900
|
+
# The first pass at the top of this block expands STAR_SOURCE rows whose
|
|
901
|
+
# leaf table already had HAS_COLUMN rows (parsed DDL). A temp built as
|
|
902
|
+
# `CREATE TEMP t AS SELECT * FROM src` where `src` is catalogued ONLY via
|
|
903
|
+
# information_schema has NO columns at the first pass — its HAS_COLUMN rows
|
|
904
|
+
# arrive with the catalog above — so the temp (and any promote out of it)
|
|
905
|
+
# produced zero edges. The star-expansion SQL is idempotent
|
|
906
|
+
# (INSERT OR REPLACE) and chains both levels (src -> temp -> persisted) in a
|
|
907
|
+
# single pass once the leaf columns exist, so one extra invocation here is
|
|
908
|
+
# the full fix. Only re-run when the catalog actually added columns; a repo
|
|
909
|
+
# with no configured catalog pays nothing.
|
|
910
|
+
if catalog_result.get("columns_loaded", 0) > 0:
|
|
911
|
+
star_edges_expanded = self._expand_star_sources(db)
|
|
912
|
+
|
|
899
913
|
# Post-catalog: resolve JOIN_COL_RESOLVE markers against the full HAS_COLUMN
|
|
900
914
|
# catalog (Bug #5, PR-5 option b). MUST run after the catalog is applied so
|
|
901
915
|
# information_schema columns are present; the suppressed sqlglot mis-bind
|
|
File without changes
|
|
File without changes
|