| 7451 | } |
| 7452 | |
| 7453 | static int arch_clusters(cbm_store_t *s, const char *project, const char *path, |
| 7454 | cbm_architecture_info_t *out) { |
| 7455 | char norm[CBM_SZ_512]; |
| 7456 | char like[CBM_SZ_512]; |
| 7457 | bool scoped = arch_path_prepare(path, norm, sizeof(norm), like, sizeof(like)); |
| 7458 | char nsqlbuf[ST_SQL_BUF]; |
| 7459 | const char *nbase = "SELECT id, name, qualified_name, file_path FROM nodes " |
| 7460 | "WHERE project=?1 AND label IN (" CBM_SQL_CALLABLE_OR_TYPE_LABELS ")"; |
| 7461 | if (scoped) { |
| 7462 | snprintf(nsqlbuf, sizeof(nsqlbuf), "%s%s ORDER BY id LIMIT ?4", nbase, |
| 7463 | arch_path_scope_sql()); |
| 7464 | } else { |
| 7465 | snprintf(nsqlbuf, sizeof(nsqlbuf), "%s ORDER BY id LIMIT ?2", nbase); |
| 7466 | } |
| 7467 | sqlite3_stmt *st = NULL; |
| 7468 | if (sqlite3_prepare_v2(s->db, nsqlbuf, CBM_NOT_FOUND, &st, NULL) != SQLITE_OK) { |
| 7469 | return CBM_STORE_OK; /* clusters are best-effort */ |
| 7470 | } |
| 7471 | bind_text(st, SKIP_ONE, project); |
| 7472 | if (scoped) { |
| 7473 | arch_bind_path_scope(st, ST_COL_2, ST_COL_3, norm, like); |
| 7474 | sqlite3_bind_int(st, ST_COL_4, CBM_CLUSTER_NODE_CAP); |
| 7475 | } else { |
| 7476 | sqlite3_bind_int(st, CBM_SZ_2, CBM_CLUSTER_NODE_CAP); |
| 7477 | } |
| 7478 | int cap = ST_INIT_CAP_8; |
| 7479 | int n = 0; |
| 7480 | int64_t *ids = malloc((size_t)cap * sizeof(int64_t)); |
| 7481 | const char **names = malloc((size_t)cap * sizeof(char *)); |
| 7482 | const char **qns = malloc((size_t)cap * sizeof(char *)); |
| 7483 | int scan_rc29; |
| 7484 | while ((scan_rc29 = sqlite3_step(st)) == SQLITE_ROW) { |
| 7485 | if (n >= cap) { |
| 7486 | cap *= ST_GROWTH; |
| 7487 | ids = safe_realloc(ids, (size_t)cap * sizeof(int64_t)); |
| 7488 | names = safe_realloc(names, (size_t)cap * sizeof(char *)); |
| 7489 | qns = safe_realloc(qns, (size_t)cap * sizeof(char *)); |
| 7490 | } |
| 7491 | ids[n] = sqlite3_column_int64(st, 0); |
| 7492 | names[n] = heap_strdup((const char *)sqlite3_column_text(st, SKIP_ONE)); |
| 7493 | qns[n] = heap_strdup((const char *)sqlite3_column_text(st, CBM_SZ_2)); |
| 7494 | n++; |
| 7495 | } |
| 7496 | if (scan_rc29 != SQLITE_DONE) { /* SCANCHK:29:st */ |
| 7497 | store_set_error_sqlite(s, "row scan aborted"); |
| 7498 | sqlite3_finalize(st); |
| 7499 | for (int ci = 0; ci < n; ci++) { |
| 7500 | safe_str_free(&names[ci]); |
| 7501 | safe_str_free(&qns[ci]); |
| 7502 | } |
| 7503 | free(ids); |
| 7504 | free((void *)names); |
| 7505 | free((void *)qns); |
| 7506 | return CBM_STORE_ERR; |
| 7507 | } |
| 7508 | sqlite3_finalize(st); |
| 7509 | if (n < CBM_CLUSTER_MIN_MEMBERS) { |
| 7510 | for (int i = 0; i < n; i++) { |
no test coverage detected