aboutsummaryrefslogtreecommitdiff
path: root/src/sql/SqlQuery.cpp
diff options
context:
space:
mode:
authordec05eba <0xdec05eba@gmail.com>2018-05-14 00:20:11 +0200
committerdec05eba <0xdec05eba@gmail.com>2018-05-14 00:27:29 +0200
commit9af086151e6d9d3fe88f9e3e21797812a3e701ba (patch)
treea11889f81b8f929c11dccbd2c1c3b3cd74fbb740 /src/sql/SqlQuery.cpp
parentebff7aeafded4dd9d245dbcfc80d9c8d83fe1242 (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/SqlQuery.cpp')
-rw-r--r--src/sql/SqlQuery.cpp129
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 };
+ }
+}