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.
- {sql_code_graph-1.5.1.dist-info → sql_code_graph-1.33.0.dist-info}/METADATA +60 -12
- sql_code_graph-1.33.0.dist-info/RECORD +71 -0
- sqlcg/__init__.py +1 -1
- sqlcg/cli/commands/analyze.py +426 -21
- sqlcg/cli/commands/catalog.py +313 -0
- sqlcg/cli/commands/db.py +23 -2
- sqlcg/cli/commands/find.py +3 -3
- sqlcg/cli/commands/gain.py +42 -14
- sqlcg/cli/commands/git.py +22 -3
- sqlcg/cli/commands/index.py +70 -33
- sqlcg/cli/commands/install.py +4 -1
- sqlcg/cli/commands/mcp.py +94 -20
- sqlcg/cli/commands/reindex.py +134 -2
- sqlcg/cli/commands/watch.py +10 -2
- sqlcg/cli/coverage.py +966 -0
- sqlcg/cli/main.py +2 -0
- sqlcg/core/config.py +158 -4
- sqlcg/core/duckdb_backend.py +255 -32
- sqlcg/core/freshness.py +46 -2
- sqlcg/core/graph_db.py +49 -7
- sqlcg/core/noise_match.py +125 -0
- sqlcg/core/queries.py +3 -0
- sqlcg/core/queries.sql +62 -3
- sqlcg/core/schema.cypher +2 -1
- sqlcg/core/schema.py +1 -1
- sqlcg/indexer/error_classify.py +47 -1
- sqlcg/indexer/git_delta.py +18 -0
- sqlcg/indexer/indexer.py +681 -30
- sqlcg/indexer/pool.py +12 -2
- sqlcg/indexer/walker.py +2 -2
- sqlcg/lineage/aggregator.py +171 -1
- sqlcg/parsers/ansi_parser.py +352 -2
- sqlcg/parsers/base.py +722 -68
- sqlcg/parsers/snowflake_parser.py +630 -5
- sqlcg/server/models.py +202 -0
- sqlcg/server/noise_filter.py +26 -34
- sqlcg/server/read_client.py +59 -2
- sqlcg/server/selfheal.py +209 -0
- sqlcg/server/server.py +267 -10
- sqlcg/server/skill.py +12 -1
- sqlcg/server/tools.py +1084 -83
- sqlcg/server/writer.py +12 -14
- sqlcg/utils/ignore.py +19 -5
- sql_code_graph-1.5.1.dist-info/RECORD +0 -67
- {sql_code_graph-1.5.1.dist-info → sql_code_graph-1.33.0.dist-info}/WHEEL +0 -0
- {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.
|
|
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
|
-
|
|
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
|
|
197
|
-
>
|
|
198
|
-
>
|
|
199
|
-
>
|
|
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
|
|
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