sqlite3_engine.cpp 2.58 KB
Newer Older
1 2 3 4
#include <biboumi.h>

#ifdef SQLITE3_FOUND

louiz’'s avatar
louiz’ committed
5 6 7
#include <database/sqlite3_engine.hpp>
#include <database/sqlite3_statement.hpp>

8 9
#include <database/query.hpp>

louiz’'s avatar
louiz’ committed
10 11 12 13 14 15 16 17 18 19 20 21 22 23
#include <utils/tolower.hpp>
#include <logger/logger.hpp>
#include <vector>

Sqlite3Engine::Sqlite3Engine(sqlite3* db):
    db(db)
{
}

Sqlite3Engine::~Sqlite3Engine()
{
  sqlite3_close(this->db);
}

24
std::set<std::string> Sqlite3Engine::get_all_columns_from_table(const std::string& table_name)
louiz’'s avatar
louiz’ committed
25
{
26
  std::set<std::string> result;
louiz’'s avatar
louiz’ committed
27 28 29 30
  char* errmsg;
  std::string query{"PRAGMA table_info(" + table_name + ")"};
  int res = sqlite3_exec(this->db, query.data(), [](void* param, int columns_nb, char** columns, char**) -> int {
    constexpr int name_column = 1;
31 32 33
    std::set<std::string>* result = static_cast<std::set<std::string>*>(param);
    if (name_column < columns_nb)
      result->insert(utils::tolower(columns[name_column]));
louiz’'s avatar
louiz’ committed
34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60
    return 0;
  }, &result, &errmsg);

  if (res != SQLITE_OK)
    {
      log_error("Error executing ", query, ": ", errmsg);
      sqlite3_free(errmsg);
    }

  return result;
}

std::unique_ptr<DatabaseEngine> Sqlite3Engine::open(const std::string& filename)
{
  sqlite3* new_db;
  auto res = sqlite3_open_v2(filename.data(), &new_db, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, nullptr);
  if (res != SQLITE_OK)
    {
      log_error("Failed to open database file ", filename, ": ", sqlite3_errmsg(new_db));
      sqlite3_close(new_db);
      throw std::runtime_error("");
    }
  return std::make_unique<Sqlite3Engine>(new_db);
}

std::tuple<bool, std::string> Sqlite3Engine::raw_exec(const std::string& query)
{
61 62 63 64 65
#ifdef DEBUG_SQL_QUERIES
  log_debug("SQL QUERY: ", query);
  const auto timer = make_sql_timer();
#endif

louiz’'s avatar
louiz’ committed
66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89
  char* error;
  const auto result = sqlite3_exec(db, query.data(), nullptr, nullptr, &error);
  if (result != SQLITE_OK)
    {
      std::string err_msg(error);
      sqlite3_free(error);
      return std::make_tuple(false, err_msg);
    }
  return std::make_tuple(true, std::string{});
}

std::unique_ptr<Statement> Sqlite3Engine::prepare(const std::string& query)
{
  sqlite3_stmt* stmt;
  auto res = sqlite3_prepare(db, query.data(), static_cast<int>(query.size()) + 1,
                             &stmt, nullptr);
  if (res != SQLITE_OK)
    {
      log_error("Error preparing statement: ", sqlite3_errmsg(db));
      return nullptr;
    }
  return std::make_unique<Sqlite3Statement>(stmt);
}

90
void Sqlite3Engine::extract_last_insert_rowid(Statement&)
louiz’'s avatar
louiz’ committed
91 92 93 94
{
  this->last_inserted_rowid = sqlite3_last_insert_rowid(this->db);
}

95
std::string Sqlite3Engine::id_column_type()
louiz’'s avatar
louiz’ committed
96 97 98
{
  return "INTEGER PRIMARY KEY AUTOINCREMENT";
}
99 100

#endif