diff options
author | dec05eba <0xdec05eba@gmail.com> | 2018-05-14 00:20:11 +0200 |
---|---|---|
committer | dec05eba <0xdec05eba@gmail.com> | 2018-05-14 00:27:29 +0200 |
commit | 9af086151e6d9d3fe88f9e3e21797812a3e701ba (patch) | |
tree | a11889f81b8f929c11dccbd2c1c3b3cd74fbb740 /src/sql | |
parent | ebff7aeafded4dd9d245dbcfc80d9c8d83fe1242 (diff) |
Replace files with sqlite
Using sqlite because sqlite has transactions, storing/loading from files
automatically, unloading data that is not accessed often.
Removed cosmetic data (node name, username). They can be added using
addData by the application that uses odhtdb instead.
Database callback functions can now be called with stored data using
database.loadNode function.
TODO: Add local user storage (with password) back, it has been temorary
disabled
Diffstat (limited to 'src/sql')
-rw-r--r-- | src/sql/SqlQuery.cpp | 129 |
1 files changed, 129 insertions, 0 deletions
diff --git a/src/sql/SqlQuery.cpp b/src/sql/SqlQuery.cpp new file mode 100644 index 0000000..47f1463 --- /dev/null +++ b/src/sql/SqlQuery.cpp @@ -0,0 +1,129 @@ +#include "../../include/odhtdb/sql/SqlQuery.hpp" +#include <sqlite3.h> + +namespace odhtdb +{ + int SqlArg::bind(sqlite3_stmt *stmt, int paramIndex) const + { + switch(type) + { + case Type::DATA_VIEW: + return sqlite3_bind_blob(stmt, paramIndex, dataView.data, dataView.size, SQLITE_STATIC); + case Type::INT: + return sqlite3_bind_int(stmt, paramIndex, integer); + case Type::INT64: + return sqlite3_bind_int64(stmt, paramIndex, integer64); + } + return SQLITE_OK; + } + + SqlQuery::SqlQuery(sqlite3 *_db, const char *sql, std::initializer_list<SqlArg> args) : + db(_db), + stmt(nullptr), + numColumns(0) + { + int rc = sqlite3_prepare_v2(db, sql, -1, &stmt, nullptr); + if(rc != SQLITE_OK) + { + std::string errMsg = "Failed to prepare sqlite statement, error: "; + errMsg += sqlite3_errmsg(db); + sqlite3_exec(db, "ROLLBACK", 0, 0, 0); + throw SqlQueryException(errMsg); + } + + int numParams = sqlite3_bind_parameter_count(stmt); + if(args.size() != numParams) + { + std::string errMsg = "Failed to prepare sqlite statement, error: Sql has "; + errMsg += std::to_string(numParams); + errMsg += " parameters, got "; + errMsg += std::to_string(args.size()); + errMsg += " arguments"; + sqlite3_finalize(stmt); + stmt = nullptr; + sqlite3_exec(db, "ROLLBACK", 0, 0, 0); + throw SqlQueryException(errMsg); + } + + int paramIndex = 1; + for(const SqlArg &arg : args) + { + rc = arg.bind(stmt, paramIndex); + if(rc != SQLITE_OK) + { + std::string errMsg = "Failed to bind param, error code: "; + errMsg += std::to_string(rc); + sqlite3_finalize(stmt); + stmt = nullptr; + sqlite3_exec(db, "ROLLBACK", 0, 0, 0); + throw SqlQueryException(errMsg); + } + ++paramIndex; + } + } + + SqlQuery::~SqlQuery() + { + sqlite3_finalize(stmt); + } + + bool SqlQuery::next() + { + int rc = sqlite3_step(stmt); + if(rc == SQLITE_DONE) + return false; + else if(rc != SQLITE_ROW) + { + std::string errMsg = "Failed to perform sql select, error: "; + errMsg += sqlite3_errmsg(db); + sqlite3_exec(db, "ROLLBACK", 0, 0, 0); + throw SqlQueryException(errMsg); + } + + numColumns = sqlite3_data_count(stmt); + return true; + } + + void SqlQuery::checkColumnIndex(int index) + { + if(index < 0 || index >= numColumns) + { + std::string errMsg; + if(numColumns == 0) + { + errMsg += "Attempt to get column "; + errMsg += std::to_string(index); + errMsg += " but result does not have any columns"; + } + else + { + errMsg += "Column index "; + errMsg += std::to_string(index); + errMsg += " has to be between 0 and "; + errMsg += std::to_string(numColumns - 1); + } + sqlite3_exec(db, "ROLLBACK", 0, 0, 0); + throw SqlQueryException(errMsg); + } + } + + int SqlQuery::getInt(int index) + { + checkColumnIndex(index); + return sqlite3_column_int(stmt, index); + } + + i64 SqlQuery::getInt64(int index) + { + checkColumnIndex(index); + return sqlite3_column_int64(stmt, index); + } + + const DataView SqlQuery::getBlob(int index) + { + checkColumnIndex(index); + const void *data = sqlite3_column_blob(stmt, index); + int size = sqlite3_column_bytes(stmt, index); + return { (void*)data, (usize)size }; + } +} |