Generic: find multiple edges by a filter. */
| 3209 | |
| 3210 | /* Generic: find multiple edges by a filter. */ |
| 3211 | static int find_edges_generic(cbm_store_t *s, sqlite3_stmt **slot, const char *sql, |
| 3212 | void (*bind_fn)(sqlite3_stmt *, const void *), const void *bind_data, |
| 3213 | cbm_edge_t **out, int *count) { |
| 3214 | if (!s || !s->db) { |
| 3215 | *out = NULL; |
| 3216 | *count = 0; |
| 3217 | return CBM_STORE_ERR; |
| 3218 | } |
| 3219 | sqlite3_stmt *stmt = prepare_cached(s, slot, sql); |
| 3220 | if (!stmt) { |
| 3221 | return CBM_STORE_ERR; |
| 3222 | } |
| 3223 | |
| 3224 | bind_fn(stmt, bind_data); |
| 3225 | |
| 3226 | int cap = ST_INIT_CAP_16; |
| 3227 | int n = 0; |
| 3228 | cbm_edge_t *arr = malloc(cap * sizeof(cbm_edge_t)); |
| 3229 | |
| 3230 | int scan_rc4; |
| 3231 | while ((scan_rc4 = sqlite3_step(stmt)) == SQLITE_ROW) { |
| 3232 | if (n >= cap) { |
| 3233 | cap *= ST_GROWTH; |
| 3234 | arr = safe_realloc(arr, cap * sizeof(cbm_edge_t)); |
| 3235 | } |
| 3236 | scan_edge(stmt, &arr[n]); |
| 3237 | n++; |
| 3238 | } |
| 3239 | if (scan_rc4 != SQLITE_DONE) { /* SCANCHK:4:stmt */ |
| 3240 | store_set_error_sqlite(s, "row scan aborted"); |
| 3241 | cbm_store_free_edges(arr, n); |
| 3242 | *out = NULL; |
| 3243 | *count = 0; |
| 3244 | return CBM_STORE_ERR; |
| 3245 | } |
| 3246 | |
| 3247 | *out = arr; |
| 3248 | *count = n; |
| 3249 | return CBM_STORE_OK; |
| 3250 | } |
| 3251 | |
| 3252 | /* Bind helpers for edge queries */ |
| 3253 | typedef struct { |
no test coverage detected