aboutsummaryrefslogtreecommitdiff
path: root/src/sql/SqlQuery.cpp
diff options
context:
space:
mode:
authordec05eba <dec05eba@protonmail.com>2018-05-14 00:20:11 +0200
committerdec05eba <dec05eba@protonmail.com>2020-08-18 23:25:46 +0200
commit8b94c3bf3a06caa7b003fe61e8242bdb00004eb5 (patch)
treec307bf3a9c1bf38ea23608b0700755fc76e6980e /src/sql/SqlQuery.cpp
parent0c8761b3d76912f034a0cb819d72f0349a25bf4f (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 };
+ }
+}