mirror of
https://github.com/VCMP-SqMod/SqMod.git
synced 2024-11-08 08:47:17 +01:00
Fixed excpetion throwing in SQLite document to that generated corrupted messages because snprintf was used instead of vsnprintf.
Revised most of the SQLite plugin and cleaned code.
This commit is contained in:
parent
b6466b9181
commit
fab15840cb
@ -4,6 +4,9 @@
|
||||
#include "Statement.hpp"
|
||||
#include "Module.hpp"
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
#include <cstring>
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
#include <sqrat.h>
|
||||
|
||||
@ -23,10 +26,11 @@ void Column::Validate() const
|
||||
{
|
||||
// Are we pointing to a valid index?
|
||||
if (m_Index < 0)
|
||||
{
|
||||
STHROWF("Invalid column index");
|
||||
}
|
||||
// Do we belong to a valid statement?
|
||||
else if (!m_Stmt)
|
||||
STHROWF("Invalid SQLite statement reference");
|
||||
m_Stmt.Validate();
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
@ -34,13 +38,16 @@ void Column::ValidateRow() const
|
||||
{
|
||||
// Are we pointing to a valid index?
|
||||
if (m_Index < 0)
|
||||
{
|
||||
STHROWF("Invalid column index");
|
||||
}
|
||||
// Do we belong to a valid statement?
|
||||
else if (!m_Stmt)
|
||||
STHROWF("Invalid SQLite statement reference");
|
||||
m_Stmt.Validate();
|
||||
// Do we have any rows available?
|
||||
else if (!m_Stmt->mGood)
|
||||
if (!m_Stmt->mGood)
|
||||
{
|
||||
STHROWF("No row available");
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
@ -89,7 +96,7 @@ SQFloat Column::GetFloat() const
|
||||
// Validate the column and statement row
|
||||
ValidateRow();
|
||||
// Return the requested information
|
||||
return (SQFloat)sqlite3_column_double(m_Stmt, m_Index);
|
||||
return static_cast< SQFloat >(sqlite3_column_double(m_Stmt, m_Index));
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
@ -113,7 +120,7 @@ Object Column::GetString() const
|
||||
// Obtain the initial stack size
|
||||
const StackGuard sg(_SqVM);
|
||||
// Push the column text on the stack
|
||||
sq_pushstring(_SqVM, (CSStr)sqlite3_column_text(m_Stmt, m_Index),
|
||||
sq_pushstring(_SqVM, reinterpret_cast< CSStr >(sqlite3_column_text(m_Stmt, m_Index)),
|
||||
sqlite3_column_bytes(m_Stmt, m_Index));
|
||||
// Get the object from the stack and return it
|
||||
return Var< Object >(_SqVM, -1).value;
|
||||
@ -143,7 +150,9 @@ Object Column::GetBlob() const
|
||||
const void * b = sqlite3_column_blob(m_Stmt, m_Index);
|
||||
// Could the memory blob be allocated?
|
||||
if (!p)
|
||||
{
|
||||
STHROWF("Unable to allocate space for column blob value");
|
||||
}
|
||||
// Is there any data to read?
|
||||
else if (!b)
|
||||
{
|
||||
@ -154,7 +163,9 @@ Object Column::GetBlob() const
|
||||
}
|
||||
// Copy the data into the memory blob
|
||||
else
|
||||
memcpy(p, b, sz);
|
||||
{
|
||||
std::memcpy(p, b, sz);
|
||||
}
|
||||
// Get the object from the stack and return it
|
||||
return Var< Object >(_SqVM, -1).value;
|
||||
}
|
||||
@ -196,9 +207,9 @@ CSStr Column::GetOriginName() const
|
||||
return sqlite3_column_origin_name(m_Stmt, m_Index);
|
||||
#else
|
||||
STHROWF("The module was compiled without this feature");
|
||||
#endif
|
||||
// Request failed
|
||||
return _SC("");
|
||||
#endif
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
|
@ -111,12 +111,18 @@ public:
|
||||
Int32 Cmp(const Column & o) const
|
||||
{
|
||||
if (m_Stmt == o.m_Stmt)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
else if (m_Stmt.HndPtr() > o.m_Stmt.HndPtr())
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Used by the script engine to convert an instance of this type to a string.
|
||||
|
@ -4,8 +4,9 @@
|
||||
#include "Connection.hpp"
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
#include <ctype.h>
|
||||
#include <stdarg.h>
|
||||
#include <cctype>
|
||||
#include <cstring>
|
||||
#include <cstdarg>
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
#include <sqrat.h>
|
||||
@ -35,8 +36,10 @@ void SqThrowF(CSStr str, ...)
|
||||
va_list args;
|
||||
va_start (args, str);
|
||||
// Write the requested contents
|
||||
if (snprintf(g_Buffer, sizeof(g_Buffer), str, args) < 0)
|
||||
strcpy(g_Buffer, "Unknown error has occurred");
|
||||
if (std::vsnprintf(g_Buffer, sizeof(g_Buffer), str, args) < 0)
|
||||
{
|
||||
std::strcpy(g_Buffer, "Unknown error has occurred");
|
||||
}
|
||||
// Release the argument list
|
||||
va_end(args);
|
||||
// Throw the exception with the resulted message
|
||||
@ -50,8 +53,10 @@ CSStr FmtStr(CSStr str, ...)
|
||||
va_list args;
|
||||
va_start (args, str);
|
||||
// Write the requested contents
|
||||
if (snprintf(g_Buffer, sizeof(g_Buffer), str, args) < 0)
|
||||
g_Buffer[0] = 0; /* make sure the string is terminated */
|
||||
if (std::vsnprintf(g_Buffer, sizeof(g_Buffer), str, args) < 0)
|
||||
{
|
||||
g_Buffer[0] = 0; // make sure the string is terminated
|
||||
}
|
||||
// Release the argument list
|
||||
va_end(args);
|
||||
// Return the data from the buffer
|
||||
@ -77,23 +82,34 @@ bool IsQueryEmpty(CSStr str)
|
||||
{
|
||||
// Is the pointer valid?
|
||||
if (!str)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
// Currently processed character
|
||||
SQChar c = 0;
|
||||
// See if the query contains any alpha numeric characters
|
||||
while ((c = *str) != 0)
|
||||
{
|
||||
if (isalnum(c) != 0)
|
||||
if (std::isalnum(c) != 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
++str;
|
||||
}
|
||||
// At this point we consider the query empty
|
||||
return true;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
StackGuard::StackGuard()
|
||||
: m_VM(_SqVM), m_Top(sq_gettop(m_VM))
|
||||
{
|
||||
/* ... */
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
StackGuard::StackGuard(HSQUIRRELVM vm)
|
||||
: m_Top(sq_gettop(vm)), m_VM(vm)
|
||||
: m_VM(vm), m_Top(sq_gettop(vm))
|
||||
{
|
||||
/* ... */
|
||||
}
|
||||
@ -104,16 +120,130 @@ StackGuard::~StackGuard()
|
||||
sq_pop(m_VM, sq_gettop(m_VM) - m_Top);
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------------------------
|
||||
StackStrF::StackStrF(HSQUIRRELVM vm, SQInteger idx, bool fmt)
|
||||
: mPtr(nullptr)
|
||||
, mLen(-1)
|
||||
, mRes(SQ_OK)
|
||||
, mObj()
|
||||
, mVM(vm)
|
||||
{
|
||||
const Int32 top = sq_gettop(vm);
|
||||
// Reset the converted value object
|
||||
sq_resetobject(&mObj);
|
||||
// Was the string or value specified?
|
||||
if (top <= (idx - 1))
|
||||
{
|
||||
mRes = sq_throwerror(vm, "Missing string or value");
|
||||
}
|
||||
// Do we have enough values to call the format function and are we allowed to?
|
||||
else if (top > idx && fmt)
|
||||
{
|
||||
// Pointer to the generated string
|
||||
SStr str = nullptr;
|
||||
// Attempt to generate the specified string format
|
||||
mRes = sqstd_format(vm, idx, &mLen, &str);
|
||||
// Did the format succeeded but ended up with a null string pointer?
|
||||
if (SQ_SUCCEEDED(mRes) && !str)
|
||||
{
|
||||
mRes = sq_throwerror(vm, "Unable to generate the string");
|
||||
}
|
||||
else
|
||||
{
|
||||
mPtr = const_cast< CSStr >(str);
|
||||
}
|
||||
}
|
||||
// Is the value on the stack an actual string?
|
||||
else if (sq_gettype(vm, idx) == OT_STRING)
|
||||
{
|
||||
// Obtain a reference to the string object
|
||||
mRes = sq_getstackobj(vm, idx, &mObj);
|
||||
// Could we retrieve the object from the stack?
|
||||
if (SQ_SUCCEEDED(mRes))
|
||||
{
|
||||
// Keep a strong reference to the object
|
||||
sq_addref(vm, &mObj);
|
||||
// Attempt to retrieve the string value from the stack
|
||||
mRes = sq_getstring(vm, idx, &mPtr);
|
||||
}
|
||||
// Did the retrieval succeeded but ended up with a null string pointer?
|
||||
if (SQ_SUCCEEDED(mRes) && !mPtr)
|
||||
{
|
||||
mRes = sq_throwerror(vm, "Unable to retrieve the string");
|
||||
}
|
||||
}
|
||||
// We have to try and convert it to string
|
||||
else
|
||||
{
|
||||
// Attempt to convert the value from the stack to a string
|
||||
mRes = sq_tostring(vm, idx);
|
||||
// Could we convert the specified value to string?
|
||||
if (SQ_SUCCEEDED(mRes))
|
||||
{
|
||||
// Obtain a reference to the resulted object
|
||||
mRes = sq_getstackobj(vm, -1, &mObj);
|
||||
// Could we retrieve the object from the stack?
|
||||
if (SQ_SUCCEEDED(mRes))
|
||||
{
|
||||
// Keep a strong reference to the object
|
||||
sq_addref(vm, &mObj);
|
||||
// Attempt to obtain the string pointer
|
||||
mRes = sq_getstring(vm, -1, &mPtr);
|
||||
}
|
||||
}
|
||||
// Pop a value from the stack regardless of the result
|
||||
sq_pop(vm, 1);
|
||||
// Did the retrieval succeeded but ended up with a null string pointer?
|
||||
if (SQ_SUCCEEDED(mRes) && !mPtr)
|
||||
{
|
||||
mRes = sq_throwerror(vm, "Unable to retrieve the value");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
StackStrF::~StackStrF()
|
||||
{
|
||||
if (mVM && !sq_isnull(mObj))
|
||||
{
|
||||
sq_release(mVM, &mObj);
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void ConnHnd::Validate() const
|
||||
{
|
||||
// Is the handle valid?
|
||||
if ((m_Hnd == nullptr) || (m_Hnd->mPtr == nullptr))
|
||||
{
|
||||
STHROWF("Invalid SQLite connection reference");
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void StmtHnd::Validate() const
|
||||
{
|
||||
// Is the handle valid?
|
||||
if ((m_Hnd == nullptr) || (m_Hnd->mPtr == nullptr))
|
||||
{
|
||||
STHROWF("Invalid SQLite statement reference");
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
ConnHnd::Handle::~Handle()
|
||||
{
|
||||
// Is there anything to close?
|
||||
if (!mPtr)
|
||||
{
|
||||
return; // Nothing to close
|
||||
}
|
||||
// Are we dealing with a memory leak? Technically shouldn't reach this situation!
|
||||
else if (mRef != 0)
|
||||
{
|
||||
// Should we deal with undefined behavior instead? How bad is one connection left open?
|
||||
_SqMod->LogErr("SQLite connection is still referenced (%s)", mName.c_str());
|
||||
}
|
||||
else
|
||||
{
|
||||
// NOTE: Should we call sqlite3_interrupt(...) before closing?
|
||||
@ -123,8 +253,10 @@ ConnHnd::Handle::~Handle()
|
||||
Flush(mQueue.size(), env, func);
|
||||
// Attempt to close the database
|
||||
if ((sqlite3_close(mPtr)) != SQLITE_OK)
|
||||
{
|
||||
_SqMod->LogErr("Unable to close SQLite connection [%s]", sqlite3_errmsg(mPtr));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
@ -132,19 +264,25 @@ void ConnHnd::Handle::Create(CSStr name, Int32 flags, CSStr vfs)
|
||||
{
|
||||
// Make sure a previous connection doesn't exist
|
||||
if (mPtr)
|
||||
{
|
||||
STHROWF("Unable to connect to database. Database already connected");
|
||||
}
|
||||
// Make sure the name is valid
|
||||
else if (!name || strlen(name) <= 0)
|
||||
else if (!name || *name == '\0')
|
||||
{
|
||||
STHROWF("Unable to connect to database. The name is invalid");
|
||||
}
|
||||
// Attempt to create the database connection
|
||||
else if ((mStatus = sqlite3_open_v2(name, &mPtr, flags, vfs)) != SQLITE_OK)
|
||||
{
|
||||
// Grab the error message before destroying the handle
|
||||
String msg(sqlite3_errmsg(mPtr) ? sqlite3_errmsg(mPtr) : _SC("Unknown reason"));
|
||||
// Must be destroyed regardless of result
|
||||
sqlite3_close(mPtr);
|
||||
// Explicitly make sure it's null
|
||||
mPtr = NULL;
|
||||
mPtr = nullptr;
|
||||
// Now its safe to throw the error
|
||||
STHROWF("Unable to connect to database [%s]", sqlite3_errstr(mStatus));
|
||||
STHROWF("Unable to connect to database [%s]", msg.c_str());
|
||||
}
|
||||
// Let's save the specified information
|
||||
mName.assign(name);
|
||||
@ -178,7 +316,7 @@ Int32 ConnHnd::Handle::Flush(Uint32 num, Object & env, Function & func)
|
||||
QueryList::iterator itr = mQueue.begin();
|
||||
QueryList::iterator end = mQueue.begin() + num;
|
||||
// Attempt to begin the flush transaction
|
||||
if ((mStatus = sqlite3_exec(mPtr, "BEGIN", NULL, NULL, NULL)) != SQLITE_OK)
|
||||
if ((mStatus = sqlite3_exec(mPtr, "BEGIN", nullptr, nullptr, nullptr)) != SQLITE_OK)
|
||||
{
|
||||
STHROWF("Unable to begin flush transaction [%s]", sqlite3_errmsg(mPtr));
|
||||
}
|
||||
@ -193,7 +331,7 @@ Int32 ConnHnd::Handle::Flush(Uint32 num, Object & env, Function & func)
|
||||
}
|
||||
*/
|
||||
// Attempt to execute the currently processed query string
|
||||
if ((mStatus = sqlite3_exec(mPtr, itr->c_str(), NULL, NULL, NULL)) == SQLITE_OK)
|
||||
if ((mStatus = sqlite3_exec(mPtr, itr->c_str(), nullptr, nullptr, nullptr)) == SQLITE_OK)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
@ -227,12 +365,12 @@ Int32 ConnHnd::Handle::Flush(Uint32 num, Object & env, Function & func)
|
||||
// Erase all queries till end or till the point of failure (if any occurred)
|
||||
mQueue.erase(mQueue.begin(), itr);
|
||||
// Attempt to commit changes requested during transaction
|
||||
if ((mStatus = sqlite3_exec(mPtr, "COMMIT", NULL, NULL, NULL)) == SQLITE_OK)
|
||||
if ((mStatus = sqlite3_exec(mPtr, "COMMIT", nullptr, nullptr, nullptr)) == SQLITE_OK)
|
||||
{
|
||||
return sqlite3_changes(mPtr);
|
||||
}
|
||||
// Attempt to roll back erroneous changes
|
||||
else if ((mStatus = sqlite3_exec(mPtr, "ROLLBACK", NULL, NULL, NULL)) != SQLITE_OK)
|
||||
else if ((mStatus = sqlite3_exec(mPtr, "ROLLBACK", nullptr, nullptr, nullptr)) != SQLITE_OK)
|
||||
{
|
||||
STHROWF("Unable to rollback flush transaction [%s]", sqlite3_errmsg(mPtr));
|
||||
}
|
||||
@ -250,17 +388,23 @@ StmtHnd::Handle::~Handle()
|
||||
{
|
||||
// Is there anything to finalize?
|
||||
if (!mPtr)
|
||||
{
|
||||
return; // Nothing to finalize
|
||||
}
|
||||
// Are we dealing with a memory leak? Technically shouldn't reach this situation!
|
||||
else if (mRef != 0)
|
||||
{
|
||||
// Should we deal with undefined behavior instead? How bad is one statement left alive?
|
||||
_SqMod->LogErr("SQLite statement is still referenced (%s)", mQuery.c_str());
|
||||
}
|
||||
else
|
||||
{
|
||||
// Attempt to finalize the statement
|
||||
if ((sqlite3_finalize(mPtr)) != SQLITE_OK)
|
||||
{
|
||||
_SqMod->LogErr("Unable to finalize SQLite statement [%s]", mConn.ErrMsg());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
@ -268,29 +412,37 @@ void StmtHnd::Handle::Create(CSStr query)
|
||||
{
|
||||
// Make sure a previous statement doesn't exist
|
||||
if (mPtr)
|
||||
{
|
||||
STHROWF("Unable to prepare statement. Statement already prepared");
|
||||
}
|
||||
// Is the specified database connection is valid?
|
||||
else if (!mConn)
|
||||
{
|
||||
STHROWF("Unable to prepare statement. Invalid connection handle");
|
||||
}
|
||||
// Save the query string and therefore multiple strlen(...) calls
|
||||
mQuery.assign(query ? query : _SC(""));
|
||||
// Is the specified query string we just saved, valid?
|
||||
if (mQuery.empty())
|
||||
{
|
||||
STHROWF("Unable to prepare statement. Invalid query string");
|
||||
}
|
||||
// Attempt to prepare a statement with the specified query string
|
||||
else if ((mStatus = sqlite3_prepare_v2(mConn, mQuery.c_str(), (Int32)mQuery.size(),
|
||||
&mPtr, NULL)) != SQLITE_OK)
|
||||
&mPtr, nullptr)) != SQLITE_OK)
|
||||
{
|
||||
// Clear the query string since it failed
|
||||
mQuery.clear();
|
||||
// Explicitly make sure the handle is null
|
||||
mPtr = NULL;
|
||||
mPtr = nullptr;
|
||||
// Now it's safe to throw the error
|
||||
STHROWF("Unable to prepare statement [%s]", mConn.ErrMsg());
|
||||
}
|
||||
else
|
||||
{
|
||||
// Obtain the number of available columns
|
||||
mColumns = sqlite3_column_count(mPtr);
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
@ -298,7 +450,9 @@ Int32 StmtHnd::Handle::GetColumnIndex(CSStr name)
|
||||
{
|
||||
// Validate the handle
|
||||
if (!mPtr)
|
||||
{
|
||||
STHROWF("Invalid SQLite statement");
|
||||
}
|
||||
// Are the names cached?
|
||||
else if (mIndexes.empty())
|
||||
{
|
||||
@ -308,17 +462,23 @@ Int32 StmtHnd::Handle::GetColumnIndex(CSStr name)
|
||||
CSStr name = (CSStr)sqlite3_column_name(mPtr, i);
|
||||
// Validate the name
|
||||
if (!name)
|
||||
{
|
||||
STHROWF("Unable to retrieve column name for index (%d)", i);
|
||||
}
|
||||
// Save it to guarantee the same lifetime as this instance
|
||||
else
|
||||
{
|
||||
mIndexes[name] = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Attempt to find the specified column
|
||||
const Indexes::iterator itr = mIndexes.find(name);
|
||||
// Was there a column with the specified name?
|
||||
if (itr != mIndexes.end())
|
||||
{
|
||||
return itr->second;
|
||||
}
|
||||
// No such column exists (expecting the invoker to validate the result)
|
||||
return -1;
|
||||
}
|
||||
@ -340,7 +500,7 @@ Transaction::Transaction(const ConnHnd & db)
|
||||
STHROWF("Invalid connection handle");
|
||||
}
|
||||
// Attempt to begin transaction
|
||||
else if ((m_Connection = sqlite3_exec(m_Connection, "BEGIN", NULL, NULL, NULL)) != SQLITE_OK)
|
||||
else if ((m_Connection = sqlite3_exec(m_Connection, "BEGIN", nullptr, nullptr, nullptr)) != SQLITE_OK)
|
||||
{
|
||||
STHROWF("Unable to begin transaction [%s]", m_Connection.ErrMsg());
|
||||
}
|
||||
@ -355,7 +515,7 @@ Transaction::~Transaction()
|
||||
return; // We're done here!
|
||||
}
|
||||
// Attempt to roll back changes because this failed to commit
|
||||
if ((m_Connection = sqlite3_exec(m_Connection, "ROLLBACK", NULL, NULL, NULL)) != SQLITE_OK)
|
||||
if ((m_Connection = sqlite3_exec(m_Connection, "ROLLBACK", nullptr, nullptr, nullptr)) != SQLITE_OK)
|
||||
{
|
||||
STHROWF("Unable to rollback transaction [%s]", m_Connection.ErrMsg());
|
||||
}
|
||||
@ -375,7 +535,7 @@ bool Transaction::Commit()
|
||||
STHROWF("Transaction was already committed");
|
||||
}
|
||||
// Attempt to commit the change during this transaction
|
||||
else if ((m_Connection = sqlite3_exec(m_Connection, "COMMIT", NULL, NULL, NULL)) != SQLITE_OK)
|
||||
else if ((m_Connection = sqlite3_exec(m_Connection, "COMMIT", nullptr, nullptr, nullptr)) != SQLITE_OK)
|
||||
{
|
||||
STHROWF("Unable to commit transaction [%s]", m_Connection.ErrMsg());
|
||||
}
|
||||
@ -432,7 +592,9 @@ CSStr EscapeString(CSStr str)
|
||||
{
|
||||
// Is there even a string to escape?
|
||||
if (!str)
|
||||
{
|
||||
return _SC(""); // Default to empty string
|
||||
}
|
||||
// Attempt to escape the specified string
|
||||
sqlite3_snprintf(sizeof(g_Buffer), g_Buffer, "%q", str);
|
||||
// Return the resulted string
|
||||
@ -445,15 +607,15 @@ CCStr EscapeStringEx(SQChar spec, CCStr str)
|
||||
// Utility that allows changing the format specifier temporarily
|
||||
static SQChar fs[] = _SC("%q");
|
||||
// Validate the specified format specifier
|
||||
if (spec != 'q' && spec != 'Q' && spec != 'w' && spec != 's')
|
||||
if ((spec != 'q') && (spec != 'Q') && (spec != 'w') && (spec != 's'))
|
||||
{
|
||||
STHROWF("Unknown format specifier: %c", spec);
|
||||
// Default to empty string
|
||||
return _SC("");
|
||||
STHROWF("Unknown format specifier: '%c'", spec);
|
||||
}
|
||||
// Is there even a string to escape?
|
||||
else if (!str)
|
||||
{
|
||||
return _SC(""); // Default to empty string
|
||||
}
|
||||
// Apply the format specifier
|
||||
fs[1] = spec;
|
||||
// Attempt to escape the specified string
|
||||
@ -469,7 +631,9 @@ CCStr ArrayToQueryColumns(Array & arr)
|
||||
{
|
||||
// Do we even have any elements to process?
|
||||
if (arr.Length() <= 0)
|
||||
{
|
||||
return _SC(""); // Default to empty string
|
||||
}
|
||||
// Allocate a vector with the required amount of column names
|
||||
std::vector< String > values(arr.Length());
|
||||
// Attempt to extract the array elements as strings
|
||||
@ -483,7 +647,9 @@ CCStr ArrayToQueryColumns(Array & arr)
|
||||
{
|
||||
// Is the name valid?
|
||||
if (itr->empty())
|
||||
{
|
||||
STHROWF("Invalid column name");
|
||||
}
|
||||
// Attempt to append the column name to the buffer
|
||||
sqlite3_snprintf(sizeof(g_Buffer) - offset, g_Buffer + offset, "[%q], ", itr->c_str());
|
||||
// Add the column name size to the offset
|
||||
@ -493,9 +659,13 @@ CCStr ArrayToQueryColumns(Array & arr)
|
||||
}
|
||||
// Trim the last coma and space
|
||||
if (offset >= 2)
|
||||
g_Buffer[offset-2] = 0;
|
||||
{
|
||||
g_Buffer[offset-2] = '\0';
|
||||
}
|
||||
else
|
||||
g_Buffer[0] = 0;
|
||||
{
|
||||
g_Buffer[0] = '\0';
|
||||
}
|
||||
// Return the resulted string
|
||||
return g_Buffer;
|
||||
}
|
||||
@ -516,7 +686,9 @@ CCStr TableToQueryColumns(Table & tbl)
|
||||
name.assign(itr.getName());
|
||||
// Is the name valid?
|
||||
if (name.empty())
|
||||
{
|
||||
STHROWF("Invalid or empty column name");
|
||||
}
|
||||
// Attempt to append the column name to the buffer
|
||||
sqlite3_snprintf(sizeof(g_Buffer) - offset, g_Buffer + offset, "[%q], ", name.c_str());
|
||||
// Add the column name size to the offset
|
||||
@ -526,9 +698,13 @@ CCStr TableToQueryColumns(Table & tbl)
|
||||
}
|
||||
// Trim the last coma and space
|
||||
if (offset >= 2)
|
||||
g_Buffer[offset-2] = 0;
|
||||
{
|
||||
g_Buffer[offset-2] = '\0';
|
||||
}
|
||||
else
|
||||
g_Buffer[0] = 0;
|
||||
{
|
||||
g_Buffer[0] = '\0';
|
||||
}
|
||||
// Return the resulted string
|
||||
return g_Buffer;
|
||||
}
|
||||
|
@ -13,6 +13,7 @@
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
#include <sqlite3.h>
|
||||
#include <squirrel.h>
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
namespace SqMod {
|
||||
@ -73,6 +74,11 @@ bool IsQueryEmpty(CSStr str);
|
||||
*/
|
||||
struct StackGuard
|
||||
{
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Default constructor.
|
||||
*/
|
||||
StackGuard();
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Base constructor.
|
||||
*/
|
||||
@ -108,8 +114,51 @@ private:
|
||||
private:
|
||||
|
||||
// --------------------------------------------------------------------------------------------
|
||||
Int32 m_Top; /* The top of the stack when this instance was created. */
|
||||
HSQUIRRELVM m_VM; /* The VM where the stack should be restored. */
|
||||
HSQUIRRELVM m_VM; // The VM where the stack should be restored.
|
||||
Int32 m_Top; // The top of the stack when this instance was created.
|
||||
};
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
* Helper structure for retrieving a value from the stack as a string or a formatted string.
|
||||
*/
|
||||
struct StackStrF
|
||||
{
|
||||
// --------------------------------------------------------------------------------------------
|
||||
CSStr mPtr; // Pointer to the C string that was retrieved.
|
||||
SQInteger mLen; // The string length if it could be retrieved.
|
||||
SQRESULT mRes; // The result of the retrieval attempts.
|
||||
HSQOBJECT mObj; // Strong reference to the string object.
|
||||
HSQUIRRELVM mVM; // The associated virtual machine.
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Base constructor.
|
||||
*/
|
||||
StackStrF(HSQUIRRELVM vm, SQInteger idx, bool fmt = true);
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Copy constructor. (disabled)
|
||||
*/
|
||||
StackStrF(const StackStrF & o) = delete;
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Copy constructor. (disabled)
|
||||
*/
|
||||
StackStrF(StackStrF && o) = delete;
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Destructor.
|
||||
*/
|
||||
~StackStrF();
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Copy constructor. (disabled)
|
||||
*/
|
||||
StackStrF & operator = (const StackStrF & o) = delete;
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Copy constructor. (disabled)
|
||||
*/
|
||||
StackStrF & operator = (StackStrF && o) = delete;
|
||||
};
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
@ -137,6 +186,11 @@ public:
|
||||
// --------------------------------------------------------------------------------------------
|
||||
typedef unsigned int Counter; // Reference counter type.
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Validate the connection handle and throw an error if invalid.
|
||||
*/
|
||||
void Validate() const;
|
||||
|
||||
protected:
|
||||
|
||||
// --------------------------------------------------------------------------------------------
|
||||
@ -171,7 +225,7 @@ protected:
|
||||
* Base constructor.
|
||||
*/
|
||||
Handle(Counter counter)
|
||||
: mPtr(NULL)
|
||||
: mPtr(nullptr)
|
||||
, mRef(counter)
|
||||
, mStatus(SQLITE_OK)
|
||||
, mQueue()
|
||||
@ -232,7 +286,7 @@ private:
|
||||
* Base constructor.
|
||||
*/
|
||||
ConnHnd(CSStr name)
|
||||
: m_Hnd(name ? new Handle(1) : NULL)
|
||||
: m_Hnd(name ? new Handle(1) : nullptr)
|
||||
{
|
||||
/* ... */
|
||||
}
|
||||
@ -243,7 +297,7 @@ public:
|
||||
* Default constructor (null).
|
||||
*/
|
||||
ConnHnd()
|
||||
: m_Hnd(NULL)
|
||||
: m_Hnd(nullptr)
|
||||
{
|
||||
/* ... */
|
||||
}
|
||||
@ -263,7 +317,7 @@ public:
|
||||
ConnHnd(ConnHnd && o)
|
||||
: m_Hnd(o.m_Hnd)
|
||||
{
|
||||
o.m_Hnd = NULL;
|
||||
o.m_Hnd = nullptr;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
@ -296,7 +350,7 @@ public:
|
||||
if (m_Hnd != o.m_Hnd)
|
||||
{
|
||||
m_Hnd = o.m_Hnd;
|
||||
o.m_Hnd = NULL;
|
||||
o.m_Hnd = nullptr;
|
||||
}
|
||||
|
||||
return *this;
|
||||
@ -367,7 +421,7 @@ public:
|
||||
*/
|
||||
operator Pointer ()
|
||||
{
|
||||
return m_Hnd ? m_Hnd->mPtr : NULL;
|
||||
return m_Hnd ? m_Hnd->mPtr : nullptr;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
@ -375,7 +429,7 @@ public:
|
||||
*/
|
||||
operator Pointer () const
|
||||
{
|
||||
return m_Hnd ? m_Hnd->mPtr : NULL;
|
||||
return m_Hnd ? m_Hnd->mPtr : nullptr;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
@ -524,6 +578,11 @@ public:
|
||||
// --------------------------------------------------------------------------------------------
|
||||
typedef unsigned int Counter; // Reference counter type.
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Validate the statement handle and throw an error if invalid.
|
||||
*/
|
||||
void Validate() const;
|
||||
|
||||
protected:
|
||||
|
||||
// --------------------------------------------------------------------------------------------
|
||||
@ -559,7 +618,7 @@ protected:
|
||||
* Base constructor.
|
||||
*/
|
||||
Handle(const ConnHnd & conn, Counter counter)
|
||||
: mPtr(NULL)
|
||||
: mPtr(nullptr)
|
||||
, mRef(counter)
|
||||
, mStatus(SQLITE_OK)
|
||||
, mConn(conn)
|
||||
@ -638,7 +697,7 @@ public:
|
||||
* Default constructor (null).
|
||||
*/
|
||||
StmtHnd()
|
||||
: m_Hnd(NULL)
|
||||
: m_Hnd(nullptr)
|
||||
{
|
||||
/* ... */
|
||||
}
|
||||
@ -659,7 +718,7 @@ public:
|
||||
StmtHnd(StmtHnd && o)
|
||||
: m_Hnd(o.m_Hnd)
|
||||
{
|
||||
o.m_Hnd = NULL;
|
||||
o.m_Hnd = nullptr;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
@ -692,7 +751,7 @@ public:
|
||||
if (m_Hnd != o.m_Hnd)
|
||||
{
|
||||
m_Hnd = o.m_Hnd;
|
||||
o.m_Hnd = NULL;
|
||||
o.m_Hnd = nullptr;
|
||||
}
|
||||
|
||||
return *this;
|
||||
@ -763,7 +822,7 @@ public:
|
||||
*/
|
||||
operator Pointer ()
|
||||
{
|
||||
return m_Hnd ? m_Hnd->mPtr : NULL;
|
||||
return m_Hnd ? m_Hnd->mPtr : nullptr;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
@ -771,7 +830,7 @@ public:
|
||||
*/
|
||||
operator Pointer () const
|
||||
{
|
||||
return m_Hnd ? m_Hnd->mPtr : NULL;
|
||||
return m_Hnd ? m_Hnd->mPtr : nullptr;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
|
@ -17,14 +17,6 @@ SQInteger Connection::Typename(HSQUIRRELVM vm)
|
||||
return 1;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void Connection::Validate() const
|
||||
{
|
||||
// Is the handle valid?
|
||||
if (!m_Handle)
|
||||
STHROWF("Invalid SQLite connection reference");
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
Connection::Connection()
|
||||
: m_Handle()
|
||||
@ -37,7 +29,9 @@ Connection::Connection(CSStr name)
|
||||
: m_Handle(name)
|
||||
{
|
||||
if (m_Handle.m_Hnd)
|
||||
m_Handle->Create(name, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, NULL);
|
||||
{
|
||||
m_Handle->Create(name, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
@ -45,7 +39,9 @@ Connection::Connection(CSStr name, Int32 flags)
|
||||
: m_Handle(name)
|
||||
{
|
||||
if (m_Handle.m_Hnd)
|
||||
m_Handle->Create(name, flags, NULL);
|
||||
{
|
||||
m_Handle->Create(name, flags, nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
@ -53,17 +49,21 @@ Connection::Connection(CSStr name, Int32 flags, CSStr vfs)
|
||||
: m_Handle(name)
|
||||
{
|
||||
if (m_Handle.m_Hnd)
|
||||
{
|
||||
m_Handle->Create(name, flags, vfs);
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
Int32 Connection::Exec(CSStr str)
|
||||
{
|
||||
// Validate the handle
|
||||
Validate();
|
||||
m_Handle.Validate();
|
||||
// Attempt to execute the specified query
|
||||
if ((m_Handle = sqlite3_exec(m_Handle, str, NULL, NULL, NULL)) != SQLITE_OK)
|
||||
if ((m_Handle = sqlite3_exec(m_Handle, str, nullptr, nullptr, nullptr)) != SQLITE_OK)
|
||||
{
|
||||
STHROWF("Unable to execute query [%s]", m_Handle.ErrMsg());
|
||||
}
|
||||
// Return rows affected by this query
|
||||
return sqlite3_changes(m_Handle);
|
||||
}
|
||||
@ -72,7 +72,7 @@ Int32 Connection::Exec(CSStr str)
|
||||
Object Connection::Query(CSStr str) const
|
||||
{
|
||||
// Validate the handle
|
||||
Validate();
|
||||
m_Handle.Validate();
|
||||
// Return the requested information
|
||||
return Object(new Statement(m_Handle, str));
|
||||
}
|
||||
@ -81,10 +81,12 @@ Object Connection::Query(CSStr str) const
|
||||
void Connection::Queue(CSStr str)
|
||||
{
|
||||
// Validate the handle
|
||||
Validate();
|
||||
m_Handle.Validate();
|
||||
// Is there a query to commit?
|
||||
if (IsQueryEmpty(str))
|
||||
{
|
||||
STHROWF("No query string to queue");
|
||||
}
|
||||
// Add the specified string to the queue
|
||||
m_Handle->mQueue.push_back(str);
|
||||
}
|
||||
@ -93,12 +95,14 @@ void Connection::Queue(CSStr str)
|
||||
bool Connection::IsReadOnly() const
|
||||
{
|
||||
// Validate the handle
|
||||
Validate();
|
||||
m_Handle.Validate();
|
||||
// Request the desired information
|
||||
const int result = sqlite3_db_readonly(m_Handle, "main");
|
||||
// Verify the result
|
||||
if (result == -1)
|
||||
{
|
||||
STHROWF("'main' is not the name of a database on connection");
|
||||
}
|
||||
// Return the requested information
|
||||
return (result != 1);
|
||||
}
|
||||
@ -107,7 +111,7 @@ bool Connection::IsReadOnly() const
|
||||
bool Connection::TableExists(CCStr name) const
|
||||
{
|
||||
// Validate the handle
|
||||
Validate();
|
||||
m_Handle.Validate();
|
||||
// Prepare a statement to inspect the master table
|
||||
Statement stmt(m_Handle, "SELECT count(*) FROM [sqlite_master] WHERE [type]='table' AND [name]=?");
|
||||
// Could the statement be created?
|
||||
@ -117,8 +121,10 @@ bool Connection::TableExists(CCStr name) const
|
||||
stmt.IndexBindS(1, name);
|
||||
// Attempt to step the statement and obtain a value
|
||||
if (stmt.Step())
|
||||
{
|
||||
return (sqlite3_column_int(stmt, 0) == 1);
|
||||
}
|
||||
}
|
||||
// Assume it doesn't exist
|
||||
return false;
|
||||
}
|
||||
@ -127,7 +133,7 @@ bool Connection::TableExists(CCStr name) const
|
||||
Object Connection::GetLastInsertRowID() const
|
||||
{
|
||||
// Validate the handle
|
||||
Validate();
|
||||
m_Handle.Validate();
|
||||
// Obtain the initial stack size
|
||||
const StackGuard sg(_SqVM);
|
||||
// Push a long integer instance with the requested value on the stack
|
||||
@ -140,26 +146,32 @@ Object Connection::GetLastInsertRowID() const
|
||||
void Connection::SetBusyTimeout(Int32 millis)
|
||||
{
|
||||
// Validate the handle
|
||||
Validate();
|
||||
m_Handle.Validate();
|
||||
// Apply requested timeout
|
||||
if ((m_Handle = sqlite3_busy_timeout(m_Handle, millis)) != SQLITE_OK)
|
||||
{
|
||||
STHROWF("Unable to set busy timeout [%s]", m_Handle.ErrMsg());
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
Int32 Connection::GetInfo(Int32 operation, bool highwater, bool reset)
|
||||
{
|
||||
// Don't even bother to continue if there's no valid connection handle
|
||||
Validate();
|
||||
m_Handle.Validate();
|
||||
// Where to retrieve the information
|
||||
Int32 cur_value;
|
||||
Int32 hiwtr_value;
|
||||
// Attempt to retrieve the specified information
|
||||
if ((m_Handle = sqlite3_db_status(m_Handle, operation, &cur_value, &hiwtr_value, reset)) != SQLITE_OK)
|
||||
{
|
||||
STHROWF("Unable to get runtime status information", m_Handle.ErrMsg());
|
||||
}
|
||||
// Return the high-water value if requested
|
||||
else if (highwater)
|
||||
{
|
||||
return hiwtr_value;
|
||||
}
|
||||
// Return the requested information
|
||||
return cur_value;
|
||||
}
|
||||
@ -168,7 +180,7 @@ Int32 Connection::GetInfo(Int32 operation, bool highwater, bool reset)
|
||||
void Connection::ReserveQueue(Uint32 num)
|
||||
{
|
||||
// Validate the handle
|
||||
Validate();
|
||||
m_Handle.Validate();
|
||||
// Perform the requested operation
|
||||
m_Handle->mQueue.reserve(m_Handle->mQueue.size() + num);
|
||||
}
|
||||
@ -177,7 +189,7 @@ void Connection::ReserveQueue(Uint32 num)
|
||||
Int32 Connection::Flush(Uint32 num)
|
||||
{
|
||||
// Validate the handle
|
||||
Validate();
|
||||
m_Handle.Validate();
|
||||
// We need to supply a null callback
|
||||
Object env;
|
||||
Function func;
|
||||
@ -189,7 +201,7 @@ Int32 Connection::Flush(Uint32 num)
|
||||
Int32 Connection::Flush(Uint32 num, Object & env, Function & func)
|
||||
{
|
||||
// Validate the handle
|
||||
Validate();
|
||||
m_Handle.Validate();
|
||||
// Attempt to flush the requested amount of queries
|
||||
return m_Handle->Flush(num, env, func);
|
||||
}
|
||||
@ -232,56 +244,21 @@ SQInteger Connection::ExecF(HSQUIRRELVM vm)
|
||||
return sq_throwerror(vm, "Invalid SQLite connection instance");
|
||||
}
|
||||
// Do we have a valid connection identifier?
|
||||
else if (!conn->m_Handle)
|
||||
else if (!(conn->m_Handle))
|
||||
{
|
||||
return sq_throwerror(vm, "Invalid SQLite connection reference");
|
||||
}
|
||||
// Do we have enough values to call the format function?
|
||||
else if (top > 2)
|
||||
{
|
||||
SStr sql = NULL;
|
||||
SQInteger len = 0;
|
||||
// Attempt to generate the specified string format
|
||||
SQRESULT ret = sqstd_format(vm, 2, &len, &sql);
|
||||
// Did the format failed?
|
||||
if (SQ_FAILED(ret))
|
||||
{
|
||||
return ret; // Propagate the exception
|
||||
}
|
||||
// Attempt to execute the specified query
|
||||
else if ((conn->m_Handle = sqlite3_exec(conn->m_Handle, sql, NULL, NULL, NULL)) != SQLITE_OK)
|
||||
{
|
||||
// Generate the query message first
|
||||
String msg("Unable to execute query ");
|
||||
// (we can't use FmtStr here because Squirrel doesn't make a copy of the message)
|
||||
msg.push_back('[');
|
||||
msg.append(conn->m_Handle.ErrMsg());
|
||||
msg.push_back(']');
|
||||
// Now throw the message
|
||||
return sq_throwerror(vm, msg.c_str());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Attempt to retrieve the value from the stack as a string
|
||||
Var< CSStr > sql(vm, 2);
|
||||
// See if the obtained value is a valid query string
|
||||
if (!sql.value)
|
||||
StackStrF val(vm, 2);
|
||||
// Have we failed to retrieve the string?
|
||||
if (SQ_FAILED(val.mRes))
|
||||
{
|
||||
return sq_throwerror(vm, "Unable to retrieve the query");
|
||||
return val.mRes; // Propagate the error!
|
||||
}
|
||||
// Attempt to execute the specified query
|
||||
else if ((conn->m_Handle = sqlite3_exec(conn->m_Handle, sql.value, NULL, NULL, NULL)) != SQLITE_OK)
|
||||
else if ((conn->m_Handle = sqlite3_exec(conn->m_Handle, val.mPtr, nullptr, nullptr, nullptr)) != SQLITE_OK)
|
||||
{
|
||||
// Generate the query message first
|
||||
String msg("Unable to execute query ");
|
||||
// (we can't use FmtStr here because Squirrel doesn't make a copy of the message)
|
||||
msg.push_back('[');
|
||||
msg.append(conn->m_Handle.ErrMsg());
|
||||
msg.push_back(']');
|
||||
// Now throw the message
|
||||
return sq_throwerror(vm, msg.c_str());
|
||||
}
|
||||
return sq_throwerror(vm, FmtStr("Unable to execute query [%s]", conn->m_Handle.ErrMsg()));
|
||||
}
|
||||
// Push the number of changes onto the stack
|
||||
sq_pushinteger(vm, sqlite3_changes(conn->m_Handle));
|
||||
@ -316,37 +293,19 @@ SQInteger Connection::QueueF(HSQUIRRELVM vm)
|
||||
return sq_throwerror(vm, "Invalid SQLite connection instance");
|
||||
}
|
||||
// Do we have a valid connection identifier?
|
||||
else if (!conn->m_Handle)
|
||||
else if (!(conn->m_Handle))
|
||||
{
|
||||
return sq_throwerror(vm, "Invalid SQLite connection reference");
|
||||
}
|
||||
// Do we have enough values to call the format function?
|
||||
else if (top > 2)
|
||||
{
|
||||
SStr sql = NULL;
|
||||
SQInteger len = 0;
|
||||
// Attempt to generate the specified string format
|
||||
SQRESULT ret = sqstd_format(vm, 2, &len, &sql);
|
||||
// Did the format failed?
|
||||
if (SQ_FAILED(ret))
|
||||
{
|
||||
return ret; // Propagate the exception
|
||||
}
|
||||
// Attempt to queue the specified query
|
||||
conn->m_Handle->mQueue.emplace_back(sql);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Attempt to retrieve the value from the stack as a string
|
||||
Var< CSStr > sql(vm, 2);
|
||||
// See if the obtained value is a valid query string
|
||||
if (!sql.value)
|
||||
StackStrF val(vm, 2);
|
||||
// Have we failed to retrieve the string?
|
||||
if (SQ_FAILED(val.mRes))
|
||||
{
|
||||
return sq_throwerror(vm, "Unable to retrieve the query");
|
||||
return val.mRes; // Propagate the error!
|
||||
}
|
||||
// Attempt to queue the specified query
|
||||
conn->m_Handle->mQueue.emplace_back(sql.value);
|
||||
}
|
||||
conn->m_Handle->mQueue.emplace_back(val.mPtr);
|
||||
// This function does not return a value
|
||||
return 0;
|
||||
}
|
||||
@ -378,51 +337,26 @@ SQInteger Connection::QueryF(HSQUIRRELVM vm)
|
||||
return sq_throwerror(vm, "Invalid SQLite connection instance");
|
||||
}
|
||||
// Do we have a valid connection identifier?
|
||||
else if (!conn->m_Handle)
|
||||
else if (!(conn->m_Handle))
|
||||
{
|
||||
return sq_throwerror(vm, "Invalid SQLite connection reference");
|
||||
}
|
||||
// Do we have enough values to call the format function?
|
||||
else if (top > 2)
|
||||
{
|
||||
SStr sql = NULL;
|
||||
SQInteger len = 0;
|
||||
// Attempt to generate the specified string format
|
||||
SQRESULT ret = sqstd_format(vm, 2, &len, &sql);
|
||||
// Did the format failed?
|
||||
if (SQ_FAILED(ret))
|
||||
{
|
||||
return ret; // Propagate the exception
|
||||
}
|
||||
// Attempt to create a statement with the specified query
|
||||
try
|
||||
{
|
||||
ClassType< Statement >::PushInstance(vm, new Statement(conn->m_Handle, sql));
|
||||
}
|
||||
catch (const Sqrat::Exception & e)
|
||||
{
|
||||
return sq_throwerror(vm, e.Message().c_str());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Attempt to retrieve the value from the stack as a string
|
||||
Var< CSStr > sql(vm, 2);
|
||||
// See if the obtained value is a valid query string
|
||||
if (!sql.value)
|
||||
StackStrF val(vm, 2);
|
||||
// Have we failed to retrieve the string?
|
||||
if (SQ_FAILED(val.mRes))
|
||||
{
|
||||
return sq_throwerror(vm, "Unable to retrieve the query");
|
||||
return val.mRes; // Propagate the error!
|
||||
}
|
||||
// Attempt to create a statement with the specified query
|
||||
try
|
||||
{
|
||||
ClassType< Statement >::PushInstance(vm, new Statement(conn->m_Handle, sql.value));
|
||||
ClassType< Statement >::PushInstance(vm, new Statement(conn->m_Handle, val.mPtr));
|
||||
}
|
||||
catch (const Sqrat::Exception & e)
|
||||
{
|
||||
return sq_throwerror(vm, e.Message().c_str());
|
||||
}
|
||||
}
|
||||
// This function returned a value
|
||||
return 1;
|
||||
}
|
||||
|
@ -20,15 +20,10 @@ protected:
|
||||
*/
|
||||
void Create(CSStr name, Int32 flags, CSStr vfs);
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Validate the document reference and throw an error if invalid.
|
||||
*/
|
||||
void Validate() const;
|
||||
|
||||
private:
|
||||
|
||||
// --------------------------------------------------------------------------------------------
|
||||
ConnHnd m_Handle; /* The handle to the managed database connection resource. */
|
||||
ConnHnd m_Handle; // The handle to the managed database connection resource.
|
||||
|
||||
public:
|
||||
|
||||
@ -125,12 +120,18 @@ public:
|
||||
Int32 Cmp(const Connection & o) const
|
||||
{
|
||||
if (m_Handle == m_Handle)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
else if (m_Handle.m_Hnd > o.m_Handle.m_Hnd)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Used by the script engine to convert an instance of this type to a string.
|
||||
@ -138,7 +139,7 @@ public:
|
||||
CSStr ToString() const
|
||||
{
|
||||
// Validate the handle
|
||||
Validate();
|
||||
m_Handle.Validate();
|
||||
// Return the requested information
|
||||
return m_Handle->mName.c_str();
|
||||
}
|
||||
@ -186,7 +187,7 @@ public:
|
||||
Int32 GetStatus() const
|
||||
{
|
||||
// Validate the handle
|
||||
Validate();
|
||||
m_Handle.Validate();
|
||||
// Return the requested information
|
||||
return m_Handle->mStatus;
|
||||
}
|
||||
@ -197,7 +198,7 @@ public:
|
||||
Int32 GetFlags() const
|
||||
{
|
||||
// Validate the handle
|
||||
Validate();
|
||||
m_Handle.Validate();
|
||||
// Return the requested information
|
||||
return m_Handle->mFlags;
|
||||
}
|
||||
@ -208,7 +209,7 @@ public:
|
||||
CSStr GetName() const
|
||||
{
|
||||
// Validate the handle
|
||||
Validate();
|
||||
m_Handle.Validate();
|
||||
// Return the requested information
|
||||
return m_Handle->mName.c_str();
|
||||
}
|
||||
@ -219,7 +220,7 @@ public:
|
||||
CSStr GetVFS() const
|
||||
{
|
||||
// Validate the handle
|
||||
Validate();
|
||||
m_Handle.Validate();
|
||||
// Return the requested information
|
||||
return m_Handle->mVFS.c_str();
|
||||
}
|
||||
@ -230,7 +231,7 @@ public:
|
||||
Int32 GetErrorCode() const
|
||||
{
|
||||
// Validate the handle
|
||||
Validate();
|
||||
m_Handle.Validate();
|
||||
// Return the requested information
|
||||
return m_Handle.ErrNo();
|
||||
}
|
||||
@ -241,7 +242,7 @@ public:
|
||||
Int32 GetExtendedErrorCode() const
|
||||
{
|
||||
// Validate the handle
|
||||
Validate();
|
||||
m_Handle.Validate();
|
||||
// Return the requested information
|
||||
return m_Handle.ExErrNo();
|
||||
}
|
||||
@ -252,7 +253,7 @@ public:
|
||||
CSStr GetErrStr() const
|
||||
{
|
||||
// Validate the handle
|
||||
Validate();
|
||||
m_Handle.Validate();
|
||||
// Return the requested information
|
||||
return m_Handle.ErrStr();
|
||||
}
|
||||
@ -263,7 +264,7 @@ public:
|
||||
CSStr GetErrMsg() const
|
||||
{
|
||||
// Validate the handle
|
||||
Validate();
|
||||
m_Handle.Validate();
|
||||
// Return the requested information
|
||||
return m_Handle.ErrMsg();
|
||||
}
|
||||
@ -274,7 +275,9 @@ public:
|
||||
void Open(CSStr name)
|
||||
{
|
||||
if (m_Handle.m_Hnd)
|
||||
m_Handle->Create(name, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, NULL);
|
||||
{
|
||||
m_Handle->Create(name, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
@ -283,7 +286,9 @@ public:
|
||||
void Open(CSStr name, Int32 flags)
|
||||
{
|
||||
if (m_Handle.m_Hnd)
|
||||
m_Handle->Create(name, flags, NULL);
|
||||
{
|
||||
m_Handle->Create(name, flags, nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
@ -292,8 +297,10 @@ public:
|
||||
void Open(CSStr name, Int32 flags, CSStr vfs)
|
||||
{
|
||||
if (m_Handle.m_Hnd)
|
||||
{
|
||||
m_Handle->Create(name, flags, vfs);
|
||||
}
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Attempt to execute the specified query.
|
||||
@ -326,7 +333,7 @@ public:
|
||||
bool GetAutoCommit() const
|
||||
{
|
||||
// Validate the handle
|
||||
Validate();
|
||||
m_Handle.Validate();
|
||||
// Return the requested information
|
||||
return sqlite3_get_autocommit(m_Handle);
|
||||
}
|
||||
@ -343,7 +350,7 @@ public:
|
||||
Int32 GetChanges() const
|
||||
{
|
||||
// Validate the handle
|
||||
Validate();
|
||||
m_Handle.Validate();
|
||||
// Return the requested information
|
||||
return sqlite3_changes(m_Handle);
|
||||
}
|
||||
@ -355,7 +362,7 @@ public:
|
||||
Int32 GetTotalChanges() const
|
||||
{
|
||||
// Validate the handle
|
||||
Validate();
|
||||
m_Handle.Validate();
|
||||
// Return the requested information
|
||||
return sqlite3_total_changes(m_Handle);
|
||||
}
|
||||
@ -366,7 +373,7 @@ public:
|
||||
bool GetTracing() const
|
||||
{
|
||||
// Validate the handle
|
||||
Validate();
|
||||
m_Handle.Validate();
|
||||
// Return the requested information
|
||||
return m_Handle->mTrace;
|
||||
}
|
||||
@ -377,16 +384,22 @@ public:
|
||||
void SetTracing(bool toggle)
|
||||
{
|
||||
// Validate the handle
|
||||
Validate();
|
||||
m_Handle.Validate();
|
||||
// Check whether changes are necessary
|
||||
if (m_Handle->mTrace == toggle)
|
||||
return; /* No point in proceeding */
|
||||
{
|
||||
return; // No point in proceeding
|
||||
}
|
||||
// Do we have to disable it?
|
||||
else if (m_Handle->mTrace)
|
||||
sqlite3_trace(m_Handle, NULL, NULL);
|
||||
{
|
||||
sqlite3_trace(m_Handle, nullptr, nullptr);
|
||||
}
|
||||
// Go ahead and enable tracing
|
||||
else
|
||||
sqlite3_trace(m_Handle, &Connection::TraceOutput, NULL);
|
||||
{
|
||||
sqlite3_trace(m_Handle, &Connection::TraceOutput, nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
@ -395,7 +408,7 @@ public:
|
||||
bool GetProfiling() const
|
||||
{
|
||||
// Validate the handle
|
||||
Validate();
|
||||
m_Handle.Validate();
|
||||
// Return the requested information
|
||||
return m_Handle->mProfile;
|
||||
}
|
||||
@ -406,16 +419,22 @@ public:
|
||||
void SetProfiling(bool toggle)
|
||||
{
|
||||
// Validate the handle
|
||||
Validate();
|
||||
m_Handle.Validate();
|
||||
// Check whether changes are necessary
|
||||
if (m_Handle->mProfile == toggle)
|
||||
return; /* No point in proceeding */
|
||||
{
|
||||
return; // No point in proceeding
|
||||
}
|
||||
// Do we have to disable it?
|
||||
else if (m_Handle->mProfile)
|
||||
sqlite3_profile(m_Handle, NULL, NULL);
|
||||
{
|
||||
sqlite3_profile(m_Handle, nullptr, nullptr);
|
||||
}
|
||||
// Go ahead and enable profiling
|
||||
else
|
||||
sqlite3_profile(m_Handle, &Connection::ProfileOutput, NULL);
|
||||
{
|
||||
sqlite3_profile(m_Handle, &Connection::ProfileOutput, nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
@ -429,7 +448,7 @@ public:
|
||||
void InterruptOperation() const
|
||||
{
|
||||
// Validate the handle
|
||||
Validate();
|
||||
m_Handle.Validate();
|
||||
// Perform the requested action
|
||||
sqlite3_interrupt(m_Handle);
|
||||
}
|
||||
@ -440,7 +459,7 @@ public:
|
||||
void ReleaseMemory() const
|
||||
{
|
||||
// Validate the handle
|
||||
Validate();
|
||||
m_Handle.Validate();
|
||||
// Perform the requested action
|
||||
sqlite3_db_release_memory(m_Handle);
|
||||
}
|
||||
@ -472,7 +491,7 @@ public:
|
||||
Uint32 QueueSize() const
|
||||
{
|
||||
// Validate the handle
|
||||
Validate();
|
||||
m_Handle.Validate();
|
||||
// Return the requested information
|
||||
return (Uint32)m_Handle->mQueue.size();
|
||||
}
|
||||
@ -488,7 +507,7 @@ public:
|
||||
void CompactQueue()
|
||||
{
|
||||
// Validate the handle
|
||||
Validate();
|
||||
m_Handle.Validate();
|
||||
// Perform the requested operation
|
||||
m_Handle->mQueue.shrink_to_fit();
|
||||
}
|
||||
@ -499,7 +518,7 @@ public:
|
||||
void ClearQueue()
|
||||
{
|
||||
// Validate the handle
|
||||
Validate();
|
||||
m_Handle.Validate();
|
||||
// Perform the requested operation
|
||||
m_Handle->mQueue.clear();
|
||||
}
|
||||
@ -510,11 +529,13 @@ public:
|
||||
void PopQueue()
|
||||
{
|
||||
// Validate the handle
|
||||
Validate();
|
||||
m_Handle.Validate();
|
||||
// Perform the requested action
|
||||
if (!m_Handle->mQueue.empty())
|
||||
{
|
||||
m_Handle->mQueue.pop_back();
|
||||
}
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Flush all queries from the queue.
|
||||
@ -522,7 +543,7 @@ public:
|
||||
Int32 Flush()
|
||||
{
|
||||
// Validate the handle
|
||||
Validate();
|
||||
m_Handle.Validate();
|
||||
// Return the requested information
|
||||
return Flush(m_Handle->mQueue.size());
|
||||
}
|
||||
@ -538,7 +559,7 @@ public:
|
||||
Int32 Flush(Object & env, Function & func)
|
||||
{
|
||||
// Validate the handle
|
||||
Validate();
|
||||
m_Handle.Validate();
|
||||
// Return the requested information
|
||||
return Flush(m_Handle->mQueue.size(), env, func);
|
||||
}
|
||||
|
@ -6,12 +6,12 @@
|
||||
#include "Column.hpp"
|
||||
|
||||
// --------------------------------------------------------------------------------------------
|
||||
#include <sqrat.h>
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
#include <cstdarg>
|
||||
|
||||
// --------------------------------------------------------------------------------------------
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdarg.h>
|
||||
#include <sqrat.h>
|
||||
|
||||
// --------------------------------------------------------------------------------------------
|
||||
#if defined(WIN32) || defined(_WIN32)
|
||||
@ -21,14 +21,14 @@
|
||||
namespace SqMod {
|
||||
|
||||
// --------------------------------------------------------------------------------------------
|
||||
PluginFuncs* _Func = NULL;
|
||||
PluginCallbacks* _Clbk = NULL;
|
||||
PluginInfo* _Info = NULL;
|
||||
PluginFuncs* _Func = nullptr;
|
||||
PluginCallbacks* _Clbk = nullptr;
|
||||
PluginInfo* _Info = nullptr;
|
||||
|
||||
// --------------------------------------------------------------------------------------------
|
||||
HSQAPI _SqAPI = NULL;
|
||||
HSQEXPORTS _SqMod = NULL;
|
||||
HSQUIRRELVM _SqVM = NULL;
|
||||
HSQAPI _SqAPI = nullptr;
|
||||
HSQEXPORTS _SqMod = nullptr;
|
||||
HSQUIRRELVM _SqVM = nullptr;
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
* Bind speciffic functions to certain server events.
|
||||
@ -54,7 +54,9 @@ void OnSquirrelInitialize()
|
||||
_SqMod = sq_api_import(_Func);
|
||||
// Did we failed to obtain the plugin exports?
|
||||
if(!_SqMod)
|
||||
{
|
||||
OutputError("Failed to attach [%s] on host plugin.", SQSQLITE_NAME);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Obtain the Squirrel API
|
||||
@ -71,12 +73,16 @@ void OnSquirrelLoad()
|
||||
{
|
||||
// Make sure that we have a valid plugin API
|
||||
if (!_SqMod)
|
||||
return; /* Unable to proceed. */
|
||||
{
|
||||
return; // Unable to proceed.
|
||||
}
|
||||
// Obtain the Squirrel API and VM
|
||||
_SqVM = _SqMod->GetSquirrelVM();
|
||||
// Make sure that a valid virtual machine exists
|
||||
if (!_SqVM)
|
||||
return; /* Unable to proceed. */
|
||||
{
|
||||
return; // Unable to proceed.
|
||||
}
|
||||
// Set this as the default database
|
||||
DefaultVM::Set(_SqVM);
|
||||
// Register the module API
|
||||
@ -92,7 +98,7 @@ void OnSquirrelTerminate()
|
||||
{
|
||||
OutputMessage("Terminating: %s", SQSQLITE_NAME);
|
||||
// Release the current database (if any)
|
||||
DefaultVM::Set(NULL);
|
||||
DefaultVM::Set(nullptr);
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
@ -101,10 +107,12 @@ void OnSquirrelTerminate()
|
||||
bool CheckAPIVer(CCStr ver)
|
||||
{
|
||||
// Obtain the numeric representation of the API version
|
||||
long vernum = strtol(ver, NULL, 10);
|
||||
long vernum = strtol(ver, nullptr, 10);
|
||||
// Check against version mismatch
|
||||
if (vernum == SQMOD_API_VER)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
// Log the incident
|
||||
OutputError("API version mismatch on %s", SQSQLITE_NAME);
|
||||
OutputMessage("=> Requested: %ld Have: %ld", vernum, SQMOD_API_VER);
|
||||
@ -121,7 +129,9 @@ static int OnInternalCommand(unsigned int type, const char * text)
|
||||
{
|
||||
case SQMOD_INITIALIZE_CMD:
|
||||
if (CheckAPIVer(text))
|
||||
{
|
||||
OnSquirrelInitialize();
|
||||
}
|
||||
break;
|
||||
case SQMOD_LOAD_CMD:
|
||||
OnSquirrelLoad();
|
||||
@ -159,9 +169,9 @@ void BindCallbacks()
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void UnbindCallbacks()
|
||||
{
|
||||
_Clbk->OnInitServer = NULL;
|
||||
_Clbk->OnInternalCommand = NULL;
|
||||
_Clbk->OnShutdownServer = NULL;
|
||||
_Clbk->OnInitServer = nullptr;
|
||||
_Clbk->OnInternalCommand = nullptr;
|
||||
_Clbk->OnShutdownServer = nullptr;
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------------------------
|
||||
@ -199,7 +209,7 @@ void RegisterAPI(HSQUIRRELVM vm)
|
||||
.Prop(_SC("TotalChanges"), &Connection::GetTotalChanges)
|
||||
.Prop(_SC("Trace"), &Connection::GetTracing, &Connection::SetTracing)
|
||||
.Prop(_SC("Profile"), &Connection::GetProfiling, &Connection::SetProfiling)
|
||||
.Prop(_SC("BusyTimeout"), (Int32 (Connection::*)(void) const)(NULL), &Connection::SetBusyTimeout)
|
||||
.Prop(_SC("BusyTimeout"), (Int32 (Connection::*)(void) const)(nullptr), &Connection::SetBusyTimeout)
|
||||
.Prop(_SC("QueueSize"), &Connection::QueueSize)
|
||||
// Member Methods
|
||||
.Func(_SC("Release"), &Connection::Release)
|
||||
@ -584,7 +594,7 @@ void RegisterAPI(HSQUIRRELVM vm)
|
||||
.Const(_SC("NOTICE"), SQLITE_NOTICE)
|
||||
.Const(_SC("NOTICE_RECOVER_ROLLBACK"), SQLITE_NOTICE_RECOVER_ROLLBACK)
|
||||
.Const(_SC("NOTICE_RECOVER_WAL"), SQLITE_NOTICE_RECOVER_WAL)
|
||||
.Const(_SC("NULL"), SQLITE_NULL)
|
||||
.Const(_SC("nullptr"), SQLITE_NULL)
|
||||
.Const(_SC("OK"), SQLITE_OK)
|
||||
.Const(_SC("OPEN_AUTOPROXY"), SQLITE_OPEN_AUTOPROXY)
|
||||
.Const(_SC("OPEN_CREATE"), SQLITE_OPEN_CREATE)
|
||||
|
@ -4,6 +4,9 @@
|
||||
#include "Column.hpp"
|
||||
#include "Module.hpp"
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
#include <cstring>
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
#include <sqrat.h>
|
||||
|
||||
@ -24,16 +27,6 @@ SQInteger Statement::Typename(HSQUIRRELVM vm)
|
||||
return 1;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void Statement::Validate() const
|
||||
{
|
||||
// Is the handle valid?
|
||||
if (!m_Handle)
|
||||
{
|
||||
STHROWF("Invalid SQLite statement reference");
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void Statement::ValidateIndex(Int32 idx) const
|
||||
{
|
||||
@ -107,7 +100,7 @@ Statement::Statement(const Connection & connection, CSStr query)
|
||||
Object Statement::GetConnection() const
|
||||
{
|
||||
// Validate the handle
|
||||
Validate();
|
||||
m_Handle.Validate();
|
||||
// Return the requested information
|
||||
return Object(new Connection(m_Handle->mConn));
|
||||
}
|
||||
@ -116,7 +109,7 @@ Object Statement::GetConnection() const
|
||||
void Statement::Reset()
|
||||
{
|
||||
// Validate the handle
|
||||
Validate();
|
||||
m_Handle.Validate();
|
||||
// Specify that we don't have a row available and we haven't finished stepping
|
||||
m_Handle->mGood = false;
|
||||
m_Handle->mDone = false;
|
||||
@ -133,7 +126,7 @@ void Statement::Reset()
|
||||
void Statement::Clear()
|
||||
{
|
||||
// Validate the handle
|
||||
Validate();
|
||||
m_Handle.Validate();
|
||||
// Specify that we don't have a row available and we haven't finished stepping
|
||||
m_Handle->mGood = false;
|
||||
m_Handle->mDone = false;
|
||||
@ -150,7 +143,7 @@ void Statement::Clear()
|
||||
Int32 Statement::Exec()
|
||||
{
|
||||
// Validate the handle
|
||||
Validate();
|
||||
m_Handle.Validate();
|
||||
// Did we reset first?
|
||||
if (m_Handle->mDone)
|
||||
{
|
||||
@ -188,7 +181,7 @@ Int32 Statement::Exec()
|
||||
bool Statement::Step()
|
||||
{
|
||||
// Validate the handle
|
||||
Validate();
|
||||
m_Handle.Validate();
|
||||
// Did we reset first?
|
||||
if (m_Handle->mDone)
|
||||
{
|
||||
@ -229,7 +222,7 @@ bool Statement::Step()
|
||||
void Statement::IndexBindA(Int32 idx, const Array & arr)
|
||||
{
|
||||
// Validate the handle
|
||||
Validate();
|
||||
m_Handle.Validate();
|
||||
// Know when to stop trying to bind values
|
||||
const Int32 max = sqlite3_bind_parameter_count(m_Handle);
|
||||
// Make sure that we are at least in bounds
|
||||
@ -267,7 +260,7 @@ void Statement::IndexBindA(Int32 idx, const Array & arr)
|
||||
void Statement::IndexBindI(Int32 idx, Int32 value)
|
||||
{
|
||||
// Validate the handle
|
||||
Validate();
|
||||
m_Handle.Validate();
|
||||
// Attempt to bind the specified value
|
||||
m_Handle = sqlite3_bind_int(m_Handle, idx, value);
|
||||
// Validate the result
|
||||
@ -281,7 +274,7 @@ void Statement::IndexBindI(Int32 idx, Int32 value)
|
||||
void Statement::IndexBindL(Int32 idx, const Object & value)
|
||||
{
|
||||
// Validate the handle
|
||||
Validate();
|
||||
m_Handle.Validate();
|
||||
// Obtain the initial stack size
|
||||
const StackGuard sg(DefaultVM::Get());
|
||||
// Push the specified object onto the stack
|
||||
@ -306,7 +299,7 @@ void Statement::IndexBindL(Int32 idx, const Object & value)
|
||||
void Statement::IndexBindV(Int32 idx, SQInteger value)
|
||||
{
|
||||
// Validate the handle
|
||||
Validate();
|
||||
m_Handle.Validate();
|
||||
// Attempt to bind the specified value
|
||||
#ifdef _SQ64
|
||||
m_Handle = sqlite3_bind_int64(m_Handle, idx, value);
|
||||
@ -324,7 +317,7 @@ void Statement::IndexBindV(Int32 idx, SQInteger value)
|
||||
void Statement::IndexBindF(Int32 idx, SQFloat value)
|
||||
{
|
||||
// Validate the handle
|
||||
Validate();
|
||||
m_Handle.Validate();
|
||||
// Attempt to bind the specified value
|
||||
m_Handle = sqlite3_bind_double(m_Handle, idx, value);
|
||||
// Validate the result
|
||||
@ -338,7 +331,7 @@ void Statement::IndexBindF(Int32 idx, SQFloat value)
|
||||
void Statement::IndexBindS(Int32 idx, CSStr value)
|
||||
{
|
||||
// Validate the handle
|
||||
Validate();
|
||||
m_Handle.Validate();
|
||||
// Attempt to bind the specified value
|
||||
m_Handle = sqlite3_bind_text(m_Handle, idx, value, -1, SQLITE_TRANSIENT);
|
||||
// Validate the result
|
||||
@ -352,7 +345,7 @@ void Statement::IndexBindS(Int32 idx, CSStr value)
|
||||
void Statement::IndexBindB(Int32 idx, bool value)
|
||||
{
|
||||
// Validate the handle
|
||||
Validate();
|
||||
m_Handle.Validate();
|
||||
// Attempt to bind the specified value
|
||||
m_Handle = sqlite3_bind_int(m_Handle, idx, value);
|
||||
// Validate the result
|
||||
@ -366,7 +359,7 @@ void Statement::IndexBindB(Int32 idx, bool value)
|
||||
void Statement::IndexBindN(Int32 idx)
|
||||
{
|
||||
// Validate the handle
|
||||
Validate();
|
||||
m_Handle.Validate();
|
||||
// Attempt to bind the specified value
|
||||
m_Handle = sqlite3_bind_null(m_Handle, idx);
|
||||
// Validate the result
|
||||
@ -380,7 +373,7 @@ void Statement::IndexBindN(Int32 idx)
|
||||
void Statement::NameBindT(const Table & tbl)
|
||||
{
|
||||
// Validate the handle
|
||||
Validate();
|
||||
m_Handle.Validate();
|
||||
// Should we clear the all the parameters?
|
||||
if (tbl.GetSize() <= 0)
|
||||
{
|
||||
@ -408,7 +401,7 @@ void Statement::NameBindT(const Table & tbl)
|
||||
void Statement::NameBindI(CSStr name, Int32 value)
|
||||
{
|
||||
// Validate the handle
|
||||
Validate();
|
||||
m_Handle.Validate();
|
||||
// Attempt to obtain the index of the specified parameter name
|
||||
const Int32 idx = sqlite3_bind_parameter_index(m_Handle, name);
|
||||
// Validate the obtained index
|
||||
@ -429,7 +422,7 @@ void Statement::NameBindI(CSStr name, Int32 value)
|
||||
void Statement::NameBindL(CSStr name, const Object & value)
|
||||
{
|
||||
// Validate the handle
|
||||
Validate();
|
||||
m_Handle.Validate();
|
||||
// Attempt to obtain the index of the specified parameter name
|
||||
const Int32 idx = sqlite3_bind_parameter_index(m_Handle, name);
|
||||
// Validate the obtained index
|
||||
@ -461,7 +454,7 @@ void Statement::NameBindL(CSStr name, const Object & value)
|
||||
void Statement::NameBindV(CSStr name, SQInteger value)
|
||||
{
|
||||
// Validate the handle
|
||||
Validate();
|
||||
m_Handle.Validate();
|
||||
// Attempt to obtain the index of the specified parameter name
|
||||
const Int32 idx = sqlite3_bind_parameter_index(m_Handle, name);
|
||||
// Validate the obtained index
|
||||
@ -486,7 +479,7 @@ void Statement::NameBindV(CSStr name, SQInteger value)
|
||||
void Statement::NameBindF(CSStr name, SQFloat value)
|
||||
{
|
||||
// Validate the handle
|
||||
Validate();
|
||||
m_Handle.Validate();
|
||||
// Attempt to obtain the index of the specified parameter name
|
||||
const Int32 idx = sqlite3_bind_parameter_index(m_Handle, name);
|
||||
// Validate the obtained index
|
||||
@ -507,7 +500,7 @@ void Statement::NameBindF(CSStr name, SQFloat value)
|
||||
void Statement::NameBindS(CSStr name, CSStr value)
|
||||
{
|
||||
// Validate the handle
|
||||
Validate();
|
||||
m_Handle.Validate();
|
||||
// Attempt to obtain the index of the specified parameter name
|
||||
const Int32 idx = sqlite3_bind_parameter_index(m_Handle, name);
|
||||
// Validate the obtained index
|
||||
@ -528,7 +521,7 @@ void Statement::NameBindS(CSStr name, CSStr value)
|
||||
void Statement::NameBindB(CSStr name, bool value)
|
||||
{
|
||||
// Validate the handle
|
||||
Validate();
|
||||
m_Handle.Validate();
|
||||
// Attempt to obtain the index of the specified parameter name
|
||||
const Int32 idx = sqlite3_bind_parameter_index(m_Handle, name);
|
||||
// Validate the obtained index
|
||||
@ -549,7 +542,7 @@ void Statement::NameBindB(CSStr name, bool value)
|
||||
void Statement::NameBindN(CSStr name)
|
||||
{
|
||||
// Validate the handle
|
||||
Validate();
|
||||
m_Handle.Validate();
|
||||
// Attempt to obtain the index of the specified parameter name
|
||||
const Int32 idx = sqlite3_bind_parameter_index(m_Handle, name);
|
||||
// Validate the obtained index
|
||||
@ -570,7 +563,7 @@ void Statement::NameBindN(CSStr name)
|
||||
void Statement::IndexBind(Int32 idx, const Object & value)
|
||||
{
|
||||
// Validate the handle
|
||||
Validate();
|
||||
m_Handle.Validate();
|
||||
// Attempt to identify the specified type
|
||||
switch (value.GetType())
|
||||
{
|
||||
@ -620,8 +613,7 @@ void Statement::IndexBind(Int32 idx, const Object & value)
|
||||
m_Handle = sqlite3_bind_int64(m_Handle, idx, longint);
|
||||
} break;
|
||||
// We don't recognize this kind of value!
|
||||
default:
|
||||
STHROWF("Attempting to bind unknown value type (%d)", idx);
|
||||
default: STHROWF("Attempting to bind unknown value type (%d)", idx);
|
||||
}
|
||||
// Validate the result
|
||||
if (m_Handle != SQLITE_OK)
|
||||
@ -634,7 +626,7 @@ void Statement::IndexBind(Int32 idx, const Object & value)
|
||||
void Statement::NameBind(CSStr name, const Object & value)
|
||||
{
|
||||
// Validate the handle
|
||||
Validate();
|
||||
m_Handle.Validate();
|
||||
// Attempt to obtain the index of the specified parameter name
|
||||
const Int32 idx = sqlite3_bind_parameter_index(m_Handle, name);
|
||||
// Validate the obtained index
|
||||
@ -691,8 +683,7 @@ void Statement::NameBind(CSStr name, const Object & value)
|
||||
m_Handle = sqlite3_bind_int64(m_Handle, idx, longint);
|
||||
} break;
|
||||
// We don't recognize this kind of value!
|
||||
default:
|
||||
STHROWF("Attempting to bind unknown value type (%s:%d)", name, idx);
|
||||
default: STHROWF("Attempting to bind unknown value type (%s:%d)", name, idx);
|
||||
}
|
||||
// Validate the result
|
||||
if (m_Handle != SQLITE_OK)
|
||||
@ -766,7 +757,9 @@ Object Statement::FetchColumnIndex(Int32 idx) const
|
||||
const void * b = sqlite3_column_blob(m_Handle, idx);
|
||||
// Could the memory blob be allocated?
|
||||
if (!p)
|
||||
{
|
||||
STHROWF("Unable to allocate space for column blob value");
|
||||
}
|
||||
// Is there any data to read?
|
||||
else if (!b)
|
||||
{
|
||||
@ -777,11 +770,12 @@ Object Statement::FetchColumnIndex(Int32 idx) const
|
||||
}
|
||||
// Copy the data into the memory blob
|
||||
else
|
||||
memcpy(p, b, sz);
|
||||
{
|
||||
std::memcpy(p, b, sz);
|
||||
}
|
||||
} break;
|
||||
// Unknown type
|
||||
default:
|
||||
STHROWF("Unknown value to fetch at index: %d", idx);
|
||||
default: STHROWF("Unknown value to fetch at index: %d", idx);
|
||||
}
|
||||
// Obtain the object with the value from the stack and return it
|
||||
return Var< Object >(DefaultVM::Get(), -1).value;
|
||||
@ -819,7 +813,7 @@ Object Statement::FetchColumn(const Object & column) const
|
||||
Array Statement::FetchArray() const
|
||||
{
|
||||
// Validate the handle
|
||||
Validate();
|
||||
m_Handle.Validate();
|
||||
// Return the requested information
|
||||
return FetchArray(0, m_Handle->mColumns);
|
||||
}
|
||||
@ -828,7 +822,7 @@ Array Statement::FetchArray() const
|
||||
Array Statement::FetchArray(Int32 min) const
|
||||
{
|
||||
// Validate the handle
|
||||
Validate();
|
||||
m_Handle.Validate();
|
||||
// Return the requested information
|
||||
return FetchArray(min, m_Handle->mColumns);
|
||||
}
|
||||
@ -913,7 +907,7 @@ Array Statement::FetchArray(Int32 min, Int32 max) const
|
||||
// Copy the data into the memory blob
|
||||
else
|
||||
{
|
||||
memcpy(p, b, sz);
|
||||
std::memcpy(p, b, sz);
|
||||
}
|
||||
// Obtain the object from the stack
|
||||
Var< Object > obj(DefaultVM::Get(), -1);
|
||||
@ -921,8 +915,7 @@ Array Statement::FetchArray(Int32 min, Int32 max) const
|
||||
arr.Bind(elem, obj.value);
|
||||
} break;
|
||||
// Unknown type
|
||||
default:
|
||||
STHROWF("Unknown value to fetch at index: %d", idx);
|
||||
default: STHROWF("Unknown value to fetch at index: %d", idx);
|
||||
}
|
||||
}
|
||||
// Return the resulted array
|
||||
@ -933,7 +926,7 @@ Array Statement::FetchArray(Int32 min, Int32 max) const
|
||||
Table Statement::FetchTable() const
|
||||
{
|
||||
// Validate the handle
|
||||
Validate();
|
||||
m_Handle.Validate();
|
||||
// Return the requested information
|
||||
return FetchTable(0, m_Handle->mColumns);
|
||||
}
|
||||
@ -942,7 +935,7 @@ Table Statement::FetchTable() const
|
||||
Table Statement::FetchTable(Int32 min) const
|
||||
{
|
||||
// Validate the handle
|
||||
Validate();
|
||||
m_Handle.Validate();
|
||||
// Return the requested information
|
||||
return FetchTable(min, m_Handle->mColumns);
|
||||
}
|
||||
@ -983,7 +976,9 @@ Table Statement::FetchTable(Int32 min, Int32 max) const
|
||||
CSStr name = sqlite3_column_name(m_Handle, idx);
|
||||
// Validate the obtained name
|
||||
if (!name)
|
||||
{
|
||||
STHROWF("Unable to retrieve name of column (%d)", idx);
|
||||
}
|
||||
// Identify the type of value that must be assigned
|
||||
switch (sqlite3_column_type(m_Handle, idx))
|
||||
{
|
||||
@ -1038,7 +1033,7 @@ Table Statement::FetchTable(Int32 min, Int32 max) const
|
||||
// Copy the data into the memory blob
|
||||
else
|
||||
{
|
||||
memcpy(p, b, sz);
|
||||
std::memcpy(p, b, sz);
|
||||
}
|
||||
// Obtain the object from the stack
|
||||
Var< Object > obj(DefaultVM::Get(), -1);
|
||||
@ -1046,8 +1041,7 @@ Table Statement::FetchTable(Int32 min, Int32 max) const
|
||||
tbl.Bind(name, obj.value);
|
||||
} break;
|
||||
// Unknown type
|
||||
default:
|
||||
STHROWF("Unknown value to fetch at index: %d", idx);
|
||||
default: STHROWF("Unknown value to fetch at index: %d", idx);
|
||||
}
|
||||
}
|
||||
// Return the resulted table
|
||||
@ -1058,7 +1052,7 @@ Table Statement::FetchTable(Int32 min, Int32 max) const
|
||||
bool Statement::CheckIndex(Int32 idx) const
|
||||
{
|
||||
// Validate the handle
|
||||
Validate();
|
||||
m_Handle.Validate();
|
||||
// Return the requested information
|
||||
return m_Handle->CheckIndex(idx);
|
||||
}
|
||||
@ -1076,7 +1070,7 @@ bool Statement::IsColumnNull(Int32 idx) const
|
||||
Int32 Statement::GetColumnIndex(CSStr name) const
|
||||
{
|
||||
// Validate the handle
|
||||
Validate();
|
||||
m_Handle.Validate();
|
||||
// Return the requested information
|
||||
return m_Handle->GetColumnIndex(name);
|
||||
}
|
||||
@ -1139,7 +1133,7 @@ Object Statement::GetColumnByIndex(Int32 idx) const
|
||||
Object Statement::GetColumnByName(CSStr name) const
|
||||
{
|
||||
// Validate the handle
|
||||
Validate();
|
||||
m_Handle.Validate();
|
||||
// Attempt to obtain the requested column index
|
||||
const Int32 idx = m_Handle->GetColumnIndex(name);
|
||||
// Validate the obtained index
|
||||
@ -1166,7 +1160,7 @@ Object Statement::GetColumn(const Object & column) const
|
||||
}
|
||||
// We don't recognize this kind of value!
|
||||
STHROWF("Unknown column identifier type");
|
||||
// We have to return something!
|
||||
// We have to return something even if we don't rach this point!
|
||||
return Object();
|
||||
}
|
||||
|
||||
|
@ -16,15 +16,10 @@ class Statement
|
||||
private:
|
||||
|
||||
// --------------------------------------------------------------------------------------------
|
||||
StmtHnd m_Handle; /* The handle to the managed database statement resource. */
|
||||
StmtHnd m_Handle; // The handle to the managed database statement resource.
|
||||
|
||||
protected:
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Validate the statement reference and throw an error if invalid.
|
||||
*/
|
||||
void Validate() const;
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Validate the statement reference and index, and throw an error if they're invalid.
|
||||
*/
|
||||
@ -125,12 +120,18 @@ public:
|
||||
Int32 Cmp(const Statement & o) const
|
||||
{
|
||||
if (m_Handle.m_Hnd == o.m_Handle.m_Hnd)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
else if (m_Handle.m_Hnd > o.m_Handle.m_Hnd)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Used by the script engine to convert an instance of this type to a string.
|
||||
@ -139,7 +140,9 @@ public:
|
||||
{
|
||||
// Validate the handle
|
||||
if (m_Handle)
|
||||
{
|
||||
return m_Handle->mQuery.c_str();
|
||||
}
|
||||
// Request failed
|
||||
return _SC("");
|
||||
}
|
||||
@ -154,7 +157,7 @@ public:
|
||||
*/
|
||||
bool IsValid() const
|
||||
{
|
||||
return (bool)m_Handle;
|
||||
return m_Handle;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
@ -192,7 +195,7 @@ public:
|
||||
Int32 GetStatus() const
|
||||
{
|
||||
// Validate the handle
|
||||
Validate();
|
||||
m_Handle.Validate();
|
||||
// Return the requested information
|
||||
return m_Handle->mStatus;
|
||||
}
|
||||
@ -203,7 +206,7 @@ public:
|
||||
Int32 GetErrorCode() const
|
||||
{
|
||||
// Validate the handle
|
||||
Validate();
|
||||
m_Handle.Validate();
|
||||
// Return the requested information
|
||||
return m_Handle.ErrNo();
|
||||
}
|
||||
@ -214,7 +217,7 @@ public:
|
||||
Int32 GetExtendedErrorCode() const
|
||||
{
|
||||
// Validate the handle
|
||||
Validate();
|
||||
m_Handle.Validate();
|
||||
// Return the requested information
|
||||
return m_Handle.ExErrNo();
|
||||
}
|
||||
@ -225,7 +228,7 @@ public:
|
||||
CSStr GetErrStr() const
|
||||
{
|
||||
// Validate the handle
|
||||
Validate();
|
||||
m_Handle.Validate();
|
||||
// Return the requested information
|
||||
return m_Handle.ErrStr();
|
||||
}
|
||||
@ -236,7 +239,7 @@ public:
|
||||
CSStr GetErrMsg() const
|
||||
{
|
||||
// Validate the handle
|
||||
Validate();
|
||||
m_Handle.Validate();
|
||||
// Return the requested information
|
||||
return m_Handle.ErrMsg();
|
||||
}
|
||||
@ -247,7 +250,7 @@ public:
|
||||
Int32 GetColumns() const
|
||||
{
|
||||
// Validate the handle
|
||||
Validate();
|
||||
m_Handle.Validate();
|
||||
// Return the requested information
|
||||
return m_Handle->mColumns;
|
||||
}
|
||||
@ -258,7 +261,7 @@ public:
|
||||
CSStr GetQuery() const
|
||||
{
|
||||
// Validate the handle
|
||||
Validate();
|
||||
m_Handle.Validate();
|
||||
// Return the requested information
|
||||
return m_Handle->mQuery.c_str();
|
||||
}
|
||||
@ -269,7 +272,7 @@ public:
|
||||
bool GetGood() const
|
||||
{
|
||||
// Validate the handle
|
||||
Validate();
|
||||
m_Handle.Validate();
|
||||
// Return the requested information
|
||||
return m_Handle->mGood;
|
||||
}
|
||||
@ -280,7 +283,7 @@ public:
|
||||
bool GetDone() const
|
||||
{
|
||||
// Validate the handle
|
||||
Validate();
|
||||
m_Handle.Validate();
|
||||
// Return the requested information
|
||||
return m_Handle->mDone;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user