Sleds/libeye/eyedb.cpp

477 lines
12 KiB
C++
Raw Normal View History

2025-03-13 21:28:38 +00:00
//
// EyeDB.cpp
// ionuCommon
//
// Created by Frank Vernon on 1/16/14.
// Copyright (c) 2013-2014 IONU Security. All rights reserved.
//
#include "eyedb.h"
#include "eyelog.h"
#include "eyeutils.h"
#include <assert.h>
#include <sstream>
namespace sequencelogic {
//MARK: EyeDB
EyeDB::EyeDB()
:_db(NULL), _db_open(false), _busy_timeout_seconds(0.0)
{
}
EyeDB::~EyeDB()
{
close();
}
bool
EyeDB::open(const char * filepath)
{
close();
if (sequencelogic::IsValidFilename(filepath)) {
int result = sqlite3_open_v2 (filepath, &_db, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE | SQLITE_OPEN_FULLMUTEX, NULL);
if (result == SQLITE_OK) {
_db_open = true;
busyTimeout(_busy_timeout_seconds);
} else {
IONUDEBUG ("EyeDB::open open/create failed - %s (%d)", filepath, result);
}
}
return _db_open;
}
void
EyeDB::close()
{
if (_db != NULL) {
sqlite3_close_v2(_db);
_db = NULL;
}
_db_open = false;
}
void
EyeDB::busyTimeout(double timeoutSeconds)
{
_busy_timeout_seconds = timeoutSeconds;
if (_db != NULL) {
sqlite3_busy_timeout(_db, (int)(_busy_timeout_seconds*1000.0));
}
}
std::string
EyeDB::filePath()
{
std::string result = sqlite3_db_filename(_db, "main");
return result;
}
bool
EyeDB::executeQuery(const std::string & query)
{
char* errmsg = NULL;
int result = sqlite3_exec(_db, query.c_str(), NULL, NULL, &errmsg);
if (result != SQLITE_OK) {
IONUDEBUG ("EyeDB::executeQuery() failed - %s (%d)", errmsg, result);
return false;
}
return true;
}
MAP_VECTOR
EyeDB::fetchResults(const statement & statement)
{
MAP_VECTOR result;
while(statement.step() == SQLITE_ROW) {
//might want to move count/column/text/blob to statement object
int columns = sqlite3_data_count(statement);
STRING_STRING_MAP rowMap;
for (int i = 0; i < columns; ++i) {
const char * key = sqlite3_column_name(statement, i);
int type = sqlite3_column_type(statement, i);
switch (type) {
case SQLITE_INTEGER:
case SQLITE_FLOAT:
case SQLITE_TEXT: {
const unsigned char * value = sqlite3_column_text(statement, i);
std::size_t value_length = sqlite3_column_bytes(statement, i);
rowMap[std::string(key)] = std::string((const char *)value, value_length);
}
break;
case SQLITE_BLOB: {
const void * value = sqlite3_column_blob(statement, i);
std::size_t value_length = sqlite3_column_bytes(statement, i);
rowMap[std::string(key)] = std::string((const char*)value, value_length);
}
break;
case SQLITE_NULL: {
rowMap[std::string(key)] = std::string();
}
break;
default:
IONUDEBUG ("EyeDB::fetchResults() Unexpected type: %d", type);
break;
}
}
result.push_back(rowMap);
}
return result;
}
//MARK: transaction
transaction::transaction(EyeDB & db)
:_commit(false), _db(db)
{
sqlite3_exec(_db, "BEGIN", 0, 0, 0);
}
transaction::~transaction()
{
if (_commit) {
sqlite3_exec(_db, "COMMIT", 0, 0, 0);
} else {
sqlite3_exec(_db, "ROLLBACK", 0, 0, 0);
}
}
void
transaction::commit()
{
_commit = true;
}
//MARK: savepoint
savepoint::savepoint(EyeDB & db, const char * savepoint)
:_commit(true), _db(db), _savepoint(savepoint)
{
std::stringstream sql;
sql << "SAVEPOINT" << " " << _savepoint;
sqlite3_exec(_db, sql.str().c_str(), 0, 0, 0);
}
savepoint::~savepoint()
{
std::stringstream sql;
if (_commit) {
sql << "RELEASE SAVEPOINT" << " " << _savepoint;
} else {
sql << "ROLLBACK TO SAVEPOINT" << " " << _savepoint;
}
sqlite3_exec(_db, sql.str().c_str(), 0, 0, 0);
}
void
savepoint::commit()
{
_commit = true;
}
//MARK: statement
statement::statement()
:stmt(NULL), prepared(false)
{
}
statement::statement(EyeDB & db, const std::string & query)
:stmt(NULL), prepared(false)
{
prepare(db, query);
}
statement::~statement()
{
finalize();
}
bool
statement::prepare(EyeDB & db, const std::string & query)
{
int result = sqlite3_prepare_v2 (db, query.c_str(), (int)query.length(), &stmt, 0);
prepared = result == SQLITE_OK;
if (!prepared) {
IONUDEBUG ("statement::prepare() prepare failed: %s", query.c_str());
}
return prepared;
}
bool
statement::bind(int position, const std::string & text)
{
if (!prepared) return false;
int result = sqlite3_bind_text(stmt, position, text.c_str(), -1, SQLITE_STATIC);
if (result != SQLITE_OK) {
IONUDEBUG ("statement::bind(text) - failed %d", result);
return false;
}
return true;
}
bool
statement::bind(int position, const void * blob, int blobLength)
{
if (!prepared) return false;
int result = sqlite3_bind_blob(stmt, position, blob, blobLength, SQLITE_TRANSIENT);
if (result != SQLITE_OK) {
IONUDEBUG ("statement::bind(blob) - failed %d", result);
return false;
}
return true;
}
bool
statement::bind(int position, int integer)
{
if (!prepared) return false;
int result = sqlite3_bind_int(stmt, position, integer);
if (result != SQLITE_OK) {
IONUDEBUG ("statement::bind(int) - failed %d", result);
return false;
}
return true;
}
bool
statement::bind(int position, double dbl)
{
if (!prepared) return false;
int result = sqlite3_bind_double(stmt, position, dbl);
if (result != SQLITE_OK) {
IONUDEBUG ("statement::bind(dbl) - failed %d", result);
return false;
}
return true;
}
bool
statement::bind(int position, sqlite3_int64 integer64)
{
if (!prepared) return false;
int result = sqlite3_bind_int64(stmt, position, integer64);
if (result != SQLITE_OK) {
IONUDEBUG ("statement::bind(int64) - failed %d", result);
return false;
}
return true;
}
bool
statement::bind(int position, const sqlite3_value * value)
{
if (!prepared) return false;
int result = sqlite3_bind_value(stmt, position, value);
if (result != SQLITE_OK) {
IONUDEBUG ("statement::bind(value) - failed %d", result);
return false;
}
return true;
}
bool
statement::bind_null(int position)
{
if (!prepared) return false;
int result = sqlite3_bind_null(stmt, position);
if (result != SQLITE_OK) {
IONUDEBUG ("statement::bind(NULL) - failed %d", result);
return false;
}
return true;
}
bool
statement::bind_zeroblob(int position, int length)
{
if (!prepared) return false;
int result = sqlite3_bind_zeroblob(stmt, position, length);
if (result != SQLITE_OK) {
IONUDEBUG ("statement::bind(NULL) - failed %d", result);
return false;
}
return true;
}
bool
statement::clear_bindings() const
{
int result = sqlite3_clear_bindings(stmt);
if (result != SQLITE_OK) {
IONUDEBUG ("statement::clear_bindings() - failed %d", result);
return false;
}
return true;
}
int
statement::step() const
{
if (!prepared) return false;
return sqlite3_step(stmt);
}
bool
statement::reset() const
{
if (!prepared) return false;
int result = sqlite3_reset(stmt);
if (result != SQLITE_OK) {
IONUDEBUG ("statement::reset() - failed %d", result);
return false;
}
return true;
}
void
statement::finalize()
{
if (stmt != NULL) {
sqlite3_finalize(stmt);
stmt = NULL;
}
}
bool
statement::isPrepared()
{
return prepared;
}
int
statement::columnType(int column)
{
return sqlite3_column_type(stmt, column);
}
double
statement::columnBytesDouble(int column)
{
return sqlite3_column_double(stmt, column);
}
int
statement::columnBytesInt(int column)
{
return sqlite3_column_bytes(stmt, column);
}
int
statement::columnBytesInt16(int column)
{
return sqlite3_column_bytes16(stmt, column);
}
const void *
statement::columnBlob(int column)
{
return sqlite3_column_blob(stmt, column);
}
int
statement::columnInt(int column)
{
return sqlite3_column_int(stmt, column);
}
sqlite_int64
statement::columnInt64(int column)
{
return sqlite3_column_int64(stmt, column);
}
const unsigned char *
statement::columnText(int column)
{
return sqlite3_column_text(stmt, column);
}
sqlite3_value *
statement::columnValue(int column)
{
return sqlite3_column_value(stmt, column);
}
const void *
statement::columnText16(int column)
{
return sqlite3_column_text16(stmt, column);
}
//MARK: PragmaAccess
PragmaAccess::PragmaAccess(EyeDB & db)
:_db(db)
{
}
std::string
PragmaAccess::get(const std::string &pragma)
{
std::string result;
std::stringstream query;
query << "PRAGMA " << pragma;
statement statement(_db, query.str());
if (statement.isPrepared())
{
MAP_VECTOR results = _db.fetchResults(statement);
for (STRING_STRING_MAP & row : results) {
for (auto column: row) {
if (result.length() > 0) {
result += ", ";
}
result += column.first + "=" + column.second;
}
}
}
return result;
}
bool
PragmaAccess::set(const std::string &pragma, const std::string &value)
{
std::stringstream query;
query << "PRAGMA " << pragma << " = " << value;
return _db.executeQuery(query.str());
}
}