Skip to main content

Deterministic SQL Change Impact Analyzer

Project description

Schema Change Impact Analyzer (SCIA)

Predict schema change risks before they break production.

SCIA analyzes SQL schema changes and tells you:

  • โœ… What will break
  • โœ… How risky it is (LOW/MEDIUM/HIGH)
  • โœ… Why it matters

Works with JSON exports, SQL migration files, or live warehouse connections.


๐Ÿš€ Quick Start

1. Install

pip install scia-core

2. Prepare Schema Files

Create two JSON files representing your schema before and after the change:

before_schema.json โ€” Original schema

[
  {
    "schema_name": "analytics",
    "table_name": "customers",
    "columns": [
      {
        "column_name": "customer_id",
        "data_type": "INT",
        "is_nullable": false,
        "ordinal_position": 1
      },
      {
        "column_name": "email",
        "data_type": "VARCHAR",
        "is_nullable": true,
        "ordinal_position": 2
      }
    ]
  }
]

after_schema.json โ€” Modified schema (e.g., removed email column)

[
  {
    "schema_name": "analytics",
    "table_name": "customers",
    "columns": [
      {
        "column_name": "customer_id",
        "data_type": "INT",
        "is_nullable": false,
        "ordinal_position": 1
      }
    ]
  }
]

3. Run Analysis

JSON Mode (Offline):

scia analyze --before before_schema.json --after after_schema.json --format markdown

SQL Mode (Migration Analysis): Analyze risk of applying a SQL migration to an existing schema (JSON or DB).

# Apply migration.sql to schema in base_schema.json
scia analyze --before base_schema.json --after migration.sql --format markdown

# Specify dialect for SQL parsing (currently only snowflake fully supported)
scia analyze --before base_schema.json --after migration.sql --dialect snowflake --format markdown

Supported ALTER operations: ADD COLUMN, DROP COLUMN, RENAME COLUMN, ALTER COLUMN (TYPE/NULLABILITY).

Database Mode (Live):

scia analyze --before PROD.ANALYTICS --after DEV.ANALYTICS --warehouse snowflake --format markdown

4. Get Risk Assessment

Output (Markdown):

RISK: HIGH
Classification: HIGH
Risk Score: 80

Findings:
1. COLUMN_REMOVED (Severity: HIGH)
   - Column 'email' removed from table 'customers'
   - Evidence: table=customers, column=email

[!NOTE] New to v0.2? Check out the Advanced Usage Guide for SQL migration analysis, live database connections, and dependency analysis features.


๐Ÿ“‹ Common Use Cases

Use Case 1: Column Removal

Scenario: Remove a column you think is unused

scia analyze \
  --before before_schema.json \
  --after after_schema.json \
  --format markdown

Output:

  • โœ… Detects if downstream views depend on this column
  • โœ… Warns about join key changes
  • โœ… Scores risk (HIGH if widely used)

Use Case 2: Type Change

Scenario: Change INT column to STRING

# before_schema.json: "data_type": "INT"
# after_schema.json: "data_type": "VARCHAR"

scia analyze \
  --before before_schema.json \
  --after after_schema.json \
  --format json

Output:

  • โœ… Identifies type incompatibility
  • โœ… Warns about casting issues
  • โœ… Risk: MEDIUM (may break queries)

Use Case 3: Nullability Change

Scenario: Make nullable column NOT NULL

# before_schema.json: "is_nullable": true
# after_schema.json: "is_nullable": false

scia analyze \
  --before before_schema.json \
  --after after_schema.json \
  --format json

Output:

  • โœ… Detects NOT NULL constraint
  • โœ… Warns about NULL values in production
  • โœ… Risk: MEDIUM (data quality issue)

๐Ÿ“Š Output Formats

Markdown (Human-Readable)

scia analyze --before before_schema.json --after after_schema.json --format markdown

Output:

# Risk Assessment: HIGH

## Findings (3)

| Finding Type | Severity | Risk | Evidence |
|---|---|---|---|
| COLUMN_REMOVED | HIGH | 80 | {table: users, column: user_id} |
| COLUMN_TYPE_CHANGED | MEDIUM | 40 | {...} |
| ...| | | |

JSON (Machine-Readable)

scia analyze --before before_schema.json --after after_schema.json --format json

Output:

{
  "risk_score": 120,
  "classification": "HIGH",
  "findings": [
    {
      "finding_type": "COLUMN_REMOVED",
      "severity": "HIGH",
      "base_risk": 80,
      "evidence": {"table": "users", "column": "user_id"},
      "description": "Column 'user_id' removed from table 'users'."
    }
  ]
}

๐Ÿ”ง CLI Reference

Basic Command

scia analyze --before <before.json> --after <after.json> [options]

Options

Option Required Example Description
--before โœ… before.json Original schema (JSON, SQL, or SCHEMA.TABLE)
--after โœ… after.json Modified schema (JSON, SQL, or SCHEMA.TABLE)
--warehouse โŒ snowflake Warehouse type (required for DB mode)
--conn-file โŒ config.yaml Connection config file
--dependency-depth โŒ 3 Max depth for dependency analysis (1-10)
--dialect โŒ snowflake SQL dialect for parsing (snowflake, postgres, mysql, bigquery, databricks, redshift). Default: snowflake. Note: Only snowflake dialect is fully supported currently.
--format โŒ json or markdown Output format (default: json)
--fail-on โŒ HIGH Exit code 1 if risk meets threshold

Exit Codes

  • 0 โ€” Success (risk below threshold or below --fail-on)
  • 1 โ€” Risk matches --fail-on threshold

Example: Use in CI/CD

# Fail CI if HIGH risk detected
scia analyze --before before.json --after after.json --fail-on HIGH

๐Ÿ’ก Examples

Example 1: Safe Column Addition

before.json:

[{"schema_name": "db", "table_name": "orders", "columns": [...]}]

after.json:

[{"schema_name": "db", "table_name": "orders", "columns": [..., {"column_name": "order_notes", "data_type": "VARCHAR", "is_nullable": true, "ordinal_position": 5}]}]

Command:

scia analyze --before before.json --after after.json --format markdown

Result: โœ… RISK: LOW โ€” New nullable column is safe


Example 2: Risky Column Removal

before.json:

[{"schema_name": "db", "table_name": "users", "columns": [{"column_name": "user_id", ...}, ...]}]

after.json:

[{"schema_name": "db", "table_name": "users", "columns": [...]}]  # user_id removed

Command:

scia analyze --before before.json --after after.json --format markdown

Result: โš ๏ธ RISK: HIGH โ€” Primary key removed, will break joins


๐Ÿ“‚ Project Structure

SCIA/
โ”œโ”€โ”€ .github/copilot-instructions.md    (AI agent guidance)
โ”œโ”€โ”€ AI_QUICK_REFERENCE.md              (Quick reference)
โ”œโ”€โ”€ README.md                          (This file)
โ”‚
โ”œโ”€โ”€ docs/                              (Documentation)
โ”‚   โ”œโ”€โ”€ design.md                      (Architecture)
โ”‚   โ”œโ”€โ”€ REQUIREMENTS.md                (Functional spec)
โ”‚   โ””โ”€โ”€ FOLDER_STRUCTURE.md            (Project organization)
โ”‚
โ”œโ”€โ”€ scia/                              (Source code)
โ”‚   โ”œโ”€โ”€ cli/main.py                    (Command-line interface)
โ”‚   โ”œโ”€โ”€ core/                          (Analysis engine)
โ”‚   โ”‚   โ”œโ”€โ”€ diff.py                    (Schema comparison)
โ”‚   โ”‚   โ”œโ”€โ”€ rules.py                   (Risk rules)
โ”‚   โ”‚   โ””โ”€โ”€ risk.py                    (Risk scoring)
โ”‚   โ”œโ”€โ”€ models/                        (Data models)
โ”‚   โ”œโ”€โ”€ output/                        (Renderers)
โ”‚   โ””โ”€โ”€ sql/                           (SQL parsing)
โ”‚
โ”œโ”€โ”€ tests/                             (Tests)
โ”‚   โ”œโ”€โ”€ test_diff.py
โ”‚   โ”œโ”€โ”€ test_rules.py
โ”‚   โ””โ”€โ”€ fixtures/                      (Test data)
โ”‚       โ”œโ”€โ”€ before.json
โ”‚       โ”œโ”€โ”€ after.json
โ”‚       โ””โ”€โ”€ after_medium.json
โ”‚
โ””โ”€โ”€ pyproject.toml                     (Package config)

๐Ÿ—๏ธ What SCIA Does (v0.2)

Detects:

  • Column removal, type changes, nullability changes
  • JOIN key breakage (High Risk)
  • GROUP BY grain changes (Medium Risk)
  • Downstream view breakage (Transitive impact)

Scores risk as:

  • LOW (<30) โ€” Safe to deploy
  • MEDIUM (30-69) โ€” Review recommended
  • HIGH (โ‰ฅ70) โ€” Likely to break systems

Outputs:

  • JSON with impact_detail
  • Markdown with "Downstream Impact" tables

๐Ÿšซ What SCIA Does NOT Do

  • โŒ Modify your schema
  • โŒ Connect to your warehouse (uses JSON exports)
  • โŒ Require a metadata catalog
  • โŒ Lock you into a vendor
  • โŒ Support dbt as a requirement (only optional enrichment)

๐Ÿ› ๏ธ For Developers

Run Tests

pytest tests/

Run a Specific Test

pytest tests/test_diff.py -v

Run with Coverage

pytest tests/ --cov=scia

Develop & Install in Editable Mode

pip install -e .

๐Ÿ“š Documentation


๐ŸŽฏ Risk Scoring

๐ŸŽฏ Risk Scoring

Each change type gets a base risk score:

Change Type Base Risk Why
Column removed 80 Breaks joins, aggregations
Type changed 40 May cause casting errors
Nullability changed 50 Data quality issues
Column added (nullable) 0 Safe โ€” won't break anything

Total risk = Sum of all findings

  • LOW (<30): Safe to deploy
  • MEDIUM (30-69): Review before deploying
  • HIGH (โ‰ฅ70): Likely to break downstream systems

๐Ÿ’ก Tips

Tip 1: Export Snowflake Schema

To get schema JSON from Snowflake:

SELECT 
  table_schema as schema_name,
  table_name,
  column_name,
  data_type,
  is_nullable,
  ordinal_position
FROM information_schema.columns
WHERE table_schema = 'ANALYTICS'
ORDER BY table_name, ordinal_position;

Export as JSON and use with SCIA.

Tip 2: Use in CI/CD

Add to your deployment pipeline:

# GitHub Actions example
- name: Check schema changes
  run: |
    scia analyze --before before.json --after after.json --fail-on HIGH
    # Job fails if HIGH risk detected

Tip 3: Compare Multiple Scenarios

# Scenario 1: Remove column
scia analyze --before base.json --after scenario1.json

# Scenario 2: Change type
scia analyze --before base.json --after scenario2.json

# Pick the safer approach

๐Ÿ”ง Troubleshooting

Connection Issues

Problem: Error: Connection failed to snowflake

Solutions:

  1. Verify config file exists: ls ~/.scia/snowflake.yaml
  2. Check credentials in config file
  3. Ensure account identifier is correct (format: account.region.snowflakecomputing.com)
  4. Use --conn-file to specify custom config location

Example:

# Use custom config file
scia analyze --before PROD.ANALYTICS --after DEV.ANALYTICS \
  --warehouse snowflake --conn-file ~/my-config.yaml

SQL Parsing Errors

Problem: Warning: Failed to parse SQL in migration.sql

Explanation: SCIA supports CREATE TABLE, ALTER ADD/DROP/MODIFY/RENAME COLUMN. Other DDL is ignored.

What Happens: Analysis continues with schema-based rules only (no SQL-specific rules).

Supported Operations:

  • โœ… CREATE TABLE
  • โœ… ALTER TABLE ADD COLUMN
  • โœ… ALTER TABLE DROP COLUMN
  • โœ… ALTER TABLE RENAME COLUMN
  • โœ… ALTER TABLE ALTER COLUMN (type/nullability changes)
  • โŒ Stored procedures, triggers, constraints (ignored)

Dependency Analysis Errors

Problem: Error: max_depth must be 1-10, got 15

Solution: Use --dependency-depth with value between 1 and 10:

scia analyze --before a.json --after b.json --dependency-depth 5

Problem: Error: DB mode requires --warehouse flag

Solution: Add --warehouse when comparing database identifiers:

scia analyze --before PROD.ANALYTICS --after DEV.ANALYTICS --warehouse snowflake

Unsupported Warehouse

Problem: Error: Databricks adapter not yet implemented

Current Support:

  • โœ… Snowflake (fully working)
  • ๐Ÿ—๏ธ Databricks (planned for v0.3)
  • ๐Ÿ—๏ธ PostgreSQL (planned for v0.3)
  • ๐Ÿ—๏ธ Redshift (planned for v0.3)

Workaround: Export your schema to JSON and use JSON mode:

scia analyze --before schema.json --after modified.json

โ“ FAQ

Q: Can SCIA connect to my warehouse directly?
A: Yes! v0.2 supports live connections to Snowflake. Use --warehouse snowflake and configure ~/.scia/snowflake.yaml. See the Advanced Usage Guide for details.

Q: Do I need dbt?
A: No. SCIA works with plain SQL, JSON exports, and warehouse metadata.

Q: What warehouses are supported?
A: v0.2 fully supports Snowflake. Databricks, PostgreSQL, and Redshift are planned for v0.3.

Q: What if my schema has thousands of columns?
A: SCIA analyzes the diff, not absolute size. Performance should be acceptable. Use --dependency-depth 1 for faster analysis.

Q: Can I use this in production?
A: Yes! v0.2 is production-ready. Start with JSON mode for testing, then enable live warehouse connections. See docs/USAGE_V02.md for best practices.


๐Ÿค Contributing

We welcome contributions! See .github/copilot-instructions.md for development guide.

Areas for contribution:

  • Warehouse adapters (BigQuery, Databricks, PostgreSQL)
  • SQL heuristics improvements
  • Real-world incident patterns
  • Testing edge cases

๐Ÿ“„ License

Apache 2.0 โ€” See LICENSE file


๐Ÿš€ What's Next?

  • v0.1 โœ…: Core schema diff, risk scoring, JSON-based analysis
  • v0.2 โœ…: SQL migration parsing, live warehouse connectivity (Snowflake), downstream impact analysis
  • v0.3 ๐Ÿ—๏ธ: Multi-warehouse support (Databricks, PostgreSQL, Redshift), advanced risk policies, incident pattern matching

๐Ÿ’ฌ Questions?

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

scia_core-0.2.0.tar.gz (45.0 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

scia_core-0.2.0-py3-none-any.whl (41.0 kB view details)

Uploaded Python 3

File details

Details for the file scia_core-0.2.0.tar.gz.

File metadata

  • Download URL: scia_core-0.2.0.tar.gz
  • Upload date:
  • Size: 45.0 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.10.12

File hashes

Hashes for scia_core-0.2.0.tar.gz
Algorithm Hash digest
SHA256 625202b859a0b6898317d1bec3efe9f577e4796dc49de86dd97f10c7f87111ec
MD5 3a6266355ee857c9b60241267e349444
BLAKE2b-256 8dc7383edb560c0e99ef4196fe311dd4642cfd0e387770b6a2b62e0dcb5f65c1

See more details on using hashes here.

File details

Details for the file scia_core-0.2.0-py3-none-any.whl.

File metadata

  • Download URL: scia_core-0.2.0-py3-none-any.whl
  • Upload date:
  • Size: 41.0 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.10.12

File hashes

Hashes for scia_core-0.2.0-py3-none-any.whl
Algorithm Hash digest
SHA256 de7aebf7d0a6d1ed1f726f0fe2e5474c1af8f15a13dcea309c810a746869f506
MD5 2dde6c8b0f8c05aa34be4a0fc1051cb8
BLAKE2b-256 ef4f55fbc41787ce908ac33cb536bcdd57b96fc1a04002c74875e83ce583d0a3

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page