dogdata_sqlx/
query_builder.rs

1use sqlx::{Database, Executor};
2
3use crate::execute::{InstrumentedExecute, InstrumentedFetch, InstrumentedPool};
4
5pub struct InstrumentedQueryBuilder<Q> {
6    pub query: Q,
7    pub sql: &'static str,
8}
9
10impl<'q, DB, A> InstrumentedQueryBuilder<sqlx::query::Query<'q, DB, A>>
11where
12    DB: Database,
13    A: 'q + Send + sqlx::IntoArguments<'q, DB>,
14{
15    pub async fn execute<P>(self, pool: &P) -> Result<DB::QueryResult, sqlx::Error>
16    where
17        P: InstrumentedPool<Database = DB> + Send + Sync,
18        for<'c> &'c P: Executor<'c, Database = DB>,
19    {
20        self.query.execute_instrumented(pool, self.sql).await
21    }
22
23    pub async fn fetch_one<P>(self, pool: &P) -> Result<DB::Row, sqlx::Error>
24    where
25        P: InstrumentedPool<Database = DB> + Send + Sync,
26        for<'c> &'c P: Executor<'c, Database = DB>,
27    {
28        self.query.fetch_one_instrumented(pool, self.sql).await
29    }
30
31    pub async fn fetch_optional<P>(self, pool: &P) -> Result<Option<DB::Row>, sqlx::Error>
32    where
33        P: InstrumentedPool<Database = DB> + Send + Sync,
34        for<'c> &'c P: Executor<'c, Database = DB>,
35    {
36        self.query.fetch_optional_instrumented(pool, self.sql).await
37    }
38
39    pub async fn fetch_all<P>(self, pool: &P) -> Result<Vec<DB::Row>, sqlx::Error>
40    where
41        P: InstrumentedPool<Database = DB> + Send + Sync,
42        for<'c> &'c P: Executor<'c, Database = DB>,
43    {
44        self.query.fetch_all_instrumented(pool, self.sql).await
45    }
46}
47
48// Implementation for sqlx::query::Map<'q, DB, F, A> (from query_as! macro)
49impl<'q, DB, F, A, O> InstrumentedQueryBuilder<sqlx::query::Map<'q, DB, F, A>>
50where
51    DB: Database,
52    F: FnMut(DB::Row) -> Result<O, sqlx::Error> + Send,
53    O: Send + Unpin,
54    A: 'q + Send + sqlx::IntoArguments<'q, DB>,
55{
56    pub async fn fetch_one<P>(self, pool: &P) -> Result<O, sqlx::Error>
57    where
58        P: InstrumentedPool<Database = DB> + Send + Sync,
59        for<'c> &'c P: Executor<'c, Database = DB>,
60    {
61        self.query.fetch_one_instrumented(pool, self.sql).await
62    }
63
64    pub async fn fetch_optional<P>(self, pool: &P) -> Result<Option<O>, sqlx::Error>
65    where
66        P: InstrumentedPool<Database = DB> + Send + Sync,
67        for<'c> &'c P: Executor<'c, Database = DB>,
68    {
69        self.query.fetch_optional_instrumented(pool, self.sql).await
70    }
71
72    pub async fn fetch_all<P>(self, pool: &P) -> Result<Vec<O>, sqlx::Error>
73    where
74        P: InstrumentedPool<Database = DB> + Send + Sync,
75        for<'c> &'c P: Executor<'c, Database = DB>,
76    {
77        self.query.fetch_all_instrumented(pool, self.sql).await
78    }
79}
80
81// Implementation for sqlx::query::QueryScalar<'q, DB, O, A> (from query_scalar! macro)
82impl<'q, DB, O, A> InstrumentedQueryBuilder<sqlx::query::QueryScalar<'q, DB, O, A>>
83where
84    DB: Database,
85    O: Send + Unpin + for<'r> sqlx::Decode<'r, DB> + sqlx::Type<DB>,
86    A: 'q + Send + sqlx::IntoArguments<'q, DB>,
87    usize: sqlx::ColumnIndex<DB::Row>,
88{
89    pub async fn fetch_one<P>(self, pool: &P) -> Result<O, sqlx::Error>
90    where
91        P: InstrumentedPool<Database = DB> + Send + Sync,
92        for<'c> &'c P: Executor<'c, Database = DB>,
93    {
94        self.query.fetch_one_instrumented(pool, self.sql).await
95    }
96
97    pub async fn fetch_optional<P>(self, pool: &P) -> Result<Option<O>, sqlx::Error>
98    where
99        P: InstrumentedPool<Database = DB> + Send + Sync,
100        for<'c> &'c P: Executor<'c, Database = DB>,
101    {
102        self.query.fetch_optional_instrumented(pool, self.sql).await
103    }
104
105    pub async fn fetch_all<P>(self, pool: &P) -> Result<Vec<O>, sqlx::Error>
106    where
107        P: InstrumentedPool<Database = DB> + Send + Sync,
108        for<'c> &'c P: Executor<'c, Database = DB>,
109    {
110        self.query.fetch_all_instrumented(pool, self.sql).await
111    }
112}