| 3046 | } |
| 3047 | |
| 3048 | int cbm_store_coverage_get(cbm_store_t *s, const char *project, cbm_coverage_row_t **out, |
| 3049 | int *count) { |
| 3050 | *out = NULL; |
| 3051 | *count = 0; |
| 3052 | if (!s || !s->db || !project) { |
| 3053 | return CBM_STORE_ERR; |
| 3054 | } |
| 3055 | sqlite3_stmt *stmt = NULL; |
| 3056 | if (sqlite3_prepare_v2(s->db, |
| 3057 | "SELECT rel_path, kind, detail FROM index_coverage " |
| 3058 | "WHERE project = ?1 ORDER BY rel_path, kind;", |
| 3059 | CBM_NOT_FOUND, &stmt, NULL) != SQLITE_OK) { |
| 3060 | store_set_error_sqlite(s, "coverage get prepare"); |
| 3061 | return CBM_STORE_ERR; |
| 3062 | } |
| 3063 | bind_text(stmt, SKIP_ONE, project); |
| 3064 | int cap = ST_INIT_CAP_16; |
| 3065 | int n = 0; |
| 3066 | cbm_coverage_row_t *arr = malloc(cap * sizeof(cbm_coverage_row_t)); |
| 3067 | int scan_rc6; |
| 3068 | while ((scan_rc6 = sqlite3_step(stmt)) == SQLITE_ROW) { |
| 3069 | if (n >= cap) { |
| 3070 | cap *= ST_GROWTH; |
| 3071 | arr = safe_realloc(arr, cap * sizeof(cbm_coverage_row_t)); |
| 3072 | } |
| 3073 | arr[n].rel_path = heap_strdup((const char *)sqlite3_column_text(stmt, 0)); |
| 3074 | arr[n].kind = heap_strdup((const char *)sqlite3_column_text(stmt, SKIP_ONE)); |
| 3075 | arr[n].detail = heap_strdup((const char *)sqlite3_column_text(stmt, CBM_SZ_2)); |
| 3076 | n++; |
| 3077 | } |
| 3078 | if (scan_rc6 != SQLITE_DONE) { /* SCANCHK:6:stmt */ |
| 3079 | store_set_error_sqlite(s, "row scan aborted"); |
| 3080 | sqlite3_finalize(stmt); |
| 3081 | cbm_store_free_coverage(arr, n); |
| 3082 | *out = NULL; |
| 3083 | *count = 0; |
| 3084 | return CBM_STORE_ERR; |
| 3085 | } |
| 3086 | sqlite3_finalize(stmt); |
| 3087 | *out = arr; |
| 3088 | *count = n; |
| 3089 | return CBM_STORE_OK; |
| 3090 | } |
| 3091 | |
| 3092 | void cbm_store_free_coverage(cbm_coverage_row_t *rows, int count) { |
| 3093 | if (!rows) { |
no test coverage detected