pub struct QueryBuilder<'a, T>where
T: Model,{ /* private fields */ }model-mysql or model-postgres or model-sqlite only.Expand description
Fluent async query builder for SELECT, COUNT, DELETE, and UPDATE.
For a model with a soft-delete column (#[soft_delete]) every operation
sees only rows not deleted, unless the chain has
with_deleted or
only_deleted; delete sets the
column and force_delete removes rows. With
#[timestamps] / #[version], update also sets
updated_at and increments the version (18.30.0).
use rust_web_server::model::{DbPool, Order, QueryBuilder};
let pool = DbPool::memory().await?;
// pool.execute("CREATE TABLE users …", &[]).await?;
// let users: Vec<User> = QueryBuilder::<User>::new(&pool)
// .where_eq("active", true)
// .order_by("name", Order::Asc)
// .limit(10)
// .fetch_all()
// .await?;Implementations§
Source§impl<'a, T> QueryBuilder<'a, T>where
T: Model,
impl<'a, T> QueryBuilder<'a, T>where
T: Model,
pub fn new(pool: &'a DbPool) -> QueryBuilder<'a, T>
Sourcepub fn with_deleted(self) -> QueryBuilder<'a, T>
pub fn with_deleted(self) -> QueryBuilder<'a, T>
Soft-deleted rows too (no effect on a model without #[soft_delete]).
Sourcepub fn only_deleted(self) -> QueryBuilder<'a, T>
pub fn only_deleted(self) -> QueryBuilder<'a, T>
Soft-deleted rows only (none for a model without #[soft_delete]).
Sourcepub fn where_eq(self, col: &str, val: impl ToColumn) -> QueryBuilder<'a, T>
pub fn where_eq(self, col: &str, val: impl ToColumn) -> QueryBuilder<'a, T>
Add a col = ? equality filter.
Sourcepub fn filter(self, expr: &str, params: Vec<Value>) -> QueryBuilder<'a, T>
pub fn filter(self, expr: &str, params: Vec<Value>) -> QueryBuilder<'a, T>
Add a raw SQL filter fragment with bind parameters.
.filter("age >= ?", vec![Value::Int(18)])Sourcepub fn order_by(self, col: &str, order: Order) -> QueryBuilder<'a, T>
pub fn order_by(self, col: &str, order: Order) -> QueryBuilder<'a, T>
Set the ORDER BY clause.
Sourcepub fn limit(self, n: u64) -> QueryBuilder<'a, T>
pub fn limit(self, n: u64) -> QueryBuilder<'a, T>
Set the LIMIT clause.
Sourcepub fn offset(self, n: u64) -> QueryBuilder<'a, T>
pub fn offset(self, n: u64) -> QueryBuilder<'a, T>
Set the OFFSET clause.
Sourcepub async fn fetch_all(self) -> Result<Vec<T>, DbError>
pub async fn fetch_all(self) -> Result<Vec<T>, DbError>
Execute SELECT * FROM table WHERE … ORDER BY … LIMIT … OFFSET ….
Sourcepub async fn fetch_one(self) -> Result<Option<T>, DbError>
pub async fn fetch_one(self) -> Result<Option<T>, DbError>
Execute SELECT * … LIMIT 1 and return the first result.
Sourcepub async fn count(self) -> Result<i64, DbError>
pub async fn count(self) -> Result<i64, DbError>
Execute SELECT COUNT(*) FROM table WHERE … (without the chain’s
ORDER BY, which PostgreSQL refuses next to an aggregate).
Sourcepub async fn delete(self) -> Result<(), DbError>
pub async fn delete(self) -> Result<(), DbError>
Execute DELETE FROM table WHERE … — for a soft-delete model,
UPDATE table SET deleted_at = now WHERE … AND deleted_at IS NULL
instead (force_delete removes the rows).
Sourcepub async fn force_delete(self) -> Result<u64, DbError>
pub async fn force_delete(self) -> Result<u64, DbError>
Execute DELETE FROM table WHERE …, removing the rows whatever the
soft-delete column says (within the query’s scope: add
with_deleted to include deleted rows).
Answers the number of rows removed.
Sourcepub async fn restore(self) -> Result<u64, DbError>
pub async fn restore(self) -> Result<u64, DbError>
Clear the soft-delete column of the matching deleted rows; answers
how many. An error for a model without #[soft_delete].
Sourcepub async fn update(self, col: &str, val: impl ToColumn) -> Result<(), DbError>
pub async fn update(self, col: &str, val: impl ToColumn) -> Result<(), DbError>
Execute UPDATE table SET col = ? WHERE … (also updated_at = now
and version = version + 1 when the model has them).
Sourcepub async fn paginate(
self,
page: u64,
per_page: u64,
) -> Result<Page<T>, DbError>
pub async fn paginate( self, page: u64, per_page: u64, ) -> Result<Page<T>, DbError>
Offset-paginated fetch: runs a COUNT(*) (with the same filters, no
limit/offset) and a SELECT … LIMIT … OFFSET …, and wraps both into a
Page. page is 1-based; both page and per_page are clamped to
a minimum of 1. Overrides any .limit()/.offset() set earlier in
the chain — page/per_page are authoritative.
Two queries, not one — if you’re paginating a very large, frequently
appended-to table and don’t need total_pages, Self::paginate_after
(keyset pagination) needs only one.
Sourcepub async fn paginate_after(
self,
cursor: Option<&str>,
per_page: u64,
) -> Result<CursorPage<T>, DbError>
pub async fn paginate_after( self, cursor: Option<&str>, per_page: u64, ) -> Result<CursorPage<T>, DbError>
Cursor (keyset) paginated fetch: orders by the primary key ascending,
fetches per_page + 1 rows to cheaply detect whether there’s a next
page, and returns a CursorPage whose next_cursor is the last
returned row’s primary key (as a string) — pass it back as cursor to
get the next page. cursor: None fetches the first page.
A single query, unlike Self::paginate — no COUNT(*), and no
OFFSET to skip over on every subsequent page, which is what makes
keyset pagination scale on large tables where offset pagination gets
slower page by page. The tradeoff: no total_items/total_pages, and
only forward iteration (no jumping to an arbitrary page).
Overrides any .order_by() set earlier in the chain — keyset
pagination requires ordering by the cursor column. Requires the
primary key to be numeric (parsed as i64); returns Err if cursor
isn’t a valid integer.
Trait Implementations§
Source§impl<'a, T> Clone for QueryBuilder<'a, T>where
T: Model,
impl<'a, T> Clone for QueryBuilder<'a, T>where
T: Model,
Source§fn clone(&self) -> QueryBuilder<'a, T>
fn clone(&self) -> QueryBuilder<'a, T>
1.0.0 (const: unstable) · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source. Read moreAuto Trait Implementations§
impl<'a, T> !RefUnwindSafe for QueryBuilder<'a, T>
impl<'a, T> !UnwindSafe for QueryBuilder<'a, T>
impl<'a, T> Freeze for QueryBuilder<'a, T>where
PhantomData<T>: Freeze,
impl<'a, T> Send for QueryBuilder<'a, T>where
PhantomData<T>: Send,
impl<'a, T> Sync for QueryBuilder<'a, T>where
PhantomData<T>: Sync,
impl<'a, T> Unpin for QueryBuilder<'a, T>where
PhantomData<T>: Unpin,
impl<'a, T> UnsafeUnpin for QueryBuilder<'a, T>where
PhantomData<T>: UnsafeUnpin,
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
impl<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
Source§impl<T> Instrument for T
impl<T> Instrument for T
Source§fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
Source§fn in_current_span(self) -> Instrumented<Self> ⓘ
fn in_current_span(self) -> Instrumented<Self> ⓘ
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
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 moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
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 moreSource§impl<T> Pointable for T
impl<T> Pointable for T
impl<T> Read<Exclusive, BecauseExclusive> for Twhere
T: ?Sized,
Source§impl<T> ServiceExt for T
impl<T> ServiceExt for T
Source§fn map_response_body<F>(self, f: F) -> MapResponseBody<Self, F>where
Self: Sized,
fn map_response_body<F>(self, f: F) -> MapResponseBody<Self, F>where
Self: Sized,
map-response-body only.Source§fn trace_for_http(self) -> Trace<Self, SharedClassifier<ServerErrorsAsFailures>>where
Self: Sized,
fn trace_for_http(self) -> Trace<Self, SharedClassifier<ServerErrorsAsFailures>>where
Self: Sized,
trace only.Source§fn trace_for_grpc(self) -> Trace<Self, SharedClassifier<GrpcErrorsAsFailures>>where
Self: Sized,
fn trace_for_grpc(self) -> Trace<Self, SharedClassifier<GrpcErrorsAsFailures>>where
Self: Sized,
trace only.