use sparrowdb::{open, GraphDb};
use sparrowdb_execution::types::Value;
fn make_db() -> (tempfile::TempDir, GraphDb) {
let dir = tempfile::tempdir().expect("tempdir");
let db = open(dir.path()).expect("open");
(dir, db)
}
#[test]
fn delete_node_with_prop_filter() {
let (_dir, db) = make_db();
db.execute("CREATE (:Person {name: 'Alice'})")
.expect("CREATE must succeed");
let before = db
.execute("MATCH (n:Person {name: 'Alice'}) RETURN n.name")
.expect("MATCH before DELETE must succeed");
assert_eq!(
before.rows.len(),
1,
"expected 1 row before DELETE, got {}",
before.rows.len()
);
db.execute("MATCH (n:Person {name: 'Alice'}) DELETE n")
.expect("MATCH DELETE must succeed");
let after = db
.execute("MATCH (n:Person {name: 'Alice'}) RETURN n.name")
.expect("MATCH after DELETE must succeed");
assert_eq!(
after.rows.len(),
0,
"expected 0 rows after DELETE, got {}",
after.rows.len()
);
}
#[test]
fn delete_all_nodes_of_label() {
let (_dir, db) = make_db();
db.execute("CREATE (:Person {name: 'Alice'})")
.expect("CREATE Alice must succeed");
db.execute("CREATE (:Person {name: 'Bob'})")
.expect("CREATE Bob must succeed");
db.execute("CREATE (:Company {name: 'Acme'})")
.expect("CREATE Company must succeed");
let before = db
.execute("MATCH (n:Person) RETURN n.name")
.expect("MATCH before DELETE must succeed");
assert_eq!(before.rows.len(), 2, "expected 2 Person rows before DELETE");
db.execute("MATCH (n:Person) DELETE n")
.expect("DELETE all Person nodes must succeed");
let after = db
.execute("MATCH (n:Person) RETURN n.name")
.expect("MATCH after DELETE must succeed");
assert_eq!(
after.rows.len(),
0,
"expected 0 Person rows after DELETE all, got {}",
after.rows.len()
);
let company = db
.execute("MATCH (n:Company {name: 'Acme'}) RETURN n.name")
.expect("MATCH Company after Person DELETE must succeed");
assert_eq!(
company.rows.len(),
1,
"Company node must survive MATCH (n:Person) DELETE n"
);
}
#[test]
fn delete_nonexistent_node_is_noop() {
let (_dir, db) = make_db();
db.execute("CREATE (:Person {name: 'Bob'})")
.expect("CREATE must succeed");
db.execute("MATCH (n:Person {name: 'Nobody'}) DELETE n")
.expect("DELETE of non-existent node must be a no-op (no error)");
let after = db
.execute("MATCH (n:Person {name: 'Bob'}) RETURN n.name")
.expect("MATCH Bob after no-op DELETE must succeed");
assert_eq!(
after.rows.len(),
1,
"Bob must still exist after deleting Nobody"
);
}
#[test]
fn deleted_node_invisible_to_future_queries() {
let (_dir, db) = make_db();
db.execute("CREATE (:Person {name: 'Alice'})")
.expect("CREATE Alice");
db.execute("CREATE (:Person {name: 'Charlie'})")
.expect("CREATE Charlie");
db.execute("MATCH (n:Person {name: 'Alice'}) DELETE n")
.expect("DELETE Alice");
let remaining = db
.execute("MATCH (n:Person) RETURN n.name")
.expect("MATCH after partial DELETE");
assert_eq!(
remaining.rows.len(),
1,
"expected 1 remaining node after deleting Alice, got {}",
remaining.rows.len()
);
assert_eq!(
remaining.rows[0][0],
Value::String("Charlie".to_string()),
"expected remaining node to be Charlie"
);
let charlie = db
.execute("MATCH (n:Person {name: 'Charlie'}) RETURN n.name")
.expect("MATCH Charlie after DELETE");
assert_eq!(
charlie.rows.len(),
1,
"Charlie must remain after deleting Alice"
);
let alice = db
.execute("MATCH (n:Person {name: 'Alice'}) RETURN n.name")
.expect("MATCH Alice after DELETE");
assert_eq!(alice.rows.len(), 0, "Alice must not appear after DELETE");
}