Skip to main content

cratestack_sqlx/delegate/
scoped_delete.rs

1//! Single-row + predicate-driven bulk DELETE wrappers bound to a
2//! `CoolContext`.
3
4use cratestack_core::{CoolContext, CoolError};
5
6use crate::audit::RunInTxOutcome;
7use crate::{DeleteMany, DeleteRecord, Filter, FilterExpr, sqlx};
8
9#[derive(Debug, Clone)]
10pub struct ScopedDeleteRecord<'a, M: 'static, PK: 'static> {
11    request: DeleteRecord<'a, M, PK>,
12    ctx: CoolContext,
13}
14
15impl<'a, M: 'static, PK: 'static> ScopedDeleteRecord<'a, M, PK> {
16    pub(super) fn new(request: DeleteRecord<'a, M, PK>, ctx: CoolContext) -> Self {
17        Self { request, ctx }
18    }
19
20    pub fn preview_sql(&self) -> String {
21        self.request.preview_sql()
22    }
23
24    /// Attach an expected version for optimistic locking. See
25    /// [`DeleteRecord::if_match`].
26    pub fn if_match(mut self, expected: i64) -> Self {
27        self.request = self.request.if_match(expected);
28        self
29    }
30
31    pub async fn run(self) -> Result<M, CoolError>
32    where
33        for<'r> M: Send + Unpin + sqlx::FromRow<'r, sqlx::postgres::PgRow> + serde::Serialize,
34        PK: Send + Clone + sqlx::Type<sqlx::Postgres> + for<'q> sqlx::Encode<'q, sqlx::Postgres>,
35    {
36        self.request.run(&self.ctx).await
37    }
38
39    pub async fn run_in_tx<'tx>(
40        self,
41        tx: &mut sqlx::Transaction<'tx, sqlx::Postgres>,
42    ) -> Result<RunInTxOutcome<M>, CoolError>
43    where
44        for<'r> M: Send + Unpin + sqlx::FromRow<'r, sqlx::postgres::PgRow> + serde::Serialize,
45        PK: Send + Clone + sqlx::Type<sqlx::Postgres> + for<'q> sqlx::Encode<'q, sqlx::Postgres>,
46    {
47        self.request.run_in_tx(tx, &self.ctx).await
48    }
49}
50
51#[derive(Debug, Clone)]
52pub struct ScopedDeleteMany<'a, M: 'static, PK: 'static> {
53    request: DeleteMany<'a, M, PK>,
54    ctx: CoolContext,
55}
56
57impl<'a, M: 'static, PK: 'static> ScopedDeleteMany<'a, M, PK> {
58    pub(super) fn new(request: DeleteMany<'a, M, PK>, ctx: CoolContext) -> Self {
59        Self { request, ctx }
60    }
61
62    pub fn where_(mut self, filter: Filter) -> Self {
63        self.request = self.request.where_(filter);
64        self
65    }
66
67    pub fn where_expr(mut self, filter: FilterExpr) -> Self {
68        self.request = self.request.where_expr(filter);
69        self
70    }
71
72    pub fn where_any(mut self, filters: impl IntoIterator<Item = FilterExpr>) -> Self {
73        self.request = self.request.where_any(filters);
74        self
75    }
76
77    /// See [`DeleteMany::where_optional`].
78    pub fn where_optional<F>(mut self, filter: Option<F>) -> Self
79    where
80        F: Into<FilterExpr>,
81    {
82        self.request = self.request.where_optional(filter);
83        self
84    }
85
86    pub fn preview_sql(&self) -> String {
87        self.request.preview_sql()
88    }
89
90    pub async fn run(self) -> Result<cratestack_core::BatchSummary, CoolError>
91    where
92        for<'r> M: Send + Unpin + sqlx::FromRow<'r, sqlx::postgres::PgRow> + serde::Serialize,
93    {
94        self.request.run(&self.ctx).await
95    }
96
97    pub async fn run_in_tx<'tx>(
98        self,
99        tx: &mut sqlx::Transaction<'tx, sqlx::Postgres>,
100    ) -> Result<RunInTxOutcome<cratestack_core::BatchSummary>, CoolError>
101    where
102        for<'r> M: Send + Unpin + sqlx::FromRow<'r, sqlx::postgres::PgRow> + serde::Serialize,
103    {
104        self.request.run_in_tx(tx, &self.ctx).await
105    }
106}