mod test_helpers;
use std::collections::BTreeMap;
use lora_database::{LoraValue, PlanTreeNode};
use serde_json::{json, Value};
use test_helpers::TestDb;
fn graph() -> TestDb {
let db = TestDb::new();
db.run("CREATE CONSTRAINT m_key IF NOT EXISTS FOR (n:M) REQUIRE n.key IS UNIQUE");
db.run(
"UNWIND range(1, 40) AS i CREATE (m:M {key: toString(i)}) \
WITH m, i WHERE i % 2 = 0 CREATE (:P)-[:SENT]->(m)",
);
db
}
fn keys(db: &TestDb, query: &str) -> Vec<Value> {
let mut params = BTreeMap::new();
params.insert(
"keys".to_string(),
LoraValue::List((1..=6).map(|i| LoraValue::String(i.to_string())).collect()),
);
let mut out: Vec<Value> = db
.run_with_params(query, params)
.into_iter()
.map(|r| r["k"].clone())
.collect();
out.sort_by_key(|v| v.as_str().unwrap_or_default().parse::<i64>().unwrap_or(0));
out
}
fn odd() -> Vec<Value> {
vec![json!("1"), json!("3"), json!("5")]
}
#[test]
fn pattern_comprehension_after_with_sees_the_projected_variable() {
let db = graph();
let written = "UNWIND $keys AS k MATCH (a:M) WHERE a.key = k \
WITH a WHERE size([(a)<-[:SENT]-(x) WHERE x:P | 1]) = 0 RETURN a.key AS k";
let bound = "UNWIND $keys AS k MATCH (a:M) WHERE a.key = k \
WITH a, size([(a)<-[:SENT]-(x) WHERE x:P | 1]) AS c WHERE c = 0 RETURN a.key AS k";
assert_eq!(keys(&db, written), odd());
assert_eq!(keys(&db, bound), odd());
}
#[test]
fn without_a_seek_and_with_renames_too() {
let db = graph();
assert_eq!(
keys(
&db,
"MATCH (a:M) WHERE a.key IN $keys WITH a WHERE size([(a)<-[:SENT]-() | 1]) = 0 RETURN a.key AS k"
),
odd()
);
assert_eq!(
keys(
&db,
"MATCH (a:M) WHERE a.key IN $keys WITH a AS b WHERE size([(b)<-[:SENT]-() | 1]) = 0 RETURN b.key AS k"
),
odd()
);
assert_eq!(
keys(
&db,
"MATCH (a:M) WHERE a.key IN $keys WITH a WHERE NOT EXISTS { (a)<-[:SENT]-() } RETURN a.key AS k"
),
odd()
);
}
fn operators(node: &PlanTreeNode, out: &mut Vec<String>) {
out.push(node.operator.clone());
for child in &node.children {
operators(child, out);
}
}
#[test]
fn the_seek_feeding_the_with_is_kept() {
let db = graph();
let plan = db
.service
.explain(
"UNWIND $keys AS k MATCH (a:M) WHERE a.key = k \
WITH a WHERE size([(a)<-[:SENT]-(x) | 1]) = 0 RETURN a.key AS k",
None,
)
.unwrap();
let mut ops = Vec::new();
operators(&plan.tree.root, &mut ops);
assert!(ops.iter().any(|o| o == "NodeByPropertyScan"), "{ops:?}");
assert!(!ops.iter().any(|o| o == "NodeScan"), "{ops:?}");
let with_projection = ops
.iter()
.enumerate()
.filter(|(_, o)| *o == "Projection")
.nth(1)
.map(|(i, _)| i)
.unwrap();
let first_filter = ops.iter().position(|o| o == "Filter").unwrap();
assert!(first_filter < with_projection, "{ops:?}");
}