1
0
mirror of https://github.com/VCMP-SqMod/SqMod.git synced 2024-11-08 08:47:17 +01:00

Fixed excpetion throwing in SQLite document to that generated corrupted messages because snprintf was used instead of vsnprintf.

Revised most of the SQLite plugin and cleaned code.
This commit is contained in:
Sandu Liviu Catalin 2016-04-02 12:11:14 +03:00
parent b6466b9181
commit fab15840cb
9 changed files with 524 additions and 310 deletions

View File

@ -4,6 +4,9 @@
#include "Statement.hpp"
#include "Module.hpp"
// ------------------------------------------------------------------------------------------------
#include <cstring>
// ------------------------------------------------------------------------------------------------
#include <sqrat.h>
@ -23,10 +26,11 @@ void Column::Validate() const
{
// Are we pointing to a valid index?
if (m_Index < 0)
{
STHROWF("Invalid column index");
}
// Do we belong to a valid statement?
else if (!m_Stmt)
STHROWF("Invalid SQLite statement reference");
m_Stmt.Validate();
}
// ------------------------------------------------------------------------------------------------
@ -34,13 +38,16 @@ void Column::ValidateRow() const
{
// Are we pointing to a valid index?
if (m_Index < 0)
{
STHROWF("Invalid column index");
}
// Do we belong to a valid statement?
else if (!m_Stmt)
STHROWF("Invalid SQLite statement reference");
m_Stmt.Validate();
// Do we have any rows available?
else if (!m_Stmt->mGood)
if (!m_Stmt->mGood)
{
STHROWF("No row available");
}
}
// ------------------------------------------------------------------------------------------------
@ -89,7 +96,7 @@ SQFloat Column::GetFloat() const
// Validate the column and statement row
ValidateRow();
// Return the requested information
return (SQFloat)sqlite3_column_double(m_Stmt, m_Index);
return static_cast< SQFloat >(sqlite3_column_double(m_Stmt, m_Index));
}
// ------------------------------------------------------------------------------------------------
@ -113,7 +120,7 @@ Object Column::GetString() const
// Obtain the initial stack size
const StackGuard sg(_SqVM);
// Push the column text on the stack
sq_pushstring(_SqVM, (CSStr)sqlite3_column_text(m_Stmt, m_Index),
sq_pushstring(_SqVM, reinterpret_cast< CSStr >(sqlite3_column_text(m_Stmt, m_Index)),
sqlite3_column_bytes(m_Stmt, m_Index));
// Get the object from the stack and return it
return Var< Object >(_SqVM, -1).value;
@ -143,7 +150,9 @@ Object Column::GetBlob() const
const void * b = sqlite3_column_blob(m_Stmt, 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)
{
@ -154,7 +163,9 @@ Object Column::GetBlob() const
}
// Copy the data into the memory blob
else
memcpy(p, b, sz);
{
std::memcpy(p, b, sz);
}
// Get the object from the stack and return it
return Var< Object >(_SqVM, -1).value;
}
@ -196,9 +207,9 @@ CSStr Column::GetOriginName() const
return sqlite3_column_origin_name(m_Stmt, m_Index);
#else
STHROWF("The module was compiled without this feature");
#endif
// Request failed
return _SC("");
#endif
}
// ------------------------------------------------------------------------------------------------

View File

@ -111,12 +111,18 @@ public:
Int32 Cmp(const Column & o) const
{
if (m_Stmt == o.m_Stmt)
{
return 0;
}
else if (m_Stmt.HndPtr() > o.m_Stmt.HndPtr())
{
return 1;
}
else
{
return -1;
}
}
/* --------------------------------------------------------------------------------------------
* Used by the script engine to convert an instance of this type to a string.

View File

@ -4,8 +4,9 @@
#include "Connection.hpp"
// ------------------------------------------------------------------------------------------------
#include <ctype.h>
#include <stdarg.h>
#include <cctype>
#include <cstring>
#include <cstdarg>
// ------------------------------------------------------------------------------------------------
#include <sqrat.h>
@ -35,8 +36,10 @@ void SqThrowF(CSStr str, ...)
va_list args;
va_start (args, str);
// Write the requested contents
if (snprintf(g_Buffer, sizeof(g_Buffer), str, args) < 0)
strcpy(g_Buffer, "Unknown error has occurred");
if (std::vsnprintf(g_Buffer, sizeof(g_Buffer), str, args) < 0)
{
std::strcpy(g_Buffer, "Unknown error has occurred");
}
// Release the argument list
va_end(args);
// Throw the exception with the resulted message
@ -50,8 +53,10 @@ CSStr FmtStr(CSStr str, ...)
va_list args;
va_start (args, str);
// Write the requested contents
if (snprintf(g_Buffer, sizeof(g_Buffer), str, args) < 0)
g_Buffer[0] = 0; /* make sure the string is terminated */
if (std::vsnprintf(g_Buffer, sizeof(g_Buffer), str, args) < 0)
{
g_Buffer[0] = 0; // make sure the string is terminated
}
// Release the argument list
va_end(args);
// Return the data from the buffer
@ -77,23 +82,34 @@ bool IsQueryEmpty(CSStr str)
{
// Is the pointer valid?
if (!str)
{
return true;
}
// Currently processed character
SQChar c = 0;
// See if the query contains any alpha numeric characters
while ((c = *str) != 0)
{
if (isalnum(c) != 0)
if (std::isalnum(c) != 0)
{
return false;
}
++str;
}
// At this point we consider the query empty
return true;
}
// ------------------------------------------------------------------------------------------------
StackGuard::StackGuard()
: m_VM(_SqVM), m_Top(sq_gettop(m_VM))
{
/* ... */
}
// ------------------------------------------------------------------------------------------------
StackGuard::StackGuard(HSQUIRRELVM vm)
: m_Top(sq_gettop(vm)), m_VM(vm)
: m_VM(vm), m_Top(sq_gettop(vm))
{
/* ... */
}
@ -104,16 +120,130 @@ StackGuard::~StackGuard()
sq_pop(m_VM, sq_gettop(m_VM) - m_Top);
}
// --------------------------------------------------------------------------------------------
StackStrF::StackStrF(HSQUIRRELVM vm, SQInteger idx, bool fmt)
: mPtr(nullptr)
, mLen(-1)
, mRes(SQ_OK)
, mObj()
, mVM(vm)
{
const Int32 top = sq_gettop(vm);
// Reset the converted value object
sq_resetobject(&mObj);
// Was the string or value specified?
if (top <= (idx - 1))
{
mRes = sq_throwerror(vm, "Missing string or value");
}
// Do we have enough values to call the format function and are we allowed to?
else if (top > idx && fmt)
{
// Pointer to the generated string
SStr str = nullptr;
// Attempt to generate the specified string format
mRes = sqstd_format(vm, idx, &mLen, &str);
// Did the format succeeded but ended up with a null string pointer?
if (SQ_SUCCEEDED(mRes) && !str)
{
mRes = sq_throwerror(vm, "Unable to generate the string");
}
else
{
mPtr = const_cast< CSStr >(str);
}
}
// Is the value on the stack an actual string?
else if (sq_gettype(vm, idx) == OT_STRING)
{
// Obtain a reference to the string object
mRes = sq_getstackobj(vm, idx, &mObj);
// Could we retrieve the object from the stack?
if (SQ_SUCCEEDED(mRes))
{
// Keep a strong reference to the object
sq_addref(vm, &mObj);
// Attempt to retrieve the string value from the stack
mRes = sq_getstring(vm, idx, &mPtr);
}
// Did the retrieval succeeded but ended up with a null string pointer?
if (SQ_SUCCEEDED(mRes) && !mPtr)
{
mRes = sq_throwerror(vm, "Unable to retrieve the string");
}
}
// We have to try and convert it to string
else
{
// Attempt to convert the value from the stack to a string
mRes = sq_tostring(vm, idx);
// Could we convert the specified value to string?
if (SQ_SUCCEEDED(mRes))
{
// Obtain a reference to the resulted object
mRes = sq_getstackobj(vm, -1, &mObj);
// Could we retrieve the object from the stack?
if (SQ_SUCCEEDED(mRes))
{
// Keep a strong reference to the object
sq_addref(vm, &mObj);
// Attempt to obtain the string pointer
mRes = sq_getstring(vm, -1, &mPtr);
}
}
// Pop a value from the stack regardless of the result
sq_pop(vm, 1);
// Did the retrieval succeeded but ended up with a null string pointer?
if (SQ_SUCCEEDED(mRes) && !mPtr)
{
mRes = sq_throwerror(vm, "Unable to retrieve the value");
}
}
}
// ------------------------------------------------------------------------------------------------
StackStrF::~StackStrF()
{
if (mVM && !sq_isnull(mObj))
{
sq_release(mVM, &mObj);
}
}
// ------------------------------------------------------------------------------------------------
void ConnHnd::Validate() const
{
// Is the handle valid?
if ((m_Hnd == nullptr) || (m_Hnd->mPtr == nullptr))
{
STHROWF("Invalid SQLite connection reference");
}
}
// ------------------------------------------------------------------------------------------------
void StmtHnd::Validate() const
{
// Is the handle valid?
if ((m_Hnd == nullptr) || (m_Hnd->mPtr == nullptr))
{
STHROWF("Invalid SQLite statement reference");
}
}
// ------------------------------------------------------------------------------------------------
ConnHnd::Handle::~Handle()
{
// Is there anything to close?
if (!mPtr)
{
return; // Nothing to close
}
// Are we dealing with a memory leak? Technically shouldn't reach this situation!
else if (mRef != 0)
{
// Should we deal with undefined behavior instead? How bad is one connection left open?
_SqMod->LogErr("SQLite connection is still referenced (%s)", mName.c_str());
}
else
{
// NOTE: Should we call sqlite3_interrupt(...) before closing?
@ -123,8 +253,10 @@ ConnHnd::Handle::~Handle()
Flush(mQueue.size(), env, func);
// Attempt to close the database
if ((sqlite3_close(mPtr)) != SQLITE_OK)
{
_SqMod->LogErr("Unable to close SQLite connection [%s]", sqlite3_errmsg(mPtr));
}
}
}
// ------------------------------------------------------------------------------------------------
@ -132,19 +264,25 @@ void ConnHnd::Handle::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 || strlen(name) <= 0)
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);
// Explicitly make sure it's null
mPtr = NULL;
mPtr = nullptr;
// Now its safe to throw the error
STHROWF("Unable to connect to database [%s]", sqlite3_errstr(mStatus));
STHROWF("Unable to connect to database [%s]", msg.c_str());
}
// Let's save the specified information
mName.assign(name);
@ -178,7 +316,7 @@ Int32 ConnHnd::Handle::Flush(Uint32 num, Object & env, Function & func)
QueryList::iterator itr = mQueue.begin();
QueryList::iterator end = mQueue.begin() + num;
// Attempt to begin the flush transaction
if ((mStatus = sqlite3_exec(mPtr, "BEGIN", NULL, NULL, NULL)) != SQLITE_OK)
if ((mStatus = sqlite3_exec(mPtr, "BEGIN", nullptr, nullptr, nullptr)) != SQLITE_OK)
{
STHROWF("Unable to begin flush transaction [%s]", sqlite3_errmsg(mPtr));
}
@ -193,7 +331,7 @@ Int32 ConnHnd::Handle::Flush(Uint32 num, Object & env, Function & func)
}
*/
// Attempt to execute the currently processed query string
if ((mStatus = sqlite3_exec(mPtr, itr->c_str(), NULL, NULL, NULL)) == SQLITE_OK)
if ((mStatus = sqlite3_exec(mPtr, itr->c_str(), nullptr, nullptr, nullptr)) == SQLITE_OK)
{
continue;
}
@ -227,12 +365,12 @@ Int32 ConnHnd::Handle::Flush(Uint32 num, Object & env, Function & func)
// 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", NULL, NULL, NULL)) == SQLITE_OK)
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", NULL, NULL, NULL)) != SQLITE_OK)
else if ((mStatus = sqlite3_exec(mPtr, "ROLLBACK", nullptr, nullptr, nullptr)) != SQLITE_OK)
{
STHROWF("Unable to rollback flush transaction [%s]", sqlite3_errmsg(mPtr));
}
@ -250,17 +388,23 @@ StmtHnd::Handle::~Handle()
{
// Is there anything to finalize?
if (!mPtr)
{
return; // Nothing to finalize
}
// Are we dealing with a memory leak? Technically shouldn't reach this situation!
else if (mRef != 0)
{
// Should we deal with undefined behavior instead? How bad is one statement left alive?
_SqMod->LogErr("SQLite statement is still referenced (%s)", mQuery.c_str());
}
else
{
// Attempt to finalize the statement
if ((sqlite3_finalize(mPtr)) != SQLITE_OK)
{
_SqMod->LogErr("Unable to finalize SQLite statement [%s]", mConn.ErrMsg());
}
}
}
// ------------------------------------------------------------------------------------------------
@ -268,29 +412,37 @@ void StmtHnd::Handle::Create(CSStr query)
{
// 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");
}
// Save the query string and therefore multiple strlen(...) calls
mQuery.assign(query ? query : _SC(""));
// Is the specified query string we just saved, valid?
if (mQuery.empty())
{
STHROWF("Unable to prepare statement. Invalid query string");
}
// Attempt to prepare a statement with the specified query string
else if ((mStatus = sqlite3_prepare_v2(mConn, mQuery.c_str(), (Int32)mQuery.size(),
&mPtr, NULL)) != SQLITE_OK)
&mPtr, nullptr)) != SQLITE_OK)
{
// Clear the query string since it failed
mQuery.clear();
// Explicitly make sure the handle is null
mPtr = 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);
}
}
// ------------------------------------------------------------------------------------------------
@ -298,7 +450,9 @@ Int32 StmtHnd::Handle::GetColumnIndex(CSStr name)
{
// Validate the handle
if (!mPtr)
{
STHROWF("Invalid SQLite statement");
}
// Are the names cached?
else if (mIndexes.empty())
{
@ -308,17 +462,23 @@ Int32 StmtHnd::Handle::GetColumnIndex(CSStr name)
CSStr name = (CSStr)sqlite3_column_name(mPtr, i);
// Validate the name
if (!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;
}
}
}
// Attempt to find the specified column
const Indexes::iterator itr = mIndexes.find(name);
// 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;
}
@ -340,7 +500,7 @@ Transaction::Transaction(const ConnHnd & db)
STHROWF("Invalid connection handle");
}
// Attempt to begin transaction
else if ((m_Connection = sqlite3_exec(m_Connection, "BEGIN", NULL, NULL, NULL)) != SQLITE_OK)
else if ((m_Connection = sqlite3_exec(m_Connection, "BEGIN", nullptr, nullptr, nullptr)) != SQLITE_OK)
{
STHROWF("Unable to begin transaction [%s]", m_Connection.ErrMsg());
}
@ -355,7 +515,7 @@ Transaction::~Transaction()
return; // We're done here!
}
// Attempt to roll back changes because this failed to commit
if ((m_Connection = sqlite3_exec(m_Connection, "ROLLBACK", NULL, NULL, NULL)) != SQLITE_OK)
if ((m_Connection = sqlite3_exec(m_Connection, "ROLLBACK", nullptr, nullptr, nullptr)) != SQLITE_OK)
{
STHROWF("Unable to rollback transaction [%s]", m_Connection.ErrMsg());
}
@ -375,7 +535,7 @@ bool Transaction::Commit()
STHROWF("Transaction was already committed");
}
// Attempt to commit the change during this transaction
else if ((m_Connection = sqlite3_exec(m_Connection, "COMMIT", NULL, NULL, NULL)) != SQLITE_OK)
else if ((m_Connection = sqlite3_exec(m_Connection, "COMMIT", nullptr, nullptr, nullptr)) != SQLITE_OK)
{
STHROWF("Unable to commit transaction [%s]", m_Connection.ErrMsg());
}
@ -432,7 +592,9 @@ CSStr EscapeString(CSStr str)
{
// Is there even a string to escape?
if (!str)
{
return _SC(""); // Default to empty string
}
// Attempt to escape the specified string
sqlite3_snprintf(sizeof(g_Buffer), g_Buffer, "%q", str);
// Return the resulted string
@ -445,15 +607,15 @@ CCStr EscapeStringEx(SQChar spec, CCStr 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')
if ((spec != 'q') && (spec != 'Q') && (spec != 'w') && (spec != 's'))
{
STHROWF("Unknown format specifier: %c", spec);
// Default to empty string
return _SC("");
STHROWF("Unknown format specifier: '%c'", spec);
}
// Is there even a string to escape?
else if (!str)
{
return _SC(""); // Default to empty string
}
// Apply the format specifier
fs[1] = spec;
// Attempt to escape the specified string
@ -469,7 +631,9 @@ 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
@ -483,7 +647,9 @@ CCStr ArrayToQueryColumns(Array & arr)
{
// Is the name valid?
if (itr->empty())
{
STHROWF("Invalid column name");
}
// Attempt to append the column name to the buffer
sqlite3_snprintf(sizeof(g_Buffer) - offset, g_Buffer + offset, "[%q], ", itr->c_str());
// Add the column name size to the offset
@ -493,9 +659,13 @@ CCStr ArrayToQueryColumns(Array & arr)
}
// Trim the last coma and space
if (offset >= 2)
g_Buffer[offset-2] = 0;
{
g_Buffer[offset-2] = '\0';
}
else
g_Buffer[0] = 0;
{
g_Buffer[0] = '\0';
}
// Return the resulted string
return g_Buffer;
}
@ -516,7 +686,9 @@ CCStr TableToQueryColumns(Table & tbl)
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(sizeof(g_Buffer) - offset, g_Buffer + offset, "[%q], ", name.c_str());
// Add the column name size to the offset
@ -526,9 +698,13 @@ CCStr TableToQueryColumns(Table & tbl)
}
// Trim the last coma and space
if (offset >= 2)
g_Buffer[offset-2] = 0;
{
g_Buffer[offset-2] = '\0';
}
else
g_Buffer[0] = 0;
{
g_Buffer[0] = '\0';
}
// Return the resulted string
return g_Buffer;
}

View File

@ -13,6 +13,7 @@
// ------------------------------------------------------------------------------------------------
#include <sqlite3.h>
#include <squirrel.h>
// ------------------------------------------------------------------------------------------------
namespace SqMod {
@ -73,6 +74,11 @@ bool IsQueryEmpty(CSStr str);
*/
struct StackGuard
{
/* --------------------------------------------------------------------------------------------
* Default constructor.
*/
StackGuard();
/* --------------------------------------------------------------------------------------------
* Base constructor.
*/
@ -108,8 +114,51 @@ private:
private:
// --------------------------------------------------------------------------------------------
Int32 m_Top; /* The top of the stack when this instance was created. */
HSQUIRRELVM m_VM; /* The VM where the stack should be restored. */
HSQUIRRELVM m_VM; // The VM where the stack should be restored.
Int32 m_Top; // The top of the stack when this instance was created.
};
/* ------------------------------------------------------------------------------------------------
* Helper structure for retrieving a value from the stack as a string or a formatted string.
*/
struct StackStrF
{
// --------------------------------------------------------------------------------------------
CSStr mPtr; // Pointer to the C string that was retrieved.
SQInteger mLen; // The string length if it could be retrieved.
SQRESULT mRes; // The result of the retrieval attempts.
HSQOBJECT mObj; // Strong reference to the string object.
HSQUIRRELVM mVM; // The associated virtual machine.
/* --------------------------------------------------------------------------------------------
* Base constructor.
*/
StackStrF(HSQUIRRELVM vm, SQInteger idx, bool fmt = true);
/* --------------------------------------------------------------------------------------------
* Copy constructor. (disabled)
*/
StackStrF(const StackStrF & o) = delete;
/* --------------------------------------------------------------------------------------------
* Copy constructor. (disabled)
*/
StackStrF(StackStrF && o) = delete;
/* --------------------------------------------------------------------------------------------
* Destructor.
*/
~StackStrF();
/* --------------------------------------------------------------------------------------------
* Copy constructor. (disabled)
*/
StackStrF & operator = (const StackStrF & o) = delete;
/* --------------------------------------------------------------------------------------------
* Copy constructor. (disabled)
*/
StackStrF & operator = (StackStrF && o) = delete;
};
/* ------------------------------------------------------------------------------------------------
@ -137,6 +186,11 @@ public:
// --------------------------------------------------------------------------------------------
typedef unsigned int Counter; // Reference counter type.
/* --------------------------------------------------------------------------------------------
* Validate the connection handle and throw an error if invalid.
*/
void Validate() const;
protected:
// --------------------------------------------------------------------------------------------
@ -171,7 +225,7 @@ protected:
* Base constructor.
*/
Handle(Counter counter)
: mPtr(NULL)
: mPtr(nullptr)
, mRef(counter)
, mStatus(SQLITE_OK)
, mQueue()
@ -232,7 +286,7 @@ private:
* Base constructor.
*/
ConnHnd(CSStr name)
: m_Hnd(name ? new Handle(1) : NULL)
: m_Hnd(name ? new Handle(1) : nullptr)
{
/* ... */
}
@ -243,7 +297,7 @@ public:
* Default constructor (null).
*/
ConnHnd()
: m_Hnd(NULL)
: m_Hnd(nullptr)
{
/* ... */
}
@ -263,7 +317,7 @@ public:
ConnHnd(ConnHnd && o)
: m_Hnd(o.m_Hnd)
{
o.m_Hnd = NULL;
o.m_Hnd = nullptr;
}
/* --------------------------------------------------------------------------------------------
@ -296,7 +350,7 @@ public:
if (m_Hnd != o.m_Hnd)
{
m_Hnd = o.m_Hnd;
o.m_Hnd = NULL;
o.m_Hnd = nullptr;
}
return *this;
@ -367,7 +421,7 @@ public:
*/
operator Pointer ()
{
return m_Hnd ? m_Hnd->mPtr : NULL;
return m_Hnd ? m_Hnd->mPtr : nullptr;
}
/* --------------------------------------------------------------------------------------------
@ -375,7 +429,7 @@ public:
*/
operator Pointer () const
{
return m_Hnd ? m_Hnd->mPtr : NULL;
return m_Hnd ? m_Hnd->mPtr : nullptr;
}
/* --------------------------------------------------------------------------------------------
@ -524,6 +578,11 @@ public:
// --------------------------------------------------------------------------------------------
typedef unsigned int Counter; // Reference counter type.
/* --------------------------------------------------------------------------------------------
* Validate the statement handle and throw an error if invalid.
*/
void Validate() const;
protected:
// --------------------------------------------------------------------------------------------
@ -559,7 +618,7 @@ protected:
* Base constructor.
*/
Handle(const ConnHnd & conn, Counter counter)
: mPtr(NULL)
: mPtr(nullptr)
, mRef(counter)
, mStatus(SQLITE_OK)
, mConn(conn)
@ -638,7 +697,7 @@ public:
* Default constructor (null).
*/
StmtHnd()
: m_Hnd(NULL)
: m_Hnd(nullptr)
{
/* ... */
}
@ -659,7 +718,7 @@ public:
StmtHnd(StmtHnd && o)
: m_Hnd(o.m_Hnd)
{
o.m_Hnd = NULL;
o.m_Hnd = nullptr;
}
/* --------------------------------------------------------------------------------------------
@ -692,7 +751,7 @@ public:
if (m_Hnd != o.m_Hnd)
{
m_Hnd = o.m_Hnd;
o.m_Hnd = NULL;
o.m_Hnd = nullptr;
}
return *this;
@ -763,7 +822,7 @@ public:
*/
operator Pointer ()
{
return m_Hnd ? m_Hnd->mPtr : NULL;
return m_Hnd ? m_Hnd->mPtr : nullptr;
}
/* --------------------------------------------------------------------------------------------
@ -771,7 +830,7 @@ public:
*/
operator Pointer () const
{
return m_Hnd ? m_Hnd->mPtr : NULL;
return m_Hnd ? m_Hnd->mPtr : nullptr;
}
/* --------------------------------------------------------------------------------------------

View File

@ -17,14 +17,6 @@ SQInteger Connection::Typename(HSQUIRRELVM vm)
return 1;
}
// ------------------------------------------------------------------------------------------------
void Connection::Validate() const
{
// Is the handle valid?
if (!m_Handle)
STHROWF("Invalid SQLite connection reference");
}
// ------------------------------------------------------------------------------------------------
Connection::Connection()
: m_Handle()
@ -37,7 +29,9 @@ Connection::Connection(CSStr name)
: m_Handle(name)
{
if (m_Handle.m_Hnd)
m_Handle->Create(name, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, NULL);
{
m_Handle->Create(name, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, nullptr);
}
}
// ------------------------------------------------------------------------------------------------
@ -45,7 +39,9 @@ Connection::Connection(CSStr name, Int32 flags)
: m_Handle(name)
{
if (m_Handle.m_Hnd)
m_Handle->Create(name, flags, NULL);
{
m_Handle->Create(name, flags, nullptr);
}
}
// ------------------------------------------------------------------------------------------------
@ -53,17 +49,21 @@ Connection::Connection(CSStr name, Int32 flags, CSStr vfs)
: m_Handle(name)
{
if (m_Handle.m_Hnd)
{
m_Handle->Create(name, flags, vfs);
}
}
// ------------------------------------------------------------------------------------------------
Int32 Connection::Exec(CSStr str)
{
// Validate the handle
Validate();
m_Handle.Validate();
// Attempt to execute the specified query
if ((m_Handle = sqlite3_exec(m_Handle, str, NULL, NULL, NULL)) != SQLITE_OK)
if ((m_Handle = sqlite3_exec(m_Handle, str, nullptr, nullptr, nullptr)) != SQLITE_OK)
{
STHROWF("Unable to execute query [%s]", m_Handle.ErrMsg());
}
// Return rows affected by this query
return sqlite3_changes(m_Handle);
}
@ -72,7 +72,7 @@ Int32 Connection::Exec(CSStr str)
Object Connection::Query(CSStr str) const
{
// Validate the handle
Validate();
m_Handle.Validate();
// Return the requested information
return Object(new Statement(m_Handle, str));
}
@ -81,10 +81,12 @@ Object Connection::Query(CSStr str) const
void Connection::Queue(CSStr str)
{
// Validate the handle
Validate();
m_Handle.Validate();
// Is there a query to commit?
if (IsQueryEmpty(str))
{
STHROWF("No query string to queue");
}
// Add the specified string to the queue
m_Handle->mQueue.push_back(str);
}
@ -93,12 +95,14 @@ void Connection::Queue(CSStr str)
bool Connection::IsReadOnly() const
{
// Validate the handle
Validate();
m_Handle.Validate();
// Request the desired information
const int result = sqlite3_db_readonly(m_Handle, "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);
}
@ -107,7 +111,7 @@ bool Connection::IsReadOnly() const
bool Connection::TableExists(CCStr name) const
{
// Validate the handle
Validate();
m_Handle.Validate();
// Prepare a statement to inspect the master table
Statement stmt(m_Handle, "SELECT count(*) FROM [sqlite_master] WHERE [type]='table' AND [name]=?");
// Could the statement be created?
@ -117,8 +121,10 @@ bool Connection::TableExists(CCStr name) const
stmt.IndexBindS(1, 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;
}
@ -127,7 +133,7 @@ bool Connection::TableExists(CCStr name) const
Object Connection::GetLastInsertRowID() const
{
// Validate the handle
Validate();
m_Handle.Validate();
// Obtain the initial stack size
const StackGuard sg(_SqVM);
// Push a long integer instance with the requested value on the stack
@ -140,26 +146,32 @@ Object Connection::GetLastInsertRowID() const
void Connection::SetBusyTimeout(Int32 millis)
{
// Validate the handle
Validate();
m_Handle.Validate();
// Apply requested timeout
if ((m_Handle = sqlite3_busy_timeout(m_Handle, millis)) != SQLITE_OK)
{
STHROWF("Unable to set busy timeout [%s]", m_Handle.ErrMsg());
}
}
// ------------------------------------------------------------------------------------------------
Int32 Connection::GetInfo(Int32 operation, bool highwater, bool reset)
{
// Don't even bother to continue if there's no valid connection handle
Validate();
m_Handle.Validate();
// Where to retrieve the information
Int32 cur_value;
Int32 hiwtr_value;
// Attempt to retrieve the specified information
if ((m_Handle = sqlite3_db_status(m_Handle, 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;
}
@ -168,7 +180,7 @@ Int32 Connection::GetInfo(Int32 operation, bool highwater, bool reset)
void Connection::ReserveQueue(Uint32 num)
{
// Validate the handle
Validate();
m_Handle.Validate();
// Perform the requested operation
m_Handle->mQueue.reserve(m_Handle->mQueue.size() + num);
}
@ -177,7 +189,7 @@ void Connection::ReserveQueue(Uint32 num)
Int32 Connection::Flush(Uint32 num)
{
// Validate the handle
Validate();
m_Handle.Validate();
// We need to supply a null callback
Object env;
Function func;
@ -189,7 +201,7 @@ Int32 Connection::Flush(Uint32 num)
Int32 Connection::Flush(Uint32 num, Object & env, Function & func)
{
// Validate the handle
Validate();
m_Handle.Validate();
// Attempt to flush the requested amount of queries
return m_Handle->Flush(num, env, func);
}
@ -232,56 +244,21 @@ SQInteger Connection::ExecF(HSQUIRRELVM vm)
return sq_throwerror(vm, "Invalid SQLite connection instance");
}
// Do we have a valid connection identifier?
else if (!conn->m_Handle)
else if (!(conn->m_Handle))
{
return sq_throwerror(vm, "Invalid SQLite connection reference");
}
// Do we have enough values to call the format function?
else if (top > 2)
{
SStr sql = NULL;
SQInteger len = 0;
// Attempt to generate the specified string format
SQRESULT ret = sqstd_format(vm, 2, &len, &sql);
// Did the format failed?
if (SQ_FAILED(ret))
{
return ret; // Propagate the exception
}
// Attempt to execute the specified query
else if ((conn->m_Handle = sqlite3_exec(conn->m_Handle, sql, NULL, NULL, NULL)) != SQLITE_OK)
{
// Generate the query message first
String msg("Unable to execute query ");
// (we can't use FmtStr here because Squirrel doesn't make a copy of the message)
msg.push_back('[');
msg.append(conn->m_Handle.ErrMsg());
msg.push_back(']');
// Now throw the message
return sq_throwerror(vm, msg.c_str());
}
}
else
{
// Attempt to retrieve the value from the stack as a string
Var< CSStr > sql(vm, 2);
// See if the obtained value is a valid query string
if (!sql.value)
StackStrF val(vm, 2);
// Have we failed to retrieve the string?
if (SQ_FAILED(val.mRes))
{
return sq_throwerror(vm, "Unable to retrieve the query");
return val.mRes; // Propagate the error!
}
// Attempt to execute the specified query
else if ((conn->m_Handle = sqlite3_exec(conn->m_Handle, sql.value, NULL, NULL, NULL)) != SQLITE_OK)
else if ((conn->m_Handle = sqlite3_exec(conn->m_Handle, val.mPtr, nullptr, nullptr, nullptr)) != SQLITE_OK)
{
// Generate the query message first
String msg("Unable to execute query ");
// (we can't use FmtStr here because Squirrel doesn't make a copy of the message)
msg.push_back('[');
msg.append(conn->m_Handle.ErrMsg());
msg.push_back(']');
// Now throw the message
return sq_throwerror(vm, msg.c_str());
}
return sq_throwerror(vm, FmtStr("Unable to execute query [%s]", conn->m_Handle.ErrMsg()));
}
// Push the number of changes onto the stack
sq_pushinteger(vm, sqlite3_changes(conn->m_Handle));
@ -316,37 +293,19 @@ SQInteger Connection::QueueF(HSQUIRRELVM vm)
return sq_throwerror(vm, "Invalid SQLite connection instance");
}
// Do we have a valid connection identifier?
else if (!conn->m_Handle)
else if (!(conn->m_Handle))
{
return sq_throwerror(vm, "Invalid SQLite connection reference");
}
// Do we have enough values to call the format function?
else if (top > 2)
{
SStr sql = NULL;
SQInteger len = 0;
// Attempt to generate the specified string format
SQRESULT ret = sqstd_format(vm, 2, &len, &sql);
// Did the format failed?
if (SQ_FAILED(ret))
{
return ret; // Propagate the exception
}
// Attempt to queue the specified query
conn->m_Handle->mQueue.emplace_back(sql);
}
else
{
// Attempt to retrieve the value from the stack as a string
Var< CSStr > sql(vm, 2);
// See if the obtained value is a valid query string
if (!sql.value)
StackStrF val(vm, 2);
// Have we failed to retrieve the string?
if (SQ_FAILED(val.mRes))
{
return sq_throwerror(vm, "Unable to retrieve the query");
return val.mRes; // Propagate the error!
}
// Attempt to queue the specified query
conn->m_Handle->mQueue.emplace_back(sql.value);
}
conn->m_Handle->mQueue.emplace_back(val.mPtr);
// This function does not return a value
return 0;
}
@ -378,51 +337,26 @@ SQInteger Connection::QueryF(HSQUIRRELVM vm)
return sq_throwerror(vm, "Invalid SQLite connection instance");
}
// Do we have a valid connection identifier?
else if (!conn->m_Handle)
else if (!(conn->m_Handle))
{
return sq_throwerror(vm, "Invalid SQLite connection reference");
}
// Do we have enough values to call the format function?
else if (top > 2)
{
SStr sql = NULL;
SQInteger len = 0;
// Attempt to generate the specified string format
SQRESULT ret = sqstd_format(vm, 2, &len, &sql);
// Did the format failed?
if (SQ_FAILED(ret))
{
return ret; // Propagate the exception
}
// Attempt to create a statement with the specified query
try
{
ClassType< Statement >::PushInstance(vm, new Statement(conn->m_Handle, sql));
}
catch (const Sqrat::Exception & e)
{
return sq_throwerror(vm, e.Message().c_str());
}
}
else
{
// Attempt to retrieve the value from the stack as a string
Var< CSStr > sql(vm, 2);
// See if the obtained value is a valid query string
if (!sql.value)
StackStrF val(vm, 2);
// Have we failed to retrieve the string?
if (SQ_FAILED(val.mRes))
{
return sq_throwerror(vm, "Unable to retrieve the query");
return val.mRes; // Propagate the error!
}
// Attempt to create a statement with the specified query
try
{
ClassType< Statement >::PushInstance(vm, new Statement(conn->m_Handle, sql.value));
ClassType< Statement >::PushInstance(vm, new Statement(conn->m_Handle, val.mPtr));
}
catch (const Sqrat::Exception & e)
{
return sq_throwerror(vm, e.Message().c_str());
}
}
// This function returned a value
return 1;
}

View File

@ -20,15 +20,10 @@ protected:
*/
void Create(CSStr name, Int32 flags, CSStr vfs);
/* --------------------------------------------------------------------------------------------
* Validate the document reference and throw an error if invalid.
*/
void Validate() const;
private:
// --------------------------------------------------------------------------------------------
ConnHnd m_Handle; /* The handle to the managed database connection resource. */
ConnHnd m_Handle; // The handle to the managed database connection resource.
public:
@ -125,12 +120,18 @@ public:
Int32 Cmp(const Connection & o) const
{
if (m_Handle == m_Handle)
{
return 0;
}
else if (m_Handle.m_Hnd > o.m_Handle.m_Hnd)
{
return 1;
}
else
{
return -1;
}
}
/* --------------------------------------------------------------------------------------------
* Used by the script engine to convert an instance of this type to a string.
@ -138,7 +139,7 @@ public:
CSStr ToString() const
{
// Validate the handle
Validate();
m_Handle.Validate();
// Return the requested information
return m_Handle->mName.c_str();
}
@ -186,7 +187,7 @@ public:
Int32 GetStatus() const
{
// Validate the handle
Validate();
m_Handle.Validate();
// Return the requested information
return m_Handle->mStatus;
}
@ -197,7 +198,7 @@ public:
Int32 GetFlags() const
{
// Validate the handle
Validate();
m_Handle.Validate();
// Return the requested information
return m_Handle->mFlags;
}
@ -208,7 +209,7 @@ public:
CSStr GetName() const
{
// Validate the handle
Validate();
m_Handle.Validate();
// Return the requested information
return m_Handle->mName.c_str();
}
@ -219,7 +220,7 @@ public:
CSStr GetVFS() const
{
// Validate the handle
Validate();
m_Handle.Validate();
// Return the requested information
return m_Handle->mVFS.c_str();
}
@ -230,7 +231,7 @@ public:
Int32 GetErrorCode() const
{
// Validate the handle
Validate();
m_Handle.Validate();
// Return the requested information
return m_Handle.ErrNo();
}
@ -241,7 +242,7 @@ public:
Int32 GetExtendedErrorCode() const
{
// Validate the handle
Validate();
m_Handle.Validate();
// Return the requested information
return m_Handle.ExErrNo();
}
@ -252,7 +253,7 @@ public:
CSStr GetErrStr() const
{
// Validate the handle
Validate();
m_Handle.Validate();
// Return the requested information
return m_Handle.ErrStr();
}
@ -263,7 +264,7 @@ public:
CSStr GetErrMsg() const
{
// Validate the handle
Validate();
m_Handle.Validate();
// Return the requested information
return m_Handle.ErrMsg();
}
@ -274,7 +275,9 @@ public:
void Open(CSStr name)
{
if (m_Handle.m_Hnd)
m_Handle->Create(name, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, NULL);
{
m_Handle->Create(name, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, nullptr);
}
}
/* --------------------------------------------------------------------------------------------
@ -283,7 +286,9 @@ public:
void Open(CSStr name, Int32 flags)
{
if (m_Handle.m_Hnd)
m_Handle->Create(name, flags, NULL);
{
m_Handle->Create(name, flags, nullptr);
}
}
/* --------------------------------------------------------------------------------------------
@ -292,8 +297,10 @@ public:
void Open(CSStr name, Int32 flags, CSStr vfs)
{
if (m_Handle.m_Hnd)
{
m_Handle->Create(name, flags, vfs);
}
}
/* --------------------------------------------------------------------------------------------
* Attempt to execute the specified query.
@ -326,7 +333,7 @@ public:
bool GetAutoCommit() const
{
// Validate the handle
Validate();
m_Handle.Validate();
// Return the requested information
return sqlite3_get_autocommit(m_Handle);
}
@ -343,7 +350,7 @@ public:
Int32 GetChanges() const
{
// Validate the handle
Validate();
m_Handle.Validate();
// Return the requested information
return sqlite3_changes(m_Handle);
}
@ -355,7 +362,7 @@ public:
Int32 GetTotalChanges() const
{
// Validate the handle
Validate();
m_Handle.Validate();
// Return the requested information
return sqlite3_total_changes(m_Handle);
}
@ -366,7 +373,7 @@ public:
bool GetTracing() const
{
// Validate the handle
Validate();
m_Handle.Validate();
// Return the requested information
return m_Handle->mTrace;
}
@ -377,16 +384,22 @@ public:
void SetTracing(bool toggle)
{
// Validate the handle
Validate();
m_Handle.Validate();
// Check whether changes are necessary
if (m_Handle->mTrace == toggle)
return; /* No point in proceeding */
{
return; // No point in proceeding
}
// Do we have to disable it?
else if (m_Handle->mTrace)
sqlite3_trace(m_Handle, NULL, NULL);
{
sqlite3_trace(m_Handle, nullptr, nullptr);
}
// Go ahead and enable tracing
else
sqlite3_trace(m_Handle, &Connection::TraceOutput, NULL);
{
sqlite3_trace(m_Handle, &Connection::TraceOutput, nullptr);
}
}
/* --------------------------------------------------------------------------------------------
@ -395,7 +408,7 @@ public:
bool GetProfiling() const
{
// Validate the handle
Validate();
m_Handle.Validate();
// Return the requested information
return m_Handle->mProfile;
}
@ -406,16 +419,22 @@ public:
void SetProfiling(bool toggle)
{
// Validate the handle
Validate();
m_Handle.Validate();
// Check whether changes are necessary
if (m_Handle->mProfile == toggle)
return; /* No point in proceeding */
{
return; // No point in proceeding
}
// Do we have to disable it?
else if (m_Handle->mProfile)
sqlite3_profile(m_Handle, NULL, NULL);
{
sqlite3_profile(m_Handle, nullptr, nullptr);
}
// Go ahead and enable profiling
else
sqlite3_profile(m_Handle, &Connection::ProfileOutput, NULL);
{
sqlite3_profile(m_Handle, &Connection::ProfileOutput, nullptr);
}
}
/* --------------------------------------------------------------------------------------------
@ -429,7 +448,7 @@ public:
void InterruptOperation() const
{
// Validate the handle
Validate();
m_Handle.Validate();
// Perform the requested action
sqlite3_interrupt(m_Handle);
}
@ -440,7 +459,7 @@ public:
void ReleaseMemory() const
{
// Validate the handle
Validate();
m_Handle.Validate();
// Perform the requested action
sqlite3_db_release_memory(m_Handle);
}
@ -472,7 +491,7 @@ public:
Uint32 QueueSize() const
{
// Validate the handle
Validate();
m_Handle.Validate();
// Return the requested information
return (Uint32)m_Handle->mQueue.size();
}
@ -488,7 +507,7 @@ public:
void CompactQueue()
{
// Validate the handle
Validate();
m_Handle.Validate();
// Perform the requested operation
m_Handle->mQueue.shrink_to_fit();
}
@ -499,7 +518,7 @@ public:
void ClearQueue()
{
// Validate the handle
Validate();
m_Handle.Validate();
// Perform the requested operation
m_Handle->mQueue.clear();
}
@ -510,11 +529,13 @@ public:
void PopQueue()
{
// Validate the handle
Validate();
m_Handle.Validate();
// Perform the requested action
if (!m_Handle->mQueue.empty())
{
m_Handle->mQueue.pop_back();
}
}
/* --------------------------------------------------------------------------------------------
* Flush all queries from the queue.
@ -522,7 +543,7 @@ public:
Int32 Flush()
{
// Validate the handle
Validate();
m_Handle.Validate();
// Return the requested information
return Flush(m_Handle->mQueue.size());
}
@ -538,7 +559,7 @@ public:
Int32 Flush(Object & env, Function & func)
{
// Validate the handle
Validate();
m_Handle.Validate();
// Return the requested information
return Flush(m_Handle->mQueue.size(), env, func);
}

View File

@ -6,12 +6,12 @@
#include "Column.hpp"
// --------------------------------------------------------------------------------------------
#include <sqrat.h>
#include <cstdio>
#include <cstdlib>
#include <cstdarg>
// --------------------------------------------------------------------------------------------
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <sqrat.h>
// --------------------------------------------------------------------------------------------
#if defined(WIN32) || defined(_WIN32)
@ -21,14 +21,14 @@
namespace SqMod {
// --------------------------------------------------------------------------------------------
PluginFuncs* _Func = NULL;
PluginCallbacks* _Clbk = NULL;
PluginInfo* _Info = NULL;
PluginFuncs* _Func = nullptr;
PluginCallbacks* _Clbk = nullptr;
PluginInfo* _Info = nullptr;
// --------------------------------------------------------------------------------------------
HSQAPI _SqAPI = NULL;
HSQEXPORTS _SqMod = NULL;
HSQUIRRELVM _SqVM = NULL;
HSQAPI _SqAPI = nullptr;
HSQEXPORTS _SqMod = nullptr;
HSQUIRRELVM _SqVM = nullptr;
/* ------------------------------------------------------------------------------------------------
* Bind speciffic functions to certain server events.
@ -54,7 +54,9 @@ void OnSquirrelInitialize()
_SqMod = sq_api_import(_Func);
// Did we failed to obtain the plugin exports?
if(!_SqMod)
{
OutputError("Failed to attach [%s] on host plugin.", SQSQLITE_NAME);
}
else
{
// Obtain the Squirrel API
@ -71,12 +73,16 @@ void OnSquirrelLoad()
{
// Make sure that we have a valid plugin API
if (!_SqMod)
return; /* Unable to proceed. */
{
return; // Unable to proceed.
}
// Obtain the Squirrel API and VM
_SqVM = _SqMod->GetSquirrelVM();
// Make sure that a valid virtual machine exists
if (!_SqVM)
return; /* Unable to proceed. */
{
return; // Unable to proceed.
}
// Set this as the default database
DefaultVM::Set(_SqVM);
// Register the module API
@ -92,7 +98,7 @@ void OnSquirrelTerminate()
{
OutputMessage("Terminating: %s", SQSQLITE_NAME);
// Release the current database (if any)
DefaultVM::Set(NULL);
DefaultVM::Set(nullptr);
}
/* --------------------------------------------------------------------------------------------
@ -101,10 +107,12 @@ void OnSquirrelTerminate()
bool CheckAPIVer(CCStr ver)
{
// Obtain the numeric representation of the API version
long vernum = strtol(ver, NULL, 10);
long vernum = strtol(ver, nullptr, 10);
// Check against version mismatch
if (vernum == SQMOD_API_VER)
{
return true;
}
// Log the incident
OutputError("API version mismatch on %s", SQSQLITE_NAME);
OutputMessage("=> Requested: %ld Have: %ld", vernum, SQMOD_API_VER);
@ -121,7 +129,9 @@ static int OnInternalCommand(unsigned int type, const char * text)
{
case SQMOD_INITIALIZE_CMD:
if (CheckAPIVer(text))
{
OnSquirrelInitialize();
}
break;
case SQMOD_LOAD_CMD:
OnSquirrelLoad();
@ -159,9 +169,9 @@ void BindCallbacks()
// ------------------------------------------------------------------------------------------------
void UnbindCallbacks()
{
_Clbk->OnInitServer = NULL;
_Clbk->OnInternalCommand = NULL;
_Clbk->OnShutdownServer = NULL;
_Clbk->OnInitServer = nullptr;
_Clbk->OnInternalCommand = nullptr;
_Clbk->OnShutdownServer = nullptr;
}
// --------------------------------------------------------------------------------------------
@ -199,7 +209,7 @@ void RegisterAPI(HSQUIRRELVM vm)
.Prop(_SC("TotalChanges"), &Connection::GetTotalChanges)
.Prop(_SC("Trace"), &Connection::GetTracing, &Connection::SetTracing)
.Prop(_SC("Profile"), &Connection::GetProfiling, &Connection::SetProfiling)
.Prop(_SC("BusyTimeout"), (Int32 (Connection::*)(void) const)(NULL), &Connection::SetBusyTimeout)
.Prop(_SC("BusyTimeout"), (Int32 (Connection::*)(void) const)(nullptr), &Connection::SetBusyTimeout)
.Prop(_SC("QueueSize"), &Connection::QueueSize)
// Member Methods
.Func(_SC("Release"), &Connection::Release)
@ -584,7 +594,7 @@ void RegisterAPI(HSQUIRRELVM vm)
.Const(_SC("NOTICE"), SQLITE_NOTICE)
.Const(_SC("NOTICE_RECOVER_ROLLBACK"), SQLITE_NOTICE_RECOVER_ROLLBACK)
.Const(_SC("NOTICE_RECOVER_WAL"), SQLITE_NOTICE_RECOVER_WAL)
.Const(_SC("NULL"), SQLITE_NULL)
.Const(_SC("nullptr"), SQLITE_NULL)
.Const(_SC("OK"), SQLITE_OK)
.Const(_SC("OPEN_AUTOPROXY"), SQLITE_OPEN_AUTOPROXY)
.Const(_SC("OPEN_CREATE"), SQLITE_OPEN_CREATE)

View File

@ -4,6 +4,9 @@
#include "Column.hpp"
#include "Module.hpp"
// ------------------------------------------------------------------------------------------------
#include <cstring>
// ------------------------------------------------------------------------------------------------
#include <sqrat.h>
@ -24,16 +27,6 @@ SQInteger Statement::Typename(HSQUIRRELVM vm)
return 1;
}
// ------------------------------------------------------------------------------------------------
void Statement::Validate() const
{
// Is the handle valid?
if (!m_Handle)
{
STHROWF("Invalid SQLite statement reference");
}
}
// ------------------------------------------------------------------------------------------------
void Statement::ValidateIndex(Int32 idx) const
{
@ -107,7 +100,7 @@ Statement::Statement(const Connection & connection, CSStr query)
Object Statement::GetConnection() const
{
// Validate the handle
Validate();
m_Handle.Validate();
// Return the requested information
return Object(new Connection(m_Handle->mConn));
}
@ -116,7 +109,7 @@ Object Statement::GetConnection() const
void Statement::Reset()
{
// Validate the handle
Validate();
m_Handle.Validate();
// Specify that we don't have a row available and we haven't finished stepping
m_Handle->mGood = false;
m_Handle->mDone = false;
@ -133,7 +126,7 @@ void Statement::Reset()
void Statement::Clear()
{
// Validate the handle
Validate();
m_Handle.Validate();
// Specify that we don't have a row available and we haven't finished stepping
m_Handle->mGood = false;
m_Handle->mDone = false;
@ -150,7 +143,7 @@ void Statement::Clear()
Int32 Statement::Exec()
{
// Validate the handle
Validate();
m_Handle.Validate();
// Did we reset first?
if (m_Handle->mDone)
{
@ -188,7 +181,7 @@ Int32 Statement::Exec()
bool Statement::Step()
{
// Validate the handle
Validate();
m_Handle.Validate();
// Did we reset first?
if (m_Handle->mDone)
{
@ -229,7 +222,7 @@ bool Statement::Step()
void Statement::IndexBindA(Int32 idx, const Array & arr)
{
// Validate the handle
Validate();
m_Handle.Validate();
// Know when to stop trying to bind values
const Int32 max = sqlite3_bind_parameter_count(m_Handle);
// Make sure that we are at least in bounds
@ -267,7 +260,7 @@ void Statement::IndexBindA(Int32 idx, const Array & arr)
void Statement::IndexBindI(Int32 idx, Int32 value)
{
// Validate the handle
Validate();
m_Handle.Validate();
// Attempt to bind the specified value
m_Handle = sqlite3_bind_int(m_Handle, idx, value);
// Validate the result
@ -281,7 +274,7 @@ void Statement::IndexBindI(Int32 idx, Int32 value)
void Statement::IndexBindL(Int32 idx, const Object & value)
{
// Validate the handle
Validate();
m_Handle.Validate();
// Obtain the initial stack size
const StackGuard sg(DefaultVM::Get());
// Push the specified object onto the stack
@ -306,7 +299,7 @@ void Statement::IndexBindL(Int32 idx, const Object & value)
void Statement::IndexBindV(Int32 idx, SQInteger value)
{
// Validate the handle
Validate();
m_Handle.Validate();
// Attempt to bind the specified value
#ifdef _SQ64
m_Handle = sqlite3_bind_int64(m_Handle, idx, value);
@ -324,7 +317,7 @@ void Statement::IndexBindV(Int32 idx, SQInteger value)
void Statement::IndexBindF(Int32 idx, SQFloat value)
{
// Validate the handle
Validate();
m_Handle.Validate();
// Attempt to bind the specified value
m_Handle = sqlite3_bind_double(m_Handle, idx, value);
// Validate the result
@ -338,7 +331,7 @@ void Statement::IndexBindF(Int32 idx, SQFloat value)
void Statement::IndexBindS(Int32 idx, CSStr value)
{
// Validate the handle
Validate();
m_Handle.Validate();
// Attempt to bind the specified value
m_Handle = sqlite3_bind_text(m_Handle, idx, value, -1, SQLITE_TRANSIENT);
// Validate the result
@ -352,7 +345,7 @@ void Statement::IndexBindS(Int32 idx, CSStr value)
void Statement::IndexBindB(Int32 idx, bool value)
{
// Validate the handle
Validate();
m_Handle.Validate();
// Attempt to bind the specified value
m_Handle = sqlite3_bind_int(m_Handle, idx, value);
// Validate the result
@ -366,7 +359,7 @@ void Statement::IndexBindB(Int32 idx, bool value)
void Statement::IndexBindN(Int32 idx)
{
// Validate the handle
Validate();
m_Handle.Validate();
// Attempt to bind the specified value
m_Handle = sqlite3_bind_null(m_Handle, idx);
// Validate the result
@ -380,7 +373,7 @@ void Statement::IndexBindN(Int32 idx)
void Statement::NameBindT(const Table & tbl)
{
// Validate the handle
Validate();
m_Handle.Validate();
// Should we clear the all the parameters?
if (tbl.GetSize() <= 0)
{
@ -408,7 +401,7 @@ void Statement::NameBindT(const Table & tbl)
void Statement::NameBindI(CSStr name, Int32 value)
{
// Validate the handle
Validate();
m_Handle.Validate();
// Attempt to obtain the index of the specified parameter name
const Int32 idx = sqlite3_bind_parameter_index(m_Handle, name);
// Validate the obtained index
@ -429,7 +422,7 @@ void Statement::NameBindI(CSStr name, Int32 value)
void Statement::NameBindL(CSStr name, const Object & value)
{
// Validate the handle
Validate();
m_Handle.Validate();
// Attempt to obtain the index of the specified parameter name
const Int32 idx = sqlite3_bind_parameter_index(m_Handle, name);
// Validate the obtained index
@ -461,7 +454,7 @@ void Statement::NameBindL(CSStr name, const Object & value)
void Statement::NameBindV(CSStr name, SQInteger value)
{
// Validate the handle
Validate();
m_Handle.Validate();
// Attempt to obtain the index of the specified parameter name
const Int32 idx = sqlite3_bind_parameter_index(m_Handle, name);
// Validate the obtained index
@ -486,7 +479,7 @@ void Statement::NameBindV(CSStr name, SQInteger value)
void Statement::NameBindF(CSStr name, SQFloat value)
{
// Validate the handle
Validate();
m_Handle.Validate();
// Attempt to obtain the index of the specified parameter name
const Int32 idx = sqlite3_bind_parameter_index(m_Handle, name);
// Validate the obtained index
@ -507,7 +500,7 @@ void Statement::NameBindF(CSStr name, SQFloat value)
void Statement::NameBindS(CSStr name, CSStr value)
{
// Validate the handle
Validate();
m_Handle.Validate();
// Attempt to obtain the index of the specified parameter name
const Int32 idx = sqlite3_bind_parameter_index(m_Handle, name);
// Validate the obtained index
@ -528,7 +521,7 @@ void Statement::NameBindS(CSStr name, CSStr value)
void Statement::NameBindB(CSStr name, bool value)
{
// Validate the handle
Validate();
m_Handle.Validate();
// Attempt to obtain the index of the specified parameter name
const Int32 idx = sqlite3_bind_parameter_index(m_Handle, name);
// Validate the obtained index
@ -549,7 +542,7 @@ void Statement::NameBindB(CSStr name, bool value)
void Statement::NameBindN(CSStr name)
{
// Validate the handle
Validate();
m_Handle.Validate();
// Attempt to obtain the index of the specified parameter name
const Int32 idx = sqlite3_bind_parameter_index(m_Handle, name);
// Validate the obtained index
@ -570,7 +563,7 @@ void Statement::NameBindN(CSStr name)
void Statement::IndexBind(Int32 idx, const Object & value)
{
// Validate the handle
Validate();
m_Handle.Validate();
// Attempt to identify the specified type
switch (value.GetType())
{
@ -620,8 +613,7 @@ void Statement::IndexBind(Int32 idx, const Object & value)
m_Handle = sqlite3_bind_int64(m_Handle, idx, longint);
} break;
// We don't recognize this kind of value!
default:
STHROWF("Attempting to bind unknown value type (%d)", idx);
default: STHROWF("Attempting to bind unknown value type (%d)", idx);
}
// Validate the result
if (m_Handle != SQLITE_OK)
@ -634,7 +626,7 @@ void Statement::IndexBind(Int32 idx, const Object & value)
void Statement::NameBind(CSStr name, const Object & value)
{
// Validate the handle
Validate();
m_Handle.Validate();
// Attempt to obtain the index of the specified parameter name
const Int32 idx = sqlite3_bind_parameter_index(m_Handle, name);
// Validate the obtained index
@ -691,8 +683,7 @@ void Statement::NameBind(CSStr name, const Object & value)
m_Handle = sqlite3_bind_int64(m_Handle, idx, longint);
} break;
// We don't recognize this kind of value!
default:
STHROWF("Attempting to bind unknown value type (%s:%d)", name, idx);
default: STHROWF("Attempting to bind unknown value type (%s:%d)", name, idx);
}
// Validate the result
if (m_Handle != SQLITE_OK)
@ -766,7 +757,9 @@ Object Statement::FetchColumnIndex(Int32 idx) const
const void * b = sqlite3_column_blob(m_Handle, idx);
// 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)
{
@ -777,11 +770,12 @@ Object Statement::FetchColumnIndex(Int32 idx) const
}
// Copy the data into the memory blob
else
memcpy(p, b, sz);
{
std::memcpy(p, b, sz);
}
} break;
// Unknown type
default:
STHROWF("Unknown value to fetch at index: %d", idx);
default: STHROWF("Unknown value to fetch at index: %d", idx);
}
// Obtain the object with the value from the stack and return it
return Var< Object >(DefaultVM::Get(), -1).value;
@ -819,7 +813,7 @@ Object Statement::FetchColumn(const Object & column) const
Array Statement::FetchArray() const
{
// Validate the handle
Validate();
m_Handle.Validate();
// Return the requested information
return FetchArray(0, m_Handle->mColumns);
}
@ -828,7 +822,7 @@ Array Statement::FetchArray() const
Array Statement::FetchArray(Int32 min) const
{
// Validate the handle
Validate();
m_Handle.Validate();
// Return the requested information
return FetchArray(min, m_Handle->mColumns);
}
@ -913,7 +907,7 @@ Array Statement::FetchArray(Int32 min, Int32 max) const
// Copy the data into the memory blob
else
{
memcpy(p, b, sz);
std::memcpy(p, b, sz);
}
// Obtain the object from the stack
Var< Object > obj(DefaultVM::Get(), -1);
@ -921,8 +915,7 @@ Array Statement::FetchArray(Int32 min, Int32 max) const
arr.Bind(elem, obj.value);
} break;
// Unknown type
default:
STHROWF("Unknown value to fetch at index: %d", idx);
default: STHROWF("Unknown value to fetch at index: %d", idx);
}
}
// Return the resulted array
@ -933,7 +926,7 @@ Array Statement::FetchArray(Int32 min, Int32 max) const
Table Statement::FetchTable() const
{
// Validate the handle
Validate();
m_Handle.Validate();
// Return the requested information
return FetchTable(0, m_Handle->mColumns);
}
@ -942,7 +935,7 @@ Table Statement::FetchTable() const
Table Statement::FetchTable(Int32 min) const
{
// Validate the handle
Validate();
m_Handle.Validate();
// Return the requested information
return FetchTable(min, m_Handle->mColumns);
}
@ -983,7 +976,9 @@ Table Statement::FetchTable(Int32 min, Int32 max) const
CSStr name = sqlite3_column_name(m_Handle, idx);
// Validate the obtained name
if (!name)
{
STHROWF("Unable to retrieve name of column (%d)", idx);
}
// Identify the type of value that must be assigned
switch (sqlite3_column_type(m_Handle, idx))
{
@ -1038,7 +1033,7 @@ Table Statement::FetchTable(Int32 min, Int32 max) const
// Copy the data into the memory blob
else
{
memcpy(p, b, sz);
std::memcpy(p, b, sz);
}
// Obtain the object from the stack
Var< Object > obj(DefaultVM::Get(), -1);
@ -1046,8 +1041,7 @@ Table Statement::FetchTable(Int32 min, Int32 max) const
tbl.Bind(name, obj.value);
} break;
// Unknown type
default:
STHROWF("Unknown value to fetch at index: %d", idx);
default: STHROWF("Unknown value to fetch at index: %d", idx);
}
}
// Return the resulted table
@ -1058,7 +1052,7 @@ Table Statement::FetchTable(Int32 min, Int32 max) const
bool Statement::CheckIndex(Int32 idx) const
{
// Validate the handle
Validate();
m_Handle.Validate();
// Return the requested information
return m_Handle->CheckIndex(idx);
}
@ -1076,7 +1070,7 @@ bool Statement::IsColumnNull(Int32 idx) const
Int32 Statement::GetColumnIndex(CSStr name) const
{
// Validate the handle
Validate();
m_Handle.Validate();
// Return the requested information
return m_Handle->GetColumnIndex(name);
}
@ -1139,7 +1133,7 @@ Object Statement::GetColumnByIndex(Int32 idx) const
Object Statement::GetColumnByName(CSStr name) const
{
// Validate the handle
Validate();
m_Handle.Validate();
// Attempt to obtain the requested column index
const Int32 idx = m_Handle->GetColumnIndex(name);
// Validate the obtained index
@ -1166,7 +1160,7 @@ Object Statement::GetColumn(const Object & column) const
}
// We don't recognize this kind of value!
STHROWF("Unknown column identifier type");
// We have to return something!
// We have to return something even if we don't rach this point!
return Object();
}

View File

@ -16,15 +16,10 @@ class Statement
private:
// --------------------------------------------------------------------------------------------
StmtHnd m_Handle; /* The handle to the managed database statement resource. */
StmtHnd m_Handle; // The handle to the managed database statement resource.
protected:
/* --------------------------------------------------------------------------------------------
* Validate the statement reference and throw an error if invalid.
*/
void Validate() const;
/* --------------------------------------------------------------------------------------------
* Validate the statement reference and index, and throw an error if they're invalid.
*/
@ -125,12 +120,18 @@ public:
Int32 Cmp(const Statement & o) const
{
if (m_Handle.m_Hnd == o.m_Handle.m_Hnd)
{
return 0;
}
else if (m_Handle.m_Hnd > o.m_Handle.m_Hnd)
{
return 1;
}
else
{
return -1;
}
}
/* --------------------------------------------------------------------------------------------
* Used by the script engine to convert an instance of this type to a string.
@ -139,7 +140,9 @@ public:
{
// Validate the handle
if (m_Handle)
{
return m_Handle->mQuery.c_str();
}
// Request failed
return _SC("");
}
@ -154,7 +157,7 @@ public:
*/
bool IsValid() const
{
return (bool)m_Handle;
return m_Handle;
}
/* --------------------------------------------------------------------------------------------
@ -192,7 +195,7 @@ public:
Int32 GetStatus() const
{
// Validate the handle
Validate();
m_Handle.Validate();
// Return the requested information
return m_Handle->mStatus;
}
@ -203,7 +206,7 @@ public:
Int32 GetErrorCode() const
{
// Validate the handle
Validate();
m_Handle.Validate();
// Return the requested information
return m_Handle.ErrNo();
}
@ -214,7 +217,7 @@ public:
Int32 GetExtendedErrorCode() const
{
// Validate the handle
Validate();
m_Handle.Validate();
// Return the requested information
return m_Handle.ExErrNo();
}
@ -225,7 +228,7 @@ public:
CSStr GetErrStr() const
{
// Validate the handle
Validate();
m_Handle.Validate();
// Return the requested information
return m_Handle.ErrStr();
}
@ -236,7 +239,7 @@ public:
CSStr GetErrMsg() const
{
// Validate the handle
Validate();
m_Handle.Validate();
// Return the requested information
return m_Handle.ErrMsg();
}
@ -247,7 +250,7 @@ public:
Int32 GetColumns() const
{
// Validate the handle
Validate();
m_Handle.Validate();
// Return the requested information
return m_Handle->mColumns;
}
@ -258,7 +261,7 @@ public:
CSStr GetQuery() const
{
// Validate the handle
Validate();
m_Handle.Validate();
// Return the requested information
return m_Handle->mQuery.c_str();
}
@ -269,7 +272,7 @@ public:
bool GetGood() const
{
// Validate the handle
Validate();
m_Handle.Validate();
// Return the requested information
return m_Handle->mGood;
}
@ -280,7 +283,7 @@ public:
bool GetDone() const
{
// Validate the handle
Validate();
m_Handle.Validate();
// Return the requested information
return m_Handle->mDone;
}