use crate::prelude::*;
use crate::query::{
QueryPlan,
request::QueryRequest,
filter::Exact,
};
use crate::col::ColProxy;
use crate::record::{ExternalRecord,FromExternalRecord,ErasedExtRecord};
use crate::header::ProjectRefFrom;
use crate::transaction::{Transaction,RevertableOp};
use std::marker::PhantomData;
use either::Either;
mod vec_opt;
mod smart_ptr;
mod btree_map_2;
mod insert;
mod delete;
mod subjoin;
mod peerjoin;
mod query;
mod opaque;
mod dynamic;
mod redundant;
mod unique;
mod split_vec;
pub use insert::Insert;
pub use delete::Delete;
pub use btree_map_2::BTreeIndex;
pub use smart_ptr::RelProxy;
pub use opaque::OpaqueRel;
pub use redundant::RedundantIndex;
pub trait RelationImpl {
type Cols: Header;
type FastCols: Header;
type Planner;
fn as_ref(&self)->RelProxy<&'_ Self> {
RelProxy::new(self)
}
fn as_mut(&mut self)->RelProxy<&'_ mut Self> {
RelProxy::new(self)
}
}
pub trait QueryOutput<'a>: RelationImpl {
type QueryRow: ExternalRecord<'a, Cols=Self::Cols>;
}
pub trait Relation<'a>: RelationImpl
+ QueryOutput<'a>
+ SelfQuery<'a>
+ Sized
{
fn subjoin<F:Col>(self) -> subjoin::SubordinateJoin<Self, F>
where subjoin::SubordinateJoin<Self, F>: Relation<'a>
{
subjoin::SubordinateJoin::new(self)
}
fn join<Rel>(self, rel:Rel) -> peerjoin::PeerJoin<Self,Rel>
where peerjoin::PeerJoin<Self,Rel>: Relation<'a>
{
peerjoin::PeerJoin::new(self,rel)
}
fn where_eq<C:ColProxy>(self, c:C) -> query::FilterRel<Self, Exact<C>>
where
query::FilterRel<Self, Exact<C>>: Relation<'a>
{
query::FilterRel { source: self, filter: Exact(c) }
}
fn project<H:Header>(self) -> query::ProjectedRel<Self, H>
where query::ProjectedRel<Self, H>: Relation<'a>
{
query::ProjectedRel { source: self, cols: PhantomData }
}
fn iter_as<O:FromExternalRecord<'a>>(&'a self) ->
<query::IterAs<'a,Self,O> as IntoIterator>::IntoIter
where
query::IterAs<'a,Self,O>: IntoIterator
{
query::IterAs { source: self, target: PhantomData }.into_iter()
}
fn as_dyn(self) -> dynamic::DynRel<Self>
where dynamic::DynRel<Self>: RelationImpl {
dynamic::DynRel::new(self)
}
fn truncate(&mut self)->Result<(), <Self::Op as RevertableOp<Self>>::Err>
where Self: Delete<HNil> {
Transaction::start(self)
.apply((Self::deleter())(HNil))
.commit()
.map_err(|e| e.left().unwrap())
}
}
pub trait Queryable<'a, Req: QueryRequest+'a>: 'a + QueryOutput<'a> + Sized {
type Plan: QueryPlan<'a, Self, Req>;
fn explain(&'a self)->&'static str { std::any::type_name::<Self::Plan>() }
fn query(&'a self, req:Req)
-> <Self::Plan as IntoIterator>::IntoIter;
fn prepare(&'a self, req:Req)->Self::Plan;
}
pub trait DynQueryable<'a, Req:QueryRequest+'a> {
type Cols: Header;
fn dyn_query(&'a self, req:Req)
-> Box<dyn 'a + Iterator<Item = ErasedExtRecord<'a, Self::Cols>>>;
}
impl<'a, Req, T> DynQueryable<'a,Req> for T where
Req: QueryRequest + 'a,
T:Queryable<'a, Req>,
{
type Cols = T::Cols;
fn dyn_query(&'a self, req:Req)
-> Box<dyn 'a + Iterator<Item = ErasedExtRecord<'a, T::Cols>>>
{
Box::new(self.query(req).map(|row| row.erase_type()))
}
}
impl<'a, Rel, Req, Plan> Queryable<'a, Req> for Rel
where sexpr!{Self::Planner, @&'a Self, @Req}: Eval<Result=Plan>,
Plan: QueryPlan<'a, Self, Req>,
Req: QueryRequest + 'a,
Rel: 'a + Relation<'a>,
{
type Plan = Plan;
fn query(&'a self, req:Req)
-> <Plan as IntoIterator>::IntoIter
{
Plan::prepare(self, req).execute()
}
fn prepare(&'a self, req:Req)->Plan {
Plan::prepare(self, req)
}
}
impl<'a, T:RelationImpl + SelfQuery<'a>> Relation<'a> for T
where T:RelationImpl + SelfQuery<'a>
{
}
pub trait SelfQuery<'a>: QueryOutput<'a> {
type Iter: Iterator<Item = Self::QueryRow>;
fn iter_all(&'a self)->Self::Iter;
}
impl<'a,R> SelfQuery<'a> for R
where R: 'a + QueryOutput<'a>,
&'a R: IntoIterator<Item = Self::QueryRow>,
{
type Iter = <&'a R as IntoIterator>::IntoIter;
fn iter_all(&'a self)->Self::Iter { self.into_iter() }
}