Skip to main content

cratestack_sqlx/delegate/
scoped_find_many.rs

1//! `ScopedFindMany` + the `select` / `include` exits to projected and
2//! side-load variants.
3
4use cratestack_core::{CoolContext, CoolError};
5
6use crate::{Filter, FilterExpr, FindMany, OrderClause, sqlx};
7
8use super::scoped_find_many_projected::ScopedProjectedFindMany;
9use super::scoped_find_many_with::ScopedFindManyWith;
10
11#[derive(Debug, Clone)]
12pub struct ScopedFindMany<'a, M: 'static, PK: 'static> {
13    pub(super) request: FindMany<'a, M, PK>,
14    pub(super) ctx: CoolContext,
15}
16
17impl<'a, M: 'static, PK: 'static> ScopedFindMany<'a, M, PK> {
18    pub(super) fn new(request: FindMany<'a, M, PK>, ctx: CoolContext) -> Self {
19        Self { request, ctx }
20    }
21
22    pub fn where_(mut self, filter: Filter) -> Self {
23        self.request = self.request.where_(filter);
24        self
25    }
26
27    pub fn where_expr(mut self, filter: FilterExpr) -> Self {
28        self.request = self.request.where_expr(filter);
29        self
30    }
31
32    pub fn where_any(mut self, filters: impl IntoIterator<Item = FilterExpr>) -> Self {
33        self.request = self.request.where_any(filters);
34        self
35    }
36
37    /// See [`FindMany::where_optional`].
38    pub fn where_optional<F>(mut self, filter: Option<F>) -> Self
39    where
40        F: Into<FilterExpr>,
41    {
42        self.request = self.request.where_optional(filter);
43        self
44    }
45
46    pub fn order_by(mut self, clause: OrderClause) -> Self {
47        self.request = self.request.order_by(clause);
48        self
49    }
50
51    pub fn limit(mut self, limit: i64) -> Self {
52        self.request = self.request.limit(limit);
53        self
54    }
55
56    pub fn offset(mut self, offset: i64) -> Self {
57        self.request = self.request.offset(offset);
58        self
59    }
60
61    pub fn for_update(mut self) -> Self {
62        self.request = self.request.for_update();
63        self
64    }
65
66    pub fn preview_sql(&self) -> String {
67        self.request.preview_sql()
68    }
69
70    pub fn preview_scoped_sql(&self) -> String {
71        self.request.preview_scoped_sql(&self.ctx)
72    }
73
74    pub async fn run(self) -> Result<Vec<M>, CoolError>
75    where
76        for<'r> M: Send + Unpin + sqlx::FromRow<'r, sqlx::postgres::PgRow>,
77    {
78        self.request.run(&self.ctx).await
79    }
80
81    pub async fn run_in_tx<'tx>(
82        self,
83        tx: &mut sqlx::Transaction<'tx, sqlx::Postgres>,
84    ) -> Result<Vec<M>, CoolError>
85    where
86        for<'r> M: Send + Unpin + sqlx::FromRow<'r, sqlx::postgres::PgRow>,
87    {
88        self.request.run_in_tx(tx, &self.ctx).await
89    }
90
91    /// See [`FindMany::include`].
92    pub fn include<Rel: 'static, RelPK: 'static>(
93        self,
94        relation: cratestack_sql::RelationInclude<M, Rel, RelPK>,
95    ) -> ScopedFindManyWith<'a, M, PK, Rel, RelPK> {
96        ScopedFindManyWith::new(self.request.include(relation), self.ctx)
97    }
98
99    /// See [`FindMany::select`].
100    pub fn select<I, C>(self, columns: I) -> ScopedProjectedFindMany<'a, M, PK>
101    where
102        I: IntoIterator<Item = C>,
103        C: cratestack_sql::IntoColumnName,
104    {
105        ScopedProjectedFindMany::new(self.request.select(columns), self.ctx)
106    }
107}