MCPcopy Create free account
hub / github.com/DeusData/codebase-memory-mcp / process_edges

Function process_edges

src/cypher/cypher.c:3121–3169  ·  view source on GitHub ↗

Process edges: look up target node, filter by label/props, add binding. * `inbound` controls which end of the edge is the target id. */

Source from the content-addressed store, hash-verified

3119/* Process edges: look up target node, filter by label/props, add binding.
3120 * `inbound` controls which end of the edge is the target id. */
3121static void process_edges(cbm_store_t *store, cbm_edge_t *edges, int edge_count, bool inbound,
3122 const cbm_node_pattern_t *target_node, binding_t *b, const char *to_var,
3123 const char *rel_var, binding_t *new_bindings, int *new_count, int max_new,
3124 int *match_count) {
3125 /* When the terminal node variable is ALREADY bound (e.g. the second pattern
3126 * `(c)-[:CALLS]->(f)` where `f` came from an earlier MATCH), we must FILTER
3127 * to edges that actually reach the bound node — not overwrite the caller's
3128 * `f` binding with whatever node the edge leads to. Overwriting corrupted
3129 * the result of dead-code queries and produced wrong rows (#627). */
3130 cbm_node_t *bound_to = binding_get(b, to_var);
3131 int64_t bound_to_id = bound_to ? bound_to->id : 0;
3132 /* The budget caps MATERIALISATION, not detection: `match_count` must stay
3133 * truthful even after `new_count` hits `max_new`. Gating the loop itself
3134 * (`ei < edge_count && *new_count < max_new`) stopped fetching entirely, so
3135 * a saturated source reported `match_count == 0` despite having neighbours —
3136 * and the OPTIONAL fallback in expand_pattern_rels then emitted an unbound
3137 * "no match" row for it. `WHERE x IS NULL` reads those rows as "nothing
3138 * points here", i.e. it reported live code as dead. Losing rows is
3139 * recoverable; asserting a match does not exist when it does is not. */
3140 for (int ei = 0; ei < edge_count; ei++) {
3141 int64_t tid = inbound ? edges[ei].source_id : edges[ei].target_id;
3142 if (bound_to && tid != bound_to_id) {
3143 continue; /* edge does not reach the already-bound terminal node */
3144 }
3145 cbm_node_t found = {0};
3146 if (cbm_store_find_node_by_id(store, tid, &found) != CBM_STORE_OK) {
3147 continue;
3148 }
3149 if (target_node->label && !label_alt_matches(found.label, target_node->label)) {
3150 node_fields_free(&found);
3151 continue;
3152 }
3153 if (!check_inline_props(&found, target_node->props, target_node->prop_count, store)) {
3154 node_fields_free(&found);
3155 continue;
3156 }
3157 (*match_count)++; /* a real neighbour exists, budget or not */
3158 if (*new_count < max_new) {
3159 binding_t nb = {0};
3160 binding_copy(&nb, b);
3161 binding_set(&nb, to_var, &found);
3162 if (rel_var) {
3163 binding_set_edge(&nb, rel_var, &edges[ei]);
3164 }
3165 new_bindings[(*new_count)++] = nb;
3166 }
3167 node_fields_free(&found);
3168 }
3169}
3170
3171/* Expand variable-length relationship via BFS */
3172/* Set when a variable-length hop range is clamped to the engine ceiling

Callers 1

expand_fixed_lengthFunction · 0.85

Calls 8

binding_getFunction · 0.85
label_alt_matchesFunction · 0.85
node_fields_freeFunction · 0.85
check_inline_propsFunction · 0.85
binding_copyFunction · 0.85
binding_setFunction · 0.85
binding_set_edgeFunction · 0.85

Tested by

no test coverage detected