test(engine): anti-join fast-vs-slow path equivalence harness

anti_join_fast_and_slow_paths_agree: the CSR has_neighbors fast path
(not { $p worksAt $_ }) and the set-oriented inner-pipeline replay (same
negation forced slow by an always-true $c.name != "" dst filter) must produce
the same result ([Charlie, Diana]). Closes the second real engine fork explicitly.
This commit is contained in:
Ragnor Comerford 2026-06-09 14:41:15 +02:00
parent e674e0c3c4
commit ce2e3d4574
No known key found for this signature in database

View file

@ -85,6 +85,55 @@ query no_nonacme_employer() {
assert_eq!(names_vec, vec!["Alice", "Charlie", "Diana"]);
}
// The anti-join has two execution forks: the CSR `has_neighbors` fast path
// (bare single-op Expand inner) and the set-oriented inner-pipeline replay (when
// dst_filters force a multi-op inner). They must agree. `not { $p worksAt $_ }`
// takes the fast path; the same negation with an always-true dst filter
// (`$c.name != ""`) is semantically identical but forces the slow path.
#[tokio::test]
async fn anti_join_fast_and_slow_paths_agree() {
let dir = tempfile::tempdir().unwrap();
let mut db = init_and_load(&dir).await;
let queries = r#"
query fast() {
match {
$p: Person
not { $p worksAt $_ }
}
return { $p.name }
}
query slow() {
match {
$p: Person
not {
$p worksAt $c
$c.name != ""
}
}
return { $p.name }
}
"#;
let names = |result: omnigraph_compiler::result::QueryResult| {
let batch = result.concat_batches().unwrap();
let col = batch
.column(0)
.as_any()
.downcast_ref::<StringArray>()
.unwrap();
let mut v: Vec<String> = (0..col.len()).map(|i| col.value(i).to_string()).collect();
v.sort();
v
};
let fast = names(query_main(&mut db, queries, "fast", &ParamMap::new()).await.unwrap());
let slow = names(query_main(&mut db, queries, "slow", &ParamMap::new()).await.unwrap());
assert_eq!(fast, slow, "anti-join fast and slow paths must agree");
// Alice->Acme, Bob->Globex employed; Charlie & Diana have no employer.
assert_eq!(fast, vec!["Charlie", "Diana"]);
}
// ─── Variable-length hops ───────────────────────────────────────────────────
const CHAIN_SCHEMA: &str = r#"