//! Hand-written query plans composed from `scan_atom`, `semijoin`, and `natural_join`. //! //! Schema: //! - `edge(src, dst)`: directed edges //! - `labeled(node)`: a set of labeled nodes //! //! Two rules are executed against the same fixture: //! - `Q1(X) :- edge(X, X), labeled(X).` (labeled self-loops) //! - `Q2(X, Y) :- edge(X, Y), labeled(Y).` (edges whose destination is labeled) use query_ops::atom::{scan_atom, AtomPattern, Term}; use query_ops::join::{natural_join, semijoin}; use query_ops::table::Table; use query_ops::value::Value; fn var(name: &str) -> Term { Term::Var(name.to_string()) } fn int(value: i64) -> Value { Value::Int(value) } #[test] fn labeled_self_loops_and_edges_into_labeled_nodes() { let edge = Table::from_rows( 2, vec![ vec![int(1), int(2)], vec![int(2), int(3)], vec![int(3), int(3)], vec![int(4), int(1)], vec![int(2), int(2)], ], ); let labeled = Table::from_rows(1, vec![vec![int(2)], vec![int(3)]]); let self_loops = scan_atom( &edge, &AtomPattern { columns: vec![var("X"), var("X")], }, ); let labeled_x = scan_atom( &labeled, &AtomPattern { columns: vec![var("X")], }, ); let q1 = semijoin(&self_loops, &labeled_x); assert_eq!(q1.columns, vec!["X".to_string()]); assert_eq!(q1.rows, vec![vec![int(3)], vec![int(2)]]); let edge_xy = scan_atom( &edge, &AtomPattern { columns: vec![var("X"), var("Y")], }, ); let labeled_y = scan_atom( &labeled, &AtomPattern { columns: vec![var("Y")], }, ); let q2 = natural_join(&edge_xy, &labeled_y); assert_eq!(q2.columns, vec!["X".to_string(), "Y".to_string()]); assert_eq!( q2.rows, vec![ vec![int(1), int(2)], vec![int(2), int(3)], vec![int(3), int(3)], vec![int(2), int(2)], ], ); }