CRUD and queries
Builder calls only collect values in memory. save(), all(), only(), count(), and exec() are execution boundaries.
let ada = client
.create_user()
.name("Ada")
.email("ada@example.com")
.save()
.await?;
let adults = client
.user()
.age_ge(18)
.order_by_desc(user::fields::CREATED_AT)
.limit(25)
.all()
.await?;
let changed = client
.update_user()
.id_eq(ada.id)
.name("Ada Lovelace")
.save()
.await?;
let removed = client.delete_user().id_eq(ada.id).exec().await?;Filter through relationships without writing a subquery:
let authors = client
.user()
.where_posts(|posts| posts.published_eq(true))
.all()
.await?;For large or narrow reads, use keyset cursors, bounded streams, and typed tuple projections:
let identities = client
.user()
.after_id(last_id)
.limit(100)
.select((user::fields::ID, user::fields::NAME))
.all()
.await?;The setter chain does not send one query per setter. Rent emits one mutation at save(). PostgreSQL and SQLite return the complete entity from that same INSERT ... RETURNING request; MySQL uses the insert identifier and one follow-up read because it lacks equivalent general-purpose returning support.
Generated predicate families include equality, inequality, greater/greater-or-equal, less/less-or-equal, membership (_in and _not_in), and null/not-null, plus _contains, _starts_with, _ends_with, and _contains_insensitive on string fields, depending on the field's type and nullability. Thus normal code is client.document().id_eq(id).version_eq(version). The longer document_predicate::id_eq(id) form remains for expressions that must be stored, reused, or combined dynamically with AND, OR, NOT, JSON operations, or extension operators.