2026-06-04 11:51:25 +02:00
|
|
|
//! 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.
|
|
|
|
|
|
2026-06-04 12:47:47 +02:00
|
|
|
use query_ops::atom::{scan_atom, AtomPattern, Term};
|
|
|
|
|
use storage::table::Table;
|
|
|
|
|
use storage::value::Value;
|
|
|
|
|
use storage::{scan_as_table, MemoryStorage, Storage, StorageError};
|
2026-06-04 11:51:25 +02:00
|
|
|
|
|
|
|
|
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(())
|
|
|
|
|
}
|