Skip to main content

SQLRules

CI PyPI Documentation License

Compile SQLRules-owned Pydantic models into safe SQLAlchemy predicates.

RuleSchema is a Pydantic v2 model. It validates Python data with normal Pydantic APIs and can be used as a FastAPI request or response model. SQLRules accepts only declarations that have a defined SQL meaning. The compiler requires one explicit database backend and returns a complete predicate for matching rows plus a notwhere() complement for rows that fail any rule.

SQLRules performs no database I/O and never changes stored values.

Quick start

Install SQLRules and the dialect provider for your database:

pip install "sqlrules>=2,<3" "sqlrules-postgresql>=2,<3"
from typing import Annotated

from pydantic import ConfigDict, Field as PydanticField, StringConstraints
from sqlalchemy import Column, Integer, MetaData, String, Table

from sqlrules import Compiler, RuleSchema, notwhere, where
from sqlrules_postgresql import PostgresPlugin

users = Table(
    "users",
    MetaData(),
    Column("id", Integer),
    Column("age", Integer),
    Column("name", String),
)


class UserRules(RuleSchema):
    model_config = ConfigDict(strict=False)

    id: int
    age: int | None = PydanticField(ge=18)
    name: Annotated[str, StringConstraints(min_length=2)]


# RuleSchema remains a normal Pydantic model.
request = UserRules.model_validate({"id": "12", "age": "21", "name": "Ada"})
assert request.id == 12

compiler = Compiler(plugins=[PostgresPlugin(server_version=(16, 0))])
compiled = compiler.compile(UserRules, users)

matching = users.select().where(*where(compiled))
failing = users.select().where(*notwhere(compiled))

A lone scalar annotation is a rule too: id: int requires the bound column to contain a compatible integer. Lax mode applies the documented SQLRules conversions; Field(strict=True), a strict Pydantic alias, or ConfigDict(strict=True) requires the database's observable logical type to match. Optional annotations accept SQL NULL.

compiled.predicate is the complete root expression. compiled.explain() shows bindings, coercions, backend assumptions, and diagnostics without executing a database EXPLAIN.

Convert an existing Pydantic model

Unrestricted Pydantic models remain usable in application code. Convert one explicitly before compiling it:

from pydantic import BaseModel, Field
from sqlrules.integrations.pydantic import from_pydantic


class ApiFilter(BaseModel):
    age: int = Field(ge=18)
    name: str


conversion = from_pydantic(ApiFilter, on_incompatible="warn")
RulesModel = conversion.model
report = conversion.report

The converter returns a usable RuleSchema class and a deterministic report. It preserves supported types, constraints, defaults, aliases, and descriptive metadata. It reports Python validators, serializers, computed fields, unsupported metadata, and other behavior it removes or changes. Conversion policies are warn (default), drop (return the report without warnings), and raise (reject any semantic loss). Default factories and Python callbacks are never executed to infer SQL rules.

Supported declarations

The scalar vocabulary is bool, int, float, Decimal, str, date, datetime, time, and UUID, plus homogeneous Literal and Enum domains, and nullable forms. Supported constraints include numeric bounds, multiple_of, string lengths, patterns, literal/enum membership, and the existing dialect markers. Use Pydantic Field, ConfigDict, strict aliases, constrained aliases, and supported Annotated metadata directly.

Unsupported declarations fail when a RuleSchema class is created. Custom validators, serializers, computed fields, arbitrary annotation metadata, string normalization, general unions, nested item validation, and arbitrary Python transforms do not have a 2.0 SQL representation.

The type and backend support matrix lists supported source types, conversions, database versions, collation assumptions, and compile-time capability errors. Unsupported backend behavior is never skipped by a warning or ignore policy.

Dialect providers

The four official packages are versioned with the core package:

pip install "sqlrules-postgresql>=2,<3"
pip install "sqlrules-sqlite>=2,<3"
pip install "sqlrules-mysql>=2,<3"
pip install "sqlrules-mssql>=2,<3"
pip install "sqlrules[dialects]"  # all four

Select exactly one backend provider when compiling. PostgreSQL text-to-scalar coercion requires PostgresPlugin(server_version=(16, 0)); MySQL text-to-int coercion requires MySQL 8.0+; SQL Server safe text conversions require SQL Server 2012+. SQLite text checks use runtime typeof() and need the bundled register_sqlite_functions() helper on each connection when text coercion, patterns, or string length constraints are used. The older register_regexp() helper remains as an alias. Unsupported combinations raise CapabilityError during compilation.

Requires Python 3.10+, Pydantic v2, and SQLAlchemy 2.x.

Metadata

Release files for sqlrules 2.0.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for sqlrules 2.0.0
File Size Uploaded
sqlrules-2.0.0.tar.gz 103.5 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for sqlrules 2.0.0
File Interpreter ABI Platform
sqlrules-2.0.0-py3-none-any.whl Python 3 none any Details

Total release size: 141.5 kB

Release files / sqlrules-2.0.0.tar.gz

Download URL sqlrules-2.0.0.tar.gz
Size 103.5 kB
Tags Source
SHA-256 checksum
How to use checksums
9d8c4ed8babe7ff3a4a1795f6ae1518d19bb97aa947efe3649e194c7b4a5bd32
BLAKE2b-256 checksum
How to use checksums
3f0bbbb4346d9493f5d546e9c3d323bc5f469463b0400fca70599893e7f4e455
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.13.14

Release files / sqlrules-2.0.0-py3-none-any.whl

Download URL sqlrules-2.0.0-py3-none-any.whl
Size 38.0 kB
Tags Python 3
SHA-256 checksum
How to use checksums
35b2037bf97c309a39809688946ad45ed539771ec8bb7d02667976c33f9d3ac6
BLAKE2b-256 checksum
How to use checksums
a1c58ce3784739f0dc177df99492625f58e47aca53cbfea7f5de8390e9904f82
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.13.14

Release history Release notifications | RSS feed

This release

2.0.0 This release

2 release files

1.0.1

2 release files

1.0.0

2 release files

0.4.0

2 release files

0.3.0

2 release files

0.2.0

2 release files

0.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page