atmosphere_core/schema/
read.rs1use crate::{
2 Bind, Error, Result,
3 hooks::{self, HookInput, HookStage, Hooks},
4 query::{QueryError, QueryResult},
5 schema::Table,
6};
7
8use async_trait::async_trait;
9use sqlx::{Executor, IntoArguments, database::Database};
10
11#[async_trait]
18pub trait Read: Table + Bind + Hooks + Send + Sync + Unpin + 'static {
19 async fn read<'e, E>(executor: E, pk: &Self::PrimaryKey) -> Result<Self>
23 where
24 E: Executor<'e, Database = crate::Driver>,
25 for<'q> <crate::Driver as Database>::Arguments<'q>: IntoArguments<'q, crate::Driver> + Send;
26
27 async fn find<'e, E>(executor: E, pk: &Self::PrimaryKey) -> Result<Option<Self>>
31 where
32 E: Executor<'e, Database = crate::Driver>,
33 for<'q> <crate::Driver as Database>::Arguments<'q>: IntoArguments<'q, crate::Driver> + Send;
34
35 async fn read_all<'e, E>(executor: E) -> Result<Vec<Self>>
38 where
39 E: Executor<'e, Database = crate::Driver>,
40 for<'q> <crate::Driver as Database>::Arguments<'q>: IntoArguments<'q, crate::Driver> + Send;
41
42 async fn reload<'e, E>(&mut self, executor: E) -> Result<()>
46 where
47 E: Executor<'e, Database = crate::Driver>,
48 for<'q> <crate::Driver as Database>::Arguments<'q>: IntoArguments<'q, crate::Driver> + Send;
49}
50
51#[async_trait]
52impl<T> Read for T
53where
54 T: Table + Bind + Hooks + Send + Sync + Unpin + 'static,
55{
56 async fn read<'e, E>(executor: E, pk: &Self::PrimaryKey) -> Result<Self>
57 where
58 E: Executor<'e, Database = crate::Driver>,
59 for<'q> <crate::Driver as Database>::Arguments<'q>: IntoArguments<'q, crate::Driver> + Send,
60 {
61 let query = crate::runtime::sql::select::<T>();
62
63 hooks::execute(HookStage::PreBind, &query, HookInput::PrimaryKey(pk)).await?;
64
65 assert!(query.bindings().columns().len() == 1);
66 assert!(query.bindings().columns()[0].field() == Self::PRIMARY_KEY.field);
67 assert!(query.bindings().columns()[0].sql() == Self::PRIMARY_KEY.sql);
68
69 hooks::execute(HookStage::PreExec, &query, HookInput::None).await?;
70
71 let res = sqlx::query_as(query.sql())
72 .bind(pk)
73 .persistent(false)
74 .fetch_one(executor)
75 .await
76 .map_err(QueryError::from)
77 .map_err(Error::Query);
78
79 hooks::execute(
80 hooks::HookStage::PostExec,
81 &query,
82 QueryResult::One(&res).into(),
83 )
84 .await?;
85
86 res
87 }
88
89 async fn find<'e, E>(executor: E, pk: &Self::PrimaryKey) -> Result<Option<Self>>
90 where
91 E: Executor<'e, Database = crate::Driver>,
92 for<'q> <crate::Driver as Database>::Arguments<'q>: IntoArguments<'q, crate::Driver> + Send,
93 {
94 let query = crate::runtime::sql::select::<T>();
95
96 hooks::execute(HookStage::PreBind, &query, HookInput::PrimaryKey(pk)).await?;
97
98 assert!(query.bindings().columns().len() == 1);
99 assert!(query.bindings().columns()[0].field() == Self::PRIMARY_KEY.field);
100 assert!(query.bindings().columns()[0].sql() == Self::PRIMARY_KEY.sql);
101
102 hooks::execute(HookStage::PreExec, &query, HookInput::None).await?;
103
104 let res = sqlx::query_as(query.sql())
105 .bind(pk)
106 .persistent(false)
107 .fetch_optional(executor)
108 .await
109 .map_err(QueryError::from)
110 .map_err(Error::Query);
111
112 hooks::execute(
113 hooks::HookStage::PostExec,
114 &query,
115 QueryResult::Optional(&res).into(),
116 )
117 .await?;
118
119 res
120 }
121
122 async fn read_all<'e, E>(executor: E) -> Result<Vec<Self>>
123 where
124 E: Executor<'e, Database = crate::Driver>,
125 for<'q> <crate::Driver as Database>::Arguments<'q>: IntoArguments<'q, crate::Driver> + Send,
126 {
127 let query = crate::runtime::sql::select_all::<T>();
128
129 hooks::execute(HookStage::PreBind, &query, HookInput::None).await?;
130 hooks::execute(HookStage::PreExec, &query, HookInput::None).await?;
131
132 let res = sqlx::query_as(query.sql())
133 .persistent(false)
134 .fetch_all(executor)
135 .await
136 .map_err(QueryError::from)
137 .map_err(Error::Query);
138
139 hooks::execute(
140 hooks::HookStage::PostExec,
141 &query,
142 QueryResult::Many(&res).into(),
143 )
144 .await?;
145
146 res
147 }
148
149 async fn reload<'e, E>(&mut self, executor: E) -> Result<()>
150 where
151 E: Executor<'e, Database = crate::Driver>,
152 for<'q> <crate::Driver as Database>::Arguments<'q>: IntoArguments<'q, crate::Driver> + Send,
153 {
154 let query = crate::runtime::sql::select_by::<T>(T::PRIMARY_KEY.as_col());
155
156 hooks::execute(HookStage::PreBind, &query, HookInput::Row(self)).await?;
157
158 let mut sql = sqlx::query_as(query.sql());
159
160 for c in query.bindings().columns() {
161 sql = self.bind(c, sql).unwrap();
162 }
163
164 hooks::execute(HookStage::PreExec, &query, HookInput::None).await?;
165
166 let res = sql
167 .persistent(false)
168 .fetch_one(executor)
169 .await
170 .map_err(QueryError::from)
171 .map_err(Error::Query);
172
173 hooks::execute(
174 hooks::HookStage::PostExec,
175 &query,
176 QueryResult::One(&res).into(),
177 )
178 .await?;
179
180 *self = res?;
181
182 Ok(())
183 }
184}