diff options
Diffstat (limited to 'src/lib/utils/sqlite3')
-rw-r--r-- | src/lib/utils/sqlite3/info.txt | 14 | ||||
-rw-r--r-- | src/lib/utils/sqlite3/sqlite3.cpp | 137 | ||||
-rw-r--r-- | src/lib/utils/sqlite3/sqlite3.h | 68 |
3 files changed, 219 insertions, 0 deletions
diff --git a/src/lib/utils/sqlite3/info.txt b/src/lib/utils/sqlite3/info.txt new file mode 100644 index 000000000..97d59d697 --- /dev/null +++ b/src/lib/utils/sqlite3/info.txt @@ -0,0 +1,14 @@ + +load_on request + +<libs> +all -> sqlite3 +</libs> + +<header:internal> +sqlite3.h +</header:internal> + +<source> +sqlite3.cpp +</source> diff --git a/src/lib/utils/sqlite3/sqlite3.cpp b/src/lib/utils/sqlite3/sqlite3.cpp new file mode 100644 index 000000000..7f6626759 --- /dev/null +++ b/src/lib/utils/sqlite3/sqlite3.cpp @@ -0,0 +1,137 @@ +/* +* SQLite wrapper +* (C) 2012 Jack Lloyd +* +* Released under the terms of the Botan license +*/ + +#include <botan/internal/sqlite3.h> +#include <stdexcept> +#include <sqlite3.h> + +namespace Botan { + +sqlite3_database::sqlite3_database(const std::string& db_filename) + { + int rc = ::sqlite3_open(db_filename.c_str(), &m_db); + + if(rc) + { + const std::string err_msg = ::sqlite3_errmsg(m_db); + ::sqlite3_close(m_db); + m_db = nullptr; + throw std::runtime_error("sqlite3_open failed - " + err_msg); + } + } + +sqlite3_database::~sqlite3_database() + { + if(m_db) + ::sqlite3_close(m_db); + m_db = nullptr; + } + +size_t sqlite3_database::row_count(const std::string& table_name) + { + sqlite3_statement stmt(this, "select count(*) from " + table_name); + + if(stmt.step()) + return stmt.get_size_t(0); + else + throw std::runtime_error("Querying size of table " + table_name + " failed"); + } + +void sqlite3_database::create_table(const std::string& table_schema) + { + char* errmsg = nullptr; + int rc = ::sqlite3_exec(m_db, table_schema.c_str(), nullptr, nullptr, &errmsg); + + if(rc != SQLITE_OK) + { + const std::string err_msg = errmsg; + ::sqlite3_free(errmsg); + ::sqlite3_close(m_db); + m_db = nullptr; + throw std::runtime_error("sqlite3_exec for table failed - " + err_msg); + } + } + + +sqlite3_statement::sqlite3_statement(sqlite3_database* db, const std::string& base_sql) + { + int rc = ::sqlite3_prepare_v2(db->m_db, base_sql.c_str(), -1, &m_stmt, nullptr); + + if(rc != SQLITE_OK) + throw std::runtime_error("sqlite3_prepare failed " + base_sql + + ", code " + std::to_string(rc)); + } + +void sqlite3_statement::bind(int column, const std::string& val) + { + int rc = ::sqlite3_bind_text(m_stmt, column, val.c_str(), -1, SQLITE_TRANSIENT); + if(rc != SQLITE_OK) + throw std::runtime_error("sqlite3_bind_text failed, code " + std::to_string(rc)); + } + +void sqlite3_statement::bind(int column, int val) + { + int rc = ::sqlite3_bind_int(m_stmt, column, val); + if(rc != SQLITE_OK) + throw std::runtime_error("sqlite3_bind_int failed, code " + std::to_string(rc)); + } + +void sqlite3_statement::bind(int column, std::chrono::system_clock::time_point time) + { + const int timeval = std::chrono::duration_cast<std::chrono::seconds>(time.time_since_epoch()).count(); + bind(column, timeval); + } + +void sqlite3_statement::bind(int column, const std::vector<byte>& val) + { + int rc = ::sqlite3_bind_blob(m_stmt, column, &val[0], val.size(), SQLITE_TRANSIENT); + if(rc != SQLITE_OK) + throw std::runtime_error("sqlite3_bind_text failed, code " + std::to_string(rc)); + } + +std::pair<const byte*, size_t> sqlite3_statement::get_blob(int column) + { + BOTAN_ASSERT(::sqlite3_column_type(m_stmt, 0) == SQLITE_BLOB, + "Return value is a blob"); + + const void* session_blob = ::sqlite3_column_blob(m_stmt, column); + const int session_blob_size = ::sqlite3_column_bytes(m_stmt, column); + + BOTAN_ASSERT(session_blob_size >= 0, "Blob size is non-negative"); + + return std::make_pair(static_cast<const byte*>(session_blob), + static_cast<size_t>(session_blob_size)); + } + +size_t sqlite3_statement::get_size_t(int column) + { + BOTAN_ASSERT(::sqlite3_column_type(m_stmt, column) == SQLITE_INTEGER, + "Return count is an integer"); + + const int sessions_int = ::sqlite3_column_int(m_stmt, column); + + BOTAN_ASSERT(sessions_int >= 0, "Expected size_t is non-negative"); + + return static_cast<size_t>(sessions_int); + } + +void sqlite3_statement::spin() + { + while(step()) {} + } + +bool sqlite3_statement::step() + { + return (::sqlite3_step(m_stmt) == SQLITE_ROW); + } + +sqlite3_statement::~sqlite3_statement() + { + ::sqlite3_finalize(m_stmt); + } + +} diff --git a/src/lib/utils/sqlite3/sqlite3.h b/src/lib/utils/sqlite3/sqlite3.h new file mode 100644 index 000000000..aef04ab4d --- /dev/null +++ b/src/lib/utils/sqlite3/sqlite3.h @@ -0,0 +1,68 @@ +/* +* SQLite wrapper +* (C) 2012 Jack Lloyd +* +* Released under the terms of the Botan license +*/ + +#ifndef BOTAN_UTILS_SQLITE_WRAPPER_H__ +#define BOTAN_UTILS_SQLITE_WRAPPER_H__ + +#include <botan/types.h> +#include <string> +#include <chrono> +#include <vector> + +class sqlite3; +class sqlite3_stmt; + +namespace Botan { + +class sqlite3_database + { + public: + sqlite3_database(const std::string& file); + + ~sqlite3_database(); + + size_t row_count(const std::string& table_name); + + void create_table(const std::string& table_schema); + private: + friend class sqlite3_statement; + + sqlite3* m_db; + }; + +class sqlite3_statement + { + public: + sqlite3_statement(sqlite3_database* db, + const std::string& base_sql); + + void bind(int column, const std::string& val); + + void bind(int column, int val); + + void bind(int column, std::chrono::system_clock::time_point time); + + void bind(int column, const std::vector<byte>& val); + + std::pair<const byte*, size_t> get_blob(int column); + + size_t get_size_t(int column); + + void spin(); + + bool step(); + + sqlite3_stmt* stmt() { return m_stmt; } + + ~sqlite3_statement(); + private: + sqlite3_stmt* m_stmt; + }; + +} + +#endif |