diff --git a/src/pEpSQLite.cc b/src/pEpSQLite.cc new file mode 100644 index 0000000..182a9d4 --- /dev/null +++ b/src/pEpSQLite.cc @@ -0,0 +1,96 @@ +#include "pEpSQLite.hh" +#include "pEpLog.hh" +#include +#include +#include + +using namespace std; + +namespace pEp { + bool pEpSQLite::log_enabled = false; + + pEpSQLite::pEpSQLite(std::string db_path) : db_path(db_path) + { + pEpLogClass("called with: db_path = "+ db_path +""); + } + + void pEpSQLite::create_or_open_db() + { + pEpLogClass("called"); + int rc{::sqlite3_open(db_path.c_str(), &db)}; + + if (rc) { + runtime_error e{string("Can't open database (" + db_path + "):" + ::sqlite3_errmsg(db))}; + throw (e); + } + } + + string pEpSQLite::get_db_path() + { + pEpLogClass("called"); + return db_path; + } + + void pEpSQLite::close_db() + { + pEpLogClass("called"); + ::sqlite3_close(db); + } + + void pEpSQLite::delete_db() + { + pEpLogClass("called"); + remove(db_path.c_str()); + if (errno) { + runtime_error e{string("could not delete db (" + db_path + "): " + strerror(errno))}; + throw (e); + } + } + + int pEpSQLite::callback(void *obj, int argc, char **argv, char **azColName) + { + RSRecord record; + for (int col = 0; col < argc; col++) { + const string key = string{azColName[col]}; + // TODO: NULL is not correct, could be a valid value + const string val = string{argv[col] ? argv[col] : "NULL"}; + record.insert({key, val}); + } + (static_cast(obj))->resultset.push_back(record); + return 0; + } + + ResultSet pEpSQLite::execute(const string& stmt) + { + pEpLogClass("called"); + this->resultset.clear(); + char *zErrMsg = nullptr; + int rc = ::sqlite3_exec(db, stmt.c_str(), (int (*)(void *, int, char **, char **)) &callback, this, &zErrMsg); + if (rc != SQLITE_OK) { + runtime_error e{string("execute: " + string(::sqlite3_errmsg(db)) + ":" + string(zErrMsg))}; + ::sqlite3_free(zErrMsg); + throw (e); + } + return resultset; + } + + string pEpSQLite::resultset_to_string(const ResultSet& rs) + { + pEpLogClass("called"); + stringstream ss; + int i = 0; + for (const RSRecord& rec : rs) { + for (const auto& item : rec) { + ss << "RESULTSET[" << i << "][" << item.first << "] = " << item.second << "\"" << endl; + } + i++; + } + return ss.str(); + } + + pEpSQLite::~pEpSQLite() + { + pEpLogClass("called"); + close_db(); + } +} diff --git a/src/pEpSQLite.hh b/src/pEpSQLite.hh new file mode 100644 index 0000000..865dae9 --- /dev/null +++ b/src/pEpSQLite.hh @@ -0,0 +1,49 @@ +// This file is under GNU General Public License 3.0 +// see LICENSE.txt +#ifndef LIBPEPADAPTER_PEPSQLITE_HH +#define LIBPEPADAPTER_PEPSQLITE_HH + +#include "sqlite3.h" +#include "pEpLog.hh" +#include +#include +#include + + +using ResultSet = std::vector>; +using RSRecord = std::map; + +namespace pEp { + class pEpSQLite { + public: + pEpSQLite() = delete; + + // The database file as a constant for the obj lifetime + pEpSQLite(std::string db_path); + std::string get_db_path(); + + // Creates the database file not existsing + // Will not create any dirs + void create_or_open_db(); + void close_db(); + + // Delete the database file + void delete_db(); + ResultSet execute(const std::string& stmt); + std::string resultset_to_string(const ResultSet& rs); + + // logging + static bool log_enabled; + Adapter::pEpLog::pEpLogger logger{"pEpSQLite", log_enabled}; + Adapter::pEpLog::pEpLogger& m4gic_logger_n4ame = logger; + ~pEpSQLite(); + private: + ::sqlite3 *db = nullptr; + std::string db_path; + ResultSet resultset; + + static int callback(void *obj, int argc, char **argv, char **azColName); + }; +} // namespace pEp + +#endif // LIBPEPADAPTER_PEPSQLITE_HH