Skip to main content

systemprompt_database/services/postgres/
ext.rs

1//! Typed-row extension methods over [`PostgresProvider`].
2//!
3//! Part of the documented sqlx allowlist: the SQL is supplied dynamically
4//! through [`QuerySelector`], so compile-time verification is impossible.
5
6use crate::error::DatabaseResult;
7
8use super::PostgresProvider;
9use super::conversion::bind_params;
10use crate::models::{FromDatabaseRow, QuerySelector, ToDbValue};
11use crate::services::provider::DatabaseProviderExt;
12
13impl DatabaseProviderExt for PostgresProvider {
14    async fn fetch_typed_optional<T: FromDatabaseRow>(
15        &self,
16        query: &dyn QuerySelector,
17        params: &[&dyn ToDbValue],
18    ) -> DatabaseResult<Option<T>> {
19        let sql = query.select_query();
20        let query_obj = sqlx::query(sql);
21        let query_obj = bind_params(query_obj, params);
22
23        let row = query_obj.fetch_optional(self.pool()).await?;
24
25        match row {
26            Some(r) => Ok(Some(T::from_postgres_row(&r)?)),
27            None => Ok(None),
28        }
29    }
30
31    async fn fetch_typed_one<T: FromDatabaseRow>(
32        &self,
33        query: &dyn QuerySelector,
34        params: &[&dyn ToDbValue],
35    ) -> DatabaseResult<T> {
36        let sql = query.select_query();
37        let query_obj = sqlx::query(sql);
38        let query_obj = bind_params(query_obj, params);
39
40        let row = query_obj.fetch_one(self.pool()).await?;
41
42        T::from_postgres_row(&row)
43    }
44
45    async fn fetch_typed_all<T: FromDatabaseRow>(
46        &self,
47        query: &dyn QuerySelector,
48        params: &[&dyn ToDbValue],
49    ) -> DatabaseResult<Vec<T>> {
50        let sql = query.select_query();
51        let query_obj = sqlx::query(sql);
52        let query_obj = bind_params(query_obj, params);
53
54        let rows = query_obj.fetch_all(self.pool()).await?;
55
56        rows.iter().map(|r| T::from_postgres_row(r)).collect()
57    }
58}