use crate::{
relation::{RelationImpl,Queryable,Relation,QueryOutput},
header::{Header, ProjectFrom},
query::{
QueryPlanImpl,
request::{QueryRequest, NewRequest},
},
record::{Record, proj::Projection},
};
use tylisp::{
sexpr, defun, defun_nocalc, HNil,
engine::{Eval},
ops::{
Phantom, Ret,
list::{BuildList,Intersect},
},
};
use std::marker::PhantomData;
pub struct RenamedRel<Rel,A,B> {
pub(crate) source: Rel,
pub(crate) cols: PhantomData<(A,B)>,
}
impl<Rel, A, B, Cols, FastCols> RelationImpl for RenamedRel<Rel,A,B>
where
A: Col, B:Col<Inner = A>,
Rel: RelationImpl<Cols=Cols, FastCols=FastCols>,
Cols: Header + RenameCol<A,B>,
Cols::Renamed: Header,
FastCols: Header + RenameCol<A,B>,
FastCols::Renamed: Header,
{
type Cols = Cols::Renamed;
type FastCols = FastCols::Renamed;
type Planner = Planner;
}
impl<'a,A,B,Cols> QueryOutput<'a> for RenamedRel<Rel,A,B>
where
A: Col, B:Col<Inner=A::Inner>,
Rel: QueryOutput<'a>,
Cols: Header,
Cols: ProjectFrom<Rel::Cols>,
Self: RelationImpl<Cols = Cols>,
{
type QueryRow = Rename<Rel::QueryRow, A,B>;
}
#[derive(Default,Copy,Clone,Debug)]
pub struct IterAllQuery;
defun!{ IterAllQuery {
(Src: RelationImpl, Cols: Header) {_:PhantomData<Src>, _:PhantomData<Cols>} =>
{NewRequest, {BuildList},
{Phantom, @HNil}};
}}
impl<'a,R,C> IntoIterator for &'a RenamedRel<R,C>
where
RenamedRel<R,C>: RelationImpl,
R: Relation<'a>,
C: ProjectFrom<R::Cols>,
{
type Item = Projection<R::QueryRow, C>;
type IntoIter = impl Iterator<Item = Self::Item>;
fn into_iter(self)->Self::IntoIter {
self.source.iter_all().map(|r| r.project())
}
}
pub struct IterAs<'a, Src,Out> {
pub(crate) source: &'a Src,
pub(crate) target: PhantomData<Out>
}
impl<'a, Src,Out:'a> IntoIterator for IterAs<'a, Src,Out>
where
Out: crate::record::FromExternalRecord<'a>,
Src: Relation<'a>,
Out::Cols: ProjectFrom<Src::Cols>,
{
type Item = Out;
type IntoIter = impl Iterator<Item = Out>;
fn into_iter(self)->Self::IntoIter {
self.source.iter_all().map(Out::from_ext_rec)
}
}
#[derive(Default,Copy,Clone,Debug)]
pub struct Planner;
defun_nocalc!{() Planner {
('a, Rel, Req) {_: &'a Rel, _: Req} => {Ret, @RenamedRelPlan<'a, Rel, Req>};
}}
pub struct RenamedRelPlan<'a, Rel, Req> {
proj: &'a Rel,
req: Req,
}
impl<'a, Rel, Req, Cols> IntoIterator for RenamedRelPlan<'a, RenamedRel<Rel,Cols>, Req>
where
Cols: Header,
Req: QueryRequest + 'a,
Rel: Queryable<'a, Req>,
Cols: ProjectFrom<Rel::Cols>
{
type Item = Projection<Rel::QueryRow, Cols>;
type IntoIter = impl Iterator<Item = Self::Item>;
fn into_iter(self)->Self::IntoIter {
self.proj.source.query(self.req).map(|r| r.project())
}
}
impl<'a, Rel, Req> QueryPlanImpl<'a, Rel, Req> for RenamedRelPlan<'a, Rel, Req>
where
{
fn prepare(proj: &'a Rel, req: Req)->Self {
RenamedRelPlan { proj, req }
}
}
#[test]
fn test_projected_rel() {
col!{A: usize}
col!{B: usize}
use crate::relation::{Relation,SelfQuery,OpaqueRel};
use crate::record::Record;
let source: OpaqueRel<Vec<(A,B)>> = OpaqueRel::new(vec![ (A(3), B(6)), (A(5), B(2)), (A(3), B(7)) ]);
let result: Vec<B> = source.as_ref().where_eq(A(3)).project::<sexpr!{B}>().iter_all().map(|rec| rec.into_cols().head).collect();
assert_eq!(vec![B(6), B(7)], result);
let result: Vec<B> = source.where_eq(A(3)).project::<sexpr!{B}>().iter_all().map(|rec| rec.into_cols().head).collect();
assert_eq!(vec![B(6), B(7)], result);
}
#[test]
fn test_iter_as() {
col!{A: usize}
col!{B: usize}
use crate::relation::{Relation,OpaqueRel};
use crate::record::Record;
let source: OpaqueRel<Vec<(A,B)>> = OpaqueRel::new(vec![ (A(3), B(6)), (A(5), B(2)), (A(3), B(7)) ]);
let result: Vec<B> = source.as_ref().where_eq(A(3)).iter_as().collect();
assert_eq!(vec![B(6), B(7)], result);
let result: Vec<B> = source.where_eq(A(3)).iter_as().collect();
assert_eq!(vec![B(6), B(7)], result);
}