fix(cypher): unify repeated variable-length nodes

Signed-off-by: King Star <mcxin.y@gmail.com>
This commit is contained in:
King Star committed 2026-08-01 10:53:01 +08:00
1 parent d6be58ef9d
commit ec29cd59a3
2 files changed
+22

No files matched your search

+5
View File
@@ -3151,6 +3151,8 @@ static void expand_var_length(cbm_store_t *store, cbm_rel_pattern_t *rel,
cbm_traverse_result_t tr = {0};
const char *dir = rel->direction ? rel->direction : "outbound";
cbm_store_bfs(store, src->id, dir, rel->types, rel->type_count, max_depth, CBM_PERCENT, &tr);
cbm_node_t *bound_to = binding_get(b, to_var);
int64_t bound_to_id = bound_to ? bound_to->id : 0;
/* Same contract as process_edges: the budget caps materialisation, never
* detection, so a saturated source cannot report match_count == 0 and get a
* fabricated OPTIONAL "no match" row. */
@@ -3159,6 +3161,9 @@ static void expand_var_length(cbm_store_t *store, cbm_rel_pattern_t *rel,
if (hop->hop < rel->min_hops) {
continue;
}
if (bound_to && hop->node.id != bound_to_id) {
continue;
}
if (target_node->label && !label_alt_matches(hop->node.label, target_node->label)) {
continue;
}
+17
View File
@@ -1371,6 +1371,22 @@ TEST(cypher_exec_variable_length) {
PASS();
}
TEST(cypher_exec_variable_length_repeated_node_var_unifies) {
cbm_store_t *s = setup_cypher_store();
cbm_cypher_result_t r = {0};
int rc = cbm_cypher_execute(s,
"MATCH (f:Function)-[:CALLS*1..2]->(f:Function) "
"RETURN f.name",
"test", 0, &r);
ASSERT_EQ(rc, 0);
ASSERT_EQ(r.row_count, 0);
cbm_cypher_result_free(&r);
cbm_store_close(s);
PASS();
}
/* Reproduce-first (#887): an EXPLICIT variable-length upper bound must still be
* capped at the engine ceiling (cbm_cypher_max_depth(), default 10). On
* origin/main, expand_var_length honoured an explicit `*1..N` verbatim (only the
@@ -3612,6 +3628,7 @@ SUITE(cypher) {
RUN_TEST(cypher_exec_limit);
RUN_TEST(cypher_exec_order_by);
RUN_TEST(cypher_exec_variable_length);
RUN_TEST(cypher_exec_variable_length_repeated_node_var_unifies);
RUN_TEST(cypher_exec_var_length_explicit_bound_capped);
RUN_TEST(cypher_exec_defines_edge);
RUN_TEST(cypher_exec_no_results);