#pragma once #include #include #include #include "Models.h" struct sqlite3; // Works on an in-memory SQLite database that is loaded from, and saved to, a // file on request (db save / backup / restore). class Database { public: Database(); ~Database(); Database(const Database&) = delete; Database& operator=(const Database&) = delete; // Loads `path` into memory if it exists, otherwise starts empty. void open(const std::string& path); void save(); std::string backup(const std::string& file); // empty = timestamped name; returns the file used void restore(const std::string& file); bool dirty() const; const std::string& path() const; // Accounts std::optional findAccount(const std::string& name) const; // canonical spelling std::vector listAccounts() const; void addAccount(const std::string& name); void removeAccount(const std::string& name); void renameAccount(const std::string& name, const std::string& newName); std::optional getAccount(const std::string& name) const; std::vector listAccountRows() const; void setAccountCooldown(const std::string& name, const std::optional& cooldown); // Tasks std::optional findTask(const std::string& name) const; // canonical spelling std::optional getTask(const std::string& name) const; std::vector listTasks() const; void addTask(const std::string& name, const std::optional& account, const std::string& status); void removeTask(const std::string& name); void renameTask(const std::string& name, const std::string& newName); void setTaskAccount(const std::string& name, const std::optional& account); void setTaskStatus(const std::string& name, const std::string& status); void setTaskNotes(const std::string& name, const std::string& notes); private: using Param = std::optional; using Row = std::vector>; void createSchema(); void exec(const std::string& sql); std::vector query(const std::string& sql, const std::vector& params = {}) const; void run(const std::string& sql, const std::vector& params); sqlite3* db_; std::string path_; bool dirty_; };