QueryGuard SQL
-
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 id FROM users")
print(result.allowed)
print(result.final_sql)
print(result.detected_tables)
print(result.errors)
Output:
True
"SELECT id 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 *. By default, SELECT * is blocked. |
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 id FROM users
Blocked:
SELECT id 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
By default, SELECT * is blocked.
SELECT * FROM users
To allow it, set:
GuardConfig(
database_type="mysql",
allow_select_star=True,
)
This remains allowed by default because it does not expose all columns:
SELECT COUNT(*) FROM users
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 id 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 id 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.
Metadata
Release files for queryguard-sql 0.1.5
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| queryguard_sql-0.1.5.tar.gz | 14.0 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| queryguard_sql-0.1.5-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 29.5 kB
Release files / queryguard_sql-0.1.5.tar.gz
| Download URL | queryguard_sql-0.1.5.tar.gz |
|---|---|
| Size | 14.0 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
7a76e27413cf152ebdbabc7212d3462925b2c3698d14e46588f497dd9a2d2b7f
|
|
BLAKE2b-256 checksum How to use checksums |
9c7ad763e1a7622590fb8cca30f26ce178b0ec9a14a3894dea59d6cf6039592d
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.12.6
|
Release files / queryguard_sql-0.1.5-py3-none-any.whl
| Download URL | queryguard_sql-0.1.5-py3-none-any.whl |
|---|---|
| Size | 15.5 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
a4b6987a220ca140d9389d5306bd66e5b16cca13072ae911df17880b52af1e10
|
|
BLAKE2b-256 checksum How to use checksums |
c80132aee002e11ea407513641d38411a92b5c0f7bcff5e4cf050eafcffcae84
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.12.6
|