mem-query 0.0.1

Relational algebra interface for Rust collections
use std::iter::Zip;
use crate::{
    header::Header,
    record::{Record,ExternalRecord,FromRecord},
    relation::{RelationImpl,QueryOutput,Insert,Delete},
    query::fallback::FallbackPlanner,
    query::filter::QueryFilter,
    transaction::{UndoLog,RevertableOp},
};
use tylisp::sexpr;

struct SplitVec<L,R> {
    left: Vec<L>,
    right: Vec<R>
}

impl<L,R> Default for SplitVec<L,R> {
    fn default()->Self {
        SplitVec {
            left: vec![],
            right: vec![]
        }
    }
}

impl<L,R> RelationImpl for SplitVec<L,R> where
    L: Record,
    R: Record,
    (L,R): Record
{
    type Cols = <(L,R) as Record>::Cols;
    type FastCols = sexpr!{};
    type Planner = FallbackPlanner;
}

impl<'a,L,R> QueryOutput<'a> for SplitVec<L,R> where
    Self: RelationImpl + 'a,
    (&'a L, &'a R): ExternalRecord<'a, Cols=Self::Cols>
{
    type QueryRow = (&'a L, &'a R);
}

impl<'a,L,R> IntoIterator for &'a SplitVec<L,R> {
    type Item = (&'a L, &'a R);
    type IntoIter = Zip<std::slice::Iter<'a, L>,
                        std::slice::Iter<'a, R>>;
    fn into_iter(self)->Self::IntoIter {
        self.left.iter().zip(self.right.iter())
    }
}

impl<L,R,H> Insert<H> for SplitVec<L,R> where
    SplitVec<L,R>: RelationImpl,
    H: Header,
    L: FromRecord<H>,
    L::Remainder: Header + Record<Cols = L::Remainder>,
    R: FromRecord<L::Remainder>
{
    type Op = InsertPair<L,R>;
    type Remainder = <R as FromRecord<L::Remainder>>::Remainder;
    fn insert_op<Rec>(rec: Rec)->(Self::Op, Self::Remainder)
    where Rec: Record<Cols=H>
    {
        let (l, remainder) = L::from_rec(rec);
        let (r, remainder) = R::from_rec(remainder);
        (InsertPair(l,r), remainder)
    }
}

struct InsertPair<L,R>(L,R);

impl<L,R> RevertableOp<SplitVec<L,R>> for InsertPair<L,R> {
    type Err = std::convert::Infallible;
    type Log = UndoInsert;
    fn apply(self, rel: &mut SplitVec<L,R>)->Result<Self::Log, Self::Err> {
        rel.left.push(self.0);
        rel.right.push(self.1);
        Ok(UndoInsert)
    }
}

struct UndoInsert;

impl<L,R> UndoLog<SplitVec<L,R>> for UndoInsert {
    fn revert(self, rel: &mut SplitVec<L,R>) {
        rel.left.pop();
        rel.right.pop();
    }
}

impl<L,R,Q> Delete<Q> for SplitVec<L,R>
where
    Q:QueryFilter,
    for<'a> (&'a L, &'a R):Record
{
    type Op = DeleteWhere<Q>;
    type Deleter = impl Fn(Q)->DeleteWhere<Q>;

    fn deleter() -> Self::Deleter {
        |q| DeleteWhere(q)
    }

//    fn delete_op(q:Q)->Self::Op {
//        DeleteWhere(q)
//    }
}   

pub struct DeleteWhere<Q>(Q);

impl<L,R,Q> RevertableOp<SplitVec<L,R>> for DeleteWhere<Q>
where
    for<'a> (&'a L, &'a R): Record,
    Q: QueryFilter,
{
    type Err = std::convert::Infallible;
    type Log = Removed<L,R>;

    fn apply(self, rel: &mut SplitVec<L,R>)->Result<Self::Log, Self::Err> {
        let mut removed: Vec<(usize, L, R)> = vec![];
        for i in (0..rel.left.len()).rev() {
            if self.0.test_record(&(&rel.left[i], &rel.right[i])) {
                removed.push((i, rel.left.remove(i), rel.right.remove(i)))
            }
        }
        Ok(Removed(removed))
    }
}
 
pub struct Removed<L,R>(Vec<(usize, L, R)>);

impl<L,R> UndoLog<SplitVec<L,R>> for Removed<L,R> {
    fn revert(mut self, rel: &mut SplitVec<L,R>) {
        for (i,l,r) in self.0.into_iter().rev() {
            rel.left.insert(i,l);
            rel.right.insert(i,r);
        }
    }
}