1use crate::database::{Database, HasArguments, HasStatement};
2use crate::describe::Describe;
3use crate::error::Error;
4use either::Either;
5use futures_core::future::BoxFuture;
6use futures_core::stream::BoxStream;
7use futures_util::{future, FutureExt, StreamExt, TryFutureExt, TryStreamExt};
8use std::fmt::Debug;
9
10pub trait Executor<'c>: Send + Debug + Sized {
26 type Database: Database;
27
28 fn execute<'e, 'q: 'e, E: 'q>(
30 self,
31 query: E,
32 ) -> BoxFuture<'e, Result<<Self::Database as Database>::QueryResult, Error>>
33 where
34 'c: 'e,
35 E: Execute<'q, Self::Database>,
36 {
37 self.execute_many(query).try_collect().boxed()
38 }
39
40 fn execute_many<'e, 'q: 'e, E: 'q>(
42 self,
43 query: E,
44 ) -> BoxStream<'e, Result<<Self::Database as Database>::QueryResult, Error>>
45 where
46 'c: 'e,
47 E: Execute<'q, Self::Database>,
48 {
49 self.fetch_many(query)
50 .try_filter_map(|step| async move {
51 Ok(match step {
52 Either::Left(rows) => Some(rows),
53 Either::Right(_) => None,
54 })
55 })
56 .boxed()
57 }
58
59 fn fetch<'e, 'q: 'e, E: 'q>(
61 self,
62 query: E,
63 ) -> BoxStream<'e, Result<<Self::Database as Database>::Row, Error>>
64 where
65 'c: 'e,
66 E: Execute<'q, Self::Database>,
67 {
68 self.fetch_many(query)
69 .try_filter_map(|step| async move {
70 Ok(match step {
71 Either::Left(_) => None,
72 Either::Right(row) => Some(row),
73 })
74 })
75 .boxed()
76 }
77
78 fn fetch_many<'e, 'q: 'e, E: 'q>(
81 self,
82 query: E,
83 ) -> BoxStream<
84 'e,
85 Result<
86 Either<<Self::Database as Database>::QueryResult, <Self::Database as Database>::Row>,
87 Error,
88 >,
89 >
90 where
91 'c: 'e,
92 E: Execute<'q, Self::Database>;
93
94 fn fetch_all<'e, 'q: 'e, E: 'q>(
96 self,
97 query: E,
98 ) -> BoxFuture<'e, Result<Vec<<Self::Database as Database>::Row>, Error>>
99 where
100 'c: 'e,
101 E: Execute<'q, Self::Database>,
102 {
103 self.fetch(query).try_collect().boxed()
104 }
105
106 fn fetch_one<'e, 'q: 'e, E: 'q>(
108 self,
109 query: E,
110 ) -> BoxFuture<'e, Result<<Self::Database as Database>::Row, Error>>
111 where
112 'c: 'e,
113 E: Execute<'q, Self::Database>,
114 {
115 self.fetch_optional(query)
116 .and_then(|row| match row {
117 Some(row) => future::ok(row),
118 None => future::err(Error::RowNotFound),
119 })
120 .boxed()
121 }
122
123 fn fetch_optional<'e, 'q: 'e, E: 'q>(
125 self,
126 query: E,
127 ) -> BoxFuture<'e, Result<Option<<Self::Database as Database>::Row>, Error>>
128 where
129 'c: 'e,
130 E: Execute<'q, Self::Database>;
131
132 #[inline]
141 fn prepare<'e, 'q: 'e>(
142 self,
143 query: &'q str,
144 ) -> BoxFuture<'e, Result<<Self::Database as HasStatement<'q>>::Statement, Error>>
145 where
146 'c: 'e,
147 {
148 self.prepare_with(query, &[])
149 }
150
151 fn prepare_with<'e, 'q: 'e>(
157 self,
158 sql: &'q str,
159 parameters: &'e [<Self::Database as Database>::TypeInfo],
160 ) -> BoxFuture<'e, Result<<Self::Database as HasStatement<'q>>::Statement, Error>>
161 where
162 'c: 'e;
163
164 #[doc(hidden)]
170 fn describe<'e, 'q: 'e>(
171 self,
172 sql: &'q str,
173 ) -> BoxFuture<'e, Result<Describe<Self::Database>, Error>>
174 where
175 'c: 'e;
176}
177
178pub trait Execute<'q, DB: Database>: Send + Sized {
186 fn sql(&self) -> &'q str;
188
189 fn statement(&self) -> Option<&<DB as HasStatement<'q>>::Statement>;
191
192 fn take_arguments(&mut self) -> Option<<DB as HasArguments<'q>>::Arguments>;
198
199 fn persistent(&self) -> bool;
201}
202
203impl<'q, DB: Database> Execute<'q, DB> for &'q str {
206 #[inline]
207 fn sql(&self) -> &'q str {
208 self
209 }
210
211 #[inline]
212 fn statement(&self) -> Option<&<DB as HasStatement<'q>>::Statement> {
213 None
214 }
215
216 #[inline]
217 fn take_arguments(&mut self) -> Option<<DB as HasArguments<'q>>::Arguments> {
218 None
219 }
220
221 #[inline]
222 fn persistent(&self) -> bool {
223 true
224 }
225}
226
227impl<'q, DB: Database> Execute<'q, DB> for (&'q str, Option<<DB as HasArguments<'q>>::Arguments>) {
228 #[inline]
229 fn sql(&self) -> &'q str {
230 self.0
231 }
232
233 #[inline]
234 fn statement(&self) -> Option<&<DB as HasStatement<'q>>::Statement> {
235 None
236 }
237
238 #[inline]
239 fn take_arguments(&mut self) -> Option<<DB as HasArguments<'q>>::Arguments> {
240 self.1.take()
241 }
242
243 #[inline]
244 fn persistent(&self) -> bool {
245 true
246 }
247}