Generic: find multiple edges by a filter. */
| 2183 | |
| 2184 | /* Generic: find multiple edges by a filter. */ |
| 2185 | static int find_edges_generic(cbm_store_t *s, sqlite3_stmt **slot, const char *sql, |
| 2186 | void (*bind_fn)(sqlite3_stmt *, const void *), const void *bind_data, |
| 2187 | cbm_edge_t **out, int *count) { |
| 2188 | if (!s || !s->db) { |
| 2189 | *out = NULL; |
| 2190 | *count = 0; |
| 2191 | return CBM_STORE_ERR; |
| 2192 | } |
| 2193 | sqlite3_stmt *stmt = prepare_cached(s, slot, sql); |
| 2194 | if (!stmt) { |
| 2195 | return CBM_STORE_ERR; |
| 2196 | } |
| 2197 | |
| 2198 | bind_fn(stmt, bind_data); |
| 2199 | |
| 2200 | int cap = ST_INIT_CAP_16; |
| 2201 | int n = 0; |
| 2202 | cbm_edge_t *arr = malloc(cap * sizeof(cbm_edge_t)); |
| 2203 | |
| 2204 | int scan_rc4; |
| 2205 | while ((scan_rc4 = sqlite3_step(stmt)) == SQLITE_ROW) { |
| 2206 | if (n >= cap) { |
| 2207 | cap *= ST_GROWTH; |
| 2208 | arr = safe_realloc(arr, cap * sizeof(cbm_edge_t)); |
| 2209 | } |
| 2210 | scan_edge(stmt, &arr[n]); |
| 2211 | n++; |
| 2212 | } |
| 2213 | if (scan_rc4 != SQLITE_DONE) { /* SCANCHK:4:stmt */ |
| 2214 | store_set_error_sqlite(s, "row scan aborted"); |
| 2215 | cbm_store_free_edges(arr, n); |
| 2216 | *out = NULL; |
| 2217 | *count = 0; |
| 2218 | return CBM_STORE_ERR; |
| 2219 | } |
| 2220 | |
| 2221 | *out = arr; |
| 2222 | *count = n; |
| 2223 | return CBM_STORE_OK; |
| 2224 | } |
| 2225 | |
| 2226 | /* Bind helpers for edge queries */ |
| 2227 | typedef struct { |
no test coverage detected