use super::{view::ViewRef, Expression, IntoExpression, Visitor};
use crate::Tuple;
use std::marker::PhantomData;
#[derive(Clone, Debug)]
pub struct Intersect<T, L, R>
where
T: Tuple,
L: Expression<T>,
R: Expression<T>,
{
left: L,
right: R,
relation_deps: Vec<String>,
view_deps: Vec<ViewRef>,
_marker: PhantomData<T>,
}
impl<T, L, R> Intersect<T, L, R>
where
T: Tuple,
L: Expression<T>,
R: Expression<T>,
{
pub fn new<IL, IR>(left: IL, right: IR) -> Self
where
IL: IntoExpression<T, L>,
IR: IntoExpression<T, R>,
{
use super::dependency;
let left = left.into_expression();
let right = right.into_expression();
let mut deps = dependency::DependencyVisitor::new();
left.visit(&mut deps);
right.visit(&mut deps);
let (relation_deps, view_deps) = deps.into_dependencies();
Self {
left,
right,
relation_deps: relation_deps.into_iter().collect(),
view_deps: view_deps.into_iter().collect(),
_marker: PhantomData,
}
}
#[inline(always)]
pub fn left(&self) -> &L {
&self.left
}
#[inline(always)]
pub fn right(&self) -> &R {
&self.right
}
#[inline(always)]
pub(crate) fn relation_deps(&self) -> &[String] {
&self.relation_deps
}
#[inline(always)]
pub(crate) fn view_deps(&self) -> &[ViewRef] {
&self.view_deps
}
}
impl<T, L, R> Expression<T> for Intersect<T, L, R>
where
T: Tuple,
L: Expression<T>,
R: Expression<T>,
{
fn visit<V>(&self, visitor: &mut V)
where
V: Visitor,
{
visitor.visit_intersect(&self);
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::{Database, Tuples};
#[test]
fn test_clone() {
let mut database = Database::new();
let r = database.add_relation::<i32>("r").unwrap();
let s = database.add_relation::<i32>("s").unwrap();
database.insert(&r, vec![1, 2, 3].into()).unwrap();
database.insert(&s, vec![1, 4, 3, 5].into()).unwrap();
let u = Intersect::new(r, s).clone();
assert_eq!(
Tuples::<i32>::from(vec![1, 3]),
database.evaluate(&u).unwrap()
);
}
}