Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Repositories and Queries

Obtain a repository for a registered model:

let users = orm.repo::<User>()?;
let mut user = User {
    id: None,
    email: "ada@example.com".to_owned(),
    display_name: "Ada".to_owned(),
    deleted_at: None,
    version: 0,
};
users.insert(&mut user).await?;
let loaded = users.find_by_id(user.id.expect("generated ID")).await?;

Repository handles retain the ORM connection context. The API includes insert/save/update, find-by-ID, first/all and count queries, soft-delete restoration, and physical delete operations. Model repositories require registration with Orm::with_models.

Model queries

The derive macro generates a ModelField<T> proxy for each field. Comparisons are typed to the field’s Rust type; for an Option<T> field, comparison methods take T. The query builder adds the soft-delete IS NULL condition automatically when the model declares #[orm(soft_delete)].

let statement = users
    .query()
    .filter(User::email.like(String::from("%@example.com")))
    .filter(User::id.gte(1_i64))
    .order_by(User::email.asc())
    .limit(20)
    .offset(0)
    .build()?;
let page: Vec<User> = users.fetch_all(&statement).await?;

Comparisons are eq, ne, gt, gte, lt, lte, and like. Conditions compose with and and or; fields also provide is_null, is_not_null, and is_true. Ordering uses asc() and desc(). A condition’s Rust type does not guarantee that the selected database supports the operator for that column type.

Use Field::new("column") when you need an untyped condition for a known column. select and order_by_name accept string column names. Identifiers are validated when the statement is built; runtime values are bound separately.

Raw SQL

Use Orm::query or query_as for developer-authored SQL outside the repository query builder. Bind runtime values rather than interpolating them:

let matching: Vec<User> = orm
    .query_as("SELECT id, email, display_name, deleted_at, version FROM users WHERE email = ?")
    .bind("ada@example.com")
    .fetch_all()
    .await?;

The query string is a static SQL string, while bind values are supplied separately. The ? placeholder is rewritten for PostgreSQL; PostgreSQL JSON operators are preserved.

For PostgreSQL arrays/ranges, see PostgreSQL Types. For SQLite-specific mappings, see SQLite Types.