Resolve the actual property value for a condition from a binding */
| 2544 | |
| 2545 | /* Resolve the actual property value for a condition from a binding */ |
| 2546 | static const char *resolve_condition_value(const cbm_condition_t *c, binding_t *b) { |
| 2547 | /* Multi-arg scalar function LHS: coalesce(f.depth, 0) >= 2 (#874). |
| 2548 | * Evaluated through the same code path as RETURN projections. The value is |
| 2549 | * consumed by eval_condition before any other condition is resolved, so a |
| 2550 | * single thread-local buffer per call is safe. */ |
| 2551 | if (c->func) { |
| 2552 | static _Thread_local char func_buf[CBM_SZ_512]; |
| 2553 | cbm_return_item_t item = {0}; |
| 2554 | item.variable = c->variable; |
| 2555 | item.property = c->property; |
| 2556 | item.func = c->func; |
| 2557 | item.args = c->args; |
| 2558 | item.arg_count = c->arg_count; |
| 2559 | return eval_multiarg_func(b, &item, func_buf, sizeof(func_buf)); |
| 2560 | } |
| 2561 | |
| 2562 | cbm_edge_t *e = binding_get_edge(b, c->variable); |
| 2563 | if (e) { |
| 2564 | return edge_prop(e, c->property); |
| 2565 | } |
| 2566 | cbm_node_t *n = binding_get(b, c->variable); |
| 2567 | if (!n) { |
| 2568 | return NULL; /* unbound variable */ |
| 2569 | } |
| 2570 | if (c->property) { |
| 2571 | return node_prop(n, c->property, b->store); |
| 2572 | } |
| 2573 | /* Bare alias (e.g. post-WITH virtual var) — use node name directly */ |
| 2574 | return n->name ? n->name : ""; |
| 2575 | } |
| 2576 | |
| 2577 | /* Evaluate a comparison operator between actual and expected strings. */ |
| 2578 | static bool eval_comparison_op(const char *op, const char *actual, const char *expected) { |
no test coverage detected