Expand additional MATCH patterns (pi >= 1) */
| 4750 | |
| 4751 | /* Expand additional MATCH patterns (pi >= 1) */ |
| 4752 | static int expand_additional_patterns(cbm_store_t *store, cbm_query_t *q, const char *project, |
| 4753 | int max_rows, binding_t **bindings, int *bind_count, |
| 4754 | int *bind_cap) { |
| 4755 | for (int pi = SKIP_ONE; pi < q->pattern_count; pi++) { |
| 4756 | cbm_pattern_t *patn = &q->patterns[pi]; |
| 4757 | bool opt = q->pattern_optional[pi]; |
| 4758 | const char *nvar = patn->nodes[0].variable ? patn->nodes[0].variable : "_n_extra"; |
| 4759 | bool start_bound = *bind_count > 0 && binding_get(&(*bindings)[0], nvar) != NULL; |
| 4760 | |
| 4761 | if (start_bound && patn->rel_count > 0) { |
| 4762 | const char *tv = nvar; |
| 4763 | expand_pattern_rels(store, patn, bindings, bind_count, bind_cap, &tv, opt); |
| 4764 | continue; |
| 4765 | } |
| 4766 | |
| 4767 | /* Single-rel pattern whose START is unbound but whose TERMINAL is already |
| 4768 | * bound: drive from the bound terminal instead of scanning all nodes for |
| 4769 | * the start var (avoids the int-overflow OOB write and the c-IS-NULL |
| 4770 | * corruption of #627). */ |
| 4771 | if (!start_bound && patn->rel_count == 1 && *bind_count > 0) { |
| 4772 | const char *term_var = patn->nodes[1].variable; |
| 4773 | bool term_bound = term_var && binding_get(&(*bindings)[0], term_var) != NULL; |
| 4774 | if (term_bound) { |
| 4775 | expand_from_bound_terminal(store, patn, bindings, bind_count, nvar, opt); |
| 4776 | continue; |
| 4777 | } |
| 4778 | } |
| 4779 | |
| 4780 | cbm_node_t *extra_nodes = NULL; |
| 4781 | int extra_count = 0; |
| 4782 | scan_pattern_nodes(store, project, max_rows, &patn->nodes[0], &extra_nodes, &extra_count); |
| 4783 | int rc = 0; |
| 4784 | if (patn->rel_count == 0) { |
| 4785 | rc = cross_join_nodes(bindings, bind_count, extra_nodes, extra_count, nvar, opt); |
| 4786 | } else { |
| 4787 | cross_join_with_rels(store, patn, bindings, bind_count, extra_nodes, extra_count, nvar, |
| 4788 | opt); |
| 4789 | } |
| 4790 | cbm_store_free_nodes(extra_nodes, extra_count); |
| 4791 | if (rc != 0) { |
| 4792 | return rc; /* allocation refused/failed: propagate as a query error */ |
| 4793 | } |
| 4794 | } |
| 4795 | return 0; |
| 4796 | } |
| 4797 | |
| 4798 | /* Project RETURN clause results */ |
| 4799 | static void execute_return_clause(cbm_query_t *q, cbm_return_clause_t *ret, binding_t *bindings, |
no test coverage detected