use super::{RelationImpl,Relation,DynQueryable,QueryOutput};
use tylisp::{defun, ops::Ret};
use crate::{
query::{QueryPlanImpl, request::QueryRequest},
header::Header,
record::{ExternalRecord,ErasedExtRecord},
};
use std::marker::PhantomData;
#[derive(Clone,Debug,Default,Hash,Eq,PartialEq,Ord,PartialOrd)]
pub struct DynRel<R>(R);
impl<R> DynRel<R> where Self:RelationImpl {
pub fn new(r:R) -> Self { DynRel(r) }
}
impl<R:RelationImpl> RelationImpl for DynRel<R>
where for<'a> ErasedExtRecord<'a, R::Cols>: ExternalRecord<'a, Cols=R::Cols>
{
type Cols = R::Cols;
type FastCols = R::FastCols;
type Planner = DynPlanner;
}
impl<'a, R:RelationImpl> QueryOutput<'a> for DynRel<R>
where Self: RelationImpl<Cols = R::Cols>,
ErasedExtRecord<'a, R::Cols>: ExternalRecord<'a, Cols=R::Cols>
{
type QueryRow = ErasedExtRecord<'a, R::Cols>;
}
impl<'a, R:Relation<'a>> IntoIterator for &'a DynRel<R> {
type Item = ErasedExtRecord<'a, R::Cols>;
type IntoIter = Box<dyn Iterator<Item = Self::Item> + 'a>;
fn into_iter(self)->Self::IntoIter {
Box::new( self.0.iter_all().map(|r| r.erase_type()))
}
}
pub struct DynPlan<'a, Req, Cols>(
&'a dyn DynQueryable<'a, Req, Cols=Cols>,
Req,
PhantomData<Cols>
);
impl<'a, Req:'a, Cols:Header> IntoIterator for DynPlan<'a, Req, Cols>
where Req: QueryRequest + 'a,
ErasedExtRecord<'a, Cols>: ExternalRecord<'a, Cols=Cols>
{
type Item = ErasedExtRecord<'a, Cols>;
type IntoIter = Box<dyn Iterator<Item = Self::Item> + 'a>;
fn into_iter(self)->Self::IntoIter {
self.0.dyn_query(self.1)
}
}
impl<'a, R:'a, Req, Cols> QueryPlanImpl<'a, DynRel<R>, Req>
for DynPlan<'a, Req, Cols>
where Req: QueryRequest + 'a,
R: Relation<'a, Cols=Cols> + DynQueryable<'a, Req,Cols = Cols>,
Cols: Header,
{
fn prepare(rel: &'a DynRel<R>, req: Req)->Self {
DynPlan(&rel.0, req, PhantomData)
}
}
#[derive(Debug,Default)]
pub struct DynPlanner;
defun!{ DynPlanner {
('a, Rel:'a + RelationImpl, Req:'a) { _:&'a DynRel<Rel>, _:Req }
=> { Ret, @DynPlan<'a, Req, Rel::Cols> };
}}
#[cfg(test)] mod test {
use super::*;
use crate::relation::{Insert, SelfQuery};
use crate::record::Record;
#[test]
fn test_dyn_rel() {
col!{pub A: u32};
col!{pub B: u32};
col!{pub C: u32};
use tylisp::sexpr;
assert_trait!{ sexpr!{A,B}: Record };
assert_trait!{ Vec<sexpr!{A,B}>: RelationImpl };
assert_trait!{ Vec<sexpr!{A,B}>: for<'a> Relation<'a> };
type RelUnderTest = Vec<(A,B)>; let mut rel: RelUnderTest = Default::default();
assert!(<RelUnderTest as Insert<_>>::insert(&mut rel, (A(3), B(11))).is_ok());
assert!(<RelUnderTest as Insert<_>>::insert(&mut rel, &(A(3), B(7))).is_ok());
assert!(<RelUnderTest as Insert<_>>::insert(&mut rel, ((B(5), C(42)), A(7))).is_ok());
let rel = rel.as_dyn();
assert_eq!(3, rel.iter_all().count());
assert_eq!(3, rel.as_ref().iter_all().count());
assert_eq!(2, rel.as_ref().where_eq(A(3)).iter_all().count());
}
}