| 2806 | } |
| 2807 | |
| 2808 | static void scan_pattern_nodes(cbm_store_t *store, const char *project, int max_rows, |
| 2809 | cbm_node_pattern_t *first, cbm_node_t **out_nodes, int *out_count) { |
| 2810 | if (first->label && strchr(first->label, '|')) { |
| 2811 | scan_alternation_labels(store, project, first->label, out_nodes, out_count); |
| 2812 | } else if (first->label) { |
| 2813 | cbm_store_find_nodes_by_label(store, project, first->label, out_nodes, out_count); |
| 2814 | } else { |
| 2815 | cbm_search_params_t params = {.project = project, |
| 2816 | .min_degree = CYP_FOUND_NONE, |
| 2817 | .max_degree = CYP_FOUND_NONE, |
| 2818 | .limit = max_rows * CYP_GROWTH_10}; |
| 2819 | cbm_search_output_t sout = {0}; |
| 2820 | cbm_store_search(store, ¶ms, &sout); |
| 2821 | *out_count = sout.count; |
| 2822 | *out_nodes = malloc(sout.count * sizeof(cbm_node_t)); |
| 2823 | for (int i = 0; i < sout.count; i++) { |
| 2824 | (*out_nodes)[i] = sout.results[i].node; |
| 2825 | sout.results[i].node.name = NULL; |
| 2826 | sout.results[i].node.project = NULL; |
| 2827 | sout.results[i].node.label = NULL; |
| 2828 | sout.results[i].node.qualified_name = NULL; |
| 2829 | sout.results[i].node.file_path = NULL; |
| 2830 | sout.results[i].node.properties_json = NULL; |
| 2831 | } |
| 2832 | cbm_store_search_free(&sout); |
| 2833 | } |
| 2834 | /* Apply inline property filters — free rejected nodes' strings */ |
| 2835 | if (first->prop_count > 0) { |
| 2836 | int kept = 0; |
| 2837 | for (int i = 0; i < *out_count; i++) { |
| 2838 | if (check_inline_props(&(*out_nodes)[i], first->props, first->prop_count, store)) { |
| 2839 | if (kept != i) { |
| 2840 | (*out_nodes)[kept] = (*out_nodes)[i]; |
| 2841 | } |
| 2842 | kept++; |
| 2843 | } else { |
| 2844 | node_fields_free(&(*out_nodes)[i]); |
| 2845 | } |
| 2846 | } |
| 2847 | *out_count = kept; |
| 2848 | } |
| 2849 | } |
| 2850 | |
| 2851 | /* ── Expand one pattern's relationships on a set of bindings ──── */ |
| 2852 |
no test coverage detected