use super::{RelationImpl,Relation,Queryable,SelfQuery,Insert,QueryOutput,Delete};
use tylisp::{defun, ops::Ret};
use crate::{
query::{QueryPlanImpl, request::QueryRequest, filter::QueryFilter},
header::Header,
record::Record,
transaction::{UndoLog, RevertableOp},
};
#[derive(Clone,Debug,Default,Hash,Eq,PartialEq,Ord,PartialOrd)]
pub struct OpaqueRel<R>(R);
impl<R> OpaqueRel<R> {
pub fn new(rel: R) -> Self {
OpaqueRel(rel)
}
}
impl<R:RelationImpl> RelationImpl for OpaqueRel<R> {
type Cols = R::Cols;
type FastCols = R::FastCols;
type Planner = OpaquePlanner;
}
impl<'a, R:QueryOutput<'a>> QueryOutput<'a> for OpaqueRel<R>
where Self: RelationImpl<Cols=R::Cols>
{
type QueryRow = R::QueryRow;
}
impl<'a, R:Relation<'a>> IntoIterator for &'a OpaqueRel<R> {
type IntoIter = <R as SelfQuery<'a>>::Iter;
type Item = R::QueryRow;
fn into_iter(self)->Self::IntoIter {
let r:&'a R = &self.0;
r.iter_all()
}
}
pub struct OpaquePlan<'a, R:'a, Req>(&'a OpaqueRel<R>, Req);
impl<'a, Req:'a, R:'a> IntoIterator for OpaquePlan<'a, R, Req>
where R: Queryable<'a, Req>, Req:QueryRequest {
type Item = R::QueryRow;
type IntoIter = <R::Plan as IntoIterator>::IntoIter;
fn into_iter(self)->Self::IntoIter {
let r:&'a R = &self.0.0;
r.query(self.1)
}
}
impl<'a, R, Req> QueryPlanImpl<'a, OpaqueRel<R>, Req> for OpaquePlan<'a, R, Req> {
fn prepare(rel: &'a OpaqueRel<R>, req: Req)->Self {
OpaquePlan(rel, req)
}
}
#[derive(Debug,Default)]
pub struct OpaquePlanner;
defun!{ OpaquePlanner {
('a, Rel:'a, Req) { _:&'a OpaqueRel<Rel>, _:Req } => { Ret, @OpaquePlan<'a, Rel, Req> };
}}
impl<R,H:Header> Insert<H> for OpaqueRel<R> where R:Insert<H> {
type Remainder = R::Remainder;
type Op = OpaqueOp<R::Op>;
fn insert_op<FromRec:Record<Cols=H>>(rec:FromRec)
-> (Self::Op, Self::Remainder) {
let (op, remainder) = R::insert_op(rec);
(OpaqueOp(op), remainder)
}
}
impl<R,Q:QueryFilter> Delete<Q> for OpaqueRel<R> where R:Delete<Q> {
type Op = OpaqueOp<R::Op>;
type Deleter = impl Fn(Q)->Self::Op;
fn deleter()->Self::Deleter {
|q| OpaqueOp((R::deleter())(q))
}
}
pub struct OpaqueOp<Op>(Op);
impl<Target, Op:RevertableOp<Target>>
RevertableOp<OpaqueRel<Target>> for OpaqueOp<Op> {
type Err = Op::Err;
type Log = OpaqueLog<Op::Log>;
fn apply(self, target:&mut OpaqueRel<Target>) -> Result<Self::Log, Self::Err> {
Ok(OpaqueLog(self.0.apply(&mut target.0)?))
}
}
pub struct OpaqueLog<Log>(Log);
impl<Target, Log:UndoLog<Target>>
UndoLog<OpaqueRel<Target>> for OpaqueLog<Log> {
fn revert(self, target: &mut OpaqueRel<Target>) {
self.0.revert(&mut target.0);
}
}