#include "Database.h" #include "BoostLog.h" #include #include bool Database::open(const std::string &path) { bool ret = true; int result = sqlite3_open(path.c_str(), &m_sqlite3); if (result != SQLITE_OK) { ret = false; LOG(error) << "open database failed."; } initialize(); return ret; } static int selectTaskCallback(void *data, int argc, char **argv, char **columnName) { auto tasks = reinterpret_cast(data); Task task; for (int i = 0; i < argc; i++) { if (argv[i] == nullptr) continue; if (strcmp(columnName[i], "id") == 0) { task.id = std::atol(argv[i]); } else if (strcmp(columnName[i], "create_time") == 0) { task.createTime = std::atol(argv[i]); } else if (strcmp(columnName[i], "content") == 0) { task.content = argv[i]; } else if (strcmp(columnName[i], "comment") == 0) { task.comment = argv[i]; } else if (strcmp(columnName[i], "finished") == 0) { task.finished = std::atol(argv[i]); } else if (strcmp(columnName[i], "parent_id") == 0) { task.parentId = std::atol(argv[i]); } } tasks->push_back(task); return 0; } Tasks Database::tasks() { Tasks ret; char *error = nullptr; if (sqlite3_exec(m_sqlite3, "select * from tasks", selectTaskCallback, &ret, &error) != SQLITE_OK) { LOG(error) << "sqlite3_exec() failed: " << error << std::endl; sqlite3_free(error); } std::unordered_map tasks; for (auto iterator = ret.begin(); iterator != ret.end();) { if (iterator->parentId >= 0) { if (tasks.count(iterator->parentId) > 0) { auto parentTask = tasks.at(iterator->parentId); parentTask->children.push_back(*iterator); tasks.insert({iterator->id, &parentTask->children.back()}); } else { LOG(warning) << "task`s parent id " << iterator->parentId << " not existed."; } iterator = ret.erase(iterator); } else { tasks.insert({iterator->id, &(*iterator)}); ++iterator; } } return ret; } bool Database::addTask(uint64_t createTime, const std::string &content, const std::string &comment, int parentId, bool finished) { bool ret = true; std::ostringstream oss; oss << "INSERT INTO tasks (create_time,content,comment,parent_id,finished) VALUES (" << createTime << ",\"" << content << "\",\"" << comment << "\"," << parentId << "," << finished << ");"; auto sql = oss.str(); char *error = nullptr; int result = sqlite3_exec(m_sqlite3, sql.c_str(), NULL, NULL, &error); if (result != SQLITE_OK) { LOG(error) << "add task failed: " << error << ", sql: " << sql; sqlite3_free(error); ret = false; } return ret; } bool Database::removeTask(int id) { bool ret = true; std::ostringstream oss; oss << "DELETE FROM tasks WHERE id = " << id << ";"; auto sql = oss.str(); char *error = nullptr; int result = sqlite3_exec(m_sqlite3, sql.c_str(), NULL, NULL, &error); if (result != SQLITE_OK) { LOG(error) << "add task failed: " << error << ", sql: " << sql; sqlite3_free(error); ret = false; } return ret; } void Database::setTaskFinished(int id, bool finished, uint64_t finishedTime) { std::ostringstream oss; oss << "UPDATE tasks SET finished = " << finished << ", finished_time = " << finishedTime << " WHERE id = " << id; auto sql = oss.str(); int result = sqlite3_exec(m_sqlite3, sql.c_str(), NULL, NULL, NULL); if (result != SQLITE_OK) { LOG(error) << "add task failed: " << sqlite3_errmsg(m_sqlite3) << ", sql: " << sql; return; } } void Database::initialize() { const char *sql = "CREATE TABLE IF NOT EXISTS tasks (id INTEGER PRIMARY KEY AUTOINCREMENT, create_time INTEGER NOT NULL, " "parent_id INTEGER, content VARCHAR(512) NOT NULL, comment VARCHAR(512) NOT NULL, finished BOLL, finished_time " "INTEGER);"; int result = sqlite3_exec(m_sqlite3, sql, NULL, NULL, NULL); if (result != SQLITE_OK) { LOG(error) << "Failed to create table: " << sqlite3_errmsg(m_sqlite3); return; } } Database::~Database() { if (m_sqlite3 != nullptr) { sqlite3_close(m_sqlite3); m_sqlite3 = nullptr; } }