20std::vector<std::string> loadIds(sqlite3* db,
const char* sql,
21 const std::string& exportLogId) {
22 std::vector<std::string> ids;
23 if (!db || exportLogId.empty()) {
32 stmt.bindText(1, exportLogId);
33 while (stmt.step() == SQLITE_ROW) {
34 ids.push_back(stmt.columnText(0));
39void saveIds(sqlite3* db,
const std::string& exportLogId,
40 const std::vector<std::string>& ids,
const char* deleteSql,
41 const char* insertSql) {
42 if (!db || exportLogId.empty()) {
50 deleteStmt.bindText(1, exportLogId);
58 for (std::size_t i = 0; i < ids.size(); ++i) {
59 const auto&
id = ids[i];
64 insertStmt.bindText(1, exportLogId);
65 insertStmt.bindText(2,
id);
66 insertStmt.bindInt(3,
static_cast<int>(i));
73 const std::shared_ptr<core::application::exporting::ExportLog>& log,
79 if (log->id.empty()) {
88 stmt.bindText(1, log->id);
89 stmt.bindText(2, log->time);
90 stmt.bindText(3, log->targetPath);
91 stmt.bindText(4, log->status);
92 stmt.bindText(5, log->message);
99 explicit Impl(std::shared_ptr<SqliteDb>
db) :
db(std::move(
db)) {}
101 std::shared_ptr<SqliteDb>
db;
108 std::shared_ptr<SqliteDb> db)
109 : pimpl_(std::make_unique<
Impl>(std::move(db))) {
111 throw std::runtime_error(
"db is null");
118 const std::shared_ptr<core::application::exporting::ExportLog>& log) {
119 const auto db = pimpl_->db->handle();
120 writeExportLog(db, log,
121 "INSERT INTO export_logs (id, time, target_path, status, "
122 "message) VALUES (?, ?, ?, ?, ?);");
124 saveIds(db, log->id, log->annualIds,
125 "DELETE FROM export_log_annuals WHERE export_log_id = ?;",
126 "INSERT OR IGNORE INTO export_log_annuals (export_log_id, "
127 "annual_id, position) VALUES (?, ?, ?);");
128 saveIds(db, log->id, log->analysisIds,
129 "DELETE FROM export_log_analyses WHERE export_log_id = ?;",
130 "INSERT OR IGNORE INTO export_log_analyses (export_log_id, "
131 "analysis_id, position) VALUES (?, ?, ?);");
135std::vector<std::shared_ptr<core::application::exporting::ExportLog>>
137 std::vector<std::shared_ptr<core::application::exporting::ExportLog>> logs;
138 const auto db = pimpl_->db->handle();
140 "SELECT id, time, target_path, status, message "
141 "FROM export_logs ORDER BY time DESC, id DESC;");
146 while (stmt.
step() == SQLITE_ROW) {
147 auto log = std::make_shared<core::application::exporting::ExportLog>();
153 log->annualIds = loadIds(db,
154 "SELECT annual_id FROM export_log_annuals WHERE "
155 "export_log_id = ? ORDER BY position, annual_id;",
159 "SELECT analysis_id FROM export_log_analyses WHERE "
160 "export_log_id = ? ORDER BY position, analysis_id;",
162 logs.push_back(std::move(log));
168std::optional<std::shared_ptr<core::application::exporting::ExportLog>>
170 const auto db = pimpl_->db->handle();
172 "SELECT id, time, target_path, status, message "
173 "FROM export_logs WHERE id = ? LIMIT 1;");
179 if (stmt.
step() != SQLITE_ROW) {
183 auto log = std::make_shared<core::application::exporting::ExportLog>();
189 log->annualIds = loadIds(db,
190 "SELECT annual_id FROM export_log_annuals WHERE "
191 "export_log_id = ? ORDER BY position, annual_id;",
195 "SELECT analysis_id FROM export_log_analyses WHERE export_log_id "
196 "= ? ORDER BY position, analysis_id;",
203 "DELETE FROM export_logs WHERE id = ?;");
212 const std::shared_ptr<core::application::exporting::ExportLog>& log) {
213 const auto db = pimpl_->db->handle();
214 writeExportLog(db, log,
215 "UPDATE export_logs SET time = ?2, target_path = ?3, status = "
216 "?4, message = ?5 WHERE id = ?1;");
218 saveIds(db, log->id, log->annualIds,
219 "DELETE FROM export_log_annuals WHERE export_log_id = ?;",
220 "INSERT OR IGNORE INTO export_log_annuals (export_log_id, "
221 "annual_id, position) VALUES (?, ?, ?);");
222 saveIds(db, log->id, log->analysisIds,
223 "DELETE FROM export_log_analyses WHERE export_log_id = ?;",
224 "INSERT OR IGNORE INTO export_log_analyses (export_log_id, "
225 "analysis_id, position) VALUES (?, ?, ?);");
230 const std::shared_ptr<core::application::exporting::ExportLog>& log) {
231 const auto db = pimpl_->db->handle();
232 writeExportLog(db, log,
233 "INSERT OR REPLACE INTO export_logs (id, time, target_path, "
234 "status, message) VALUES (?, ?, ?, ?, ?);");
236 saveIds(db, log->id, log->annualIds,
237 "DELETE FROM export_log_annuals WHERE export_log_id = ?;",
238 "INSERT OR IGNORE INTO export_log_annuals (export_log_id, "
239 "annual_id, position) VALUES (?, ?, ?);");
240 saveIds(db, log->id, log->analysisIds,
241 "DELETE FROM export_log_analyses WHERE export_log_id = ?;",
242 "INSERT OR IGNORE INTO export_log_analyses (export_log_id, "
243 "analysis_id, position) VALUES (?, ?, ?);");
Declares the persisted metadata record for an export run.
Declares the lightweight SQLite connection wrapper.
Declares the SQLite-backed export log repository.
RAII wrapper for sqlite3_stmt* that auto-finalizes on destruction.
void clearExportLogs() override
Remove all export log entries.
SqliteExportLogRepository(const std::string &dbPath)
Create an export log repository for the database at the given path.
std::vector< std::shared_ptr< core::application::exporting::ExportLog > > getExportLogs() const override
Retrieve all export log entries.
std::optional< std::shared_ptr< core::application::exporting::ExportLog > > getExportLogById(const std::string &id) const override
Retrieve an export log entry by identifier.
void addExportLog(const std::shared_ptr< core::application::exporting::ExportLog > &log) override
Insert a new export log entry.
void upsertExportLog(const std::shared_ptr< core::application::exporting::ExportLog > &log) override
Insert or update an export log entry.
~SqliteExportLogRepository() override
Destroy the repository.
void updateExportLog(const std::shared_ptr< core::application::exporting::ExportLog > &log) override
Update an existing export log entry.
void removeExportLog(const std::string &id) override
Remove an export log entry by identifier.
std::string columnText(int col) const noexcept
void bindText(int col, const std::string &v) noexcept
std::string generateUuid()
Impl(std::shared_ptr< SqliteDb > db)
std::shared_ptr< SqliteDb > db