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