Expand additional MATCH patterns (pi >= 1) */
| 4718 | |
| 4719 | /* Expand additional MATCH patterns (pi >= 1) */ |
| 4720 | static int expand_additional_patterns(cbm_store_t *store, cbm_query_t *q, const char *project, |
| 4721 | int max_rows, binding_t **bindings, int *bind_count, |
| 4722 | int *bind_cap) { |
| 4723 | for (int pi = SKIP_ONE; pi < q->pattern_count; pi++) { |
| 4724 | cbm_pattern_t *patn = &q->patterns[pi]; |
| 4725 | bool opt = q->pattern_optional[pi]; |
| 4726 | const char *nvar = patn->nodes[0].variable ? patn->nodes[0].variable : "_n_extra"; |
| 4727 | bool start_bound = *bind_count > 0 && binding_get(&(*bindings)[0], nvar) != NULL; |
| 4728 | |
| 4729 | if (start_bound && patn->rel_count > 0) { |
| 4730 | const char *tv = nvar; |
| 4731 | expand_pattern_rels(store, patn, bindings, bind_count, bind_cap, &tv, opt); |
| 4732 | continue; |
| 4733 | } |
| 4734 | |
| 4735 | /* Single-rel pattern whose START is unbound but whose TERMINAL is already |
| 4736 | * bound: drive from the bound terminal instead of scanning all nodes for |
| 4737 | * the start var (avoids the int-overflow OOB write and the c-IS-NULL |
| 4738 | * corruption of #627). */ |
| 4739 | if (!start_bound && patn->rel_count == 1 && *bind_count > 0) { |
| 4740 | const char *term_var = patn->nodes[1].variable; |
| 4741 | bool term_bound = term_var && binding_get(&(*bindings)[0], term_var) != NULL; |
| 4742 | if (term_bound) { |
| 4743 | expand_from_bound_terminal(store, patn, bindings, bind_count, nvar, opt); |
| 4744 | continue; |
| 4745 | } |
| 4746 | } |
| 4747 | |
| 4748 | cbm_node_t *extra_nodes = NULL; |
| 4749 | int extra_count = 0; |
| 4750 | scan_pattern_nodes(store, project, max_rows, &patn->nodes[0], &extra_nodes, &extra_count); |
| 4751 | int rc = 0; |
| 4752 | if (patn->rel_count == 0) { |
| 4753 | rc = cross_join_nodes(bindings, bind_count, extra_nodes, extra_count, nvar, opt); |
| 4754 | } else { |
| 4755 | cross_join_with_rels(store, patn, bindings, bind_count, extra_nodes, extra_count, nvar, |
| 4756 | opt); |
| 4757 | } |
| 4758 | cbm_store_free_nodes(extra_nodes, extra_count); |
| 4759 | if (rc != 0) { |
| 4760 | return rc; /* allocation refused/failed: propagate as a query error */ |
| 4761 | } |
| 4762 | } |
| 4763 | return 0; |
| 4764 | } |
| 4765 | |
| 4766 | /* Project RETURN clause results */ |
| 4767 | static void execute_return_clause(cbm_query_t *q, cbm_return_clause_t *ret, binding_t *bindings, |
no test coverage detected