Architecture¶
Yara ORM splits cleanly into a Python model layer and a compiled Rust engine. Python owns the ergonomics — models, querysets, SQL generation — and hands finished SQL plus parameters to Rust, which owns the performance-critical work: pooling, binding, type conversion and row decoding.
┌─────────────────────────────────────────────┐
│ Python (python/yara_orm) ................. │
│ Model / metaclass ....... schema + ORM API│
│ QuerySet ................ lazy SQL builder│
│ fields .................... abstract types│
│ dialects ................ per-DB SQL rules│
└───────────────┬─────────────────────────────┘
│ sql + params (PyO3 / asyncio bridge)
┌───────────────▼─────────────────────────────┐
│ Rust (rust/src) → yara_orm._engine ..... │
│ Engine ...................... async facade│
│ Backend trait .............. pluggable DBs│
│ PgBackend ............... tokio-postgres│
│ SqliteBackend ................. rusqlite│
│ Value .................. Py⇆Rust⇆SQL types│
└─────────────────────────────────────────────┘
Responsibilities¶
- Rust owns pooling (deadpool), parameter binding, type conversion and row decoding. The async bridge (PyO3 + pyo3-async-runtimes on tokio) lets Rust futures await without blocking your asyncio event loop.
- Python owns the model metaclass, descriptors for relations, the lazy queryset/SQL builder, and the per-dialect SQL rules.
Key design points¶
Valueenum is the currency that crosses the boundary — a single tagged type that converts Python scalars ⇄ Rust ⇄ SQL parameters, checking the common scalar types first to minimize per-value work on large binds.- Positional row decoding — SELECTs return column values by index with no per-row column-name allocation and no dict; Python fills model instances using a precomputed decode plan. This is a major part of why reads are fast (see Performance).
- Compiled-SQL + prepared-statement caching — the SELECT column list, single-row INSERT
and a fast-path
get()are built once per model and reused; each pooled connection caches prepared statements. - Metaclass-driven models —
ModelMetabuilds a_meta: MetaInfofor every model (table, fields, primary key, relations, m2m), and installs descriptors for forward/reverse relations and many-to-many managers.
Adding a database¶
Backends plug in at exactly two seams, and the model layer never changes:
- Rust — implement the
Backendtrait (connect, execute, fetch, value conversion) and add a scheme match inrust/src/backend/mod.rs. - Python — add a
BaseDialectsubclass inpython/yara_orm/dialects.pyand register it withregister_dialect(name, DialectClass).
See Backends for how PostgreSQL and SQLite use these seams.
Distribution¶
Yara ORM is built with maturin in a mixed Python/Rust layout
(python-source = "python", native module yara_orm._engine). Wheels are non-abi3 — one
wheel per CPython minor version — published for Linux, macOS and Windows. See
Installation.