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.