sqlitegraph 3.9.0

Embedded graph database with explicit SQLite, native-v3, and combined backend modes; HNSW vector search; and graph algorithms
Documentation
use super::V3Backend;
use crate::SqliteGraphError;
use crate::backend::native::v3::edge_compat::Direction;
use crate::pattern_engine::{PatternTriple, TripleMatch};
use crate::snapshot::SnapshotId;

impl V3Backend {
    pub(super) fn query_nodes_by_kind_support(
        &self,
        snapshot_id: SnapshotId,
        kind: &str,
    ) -> Result<Vec<i64>, SqliteGraphError> {
        Self::require_current_snapshot(snapshot_id)?;
        Ok(self.kind_index.get(kind))
    }

    pub(super) fn query_nodes_by_name_pattern_support(
        &self,
        snapshot_id: SnapshotId,
        pattern: &str,
    ) -> Result<Vec<i64>, SqliteGraphError> {
        Self::require_current_snapshot(snapshot_id)?;

        if pattern.ends_with('*') && !pattern.starts_with('*') && !pattern.contains('?') {
            let prefix = &pattern[..pattern.len() - 1];
            Ok(self.name_index.get_prefix(prefix))
        } else if pattern.contains('*') || pattern.contains('?') {
            Ok(self.name_index.get_glob(pattern))
        } else {
            Ok(self.name_index.get_exact(pattern))
        }
    }

    pub(super) fn match_triples_support(
        &self,
        pattern: &PatternTriple,
    ) -> Result<Vec<TripleMatch>, SqliteGraphError> {
        pattern.validate()?;

        let mut matches = Vec::new();
        let v3_direction = match pattern.direction {
            crate::backend::BackendDirection::Outgoing => Direction::Outgoing,
            crate::backend::BackendDirection::Incoming => Direction::Incoming,
        };

        let start_candidates: Vec<i64> = if let Some(ref start_label) = pattern.start_label {
            self.kind_index.get(start_label)
        } else {
            self.get_all_node_ids()?
        };

        for start_id in start_candidates {
            let edge_store = self.edge_store.read();
            let neighbors =
                match edge_store.neighbors_filtered(start_id, v3_direction, &pattern.edge_type) {
                    Ok(neighbors) => neighbors,
                    Err(_) => continue,
                };

            drop(edge_store);

            for end_id in neighbors.iter() {
                if let Some(ref end_label) = pattern.end_label {
                    let label_matches = self.kind_index.get(end_label).contains(end_id);
                    if !label_matches {
                        continue;
                    }
                }

                if !self.check_property_filters(start_id, *end_id, pattern)? {
                    continue;
                }

                let edge_id =
                    self.generate_edge_id(start_id, *end_id, v3_direction, &pattern.edge_type);

                matches.push(TripleMatch::new(start_id, edge_id, *end_id));
            }
        }

        matches.sort_by(|a, b| {
            a.start_id
                .cmp(&b.start_id)
                .then_with(|| a.edge_id.cmp(&b.edge_id))
                .then_with(|| a.end_id.cmp(&b.end_id))
        });

        Ok(matches)
    }
}