use crate::{entity::EntityID, Entity, Error, QueryInterface, WithID};
use std::hash::Hasher;
pub trait Resolvable<'r, 'q>: super::build::QueryComponent
where
'q: 'r,
{
type Output;
fn qi(&self) -> &'r QueryInterface<'q>;
fn exec(self) -> Result<(), Error>
where
Self: Sized,
{
self.no_result()
}
fn one(self) -> Result<Option<WithID<Self::Output>>, Error>
where
Self: Sized,
Self::Output: Entity,
{
self.result()
}
fn one_id(self) -> Result<Option<Self::Output>, Error>
where
Self: Sized,
Self::Output: EntityID,
{
self.id_result()
}
fn all(self) -> Result<Vec<WithID<Self::Output>>, Error>
where
Self: Sized,
Self::Output: Entity,
{
self.results()
}
fn all_ids(self) -> Result<Vec<Self::Output>, Error>
where
Self: Sized,
Self::Output: EntityID,
{
self.id_results()
}
fn no_result(self) -> Result<(), Error>
where
Self: Sized,
{
let mut hasher = std::collections::hash_map::DefaultHasher::new();
self.contribute(&mut hasher);
self.qi().with_cache(
hasher.finish(),
|| self.qi().db.conn.prepare(self.derive().assemble()).unwrap(),
|stmt| {
self.bind(stmt)?;
self.qi().expect_no_result(stmt)
},
)?
}
fn result(self) -> Result<Option<WithID<Self::Output>>, Error>
where
Self: Sized,
Self::Output: Entity,
{
let mut hasher = std::collections::hash_map::DefaultHasher::new();
self.contribute(&mut hasher);
self.qi().with_cache(
hasher.finish(),
|| {
let query = self.derive().assemble();
self.qi().db.conn.prepare(query).unwrap()
},
|stmt| {
self.bind(stmt)?;
self.qi().expect_one_result(stmt, &mut |stmt| {
let id: i64 = stmt.read(0)?;
Ok(WithID::wrap(Self::Output::build_from(stmt)?, id))
})
},
)?
}
fn id_result(self) -> Result<Option<Self::Output>, Error>
where
Self: Sized,
Self::Output: EntityID,
{
let mut hasher = std::collections::hash_map::DefaultHasher::new();
self.contribute(&mut hasher);
self.qi().with_cache(
hasher.finish(),
|| {
let query = self.derive().assemble();
self.qi().db.conn.prepare(query).unwrap()
},
|stmt| {
self.bind(stmt)?;
self.qi().expect_one_result(stmt, &mut |stmt| {
let id: i64 = stmt.read(0)?;
Ok(Self::Output::from_raw_id(id))
})
},
)?
}
fn results(self) -> Result<Vec<WithID<Self::Output>>, Error>
where
Self: Sized,
Self::Output: Entity,
{
let mut hasher = std::collections::hash_map::DefaultHasher::new();
self.contribute(&mut hasher);
self.qi().with_cache(
hasher.finish(),
|| self.qi().db.conn.prepare(self.derive().assemble()).unwrap(),
|stmt| {
self.bind(stmt)?;
let mut res = Vec::new();
loop {
let state = stmt.next()?;
if state == sqlite::State::Done {
break;
}
let id: i64 = stmt.read(0)?;
res.push(WithID::wrap(Self::Output::build_from(stmt)?, id));
}
Ok(res)
},
)?
}
fn id_results(self) -> Result<Vec<Self::Output>, Error>
where
Self: Sized,
Self::Output: EntityID,
{
let mut hasher = std::collections::hash_map::DefaultHasher::new();
self.contribute(&mut hasher);
self.qi().with_cache(
hasher.finish(),
|| self.qi().db.conn.prepare(self.derive().assemble()).unwrap(),
|stmt| {
self.bind(stmt)?;
let mut res = Vec::new();
loop {
let state = stmt.next()?;
if state == sqlite::State::Done {
break;
}
let id: i64 = stmt.read(0)?;
res.push(Self::Output::from_raw_id(id));
}
Ok(res)
},
)?
}
}