with_props=false skips the per-label/per-type JSON property-key discovery: * those json_each() scans walk EVERY row of each label/type (minutes-scale on * multi-million-node graphs) and get_architecture only needs the counts. */
| 5217 | * those json_each() scans walk EVERY row of each label/type (minutes-scale on |
| 5218 | * multi-million-node graphs) and get_architecture only needs the counts. */ |
| 5219 | static int get_schema_impl(cbm_store_t *s, const char *project, cbm_schema_info_t *out, |
| 5220 | bool with_props) { |
| 5221 | memset(out, 0, sizeof(*out)); |
| 5222 | if (!s || !s->db) { |
| 5223 | return CBM_NOT_FOUND; |
| 5224 | } |
| 5225 | |
| 5226 | /* Node labels */ |
| 5227 | { |
| 5228 | const char *sql = "SELECT label, COUNT(*) FROM nodes WHERE project = ?1 GROUP BY label " |
| 5229 | "ORDER BY COUNT(*) DESC;"; |
| 5230 | sqlite3_stmt *stmt = NULL; |
| 5231 | if (sqlite3_prepare_v2(s->db, sql, CBM_NOT_FOUND, &stmt, NULL) != SQLITE_OK || !stmt) { |
| 5232 | if (stmt) { |
| 5233 | sqlite3_finalize(stmt); |
| 5234 | } |
| 5235 | return CBM_NOT_FOUND; |
| 5236 | } |
| 5237 | bind_text(stmt, SKIP_ONE, project); |
| 5238 | |
| 5239 | int cap = ST_INIT_CAP_8; |
| 5240 | int n = 0; |
| 5241 | cbm_label_count_t *arr = malloc(cap * sizeof(cbm_label_count_t)); |
| 5242 | if (!arr) { |
| 5243 | sqlite3_finalize(stmt); |
| 5244 | return CBM_NOT_FOUND; |
| 5245 | } |
| 5246 | int scan_rc16; |
| 5247 | while ((scan_rc16 = sqlite3_step(stmt)) == SQLITE_ROW) { |
| 5248 | if (n >= cap) { |
| 5249 | int new_cap = cap * ST_GROWTH; |
| 5250 | void *tmp = realloc(arr, new_cap * sizeof(cbm_label_count_t)); |
| 5251 | if (!tmp) { |
| 5252 | for (int i = 0; i < n; i++) { |
| 5253 | safe_str_free(&arr[i].label); |
| 5254 | } |
| 5255 | free(arr); |
| 5256 | sqlite3_finalize(stmt); |
| 5257 | return CBM_NOT_FOUND; |
| 5258 | } |
| 5259 | arr = tmp; |
| 5260 | cap = new_cap; |
| 5261 | } |
| 5262 | arr[n].label = heap_strdup((const char *)sqlite3_column_text(stmt, 0)); |
| 5263 | arr[n].count = sqlite3_column_int(stmt, SKIP_ONE); |
| 5264 | arr[n].properties = NULL; |
| 5265 | arr[n].property_count = 0; |
| 5266 | n++; |
| 5267 | } |
| 5268 | if (scan_rc16 != SQLITE_DONE) { /* SCANCHK:16:stmt */ |
| 5269 | store_set_error_sqlite(s, "row scan aborted"); |
| 5270 | sqlite3_finalize(stmt); |
| 5271 | out->node_labels = arr; |
| 5272 | out->node_label_count = n; |
| 5273 | return CBM_STORE_ERR; |
| 5274 | } |
| 5275 | sqlite3_finalize(stmt); |
| 5276 | out->node_labels = arr; |
no test coverage detected