MCPcopy Create free account
hub / github.com/NodeDB-Lab/nodedb / execute_triple

Function execute_triple

nodedb/src/engine/graph/pattern/executor/mod.rs:176–249  ·  view source on GitHub ↗

Execute a single triple `(src)-[edge]->(dst)` against a binding row.

(
    triple: &PatternTriple,
    csr: &CsrIndex,
    input_row: &BindingRow,
    state: &mut ExecutionState,
    frontier_bitmap: Option<&nodedb_types::SurrogateBitmap>,
)

Source from the content-addressed store, hash-verified

174
175/// Execute a single triple `(src)-[edge]->(dst)` against a binding row.
176fn execute_triple(
177 triple: &PatternTriple,
178 csr: &CsrIndex,
179 input_row: &BindingRow,
180 state: &mut ExecutionState,
181 frontier_bitmap: Option<&nodedb_types::SurrogateBitmap>,
182) -> Result<Vec<BindingRow>, crate::Error> {
183 let direction = triple.edge.direction.to_csr_direction();
184 let label_filter = triple.edge.edge_type.as_deref();
185 let src_nodes = resolve_binding(&triple.src, csr, input_row, frontier_bitmap);
186
187 if src_nodes.is_empty() {
188 return Ok(Vec::new());
189 }
190
191 let mut results = Vec::new();
192
193 if triple.edge.is_variable_length() {
194 // Path strings are only needed when the edge variable is bound
195 // (e.g. `(a)-[e*1..3]->(b) RETURN e`). For anonymous variable
196 // expansions skip all `format!`/`String` work in the hot loop.
197 let want_path = triple.edge.name.is_some();
198 for &src_id in &src_nodes {
199 let expansion = expansion::expand_variable_length(
200 csr,
201 src_id,
202 label_filter,
203 direction,
204 triple.edge.min_hops,
205 triple.edge.max_hops,
206 want_path,
207 );
208 if expansion.truncated {
209 state.truncated = true;
210 }
211 for (dst_id, path) in expansion.results {
212 if !binding_compatible(&triple.dst, csr, input_row, dst_id) {
213 continue;
214 }
215 let mut row = input_row.clone();
216 bind_node(&mut row, &triple.src, csr, src_id);
217 bind_node(&mut row, &triple.dst, csr, dst_id);
218 if let Some(ref edge_name) = triple.edge.name {
219 row.insert(edge_name.clone(), path);
220 }
221 results.push(row);
222 }
223 }
224 } else {
225 for &src_id in &src_nodes {
226 let neighbors = expansion::collect_neighbors(csr, src_id, label_filter, direction);
227 for (lid, dst_id) in neighbors {
228 if !binding_compatible(&triple.dst, csr, input_row, dst_id) {
229 continue;
230 }
231 let mut row = input_row.clone();
232 bind_node(&mut row, &triple.src, csr, src_id);
233 bind_node(&mut row, &triple.dst, csr, dst_id);

Callers 1

execute_chainFunction · 0.85

Calls 13

resolve_bindingFunction · 0.85
expand_variable_lengthFunction · 0.85
binding_compatibleFunction · 0.85
bind_nodeFunction · 0.85
collect_neighborsFunction · 0.85
to_csr_directionMethod · 0.80
is_emptyMethod · 0.45
is_variable_lengthMethod · 0.45
cloneMethod · 0.45
insertMethod · 0.45
pushMethod · 0.45
node_name_rawMethod · 0.45

Tested by

no test coverage detected