3.2.2020
Pokud píšeme aplikaci v C++ (tedy nemusíme se "omezovat" na čisté neobjektové C), můžeme si některé častěji používané funkce SQLite zabalit do tříd/objektů jazyka C++. Napsal jsem jednoduché zabalení do 2 tříd: database a command. Třída database zabaluje základnífunkce nad ukazatelem sqlite3*. Třída command zabaluje funkce nad "prepared statement", tj. ukazatelem sqlite3_stmt*
Následující zdrojový kód naleznete také na mém GitHubu a můžete jej použít a upravit podle svých potřeb.
#pragma once #ifndef RCSQLITE3_H #define RCSQLITE3_H #include <sqlite3.h> #include <stdexcept> #include <string.h> #include <assert.h> namespace rc { namespace sqlite { inline void __attribute__((noreturn)) fatal_exit() noexcept { std::terminate(); } class database { protected: sqlite3* _pointer = nullptr; public: ~database() noexcept { release(); } void release() noexcept { if (_pointer) { if (sqlite3_close(_pointer) != SQLITE_OK) rc::sqlite::fatal_exit(); _pointer = nullptr; } } __attribute__((always_inline)) operator sqlite3*() const noexcept { return _pointer; } __attribute__((always_inline)) sqlite3* handle() const noexcept { return _pointer; } __attribute__((always_inline)) bool opened() noexcept { return (_pointer != nullptr); } void open(const char* file_path) { release(); int sqlres = sqlite3_open(file_path, &_pointer); if (sqlres != SQLITE_OK) { release(); throw std::runtime_error(sqlite3_errstr(sqlres)); } } void create(const char* file_path) { release(); int ires = sqlite3_open(file_path, &_pointer); if (ires != SQLITE_OK) { release(); throw std::runtime_error(sqlite3_errstr(ires)); } } void execute_command(const char* sz_sql) { assert(_pointer != nullptr); int sqlres = sqlite3_exec(_pointer, sz_sql, nullptr, nullptr, nullptr); if (sqlres != SQLITE_OK) throw std::runtime_error(sqlite3_errstr(sqlres)); } void begin_transaction() { execute_command("BEGIN TRANSACTION;"); } void end_transaction() { execute_command("END TRANSACTION;"); } void check_integrity() { execute_command("PRAGMA integrity_check;"); } }; // class database class command { private: sqlite3_stmt* _stmt = nullptr; database* _database = nullptr; public: command(const char* sz_sql, database* db) { create(sz_sql, db); } command(const std::string& str_sql, database* db) { create(str_sql.c_str(), db); } ~command() noexcept { release(); } void release() noexcept { if (_stmt != nullptr) { int vysl = sqlite3_reset(_stmt); if (vysl != SQLITE_OK) rc::sqlite::fatal_exit(); vysl = sqlite3_finalize(_stmt); if (vysl != SQLITE_OK) rc::sqlite::fatal_exit(); _stmt = nullptr; } } // Pokud není další záznam příkazu, vrátí false // Při jiné chybě SQLite vyvolá kritické ukončení bool next_line() noexcept { assert(_stmt != nullptr); int sqlres = sqlite3_step(_stmt); if (SQLITE_ERROR == sqlres) rc::sqlite::fatal_exit(); return (SQLITE_ROW == sqlres); } // Musí být ověřeno předchozí úspěšné provedení funkce next_line, // a nesmí být před tímto _smtp uvolněn std::string get_text(int column_index) noexcept { assert(_stmt != nullptr); const unsigned char* pt = sqlite3_column_text(_stmt, column_index); if (nullptr == pt) return std::string(""); else { size_t length = static_cast(sqlite3_column_bytes(_stmt, column_index)); return std::string((const char*)pt, length); } } sqlite3_int64 get_int64(int column_index) noexcept { assert(_stmt != nullptr); return sqlite3_column_int64(_stmt, column_index); } const void* get_blob(int column_index) noexcept { assert(_stmt != nullptr); return sqlite3_column_blob(_stmt, column_index); } size_t get_blob_size(int column_index) noexcept { assert(_stmt != nullptr); return static_cast (sqlite3_column_bytes(_stmt, column_index)); } void set_param_text(int param_number, const char* text) { assert(_stmt != nullptr); int sqlres = sqlite3_bind_text(_stmt, param_number, text, static_cast (strlen(text)), SQLITE_STATIC); if (sqlres != SQLITE_OK) { release(); throw std::logic_error(sqlite3_errstr(sqlres)); } } void set_param_int64(int param_number, sqlite3_int64 i64_value) { assert(_stmt != nullptr); int sqlres = sqlite3_bind_int64(_stmt, param_number, i64_value); if (sqlres != SQLITE_OK) { release(); throw std::logic_error(sqlite3_errstr(sqlres)); } } void set_param_blob(int param_number, const void* p_value, size_t bytes_count) { assert(_stmt != nullptr); int sqlres = sqlite3_bind_blob64(_stmt, param_number, p_value, static_cast (bytes_count), nullptr); if (sqlres != SQLITE_OK) { release(); throw std::logic_error(sqlite3_errstr(sqlres)); } } // on error throw exception void execute() { assert(_stmt != nullptr); int sqlres = sqlite3_step(_stmt); if ((sqlres != SQLITE_OK) && (sqlres != SQLITE_DONE)) throw std::runtime_error(sqlite3_errstr(sqlres)); } private: void create(const char* sz_sql, rc::sqlite::database* db) { assert(db!= nullptr); if (nullptr == db) rc::sqlite::fatal_exit(); _database = db; int sqlres = sqlite3_prepare_v2(*_database, sz_sql, static_cast (strlen(sz_sql)), &_stmt, nullptr); if (SQLITE_OK != sqlres) { release(); throw std::runtime_error(sqlite3_errstr(sqlres)); } } }; // class command } // namespace sqlite } // namespace rc #endif // RCSQLITE3_H
Školení
Kontakt
739 219 991
live:radekchalupa_1
Nové články