use crate::{
backend::BackendDirection,
errors::SqliteGraphError,
graph::SqliteGraph,
pattern_engine::{PatternTriple, TripleMatch, match_triples},
pattern_engine_cache::{
edge_validation::edge_exists_with_type, edge_validation::get_edge_id,
fast_path_detection::can_use_fast_path, fast_path_detection::can_use_partial_fast_path,
},
};
pub fn match_triples_fast(
graph: &SqliteGraph,
pattern: &PatternTriple,
) -> Result<Vec<TripleMatch>, SqliteGraphError> {
pattern.validate()?;
if can_use_fast_path(pattern) {
return execute_fast_path(graph, pattern);
}
if can_use_partial_fast_path(pattern) {
return execute_partial_fast_path(graph, pattern);
}
execute_sql_only(graph, pattern)
}
fn execute_fast_path(
graph: &SqliteGraph,
pattern: &PatternTriple,
) -> Result<Vec<TripleMatch>, SqliteGraphError> {
let mut matches = Vec::new();
let entity_ids = graph.all_entity_ids()?;
for &source_id in &entity_ids {
let candidates = match pattern.direction {
BackendDirection::Outgoing => graph.fetch_outgoing(source_id)?,
BackendDirection::Incoming => graph.fetch_incoming(source_id)?,
};
for &target_id in &candidates {
let (from_id, to_id) = match pattern.direction {
BackendDirection::Outgoing => (source_id, target_id),
BackendDirection::Incoming => (target_id, source_id),
};
if edge_exists_with_type(
graph,
from_id,
to_id,
&pattern.edge_type,
BackendDirection::Outgoing,
)? {
let edge_id = get_edge_id(graph, from_id, to_id, &pattern.edge_type)?;
let triple_match = match pattern.direction {
BackendDirection::Outgoing => TripleMatch::new(source_id, edge_id, target_id),
BackendDirection::Incoming => TripleMatch::new(source_id, edge_id, target_id),
};
matches.push(triple_match);
}
}
}
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)
}
fn execute_partial_fast_path(
graph: &SqliteGraph,
pattern: &PatternTriple,
) -> Result<Vec<TripleMatch>, SqliteGraphError> {
match_triples(graph, pattern)
}
fn execute_sql_only(
graph: &SqliteGraph,
pattern: &PatternTriple,
) -> Result<Vec<TripleMatch>, SqliteGraphError> {
match_triples(graph, pattern)
}