use crate::{
header::Header,
record::{Record, FromRecord},
relation::{RelationImpl, Insert, QueryOutput, Delete},
query::{fallback::FallbackPlanner, filter::QueryFilter},
transaction::{RevertableOp, UndoLog}
};
use tylisp::sexpr;
#[cfg(test)] use crate::{
relation::{Relation, Queryable},
};
use std::convert::Infallible;
impl<R:Record> RelationImpl for Option<R> {
type Cols = R::Cols;
type FastCols = R::Cols;
type Planner = FallbackPlanner;
}
impl<'a, R> QueryOutput<'a> for Option<R>
where Self:RelationImpl,
R: 'a + Record<Cols = Self::Cols>
{
type QueryRow = &'a R;
}
impl<R:Record> RelationImpl for Vec<R> {
type Cols = R::Cols;
type FastCols = sexpr!{};
type Planner = FallbackPlanner;
}
impl<'a, R> QueryOutput<'a> for Vec<R>
where Self:RelationImpl,
R: 'a + Record<Cols = Self::Cols>
{
type QueryRow = &'a R;
}
impl<R:Record, H:Header> Insert<H> for Vec<R>
where R: FromRecord<H> {
type Remainder = R::Remainder;
type Op = RevertablePush<R>;
fn insert_op<FromRec:Record<Cols=H>>(rec:FromRec) -> (Self::Op, Self::Remainder) {
let (inserted, remainder) = R::from_rec(rec);
(RevertablePush(inserted), remainder)
}
}
impl<R:Record, H:Header> Insert<H> for Option<R>
where R: FromRecord<H> {
type Remainder = R::Remainder;
type Op = RevertableSetOption<R>;
fn insert_op<FromRec:Record<Cols=H>>(rec:FromRec) -> (Self::Op, Self::Remainder) {
let (inserted, remainder) = R::from_rec(rec);
(RevertableSetOption(inserted), remainder)
}
}
pub struct RevertablePush<T>(T);
pub struct RevertableSetOption<T>(T);
pub struct Pop;
impl<T> RevertableOp<Vec<T>> for RevertablePush<T> {
type Err = Infallible;
type Log = Pop;
fn apply(self, target: &mut Vec<T>) -> Result<Pop, Infallible> {
target.push(self.0);
Ok(Pop)
}
}
impl<T> UndoLog<Vec<T>> for Pop {
fn revert(self, target: &mut Vec<T>) { target.pop(); }
}
impl<T> UndoLog<Option<T>> for Pop {
fn revert(self, target: &mut Option<T>) { *target = None; }
}
#[derive(thiserror::Error, Debug, Clone)]
#[error("The relation {0} has no available space.")]
pub struct CapacityErr(&'static str);
impl<T> RevertableOp<Option<T>> for RevertableSetOption<T> {
type Err = CapacityErr;
type Log = Pop;
fn apply(self, target: &mut Option<T>)->Result<Pop, CapacityErr> {
match target {
Some(_) => Err(CapacityErr(std::any::type_name::<Self>())),
None => { *target = Some(self.0); Ok( Pop ) }
}
}
}
impl<R,Q> Delete<Q> for Vec<R>
where
Q:QueryFilter,
R:Record
{
type Op = DeleteWhere<Q>;
type Deleter = impl Fn(Q)->DeleteWhere<Q>;
fn deleter() -> Self::Deleter {
|q| DeleteWhere(q)
}
}
impl<R,Q> Delete<Q> for Option<R>
where
Q:QueryFilter,
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<R,Q> RevertableOp<Vec<R>> for DeleteWhere<Q>
where
R: Record,
Q: QueryFilter,
{
type Err = Infallible;
type Log = VecRemoved<R>;
fn apply(self, target: &mut Vec<R>)->Result<VecRemoved<R>, Infallible> {
let mut removed: Vec<(usize, R)> = vec![];
for i in (0..target.len()).rev() {
if self.0.test_record(&target[i]) {
removed.push((i, target.remove(i)))
}
}
Ok(VecRemoved(removed))
}
}
impl<R,Q> RevertableOp<Option<R>> for DeleteWhere<Q>
where
R: Record,
Q: QueryFilter,
{
type Err = Infallible;
type Log = OptRemoved<R>;
fn apply(self, target: &mut Option<R>)->Result<OptRemoved<R>, Infallible> {
if Option::as_mut(target)
.filter(|&&mut ref r| self.0.test_record(r))
.is_some() {
Ok(OptRemoved(target.take()))
} else {
Ok(OptRemoved(None))
}
}
}
pub struct VecRemoved<R>(Vec<(usize, R)>);
impl<R> UndoLog<Vec<R>> for VecRemoved<R> {
fn revert(self, dest: &mut Vec<R>) {
for (i,r) in self.0.into_iter().rev() {
dest.insert(i,r)
}
}
}
pub struct OptRemoved<R>(Option<R>);
impl<R> UndoLog<Option<R>> for OptRemoved<R> {
fn revert(self, dest: &mut Option<R>) {
if self.0.is_some() {
*dest = self.0;
}
}
}
#[test]
fn test_vec_delete() {
use tylisp::HNil;
use crate::query::filter::Exact;
use crate::relation::RelProxy;
col!{pub A: u32};
col!{pub B: u32};
let orig = vec![
(A(1), B(3)),
(A(2), B(2)),
(A(3), B(3)),
];
let mut v = orig.clone();
let undo = DeleteWhere(HNil).apply(&mut v).unwrap();
assert_eq!(v, vec![]);
undo.revert(&mut v);
assert_eq!(v, orig);
let mut v = orig.clone();
RelProxy::<&mut Vec<_>>::new(&mut v).truncate().unwrap();
assert_eq!(v, vec![]);
let mut v = orig.clone();
let undo = DeleteWhere(Exact(A(2))).apply(&mut v).unwrap();
assert_eq!(v, vec![(A(1), B(3)), (A(3), B(3))]);
undo.revert(&mut v);
assert_eq!(v, orig);
let mut v = orig.clone();
RelProxy::<&mut Vec<_>>::new(&mut v).where_eq(&A(2)).truncate().unwrap();
assert_eq!(v, vec![(A(1), B(3)), (A(3), B(3))]);
let mut v = orig.clone();
let undo = DeleteWhere(Exact(B(3))).apply(&mut v).unwrap();
assert_eq!(v, vec![(A(2), B(2))]);
undo.revert(&mut v);
assert_eq!(v, orig);
let mut v = orig.clone();
RelProxy::<&mut Vec<_>>::new(&mut v).where_eq(&B(3)).truncate().unwrap();
assert_eq!(v, vec![(A(2), B(2))]);
}
#[test]
fn test_opt_delete() {
use tylisp::HNil;
use crate::query::filter::Exact;
use crate::relation::RelProxy;
col!{pub A: u32};
col!{pub B: u32};
let orig = Some((A(1), B(3)));
let mut v = orig.clone();
let undo = DeleteWhere(HNil).apply(&mut v).unwrap();
assert_eq!(v, None);
undo.revert(&mut v);
assert_eq!(v, orig);
let mut v = orig.clone();
RelProxy::<&mut _>::new(&mut v).truncate().unwrap();
assert_eq!(v, None);
let mut v = orig.clone();
let undo = DeleteWhere(Exact(A(2))).apply(&mut v).unwrap();
assert_eq!(v, orig);
undo.revert(&mut v);
assert_eq!(v, orig);
let mut v = orig.clone();
RelProxy::<&mut _>::new(&mut v).where_eq(&A(2)).truncate().unwrap();
assert_eq!(v, orig);
let mut v = orig.clone();
let undo = DeleteWhere(Exact(B(3))).apply(&mut v).unwrap();
assert_eq!(v, None);
undo.revert(&mut v);
assert_eq!(v, orig);
let mut v = orig.clone();
RelProxy::<&mut _>::new(&mut v).where_eq(&B(3)).truncate().unwrap();
assert_eq!(v, None);
}
#[test]
fn test_vec_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;
use crate::query::request::{BlankRequest, QueryRequest};
assert_trait!{ BlankRequest: QueryRequest };
let all:Vec<_> = rel.query(BlankRequest).collect();
assert_eq!(3, all.len());
use crate::record::{Record};
use crate::query::filter::Exact;
use crate::query::order::{Asc, Desc};
assert_eq!(vec![11,7],
rel.query(BlankRequest.add_filter(Exact(A(3))))
.map(|rec| **rec.col_ref::<B>() )
.collect::<Vec<_>>()
);
assert_eq!(vec![7,3,3],
rel.query(BlankRequest.set_order::<sexpr!{Asc<B>}>()
)
.map(|rec| **rec.col_ref::<A>() )
.collect::<Vec<_>>()
);
assert_eq!(vec![3,3,7],
rel.query(BlankRequest.set_order::<sexpr!{Desc<B>}>()
)
.map(|rec| **rec.col_ref::<A>() )
.collect::<Vec<_>>()
);
assert_eq!(vec![7,11,5],
rel.query(BlankRequest.set_order::<sexpr!{Asc<A>, Asc<B>}>()
)
.map(|rec| **rec.col_ref::<B>() )
.collect::<Vec<_>>()
);
assert_eq!(vec![7,11],
rel.query(BlankRequest.add_filter(Exact(A(3)))
.set_order::<sexpr!{Asc<B>}>())
.map(|rec| **rec.col_ref::<B>() )
.collect::<Vec<_>>()
);
assert_eq!(vec![11, 7],
rel.query(BlankRequest.set_order::<sexpr!{Desc<B>}>()
.add_filter(Exact(A(3))))
.map(|rec| **rec.col_ref::<B>() )
.collect::<Vec<_>>()
);
}
#[test]
fn test_option_rel() {
col!{pub A: u32};
col!{pub B: u32};
col!{pub C: u32};
use tylisp::sexpr;
assert_trait!{ (A,B): Record };
assert_trait!{ Option<(A,B)>: RelationImpl };
assert_trait!{ Option<(A,B)>: for<'a> Relation<'a> };
type RelUnderTest = Option<(A,B)>;
let mut rel: RelUnderTest = Default::default();
assert!(<RelUnderTest as Insert<_>>::insert(&mut rel, (A(3), B(11))).is_ok());
rel = None;
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_err());
let rel = rel;
use crate::query::request::{BlankRequest, QueryRequest};
assert_trait!{ BlankRequest: QueryRequest };
let all:Vec<_> = rel.query(BlankRequest).collect();
assert_eq!(1, all.len());
use crate::record::{Record};
use crate::query::filter::Exact;
use crate::query::order::{Asc, Desc};
assert_eq!(vec![7],
rel.query(BlankRequest.add_filter(Exact(A(3))))
.map(|rec| **rec.col_ref::<B>() )
.collect::<Vec<_>>()
);
assert_eq!(vec![3],
rel.query(BlankRequest.set_order::<sexpr!{Asc<B>}>()
)
.map(|rec| **rec.col_ref::<A>() )
.collect::<Vec<_>>()
);
assert_eq!(vec![7],
rel.query(BlankRequest.add_filter(Exact(A(3)))
.set_order::<sexpr!{Asc<B>}>())
.map(|rec| **rec.col_ref::<B>() )
.collect::<Vec<_>>()
);
assert_eq!(Vec::<u32>::new(),
rel.query(BlankRequest.set_order::<sexpr!{Desc<B>}>()
.add_filter(Exact(A(5))))
.map(|rec| **rec.col_ref::<B>() )
.collect::<Vec<_>>()
);
}