map/das-dn/inc/sqlite/KompexSQLiteDatabase.h
2024-07-08 10:27:17 +08:00

343 lines
19 KiB
C++

/*
This file is part of Kompex SQLite Wrapper.
Copyright (c) 2008-2021 Sven Broeske
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#ifndef KompexSQLiteDatabase_H
#define KompexSQLiteDatabase_H
#include <string>
#include "sqlite3.h"
#include "KompexSQLitePrerequisites.h"
namespace Kompex
{
//! Administration of the database and all concerning settings.
class _SQLiteWrapperExport SQLiteDatabase
{
public:
//! Default constructor.\n
//! Closes automatically the connection to a SQLite database file.
SQLiteDatabase();
/**
Overloaded constructor.\n
Opens a connection to a SQLite database file.
@param filename Database filename (UTF-8)
@param flags Flags \n
SQLITE_OPEN_READONLY\n
The database is opened in read-only mode. \n
If the database does not already exist, an error is returned.\n
SQLITE_OPEN_READWRITE\n
The database is opened for reading and writing if possible, \n
or reading only if the file is write protected by the operating system. \n
In either case the database must already exist, otherwise an error is returned.\n
SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE\n
The database is opened for reading and writing, \n
and is creates it if it does not already exist.
@param zVfs Name of VFS module to use\n
NULL for default
*/
SQLiteDatabase(const char *filename, int flags, const char *zVfs);
/**
Overloaded constructor.\n
Opens a connection to a SQLite database file.
@param filename Database filename (UTF-8)
@param flags Flags \n
SQLITE_OPEN_READONLY\n
The database is opened in read-only mode. \n
If the database does not already exist, an error is returned.\n
SQLITE_OPEN_READWRITE\n
The database is opened for reading and writing if possible, \n
or reading only if the file is write protected by the operating system. \n
In either case the database must already exist, otherwise an error is returned.\n
SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE\n
The database is opened for reading and writing, \n
and is creates it if it does not already exist.
@param zVfs Name of VFS module to use\n
NULL for default
*/
SQLiteDatabase(const std::string &filename, int flags, const char *zVfs);
//! Overloaded constructor.\n
//! Opens a connection to a SQLite database file.
//! @param filename Database filename (UTF-16)
SQLiteDatabase(const wchar_t *filename);
//! Destructor
virtual ~SQLiteDatabase();
/**
Opens a connection to a SQLite database file.\n
Shut down existing database handle, if one exist.
@param filename Database filename (UTF-8)
@param flags Flags \n
SQLITE_OPEN_READONLY\n
The database is opened in read-only mode. \n
If the database does not already exist, an error is returned.\n
SQLITE_OPEN_READWRITE\n
The database is opened for reading and writing if possible, \n
or reading only if the file is write protected by the operating system. \n
In either case the database must already exist, otherwise an error is returned.\n
SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE\n
The database is opened for reading and writing, \n
and is creates it if it does not already exist.
@param zVfs Name of VFS module to use\n
NULL for default
*/
void Open(const char *filename, int flags, const char *zVfs);
/**
Opens a connection to a SQLite database file.
Shut down existing database handle, if one exist.
@param filename Database filename (UTF-8)
@param flags Flags\n
SQLITE_OPEN_READONLY\n
The database is opened in read-only mode. \n
If the database does not already exist, an error is returned.\n
SQLITE_OPEN_READWRITE\n
The database is opened for reading and writing if possible, \n
or reading only if the file is write protected by the operating system. \n
In either case the database must already exist, otherwise an error is returned.\n
SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE\n
The database is opened for reading and writing, \n
and is creates it if it does not already exist.
@param zVfs Name of VFS module to use\n
NULL for default
*/
void Open(const std::string &filename, int flags, const char *zVfs);
//! Opens a connection to a SQLite database file.\n
//! Shut down existing database handle, if one exist.
//! @param filename Database filename (UTF-16)
void Open(const wchar_t *filename);
//! Closes a connection to a SQLite database file.
void Close();
//! Returns the SQLite db handle.
sqlite3 *GetDatabaseHandle() const {return mDatabaseHandle;}
//! Returns the version number of sqlite.
inline int GetLibVersionNumber() const {return sqlite3_libversion_number();}
//! Returns the number of database rows that were changed, inserted or deleted\n
//! by the most recently completed SQL statement.
int GetDatabaseChanges() const {return sqlite3_changes(mDatabaseHandle);}
//! Returns the total number of row changes caused by INSERT, UPDATE or DELETE statements\n
//! since the database connection was opened. The count includes all changes from all trigger contexts.\n
//! However, the count does not include changes used to implement REPLACE constraints,\n
//! do rollbacks or ABORT processing, or DROP table processing.\n
//! The changes are counted as soon as the statement that makes them is completed.
int GetTotalDatabaseChanges() const {return sqlite3_total_changes(mDatabaseHandle);}
//! Causes any pending database operation to abort and return at its earliest opportunity.\n
//! This routine is typically called in response to a user action such as pressing "Cancel"\n
//! or Ctrl-C where the user wants a long query operation to halt immediately.
void InterruptDatabaseOperation() const {sqlite3_interrupt(mDatabaseHandle);}
//! Returns non-zero or zero if the given database connection is or is not in autocommit mode, respectively.\n
//! Autocommit mode is on by default. Autocommit mode is disabled by a BEGIN statement.\n
//! Autocommit mode is re-enabled by a COMMIT or ROLLBACK.
int GetAutoCommit() const {return sqlite3_get_autocommit(mDatabaseHandle);}
//! Trace() is invoked at various times when a SQL statement is being run by FetchRow(), SqlStatement() or ExecuteAndFree(). \n
//! The callback returns a UTF-8 rendering of the SQL statement text as the statement first begins executing.\n
//! Output: std::cout
inline void ActivateTracing() const {sqlite3_trace(mDatabaseHandle, &Kompex::SQLiteDatabase::TraceOutput, 0);}
//! Profile() is invoked as each SQL statement finishes.\n
//! The profile callback contains the original statement text\n
//! and an estimate of wall-clock time of how long that statement took to run.\n
//! Note: time in ns\n
//! Output: std::cout
inline void ActivateProfiling() const {sqlite3_profile(mDatabaseHandle, &Kompex::SQLiteDatabase::ProfileOutput, 0);}
//! The SetSoftHeapLimit() interface places a "soft" limit on the amount of heap memory that may be allocated by SQLite.\n
//! If an internal allocation is requested that would exceed the soft heap limit, sqlite3_release_memory()\n
//! is invoked one or more times to free up some space before the allocation is performed.\n
//! The limit is called "soft", because if sqlite3_release_memory() cannot free sufficient memory to\n
//! prevent the limit from being exceeded, the memory is allocated anyway and the current operation proceeds.\n
//! A negative or zero value for heapLimit means that there is no soft heap limit and sqlite3_release_memory()\n
//! will only be called when memory is exhausted. The default value for the soft heap limit is zero.
//! @param heapLimit Heap limit in bytes.
inline void SetSoftHeapLimit(int heapLimit) const {sqlite3_soft_heap_limit(heapLimit);}
//! The ReleaseMemory() interface attempts to free N bytes of heap memory by deallocating\n
//! non-essential memory allocations held by the database library.\n
//! Memory used to cache database pages to improve performance is an example of non-essential memory.\n
//! ReleaseMemory() returns the number of bytes actually freed, which might be more or less than the amount requested.
//! @param bytesOfMemory Memory in bytes, which should be freed
inline int ReleaseMemory(int bytesOfMemory) const {return sqlite3_release_memory(bytesOfMemory);}
//! GetMemoryUsed() returns the number of bytes of memory currently outstanding (malloced but not freed).
long long GetMemoryUsage() const {return sqlite3_memory_used();}
//! GetMemoryHighwaterMark() returns the maximum value of used bytes since the high-water mark was last reset.
//! @param resetFlag The memory high-water mark is reset to the current value of GetMemoryUsage() if resetFlag is true.\n
//! The value returned by GetMemoryHighwaterMark(true) is the high-water mark prior to the reset.
long long GetMemoryHighwaterMark(bool resetFlag = false) const {return sqlite3_memory_highwater(resetFlag);}
//! Provided encodings for MoveDatabaseToMemory().
enum UtfEncoding {UTF8, UTF16};
//! Move the whole database into memory.\n
//! Please pay attention, that after a call of MoveDatabaseToMemory() all SQL statements are executed into memory.\n
//! i.e. that all changes will be lost after closing the database!
//! Hint: this method can only be used for databases which were openend with a UTF8 filename
//! @param encoding Encoding which will be used for moving the data.
void MoveDatabaseToMemory(UtfEncoding encoding = UTF8);
//! Takes a snapshot of a database which is located in memory and saves it to a database file.
//! @param filename Filename for the new database file to which the snapshot will be saved.\n
//! When you leave the filename blank, you will overwrite your origin file database.
void SaveDatabaseFromMemoryToFile(const std::string &filename = "");
//! Takes a snapshot of a database which is located in memory and saves it to a database file.
//! @param filename Filename for the new database file to which the snapshot will be saved.
void SaveDatabaseFromMemoryToFile(const wchar_t *filename);
//! This function returns the rowid of the most recent successful INSERT into the database.\n
//! If no successful INSERTs have ever occurred on that database connection, zero is returned.\n\n
//! What is the rowid?\n
//! Each entry in a SQLite table has a unique 64-bit signed integer key called the "rowid".\n
//! The rowid is always available as an undeclared column named ROWID, OID or _ROWID_ as long as\n
//! those names are not also used by explicitly declared columns. If the table has a column\n
//! of type INTEGER PRIMARY KEY then that column is another alias for the rowid.
long long GetLastInsertRowId() const {return sqlite3_last_insert_rowid(mDatabaseHandle);}
//! This function returns true if the database was opened in read-only mode an false if the\n
//! database was opened in read/write mode.
bool IsDatabaseReadOnly();
//! This function attempts to free as much heap memory as possible from the database connection.
inline void ReleaseMemory() {sqlite3_db_release_memory(mDatabaseHandle);}
/**
This method can be used to register a new virtual table module name. Module names must be\n
registered before creating a new virtual table using the module and before using a preexisting\n
virtual table for the module. The module name will be registered with this database handle.
@param moduleName Name of the module.
@param module Pointer to the implementation of the virtual table module.
@param clientData Arbitrary client data pointer that is passed through into the xCreate\n
and xConnect methods of the virtual table module when a new virtual\n
table is be being created or reinitialized.
@param xDestroy Pointer to a destructor for the clientData. SQLite will invoke the destructor\n
function (if it is not NULL) when SQLite no longer needs the clientData pointer.\n
The destructor will also be invoked if the call to CreateModule() fails.
*/
void CreateModule(const std::string &moduleName, const sqlite3_module *module, void *clientData, void(*xDestroy)(void*));
//! Removes all virtual table modules except those named in parameter keepModules.
//! @param keepModules If the parameter is NULL (default), then all virtual table modules are removed.\n
//! Must be otherwise a pointer to an array of pointers to strings where the array\n
//! is terminated by a single NULL pointer.
void DropModules(const char **keepModules = NULL);
//! Returns the number of lookaside memory slots currently checked out.
int GetNumberOfCheckedOutLookasideMemorySlots() const;
//! Returns the approximate number of bytes of heap memory used by all pager caches.
int GetHeapMemoryUsedByPagerCaches() const;
//! Returns the approximate number of bytes of heap memory used to store the schema for\n
//! all databases associated with the connection - main, temp, and any ATTACH-ed databases.\n
//! The full amount of memory used by the schemas is reported, even if the schema memory is\n
//! shared with other database connections due to shared cache mode being enabled.
int GetHeapMemoryUsedToStoreSchemas() const;
//! Returns the approximate number of bytes of heap and lookaside memory used by all\n
//! prepared statements associated with the database connection.
int GetHeapAndLookasideMemoryUsedByPreparedStatements() const;
//! Returns the number of pager cache hits that have occurred.
int GetPagerCacheHitCount() const;
//! Returns the number of pager cache misses that have occurred.
int GetPagerCacheMissCount() const;
//! Returns the number of dirty cache entries that have been written to disk. Specifically,\n
//! the number of pages written to the wal file in wal mode databases, or the number of pages\n
//! written to the database file in rollback mode databases. Any pages written as part of\n
//! transaction rollback or database recovery operations are not included. If an IO or other\n
//! error occurs while writing a page to disk, the effect on subsequent SQLITE_DBSTATUS_CACHE_WRITE\n
//! requests is undefined.
int GetNumberOfDirtyCacheEntries() const;
//! Returns zero if all foreign key constraints (deferred or immediate) have been resolved.
int GetNumberOfUnresolvedForeignKeys() const;
//! Returns the current transaction state of the schema.\n
//! @param schema Name of the schema. If the schema is NULL (default), then the highest transaction state\n
//! of any schema on the database connection is returned.
//! Possible transaction states:\n
//! 0 (SQLITE_TXN_NONE):\n
//! No transaction is currently pending.\n
//! 1 (SQLITE_TXN_READ):\n
//! The database is currently in a read transaction. Content has been read from the database file\n
//! but nothing in the database file has changed. The transaction state will advanced to SQLITE_TXN_WRITE\n
//! if any changes occurand there are no other conflicting concurrent write transactions. The transaction\n
//! state will revert to SQLITE_TXN_NONE following a ROLLBACK or COMMIT.\n
//! 2 (SQLITE_TXN_WRITE):\n
//! The database is currently in a write transaction. Content has been written to the database file but has\n
//! not yet committed. The transaction state will change to to SQLITE_TXN_NONE at the next ROLLBACK or COMMIT.
int GetTransactionState(const char* schema = NULL) const;
//! Returns the highest number of lookaside memory slots that has been checked out.
//! @param resetValue Allows to reset the highest value.
int GetHighestNumberOfCheckedOutLookasideMemorySlots(bool resetValue = false);
//! Returns the number malloc attempts that were satisfied using lookaside memory.
//! @param resetValue Allows to reset the highest value.
int GetLookasideMemoryHitCount(bool resetValue = false);
//! Returns the number malloc attempts that might have been satisfied using lookaside memory\n
//! but failed due to the amount of memory requested being larger than the lookaside slot size.
//! @param resetValue Allows to reset the highest value.
int GetLookasideMemoryMissCountDueToSmallSlotSize(bool resetValue = false);
//! Returns the number malloc attempts that might have been satisfied using lookaside memory\n
//! but failed due to all lookaside memory already being in use.
//! @param resetValue Allows to reset the highest value.
int GetLookasideMemoryMissCountDueToFullMemory(bool resetValue = false);
protected:
//! Callback function for ActivateTracing() [sqlite3_trace]
static void TraceOutput(void *ptr, const char *sql);
//! Callback function for ActivateProfiling() [sqlite3_profile]
static void ProfileOutput(void *ptr, const char *sql, sqlite3_uint64 time);
//! Build and modify the structure of your tables and other objects in the memory database.
static int ProcessDDLRow(void *db, int nColumns, char **values, char **columns);
//! Insert all data from the origin database into the memory database.
static int ProcessDMLRow(void *db, int nColumns, char **values, char **columns);
//! Takes and saves a snapshot of the memory database in a file.
void TakeSnapshot(sqlite3 *destinationDatabase);
//! Returns internal runtime status information associated with the current database connection.
int GetRuntimeStatusInformation(int operation, bool highwaterValue = false, bool resetFlag = false) const;
private:
//! SQLite db handle
struct sqlite3 *mDatabaseHandle;
//! Is the database currently stored in memory?
bool mIsMemoryDatabaseActive;
//! Database filename UTF-8
std::string mDatabaseFilenameUtf8;
//! Database filename UTF-16
std::wstring mDatabaseFilenameUtf16;
//! Clean up routine if something failed in MoveDatabaseToMemory()
void CleanUpFailedMemoryDatabase(sqlite3 *memoryDatabase, sqlite3 *rollbackDatabase, bool isDetachNecessary, bool isRollbackNecessary, sqlite3_stmt *stmt, const std::string &errMsg, int internalSqliteErrCode);
};
};
#endif // KompexSQLiteDatabase_H