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

Function process_edges

src/cypher/cypher.c:3128–3174  ·  view source on GitHub ↗

Source from the content-addressed store, hash-verified

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

Callers 1

expand_fixed_lengthFunction · 0.85

Calls 9

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
binding_out_appendFunction · 0.85

Tested by

no test coverage detected