diff options
Diffstat (limited to '3rdparty/sqlitecpp/source/SQLiteCpp/Database.cpp')
-rw-r--r-- | 3rdparty/sqlitecpp/source/SQLiteCpp/Database.cpp | 452 |
1 files changed, 0 insertions, 452 deletions
diff --git a/3rdparty/sqlitecpp/source/SQLiteCpp/Database.cpp b/3rdparty/sqlitecpp/source/SQLiteCpp/Database.cpp deleted file mode 100644 index eb76c88..0000000 --- a/3rdparty/sqlitecpp/source/SQLiteCpp/Database.cpp +++ /dev/null @@ -1,452 +0,0 @@ -/** - * @file Database.cpp - * @ingroup SQLiteCpp - * @brief Management of a SQLite Database Connection. - * - * Copyright (c) 2012-2021 Sebastien Rombauts ([email protected]) - * - * Distributed under the MIT License (MIT) (See accompanying file LICENSE.txt - * or copy at http://opensource.org/licenses/MIT) - */ -#include <SQLiteCpp/Database.h> - -#include <SQLiteCpp/Assertion.h> -#include <SQLiteCpp/Backup.h> -#include <SQLiteCpp/Exception.h> -#include <SQLiteCpp/Statement.h> - -#include <sqlite3.h> -#include <fstream> -#include <string.h> - -#ifndef SQLITE_DETERMINISTIC -#define SQLITE_DETERMINISTIC 0x800 -#endif // SQLITE_DETERMINISTIC - - -namespace SQLite -{ - -const int OPEN_READONLY = SQLITE_OPEN_READONLY; -const int OPEN_READWRITE = SQLITE_OPEN_READWRITE; -const int OPEN_CREATE = SQLITE_OPEN_CREATE; -const int OPEN_URI = SQLITE_OPEN_URI; -const int OPEN_MEMORY = SQLITE_OPEN_MEMORY; -const int OPEN_NOMUTEX = SQLITE_OPEN_NOMUTEX; -const int OPEN_FULLMUTEX = SQLITE_OPEN_FULLMUTEX; -const int OPEN_SHAREDCACHE = SQLITE_OPEN_SHAREDCACHE; -const int OPEN_PRIVATECACHE = SQLITE_OPEN_PRIVATECACHE; -#if SQLITE_VERSION_NUMBER >= 3031000 -const int OPEN_NOFOLLOW = SQLITE_OPEN_NOFOLLOW; -#else -const int OPEN_NOFOLLOW = 0; -#endif - -const int OK = SQLITE_OK; - -const char* VERSION = SQLITE_VERSION; -const int VERSION_NUMBER = SQLITE_VERSION_NUMBER; - -// Return SQLite version string using runtime call to the compiled library -const char* getLibVersion() noexcept -{ - return sqlite3_libversion(); -} - -// Return SQLite version number using runtime call to the compiled library -int getLibVersionNumber() noexcept -{ - return sqlite3_libversion_number(); -} - - -// Open the provided database UTF-8 filename with SQLite::OPEN_xxx provided flags. -Database::Database(const char* apFilename, - const int aFlags /* = SQLite::OPEN_READONLY*/, - const int aBusyTimeoutMs /* = 0 */, - const char* apVfs /* = nullptr*/) : - mFilename(apFilename) -{ - sqlite3* handle; - const int ret = sqlite3_open_v2(apFilename, &handle, aFlags, apVfs); - mSQLitePtr.reset(handle); - if (SQLITE_OK != ret) - { - throw SQLite::Exception(handle, ret); - } - if (aBusyTimeoutMs > 0) - { - setBusyTimeout(aBusyTimeoutMs); - } -} - -// Deleter functor to use with smart pointers to close the SQLite database connection in an RAII fashion. -void Database::Deleter::operator()(sqlite3* apSQLite) -{ - const int ret = sqlite3_close(apSQLite); // Calling sqlite3_close() with a nullptr argument is a harmless no-op. - - // Avoid unreferenced variable warning when build in release mode - (void) ret; - - // Only case of error is SQLITE_BUSY: "database is locked" (some statements are not finalized) - // Never throw an exception in a destructor : - SQLITECPP_ASSERT(SQLITE_OK == ret, "database is locked"); // See SQLITECPP_ENABLE_ASSERT_HANDLER -} - -/** - * @brief Set a busy handler that sleeps for a specified amount of time when a table is locked. - * - * This is useful in multithreaded program to handle case where a table is locked for writting by a thread. - * Any other thread cannot access the table and will receive a SQLITE_BUSY error: - * setting a timeout will wait and retry up to the time specified before returning this SQLITE_BUSY error. - * Reading the value of timeout for current connection can be done with SQL query "PRAGMA busy_timeout;". - * Default busy timeout is 0ms. - * - * @param[in] aBusyTimeoutMs Amount of milliseconds to wait before returning SQLITE_BUSY - * - * @throw SQLite::Exception in case of error - */ -void Database::setBusyTimeout(const int aBusyTimeoutMs) -{ - const int ret = sqlite3_busy_timeout(getHandle(), aBusyTimeoutMs); - check(ret); -} - -// Shortcut to execute one or multiple SQL statements without results (UPDATE, INSERT, ALTER, COMMIT, CREATE...). -// Return the number of changes. -int Database::exec(const char* apQueries) -{ - const int ret = tryExec(apQueries); - check(ret); - - // Return the number of rows modified by those SQL statements (INSERT, UPDATE or DELETE only) - return sqlite3_changes(getHandle()); -} - -int Database::tryExec(const char* apQueries) noexcept -{ - return sqlite3_exec(getHandle(), apQueries, nullptr, nullptr, nullptr); -} - -// Shortcut to execute a one step query and fetch the first column of the result. -// WARNING: Be very careful with this dangerous method: you have to -// make a COPY OF THE result, else it will be destroy before the next line -// (when the underlying temporary Statement and Column objects are destroyed) -// this is an issue only for pointer type result (ie. char* and blob) -// (use the Column copy-constructor) -Column Database::execAndGet(const char* apQuery) -{ - Statement query(*this, apQuery); - (void)query.executeStep(); // Can return false if no result, which will throw next line in getColumn() - return query.getColumn(0); -} - -// Shortcut to test if a table exists. -bool Database::tableExists(const char* apTableName) -{ - Statement query(*this, "SELECT count(*) FROM sqlite_master WHERE type='table' AND name=?"); - query.bind(1, apTableName); - (void)query.executeStep(); // Cannot return false, as the above query always return a result - return (1 == query.getColumn(0).getInt()); -} - -// Get the rowid of the most recent successful INSERT into the database from the current connection. -long long Database::getLastInsertRowid() const noexcept -{ - return sqlite3_last_insert_rowid(getHandle()); -} - -// Get number of rows modified by last INSERT, UPDATE or DELETE statement (not DROP table). -int Database::getChanges() const noexcept -{ - return sqlite3_changes(getHandle()); -} - -// Get total number of rows modified by all INSERT, UPDATE or DELETE statement since connection. -int Database::getTotalChanges() const noexcept -{ - return sqlite3_total_changes(getHandle()); -} - -// Return the numeric result code for the most recent failed API call (if any). -int Database::getErrorCode() const noexcept -{ - return sqlite3_errcode(getHandle()); -} - -// Return the extended numeric result code for the most recent failed API call (if any). -int Database::getExtendedErrorCode() const noexcept -{ - return sqlite3_extended_errcode(getHandle()); -} - -// Return UTF-8 encoded English language explanation of the most recent failed API call (if any). -const char* Database::getErrorMsg() const noexcept -{ - return sqlite3_errmsg(getHandle()); -} - -// Attach a custom function to your sqlite database. Assumes UTF8 text representation. -// Parameter details can be found here: http://www.sqlite.org/c3ref/create_function.html -void Database::createFunction(const char* apFuncName, - int aNbArg, - bool abDeterministic, - void* apApp, - void (*apFunc)(sqlite3_context *, int, sqlite3_value **), - void (*apStep)(sqlite3_context *, int, sqlite3_value **) /* = nullptr */, - void (*apFinal)(sqlite3_context *) /* = nullptr */, // NOLINT(readability/casting) - void (*apDestroy)(void *) /* = nullptr */) -{ - int textRep = SQLITE_UTF8; - // optimization if deterministic function (e.g. of nondeterministic function random()) - if (abDeterministic) - { - textRep = textRep | SQLITE_DETERMINISTIC; - } - const int ret = sqlite3_create_function_v2(getHandle(), apFuncName, aNbArg, textRep, - apApp, apFunc, apStep, apFinal, apDestroy); - check(ret); -} - -// Load an extension into the sqlite database. Only affects the current connection. -// Parameter details can be found here: http://www.sqlite.org/c3ref/load_extension.html -void Database::loadExtension(const char* apExtensionName, const char *apEntryPointName) -{ -#ifdef SQLITE_OMIT_LOAD_EXTENSION - // Unused - (void)apExtensionName; - (void)apEntryPointName; - - throw SQLite::Exception("sqlite extensions are disabled"); -#else -#ifdef SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION // Since SQLite 3.13 (2016-05-18): - // Security warning: - // It is recommended that the SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION method be used to enable only this interface. - // The use of the sqlite3_enable_load_extension() interface should be avoided to keep the SQL load_extension() - // disabled and prevent SQL injections from giving attackers access to extension loading capabilities. - // (NOTE: not using nullptr: cannot pass object of non-POD type 'std::__1::nullptr_t' through variadic function) - int ret = sqlite3_db_config(getHandle(), SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION, 1, NULL); // NOTE: not using nullptr -#else - int ret = sqlite3_enable_load_extension(getHandle(), 1); -#endif - check(ret); - - ret = sqlite3_load_extension(getHandle(), apExtensionName, apEntryPointName, 0); - check(ret); -#endif -} - -// Set the key for the current sqlite database instance. -void Database::key(const std::string& aKey) const -{ - int passLen = static_cast<int>(aKey.length()); -#ifdef SQLITE_HAS_CODEC - if (passLen > 0) - { - const int ret = sqlite3_key(getHandle(), aKey.c_str(), passLen); - check(ret); - } -#else // SQLITE_HAS_CODEC - if (passLen > 0) - { - throw SQLite::Exception("No encryption support, recompile with SQLITE_HAS_CODEC to enable."); - } -#endif // SQLITE_HAS_CODEC -} - -// Reset the key for the current sqlite database instance. -void Database::rekey(const std::string& aNewKey) const -{ -#ifdef SQLITE_HAS_CODEC - int passLen = aNewKey.length(); - if (passLen > 0) - { - const int ret = sqlite3_rekey(getHandle(), aNewKey.c_str(), passLen); - check(ret); - } - else - { - const int ret = sqlite3_rekey(getHandle(), nullptr, 0); - check(ret); - } -#else // SQLITE_HAS_CODEC - static_cast<void>(aNewKey); // silence unused parameter warning - throw SQLite::Exception("No encryption support, recompile with SQLITE_HAS_CODEC to enable."); -#endif // SQLITE_HAS_CODEC -} - -// Test if a file contains an unencrypted database. -bool Database::isUnencrypted(const std::string& aFilename) -{ - if (aFilename.empty()) - { - throw SQLite::Exception("Could not open database, the aFilename parameter was empty."); - } - - std::ifstream fileBuffer(aFilename.c_str(), std::ios::in | std::ios::binary); - char header[16]; - if (fileBuffer.is_open()) - { - fileBuffer.seekg(0, std::ios::beg); - fileBuffer.getline(header, 16); - fileBuffer.close(); - } - else - { - throw SQLite::Exception("Error opening file: " + aFilename); - } - - return strncmp(header, "SQLite format 3\000", 16) == 0; -} - -// Parse header data from a database. -Header Database::getHeaderInfo(const std::string& aFilename) -{ - Header h; - unsigned char buf[100]; - char* pBuf = reinterpret_cast<char*>(&buf[0]); - char* pHeaderStr = reinterpret_cast<char*>(&h.headerStr[0]); - - if (aFilename.empty()) - { - throw SQLite::Exception("Filename parameter is empty"); - } - - { - std::ifstream fileBuffer(aFilename.c_str(), std::ios::in | std::ios::binary); - if (fileBuffer.is_open()) - { - fileBuffer.seekg(0, std::ios::beg); - fileBuffer.read(pBuf, 100); - fileBuffer.close(); - if (fileBuffer.gcount() < 100) - { - throw SQLite::Exception("File " + aFilename + " is too short"); - } - } - else - { - throw SQLite::Exception("Error opening file " + aFilename); - } - } - - // If the "magic string" can't be found then header is invalid, corrupt or unreadable - memcpy(pHeaderStr, pBuf, 16); - pHeaderStr[15] = '\0'; - if (strncmp(pHeaderStr, "SQLite format 3", 15) != 0) - { - throw SQLite::Exception("Invalid or encrypted SQLite header in file " + aFilename); - } - - h.pageSizeBytes = (buf[16] << 8) | buf[17]; - h.fileFormatWriteVersion = buf[18]; - h.fileFormatReadVersion = buf[19]; - h.reservedSpaceBytes = buf[20]; - h.maxEmbeddedPayloadFrac = buf[21]; - h.minEmbeddedPayloadFrac = buf[22]; - h.leafPayloadFrac = buf[23]; - - h.fileChangeCounter = - (buf[24] << 24) | - (buf[25] << 16) | - (buf[26] << 8) | - (buf[27] << 0); - - h.databaseSizePages = - (buf[28] << 24) | - (buf[29] << 16) | - (buf[30] << 8) | - (buf[31] << 0); - - h.firstFreelistTrunkPage = - (buf[32] << 24) | - (buf[33] << 16) | - (buf[34] << 8) | - (buf[35] << 0); - - h.totalFreelistPages = - (buf[36] << 24) | - (buf[37] << 16) | - (buf[38] << 8) | - (buf[39] << 0); - - h.schemaCookie = - (buf[40] << 24) | - (buf[41] << 16) | - (buf[42] << 8) | - (buf[43] << 0); - - h.schemaFormatNumber = - (buf[44] << 24) | - (buf[45] << 16) | - (buf[46] << 8) | - (buf[47] << 0); - - h.defaultPageCacheSizeBytes = - (buf[48] << 24) | - (buf[49] << 16) | - (buf[50] << 8) | - (buf[51] << 0); - - h.largestBTreePageNumber = - (buf[52] << 24) | - (buf[53] << 16) | - (buf[54] << 8) | - (buf[55] << 0); - - h.databaseTextEncoding = - (buf[56] << 24) | - (buf[57] << 16) | - (buf[58] << 8) | - (buf[59] << 0); - - h.userVersion = - (buf[60] << 24) | - (buf[61] << 16) | - (buf[62] << 8) | - (buf[63] << 0); - - h.incrementalVaccumMode = - (buf[64] << 24) | - (buf[65] << 16) | - (buf[66] << 8) | - (buf[67] << 0); - - h.applicationId = - (buf[68] << 24) | - (buf[69] << 16) | - (buf[70] << 8) | - (buf[71] << 0); - - h.versionValidFor = - (buf[92] << 24) | - (buf[93] << 16) | - (buf[94] << 8) | - (buf[95] << 0); - - h.sqliteVersion = - (buf[96] << 24) | - (buf[97] << 16) | - (buf[98] << 8) | - (buf[99] << 0); - - return h; -} - -void Database::backup(const char* apFilename, BackupType aType) -{ - // Open the database file identified by apFilename - Database otherDatabase(apFilename, SQLite::OPEN_READWRITE | SQLite::OPEN_CREATE); - - // For a 'Save' operation, data is copied from the current Database to the other. A 'Load' is the reverse. - Database& src = (aType == Save ? *this : otherDatabase); - Database& dest = (aType == Save ? otherDatabase : *this); - - // Set up the backup procedure to copy between the "main" databases of each connection - Backup bkp(dest, src); - bkp.executeStep(); // Execute all steps at once - - // RAII Finish Backup an Close the other Database -} - -} // namespace SQLite |