use rusqlite::Connection;
const SCHEMA: &str = r#"
PRAGMA foreign_keys = ON;
CREATE TABLE graph_nodes (
id TEXT PRIMARY KEY,
kind TEXT NOT NULL,
label TEXT NOT NULL,
properties_json TEXT NOT NULL DEFAULT '{}',
provenance_json TEXT NOT NULL DEFAULT '[]',
freshness_json TEXT,
row_hash TEXT,
source_watermark TEXT
);
CREATE INDEX idx_graph_nodes_kind ON graph_nodes(kind);
CREATE INDEX idx_graph_nodes_kind_label ON graph_nodes(kind, label, id);
CREATE TABLE graph_edges (
edge_key TEXT NOT NULL UNIQUE,
from_id TEXT NOT NULL,
to_id TEXT NOT NULL,
kind TEXT NOT NULL,
properties_json TEXT NOT NULL DEFAULT '{}',
provenance_json TEXT NOT NULL DEFAULT '[]',
freshness_json TEXT,
row_hash TEXT,
source_watermark TEXT,
PRIMARY KEY (from_id, to_id, kind)
);
CREATE INDEX idx_graph_edges_from_kind ON graph_edges(from_id, kind);
CREATE INDEX idx_graph_edges_to_kind ON graph_edges(to_id, kind);
CREATE UNIQUE INDEX idx_graph_edges_edge_key ON graph_edges(edge_key);
CREATE TABLE graph_node_properties (
node_id TEXT NOT NULL,
key TEXT NOT NULL,
value TEXT NOT NULL,
PRIMARY KEY (node_id, key)
);
CREATE INDEX idx_graph_node_properties_key_value_node
ON graph_node_properties(key, value, node_id);
CREATE TABLE graph_edge_properties (
edge_key TEXT NOT NULL,
key TEXT NOT NULL,
value TEXT NOT NULL,
PRIMARY KEY (edge_key, key)
);
CREATE INDEX idx_graph_edge_properties_key_value_edge
ON graph_edge_properties(key, value, edge_key);
"#;
const HUB_LEAVES: usize = 1_000;
const CHAIN_DEPTH: usize = 500;
fn build_synthetic_graph() -> Connection {
let conn = Connection::open_in_memory().unwrap();
conn.execute_batch(SCHEMA).unwrap();
let tx_conn = &conn;
let tx = tx_conn.unchecked_transaction().unwrap();
tx.execute(
"INSERT INTO graph_nodes(id, kind, label) VALUES ('hub-0', 'file', 'hub_file.rs')",
[],
)
.unwrap();
{
let mut insert_node = tx
.prepare("INSERT INTO graph_nodes(id, kind, label) VALUES (?1, 'symbol', ?2)")
.unwrap();
let mut insert_edge = tx
.prepare("INSERT INTO graph_edges(edge_key, from_id, to_id, kind) VALUES (?1, 'hub-0', ?2, 'defines')")
.unwrap();
let mut insert_node_prop = tx
.prepare(
"INSERT INTO graph_node_properties(node_id, key, value) VALUES (?1, 'path', ?2)",
)
.unwrap();
let mut insert_edge_prop = tx
.prepare(
"INSERT INTO graph_edge_properties(edge_key, key, value) VALUES (?1, 'label', ?2)",
)
.unwrap();
for idx in 0..HUB_LEAVES {
let node_id = format!("leaf-{idx:05}");
let edge_key = format!("edge-hub-{idx:05}");
let path = if idx % 3 == 0 {
"src/lib.rs"
} else {
"src/main.rs"
};
let label = if idx % 10 == 0 { "hot" } else { "cold" };
insert_node.execute((&node_id, &node_id)).unwrap();
insert_edge.execute((&edge_key, &node_id)).unwrap();
insert_node_prop.execute((&node_id, path)).unwrap();
insert_edge_prop.execute((&edge_key, label)).unwrap();
}
}
{
let mut insert_node = tx
.prepare("INSERT INTO graph_nodes(id, kind, label) VALUES (?1, 'symbol', ?1)")
.unwrap();
for idx in 0..CHAIN_DEPTH {
let id = format!("chain-{idx:05}");
insert_node.execute([&id]).unwrap();
}
let mut insert_edge = tx
.prepare(
"INSERT INTO graph_edges(edge_key, from_id, to_id, kind) \
VALUES (?1, ?2, ?3, 'calls')",
)
.unwrap();
for idx in 0..(CHAIN_DEPTH - 1) {
let edge_key = format!("edge-chain-{idx:05}");
let from = format!("chain-{idx:05}");
let to = format!("chain-{:05}", idx + 1);
insert_edge.execute((&edge_key, &from, &to)).unwrap();
}
}
tx.commit().unwrap();
conn.execute_batch("ANALYZE").unwrap();
conn
}
fn query_plan(conn: &Connection, sql: &str) -> String {
let mut stmt = conn.prepare(&format!("EXPLAIN QUERY PLAN {sql}")).unwrap();
let rows: Vec<String> = stmt
.query_map([], |row| row.get::<_, String>(3))
.unwrap()
.map(|r| r.unwrap())
.collect();
rows.join("\n")
}
fn assert_plan_uses(plan: &str, indexes: &[&str], shape: &str) {
for index in indexes {
assert!(
plan.contains(index),
"{shape} plan must use {index}; got plan:\n{plan}"
);
}
let lower = plan.to_lowercase();
assert!(
!lower.contains("scan graph_edges") && !lower.contains("scan graph_nodes"),
"{shape} plan must not scan base tables; got plan:\n{plan}"
);
}
#[test]
fn edge_property_scan_uses_property_and_edge_key_indexes() {
let conn = build_synthetic_graph();
let sql = "SELECT e.edge_key, e.from_id, e.to_id, e.kind \
FROM graph_edge_properties ep0 INDEXED BY idx_graph_edge_properties_key_value_edge \
JOIN graph_edges e INDEXED BY idx_graph_edges_edge_key ON e.edge_key = ep0.edge_key \
WHERE ep0.key = 'label' AND ep0.value = 'cold' AND e.kind = 'defines' \
ORDER BY ep0.edge_key LIMIT 51";
let plan = query_plan(&conn, sql);
assert_plan_uses(
&plan,
&[
"idx_graph_edge_properties_key_value_edge",
"idx_graph_edges_edge_key",
],
"edge_property_scan",
);
}
#[test]
fn incident_edges_union_uses_directional_indexes_on_hub() {
let conn = build_synthetic_graph();
let sql = "SELECT edge_key, from_id, to_id, kind FROM ( \
SELECT e.edge_key, e.from_id, e.to_id, e.kind \
FROM graph_edges e INDEXED BY idx_graph_edges_from_kind \
WHERE e.from_id = 'hub-0' \
UNION \
SELECT e.edge_key, e.from_id, e.to_id, e.kind \
FROM graph_edges e INDEXED BY idx_graph_edges_to_kind \
WHERE e.to_id = 'hub-0' \
) e ORDER BY e.edge_key LIMIT 51";
let plan = query_plan(&conn, sql);
assert_plan_uses(
&plan,
&["idx_graph_edges_from_kind", "idx_graph_edges_to_kind"],
"incident_edges",
);
}
#[test]
fn kind_property_filter_uses_kind_and_property_indexes() {
let conn = build_synthetic_graph();
let sql = "SELECT id, kind, label FROM graph_nodes \
WHERE kind = 'symbol' \
AND EXISTS ( \
SELECT 1 FROM graph_node_properties p0 \
INDEXED BY idx_graph_node_properties_key_value_node \
WHERE p0.node_id = graph_nodes.id \
AND p0.key = 'path' AND p0.value = 'src/main.rs' \
) \
ORDER BY id LIMIT 51";
let plan = query_plan(&conn, sql);
assert_plan_uses(
&plan,
&[
"idx_graph_nodes_kind_label",
"idx_graph_node_properties_key_value_node",
],
"kind_property_filter",
);
}
#[test]
fn path_frontier_probe_uses_from_kind_index_on_hub_and_chain() {
let conn = build_synthetic_graph();
let probe_sql = "SELECT from_id, to_id FROM graph_edges INDEXED BY idx_graph_edges_from_kind \
WHERE from_id = ?1 ORDER BY from_id, to_id, kind";
for node in ["hub-0", "chain-00000", "chain-00250"] {
let sql = probe_sql.replace("?1", &format!("'{node}'"));
let plan = query_plan(&conn, &sql);
assert_plan_uses(&plan, &["idx_graph_edges_from_kind"], "path_frontier");
}
}
#[test]
fn path_frontier_chunk_uses_from_kind_index() {
let conn = build_synthetic_graph();
let sql = "SELECT from_id, to_id FROM graph_edges INDEXED BY idx_graph_edges_from_kind \
WHERE from_id IN ('hub-0', 'chain-00000', 'chain-00250') \
AND kind = 'calls' \
ORDER BY from_id, to_id, kind";
let plan = query_plan(&conn, sql);
assert_plan_uses(&plan, &["idx_graph_edges_from_kind"], "path_frontier_chunk");
}