sql-code-graph 1.5.1__py3-none-any.whl → 1.33.0__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.
Files changed (46) hide show
  1. {sql_code_graph-1.5.1.dist-info → sql_code_graph-1.33.0.dist-info}/METADATA +60 -12
  2. sql_code_graph-1.33.0.dist-info/RECORD +71 -0
  3. sqlcg/__init__.py +1 -1
  4. sqlcg/cli/commands/analyze.py +426 -21
  5. sqlcg/cli/commands/catalog.py +313 -0
  6. sqlcg/cli/commands/db.py +23 -2
  7. sqlcg/cli/commands/find.py +3 -3
  8. sqlcg/cli/commands/gain.py +42 -14
  9. sqlcg/cli/commands/git.py +22 -3
  10. sqlcg/cli/commands/index.py +70 -33
  11. sqlcg/cli/commands/install.py +4 -1
  12. sqlcg/cli/commands/mcp.py +94 -20
  13. sqlcg/cli/commands/reindex.py +134 -2
  14. sqlcg/cli/commands/watch.py +10 -2
  15. sqlcg/cli/coverage.py +966 -0
  16. sqlcg/cli/main.py +2 -0
  17. sqlcg/core/config.py +158 -4
  18. sqlcg/core/duckdb_backend.py +255 -32
  19. sqlcg/core/freshness.py +46 -2
  20. sqlcg/core/graph_db.py +49 -7
  21. sqlcg/core/noise_match.py +125 -0
  22. sqlcg/core/queries.py +3 -0
  23. sqlcg/core/queries.sql +62 -3
  24. sqlcg/core/schema.cypher +2 -1
  25. sqlcg/core/schema.py +1 -1
  26. sqlcg/indexer/error_classify.py +47 -1
  27. sqlcg/indexer/git_delta.py +18 -0
  28. sqlcg/indexer/indexer.py +681 -30
  29. sqlcg/indexer/pool.py +12 -2
  30. sqlcg/indexer/walker.py +2 -2
  31. sqlcg/lineage/aggregator.py +171 -1
  32. sqlcg/parsers/ansi_parser.py +352 -2
  33. sqlcg/parsers/base.py +722 -68
  34. sqlcg/parsers/snowflake_parser.py +630 -5
  35. sqlcg/server/models.py +202 -0
  36. sqlcg/server/noise_filter.py +26 -34
  37. sqlcg/server/read_client.py +59 -2
  38. sqlcg/server/selfheal.py +209 -0
  39. sqlcg/server/server.py +267 -10
  40. sqlcg/server/skill.py +12 -1
  41. sqlcg/server/tools.py +1084 -83
  42. sqlcg/server/writer.py +12 -14
  43. sqlcg/utils/ignore.py +19 -5
  44. sql_code_graph-1.5.1.dist-info/RECORD +0 -67
  45. {sql_code_graph-1.5.1.dist-info → sql_code_graph-1.33.0.dist-info}/WHEEL +0 -0
  46. {sql_code_graph-1.5.1.dist-info → sql_code_graph-1.33.0.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.5.1
3
+ Version: 1.33.0
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
@@ -90,8 +90,11 @@ for that project.
90
90
  ## Full setup (recommended)
91
91
 
92
92
  ```bash
93
- # 1. Install
94
- pip install sql-code-graph
93
+ # 1. Install (this project uses uv — never pip)
94
+ uv tool install sql-code-graph # global tool (recommended)
95
+ # — or, from a source checkout:
96
+ # git clone https://github.com/Warhorze/sql-code-graph
97
+ # cd sql-code-graph && uv sync # then run via `uv run sqlcg …`
95
98
 
96
99
  # 2. Register with Claude Code (writes ~/.claude.json)
97
100
  sqlcg install
@@ -193,10 +196,51 @@ sqlcg index . --dialect snowflake # index DDL + ETLs together
193
196
  After indexing, `sqlcg db info` shows non-zero `STAR_EXPANSION lineage edges`, and
194
197
  `trace_column_lineage` returns results for queries that previously returned empty.
195
198
 
196
- > **Note:** earlier versions accepted an exported `INFORMATION_SCHEMA` CSV (`sqlcg
197
- > load-schema`). That path was **removed** profiling showed it added zero lineage
198
- > edges over DDL + cross-file CTAS resolution on a real warehouse. DDL is now the
199
- > single source of column truth; no CSV is needed or accepted.
199
+ > **Note:** an earlier `sqlcg load-schema` command was removed in 2026-05 — it fed
200
+ > column names into the parse/qualify loop (hot path) and measured zero edge delta on
201
+ > a real warehouse. The new `sqlcg catalog load` (see below) is different: it writes
202
+ > `HAS_COLUMN` rows **after** indexing and never touches the parser.
203
+
204
+ ## INFORMATION_SCHEMA catalog enrichment
205
+
206
+ If your warehouse DDL lives in XML changelogs (Liquibase, Flyway) or other non-SQL
207
+ formats that sqlcg cannot parse, you can supply an `INFORMATION_SCHEMA.COLUMNS` export
208
+ to enrich edge health without re-parsing anything.
209
+
210
+ ```bash
211
+ # Export from Snowflake (or any SQL client):
212
+ # SELECT table_catalog, table_schema, table_name, column_name, ordinal_position, data_type
213
+ # FROM information_schema.columns
214
+ # WHERE table_schema NOT IN ('INFORMATION_SCHEMA')
215
+ # ORDER BY table_schema, table_name, ordinal_position;
216
+ # → save as columns.csv
217
+
218
+ sqlcg catalog load columns.csv
219
+ sqlcg gain # check the delta
220
+ ```
221
+
222
+ **What it does:**
223
+ - Reads `table_catalog` (optional), `table_schema`, `table_name`, `column_name` columns.
224
+ - Delimiter sniffed (`,` or `;`); extra columns ignored; names case-folded to lowercase.
225
+ - Creates `SqlColumn` nodes and `HAS_COLUMN(source='information_schema')` edges.
226
+ - DDL-sourced rows are never overwritten (`ddl > information_schema > usage` precedence).
227
+ - Idempotent — running it twice produces no row growth.
228
+ - Catalog-sourced rows survive per-file reindex (`sqlcg reindex`).
229
+
230
+ **Persisting across full rebuilds:** add to `.sqlcg.toml`:
231
+
232
+ ```toml
233
+ [sqlcg.catalog]
234
+ path = "/path/to/columns.csv"
235
+ ```
236
+
237
+ With this set, `sqlcg index` automatically re-applies the catalog at the end of each
238
+ full rebuild. If the file is missing, indexing succeeds with a warning.
239
+
240
+ **What it does not do:**
241
+ - It does not feed column names into the parse/qualify hot path — `SELECT *` expansion
242
+ uses only DDL files and cross-file CTAS bodies (unchanged).
243
+ - It does not create new lineage edges — it only validates / invalidates existing ones.
200
244
 
201
245
  ## MCP tools reference
202
246
 
@@ -207,16 +251,18 @@ After indexing, `sqlcg db info` shows non-zero `STAR_EXPANSION lineage edges`, a
207
251
  | `trace_column_lineage(table_col)` | Trace a column's value upstream to its sources |
208
252
  | `get_upstream_dependencies(table_col)` | Full upstream dependency chain |
209
253
  | `get_downstream_dependencies(table_col)` | Full downstream dependency chain |
210
- | `find_table_usages(table_name)` | Find all queries that read a table |
254
+ | `find_table_usages(table_name)` | Find all queries that read a table (3-signal: direct SELECT, SELECT *, or column-lineage CTE read) |
211
255
  | `find_definition(table_qualified)` | Find where a table/view is defined |
212
256
  | **Change impact** | |
213
- | `get_change_scope(table_qualified)` | Blast radius of changing a table (impact + risk) |
214
- | `diff_impact(changed_files)` | What a set of changed files affects downstream |
257
+ | `get_change_scope(table_qualified)` | Blast radius of changing a table (impact + risk); `gating_join_tables` field adds row-reachability supplement (see caveats) |
258
+ | `diff_impact(changed_files)` | What a set of changed files affects downstream; `gating_join_tables` field adds row-reachability supplement (see caveats) |
215
259
  | `get_backfill_order(table_qualified)` | Topological rebuild/backfill order |
216
260
  | `scope_change(target)` | Synthesised change-scope summary for a target |
261
+ | `get_empty_propagation(tables)` | Downstream blast radius when named table(s) are empty — two views: value-derivation (primary) + row-reachability (supplement) |
262
+ | `get_pr_impact(base_ref)` | Detect producers a PR dropped + their blast radius; code-regression detection, not runtime monitoring |
217
263
  | **Analysis** | |
218
264
  | `get_hub_ranking(k)` | Top-k tables by downstream dependent count (hub/centrality) |
219
- | `analyze_unused()` | Tables with no within-corpus consumers (dead-code candidates, heuristic) |
265
+ | `analyze_unused()` | Tables with no within-corpus consumers (dead-code candidates, heuristic); uses 3-signal "used" definition — direct SELECT, SELECT *, or CTE-derived column read |
220
266
  | **Search & meta** | |
221
267
  | `search_sql_pattern(query)` | Full-text search across indexed SQL |
222
268
  | `list_dialects_and_repos()` | List indexed repos and dialects (catalogue) |
@@ -252,7 +298,9 @@ sqlcg index <path> --dialect auto # read dialect from .sqlcg.toml
252
298
  sqlcg index <path> --profile # index + print per-stage timing and slowest files
253
299
  sqlcg index <path> --include-working-tree # also index uncommitted changes (marks graph dirty)
254
300
  sqlcg reindex <path> --from <sha> --to <sha> # incremental resync of only changed files
255
- sqlcg analyze unused # tables with no query references
301
+ sqlcg analyze unused # tables with no within-corpus consumers (3-signal: direct SELECT, SELECT *, or CTE-derived column read)
302
+ sqlcg analyze empty-impact <table>... # downstream blast radius when named table(s) are empty (two views)
303
+ sqlcg analyze pr-impact --base <ref> # detect producers a PR dropped + their blast radius (code-regression detection)
256
304
  sqlcg analyze upstream/downstream # trace lineage from the CLI
257
305
  sqlcg find table/column/pattern # search the graph
258
306
  sqlcg watch <path> # watch for file changes
@@ -0,0 +1,71 @@
1
+ sqlcg/__init__.py,sha256=eUMoB2vKl2ho6_w-fT0h0Atb36ONmYWYv3oayOjVeIs,116
2
+ sqlcg/__main__.py,sha256=1YoFLcqEgTwYq1J3TbUwpkdG0zeeLIf2fJvwWI-CLFU,109
3
+ sqlcg/cli/__init__.py,sha256=W8fD0LpMq2xm_5WKGNMvJh2WBL1ho5E8hUeAqXQYT1g,28
4
+ sqlcg/cli/coverage.py,sha256=Xm9ITzZDHv2mJ70Q5jCacVuhDStVrE3gq12_-Ypvtd8,43823
5
+ sqlcg/cli/main.py,sha256=tlFvl-l9hWfZBP9dO2svZXvLDbh7T5731CFyctuVqDI,2485
6
+ sqlcg/cli/commands/__init__.py,sha256=oSHtr6VD-jNubOjuCQyZj2tBppjMEpQDh-IGQ8of9eA,30
7
+ sqlcg/cli/commands/analyze.py,sha256=XMax3uHyNEe8SIMEhiLBdtbQb8QUwncoQKTB2LIT3Vg,30000
8
+ sqlcg/cli/commands/catalog.py,sha256=xCIWp_9xcDPHIMUB0xrZR3-G0WMvKbfq4yMwe2sDT2g,12670
9
+ sqlcg/cli/commands/db.py,sha256=QEDPs0boeFe8ETE8BWe7I2JLSXROUI571SHXMTUqxh8,7982
10
+ sqlcg/cli/commands/find.py,sha256=uMdG08bU-AvB9RqsTKPfdVnJet7b3Ebj0xbsjqTclYA,2678
11
+ sqlcg/cli/commands/gain.py,sha256=PQCWjlisjUY4Gz_MkppXPI1_w8xsB4DPlN7uAxx0GvY,10149
12
+ sqlcg/cli/commands/git.py,sha256=OCqq5ApKgOyYouC_olJoyugaS2jsvEkq5MEcmFAXXEo,7255
13
+ sqlcg/cli/commands/index.py,sha256=KGy0vPlvFcMetBjT5wIEvEcy9MEcLt7lhNaKfRWUkgU,19502
14
+ sqlcg/cli/commands/install.py,sha256=4aZzvDNdl2Ea5v-ufR8Oj1qq30oGS_9jX17etYpoan8,10148
15
+ sqlcg/cli/commands/mcp.py,sha256=drh5udcroZFddmJAG3q9JWxekDqTO9H4xC-oIqiis-Y,14871
16
+ sqlcg/cli/commands/reindex.py,sha256=pNBonQYUhHwfJFWJjWq_uQorMmTcJ9HRT1MNH6v_YYo,19357
17
+ sqlcg/cli/commands/report.py,sha256=JU0qjyMxwOukE7bN3XvvIzOI7zMg_Gsnvk_8F6pKNpA,4915
18
+ sqlcg/cli/commands/uninstall.py,sha256=WrA1FnINxnd6mmE4-_QBK0aHBnibstJeAT8swnQKG4M,8962
19
+ sqlcg/cli/commands/watch.py,sha256=_OvUQ4m_Pp2lAzI_f9UX2Gwb56zbsaSC4Tj8h51uciA,2806
20
+ sqlcg/core/__init__.py,sha256=dXvLWpbQ72f5CM6sKSvBDnEGqGuIZaN5MmHyD8Vf1aA,154
21
+ sqlcg/core/config.py,sha256=QxhIiF_let_ablMa-WttGbcAlCCDIpT4lR4tUVymIEI,19091
22
+ sqlcg/core/duckdb_backend.py,sha256=Yc1TBYvR7Yc3jaz4cZ6VseFEhTemm9rBe4jAGK0Fx0s,40112
23
+ sqlcg/core/freshness.py,sha256=Cm-w7jACPrt8TIstZpCzDJpYsHCiBo63ni5js8wCGbg,6248
24
+ sqlcg/core/graph_db.py,sha256=QLkJk1bDA9s00QQlivBBfoUl6GSZiVSC6_9kY-IxsuY,10255
25
+ sqlcg/core/jobs.py,sha256=Je-fCdSKRgiSsv1W8SgNAlp36a7t7-pJZ-qKPbka9OE,3298
26
+ sqlcg/core/noise_match.py,sha256=8jxMBum0HB7wnVyS8hHaklO279QOSNKDmPtv-0RujD8,4781
27
+ sqlcg/core/queries.cypher,sha256=cvPOVe5GUOzJN4bxUvDxNI--xIIP8gm42TR-gUnea4U,4685
28
+ sqlcg/core/queries.py,sha256=LgJcxMfienHD-ug2tAKMfcpfFrhtJvVXCsxrco9jAb0,3513
29
+ sqlcg/core/queries.sql,sha256=EDSnJKz6gnWWYTlXBmyGmNYNhuX5V11CTP9IWVs0YlU,13695
30
+ sqlcg/core/schema.cypher,sha256=StaJqIzOLwF2X9HYvfHSdGiYGFb_YkiHubPrTu-Qpmg,2898
31
+ sqlcg/core/schema.py,sha256=6KrMzbfceM4k0p2i7hPz8eNBco5_1eGXwdGTd3VUaok,1477
32
+ sqlcg/indexer/__init__.py,sha256=Wh20Unz2OHs1oIyWLrpurPAasF0BET2g4iXtNk7mh2U,56
33
+ sqlcg/indexer/dbt_adapter.py,sha256=EB5x1WU5Z9d-I97ADDj88S_hG1C4z4nbrv8JUCzXfy8,686
34
+ sqlcg/indexer/error_classify.py,sha256=-sp8cRmuOBHu_CxnCtaXf34YxHFYwIFNjIrn4LaEv6M,7142
35
+ sqlcg/indexer/git_delta.py,sha256=zYdH5q-jV7w_ne8Oxdywsy0N3rwUjpd5RjEDurlrMSA,5026
36
+ sqlcg/indexer/indexer.py,sha256=qUTMkK3P3eCghjGzmM9QwzfUL23FOJ5siQ5HS_1l4nk,98037
37
+ sqlcg/indexer/pool.py,sha256=iMmCQtpDRKBTQBep2_EUq9THcsE18Zgk0hdaFB_CwiA,19006
38
+ sqlcg/indexer/walker.py,sha256=Cft6JiJtdBFy0HR6L9pJdr5Fg0eRR3XBW1OMtM2apto,1947
39
+ sqlcg/indexer/watcher.py,sha256=mJQq1LASRLKKwhz0WhCUWPLLqyPR2_-FD_8efYU6gE8,8442
40
+ sqlcg/lineage/__init__.py,sha256=Da1DlYwtK13WHv_RnHjAtNkHTOuFbhxqCjT1Le7DsWM,46
41
+ sqlcg/lineage/aggregator.py,sha256=zR9h0I14GtPQYT9bTs_UbVyjaUVgpEhAynKBNc4VPnA,13325
42
+ sqlcg/lineage/schema_resolver.py,sha256=iXt6LYF6UVWsGUpcfbmjmGn9wCgXl721lTGf_8AaWcc,7320
43
+ sqlcg/metrics/__init__.py,sha256=hLJ6wm4St8qqYwKh3o9QG7lcEt1BEYM31ccqO9tGpIg,133
44
+ sqlcg/metrics/store.py,sha256=KuDtxvyAgug9_KtiSCpvgKM2VZM7VSaI3D11uMLjJJk,10604
45
+ sqlcg/parsers/__init__.py,sha256=AamA8wBbDZV9_zEtZCI4Hyen5UAVKHmBwjTghTt2PZE,785
46
+ sqlcg/parsers/ansi_parser.py,sha256=KLbNapfPU20eWK-pullEFvhP78aroU9qlg2aj8ZcESo,37926
47
+ sqlcg/parsers/base.py,sha256=D9FwirsitJEGoYNUvclWVbeMgvkePr4Frqbs3G29XEg,92871
48
+ sqlcg/parsers/bigquery_parser.py,sha256=mOnWTfXB_Dp4JwFE1PVYOB6CDPf5nYE0Dea8kJCl9uQ,2827
49
+ sqlcg/parsers/postgres_parser.py,sha256=lYfUpQY6j4Qm7ndXBtXbgPoGzYqYddWt5YeFnWKdA6I,946
50
+ sqlcg/parsers/registry.py,sha256=LXy1F6rqQI6VdxpRvZg_tNpoEucW3mXZHYBMlMONbX4,1496
51
+ sqlcg/parsers/snowflake_parser.py,sha256=cv7bzBm6Wmwa8uY41Y59ebfFjnP1Gk0Sjp2KN_QBGD8,47542
52
+ sqlcg/parsers/tsql_parser.py,sha256=RRj1pACtAk2tLTDaFWRYF67a0IDvaf5A1YQXWIz0bpQ,956
53
+ sqlcg/server/__init__.py,sha256=n4wuNE7xyJIJxJZBtmtdccCMQfvTdF-IqIaZVbC4FC4,35
54
+ sqlcg/server/control.py,sha256=qUcztb_aDhL-_X_Nq4q6uGx17cUlbLnI6vUpoZsEjbo,4506
55
+ sqlcg/server/exceptions.py,sha256=EONw34icOByCTpppSQrvQBW6asc4hfqaGDCAFjv96II,469
56
+ sqlcg/server/models.py,sha256=vp9oG81V6cSkbkbH8HZ8ZrEGWzDLapgojQHhk9niC0c,29194
57
+ sqlcg/server/noise_filter.py,sha256=gTuiRKVFAizf_F4MODY4T34IQgzoxiDb-ilaTgg7Voo,6171
58
+ sqlcg/server/read_client.py,sha256=ReeDHCff1G-WQzCH3Ow_hAUSEULRGq1lBr2AIOqur5c,10467
59
+ sqlcg/server/selfheal.py,sha256=eL6D81N4tz-Feuw1uh3VzrUkW5qfbhLuLtyMqIiib3A,8299
60
+ sqlcg/server/server.py,sha256=GUo6vVR2z80zH3geCanm1Eg-B4miUXmv78oLVBD4dlA,37407
61
+ sqlcg/server/skill.py,sha256=TMCSn3kBYS7GzGz3L50ZwvuBUCD4otS0FSsPGK8juWs,14434
62
+ sqlcg/server/tools.py,sha256=PhOvHotGJnTlcRWy_w8IMpIrJ4DSNLhi1vRzQW27aSg,121092
63
+ sqlcg/server/writer.py,sha256=wXaXoL0adyDqrYxmnWb8mWXOmUQJxtLcPImeDPyxVes,18284
64
+ sqlcg/utils/__init__.py,sha256=--iqt5ThTXmT8Wz7da8hs3n0zDfYPl8P-z5OgRJ_77E,154
65
+ sqlcg/utils/hashing.py,sha256=H25-sYfxHKb3_IERFnHyAIYNiXN470Oqo5sJT_D3YOA,438
66
+ sqlcg/utils/ignore.py,sha256=6__DfiYgynI2b8nH52O2BzI1EZcZ_LRazhqEOJVGGcE,1955
67
+ sqlcg/utils/logging.py,sha256=u0fCmYsLj9o81vawm3xZTHaw68GQYVm7JxG-gP81u8A,840
68
+ sql_code_graph-1.33.0.dist-info/METADATA,sha256=zEAtNat6hBOJ-K6FUzyTtc_qrR9waQWGdV8d_1meoQo,17791
69
+ sql_code_graph-1.33.0.dist-info/WHEEL,sha256=mffPy8wBnZQn2VnJUU5jE99KsxaSfiyMHV9Yt0aLVxs,87
70
+ sql_code_graph-1.33.0.dist-info/entry_points.txt,sha256=Wfe49sVzV9p4eVFGo5RxcV-frr3HOP0yzzst8JBxQLQ,46
71
+ sql_code_graph-1.33.0.dist-info/RECORD,,
sqlcg/__init__.py CHANGED
@@ -1,5 +1,5 @@
1
1
  """SQL Code Graph - SQL lineage and dependency analysis tool."""
2
2
 
3
- __version__ = "1.5.1"
3
+ __version__ = "1.33.0"
4
4
 
5
5
  __all__ = ["__version__"]