| 3649 | } |
| 3650 | |
| 3651 | static const char *project_item(binding_t *b, cbm_return_item_t *item, char *func_buf, |
| 3652 | size_t buf_sz) { |
| 3653 | if (item->kase) { |
| 3654 | return eval_case_expr(item->kase, b); |
| 3655 | } |
| 3656 | if (item->args) { |
| 3657 | return eval_multiarg_func(b, item, func_buf, buf_sz); |
| 3658 | } |
| 3659 | /* Entity-introspection functions operate on the bound node/edge itself, |
| 3660 | * not on a scalar property value. */ |
| 3661 | if (item->func) { |
| 3662 | if (strcmp(item->func, "labels") == 0) { |
| 3663 | cbm_node_t *n = binding_get(b, item->variable); |
| 3664 | if (n && n->label) { |
| 3665 | snprintf(func_buf, buf_sz, "[\"%s\"]", n->label); |
| 3666 | return func_buf; |
| 3667 | } |
| 3668 | return "[]"; |
| 3669 | } |
| 3670 | if (strcmp(item->func, "type") == 0) { |
| 3671 | cbm_edge_t *e = binding_get_edge(b, item->variable); |
| 3672 | return (e && e->type) ? e->type : ""; |
| 3673 | } |
| 3674 | if (strcmp(item->func, "id") == 0) { |
| 3675 | cbm_node_t *n = binding_get(b, item->variable); |
| 3676 | if (n) { |
| 3677 | snprintf(func_buf, buf_sz, "%lld", (long long)n->id); |
| 3678 | return func_buf; |
| 3679 | } |
| 3680 | cbm_edge_t *e = binding_get_edge(b, item->variable); |
| 3681 | if (e) { |
| 3682 | snprintf(func_buf, buf_sz, "%lld", (long long)e->id); |
| 3683 | return func_buf; |
| 3684 | } |
| 3685 | return ""; |
| 3686 | } |
| 3687 | if (strcmp(item->func, "keys") == 0) { |
| 3688 | cbm_node_t *n = binding_get(b, item->variable); |
| 3689 | return n ? node_keys_list(n, func_buf, buf_sz) : "[]"; |
| 3690 | } |
| 3691 | if (strcmp(item->func, "properties") == 0) { |
| 3692 | cbm_node_t *n = binding_get(b, item->variable); |
| 3693 | if (n) { |
| 3694 | return n->properties_json ? n->properties_json : "{}"; |
| 3695 | } |
| 3696 | cbm_edge_t *e = binding_get_edge(b, item->variable); |
| 3697 | if (e) { |
| 3698 | return e->properties_json ? e->properties_json : "{}"; |
| 3699 | } |
| 3700 | return "{}"; |
| 3701 | } |
| 3702 | } |
| 3703 | const char *raw = binding_get_virtual(b, item->variable, item->property); |
| 3704 | if (is_scalar_value_func(item->func)) { |
| 3705 | return apply_string_func(item->func, raw, func_buf, buf_sz); |
| 3706 | } |
| 3707 | /* Copy into the caller's per-column buffer. `raw` may point to node_prop's |
| 3708 | * rotating scratch buffer, which the next column's projection would overwrite |
no test coverage detected