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. */
| 5006 | * those json_each() scans walk EVERY row of each label/type (minutes-scale on |
| 5007 | * multi-million-node graphs) and get_architecture only needs the counts. */ |
| 5008 | static int get_schema_impl(cbm_store_t *s, const char *project, cbm_schema_info_t *out, |
| 5009 | bool with_props) { |
| 5010 | memset(out, 0, sizeof(*out)); |
| 5011 | if (!s || !s->db) { |
| 5012 | return CBM_NOT_FOUND; |
| 5013 | } |
| 5014 | |
| 5015 | /* Node labels */ |
| 5016 | { |
| 5017 | const char *sql = "SELECT label, COUNT(*) FROM nodes WHERE project = ?1 GROUP BY label " |
| 5018 | "ORDER BY COUNT(*) DESC;"; |
| 5019 | sqlite3_stmt *stmt = NULL; |
| 5020 | if (sqlite3_prepare_v2(s->db, sql, CBM_NOT_FOUND, &stmt, NULL) != SQLITE_OK || !stmt) { |
| 5021 | if (stmt) { |
| 5022 | sqlite3_finalize(stmt); |
| 5023 | } |
| 5024 | return CBM_NOT_FOUND; |
| 5025 | } |
| 5026 | bind_text(stmt, SKIP_ONE, project); |
| 5027 | |
| 5028 | int cap = ST_INIT_CAP_8; |
| 5029 | int n = 0; |
| 5030 | cbm_label_count_t *arr = malloc(cap * sizeof(cbm_label_count_t)); |
| 5031 | if (!arr) { |
| 5032 | sqlite3_finalize(stmt); |
| 5033 | return CBM_NOT_FOUND; |
| 5034 | } |
| 5035 | int scan_rc16; |
| 5036 | while ((scan_rc16 = sqlite3_step(stmt)) == SQLITE_ROW) { |
| 5037 | if (n >= cap) { |
| 5038 | int new_cap = cap * ST_GROWTH; |
| 5039 | void *tmp = realloc(arr, new_cap * sizeof(cbm_label_count_t)); |
| 5040 | if (!tmp) { |
| 5041 | for (int i = 0; i < n; i++) { |
| 5042 | safe_str_free(&arr[i].label); |
| 5043 | } |
| 5044 | free(arr); |
| 5045 | sqlite3_finalize(stmt); |
| 5046 | return CBM_NOT_FOUND; |
| 5047 | } |
| 5048 | arr = tmp; |
| 5049 | cap = new_cap; |
| 5050 | } |
| 5051 | arr[n].label = heap_strdup((const char *)sqlite3_column_text(stmt, 0)); |
| 5052 | arr[n].count = sqlite3_column_int(stmt, SKIP_ONE); |
| 5053 | arr[n].properties = NULL; |
| 5054 | arr[n].property_count = 0; |
| 5055 | n++; |
| 5056 | } |
| 5057 | if (scan_rc16 != SQLITE_DONE) { /* SCANCHK:16:stmt */ |
| 5058 | store_set_error_sqlite(s, "row scan aborted"); |
| 5059 | sqlite3_finalize(stmt); |
| 5060 | out->node_labels = arr; |
| 5061 | out->node_label_count = n; |
| 5062 | return CBM_STORE_ERR; |
| 5063 | } |
| 5064 | sqlite3_finalize(stmt); |
| 5065 | out->node_labels = arr; |
no test coverage detected