use super::{evaluate, expression_ext::ExpressionExt, helpers::gallop, Database};
use crate::{expression::Expression, Error, Tuple};
use std::any::Any;
use std::{
cell::{Ref, RefCell},
ops::Deref,
rc::Rc,
};
#[derive(Clone, Debug, PartialEq)]
pub struct Tuples<T: Tuple> {
items: Vec<T>,
}
impl<T: Tuple, I: IntoIterator<Item = T>> From<I> for Tuples<T> {
fn from(iterator: I) -> Self {
let mut items: Vec<T> = iterator.into_iter().collect();
items.sort_unstable();
items.dedup();
Tuples { items }
}
}
impl<T: Tuple> Tuples<T> {
pub(crate) fn merge(self, other: Self) -> Self {
let mut tuples = Vec::with_capacity(self.items.len() + other.items.len());
tuples.extend(self.items.into_iter());
tuples.extend(other.items.into_iter());
tuples.into()
}
pub fn items(&self) -> &[T] {
&self.items
}
#[inline(always)]
pub fn into_tuples(self) -> Vec<T> {
self.items
}
}
impl<T: Tuple> Deref for Tuples<T> {
type Target = Vec<T>;
fn deref(&self) -> &Self::Target {
&self.items
}
}
impl<T: Tuple> core::ops::DerefMut for Tuples<T> {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.items
}
}
pub(super) trait DynInstance {
fn as_any(&self) -> &dyn Any;
fn changed(&self) -> bool;
fn clone_box(&self) -> Box<dyn DynInstance>;
}
pub(super) trait DynViewInstance {
fn as_any(&self) -> &dyn Any;
fn instance(&self) -> &dyn DynInstance;
fn initialize(&self, db: &Database) -> Result<(), Error>;
fn stabilize(&self, db: &Database) -> Result<(), Error>;
fn clone_box(&self) -> Box<dyn DynViewInstance>;
}
#[derive(Debug, PartialEq)]
pub(super) struct Instance<T: Tuple> {
stable: Rc<RefCell<Vec<Tuples<T>>>>,
recent: Rc<RefCell<Tuples<T>>>,
to_add: Rc<RefCell<Vec<Tuples<T>>>>,
}
impl<T: Tuple> Instance<T> {
pub fn new() -> Self {
Self {
stable: Rc::new(RefCell::new(Vec::new())),
recent: Rc::new(RefCell::new(Vec::new().into())),
to_add: Rc::new(RefCell::new(Vec::new())),
}
}
pub fn insert(&self, tuples: Tuples<T>) {
if !tuples.is_empty() {
self.to_add.borrow_mut().push(tuples);
}
}
#[inline(always)]
pub fn stable(&self) -> Ref<Vec<Tuples<T>>> {
self.stable.borrow()
}
#[inline(always)]
pub fn recent(&self) -> Ref<Tuples<T>> {
self.recent.borrow()
}
#[inline(always)]
pub fn to_add(&self) -> Ref<Vec<Tuples<T>>> {
self.to_add.borrow()
}
}
impl<T: Tuple> Clone for Instance<T> {
fn clone(&self) -> Self {
Self {
stable: Rc::new(RefCell::new(self.stable.borrow().clone())),
recent: Rc::new(RefCell::new(self.recent.borrow().clone())),
to_add: Rc::new(RefCell::new(self.to_add.borrow().clone())),
}
}
}
impl<T> DynInstance for Instance<T>
where
T: Tuple + 'static,
{
fn as_any(&self) -> &dyn Any {
self
}
fn changed(&self) -> bool {
if !self.recent.borrow().is_empty() {
let mut recent =
::std::mem::replace(&mut (*self.recent.borrow_mut()), Vec::new().into());
while self
.stable
.borrow()
.last()
.map(|x| x.len() <= 2 * recent.len())
== Some(true)
{
let last = self.stable.borrow_mut().pop().unwrap();
recent = recent.merge(last);
}
self.stable.borrow_mut().push(recent);
}
let to_add = self.to_add.borrow_mut().pop();
if let Some(mut to_add) = to_add {
while let Some(to_add_more) = self.to_add.borrow_mut().pop() {
to_add = to_add.merge(to_add_more);
}
for batch in self.stable.borrow().iter() {
let mut slice = &batch[..];
to_add.items.retain(|x| {
slice = gallop(slice, |y| y < x);
slice.is_empty() || &slice[0] != x
});
}
*self.recent.borrow_mut() = to_add;
}
!self.recent.borrow().is_empty()
}
fn clone_box(&self) -> Box<dyn DynInstance> {
let mut to_add = Vec::new();
for batch in self.to_add.borrow().iter() {
to_add.push(batch.clone());
}
let recent = (*self.recent.borrow()).clone();
let mut stable: Vec<Tuples<T>> = Vec::new();
for batch in self.stable.borrow().iter() {
stable.push(batch.clone());
}
Box::new(Self {
stable: Rc::new(RefCell::new(stable)),
recent: Rc::new(RefCell::new(recent)),
to_add: Rc::new(RefCell::new(to_add)),
})
}
}
pub(super) struct ViewInstance<T, E>
where
T: Tuple,
E: Expression<T>,
{
instance: Instance<T>,
expression: E,
}
impl<T, E> ViewInstance<T, E>
where
T: Tuple,
E: Expression<T>,
{
pub fn new(expression: E) -> Self {
Self {
instance: Instance::new(),
expression,
}
}
pub fn instance(&self) -> &Instance<T> {
&self.instance
}
}
impl<T, E> DynViewInstance for ViewInstance<T, E>
where
T: Tuple + 'static,
E: ExpressionExt<T> + 'static,
{
fn as_any(&self) -> &dyn Any {
self
}
fn instance(&self) -> &dyn DynInstance {
&self.instance
}
fn initialize(&self, db: &Database) -> Result<(), Error> {
let incremental = evaluate::IncrementalCollector::new(db);
let stable = self.expression.collect_stable(&incremental)?;
for batch in stable {
self.instance.insert(batch);
}
Ok(())
}
fn stabilize(&self, db: &Database) -> Result<(), Error> {
let incremental = evaluate::IncrementalCollector::new(db);
let recent = self.expression.collect_recent(&incremental)?;
self.instance.insert(recent);
Ok(())
}
fn clone_box(&self) -> Box<dyn DynViewInstance> {
Box::new(Self {
instance: self.instance.clone(),
expression: self.expression.clone(),
})
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_clone_instance() {
{
let instance = Instance::<bool>::new();
assert_eq!(instance, instance.clone());
}
{
let instance = Instance::<i32> {
stable: Rc::new(RefCell::new(vec![vec![1, 2].into()])),
recent: Rc::new(RefCell::new(vec![2, 3, 4].into())),
to_add: Rc::new(RefCell::new(vec![vec![4, 5].into()])),
};
let cloned = instance.clone();
assert_eq!(instance, cloned);
}
}
#[test]
fn test_tuples_from_list() {
{
let tuples = Tuples::<i32>::from(vec![]);
assert_eq!(Vec::<i32>::new(), tuples.items());
}
{
let tuples = Tuples::<i32>::from(vec![5, 4, 2, 1, 3]);
assert_eq!(vec![1, 2, 3, 4, 5], tuples.items());
}
{
let tuples = Tuples::<i32>::from(vec![3, 2, 2, 1, 3]);
assert_eq!(vec![1, 2, 3], tuples.items());
}
}
#[test]
fn test_tuples_merge() {
{
let tuples = Tuples::<i32>::from(vec![]);
assert_eq!(Vec::<i32>::new(), tuples.merge(vec![].into()).items());
}
{
let tuples = Tuples::<i32>::from(vec![5, 4]);
assert_eq!(vec![2, 3, 4, 5], tuples.merge(vec![2, 3].into()).items());
}
{
let tuples = Tuples::<i32>::from(vec![5, 4, 4]);
assert_eq!(vec![3, 4, 5], tuples.merge(vec![5, 3].into()).items());
}
}
#[test]
fn test_instance_insert() {
{
let relation = Instance::<i32> {
stable: Rc::new(RefCell::new(vec![])),
recent: Rc::new(RefCell::new(vec![].into())),
to_add: Rc::new(RefCell::new(vec![])),
};
relation.insert(vec![].into());
assert_eq!(Vec::<Tuples<i32>>::new(), *relation.stable.borrow());
assert_eq!(Vec::<i32>::new(), relation.recent.borrow().items);
assert_eq!(Vec::<Tuples<i32>>::new(), *relation.to_add.borrow());
}
{
let relation: Instance<i32> = Instance {
stable: Rc::new(RefCell::new(vec![])),
recent: Rc::new(RefCell::new(vec![1, 2, 3].into())),
to_add: Rc::new(RefCell::new(vec![])),
};
relation.insert(vec![].into());
assert_eq!(Vec::<Tuples<i32>>::new(), *relation.stable.borrow());
assert_eq!(vec![1, 2, 3], relation.recent.borrow().items);
assert_eq!(Vec::<Tuples<i32>>::new(), *relation.to_add.borrow());
}
{
let relation: Instance<i32> = Instance {
stable: Rc::new(RefCell::new(vec![])),
recent: Rc::new(RefCell::new(vec![1, 2, 3].into())),
to_add: Rc::new(RefCell::new(vec![])),
};
relation.insert(vec![5, 4].into());
assert_eq!(Vec::<Tuples<i32>>::new(), *relation.stable.borrow());
assert_eq!(vec![1, 2, 3], relation.recent.borrow().items);
assert_eq!(
Vec::<Tuples<i32>>::from(vec![vec![4, 5].into()]),
*relation.to_add.borrow(),
);
}
}
#[test]
fn test_instance_changed() {
{
let relation: Instance<i32> = Instance {
stable: Rc::new(RefCell::new(vec![])),
recent: Rc::new(RefCell::new(vec![].into())),
to_add: Rc::new(RefCell::new(vec![])),
};
relation.changed();
assert_eq!(Vec::<Tuples<i32>>::new(), *relation.stable.borrow());
assert_eq!(Vec::<i32>::new(), relation.recent.borrow().items);
assert_eq!(Vec::<Tuples<i32>>::new(), *relation.to_add.borrow());
}
{
let relation = Instance::<i32> {
stable: Rc::new(RefCell::new(vec![])),
recent: Rc::new(RefCell::new(vec![].into())),
to_add: Rc::new(RefCell::new(vec![vec![1, 2].into()])),
};
assert!(relation.changed());
assert_eq!(Vec::<Tuples<i32>>::new(), *relation.stable.borrow());
assert_eq!(vec![1, 2], relation.recent.borrow().items);
assert_eq!(Vec::<Tuples<i32>>::new(), *relation.to_add.borrow());
}
{
let relation = Instance::<i32> {
stable: Rc::new(RefCell::new(vec![])),
recent: Rc::new(RefCell::new(vec![1, 2].into())),
to_add: Rc::new(RefCell::new(vec![])),
};
assert!(!relation.changed());
assert_eq!(
Vec::<Tuples<i32>>::from(vec![vec![1, 2].into()]),
*relation.stable.borrow()
);
assert_eq!(Vec::<i32>::new(), relation.recent.borrow().items);
assert_eq!(Vec::<Tuples<i32>>::new(), *relation.to_add.borrow());
}
{
let relation = Instance::<i32> {
stable: Rc::new(RefCell::new(vec![])),
recent: Rc::new(RefCell::new(vec![1, 2].into())),
to_add: Rc::new(RefCell::new(vec![vec![3, 4].into()])),
};
assert!(relation.changed());
assert_eq!(
Vec::<Tuples<i32>>::from(vec![vec![1, 2].into()]),
*relation.stable.borrow()
);
assert_eq!(vec![3, 4], relation.recent.borrow().items);
assert_eq!(Vec::<Tuples<i32>>::new(), *relation.to_add.borrow());
}
{
let relation = Instance::<i32> {
stable: Rc::new(RefCell::new(vec![vec![1, 2].into()])),
recent: Rc::new(RefCell::new(vec![2, 3, 4].into())),
to_add: Rc::new(RefCell::new(vec![vec![4, 5].into()])),
};
assert!(relation.changed());
assert_eq!(
Vec::<Tuples<i32>>::from(vec![vec![1, 2, 3, 4].into()]),
*relation.stable.borrow()
);
assert_eq!(vec![5], relation.recent.borrow().items);
assert_eq!(Vec::<Tuples<i32>>::new(), *relation.to_add.borrow());
}
{
let relation = Instance::<i32> {
stable: Rc::new(RefCell::new(vec![vec![1, 2].into()])),
recent: Rc::new(RefCell::new(vec![2, 3, 4].into())),
to_add: Rc::new(RefCell::new(vec![vec![1, 5].into()])),
};
assert!(relation.changed());
assert_eq!(
Vec::<Tuples<i32>>::from(vec![vec![1, 2, 3, 4].into()]),
*relation.stable.borrow()
);
assert_eq!(vec![5], relation.recent.borrow().items);
assert_eq!(Vec::<Tuples<i32>>::new(), *relation.to_add.borrow());
}
}
}