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