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

View File

@ -111,11 +111,17 @@ public:
Int32 Cmp(const Column & o) const Int32 Cmp(const Column & o) const
{ {
if (m_Stmt == o.m_Stmt) if (m_Stmt == o.m_Stmt)
{
return 0; return 0;
}
else if (m_Stmt.HndPtr() > o.m_Stmt.HndPtr()) else if (m_Stmt.HndPtr() > o.m_Stmt.HndPtr())
{
return 1; return 1;
}
else else
{
return -1; return -1;
}
} }
/* -------------------------------------------------------------------------------------------- /* --------------------------------------------------------------------------------------------

View File

@ -4,8 +4,9 @@
#include "Connection.hpp" #include "Connection.hpp"
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
#include <ctype.h> #include <cctype>
#include <stdarg.h> #include <cstring>
#include <cstdarg>
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
#include <sqrat.h> #include <sqrat.h>
@ -35,8 +36,10 @@ void SqThrowF(CSStr str, ...)
va_list args; va_list args;
va_start (args, str); va_start (args, str);
// Write the requested contents // Write the requested contents
if (snprintf(g_Buffer, sizeof(g_Buffer), str, args) < 0) if (std::vsnprintf(g_Buffer, sizeof(g_Buffer), str, args) < 0)
strcpy(g_Buffer, "Unknown error has occurred"); {
std::strcpy(g_Buffer, "Unknown error has occurred");
}
// Release the argument list // Release the argument list
va_end(args); va_end(args);
// Throw the exception with the resulted message // Throw the exception with the resulted message
@ -50,8 +53,10 @@ CSStr FmtStr(CSStr str, ...)
va_list args; va_list args;
va_start (args, str); va_start (args, str);
// Write the requested contents // Write the requested contents
if (snprintf(g_Buffer, sizeof(g_Buffer), str, args) < 0) if (std::vsnprintf(g_Buffer, sizeof(g_Buffer), str, args) < 0)
g_Buffer[0] = 0; /* make sure the string is terminated */ {
g_Buffer[0] = 0; // make sure the string is terminated
}
// Release the argument list // Release the argument list
va_end(args); va_end(args);
// Return the data from the buffer // Return the data from the buffer
@ -77,23 +82,34 @@ bool IsQueryEmpty(CSStr str)
{ {
// Is the pointer valid? // Is the pointer valid?
if (!str) if (!str)
{
return true; return true;
}
// Currently processed character // Currently processed character
SQChar c = 0; SQChar c = 0;
// See if the query contains any alpha numeric characters // See if the query contains any alpha numeric characters
while ((c = *str) != 0) while ((c = *str) != 0)
{ {
if (isalnum(c) != 0) if (std::isalnum(c) != 0)
{
return false; return false;
}
++str; ++str;
} }
// At this point we consider the query empty // At this point we consider the query empty
return true; return true;
} }
// ------------------------------------------------------------------------------------------------
StackGuard::StackGuard()
: m_VM(_SqVM), m_Top(sq_gettop(m_VM))
{
/* ... */
}
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
StackGuard::StackGuard(HSQUIRRELVM 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); 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() ConnHnd::Handle::~Handle()
{ {
// Is there anything to close? // Is there anything to close?
if (!mPtr) if (!mPtr)
{
return; // Nothing to close return; // Nothing to close
}
// Are we dealing with a memory leak? Technically shouldn't reach this situation! // Are we dealing with a memory leak? Technically shouldn't reach this situation!
else if (mRef != 0) else if (mRef != 0)
{
// Should we deal with undefined behavior instead? How bad is one connection left open? // 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()); _SqMod->LogErr("SQLite connection is still referenced (%s)", mName.c_str());
}
else else
{ {
// NOTE: Should we call sqlite3_interrupt(...) before closing? // NOTE: Should we call sqlite3_interrupt(...) before closing?
@ -123,7 +253,9 @@ ConnHnd::Handle::~Handle()
Flush(mQueue.size(), env, func); Flush(mQueue.size(), env, func);
// Attempt to close the database // Attempt to close the database
if ((sqlite3_close(mPtr)) != SQLITE_OK) if ((sqlite3_close(mPtr)) != SQLITE_OK)
{
_SqMod->LogErr("Unable to close SQLite connection [%s]", sqlite3_errmsg(mPtr)); _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 // Make sure a previous connection doesn't exist
if (mPtr) if (mPtr)
{
STHROWF("Unable to connect to database. Database already connected"); STHROWF("Unable to connect to database. Database already connected");
}
// Make sure the name is valid // 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"); STHROWF("Unable to connect to database. The name is invalid");
}
// Attempt to create the database connection // Attempt to create the database connection
else if ((mStatus = sqlite3_open_v2(name, &mPtr, flags, vfs)) != SQLITE_OK) 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 // Must be destroyed regardless of result
sqlite3_close(mPtr); sqlite3_close(mPtr);
// Explicitly make sure it's null // Explicitly make sure it's null
mPtr = NULL; mPtr = nullptr;
// Now its safe to throw the error // 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 // Let's save the specified information
mName.assign(name); mName.assign(name);
@ -178,7 +316,7 @@ Int32 ConnHnd::Handle::Flush(Uint32 num, Object & env, Function & func)
QueryList::iterator itr = mQueue.begin(); QueryList::iterator itr = mQueue.begin();
QueryList::iterator end = mQueue.begin() + num; QueryList::iterator end = mQueue.begin() + num;
// Attempt to begin the flush transaction // 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)); 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 // 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; 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) // Erase all queries till end or till the point of failure (if any occurred)
mQueue.erase(mQueue.begin(), itr); mQueue.erase(mQueue.begin(), itr);
// Attempt to commit changes requested during transaction // 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); return sqlite3_changes(mPtr);
} }
// Attempt to roll back erroneous changes // 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)); STHROWF("Unable to rollback flush transaction [%s]", sqlite3_errmsg(mPtr));
} }
@ -250,16 +388,22 @@ StmtHnd::Handle::~Handle()
{ {
// Is there anything to finalize? // Is there anything to finalize?
if (!mPtr) if (!mPtr)
{
return; // Nothing to finalize return; // Nothing to finalize
}
// Are we dealing with a memory leak? Technically shouldn't reach this situation! // Are we dealing with a memory leak? Technically shouldn't reach this situation!
else if (mRef != 0) else if (mRef != 0)
{
// Should we deal with undefined behavior instead? How bad is one statement left alive? // 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()); _SqMod->LogErr("SQLite statement is still referenced (%s)", mQuery.c_str());
}
else else
{ {
// Attempt to finalize the statement // Attempt to finalize the statement
if ((sqlite3_finalize(mPtr)) != SQLITE_OK) if ((sqlite3_finalize(mPtr)) != SQLITE_OK)
{
_SqMod->LogErr("Unable to finalize SQLite statement [%s]", mConn.ErrMsg()); _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 // Make sure a previous statement doesn't exist
if (mPtr) if (mPtr)
{
STHROWF("Unable to prepare statement. Statement already prepared"); STHROWF("Unable to prepare statement. Statement already prepared");
}
// Is the specified database connection is valid? // Is the specified database connection is valid?
else if (!mConn) else if (!mConn)
{
STHROWF("Unable to prepare statement. Invalid connection handle"); STHROWF("Unable to prepare statement. Invalid connection handle");
}
// Save the query string and therefore multiple strlen(...) calls // Save the query string and therefore multiple strlen(...) calls
mQuery.assign(query ? query : _SC("")); mQuery.assign(query ? query : _SC(""));
// Is the specified query string we just saved, valid? // Is the specified query string we just saved, valid?
if (mQuery.empty()) if (mQuery.empty())
{
STHROWF("Unable to prepare statement. Invalid query string"); STHROWF("Unable to prepare statement. Invalid query string");
}
// Attempt to prepare a statement with the specified 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(), 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 // Clear the query string since it failed
mQuery.clear(); mQuery.clear();
// Explicitly make sure the handle is null // Explicitly make sure the handle is null
mPtr = NULL; mPtr = nullptr;
// Now it's safe to throw the error // Now it's safe to throw the error
STHROWF("Unable to prepare statement [%s]", mConn.ErrMsg()); STHROWF("Unable to prepare statement [%s]", mConn.ErrMsg());
} }
else else
{
// Obtain the number of available columns // Obtain the number of available columns
mColumns = sqlite3_column_count(mPtr); mColumns = sqlite3_column_count(mPtr);
}
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
@ -298,7 +450,9 @@ Int32 StmtHnd::Handle::GetColumnIndex(CSStr name)
{ {
// Validate the handle // Validate the handle
if (!mPtr) if (!mPtr)
{
STHROWF("Invalid SQLite statement"); STHROWF("Invalid SQLite statement");
}
// Are the names cached? // Are the names cached?
else if (mIndexes.empty()) else if (mIndexes.empty())
{ {
@ -308,17 +462,23 @@ Int32 StmtHnd::Handle::GetColumnIndex(CSStr name)
CSStr name = (CSStr)sqlite3_column_name(mPtr, i); CSStr name = (CSStr)sqlite3_column_name(mPtr, i);
// Validate the name // Validate the name
if (!name) if (!name)
{
STHROWF("Unable to retrieve column name for index (%d)", i); STHROWF("Unable to retrieve column name for index (%d)", i);
}
// Save it to guarantee the same lifetime as this instance // Save it to guarantee the same lifetime as this instance
else else
{
mIndexes[name] = i; mIndexes[name] = i;
}
} }
} }
// Attempt to find the specified column // Attempt to find the specified column
const Indexes::iterator itr = mIndexes.find(name); const Indexes::iterator itr = mIndexes.find(name);
// Was there a column with the specified name? // Was there a column with the specified name?
if (itr != mIndexes.end()) if (itr != mIndexes.end())
{
return itr->second; return itr->second;
}
// No such column exists (expecting the invoker to validate the result) // No such column exists (expecting the invoker to validate the result)
return -1; return -1;
} }
@ -340,7 +500,7 @@ Transaction::Transaction(const ConnHnd & db)
STHROWF("Invalid connection handle"); STHROWF("Invalid connection handle");
} }
// Attempt to begin transaction // 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()); STHROWF("Unable to begin transaction [%s]", m_Connection.ErrMsg());
} }
@ -355,7 +515,7 @@ Transaction::~Transaction()
return; // We're done here! return; // We're done here!
} }
// Attempt to roll back changes because this failed to commit // 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()); STHROWF("Unable to rollback transaction [%s]", m_Connection.ErrMsg());
} }
@ -375,7 +535,7 @@ bool Transaction::Commit()
STHROWF("Transaction was already committed"); STHROWF("Transaction was already committed");
} }
// Attempt to commit the change during this transaction // 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()); STHROWF("Unable to commit transaction [%s]", m_Connection.ErrMsg());
} }
@ -432,7 +592,9 @@ CSStr EscapeString(CSStr str)
{ {
// Is there even a string to escape? // Is there even a string to escape?
if (!str) if (!str)
{
return _SC(""); // Default to empty string return _SC(""); // Default to empty string
}
// Attempt to escape the specified string // Attempt to escape the specified string
sqlite3_snprintf(sizeof(g_Buffer), g_Buffer, "%q", str); sqlite3_snprintf(sizeof(g_Buffer), g_Buffer, "%q", str);
// Return the resulted string // Return the resulted string
@ -445,15 +607,15 @@ CCStr EscapeStringEx(SQChar spec, CCStr str)
// Utility that allows changing the format specifier temporarily // Utility that allows changing the format specifier temporarily
static SQChar fs[] = _SC("%q"); static SQChar fs[] = _SC("%q");
// Validate the specified format specifier // 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); STHROWF("Unknown format specifier: '%c'", spec);
// Default to empty string
return _SC("");
} }
// Is there even a string to escape? // Is there even a string to escape?
else if (!str) else if (!str)
{
return _SC(""); // Default to empty string return _SC(""); // Default to empty string
}
// Apply the format specifier // Apply the format specifier
fs[1] = spec; fs[1] = spec;
// Attempt to escape the specified string // Attempt to escape the specified string
@ -469,7 +631,9 @@ CCStr ArrayToQueryColumns(Array & arr)
{ {
// Do we even have any elements to process? // Do we even have any elements to process?
if (arr.Length() <= 0) if (arr.Length() <= 0)
{
return _SC(""); // Default to empty string return _SC(""); // Default to empty string
}
// Allocate a vector with the required amount of column names // Allocate a vector with the required amount of column names
std::vector< String > values(arr.Length()); std::vector< String > values(arr.Length());
// Attempt to extract the array elements as strings // Attempt to extract the array elements as strings
@ -483,7 +647,9 @@ CCStr ArrayToQueryColumns(Array & arr)
{ {
// Is the name valid? // Is the name valid?
if (itr->empty()) if (itr->empty())
{
STHROWF("Invalid column name"); STHROWF("Invalid column name");
}
// Attempt to append the column name to the buffer // Attempt to append the column name to the buffer
sqlite3_snprintf(sizeof(g_Buffer) - offset, g_Buffer + offset, "[%q], ", itr->c_str()); sqlite3_snprintf(sizeof(g_Buffer) - offset, g_Buffer + offset, "[%q], ", itr->c_str());
// Add the column name size to the offset // Add the column name size to the offset
@ -493,9 +659,13 @@ CCStr ArrayToQueryColumns(Array & arr)
} }
// Trim the last coma and space // Trim the last coma and space
if (offset >= 2) if (offset >= 2)
g_Buffer[offset-2] = 0; {
g_Buffer[offset-2] = '\0';
}
else else
g_Buffer[0] = 0; {
g_Buffer[0] = '\0';
}
// Return the resulted string // Return the resulted string
return g_Buffer; return g_Buffer;
} }
@ -516,7 +686,9 @@ CCStr TableToQueryColumns(Table & tbl)
name.assign(itr.getName()); name.assign(itr.getName());
// Is the name valid? // Is the name valid?
if (name.empty()) if (name.empty())
{
STHROWF("Invalid or empty column name"); STHROWF("Invalid or empty column name");
}
// Attempt to append the column name to the buffer // Attempt to append the column name to the buffer
sqlite3_snprintf(sizeof(g_Buffer) - offset, g_Buffer + offset, "[%q], ", name.c_str()); sqlite3_snprintf(sizeof(g_Buffer) - offset, g_Buffer + offset, "[%q], ", name.c_str());
// Add the column name size to the offset // Add the column name size to the offset
@ -526,9 +698,13 @@ CCStr TableToQueryColumns(Table & tbl)
} }
// Trim the last coma and space // Trim the last coma and space
if (offset >= 2) if (offset >= 2)
g_Buffer[offset-2] = 0; {
g_Buffer[offset-2] = '\0';
}
else else
g_Buffer[0] = 0; {
g_Buffer[0] = '\0';
}
// Return the resulted string // Return the resulted string
return g_Buffer; return g_Buffer;
} }

View File

@ -13,6 +13,7 @@
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
#include <sqlite3.h> #include <sqlite3.h>
#include <squirrel.h>
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
namespace SqMod { namespace SqMod {
@ -73,6 +74,11 @@ bool IsQueryEmpty(CSStr str);
*/ */
struct StackGuard struct StackGuard
{ {
/* --------------------------------------------------------------------------------------------
* Default constructor.
*/
StackGuard();
/* -------------------------------------------------------------------------------------------- /* --------------------------------------------------------------------------------------------
* Base constructor. * Base constructor.
*/ */
@ -108,8 +114,51 @@ private:
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. typedef unsigned int Counter; // Reference counter type.
/* --------------------------------------------------------------------------------------------
* Validate the connection handle and throw an error if invalid.
*/
void Validate() const;
protected: protected:
// -------------------------------------------------------------------------------------------- // --------------------------------------------------------------------------------------------
@ -171,7 +225,7 @@ protected:
* Base constructor. * Base constructor.
*/ */
Handle(Counter counter) Handle(Counter counter)
: mPtr(NULL) : mPtr(nullptr)
, mRef(counter) , mRef(counter)
, mStatus(SQLITE_OK) , mStatus(SQLITE_OK)
, mQueue() , mQueue()
@ -232,7 +286,7 @@ private:
* Base constructor. * Base constructor.
*/ */
ConnHnd(CSStr name) 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). * Default constructor (null).
*/ */
ConnHnd() ConnHnd()
: m_Hnd(NULL) : m_Hnd(nullptr)
{ {
/* ... */ /* ... */
} }
@ -263,7 +317,7 @@ public:
ConnHnd(ConnHnd && o) ConnHnd(ConnHnd && o)
: m_Hnd(o.m_Hnd) : m_Hnd(o.m_Hnd)
{ {
o.m_Hnd = NULL; o.m_Hnd = nullptr;
} }
/* -------------------------------------------------------------------------------------------- /* --------------------------------------------------------------------------------------------
@ -296,7 +350,7 @@ public:
if (m_Hnd != o.m_Hnd) if (m_Hnd != o.m_Hnd)
{ {
m_Hnd = o.m_Hnd; m_Hnd = o.m_Hnd;
o.m_Hnd = NULL; o.m_Hnd = nullptr;
} }
return *this; return *this;
@ -367,7 +421,7 @@ public:
*/ */
operator Pointer () operator Pointer ()
{ {
return m_Hnd ? m_Hnd->mPtr : NULL; return m_Hnd ? m_Hnd->mPtr : nullptr;
} }
/* -------------------------------------------------------------------------------------------- /* --------------------------------------------------------------------------------------------
@ -375,7 +429,7 @@ public:
*/ */
operator Pointer () const 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. typedef unsigned int Counter; // Reference counter type.
/* --------------------------------------------------------------------------------------------
* Validate the statement handle and throw an error if invalid.
*/
void Validate() const;
protected: protected:
// -------------------------------------------------------------------------------------------- // --------------------------------------------------------------------------------------------
@ -559,7 +618,7 @@ protected:
* Base constructor. * Base constructor.
*/ */
Handle(const ConnHnd & conn, Counter counter) Handle(const ConnHnd & conn, Counter counter)
: mPtr(NULL) : mPtr(nullptr)
, mRef(counter) , mRef(counter)
, mStatus(SQLITE_OK) , mStatus(SQLITE_OK)
, mConn(conn) , mConn(conn)
@ -638,7 +697,7 @@ public:
* Default constructor (null). * Default constructor (null).
*/ */
StmtHnd() StmtHnd()
: m_Hnd(NULL) : m_Hnd(nullptr)
{ {
/* ... */ /* ... */
} }
@ -659,7 +718,7 @@ public:
StmtHnd(StmtHnd && o) StmtHnd(StmtHnd && o)
: m_Hnd(o.m_Hnd) : m_Hnd(o.m_Hnd)
{ {
o.m_Hnd = NULL; o.m_Hnd = nullptr;
} }
/* -------------------------------------------------------------------------------------------- /* --------------------------------------------------------------------------------------------
@ -692,7 +751,7 @@ public:
if (m_Hnd != o.m_Hnd) if (m_Hnd != o.m_Hnd)
{ {
m_Hnd = o.m_Hnd; m_Hnd = o.m_Hnd;
o.m_Hnd = NULL; o.m_Hnd = nullptr;
} }
return *this; return *this;
@ -763,7 +822,7 @@ public:
*/ */
operator Pointer () operator Pointer ()
{ {
return m_Hnd ? m_Hnd->mPtr : NULL; return m_Hnd ? m_Hnd->mPtr : nullptr;
} }
/* -------------------------------------------------------------------------------------------- /* --------------------------------------------------------------------------------------------
@ -771,7 +830,7 @@ public:
*/ */
operator Pointer () const 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; return 1;
} }
// ------------------------------------------------------------------------------------------------
void Connection::Validate() const
{
// Is the handle valid?
if (!m_Handle)
STHROWF("Invalid SQLite connection reference");
}
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
Connection::Connection() Connection::Connection()
: m_Handle() : m_Handle()
@ -37,7 +29,9 @@ Connection::Connection(CSStr name)
: m_Handle(name) : m_Handle(name)
{ {
if (m_Handle.m_Hnd) 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) : m_Handle(name)
{ {
if (m_Handle.m_Hnd) 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) : m_Handle(name)
{ {
if (m_Handle.m_Hnd) if (m_Handle.m_Hnd)
{
m_Handle->Create(name, flags, vfs); m_Handle->Create(name, flags, vfs);
}
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
Int32 Connection::Exec(CSStr str) Int32 Connection::Exec(CSStr str)
{ {
// Validate the handle // Validate the handle
Validate(); m_Handle.Validate();
// Attempt to execute the specified query // 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()); STHROWF("Unable to execute query [%s]", m_Handle.ErrMsg());
}
// Return rows affected by this query // Return rows affected by this query
return sqlite3_changes(m_Handle); return sqlite3_changes(m_Handle);
} }
@ -72,7 +72,7 @@ Int32 Connection::Exec(CSStr str)
Object Connection::Query(CSStr str) const Object Connection::Query(CSStr str) const
{ {
// Validate the handle // Validate the handle
Validate(); m_Handle.Validate();
// Return the requested information // Return the requested information
return Object(new Statement(m_Handle, str)); return Object(new Statement(m_Handle, str));
} }
@ -81,10 +81,12 @@ Object Connection::Query(CSStr str) const
void Connection::Queue(CSStr str) void Connection::Queue(CSStr str)
{ {
// Validate the handle // Validate the handle
Validate(); m_Handle.Validate();
// Is there a query to commit? // Is there a query to commit?
if (IsQueryEmpty(str)) if (IsQueryEmpty(str))
{
STHROWF("No query string to queue"); STHROWF("No query string to queue");
}
// Add the specified string to the queue // Add the specified string to the queue
m_Handle->mQueue.push_back(str); m_Handle->mQueue.push_back(str);
} }
@ -93,12 +95,14 @@ void Connection::Queue(CSStr str)
bool Connection::IsReadOnly() const bool Connection::IsReadOnly() const
{ {
// Validate the handle // Validate the handle
Validate(); m_Handle.Validate();
// Request the desired information // Request the desired information
const int result = sqlite3_db_readonly(m_Handle, "main"); const int result = sqlite3_db_readonly(m_Handle, "main");
// Verify the result // Verify the result
if (result == -1) if (result == -1)
{
STHROWF("'main' is not the name of a database on connection"); STHROWF("'main' is not the name of a database on connection");
}
// Return the requested information // Return the requested information
return (result != 1); return (result != 1);
} }
@ -107,7 +111,7 @@ bool Connection::IsReadOnly() const
bool Connection::TableExists(CCStr name) const bool Connection::TableExists(CCStr name) const
{ {
// Validate the handle // Validate the handle
Validate(); m_Handle.Validate();
// Prepare a statement to inspect the master table // Prepare a statement to inspect the master table
Statement stmt(m_Handle, "SELECT count(*) FROM [sqlite_master] WHERE [type]='table' AND [name]=?"); Statement stmt(m_Handle, "SELECT count(*) FROM [sqlite_master] WHERE [type]='table' AND [name]=?");
// Could the statement be created? // Could the statement be created?
@ -117,7 +121,9 @@ bool Connection::TableExists(CCStr name) const
stmt.IndexBindS(1, name); stmt.IndexBindS(1, name);
// Attempt to step the statement and obtain a value // Attempt to step the statement and obtain a value
if (stmt.Step()) if (stmt.Step())
{
return (sqlite3_column_int(stmt, 0) == 1); return (sqlite3_column_int(stmt, 0) == 1);
}
} }
// Assume it doesn't exist // Assume it doesn't exist
return false; return false;
@ -127,7 +133,7 @@ bool Connection::TableExists(CCStr name) const
Object Connection::GetLastInsertRowID() const Object Connection::GetLastInsertRowID() const
{ {
// Validate the handle // Validate the handle
Validate(); m_Handle.Validate();
// Obtain the initial stack size // Obtain the initial stack size
const StackGuard sg(_SqVM); const StackGuard sg(_SqVM);
// Push a long integer instance with the requested value on the stack // 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) void Connection::SetBusyTimeout(Int32 millis)
{ {
// Validate the handle // Validate the handle
Validate(); m_Handle.Validate();
// Apply requested timeout // Apply requested timeout
if ((m_Handle = sqlite3_busy_timeout(m_Handle, millis)) != SQLITE_OK) if ((m_Handle = sqlite3_busy_timeout(m_Handle, millis)) != SQLITE_OK)
{
STHROWF("Unable to set busy timeout [%s]", m_Handle.ErrMsg()); STHROWF("Unable to set busy timeout [%s]", m_Handle.ErrMsg());
}
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
Int32 Connection::GetInfo(Int32 operation, bool highwater, bool reset) Int32 Connection::GetInfo(Int32 operation, bool highwater, bool reset)
{ {
// Don't even bother to continue if there's no valid connection handle // Don't even bother to continue if there's no valid connection handle
Validate(); m_Handle.Validate();
// Where to retrieve the information // Where to retrieve the information
Int32 cur_value; Int32 cur_value;
Int32 hiwtr_value; Int32 hiwtr_value;
// Attempt to retrieve the specified information // Attempt to retrieve the specified information
if ((m_Handle = sqlite3_db_status(m_Handle, operation, &cur_value, &hiwtr_value, reset)) != SQLITE_OK) 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()); STHROWF("Unable to get runtime status information", m_Handle.ErrMsg());
}
// Return the high-water value if requested // Return the high-water value if requested
else if (highwater) else if (highwater)
{
return hiwtr_value; return hiwtr_value;
}
// Return the requested information // Return the requested information
return cur_value; return cur_value;
} }
@ -168,7 +180,7 @@ Int32 Connection::GetInfo(Int32 operation, bool highwater, bool reset)
void Connection::ReserveQueue(Uint32 num) void Connection::ReserveQueue(Uint32 num)
{ {
// Validate the handle // Validate the handle
Validate(); m_Handle.Validate();
// Perform the requested operation // Perform the requested operation
m_Handle->mQueue.reserve(m_Handle->mQueue.size() + num); m_Handle->mQueue.reserve(m_Handle->mQueue.size() + num);
} }
@ -177,7 +189,7 @@ void Connection::ReserveQueue(Uint32 num)
Int32 Connection::Flush(Uint32 num) Int32 Connection::Flush(Uint32 num)
{ {
// Validate the handle // Validate the handle
Validate(); m_Handle.Validate();
// We need to supply a null callback // We need to supply a null callback
Object env; Object env;
Function func; Function func;
@ -189,7 +201,7 @@ Int32 Connection::Flush(Uint32 num)
Int32 Connection::Flush(Uint32 num, Object & env, Function & func) Int32 Connection::Flush(Uint32 num, Object & env, Function & func)
{ {
// Validate the handle // Validate the handle
Validate(); m_Handle.Validate();
// Attempt to flush the requested amount of queries // Attempt to flush the requested amount of queries
return m_Handle->Flush(num, env, func); return m_Handle->Flush(num, env, func);
} }
@ -232,56 +244,21 @@ SQInteger Connection::ExecF(HSQUIRRELVM vm)
return sq_throwerror(vm, "Invalid SQLite connection instance"); return sq_throwerror(vm, "Invalid SQLite connection instance");
} }
// Do we have a valid connection identifier? // 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"); return sq_throwerror(vm, "Invalid SQLite connection reference");
} }
// Do we have enough values to call the format function? // Attempt to retrieve the value from the stack as a string
else if (top > 2) StackStrF val(vm, 2);
// Have we failed to retrieve the string?
if (SQ_FAILED(val.mRes))
{ {
SStr sql = NULL; return val.mRes; // Propagate the error!
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 execute the specified query
else if ((conn->m_Handle = sqlite3_exec(conn->m_Handle, val.mPtr, nullptr, nullptr, nullptr)) != SQLITE_OK)
{ {
// Attempt to retrieve the value from the stack as a string return sq_throwerror(vm, FmtStr("Unable to execute query [%s]", conn->m_Handle.ErrMsg()));
Var< CSStr > sql(vm, 2);
// See if the obtained value is a valid query string
if (!sql.value)
{
return sq_throwerror(vm, "Unable to retrieve the query");
}
// Attempt to execute the specified query
else if ((conn->m_Handle = sqlite3_exec(conn->m_Handle, sql.value, 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());
}
} }
// Push the number of changes onto the stack // Push the number of changes onto the stack
sq_pushinteger(vm, sqlite3_changes(conn->m_Handle)); 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"); return sq_throwerror(vm, "Invalid SQLite connection instance");
} }
// Do we have a valid connection identifier? // 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"); return sq_throwerror(vm, "Invalid SQLite connection reference");
} }
// Do we have enough values to call the format function? // Attempt to retrieve the value from the stack as a string
else if (top > 2) StackStrF val(vm, 2);
// Have we failed to retrieve the string?
if (SQ_FAILED(val.mRes))
{ {
SStr sql = NULL; return val.mRes; // Propagate the error!
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)
{
return sq_throwerror(vm, "Unable to retrieve the query");
}
// Attempt to queue the specified query
conn->m_Handle->mQueue.emplace_back(sql.value);
} }
// Attempt to queue the specified query
conn->m_Handle->mQueue.emplace_back(val.mPtr);
// This function does not return a value // This function does not return a value
return 0; return 0;
} }
@ -378,50 +337,25 @@ SQInteger Connection::QueryF(HSQUIRRELVM vm)
return sq_throwerror(vm, "Invalid SQLite connection instance"); return sq_throwerror(vm, "Invalid SQLite connection instance");
} }
// Do we have a valid connection identifier? // 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"); return sq_throwerror(vm, "Invalid SQLite connection reference");
} }
// Do we have enough values to call the format function? // Attempt to retrieve the value from the stack as a string
else if (top > 2) StackStrF val(vm, 2);
// Have we failed to retrieve the string?
if (SQ_FAILED(val.mRes))
{ {
SStr sql = NULL; return val.mRes; // Propagate the error!
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 create a statement with the specified query
try
{ {
// Attempt to retrieve the value from the stack as a string ClassType< Statement >::PushInstance(vm, new Statement(conn->m_Handle, val.mPtr));
Var< CSStr > sql(vm, 2); }
// See if the obtained value is a valid query string catch (const Sqrat::Exception & e)
if (!sql.value) {
{ return sq_throwerror(vm, e.Message().c_str());
return sq_throwerror(vm, "Unable to retrieve the query");
}
// Attempt to create a statement with the specified query
try
{
ClassType< Statement >::PushInstance(vm, new Statement(conn->m_Handle, sql.value));
}
catch (const Sqrat::Exception & e)
{
return sq_throwerror(vm, e.Message().c_str());
}
} }
// This function returned a value // This function returned a value
return 1; return 1;

View File

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

View File

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

View File

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

View File

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