Database.cc 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127
  1. // SPDX-License-Identifier: GPL-3.0-or-later
  2. #include "Database.h"
  3. const char *ml::Database::SQL_CREATE_ANOMALIES_TABLE =
  4. "CREATE TABLE IF NOT EXISTS anomaly_events( "
  5. " anomaly_detector_name text NOT NULL, "
  6. " anomaly_detector_version int NOT NULL, "
  7. " host_id text NOT NULL, "
  8. " after int NOT NULL, "
  9. " before int NOT NULL, "
  10. " anomaly_event_info text, "
  11. " PRIMARY KEY( "
  12. " anomaly_detector_name, anomaly_detector_version, "
  13. " host_id, after, before "
  14. " ) "
  15. ");";
  16. const char *ml::Database::SQL_INSERT_ANOMALY =
  17. "INSERT INTO anomaly_events( "
  18. " anomaly_detector_name, anomaly_detector_version, "
  19. " host_id, after, before, anomaly_event_info) "
  20. "VALUES (?1, ?2, ?3, ?4, ?5, ?6);";
  21. const char *ml::Database::SQL_SELECT_ANOMALY =
  22. "SELECT anomaly_event_info FROM anomaly_events WHERE"
  23. " anomaly_detector_name == ?1 AND"
  24. " anomaly_detector_version == ?2 AND"
  25. " host_id == ?3 AND"
  26. " after == ?4 AND"
  27. " before == ?5;";
  28. const char *ml::Database::SQL_SELECT_ANOMALY_EVENTS =
  29. "SELECT after, before FROM anomaly_events WHERE"
  30. " anomaly_detector_name == ?1 AND"
  31. " anomaly_detector_version == ?2 AND"
  32. " host_id == ?3 AND"
  33. " after >= ?4 AND"
  34. " before <= ?5;";
  35. using namespace ml;
  36. bool Statement::prepare(sqlite3 *Conn) {
  37. if (!Conn)
  38. return false;
  39. if (ParsedStmt)
  40. return true;
  41. int RC = sqlite3_prepare_v2(Conn, RawStmt, -1, &ParsedStmt, nullptr);
  42. if (RC == SQLITE_OK)
  43. return true;
  44. std::string Msg = "Statement \"%s\" preparation failed due to \"%s\"";
  45. error(Msg.c_str(), RawStmt, sqlite3_errstr(RC));
  46. return false;
  47. }
  48. bool Statement::bindValue(size_t Pos, const std::string &Value) {
  49. int RC = sqlite3_bind_text(ParsedStmt, Pos, Value.c_str(), -1, SQLITE_TRANSIENT);
  50. if (RC == SQLITE_OK)
  51. return true;
  52. error("Failed to bind text '%s' (pos = %zu) in statement '%s'.", Value.c_str(), Pos, RawStmt);
  53. return false;
  54. }
  55. bool Statement::bindValue(size_t Pos, const int Value) {
  56. int RC = sqlite3_bind_int(ParsedStmt, Pos, Value);
  57. if (RC == SQLITE_OK)
  58. return true;
  59. error("Failed to bind integer %d (pos = %zu) in statement '%s'.", Value, Pos, RawStmt);
  60. return false;
  61. }
  62. bool Statement::resetAndClear(bool Ret) {
  63. int RC = sqlite3_reset(ParsedStmt);
  64. if (RC != SQLITE_OK) {
  65. error("Could not reset statement: '%s'", RawStmt);
  66. return false;
  67. }
  68. RC = sqlite3_clear_bindings(ParsedStmt);
  69. if (RC != SQLITE_OK) {
  70. error("Could not clear bindings in statement: '%s'", RawStmt);
  71. return false;
  72. }
  73. return Ret;
  74. }
  75. Database::Database(const std::string &Path) {
  76. // Get sqlite3 connection handle.
  77. int RC = sqlite3_open(Path.c_str(), &Conn);
  78. if (RC != SQLITE_OK) {
  79. std::string Msg = "Failed to initialize ML DB at %s, due to \"%s\"";
  80. error(Msg.c_str(), Path.c_str(), sqlite3_errstr(RC));
  81. sqlite3_close(Conn);
  82. Conn = nullptr;
  83. return;
  84. }
  85. // Create anomaly events table if it does not exist.
  86. char *ErrMsg;
  87. RC = sqlite3_exec(Conn, SQL_CREATE_ANOMALIES_TABLE, nullptr, nullptr, &ErrMsg);
  88. if (RC == SQLITE_OK)
  89. return;
  90. error("SQLite error during database initialization, rc = %d (%s)", RC, ErrMsg);
  91. error("SQLite failed statement: %s", SQL_CREATE_ANOMALIES_TABLE);
  92. sqlite3_free(ErrMsg);
  93. sqlite3_close(Conn);
  94. Conn = nullptr;
  95. }
  96. Database::~Database() {
  97. if (!Conn)
  98. return;
  99. int RC = sqlite3_close(Conn);
  100. if (RC != SQLITE_OK)
  101. error("Could not close connection properly (rc=%d)", RC);
  102. }