sql-diff-explainer 0.1.4__py3-none-any.whl → 0.1.5__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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: sql-diff-explainer
3
- Version: 0.1.4
3
+ Version: 0.1.5
4
4
  Summary: Explain SQL schema and migration differences
5
5
  Author: zmodz1010
6
6
  License: MIT
@@ -31,6 +31,7 @@ than formatting.
31
31
  - [Directory comparison](#directory-comparison)
32
32
  - [Git-aware pull-request comparison](#git-aware-pull-request-comparison)
33
33
  - [SARIF and HTML reports](#sarif-and-html-reports)
34
+ - [Additional SQL QA analyses](#additional-sql-qa-analyses)
34
35
  - [What it compares](#what-it-compares)
35
36
  - [Use cases](#use-cases)
36
37
  - [Scope and limitations](#scope-and-limitations)
@@ -114,8 +115,15 @@ Try the runnable before/after pairs in [`examples/`](examples/):
114
115
  sql-diff-explainer examples/filter_before.sql examples/filter_after.sql --format json
115
116
  sql-diff-explainer examples/aggregation_before.sql examples/aggregation_after.sql
116
117
  sql-diff-explainer examples/distinct_before.sql examples/distinct_after.sql
118
+ sql-diff-explainer examples/cte_lineage_before.sql examples/cte_lineage_after.sql --format json
119
+ sql-diff-explainer examples/output_contract_before.sql examples/output_contract_after.sql --format json
120
+ sql-diff-explainer --analyze-migration examples/migration.sql --format json
117
121
  ```
118
122
 
123
+ `--analyze-migration FILE` accepts multi-statement migration scripts and emits
124
+ text or JSON. It supports common `ALTER TABLE` column operations; SARIF and
125
+ HTML formats are not available for this separate migration mode.
126
+
119
127
  ### Directory comparison
120
128
 
121
129
  Compare two directory trees recursively. SQL files are paired by their exact
@@ -212,6 +220,63 @@ and file paths. Python callers can use `to_sarif(result)` or
212
220
  `render_html_report(result)` with either `SQLDiffResult` or
213
221
  `SQLDirectoryDiffResult`.
214
222
 
223
+ ## Additional SQL QA analyses
224
+
225
+ Query comparisons include three static QA views in `SQLDiffResult` and JSON
226
+ output:
227
+
228
+ - **CTE lineage** (`lineage`) traces explicit output expressions through
229
+ non-recursive CTE chains to their source columns. Changed sources or
230
+ expressions are also included in `changes` and the risk summary. Lineage
231
+ requires explicit projections, aliases for calculated expressions, and
232
+ direct table/CTE sources; recursive CTEs, wildcard projections, nested
233
+ subqueries, CTE column alias lists, and ambiguous unqualified columns are
234
+ reported as unsupported.
235
+ - **Output-schema contracts** (`schema_contract`) report added, removed,
236
+ renamed, reordered, changed, and supported type-changed output columns.
237
+ Types are inferred only for explicit casts and aliased literals; column types
238
+ that require a database catalog remain unknown. Wildcard projections, unnamed
239
+ expressions, and set operations are reported as unsupported.
240
+ - **Validation suggestions** (`validation_checks`) provide a checklist and,
241
+ when the before/after output columns are compatible, SQL for unmatched-row
242
+ and duplicate checks. The unmatched-row query uses `EXCEPT`; adapt it for
243
+ dialects that use different set-difference syntax. These checks are
244
+ suggestions only: SQL Diff Explainer never connects to a database or
245
+ executes generated SQL.
246
+
247
+ Use the analysis helpers directly when needed:
248
+
249
+ ```python
250
+ from sql_diff_explainer import (
251
+ analyze_migration,
252
+ compare_output_schema,
253
+ trace_cte_lineage,
254
+ )
255
+
256
+ before_sql = """
257
+ WITH totals AS (SELECT customer_id, amount FROM sales)
258
+ SELECT customer_id, amount FROM totals
259
+ """
260
+ after_sql = """
261
+ WITH totals AS (SELECT customer_id, net_amount AS amount FROM sales)
262
+ SELECT customer_id, amount FROM totals
263
+ """
264
+
265
+ lineage = trace_cte_lineage(before_sql, after_sql)
266
+ contract = compare_output_schema(before_sql, after_sql)
267
+ migration = analyze_migration(
268
+ "ALTER TABLE users ADD COLUMN email TEXT;"
269
+ "ALTER TABLE users RENAME COLUMN old_email TO email_address;"
270
+ )
271
+ print(lineage.to_dict(), contract.to_dict(), migration.to_dict())
272
+ ```
273
+
274
+ Migration analysis recognizes `ADD COLUMN`, `DROP COLUMN`, `RENAME COLUMN`,
275
+ `ALTER COLUMN ... TYPE`, and `ALTER COLUMN ... SET/DROP NOT NULL`. Other
276
+ statements and ALTER actions are listed as unsupported rather than being
277
+ silently treated as analyzed. Use `--analyze-migration` for a file or
278
+ `analyze_migration(sql)` from Python.
279
+
215
280
  ## What it compares
216
281
 
217
282
  The analyzer compares supported `SELECT` query features and reports additions,
@@ -225,6 +290,7 @@ removals, or changes with a low, medium, or high risk classification:
225
290
  | Aggregation | Aggregate functions and `GROUP BY` expressions |
226
291
  | Ordering and pagination | `ORDER BY`, `LIMIT`, and `OFFSET` |
227
292
  | Duplicate handling | `DISTINCT` added or removed |
293
+ | Output schema | Result-column additions, removals, renames, ordering, and known type changes |
228
294
 
229
295
  Join or filter changes can alter which rows qualify; grouping or aggregation
230
296
  changes can change a metric's meaning or result grain; and pagination changes
@@ -244,11 +310,14 @@ can affect which rows downstream consumers receive.
244
310
  This is static analysis, not a SQL execution engine or correctness proof. It
245
311
  does not connect to a database, validate schemas or permissions, estimate query
246
312
  plans or cost, inspect table statistics or null rates, or decide whether a
247
- business metric is correct. It compares supported query structure; it does not
248
- analyze a multi-statement migration file or guarantee complete semantic
249
- equivalence across SQL dialects. Risk levels are review signals, not
250
- predictions. Pair the report with warehouse tests, representative row-count
251
- checks, query-plan review, and domain-owner input.
313
+ business metric is correct. Output-column types that require database metadata
314
+ are unknown. CTE lineage and query validation SQL support only the documented
315
+ static cases, and migration analysis recognizes only the listed `ALTER TABLE`
316
+ operations. Generated validation SQL is not executed and may need dialect
317
+ adaptation. The analyzer does not guarantee complete semantic equivalence
318
+ across SQL dialects. Risk levels are review signals, not predictions. Pair the
319
+ report with warehouse tests, representative row-count checks, query-plan
320
+ review, and domain-owner input.
252
321
 
253
322
  ## Development
254
323
 
@@ -0,0 +1,10 @@
1
+ sql_diff_explainer/__init__.py,sha256=aAC9OzousRZ9LohX-3rihFzxbsJIAEL-3u1mYw1mtPk,1479
2
+ sql_diff_explainer/analysis.py,sha256=lpslLkUcszmlyK64-TWwhmuq1ywLpdM13nGdMglIfCU,29734
3
+ sql_diff_explainer/cli.py,sha256=M95AFxK1yb_0DQNb1HLLmczq6DrWKKnS1rHuA6n1xRc,11292
4
+ sql_diff_explainer/core.py,sha256=ZUtSCyocITV6FshwFjUjqu2oVTi6OJq5NsiT6IpSmAs,26854
5
+ sql_diff_explainer/reports.py,sha256=Nz8cttmNJ0B0awIZDaCX5L2qFD4wcEZH36IsHv8_OJI,16573
6
+ sql_diff_explainer-0.1.5.dist-info/METADATA,sha256=ype-3pwxVnNha6LbRuFJpcfKv5dwdgUjKhPaSlJ7zUU,12967
7
+ sql_diff_explainer-0.1.5.dist-info/WHEEL,sha256=W3fkpkm7-wf9vBI5Z-7s0eWkeM-spu78I8Neb98DeEg,87
8
+ sql_diff_explainer-0.1.5.dist-info/entry_points.txt,sha256=Pu2gG46es25JExzGO58plyLEsFedeCUM-TQnUeLpOlI,67
9
+ sql_diff_explainer-0.1.5.dist-info/licenses/LICENSE,sha256=OJ2eEuGmpMxVb7jSmuVgeDcVHCEOMBkZgLgTlnK5mQQ,1087
10
+ sql_diff_explainer-0.1.5.dist-info/RECORD,,
@@ -1,9 +0,0 @@
1
- sql_diff_explainer/__init__.py,sha256=WLNMW_RRKVgtdpjVARZXURnFawVxN5eZn7z-s15tBP4,789
2
- sql_diff_explainer/cli.py,sha256=aOXVY-aivbe62DfERqxyGUNQ9QqadH6Bak3t3tPNn7s,5616
3
- sql_diff_explainer/core.py,sha256=cS-k8mgX_TWKQe1aX2HIZii5ial8DN2XLDU2-wkQjw4,23136
4
- sql_diff_explainer/reports.py,sha256=HrCFzxaxew-J62FQK4TC4mB-cTfEn6dLS8gLlvY24L0,8254
5
- sql_diff_explainer-0.1.4.dist-info/METADATA,sha256=mDI0Vyz1drIxfacjybYpUTHolar00roj1AN1GRE3_d0,9676
6
- sql_diff_explainer-0.1.4.dist-info/WHEEL,sha256=W3fkpkm7-wf9vBI5Z-7s0eWkeM-spu78I8Neb98DeEg,87
7
- sql_diff_explainer-0.1.4.dist-info/entry_points.txt,sha256=Pu2gG46es25JExzGO58plyLEsFedeCUM-TQnUeLpOlI,67
8
- sql_diff_explainer-0.1.4.dist-info/licenses/LICENSE,sha256=OJ2eEuGmpMxVb7jSmuVgeDcVHCEOMBkZgLgTlnK5mQQ,1087
9
- sql_diff_explainer-0.1.4.dist-info/RECORD,,