Skip to main content

QuerySet

Struct QuerySet 

Source
pub struct QuerySet<T> { /* private fields */ }
Expand description

A lazy, chainable SQL query.

Carries a sea-query SelectStatement plus pool-resolution state. Nothing is sent to the database until a terminal method is awaited. Cloning is cheap (the SelectStatement clones in O(query size)).

Implementations§

Source§

impl<T> QuerySet<T>

Source

pub fn with_deleted(self) -> Self

Feature #72 — include soft-deleted rows in this query. Skips the auto WHERE deleted_at IS NULL injection. No-op on models that aren’t tagged #[umbral(soft_delete)].

Source

pub fn only_deleted(self) -> Self

Feature #72 — only soft-deleted rows. Useful for admin trash views and undelete workflows. No-op on models that aren’t tagged #[umbral(soft_delete)].

Source

pub fn hard_delete(self) -> Self

Feature #72 — force a real DELETE for the next .delete() terminal call. Soft-delete models normally rewrite delete() as UPDATE ... SET deleted_at = NOW(); .hard_delete() bypasses that for GDPR purges, test cleanup, or any other case where the row truly should be gone. No-op on models that aren’t tagged #[umbral(soft_delete)] (their delete() is already a hard DELETE).

Source

pub fn only(self, cols: &[&str]) -> Self

Gap #111 — restrict the SELECT to the named columns.

Affects Self::to_sql / Self::to_sql_pg (the SELECT list shrinks to just these columns) and propagates into Self::values when that terminal is called without its own explicit column slice.

The typed terminals (fetch / first / get) refuse to run with .only() set because a partial-column row can’t satisfy T’s FromRow impl. The error message points at .values(...) (returns Vec<serde_json::Value>) as the execution path. Use .only() for .to_sql() inspection and .values() for actual reads.

// Inspect: "SELECT \"id\", \"name\" FROM \"brand\" WHERE \"id\" = ?"
let sql = Brand::objects()
    .filter(brand::ID.eq(1))
    .only(&["id", "name"])
    .to_sql();

// Execute (returns JSON rows):
let rows = Brand::objects()
    .filter(brand::ID.eq(1))
    .values(&["id", "name"])
    .await?;

Unknown column names are not validated here — they surface at terminal time the same way .values() reports them (the rendered SQL contains the bad identifier and SQLite/Postgres raises). This keeps the chainable surface return-type-stable.

Source

pub fn atomic(self) -> Self

Wrap this QuerySet’s write terminal in a transaction. Reads are unaffected (read terminals are single statements and the DB gives them a consistent snapshot). Mutually exclusive with Self::on_tx — if both are set, on_tx wins (you’re already inside a transaction, so wrapping again would deadlock or fail on backends without nested transactions).

Source

pub fn non_atomic(self) -> Self

Opt this QuerySet’s write terminal out of the global App::builder().atomic_transactions(true) default. Useful in hot-path batches where the caller already owns the outer transaction.

Source§

impl<T> QuerySet<T>

Chainable methods on every QuerySet<T>.

These are model-agnostic: they only touch the sea-query SelectStatement and the pool-resolution slot, neither of which depends on T. Terminals (which need row mapping) live in the impl<T: Model> QuerySet<T> block below.

Source

pub fn filter(self, p: Predicate<T>) -> Self

Add a WHERE condition. Multiple .filter calls AND together (sea-query’s and_where semantics — applied at terminal time once the resolved pool’s backend is known).

Source

pub fn exclude(self, p: Predicate<T>) -> Self

Add a negated WHERE condition. The negated predicate ANDs into the chain alongside any filter() calls, so .filter(A).exclude(B).filter(C) renders as WHERE A AND NOT B AND C. Sugar for filter(Q::not(p)).

The negated-filter terminal.

Source

pub fn order_by(self, o: OrderExpr<T>) -> Self

Add an ORDER BY clause. Multiple .order_by calls append. The first explicit call also opts out of the model’s #[umbral(ordering = [...])] default (BUG-8): explicit ordering replaces the default rather than stacking on top of it.

Source

pub fn limit(self, n: u64) -> Self

Set LIMIT.

Source

pub fn offset(self, n: u64) -> Self

Set OFFSET.

Source

pub fn on(self, pool: &SqlitePool) -> Self

Override the pool resolved at terminal time with a SQLite pool.

Wins over the ambient default. Used by tests that drive the ORM without going through App::build(). For a Postgres override use Self::on_pg.

Source

pub fn on_pg(self, pool: &PgPool) -> Self

Override the pool resolved at terminal time with a Postgres pool.

The Postgres counterpart of Self::on. Tests that want to exercise the Postgres branch (or that drive against a real Postgres instance) reach for this directly.

Source

pub fn on_tx(self, tx: &mut Transaction) -> QuerySetTx<'_, T>

Attach this QuerySet to an open transaction.

Returns a QuerySetTx that holds both the query and a mutable reference to the transaction. Every terminal on QuerySetTx (fetch, first, count, exists, get, delete, update_values) executes inside the open transaction so all operations in the same closure commit or roll back as a unit.

umbral::db::transaction(|tx| async move {
    let order = Order::objects().on_tx(tx).create(new_order).await?;
    Stock::objects()
        .on_tx(tx)
        .filter(stock::SKU.eq(sku))
        .update_values(delta)
        .await?;
    Ok::<_, MyError>(order)
}).await?;

Eagerly load a single FK field by name.

After the main SELECT returns rows, a batch SELECT ... FROM <related_table> WHERE id IN (...) fetches all referenced rows in one round-trip. Each returned row is deserialised as the target model and stored in ForeignKey<U>.resolved so template rendering ({{ post.author.username }}) and serde_json::to_value(&post)["author"]["username"] both work without additional queries.

Calling select_related multiple times accumulates the names: .select_related("author").select_related("editor") works the same as .select_related_many(&["author", "editor"]).

§Nested traversal (post-#42)

.select_related("author__manager") walks the FK chain through the __ separator. One batched IN (...) query per hop — 1 + len(hops) round-trips regardless of parent count. No N+1. Each hop’s related row is embedded into the prior level’s JSON, and recursive ForeignKey<T>::Deserialize unpacks the chain into resolved() slots at every depth. Bonus: a select_related’d model now round-trips through serde_json::to_value(&t) / from_value without losing the resolved relation.

§Companion shapes
  • join_related(name) — same goal (load related rows) via a true LEFT JOIN in the main SELECT. One round-trip total vs. select_related’s 1 + N batched-IN approach. Wider per-row payload; better when round-trip count dominates.
  • prefetch_related(name) — M2M batched loading (one query per declared M2M field). For reverse-FK collections (prefetch_related("comment_set")-style) see gap #44 — not yet implemented.
§Loud errors

Unknown field names (typos, M2M names accidentally passed here, fields without fk_target) return a clear sqlx::Error::Protocol from the terminal naming the bad hop and the table it was looked up against. Pre-#42 these silently no-op’d.

Eagerly load multiple FK fields in one call.

Sugar for chained .select_related(name) calls.

JOIN-based eager FK loading — emits LEFT JOIN <related> ON ... in the main SELECT (with aliased child columns <field>__<col>) so one round-trip pulls the parent + related rows together.

Trade-off vs. Self::select_related:

  • select_related runs ONE extra batched query after the main fetch (SELECT * FROM related WHERE id IN (...)). Two round-trips total; rows stay narrow.
  • join_related runs the main query AS the join — one round-trip total — at the cost of a wider per-row payload (every related column rides along even for duplicated parents).

Both populate ForeignKey<U>.resolved the same way so downstream code (templates, serde) doesn’t care which path was used. Pick join_related when round-trip count dominates (hot listing pages, small related tables) and select_related when the related row is wide or only loaded for a subset of the parent rows.

Composes with .select_related(other_fk) and .prefetch_related(m2m) — different fields can take different paths in the same query.

Multi-hop FK chains are supported: a "__"-separated path like "author__manager" resolves one JOIN per hop in a single query.

Constraints: FK fields must live in model.fields (M2M links route through prefetch_related), and every related model along the chain must be registered with the framework (App::builder().model::<U>() or contributed by a plugin) so we can resolve its column layout for the aliased SELECT.

Sugar for chained Self::join_related calls.

LEFT JOIN the related path — keeps parent rows whose relation is absent (the relation hydrates as unresolved/None). Accepts a nested path ("plugin__author"); the join type applies to the deepest hop.

INNER JOIN the related path — drops parent rows whose relation is absent. The default for a NOT NULL FK.

RIGHT JOIN the related path. Postgres-unconditional; SQLite needs >= 3.39 — a runtime warning fires on older SQLite (see the boot/runtime note in the joins docs). The precise version gate lives at execute time (the SQLite driver’s own error); the warn is the early nudge.

Eagerly load an M2M relation via a single batched join.

After the main SELECT returns rows, one query of the shape SELECT j.parent_id, child.* FROM <child_table> child INNER JOIN <junction> j ON child.<pk> = j.child_id WHERE j.parent_id IN (...) fetches every related child for every parent in one round-trip. Each parent’s M2M.resolved slot is populated with its matching children.

The M2M counterpart of Self::select_related for FKs — same goal of killing N+1: a batch-loaded prefetch_related('tags').

§Reverse-FK collections (post-#44)

prefetch_related also loads ReverseSet<C> fields — the “for each Post, give me every Comment that points at it” shape. Declare the field on the parent with #[sqlx(skip)] #[serde(skip)] #[umbral(reverse_fk = "<fk_col>")] pub <name>: ReverseSet<C> where <fk_col> names the FK column on C pointing back. One SELECT * FROM <child> WHERE <fk_col> IN (parent_pks) regardless of parent count — no N+1.

§Scope (v1)
  • M2M + reverse-FK only. FK fields go through Self::select_related (batched IN) or Self::join_related (LEFT JOIN).
  • i64 parent PK only. Same constraint as the rest of the M2M plumbing; models with non-i64 PKs surface a clean compile error.
  • Unknown field name → loud error (post-#42). If the name matches neither an M2M nor a ReverseSet field, fetch returns a clear sqlx::Error::Protocol pointing at the right method.

Eagerly load multiple M2M relations. Sugar for chained .prefetch_related(name) calls.

Source

pub fn into_subquery(self, col_name: &str) -> Subquery

Convert this QuerySet into a [Subquery] suitable for use in an IN (SELECT ...) predicate. Projects only the named column; the accumulated WHERE / ORDER BY survive.

Post::objects().filter(...).into_subquery("author_id")Subquery you can hand to user::ID.in_subquery(...).

Source

pub fn union(self, other: QuerySet<T>) -> Self

Combine this QuerySet with other via SQL UNION (gap #28). Both QuerySets must produce the same column shape — which they always do here because both are typed QuerySet<T>. Duplicates are removed (the de-duplicating UNION, not UNION ALL).

Source

pub fn intersect(self, other: QuerySet<T>) -> Self

Combine this QuerySet with other via SQL INTERSECT (gap #28). Returns rows present in BOTH inputs.

Source

pub fn except(self, other: QuerySet<T>) -> Self

Combine this QuerySet with other via SQL EXCEPT (gap #28). Returns rows present in self but not in other.

Source

pub fn distinct(self) -> Self

Emit SELECT DISTINCT ... for this query (gap #17). Most useful when combined with Self::values to dedupe a column-projected list (distinct().values(&["tag"])); the full-row DISTINCT is rarely what you want.

Postgres-specific DISTINCT ON (cols) is deferred until a real consumer surfaces the need — the standard DISTINCT covers most use cases.

Source§

impl<T: Model> QuerySet<T>

Terminal methods for every QuerySet<T> where T: Model.

Each terminal that materializes T carries a FromRow bound on the method (not the impl block) — the conjunction of both backends’ FromRow impls. #[derive(sqlx::FromRow)] emits a generic-over-R impl, so any user struct with standard field types satisfies both bounds automatically.

Source

pub fn to_sql(&self) -> String

Render the SQL the QuerySet would execute, without running it.

Returns the prepared statement with ? placeholders for the bound values, exactly the string sqlx would send. Useful for eprintln!-style debugging and for tests that want to pin the rendered query without round-tripping through a pool.

The bound values are intentionally not surfaced (sqlx’s binder types aren’t part of umbral’s public surface); a (sql, values) accessor lands when EXPLAIN-style integration needs it.

The rendered placeholder dialect is SQLite’s (?). When the dispatched pool is Postgres the actual at-execute rendering uses $1-style placeholders; the to_sql debug surface continues to emit SQLite-style for stability across calls regardless of which pool is registered.

Source

pub fn to_sql_pg(&self) -> String

Render the QuerySet’s SQL against the Postgres dialect, without running it. Companion to Self::to_sql.

The two render slightly different placeholder syntax (? for SQLite, $1..$N for Postgres) and any Postgres-specific operators like the array @> / <@ / && family only render correctly through this entry point — to_sql’s SQLite path leaves $N tokens in the template untouched. Use this when debugging a Postgres query or asserting on the rendered shape in tests.

Source

pub async fn fetch(self) -> Result<Vec<T>, Error>
where T: for<'r> FromRow<'r, SqliteRow> + for<'r> FromRow<'r, PgRow> + HydrateRelated,

Run the SELECT and return every matching row.

If .select_related(name) was called, a follow-up batch query populates ForeignKey<U>.resolved for each named field before the rows are returned.

Source

pub async fn try_for_each<F, E>( self, chunk_size: usize, callback: F, ) -> Result<(), TryForEachError<E>>
where T: for<'r> FromRow<'r, SqliteRow> + for<'r> FromRow<'r, PgRow> + HydrateRelated, F: FnMut(T) -> Result<(), E>,

Feature 29 Phase 1 — chunked streaming via a callback.

Runs the SELECT in pages of chunk_size rows and invokes callback once per row. Memory bound = chunk_size * sizeof::<T> instead of the full row count fetch() would buffer, so this is the right shape for million-row exports, migrations, and batch transforms.

Deliberately NOT named iterator() — that name suggests a Stream-shaped return value, which would force a futures-util dep. The callback shape is idiomatic Rust, requires no new crates, and ships the same memory bound. A future iterator() returning BoxStream<T> can land later once futures-util is in the workspace for some other reason (likely SSE / WebSockets).

Error contract: the callback may return any error type E. SQL failures become TryForEachError::Sqlx; callback errors become TryForEachError::Callback(e). The first error stops the walk — subsequent rows are not fetched.

Caveats: pages are stable only if the result set isn’t being mutated concurrently. For consistent-snapshot iteration over a live table, wrap the call in a serialised-or-repeatable-read transaction. select_related and prefetch_related hooks are NOT applied on each row — try_for_each is intentionally the “raw column data, one row at a time” terminal.

Source

pub async fn first(self) -> Result<Option<T>, Error>
where T: for<'r> FromRow<'r, SqliteRow> + for<'r> FromRow<'r, PgRow> + HydrateRelated,

Run the SELECT with LIMIT 1 and return the first row, if any.

Source

pub async fn earliest(self, col_name: &'static str) -> Result<Option<T>, Error>
where T: for<'r> FromRow<'r, SqliteRow> + for<'r> FromRow<'r, PgRow> + HydrateRelated,

Return the row with the smallest value in col_name. Sugar for order_by(col.asc()).first(). The earliest('created_at') terminal.

Takes a &'static str column name (same shape as select_related) so the call site stays terse: .earliest("created_at") reads naturally without spelling out .asc().

Source

pub async fn latest(self, col_name: &'static str) -> Result<Option<T>, Error>
where T: for<'r> FromRow<'r, SqliteRow> + for<'r> FromRow<'r, PgRow> + HydrateRelated,

Return the row with the largest value in col_name. Sugar for order_by(col.desc()).first(). The latest('created_at') terminal.

Source

pub async fn in_bulk( self, pks: Vec<T::PrimaryKey>, ) -> Result<HashMap<T::PrimaryKey, T>, Error>
where T: for<'r> FromRow<'r, SqliteRow> + for<'r> FromRow<'r, PgRow> + HydrateRelated, T::PrimaryKey: Hash + Eq,

Fetch many rows by their primary keys and return a HashMap<T::PrimaryKey, T> keyed by PK. The everyday companion to a cached list of ids — User::objects().in_bulk(user_ids) gives you direct lookup access without a second .iter().find(...) pass per id.

Missing ids are silently absent from the map; callers that need the existence check can compare map.len() to pks.len(). Empty input is a no-op (returns the empty map).

PK-agnostic (PK lift — was Vec<i64> / HashMap<i64, T>): the key is the model’s PrimaryKey type, so i64-, String/slug-, and Uuid-keyed models all work. The map key requires Hash + Eq, which every standard PK type (integers, String, Uuid) satisfies.

Source

pub async fn explain(self) -> Result<String, Error>

Return the database’s execution plan for this query as a plain-text string. Doesn’t run the underlying query — just asks the DB how it would be executed.

Backend dispatch:

  • SQLite: EXPLAIN QUERY PLAN <sql> — returns the planner’s nested loop hierarchy, one row per access step.
  • Postgres: EXPLAIN <sql> — returns the default text plan. For machine-readable output use raw sqlx with EXPLAIN (FORMAT JSON); the framework defaults to text because most callers want eyeball-able output.

Lines are joined with newlines. The returned string is what a developer would paste into a debugger or a perf-review issue.

Source

pub async fn count(self) -> Result<i64, Error>

Run SELECT COUNT(*) against the same FROM + WHERE.

Reshapes the query rather than wrapping the existing SELECT: the projection becomes COUNT(*) and LIMIT/OFFSET drop away. ORDER BY is harmless on a scalar aggregate and is left in place. The row type is (i64,) so the FromRow constraint comes from sqlx’s tuple impl rather than the user struct — count() doesn’t need T’s FromRow bounds.

Source

pub async fn exists(self) -> Result<bool, Error>
where T: for<'r> FromRow<'r, SqliteRow> + for<'r> FromRow<'r, PgRow> + HydrateRelated,

Return whether any row matches.

M1 keeps the simple form: add LIMIT 1, fetch, check non-empty. A later milestone may swap the projection for SELECT 1 to skip column materialisation.

Source

pub async fn get(self) -> Result<T, GetError>
where T: for<'r> FromRow<'r, SqliteRow> + for<'r> FromRow<'r, PgRow> + HydrateRelated,

.get() — the exactly-one terminal.

Returns Ok(row) when the filter chain matches exactly one row. The two not-exactly-one cases each get their own GetError variant so the caller can branch deliberately:

  • GetError::NotFound — zero rows matched. The right choice for “fetch the row this user just clicked on; 404 if it’s gone.”
  • GetError::MultipleObjectsReturned — more than one row matched. The right choice for filters that should be uniquely-keyed (e.g. .filter(user::EMAIL.eq("...")) when email has a UNIQUE constraint); a result of 2+ is a data-integrity bug worth crashing on.
  • The underlying sqlx error wraps as GetError::Sqlx.

Internally this issues SELECT ... LIMIT 2 — the cheapest way to distinguish “one row” from “many.” The second row, if it exists, isn’t materialised beyond the bare FromRow call.

match Post::objects().filter(post::ID.eq(42)).get().await {
    Ok(p)                                            => /* render */,
    Err(GetError::NotFound)                          => /* 404 */,
    Err(GetError::MultipleObjectsReturned)           => unreachable!("ID is unique"),
    Err(GetError::Sqlx(e))                           => /* 500 */,
}
Source

pub async fn values(self, columns: &[&str]) -> Result<Vec<JsonValue>, Error>

Project the query to only the named columns, returning a vector of serde_json::Value::Object rows instead of typed T instances. The columns-projection terminal: values('id', 'title').

Use when a list view only needs a few fields — skipping the 50KB body BLOB on every Post saves both memory and the FromRow hydration overhead. Each returned Value is an object keyed by the requested column names, with values typed per the column’s declared SqlType (integers stay integers, booleans stay booleans, dates render as ISO strings).

Unknown column names fail loudly with sqlx::Error::Protocol naming the offending column. Composes with filter, exclude, order_by, limit, offset exactly the way the typed terminals do.

let rows = Post::objects()
    .filter(post::PUBLISHED.eq(true))
    .order_by(post::ID.desc())
    .values(&["id", "title"])
    .await?;
// [ { "id": 3, "title": "c" }, ... ]
Source

pub async fn aggregate( self, aggs: &[(&str, Aggregate)], ) -> Result<JsonValue, Error>

Single-row aggregate. Runs SELECT AGG(col) AS name, ... with the QuerySet’s accumulated WHERE clause (ORDER BY / LIMIT / OFFSET are dropped — they make no sense over an aggregate without GROUP BY).

Returns a serde_json::Value::Object keyed by the supplied names. COUNT comes back as an integer; AVG as a float; SUM / MAX / MIN inherit the source column’s declared type.

use umbral::orm::Aggregate;
let summary = Post::objects()
    .filter(post::PUBLISHED.eq(true))
    .aggregate(&[
        ("count", Aggregate::count()),
        ("total", Aggregate::sum("view_count")),
    ])
    .await?;
// { "count": 42, "total": 9999 }
Source

pub async fn annotate( self, group_cols: &[&str], aggs: &[(&str, Aggregate)], ) -> Result<Vec<JsonValue>, Error>

Grouped aggregate. Runs SELECT <group_cols>, AGG(col) AS name, ... GROUP BY <group_cols> with the accumulated WHERE clause.

Returns one Value::Object per group, with both the group columns and each named aggregate as fields. Group columns are decoded per their declared SqlType (so an integer author_id stays a JSON number).

let by_author = Post::objects()
    .annotate(&["author_id"], &[("count", Aggregate::count())])
    .await?;
// [ { "author_id": 1, "count": 3 }, { "author_id": 2, "count": 2 } ]

The chainable annotate(alias=Agg("relation")): attach a related-aggregate annotation to this QuerySet. The annotation is query-builder state — it renders as a correlated scalar subquery inside the one SELECT every terminal builds, so it composes with .filter / .order_by / .limit, stacks with further annotations, and shows up in Self::explain / Self::to_sql out of the box. Never a side query, never an N+1.

relation names a ReverseSet relation on the model (#[umbral(reverse_fk = "...")]), the same names prefetch_related accepts. When no declared relation matches, the resolver AUTO-DISCOVERS the relation (gaps2 #45): it scans the model registry for any child whose FK targets this parent’s table and matches relation against the child’s conventional name forms (table name, snake_case / lowercase struct name, any of those with a _set suffix). Declared relations always take precedence; an ambiguous auto-match (two children, or a child with two FKs to this parent) poisons the annotation with an error that names the candidates and points at the #[umbral(reverse_fk = "...")] escape hatch. Any crate::orm::Aggregate works; non-count aggregates name a column on the CHILD model:

let rows = Plugin::objects()
    .filter(plugin::MODERATION.eq("approved"))
    .annotate_count("comment_set")                                // COUNT(*)
    .annotate_related("rating_avg", "review_set", Aggregate::avg("rating"))
    .fetch_annotated()
    .await?;                       // Vec<(Plugin, Map<alias, value>)>

An unknown relation name doesn’t panic the (infallible) builder — it poisons the annotation, and every fallible consumer (fetch_annotated, explain) reports it loudly. v1 caveats: child rows aggregate unconditionally — a child-side predicate (a filtered count) and child soft-delete awareness are tracked follow-ups (gaps2 #39).

Source

pub fn annotate_count(self, relation: &str) -> Self

Sugar for the overwhelmingly common annotation: annotate_related("<relation>_count", relation, Aggregate::count()). .annotate_count("comment_set") exposes the value under the comment_set_count alias in Self::fetch_annotated.

Source

pub fn annotate_count_where<C: Model>( self, alias: &str, relation: &str, pred: Predicate<C>, ) -> Self

Like Self::annotate_count but counts only the children matching pred — a filtered count over "comments". C is the CHILD model, so the predicate is typed against the child’s columns (comment::MODERATION.eq("visible")). The predicate renders into the correlated count subquery’s WHERE alongside the FK correlation and the auto soft-delete filter.

Plugin::objects()
    .annotate_count_where::<PluginComment>(
        "visible_comments",
        "comment_set",
        plugin_comment::MODERATION.eq("visible"),
    )
Source

pub async fn fetch_annotated( self, ) -> Result<Vec<(T, Map<String, JsonValue>)>, Error>
where T: for<'r> FromRow<'r, SqliteRow> + for<'r> FromRow<'r, PgRow>,

Run the SELECT and return every matching row with its annotation values — the execution terminal for Self::annotate_related / Self::annotate_count. One query; each row’s annotations arrive as an alias → JSON value map (count → integer, AVG → float/null, SUM/MAX/MIN → typed per the child column, NULL on empty sets for the non-count aggregates).

Source

pub async fn delete(self) -> Result<u64, Error>

DELETE FROM table WHERE <predicates>. Returns the number of rows deleted. With no .filter calls, deletes every row.

Fires bulk_post_delete:<table> once with the list of removed PKs when at least one row was deleted. Per-row pre_delete / post_delete are NOT fired by this path — use Manager::delete_instance when per-row signal semantics are required.

Feature #72: for #[umbral(soft_delete)] models this rewrites to UPDATE ... SET deleted_at = NOW() WHERE ... so rows survive in the DB (filtered out of subsequent queries by the auto WHERE deleted_at IS NULL). Call .hard_delete() beforehand for a real DELETE (GDPR purge, test cleanup).

Source

pub async fn update_expr( self, col_name: &str, expr: FExpr, ) -> Result<u64, WriteError>

UPDATE table SET col = <expr> WHERE <predicates> using an F-expression for the new value.

This is the companion to update_values for atomic column arithmetic. F::col("views").add(1) produces an FExpr that renders as SET views = views + 1 — the database computes the increment atomically on the server side rather than needing a read-modify-write round-trip in application code.

use umbral::orm::F;

Post::objects()
    .filter(post::ID.eq(42))
    .update_expr("views", F::col("views").add(1))
    .await?;

Mixing update_values and update_expr for different columns in one statement requires two separate calls. A combined API (a map where values can be either JSON or FExpr) would require a new sum type; deferred until a consumer surfaces the need.

Source

pub async fn update_values( self, values: Map<String, Value>, ) -> Result<u64, WriteError>

UPDATE table SET k=v[, ...] WHERE <predicates>. The values map provides column_name → JSON value pairs; each is converted to a sea_query::Value per the column’s declared SqlType via crate::orm::write::json_to_sea_value. Returns the number of rows affected.

Unknown columns in the map fail loudly with WriteError::UnknownColumn. JSON null is rejected for non-nullable columns; supplying a column that exists but is absent from the map is silently a no-op (the column keeps its current value — PATCH semantics, not PUT).

Fires bulk_post_save:<table> once with { ids, created: false, actor } when at least one row matched. Per-row pre_save / post_save are NOT fired — use Manager::save when per-row signal semantics are required.

Source

pub async fn fetch_pg(self, pool: &PgPool) -> Result<Vec<T>, Error>
where T: for<'r> FromRow<'r, PgRow>,

Run the SELECT against an explicit PgPool and return every matching row. Bound by FromRow<PgRow> alone so models with Postgres-only field types compile.

Source

pub async fn first_pg(self, pool: &PgPool) -> Result<Option<T>, Error>
where T: for<'r> FromRow<'r, PgRow>,

Run the SELECT against an explicit PgPool with LIMIT 1.

Source

pub async fn count_pg(self, pool: &PgPool) -> Result<i64, Error>

Run SELECT COUNT(*) against an explicit PgPool. No FromRow bound on T — the count tuple type is (i64,).

Source

pub async fn exists_pg(self, pool: &PgPool) -> Result<bool, Error>
where T: for<'r> FromRow<'r, PgRow>,

Return whether any row matches, against an explicit PgPool.

Source

pub async fn get_pg(self, pool: &PgPool) -> Result<T, GetError>
where T: for<'r> FromRow<'r, PgRow>,

Exactly-one terminal against an explicit PgPool. See QuerySet::get for the error-variant semantics.

Trait Implementations§

Source§

impl<T> Clone for QuerySet<T>

Source§

fn clone(&self) -> Self

Returns a duplicate of the value. Read more
1.0.0 (const: unstable) · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl<T> Debug for QuerySet<T>

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more

Auto Trait Implementations§

§

impl<T> !RefUnwindSafe for QuerySet<T>

§

impl<T> !UnwindSafe for QuerySet<T>

§

impl<T> Freeze for QuerySet<T>

§

impl<T> Send for QuerySet<T>
where T: Send,

§

impl<T> Sync for QuerySet<T>
where T: Sync,

§

impl<T> Unpin for QuerySet<T>
where T: Unpin,

§

impl<T> UnsafeUnpin for QuerySet<T>

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
where ST: ?Sized, DT: ?Sized,

Source§

impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
where ST: ?Sized, DT: ?Sized,

Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T> FromRef<T> for T
where T: Clone,

Source§

fn from_ref(input: &T) -> T

Converts to this type from a reference to the input type.
Source§

impl<A, B, T> HttpServerConnExec<A, B> for T
where B: Body,

Source§

impl<T> Instrument for T

Source§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Source§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> IntoEither for T

Source§

fn into_either(self, into_left: bool) -> Either<Self, Self>

Converts self into a Left variant of Either<Self, Self> if into_left is true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
where F: FnOnce(&Self) -> bool,

Converts self into a Left variant of Either<Self, Self> if into_left(&self) returns true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

impl<T> Paint for T
where T: ?Sized,

Source§

fn fg(&self, value: Color) -> Painted<&T>

Returns a styled value derived from self with the foreground set to value.

This method should be used rarely. Instead, prefer to use color-specific builder methods like red() and green(), which have the same functionality but are pithier.

§Example

Set foreground color to white using fg():

use yansi::{Paint, Color};

painted.fg(Color::White);

Set foreground color to white using white().

use yansi::Paint;

painted.white();
Source§

fn primary(&self) -> Painted<&T>

Returns self with the fg() set to [Color :: Primary].

§Example
println!("{}", value.primary());
Source§

fn fixed(&self, color: u8) -> Painted<&T>

Returns self with the fg() set to [Color :: Fixed].

§Example
println!("{}", value.fixed(color));
Source§

fn rgb(&self, r: u8, g: u8, b: u8) -> Painted<&T>

Returns self with the fg() set to [Color :: Rgb].

§Example
println!("{}", value.rgb(r, g, b));
Source§

fn black(&self) -> Painted<&T>

Returns self with the fg() set to [Color :: Black].

§Example
println!("{}", value.black());
Source§

fn red(&self) -> Painted<&T>

Returns self with the fg() set to [Color :: Red].

§Example
println!("{}", value.red());
Source§

fn green(&self) -> Painted<&T>

Returns self with the fg() set to [Color :: Green].

§Example
println!("{}", value.green());
Source§

fn yellow(&self) -> Painted<&T>

Returns self with the fg() set to [Color :: Yellow].

§Example
println!("{}", value.yellow());
Source§

fn blue(&self) -> Painted<&T>

Returns self with the fg() set to [Color :: Blue].

§Example
println!("{}", value.blue());
Source§

fn magenta(&self) -> Painted<&T>

Returns self with the fg() set to [Color :: Magenta].

§Example
println!("{}", value.magenta());
Source§

fn cyan(&self) -> Painted<&T>

Returns self with the fg() set to [Color :: Cyan].

§Example
println!("{}", value.cyan());
Source§

fn white(&self) -> Painted<&T>

Returns self with the fg() set to [Color :: White].

§Example
println!("{}", value.white());
Source§

fn bright_black(&self) -> Painted<&T>

Returns self with the fg() set to [Color :: BrightBlack].

§Example
println!("{}", value.bright_black());
Source§

fn bright_red(&self) -> Painted<&T>

Returns self with the fg() set to [Color :: BrightRed].

§Example
println!("{}", value.bright_red());
Source§

fn bright_green(&self) -> Painted<&T>

Returns self with the fg() set to [Color :: BrightGreen].

§Example
println!("{}", value.bright_green());
Source§

fn bright_yellow(&self) -> Painted<&T>

Returns self with the fg() set to [Color :: BrightYellow].

§Example
println!("{}", value.bright_yellow());
Source§

fn bright_blue(&self) -> Painted<&T>

Returns self with the fg() set to [Color :: BrightBlue].

§Example
println!("{}", value.bright_blue());
Source§

fn bright_magenta(&self) -> Painted<&T>

Returns self with the fg() set to [Color :: BrightMagenta].

§Example
println!("{}", value.bright_magenta());
Source§

fn bright_cyan(&self) -> Painted<&T>

Returns self with the fg() set to [Color :: BrightCyan].

§Example
println!("{}", value.bright_cyan());
Source§

fn bright_white(&self) -> Painted<&T>

Returns self with the fg() set to [Color :: BrightWhite].

§Example
println!("{}", value.bright_white());
Source§

fn bg(&self, value: Color) -> Painted<&T>

Returns a styled value derived from self with the background set to value.

This method should be used rarely. Instead, prefer to use color-specific builder methods like on_red() and on_green(), which have the same functionality but are pithier.

§Example

Set background color to red using fg():

use yansi::{Paint, Color};

painted.bg(Color::Red);

Set background color to red using on_red().

use yansi::Paint;

painted.on_red();
Source§

fn on_primary(&self) -> Painted<&T>

Returns self with the bg() set to [Color :: Primary].

§Example
println!("{}", value.on_primary());
Source§

fn on_fixed(&self, color: u8) -> Painted<&T>

Returns self with the bg() set to [Color :: Fixed].

§Example
println!("{}", value.on_fixed(color));
Source§

fn on_rgb(&self, r: u8, g: u8, b: u8) -> Painted<&T>

Returns self with the bg() set to [Color :: Rgb].

§Example
println!("{}", value.on_rgb(r, g, b));
Source§

fn on_black(&self) -> Painted<&T>

Returns self with the bg() set to [Color :: Black].

§Example
println!("{}", value.on_black());
Source§

fn on_red(&self) -> Painted<&T>

Returns self with the bg() set to [Color :: Red].

§Example
println!("{}", value.on_red());
Source§

fn on_green(&self) -> Painted<&T>

Returns self with the bg() set to [Color :: Green].

§Example
println!("{}", value.on_green());
Source§

fn on_yellow(&self) -> Painted<&T>

Returns self with the bg() set to [Color :: Yellow].

§Example
println!("{}", value.on_yellow());
Source§

fn on_blue(&self) -> Painted<&T>

Returns self with the bg() set to [Color :: Blue].

§Example
println!("{}", value.on_blue());
Source§

fn on_magenta(&self) -> Painted<&T>

Returns self with the bg() set to [Color :: Magenta].

§Example
println!("{}", value.on_magenta());
Source§

fn on_cyan(&self) -> Painted<&T>

Returns self with the bg() set to [Color :: Cyan].

§Example
println!("{}", value.on_cyan());
Source§

fn on_white(&self) -> Painted<&T>

Returns self with the bg() set to [Color :: White].

§Example
println!("{}", value.on_white());
Source§

fn on_bright_black(&self) -> Painted<&T>

Returns self with the bg() set to [Color :: BrightBlack].

§Example
println!("{}", value.on_bright_black());
Source§

fn on_bright_red(&self) -> Painted<&T>

Returns self with the bg() set to [Color :: BrightRed].

§Example
println!("{}", value.on_bright_red());
Source§

fn on_bright_green(&self) -> Painted<&T>

Returns self with the bg() set to [Color :: BrightGreen].

§Example
println!("{}", value.on_bright_green());
Source§

fn on_bright_yellow(&self) -> Painted<&T>

Returns self with the bg() set to [Color :: BrightYellow].

§Example
println!("{}", value.on_bright_yellow());
Source§

fn on_bright_blue(&self) -> Painted<&T>

Returns self with the bg() set to [Color :: BrightBlue].

§Example
println!("{}", value.on_bright_blue());
Source§

fn on_bright_magenta(&self) -> Painted<&T>

Returns self with the bg() set to [Color :: BrightMagenta].

§Example
println!("{}", value.on_bright_magenta());
Source§

fn on_bright_cyan(&self) -> Painted<&T>

Returns self with the bg() set to [Color :: BrightCyan].

§Example
println!("{}", value.on_bright_cyan());
Source§

fn on_bright_white(&self) -> Painted<&T>

Returns self with the bg() set to [Color :: BrightWhite].

§Example
println!("{}", value.on_bright_white());
Source§

fn attr(&self, value: Attribute) -> Painted<&T>

Enables the styling Attribute value.

This method should be used rarely. Instead, prefer to use attribute-specific builder methods like bold() and underline(), which have the same functionality but are pithier.

§Example

Make text bold using attr():

use yansi::{Paint, Attribute};

painted.attr(Attribute::Bold);

Make text bold using using bold().

use yansi::Paint;

painted.bold();
Source§

fn bold(&self) -> Painted<&T>

Returns self with the attr() set to [Attribute :: Bold].

§Example
println!("{}", value.bold());
Source§

fn dim(&self) -> Painted<&T>

Returns self with the attr() set to [Attribute :: Dim].

§Example
println!("{}", value.dim());
Source§

fn italic(&self) -> Painted<&T>

Returns self with the attr() set to [Attribute :: Italic].

§Example
println!("{}", value.italic());
Source§

fn underline(&self) -> Painted<&T>

Returns self with the attr() set to [Attribute :: Underline].

§Example
println!("{}", value.underline());

Returns self with the attr() set to [Attribute :: Blink].

§Example
println!("{}", value.blink());

Returns self with the attr() set to [Attribute :: RapidBlink].

§Example
println!("{}", value.rapid_blink());
Source§

fn invert(&self) -> Painted<&T>

Returns self with the attr() set to [Attribute :: Invert].

§Example
println!("{}", value.invert());
Source§

fn conceal(&self) -> Painted<&T>

Returns self with the attr() set to [Attribute :: Conceal].

§Example
println!("{}", value.conceal());
Source§

fn strike(&self) -> Painted<&T>

Returns self with the attr() set to [Attribute :: Strike].

§Example
println!("{}", value.strike());
Source§

fn quirk(&self, value: Quirk) -> Painted<&T>

Enables the yansi Quirk value.

This method should be used rarely. Instead, prefer to use quirk-specific builder methods like mask() and wrap(), which have the same functionality but are pithier.

§Example

Enable wrapping using .quirk():

use yansi::{Paint, Quirk};

painted.quirk(Quirk::Wrap);

Enable wrapping using wrap().

use yansi::Paint;

painted.wrap();
Source§

fn mask(&self) -> Painted<&T>

Returns self with the quirk() set to [Quirk :: Mask].

§Example
println!("{}", value.mask());
Source§

fn wrap(&self) -> Painted<&T>

Returns self with the quirk() set to [Quirk :: Wrap].

§Example
println!("{}", value.wrap());
Source§

fn linger(&self) -> Painted<&T>

Returns self with the quirk() set to [Quirk :: Linger].

§Example
println!("{}", value.linger());
Source§

fn clear(&self) -> Painted<&T>

👎Deprecated since 1.0.1:

renamed to resetting() due to conflicts with Vec::clear(). The clear() method will be removed in a future release.

Returns self with the quirk() set to [Quirk :: Clear].

§Example
println!("{}", value.clear());
Source§

fn resetting(&self) -> Painted<&T>

Returns self with the quirk() set to [Quirk :: Resetting].

§Example
println!("{}", value.resetting());
Source§

fn bright(&self) -> Painted<&T>

Returns self with the quirk() set to [Quirk :: Bright].

§Example
println!("{}", value.bright());
Source§

fn on_bright(&self) -> Painted<&T>

Returns self with the quirk() set to [Quirk :: OnBright].

§Example
println!("{}", value.on_bright());
Source§

fn whenever(&self, value: Condition) -> Painted<&T>

Conditionally enable styling based on whether the Condition value applies. Replaces any previous condition.

See the crate level docs for more details.

§Example

Enable styling painted only when both stdout and stderr are TTYs:

use yansi::{Paint, Condition};

painted.red().on_yellow().whenever(Condition::STDOUTERR_ARE_TTY);
Source§

fn new(self) -> Painted<Self>
where Self: Sized,

Create a new Painted with a default Style. Read more
Source§

fn paint<S>(&self, style: S) -> Painted<&Self>
where S: Into<Style>,

Apply a style wholesale to self. Any previous style is replaced. Read more
Source§

impl<T> Read<Exclusive, BecauseExclusive> for T
where T: ?Sized,

Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<V, T> VZip<V> for T
where V: MultiLane<T>,

Source§

fn vzip(self) -> V

Source§

impl<T> WithSubscriber for T

Source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more