sqldoc 1.3.0__tar.gz
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.
- sqldoc-1.3.0/PKG-INFO +325 -0
- sqldoc-1.3.0/README.md +299 -0
- sqldoc-1.3.0/pyproject.toml +44 -0
- sqldoc-1.3.0/setup.cfg +4 -0
- sqldoc-1.3.0/sqldoc/__init__.py +1 -0
- sqldoc-1.3.0/sqldoc/ai.py +311 -0
- sqldoc-1.3.0/sqldoc/cli.py +828 -0
- sqldoc-1.3.0/sqldoc/extractor.py +428 -0
- sqldoc-1.3.0/sqldoc/health.py +273 -0
- sqldoc-1.3.0/sqldoc/health_renderer.py +197 -0
- sqldoc-1.3.0/sqldoc/intel.py +332 -0
- sqldoc-1.3.0/sqldoc/intel_renderer.py +172 -0
- sqldoc-1.3.0/sqldoc/json_renderer.py +45 -0
- sqldoc-1.3.0/sqldoc/markdown_renderer.py +214 -0
- sqldoc-1.3.0/sqldoc/pdf_renderer.py +243 -0
- sqldoc-1.3.0/sqldoc/pii.py +418 -0
- sqldoc-1.3.0/sqldoc/pii_renderer.py +201 -0
- sqldoc-1.3.0/sqldoc/quality.py +210 -0
- sqldoc-1.3.0/sqldoc/quality_renderer.py +196 -0
- sqldoc-1.3.0/sqldoc/renderer.py +974 -0
- sqldoc-1.3.0/sqldoc/sarif.py +86 -0
- sqldoc-1.3.0/sqldoc/snapshot.py +227 -0
- sqldoc-1.3.0/sqldoc.egg-info/PKG-INFO +325 -0
- sqldoc-1.3.0/sqldoc.egg-info/SOURCES.txt +37 -0
- sqldoc-1.3.0/sqldoc.egg-info/dependency_links.txt +1 -0
- sqldoc-1.3.0/sqldoc.egg-info/entry_points.txt +2 -0
- sqldoc-1.3.0/sqldoc.egg-info/requires.txt +12 -0
- sqldoc-1.3.0/sqldoc.egg-info/top_level.txt +1 -0
- sqldoc-1.3.0/tests/test_ai.py +125 -0
- sqldoc-1.3.0/tests/test_cli.py +292 -0
- sqldoc-1.3.0/tests/test_extractor.py +80 -0
- sqldoc-1.3.0/tests/test_health.py +92 -0
- sqldoc-1.3.0/tests/test_intel.py +138 -0
- sqldoc-1.3.0/tests/test_json_renderer.py +50 -0
- sqldoc-1.3.0/tests/test_pii.py +182 -0
- sqldoc-1.3.0/tests/test_quality.py +91 -0
- sqldoc-1.3.0/tests/test_renderers.py +104 -0
- sqldoc-1.3.0/tests/test_sarif.py +46 -0
- sqldoc-1.3.0/tests/test_snapshot.py +85 -0
sqldoc-1.3.0/PKG-INFO
ADDED
|
@@ -0,0 +1,325 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: sqldoc
|
|
3
|
+
Version: 1.3.0
|
|
4
|
+
Summary: SQL Server database documentation generator + PII/compliance scanner, with optional AI-written descriptions.
|
|
5
|
+
Author: htamber
|
|
6
|
+
Project-URL: Homepage, https://github.com/htamber1/sqldoc
|
|
7
|
+
Project-URL: Repository, https://github.com/htamber1/sqldoc
|
|
8
|
+
Keywords: sql-server,documentation,database,schema,er-diagram
|
|
9
|
+
Classifier: Programming Language :: Python :: 3
|
|
10
|
+
Classifier: Environment :: Console
|
|
11
|
+
Classifier: Topic :: Database
|
|
12
|
+
Classifier: Topic :: Documentation
|
|
13
|
+
Requires-Python: >=3.10
|
|
14
|
+
Description-Content-Type: text/markdown
|
|
15
|
+
Requires-Dist: anthropic>=0.109
|
|
16
|
+
Requires-Dist: click>=8.1
|
|
17
|
+
Requires-Dist: Jinja2>=3.1
|
|
18
|
+
Requires-Dist: pyodbc>=5.0
|
|
19
|
+
Requires-Dist: python-dotenv>=1.0
|
|
20
|
+
Requires-Dist: PyYAML>=6.0
|
|
21
|
+
Requires-Dist: fpdf2>=2.8
|
|
22
|
+
Requires-Dist: requests>=2.31
|
|
23
|
+
Provides-Extra: test
|
|
24
|
+
Requires-Dist: pytest>=8; extra == "test"
|
|
25
|
+
Requires-Dist: pypdf>=4; extra == "test"
|
|
26
|
+
|
|
27
|
+
# sqldoc
|
|
28
|
+
|
|
29
|
+
[](https://github.com/htamber1/sqldoc/actions/workflows/ci.yml)
|
|
30
|
+
|
|
31
|
+
Automated documentation generator for **SQL Server** databases.
|
|
32
|
+
|
|
33
|
+
`sqldoc` connects to a SQL Server database, extracts its schema, uses an LLM to
|
|
34
|
+
write plain-English descriptions of every table and column, and renders it all
|
|
35
|
+
into a single self-contained HTML file you can open in any browser or hand to a
|
|
36
|
+
colleague.
|
|
37
|
+
|
|
38
|
+
## 🔒 Privacy guarantee
|
|
39
|
+
|
|
40
|
+
**sqldoc runs on-premise by default and never reads your data.**
|
|
41
|
+
|
|
42
|
+
- **Local by default.** In the default local mode, all AI processing runs against
|
|
43
|
+
a [Ollama](https://ollama.com) instance on your own machine. **No data of any
|
|
44
|
+
kind leaves your network** — not schema, not metadata, nothing.
|
|
45
|
+
- **Row data is never read.** sqldoc queries only SQL Server's `sys.*` catalog
|
|
46
|
+
views. It does not issue a single `SELECT` against your tables, so actual row
|
|
47
|
+
data is never read, stored, or transmitted — in *any* mode.
|
|
48
|
+
- **Cloud is opt-in and explicit.** Sending anything off-network requires
|
|
49
|
+
`--mode cloud`, which prints a warning and requires interactive confirmation
|
|
50
|
+
before making a network call. Even then, only *schema metadata* (table/column
|
|
51
|
+
names, data types, keys, and row counts) is sent to the Anthropic API.
|
|
52
|
+
|
|
53
|
+
This makes sqldoc safe to run against production and regulated databases: the
|
|
54
|
+
worst-case disclosure in cloud mode is a column *name* like `Employee.Salary` —
|
|
55
|
+
never a salary.
|
|
56
|
+
|
|
57
|
+
## What it does
|
|
58
|
+
|
|
59
|
+
1. **Extracts** schema metadata from the `sys.*` catalog views — tables, columns,
|
|
60
|
+
data types, primary/foreign keys, row counts, indexes, views (with their SQL
|
|
61
|
+
definitions), stored procedures (with parameters), and any existing
|
|
62
|
+
`MS_Description` extended properties.
|
|
63
|
+
2. **Enriches** it with AI-generated descriptions: a short summary for each table,
|
|
64
|
+
view, and stored procedure, plus a one-line description for each column that
|
|
65
|
+
doesn't already have one. Enrichment runs concurrently (see `--concurrency`),
|
|
66
|
+
retries transient failures with exponential backoff, and caches descriptions
|
|
67
|
+
so re-running only regenerates objects whose structure changed.
|
|
68
|
+
3. **Renders** a standalone HTML document — grouped by schema, with an ER diagram,
|
|
69
|
+
real-time search, and collapsible view/procedure definitions, styled inline,
|
|
70
|
+
no external assets or dependencies to serve.
|
|
71
|
+
|
|
72
|
+
### HTML output — an IDE-like reading experience
|
|
73
|
+
|
|
74
|
+
The HTML report is a self-contained, dark-themed app (one file, no external
|
|
75
|
+
assets) built for navigating large schemas:
|
|
76
|
+
|
|
77
|
+
- **Sidebar navigation tree** — a collapsible left panel lists every schema and
|
|
78
|
+
its tables/views/procedures (type-tagged); click any item to smooth-scroll to
|
|
79
|
+
its card. The whole sidebar and each schema node collapse.
|
|
80
|
+
- **Interactive ER diagram** — schema-banded left-to-right layout showing only
|
|
81
|
+
FK-connected tables, with arrows colored by schema. Hover a table to spotlight
|
|
82
|
+
its relationships; click it to jump to its documentation card.
|
|
83
|
+
- **Real-time search + type filter** — filter to All / Tables / Views /
|
|
84
|
+
Procedures and search across names and columns at once.
|
|
85
|
+
- **Copy SQL** — one-click copy button on every view and stored-procedure
|
|
86
|
+
definition.
|
|
87
|
+
- **Color-coded row counts** — green pills for populated tables, gray for empty
|
|
88
|
+
ones, with thousands separators.
|
|
89
|
+
|
|
90
|
+
## Requirements
|
|
91
|
+
|
|
92
|
+
- **Python 3.10+**
|
|
93
|
+
- **Microsoft ODBC Driver 18 for SQL Server** installed on the host
|
|
94
|
+
([download](https://learn.microsoft.com/sql/connect/odbc/download-odbc-driver-for-sql-server)).
|
|
95
|
+
This is a system package, not a pip dependency.
|
|
96
|
+
- For **local mode**: a running [Ollama](https://ollama.com) with a model pulled
|
|
97
|
+
(default `llama3.1:8b` — `ollama pull llama3.1:8b`).
|
|
98
|
+
- For **cloud mode**: an Anthropic API key.
|
|
99
|
+
|
|
100
|
+
## Installation
|
|
101
|
+
|
|
102
|
+
```bash
|
|
103
|
+
python -m venv venv
|
|
104
|
+
venv/Scripts/activate # Windows; source venv/bin/activate on macOS/Linux
|
|
105
|
+
pip install . # installs sqldoc and the `sqldoc` command
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
Use `pip install -e .` for an editable/development install. For cloud mode,
|
|
109
|
+
create a `.env` file in the working directory with your API key:
|
|
110
|
+
|
|
111
|
+
```
|
|
112
|
+
ANTHROPIC_API_KEY=sk-ant-...
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
## Usage
|
|
116
|
+
|
|
117
|
+
sqldoc has two subcommands — **`sqldoc doc`** (generate documentation) and
|
|
118
|
+
**`sqldoc scan`** (scan for PII / compliance). For backward compatibility,
|
|
119
|
+
`sqldoc` with options but no subcommand runs `doc`:
|
|
120
|
+
|
|
121
|
+
```bash
|
|
122
|
+
sqldoc doc --server <host> --database <db> --username <user> --password <pw> \
|
|
123
|
+
--output docs.html
|
|
124
|
+
# equivalently: sqldoc --server <host> ... --output docs.html
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
You can also run it as a module without installing (`python -m sqldoc.cli ...`).
|
|
128
|
+
|
|
129
|
+
```bash
|
|
130
|
+
python -m sqldoc.cli --server <host> --database <db> \
|
|
131
|
+
--username <user> --password <pw> --output docs.html
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
### Examples
|
|
135
|
+
|
|
136
|
+
Local mode (default — uses Ollama, nothing leaves your network):
|
|
137
|
+
|
|
138
|
+
```bash
|
|
139
|
+
python -m sqldoc.cli --server localhost --database AdventureWorks2022 \
|
|
140
|
+
--username sa --password '***' --output docs.html
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
Cloud mode (Anthropic — prompts for confirmation before sending metadata):
|
|
144
|
+
|
|
145
|
+
```bash
|
|
146
|
+
python -m sqldoc.cli --server localhost --database AdventureWorks2022 \
|
|
147
|
+
--username sa --password '***' --mode cloud --output docs.html
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
Schema-only, no AI (fastest; nothing leaves the machine):
|
|
151
|
+
|
|
152
|
+
```bash
|
|
153
|
+
python -m sqldoc.cli --server localhost --database AdventureWorks2022 \
|
|
154
|
+
--username sa --password '***' --no-ai --output docs.html
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
Markdown export for a GitHub wiki (format inferred from the `.md` extension):
|
|
158
|
+
|
|
159
|
+
```bash
|
|
160
|
+
python -m sqldoc.cli --server localhost --database AdventureWorks2022 \
|
|
161
|
+
--username sa --password '***' --no-ai --output docs.md
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
PDF export (self-contained, no system libraries — uses `fpdf2`):
|
|
165
|
+
|
|
166
|
+
```bash
|
|
167
|
+
python -m sqldoc.cli --server localhost --database AdventureWorks2022 \
|
|
168
|
+
--username sa --password '***' --no-ai --output docs.pdf
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
### Options
|
|
172
|
+
|
|
173
|
+
| Option | Description |
|
|
174
|
+
| --- | --- |
|
|
175
|
+
| `--server` | SQL Server hostname or IP (**required**) |
|
|
176
|
+
| `--database` | Database name to document (**required**) |
|
|
177
|
+
| `--username` | SQL Server username (**required**) |
|
|
178
|
+
| `--password` | SQL Server password (**required**) |
|
|
179
|
+
| `--connection-string` | Full ODBC connection string — an alternative to the four flags above |
|
|
180
|
+
| `--output` | Output file path (default `documentation.html`) |
|
|
181
|
+
| `--format html\|markdown\|pdf` | Output format. Defaults to the `--output` extension (`.md`→markdown, `.pdf`→pdf), else HTML |
|
|
182
|
+
| `--mode local\|cloud` | AI backend: `local` (Ollama, default) or `cloud` (Anthropic) |
|
|
183
|
+
| `--model` | Model to use. Defaults per mode: `llama3.1:8b` (local), `claude-haiku-4-5` (cloud) |
|
|
184
|
+
| `--schemas` | Comma-separated list of schemas to include (default: all) |
|
|
185
|
+
| `--no-ai` | Skip AI descriptions, output schema only |
|
|
186
|
+
| `--concurrency` | Parallel AI calls during enrichment, 1-64 (default `8`) |
|
|
187
|
+
| `--snapshot` | JSON schema-snapshot path for change detection (default `.sqldoc-snapshots/<database>.json`) |
|
|
188
|
+
| `--no-snapshot` | Disable schema snapshot + change detection for this run |
|
|
189
|
+
| `--cache` | AI description cache path (default `.sqldoc-cache/<database>.json`) |
|
|
190
|
+
| `--no-cache` | Disable the AI description cache (always regenerate) |
|
|
191
|
+
| `--config` | Path to a config file (default `.sqldoc.yml` if present) |
|
|
192
|
+
| `--yes` / `-y` | Skip the cloud-mode confirmation prompt (for non-interactive/CI use) |
|
|
193
|
+
|
|
194
|
+
Instead of the four connection flags you can pass a single
|
|
195
|
+
`--connection-string` (handy for enterprise/Azure connection strings); the
|
|
196
|
+
database name is parsed from it for labeling. Any option (and the connection
|
|
197
|
+
flags) can also be supplied from a config file — see below.
|
|
198
|
+
|
|
199
|
+
```bash
|
|
200
|
+
python -m sqldoc.cli --connection-string \
|
|
201
|
+
"DRIVER={ODBC Driver 18 for SQL Server};SERVER=host;DATABASE=Sales;UID=user;PWD=***;TrustServerCertificate=yes;" \
|
|
202
|
+
--output docs.html
|
|
203
|
+
```
|
|
204
|
+
|
|
205
|
+
## Config file
|
|
206
|
+
|
|
207
|
+
Rather than passing the same flags every run, drop a `.sqldoc.yml` in the working
|
|
208
|
+
directory. Every key maps to the CLI option of the same name; an explicitly
|
|
209
|
+
passed CLI flag always overrides the config, which in turn overrides the built-in
|
|
210
|
+
defaults. Copy [`.sqldoc.example.yml`](.sqldoc.example.yml) to get started:
|
|
211
|
+
|
|
212
|
+
```yaml
|
|
213
|
+
server: localhost
|
|
214
|
+
database: AdventureWorks2022
|
|
215
|
+
username: sa
|
|
216
|
+
mode: local
|
|
217
|
+
concurrency: 8
|
|
218
|
+
# password: better supplied via --password than committed to disk
|
|
219
|
+
```
|
|
220
|
+
|
|
221
|
+
Then simply:
|
|
222
|
+
|
|
223
|
+
```bash
|
|
224
|
+
python -m sqldoc.cli --output docs.html # reads .sqldoc.yml
|
|
225
|
+
python -m sqldoc.cli --mode cloud --output docs.html # override just one setting
|
|
226
|
+
```
|
|
227
|
+
|
|
228
|
+
> `.sqldoc.yml` is **gitignored** because it can contain a database password.
|
|
229
|
+
> Keep secrets out of it (use `--password` or `.env`) if you plan to share it.
|
|
230
|
+
|
|
231
|
+
## Schema change detection
|
|
232
|
+
|
|
233
|
+
Every run writes a JSON snapshot of the schema's *structure* (object names,
|
|
234
|
+
column types, keys, indexes, parameters — never descriptions or row data) to
|
|
235
|
+
`.sqldoc-snapshots/<database>.json`. On the next run, sqldoc diffs the live
|
|
236
|
+
schema against that snapshot and prints what changed, like a git diff for your
|
|
237
|
+
database:
|
|
238
|
+
|
|
239
|
+
```text
|
|
240
|
+
Schema changes since last run (.sqldoc-snapshots/AdventureWorks2022.json):
|
|
241
|
+
+ table Sales.Promotion (6 columns)
|
|
242
|
+
- table dbo.LegacyAudit
|
|
243
|
+
~ table HumanResources.Employee
|
|
244
|
+
+ column PreferredName
|
|
245
|
+
- column MiddleName
|
|
246
|
+
~ column MaritalStatus: type int -> nchar
|
|
247
|
+
+ view Sales.vActiveCustomers
|
|
248
|
+
Schema changes: 1 table(s) added, 1 table(s) removed, 1 table(s) modified, 1 view/proc change(s)
|
|
249
|
+
```
|
|
250
|
+
|
|
251
|
+
New/dropped tables, new/dropped columns, and type/nullability/key changes are
|
|
252
|
+
all reported. The first run just saves a baseline. Disable with `--no-snapshot`,
|
|
253
|
+
or point somewhere specific with `--snapshot path.json`. Snapshots are
|
|
254
|
+
gitignored by default; commit them intentionally if you want cross-commit or CI
|
|
255
|
+
change tracking.
|
|
256
|
+
|
|
257
|
+
## PII / compliance scanning
|
|
258
|
+
|
|
259
|
+
`sqldoc scan` turns sqldoc into a compliance tool. It identifies columns that
|
|
260
|
+
likely hold personal or regulated data and writes a self-contained HTML
|
|
261
|
+
compliance report — a risk dashboard, per-column **HIGH / MEDIUM / LOW** ratings,
|
|
262
|
+
the regulation each finding maps to (**HIPAA / GDPR / PCI-DSS**), recommended
|
|
263
|
+
actions, and a CSV export.
|
|
264
|
+
|
|
265
|
+
```bash
|
|
266
|
+
# Name + data-type analysis only — reads no row data:
|
|
267
|
+
sqldoc scan --server localhost --database AdventureWorks2022 \
|
|
268
|
+
--username sa --password '***' --output pii-report.html
|
|
269
|
+
```
|
|
270
|
+
|
|
271
|
+
Detection matches column names (SSN, national ID, credit card, email, phone,
|
|
272
|
+
date of birth, passport, address, credentials, …) and confirms with the data
|
|
273
|
+
type. Add **`--sample`** to read up to 5 values per flagged column and have the
|
|
274
|
+
AI confirm whether they look like real PII:
|
|
275
|
+
|
|
276
|
+
```bash
|
|
277
|
+
sqldoc scan --server localhost --database AdventureWorks2022 \
|
|
278
|
+
--username sa --password '***' --sample --mode local --output pii-report.html
|
|
279
|
+
```
|
|
280
|
+
|
|
281
|
+
> `--sample` reads real values (which may be actual PII) purely to score
|
|
282
|
+
> confidence — **sampled values are never stored**, only the verdict. It is
|
|
283
|
+
> opt-in and prompts for confirmation; in cloud mode the samples are sent to the
|
|
284
|
+
> API, so prefer `--mode local` for sampling.
|
|
285
|
+
|
|
286
|
+
**PII drift** — each scan snapshots its findings; the next scan reports new,
|
|
287
|
+
resolved, and risk-changed findings (like schema change detection, for regulated
|
|
288
|
+
data). `--baseline PATH` / `--no-baseline`.
|
|
289
|
+
|
|
290
|
+
**CI gating** — `--fail-on high` exits non-zero if any HIGH finding exists;
|
|
291
|
+
`--fail-on new-high` fails only on a *new* HIGH finding vs the baseline. Combine
|
|
292
|
+
with `--sarif` to both gate the build and upload findings.
|
|
293
|
+
|
|
294
|
+
**SARIF export** — add `--sarif findings.sarif` to also emit SARIF 2.1.0 for
|
|
295
|
+
**GitHub Advanced Security** / **Azure DevOps**, so PII findings appear in the
|
|
296
|
+
security dashboard and can gate CI:
|
|
297
|
+
|
|
298
|
+
```bash
|
|
299
|
+
sqldoc scan --server localhost --database AdventureWorks2022 \
|
|
300
|
+
--username sa --password '***' --sarif findings.sarif
|
|
301
|
+
```
|
|
302
|
+
|
|
303
|
+
**Custom patterns** — define org-specific sensitive-column categories in
|
|
304
|
+
`.sqldoc.yml` under `pii_patterns:` (checked before the built-in catalog). See
|
|
305
|
+
[`.sqldoc.example.yml`](.sqldoc.example.yml):
|
|
306
|
+
|
|
307
|
+
```yaml
|
|
308
|
+
pii_patterns:
|
|
309
|
+
- category: "Employee ID"
|
|
310
|
+
patterns: ['\bempid\b', 'employeenumber']
|
|
311
|
+
severity: MEDIUM # HIGH / MEDIUM / LOW
|
|
312
|
+
regulations: ["Internal Policy"]
|
|
313
|
+
action: "Restrict to HR systems."
|
|
314
|
+
types: [varchar, nvarchar] # optional; a matching type confirms
|
|
315
|
+
```
|
|
316
|
+
|
|
317
|
+
## How it works
|
|
318
|
+
|
|
319
|
+
`sqldoc` is a three-stage pipeline, one module per stage:
|
|
320
|
+
|
|
321
|
+
- `sqldoc/extractor.py` — queries the `sys.*` catalog views and builds `Table` /
|
|
322
|
+
`Column` / `Index` / `View` / `StoredProcedure` dataclasses.
|
|
323
|
+
- `sqldoc/ai.py` — fills in descriptions via Ollama (local) or the Anthropic SDK
|
|
324
|
+
(cloud), running the calls concurrently across a thread pool.
|
|
325
|
+
- `sqldoc/renderer.py` — renders the enriched data to a single HTML file.
|
sqldoc-1.3.0/README.md
ADDED
|
@@ -0,0 +1,299 @@
|
|
|
1
|
+
# sqldoc
|
|
2
|
+
|
|
3
|
+
[](https://github.com/htamber1/sqldoc/actions/workflows/ci.yml)
|
|
4
|
+
|
|
5
|
+
Automated documentation generator for **SQL Server** databases.
|
|
6
|
+
|
|
7
|
+
`sqldoc` connects to a SQL Server database, extracts its schema, uses an LLM to
|
|
8
|
+
write plain-English descriptions of every table and column, and renders it all
|
|
9
|
+
into a single self-contained HTML file you can open in any browser or hand to a
|
|
10
|
+
colleague.
|
|
11
|
+
|
|
12
|
+
## 🔒 Privacy guarantee
|
|
13
|
+
|
|
14
|
+
**sqldoc runs on-premise by default and never reads your data.**
|
|
15
|
+
|
|
16
|
+
- **Local by default.** In the default local mode, all AI processing runs against
|
|
17
|
+
a [Ollama](https://ollama.com) instance on your own machine. **No data of any
|
|
18
|
+
kind leaves your network** — not schema, not metadata, nothing.
|
|
19
|
+
- **Row data is never read.** sqldoc queries only SQL Server's `sys.*` catalog
|
|
20
|
+
views. It does not issue a single `SELECT` against your tables, so actual row
|
|
21
|
+
data is never read, stored, or transmitted — in *any* mode.
|
|
22
|
+
- **Cloud is opt-in and explicit.** Sending anything off-network requires
|
|
23
|
+
`--mode cloud`, which prints a warning and requires interactive confirmation
|
|
24
|
+
before making a network call. Even then, only *schema metadata* (table/column
|
|
25
|
+
names, data types, keys, and row counts) is sent to the Anthropic API.
|
|
26
|
+
|
|
27
|
+
This makes sqldoc safe to run against production and regulated databases: the
|
|
28
|
+
worst-case disclosure in cloud mode is a column *name* like `Employee.Salary` —
|
|
29
|
+
never a salary.
|
|
30
|
+
|
|
31
|
+
## What it does
|
|
32
|
+
|
|
33
|
+
1. **Extracts** schema metadata from the `sys.*` catalog views — tables, columns,
|
|
34
|
+
data types, primary/foreign keys, row counts, indexes, views (with their SQL
|
|
35
|
+
definitions), stored procedures (with parameters), and any existing
|
|
36
|
+
`MS_Description` extended properties.
|
|
37
|
+
2. **Enriches** it with AI-generated descriptions: a short summary for each table,
|
|
38
|
+
view, and stored procedure, plus a one-line description for each column that
|
|
39
|
+
doesn't already have one. Enrichment runs concurrently (see `--concurrency`),
|
|
40
|
+
retries transient failures with exponential backoff, and caches descriptions
|
|
41
|
+
so re-running only regenerates objects whose structure changed.
|
|
42
|
+
3. **Renders** a standalone HTML document — grouped by schema, with an ER diagram,
|
|
43
|
+
real-time search, and collapsible view/procedure definitions, styled inline,
|
|
44
|
+
no external assets or dependencies to serve.
|
|
45
|
+
|
|
46
|
+
### HTML output — an IDE-like reading experience
|
|
47
|
+
|
|
48
|
+
The HTML report is a self-contained, dark-themed app (one file, no external
|
|
49
|
+
assets) built for navigating large schemas:
|
|
50
|
+
|
|
51
|
+
- **Sidebar navigation tree** — a collapsible left panel lists every schema and
|
|
52
|
+
its tables/views/procedures (type-tagged); click any item to smooth-scroll to
|
|
53
|
+
its card. The whole sidebar and each schema node collapse.
|
|
54
|
+
- **Interactive ER diagram** — schema-banded left-to-right layout showing only
|
|
55
|
+
FK-connected tables, with arrows colored by schema. Hover a table to spotlight
|
|
56
|
+
its relationships; click it to jump to its documentation card.
|
|
57
|
+
- **Real-time search + type filter** — filter to All / Tables / Views /
|
|
58
|
+
Procedures and search across names and columns at once.
|
|
59
|
+
- **Copy SQL** — one-click copy button on every view and stored-procedure
|
|
60
|
+
definition.
|
|
61
|
+
- **Color-coded row counts** — green pills for populated tables, gray for empty
|
|
62
|
+
ones, with thousands separators.
|
|
63
|
+
|
|
64
|
+
## Requirements
|
|
65
|
+
|
|
66
|
+
- **Python 3.10+**
|
|
67
|
+
- **Microsoft ODBC Driver 18 for SQL Server** installed on the host
|
|
68
|
+
([download](https://learn.microsoft.com/sql/connect/odbc/download-odbc-driver-for-sql-server)).
|
|
69
|
+
This is a system package, not a pip dependency.
|
|
70
|
+
- For **local mode**: a running [Ollama](https://ollama.com) with a model pulled
|
|
71
|
+
(default `llama3.1:8b` — `ollama pull llama3.1:8b`).
|
|
72
|
+
- For **cloud mode**: an Anthropic API key.
|
|
73
|
+
|
|
74
|
+
## Installation
|
|
75
|
+
|
|
76
|
+
```bash
|
|
77
|
+
python -m venv venv
|
|
78
|
+
venv/Scripts/activate # Windows; source venv/bin/activate on macOS/Linux
|
|
79
|
+
pip install . # installs sqldoc and the `sqldoc` command
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
Use `pip install -e .` for an editable/development install. For cloud mode,
|
|
83
|
+
create a `.env` file in the working directory with your API key:
|
|
84
|
+
|
|
85
|
+
```
|
|
86
|
+
ANTHROPIC_API_KEY=sk-ant-...
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
## Usage
|
|
90
|
+
|
|
91
|
+
sqldoc has two subcommands — **`sqldoc doc`** (generate documentation) and
|
|
92
|
+
**`sqldoc scan`** (scan for PII / compliance). For backward compatibility,
|
|
93
|
+
`sqldoc` with options but no subcommand runs `doc`:
|
|
94
|
+
|
|
95
|
+
```bash
|
|
96
|
+
sqldoc doc --server <host> --database <db> --username <user> --password <pw> \
|
|
97
|
+
--output docs.html
|
|
98
|
+
# equivalently: sqldoc --server <host> ... --output docs.html
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
You can also run it as a module without installing (`python -m sqldoc.cli ...`).
|
|
102
|
+
|
|
103
|
+
```bash
|
|
104
|
+
python -m sqldoc.cli --server <host> --database <db> \
|
|
105
|
+
--username <user> --password <pw> --output docs.html
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
### Examples
|
|
109
|
+
|
|
110
|
+
Local mode (default — uses Ollama, nothing leaves your network):
|
|
111
|
+
|
|
112
|
+
```bash
|
|
113
|
+
python -m sqldoc.cli --server localhost --database AdventureWorks2022 \
|
|
114
|
+
--username sa --password '***' --output docs.html
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
Cloud mode (Anthropic — prompts for confirmation before sending metadata):
|
|
118
|
+
|
|
119
|
+
```bash
|
|
120
|
+
python -m sqldoc.cli --server localhost --database AdventureWorks2022 \
|
|
121
|
+
--username sa --password '***' --mode cloud --output docs.html
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
Schema-only, no AI (fastest; nothing leaves the machine):
|
|
125
|
+
|
|
126
|
+
```bash
|
|
127
|
+
python -m sqldoc.cli --server localhost --database AdventureWorks2022 \
|
|
128
|
+
--username sa --password '***' --no-ai --output docs.html
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
Markdown export for a GitHub wiki (format inferred from the `.md` extension):
|
|
132
|
+
|
|
133
|
+
```bash
|
|
134
|
+
python -m sqldoc.cli --server localhost --database AdventureWorks2022 \
|
|
135
|
+
--username sa --password '***' --no-ai --output docs.md
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
PDF export (self-contained, no system libraries — uses `fpdf2`):
|
|
139
|
+
|
|
140
|
+
```bash
|
|
141
|
+
python -m sqldoc.cli --server localhost --database AdventureWorks2022 \
|
|
142
|
+
--username sa --password '***' --no-ai --output docs.pdf
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
### Options
|
|
146
|
+
|
|
147
|
+
| Option | Description |
|
|
148
|
+
| --- | --- |
|
|
149
|
+
| `--server` | SQL Server hostname or IP (**required**) |
|
|
150
|
+
| `--database` | Database name to document (**required**) |
|
|
151
|
+
| `--username` | SQL Server username (**required**) |
|
|
152
|
+
| `--password` | SQL Server password (**required**) |
|
|
153
|
+
| `--connection-string` | Full ODBC connection string — an alternative to the four flags above |
|
|
154
|
+
| `--output` | Output file path (default `documentation.html`) |
|
|
155
|
+
| `--format html\|markdown\|pdf` | Output format. Defaults to the `--output` extension (`.md`→markdown, `.pdf`→pdf), else HTML |
|
|
156
|
+
| `--mode local\|cloud` | AI backend: `local` (Ollama, default) or `cloud` (Anthropic) |
|
|
157
|
+
| `--model` | Model to use. Defaults per mode: `llama3.1:8b` (local), `claude-haiku-4-5` (cloud) |
|
|
158
|
+
| `--schemas` | Comma-separated list of schemas to include (default: all) |
|
|
159
|
+
| `--no-ai` | Skip AI descriptions, output schema only |
|
|
160
|
+
| `--concurrency` | Parallel AI calls during enrichment, 1-64 (default `8`) |
|
|
161
|
+
| `--snapshot` | JSON schema-snapshot path for change detection (default `.sqldoc-snapshots/<database>.json`) |
|
|
162
|
+
| `--no-snapshot` | Disable schema snapshot + change detection for this run |
|
|
163
|
+
| `--cache` | AI description cache path (default `.sqldoc-cache/<database>.json`) |
|
|
164
|
+
| `--no-cache` | Disable the AI description cache (always regenerate) |
|
|
165
|
+
| `--config` | Path to a config file (default `.sqldoc.yml` if present) |
|
|
166
|
+
| `--yes` / `-y` | Skip the cloud-mode confirmation prompt (for non-interactive/CI use) |
|
|
167
|
+
|
|
168
|
+
Instead of the four connection flags you can pass a single
|
|
169
|
+
`--connection-string` (handy for enterprise/Azure connection strings); the
|
|
170
|
+
database name is parsed from it for labeling. Any option (and the connection
|
|
171
|
+
flags) can also be supplied from a config file — see below.
|
|
172
|
+
|
|
173
|
+
```bash
|
|
174
|
+
python -m sqldoc.cli --connection-string \
|
|
175
|
+
"DRIVER={ODBC Driver 18 for SQL Server};SERVER=host;DATABASE=Sales;UID=user;PWD=***;TrustServerCertificate=yes;" \
|
|
176
|
+
--output docs.html
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
## Config file
|
|
180
|
+
|
|
181
|
+
Rather than passing the same flags every run, drop a `.sqldoc.yml` in the working
|
|
182
|
+
directory. Every key maps to the CLI option of the same name; an explicitly
|
|
183
|
+
passed CLI flag always overrides the config, which in turn overrides the built-in
|
|
184
|
+
defaults. Copy [`.sqldoc.example.yml`](.sqldoc.example.yml) to get started:
|
|
185
|
+
|
|
186
|
+
```yaml
|
|
187
|
+
server: localhost
|
|
188
|
+
database: AdventureWorks2022
|
|
189
|
+
username: sa
|
|
190
|
+
mode: local
|
|
191
|
+
concurrency: 8
|
|
192
|
+
# password: better supplied via --password than committed to disk
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
Then simply:
|
|
196
|
+
|
|
197
|
+
```bash
|
|
198
|
+
python -m sqldoc.cli --output docs.html # reads .sqldoc.yml
|
|
199
|
+
python -m sqldoc.cli --mode cloud --output docs.html # override just one setting
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
> `.sqldoc.yml` is **gitignored** because it can contain a database password.
|
|
203
|
+
> Keep secrets out of it (use `--password` or `.env`) if you plan to share it.
|
|
204
|
+
|
|
205
|
+
## Schema change detection
|
|
206
|
+
|
|
207
|
+
Every run writes a JSON snapshot of the schema's *structure* (object names,
|
|
208
|
+
column types, keys, indexes, parameters — never descriptions or row data) to
|
|
209
|
+
`.sqldoc-snapshots/<database>.json`. On the next run, sqldoc diffs the live
|
|
210
|
+
schema against that snapshot and prints what changed, like a git diff for your
|
|
211
|
+
database:
|
|
212
|
+
|
|
213
|
+
```text
|
|
214
|
+
Schema changes since last run (.sqldoc-snapshots/AdventureWorks2022.json):
|
|
215
|
+
+ table Sales.Promotion (6 columns)
|
|
216
|
+
- table dbo.LegacyAudit
|
|
217
|
+
~ table HumanResources.Employee
|
|
218
|
+
+ column PreferredName
|
|
219
|
+
- column MiddleName
|
|
220
|
+
~ column MaritalStatus: type int -> nchar
|
|
221
|
+
+ view Sales.vActiveCustomers
|
|
222
|
+
Schema changes: 1 table(s) added, 1 table(s) removed, 1 table(s) modified, 1 view/proc change(s)
|
|
223
|
+
```
|
|
224
|
+
|
|
225
|
+
New/dropped tables, new/dropped columns, and type/nullability/key changes are
|
|
226
|
+
all reported. The first run just saves a baseline. Disable with `--no-snapshot`,
|
|
227
|
+
or point somewhere specific with `--snapshot path.json`. Snapshots are
|
|
228
|
+
gitignored by default; commit them intentionally if you want cross-commit or CI
|
|
229
|
+
change tracking.
|
|
230
|
+
|
|
231
|
+
## PII / compliance scanning
|
|
232
|
+
|
|
233
|
+
`sqldoc scan` turns sqldoc into a compliance tool. It identifies columns that
|
|
234
|
+
likely hold personal or regulated data and writes a self-contained HTML
|
|
235
|
+
compliance report — a risk dashboard, per-column **HIGH / MEDIUM / LOW** ratings,
|
|
236
|
+
the regulation each finding maps to (**HIPAA / GDPR / PCI-DSS**), recommended
|
|
237
|
+
actions, and a CSV export.
|
|
238
|
+
|
|
239
|
+
```bash
|
|
240
|
+
# Name + data-type analysis only — reads no row data:
|
|
241
|
+
sqldoc scan --server localhost --database AdventureWorks2022 \
|
|
242
|
+
--username sa --password '***' --output pii-report.html
|
|
243
|
+
```
|
|
244
|
+
|
|
245
|
+
Detection matches column names (SSN, national ID, credit card, email, phone,
|
|
246
|
+
date of birth, passport, address, credentials, …) and confirms with the data
|
|
247
|
+
type. Add **`--sample`** to read up to 5 values per flagged column and have the
|
|
248
|
+
AI confirm whether they look like real PII:
|
|
249
|
+
|
|
250
|
+
```bash
|
|
251
|
+
sqldoc scan --server localhost --database AdventureWorks2022 \
|
|
252
|
+
--username sa --password '***' --sample --mode local --output pii-report.html
|
|
253
|
+
```
|
|
254
|
+
|
|
255
|
+
> `--sample` reads real values (which may be actual PII) purely to score
|
|
256
|
+
> confidence — **sampled values are never stored**, only the verdict. It is
|
|
257
|
+
> opt-in and prompts for confirmation; in cloud mode the samples are sent to the
|
|
258
|
+
> API, so prefer `--mode local` for sampling.
|
|
259
|
+
|
|
260
|
+
**PII drift** — each scan snapshots its findings; the next scan reports new,
|
|
261
|
+
resolved, and risk-changed findings (like schema change detection, for regulated
|
|
262
|
+
data). `--baseline PATH` / `--no-baseline`.
|
|
263
|
+
|
|
264
|
+
**CI gating** — `--fail-on high` exits non-zero if any HIGH finding exists;
|
|
265
|
+
`--fail-on new-high` fails only on a *new* HIGH finding vs the baseline. Combine
|
|
266
|
+
with `--sarif` to both gate the build and upload findings.
|
|
267
|
+
|
|
268
|
+
**SARIF export** — add `--sarif findings.sarif` to also emit SARIF 2.1.0 for
|
|
269
|
+
**GitHub Advanced Security** / **Azure DevOps**, so PII findings appear in the
|
|
270
|
+
security dashboard and can gate CI:
|
|
271
|
+
|
|
272
|
+
```bash
|
|
273
|
+
sqldoc scan --server localhost --database AdventureWorks2022 \
|
|
274
|
+
--username sa --password '***' --sarif findings.sarif
|
|
275
|
+
```
|
|
276
|
+
|
|
277
|
+
**Custom patterns** — define org-specific sensitive-column categories in
|
|
278
|
+
`.sqldoc.yml` under `pii_patterns:` (checked before the built-in catalog). See
|
|
279
|
+
[`.sqldoc.example.yml`](.sqldoc.example.yml):
|
|
280
|
+
|
|
281
|
+
```yaml
|
|
282
|
+
pii_patterns:
|
|
283
|
+
- category: "Employee ID"
|
|
284
|
+
patterns: ['\bempid\b', 'employeenumber']
|
|
285
|
+
severity: MEDIUM # HIGH / MEDIUM / LOW
|
|
286
|
+
regulations: ["Internal Policy"]
|
|
287
|
+
action: "Restrict to HR systems."
|
|
288
|
+
types: [varchar, nvarchar] # optional; a matching type confirms
|
|
289
|
+
```
|
|
290
|
+
|
|
291
|
+
## How it works
|
|
292
|
+
|
|
293
|
+
`sqldoc` is a three-stage pipeline, one module per stage:
|
|
294
|
+
|
|
295
|
+
- `sqldoc/extractor.py` — queries the `sys.*` catalog views and builds `Table` /
|
|
296
|
+
`Column` / `Index` / `View` / `StoredProcedure` dataclasses.
|
|
297
|
+
- `sqldoc/ai.py` — fills in descriptions via Ollama (local) or the Anthropic SDK
|
|
298
|
+
(cloud), running the calls concurrently across a thread pool.
|
|
299
|
+
- `sqldoc/renderer.py` — renders the enriched data to a single HTML file.
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=61"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "sqldoc"
|
|
7
|
+
version = "1.3.0"
|
|
8
|
+
description = "SQL Server database documentation generator + PII/compliance scanner, with optional AI-written descriptions."
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
requires-python = ">=3.10"
|
|
11
|
+
authors = [{ name = "htamber" }]
|
|
12
|
+
keywords = ["sql-server", "documentation", "database", "schema", "er-diagram"]
|
|
13
|
+
classifiers = [
|
|
14
|
+
"Programming Language :: Python :: 3",
|
|
15
|
+
"Environment :: Console",
|
|
16
|
+
"Topic :: Database",
|
|
17
|
+
"Topic :: Documentation",
|
|
18
|
+
]
|
|
19
|
+
dependencies = [
|
|
20
|
+
"anthropic>=0.109",
|
|
21
|
+
"click>=8.1",
|
|
22
|
+
"Jinja2>=3.1",
|
|
23
|
+
"pyodbc>=5.0",
|
|
24
|
+
"python-dotenv>=1.0",
|
|
25
|
+
"PyYAML>=6.0",
|
|
26
|
+
"fpdf2>=2.8",
|
|
27
|
+
"requests>=2.31",
|
|
28
|
+
]
|
|
29
|
+
|
|
30
|
+
[project.optional-dependencies]
|
|
31
|
+
test = ["pytest>=8", "pypdf>=4"]
|
|
32
|
+
|
|
33
|
+
[project.urls]
|
|
34
|
+
Homepage = "https://github.com/htamber1/sqldoc"
|
|
35
|
+
Repository = "https://github.com/htamber1/sqldoc"
|
|
36
|
+
|
|
37
|
+
[project.scripts]
|
|
38
|
+
sqldoc = "sqldoc.cli:cli"
|
|
39
|
+
|
|
40
|
+
[tool.setuptools]
|
|
41
|
+
packages = ["sqldoc"]
|
|
42
|
+
|
|
43
|
+
[tool.pytest.ini_options]
|
|
44
|
+
testpaths = ["tests"]
|
sqldoc-1.3.0/setup.cfg
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = "1.3.0"
|