use super::{RelationImpl,Relation,Queryable,QueryOutput,Insert,Delete};
use tylisp::{defun, ops::Ret};
use crate::{
query::{QueryPlanImpl, request::QueryRequest, filter::QueryFilter},
transaction::{RevertableOp,Transaction,UndoLog,Accessor},
header::Header,
record::Record,
};
use std::ops::{Deref,DerefMut};
#[derive(Clone,Debug)]
pub struct RelProxy<Ptr>(Ptr);
impl<Ptr> RelProxy<Ptr> {
pub fn new(rel: impl Into<Ptr>) -> Self {
RelProxy(rel.into())
}
}
impl<Ptr:Deref> Deref for RelProxy<Ptr> {
type Target = Ptr::Target;
fn deref(&self)->&Ptr::Target { self.0.deref() }
}
impl<Ptr:Deref<Target=R>, R:RelationImpl> RelationImpl for RelProxy<Ptr> {
type Cols = R::Cols;
type FastCols = R::FastCols;
type Planner = ProxyPlanner;
}
impl<'a, Ptr:Deref<Target = R>, R:QueryOutput<'a>>
QueryOutput<'a> for RelProxy<Ptr> {
type QueryRow = R::QueryRow;
}
impl<'a, Ptr:Deref<Target=R>, R:'a + Relation<'a>>
IntoIterator for &'a RelProxy<Ptr> {
type IntoIter = impl Iterator<Item = Self::Item>;
type Item = R::QueryRow;
fn into_iter(self)->Self::IntoIter {
let r:&'a R = &*self.0;
r.iter_all()
}
}
pub struct ProxyPlan<'a, Ptr, Req>(&'a RelProxy<Ptr>, Req);
impl<'a, Ptr:'a + Deref<Target=Rel>, Req:'a, Rel> IntoIterator for ProxyPlan<'a, Ptr, Req>
where Rel: Queryable<'a, Req>,
Req: QueryRequest,
{
type Item = Rel::QueryRow;
type IntoIter = <Rel::Plan as IntoIterator>::IntoIter;
fn into_iter(self)->Self::IntoIter {
let r:&'a Rel = &*self.0;
r.query(self.1)
}
}
impl<'a, Ptr, Req> QueryPlanImpl<'a, RelProxy<Ptr>, Req> for ProxyPlan<'a, Ptr, Req> {
fn prepare(rel: &'a RelProxy<Ptr>, req: Req)->Self {
ProxyPlan(rel, req)
}
}
#[derive(Debug,Default)]
pub struct ProxyPlanner;
defun!{ ProxyPlanner {
('a, Rel:'a, Req) { _:&'a RelProxy<Rel>, _:Req } => { Ret, @ProxyPlan<'a, Rel, Req> };
}}
impl<Ptr:DerefMut<Target=R>, R, H> Insert<H> for RelProxy<Ptr>
where
R: Insert<H>,
H: Header,
{
type Remainder = R::Remainder;
type Op = ProxyOp<R::Op>;
fn insert_op<FromRec:Record<Cols=H>>(rec:FromRec)
-> (Self::Op, Self::Remainder) {
let (op, remainder) = R::insert_op(rec);
(ProxyOp(op), remainder)
}
}
impl<Ptr:DerefMut<Target=R>, R, Q> Delete<Q> for RelProxy<Ptr>
where
R: Delete<Q>,
Q: QueryFilter,
{
type Op = ProxyOp<R::Op>;
type Deleter = impl Fn(Q)->Self::Op;
fn deleter() -> Self::Deleter {
|q| ProxyOp((R::deleter())(q))
}
}
pub struct ProxyOp<Op>(Op);
impl<Ptr, Op> RevertableOp<RelProxy<Ptr>> for ProxyOp<Op>
where
Ptr: DerefMut,
Op: RevertableOp<Ptr::Target>
{
type Err = impl std::error::Error;
type Log = impl UndoLog<RelProxy<Ptr>>;
fn apply(self, proxy: &mut RelProxy<Ptr>)->Result<Self::Log,Self::Err> {
Transaction::start(proxy)
.subtransaction(AccessProxy, move |tx| tx.apply(self.0))
.into_undo_log()
}
}
struct AccessProxy;
impl<Ptr> Accessor<RelProxy<Ptr>> for AccessProxy
where Ptr: DerefMut {
type Dest = Ptr::Target;
fn access<F,O>(&self, proxy: &mut RelProxy<Ptr>, op:F)->O
where F:FnOnce(&mut Self::Dest)->O
{
op(&mut *proxy.0)
}
}