// // Created by quentin on 1/18/23. // #include "database.h" #include #include bool Database::doesAccountExist(const std::string &account, sqlite3 *db) { sqlite3_stmt *stmt; int rc = sqlite3_prepare_v2(db, "SELECT * FROM account WHERE name = ?", -1, &stmt, nullptr); if (rc != SQLITE_OK) throw std::runtime_error("Failed to prepare account exist query."); sqlite3_bind_text(stmt, 1, account.c_str(), -1, SQLITE_TRANSIENT); rc = sqlite3_step(stmt); sqlite3_finalize(stmt); if (rc == SQLITE_ROW) { return true; } else if (rc == SQLITE_DONE) { return false; } else { throw std::runtime_error("Failed to step account existing statement."); } } bool Database::deleteAccount(const std::string &account, sqlite3 *db) { sqlite3_stmt *stmt; int rc = sqlite3_prepare_v2(db, "DELETE FROM account WHERE name = ?", -1, &stmt, nullptr); if (rc != SQLITE_OK) throw std::runtime_error("Failed to delete account " + account); sqlite3_bind_text(stmt, 1, account.c_str(), -1, SQLITE_TRANSIENT); rc = sqlite3_step(stmt); sqlite3_finalize(stmt); return (rc == SQLITE_DONE); } double Database::getValue(const std::string &account, sqlite3 *db) { sqlite3_stmt *stmt; int rc = sqlite3_prepare_v2(db, "SELECT id, cachedValue FROM account WHERE name = ?", -1, &stmt, nullptr); if (rc != SQLITE_OK) throw std::runtime_error("Failed preparing cashedValue " + account); sqlite3_bind_text(stmt, 1, account.c_str(), -1, SQLITE_TRANSIENT); rc = sqlite3_step(stmt); if (rc == SQLITE_ROW) { double value; if (sqlite3_column_type(stmt, 1) == SQLITE_NULL) { value = cacheAccountValue(sqlite3_column_int64(stmt, 0), db); sqlite3_finalize(stmt); return value; } value = sqlite3_column_double(stmt, 1); sqlite3_finalize(stmt); return value; } else if (rc == SQLITE_DONE) throw std::runtime_error("Account doesnt exist? Shouldn't be possible in this call."); else throw std::runtime_error("Failed to step getValue statement."); } double Database::cacheAccountValue(long long accountId, sqlite3 *db) { sqlite3_stmt *stmt; int rc = sqlite3_prepare_v2(db, "SELECT SUM(value) FROM (" "SELECT value * -1 as value FROM payment WHERE accountId = ? " "UNION ALL " "SELECT value FROM earning WHERE accountId = ?);", -1, &stmt, nullptr); if (rc != SQLITE_OK) throw std::runtime_error("Failed preparing get cashedValue " + std::to_string(accountId)); sqlite3_bind_int64(stmt, 1, accountId); sqlite3_bind_int64(stmt, 2, accountId); rc = sqlite3_step(stmt); double value; if (rc == SQLITE_ROW) value = sqlite3_column_double(stmt, 0); else if (rc == SQLITE_DONE) value = 0; else throw std::runtime_error("Failed get cashedValue " + std::to_string(accountId)); sqlite3_reset(stmt); rc = sqlite3_prepare_v2(db, "UPDATE account SET cachedValue = ? WHERE id = ?", -1, &stmt, nullptr); if (rc != SQLITE_OK) throw std::runtime_error("Failed preparing set cashedValue " + std::to_string(accountId)); sqlite3_bind_double(stmt, 1, value); sqlite3_bind_int64(stmt, 2, accountId); rc = sqlite3_step(stmt); if (rc == SQLITE_DONE) return value; throw std::runtime_error("Failed to set cashedValue for " + std::to_string(accountId)); }