123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131 |
- // SPDX-License-Identifier: GPL-3.0-or-later
- #ifndef ML_DATABASE_H
- #define ML_DATABASE_H
- #include "Dimension.h"
- #include "ml-private.h"
- #include "json/single_include/nlohmann/json.hpp"
- namespace ml {
- class Statement {
- public:
- using RowCallback = std::function<void(sqlite3_stmt *Stmt)>;
- public:
- Statement(const char *RawStmt) : RawStmt(RawStmt), ParsedStmt(nullptr) {}
- template<typename ...ArgTypes>
- bool exec(sqlite3 *Conn, RowCallback RowCb, ArgTypes ...Args) {
- if (!prepare(Conn))
- return false;
- switch (bind(1, Args...)) {
- case 0:
- return false;
- case sizeof...(Args):
- break;
- default:
- return resetAndClear(false);
- }
- while (true) {
- switch (int RC = sqlite3_step(ParsedStmt)) {
- case SQLITE_BUSY: case SQLITE_LOCKED:
- usleep(SQLITE_INSERT_DELAY * USEC_PER_MS);
- continue;
- case SQLITE_ROW:
- RowCb(ParsedStmt);
- continue;
- case SQLITE_DONE:
- return resetAndClear(true);
- default:
- error("Stepping through '%s' returned rc=%d", RawStmt, RC);
- return resetAndClear(false);
- }
- }
- }
- ~Statement() {
- if (!ParsedStmt)
- return;
- int RC = sqlite3_finalize(ParsedStmt);
- if (RC != SQLITE_OK)
- error("Could not properly finalize statement (rc=%d)", RC);
- }
- private:
- bool prepare(sqlite3 *Conn);
- bool bindValue(size_t Pos, const int Value);
- bool bindValue(size_t Pos, const std::string &Value);
- template<typename ArgType, typename ...ArgTypes>
- size_t bind(size_t Pos, ArgType T) {
- return bindValue(Pos, T);
- }
- template<typename ArgType, typename ...ArgTypes>
- size_t bind(size_t Pos, ArgType T, ArgTypes ...Args) {
- return bindValue(Pos, T) + bind(Pos + 1, Args...);
- }
- bool resetAndClear(bool Ret);
- private:
- const char *RawStmt;
- sqlite3_stmt *ParsedStmt;
- };
- class Database {
- private:
- static const char *SQL_CREATE_ANOMALIES_TABLE;
- static const char *SQL_INSERT_ANOMALY;
- static const char *SQL_SELECT_ANOMALY;
- static const char *SQL_SELECT_ANOMALY_EVENTS;
- public:
- Database(const std::string &Path);
- ~Database();
- template<typename ...ArgTypes>
- bool insertAnomaly(ArgTypes... Args) {
- Statement::RowCallback RowCb = [](sqlite3_stmt *Stmt) { (void) Stmt; };
- return InsertAnomalyStmt.exec(Conn, RowCb, Args...);
- }
- template<typename ...ArgTypes>
- bool getAnomalyInfo(nlohmann::json &Json, ArgTypes&&... Args) {
- Statement::RowCallback RowCb = [&](sqlite3_stmt *Stmt) {
- const char *Text = static_cast<const char *>(sqlite3_column_blob(Stmt, 0));
- Json = nlohmann::json::parse(Text);
- };
- return GetAnomalyInfoStmt.exec(Conn, RowCb, Args...);
- }
- template<typename ...ArgTypes>
- bool getAnomaliesInRange(std::vector<std::pair<time_t, time_t>> &V, ArgTypes&&... Args) {
- Statement::RowCallback RowCb = [&](sqlite3_stmt *Stmt) {
- V.push_back({
- sqlite3_column_int64(Stmt, 0),
- sqlite3_column_int64(Stmt, 1)
- });
- };
- return GetAnomaliesInRangeStmt.exec(Conn, RowCb, Args...);
- }
- private:
- sqlite3 *Conn;
- Statement InsertAnomalyStmt{SQL_INSERT_ANOMALY};
- Statement GetAnomalyInfoStmt{SQL_SELECT_ANOMALY};
- Statement GetAnomaliesInRangeStmt{SQL_SELECT_ANOMALY_EVENTS};
- };
- }
- #endif /* ML_DATABASE_H */
|