//! End-to-end: load rows into [`MemoryStorage`], scan as a [`Table`], //! run [`scan_atom`] against it. //! //! Demonstrates that `query-ops` operators can consume from a storage backend //! through the [`scan_as_table`] bridge, with no changes to `query-ops` itself. use query_ops::atom::{AtomPattern, Term, scan_atom}; use query_storage::table::Table; use query_storage::value::Value; use query_storage::{MemoryStorage, Storage, StorageError, scan_as_table}; fn i(x: i64) -> Value { Value::Int(x) } fn var(name: &str) -> Term { Term::Var(name.to_string()) } #[test] fn scan_atom_consumes_from_memory_backend() -> Result<(), StorageError> { let mut storage = MemoryStorage::new(); storage.create_relation("edge", 2)?; storage.insert("edge", vec![i(1), i(2)])?; storage.insert("edge", vec![i(2), i(2)])?; storage.insert("edge", vec![i(3), i(3)])?; storage.insert("edge", vec![i(4), i(5)])?; let edge_table: Table = scan_as_table(&storage, "edge")?; let self_loops = scan_atom( &edge_table, &AtomPattern { columns: vec![var("X"), var("X")], }, ); assert_eq!(self_loops.columns, vec!["X".to_string()]); assert_eq!(self_loops.rows, vec![vec![i(2)], vec![i(3)]]); Ok(()) }