Skip to main content

SQL validation and policy enforcement for NL2SQL pipelines

Project description

QueryGuard SQL

QueryGuard SQL banner

PyPI version Python versions License GitHub repository

  • QueryGuard SQL is a small Python library for validating SQL before execution.

  • It is useful for LLM-generated SQL, NL2SQL apps, analytics assistants, and any workflow where SQL should be checked before it reaches the database.

Repository: github.com/WajeehAlamoudi/QueryGuard

Install

pip install queryguard-sql

Import package:

from queryguard import QueryGuard, GuardConfig

Quick Use

from queryguard import QueryGuard, GuardConfig

config = GuardConfig(
    database_type="mysql",
    allowed_tables=["users", "orders"],
    read_only=True,
    max_rows=100,
)

guard = QueryGuard(config)

result = guard.check("SELECT * FROM users")

print(result.allowed)
print(result.final_sql)
print(result.detected_tables)
print(result.errors)

Output:

True
"SELECT * FROM users LIMIT 100"
["users"]
[]

When To Use

Use QueryGuard SQL when you need to:

  • check SQL generated by an LLM
  • enforce read-only SQL
  • allow or block specific tables
  • validate columns using a schema
  • add safe row limits
  • suggest similar table names
  • inspect SQL before database execution

GuardConfig

GuardConfig defines the policy used by QueryGuard.

config = GuardConfig(
    database_type="postgres",
    allowed_tables=["public.users", "public.orders"],
    blocked_tables=["public.payments"],
    read_only=True,
    allow_select_star=False,
    max_rows=500,
    schema={
        "public.users": ["id", "name", "email"],
        "public.orders": ["id", "user_id", "total"],
    },
    suggest_tables=True,
    auto_fix_tables=False,
)

Parameters

Parameter Type Default Description
database_type str required SQL dialect, such as mysql, postgres, sqlite, bigquery, snowflake, tsql.
allowed_tables list[str] | None None Tables that may be queried. None means allow all tables unless blocked.
blocked_tables list[str] [] Tables that must always be blocked. This wins over allowed_tables.
read_only bool True Allows only read-only query types when enabled.
allow_select_star bool False Allows SELECT * when schema rules are active.
max_rows int | None 1000 Adds or lowers row limits. None disables limit rewriting.
schema dict[str, list[str]] | None None Known tables and allowed columns.
suggest_tables bool True Suggests similar known table names.
auto_fix_tables bool False Reserved for table auto-fix behavior. Prefer suggestions for now.

Table Rules

GuardConfig(
    database_type="mysql",
    allowed_tables=["users"],
)

Allowed:

SELECT * FROM users

Blocked:

SELECT * FROM payments

Schema-qualified table names are strict:

allowed_tables=["analytics.users"]

allows:

SELECT id FROM analytics.users

but not:

SELECT id FROM public.users

Schema Rules

If schema is provided, QueryGuard can validate selected columns.

GuardConfig(
    database_type="mysql",
    schema={
        "users": ["id", "name", "email"],
    },
)

Allowed:

SELECT id, name FROM users

Blocked:

SELECT password_hash FROM users

SELECT Star

When schema is provided and allow_select_star=False, this is blocked:

SELECT * FROM users

This remains allowed:

SELECT COUNT(*) FROM users

If no schema is provided, SELECT * is allowed because no column policy is active.

Suggestions

Suggestions use known tables from allowed_tables or schema.

guard = QueryGuard(
    GuardConfig(
        database_type="mysql",
        allowed_tables=["users", "orders"],
        suggest_tables=True,
    )
)

result = guard.check("SELECT * FROM usres")

print(result.suggestions)

Output:

{"usres": ["users"]}

QueryGuard

QueryGuard receives a GuardConfig and uses it to validate SQL.

guard = QueryGuard(config)

Methods

Method Returns Description
check(sql, raise_on_blocked=False) GuardResult Full validation result.
validate(sql) str Returns safe SQL or raises if blocked.
rewrite(sql) str Returns rewritten SQL or raises if blocked.
is_safe(sql) bool Returns True when SQL is allowed.
tables(sql) list[str] Returns detected table names.
check_many(sqls) list[GuardResult] Checks many SQL strings.
explain(sql) str Human-readable explanation.
set_policy(config) None Replaces the current config.

Example

result = guard.check("DELETE FROM users")

print(result.allowed)
print(result.errors)

Output:

False
["DELETE is not allowed in read_only mode"]

GuardResult

guard.check() returns a GuardResult.

result.allowed          # bool
result.original_sql     # str
result.final_sql        # str | None
result.database_type    # str | None
result.detected_tables  # list[str]
result.errors           # list[str]
result.warnings         # list[str]
result.suggestions      # dict[str, list[str]]

Example:

result = guard.check("SELECT * FROM users")

if result.allowed:
    db.execute(result.final_sql)
else:
    print(result.errors)

Supported Dialects

Common supported dialect names:

mysql
mariadb
postgres
postgresql
sqlite
bigquery
snowflake
duckdb
redshift
trino
presto
spark
tsql
sqlserver
mssql
oracle
clickhouse

QueryGuard SQL uses sqlglot for SQL parsing and generation.

Security Note

QueryGuard SQL validates SQL structure and configured policy before execution. It does not replace database permissions, parameterized queries, or least-privilege database users.

For production systems, always keep database-side protections enabled.

License

MIT License.

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

queryguard_sql-0.1.4.tar.gz (13.4 kB view details)

Uploaded Source

Built Distribution

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

queryguard_sql-0.1.4-py3-none-any.whl (15.5 kB view details)

Uploaded Python 3

File details

Details for the file queryguard_sql-0.1.4.tar.gz.

File metadata

  • Download URL: queryguard_sql-0.1.4.tar.gz
  • Upload date:
  • Size: 13.4 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.6

File hashes

Hashes for queryguard_sql-0.1.4.tar.gz
Algorithm Hash digest
SHA256 de0c06351af476f18b1c12d83fb1341e85a6fd3c0c57881982f345a28f3e00a1
MD5 c4e7648a5328e0ddca36c1387376788c
BLAKE2b-256 664bdf77c4bc515a1fa803474992a1daee38574e639e3e3cb0b43024e69a821b

See more details on using hashes here.

File details

Details for the file queryguard_sql-0.1.4-py3-none-any.whl.

File metadata

  • Download URL: queryguard_sql-0.1.4-py3-none-any.whl
  • Upload date:
  • Size: 15.5 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.6

File hashes

Hashes for queryguard_sql-0.1.4-py3-none-any.whl
Algorithm Hash digest
SHA256 bbb37a48dfafd357d14e144e7a306fc30b7397c7661425d44f264ad774ed744d
MD5 3e879b8ec64c7e677b74aec9bfabbd6d
BLAKE2b-256 4d234e32d6d0853a9e07f8de1c62be9e6efd18a9bbb79e5b87331ef0dd79c58f

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