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)
}
}
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);
}
}
}