| 4465 | /* ── Main entry point ─────────────────────────────────────────── */ |
| 4466 | |
| 4467 | int cbm_cypher_execute(cbm_store_t *store, const char *query, const char *project, int max_rows, |
| 4468 | cbm_cypher_result_t *out) { |
| 4469 | memset(out, 0, sizeof(*out)); |
| 4470 | if (max_rows <= 0) { |
| 4471 | max_rows = CYPHER_RESULT_CEILING; |
| 4472 | } |
| 4473 | |
| 4474 | cbm_query_t *q = NULL; |
| 4475 | char *err = NULL; |
| 4476 | if (cbm_cypher_parse(query, &q, &err) < 0) { |
| 4477 | out->error = err; |
| 4478 | return CBM_NOT_FOUND; |
| 4479 | } |
| 4480 | |
| 4481 | result_builder_t rb = {0}; |
| 4482 | // cppcheck-suppress knownConditionTrueFalse |
| 4483 | if (execute_single(store, q, project, max_rows, &rb) < 0) { |
| 4484 | cbm_query_free(q); |
| 4485 | return CBM_NOT_FOUND; |
| 4486 | } |
| 4487 | |
| 4488 | /* UNION chain */ |
| 4489 | cbm_query_t *uq = q->union_next; |
| 4490 | while (uq) { |
| 4491 | result_builder_t rb2 = {0}; |
| 4492 | // cppcheck-suppress knownConditionTrueFalse |
| 4493 | if (execute_single(store, uq, project, max_rows, &rb2) < 0) { |
| 4494 | rb_free(&rb); |
| 4495 | rb_free(&rb2); |
| 4496 | cbm_query_free(q); |
| 4497 | return CBM_NOT_FOUND; |
| 4498 | } |
| 4499 | /* Concatenate rows from rb2 into rb */ |
| 4500 | for (int i = 0; i < rb2.row_count; i++) { |
| 4501 | rb_add_row(&rb, rb2.rows[i]); |
| 4502 | } |
| 4503 | rb_free(&rb2); |
| 4504 | |
| 4505 | uq = uq->union_next; |
| 4506 | } |
| 4507 | |
| 4508 | /* UNION (not ALL) deduplication */ |
| 4509 | if (q->union_next && !q->union_all) { |
| 4510 | rb_apply_distinct(&rb); |
| 4511 | } |
| 4512 | |
| 4513 | /* Check ceiling */ |
| 4514 | if (rb.row_count >= CYPHER_RESULT_CEILING) { |
| 4515 | rb_free(&rb); |
| 4516 | cbm_query_free(q); |
| 4517 | out->error = heap_strdup("result exceeded 100k rows — use narrower filters or add LIMIT"); |
| 4518 | return CBM_NOT_FOUND; |
| 4519 | } |
| 4520 | |
| 4521 | out->columns = rb.columns; |
| 4522 | out->col_count = rb.col_count; |
| 4523 | out->rows = rb.rows; |
| 4524 | out->row_count = rb.row_count; |
no test coverage detected