C++11 library providing functionality common to all adapters.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

167 lines
4.7 KiB

#include "pEpSQLite.hh"
#include "pEpLog.hh"
#include <iostream>
#include <cstdio>
#include <stdexcept>
#include <string>
#include <cstring>
using namespace std;
namespace pEp {
bool pEpSQLite::log_enabled = false;
pEpSQLite::pEpSQLite(const 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{ "pEpSQLite: create_or_open_db(\"" + db_path +
"\") - failed with sqlite3 error: " + std::to_string(rc) + " - " +
::sqlite3_errmsg(db) };
close_db();
throw(e);
}
}
string pEpSQLite::get_db_path() const
{
pEpLogClass("called");
return db_path;
}
void pEpSQLite::close_db()
{
pEpLogClass("called");
if (db != nullptr) {
::sqlite3_close(db);
db = nullptr;
}
}
bool pEpSQLite::is_open() const
{
if (db == nullptr) {
return false;
} else {
return true;
}
}
void pEpSQLite::delete_db()
{
pEpLogClass("called");
close_db();
int status = remove(db_path.c_str());
if (status) {
runtime_error e{ "pEpSQLite: delete_db(\"" + db_path + "\"): failed with error: " +
std::to_string(status) + " - " + 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<pEpSQLite *>(obj))->resultset.push_back(record);
return 0;
}
ResultSet pEpSQLite::execute(const string &stmt)
{
if (!is_open()) {
DBNotOpenException e{ "pEpSQLite: execute() failed - db is not open:" };
throw(e);
} else {
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) {
if (rc == SQLITE_CONSTRAINT) {
ConstraintException e{ "pEpSQLite: execute() failed with sqlite error: " +
std::to_string(rc) + " - " + string(zErrMsg) };
::sqlite3_free(zErrMsg);
throw(e);
}
runtime_error e{ "pEpSQLite: execute() failed with sqlite error: " +
std::to_string(rc) + " - " + string(zErrMsg) };
::sqlite3_free(zErrMsg);
throw(e);
}
}
return resultset;
}
// Utils
string pEpSQLite::to_string(const RSRecord &rec)
{
stringstream ss;
for (const auto &col : rec) {
ss << "[\"" << col.first << "\"] = \"" << col.second << "\"" << endl;
}
return ss.str();
}
string pEpSQLite::to_string(const ResultSet &rs)
{
stringstream ss;
ss << "ROWCOUNT: " << rs.size() << endl;
int i = 0;
for (const RSRecord &rec : rs) {
ss << "ROW[" << i << "]" << endl << to_string(rec);
i++;
}
return ss.str();
}
//Helper
int pEpSQLite::eval_sql_count(const ResultSet& rs, const string& countfieldname)
{
int rescount = 0;
// Get row
RSRecord rec{};
if (rs.size() != 1) {
runtime_error e{ "ListManagerDummy: eval_sql_count() - row count != 1" };
throw_with_nested(e);
}
try {
rec = rs.at(0);
} catch (...) {
runtime_error e{ "ListManagerDummy: eval_sql_count() - cant get row nr 0" };
throw_with_nested(e);
}
// Get field
try {
rescount = stoi(rec.at(countfieldname));
} catch (...) {
runtime_error e{ "ListManagerDummy: eval_sql_count() - field not existing" };
throw_with_nested(e);
}
return rescount;
}
pEpSQLite::~pEpSQLite()
{
pEpLogClass("called");
close_db();
}
} // namespace pEp