| 3072 | } |
| 3073 | |
| 3074 | static void scan_pattern_nodes(cbm_store_t *store, const char *project, int max_rows, |
| 3075 | cbm_node_pattern_t *first, cbm_node_t **out_nodes, int *out_count) { |
| 3076 | if (first->label && strchr(first->label, '|')) { |
| 3077 | scan_alternation_labels(store, project, first->label, out_nodes, out_count); |
| 3078 | } else if (first->label) { |
| 3079 | cbm_store_find_nodes_by_label(store, project, first->label, out_nodes, out_count); |
| 3080 | } else { |
| 3081 | cbm_search_params_t params = {.project = project, |
| 3082 | .min_degree = CYP_FOUND_NONE, |
| 3083 | .max_degree = CYP_FOUND_NONE, |
| 3084 | .limit = max_rows * CYP_GROWTH_10}; |
| 3085 | cbm_search_output_t sout = {0}; |
| 3086 | cbm_store_search(store, ¶ms, &sout); |
| 3087 | *out_count = sout.count; |
| 3088 | *out_nodes = malloc(sout.count * sizeof(cbm_node_t)); |
| 3089 | for (int i = 0; i < sout.count; i++) { |
| 3090 | (*out_nodes)[i] = sout.results[i].node; |
| 3091 | sout.results[i].node.name = NULL; |
| 3092 | sout.results[i].node.project = NULL; |
| 3093 | sout.results[i].node.label = NULL; |
| 3094 | sout.results[i].node.qualified_name = NULL; |
| 3095 | sout.results[i].node.file_path = NULL; |
| 3096 | sout.results[i].node.properties_json = NULL; |
| 3097 | } |
| 3098 | cbm_store_search_free(&sout); |
| 3099 | } |
| 3100 | /* Apply inline property filters — free rejected nodes' strings */ |
| 3101 | if (first->prop_count > 0) { |
| 3102 | int kept = 0; |
| 3103 | for (int i = 0; i < *out_count; i++) { |
| 3104 | if (check_inline_props(&(*out_nodes)[i], first->props, first->prop_count, store)) { |
| 3105 | if (kept != i) { |
| 3106 | (*out_nodes)[kept] = (*out_nodes)[i]; |
| 3107 | } |
| 3108 | kept++; |
| 3109 | } else { |
| 3110 | node_fields_free(&(*out_nodes)[i]); |
| 3111 | } |
| 3112 | } |
| 3113 | *out_count = kept; |
| 3114 | } |
| 3115 | } |
| 3116 | |
| 3117 | /* ── Expand one pattern's relationships on a set of bindings ──── */ |
| 3118 |
no test coverage detected