1
0
mirror of https://github.com/VCMP-SqMod/SqMod.git synced 2025-07-30 20:51:48 +02:00

Merge SQLite library into a single file.

This commit is contained in:
Sandu Liviu Catalin
2020-03-22 02:44:33 +02:00
parent 91c0f2ec02
commit 8ea13de743
18 changed files with 5629 additions and 5864 deletions

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -1,540 +0,0 @@
// ------------------------------------------------------------------------------------------------
#include "Library/SQLite/Column.hpp"
// ------------------------------------------------------------------------------------------------
#include <cstdlib>
#include <cstring>
// ------------------------------------------------------------------------------------------------
#include <sqstdblob.h>
// ------------------------------------------------------------------------------------------------
namespace SqMod {
// ------------------------------------------------------------------------------------------------
SQMODE_DECL_TYPENAME(Typename, _SC("SqLiteColumn"))
// ------------------------------------------------------------------------------------------------
static inline bool IsDigitsOnly(CSStr str)
{
while (std::isdigit(*str) || std::isspace(*str))
{
++str;
}
// Return whether we reached the end while searching
return *str == '\0';
}
// ------------------------------------------------------------------------------------------------
#if defined(_DEBUG) || defined(SQMOD_EXCEPTLOC)
void Column::Validate(CCStr file, Int32 line) const
{
// Are we pointing to a valid index?
if (m_Index < 0)
{
SqThrowF("Invalid column index: %d < 0 =>[%s:%d]", m_Index, file, line);
}
// Do we have a valid statement handle?
else if (!m_Handle)
{
SqThrowF("Invalid SQLite statement reference =>[%s:%d]", file, line);
}
}
#else
void Column::Validate() const
{
// Are we pointing to a valid index?
if (m_Index < 0)
{
SqThrowF("Invalid column index: %d < 0", m_Index);
}
// Do we have a valid statement handle?
else if (!m_Handle)
{
SqThrowF("Invalid SQLite statement reference");
}
}
#endif // _DEBUG
// ------------------------------------------------------------------------------------------------
#if defined(_DEBUG) || defined(SQMOD_EXCEPTLOC)
void Column::ValidateCreated(CCStr file, Int32 line) const
{
// Are we pointing to a valid index?
if (m_Index < 0)
{
SqThrowF("Invalid column index: %d < 0 =>[%s:%d]", m_Index, file, line);
}
else if (!m_Handle)
{
SqThrowF("Invalid SQLite statement reference =>[%s:%d]", file, line);
}
else if (m_Handle->mPtr == nullptr)
{
SqThrowF("Invalid SQLite statement =>[%s:%d]", file, line);
}
}
#else
void Column::ValidateCreated() const
{
// Are we pointing to a valid index?
if (m_Index < 0)
{
SqThrowF("Invalid column index: %d < 0", m_Index);
}
else if (!m_Handle)
{
SqThrowF("Invalid SQLite statement reference");
}
else if (m_Handle->mPtr == nullptr)
{
SqThrowF("Invalid SQLite statement");
}
}
#endif // _DEBUG
// ------------------------------------------------------------------------------------------------
#if defined(_DEBUG) || defined(SQMOD_EXCEPTLOC)
const StmtRef & Column::GetValid(CCStr file, Int32 line) const
{
Validate(file, line);
return m_Handle;
}
#else
const StmtRef & Column::GetValid() const
{
Validate();
return m_Handle;
}
#endif // _DEBUG
// ------------------------------------------------------------------------------------------------
#if defined(_DEBUG) || defined(SQMOD_EXCEPTLOC)
const StmtRef & Column::GetCreated(CCStr file, Int32 line) const
{
ValidateCreated(file, line);
return m_Handle;
}
#else
const StmtRef & Column::GetCreated() const
{
ValidateCreated();
return m_Handle;
}
#endif // _DEBUG
// ------------------------------------------------------------------------------------------------
#if defined(_DEBUG) || defined(SQMOD_EXCEPTLOC)
void Column::ValidateColumn(Int32 idx, CCStr file, Int32 line) const
{
ValidateCreated(file, line);
// Is the specified index in range?
if (!m_Handle->CheckColumn(idx))
{
SqThrowF("Column index is out of range: %d:%d =>[%s:%d]", idx, m_Handle->mColumns,
file, line);
}
}
#else
void Column::ValidateColumn(Int32 idx) const
{
ValidateCreated();
// Is the specified index in range?
if (!m_Handle->CheckColumn(idx))
{
SqThrowF("Column index is out of range: %d:%d", idx, m_Handle->mColumns);
}
}
#endif // _DEBUG
// ------------------------------------------------------------------------------------------------
#if defined(_DEBUG) || defined(SQMOD_EXCEPTLOC)
void Column::ValidateRow(CCStr file, Int32 line) const
{
ValidateCreated(file, line);
// Do we have any rows available?
if (!m_Handle->mGood)
{
STHROWF("No row available =>[%s:%d]", file, line);
}
}
#else
void Column::ValidateRow() const
{
ValidateCreated();
// Do we have any rows available?
if (!m_Handle->mGood)
{
STHROWF("No row available");
}
}
#endif // _DEBUG
// ------------------------------------------------------------------------------------------------
void Column::SetIndex(const Object & column)
{
// Where the index will be extracted
Int32 idx = -1;
// Grab the object virtual machine
HSQUIRRELVM vm = column.GetVM();
// Remember the current stack size
const StackGuard sg(vm);
// Push the specified object onto the stack
Var< const Object & >::push(vm, column);
// Identify the type of column was given
switch (column.GetType())
{
// Is this a string value?
case OT_STRING:
{
// Obtain the object from the stack as a string
StackStrF val(vm, -1);
// Validate the result
if (SQ_FAILED(val.Proc(false)))
{
STHROWF("%s", LastErrorString(vm).c_str());
}
// Is the obtained string empty?
else if (val.mLen <= 0)
{
STHROWF("Cannot use an empty column name");
}
// Attempt to find a column with the specified name
idx = m_Handle->GetColumnIndex(val.mPtr);
} break;
// Is this an integer value? (or at least can be easily converted to one)
case OT_INTEGER:
case OT_FLOAT:
case OT_BOOL:
{
idx = ConvTo< Int32 >::From(PopStackInteger(vm, -1));
} break;
// Is this an instance that we can extract either a string or integer from it?
case OT_INSTANCE:
{
// Obtain the object from the stack as a string
StackStrF val(vm, -1);
// Validate the result
if (SQ_FAILED(val.Proc(false)))
{
STHROWF("%s", LastErrorString(vm).c_str());
}
// Is the obtained string empty?
else if (val.mLen <= 0)
{
STHROWF("Cannot use an empty column name");
}
// Check if this value is made only of digits
else if (IsDigitsOnly(val.mPtr))
{
idx = ConvNum< Int32 >::FromStr(val.mPtr);
}
// Attempt to find a column with the specified name
else
{
idx = m_Handle->GetColumnIndex(val.mPtr);
}
} break;
// We don't recognize this kind of value!
default: STHROWF("Unknown column index of type (%s)", SqTypeName(column.GetType()));
}
// Assign the index with a failsafe to invalid on error
AutoAssign< Int32 > aa(m_Index, -1, idx);
// Validate the obtained column index
SQMOD_VALIDATE_COLUMN(*this, idx);
// Don't fall back to the invalid index anymore
aa.Set(idx);
}
// ------------------------------------------------------------------------------------------------
Object Column::GetStatement() const
{
return GetStatementObj(m_Handle);
}
// ------------------------------------------------------------------------------------------------
Object Column::GetConnection() const
{
return GetConnectionObj(SQMOD_GET_VALID(*this)->mConn);
}
// ------------------------------------------------------------------------------------------------
bool Column::IsNull() const
{
return (sqlite3_column_type(SQMOD_GET_CREATED(*this)->mPtr, m_Index) == SQLITE_NULL);
}
// ------------------------------------------------------------------------------------------------
CSStr Column::GetName() const
{
return sqlite3_column_name(SQMOD_GET_CREATED(*this)->mPtr, m_Index);
}
// ------------------------------------------------------------------------------------------------
CSStr Column::GetOriginName() const
{
#ifdef SQLITE_ENABLE_COLUMN_METADATA
return sqlite3_column_origin_name(SQMOD_GET_CREATED(*this)->mPtr, m_Index);
#else
STHROWF("The module was compiled without this feature");
// Request failed
return _SC("");
#endif
}
// ------------------------------------------------------------------------------------------------
Int32 Column::GetType() const
{
return sqlite3_column_type(SQMOD_GET_CREATED(*this)->mPtr, m_Index);
}
// ------------------------------------------------------------------------------------------------
Int32 Column::GetBytes() const
{
return sqlite3_column_bytes(SQMOD_GET_CREATED(*this)->mPtr, m_Index);
}
// ------------------------------------------------------------------------------------------------
Object Column::GetValue() const
{
SQMOD_VALIDATE_ROW(*this);
// Obtain the initial stack size
const StackGuard sg;
// Identify which type of value must be pushed on the stack
switch (sqlite3_column_type(m_Handle->mPtr, m_Index))
{
// Is this a null value?
case SQLITE_NULL:
{
sq_pushnull(DefaultVM::Get());
} break;
// Is this an integer?
case SQLITE_INTEGER:
{
sq_pushinteger(DefaultVM::Get(), sqlite3_column_integer(m_Handle->mPtr, m_Index));
} break;
// Is this a floating point?
case SQLITE_FLOAT:
{
sq_pushfloat(DefaultVM::Get(),
ConvTo< SQFloat >::From(sqlite3_column_double(m_Handle->mPtr, m_Index)));
} break;
// Is this a string?
case SQLITE_TEXT:
{
sq_pushstring(DefaultVM::Get(),
reinterpret_cast< CSStr >(sqlite3_column_text(m_Handle->mPtr, m_Index)),
sqlite3_column_bytes(m_Handle->mPtr, m_Index));
} break;
// Is this raw data?
case SQLITE_BLOB:
{
// Retrieve the size of the blob that must be allocated
const Int32 size = sqlite3_column_bytes(m_Handle->mPtr, m_Index);
// Retrieve the the actual blob data that must be returned
auto data = reinterpret_cast< CCStr >(sqlite3_column_blob(m_Handle->mPtr, m_Index));
// Attempt to create a buffer with the blob data on the stack
Var< const SqBuffer & >::push(DefaultVM::Get(), SqBuffer(data, size, 0));
} break;
// Unknown type
default: STHROWF("Unknown value to fetch at index: %d", m_Index);
}
// Obtain the object with the value from the stack and return it
return Var< Object >(DefaultVM::Get(), -1).value;
}
// ------------------------------------------------------------------------------------------------
Object Column::GetNumber() const
{
SQMOD_VALIDATE_ROW(*this);
// Obtain the initial stack size
const StackGuard sg;
// Identify which type of value must be pushed on the stack
switch (sqlite3_column_type(m_Handle->mPtr, m_Index))
{
// Is this a null value?
case SQLITE_NULL:
{
sq_pushinteger(DefaultVM::Get(), 0);
} break;
// Is this an integer?
case SQLITE_INTEGER:
{
sq_pushinteger(DefaultVM::Get(), sqlite3_column_integer(m_Handle->mPtr, m_Index));
} break;
// Is this a floating point?
case SQLITE_FLOAT:
{
sq_pushfloat(DefaultVM::Get(),
ConvTo< SQFloat >::From(sqlite3_column_double(m_Handle->mPtr, m_Index)));
} break;
// Is this a string?
case SQLITE_TEXT:
{
auto str = reinterpret_cast< CSStr >(sqlite3_column_text(m_Handle->mPtr, m_Index));
// Is there even a string to parse?
if (!str || *str == '\0')
{
sq_pushinteger(DefaultVM::Get(), 0);
}
// Can we treat this string as a float?
else if (!std::strchr(str, '.'))
{
sq_pushfloat(DefaultVM::Get(),
ConvTo< SQFloat >::From(std::strtod(str, nullptr)));
}
else
{
sq_pushinteger(DefaultVM::Get(),
ConvTo< SQInteger >::From(std::strtoll(str, nullptr, 10)));
}
} break;
// Unknown type
default: STHROWF("Unknown number to fetch at index: %d", m_Index);
}
// Obtain the object with the value from the stack and return it
return Var< Object >(DefaultVM::Get(), -1).value;
}
// ------------------------------------------------------------------------------------------------
SQInteger Column::GetInteger() const
{
SQMOD_VALIDATE_ROW(*this);
// Return the requested information
return sqlite3_column_integer(m_Handle->mPtr, m_Index);
}
// ------------------------------------------------------------------------------------------------
SQFloat Column::GetFloat() const
{
SQMOD_VALIDATE_ROW(*this);
// Return the requested information
return ConvTo< SQFloat >::From(sqlite3_column_double(m_Handle->mPtr, m_Index));
}
// ------------------------------------------------------------------------------------------------
Object Column::GetLong() const
{
SQMOD_VALIDATE_ROW(*this);
// Return the requested information
return Object(new SLongInt(sqlite3_column_int64(m_Handle->mPtr, m_Index)));
}
// ------------------------------------------------------------------------------------------------
Object Column::GetString() const
{
SQMOD_VALIDATE_ROW(*this);
// Obtain the initial stack size
const StackGuard sg;
// Push the column text on the stack
sq_pushstring(DefaultVM::Get(), reinterpret_cast< CSStr >(sqlite3_column_text(m_Handle->mPtr, m_Index)),
sqlite3_column_bytes(m_Handle->mPtr, m_Index));
// Get the object from the stack and return it
return Var< Object >(DefaultVM::Get(), -1).value;
}
// ------------------------------------------------------------------------------------------------
bool Column::GetBoolean() const
{
SQMOD_VALIDATE_ROW(*this);
// Return the requested information
return sqlite3_column_int(m_Handle->mPtr, m_Index) > 0;
}
// ------------------------------------------------------------------------------------------------
SQChar Column::GetChar() const
{
SQMOD_VALIDATE_ROW(*this);
// Return the requested information
return (SQChar)sqlite3_column_int(m_Handle->mPtr, m_Index);
}
// ------------------------------------------------------------------------------------------------
Object Column::GetBuffer() const
{
SQMOD_VALIDATE_ROW(*this);
// Remember the current stack size
const StackGuard sg;
// Retrieve the size of the blob that must be allocated
const Int32 size = sqlite3_column_bytes(m_Handle->mPtr, m_Index);
// Retrieve the the actual blob data that must be returned
auto data = reinterpret_cast< CCStr >(sqlite3_column_blob(m_Handle->mPtr, m_Index));
// Attempt to create a buffer with the blob data on the stack
Var< const SqBuffer & >::push(DefaultVM::Get(), SqBuffer(data, size, 0));
// Get the object from the stack and return it
return Var< Object >(DefaultVM::Get(), -1).value;
}
// ------------------------------------------------------------------------------------------------
Object Column::GetBlob() const
{
SQMOD_VALIDATE_ROW(*this);
// Obtain the initial stack size
const StackGuard sg;
// Obtain the size of the data
const Int32 sz = sqlite3_column_bytes(m_Handle->mPtr, m_Index);
// Allocate a blob of the same size
SQUserPointer p = sqstd_createblob(DefaultVM::Get(), sz);
// Obtain a pointer to the data
const void * b = sqlite3_column_blob(m_Handle->mPtr, m_Index);
// Could the memory blob be allocated?
if (!p)
{
STHROWF("Unable to allocate space for column blob value");
}
// Is there any data to read?
else if (!b)
{
// Pop the memory blob from the stack
sq_pop(DefaultVM::Get(), 1);
// Push a null value instead
sq_pushnull(DefaultVM::Get());
}
// Copy the data into the memory blob
else
{
std::memcpy(p, b, sz);
}
// Get the object from the stack and return it
return Var< Object >(DefaultVM::Get(), -1).value;
}
// ================================================================================================
void Register_Column(Table & sqlns)
{
sqlns.Bind(_SC("Column"),
Class< Column >(sqlns.GetVM(), Typename::Str)
// Constructors
.Ctor()
.Ctor< const Column & >()
// Meta-methods
.SquirrelFunc(_SC("_typename"), &Typename::Fn)
.Func(_SC("_tostring"), &Column::ToString)
// Properties
.Prop(_SC("IsValid"), &Column::IsValid)
.Prop(_SC("References"), &Column::GetRefCount)
.Prop(_SC("Index"), &Column::GetIndex)
.Prop(_SC("Statement"), &Column::GetStatement)
.Prop(_SC("Connection"), &Column::GetConnection)
.Prop(_SC("IsNull"), &Column::IsNull)
.Prop(_SC("Name"), &Column::GetName)
.Prop(_SC("OriginName"), &Column::GetOriginName)
.Prop(_SC("Type"), &Column::GetType)
.Prop(_SC("Bytes"), &Column::GetBytes)
.Prop(_SC("Value"), &Column::GetValue)
.Prop(_SC("Number"), &Column::GetNumber)
.Prop(_SC("Integer"), &Column::GetInteger)
.Prop(_SC("Float"), &Column::GetFloat)
.Prop(_SC("Long"), &Column::GetLong)
.Prop(_SC("String"), &Column::GetString)
.Prop(_SC("Boolean"), &Column::GetBoolean)
.Prop(_SC("Char"), &Column::GetChar)
.Prop(_SC("Buffer"), &Column::GetBuffer)
.Prop(_SC("Blob"), &Column::GetBlob)
// Member Methods
.Func(_SC("Release"), &Column::Release)
);
}
} // Namespace:: SqMod

View File

@@ -1,339 +0,0 @@
#pragma once
// ------------------------------------------------------------------------------------------------
#include "Library/SQLite/Handle.hpp"
// ------------------------------------------------------------------------------------------------
namespace SqMod {
/* ------------------------------------------------------------------------------------------------
* Used to manage and interact with statement columns.
*/
class Column
{
// --------------------------------------------------------------------------------------------
friend class Statement;
private:
// --------------------------------------------------------------------------------------------
Int32 m_Index; // The index of the managed column.
StmtRef m_Handle; // The statement where the column exist.
protected:
/* --------------------------------------------------------------------------------------------
* Validate the managed statement handle and throw an error if invalid.
*/
#if defined(_DEBUG) || defined(SQMOD_EXCEPTLOC)
void Validate(CCStr file, Int32 line) const;
#else
void Validate() const;
#endif // _DEBUG
/* --------------------------------------------------------------------------------------------
* Validate the managed statement handle and throw an error if invalid.
*/
#if defined(_DEBUG) || defined(SQMOD_EXCEPTLOC)
void ValidateCreated(CCStr file, Int32 line) const;
#else
void ValidateCreated() const;
#endif // _DEBUG
/* --------------------------------------------------------------------------------------------
* Validate the managed statement handle and throw an error if invalid.
*/
#if defined(_DEBUG) || defined(SQMOD_EXCEPTLOC)
const StmtRef & GetValid(CCStr file, Int32 line) const;
#else
const StmtRef & GetValid() const;
#endif // _DEBUG
/* --------------------------------------------------------------------------------------------
* Validate the managed statement handle and throw an error if invalid.
*/
#if defined(_DEBUG) || defined(SQMOD_EXCEPTLOC)
const StmtRef & GetCreated(CCStr file, Int32 line) const;
#else
const StmtRef & GetCreated() const;
#endif // _DEBUG
/* --------------------------------------------------------------------------------------------
* Validate the statement reference and column index, and throw an error if they're invalid.
*/
#if defined(_DEBUG) || defined(SQMOD_EXCEPTLOC)
void ValidateColumn(Int32 idx, CCStr file, Int32 line) const;
#else
void ValidateColumn(Int32 idx) const;
#endif // _DEBUG
/* --------------------------------------------------------------------------------------------
* Validate the statement reference and row, and throw an error if they're invalid.
*/
#if defined(_DEBUG) || defined(SQMOD_EXCEPTLOC)
void ValidateRow(CCStr file, Int32 line) const;
#else
void ValidateRow() const;
#endif // _DEBUG
/* --------------------------------------------------------------------------------------------
* Modify the index to the specified value.
*/
void SetIndex(Int32 idx)
{
// Assign the index with a failsafe to invalid on error
AutoAssign< Int32 > aa(m_Index, -1, idx);
// Validate the obtained column index
SQMOD_VALIDATE_COLUMN(*this, idx);
// Don't fall back to the invalid index anymore
aa.Set(idx);
}
/* --------------------------------------------------------------------------------------------
* Modify the index to the specified value.
*/
void SetIndex(CSStr name)
{
SetIndex(SQMOD_GET_CREATED(*this)->GetColumnIndex(name));
}
/* --------------------------------------------------------------------------------------------
* Modify the index to the specified value.
*/
void SetIndex(const Object & column);
public:
/* --------------------------------------------------------------------------------------------
* Default constructor (null).
*/
Column()
: m_Index(-1), m_Handle()
{
/* ... */
}
/* --------------------------------------------------------------------------------------------
* No column constructor.
*/
Column(const StmtRef & stmt)
: m_Index(-1), m_Handle(stmt)
{
/* ... */
}
/* --------------------------------------------------------------------------------------------
* Index constructor.
*/
Column(const StmtRef & stmt, Int32 idx)
: m_Index(idx), m_Handle(stmt)
{
SQMOD_VALIDATE_COLUMN(*this, m_Index);
}
/* --------------------------------------------------------------------------------------------
* Name constructor.
*/
Column(const StmtRef & stmt, CSStr name)
: m_Index(stmt ? stmt->GetColumnIndex(name) : -1), m_Handle(stmt)
{
SQMOD_VALIDATE_COLUMN(*this, m_Index);
}
/* --------------------------------------------------------------------------------------------
* Dynamic constructor.
*/
Column(const StmtRef & stmt, const Object & column)
: m_Index(-1), m_Handle(stmt)
{
if (!m_Handle)
{
STHROWF("Invalid SQLite statement reference");
}
// Extract the index
SetIndex(column);
}
/* --------------------------------------------------------------------------------------------
* Copy constructor.
*/
Column(const Column & o) = default;
/* --------------------------------------------------------------------------------------------
* Move constructor.
*/
Column(Column && o) = default;
/* --------------------------------------------------------------------------------------------
* Copy assignment operator.
*/
Column & operator = (const Column & o) = default;
/* --------------------------------------------------------------------------------------------
* Move assignment operator.
*/
Column & operator = (Column && o) = default;
/* --------------------------------------------------------------------------------------------
* Perform an equality comparison between two table column indexes.
*/
bool operator == (const Column & o) const
{
return (m_Index == o.m_Index);
}
/* --------------------------------------------------------------------------------------------
* Perform an inequality comparison between two table column indexes.
*/
bool operator != (const Column & o) const
{
return (m_Index != o.m_Index);
}
/* --------------------------------------------------------------------------------------------
* Implicit conversion to boolean for use in boolean operations.
*/
operator bool () const
{
return m_Index >= 0;
}
/* --------------------------------------------------------------------------------------------
* Used by the script engine to convert an instance of this type to a string.
*/
CSStr ToString() const
{
CSStr val = nullptr;
// Can we attempt to return the parameter name?
if (m_Handle && m_Index)
{
val = sqlite3_column_name(m_Handle->mPtr, m_Index);
}
else
{
val = ToStrF(_SC("%d"), m_Index);
}
// Return the value if valid
return val ? val : _SC("");
}
/* --------------------------------------------------------------------------------------------
* See whether the column is valid.
*/
bool IsValid() const
{
return m_Handle; // An invalid statement means an invalid column
}
/* --------------------------------------------------------------------------------------------
* Return the number of active references to the associated statement handle.
*/
Uint32 GetRefCount() const
{
return m_Handle.Count();
}
/* --------------------------------------------------------------------------------------------
* Retrieve the referenced column index.
*/
Int32 GetIndex() const
{
return m_Index;
}
/* --------------------------------------------------------------------------------------------
* Retrieve the referenced database statement.
*/
Object GetStatement() const;
/* --------------------------------------------------------------------------------------------
* Retrieve the referenced database connection.
*/
Object GetConnection() const;
/* --------------------------------------------------------------------------------------------
* Release the reference to the referenced database statement and column index.
*/
void Release()
{
m_Handle.Reset();
m_Index = -1;
}
/* --------------------------------------------------------------------------------------------
* Check whether the referenced column is null.
*/
bool IsNull() const;
/* --------------------------------------------------------------------------------------------
* Retrieve the name of the referenced column index.
*/
CSStr GetName() const;
/* --------------------------------------------------------------------------------------------
* Retrieve the column origin name if the library was compiled with such feature.
*/
CSStr GetOriginName() const;
/* --------------------------------------------------------------------------------------------
* Retrieve the type identifier of the referenced column index.
*/
Int32 GetType() const;
/* --------------------------------------------------------------------------------------------
* Retrieve the size in bytes of the referenced column index.
*/
Int32 GetBytes() const;
/* --------------------------------------------------------------------------------------------
* Retrieve the value inside the referenced column as a dynamic type.
*/
Object GetValue() const;
/* --------------------------------------------------------------------------------------------
* Retrieve the value inside the referenced column as a numeric type.
*/
Object GetNumber() const;
/* --------------------------------------------------------------------------------------------
* Retrieve the value inside the referenced column as a native script integer.
*/
SQInteger GetInteger() const;
/* --------------------------------------------------------------------------------------------
* Retrieve the value inside the referenced column as a native script floating point.
*/
SQFloat GetFloat() const;
/* --------------------------------------------------------------------------------------------
* Retrieve the value inside the referenced column as a long integer.
*/
Object GetLong() const;
/* --------------------------------------------------------------------------------------------
* Retrieve the value inside the referenced column as a string.
*/
Object GetString() const;
/* --------------------------------------------------------------------------------------------
* Retrieve the value inside the referenced column as a boolean.
*/
bool GetBoolean() const;
/* --------------------------------------------------------------------------------------------
* Retrieve the value inside the referenced column as a character.
*/
SQChar GetChar() const;
/* --------------------------------------------------------------------------------------------
* Retrieve the value inside the referenced column as a memory buffer.
*/
Object GetBuffer() const;
/* --------------------------------------------------------------------------------------------
* Retrieve the value inside the referenced column as a memory blob.
*/
Object GetBlob() const;
};
} // Namespace:: SqMod

View File

@@ -1,219 +0,0 @@
// ------------------------------------------------------------------------------------------------
#include "Library/SQLite/Common.hpp"
#include "Library/SQLite/Connection.hpp"
#include "Library/SQLite/Statement.hpp"
// ------------------------------------------------------------------------------------------------
namespace SqMod {
// ------------------------------------------------------------------------------------------------
Object GetConnectionObj(const ConnRef & conn)
{
return Object(new Connection(conn));
}
// ------------------------------------------------------------------------------------------------
Object GetStatementObj(const StmtRef & stmt)
{
return Object(new Statement(stmt));
}
// ------------------------------------------------------------------------------------------------
bool IsQueryEmpty(CSStr str)
{
// Is the pointer valid?
if (!str || *str == '\0')
{
return true;
}
// Currently processed character
SQChar c = 0;
// See if the query contains any alpha numeric characters
while ((c = *str) != 0)
{
if (std::isalnum(c) != 0)
{
return false;
}
++str;
}
// At this point we consider the query empty
return true;
}
// ------------------------------------------------------------------------------------------------
CSStr GetErrStr(Int32 status)
{
return sqlite3_errstr(status);
}
// ------------------------------------------------------------------------------------------------
void SetSoftHeapLimit(Int32 limit)
{
sqlite3_soft_heap_limit(limit);
}
// ------------------------------------------------------------------------------------------------
Int32 ReleaseMemory(Int32 bytes)
{
return sqlite3_release_memory(bytes);
}
// ------------------------------------------------------------------------------------------------
Object GetMemoryUsage()
{
// Obtain the initial stack size
const StackGuard sg;
// Push a long integer instance with the requested value on the stack
return Object(new SLongInt(sqlite3_memory_used()));
}
// ------------------------------------------------------------------------------------------------
Object GetMemoryHighwaterMark(bool reset)
{
// Obtain the initial stack size
const StackGuard sg;
// Push a long integer instance with the requested value on the stack
return Object(new SLongInt(sqlite3_memory_highwater(reset)));
}
// ------------------------------------------------------------------------------------------------
CSStr EscapeString(StackStrF & str)
{
// Is there even a string to escape?
if (str.mLen <= 0)
{
return _SC(""); // Default to empty string
}
// Attempt to escape the specified string
sqlite3_snprintf(GetTempBuffSize(), GetTempBuff(), "%q", str.mPtr);
// Return the resulted string
return GetTempBuff();
}
// ------------------------------------------------------------------------------------------------
CCStr EscapeStringEx(SQChar spec, StackStrF & str)
{
// Utility that allows changing the format specifier temporarily
static SQChar fs[] = _SC("%q");
// Validate the specified format specifier
if ((spec != 'q') && (spec != 'Q') && (spec != 'w') && (spec != 's'))
{
STHROWF("Unknown format specifier: '%c'", spec);
}
// Is there even a string to escape?
else if (!str.mLen)
{
return _SC(""); // Default to empty string
}
// Apply the format specifier
fs[1] = spec;
// Attempt to escape the specified string
sqlite3_snprintf(GetTempBuffSize(), GetTempBuff(), fs, str.mPtr);
// Restore the format specifier
fs[1] = 'q';
// Return the resulted string
return GetTempBuff();
}
// ------------------------------------------------------------------------------------------------
CCStr ArrayToQueryColumns(Array & arr)
{
// Do we even have any elements to process?
if (arr.Length() <= 0)
{
return _SC(""); // Default to empty string
}
// Allocate a vector with the required amount of column names
std::vector< String > values(arr.Length());
// Attempt to extract the array elements as strings
arr.GetArray< String >(&values[0], values.size());
// Used to know the position of the next column name
Uint32 offset = 0;
// Obtain the start of the array
auto itr = values.begin();
// Process all elements within range
for (; itr != values.end() && offset < GetTempBuffSize(); ++itr)
{
// Is the name valid?
if (itr->empty())
{
STHROWF("Invalid column name");
}
// Attempt to append the column name to the buffer
sqlite3_snprintf(static_cast< int >(GetTempBuffSize() - offset), GetTempBuff() + offset, "[%q], ", itr->c_str());
// Add the column name size to the offset
offset += itr->size();
// Also include the comma and space in the offset
offset += 2;
}
// Trim the last coma and space
if (offset >= 2)
{
GetTempBuff()[offset-2] = '\0';
}
else
{
GetTempBuff()[0] = '\0';
}
// Return the resulted string
return GetTempBuff();
}
// ------------------------------------------------------------------------------------------------
CCStr TableToQueryColumns(Table & tbl)
{
// Used to know the position of the next column name
Uint32 offset = 0;
// Used to obtain the column name temporarily
String name;
// Obtain the start of the table
Table::iterator itr;
// Process all elements within range
while (tbl.Next(itr))
{
// Use the element key as the column name
name.assign(itr.getName());
// Is the name valid?
if (name.empty())
{
STHROWF("Invalid or empty column name");
}
// Attempt to append the column name to the buffer
sqlite3_snprintf(static_cast< int >(GetTempBuffSize() - offset), GetTempBuff() + offset, "[%q], ", name.c_str());
// Add the column name size to the offset
offset += name.size();
// Also include the comma and space in the offset
offset += 2;
}
// Trim the last coma and space
if (offset >= 2)
{
GetTempBuff()[offset-2] = '\0';
}
else
{
GetTempBuff()[0] = '\0';
}
// Return the resulted string
return GetTempBuff();
}
// ================================================================================================
void Register_Common(Table & sqlns)
{
sqlns.Func(_SC("IsQueryEmpty"), &IsQueryEmpty)
.Func(_SC("GetErrStr"), &GetErrStr)
.Func(_SC("SetSoftHeapLimit"), &SetSoftHeapLimit)
.Func(_SC("ReleaseMemory"), &ReleaseMemory)
.Func(_SC("MemoryUsage"), &GetMemoryUsage)
.Func(_SC("MemoryHighwaterMark"), &GetMemoryHighwaterMark)
.Func(_SC("ArrayToQueryColumns"), &ArrayToQueryColumns)
.Func(_SC("TableToQueryColumns"), &TableToQueryColumns)
.FmtFunc(_SC("EscapeString"), &EscapeString)
.FmtFunc(_SC("EscapeStringEx"), &EscapeStringEx)
.FmtFunc(_SC("Escape"), &EscapeString)
.FmtFunc(_SC("EscapeEx"), &EscapeStringEx);
}
} // Namespace:: SqMod

View File

@@ -1,153 +0,0 @@
#pragma once
// ------------------------------------------------------------------------------------------------
#include "Base/Shared.hpp"
// ------------------------------------------------------------------------------------------------
#include "Library/Numeric/LongInt.hpp"
#include "Library/Utils/Buffer.hpp"
#include "Library/Chrono/Date.hpp"
#include "Library/Chrono/Datetime.hpp"
#include "Library/Chrono/Time.hpp"
#include "Library/Chrono/Timestamp.hpp"
// ------------------------------------------------------------------------------------------------
#include <sqlite3.h>
// ------------------------------------------------------------------------------------------------
namespace SqMod {
/* ------------------------------------------------------------------------------------------------
* Forward declarations.
*/
class Connection;
class Statement;
class Column;
class Transaction;
/* ------------------------------------------------------------------------------------------------
* SOFTWARE INFORMATION
*/
#define SQSQLITE_NAME "Squirrel SQLite Module"
#define SQSQLITE_AUTHOR "Sandu Liviu Catalin (S.L.C)"
#define SQSQLITE_COPYRIGHT "Copyright (C) 2018 Sandu Liviu Catalin"
#define SQSQLITE_HOST_NAME "SqModSQLiteHost"
#define SQSQLITE_VERSION 001
#define SQSQLITE_VERSION_STR "0.0.1"
#define SQSQLITE_VERSION_MAJOR 0
#define SQSQLITE_VERSION_MINOR 0
#define SQSQLITE_VERSION_PATCH 1
/* ------------------------------------------------------------------------------------------------
* Handle validation.
*/
#if defined(_DEBUG) || defined(SQMOD_EXCEPTLOC)
#define SQMOD_THROW_CURRENT(x, a) (x).ThrowCurrent(a, __FILE__, __LINE__)
#define SQMOD_VALIDATE(x) (x).Validate(__FILE__, __LINE__)
#define SQMOD_VALIDATE_CREATED(x) (x).ValidateCreated(__FILE__, __LINE__)
#define SQMOD_VALIDATE_PARAM(x, i) (x).ValidateParam((i), __FILE__, __LINE__)
#define SQMOD_VALIDATE_COLUMN(x, i) (x).ValidateColumn((i), __FILE__, __LINE__)
#define SQMOD_VALIDATE_ROW(x) (x).ValidateRow(__FILE__, __LINE__)
#define SQMOD_GET_VALID(x) (x).GetValid(__FILE__, __LINE__)
#define SQMOD_GET_CREATED(x) (x).GetCreated(__FILE__, __LINE__)
#else
#define SQMOD_THROW_CURRENT(x, a) (x).ThrowCurrent(a)
#define SQMOD_VALIDATE(x) (x).Validate()
#define SQMOD_VALIDATE_CREATED(x) (x).ValidateCreated()
#define SQMOD_VALIDATE_PARAM(x, i) (x).ValidateParam((i))
#define SQMOD_VALIDATE_COLUMN(x, i) (x).ValidateColumn((i))
#define SQMOD_VALIDATE_ROW(x) (x).ValidateRow()
#define SQMOD_GET_VALID(x) (x).GetValid()
#define SQMOD_GET_CREATED(x) (x).GetCreated()
#endif // _DEBUG
/* ------------------------------------------------------------------------------------------------
* Helper macros for architecture differences.
*/
#ifdef _SQ64
#define sqlite3_bind_integer sqlite3_bind_int64
#define sqlite3_column_integer sqlite3_column_int64
#else
#define sqlite3_bind_integer sqlite3_bind_int
#define sqlite3_column_integer sqlite3_column_int
#endif
/* ------------------------------------------------------------------------------------------------
* Forward declarations.
*/
struct ConnHnd;
struct StmtHnd;
/* ------------------------------------------------------------------------------------------------
* Common typedefs.
*/
typedef SharedPtr< ConnHnd > ConnRef;
typedef SharedPtr< StmtHnd > StmtRef;
/* ------------------------------------------------------------------------------------------------
* Obtain a script object from a connection handle. (meant to avoid having to include the header)
*/
Object GetConnectionObj(const ConnRef & conn);
/* ------------------------------------------------------------------------------------------------
* Obtain a script object from a statement handle. (meant to avoid having to include the header)
*/
Object GetStatementObj(const StmtRef & stmt);
/* ------------------------------------------------------------------------------------------------
* Generate a formatted query.
*/
CSStr QFmtStr(CSStr str, ...);
/* ------------------------------------------------------------------------------------------------
* Tests if a certain query string is empty.
*/
bool IsQueryEmpty(CSStr str);
/* ------------------------------------------------------------------------------------------------
* Retrieve the string representation of a certain status code.
*/
CSStr GetErrStr(Int32 status);
/* ------------------------------------------------------------------------------------------------
* Set a specific heap limit.
*/
void SetSoftHeapLimit(Int32 limit);
/* ------------------------------------------------------------------------------------------------
* Release the specified amount of memory.
*/
Int32 ReleaseMemory(Int32 bytes);
/* ------------------------------------------------------------------------------------------------
* Retrieve the current memory usage.
*/
Object GetMemoryUsage();
/* ------------------------------------------------------------------------------------------------
* Retrieve the memory high watermark.
*/
Object GetMemoryHighwaterMark(bool reset);
/* ------------------------------------------------------------------------------------------------
* Retrieve the escaped version of the specified string.
*/
CSStr EscapeString(StackStrF & str);
/* ------------------------------------------------------------------------------------------------
* Retrieve the escaped version of the specified string using the supplied format specifier.
*/
CCStr EscapeStringEx(SQChar spec, StackStrF & str);
/* ------------------------------------------------------------------------------------------------
* Convert the values from the specified array to a list of column names string.
*/
CCStr ArrayToQueryColumns(Array & arr);
/* ------------------------------------------------------------------------------------------------
* Convert the keys from the specified array to a list of column names string.
*/
CCStr TableToQueryColumns(Table & tbl);
} // Namespace:: SqMod

View File

@@ -1,407 +0,0 @@
// ------------------------------------------------------------------------------------------------
#include "Library/SQLite/Connection.hpp"
#include "Library/SQLite/Statement.hpp"
// ------------------------------------------------------------------------------------------------
namespace SqMod {
// ------------------------------------------------------------------------------------------------
SQMODE_DECL_TYPENAME(Typename, _SC("SqLiteConnection"))
// ------------------------------------------------------------------------------------------------
void Connection::TraceOutput(void * /*ptr*/, CCStr sql)
{
LogInf("SQLite Trace: %s", sql);
}
// ------------------------------------------------------------------------------------------------
void Connection::ProfileOutput(void * /*ptr*/, CCStr sql, sqlite3_uint64 time)
{
LogInf("SQLite profile (time: %llu): %s", time, sql);
}
// ------------------------------------------------------------------------------------------------
#if defined(_DEBUG) || defined(SQMOD_EXCEPTLOC)
void Connection::Validate(CCStr file, Int32 line) const
{
if (!m_Handle)
{
SqThrowF("Invalid SQLite connection reference =>[%s:%d]", file, line);
}
}
#else
void Connection::Validate() const
{
if (!m_Handle)
{
SqThrowF("Invalid SQLite connection reference");
}
}
#endif // _DEBUG
// ------------------------------------------------------------------------------------------------
#if defined(_DEBUG) || defined(SQMOD_EXCEPTLOC)
void Connection::ValidateCreated(CCStr file, Int32 line) const
{
if (!m_Handle)
{
SqThrowF("Invalid SQLite connection reference =>[%s:%d]", file, line);
}
else if (m_Handle->mPtr == nullptr)
{
SqThrowF("Invalid SQLite connection =>[%s:%d]", file, line);
}
}
#else
void Connection::ValidateCreated() const
{
if (!m_Handle)
{
SqThrowF("Invalid SQLite connection reference");
}
else if (m_Handle->mPtr == nullptr)
{
SqThrowF("Invalid SQLite connection");
}
}
#endif // _DEBUG
// ------------------------------------------------------------------------------------------------
#if defined(_DEBUG) || defined(SQMOD_EXCEPTLOC)
const ConnRef & Connection::GetValid(CCStr file, Int32 line) const
{
Validate(file, line);
return m_Handle;
}
#else
const ConnRef & Connection::GetValid() const
{
Validate();
return m_Handle;
}
#endif // _DEBUG
// ------------------------------------------------------------------------------------------------
#if defined(_DEBUG) || defined(SQMOD_EXCEPTLOC)
const ConnRef & Connection::GetCreated(CCStr file, Int32 line) const
{
ValidateCreated(file, line);
return m_Handle;
}
#else
const ConnRef & Connection::GetCreated() const
{
ValidateCreated();
return m_Handle;
}
#endif // _DEBUG
// ------------------------------------------------------------------------------------------------
void Connection::Open(StackStrF & name)
{
// Should we create a connection handle?
if (!m_Handle)
{
m_Handle = ConnRef(new ConnHnd());
}
// Make sure another database isn't opened
if (SQMOD_GET_VALID(*this)->mPtr != nullptr)
{
STHROWF("Already referencing a valid database connection");
}
// Effing signed/unsigned warnings everywhere. I just need it to shut up.
constexpr unsigned OPEN_READWRITE_F = SQLITE_OPEN_READWRITE;
constexpr unsigned OPEN_CREATE_F = SQLITE_OPEN_CREATE;
// Perform the requested operation
m_Handle->Create(name.mPtr, OPEN_READWRITE_F | OPEN_CREATE_F, nullptr);
}
// ------------------------------------------------------------------------------------------------
void Connection::Open(StackStrF & name, Int32 flags)
{
// Should we create a connection handle?
if (!m_Handle)
{
m_Handle = ConnRef(new ConnHnd());
}
// Make sure another database isn't opened
if (SQMOD_GET_VALID(*this)->mPtr != nullptr)
{
STHROWF("Already referencing a valid database connection");
}
// Perform the requested operation
m_Handle->Create(name.mPtr, flags, nullptr);
}
// ------------------------------------------------------------------------------------------------
void Connection::Open(StackStrF & name, Int32 flags, StackStrF & vfs)
{
// Should we create a connection handle?
if (!m_Handle)
{
m_Handle = ConnRef(new ConnHnd());
}
// Make sure another database isn't opened
if (SQMOD_GET_VALID(*this)->mPtr != nullptr)
{
STHROWF("Already referencing a valid database connection");
}
// Perform the requested operation
m_Handle->Create(name.mPtr, flags, vfs.mPtr);
}
// ------------------------------------------------------------------------------------------------
Int32 Connection::Exec(StackStrF & str)
{
SQMOD_VALIDATE_CREATED(*this);
// Attempt to execute the specified query
m_Handle->mStatus = sqlite3_exec(m_Handle->mPtr, str.mPtr, nullptr, nullptr, nullptr);
// Validate the execution result
if (m_Handle->mStatus != SQLITE_OK)
{
STHROWF("Unable to execute query [%s]", m_Handle->ErrMsg());
}
// Return rows affected by this query
return sqlite3_changes(m_Handle->mPtr);
}
// ------------------------------------------------------------------------------------------------
Object Connection::Query(StackStrF & str) const
{
SQMOD_VALIDATE_CREATED(*this);
// Return the requested information
return Object(new Statement(m_Handle, str));
}
// ------------------------------------------------------------------------------------------------
void Connection::Queue(StackStrF & str)
{
SQMOD_VALIDATE(*this);
// Is there a query to commit?
if (!str.mLen || IsQueryEmpty(str.mPtr))
{
STHROWF("No query string to queue");
}
// Add the specified string to the queue
m_Handle->mQueue.emplace_back(str.mPtr, str.mLen);
}
// ------------------------------------------------------------------------------------------------
bool Connection::IsReadOnly() const
{
// Request the desired information
const int result = sqlite3_db_readonly(SQMOD_GET_CREATED(*this)->mPtr, "main");
// Verify the result
if (result == -1)
{
STHROWF("'main' is not the name of a database on connection");
}
// Return the requested information
return (result != 1);
}
// ------------------------------------------------------------------------------------------------
bool Connection::TableExists(StackStrF & name) const
{
StackStrF query("SELECT count(*) FROM [sqlite_master] WHERE [type]='table' AND [name]=?");
// Prepare a statement to inspect the master table
Statement stmt(SQMOD_GET_CREATED(*this), query);
// Could the statement be created?
if (stmt.IsValid())
{
// Bind the specified name onto the statement parameter
Parameter(stmt.GetHandle(), 1).SetString(name);
// Attempt to step the statement and obtain a value
if (stmt.Step())
{
return (sqlite3_column_int(stmt, 0) == 1);
}
}
// Assume it doesn't exist
return false;
}
// ------------------------------------------------------------------------------------------------
void Connection::SetTracing(bool toggle)
{
// Check whether changes are necessary
if (SQMOD_GET_CREATED(*this)->mTrace == toggle)
{
return; // No point in proceeding
}
// Do we have to disable it?
else if (m_Handle->mTrace)
{
sqlite3_trace(m_Handle->mPtr, nullptr, nullptr);
}
// Go ahead and enable tracing
else
{
sqlite3_trace(m_Handle->mPtr, &Connection::TraceOutput, nullptr);
}
}
// ------------------------------------------------------------------------------------------------
void Connection::SetProfiling(bool toggle)
{
// Check whether changes are necessary
if (SQMOD_GET_CREATED(*this)->mProfile == toggle)
{
return; // No point in proceeding
}
// Do we have to disable it?
else if (m_Handle->mProfile)
{
sqlite3_profile(m_Handle->mPtr, nullptr, nullptr);
}
// Go ahead and enable profiling
else
{
sqlite3_profile(m_Handle->mPtr, &Connection::ProfileOutput, nullptr);
}
}
// ------------------------------------------------------------------------------------------------
void Connection::SetBusyTimeout(Int32 millis)
{
SQMOD_VALIDATE_CREATED(*this);
// Apply the requested timeout
if ((m_Handle->mStatus = sqlite3_busy_timeout(m_Handle->mPtr, millis)) != SQLITE_OK)
{
STHROWF("Unable to set busy timeout [%s]", m_Handle->ErrMsg());
}
}
// ------------------------------------------------------------------------------------------------
Int32 Connection::GetInfo(Int32 operation, bool highwater, bool reset)
{
// Where to retrieve the information
Int32 cur_value;
Int32 hiwtr_value;
// Attempt to retrieve the specified information
if ((m_Handle->mStatus = sqlite3_db_status(SQMOD_GET_CREATED(*this)->mPtr, operation, &cur_value, &hiwtr_value, reset)) != SQLITE_OK)
{
STHROWF("Unable to get runtime status information", m_Handle->ErrMsg());
}
// Return the high-water value if requested
else if (highwater)
{
return hiwtr_value;
}
// Return the requested information
return cur_value;
}
// ------------------------------------------------------------------------------------------------
void Connection::ReserveQueue(Uint32 num)
{
SQMOD_VALIDATE(*this);
// Perform the requested operation
m_Handle->mQueue.reserve(m_Handle->mQueue.size() + num);
}
// ------------------------------------------------------------------------------------------------
void Connection::PopQueue()
{
SQMOD_VALIDATE(*this);
// Perform the requested operation
if (!SQMOD_GET_VALID(*this)->mQueue.empty())
{
m_Handle->mQueue.pop_back();
}
}
// ------------------------------------------------------------------------------------------------
Int32 Connection::Flush()
{
SQMOD_VALIDATE_CREATED(*this);
// Perform the requested operation
return m_Handle->Flush(m_Handle->mQueue.size(), NullObject(), NullFunction());
}
// ------------------------------------------------------------------------------------------------
Int32 Connection::Flush(SQInteger num)
{
SQMOD_VALIDATE_CREATED(*this);
// Perform the requested operation
return m_Handle->Flush(ConvTo< Uint32 >::From(num), NullObject(), NullFunction());
}
// ------------------------------------------------------------------------------------------------
Int32 Connection::Flush(Object & env, Function & func)
{
SQMOD_VALIDATE_CREATED(*this);
// Perform the requested operation
return m_Handle->Flush(m_Handle->mQueue.size(), env, func);
}
// ------------------------------------------------------------------------------------------------
Int32 Connection::Flush(SQInteger num, Object & env, Function & func)
{
SQMOD_VALIDATE_CREATED(*this);
// Perform the requested operation
return m_Handle->Flush(ConvTo< Uint32 >::From(num), env, func);
}
// ================================================================================================
void Register_Connection(Table & sqlns)
{
sqlns.Bind(_SC("Connection"),
Class< Connection >(sqlns.GetVM(), Typename::Str)
// Constructors
.Ctor()
.Ctor< StackStrF & >()
.Ctor< StackStrF &, Int32 >()
.Ctor< StackStrF &, Int32, StackStrF & >()
// Meta-methods
.SquirrelFunc(_SC("_typename"), &Typename::Fn)
.Func(_SC("_tostring"), &Connection::ToString)
// Properties
.Prop(_SC("IsValid"), &Connection::IsValid)
.Prop(_SC("Connected"), &Connection::IsConnected)
.Prop(_SC("References"), &Connection::GetRefCount)
.Prop(_SC("Status"), &Connection::GetStatus)
.Prop(_SC("Flags"), &Connection::GetFlags)
.Prop(_SC("Name"), &Connection::GetName)
.Prop(_SC("VFS"), &Connection::GetVFS)
.Prop(_SC("ErrCode"), &Connection::GetErrorCode)
.Prop(_SC("ExErrCode"), &Connection::GetExtendedErrorCode)
.Prop(_SC("ExtendedErrCode"), &Connection::GetExtendedErrorCode)
.Prop(_SC("ErrStr"), &Connection::GetErrStr)
.Prop(_SC("ErrMsg"), &Connection::GetErrMsg)
.Prop(_SC("ReadOnly"), &Connection::IsReadOnly)
.Prop(_SC("Autocommit"), &Connection::GetAutoCommit)
.Prop(_SC("LastInsertRowId"), &Connection::GetLastInsertRowID)
.Prop(_SC("Changes"), &Connection::GetChanges)
.Prop(_SC("TotalChanges"), &Connection::GetTotalChanges)
.Prop(_SC("Trace"), &Connection::GetTracing, &Connection::SetTracing)
.Prop(_SC("Profile"), &Connection::GetProfiling, &Connection::SetProfiling)
.Prop(_SC("QueueSize"), &Connection::QueueSize)
// Member Methods
.Func(_SC("Release"), &Connection::Release)
.FmtFunc(_SC("Exec"), &Connection::Exec)
.FmtFunc(_SC("Queue"), &Connection::Queue)
.FmtFunc(_SC("Query"), &Connection::Query)
.FmtFunc(_SC("TableExists"), &Connection::TableExists)
.Func(_SC("InterruptOperation"), &Connection::InterruptOperation)
.Func(_SC("SetBusyTimeout"), &Connection::SetBusyTimeout)
.Func(_SC("ReleaseMemory"), &Connection::ReleaseMemory)
.Func(_SC("ReserveQueue"), &Connection::ReserveQueue)
.Func(_SC("CompactQueue"), &Connection::CompactQueue)
.Func(_SC("ClearQueue"), &Connection::ClearQueue)
.Func(_SC("PopQueue"), &Connection::PopQueue)
// Member Overloads
.Overload< void (Connection::*)(StackStrF &) >(_SC("Open"), &Connection::Open)
.Overload< void (Connection::*)(StackStrF &, Int32) >(_SC("Open"), &Connection::Open)
.Overload< void (Connection::*)(StackStrF &, Int32, StackStrF &) >(_SC("Open"), &Connection::Open)
.Overload< Int32 (Connection::*)(Int32) >(_SC("GetInfo"), &Connection::GetInfo)
.Overload< Int32 (Connection::*)(Int32, bool) >(_SC("GetInfo"), &Connection::GetInfo)
.Overload< Int32 (Connection::*)(Int32, bool, bool) >(_SC("GetInfo"), &Connection::GetInfo)
.Overload< Int32 (Connection::*)(void) >(_SC("Flush"), &Connection::Flush)
.Overload< Int32 (Connection::*)(SQInteger) >(_SC("Flush"), &Connection::Flush)
.Overload< Int32 (Connection::*)(Object &, Function &) >(_SC("Flush"), &Connection::Flush)
.Overload< Int32 (Connection::*)(SQInteger, Object &, Function &) >(_SC("Flush"), &Connection::Flush)
);
}
} // Namespace:: SqMod

View File

@@ -1,481 +0,0 @@
#pragma once
// ------------------------------------------------------------------------------------------------
#include "Library/SQLite/Handle.hpp"
// ------------------------------------------------------------------------------------------------
#include <utility>
// ------------------------------------------------------------------------------------------------
namespace SqMod {
/* ------------------------------------------------------------------------------------------------
* Used to manage and interact with a database connection.
*/
class Connection
{
private:
// --------------------------------------------------------------------------------------------
ConnRef m_Handle; // Reference to the managed connection.
protected:
/* --------------------------------------------------------------------------------------------
* Callback function for ActivateTracing()
*/
static void TraceOutput(void * ptr, CCStr sql);
/* --------------------------------------------------------------------------------------------
* Callback function for ActivateProfiling()
*/
static void ProfileOutput(void * ptr, CCStr sql, sqlite3_uint64 time);
/* --------------------------------------------------------------------------------------------
* Validate the managed connection handle and throw an error if invalid.
*/
#if defined(_DEBUG) || defined(SQMOD_EXCEPTLOC)
void Validate(CCStr file, Int32 line) const;
#else
void Validate() const;
#endif // _DEBUG
/* --------------------------------------------------------------------------------------------
* Validate the managed connection handle and throw an error if invalid.
*/
#if defined(_DEBUG) || defined(SQMOD_EXCEPTLOC)
void ValidateCreated(CCStr file, Int32 line) const;
#else
void ValidateCreated() const;
#endif // _DEBUG
/* --------------------------------------------------------------------------------------------
* Validate the managed connection handle and throw an error if invalid.
*/
#if defined(_DEBUG) || defined(SQMOD_EXCEPTLOC)
const ConnRef & GetValid(CCStr file, Int32 line) const;
#else
const ConnRef & GetValid() const;
#endif // _DEBUG
/* --------------------------------------------------------------------------------------------
* Validate the managed connection handle and throw an error if invalid.
*/
#if defined(_DEBUG) || defined(SQMOD_EXCEPTLOC)
const ConnRef & GetCreated(CCStr file, Int32 line) const;
#else
const ConnRef & GetCreated() const;
#endif // _DEBUG
public:
/* --------------------------------------------------------------------------------------------
* Attempt to open the specified database.
*/
Connection()
: m_Handle()
{
/* ... */
}
/* --------------------------------------------------------------------------------------------
* Explicit constructor.
*/
explicit Connection(StackStrF & name)
: m_Handle(new ConnHnd())
{
// Effing signed/unsigned warnings everywhere. I just need it to shut up.
constexpr unsigned OPEN_READWRITE_F = SQLITE_OPEN_READWRITE;
constexpr unsigned OPEN_CREATE_F = SQLITE_OPEN_CREATE;
SQMOD_GET_VALID(*this)->Create(name.mPtr, OPEN_READWRITE_F | OPEN_CREATE_F, nullptr);
}
/* --------------------------------------------------------------------------------------------
* Explicit constructor.
*/
Connection(StackStrF & name, Int32 flags)
: m_Handle(new ConnHnd())
{
SQMOD_GET_VALID(*this)->Create(name.mPtr, flags, nullptr);
}
/* --------------------------------------------------------------------------------------------
* Explicit constructor.
*/
Connection(StackStrF & name, Int32 flags, StackStrF & vfs)
: m_Handle(new ConnHnd())
{
SQMOD_GET_VALID(*this)->Create(name.mPtr, flags, vfs.mPtr);
}
/* --------------------------------------------------------------------------------------------
* Direct handle constructor.
*/
explicit Connection(ConnRef c)
: m_Handle(std::move(c))
{
/* ... */
}
/* --------------------------------------------------------------------------------------------
* Copy constructor.
*/
Connection(const Connection & o) = default;
/* --------------------------------------------------------------------------------------------
* Move constructor.
*/
Connection(Connection && o) = default;
/* --------------------------------------------------------------------------------------------
* Copy assignment operator.
*/
Connection & operator = (const Connection & o) = default;
/* --------------------------------------------------------------------------------------------
* Move assignment operator.
*/
Connection & operator = (Connection && o) = default;
/* --------------------------------------------------------------------------------------------
* Perform an equality comparison between two connections.
*/
bool operator == (const Connection & o) const
{
return (m_Handle == o.m_Handle);
}
/* --------------------------------------------------------------------------------------------
* Perform an inequality comparison between two connections.
*/
bool operator != (const Connection & o) const
{
return (m_Handle != o.m_Handle);
}
/* --------------------------------------------------------------------------------------------
* Implicit conversion to the raw connection handle.
*/
operator sqlite3 * () //NOLINT (intentionally implicit)
{
return m_Handle ? m_Handle->mPtr : nullptr;
}
/* --------------------------------------------------------------------------------------------
* Implicit conversion to the raw connection handle.
*/
operator sqlite3 * () const //NOLINT (intentionally implicit)
{
return m_Handle ? m_Handle->mPtr : nullptr;
}
/* --------------------------------------------------------------------------------------------
* Used by the script engine to convert an instance of this type to a string.
*/
const String & ToString() const
{
return m_Handle ? m_Handle->mName : NullString();
}
/* --------------------------------------------------------------------------------------------
* Retrieve the associated connection handle.
*/
const ConnRef & GetHandle() const
{
return m_Handle;
}
/* --------------------------------------------------------------------------------------------
* See whether the managed connection handle is valid.
*/
bool IsValid() const
{
return m_Handle;
}
/* --------------------------------------------------------------------------------------------
* See whether the managed connection handle was connected.
*/
bool IsConnected() const
{
return m_Handle && (m_Handle->mPtr != nullptr);
}
/* --------------------------------------------------------------------------------------------
* Return the number of active references to this connection handle.
*/
Uint32 GetRefCount() const
{
return m_Handle.Count();
}
/* --------------------------------------------------------------------------------------------
* Release the reference to the associated database connection.
*/
void Release()
{
m_Handle.Reset();
}
/* --------------------------------------------------------------------------------------------
* Retrieve the last received status code.
*/
Int32 GetStatus() const
{
return SQMOD_GET_VALID(*this)->mStatus;
}
/* --------------------------------------------------------------------------------------------
* Retrieve the flags used to create this database connection.
*/
Int32 GetFlags() const
{
return SQMOD_GET_VALID(*this)->mFlags;
}
/* --------------------------------------------------------------------------------------------
* Retrieve the name used to create this database connection.
*/
const String & GetName() const
{
return SQMOD_GET_VALID(*this)->mName;
}
/* --------------------------------------------------------------------------------------------
* Retrieve the virtual file system used to create this database connection.
*/
const String & GetVFS() const
{
return SQMOD_GET_VALID(*this)->mVFS;
}
/* --------------------------------------------------------------------------------------------
* Return the numeric result code for the most recent failed API call (if any).
*/
Int32 GetErrorCode() const
{
return SQMOD_GET_VALID(*this)->ErrNo();
}
/* --------------------------------------------------------------------------------------------
* Return the extended numeric result code for the most recent failed API call (if any).
*/
Int32 GetExtendedErrorCode() const
{
return SQMOD_GET_VALID(*this)->ExErrNo();
}
/* --------------------------------------------------------------------------------------------
* Retrieve the message of the last received error code.
*/
CSStr GetErrStr() const
{
return SQMOD_GET_VALID(*this)->ErrStr();
}
/* --------------------------------------------------------------------------------------------
* Return the last error message associated with this database connection.
*/
CSStr GetErrMsg() const
{
return SQMOD_GET_VALID(*this)->ErrMsg();
}
/* --------------------------------------------------------------------------------------------
* Attempt to open the specified database.
*/
void Open(StackStrF & name);
/* --------------------------------------------------------------------------------------------
* Attempt to open the specified database.
*/
void Open(StackStrF & name, Int32 flags);
/* --------------------------------------------------------------------------------------------
* Attempt to open the specified database.
*/
void Open(StackStrF & name, Int32 flags, StackStrF & vfs);
/* --------------------------------------------------------------------------------------------
* Attempt to execute the specified query.
*/
Int32 Exec(StackStrF & str);
/* --------------------------------------------------------------------------------------------
* Attempt to queue the specified query.
*/
void Queue(StackStrF & str);
/* --------------------------------------------------------------------------------------------
* Attempt to create a statement from the specified query.
*/
Object Query(StackStrF & str) const;
/* --------------------------------------------------------------------------------------------
* See if the database connection was opened in read-only mode.
*/
bool IsReadOnly() const;
/* --------------------------------------------------------------------------------------------
* Shortcut to test if a table exists.
*/
bool TableExists(StackStrF & name) const;
/* --------------------------------------------------------------------------------------------
* See if the database connection is or is not in auto-commit mode.
*/
bool GetAutoCommit() const
{
return sqlite3_get_autocommit(SQMOD_GET_CREATED(*this)->mPtr);
}
/* --------------------------------------------------------------------------------------------
* Get the row-id of the most recent successful INSERT into the database from the current connection.
*/
Object GetLastInsertRowID() const
{
return Object(new SLongInt(sqlite3_last_insert_rowid(SQMOD_GET_CREATED(*this)->mPtr)));
}
/* --------------------------------------------------------------------------------------------
* Returns the number of database rows that were changed, inserted or deleted
* by the most recently completed SQL statement.
*/
Int32 GetChanges() const
{
return sqlite3_changes(SQMOD_GET_CREATED(*this)->mPtr);
}
/* --------------------------------------------------------------------------------------------
* Returns the total number of row changes caused by INSERT, UPDATE or DELETE statements
* since the database connection was opened.
*/
Int32 GetTotalChanges() const
{
return sqlite3_total_changes(SQMOD_GET_CREATED(*this)->mPtr);
}
/* --------------------------------------------------------------------------------------------
* See if this database connection has tracing enabled.
*/
bool GetTracing() const
{
return SQMOD_GET_VALID(*this)->mTrace;
}
/* --------------------------------------------------------------------------------------------
* Activate or deactivate tracing on this database connection.
*/
void SetTracing(bool toggle);
/* --------------------------------------------------------------------------------------------
* See if this database connection has profiling enabled.
*/
bool GetProfiling() const
{
return SQMOD_GET_VALID(*this)->mProfile;
}
/* --------------------------------------------------------------------------------------------
* Activate or deactivate profiling on this database connection.
*/
void SetProfiling(bool toggle);
/* --------------------------------------------------------------------------------------------
* Set a busy handler that sleeps for a specified amount of time when a table is locked.
*/
void SetBusyTimeout(Int32 millis);
/* --------------------------------------------------------------------------------------------
* Causes any pending database operation to abort and return at its earliest opportunity.
*/
void InterruptOperation() const
{
sqlite3_interrupt(SQMOD_GET_CREATED(*this)->mPtr);
}
/* --------------------------------------------------------------------------------------------
* Attempts to free as much heap memory as possible from the database connection.
*/
void ReleaseMemory() const
{
sqlite3_db_release_memory(SQMOD_GET_CREATED(*this)->mPtr);
}
/* --------------------------------------------------------------------------------------------
* Returns internal runtime status information associated with the current database connection.
*/
Int32 GetInfo(Int32 operation)
{
return GetInfo(operation, false, false);
}
/* --------------------------------------------------------------------------------------------
* Returns internal runtime status information associated with the current database connection.
*/
Int32 GetInfo(Int32 operation, bool highwater)
{
return GetInfo(operation, highwater, false);
}
/* --------------------------------------------------------------------------------------------
* Returns internal runtime status information associated with the current database connection.
*/
Int32 GetInfo(Int32 operation, bool highwater, bool reset);
/* --------------------------------------------------------------------------------------------
* Retrieve the number of queries in the queue.
*/
Uint32 QueueSize() const
{
return ConvTo< Uint32 >::From(SQMOD_GET_VALID(*this)->mQueue.size());
}
/* --------------------------------------------------------------------------------------------
* Reserve space upfront for the specified amount of queries in the query queue.
*/
void ReserveQueue(Uint32 num);
/* --------------------------------------------------------------------------------------------
* Release memory that is not occupied from the query queue.
*/
void CompactQueue()
{
SQMOD_GET_VALID(*this)->mQueue.shrink_to_fit();
}
/* --------------------------------------------------------------------------------------------
* Remove all queries from the queue without executing them.
*/
void ClearQueue()
{
SQMOD_GET_VALID(*this)->mQueue.clear();
}
/* --------------------------------------------------------------------------------------------
* Remove the last query from the queue.
*/
void PopQueue();
/* --------------------------------------------------------------------------------------------
* Flush all queries from the queue.
*/
Int32 Flush();
/* --------------------------------------------------------------------------------------------
* Flush a specific amount of queries from the queue.
*/
Int32 Flush(SQInteger num);
/* --------------------------------------------------------------------------------------------
* Flush all queries from the queue and handle errors manually.
*/
Int32 Flush(Object & env, Function & func);
/* --------------------------------------------------------------------------------------------
* Flush a specific amount of queries from the queue and handle errors manually.
*/
Int32 Flush(SQInteger num, Object & env, Function & func);
};
} // Namespace:: SqMod

View File

@@ -1,367 +0,0 @@
// ------------------------------------------------------------------------------------------------
#include "Library/SQLite/Common.hpp"
// ------------------------------------------------------------------------------------------------
namespace SqMod {
/* ------------------------------------------------------------------------------------------------
* Helper class that represents an integral enumeration value. Used to reduce compilation times.
*/
struct EnumElement
{
CSStr Name;
Int32 Value;
};
// ------------------------------------------------------------------------------------------------
static const EnumElement g_MainEnum[] = {
{_SC("ABORT"), SQLITE_ABORT},
{_SC("ABORT_ROLLBACK"), SQLITE_ABORT_ROLLBACK},
{_SC("ACCESS_EXISTS"), SQLITE_ACCESS_EXISTS},
{_SC("ACCESS_READ"), SQLITE_ACCESS_READ},
{_SC("ACCESS_READWRITE"), SQLITE_ACCESS_READWRITE},
{_SC("ALTER_TABLE"), SQLITE_ALTER_TABLE},
{_SC("ANALYZE"), SQLITE_ANALYZE},
{_SC("ANY"), SQLITE_ANY},
{_SC("ATTACH"), SQLITE_ATTACH},
{_SC("AUTH"), SQLITE_AUTH},
{_SC("AUTH_USER"), SQLITE_AUTH_USER},
{_SC("BLOB"), SQLITE_BLOB},
{_SC("BUSY"), SQLITE_BUSY},
{_SC("BUSY_RECOVERY"), SQLITE_BUSY_RECOVERY},
{_SC("BUSY_SNAPSHOT"), SQLITE_BUSY_SNAPSHOT},
{_SC("CANTOPEN"), SQLITE_CANTOPEN},
{_SC("CANTOPEN_CONVPATH"), SQLITE_CANTOPEN_CONVPATH},
{_SC("CANTOPEN_FULLPATH"), SQLITE_CANTOPEN_FULLPATH},
{_SC("CANTOPEN_ISDIR"), SQLITE_CANTOPEN_ISDIR},
{_SC("CANTOPEN_NOTEMPDIR"), SQLITE_CANTOPEN_NOTEMPDIR},
{_SC("CHECKPOINT_FULL"), SQLITE_CHECKPOINT_FULL},
{_SC("CHECKPOINT_PASSIVE"), SQLITE_CHECKPOINT_PASSIVE},
{_SC("CHECKPOINT_RESTART"), SQLITE_CHECKPOINT_RESTART},
{_SC("CHECKPOINT_TRUNCATE"), SQLITE_CHECKPOINT_TRUNCATE},
{_SC("CONFIG_COVERING_INDEX_SCAN"), SQLITE_CONFIG_COVERING_INDEX_SCAN},
{_SC("CONFIG_GETMALLOC"), SQLITE_CONFIG_GETMALLOC},
{_SC("CONFIG_GETMUTEX"), SQLITE_CONFIG_GETMUTEX},
{_SC("CONFIG_GETPCACHE"), SQLITE_CONFIG_GETPCACHE},
{_SC("CONFIG_GETPCACHE2"), SQLITE_CONFIG_GETPCACHE2},
{_SC("CONFIG_HEAP"), SQLITE_CONFIG_HEAP},
{_SC("CONFIG_LOG"), SQLITE_CONFIG_LOG},
{_SC("CONFIG_LOOKASIDE"), SQLITE_CONFIG_LOOKASIDE},
{_SC("CONFIG_MALLOC"), SQLITE_CONFIG_MALLOC},
{_SC("CONFIG_MEMSTATUS"), SQLITE_CONFIG_MEMSTATUS},
{_SC("CONFIG_MMAP_SIZE"), SQLITE_CONFIG_MMAP_SIZE},
{_SC("CONFIG_MULTITHREAD"), SQLITE_CONFIG_MULTITHREAD},
{_SC("CONFIG_MUTEX"), SQLITE_CONFIG_MUTEX},
{_SC("CONFIG_PAGECACHE"), SQLITE_CONFIG_PAGECACHE},
{_SC("CONFIG_PCACHE"), SQLITE_CONFIG_PCACHE},
{_SC("CONFIG_PCACHE2"), SQLITE_CONFIG_PCACHE2},
{_SC("CONFIG_PCACHE_HDRSZ"), SQLITE_CONFIG_PCACHE_HDRSZ},
{_SC("CONFIG_PMASZ"), SQLITE_CONFIG_PMASZ},
{_SC("CONFIG_SCRATCH"), SQLITE_CONFIG_SCRATCH},
{_SC("CONFIG_SERIALIZED"), SQLITE_CONFIG_SERIALIZED},
{_SC("CONFIG_SINGLETHREAD"), SQLITE_CONFIG_SINGLETHREAD},
{_SC("CONFIG_SQLLOG"), SQLITE_CONFIG_SQLLOG},
{_SC("CONFIG_URI"), SQLITE_CONFIG_URI},
{_SC("CONFIG_WIN32_HEAPSIZE"), SQLITE_CONFIG_WIN32_HEAPSIZE},
{_SC("CONSTRAINT"), SQLITE_CONSTRAINT},
{_SC("CONSTRAINT_CHECK"), SQLITE_CONSTRAINT_CHECK},
{_SC("CONSTRAINT_COMMITHOOK"), SQLITE_CONSTRAINT_COMMITHOOK},
{_SC("CONSTRAINT_FOREIGNKEY"), SQLITE_CONSTRAINT_FOREIGNKEY},
{_SC("CONSTRAINT_FUNCTION"), SQLITE_CONSTRAINT_FUNCTION},
{_SC("CONSTRAINT_NOTNULL"), SQLITE_CONSTRAINT_NOTNULL},
{_SC("CONSTRAINT_PRIMARYKEY"), SQLITE_CONSTRAINT_PRIMARYKEY},
{_SC("CONSTRAINT_ROWID"), SQLITE_CONSTRAINT_ROWID},
{_SC("CONSTRAINT_TRIGGER"), SQLITE_CONSTRAINT_TRIGGER},
{_SC("CONSTRAINT_UNIQUE"), SQLITE_CONSTRAINT_UNIQUE},
{_SC("CONSTRAINT_VTAB"), SQLITE_CONSTRAINT_VTAB},
{_SC("COPY"), SQLITE_COPY},
{_SC("CORRUPT"), SQLITE_CORRUPT},
{_SC("CORRUPT_VTAB"), SQLITE_CORRUPT_VTAB},
{_SC("CREATE_INDEX"), SQLITE_CREATE_INDEX},
{_SC("CREATE_TABLE"), SQLITE_CREATE_TABLE},
{_SC("CREATE_TEMP_INDEX"), SQLITE_CREATE_TEMP_INDEX},
{_SC("CREATE_TEMP_TABLE"), SQLITE_CREATE_TEMP_TABLE},
{_SC("CREATE_TEMP_TRIGGER"), SQLITE_CREATE_TEMP_TRIGGER},
{_SC("CREATE_TEMP_VIEW"), SQLITE_CREATE_TEMP_VIEW},
{_SC("CREATE_TRIGGER"), SQLITE_CREATE_TRIGGER},
{_SC("CREATE_VIEW"), SQLITE_CREATE_VIEW},
{_SC("CREATE_VTABLE"), SQLITE_CREATE_VTABLE},
{_SC("DBCONFIG_ENABLE_FKEY"), SQLITE_DBCONFIG_ENABLE_FKEY},
{_SC("DBCONFIG_ENABLE_TRIGGER"), SQLITE_DBCONFIG_ENABLE_TRIGGER},
{_SC("DBCONFIG_LOOKASIDE"), SQLITE_DBCONFIG_LOOKASIDE},
{_SC("DBSTATUS_CACHE_HIT"), SQLITE_DBSTATUS_CACHE_HIT},
{_SC("DBSTATUS_CACHE_MISS"), SQLITE_DBSTATUS_CACHE_MISS},
{_SC("DBSTATUS_CACHE_USED"), SQLITE_DBSTATUS_CACHE_USED},
{_SC("DBSTATUS_CACHE_WRITE"), SQLITE_DBSTATUS_CACHE_WRITE},
{_SC("DBSTATUS_DEFERRED_FKS"), SQLITE_DBSTATUS_DEFERRED_FKS},
{_SC("DBSTATUS_LOOKASIDE_HIT"), SQLITE_DBSTATUS_LOOKASIDE_HIT},
{_SC("DBSTATUS_LOOKASIDE_MISS_FULL"), SQLITE_DBSTATUS_LOOKASIDE_MISS_FULL},
{_SC("DBSTATUS_LOOKASIDE_MISS_SIZE"), SQLITE_DBSTATUS_LOOKASIDE_MISS_SIZE},
{_SC("DBSTATUS_LOOKASIDE_USED"), SQLITE_DBSTATUS_LOOKASIDE_USED},
{_SC("DBSTATUS_MAX"), SQLITE_DBSTATUS_MAX},
{_SC("DBSTATUS_SCHEMA_USED"), SQLITE_DBSTATUS_SCHEMA_USED},
{_SC("DBSTATUS_STMT_USED"), SQLITE_DBSTATUS_STMT_USED},
{_SC("DELETE"), SQLITE_DELETE},
{_SC("DENY"), SQLITE_DENY},
{_SC("DETACH"), SQLITE_DETACH},
{_SC("DETERMINISTIC"), SQLITE_DETERMINISTIC},
{_SC("DONE"), SQLITE_DONE},
{_SC("DROP_INDEX"), SQLITE_DROP_INDEX},
{_SC("DROP_TABLE"), SQLITE_DROP_TABLE},
{_SC("DROP_TEMP_INDEX"), SQLITE_DROP_TEMP_INDEX},
{_SC("DROP_TEMP_TABLE"), SQLITE_DROP_TEMP_TABLE},
{_SC("DROP_TEMP_TRIGGER"), SQLITE_DROP_TEMP_TRIGGER},
{_SC("DROP_TEMP_VIEW"), SQLITE_DROP_TEMP_VIEW},
{_SC("DROP_TRIGGER"), SQLITE_DROP_TRIGGER},
{_SC("DROP_VIEW"), SQLITE_DROP_VIEW},
{_SC("DROP_VTABLE"), SQLITE_DROP_VTABLE},
{_SC("EMPTY"), SQLITE_EMPTY},
{_SC("ERROR"), SQLITE_ERROR},
{_SC("FAIL"), SQLITE_FAIL},
{_SC("FCNTL_BUSYHANDLER"), SQLITE_FCNTL_BUSYHANDLER},
{_SC("FCNTL_CHUNK_SIZE"), SQLITE_FCNTL_CHUNK_SIZE},
{_SC("FCNTL_COMMIT_PHASETWO"), SQLITE_FCNTL_COMMIT_PHASETWO},
{_SC("FCNTL_FILE_POINTER"), SQLITE_FCNTL_FILE_POINTER},
{_SC("FCNTL_GET_LOCKPROXYFILE"), SQLITE_FCNTL_GET_LOCKPROXYFILE},
{_SC("FCNTL_HAS_MOVED"), SQLITE_FCNTL_HAS_MOVED},
{_SC("FCNTL_LAST_ERRNO"), SQLITE_FCNTL_LAST_ERRNO},
{_SC("FCNTL_LOCKSTATE"), SQLITE_FCNTL_LOCKSTATE},
{_SC("FCNTL_MMAP_SIZE"), SQLITE_FCNTL_MMAP_SIZE},
{_SC("FCNTL_OVERWRITE"), SQLITE_FCNTL_OVERWRITE},
{_SC("FCNTL_PERSIST_WAL"), SQLITE_FCNTL_PERSIST_WAL},
{_SC("FCNTL_POWERSAFE_OVERWRITE"), SQLITE_FCNTL_POWERSAFE_OVERWRITE},
{_SC("FCNTL_PRAGMA"), SQLITE_FCNTL_PRAGMA},
{_SC("FCNTL_RBU"), SQLITE_FCNTL_RBU},
{_SC("FCNTL_SET_LOCKPROXYFILE"), SQLITE_FCNTL_SET_LOCKPROXYFILE},
{_SC("FCNTL_SIZE_HINT"), SQLITE_FCNTL_SIZE_HINT},
{_SC("FCNTL_SYNC"), SQLITE_FCNTL_SYNC},
{_SC("FCNTL_SYNC_OMITTED"), SQLITE_FCNTL_SYNC_OMITTED},
{_SC("FCNTL_TEMPFILENAME"), SQLITE_FCNTL_TEMPFILENAME},
{_SC("FCNTL_TRACE"), SQLITE_FCNTL_TRACE},
{_SC("FCNTL_VFSNAME"), SQLITE_FCNTL_VFSNAME},
{_SC("FCNTL_WAL_BLOCK"), SQLITE_FCNTL_WAL_BLOCK},
{_SC("FCNTL_WIN32_AV_RETRY"), SQLITE_FCNTL_WIN32_AV_RETRY},
{_SC("FCNTL_WIN32_SET_HANDLE"), SQLITE_FCNTL_WIN32_SET_HANDLE},
{_SC("FCNTL_ZIPVFS"), SQLITE_FCNTL_ZIPVFS},
{_SC("FLOAT"), SQLITE_FLOAT},
{_SC("FORMAT"), SQLITE_FORMAT},
{_SC("FULL"), SQLITE_FULL},
{_SC("FUNCTION"), SQLITE_FUNCTION},
{_SC("IGNORE"), SQLITE_IGNORE},
{_SC("INDEX_CONSTRAINT_EQ"), SQLITE_INDEX_CONSTRAINT_EQ},
{_SC("INDEX_CONSTRAINT_GE"), SQLITE_INDEX_CONSTRAINT_GE},
{_SC("INDEX_CONSTRAINT_GT"), SQLITE_INDEX_CONSTRAINT_GT},
{_SC("INDEX_CONSTRAINT_LE"), SQLITE_INDEX_CONSTRAINT_LE},
{_SC("INDEX_CONSTRAINT_LT"), SQLITE_INDEX_CONSTRAINT_LT},
{_SC("INDEX_CONSTRAINT_MATCH"), SQLITE_INDEX_CONSTRAINT_MATCH},
{_SC("INDEX_SCAN_UNIQUE"), SQLITE_INDEX_SCAN_UNIQUE},
{_SC("INSERT"), SQLITE_INSERT},
{_SC("INTEGER"), SQLITE_INTEGER},
{_SC("INTERNAL"), SQLITE_INTERNAL},
{_SC("INTERRUPT"), SQLITE_INTERRUPT},
{_SC("IOCAP_ATOMIC"), SQLITE_IOCAP_ATOMIC},
{_SC("IOCAP_ATOMIC16K"), SQLITE_IOCAP_ATOMIC16K},
{_SC("IOCAP_ATOMIC1K"), SQLITE_IOCAP_ATOMIC1K},
{_SC("IOCAP_ATOMIC2K"), SQLITE_IOCAP_ATOMIC2K},
{_SC("IOCAP_ATOMIC32K"), SQLITE_IOCAP_ATOMIC32K},
{_SC("IOCAP_ATOMIC4K"), SQLITE_IOCAP_ATOMIC4K},
{_SC("IOCAP_ATOMIC512"), SQLITE_IOCAP_ATOMIC512},
{_SC("IOCAP_ATOMIC64K"), SQLITE_IOCAP_ATOMIC64K},
{_SC("IOCAP_ATOMIC8K"), SQLITE_IOCAP_ATOMIC8K},
{_SC("IOCAP_IMMUTABLE"), SQLITE_IOCAP_IMMUTABLE},
{_SC("IOCAP_POWERSAFE_OVERWRITE"), SQLITE_IOCAP_POWERSAFE_OVERWRITE},
{_SC("IOCAP_SAFE_APPEND"), SQLITE_IOCAP_SAFE_APPEND},
{_SC("IOCAP_SEQUENTIAL"), SQLITE_IOCAP_SEQUENTIAL},
{_SC("IOCAP_UNDELETABLE_WHEN_OPEN"), SQLITE_IOCAP_UNDELETABLE_WHEN_OPEN},
{_SC("IOERR"), SQLITE_IOERR},
{_SC("IOERR_ACCESS"), SQLITE_IOERR_ACCESS},
{_SC("IOERR_BLOCKED"), SQLITE_IOERR_BLOCKED},
{_SC("IOERR_CHECKRESERVEDLOCK"), SQLITE_IOERR_CHECKRESERVEDLOCK},
{_SC("IOERR_CLOSE"), SQLITE_IOERR_CLOSE},
{_SC("IOERR_CONVPATH"), SQLITE_IOERR_CONVPATH},
{_SC("IOERR_DELETE"), SQLITE_IOERR_DELETE},
{_SC("IOERR_DELETE_NOENT"), SQLITE_IOERR_DELETE_NOENT},
{_SC("IOERR_DIR_CLOSE"), SQLITE_IOERR_DIR_CLOSE},
{_SC("IOERR_DIR_FSYNC"), SQLITE_IOERR_DIR_FSYNC},
{_SC("IOERR_FSTAT"), SQLITE_IOERR_FSTAT},
{_SC("IOERR_FSYNC"), SQLITE_IOERR_FSYNC},
{_SC("IOERR_GETTEMPPATH"), SQLITE_IOERR_GETTEMPPATH},
{_SC("IOERR_LOCK"), SQLITE_IOERR_LOCK},
{_SC("IOERR_MMAP"), SQLITE_IOERR_MMAP},
{_SC("IOERR_NOMEM"), SQLITE_IOERR_NOMEM},
{_SC("IOERR_RDLOCK"), SQLITE_IOERR_RDLOCK},
{_SC("IOERR_READ"), SQLITE_IOERR_READ},
{_SC("IOERR_SEEK"), SQLITE_IOERR_SEEK},
{_SC("IOERR_SHMLOCK"), SQLITE_IOERR_SHMLOCK},
{_SC("IOERR_SHMMAP"), SQLITE_IOERR_SHMMAP},
{_SC("IOERR_SHMOPEN"), SQLITE_IOERR_SHMOPEN},
{_SC("IOERR_SHMSIZE"), SQLITE_IOERR_SHMSIZE},
{_SC("IOERR_SHORT_READ"), SQLITE_IOERR_SHORT_READ},
{_SC("IOERR_TRUNCATE"), SQLITE_IOERR_TRUNCATE},
{_SC("IOERR_UNLOCK"), SQLITE_IOERR_UNLOCK},
{_SC("IOERR_VNODE"), SQLITE_IOERR_VNODE},
{_SC("IOERR_WRITE"), SQLITE_IOERR_WRITE},
{_SC("LIMIT_ATTACHED"), SQLITE_LIMIT_ATTACHED},
{_SC("LIMIT_COLUMN"), SQLITE_LIMIT_COLUMN},
{_SC("LIMIT_COMPOUND_SELECT"), SQLITE_LIMIT_COMPOUND_SELECT},
{_SC("LIMIT_EXPR_DEPTH"), SQLITE_LIMIT_EXPR_DEPTH},
{_SC("LIMIT_FUNCTION_ARG"), SQLITE_LIMIT_FUNCTION_ARG},
{_SC("LIMIT_LENGTH"), SQLITE_LIMIT_LENGTH},
{_SC("LIMIT_LIKE_PATTERN_LENGTH"), SQLITE_LIMIT_LIKE_PATTERN_LENGTH},
{_SC("LIMIT_SQL_LENGTH"), SQLITE_LIMIT_SQL_LENGTH},
{_SC("LIMIT_TRIGGER_DEPTH"), SQLITE_LIMIT_TRIGGER_DEPTH},
{_SC("LIMIT_VARIABLE_NUMBER"), SQLITE_LIMIT_VARIABLE_NUMBER},
{_SC("LIMIT_VDBE_OP"), SQLITE_LIMIT_VDBE_OP},
{_SC("LIMIT_WORKER_THREADS"), SQLITE_LIMIT_WORKER_THREADS},
{_SC("LOCKED"), SQLITE_LOCKED},
{_SC("LOCKED_SHAREDCACHE"), SQLITE_LOCKED_SHAREDCACHE},
{_SC("LOCK_EXCLUSIVE"), SQLITE_LOCK_EXCLUSIVE},
{_SC("LOCK_NONE"), SQLITE_LOCK_NONE},
{_SC("LOCK_PENDING"), SQLITE_LOCK_PENDING},
{_SC("LOCK_RESERVED"), SQLITE_LOCK_RESERVED},
{_SC("LOCK_SHARED"), SQLITE_LOCK_SHARED},
{_SC("MISMATCH"), SQLITE_MISMATCH},
{_SC("MISUSE"), SQLITE_MISUSE},
{_SC("MUTEX_FAST"), SQLITE_MUTEX_FAST},
{_SC("MUTEX_RECURSIVE"), SQLITE_MUTEX_RECURSIVE},
{_SC("MUTEX_STATIC_APP1"), SQLITE_MUTEX_STATIC_APP1},
{_SC("MUTEX_STATIC_APP2"), SQLITE_MUTEX_STATIC_APP2},
{_SC("MUTEX_STATIC_APP3"), SQLITE_MUTEX_STATIC_APP3},
{_SC("MUTEX_STATIC_LRU"), SQLITE_MUTEX_STATIC_LRU},
{_SC("MUTEX_STATIC_LRU2"), SQLITE_MUTEX_STATIC_LRU2},
{_SC("MUTEX_STATIC_MASTER"), SQLITE_MUTEX_STATIC_MASTER},
{_SC("MUTEX_STATIC_MEM"), SQLITE_MUTEX_STATIC_MEM},
{_SC("MUTEX_STATIC_MEM2"), SQLITE_MUTEX_STATIC_MEM2},
{_SC("MUTEX_STATIC_OPEN"), SQLITE_MUTEX_STATIC_OPEN},
{_SC("MUTEX_STATIC_PMEM"), SQLITE_MUTEX_STATIC_PMEM},
{_SC("MUTEX_STATIC_PRNG"), SQLITE_MUTEX_STATIC_PRNG},
{_SC("MUTEX_STATIC_VFS1"), SQLITE_MUTEX_STATIC_VFS1},
{_SC("MUTEX_STATIC_VFS2"), SQLITE_MUTEX_STATIC_VFS2},
{_SC("MUTEX_STATIC_VFS3"), SQLITE_MUTEX_STATIC_VFS3},
{_SC("NOLFS"), SQLITE_NOLFS},
{_SC("NOMEM"), SQLITE_NOMEM},
{_SC("NOTADB"), SQLITE_NOTADB},
{_SC("NOTFOUND"), SQLITE_NOTFOUND},
{_SC("NOTICE"), SQLITE_NOTICE},
{_SC("NOTICE_RECOVER_ROLLBACK"), SQLITE_NOTICE_RECOVER_ROLLBACK},
{_SC("NOTICE_RECOVER_WAL"), SQLITE_NOTICE_RECOVER_WAL},
{_SC("NULL"), SQLITE_NULL},
{_SC("OK"), SQLITE_OK},
{_SC("OPEN_AUTOPROXY"), SQLITE_OPEN_AUTOPROXY},
{_SC("OPEN_CREATE"), SQLITE_OPEN_CREATE},
{_SC("OPEN_DELETEONCLOSE"), SQLITE_OPEN_DELETEONCLOSE},
{_SC("OPEN_EXCLUSIVE"), SQLITE_OPEN_EXCLUSIVE},
{_SC("OPEN_FULLMUTEX"), SQLITE_OPEN_FULLMUTEX},
{_SC("OPEN_MAIN_DB"), SQLITE_OPEN_MAIN_DB},
{_SC("OPEN_MAIN_JOURNAL"), SQLITE_OPEN_MAIN_JOURNAL},
{_SC("OPEN_MASTER_JOURNAL"), SQLITE_OPEN_MASTER_JOURNAL},
{_SC("OPEN_MEMORY"), SQLITE_OPEN_MEMORY},
{_SC("OPEN_NOMUTEX"), SQLITE_OPEN_NOMUTEX},
{_SC("OPEN_PRIVATECACHE"), SQLITE_OPEN_PRIVATECACHE},
{_SC("OPEN_READONLY"), SQLITE_OPEN_READONLY},
{_SC("OPEN_READWRITE"), SQLITE_OPEN_READWRITE},
{_SC("OPEN_SHAREDCACHE"), SQLITE_OPEN_SHAREDCACHE},
{_SC("OPEN_SUBJOURNAL"), SQLITE_OPEN_SUBJOURNAL},
{_SC("OPEN_TEMP_DB"), SQLITE_OPEN_TEMP_DB},
{_SC("OPEN_TEMP_JOURNAL"), SQLITE_OPEN_TEMP_JOURNAL},
{_SC("OPEN_TRANSIENT_DB"), SQLITE_OPEN_TRANSIENT_DB},
{_SC("OPEN_URI"), SQLITE_OPEN_URI},
{_SC("OPEN_WAL"), SQLITE_OPEN_WAL},
{_SC("PERM"), SQLITE_PERM},
{_SC("PRAGMA"), SQLITE_PRAGMA},
{_SC("PROTOCOL"), SQLITE_PROTOCOL},
{_SC("RANGE"), SQLITE_RANGE},
{_SC("READ"), SQLITE_READ},
{_SC("READONLY"), SQLITE_READONLY},
{_SC("READONLY_CANTLOCK"), SQLITE_READONLY_CANTLOCK},
{_SC("READONLY_DBMOVED"), SQLITE_READONLY_DBMOVED},
{_SC("READONLY_RECOVERY"), SQLITE_READONLY_RECOVERY},
{_SC("READONLY_ROLLBACK"), SQLITE_READONLY_ROLLBACK},
{_SC("RECURSIVE"), SQLITE_RECURSIVE},
{_SC("REINDEX"), SQLITE_REINDEX},
{_SC("REPLACE"), SQLITE_REPLACE},
{_SC("ROLLBACK"), SQLITE_ROLLBACK},
{_SC("ROW"), SQLITE_ROW},
{_SC("SAVEPOINT"), SQLITE_SAVEPOINT},
{_SC("SCANSTAT_EST"), SQLITE_SCANSTAT_EST},
{_SC("SCANSTAT_EXPLAIN"), SQLITE_SCANSTAT_EXPLAIN},
{_SC("SCANSTAT_NAME"), SQLITE_SCANSTAT_NAME},
{_SC("SCANSTAT_NLOOP"), SQLITE_SCANSTAT_NLOOP},
{_SC("SCANSTAT_NVISIT"), SQLITE_SCANSTAT_NVISIT},
{_SC("SCANSTAT_SELECTID"), SQLITE_SCANSTAT_SELECTID},
{_SC("SCHEMA"), SQLITE_SCHEMA},
{_SC("SELECT"), SQLITE_SELECT},
{_SC("SHM_EXCLUSIVE"), SQLITE_SHM_EXCLUSIVE},
{_SC("SHM_LOCK"), SQLITE_SHM_LOCK},
{_SC("SHM_NLOCK"), SQLITE_SHM_NLOCK},
{_SC("SHM_SHARED"), SQLITE_SHM_SHARED},
{_SC("SHM_UNLOCK"), SQLITE_SHM_UNLOCK},
{_SC("STATUS_MALLOC_COUNT"), SQLITE_STATUS_MALLOC_COUNT},
{_SC("STATUS_MALLOC_SIZE"), SQLITE_STATUS_MALLOC_SIZE},
{_SC("STATUS_MEMORY_USED"), SQLITE_STATUS_MEMORY_USED},
{_SC("STATUS_PAGECACHE_OVERFLOW"), SQLITE_STATUS_PAGECACHE_OVERFLOW},
{_SC("STATUS_PAGECACHE_SIZE"), SQLITE_STATUS_PAGECACHE_SIZE},
{_SC("STATUS_PAGECACHE_USED"), SQLITE_STATUS_PAGECACHE_USED},
{_SC("STATUS_PARSER_STACK"), SQLITE_STATUS_PARSER_STACK},
{_SC("STATUS_SCRATCH_OVERFLOW"), SQLITE_STATUS_SCRATCH_OVERFLOW},
{_SC("STATUS_SCRATCH_SIZE"), SQLITE_STATUS_SCRATCH_SIZE},
{_SC("STATUS_SCRATCH_USED"), SQLITE_STATUS_SCRATCH_USED},
{_SC("STMTSTATUS_AUTOINDEX"), SQLITE_STMTSTATUS_AUTOINDEX},
{_SC("STMTSTATUS_FULLSCAN_STEP"), SQLITE_STMTSTATUS_FULLSCAN_STEP},
{_SC("STMTSTATUS_SORT"), SQLITE_STMTSTATUS_SORT},
{_SC("STMTSTATUS_VM_STEP"), SQLITE_STMTSTATUS_VM_STEP},
{_SC("SYNC_DATAONLY"), SQLITE_SYNC_DATAONLY},
{_SC("SYNC_FULL"), SQLITE_SYNC_FULL},
{_SC("SYNC_NORMAL"), SQLITE_SYNC_NORMAL},
{_SC("TESTCTRL_ALWAYS"), SQLITE_TESTCTRL_ALWAYS},
{_SC("TESTCTRL_ASSERT"), SQLITE_TESTCTRL_ASSERT},
{_SC("TESTCTRL_BENIGN_MALLOC_HOOKS"), SQLITE_TESTCTRL_BENIGN_MALLOC_HOOKS},
{_SC("TESTCTRL_BITVEC_TEST"), SQLITE_TESTCTRL_BITVEC_TEST},
{_SC("TESTCTRL_BYTEORDER"), SQLITE_TESTCTRL_BYTEORDER},
{_SC("TESTCTRL_EXPLAIN_STMT"), SQLITE_TESTCTRL_EXPLAIN_STMT},
{_SC("TESTCTRL_FAULT_INSTALL"), SQLITE_TESTCTRL_FAULT_INSTALL},
{_SC("TESTCTRL_FIRST"), SQLITE_TESTCTRL_FIRST},
{_SC("TESTCTRL_IMPOSTER"), SQLITE_TESTCTRL_IMPOSTER},
{_SC("TESTCTRL_ISINIT"), SQLITE_TESTCTRL_ISINIT},
{_SC("TESTCTRL_ISKEYWORD"), SQLITE_TESTCTRL_ISKEYWORD},
{_SC("TESTCTRL_LAST"), SQLITE_TESTCTRL_LAST},
{_SC("TESTCTRL_LOCALTIME_FAULT"), SQLITE_TESTCTRL_LOCALTIME_FAULT},
{_SC("TESTCTRL_NEVER_CORRUPT"), SQLITE_TESTCTRL_NEVER_CORRUPT},
{_SC("TESTCTRL_OPTIMIZATIONS"), SQLITE_TESTCTRL_OPTIMIZATIONS},
{_SC("TESTCTRL_PENDING_BYTE"), SQLITE_TESTCTRL_PENDING_BYTE},
{_SC("TESTCTRL_PRNG_RESET"), SQLITE_TESTCTRL_PRNG_RESET},
{_SC("TESTCTRL_PRNG_RESTORE"), SQLITE_TESTCTRL_PRNG_RESTORE},
{_SC("TESTCTRL_PRNG_SAVE"), SQLITE_TESTCTRL_PRNG_SAVE},
{_SC("TESTCTRL_RESERVE"), SQLITE_TESTCTRL_RESERVE},
{_SC("TESTCTRL_SCRATCHMALLOC"), SQLITE_TESTCTRL_SCRATCHMALLOC},
{_SC("TESTCTRL_SORTER_MMAP"), SQLITE_TESTCTRL_SORTER_MMAP},
{_SC("TESTCTRL_VDBE_COVERAGE"), SQLITE_TESTCTRL_VDBE_COVERAGE},
{_SC("TEXT"), SQLITE_TEXT},
{_SC("TOOBIG"), SQLITE_TOOBIG},
{_SC("TRANSACTION"), SQLITE_TRANSACTION},
{_SC("UPDATE"), SQLITE_UPDATE},
{_SC("UTF16"), SQLITE_UTF16},
{_SC("UTF16BE"), SQLITE_UTF16BE},
{_SC("UTF16LE"), SQLITE_UTF16LE},
{_SC("UTF16_ALIGNED"), SQLITE_UTF16_ALIGNED},
{_SC("UTF8"), SQLITE_UTF8},
{_SC("VERSION_NUMBER"), SQLITE_VERSION_NUMBER},
{_SC("VTAB_CONSTRAINT_SUPPORT"), SQLITE_VTAB_CONSTRAINT_SUPPORT},
{_SC("WARNING"), SQLITE_WARNING},
{_SC("WARNING_AUTOINDEX"), SQLITE_WARNING_AUTOINDEX}
};
// ================================================================================================
void Register_Constants(Table & sqlns)
{
Enumeration e(sqlns.GetVM());
for (Uint32 n = 0; n < (sizeof(g_MainEnum) / sizeof(EnumElement)); ++n)
{
e.Const(g_MainEnum[n].Name, g_MainEnum[n].Value);
}
ConstTable(sqlns.GetVM()).Enum(_SC("ESQLite"), e);
}
} // Namespace:: SqMod

View File

@@ -1,297 +0,0 @@
// ------------------------------------------------------------------------------------------------
#include "Library/SQLite/Handle.hpp"
#include <utility>
// ------------------------------------------------------------------------------------------------
namespace SqMod {
// ------------------------------------------------------------------------------------------------
ConnHnd::ConnHnd()
: mPtr(nullptr)
, mStatus(SQLITE_OK)
, mQueue()
, mFlags(0)
, mName()
, mVFS()
, mMemory(false)
, mTrace(false)
, mProfile(false)
{
/* ... */
}
// ------------------------------------------------------------------------------------------------
ConnHnd::~ConnHnd()
{
// Is there anything to close?
if (mPtr != nullptr)
{
// Flush remaining queries in the queue and ignore the result
Flush(mQueue.size(), NullObject(), NullFunction());
// NOTE: Should we call sqlite3_interrupt(...) before closing?
// Attempt to close the database
if ((sqlite3_close(mPtr)) != SQLITE_OK)
{
LogErr("Unable to close SQLite connection [%s]", sqlite3_errmsg(mPtr));
}
}
}
// ------------------------------------------------------------------------------------------------
void ConnHnd::Create(CSStr name, Int32 flags, CSStr vfs)
{
// Make sure a previous connection doesn't exist
if (mPtr)
{
STHROWF("Unable to connect to database. Database already connected");
}
// Make sure the name is valid
else if (!name || *name == '\0')
{
STHROWF("Unable to connect to database. The name is invalid");
}
// Attempt to create the database connection
else if ((mStatus = sqlite3_open_v2(name, &mPtr, flags, vfs)) != SQLITE_OK)
{
// Grab the error message before destroying the handle
String msg(sqlite3_errmsg(mPtr) ? sqlite3_errmsg(mPtr) : _SC("Unknown reason"));
// Must be destroyed regardless of result
sqlite3_close(mPtr);
// Prevent further use of this handle
mPtr = nullptr;
// Now its safe to throw the error
STHROWF("Unable to connect to database [%s]", msg.c_str());
}
// Let's save the specified information
mName.assign(name);
mFlags = flags;
mVFS.assign(vfs ? vfs : _SC(""));
// Optional check if database is initially stored in memory
mMemory = (mName == _SC(":memory:"));
}
// ------------------------------------------------------------------------------------------------
Int32 ConnHnd::Flush(Uint32 num, Object & env, Function & func)
{
// Do we even have a valid connection?
if (!mPtr)
{
return -1; // No connection!
}
// Is there anything to flush?
else if (!num || mQueue.empty())
{
return 0; // Nothing to process!
}
// Can we even flush that many?
else if (num > mQueue.size())
{
num = mQueue.size();
}
// Generate the function that should be called upon error
Function callback = Function(env.GetVM(), env.GetObject(), func.GetFunc());
// Obtain iterators to the range of queries that should be flushed
auto itr = mQueue.begin();
auto end = mQueue.begin() + num;
// Attempt to begin the flush transaction
if ((mStatus = sqlite3_exec(mPtr, "BEGIN", nullptr, nullptr, nullptr)) != SQLITE_OK)
{
STHROWF("Unable to begin flush transaction [%s]", sqlite3_errmsg(mPtr));
}
// Process all queries within range of selection
for (; itr != end; ++itr)
{
// Should we manually terminate this query?
/*
if (*(*itr).rbegin() != ';')
{
itr->push_back(';');
}
*/
// Attempt to execute the currently processed query string
if ((mStatus = sqlite3_exec(mPtr, itr->c_str(), nullptr, nullptr, nullptr)) == SQLITE_OK)
{
continue;
}
// Do we have to execute any callback to resolve our issue?
else if (!callback.IsNull())
{
try
{
// Ask the callback whether the query processing should end here
SharedPtr< bool > ret = callback.Evaluate< bool >(mStatus, *itr);
// Should we break here?
if (!!ret && !(*ret))
{
break;
}
}
catch (const Sqrat::Exception & e)
{
LogErr("Squirrel error caught in flush handler [%s]", e.what());
}
catch (const std::exception & e)
{
LogErr("Program error caught in flush handler [%s]", e.what());
}
catch (...)
{
LogErr("Unknown error caught in flush handler");
}
}
}
// Erase all queries till end or till the point of failure (if any occurred)
mQueue.erase(mQueue.begin(), itr);
// Attempt to commit changes requested during transaction
if ((mStatus = sqlite3_exec(mPtr, "COMMIT", nullptr, nullptr, nullptr)) == SQLITE_OK)
{
return sqlite3_changes(mPtr);
}
// Attempt to roll back erroneous changes
else if ((mStatus = sqlite3_exec(mPtr, "ROLLBACK", nullptr, nullptr, nullptr)) != SQLITE_OK)
{
STHROWF("Unable to rollback flush transaction [%s]", sqlite3_errmsg(mPtr));
}
// The transaction failed somehow but we managed to rollback
else
{
STHROWF("Unable to commit flush transaction [%s]", sqlite3_errmsg(mPtr));
}
// Operation failed
return -1;
}
// ------------------------------------------------------------------------------------------------
StmtHnd::StmtHnd(ConnRef conn)
: mPtr(nullptr)
, mStatus(SQLITE_OK)
, mConn(std::move(conn))
, mQuery()
, mColumns(0)
, mParameters(0)
, mIndexes()
, mGood(false)
, mDone(false)
{
/* ... */
}
// ------------------------------------------------------------------------------------------------
StmtHnd::~StmtHnd()
{
// Is there anything to finalize?
if (mPtr != nullptr)
{
// Attempt to finalize the statement
if ((sqlite3_finalize(mPtr)) != SQLITE_OK)
{
LogErr("Unable to finalize SQLite statement [%s]", mConn->ErrMsg());
}
}
}
// ------------------------------------------------------------------------------------------------
void StmtHnd::Create(CSStr query, SQInteger length)
{
// Make sure a previous statement doesn't exist
if (mPtr)
{
STHROWF("Unable to prepare statement. Statement already prepared");
}
// Is the specified database connection is valid?
else if (!mConn)
{
STHROWF("Unable to prepare statement. Invalid connection handle");
}
// Is the specified query string valid?
else if (!query || !length || *query == '\0')
{
STHROWF("Unable to prepare statement. Invalid or empty query string");
}
// Save the query string
mQuery.assign(query, length);
// Attempt to prepare a statement with the specified query string
if ((mStatus = sqlite3_prepare_v2(mConn->mPtr, mQuery.c_str(), ConvTo< Int32 >::From(mQuery.size()),
&mPtr, nullptr)) != SQLITE_OK)
{
// Clear the query string since it failed
mQuery.clear();
// Explicitly make sure the handle is null
mPtr = nullptr;
// Now it's safe to throw the error
STHROWF("Unable to prepare statement [%s]", mConn->ErrMsg());
}
else
{
// Obtain the number of available columns
mColumns = sqlite3_column_count(mPtr);
// Obtain the number of available parameters
mParameters = sqlite3_bind_parameter_count(mPtr);
}
}
// ------------------------------------------------------------------------------------------------
Int32 StmtHnd::GetColumnIndex(CSStr name, SQInteger length)
{
// Validate the handle
if (!mPtr)
{
STHROWF("Invalid SQLite statement");
}
// Are the names cached?
else if (mIndexes.empty())
{
for (Int32 i = 0; i < mColumns; ++i)
{
// Get the column name at the current index
auto column_name = static_cast< CSStr >(sqlite3_column_name(mPtr, i));
// Validate the name
if (!column_name)
{
STHROWF("Unable to retrieve column name for index (%d)", i);
}
// Save it to guarantee the same lifetime as this instance
else
{
mIndexes[name] = i;
}
}
}
const String str(name, length < 0 ? std::strlen(name) : length);
// Attempt to find the specified column
const Indexes::iterator itr = mIndexes.find(str);
// Was there a column with the specified name?
if (itr != mIndexes.end())
{
return itr->second;
}
// No such column exists (expecting the invoker to validate the result)
return -1;
}
// ------------------------------------------------------------------------------------------------
CCStr StmtHnd::ErrStr() const
{
return mConn ? sqlite3_errstr(sqlite3_errcode(mConn->mPtr)) : _SC("");
}
// ------------------------------------------------------------------------------------------------
CCStr StmtHnd::ErrMsg() const
{
return mConn ? sqlite3_errmsg(mConn->mPtr) : _SC("");
}
// ------------------------------------------------------------------------------------------------
Int32 StmtHnd::ErrNo() const
{
return mConn ? sqlite3_errcode(mConn->mPtr) : SQLITE_NOMEM;
}
// ------------------------------------------------------------------------------------------------
Int32 StmtHnd::ExErrNo() const
{
return mConn ? sqlite3_extended_errcode(mConn->mPtr) : SQLITE_NOMEM;
}
} // Namespace:: SqMod

View File

@@ -1,249 +0,0 @@
#pragma once
// ------------------------------------------------------------------------------------------------
#include "Library/SQLite/Common.hpp"
// ------------------------------------------------------------------------------------------------
#include <vector>
#include <map>
// ------------------------------------------------------------------------------------------------
namespace SqMod {
/* ------------------------------------------------------------------------------------------------
* The structure that holds the data associated with a certain connection.
*/
struct ConnHnd
{
public:
// --------------------------------------------------------------------------------------------
typedef sqlite3 Type; // The managed type.
// --------------------------------------------------------------------------------------------
typedef Type* Pointer; // Pointer to the managed type.
typedef const Type* ConstPtr; // Constant pointer to the managed type.
// --------------------------------------------------------------------------------------------
typedef Type& Reference; // Reference to the managed type.
typedef const Type& ConstRef; // Constant reference to the managed type.
// --------------------------------------------------------------------------------------------
typedef std::vector< String > QueryList; // Container used to queue queries.
public:
// --------------------------------------------------------------------------------------------
Pointer mPtr; // The connection handle resource.
// --------------------------------------------------------------------------------------------
Int32 mStatus; // The last status code of this connection handle.
// --------------------------------------------------------------------------------------------
QueryList mQueue; // A queue of queries to be executed in groups.
// --------------------------------------------------------------------------------------------
Int32 mFlags; // The flags used to create the database connection handle.
String mName; // The specified name to be used as the database file.
String mVFS; // The specified virtual file system.
// --------------------------------------------------------------------------------------------
bool mMemory; // Whether the database exists in memory and not disk.
bool mTrace; // Whether tracing was activated on the database.
bool mProfile; // Whether profiling was activated on the database.
/* --------------------------------------------------------------------------------------------
* Default constructor.
*/
ConnHnd();
/* --------------------------------------------------------------------------------------------
* Copy constructor. (disabled)
*/
ConnHnd(const ConnHnd & o) = delete;
/* --------------------------------------------------------------------------------------------
* Move constructor. (disabled)
*/
ConnHnd(ConnHnd && o) = delete;
/* --------------------------------------------------------------------------------------------
* Destructor.
*/
~ConnHnd();
/* --------------------------------------------------------------------------------------------
* Copy assignment operator. (disabled)
*/
ConnHnd & operator = (const ConnHnd & o) = delete;
/* --------------------------------------------------------------------------------------------
* Move assignment operator. (disabled)
*/
ConnHnd & operator = (ConnHnd && o) = delete;
/* --------------------------------------------------------------------------------------------
* Create the database connection resource.
*/
void Create(CSStr name, Int32 flags, CSStr vfs);
/* --------------------------------------------------------------------------------------------
* Execute a specific amount of queries from the queue.
*/
Int32 Flush(Uint32 num, Object & env, Function & func);
/* --------------------------------------------------------------------------------------------
* Retrieve the message of the last received error code.
*/
CCStr ErrStr() const
{
return sqlite3_errstr(sqlite3_errcode(mPtr));
}
/* --------------------------------------------------------------------------------------------
* Return the last error message associated with this database connection.
*/
CCStr ErrMsg() const
{
return sqlite3_errmsg(mPtr);
}
/* --------------------------------------------------------------------------------------------
* Return the numeric result code for the most recent failed API call (if any).
*/
Int32 ErrNo() const
{
return sqlite3_errcode(mPtr);
}
/* --------------------------------------------------------------------------------------------
* Return the extended numeric result code for the most recent failed API call (if any).
*/
Int32 ExErrNo() const
{
return sqlite3_extended_errcode(mPtr);
}
};
/* ------------------------------------------------------------------------------------------------
* The structure that holds the data associated with a certain statement.
*/
struct StmtHnd
{
public:
// --------------------------------------------------------------------------------------------
typedef sqlite3_stmt Type; // The managed type.
// --------------------------------------------------------------------------------------------
typedef Type* Pointer; // Pointer to the managed type.
typedef const Type* ConstPtr; // Constant pointer to the managed type.
// --------------------------------------------------------------------------------------------
typedef Type& Reference; // Reference to the managed type.
typedef const Type& ConstRef; // Constant reference to the managed type.
// --------------------------------------------------------------------------------------------
typedef std::map< String, int > Indexes; // Container used to identify column indexes.
public:
// --------------------------------------------------------------------------------------------
Pointer mPtr; // The statement handle resource.
// --------------------------------------------------------------------------------------------
Int32 mStatus; // The last status code of this connection handle.
// --------------------------------------------------------------------------------------------
ConnRef mConn; // The handle to the associated database connection.
// --------------------------------------------------------------------------------------------
String mQuery; // The query string used to create this statement.
// --------------------------------------------------------------------------------------------
Int32 mColumns; // The amount of columns available in this statement.
Int32 mParameters; // The amount of parameters available in this statement.
Indexes mIndexes; // An associative container with column names and their index.
// --------------------------------------------------------------------------------------------
bool mGood; // True when a row has been fetched with step.
bool mDone; // True when the last step had no more rows to fetch.
/* --------------------------------------------------------------------------------------------
* Default constructor.
*/
StmtHnd(ConnRef conn);
/* --------------------------------------------------------------------------------------------
* Copy constructor. (disabled)
*/
StmtHnd(const StmtHnd & o) = delete;
/* --------------------------------------------------------------------------------------------
* Move constructor. (disabled)
*/
StmtHnd(StmtHnd && o) = delete;
/* --------------------------------------------------------------------------------------------
* Destructor.
*/
~StmtHnd();
/* --------------------------------------------------------------------------------------------
* Copy assignment operator. (disabled)
*/
StmtHnd & operator = (const StmtHnd & o) = delete;
/* --------------------------------------------------------------------------------------------
* Move assignment operator. (disabled)
*/
StmtHnd & operator = (StmtHnd && o) = delete;
/* --------------------------------------------------------------------------------------------
* Create the database statement resource.
*/
void Create(CSStr query, SQInteger length = -1);
/* --------------------------------------------------------------------------------------------
* Check whether a specific column index is in range.
*/
bool CheckColumn(Int32 idx) const
{
return (idx >= 0) && (idx < mColumns);
}
/* --------------------------------------------------------------------------------------------
* Check whether a specific parameter index is in range.
*/
bool CheckParameter(Int32 idx) const
{
return (idx >= 1) && (idx <= mParameters);
}
/* --------------------------------------------------------------------------------------------
* Retrieve the column index associated with the specified name.
*/
Int32 GetColumnIndex(CSStr name, SQInteger length = -1);
/* --------------------------------------------------------------------------------------------
* Retrieve the message of the last received error code.
*/
CCStr ErrStr() const;
/* --------------------------------------------------------------------------------------------
* Return the last error message associated with this database connection.
*/
CCStr ErrMsg() const;
/* --------------------------------------------------------------------------------------------
* Return the numeric result code for the most recent failed API call (if any).
*/
Int32 ErrNo() const;
/* --------------------------------------------------------------------------------------------
* Return the extended numeric result code for the most recent failed API call (if any).
*/
Int32 ExErrNo() const;
};
} // Namespace:: SqMod

View File

@@ -1,789 +0,0 @@
// ------------------------------------------------------------------------------------------------
#include "Library/SQLite/Parameter.hpp"
// ------------------------------------------------------------------------------------------------
#include <ctime>
// ------------------------------------------------------------------------------------------------
#include <sqstdblob.h>
// ------------------------------------------------------------------------------------------------
namespace SqMod {
// ------------------------------------------------------------------------------------------------
// Error message when failed to bind value to parameter index.
#define SQMOD_BINDFAILED "Unable to bind (%s) parameter (%d) because [%s]"
// ------------------------------------------------------------------------------------------------
SQMODE_DECL_TYPENAME(Typename, _SC("SqLiteParameter"))
// ------------------------------------------------------------------------------------------------
static inline bool IsDigitsOnly(CSStr str)
{
while (std::isdigit(*str) || std::isspace(*str))
{
++str;
}
// Return whether we reached the end while searching
return *str == '\0';
}
// ------------------------------------------------------------------------------------------------
#if defined(_DEBUG) || defined(SQMOD_EXCEPTLOC)
void Parameter::Validate(CCStr file, Int32 line) const
{
// Are we pointing to a valid index?
if (m_Index < 0)
{
SqThrowF("Invalid column index: %d < 0 =>[%s:%d]", m_Index, file, line);
}
// Do we have a valid statement handle?
else if (!m_Handle)
{
SqThrowF("Invalid SQLite statement reference =>[%s:%d]", file, line);
}
}
#else
void Parameter::Validate() const
{
// Are we pointing to a valid index?
if (m_Index < 0)
{
SqThrowF("Invalid column index: %d < 0", m_Index);
}
// Do we have a valid statement handle?
else if (!m_Handle)
{
SqThrowF("Invalid SQLite statement reference");
}
}
#endif // _DEBUG
// ------------------------------------------------------------------------------------------------
#if defined(_DEBUG) || defined(SQMOD_EXCEPTLOC)
void Parameter::ValidateCreated(CCStr file, Int32 line) const
{
// Are we pointing to a valid index?
if (m_Index < 0)
{
SqThrowF("Invalid column index: %d < 0 =>[%s:%d]", m_Index, file, line);
}
else if (!m_Handle)
{
SqThrowF("Invalid SQLite statement reference =>[%s:%d]", file, line);
}
else if (m_Handle->mPtr == nullptr)
{
SqThrowF("Invalid SQLite statement =>[%s:%d]", file, line);
}
}
#else
void Parameter::ValidateCreated() const
{
// Are we pointing to a valid index?
if (m_Index < 0)
{
SqThrowF("Invalid column index: %d < 0", m_Index);
}
else if (!m_Handle)
{
SqThrowF("Invalid SQLite statement reference");
}
else if (m_Handle->mPtr == nullptr)
{
SqThrowF("Invalid SQLite statement");
}
}
#endif // _DEBUG
// ------------------------------------------------------------------------------------------------
#if defined(_DEBUG) || defined(SQMOD_EXCEPTLOC)
const StmtRef & Parameter::GetValid(CCStr file, Int32 line) const
{
Validate(file, line);
return m_Handle;
}
#else
const StmtRef & Parameter::GetValid() const
{
Validate();
return m_Handle;
}
#endif // _DEBUG
// ------------------------------------------------------------------------------------------------
#if defined(_DEBUG) || defined(SQMOD_EXCEPTLOC)
const StmtRef & Parameter::GetCreated(CCStr file, Int32 line) const
{
ValidateCreated(file, line);
return m_Handle;
}
#else
const StmtRef & Parameter::GetCreated() const
{
ValidateCreated();
return m_Handle;
}
#endif // _DEBUG
// ------------------------------------------------------------------------------------------------
#if defined(_DEBUG) || defined(SQMOD_EXCEPTLOC)
void Parameter::ValidateParam(Int32 idx, CCStr file, Int32 line) const
{
ValidateCreated(file, line);
// Is the specified index in range?
if (!m_Handle->CheckParameter(idx))
{
SqThrowF("Parameter index is out of range (%d:%d) =>[%s:%d]", idx, m_Handle->mParameters,
file, line);
}
}
#else
void Parameter::ValidateParam(Int32 idx) const
{
ValidateCreated();
// Is the specified index in range?
if (!m_Handle->CheckParameter(idx))
{
SqThrowF("Parameter index is out of range (%d:%d)", idx, m_Handle->mParameters);
}
}
#endif // _DEBUG
// ------------------------------------------------------------------------------------------------
void Parameter::SetIndex(const Object & param)
{
// Where the index will be extracted
Int32 idx = 0;
// Grab the object virtual machine
HSQUIRRELVM vm = param.GetVM();
// Remember the current stack size
const StackGuard sg(vm);
// Push the specified object onto the stack
Var< const Object & >::push(vm, param);
// Identify the type of parameter was given
switch (param.GetType())
{
// Is this a string value?
case OT_STRING:
{
// Obtain the object from the stack as a string
StackStrF val(vm, -1);
// Validate the result
if (SQ_FAILED(val.Proc(false)))
{
STHROWF("%s", LastErrorString(vm).c_str());
}
// Is the obtained string empty?
else if (val.mLen <= 0)
{
STHROWF("Cannot use an empty parameter name");
}
// Attempt to find a parameter with the specified name
idx = sqlite3_bind_parameter_index(SQMOD_GET_CREATED(*this)->mPtr, val.mPtr);
} break;
// Is this an integer value? (or at least can be easily converted to one)
case OT_INTEGER:
case OT_FLOAT:
case OT_BOOL:
{
idx = ConvTo< Int32 >::From(PopStackInteger(vm, -1));
} break;
// Is this an instance that we can extract either a string or integer from it?
case OT_INSTANCE:
{
// Obtain the object from the stack as a string
StackStrF val(vm, -1);
// Validate the result
if (SQ_FAILED(val.Proc(false)))
{
STHROWF("%s", LastErrorString(vm).c_str());
}
// Is the obtained string empty?
else if (val.mLen <= 0)
{
STHROWF("Cannot use an empty parameter name");
}
// Check if this value is made only of digits
else if (IsDigitsOnly(val.mPtr))
{
idx = ConvNum< Int32 >::FromStr(val.mPtr);
}
// Attempt to find a parameter with the specified name
else
{
idx = sqlite3_bind_parameter_index(SQMOD_GET_CREATED(*this)->mPtr, val.mPtr);
}
} break;
// We don't recognize this kind of value!
default: STHROWF("Unknown parameter index of type (%s)", SqTypeName(param.GetType()));
}
// Assign the index with a failsafe to invalid on error
AutoAssign< Int32 > aa(m_Index, 0, idx);
// Validate the obtained parameter index
SQMOD_VALIDATE_PARAM(*this, idx);
// Don't fall back to the invalid index anymore
aa.Set(idx);
}
// ------------------------------------------------------------------------------------------------
Object Parameter::GetStatement() const
{
return GetStatementObj(m_Handle);
}
// ------------------------------------------------------------------------------------------------
Object Parameter::GetConnection() const
{
return GetConnectionObj(SQMOD_GET_VALID(*this)->mConn);
}
// ------------------------------------------------------------------------------------------------
void Parameter::SetValue(const Object & value)
{
switch (value.GetType())
{
case OT_NULL:
{
SetNull();
} break;
case OT_INTEGER:
{
SetInteger(value.Cast< SQInteger >());
} break;
case OT_FLOAT:
{
SetFloat(value.Cast< SQFloat >());
} break;
case OT_BOOL:
{
SetBool(value.Cast< bool >());
} break;
case OT_STRING:
{
SQMOD_VALIDATE_CREATED(*this);
// Remember the current stack size
const StackGuard sg;
// Push the object onto the stack
Var< Object >::push(DefaultVM::Get(), value);
// Pop the object from the stack as a string
const Var< CSStr > str(DefaultVM::Get(), -1);
// Attempt to bind the specified value
SetStringRaw(str.value, ConvTo< SQInteger >::From(str.size));
} break;
default: STHROWF("No known conversion for the specified value type");
}
}
// ------------------------------------------------------------------------------------------------
void Parameter::SetBool(bool value)
{
SQMOD_VALIDATE_CREATED(*this);
// Attempt to bind the specified value
m_Handle->mStatus = sqlite3_bind_int(m_Handle->mPtr, m_Index, value);
// Validate the result
if (m_Handle->mStatus != SQLITE_OK)
{
STHROWF(SQMOD_BINDFAILED, "bool", m_Index, m_Handle->ErrMsg());
}
}
// ------------------------------------------------------------------------------------------------
void Parameter::SetChar(SQInteger value)
{
SQMOD_VALIDATE_CREATED(*this);
// Attempt to bind the specified value
m_Handle->mStatus = sqlite3_bind_int(m_Handle->mPtr, m_Index, ConvTo< SQChar >::From(value));
// Validate the result
if (m_Handle->mStatus != SQLITE_OK)
{
STHROWF(SQMOD_BINDFAILED, "char", m_Index, m_Handle->ErrMsg());
}
}
// ------------------------------------------------------------------------------------------------
void Parameter::SetInteger(SQInteger value)
{
SQMOD_VALIDATE_CREATED(*this);
// Attempt to bind the specified value
m_Handle->mStatus = sqlite3_bind_integer(m_Handle->mPtr, m_Index, value);
// Validate the result
if (m_Handle->mStatus != SQLITE_OK)
{
STHROWF(SQMOD_BINDFAILED, "integer", m_Index, m_Handle->ErrMsg());
}
}
// ------------------------------------------------------------------------------------------------
void Parameter::SetInt8(SQInteger value)
{
SQMOD_VALIDATE_CREATED(*this);
// Attempt to bind the specified value
m_Handle->mStatus = sqlite3_bind_int(m_Handle->mPtr, m_Index, ConvTo< Int8 >::From(value));
// Validate the result
if (m_Handle->mStatus != SQLITE_OK)
{
STHROWF(SQMOD_BINDFAILED, "int8", m_Index, m_Handle->ErrMsg());
}
}
// ------------------------------------------------------------------------------------------------
void Parameter::SetUint8(SQInteger value)
{
SQMOD_VALIDATE_CREATED(*this);
// Attempt to bind the specified value
m_Handle->mStatus = sqlite3_bind_int(m_Handle->mPtr, m_Index, ConvTo< Uint8 >::From(value));
// Validate the result
if (m_Handle->mStatus != SQLITE_OK)
{
STHROWF(SQMOD_BINDFAILED, "uint8", m_Index, m_Handle->ErrMsg());
}
}
// ------------------------------------------------------------------------------------------------
void Parameter::SetInt16(SQInteger value)
{
SQMOD_VALIDATE_CREATED(*this);
// Attempt to bind the specified value
m_Handle->mStatus = sqlite3_bind_int(m_Handle->mPtr, m_Index, ConvTo< Int16 >::From(value));
// Validate the result
if (m_Handle->mStatus != SQLITE_OK)
{
STHROWF(SQMOD_BINDFAILED, "int16", m_Index, m_Handle->ErrMsg());
}
}
// ------------------------------------------------------------------------------------------------
void Parameter::SetUint16(SQInteger value)
{
SQMOD_VALIDATE_CREATED(*this);
// Attempt to bind the specified value
m_Handle->mStatus = sqlite3_bind_int(m_Handle->mPtr, m_Index, ConvTo< Uint16 >::From(value));
// Validate the result
if (m_Handle->mStatus != SQLITE_OK)
{
STHROWF(SQMOD_BINDFAILED, "uint16", m_Index, m_Handle->ErrMsg());
}
}
// ------------------------------------------------------------------------------------------------
void Parameter::SetInt32(SQInteger value)
{
SQMOD_VALIDATE_CREATED(*this);
// Attempt to bind the specified value
m_Handle->mStatus = sqlite3_bind_int(m_Handle->mPtr, m_Index, ConvTo< Int32 >::From(value));
// Validate the result
if (m_Handle->mStatus != SQLITE_OK)
{
STHROWF(SQMOD_BINDFAILED, "int32", m_Index, m_Handle->ErrMsg());
}
}
// ------------------------------------------------------------------------------------------------
void Parameter::SetUint32(SQInteger value)
{
SQMOD_VALIDATE_CREATED(*this);
// Attempt to bind the specified value
m_Handle->mStatus = sqlite3_bind_int(m_Handle->mPtr, m_Index, ConvTo< Uint32 >::From(value));
// Validate the result
if (m_Handle->mStatus != SQLITE_OK)
{
STHROWF(SQMOD_BINDFAILED, "uint32", m_Index, m_Handle->ErrMsg());
}
}
// ------------------------------------------------------------------------------------------------
void Parameter::SetInt64(const Object & value)
{
SQMOD_VALIDATE_CREATED(*this);
// Attempt to bind the specified value
m_Handle->mStatus = sqlite3_bind_int64(m_Handle->mPtr, m_Index, value.Cast< const SLongInt & >().GetNum());
// Validate the result
if (m_Handle->mStatus != SQLITE_OK)
{
STHROWF(SQMOD_BINDFAILED, "int64", m_Index, m_Handle->ErrMsg());
}
}
// ------------------------------------------------------------------------------------------------
void Parameter::SetUint64(const Object & value)
{
SQMOD_VALIDATE_CREATED(*this);
// Attempt to bind the specified value
m_Handle->mStatus = sqlite3_bind_int64(m_Handle->mPtr, m_Index, value.Cast< const ULongInt & >().GetNum());
// Validate the result
if (m_Handle->mStatus != SQLITE_OK)
{
STHROWF(SQMOD_BINDFAILED, "uint64", m_Index, m_Handle->ErrMsg());
}
}
// ------------------------------------------------------------------------------------------------
void Parameter::SetFloat(SQFloat value)
{
SQMOD_VALIDATE_CREATED(*this);
// Attempt to bind the specified value
m_Handle->mStatus = sqlite3_bind_double(m_Handle->mPtr, m_Index, value);
// Validate the result
if (m_Handle->mStatus != SQLITE_OK)
{
STHROWF(SQMOD_BINDFAILED, "float", m_Index, m_Handle->ErrMsg());
}
}
// ------------------------------------------------------------------------------------------------
void Parameter::SetFloat32(SQFloat value)
{
SQMOD_VALIDATE_CREATED(*this);
// Attempt to bind the specified value
m_Handle->mStatus = sqlite3_bind_double(m_Handle->mPtr, m_Index, ConvTo< Float32 >::From(value));
// Validate the result
if (m_Handle->mStatus != SQLITE_OK)
{
STHROWF(SQMOD_BINDFAILED, "float32", m_Index, m_Handle->ErrMsg());
}
}
// ------------------------------------------------------------------------------------------------
void Parameter::SetFloat64(SQFloat value)
{
SQMOD_VALIDATE_CREATED(*this);
// Attempt to bind the specified value
m_Handle->mStatus = sqlite3_bind_double(m_Handle->mPtr, m_Index, value);
// Validate the result
if (m_Handle->mStatus != SQLITE_OK)
{
STHROWF(SQMOD_BINDFAILED, "float64", m_Index, m_Handle->ErrMsg());
}
}
// ------------------------------------------------------------------------------------------------
void Parameter::SetString(StackStrF & value)
{
SQMOD_VALIDATE_CREATED(*this);
// Attempt to bind the specified value
m_Handle->mStatus = sqlite3_bind_text(m_Handle->mPtr, m_Index, value.mPtr, value.mLen, SQLITE_TRANSIENT);
// Validate the result
if (m_Handle->mStatus != SQLITE_OK)
{
STHROWF(SQMOD_BINDFAILED, "string", m_Index, m_Handle->ErrMsg());
}
}
// ------------------------------------------------------------------------------------------------
void Parameter::SetStringRaw(CSStr value, SQInteger length)
{
SQMOD_VALIDATE_CREATED(*this);
// Attempt to bind the specified value
m_Handle->mStatus = sqlite3_bind_text(m_Handle->mPtr, m_Index, value, length, SQLITE_TRANSIENT);
// Validate the result
if (m_Handle->mStatus != SQLITE_OK)
{
STHROWF(SQMOD_BINDFAILED, "string", m_Index, m_Handle->ErrMsg());
}
}
// ------------------------------------------------------------------------------------------------
void Parameter::SetZeroBlob(SQInteger size)
{
SQMOD_VALIDATE_CREATED(*this);
// Attempt to bind the specified value
m_Handle->mStatus = sqlite3_bind_zeroblob(m_Handle->mPtr, m_Index, ConvTo< Int32 >::From(size));
// Validate the result
if (m_Handle->mStatus != SQLITE_OK)
{
STHROWF(SQMOD_BINDFAILED, "blob", m_Index, m_Handle->ErrMsg());
}
}
// ------------------------------------------------------------------------------------------------
void Parameter::SetBlob(const Object & value)
{
SQMOD_VALIDATE_CREATED(*this);
// The blob data pointer and size
SQUserPointer ptr = nullptr;
SQInteger len = 0;
// Grab the associated object virtual machine
HSQUIRRELVM vm = value.GetVM();
// Extract the blob data from the specified object
{
// Remember the current stack size
const StackGuard sg(vm);
// Push the specified object onto the stack
Var< const Object & >::push(vm, value);
// Grab the blob data pointer
if (SQ_FAILED(sqstd_getblob(vm, -1, &ptr)))
{
STHROWF("Unable to obtain the blob data");
}
// Grab the blob data size
len = sqstd_getblobsize(vm, -1);
}
// Attempt to bind the specified value
m_Handle->mStatus = sqlite3_bind_blob(m_Handle->mPtr, m_Index, ptr, len, SQLITE_TRANSIENT);
// Validate the result
if (m_Handle->mStatus != SQLITE_OK)
{
STHROWF(SQMOD_BINDFAILED, "blob", m_Index, m_Handle->ErrMsg());
}
}
// ------------------------------------------------------------------------------------------------
void Parameter::SetData(const SqBuffer & value)
{
// Grab the internal buffer
Buffer & buff = *value.GetRef();
// Attempt to bind the specified value
#ifdef _SQ64
m_Handle->mStatus = sqlite3_bind_blob64(m_Handle->mPtr, m_Index, buff.Data(), buff.Position(), SQLITE_TRANSIENT);
#else
m_Handle->mStatus = sqlite3_bind_blob(m_Handle->mPtr, m_Index, buff.Data(), buff.Position(), SQLITE_TRANSIENT);
#endif
// Validate the result
if (m_Handle->mStatus != SQLITE_OK)
{
STHROWF(SQMOD_BINDFAILED, "buffer", m_Index, m_Handle->ErrMsg());
}
}
// ------------------------------------------------------------------------------------------------
void Parameter::SetDataEx(const SqBuffer & value, SQInteger offset, SQInteger length)
{
// Grab the internal buffer
Buffer & buff = *value.GetRef();
// Make sure we are within range
if (offset < 0)
{
STHROWF("Negative buffer offset is not allowed: %d", offset);
}
else if (offset < 0)
{
STHROWF("Negative buffer length is not allowed: %d", length);
}
else if (offset + length > buff.Capacity())
{
STHROWF("Buffer range is outside boundaries: (%d+%d) > %u", offset, length, buff.Capacity());
}
// Attempt to bind the specified value
#ifdef _SQ64
m_Handle->mStatus = sqlite3_bind_blob64(m_Handle->mPtr, m_Index, (buff.Data() + offset), static_cast< int >(offset + length), SQLITE_TRANSIENT);
#else
m_Handle->mStatus = sqlite3_bind_blob(m_Handle->mPtr, m_Index, (buff.Data() + offset), static_cast< int >(offset + length), SQLITE_TRANSIENT);
#endif
// Validate the result
if (m_Handle->mStatus != SQLITE_OK)
{
STHROWF(SQMOD_BINDFAILED, "buffer", m_Index, m_Handle->ErrMsg());
}
}
// ------------------------------------------------------------------------------------------------
void Parameter::SetDate(const Date & value)
{
SQMOD_VALIDATE_CREATED(*this);
// Attempt to generate the specified date string
CSStr ptr = FmtStr(_SC("%s 00:00:00"), value.ToString());
// Attempt to bind the specified value
m_Handle->mStatus = sqlite3_bind_text(m_Handle->mPtr, m_Index, ptr, -1, SQLITE_TRANSIENT);
// Validate the result
if (m_Handle->mStatus != SQLITE_OK)
{
STHROWF(SQMOD_BINDFAILED, "date", m_Index, m_Handle->ErrMsg());
}
}
// ------------------------------------------------------------------------------------------------
void Parameter::SetDateEx(SQInteger year, SQInteger month, SQInteger day)
{
SQMOD_VALIDATE_CREATED(*this);
// Convert the specified values within the proper ranges
const uint16_t y = ConvTo< uint16_t >::From(year);
const uint8_t m = ConvTo< uint8_t >::From(month), d = ConvTo< uint8_t >::From(day);
// Validate the specified date
if (!Chrono::ValidDate(y, m, d))
{
STHROWF("Invalid date (%u-%u-%u)", y, m, d);
}
// Attempt to generate the specified date string
CSStr ptr = FmtStr(_SC("%u-%u-%u 00:00:00"), y, m, d);
// Attempt to bind the specified value
m_Handle->mStatus = sqlite3_bind_text(m_Handle->mPtr, m_Index, ptr, -1, SQLITE_TRANSIENT);
// Validate the result
if (m_Handle->mStatus != SQLITE_OK)
{
STHROWF(SQMOD_BINDFAILED, "date", m_Index, m_Handle->ErrMsg());
}
}
// ------------------------------------------------------------------------------------------------
void Parameter::SetTime(const Time & value)
{
SQMOD_VALIDATE_CREATED(*this);
// Attempt to bind the specified value
m_Handle->mStatus = sqlite3_bind_int(m_Handle->mPtr, m_Index, value.GetTimestamp().GetSecondsI());
// Validate the result
if (m_Handle->mStatus != SQLITE_OK)
{
STHROWF(SQMOD_BINDFAILED, "time", m_Index, m_Handle->ErrMsg());
}
}
// ------------------------------------------------------------------------------------------------
void Parameter::SetTimeEx(SQInteger hour, SQInteger minute, SQInteger second)
{
SQMOD_VALIDATE_CREATED(*this);
// Convert the specified values within the proper ranges
const uint8_t h = ConvTo< uint8_t >::From(hour)
, m = ConvTo< uint8_t >::From(minute)
, s = ConvTo< uint8_t >::From(second);
// Is the specified hour within range?
if (h >= 24)
{
STHROWF("Hour value is out of range: %u >= 24", h);
}
// Is the specified minute within range?
else if (m >= 60)
{
STHROWF("Minute value is out of range: %u >= 60", m);
}
// Is the specified second within range?
else if (s >= 60)
{
STHROWF("Second value is out of range: %u >= 60", s);
}
// Calculate the number of seconds in the specified time and bind the resulted value
m_Handle->mStatus = sqlite3_bind_int(m_Handle->mPtr, m_Index, (h * (60 * 60)) + (m * 60) + s);
// Validate the result
if (m_Handle->mStatus != SQLITE_OK)
{
STHROWF(SQMOD_BINDFAILED, "time", m_Index, m_Handle->ErrMsg());
}
}
// ------------------------------------------------------------------------------------------------
void Parameter::SetDatetime(const Datetime & value)
{
SetDatetimeEx(value.GetYear(), value.GetMonth(), value.GetDay(), value.GetHour(), value.GetMinute(), value.GetSecond());
}
// ------------------------------------------------------------------------------------------------
void Parameter::SetDatetimeEx(SQInteger year, SQInteger month, SQInteger day, SQInteger hour, SQInteger minute, SQInteger second)
{
SQMOD_VALIDATE_CREATED(*this);
// Convert the specified values within the proper ranges
const uint16_t y = ConvTo< uint16_t >::From(year);
const uint8_t mo = ConvTo< uint8_t >::From(month)
, d = ConvTo< uint8_t >::From(day)
, h = ConvTo< uint8_t >::From(hour)
, mi = ConvTo< uint8_t >::From(minute)
, s = ConvTo< uint8_t >::From(second);
// Validate the specified date
if (!Chrono::ValidDate(y, mo, d))
{
STHROWF("Invalid date (%u-%u-%u)", y, mo, d);
}
// Is the specified hour within range?
else if (h >= 24)
{
STHROWF("Hour value is out of range: %u >= 24", h);
}
// Is the specified minute within range?
else if (mi >= 60)
{
STHROWF("Minute value is out of range: %u >= 60", mi);
}
// Is the specified second within range?
else if (s >= 60)
{
STHROWF("Second value is out of range: %u >= 60", s);
}
// Attempt to generate the specified date string
CSStr ptr = FmtStr(_SC("%04u-%02u-%02u %02u:%02u:%02u"), y, mo, d, h, mi, s);
// Attempt to bind the specified value
m_Handle->mStatus = sqlite3_bind_text(m_Handle->mPtr, m_Index, ptr, -1, SQLITE_TRANSIENT);
// Validate the result
if (m_Handle->mStatus != SQLITE_OK)
{
STHROWF(SQMOD_BINDFAILED, "date-time", m_Index, m_Handle->ErrMsg());
}
}
// ------------------------------------------------------------------------------------------------
void Parameter::SetNow()
{
SQMOD_VALIDATE_CREATED(*this);
// Attempt to bind the specified value
m_Handle->mStatus = sqlite3_bind_int(m_Handle->mPtr, m_Index,
static_cast< Int32 >(std::time(nullptr)));
// Validate the result
if (m_Handle->mStatus != SQLITE_OK)
{
STHROWF(SQMOD_BINDFAILED, "time-stamp", m_Index, m_Handle->ErrMsg());
}
}
// ------------------------------------------------------------------------------------------------
void Parameter::SetNull()
{
SQMOD_VALIDATE_CREATED(*this);
// Attempt to bind the specified value
m_Handle->mStatus = sqlite3_bind_null(m_Handle->mPtr, m_Index);
// Validate the result
if (m_Handle->mStatus != SQLITE_OK)
{
STHROWF(SQMOD_BINDFAILED, "null", m_Index, m_Handle->ErrMsg());
}
}
// ================================================================================================
void Register_Parameter(Table & sqlns)
{
sqlns.Bind(_SC("Parameter"),
Class< Parameter >(sqlns.GetVM(), Typename::Str)
// Constructors
.Ctor()
.Ctor< const Parameter & >()
// Meta-methods
.SquirrelFunc(_SC("_typename"), &Typename::Fn)
.Func(_SC("_tostring"), &Parameter::ToString)
// Properties
.Prop(_SC("IsValid"), &Parameter::IsValid)
.Prop(_SC("References"), &Parameter::GetRefCount)
.Prop(_SC("Index"), &Parameter::GetIndex)
.Prop(_SC("Statement"), &Parameter::GetStatement)
.Prop(_SC("Connection"), &Parameter::GetConnection)
.Prop(_SC("References"), &Parameter::GetRefCount)
.Prop(_SC("Name"), &Parameter::GetName)
// Member Methods
.Func(_SC("Release"), &Parameter::Release)
.Func(_SC("SetValue"), &Parameter::SetValue)
.Func(_SC("SetBool"), &Parameter::SetBool)
.Func(_SC("SetChar"), &Parameter::SetChar)
.Func(_SC("SetInteger"), &Parameter::SetInteger)
.Func(_SC("SetInt8"), &Parameter::SetInt8)
.Func(_SC("SetUint8"), &Parameter::SetUint8)
.Func(_SC("SetInt16"), &Parameter::SetInt16)
.Func(_SC("SetUint16"), &Parameter::SetUint16)
.Func(_SC("SetInt32"), &Parameter::SetInt32)
.Func(_SC("SetUint32"), &Parameter::SetUint32)
.Func(_SC("SetInt64"), &Parameter::SetInt64)
.Func(_SC("SetUint64"), &Parameter::SetUint64)
.Func(_SC("SetFloat"), &Parameter::SetFloat)
.Func(_SC("SetFloat32"), &Parameter::SetFloat32)
.Func(_SC("SetFloat64"), &Parameter::SetFloat64)
.FmtFunc(_SC("SetString"), &Parameter::SetString)
.Func(_SC("SetZeroBlob"), &Parameter::SetZeroBlob)
.Func(_SC("SetBlob"), &Parameter::SetBlob)
.Func(_SC("SetData"), &Parameter::SetData)
.Func(_SC("SetDataEx"), &Parameter::SetDataEx)
.Func(_SC("SetDate"), &Parameter::SetDate)
.Func(_SC("SetDateEx"), &Parameter::SetDateEx)
.Func(_SC("SetTime"), &Parameter::SetTime)
.Func(_SC("SetTimeEx"), &Parameter::SetTimeEx)
.Func(_SC("SetDatetime"), &Parameter::SetDatetime)
.Func(_SC("SetDatetimeEx"), &Parameter::SetDatetimeEx)
.Func(_SC("SetNow"), &Parameter::SetNow)
.Func(_SC("SetNull"), &Parameter::SetNull)
);
}
} // Namespace:: SqMod

View File

@@ -1,411 +0,0 @@
#pragma once
// ------------------------------------------------------------------------------------------------
#include "Library/SQLite/Handle.hpp"
// ------------------------------------------------------------------------------------------------
#include <cctype>
// ------------------------------------------------------------------------------------------------
namespace SqMod {
/* ------------------------------------------------------------------------------------------------
* Used to manage and interact with parameters from a database statement.
*/
class Parameter
{
// --------------------------------------------------------------------------------------------
friend class Statement;
private:
// --------------------------------------------------------------------------------------------
Int32 m_Index; // The index of the managed parameter.
StmtRef m_Handle; // Reference to the managed statement.
protected:
/* --------------------------------------------------------------------------------------------
* Validate the managed statement handle and throw an error if invalid.
*/
#if defined(_DEBUG) || defined(SQMOD_EXCEPTLOC)
void Validate(CCStr file, Int32 line) const;
#else
void Validate() const;
#endif // _DEBUG
/* --------------------------------------------------------------------------------------------
* Validate the managed statement handle and throw an error if invalid.
*/
#if defined(_DEBUG) || defined(SQMOD_EXCEPTLOC)
void ValidateCreated(CCStr file, Int32 line) const;
#else
void ValidateCreated() const;
#endif // _DEBUG
/* --------------------------------------------------------------------------------------------
* Validate the managed statement handle and throw an error if invalid.
*/
#if defined(_DEBUG) || defined(SQMOD_EXCEPTLOC)
const StmtRef & GetValid(CCStr file, Int32 line) const;
#else
const StmtRef & GetValid() const;
#endif // _DEBUG
/* --------------------------------------------------------------------------------------------
* Validate the managed statement handle and throw an error if invalid.
*/
#if defined(_DEBUG) || defined(SQMOD_EXCEPTLOC)
const StmtRef & GetCreated(CCStr file, Int32 line) const;
#else
const StmtRef & GetCreated() const;
#endif // _DEBUG
/* --------------------------------------------------------------------------------------------
* Validate the statement reference and parameter index, and throw an error if they're invalid.
*/
#if defined(_DEBUG) || defined(SQMOD_EXCEPTLOC)
void ValidateParam(Int32 idx, CCStr file, Int32 line) const;
#else
void ValidateParam(Int32 idx) const;
#endif // _DEBUG
/* --------------------------------------------------------------------------------------------
* Modify the index to the specified value.
*/
void SetIndex(Int32 idx)
{
// Assign the index with a failsafe to invalid on error
AutoAssign< Int32 > aa(m_Index, -1, idx);
// Validate the obtained parameter index
SQMOD_VALIDATE_PARAM(*this, idx);
// Don't fall back to the invalid index anymore
aa.Set(idx);
}
/* --------------------------------------------------------------------------------------------
* Modify the index to the specified value.
*/
void SetIndex(CSStr name)
{
SetIndex(sqlite3_bind_parameter_index(SQMOD_GET_CREATED(*this)->mPtr, name));
}
/* --------------------------------------------------------------------------------------------
* Modify the index to the specified value.
*/
void SetIndex(const Object & param);
public:
/* --------------------------------------------------------------------------------------------
* Default constructor (null).
*/
Parameter()
: m_Index(0), m_Handle()
{
/* ... */
}
/* --------------------------------------------------------------------------------------------
* No parameter constructor.
*/
Parameter(const StmtRef & stmt)
: m_Index(0), m_Handle(stmt)
{
/* ... */
}
/* --------------------------------------------------------------------------------------------
* Index constructor.
*/
Parameter(const StmtRef & stmt, Int32 idx)
: m_Index(idx), m_Handle(stmt)
{
SQMOD_VALIDATE_PARAM(*this, m_Index);
}
/* --------------------------------------------------------------------------------------------
* Name constructor.
*/
Parameter(const StmtRef & stmt, CSStr name)
: m_Index(stmt ? sqlite3_bind_parameter_index(stmt->mPtr, name) : 0), m_Handle(stmt)
{
SQMOD_VALIDATE_PARAM(*this, m_Index);
}
/* --------------------------------------------------------------------------------------------
* Dynamic constructor.
*/
Parameter(const StmtRef & stmt, const Object & param)
: m_Index(0), m_Handle(stmt)
{
if (!m_Handle)
{
STHROWF("Invalid SQLite statement reference");
}
// Extract the index
SetIndex(param);
}
/* --------------------------------------------------------------------------------------------
* Copy constructor.
*/
Parameter(const Parameter & o) = default;
/* --------------------------------------------------------------------------------------------
* Move constructor.
*/
Parameter(Parameter && o) = default;
/* --------------------------------------------------------------------------------------------
* Copy assignment operator.
*/
Parameter & operator = (const Parameter & o) = default;
/* --------------------------------------------------------------------------------------------
* Move assignment operator.
*/
Parameter & operator = (Parameter && o) = default;
/* --------------------------------------------------------------------------------------------
* Perform an equality comparison between two parameter indexes.
*/
bool operator == (const Parameter & o) const
{
return (m_Index == o.m_Index);
}
/* --------------------------------------------------------------------------------------------
* Perform an inequality comparison between two parameter indexes.
*/
bool operator != (const Parameter & o) const
{
return (m_Index != o.m_Index);
}
/* --------------------------------------------------------------------------------------------
* Implicit conversion to boolean for use in boolean operations.
*/
operator bool () const
{
return m_Index >= 0;
}
/* --------------------------------------------------------------------------------------------
* Used by the script engine to convert an instance of this type to a string.
*/
CSStr ToString() const
{
CSStr val = nullptr;
// Can we attempt to return the parameter name?
if (m_Handle && m_Index)
{
val = sqlite3_bind_parameter_name(m_Handle->mPtr, m_Index);
}
else
{
val = ToStrF(_SC("%d"), m_Index);
}
// Return the value if valid
return val ? val : _SC("");
}
/* --------------------------------------------------------------------------------------------
* See whether this statement is valid.
*/
bool IsValid() const
{
return m_Handle; // An invalid statement means an invalid parameter
}
/* --------------------------------------------------------------------------------------------
* Return the number of active references to this statement handle.
*/
Uint32 GetRefCount() const
{
return m_Handle.Count();
}
/* --------------------------------------------------------------------------------------------
* Retrieve the associated parameter index.
*/
Int32 GetIndex() const
{
return m_Index;
}
/* --------------------------------------------------------------------------------------------
* Retrieve the associated database statement.
*/
Object GetStatement() const;
/* --------------------------------------------------------------------------------------------
* Retrieve the associated database connection.
*/
Object GetConnection() const;
/* --------------------------------------------------------------------------------------------
* Retrieve the name of the referenced parameter.
*/
CSStr GetName() const
{
return sqlite3_bind_parameter_name(SQMOD_GET_CREATED(*this)->mPtr, m_Index);
}
/* --------------------------------------------------------------------------------------------
* Release the reference to the associated database statement and parameter index.
*/
void Release()
{
m_Handle.Reset();
m_Index = 0;
}
/* --------------------------------------------------------------------------------------------
* Attempt to bind a dynamic value at the referenced parameter index.
*/
void SetValue(const Object & value);
/* --------------------------------------------------------------------------------------------
* Attempt to bind a boolean value at the referenced parameter index.
*/
void SetBool(bool value);
/* --------------------------------------------------------------------------------------------
* Attempt to bind a character value at the referenced parameter index.
*/
void SetChar(SQInteger value);
/* --------------------------------------------------------------------------------------------
* Attempt to bind a native integer value at the referenced parameter index.
*/
void SetInteger(SQInteger value);
/* --------------------------------------------------------------------------------------------
* Attempt to bind a signed 8 bit integer value at the referenced parameter index.
*/
void SetInt8(SQInteger value);
/* --------------------------------------------------------------------------------------------
* Attempt to bind an unsigned 8 bit integer value at the referenced parameter index.
*/
void SetUint8(SQInteger value);
/* --------------------------------------------------------------------------------------------
* Attempt to bind a signed 16 bit integer value at the referenced parameter index.
*/
void SetInt16(SQInteger value);
/* --------------------------------------------------------------------------------------------
* Attempt to bind an unsigned 16 bit integer value at the referenced parameter index.
*/
void SetUint16(SQInteger value);
/* --------------------------------------------------------------------------------------------
* Attempt to bind a signed 32 bit integer value at the referenced parameter index.
*/
void SetInt32(SQInteger value);
/* --------------------------------------------------------------------------------------------
* Attempt to bind an unsigned 32 bit integer value at the referenced parameter index.
*/
void SetUint32(SQInteger value);
/* --------------------------------------------------------------------------------------------
* Attempt to bind a signed 64 bit integer value at the referenced parameter index.
*/
void SetInt64(const Object & value);
/* --------------------------------------------------------------------------------------------
* Attempt to bind an unsigned 64 bit integer value at the referenced parameter index.
*/
void SetUint64(const Object & value);
/* --------------------------------------------------------------------------------------------
* Attempt to bind a native floating point value at the referenced parameter index.
*/
void SetFloat(SQFloat value);
/* --------------------------------------------------------------------------------------------
* Attempt to bind a 32 bit floating point value at the referenced parameter index.
*/
void SetFloat32(SQFloat value);
/* --------------------------------------------------------------------------------------------
* Attempt to bind a 64 bit floating point value at the referenced parameter index.
*/
void SetFloat64(SQFloat value);
/* --------------------------------------------------------------------------------------------
* Attempt to bind a string value at the referenced parameter index.
*/
void SetString(StackStrF & value);
/* --------------------------------------------------------------------------------------------
* Attempt to bind a string value at the referenced parameter index.
*/
void SetStringRaw(CSStr value, SQInteger length = -1);
/* --------------------------------------------------------------------------------------------
* Attempt to bind a zeroed blob value at the referenced parameter index.
*/
void SetZeroBlob(SQInteger size);
/* --------------------------------------------------------------------------------------------
* Attempt to bind a blob value at the referenced parameter index.
*/
void SetBlob(const Object & value);
/* --------------------------------------------------------------------------------------------
* Attempt to bind a buffer value at the referenced parameter index.
*/
void SetData(const SqBuffer & value);
/* --------------------------------------------------------------------------------------------
* Attempt to bind a buffer value at the referenced parameter index.
*/
void SetDataEx(const SqBuffer & value, SQInteger offset, SQInteger length);
/* --------------------------------------------------------------------------------------------
* Attempt to bind a date value at the referenced parameter index.
*/
void SetDate(const Date & value);
/* --------------------------------------------------------------------------------------------
* Attempt to bind a date value at the referenced parameter index.
*/
void SetDateEx(SQInteger year, SQInteger month, SQInteger day);
/* --------------------------------------------------------------------------------------------
* Attempt to bind a time value at the referenced parameter index.
*/
void SetTime(const Time & value);
/* --------------------------------------------------------------------------------------------
* Attempt to bind a time value at the referenced parameter index.
*/
void SetTimeEx(SQInteger hour, SQInteger minute, SQInteger second);
/* --------------------------------------------------------------------------------------------
* Attempt to bind a date-time value at the referenced parameter index.
*/
void SetDatetime(const Datetime & value);
/* --------------------------------------------------------------------------------------------
* Attempt to bind a date-time value at the referenced parameter index.
*/
void SetDatetimeEx(SQInteger year, SQInteger month, SQInteger day, SQInteger hour, SQInteger minute, SQInteger second);
/* --------------------------------------------------------------------------------------------
* Attempt to bind the current timestamp at the referenced parameter index.
*/
void SetNow();
/* --------------------------------------------------------------------------------------------
* Attempt to bind a null value at the referenced parameter index.
*/
void SetNull();
};
} // Namespace:: SqMod

View File

@@ -1,525 +0,0 @@
// ------------------------------------------------------------------------------------------------
#include "Library/SQLite/Statement.hpp"
#include "Library/SQLite/Connection.hpp"
#include "Library/SQLite/Column.hpp"
// ------------------------------------------------------------------------------------------------
#include <cstring>
// ------------------------------------------------------------------------------------------------
namespace SqMod {
// ------------------------------------------------------------------------------------------------
SQMODE_DECL_TYPENAME(Typename, _SC("SqLiteStatement"))
// ------------------------------------------------------------------------------------------------
#if defined(_DEBUG) || defined(SQMOD_EXCEPTLOC)
void Statement::Validate(CCStr file, Int32 line) const
{
if (!m_Handle)
{
SqThrowF("Invalid SQLite statement reference =>[%s:%d]", file, line);
}
}
#else
void Statement::Validate() const
{
if (!m_Handle)
{
SqThrowF("Invalid SQLite statement reference");
}
}
#endif // _DEBUG
// ------------------------------------------------------------------------------------------------
#if defined(_DEBUG) || defined(SQMOD_EXCEPTLOC)
void Statement::ValidateCreated(CCStr file, Int32 line) const
{
if (!m_Handle)
{
SqThrowF("Invalid SQLite statement reference =>[%s:%d]", file, line);
}
else if (m_Handle->mPtr == nullptr)
{
SqThrowF("Invalid SQLite statement =>[%s:%d]", file, line);
}
}
#else
void Statement::ValidateCreated() const
{
if (!m_Handle)
{
SqThrowF("Invalid SQLite statement reference");
}
else if (m_Handle->mPtr == nullptr)
{
SqThrowF("Invalid SQLite statement");
}
}
#endif // _DEBUG
// ------------------------------------------------------------------------------------------------
#if defined(_DEBUG) || defined(SQMOD_EXCEPTLOC)
const StmtRef & Statement::GetValid(CCStr file, Int32 line) const
{
Validate(file, line);
return m_Handle;
}
#else
const StmtRef & Statement::GetValid() const
{
Validate();
return m_Handle;
}
#endif // _DEBUG
// ------------------------------------------------------------------------------------------------
#if defined(_DEBUG) || defined(SQMOD_EXCEPTLOC)
const StmtRef & Statement::GetCreated(CCStr file, Int32 line) const
{
ValidateCreated(file, line);
return m_Handle;
}
#else
const StmtRef & Statement::GetCreated() const
{
ValidateCreated();
return m_Handle;
}
#endif // _DEBUG
// ------------------------------------------------------------------------------------------------
#if defined(_DEBUG) || defined(SQMOD_EXCEPTLOC)
void Statement::ValidateColumn(Int32 idx, CCStr file, Int32 line) const
{
ValidateCreated(file, line);
// Is the specified index in range?
if (!m_Handle->CheckColumn(idx))
{
SqThrowF("Column index is out of range: %d:%d =>[%s:%d]", idx, m_Handle->mColumns,
file, line);
}
}
#else
void Statement::ValidateColumn(Int32 idx) const
{
ValidateCreated();
// Is the specified index in range?
if (!m_Handle->CheckColumn(idx))
{
SqThrowF("Column index is out of range: %d:%d", idx, m_Handle->mColumns);
}
}
#endif // _DEBUG
// ------------------------------------------------------------------------------------------------
#if defined(_DEBUG) || defined(SQMOD_EXCEPTLOC)
void Statement::ValidateParam(Int32 idx, CCStr file, Int32 line) const
{
ValidateCreated(file, line);
// Is the specified index in range?
if (!m_Handle->CheckParameter(idx))
{
SqThrowF("Parameter index is out of range: %d:%d =>[%s:%d]", idx, m_Handle->mParameters,
file, line);
}
}
#else
void Statement::ValidateParam(Int32 idx) const
{
ValidateCreated();
// Is the specified index in range?
if (!m_Handle->CheckParameter(idx))
{
SqThrowF("Parameter index is out of range: %d:%d", idx, m_Handle->mParameters);
}
}
#endif // _DEBUG
// ------------------------------------------------------------------------------------------------
#if defined(_DEBUG) || defined(SQMOD_EXCEPTLOC)
void Statement::ValidateRow(CCStr file, Int32 line) const
{
ValidateCreated(file, line);
// Do we have any rows available?
if (!m_Handle->mGood)
{
SqThrowF("No row available =>[%s:%d]", file, line);
}
}
#else
void Statement::ValidateRow() const
{
ValidateCreated();
// Do we have any rows available?
if (!m_Handle->mGood)
{
SqThrowF("No row available");
}
}
#endif // _DEBUG
// ------------------------------------------------------------------------------------------------
Statement::Statement(const Connection & connection, StackStrF & query)
: m_Handle(new StmtHnd(connection.GetHandle()))
{
SQMOD_GET_VALID(*this)->Create(query.mPtr, query.mLen);
}
// ------------------------------------------------------------------------------------------------
Object Statement::GetConnection() const
{
return Object(new Connection(SQMOD_GET_VALID(*this)->mConn));
}
// ------------------------------------------------------------------------------------------------
Statement & Statement::Reset()
{
SQMOD_VALIDATE_CREATED(*this);
// Specify that we don't have a row available and we haven't finished stepping
m_Handle->mGood = false;
m_Handle->mDone = false;
// Attempt to reset the statement to it's initial state
m_Handle->mStatus = sqlite3_reset(m_Handle->mPtr);
// Validate the result
if (m_Handle->mStatus != SQLITE_OK)
{
STHROWF("Unable to reset statement [%s]", m_Handle->ErrStr());
}
// Allow further chaining of operations
return *this;
}
// ------------------------------------------------------------------------------------------------
Statement & Statement::Clear()
{
SQMOD_VALIDATE_CREATED(*this);
// Specify that we don't have a row available and we haven't finished stepping
m_Handle->mGood = false;
m_Handle->mDone = false;
// Attempt to clear the statement
m_Handle->mStatus = sqlite3_clear_bindings(m_Handle->mPtr);
// Validate the result
if (m_Handle->mStatus != SQLITE_OK)
{
STHROWF("Unable to clear statement [%s]", m_Handle->ErrStr());
}
// Allow further chaining of operations
return *this;
}
// ------------------------------------------------------------------------------------------------
Int32 Statement::Exec()
{
SQMOD_VALIDATE_CREATED(*this);
// Did we reset first?
if (m_Handle->mDone)
{
STHROWF("Executed without resetting first");
}
// Attempt to step the statement
m_Handle->mStatus = sqlite3_step(m_Handle->mPtr);
// Have we finished stepping?
if (m_Handle->mStatus == SQLITE_DONE)
{
// Specify that we don't have row available and we finished stepping
m_Handle->mGood = false;
m_Handle->mDone = true;
// Return the changes made by this statement
return sqlite3_changes(m_Handle->mConn->mPtr);
}
// Specify that we don't have any row and we haven't finished stepping
m_Handle->mGood = false;
m_Handle->mDone = false;
// Inspect the result
switch (m_Handle->mStatus)
{
// We don't expect any rows to be returned in this case!
case SQLITE_ROW: STHROWF("Results were found");
// fall through
case SQLITE_BUSY: STHROWF("Database was busy");
// fall through
case SQLITE_ERROR: STHROWF("Runtime error occurred");
// fall through
case SQLITE_MISUSE: STHROWF("Statement misuse");
// fall through
default: STHROWF("Unknown failure [%s]", m_Handle->ErrStr());
}
// Operation failed (shouldn't reach this point!)
return -1;
}
// ------------------------------------------------------------------------------------------------
bool Statement::Step()
{
SQMOD_VALIDATE_CREATED(*this);
// Did we reset first?
if (m_Handle->mDone)
{
STHROWF("Stepped without resetting first");
}
// Attempt to step the statement
m_Handle->mStatus = sqlite3_step(m_Handle->mPtr);
// Do we have a row available?
if (m_Handle->mStatus == SQLITE_ROW)
{
// Specify that we have a row available
return (m_Handle->mGood = true);
}
// Have we finished stepping?
else if (m_Handle->mStatus == SQLITE_DONE)
{
// Specify that we finished stepping
m_Handle->mDone = true;
// Specify that we don't have a row available
return (m_Handle->mGood = false);
}
// Specify that we don't have any row and we haven't finished stepping
m_Handle->mGood = false;
m_Handle->mDone = false;
// Inspect the result
switch (m_Handle->mStatus)
{
case SQLITE_BUSY: STHROWF("Database was busy");
// fall through
case SQLITE_ERROR: STHROWF("Runtime error occurred");
// fall through
case SQLITE_MISUSE: STHROWF("Statement misuse");
// fall through
default: STHROWF("Unknown failure [%s]", m_Handle->ErrStr());
}
// Operation failed (shouldn't reach this point!)
return false;
}
// ------------------------------------------------------------------------------------------------
Statement & Statement::SetArray(Int32 idx, const Array & arr)
{
// Obtain a script iterator
Array::iterator itr;
// Create a parameter instance to bind the values
Parameter param(m_Handle);
// Process each element until _next returns null
while (idx <= m_Handle->mParameters && arr.Next(itr))
{
// Update the parameter index
param.SetIndex(idx++);
// Bind it to the current index
param.SetValue(Object(itr.getValue()));
}
// Allow further chaining of operations
return *this;
}
// ------------------------------------------------------------------------------------------------
Statement & Statement::SetTable(const Table & tbl)
{
// Is there anything to bind?
if (tbl.GetSize() <= 0)
{
return *this; // Nothing to bind!
}
// Obtain a table iterator
Table::iterator itr;
// Create a parameter instance to bind the values
Parameter param(m_Handle);
// Process each element until _next returns null
while (tbl.Next(itr))
{
// Update the parameter index
param.SetIndex(itr.getName());
// Bind it to the current index
param.SetValue(Object(itr.getValue()));
}
// Allow further chaining of operations
return *this;
}
// ------------------------------------------------------------------------------------------------
Array Statement::GetArray(Int32 min, Int32 max) const
{
SQMOD_VALIDATE_ROW(*this);
// Is the specified minimum index valid?
if (min < 0)
{
STHROWF("Minimum is bellow zero: %d", min);
}
// Is the minimum actually the minimum?
else if (min > max)
{
STHROWF("Minimum is higher than maximum: %d > %d", min, max);
}
// Is the minimum in range?
else if (!m_Handle->CheckColumn(min))
{
STHROWF("Minimum is out of range: %d:%d", min, m_Handle->mColumns);
}
// Is the maximum in range?
else if (!m_Handle->CheckColumn(max))
{
STHROWF("Maximum is out of range: %d:%d", max, m_Handle->mColumns);
}
// Allocate an array large enough to hold the values from selected columns
Array arr(DefaultVM::Get(), max-min);
// Create a column instance to retrieve the values
Column column(m_Handle);
// Array element counter
Int32 elem = 0;
// Process the range of selected columns
while (min <= max)
{
// Update the column index
column.SetIndex(min++);
// Retrieve the column value and bind it to the array
arr.SetValue(elem++, column.GetValue());
}
// Return the resulted array
return arr;
}
// ------------------------------------------------------------------------------------------------
Table Statement::GetTable(Int32 min, Int32 max) const
{
SQMOD_VALIDATE_ROW(*this);
// Is the specified minimum index valid?
if (min < 0)
{
STHROWF("Minimum is bellow zero: %d", min);
}
// Is the minimum actually the minimum?
else if (min > max)
{
STHROWF("Minimum is higher than maximum: %d > %d", min, max);
}
// Is the minimum in range>
else if (!m_Handle->CheckColumn(min))
{
STHROWF("Minimum is out of range: %d:%d", min, m_Handle->mColumns);
}
// Is the maximum in range?
else if (!m_Handle->CheckColumn(max))
{
STHROWF("Maximum is out of range: %d:%d", max, m_Handle->mColumns);
}
// Create a table to hold the selected column values
Table tbl(DefaultVM::Get());
// Create a column instance to retrieve the values
Column column(m_Handle);
// Process the range of selected columns
while (min <= max)
{
// Attempt to obtain the column name
CSStr name = sqlite3_column_name(m_Handle->mPtr, min);
// Validate the obtained name
if (!name)
{
STHROWF("Unable to retrieve name of column (%d)", min);
}
// Update the column index
column.SetIndex(min++);
// Retrieve the column value and bind it to the table
tbl.SetValue(name, column.GetValue());
}
// Return the resulted table
return tbl;
}
// ================================================================================================
void Register_Statement(Table & sqlns)
{
sqlns.Bind(_SC("Statement"),
Class< Statement >(sqlns.GetVM(), Typename::Str)
// Constructors
.Ctor()
.Ctor< const Statement & >()
.Ctor< const Connection &, StackStrF & >()
// Meta-methods
.SquirrelFunc(_SC("_typename"), &Typename::Fn)
.Func(_SC("_tostring"), &Statement::ToString)
// Properties
.Prop(_SC("IsValid"), &Statement::IsValid)
.Prop(_SC("Prepared"), &Statement::IsPrepared)
.Prop(_SC("References"), &Statement::GetReferences)
.Prop(_SC("Connection"), &Statement::GetConnection)
.Prop(_SC("Status"), &Statement::GetStatus)
.Prop(_SC("ErrCode"), &Statement::GetErrorCode)
.Prop(_SC("ExErrCode"), &Statement::GetExtendedErrorCode)
.Prop(_SC("ExtendedErrCode"), &Statement::GetExtendedErrorCode)
.Prop(_SC("ErrStr"), &Statement::GetErrStr)
.Prop(_SC("ErrMsg"), &Statement::GetErrMsg)
.Prop(_SC("Columns"), &Statement::GetColumns)
.Prop(_SC("Parameters"), &Statement::GetParameters)
.Prop(_SC("Query"), &Statement::GetQuery)
.Prop(_SC("Good"), &Statement::GetGood)
.Prop(_SC("Done"), &Statement::GetDone)
.Prop(_SC("DataCount"), &Statement::GetDataCount)
// Member Methods
.Func(_SC("Release"), &Statement::Release)
.Func(_SC("CheckParameter"), &Statement::CheckParameter)
.FmtFunc(_SC("GetParameterIndex"), &Statement::GetParameterIndex)
.Func(_SC("GetParameterName"), &Statement::GetParameterName)
.Func(_SC("CheckColumn"), &Statement::CheckColumn)
.Func(_SC("IsColumnNull"), &Statement::IsColumnNull)
.FmtFunc(_SC("ColumnIndex"), &Statement::GetColumnIndex)
.Func(_SC("ColumnName"), &Statement::GetColumnName)
.Func(_SC("ColumnOriginName"), &Statement::GetColumnOriginName)
.Func(_SC("ColumnType"), &Statement::GetColumnType)
.Func(_SC("ColumnBytes"), &Statement::GetColumnBytes)
.Func(_SC("Reset"), &Statement::Reset)
.Func(_SC("Clear"), &Statement::Clear)
.Func(_SC("Exec"), &Statement::Exec)
.Func(_SC("Step"), &Statement::Step)
.Func(_SC("Param"), &Statement::GetParameter)
.Func(_SC("Parameter"), &Statement::GetParameter)
.Func(_SC("SetValue"), &Statement::SetValue)
.Func(_SC("SetBool"), &Statement::SetBool)
.Func(_SC("SetChar"), &Statement::SetChar)
.Func(_SC("SetInteger"), &Statement::SetInteger)
.Func(_SC("SetInt8"), &Statement::SetInt8)
.Func(_SC("SetUint8"), &Statement::SetUint8)
.Func(_SC("SetInt16"), &Statement::SetInt16)
.Func(_SC("SetUint16"), &Statement::SetUint16)
.Func(_SC("SetInt32"), &Statement::SetInt32)
.Func(_SC("SetUint32"), &Statement::SetUint32)
.Func(_SC("SetInt64"), &Statement::SetInt64)
.Func(_SC("SetUint64"), &Statement::SetUint64)
.Func(_SC("SetFloat"), &Statement::SetFloat)
.Func(_SC("SetFloat32"), &Statement::SetFloat32)
.Func(_SC("SetFloat64"), &Statement::SetFloat64)
.FmtFunc(_SC("SetString"), &Statement::SetString)
.Func(_SC("SetZeroBlob"), &Statement::SetZeroBlob)
.Func(_SC("SetBlob"), &Statement::SetBlob)
.Func(_SC("SetData"), &Statement::SetData)
.Func(_SC("SetDate"), &Statement::SetDate)
.Func(_SC("SetDateEx"), &Statement::SetDateEx)
.Func(_SC("SetTime"), &Statement::SetTime)
.Func(_SC("SetTimeEx"), &Statement::SetTimeEx)
.Func(_SC("SetDatetime"), &Statement::SetDatetime)
.Func(_SC("SetDatetimeEx"), &Statement::SetDatetimeEx)
.Func(_SC("SetNow"), &Statement::SetNow)
.Func(_SC("SetNull"), &Statement::SetNull)
.Func(_SC("SetArray"), &Statement::SetArray)
.Func(_SC("SetTable"), &Statement::SetTable)
.Func(_SC("Field"), &Statement::GetColumn)
.Func(_SC("Column"), &Statement::GetColumn)
.Func(_SC("GetValue"), &Statement::GetValue)
.Func(_SC("GetNumber"), &Statement::GetNumber)
.Func(_SC("GetInteger"), &Statement::GetInteger)
.Func(_SC("GetFloat"), &Statement::GetFloat)
.Func(_SC("GetLong"), &Statement::GetLong)
.Func(_SC("GetString"), &Statement::GetString)
.Func(_SC("GetBoolean"), &Statement::GetBoolean)
.Func(_SC("GetChar"), &Statement::GetChar)
.Func(_SC("GetBuffer"), &Statement::GetBuffer)
.Func(_SC("GetBlob"), &Statement::GetBlob)
// Member overloads
.Overload< Array (Statement::*)(void) const >(_SC("GetArray"), &Statement::GetArray)
.Overload< Array (Statement::*)(Int32) const >(_SC("GetArray"), &Statement::GetArray)
.Overload< Array (Statement::*)(Int32, Int32) const >(_SC("GetArray"), &Statement::GetArray)
.Overload< Table (Statement::*)(void) const >(_SC("GetTable"), &Statement::GetTable)
.Overload< Table (Statement::*)(Int32) const >(_SC("GetTable"), &Statement::GetTable)
.Overload< Table (Statement::*)(Int32, Int32) const >(_SC("GetTable"), &Statement::GetTable)
);
}
} // Namespace:: SqMod

View File

@@ -1,868 +0,0 @@
#pragma once
// ------------------------------------------------------------------------------------------------
#include "Library/SQLite/Handle.hpp"
#include "Library/SQLite/Parameter.hpp"
#include "Library/SQLite/Column.hpp"
#include "Library/Utils/Buffer.hpp"
// ------------------------------------------------------------------------------------------------
namespace SqMod {
/* ------------------------------------------------------------------------------------------------
* Used to manage and interact a database statement.
*/
class Statement
{
private:
// --------------------------------------------------------------------------------------------
StmtRef m_Handle; // Reference to the managed statement.
protected:
/* --------------------------------------------------------------------------------------------
* Validate the managed statement handle and throw an error if invalid.
*/
#if defined(_DEBUG) || defined(SQMOD_EXCEPTLOC)
void Validate(CCStr file, Int32 line) const;
#else
void Validate() const;
#endif // _DEBUG
/* --------------------------------------------------------------------------------------------
* Validate the managed statement handle and throw an error if invalid.
*/
#if defined(_DEBUG) || defined(SQMOD_EXCEPTLOC)
void ValidateCreated(CCStr file, Int32 line) const;
#else
void ValidateCreated() const;
#endif // _DEBUG
/* --------------------------------------------------------------------------------------------
* Validate the managed statement handle and throw an error if invalid.
*/
#if defined(_DEBUG) || defined(SQMOD_EXCEPTLOC)
const StmtRef & GetValid(CCStr file, Int32 line) const;
#else
const StmtRef & GetValid() const;
#endif // _DEBUG
/* --------------------------------------------------------------------------------------------
* Validate the managed statement handle and throw an error if invalid.
*/
#if defined(_DEBUG) || defined(SQMOD_EXCEPTLOC)
const StmtRef & GetCreated(CCStr file, Int32 line) const;
#else
const StmtRef & GetCreated() const;
#endif // _DEBUG
/* --------------------------------------------------------------------------------------------
* Validate the statement reference and column index, and throw an error if they're invalid.
*/
#if defined(_DEBUG) || defined(SQMOD_EXCEPTLOC)
void ValidateColumn(Int32 idx, CCStr file, Int32 line) const;
#else
void ValidateColumn(Int32 idx) const;
#endif // _DEBUG
/* --------------------------------------------------------------------------------------------
* Validate the statement reference and parameter index, and throw an error if they're invalid.
*/
#if defined(_DEBUG) || defined(SQMOD_EXCEPTLOC)
void ValidateParam(Int32 idx, CCStr file, Int32 line) const;
#else
void ValidateParam(Int32 idx) const;
#endif // _DEBUG
/* --------------------------------------------------------------------------------------------
* Validate the statement reference and row, and throw an error if they're invalid.
*/
#if defined(_DEBUG) || defined(SQMOD_EXCEPTLOC)
void ValidateRow(CCStr file, Int32 line) const;
#else
void ValidateRow() const;
#endif // _DEBUG
public:
/* --------------------------------------------------------------------------------------------
* Default constructor.
*/
Statement()
: m_Handle()
{
/* ... */
}
/* --------------------------------------------------------------------------------------------
* Construct a statement under the specified connection using the specified string.
*/
Statement(const ConnRef & connection, StackStrF & query)
: m_Handle(new StmtHnd(connection))
{
SQMOD_GET_VALID(*this)->Create(query.mPtr, query.mLen);
}
/* --------------------------------------------------------------------------------------------
* Construct a statement under the specified connection using the specified string.
*/
Statement(const Connection & connection, StackStrF & query);
/* --------------------------------------------------------------------------------------------
* Direct handle constructor.
*/
Statement(const StmtRef & s)
: m_Handle(s)
{
/* ... */
}
/* --------------------------------------------------------------------------------------------
* Copy constructor.
*/
Statement(const Statement & o) = default;
/* --------------------------------------------------------------------------------------------
* Move constructor.
*/
Statement(Statement && o) = default;
/* --------------------------------------------------------------------------------------------
* Copy assignment operator.
*/
Statement & operator = (const Statement & o) = default;
/* --------------------------------------------------------------------------------------------
* Move assignment operator.
*/
Statement & operator = (Statement && o) = default;
/* --------------------------------------------------------------------------------------------
* Perform an equality comparison between two connections.
*/
bool operator == (const Statement & o) const
{
return (m_Handle.Get() == o.m_Handle.Get());
}
/* --------------------------------------------------------------------------------------------
* Perform an inequality comparison between two connections.
*/
bool operator != (const Statement & o) const
{
return (m_Handle.Get() != o.m_Handle.Get());
}
/* --------------------------------------------------------------------------------------------
* Implicit conversion to the raw connection handle.
*/
operator sqlite3_stmt * ()
{
return m_Handle ? m_Handle->mPtr : nullptr;
}
/* --------------------------------------------------------------------------------------------
* Implicit conversion to the raw connection handle.
*/
operator sqlite3_stmt * () const
{
return m_Handle ? m_Handle->mPtr : nullptr;
}
/* --------------------------------------------------------------------------------------------
* Used by the script engine to convert an instance of this type to a string.
*/
const String & ToString() const
{
return m_Handle ? m_Handle->mQuery : NullString();
}
/* --------------------------------------------------------------------------------------------
* Retrieve the associated statement handle.
*/
const StmtRef & GetHandle() const
{
return m_Handle;
}
/* --------------------------------------------------------------------------------------------
* See whether the managed handle is valid.
*/
bool IsValid() const
{
return m_Handle;
}
/* --------------------------------------------------------------------------------------------
* See whether the managed statement is valid.
*/
bool IsPrepared() const
{
return m_Handle && (m_Handle->mPtr != nullptr);
}
/* --------------------------------------------------------------------------------------------
* Return the number of active references to this statement handle.
*/
Uint32 GetReferences() const
{
return m_Handle.Count();
}
/* --------------------------------------------------------------------------------------------
* Retrieve the associated database connection.
*/
Object GetConnection() const;
/* --------------------------------------------------------------------------------------------
* Release the reference to the associated database statement.
*/
void Release()
{
m_Handle.Reset();
}
/* --------------------------------------------------------------------------------------------
* Retrieve the last received status code.
*/
Int32 GetStatus() const
{
return SQMOD_GET_VALID(*this)->mStatus;
}
/* --------------------------------------------------------------------------------------------
* Return the numeric result code for the most recent failed API call (if any).
*/
Int32 GetErrorCode() const
{
return SQMOD_GET_VALID(*this)->ErrNo();
}
/* --------------------------------------------------------------------------------------------
* Return the extended numeric result code for the most recent failed API call (if any).
*/
Int32 GetExtendedErrorCode() const
{
return SQMOD_GET_VALID(*this)->ExErrNo();
}
/* --------------------------------------------------------------------------------------------
* Retrieve the message of the last received error code.
*/
CSStr GetErrStr() const
{
return SQMOD_GET_VALID(*this)->ErrStr();
}
/* --------------------------------------------------------------------------------------------
* Return the last error message associated with this database connection.
*/
CSStr GetErrMsg() const
{
return SQMOD_GET_VALID(*this)->ErrMsg();
}
/* --------------------------------------------------------------------------------------------
* Retrieve the amount of requested columns.
*/
Int32 GetColumns() const
{
return SQMOD_GET_VALID(*this)->mColumns;
}
/* --------------------------------------------------------------------------------------------
* Retrieve the amount of specified parameters.
*/
Int32 GetParameters() const
{
return SQMOD_GET_VALID(*this)->mParameters;
}
/* --------------------------------------------------------------------------------------------
* Retrieve the query string used to create this statement.
*/
const String & GetQuery() const
{
return SQMOD_GET_VALID(*this)->mQuery;
}
/* --------------------------------------------------------------------------------------------
* See if the last step retrieved a valid row.
*/
bool GetGood() const
{
return SQMOD_GET_CREATED(*this)->mGood;
}
/* --------------------------------------------------------------------------------------------
* See if there are any steps left.
*/
bool GetDone() const
{
return SQMOD_GET_CREATED(*this)->mDone;
}
/* --------------------------------------------------------------------------------------------
* Check whether a specific parameter index is within range.
*/
bool CheckParameter(Int32 idx) const
{
return SQMOD_GET_VALID(*this)->CheckParameter(idx);
}
/* --------------------------------------------------------------------------------------------
* Retrieve the parameter index associated with the specified name.
*/
Int32 GetParameterIndex(StackStrF & name) const
{
return sqlite3_bind_parameter_index(SQMOD_GET_VALID(*this)->mPtr, name.mPtr);
}
/* --------------------------------------------------------------------------------------------
* Retrieve the parameter name associated with the specified index.
*/
CSStr GetParameterName(Int32 idx) const
{
// Validate the specified index
if (!idx)
{
STHROWF("Invalid parameter index (%d)", idx);
}
// Attempt to locate the name at the specified index
CSStr name = sqlite3_bind_parameter_name(SQMOD_GET_VALID(*this)->mPtr, idx);
// Validate the obtained string
if (!name)
{
STHROWF("No such parameter exists (%d)", idx);
}
// Return the obtained string
return name;
}
/* --------------------------------------------------------------------------------------------
* Check whether a specific column index is within range.
*/
bool CheckColumn(Int32 idx) const
{
return SQMOD_GET_VALID(*this)->CheckColumn(idx);
}
/* --------------------------------------------------------------------------------------------
* Retrieve the amount of columns available in the current row.
*/
Int32 GetDataCount() const
{
return sqlite3_data_count(SQMOD_GET_VALID(*this)->mPtr);
}
/* --------------------------------------------------------------------------------------------
* Check whether the specified column is null.
*/
bool IsColumnNull(Int32 idx) const
{
return (sqlite3_column_type(SQMOD_GET_VALID(*this)->mPtr, idx) == SQLITE_NULL);
}
/* --------------------------------------------------------------------------------------------
* Retrieve the column index associated with the specified name.
*/
Int32 GetColumnIndex(StackStrF & name) const
{
return SQMOD_GET_VALID(*this)->GetColumnIndex(name.mPtr, name.mLen);
}
/* --------------------------------------------------------------------------------------------
* Retrieve the column name associated with the specified index.
*/
CSStr GetColumnName(Int32 idx) const
{
return sqlite3_column_name(SQMOD_GET_VALID(*this)->mPtr, idx);
}
/* --------------------------------------------------------------------------------------------
* Retrieve the column origin name if the library was compiled with such feature.
*/
CSStr GetColumnOriginName(Int32 idx) const
{
#ifdef SQLITE_ENABLE_COLUMN_METADATA
return sqlite3_column_origin_name(SQMOD_GET_VALID(*this)->mPtr, idx);
#else
// The compiler moans when extra warnings are enabled
SQMOD_UNUSED_VAR(idx);
// Stop the execution here!
STHROWF("The module was compiled without this feature");
// We have to return something
return _SC("");
#endif
}
/* --------------------------------------------------------------------------------------------
* Retrieve the type identifier of the column associated with the specified index.
*/
Int32 GetColumnType(Int32 idx) const
{
return sqlite3_column_type(SQMOD_GET_VALID(*this)->mPtr, idx);
}
/* --------------------------------------------------------------------------------------------
* Retrieve the size in bytes of the column associated with the specified index.
*/
Int32 GetColumnBytes(Int32 idx) const
{
return sqlite3_column_bytes(SQMOD_GET_VALID(*this)->mPtr, idx);
}
/* --------------------------------------------------------------------------------------------
* Reset the statement back to its initial position to be stepped again.
*/
Statement & Reset();
/* --------------------------------------------------------------------------------------------
* Clear any values binded to this statement.
*/
Statement & Clear();
/* --------------------------------------------------------------------------------------------
* Execute this statement and don't expect any rows to be returned.
*/
Int32 Exec();
/* --------------------------------------------------------------------------------------------
* Step the statement and expect a row to be returned.
*/
bool Step();
/* --------------------------------------------------------------------------------------------
* Retrieve the parameter with the specified name or index.
*/
Object GetParameter(const Object & param) const
{
return Object(new Parameter(m_Handle, param));
}
/* --------------------------------------------------------------------------------------------
* Attempt to bind a dynamic value at the specified parameter index.
*/
Statement & SetValue(const Object & param, const Object & value)
{
Parameter(SQMOD_GET_CREATED(*this), param).SetValue(value);
// Allow chaining of operations
return *this;
}
/* --------------------------------------------------------------------------------------------
* Attempt to bind a boolean value at the specified parameter index.
*/
Statement & SetBool(const Object & param, bool value)
{
Parameter(SQMOD_GET_CREATED(*this), param).SetBool(value);
// Allow chaining of operations
return *this;
}
/* --------------------------------------------------------------------------------------------
* Attempt to bind a character value at the specified parameter index.
*/
Statement & SetChar(const Object & param, SQInteger value)
{
Parameter(SQMOD_GET_CREATED(*this), param).SetChar(value);
// Allow chaining of operations
return *this;
}
/* --------------------------------------------------------------------------------------------
* Attempt to bind a native integer value at the specified parameter index.
*/
Statement & SetInteger(const Object & param, SQInteger value)
{
Parameter(SQMOD_GET_CREATED(*this), param).SetInteger(value);
// Allow chaining of operations
return *this;
}
/* --------------------------------------------------------------------------------------------
* Attempt to bind a signed 8 bit integer value at the specified parameter index.
*/
Statement & SetInt8(const Object & param, SQInteger value)
{
Parameter(SQMOD_GET_CREATED(*this), param).SetInt8(value);
// Allow chaining of operations
return *this;
}
/* --------------------------------------------------------------------------------------------
* Attempt to bind an unsigned 8 bit integer value at the specified parameter index.
*/
Statement & SetUint8(const Object & param, SQInteger value)
{
Parameter(SQMOD_GET_CREATED(*this), param).SetUint8(value);
// Allow chaining of operations
return *this;
}
/* --------------------------------------------------------------------------------------------
* Attempt to bind a signed 16 bit integer value at the specified parameter index.
*/
Statement & SetInt16(const Object & param, SQInteger value)
{
Parameter(SQMOD_GET_CREATED(*this), param).SetInt16(value);
// Allow chaining of operations
return *this;
}
/* --------------------------------------------------------------------------------------------
* Attempt to bind an unsigned 16 bit integer value at the specified parameter index.
*/
Statement & SetUint16(const Object & param, SQInteger value)
{
Parameter(SQMOD_GET_CREATED(*this), param).SetUint16(value);
// Allow chaining of operations
return *this;
}
/* --------------------------------------------------------------------------------------------
* Attempt to bind a signed 32 bit integer value at the specified parameter index.
*/
Statement & SetInt32(const Object & param, SQInteger value)
{
Parameter(SQMOD_GET_CREATED(*this), param).SetInt32(value);
// Allow chaining of operations
return *this;
}
/* --------------------------------------------------------------------------------------------
* Attempt to bind an unsigned 32 bit integer value at the specified parameter index.
*/
Statement & SetUint32(const Object & param, SQInteger value)
{
Parameter(SQMOD_GET_CREATED(*this), param).SetUint32(value);
// Allow chaining of operations
return *this;
}
/* --------------------------------------------------------------------------------------------
* Attempt to bind a signed 64 bit integer value at the specified parameter index.
*/
Statement & SetInt64(const Object & param, const Object & value)
{
Parameter(SQMOD_GET_CREATED(*this), param).SetInt64(value);
// Allow chaining of operations
return *this;
}
/* --------------------------------------------------------------------------------------------
* Attempt to bind an unsigned 64 bit integer value at the specified parameter index.
*/
Statement & SetUint64(const Object & param, const Object & value)
{
Parameter(SQMOD_GET_CREATED(*this), param).SetUint64(value);
// Allow chaining of operations
return *this;
}
/* --------------------------------------------------------------------------------------------
* Attempt to bind a native floating point value at the specified parameter index.
*/
Statement & SetFloat(const Object & param, SQFloat value)
{
Parameter(SQMOD_GET_CREATED(*this), param).SetFloat(value);
// Allow chaining of operations
return *this;
}
/* --------------------------------------------------------------------------------------------
* Attempt to bind a 32 bit floating point value at the specified parameter index.
*/
Statement & SetFloat32(const Object & param, SQFloat value)
{
Parameter(SQMOD_GET_CREATED(*this), param).SetFloat32(value);
// Allow chaining of operations
return *this;
}
/* --------------------------------------------------------------------------------------------
* Attempt to bind a 64 bit floating point value at the specified parameter index.
*/
Statement & SetFloat64(const Object & param, SQFloat value)
{
Parameter(SQMOD_GET_CREATED(*this), param).SetFloat64(value);
// Allow chaining of operations
return *this;
}
/* --------------------------------------------------------------------------------------------
* Attempt to bind a string value at the specified parameter index.
*/
Statement & SetString(const Object & param, StackStrF & value)
{
Parameter(SQMOD_GET_CREATED(*this), param).SetString(value);
// Allow chaining of operations
return *this;
}
/* --------------------------------------------------------------------------------------------
* Attempt to bind a zeroed blob value at the specified parameter index.
*/
Statement & SetZeroBlob(const Object & param, SQInteger size)
{
Parameter(SQMOD_GET_CREATED(*this), param).SetZeroBlob(size);
// Allow chaining of operations
return *this;
}
/* --------------------------------------------------------------------------------------------
* Attempt to bind a blob value at the specified parameter index.
*/
Statement & SetBlob(const Object & param, const Object & value)
{
Parameter(SQMOD_GET_CREATED(*this), param).SetBlob(value);
// Allow chaining of operations
return *this;
}
/* --------------------------------------------------------------------------------------------
* Attempt to bind a buffer value at the specified parameter index.
*/
Statement & SetData(const Object & param, const Object & value)
{
Parameter(SQMOD_GET_CREATED(*this), param).SetData(value.Cast< const SqBuffer & >());
// Allow chaining of operations
return *this;
}
/* --------------------------------------------------------------------------------------------
* Attempt to bind a date value at the specified parameter index.
*/
Statement & SetDate(const Object & param, const Object & value)
{
Parameter(SQMOD_GET_CREATED(*this), param).SetDate(value.Cast< const Date & >());
// Allow chaining of operations
return *this;
}
/* --------------------------------------------------------------------------------------------
* Attempt to bind a date value at the specified parameter index.
*/
Statement & SetDateEx(const Object & param, SQInteger year, SQInteger month, SQInteger day)
{
Parameter(SQMOD_GET_CREATED(*this), param).SetDateEx(year, month, day);
// Allow chaining of operations
return *this;
}
/* --------------------------------------------------------------------------------------------
* Attempt to bind a time value at the specified parameter index.
*/
Statement & SetTime(const Object & param, const Object & value)
{
Parameter(SQMOD_GET_CREATED(*this), param).SetTime(value.Cast< const Time & >());
// Allow chaining of operations
return *this;
}
/* --------------------------------------------------------------------------------------------
* Attempt to bind a time value at the specified parameter index.
*/
Statement & SetTimeEx(const Object & param, SQInteger hour, SQInteger minute, SQInteger second)
{
Parameter(SQMOD_GET_CREATED(*this), param).SetTimeEx(hour, minute, second);
// Allow chaining of operations
return *this;
}
/* --------------------------------------------------------------------------------------------
* Attempt to bind a date-time value at the specified parameter index.
*/
Statement & SetDatetime(const Object & param, const Object & value)
{
Parameter(SQMOD_GET_CREATED(*this), param).SetDatetime(value.Cast< const Datetime & >());
// Allow chaining of operations
return *this;
}
/* --------------------------------------------------------------------------------------------
* Attempt to bind a date-time value at the specified parameter index.
*/
Statement & SetDatetimeEx(const Object & param, SQInteger year, SQInteger month, SQInteger day,
SQInteger hour, SQInteger minute, SQInteger second)
{
Parameter(SQMOD_GET_CREATED(*this), param).SetDatetimeEx(year, month, day, hour, minute, second);
// Allow chaining of operations
return *this;
}
/* --------------------------------------------------------------------------------------------
* Attempt to bind the current timestamp at the specified parameter index.
*/
Statement & SetNow(const Object & param)
{
Parameter(SQMOD_GET_CREATED(*this), param).SetNow();
// Allow chaining of operations
return *this;
}
/* --------------------------------------------------------------------------------------------
* Attempt to bind a null value at the specified parameter index.
*/
Statement & SetNull(const Object & param)
{
Parameter(SQMOD_GET_CREATED(*this), param).SetNull();
// Allow chaining of operations
return *this;
}
/* --------------------------------------------------------------------------------------------
* Attempt to bind the values from an array starting at the specified index.
*/
Statement & SetArray(Int32 idx, const Array & arr);
/* --------------------------------------------------------------------------------------------
* Attempt to bind the values from an associative container.
*/
Statement & SetTable(const Table & tbl);
/* --------------------------------------------------------------------------------------------
* Retrieve the column with the specified name or index.
*/
Object GetColumn(const Object & column) const
{
return Object(new Column(m_Handle, column));
}
/* --------------------------------------------------------------------------------------------
* Retrieve the value inside the referenced column as a dynamic type.
*/
Object GetValue(const Object & column) const
{
return Column(SQMOD_GET_CREATED(*this), column).GetValue();
}
/* --------------------------------------------------------------------------------------------
* Retrieve the value inside the referenced column as a numeric type.
*/
Object GetNumber(const Object & column) const
{
return Column(SQMOD_GET_CREATED(*this), column).GetNumber();
}
/* --------------------------------------------------------------------------------------------
* Retrieve the value inside the referenced column as a native script integer.
*/
SQInteger GetInteger(const Object & column) const
{
return Column(SQMOD_GET_CREATED(*this), column).GetInteger();
}
/* --------------------------------------------------------------------------------------------
* Retrieve the value inside the referenced column as a native script floating point.
*/
SQFloat GetFloat(const Object & column) const
{
return Column(SQMOD_GET_CREATED(*this), column).GetFloat();
}
/* --------------------------------------------------------------------------------------------
* Retrieve the value inside the referenced column as a long integer.
*/
Object GetLong(const Object & column) const
{
return Column(SQMOD_GET_CREATED(*this), column).GetLong();
}
/* --------------------------------------------------------------------------------------------
* Retrieve the value inside the referenced column as a string.
*/
Object GetString(const Object & column) const
{
return Column(SQMOD_GET_CREATED(*this), column).GetString();
}
/* --------------------------------------------------------------------------------------------
* Retrieve the value inside the referenced column as a boolean.
*/
bool GetBoolean(const Object & column) const
{
return Column(SQMOD_GET_CREATED(*this), column).GetBoolean();
}
/* --------------------------------------------------------------------------------------------
* Retrieve the value inside the referenced column as a character.
*/
SQChar GetChar(const Object & column) const
{
return Column(SQMOD_GET_CREATED(*this), column).GetChar();
}
/* --------------------------------------------------------------------------------------------
* Retrieve the value inside the referenced column as a memory buffer.
*/
Object GetBuffer(const Object & column) const
{
return Column(SQMOD_GET_CREATED(*this), column).GetBuffer();
}
/* --------------------------------------------------------------------------------------------
* Retrieve the value inside the referenced column as a memory blob.
*/
Object GetBlob(const Object & column) const
{
return Column(SQMOD_GET_CREATED(*this), column).GetBlob();
}
/* --------------------------------------------------------------------------------------------
* Retrieve the row as an array container.
*/
Array GetArray() const
{
return GetArray(0, SQMOD_GET_CREATED(*this)->mColumns);
}
/* --------------------------------------------------------------------------------------------
* Retrieve the row as an array container.
*/
Array GetArray(Int32 min) const
{
return GetArray(min, SQMOD_GET_CREATED(*this)->mColumns);
}
/* --------------------------------------------------------------------------------------------
* Retrieve the row as an array container.
*/
Array GetArray(Int32 min, Int32 max) const;
/* --------------------------------------------------------------------------------------------
* Retrieve the row as an associative container.
*/
Table GetTable() const
{
// Is there something to return?
if (SQMOD_GET_CREATED(*this)->mColumns > 0)
{
return GetTable(0, m_Handle->mColumns - 1);
}
// Fallback to empty table
return NullTable();
}
/* --------------------------------------------------------------------------------------------
* Retrieve the row as an associative container.
*/
Table GetTable(Int32 min) const
{
// Is there something to return?
if (SQMOD_GET_CREATED(*this)->mColumns > 0)
{
return GetTable(min, m_Handle->mColumns - 1);
}
// Fallback to empty table
return NullTable();
}
/* --------------------------------------------------------------------------------------------
* Retrieve the row as an associative container.
*/
Table GetTable(Int32 min, Int32 max) const;
};
} // Namespace:: SqMod

View File

@@ -1,102 +0,0 @@
// ------------------------------------------------------------------------------------------------
#include "Library/SQLite/Transaction.hpp"
#include <utility>
#include "Library/SQLite/Connection.hpp"
// ------------------------------------------------------------------------------------------------
namespace SqMod {
// ------------------------------------------------------------------------------------------------
SQMODE_DECL_TYPENAME(Typename, _SC("SqLiteTransaction"))
// ------------------------------------------------------------------------------------------------
Transaction::Transaction(const Connection & db)
: Transaction(db.GetHandle())
{
/* ... */
}
// ------------------------------------------------------------------------------------------------
Transaction::Transaction(ConnRef db)
: m_Handle(std::move(db)), m_Committed(false)
{
// Was the specified database connection valid?
if (!m_Handle)
{
STHROWF("Invalid connection handle");
}
// Attempt to begin transaction
m_Handle->mStatus = sqlite3_exec(m_Handle->mPtr, "BEGIN", nullptr, nullptr, nullptr);
// Validate the result
if (m_Handle->mStatus != SQLITE_OK)
{
STHROWF("Unable to begin transaction [%s]", m_Handle->ErrMsg());
}
}
// ------------------------------------------------------------------------------------------------
Transaction::~Transaction()
{
// Was this transaction successfully committed?
if (m_Committed)
{
return; // We're done here!
}
// Attempt to roll back changes because this failed to commit
m_Handle->mStatus = sqlite3_exec(m_Handle->mPtr, "ROLLBACK", nullptr, nullptr, nullptr);
// Validate the result
if (m_Handle->mStatus != SQLITE_OK)
{
// We cannot throw exceptions in destructor
LogErr("Unable to rollback transaction [%s]", m_Handle->ErrMsg());
}
}
// ------------------------------------------------------------------------------------------------
bool Transaction::Commit()
{
// We shouldn't even be here if there wasn't a valid connection but let's be sure
if (!m_Handle)
{
STHROWF("Invalid database connection");
}
// Was this transaction already committed?
else if (m_Committed)
{
STHROWF("Transaction was already committed");
}
// Attempt to commit the change during this transaction
m_Handle->mStatus = sqlite3_exec(m_Handle->mPtr, "COMMIT", nullptr, nullptr, nullptr);
// Validate the result
if (m_Handle->mStatus != SQLITE_OK)
{
STHROWF("Unable to commit transaction [%s]", m_Handle->ErrMsg());
}
else
{
m_Committed = true; // Everything was committed successfully
}
// Return the result
return m_Committed;
}
// ================================================================================================
void Register_Transaction(Table & sqlns)
{
sqlns.Bind(_SC("Transaction"),
Class< Transaction, NoCopy< Transaction > >(sqlns.GetVM(), Typename::Str)
// Constructors
.Ctor< const Connection & >()
// Meta-methods
.SquirrelFunc(_SC("_typename"), &Typename::Fn)
.Func(_SC("_tostring"), &Transaction::ToString)
// Properties
.Prop(_SC("IsValid"), &Transaction::IsValid)
.Prop(_SC("Committed"), &Transaction::Commited)
// Member Methods
.Func(_SC("Commit"), &Transaction::Commit)
);
}
} // Namespace:: SqMod

View File

@@ -1,95 +0,0 @@
#pragma once
// ------------------------------------------------------------------------------------------------
#include "Library/SQLite/Handle.hpp"
// ------------------------------------------------------------------------------------------------
namespace SqMod {
/* ------------------------------------------------------------------------------------------------
* Implements the RAII pattern for database transactions.
*/
class Transaction
{
public:
/* --------------------------------------------------------------------------------------------
* Construct by taking the handle from a connection.
*/
Transaction(const Connection & db);
/* --------------------------------------------------------------------------------------------
* Construct using the direct connection handle.
*/
Transaction(ConnRef 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;
/* --------------------------------------------------------------------------------------------
* Used by the script engine to convert an instance of this type to a string.
*/
const String & ToString() const
{
return m_Handle ? m_Handle->mName : NullString();
}
/* --------------------------------------------------------------------------------------------
* Retrieve the associated statement handle.
*/
const ConnRef & GetHandle() const
{
return m_Handle;
}
/* --------------------------------------------------------------------------------------------
* See whether the managed handle is valid.
*/
bool IsValid() const
{
return m_Handle;
}
/* --------------------------------------------------------------------------------------------
* Attempt to commit changes to the database.
*/
bool Commit();
/* --------------------------------------------------------------------------------------------
* See whether the change during this transaction were successfully committed.
*/
bool Commited() const
{
return m_Committed;
}
private:
// --------------------------------------------------------------------------------------------
ConnRef m_Handle; // The database connection handle where the transaction began.
bool m_Committed; // Whether changes were successfully committed to the database.
};
} // Namespace:: SqMod