mirror of
https://github.com/VCMP-SqMod/SqMod.git
synced 2024-11-14 03:37:16 +01:00
416 lines
14 KiB
C++
416 lines
14 KiB
C++
|
#ifndef _LIBRARY_SQLITE_SHARED_HPP_
|
||
|
#define _LIBRARY_SQLITE_SHARED_HPP_
|
||
|
|
||
|
// ------------------------------------------------------------------------------------------------
|
||
|
#include "Common.hpp"
|
||
|
#include "Library/LongInt.hpp"
|
||
|
|
||
|
// ------------------------------------------------------------------------------------------------
|
||
|
#include <sqlite3.h>
|
||
|
|
||
|
// ------------------------------------------------------------------------------------------------
|
||
|
#include <queue>
|
||
|
|
||
|
// ------------------------------------------------------------------------------------------------
|
||
|
namespace SqMod {
|
||
|
namespace SQLite {
|
||
|
|
||
|
// ------------------------------------------------------------------------------------------------
|
||
|
class Connection;
|
||
|
class Statement;
|
||
|
class Result;
|
||
|
|
||
|
/* ------------------------------------------------------------------------------------------------
|
||
|
* A managed handle to a shared SQLite connection.
|
||
|
*/
|
||
|
class ConnectionHandle
|
||
|
{
|
||
|
// --------------------------------------------------------------------------------------------
|
||
|
friend class Connection;
|
||
|
|
||
|
protected:
|
||
|
|
||
|
/* --------------------------------------------------------------------------------------------
|
||
|
* Helper class responsible for managing the handle to an SQLite connection resource.
|
||
|
*/
|
||
|
struct Handle
|
||
|
{
|
||
|
friend class ConnectionHandle;
|
||
|
|
||
|
/* ----------------------------------------------------------------------------------------
|
||
|
* The type of container used to queue queries for group execution.
|
||
|
*/
|
||
|
typedef std::queue< String > QueryList;
|
||
|
|
||
|
/* ----------------------------------------------------------------------------------------
|
||
|
* The amount of references to this handle instance.
|
||
|
*/
|
||
|
mutable SQUint32 Ref;
|
||
|
|
||
|
/* ----------------------------------------------------------------------------------------
|
||
|
* The handle to the managed SQLite connection resource.
|
||
|
*/
|
||
|
sqlite3* Ptr;
|
||
|
|
||
|
/* ----------------------------------------------------------------------------------------
|
||
|
* The flags used to create the SQLite connection handle.
|
||
|
*/
|
||
|
SQInt32 Flags;
|
||
|
|
||
|
/* ----------------------------------------------------------------------------------------
|
||
|
* The specified path to be used as the database file.
|
||
|
*/
|
||
|
String Path;
|
||
|
|
||
|
/* ----------------------------------------------------------------------------------------
|
||
|
* The specified virtual file system.
|
||
|
*/
|
||
|
String VFS;
|
||
|
|
||
|
/* ----------------------------------------------------------------------------------------
|
||
|
* The last status code of this connection handle.
|
||
|
*/
|
||
|
SQInt32 Status;
|
||
|
|
||
|
/* ----------------------------------------------------------------------------------------
|
||
|
* A queue of queries to be executed in groups in order to reduce lag.
|
||
|
*/
|
||
|
QueryList Queue;
|
||
|
|
||
|
/* ----------------------------------------------------------------------------------------
|
||
|
* The global tag associated with this resource.
|
||
|
*/
|
||
|
SqTag Tag;
|
||
|
|
||
|
/* ----------------------------------------------------------------------------------------
|
||
|
* The global data associated with this resource.
|
||
|
*/
|
||
|
SqObj Data;
|
||
|
|
||
|
/* ----------------------------------------------------------------------------------------
|
||
|
* Whether the database exists in memory and not disk.
|
||
|
*/
|
||
|
bool Memory;
|
||
|
|
||
|
/* ----------------------------------------------------------------------------------------
|
||
|
* Whether tracing was activated on the database.
|
||
|
*/
|
||
|
bool Trace;
|
||
|
|
||
|
/* ----------------------------------------------------------------------------------------
|
||
|
* Whether profiling was activated on the database.
|
||
|
*/
|
||
|
bool Profile;
|
||
|
|
||
|
private:
|
||
|
|
||
|
/* ----------------------------------------------------------------------------------------
|
||
|
* Handle constructor.
|
||
|
*/
|
||
|
Handle(const String & path, SQInt32 flags, const String & vfs)
|
||
|
: Ref(1), Ptr(NULL), Flags(flags), Path(path), VFS(vfs)
|
||
|
, Status(SQLITE_OK), Queue(), Tag(), Data()
|
||
|
, Memory(path == ":memory:"), Trace(false), Profile(false)
|
||
|
{
|
||
|
/* ... */
|
||
|
}
|
||
|
|
||
|
/* ----------------------------------------------------------------------------------------
|
||
|
* Copy constructor (disabled)
|
||
|
*/
|
||
|
Handle(const Handle &) = delete;
|
||
|
|
||
|
/* ----------------------------------------------------------------------------------------
|
||
|
* Move constructor (disabled)
|
||
|
*/
|
||
|
Handle(Handle &&) = delete;
|
||
|
|
||
|
/* ----------------------------------------------------------------------------------------
|
||
|
* Handle destructor.
|
||
|
*/
|
||
|
~Handle()
|
||
|
{
|
||
|
// If a valid handle exists then attempt to release it
|
||
|
if (Ptr != NULL && (Status = sqlite3_close(Ptr)) != SQLITE_OK)
|
||
|
{
|
||
|
LogErr("Unable to <close database connection> because : %s", sqlite3_errmsg(Ptr));
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/* ----------------------------------------------------------------------------------------
|
||
|
* Copy assignment operator (disabled)
|
||
|
*/
|
||
|
Handle & operator = (const Handle &) = delete;
|
||
|
|
||
|
/* ----------------------------------------------------------------------------------------
|
||
|
* Move assignment operator (disabled)
|
||
|
*/
|
||
|
Handle & operator = (Handle &&) = delete;
|
||
|
};
|
||
|
|
||
|
/* --------------------------------------------------------------------------------------------
|
||
|
* Acquire a strong reference to the resource handle.
|
||
|
*/
|
||
|
void Grab()
|
||
|
{
|
||
|
// If a valid handle exists then grab a reference to it
|
||
|
if (Hnd != nullptr)
|
||
|
{
|
||
|
++(Hnd->Ref);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/* --------------------------------------------------------------------------------------------
|
||
|
* Release the handle reference and therefore the handle it self if no more references exist.
|
||
|
*/
|
||
|
void Drop()
|
||
|
{
|
||
|
// If a valid handle exists then delete it if this is the last released reference
|
||
|
if (Hnd != nullptr && --(Hnd->Ref) == 0)
|
||
|
{
|
||
|
delete Hnd;
|
||
|
}
|
||
|
// Explicitly make sure the handle is null
|
||
|
Hnd = nullptr;
|
||
|
}
|
||
|
|
||
|
public:
|
||
|
|
||
|
/* --------------------------------------------------------------------------------------------
|
||
|
* The handle instance that manages the SQLite resource.
|
||
|
*/
|
||
|
Handle * Hnd;
|
||
|
|
||
|
/* --------------------------------------------------------------------------------------------
|
||
|
* Default constructor (invalid).
|
||
|
*/
|
||
|
ConnectionHandle();
|
||
|
|
||
|
/* --------------------------------------------------------------------------------------------
|
||
|
* Open a connection to a database using the specified path, flags and vfs.
|
||
|
*/
|
||
|
ConnectionHandle(const SQChar * path, SQInt32 flags, const SQChar * vfs);
|
||
|
|
||
|
/* --------------------------------------------------------------------------------------------
|
||
|
* Copy constructor.
|
||
|
*/
|
||
|
ConnectionHandle(const ConnectionHandle & o);
|
||
|
|
||
|
/* --------------------------------------------------------------------------------------------
|
||
|
* Move constructor.
|
||
|
*/
|
||
|
ConnectionHandle(ConnectionHandle && o);
|
||
|
|
||
|
/* --------------------------------------------------------------------------------------------
|
||
|
* Destructor.
|
||
|
*/
|
||
|
~ConnectionHandle();
|
||
|
|
||
|
/* --------------------------------------------------------------------------------------------
|
||
|
* Copy assignment operator.
|
||
|
*/
|
||
|
ConnectionHandle & operator = (const ConnectionHandle & o);
|
||
|
|
||
|
/* --------------------------------------------------------------------------------------------
|
||
|
* Move assignment operator.
|
||
|
*/
|
||
|
ConnectionHandle & operator = (ConnectionHandle && o);
|
||
|
|
||
|
/* --------------------------------------------------------------------------------------------
|
||
|
* Implicit conversion to boolean.
|
||
|
*/
|
||
|
operator bool () const
|
||
|
{
|
||
|
return (Hnd != nullptr) && (Hnd->Ptr != NULL);
|
||
|
}
|
||
|
|
||
|
/* --------------------------------------------------------------------------------------------
|
||
|
* Negation operator.
|
||
|
*/
|
||
|
operator ! () const
|
||
|
{
|
||
|
return (Hnd == nullptr) || (Hnd->Ptr == NULL);
|
||
|
}
|
||
|
|
||
|
/* --------------------------------------------------------------------------------------------
|
||
|
* Implicit conversion to raw SQLite connection handle.
|
||
|
*/
|
||
|
operator sqlite3 * () const
|
||
|
{
|
||
|
return (Hnd != nullptr) ? Hnd->Ptr : NULL;
|
||
|
}
|
||
|
|
||
|
/* --------------------------------------------------------------------------------------------
|
||
|
* Implicit conversion to integer status code.
|
||
|
*/
|
||
|
operator SQInt32 () const
|
||
|
{
|
||
|
return (Hnd != nullptr) ? Hnd->Status : 0;
|
||
|
}
|
||
|
|
||
|
/* --------------------------------------------------------------------------------------------
|
||
|
* Member of pointer operator.
|
||
|
*/
|
||
|
Handle * operator -> () const
|
||
|
{
|
||
|
return Hnd;
|
||
|
}
|
||
|
|
||
|
/* --------------------------------------------------------------------------------------------
|
||
|
* Indirection operator.
|
||
|
*/
|
||
|
Handle & operator * () const
|
||
|
{
|
||
|
return *Hnd;
|
||
|
}
|
||
|
|
||
|
/* --------------------------------------------------------------------------------------------
|
||
|
* Equality operator.
|
||
|
*/
|
||
|
bool operator == (const ConnectionHandle & o) const
|
||
|
{
|
||
|
return (Hnd == o.Hnd);
|
||
|
}
|
||
|
|
||
|
/* --------------------------------------------------------------------------------------------
|
||
|
* Inequality operator.
|
||
|
*/
|
||
|
bool operator != (const ConnectionHandle & o) const
|
||
|
{
|
||
|
return (Hnd != o.Hnd);
|
||
|
}
|
||
|
|
||
|
/* --------------------------------------------------------------------------------------------
|
||
|
* Reset this handle and release the internal reference.
|
||
|
*/
|
||
|
void Release()
|
||
|
{
|
||
|
Drop();
|
||
|
}
|
||
|
|
||
|
/* --------------------------------------------------------------------------------------------
|
||
|
* Retrieve the number of active references to this handle.
|
||
|
*/
|
||
|
SQUint32 Count() const
|
||
|
{
|
||
|
return (Hnd != nullptr) ? Hnd->Ref : 0;
|
||
|
}
|
||
|
|
||
|
/* --------------------------------------------------------------------------------------------
|
||
|
* Retrieve the error message associated with the value in status.
|
||
|
*/
|
||
|
const SQChar * ErrStr() const
|
||
|
{
|
||
|
return sqlite3_errstr(Hnd->Status);
|
||
|
}
|
||
|
|
||
|
/* --------------------------------------------------------------------------------------------
|
||
|
* Retrieve the error message associated with the connection.
|
||
|
*/
|
||
|
const SQChar * ErrMsg() const
|
||
|
{
|
||
|
return sqlite3_errmsg(Hnd->Ptr);
|
||
|
}
|
||
|
|
||
|
/* --------------------------------------------------------------------------------------------
|
||
|
* Retrieve the error code associated with the connection.
|
||
|
*/
|
||
|
SQInt32 ErrNo() const
|
||
|
{
|
||
|
return sqlite3_errcode(Hnd->Ptr);
|
||
|
}
|
||
|
};
|
||
|
|
||
|
/* ------------------------------------------------------------------------------------------------
|
||
|
* RAII encapsulation of a SQLite Transaction.
|
||
|
*/
|
||
|
class Transaction
|
||
|
{
|
||
|
public:
|
||
|
|
||
|
/* --------------------------------------------------------------------------------------------
|
||
|
* Default constructor.
|
||
|
*/
|
||
|
Transaction(const Connection & db);
|
||
|
|
||
|
/* --------------------------------------------------------------------------------------------
|
||
|
* Copy constructor (disabled).
|
||
|
*/
|
||
|
Transaction(const Transaction & o) = delete;
|
||
|
|
||
|
/* --------------------------------------------------------------------------------------------
|
||
|
* Move constructor (disabled).
|
||
|
*/
|
||
|
Transaction(Transaction && o) = delete;
|
||
|
|
||
|
/* --------------------------------------------------------------------------------------------
|
||
|
* Destructor.
|
||
|
*/
|
||
|
~Transaction();
|
||
|
|
||
|
/* --------------------------------------------------------------------------------------------
|
||
|
* Copy assignment operator (disabled).
|
||
|
*/
|
||
|
Transaction & operator = (const Transaction & o) = delete;
|
||
|
|
||
|
/* --------------------------------------------------------------------------------------------
|
||
|
* Move assignment operator (disabled).
|
||
|
*/
|
||
|
Transaction & operator = (Transaction && o) = delete;
|
||
|
|
||
|
/* --------------------------------------------------------------------------------------------
|
||
|
* Commit the transaction.
|
||
|
*/
|
||
|
void Commit();
|
||
|
|
||
|
/* --------------------------------------------------------------------------------------------
|
||
|
* See whether the transaction was committed.
|
||
|
*/
|
||
|
bool Commited() const
|
||
|
{
|
||
|
return m_Commited;
|
||
|
}
|
||
|
|
||
|
protected:
|
||
|
|
||
|
// --------------------------------------------------------------------------------------------
|
||
|
|
||
|
private:
|
||
|
|
||
|
/* --------------------------------------------------------------------------------------------
|
||
|
* The SQLite connection associated with this transaction.
|
||
|
*/
|
||
|
ConnectionHandle m_Connection;
|
||
|
|
||
|
/* --------------------------------------------------------------------------------------------
|
||
|
* Whether the changes were committed.
|
||
|
*/
|
||
|
bool m_Commited;
|
||
|
};
|
||
|
|
||
|
/* ------------------------------------------------------------------------------------------------
|
||
|
* Places a "soft" limit on the amount of heap memory that may be allocated by SQLite.
|
||
|
*/
|
||
|
void SetSoftHeapLimit(SQInt32 limit);
|
||
|
|
||
|
/* ------------------------------------------------------------------------------------------------
|
||
|
* Attempts to free N bytes of heap memory by deallocating non-essential memory allocations
|
||
|
* held by the database library.
|
||
|
*/
|
||
|
SQInt32 ReleaseMemory(SQInt32 bytes);
|
||
|
|
||
|
/* ------------------------------------------------------------------------------------------------
|
||
|
* Returns the number of bytes of memory currently outstanding (malloced but not freed).
|
||
|
*/
|
||
|
SLongInt GetMemoryUsage();
|
||
|
|
||
|
/* ------------------------------------------------------------------------------------------------
|
||
|
* Returns the maximum value of used bytes since the high-water mark was last reset.
|
||
|
*/
|
||
|
SLongInt GetMemoryHighwaterMark(bool reset);
|
||
|
|
||
|
} // Namespace:: SQLite
|
||
|
} // Namespace:: SqMod
|
||
|
|
||
|
#endif // _LIBRARY_SQLITE_SHARED_HPP_
|