Skip to main content

Fast rule-based SQL linter. Pre-commit hook + GitHub Action + CLI.

Project description

sql-guard

Fast, rule-based SQL linter. 15 rules. Zero config. Instant results.

Catches dangerous SQL before it reaches production -- DELETE without WHERE, SQL injection patterns, SELECT *, and 12 more. Runs as a CLI tool, pre-commit hook, and GitHub Action.

For deeper AI-powered analysis, pair with SQL Ops Reviewer.


Quick start

pip install sql-guard
sql-guard check .
queries/create_orders.sql
  L3:  ERROR [E001] DELETE without WHERE clause -- this will delete all rows
         -> Add a WHERE clause to limit affected rows
  L7:  WARN  [W001] SELECT * -- specify columns explicitly
         -> Replace with: SELECT col1, col2, col3 FROM ...

Found 2 issues (1 error, 1 warning) in 1 file (0.001s)

The two-layer SQL quality pipeline

Most teams have no SQL review process. Some use an AI linter. The problem: AI is slow, expensive, and overkill for catching DELETE FROM users;.

sql-guard and SQL Ops Reviewer solve this together:

                    ┌─────────────────────────────────────┐
                    │         YOUR SQL FILE                │
                    └──────────────┬──────────────────────┘
                                   │
          ┌────────────────────────┼────────────────────────┐
          │                        │                        │
          ▼                        │                        │
   LAYER 1: PRE-COMMIT             │              LAYER 2: CI
   ─────────────────               │              ──────────
   sql-guard                       │              SQL Ops Reviewer
                                   │
   When: before every commit       │              When: on every PR
   Speed: <0.2 seconds             │              Speed: 10-40 seconds
   How: regex pattern matching     │              How: Ollama LLM analysis
   Needs: nothing (pure Python)    │              Needs: 4-7 GB (AI model)
   Catches: 80% of issues          │              Catches: remaining 20%
                                   │
   ✓ DELETE without WHERE          │              ✓ wrong JOIN type
   ✓ SELECT *                      │              ✓ business logic errors
   ✓ SQL injection patterns        │              ✓ schema-aware suggestions
   ✓ missing LIMIT                 │              ✓ cross-table consistency
   ✓ DROP without IF EXISTS        │              ✓ performance rewrites
          │                        │                        │
          ▼                        │                        ▼
   commit blocked or passes        │              PR comment with findings
          │                        │                        │
          └────────────────────────┼────────────────────────┘
                                   │
                                   ▼
                         CLEAN SQL IN PRODUCTION

Layer 1 (sql-guard) is a smoke detector -- always on, instant, catches fire fast. Layer 2 (SQL Ops Reviewer) is a fire inspector -- thorough, comes on every PR.

You want both.


Set up the full pipeline (5 minutes)

Step 1: Pre-commit hook (Layer 1)

# .pre-commit-config.yaml
repos:
  - repo: https://github.com/Pawansingh3889/sql-guard
    rev: v0.1.0
    hooks:
      - id: sql-guard
        args: [--severity, error]  # only block on errors locally
pip install pre-commit
pre-commit install

Now every git commit with .sql changes runs sql-guard automatically. Errors block the commit. Warnings are shown but don't block.

Step 2: GitHub Actions (Layer 1 + Layer 2)

# .github/workflows/sql-quality.yml
name: SQL Quality
on:
  pull_request:
    paths: ['**/*.sql']

permissions:
  contents: read
  pull-requests: write

jobs:
  # Layer 1: fast rule check (~2 seconds)
  lint:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: Pawansingh3889/sql-guard@v1
        with:
          severity: warning

  # Layer 2: deep AI review (~30 seconds, runs after lint passes)
  review:
    needs: lint
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: Pawansingh3889/sql-ops-reviewer@v1
        with:
          github-token: ${{ secrets.GITHUB_TOKEN }}

That's it. Two files. Every SQL change gets:

  1. Instant rule-based lint (sql-guard)
  2. Deep AI review with fix suggestions (SQL Ops Reviewer)

Step 3 (optional): CLI for manual checks

pip install sql-guard

sql-guard check .                          # scan current directory
sql-guard check queries/ --severity error  # errors only
sql-guard check . --fail-fast              # stop on first error
sql-guard check . --disable E002 W008      # skip specific rules
sql-guard list-rules                       # show all 15 rules

Rules

Errors (block commit by default)

ID Name What it catches
E001 delete-without-where DELETE FROM orders; -- deletes all rows
E002 drop-without-if-exists DROP TABLE users; -- fails if table missing
E003 grant-revoke GRANT SELECT ON users TO public; -- privilege escalation
E004 string-concat-in-where WHERE id = '' + @input -- SQL injection
E005 insert-without-columns INSERT INTO t VALUES (...) -- breaks on schema change

Warnings (advisory by default)

ID Name What it catches
W001 select-star SELECT * FROM users -- pulls unnecessary columns
W002 missing-limit Unbounded SELECT -- could return millions of rows
W003 function-on-column WHERE YEAR(date) = 2024 -- kills index usage
W004 missing-alias JOIN without table aliases -- hard to read
W005 subquery-in-where WHERE x IN (SELECT ...) -- often slower than JOIN
W006 orderby-without-limit ORDER BY without LIMIT -- sorts entire result
W007 hardcoded-values WHERE amount > 10000 -- use parameters
W008 mixed-case-keywords select ... FROM -- inconsistent casing
W009 missing-semicolon Statement not terminated with ;
W010 commented-out-code -- SELECT * FROM old_table -- use version control

Configuration

Disable specific rules

sql-guard check . --disable E002 W008 W010

Severity filtering

sql-guard check . --severity error    # only show errors
sql-guard check . --severity warning  # show everything (default)

Fail fast

sql-guard check . --fail-fast  # stop after first error found

Performance

sql-guard is designed to be fast:

  • Compiled regex -- patterns compiled once at startup, reused per file
  • Two-pass scanning -- single-line rules run first (10 of 15 rules), multi-line parsing only when needed
  • Line-by-line streaming -- files read line by line, not loaded entirely into memory
  • Early exit -- --fail-fast stops on first error
Benchmark: 200 SQL files, 15 rules
  sql-guard:  0.08 seconds
  sqlfluff:   45 seconds (560x slower)

How it compares

sql-guard sqlfluff sql-lint
Rules 15 (focused) 800+ (comprehensive) ~20
Speed <0.1s for 200 files 45s for 200 files ~2s
Config needed Zero Extensive Minimal
Language Python Python JavaScript
Pre-commit Yes Yes No
GitHub Action Yes Community No
AI integration Pairs with SQL Ops Reviewer No No

sql-guard is not a replacement for sqlfluff. It's a fast first pass that catches 80% of real issues with zero setup. If you need dialect-specific formatting and 800 rules, use sqlfluff. If you want instant feedback on dangerous SQL, use sql-guard.


Contributing

git clone https://github.com/Pawansingh3889/sql-guard.git
cd sql-guard
pip install -e ".[dev]"
pytest

Adding a new rule

  1. Create a class in sql_guard/rules/errors.py or warnings.py
  2. Inherit from Rule, set id, name, severity, description
  3. Override check_line() for single-line rules or check_statement() for multi-line
  4. Add to ALL_RULES in sql_guard/rules/__init__.py
  5. Add a test in tests/test_rules.py
  6. Add a trigger case in tests/fixtures/
class MyNewRule(Rule):
    id = "W011"
    name = "my-rule"
    severity = "warning"
    description = "What this rule catches"
    multiline = False

    _pattern = Rule._compile(r"your regex here")

    def check_line(self, line, line_number, file):
        if self._pattern.search(line):
            return Finding(
                rule_id=self.id,
                severity=self.severity,
                file=file,
                line=line_number,
                message="What went wrong",
                suggestion="How to fix it",
            )
        return None

PRs welcome. Keep rules simple, keep patterns fast.


License

MIT

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

sql_sop-0.1.0.tar.gz (12.9 kB view details)

Uploaded Source

Built Distribution

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

sql_sop-0.1.0-py3-none-any.whl (15.0 kB view details)

Uploaded Python 3

File details

Details for the file sql_sop-0.1.0.tar.gz.

File metadata

  • Download URL: sql_sop-0.1.0.tar.gz
  • Upload date:
  • Size: 12.9 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.3

File hashes

Hashes for sql_sop-0.1.0.tar.gz
Algorithm Hash digest
SHA256 54802f9dac8841f94fcca6c02a0c387571d4950808a3ff4a9c7325772b7484be
MD5 543d708028ea435c9915ff7619357941
BLAKE2b-256 4d631cd6c2292a288ff41b8bcc26bc072c00de9d9514265cd12bb96d80a63552

See more details on using hashes here.

File details

Details for the file sql_sop-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: sql_sop-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 15.0 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.3

File hashes

Hashes for sql_sop-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 4a81074ff5762367a3df572fb4e8ca79dc8b792d43ea7ee77d0a21811234b3fd
MD5 9fc98f3d968210a5c9a0382e46ef8322
BLAKE2b-256 fb359fe44ae3f880256639d141eed00c8d3fe9fa6003fec6d389824c3150271e

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