pub trait GraphBackend {
Show 21 methods
// Required methods
fn insert_node(&self, node: NodeSpec) -> Result<i64, SqliteGraphError>;
fn insert_edge(&self, edge: EdgeSpec) -> Result<i64, SqliteGraphError>;
fn update_node(
&self,
node_id: i64,
node: NodeSpec,
) -> Result<i64, SqliteGraphError>;
fn delete_entity(&self, id: i64) -> Result<(), SqliteGraphError>;
fn entity_ids(&self) -> Result<Vec<i64>, SqliteGraphError>;
fn get_node(
&self,
snapshot_id: SnapshotId,
id: i64,
) -> Result<GraphEntity, SqliteGraphError>;
fn neighbors(
&self,
snapshot_id: SnapshotId,
node: i64,
query: NeighborQuery,
) -> Result<Vec<i64>, SqliteGraphError>;
fn bfs(
&self,
snapshot_id: SnapshotId,
start: i64,
depth: u32,
) -> Result<Vec<i64>, SqliteGraphError>;
fn shortest_path(
&self,
snapshot_id: SnapshotId,
start: i64,
end: i64,
) -> Result<Option<Vec<i64>>, SqliteGraphError>;
fn node_degree(
&self,
snapshot_id: SnapshotId,
node: i64,
) -> Result<(usize, usize), SqliteGraphError>;
fn k_hop(
&self,
snapshot_id: SnapshotId,
start: i64,
depth: u32,
direction: BackendDirection,
) -> Result<Vec<i64>, SqliteGraphError>;
fn k_hop_filtered(
&self,
snapshot_id: SnapshotId,
start: i64,
depth: u32,
direction: BackendDirection,
allowed_edge_types: &[&str],
) -> Result<Vec<i64>, SqliteGraphError>;
fn chain_query(
&self,
snapshot_id: SnapshotId,
start: i64,
chain: &[ChainStep],
) -> Result<Vec<i64>, SqliteGraphError>;
fn pattern_search(
&self,
snapshot_id: SnapshotId,
start: i64,
pattern: &PatternQuery,
) -> Result<Vec<PatternMatch>, SqliteGraphError>;
fn checkpoint(&self) -> Result<(), SqliteGraphError>;
fn flush(&self) -> Result<(), SqliteGraphError>;
fn backup(
&self,
backup_dir: &Path,
) -> Result<BackupResult, SqliteGraphError>;
fn snapshot_export(
&self,
export_dir: &Path,
) -> Result<SnapshotMetadata, SqliteGraphError>;
fn snapshot_import(
&self,
import_dir: &Path,
) -> Result<ImportMetadata, SqliteGraphError>;
fn query_nodes_by_kind(
&self,
snapshot_id: SnapshotId,
kind: &str,
) -> Result<Vec<i64>, SqliteGraphError>;
fn query_nodes_by_name_pattern(
&self,
snapshot_id: SnapshotId,
pattern: &str,
) -> Result<Vec<i64>, SqliteGraphError>;
}Expand description
Backend trait defining the interface for graph database backends.
Each trait method delegates to backend-specific primitives while ensuring deterministic behavior and a single integration surface for consumers.
§Snapshot Isolation
All read operations require a snapshot_id: SnapshotId parameter to enforce
ACID compliance. Reads only observe data committed at or before the snapshot.
Required Methods§
fn insert_node(&self, node: NodeSpec) -> Result<i64, SqliteGraphError>
fn insert_edge(&self, edge: EdgeSpec) -> Result<i64, SqliteGraphError>
Sourcefn update_node(
&self,
node_id: i64,
node: NodeSpec,
) -> Result<i64, SqliteGraphError>
fn update_node( &self, node_id: i64, node: NodeSpec, ) -> Result<i64, SqliteGraphError>
Update an existing node in place without allocating a new node ID
This modifies the data associated with an existing node while preserving its node_id. This is critical for avoiding node region exhaustion in the Native V2 backend, which has a hard limit of 2048 nodes.
§Arguments
node_id- The ID of the node to update (must exist)node- New node specification (kind, name, file_path, data)
§Returns
The same node_id that was passed in, if update succeeded
§Errors
Returns SqliteGraphError if:
- The node_id doesn’t exist
- The update operation fails
- The backend doesn’t support in-place updates
§Behavior by Backend
- Native V2: Uses WAL to update node data in place, preserving node_id
- SQLite: Uses UPDATE SQL query on entities table
§Example
// Create a node
let node_id = backend.insert_node(NodeSpec {
kind: "File".to_string(),
name: "main.rs".to_string(),
file_path: Some("main.rs".to_string()),
data: serde_json::json!({"hash": "abc123"}),
})?;
// Update it - this does NOT allocate a new node_id
let updated_id = backend.update_node(node_id, NodeSpec {
kind: "File".to_string(),
name: "main.rs".to_string(),
file_path: Some("main.rs".to_string()),
data: serde_json::json!({"hash": "def456", "modified": true}),
})?;
assert_eq!(updated_id, node_id); // Same ID!Sourcefn delete_entity(&self, id: i64) -> Result<(), SqliteGraphError>
fn delete_entity(&self, id: i64) -> Result<(), SqliteGraphError>
Delete an entity (node) from the graph by ID
This removes the entity and all associated edges from the graph. For SQLite backend: deletes from entities table and cascades to edges For Native backend: marks node as deleted and updates adjacency indexes
Sourcefn entity_ids(&self) -> Result<Vec<i64>, SqliteGraphError>
fn entity_ids(&self) -> Result<Vec<i64>, SqliteGraphError>
Get all entity IDs from the graph
Returns a vector of all node IDs currently stored in the graph. For SQLite backend: queries all IDs from entities table For Native backend: iterates over node store
fn get_node( &self, snapshot_id: SnapshotId, id: i64, ) -> Result<GraphEntity, SqliteGraphError>
fn neighbors( &self, snapshot_id: SnapshotId, node: i64, query: NeighborQuery, ) -> Result<Vec<i64>, SqliteGraphError>
fn bfs( &self, snapshot_id: SnapshotId, start: i64, depth: u32, ) -> Result<Vec<i64>, SqliteGraphError>
fn shortest_path( &self, snapshot_id: SnapshotId, start: i64, end: i64, ) -> Result<Option<Vec<i64>>, SqliteGraphError>
fn node_degree( &self, snapshot_id: SnapshotId, node: i64, ) -> Result<(usize, usize), SqliteGraphError>
fn k_hop( &self, snapshot_id: SnapshotId, start: i64, depth: u32, direction: BackendDirection, ) -> Result<Vec<i64>, SqliteGraphError>
fn k_hop_filtered( &self, snapshot_id: SnapshotId, start: i64, depth: u32, direction: BackendDirection, allowed_edge_types: &[&str], ) -> Result<Vec<i64>, SqliteGraphError>
fn chain_query( &self, snapshot_id: SnapshotId, start: i64, chain: &[ChainStep], ) -> Result<Vec<i64>, SqliteGraphError>
fn pattern_search( &self, snapshot_id: SnapshotId, start: i64, pattern: &PatternQuery, ) -> Result<Vec<PatternMatch>, SqliteGraphError>
Sourcefn checkpoint(&self) -> Result<(), SqliteGraphError>
fn checkpoint(&self) -> Result<(), SqliteGraphError>
Trigger WAL checkpoint for backends that support write-ahead logging
For Native backend with WAL: flushes WAL to graph file For SQLite backend: executes PRAGMA wal_checkpoint(TRUNCATE) For backends without WAL: returns Ok(()) as no-op
Sourcefn flush(&self) -> Result<(), SqliteGraphError>
fn flush(&self) -> Result<(), SqliteGraphError>
Force immediate flush of WAL buffer to disk
Ensures all buffered WAL records (including KV writes) are persisted immediately, making them visible to other processes.
For Native V2 backend with WAL: flushes WAL buffer to disk For SQLite backend: returns Ok(()) as no-op (SQLite handles sync) For backends without WAL: returns Ok(()) as no-op
Sourcefn backup(&self, backup_dir: &Path) -> Result<BackupResult, SqliteGraphError>
fn backup(&self, backup_dir: &Path) -> Result<BackupResult, SqliteGraphError>
Create a backup of the database
Creates a consistent snapshot of the database including all data pages. For Native V2 backend, optionally checkpoints before backup to ensure WAL is applied and snapshot is consistent.
§Arguments
backup_dir- Destination directory for backup files
§Returns
Backup result with paths, checksum, and metadata
Sourcefn snapshot_export(
&self,
export_dir: &Path,
) -> Result<SnapshotMetadata, SqliteGraphError>
fn snapshot_export( &self, export_dir: &Path, ) -> Result<SnapshotMetadata, SqliteGraphError>
Export database snapshot to the specified directory
Creates a consistent snapshot of the current database state. For Native backend: uses V2 snapshot format For SQLite backend: uses JSON dump format
§Arguments
export_dir- Directory path where snapshot will be written
§Returns
Snapshot metadata including file paths and size information
Sourcefn snapshot_import(
&self,
import_dir: &Path,
) -> Result<ImportMetadata, SqliteGraphError>
fn snapshot_import( &self, import_dir: &Path, ) -> Result<ImportMetadata, SqliteGraphError>
Import database snapshot from the specified directory
Restores database state from a previously created snapshot. For Native backend: loads V2 snapshot format For SQLite backend: loads JSON dump format
§Arguments
import_dir- Directory path containing snapshot files
§Returns
Import metadata including number of records imported
Sourcefn query_nodes_by_kind(
&self,
snapshot_id: SnapshotId,
kind: &str,
) -> Result<Vec<i64>, SqliteGraphError>
fn query_nodes_by_kind( &self, snapshot_id: SnapshotId, kind: &str, ) -> Result<Vec<i64>, SqliteGraphError>
Query all nodes with a given kind
Returns all node IDs where the node’s kind equals the given string. Results are sorted by node ID for deterministic output.
§Arguments
snapshot_id- Only return data committed at or before this snapshotkind- Kind string to match (case-sensitive)
§Returns
Vector of node IDs with matching kind
Sourcefn query_nodes_by_name_pattern(
&self,
snapshot_id: SnapshotId,
pattern: &str,
) -> Result<Vec<i64>, SqliteGraphError>
fn query_nodes_by_name_pattern( &self, snapshot_id: SnapshotId, pattern: &str, ) -> Result<Vec<i64>, SqliteGraphError>
Query nodes by name pattern using glob matching
Returns all node IDs where the node’s label matches the glob pattern. Pattern syntax:
*matches any sequence of characters?matches exactly one character
§Arguments
snapshot_id- Only return data committed at or before this snapshotpattern- Glob pattern to match against node labels
§Returns
Vector of node IDs with matching labels
Implementations on Foreign Types§
Source§impl<B> GraphBackend for &Bwhere
B: GraphBackend + ?Sized,
Reference implementation for GraphBackend trait that works with references.
impl<B> GraphBackend for &Bwhere
B: GraphBackend + ?Sized,
Reference implementation for GraphBackend trait that works with references.