1use super::*;
3
4mod params; pub use params::{Params, Param, ToParam};
5mod row; pub use row::{Value, Row, TryFromRefRow, }; mod flavor; pub use flavor::{Flavor};
7
8pub trait Connection<R>
11where R: Row,
12{
13 fn flavor(&self) -> Flavor;
15
16 fn execute_with_params<S, P>(&mut self, query: S, params: &P) -> Result<()>
18 where S: std::convert::AsRef<str>,
19 P: Params;
20
21 fn execute_with_params_iterator<'a, S, I, P>(&mut self, query: S, params_iter: I) -> Result<()>
23 where S: std::convert::AsRef<str>,
24 P: Params + 'a,
25 I: core::iter::IntoIterator<Item = &'a P>;
26
27 fn query<S>(&mut self, query: S) -> Result<Vec<R>>
36 where S: std::convert::AsRef<str>;
37
38 fn query_try_as_object<S, T>(&mut self, query: S) -> Result<Vec<T>>
124 where S: std::convert::AsRef<str>,
125 T: TryFromRefRow<R>,
126 {
127 self.query(query)?
128 .iter()
129 .map(|r: &R| Ok(T::try_from(r)?) )
130 .collect::<Result<Vec<T>>>()
131 }
132
133fn query_first<S>(&mut self, query: S) -> Result<Option<R>>
150 where S: std::convert::AsRef<str>,
151 {
152 Ok(self.query(query)?.into_iter().nth(0))
153 }
154
155 fn query_first_try_as_object<S, T>(&mut self, query: S) -> Result<Option<T>>
157 where S: std::convert::AsRef<str>,
158 T: TryFromRefRow<R>,
159 {
160 if let Some(r) = self.query_first::<_>(query)? {
161 Ok(Some(T::try_from(&r)?))
162 } else {
163 Ok(None)
164 }
165 }
166
167fn query_drop<S>(&mut self, query: S) -> Result<()>
183 where S: std::convert::AsRef<str>
184 {
185 self.query_first::<_>(query)?;
186 Ok(())
187 }
188}
189
190mod sql; mod table; pub use table::{Table, TableStatement, TableFlavoredStatement};
192mod insert; pub use insert::{Insert, InsertMultiple, InsertStatement, InsertFlavoredStatement};
193mod select; pub use select::{Select as SelectV2, SelectStatement, SelectFlavoredStatement};
194mod update; pub use update::{Update, UpdateStatement, UpdateFlavoredStatement};
195mod delete; pub use delete::{Delete, DeleteStatement, DeleteFlavoredStatement};
196mod filter; pub use filter::{Filter, FlavoredFilter};
197mod order; pub use order::{Order, FlavoredOrder};
198
199fn statement_with_conn_filter_order_limit_offset_options<C, R, F, O>(statement: String, conn: &C, filter: Option<&F>, order: Option<&O>, limit: Option<usize>, offset: Option<usize>) -> Result<String>
201where C: Connection<R>, R: Row, F: FlavoredFilter, O: FlavoredOrder,
202{
203 let statement = if let Some(filter) = filter {
204 let filter = filter.filter(conn)?;
205 if ! filter.is_empty() { format!("{statement} WHERE {filter}") }
206 else { statement }
207 } else { statement };
208 let statement = if let Some(order) = order {
209 let order = order.as_order_clause(conn)?;
210 if ! order.is_empty() { format!("{statement} ORDER BY {order}") }
211 else { statement }
212 } else { statement };
213 let statement = if let Some(limit) = limit { format!("{statement} LIMIT {limit}") } else { statement };
214 let statement = if let Some(offset) = offset {
215 if offset > 0 { format!("{statement} OFFSET {offset}") }
216 else { statement }
217 } else { statement };
218 Ok(statement)
219}
220fn statement_with_filter_order_limit_offset_options<F, O>(statement: String, filter: Option<&F>, order: Option<&O>, limit: Option<usize>, offset: Option<usize>) -> Result<String>
222where F: Filter, O: Order,
223{
224 let statement = if let Some(filter) = filter {
225 let filter = filter.filter();
226 if ! filter.is_empty() { format!("{statement} WHERE {filter}") }
227 else { statement }
228 } else { statement };
229 let statement = if let Some(order) = order {
230 let order = order.as_order_clause();
231 if ! order.is_empty() { format!("{statement} ORDER BY {order}") }
232 else { statement }
233 } else { statement };
234 let statement = if let Some(limit) = limit { format!("{statement} LIMIT {limit}") } else { statement };
235 let statement = if let Some(offset) = offset {
236 if offset > 0 { format!("{statement} OFFSET {offset}") }
237 else { statement }
238 } else { statement };
239 Ok(statement)
240}
241
242#[cfg(test)]
243pub mod tests {
244 use super::*;
245
246 pub struct SQLiteFlavoredConnection {}
247 impl<R> Connection<R> for SQLiteFlavoredConnection
248 where R: traits::Row
249 {
250 fn flavor(&self) -> Flavor { Flavor::SQLite }
251 fn execute_with_params<S, P>(&mut self, _query: S, _params: &P) -> Result<()>
252 where S: std::convert::AsRef<str>, P: Params,
253 { Err("command not available for SQLiteFlavoredConnection".into()) }
254 fn execute_with_params_iterator<'a, S, I, P>(&mut self, _query: S, _params_iter: I) -> Result<()>
255 where S: std::convert::AsRef<str>, P: Params + 'a,
256 I: core::iter::IntoIterator<Item = &'a P>,
257 { Err("command not available for SQLiteFlavoredConnection".into()) }
258 fn query<S>(&mut self, _query: S) -> Result<Vec<R>>
259 where S: std::convert::AsRef<str>,
260 { Err("command not available for SQLiteFlavoredConnection".into()) }
261 }
262
263 pub struct Row {}
264 impl row::Row for Row {
265 fn get_value(&self, _i: usize) -> Option<Result<Value>> { None }
266 fn get<T>(&self, _i: usize) -> Option<Result<T>>
267 where T: row::TryFromValue,
268 { None }
269 }
270}
271
272#[cfg(feature="compatibility_v0_10")]
273mod execute;
274#[cfg(feature="compatibility_v0_10")]
275pub use execute::{ExecuteTrait};
276#[cfg(feature="compatibility_v0_10")]
277mod query;
278#[cfg(feature="compatibility_v0_10")]
279pub use query::{QueryTrait};
280
281#[cfg(feature="compatibility_v0_10")]
286pub trait AsStatement<I> {
287 fn as_statement(&self) -> Result<String>;
288}
289
290#[cfg(feature="compatibility_v0_10")]
291pub trait IsSelect {}
292
293#[cfg(feature="compatibility_v0_10")]
294pub trait Select<T, I>
295where T: AsStatement<I> + IsSelect
296{
297 fn select(&self, as_statement: &T) -> Result<Vec<I>>;
298}
299
300#[cfg(feature="compatibility_v0_10")]
301pub trait CreateTable<T>
302where T: AsStatement<()>
303{
304 fn create_table(&mut self, as_statement: &T) -> Result<()>;
305}