| 8084 | } |
| 8085 | |
| 8086 | int cbm_store_adr_get(cbm_store_t *s, const char *project, cbm_adr_t *out) { |
| 8087 | if (!s || !s->db || !project || !out) { |
| 8088 | return CBM_STORE_ERR; |
| 8089 | } |
| 8090 | memset(out, 0, sizeof(*out)); |
| 8091 | |
| 8092 | /* ADR storage was added after the original graph schema. A readable |
| 8093 | * legacy generation without project_summaries has no ADR to preserve; it |
| 8094 | * is not a read failure and must remain replaceable by a full reindex. */ |
| 8095 | sqlite3_stmt *table_stmt = NULL; |
| 8096 | int rc = sqlite3_prepare_v2( |
| 8097 | s->db, |
| 8098 | "SELECT 1 FROM sqlite_master WHERE type='table' AND name='project_summaries' LIMIT 1;", |
| 8099 | CBM_NOT_FOUND, &table_stmt, NULL); |
| 8100 | if (rc != SQLITE_OK) { |
| 8101 | store_set_error_sqlite(s, "adr_get table probe"); |
| 8102 | return CBM_STORE_ERR; |
| 8103 | } |
| 8104 | rc = sqlite3_step(table_stmt); |
| 8105 | if (rc == SQLITE_DONE) { |
| 8106 | sqlite3_finalize(table_stmt); |
| 8107 | return CBM_STORE_NOT_FOUND; |
| 8108 | } |
| 8109 | if (rc != SQLITE_ROW || sqlite3_finalize(table_stmt) != SQLITE_OK) { |
| 8110 | store_set_error_sqlite(s, "adr_get table probe step"); |
| 8111 | return CBM_STORE_ERR; |
| 8112 | } |
| 8113 | |
| 8114 | const char *sql = "SELECT project, summary, created_at, updated_at FROM project_summaries " |
| 8115 | "WHERE project=?1"; |
| 8116 | sqlite3_stmt *stmt = NULL; |
| 8117 | if (sqlite3_prepare_v2(s->db, sql, CBM_NOT_FOUND, &stmt, NULL) != SQLITE_OK) { |
| 8118 | store_set_error_sqlite(s, "adr_get"); |
| 8119 | return CBM_STORE_ERR; |
| 8120 | } |
| 8121 | if (bind_text(stmt, SKIP_ONE, project) != SQLITE_OK) { |
| 8122 | store_set_error_sqlite(s, "adr_get bind"); |
| 8123 | sqlite3_finalize(stmt); |
| 8124 | return CBM_STORE_ERR; |
| 8125 | } |
| 8126 | rc = sqlite3_step(stmt); |
| 8127 | if (rc != SQLITE_ROW) { |
| 8128 | if (rc != SQLITE_DONE) { |
| 8129 | store_set_error_sqlite(s, "adr_get step"); |
| 8130 | } |
| 8131 | sqlite3_finalize(stmt); |
| 8132 | if (rc == SQLITE_DONE) { |
| 8133 | store_set_error(s, "no ADR found"); |
| 8134 | return CBM_STORE_NOT_FOUND; |
| 8135 | } |
| 8136 | return CBM_STORE_ERR; |
| 8137 | } |
| 8138 | out->project = heap_strdup((const char *)sqlite3_column_text(stmt, 0)); |
| 8139 | out->content = heap_strdup((const char *)sqlite3_column_text(stmt, SKIP_ONE)); |
| 8140 | out->created_at = heap_strdup((const char *)sqlite3_column_text(stmt, CBM_SZ_2)); |
| 8141 | out->updated_at = heap_strdup((const char *)sqlite3_column_text(stmt, CBM_SZ_3)); |
| 8142 | rc = sqlite3_finalize(stmt); |
| 8143 | if (rc != SQLITE_OK) { |