use crate::database::{Database, HasArguments, HasStatement};
use crate::describe::Describe;
use crate::error::Error;
use either::Either;
use std::fmt::Debug;
use crate::{chan_stream, Pool};
use crate::io::chan_stream::{ChanStream, Stream, TryStream};
pub trait Executor: Send + Debug + Sized {
type Database: Database;
fn execute<'q,E:'q>(
&mut self,
query: E,
) -> Result<<Self::Database as Database>::QueryResult, Error> where E: Execute<'q, Self::Database>
{
let mut s = self.execute_many(query);
s.collect(|it|{
Some(Ok(it))
})
}
fn execute_many<'q,E: 'q>(
&mut self,
query: E,
) -> ChanStream<<Self::Database as Database>::QueryResult>
where E: Execute<'q, Self::Database>,
{
let mut s = self.fetch_many(query);
s.map(|either| {
match either {
Either::Left(rows) => {
Some(rows)
}
Either::Right(_) => {
None
}
}
})
}
fn fetch<'q, E: 'q>(
&mut self,
query: E,
) -> ChanStream<<Self::Database as Database>::Row> where E: Execute<'q, Self::Database>,
{
let mut s = self.fetch_many(query);
s.map(|either| {
match either{
Either::Left(rows) => {
None
}
Either::Right(row) => {
Some(row)
}
}
})
}
fn fetch_many<'q, E: 'q>(
&mut self,
query: E,
) -> ChanStream<Either<<Self::Database as Database>::QueryResult, <Self::Database as Database>::Row>> where E: Execute<'q, Self::Database>;
fn fetch_all< 'q, E: 'q>(
&mut self,
query: E,
) -> Result<Vec<<Self::Database as Database>::Row>, Error> where E: Execute<'q, Self::Database>
{
self.fetch(query).collect(|it|{
Some(Ok(it))
})
}
fn fetch_one<'q, E: 'q>(
&mut self,
query: E,
) -> Result<<Self::Database as Database>::Row, Error>
where E: Execute<'q, Self::Database>,
{
let row = self.fetch_optional(query)?;
match row {
Some(row) => Ok(row),
None => Err(Error::RowNotFound),
}
}
fn fetch_optional<'q, E: 'q>(
&mut self,
query: E,
) -> Result<Option<<Self::Database as Database>::Row>, Error>
where E: Execute<'q, Self::Database>;
#[inline]
fn prepare<'q>(
&mut self,
query: &'q str,
) -> Result<<Self::Database as HasStatement>::Statement, Error> {
self.prepare_with(query, &[])
}
fn prepare_with<'q>(
&mut self,
sql: &'q str,
parameters: &'q [<Self::Database as Database>::TypeInfo],
) -> Result<<Self::Database as HasStatement>::Statement, Error>;
#[doc(hidden)]
fn describe(
&mut self,
sql: &str,
) -> Result<Describe<Self::Database>, Error>;
}
pub trait Execute<'q, DB: Database>: Send + Sized {
fn sql(&self) -> &str;
fn statement(&self) -> Option<&<DB as HasStatement>::Statement>;
fn take_arguments(&mut self) -> Option<<DB as HasArguments<'q>>::Arguments>;
fn persistent(&self) -> bool;
}
impl<'q, DB: Database> Execute<'q, DB> for &'q str {
#[inline]
fn sql(&self) -> &'q str {
self
}
#[inline]
fn statement(&self) -> Option<&<DB as HasStatement>::Statement> {
None
}
#[inline]
fn take_arguments(&mut self) -> Option<<DB as HasArguments<'q>>::Arguments> {
None
}
#[inline]
fn persistent(&self) -> bool {
true
}
}
impl<'q, DB: Database> Execute<'q, DB> for (&'q str, Option<<DB as HasArguments<'q>>::Arguments>) {
#[inline]
fn sql(&self) -> &'q str {
self.0
}
#[inline]
fn statement(&self) -> Option<&<DB as HasStatement>::Statement> {
None
}
#[inline]
fn take_arguments(&mut self) -> Option<<DB as HasArguments<'q>>::Arguments> {
self.1.take()
}
#[inline]
fn persistent(&self) -> bool {
true
}
}