mirror of
https://github.com/VCMP-SqMod/SqMod.git
synced 2025-01-31 09:57:14 +01:00
Switched the SQLite module to use C++ exceptions to fix the Sqrat issues and gain significantly more performance.
Also fixed various other issues in the SQLite module.
This commit is contained in:
parent
8340a5dbc4
commit
331b03028c
@ -363,6 +363,7 @@
|
|||||||
<Add option="-Wextra" />
|
<Add option="-Wextra" />
|
||||||
<Add option="-Wall" />
|
<Add option="-Wall" />
|
||||||
<Add option="-DSQMOD_PLUGIN_API" />
|
<Add option="-DSQMOD_PLUGIN_API" />
|
||||||
|
<Add option="-DSCRAT_USE_EXCEPTIONS" />
|
||||||
<Add directory="../modules/sqlite" />
|
<Add directory="../modules/sqlite" />
|
||||||
<Add directory="../shared" />
|
<Add directory="../shared" />
|
||||||
<Add directory="../include" />
|
<Add directory="../include" />
|
||||||
|
@ -19,107 +19,91 @@ SQInteger Column::Typename(HSQUIRRELVM vm)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
bool Column::Validate() const
|
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)
|
||||||
_SqMod->SqThrow("Invalid column index");
|
SqThrowF("Invalid column index");
|
||||||
// Do we belong to a valid statement?
|
// Do we belong to a valid statement?
|
||||||
else if (!m_Stmt)
|
else if (!m_Stmt)
|
||||||
_SqMod->SqThrow("Invalid SQLite statement reference");
|
SqThrowF("Invalid SQLite statement reference");
|
||||||
// Requirements satisfied
|
|
||||||
else
|
|
||||||
return true;
|
|
||||||
// Validation failed
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
bool Column::RowAvailable() const
|
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)
|
||||||
_SqMod->SqThrow("Invalid column index");
|
SqThrowF("Invalid column index");
|
||||||
// Do we belong to a valid statement?
|
// Do we belong to a valid statement?
|
||||||
else if (!m_Stmt)
|
else if (!m_Stmt)
|
||||||
_SqMod->SqThrow("Invalid SQLite statement reference");
|
SqThrowF("Invalid SQLite statement reference");
|
||||||
// Do we have any rows available?
|
// Do we have any rows available?
|
||||||
else if (!m_Stmt->mGood)
|
else if (!m_Stmt->mGood)
|
||||||
_SqMod->SqThrow("No row available");
|
SqThrowF("No row available");
|
||||||
// Requirements satisfied
|
|
||||||
else
|
|
||||||
return true;
|
|
||||||
// Validation failed
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
Object Column::GetStatement() const
|
Object Column::GetStatement() const
|
||||||
{
|
{
|
||||||
// Validate the handle
|
// Validate the column
|
||||||
if (Validate())
|
Validate();
|
||||||
|
// Return the requested information
|
||||||
return Object(new Statement(m_Stmt));
|
return Object(new Statement(m_Stmt));
|
||||||
// Request failed
|
|
||||||
return Object(new Statement());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
Object Column::GetConnection() const
|
Object Column::GetConnection() const
|
||||||
{
|
{
|
||||||
// Validate the handle
|
// Validate the column
|
||||||
if (Validate())
|
Validate();
|
||||||
|
// Return the requested information
|
||||||
return Object(new Connection(m_Stmt->mConn));
|
return Object(new Connection(m_Stmt->mConn));
|
||||||
// Request failed
|
|
||||||
return Object(new Connection());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
Int32 Column::GetNumber() const
|
Int32 Column::GetNumber() const
|
||||||
{
|
{
|
||||||
// Validate the handle and index
|
// Validate the column and statement row
|
||||||
if (RowAvailable())
|
ValidateRow();
|
||||||
|
// Return the requested information
|
||||||
return sqlite3_column_int(m_Stmt, m_Index);
|
return sqlite3_column_int(m_Stmt, m_Index);
|
||||||
// Request failed
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
SQInteger Column::GetInteger() const
|
SQInteger Column::GetInteger() const
|
||||||
{
|
{
|
||||||
// Validate the handle and index
|
// Validate the column and statement row
|
||||||
if (RowAvailable())
|
ValidateRow();
|
||||||
|
// Return the requested information
|
||||||
#ifdef _SQ64
|
#ifdef _SQ64
|
||||||
return sqlite3_column_int64(m_Stmt, m_Index);
|
return sqlite3_column_int64(m_Stmt, m_Index);
|
||||||
#else
|
#else
|
||||||
return sqlite3_column_int(m_Stmt, m_Index);
|
return sqlite3_column_int(m_Stmt, m_Index);
|
||||||
#endif
|
#endif
|
||||||
// Request failed
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
SQFloat Column::GetFloat() const
|
SQFloat Column::GetFloat() const
|
||||||
{
|
{
|
||||||
// Validate the handle and index
|
// Validate the column and statement row
|
||||||
if (RowAvailable())
|
ValidateRow();
|
||||||
|
// Return the requested information
|
||||||
return (SQFloat)sqlite3_column_double(m_Stmt, m_Index);
|
return (SQFloat)sqlite3_column_double(m_Stmt, m_Index);
|
||||||
// Request failed
|
|
||||||
return SQFloat(0.0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
Object Column::GetLong() const
|
Object Column::GetLong() const
|
||||||
{
|
{
|
||||||
// Validate the handle and index
|
// Validate the column and statement row
|
||||||
if (!RowAvailable())
|
ValidateRow();
|
||||||
return Object(); // Request failed
|
|
||||||
// Obtain the initial stack size
|
// Obtain the initial stack size
|
||||||
const Int32 top = sq_gettop(_SqVM);
|
const Int32 top = sq_gettop(_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
|
||||||
_SqMod->PushSLongObject(_SqVM, sqlite3_column_int64(m_Stmt, m_Index));
|
_SqMod->PushSLongObject(_SqVM, sqlite3_column_int64(m_Stmt, m_Index));
|
||||||
// Obtain the object from the stack
|
// Obtain the object from the stack
|
||||||
Var< Object > inst(_SqVM, -1);
|
Var< Object > inst(_SqVM, -1);
|
||||||
// Remove an pushed values (if any) to restore the stack
|
// Remove any pushed values (if any) to restore the stack
|
||||||
sq_pop(_SqVM, sq_gettop(_SqVM) - top);
|
sq_pop(_SqVM, sq_gettop(_SqVM) - top);
|
||||||
// Return the long integer instance
|
// Return the long integer instance
|
||||||
return inst.value;
|
return inst.value;
|
||||||
@ -128,9 +112,8 @@ Object Column::GetLong() const
|
|||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
Object Column::GetString() const
|
Object Column::GetString() const
|
||||||
{
|
{
|
||||||
// Validate the handle and index
|
// Validate the column and statement row
|
||||||
if (!RowAvailable())
|
ValidateRow();
|
||||||
return Object(); // Request failed
|
|
||||||
// Obtain the initial stack size
|
// Obtain the initial stack size
|
||||||
const Int32 top = sq_gettop(_SqVM);
|
const Int32 top = sq_gettop(_SqVM);
|
||||||
// Push the column text on the stack
|
// Push the column text on the stack
|
||||||
@ -138,7 +121,7 @@ Object Column::GetString() const
|
|||||||
sqlite3_column_bytes(m_Stmt, m_Index));
|
sqlite3_column_bytes(m_Stmt, m_Index));
|
||||||
// Obtain the object from the stack
|
// Obtain the object from the stack
|
||||||
Var< Object > inst(_SqVM, -1);
|
Var< Object > inst(_SqVM, -1);
|
||||||
// Remove an pushed values (if any) to restore the stack
|
// Remove any pushed values (if any) to restore the stack
|
||||||
sq_pop(_SqVM, sq_gettop(_SqVM) - top);
|
sq_pop(_SqVM, sq_gettop(_SqVM) - top);
|
||||||
// Return the long integer instance
|
// Return the long integer instance
|
||||||
return inst.value;
|
return inst.value;
|
||||||
@ -147,19 +130,17 @@ Object Column::GetString() const
|
|||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
bool Column::GetBoolean() const
|
bool Column::GetBoolean() const
|
||||||
{
|
{
|
||||||
// Validate the handle and index
|
// Validate the column and statement row
|
||||||
if (RowAvailable())
|
ValidateRow();
|
||||||
|
// Return the requested information
|
||||||
return sqlite3_column_int(m_Stmt, m_Index) > 0;
|
return sqlite3_column_int(m_Stmt, m_Index) > 0;
|
||||||
// Request failed
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
Object Column::GetBlob() const
|
Object Column::GetBlob() const
|
||||||
{
|
{
|
||||||
// Validate the handle and index
|
// Validate the column and statement row
|
||||||
if (RowAvailable())
|
ValidateRow();
|
||||||
return Object(); // Request failed
|
|
||||||
// Obtain the initial stack size
|
// Obtain the initial stack size
|
||||||
const Int32 top = sq_gettop(_SqVM);
|
const Int32 top = sq_gettop(_SqVM);
|
||||||
// Obtain the size of the data
|
// Obtain the size of the data
|
||||||
@ -170,71 +151,63 @@ 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)
|
||||||
{
|
SqThrowF("Unable to allocate space for column blob value");
|
||||||
_SqMod->SqThrow("Unable to allocate space for column blob value");
|
|
||||||
// Request failed
|
|
||||||
return Object();
|
|
||||||
}
|
|
||||||
// Is there any data to read?
|
// Is there any data to read?
|
||||||
else if (!b)
|
else if (!b)
|
||||||
{
|
{
|
||||||
// Pop the memory blob from the stack
|
// Pop the memory blob from the stack
|
||||||
sq_pop(_SqVM, sq_gettop(_SqVM) - top);
|
sq_pop(_SqVM, sq_gettop(_SqVM) - top);
|
||||||
// Now throw the error
|
// Push a null value instead
|
||||||
_SqMod->SqThrow("Unable to read data from column blob value");
|
sq_pushnull(_SqVM);
|
||||||
// Request failed
|
|
||||||
return Object();
|
|
||||||
}
|
}
|
||||||
// Copy the data into the memory blob
|
// Copy the data into the memory blob
|
||||||
else
|
else
|
||||||
memcpy(p, b, sz);
|
memcpy(p, b, sz);
|
||||||
// Obtain the object from the stack
|
// Obtain the object from the stack
|
||||||
Var< Object > inst(_SqVM, -1);
|
Var< Object > inst(_SqVM, -1);
|
||||||
// Remove an pushed values (if any) to restore the stack
|
// Remove any pushed values (if any) to restore the stack
|
||||||
sq_pop(_SqVM, sq_gettop(_SqVM) - top);
|
sq_pop(_SqVM, sq_gettop(_SqVM) - top);
|
||||||
// Return the long integer instance
|
// Return the blob instance
|
||||||
return inst.value;
|
return inst.value;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
SQChar Column::GetChar() const
|
SQChar Column::GetChar() const
|
||||||
{
|
{
|
||||||
// Validate the handle and index
|
// Validate the column and statement row
|
||||||
if (RowAvailable())
|
ValidateRow();
|
||||||
|
// Return the requested information
|
||||||
return (SQChar)sqlite3_column_int(m_Stmt, m_Index);
|
return (SQChar)sqlite3_column_int(m_Stmt, m_Index);
|
||||||
// Request failed
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
bool Column::IsNull() const
|
bool Column::IsNull() const
|
||||||
{
|
{
|
||||||
// Can we make the request?
|
// Validate the column
|
||||||
if (Validate())
|
Validate();
|
||||||
|
// Return the requested information
|
||||||
return (sqlite3_column_type(m_Stmt, m_Index) == SQLITE_NULL);
|
return (sqlite3_column_type(m_Stmt, m_Index) == SQLITE_NULL);
|
||||||
// Request failed
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
CSStr Column::GetName() const
|
CSStr Column::GetName() const
|
||||||
{
|
{
|
||||||
// Can we make the request?
|
// Validate the column
|
||||||
if (Validate())
|
Validate();
|
||||||
|
// Return the requested information
|
||||||
return sqlite3_column_name(m_Stmt, m_Index);
|
return sqlite3_column_name(m_Stmt, m_Index);
|
||||||
// Request failed
|
|
||||||
return _SC("");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
CSStr Column::GetOriginName() const
|
CSStr Column::GetOriginName() const
|
||||||
{
|
{
|
||||||
#ifdef SQLITE_ENABLE_COLUMN_METADATA
|
#ifdef SQLITE_ENABLE_COLUMN_METADATA
|
||||||
// Can we make the request?
|
// Validate the column
|
||||||
if (Validate())
|
Validate();
|
||||||
|
// Return the requested information
|
||||||
return sqlite3_column_origin_name(m_Stmt, m_Index);
|
return sqlite3_column_origin_name(m_Stmt, m_Index);
|
||||||
#else
|
#else
|
||||||
_SqMod->SqThrow("The module was compiled without this feature");
|
SqThrowF("The module was compiled without this feature");
|
||||||
#endif
|
#endif
|
||||||
// Request failed
|
// Request failed
|
||||||
return _SC("");
|
return _SC("");
|
||||||
@ -243,22 +216,19 @@ CSStr Column::GetOriginName() const
|
|||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
Int32 Column::GetType() const
|
Int32 Column::GetType() const
|
||||||
{
|
{
|
||||||
// Can we make the request?
|
// Validate the column
|
||||||
if (Validate())
|
Validate();
|
||||||
|
// Return the requested information
|
||||||
return sqlite3_column_type(m_Stmt, m_Index);
|
return sqlite3_column_type(m_Stmt, m_Index);
|
||||||
// Request failed
|
|
||||||
return -1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
Int32 Column::GetBytes() const
|
Int32 Column::GetBytes() const
|
||||||
{
|
{
|
||||||
// Can we make the request?
|
// Validate the column
|
||||||
if (Validate())
|
Validate();
|
||||||
|
// Return the requested information
|
||||||
return sqlite3_column_bytes(m_Stmt, m_Index);
|
return sqlite3_column_bytes(m_Stmt, m_Index);
|
||||||
// Request failed
|
|
||||||
return -1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
} // Namespace:: SqMod
|
} // Namespace:: SqMod
|
||||||
|
@ -27,12 +27,12 @@ private:
|
|||||||
/* --------------------------------------------------------------------------------------------
|
/* --------------------------------------------------------------------------------------------
|
||||||
* 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.
|
||||||
*/
|
*/
|
||||||
bool Validate() const;
|
void Validate() const;
|
||||||
|
|
||||||
/* --------------------------------------------------------------------------------------------
|
/* --------------------------------------------------------------------------------------------
|
||||||
* Validate the statement reference, index and row, and throw an error if they're invalid.
|
* Validate the statement reference, index and row, and throw an error if they're invalid.
|
||||||
*/
|
*/
|
||||||
bool RowAvailable() const;
|
void ValidateRow() const;
|
||||||
|
|
||||||
/* --------------------------------------------------------------------------------------------
|
/* --------------------------------------------------------------------------------------------
|
||||||
* Base constructor.
|
* Base constructor.
|
||||||
|
@ -15,6 +15,27 @@ static SQChar g_Buffer[4096]; // Common buffer to reduce memory allocations.
|
|||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
namespace SqMod {
|
namespace SqMod {
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------------------------------
|
||||||
|
SStr GetTempBuff()
|
||||||
|
{
|
||||||
|
return g_Buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------------------------------
|
||||||
|
void SqThrowF(CSStr str, ...)
|
||||||
|
{
|
||||||
|
// Initialize the argument list
|
||||||
|
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");
|
||||||
|
// Release the argument list
|
||||||
|
va_end(args);
|
||||||
|
// Throw the exception with the resulted message
|
||||||
|
throw Sqrat::Exception(g_Buffer);
|
||||||
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
CSStr FmtStr(CSStr str, ...)
|
CSStr FmtStr(CSStr str, ...)
|
||||||
{
|
{
|
||||||
@ -72,7 +93,7 @@ ConnHnd::Handle::~Handle()
|
|||||||
// 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.");
|
_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?
|
||||||
@ -91,18 +112,10 @@ 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)
|
||||||
{
|
SqThrowF("Unable to connect to database. Database already connected");
|
||||||
_SqMod->SqThrow("Unable to connect to database. Database already connected");
|
|
||||||
// Unable to proceed
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// Make sure the name is valid
|
// Make sure the name is valid
|
||||||
else if (!name || strlen(name) <= 0)
|
else if (!name || strlen(name) <= 0)
|
||||||
{
|
SqThrowF("Unable to connect to database. The name is invalid");
|
||||||
_SqMod->SqThrow("Unable to connect to database. The name is invalid");
|
|
||||||
// Unable to proceed
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// 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)
|
||||||
{
|
{
|
||||||
@ -111,9 +124,7 @@ void ConnHnd::Handle::Create(CSStr name, Int32 flags, CSStr vfs)
|
|||||||
// Explicitly make sure it's null
|
// Explicitly make sure it's null
|
||||||
mPtr = NULL;
|
mPtr = NULL;
|
||||||
// Now its safe to throw the error
|
// Now its safe to throw the error
|
||||||
_SqMod->SqThrow("Unable to connect to database [%s]", sqlite3_errstr(mStatus));
|
SqThrowF("Unable to connect to database [%s]", sqlite3_errstr(mStatus));
|
||||||
// Unable to proceed
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
// Let's save the specified information
|
// Let's save the specified information
|
||||||
mName.assign(name);
|
mName.assign(name);
|
||||||
@ -142,11 +153,7 @@ Int32 ConnHnd::Handle::Flush(Uint32 num, Object & env, Function & func)
|
|||||||
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", NULL, NULL, NULL)) != SQLITE_OK)
|
||||||
{
|
SqThrowF("Unable to begin transaction [%s]", sqlite3_errmsg(mPtr));
|
||||||
_SqMod->SqThrow("Unable to begin transaction [%s]", sqlite3_errmsg(mPtr));
|
|
||||||
// Unable to proceed
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
// Process all queries within range of selection
|
// Process all queries within range of selection
|
||||||
for (; itr != end; ++itr)
|
for (; itr != end; ++itr)
|
||||||
{
|
{
|
||||||
@ -175,10 +182,10 @@ Int32 ConnHnd::Handle::Flush(Uint32 num, Object & env, Function & func)
|
|||||||
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", NULL, NULL, NULL)) != SQLITE_OK)
|
||||||
_SqMod->SqThrow("Unable to rollback transaction [%s]", sqlite3_errmsg(mPtr));
|
SqThrowF("Unable to rollback transaction [%s]", sqlite3_errmsg(mPtr));
|
||||||
// The transaction failed somehow but we managed to rollback
|
// The transaction failed somehow but we managed to rollback
|
||||||
else
|
else
|
||||||
_SqMod->SqThrow("Unable to commit transaction because [%s]", sqlite3_errmsg(mPtr));
|
SqThrowF("Unable to commit transaction because [%s]", sqlite3_errmsg(mPtr));
|
||||||
// Operation failed
|
// Operation failed
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@ -192,7 +199,7 @@ StmtHnd::Handle::~Handle()
|
|||||||
// 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.");
|
_SqMod->LogErr("SQLite statement is still referenced (%s)", mQuery.c_str());
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Attempt to finalize the statement
|
// Attempt to finalize the statement
|
||||||
@ -206,33 +213,25 @@ 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)
|
||||||
{
|
SqThrowF("Unable to prepare statement. Statement already prepared");
|
||||||
_SqMod->SqThrow("Unable to prepare statement. Statement already prepared");
|
|
||||||
// Unable to proceed
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// Is the specified database connection is valid?
|
// Is the specified database connection is valid?
|
||||||
else if (!mConn)
|
else if (!mConn)
|
||||||
{
|
SqThrowF("Unable to prepare statement. Invalid connection handle");
|
||||||
_SqMod->SqThrow("Unable to prepare statement. Invalid connection handle");
|
|
||||||
// Unable to proceed
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// 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())
|
||||||
_SqMod->SqThrow("Unable to prepare statement. Invalid query string");
|
SqThrowF("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, NULL)) != SQLITE_OK)
|
||||||
{
|
{
|
||||||
// Clear the query string since it failed
|
// Clear the query string since it failed
|
||||||
mQuery.clear();
|
mQuery.clear();
|
||||||
// Now it's safe to throw the error
|
|
||||||
_SqMod->SqThrow("Unable to prepare statement [%s]", mConn.ErrMsg());
|
|
||||||
// Explicitly make sure the handle is null
|
// Explicitly make sure the handle is null
|
||||||
mPtr = NULL;
|
mPtr = NULL;
|
||||||
|
// Now it's safe to throw the error
|
||||||
|
SqThrowF("Unable to prepare statement [%s]", mConn.ErrMsg());
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
// Obtain the number of available columns
|
// Obtain the number of available columns
|
||||||
@ -244,7 +243,7 @@ Int32 StmtHnd::Handle::GetColumnIndex(CSStr name)
|
|||||||
{
|
{
|
||||||
// Validate the handle
|
// Validate the handle
|
||||||
if (!mPtr)
|
if (!mPtr)
|
||||||
_SqMod->SqThrow("Invalid SQLite statement");
|
SqThrowF("Invalid SQLite statement");
|
||||||
// Are the names cached?
|
// Are the names cached?
|
||||||
else if (mIndexes.empty())
|
else if (mIndexes.empty())
|
||||||
{
|
{
|
||||||
@ -254,7 +253,7 @@ 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)
|
||||||
_SqMod->SqThrow("Unable to retrieve column name for index (%d)", i);
|
SqThrowF("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;
|
||||||
@ -269,6 +268,12 @@ Int32 StmtHnd::Handle::GetColumnIndex(CSStr name)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------------------------------
|
||||||
|
CSStr GetErrStr(Int32 status)
|
||||||
|
{
|
||||||
|
return sqlite3_errstr(status);
|
||||||
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
void SetSoftHeapLimit(Int32 limit)
|
void SetSoftHeapLimit(Int32 limit)
|
||||||
{
|
{
|
||||||
@ -290,7 +295,7 @@ Object GetMemoryUsage()
|
|||||||
_SqMod->PushSLongObject(_SqVM, sqlite3_memory_used());
|
_SqMod->PushSLongObject(_SqVM, sqlite3_memory_used());
|
||||||
// Obtain the object from the stack
|
// Obtain the object from the stack
|
||||||
Var< Object > inst(_SqVM, -1);
|
Var< Object > inst(_SqVM, -1);
|
||||||
// Remove an pushed values (if any) to restore the stack
|
// Remove any pushed values (if any) to restore the stack
|
||||||
sq_pop(_SqVM, sq_gettop(_SqVM) - top);
|
sq_pop(_SqVM, sq_gettop(_SqVM) - top);
|
||||||
// Return the long integer instance
|
// Return the long integer instance
|
||||||
return inst.value;
|
return inst.value;
|
||||||
@ -305,7 +310,7 @@ Object GetMemoryHighwaterMark(bool reset)
|
|||||||
_SqMod->PushSLongObject(_SqVM, sqlite3_memory_highwater(reset));
|
_SqMod->PushSLongObject(_SqVM, sqlite3_memory_highwater(reset));
|
||||||
// Obtain the object from the stack
|
// Obtain the object from the stack
|
||||||
Var< Object > inst(_SqVM, -1);
|
Var< Object > inst(_SqVM, -1);
|
||||||
// Remove an pushed values (if any) to restore the stack
|
// Remove any pushed values (if any) to restore the stack
|
||||||
sq_pop(_SqVM, sq_gettop(_SqVM) - top);
|
sq_pop(_SqVM, sq_gettop(_SqVM) - top);
|
||||||
// Return the long integer instance
|
// Return the long integer instance
|
||||||
return inst.value;
|
return inst.value;
|
||||||
@ -331,7 +336,7 @@ CCStr EscapeStringEx(SQChar spec, CCStr str)
|
|||||||
// 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')
|
||||||
{
|
{
|
||||||
_SqMod->SqThrow("Unknown format specifier: %c", spec);
|
SqThrowF("Unknown format specifier: %c", spec);
|
||||||
// Default to empty string
|
// Default to empty string
|
||||||
return _SC("");
|
return _SC("");
|
||||||
}
|
}
|
||||||
@ -367,11 +372,7 @@ CCStr ArrayToQueryColumns(Array & arr)
|
|||||||
{
|
{
|
||||||
// Is the name valid?
|
// Is the name valid?
|
||||||
if (itr->empty())
|
if (itr->empty())
|
||||||
{
|
SqThrowF("Invalid column name");
|
||||||
_SqMod->SqThrow("Invalid column name");
|
|
||||||
// Default to empty string
|
|
||||||
return _SC("");
|
|
||||||
}
|
|
||||||
// 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
|
||||||
@ -403,11 +404,7 @@ 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())
|
||||||
{
|
SqThrowF("Invalid column name");
|
||||||
_SqMod->SqThrow("Invalid column name");
|
|
||||||
// Default to empty string
|
|
||||||
return _SC("");
|
|
||||||
}
|
|
||||||
// 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
|
||||||
|
@ -38,6 +38,16 @@ class Transaction;
|
|||||||
#define SQSQLITE_VERSION_MINOR 0
|
#define SQSQLITE_VERSION_MINOR 0
|
||||||
#define SQSQLITE_VERSION_PATCH 1
|
#define SQSQLITE_VERSION_PATCH 1
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------------------------------------------
|
||||||
|
* Retrieve the temporary buffer.
|
||||||
|
*/
|
||||||
|
SStr GetTempBuff();
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------------------------------------------
|
||||||
|
* Throw a formatted exception.
|
||||||
|
*/
|
||||||
|
void SqThrowF(CSStr str, ...);
|
||||||
|
|
||||||
/* ------------------------------------------------------------------------------------------------
|
/* ------------------------------------------------------------------------------------------------
|
||||||
* Generate a formatted string.
|
* Generate a formatted string.
|
||||||
*/
|
*/
|
||||||
@ -726,42 +736,47 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
/* ------------------------------------------------------------------------------------------------
|
/* ------------------------------------------------------------------------------------------------
|
||||||
*
|
* Retrieve the string representation of a certain status code.
|
||||||
|
*/
|
||||||
|
CSStr GetErrStr(Int32 status);
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------------------------------------------
|
||||||
|
* Set a specific heap limit.
|
||||||
*/
|
*/
|
||||||
void SetSoftHeapLimit(Int32 limit);
|
void SetSoftHeapLimit(Int32 limit);
|
||||||
|
|
||||||
/* ------------------------------------------------------------------------------------------------
|
/* ------------------------------------------------------------------------------------------------
|
||||||
*
|
* Release the specified amount of memory.
|
||||||
*/
|
*/
|
||||||
Int32 ReleaseMemory(Int32 bytes);
|
Int32 ReleaseMemory(Int32 bytes);
|
||||||
|
|
||||||
/* ------------------------------------------------------------------------------------------------
|
/* ------------------------------------------------------------------------------------------------
|
||||||
*
|
* Retrieve the current memory usage.
|
||||||
*/
|
*/
|
||||||
Object GetMemoryUsage();
|
Object GetMemoryUsage();
|
||||||
|
|
||||||
/* ------------------------------------------------------------------------------------------------
|
/* ------------------------------------------------------------------------------------------------
|
||||||
*
|
* Retrieve the memory high watermark.
|
||||||
*/
|
*/
|
||||||
Object GetMemoryHighwaterMark(bool reset);
|
Object GetMemoryHighwaterMark(bool reset);
|
||||||
|
|
||||||
/* ------------------------------------------------------------------------------------------------
|
/* ------------------------------------------------------------------------------------------------
|
||||||
*
|
* Retrieve the escaped version of the specified string.
|
||||||
*/
|
*/
|
||||||
CSStr EscapeString(CSStr str);
|
CSStr EscapeString(CSStr str);
|
||||||
|
|
||||||
/* ------------------------------------------------------------------------------------------------
|
/* ------------------------------------------------------------------------------------------------
|
||||||
*
|
* Retrieve the escaped version of the specified string using the supplied format specifier.
|
||||||
*/
|
*/
|
||||||
CCStr EscapeStringEx(SQChar spec, CCStr str);
|
CCStr EscapeStringEx(SQChar spec, CCStr str);
|
||||||
|
|
||||||
/* ------------------------------------------------------------------------------------------------
|
/* ------------------------------------------------------------------------------------------------
|
||||||
*
|
* Convert the values from the specified array to a list of column names string.
|
||||||
*/
|
*/
|
||||||
CCStr ArrayToQueryColumns(Array & arr);
|
CCStr ArrayToQueryColumns(Array & arr);
|
||||||
|
|
||||||
/* ------------------------------------------------------------------------------------------------
|
/* ------------------------------------------------------------------------------------------------
|
||||||
*
|
* Convert the keys from the specified array to a list of column names string.
|
||||||
*/
|
*/
|
||||||
CCStr TableToQueryColumns(Table & tbl);
|
CCStr TableToQueryColumns(Table & tbl);
|
||||||
|
|
||||||
|
@ -18,13 +18,11 @@ SQInteger Connection::Typename(HSQUIRRELVM vm)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
bool Connection::Validate() const
|
void Connection::Validate() const
|
||||||
{
|
{
|
||||||
if (m_Handle)
|
// Is the handle valid?
|
||||||
return true;
|
if (!m_Handle)
|
||||||
// Invalid connection reference
|
SqThrowF("Invalid SQLite connection reference");
|
||||||
_SqMod->SqThrow("Invalid SQLite connection reference");
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
@ -40,12 +38,6 @@ Connection::Connection(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, NULL);
|
||||||
// Because Sqrat is majorly stupid and clears the error message
|
|
||||||
// then does an assert on debug builds thinking the type wasn't registered
|
|
||||||
// or throws a generic "unknown error" message on release builds
|
|
||||||
// we have to use this approach
|
|
||||||
if (Sqrat::Error::Occurred(_SqVM))
|
|
||||||
_SqMod->LogErr("%s", Sqrat::Error::Message(_SqVM).c_str());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
@ -54,12 +46,6 @@ Connection::Connection(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, NULL);
|
||||||
// Because Sqrat is majorly stupid and clears the error message
|
|
||||||
// then does an assert on debug builds thinking the type wasn't registered
|
|
||||||
// or throws a generic "unknown error" message on release builds
|
|
||||||
// we have to use this approach
|
|
||||||
if (Sqrat::Error::Occurred(_SqVM))
|
|
||||||
_SqMod->LogErr("%s", Sqrat::Error::Message(_SqVM).c_str());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
@ -68,48 +54,38 @@ Connection::Connection(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);
|
||||||
// Because Sqrat is majorly stupid and clears the error message
|
|
||||||
// then does an assert on debug builds thinking the type wasn't registered
|
|
||||||
// or throws a generic "unknown error" message on release builds
|
|
||||||
// we have to use this approach
|
|
||||||
if (Sqrat::Error::Occurred(_SqVM))
|
|
||||||
_SqMod->LogErr("%s", Sqrat::Error::Message(_SqVM).c_str());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
Int32 Connection::Exec(CSStr str)
|
Int32 Connection::Exec(CSStr str)
|
||||||
{
|
{
|
||||||
// Validate the handle
|
// Validate the handle
|
||||||
if (Validate() && (m_Handle = sqlite3_exec(m_Handle, str, NULL, NULL, NULL)) != SQLITE_OK)
|
Validate();
|
||||||
_SqMod->SqThrow("Unable to execute query [%s]", m_Handle.ErrMsg());
|
// Attempt to execute the specified query
|
||||||
|
if ((m_Handle = sqlite3_exec(m_Handle, str, NULL, NULL, NULL)) != SQLITE_OK)
|
||||||
|
SqThrowF("Unable to execute query [%s]", m_Handle.ErrMsg());
|
||||||
// Return rows affected by this query
|
// Return rows affected by this query
|
||||||
else
|
|
||||||
return sqlite3_changes(m_Handle);
|
return sqlite3_changes(m_Handle);
|
||||||
// Operation failed
|
|
||||||
return -1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
Object Connection::Query(CSStr str) const
|
Object Connection::Query(CSStr str) const
|
||||||
{
|
{
|
||||||
// Validate the handle
|
// Validate the handle
|
||||||
if (Validate())
|
Validate();
|
||||||
|
// Return the requested information
|
||||||
return Object(new Statement(m_Handle, str));
|
return Object(new Statement(m_Handle, str));
|
||||||
// Request failed
|
|
||||||
return Object(new Statement());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
void Connection::Queue(CSStr str)
|
void Connection::Queue(CSStr str)
|
||||||
{
|
{
|
||||||
// Validate the handle
|
// Validate the handle
|
||||||
if (!Validate())
|
Validate();
|
||||||
return; // Nothing to commit
|
|
||||||
// Is there a query to commit?
|
// Is there a query to commit?
|
||||||
else if (IsQueryEmpty(str))
|
if (IsQueryEmpty(str))
|
||||||
_SqMod->SqThrow("No query to queue");
|
SqThrowF("No query string to queue");
|
||||||
// Add the specified string to the queue
|
// Add the specified string to the queue
|
||||||
else
|
|
||||||
m_Handle->mQueue.push_back(str);
|
m_Handle->mQueue.push_back(str);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -117,26 +93,21 @@ void Connection::Queue(CSStr str)
|
|||||||
bool Connection::IsReadOnly() const
|
bool Connection::IsReadOnly() const
|
||||||
{
|
{
|
||||||
// Validate the handle
|
// Validate the handle
|
||||||
if (!Validate())
|
Validate();
|
||||||
return false;
|
|
||||||
// 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)
|
||||||
_SqMod->SqThrow("'main' is not the name of a database on connection");
|
SqThrowF("'main' is not the name of a database on connection");
|
||||||
// Return the result
|
// Return the requested information
|
||||||
else
|
|
||||||
return (result != 1);
|
return (result != 1);
|
||||||
// Inexistent is same as read-only
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
bool Connection::TableExists(CCStr name) const
|
bool Connection::TableExists(CCStr name) const
|
||||||
{
|
{
|
||||||
// Validate the handle
|
// Validate the handle
|
||||||
if (!Validate())
|
Validate();
|
||||||
return false;
|
|
||||||
// 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?
|
||||||
@ -156,8 +127,7 @@ bool Connection::TableExists(CCStr name) const
|
|||||||
Object Connection::GetLastInsertRowID() const
|
Object Connection::GetLastInsertRowID() const
|
||||||
{
|
{
|
||||||
// Validate the handle
|
// Validate the handle
|
||||||
if (!Validate())
|
Validate();
|
||||||
return Object();
|
|
||||||
// Obtain the initial stack size
|
// Obtain the initial stack size
|
||||||
const Int32 top = sq_gettop(_SqVM);
|
const Int32 top = sq_gettop(_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
|
||||||
@ -173,127 +143,108 @@ Object Connection::GetLastInsertRowID() const
|
|||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
void Connection::SetBusyTimeout(Int32 millis)
|
void Connection::SetBusyTimeout(Int32 millis)
|
||||||
{
|
{
|
||||||
// Validate the handle and apply requested timeout
|
// Validate the handle
|
||||||
if (Validate() && ((m_Handle = sqlite3_busy_timeout(m_Handle, millis)) != SQLITE_OK))
|
Validate();
|
||||||
_SqMod->SqThrow("Unable to set busy timeout [%s]", m_Handle.ErrMsg());
|
// Apply requested timeout
|
||||||
|
if ((m_Handle = sqlite3_busy_timeout(m_Handle, millis)) != SQLITE_OK)
|
||||||
|
SqThrowF("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
|
||||||
if (!Validate())
|
Validate();
|
||||||
return -1;
|
|
||||||
// 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)
|
||||||
_SqMod->SqThrow("Unable to get runtime status information", m_Handle.ErrMsg());
|
SqThrowF("Unable to get runtime status information", m_Handle.ErrMsg());
|
||||||
// Return what was requested
|
// Return the high-water value if requested
|
||||||
else if (highwater)
|
else if (highwater)
|
||||||
return hiwtr_value;
|
return hiwtr_value;
|
||||||
else
|
// Return the requested information
|
||||||
return cur_value;
|
return cur_value;
|
||||||
// Request failed
|
|
||||||
return -1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
Connection Connection::CopyToMemory()
|
Connection Connection::CopyToMemory()
|
||||||
{
|
{
|
||||||
// Validate the handle
|
// Validate the handle
|
||||||
if (!Validate())
|
Validate();
|
||||||
return Connection();
|
|
||||||
// Is the database already in memory?
|
// Is the database already in memory?
|
||||||
else if (m_Handle->mMemory)
|
if (m_Handle->mMemory)
|
||||||
{
|
SqThrowF("The database is already in memory");
|
||||||
_SqMod->SqThrow("The database is already in memory");
|
|
||||||
// No reason to move it again
|
|
||||||
return Connection();
|
|
||||||
}
|
|
||||||
// Destination database
|
// Destination database
|
||||||
ConnHnd db(_SC(""));
|
ConnHnd db(_SC(""));
|
||||||
// Attempt to open an in-memory database
|
// Attempt to open the in-memory database
|
||||||
db->Create(_SC(":memory:"), SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, NULL);
|
db->Create(_SC(":memory:"), SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, NULL);
|
||||||
// See if the database could be opened
|
// Clear the temporary buffer
|
||||||
if (!db)
|
GetTempBuff()[0] = 0;
|
||||||
// The creation process already generated the error
|
|
||||||
return Connection();
|
|
||||||
// Clear any previous error (there shouldn't be any but just in case)
|
|
||||||
Sqrat::Error::Clear(_SqVM);
|
|
||||||
// Begin a transaction to replicate the schema of origin database
|
// Begin a transaction to replicate the schema of origin database
|
||||||
if ((m_Handle = sqlite3_exec(m_Handle, "BEGIN", NULL, NULL, NULL)) != SQLITE_OK)
|
if ((m_Handle = sqlite3_exec(m_Handle, "BEGIN", NULL, NULL, NULL)) != SQLITE_OK)
|
||||||
_SqMod->SqThrow("Unable to begin schema replication [%s]", m_Handle.ErrMsg());
|
SqThrowF("Unable to begin schema replication [%s]", m_Handle.ErrMsg());
|
||||||
// Attempt to replicate the schema of origin database to the in-memory one
|
// Attempt to replicate the schema of origin database to the in-memory one
|
||||||
else if ((m_Handle = sqlite3_exec(m_Handle,
|
else if ((m_Handle = sqlite3_exec(m_Handle,
|
||||||
"SELECT [sql] FROM [sqlite_master] WHERE [sql] NOT NULL AND [tbl_name] != 'sqlite_sequence'",
|
"SELECT [sql] FROM [sqlite_master] WHERE [sql] NOT NULL AND [tbl_name] != 'sqlite_sequence'",
|
||||||
&Connection::ProcessDDLRow, db->mPtr, NULL)) != SQLITE_OK)
|
&Connection::ProcessDDLRow, db->mPtr, NULL)) != SQLITE_OK)
|
||||||
{
|
{
|
||||||
// Did the error occurred from the DDL process function?
|
// Did the error occurred from the DDL process function?
|
||||||
if (Sqrat::Error::Occurred(_SqVM))
|
if (GetTempBuff()[0] != 0)
|
||||||
{
|
|
||||||
// Obtain the occurred message
|
|
||||||
String msg(Sqrat::Error::Message(_SqVM));
|
|
||||||
// Throw the resulted message but also include the point where it failed
|
// Throw the resulted message but also include the point where it failed
|
||||||
_SqMod->SqThrow("Unable to replicate schema [%s]", msg.c_str());
|
SqThrowF("Unable to replicate schema [%s]", GetTempBuff());
|
||||||
}
|
|
||||||
// Obtain the message from the connection handle if possible
|
// Obtain the message from the connection handle if possible
|
||||||
else
|
else
|
||||||
_SqMod->SqThrow("Unable to replicate schema [%s]", m_Handle.ErrMsg());
|
SqThrowF("Unable to replicate schema [%s]", m_Handle.ErrMsg());
|
||||||
}
|
}
|
||||||
// Attempt to commit the changes to the database schema replication
|
// Attempt to commit the changes to the database schema replication
|
||||||
else if ((m_Handle = sqlite3_exec(m_Handle, "COMMIT", NULL, NULL, NULL)) != SQLITE_OK)
|
else if ((m_Handle = sqlite3_exec(m_Handle, "COMMIT", NULL, NULL, NULL)) != SQLITE_OK)
|
||||||
_SqMod->SqThrow("Unable to commit schema replication [%s]", m_Handle.ErrMsg());
|
SqThrowF("Unable to commit schema replication [%s]", m_Handle.ErrMsg());
|
||||||
// Attempt to attach the origin database to the in-memory one
|
// Attempt to attach the origin database to the in-memory one
|
||||||
else if ((db = sqlite3_exec(db, QFmtStr("ATTACH DATABASE '%q' as origin", m_Handle->mName.c_str()),
|
else if ((db = sqlite3_exec(db, QFmtStr("ATTACH DATABASE '%q' as origin", m_Handle->mName.c_str()),
|
||||||
NULL, NULL, NULL)) != SQLITE_OK)
|
NULL, NULL, NULL)) != SQLITE_OK)
|
||||||
_SqMod->SqThrow("Unable to attach origin [%s]", db.ErrMsg());
|
SqThrowF("Unable to attach origin [%s]", db.ErrMsg());
|
||||||
// Begin a transaction to replicate the data of origin database
|
// Begin a transaction to replicate the data of origin database
|
||||||
else if ((db = sqlite3_exec(db, "BEGIN", NULL, NULL, NULL) != SQLITE_OK))
|
else if ((db = sqlite3_exec(db, "BEGIN", NULL, NULL, NULL) != SQLITE_OK))
|
||||||
_SqMod->SqThrow("Unable to begin data replication [%s]", db.ErrMsg());
|
SqThrowF("Unable to begin data replication [%s]", db.ErrMsg());
|
||||||
// Attempt to replicate the data of origin database to the in-memory one
|
// Attempt to replicate the data of origin database to the in-memory one
|
||||||
else if ((db = sqlite3_exec(db, "SELECT [name] FROM [origin.sqlite_master] WHERE [type]='table'",
|
else if ((db = sqlite3_exec(db, "SELECT [name] FROM [origin.sqlite_master] WHERE [type]='table'",
|
||||||
&Connection::ProcessDMLRow, db->mPtr, NULL)) != SQLITE_OK)
|
&Connection::ProcessDMLRow, db->mPtr, NULL)) != SQLITE_OK)
|
||||||
{
|
{
|
||||||
// Did the error occurred from the DML process function?
|
// Did the error occurred from the DML process function?
|
||||||
if (Sqrat::Error::Occurred(_SqVM))
|
if (GetTempBuff()[0] != 0)
|
||||||
{
|
{
|
||||||
// Obtain the occurred message
|
|
||||||
String msg(Sqrat::Error::Message(_SqVM));
|
|
||||||
// Throw the resulted message but also include the point where it failed
|
// Throw the resulted message but also include the point where it failed
|
||||||
_SqMod->SqThrow("Unable to replicate data [%s]", msg.c_str());
|
SqThrowF("Unable to replicate data [%s]", GetTempBuff());
|
||||||
}
|
}
|
||||||
// Obtain the message from the connection handle if possible
|
// Obtain the message from the connection handle if possible
|
||||||
else
|
else
|
||||||
_SqMod->SqThrow("Unable to replicate data [%s]", db.ErrMsg());
|
SqThrowF("Unable to replicate data [%s]", db.ErrMsg());
|
||||||
}
|
}
|
||||||
// Attempt to commit the changes to the database data replication
|
// Attempt to commit the changes to the database data replication
|
||||||
else if ((db = sqlite3_exec(db, "COMMIT", NULL, NULL, NULL)) != SQLITE_OK)
|
else if ((db = sqlite3_exec(db, "COMMIT", NULL, NULL, NULL)) != SQLITE_OK)
|
||||||
{
|
{
|
||||||
_SqMod->SqThrow("Unable to commit data replication [%s]", db.ErrMsg());
|
|
||||||
// Attempt to rollback changes from the data copy operation
|
// Attempt to rollback changes from the data copy operation
|
||||||
if ((db = sqlite3_exec(db, "ROLLBACK", NULL, NULL, NULL)) != SQLITE_OK)
|
if ((db = sqlite3_exec(db, "ROLLBACK", NULL, NULL, NULL)) != SQLITE_OK)
|
||||||
_SqMod->SqThrow("Unable to rollback data replication [%s]", db.ErrMsg());
|
SqThrowF("Unable to rollback data replication [%s]", db.ErrMsg());
|
||||||
// Attempt to detach the disk origin from in-memory database
|
// Attempt to detach the disk origin from in-memory database
|
||||||
else if ((db = sqlite3_exec(db, "DETACH DATABASE origin", NULL, NULL, NULL)) != SQLITE_OK)
|
else if ((db = sqlite3_exec(db, "DETACH DATABASE origin", NULL, NULL, NULL)) != SQLITE_OK)
|
||||||
_SqMod->SqThrow("Unable to detach origin [%s]", db.ErrMsg());
|
SqThrowF("Unable to detach origin [%s]", db.ErrMsg());
|
||||||
|
// Operation failed
|
||||||
|
SqThrowF("Unable to commit data replication [%s]", db.ErrMsg());
|
||||||
}
|
}
|
||||||
// At this point everything went fine and the database instance should be returned
|
// At this point everything went fine and the database instance should be returned
|
||||||
else
|
|
||||||
return Connection(db);
|
return Connection(db);
|
||||||
// Failed to replicate the database
|
|
||||||
return Connection();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
void Connection::CopyToDatabase(Connection & db)
|
void Connection::CopyToDatabase(const Connection & db)
|
||||||
{
|
{
|
||||||
// Make sure that we have two valid database handles
|
// Make sure that we have two valid database handles
|
||||||
if (Validate() && db.Validate())
|
Validate();
|
||||||
_SqMod->SqThrow("Invalid database connections");
|
db.Validate();
|
||||||
// Attempt to take the snapshot and return the result
|
// Attempt to take the snapshot and return the result
|
||||||
else
|
|
||||||
TakeSnapshot(db.m_Handle);
|
TakeSnapshot(db.m_Handle);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -301,27 +252,21 @@ void Connection::CopyToDatabase(Connection & db)
|
|||||||
Int32 Connection::Flush(Uint32 num)
|
Int32 Connection::Flush(Uint32 num)
|
||||||
{
|
{
|
||||||
// Validate the handle
|
// Validate the handle
|
||||||
if (Validate())
|
Validate();
|
||||||
{
|
|
||||||
// We need to supply a null callback
|
// We need to supply a null callback
|
||||||
Object env;
|
Object env;
|
||||||
Function func;
|
Function func;
|
||||||
// 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);
|
||||||
}
|
}
|
||||||
// Request failed
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
Int32 Connection::Flush(Uint32 num, Object & env, Function & func)
|
Int32 Connection::Flush(Uint32 num, Object & env, Function & func)
|
||||||
{
|
{
|
||||||
// Validate the handle
|
// Validate the handle
|
||||||
if (Validate())
|
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);
|
||||||
// Request failed
|
|
||||||
return -1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
@ -340,10 +285,10 @@ int Connection::ProcessDDLRow(void * db, int columns_count, char ** values, char
|
|||||||
{
|
{
|
||||||
// Make sure that exactly one column exists in the result
|
// Make sure that exactly one column exists in the result
|
||||||
if (columns_count != 1)
|
if (columns_count != 1)
|
||||||
_SqMod->SqThrow("Error occurred during DDL: columns != 1");
|
FmtStr("Error occurred during DDL: columns != 1");
|
||||||
// Execute the sql statement in values[0] in the received database connection
|
// Execute the sql statement in values[0] in the received database connection
|
||||||
else if (sqlite3_exec((sqlite3 *)db, values[0], NULL, NULL, NULL) != SQLITE_OK)
|
else if (sqlite3_exec((sqlite3 *)db, values[0], NULL, NULL, NULL) != SQLITE_OK)
|
||||||
_SqMod->SqThrow("Error occurred during DDL execution: %s", sqlite3_errmsg((sqlite3 *)db));
|
FmtStr("Error occurred during DDL execution: %s", sqlite3_errmsg((sqlite3 *)db));
|
||||||
else
|
else
|
||||||
// Continue processing
|
// Continue processing
|
||||||
return 0;
|
return 0;
|
||||||
@ -356,7 +301,7 @@ int Connection::ProcessDMLRow(void * db, int columns_count, char ** values, char
|
|||||||
// Make sure that exactly one column exists in the result
|
// Make sure that exactly one column exists in the result
|
||||||
if (columns_count != 1)
|
if (columns_count != 1)
|
||||||
{
|
{
|
||||||
_SqMod->SqThrow("Error occurred during DML: columns != 1");
|
FmtStr("Error occurred during DML: columns != 1");
|
||||||
// Operation aborted
|
// Operation aborted
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@ -364,7 +309,7 @@ int Connection::ProcessDMLRow(void * db, int columns_count, char ** values, char
|
|||||||
char * sql = sqlite3_mprintf("INSERT INTO main.%q SELECT * FROM origin.%q", values[0], values[0]);
|
char * sql = sqlite3_mprintf("INSERT INTO main.%q SELECT * FROM origin.%q", values[0], values[0]);
|
||||||
// Attempt to execute the generated query string on the received database connection
|
// Attempt to execute the generated query string on the received database connection
|
||||||
if (sqlite3_exec((sqlite3 *)db, sql, NULL, NULL, NULL) != SQLITE_OK)
|
if (sqlite3_exec((sqlite3 *)db, sql, NULL, NULL, NULL) != SQLITE_OK)
|
||||||
_SqMod->SqThrow("Error occurred during DML execution: %s", sqlite3_errmsg((sqlite3 *)db));
|
FmtStr("Error occurred during DML execution: %s", sqlite3_errmsg((sqlite3 *)db));
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Free the generated query string
|
// Free the generated query string
|
||||||
@ -379,19 +324,24 @@ int Connection::ProcessDMLRow(void * db, int columns_count, char ** values, char
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
void Connection::TakeSnapshot(ConnHnd & destination)
|
void Connection::TakeSnapshot(const ConnHnd & destination)
|
||||||
{
|
{
|
||||||
// Attempt to initialize a backup structure
|
// Attempt to initialize a backup structure
|
||||||
sqlite3_backup * backup = sqlite3_backup_init(destination, "main", m_Handle, "main");
|
sqlite3_backup * backup = sqlite3_backup_init(destination, "main", m_Handle, "main");
|
||||||
// See if the backup structure could be created
|
// See if the backup structure could be created
|
||||||
if (!backup)
|
if (!backup)
|
||||||
_SqMod->SqThrow("Unable to initialize the backup structure [%s]", destination.ErrMsg());
|
SqThrowF("Unable to initialize the backup structure [%s]", destination.ErrMsg());
|
||||||
// -1 to copy the entire source database to the destination
|
// -1 to copy the entire source database to the destination
|
||||||
else if ((m_Handle = sqlite3_backup_step(backup, -1)) != SQLITE_DONE)
|
if ((m_Handle = sqlite3_backup_step(backup, -1)) != SQLITE_DONE)
|
||||||
_SqMod->SqThrow("Unable to copy source [%s]", m_Handle.ErrStr());
|
{
|
||||||
|
// Finalize the backup structure first
|
||||||
|
sqlite3_backup_finish(backup);
|
||||||
|
// Now it's safe to throw the error
|
||||||
|
SqThrowF("Unable to copy source [%s]", m_Handle.ErrStr());
|
||||||
|
}
|
||||||
// Clean up resources allocated by sqlite3_backup_init()
|
// Clean up resources allocated by sqlite3_backup_init()
|
||||||
if ((m_Handle = sqlite3_backup_finish(backup)) != SQLITE_OK)
|
if ((m_Handle = sqlite3_backup_finish(backup)) != SQLITE_OK)
|
||||||
_SqMod->SqThrow("Unable to finalize backup [%s]", m_Handle.ErrStr());
|
SqThrowF("Unable to finalize backup [%s]", m_Handle.ErrStr());
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
@ -421,16 +371,16 @@ SQInteger Connection::ExecF(HSQUIRRELVM vm)
|
|||||||
// Now we can throw the error message
|
// Now we can throw the error message
|
||||||
return sq_throwerror(vm, "Unable to retrieve the query");
|
return sq_throwerror(vm, "Unable to retrieve the query");
|
||||||
}
|
}
|
||||||
|
// Prevent the object from being destroyed once we pop it
|
||||||
|
Var< Object > obj(vm, -1);
|
||||||
|
// If the value was converted to a string then pop the string
|
||||||
|
sq_pop(vm, sq_gettop(vm) - top);
|
||||||
// Attempt to execute the specified query
|
// Attempt to execute the specified query
|
||||||
if ((inst.value->m_Handle = sqlite3_exec(inst.value->m_Handle, sql, NULL, NULL, NULL)) != SQLITE_OK)
|
if ((inst.value->m_Handle = sqlite3_exec(inst.value->m_Handle, sql, NULL, NULL, NULL)) != SQLITE_OK)
|
||||||
{
|
{
|
||||||
// If the value was converted to a string then pop the string
|
|
||||||
sq_pop(vm, sq_gettop(vm) - top);
|
|
||||||
// Generate the error message and throw the resulted string
|
// Generate the error message and throw the resulted string
|
||||||
return sq_throwerror(vm, FmtStr("Unable to execute query [%s]", inst.value->m_Handle.ErrMsg()));
|
return sq_throwerror(vm, FmtStr("Unable to execute query [%s]", inst.value->m_Handle.ErrMsg()));
|
||||||
}
|
}
|
||||||
// If the value was converted to a string then pop the string
|
|
||||||
sq_pop(vm, sq_gettop(vm) - top);
|
|
||||||
// Push the result onto the stack
|
// Push the result onto the stack
|
||||||
sq_pushinteger(vm, sqlite3_changes(inst.value->m_Handle));
|
sq_pushinteger(vm, sqlite3_changes(inst.value->m_Handle));
|
||||||
}
|
}
|
||||||
@ -492,6 +442,7 @@ SQInteger Connection::QueueF(HSQUIRRELVM vm)
|
|||||||
{
|
{
|
||||||
// If the value was converted to a string then pop the string
|
// If the value was converted to a string then pop the string
|
||||||
sq_pop(vm, sq_gettop(vm) - top);
|
sq_pop(vm, sq_gettop(vm) - top);
|
||||||
|
// Now we can throw the error message
|
||||||
return sq_throwerror(vm,"No query to queue");
|
return sq_throwerror(vm,"No query to queue");
|
||||||
}
|
}
|
||||||
// Attempt to queue the specified query
|
// Attempt to queue the specified query
|
||||||
@ -549,17 +500,18 @@ SQInteger Connection::QueryF(HSQUIRRELVM vm)
|
|||||||
// Now we can throw the error message
|
// Now we can throw the error message
|
||||||
return sq_throwerror(vm, "Unable to retrieve the query");
|
return sq_throwerror(vm, "Unable to retrieve the query");
|
||||||
}
|
}
|
||||||
// Attempt to create a statement with the specified query
|
// Prevent the object from being destroyed once we pop it
|
||||||
ClassType< Statement >::PushInstance(vm, new Statement(inst.value->m_Handle, sql));
|
Var< Object > obj(vm, -1);
|
||||||
// If the value was converted to a string then pop the string
|
// If the value was converted to a string then pop the string
|
||||||
sq_pop(vm, sq_gettop(vm) - top);
|
sq_pop(vm, sq_gettop(vm) - top);
|
||||||
// See if any errors occured
|
// Attempt to create a statement with the specified query
|
||||||
if (Sqrat::Error::Occurred(vm))
|
try
|
||||||
{
|
{
|
||||||
// Obtain the error message from sqrat
|
ClassType< Statement >::PushInstance(vm, new Statement(inst.value->m_Handle, sql));
|
||||||
String msg = Sqrat::Error::Message(vm);
|
}
|
||||||
// Throw the error message further down the line
|
catch (const Sqrat::Exception & e)
|
||||||
return sq_throwerror(vm, msg.c_str());
|
{
|
||||||
|
return sq_throwerror(vm, e.Message().c_str());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Do we have enough values to call the format function?
|
// Do we have enough values to call the format function?
|
||||||
@ -573,14 +525,13 @@ SQInteger Connection::QueryF(HSQUIRRELVM vm)
|
|||||||
if (SQ_FAILED(ret))
|
if (SQ_FAILED(ret))
|
||||||
return ret;
|
return ret;
|
||||||
// Attempt to create a statement with the specified query
|
// Attempt to create a statement with the specified query
|
||||||
ClassType< Statement >::PushInstance(vm, new Statement(inst.value->m_Handle, sql));
|
try
|
||||||
// See if any errors occured
|
|
||||||
if (Sqrat::Error::Occurred(vm))
|
|
||||||
{
|
{
|
||||||
// Obtain the error message from sqrat
|
ClassType< Statement >::PushInstance(vm, new Statement(inst.value->m_Handle, sql));
|
||||||
String msg = Sqrat::Error::Message(vm);
|
}
|
||||||
// Throw the error message further down the line
|
catch (const Sqrat::Exception & e)
|
||||||
return sq_throwerror(vm, msg.c_str());
|
{
|
||||||
|
return sq_throwerror(vm, e.Message().c_str());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// All methods of retrieving the message value failed
|
// All methods of retrieving the message value failed
|
||||||
|
@ -23,7 +23,7 @@ protected:
|
|||||||
/* --------------------------------------------------------------------------------------------
|
/* --------------------------------------------------------------------------------------------
|
||||||
* Validate the document reference and throw an error if invalid.
|
* Validate the document reference and throw an error if invalid.
|
||||||
*/
|
*/
|
||||||
bool Validate() const;
|
void Validate() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
@ -138,10 +138,9 @@ public:
|
|||||||
CSStr ToString() const
|
CSStr ToString() const
|
||||||
{
|
{
|
||||||
// Validate the handle
|
// Validate the handle
|
||||||
if (Validate())
|
Validate();
|
||||||
|
// Return the requested information
|
||||||
return m_Handle->mName.c_str();
|
return m_Handle->mName.c_str();
|
||||||
// Request failed
|
|
||||||
return _SC("");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* --------------------------------------------------------------------------------------------
|
/* --------------------------------------------------------------------------------------------
|
||||||
@ -187,10 +186,9 @@ public:
|
|||||||
Int32 GetStatus() const
|
Int32 GetStatus() const
|
||||||
{
|
{
|
||||||
// Validate the handle
|
// Validate the handle
|
||||||
if (Validate())
|
Validate();
|
||||||
|
// Return the requested information
|
||||||
return m_Handle->mStatus;
|
return m_Handle->mStatus;
|
||||||
// Request failed
|
|
||||||
return -1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* --------------------------------------------------------------------------------------------
|
/* --------------------------------------------------------------------------------------------
|
||||||
@ -199,10 +197,9 @@ public:
|
|||||||
Int32 GetFlags() const
|
Int32 GetFlags() const
|
||||||
{
|
{
|
||||||
// Validate the handle
|
// Validate the handle
|
||||||
if (Validate())
|
Validate();
|
||||||
|
// Return the requested information
|
||||||
return m_Handle->mFlags;
|
return m_Handle->mFlags;
|
||||||
// Request failed
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* --------------------------------------------------------------------------------------------
|
/* --------------------------------------------------------------------------------------------
|
||||||
@ -211,10 +208,9 @@ public:
|
|||||||
CSStr GetName() const
|
CSStr GetName() const
|
||||||
{
|
{
|
||||||
// Validate the handle
|
// Validate the handle
|
||||||
if (Validate())
|
Validate();
|
||||||
|
// Return the requested information
|
||||||
return m_Handle->mName.c_str();
|
return m_Handle->mName.c_str();
|
||||||
// Request failed
|
|
||||||
return _SC("");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* --------------------------------------------------------------------------------------------
|
/* --------------------------------------------------------------------------------------------
|
||||||
@ -223,10 +219,9 @@ public:
|
|||||||
CSStr GetVFS() const
|
CSStr GetVFS() const
|
||||||
{
|
{
|
||||||
// Validate the handle
|
// Validate the handle
|
||||||
if (Validate())
|
Validate();
|
||||||
|
// Return the requested information
|
||||||
return m_Handle->mVFS.c_str();
|
return m_Handle->mVFS.c_str();
|
||||||
// Request failed
|
|
||||||
return _SC("");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* --------------------------------------------------------------------------------------------
|
/* --------------------------------------------------------------------------------------------
|
||||||
@ -234,9 +229,10 @@ public:
|
|||||||
*/
|
*/
|
||||||
Int32 GetErrorCode() const
|
Int32 GetErrorCode() const
|
||||||
{
|
{
|
||||||
if (Validate())
|
// Validate the handle
|
||||||
|
Validate();
|
||||||
|
// Return the requested information
|
||||||
return m_Handle.ErrNo();
|
return m_Handle.ErrNo();
|
||||||
return -1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* --------------------------------------------------------------------------------------------
|
/* --------------------------------------------------------------------------------------------
|
||||||
@ -244,9 +240,10 @@ public:
|
|||||||
*/
|
*/
|
||||||
Int32 GetExtendedErrorCode() const
|
Int32 GetExtendedErrorCode() const
|
||||||
{
|
{
|
||||||
if (Validate())
|
// Validate the handle
|
||||||
|
Validate();
|
||||||
|
// Return the requested information
|
||||||
return m_Handle.ExErrNo();
|
return m_Handle.ExErrNo();
|
||||||
return -1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* --------------------------------------------------------------------------------------------
|
/* --------------------------------------------------------------------------------------------
|
||||||
@ -254,9 +251,10 @@ public:
|
|||||||
*/
|
*/
|
||||||
CSStr GetErrStr() const
|
CSStr GetErrStr() const
|
||||||
{
|
{
|
||||||
if (Validate())
|
// Validate the handle
|
||||||
|
Validate();
|
||||||
|
// Return the requested information
|
||||||
return m_Handle.ErrStr();
|
return m_Handle.ErrStr();
|
||||||
return _SC("");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* --------------------------------------------------------------------------------------------
|
/* --------------------------------------------------------------------------------------------
|
||||||
@ -264,9 +262,10 @@ public:
|
|||||||
*/
|
*/
|
||||||
CSStr GetErrMsg() const
|
CSStr GetErrMsg() const
|
||||||
{
|
{
|
||||||
if (Validate())
|
// Validate the handle
|
||||||
|
Validate();
|
||||||
|
// Return the requested information
|
||||||
return m_Handle.ErrMsg();
|
return m_Handle.ErrMsg();
|
||||||
return _SC("");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* --------------------------------------------------------------------------------------------
|
/* --------------------------------------------------------------------------------------------
|
||||||
@ -326,11 +325,10 @@ public:
|
|||||||
*/
|
*/
|
||||||
bool GetAutoCommit() const
|
bool GetAutoCommit() const
|
||||||
{
|
{
|
||||||
// Request failed
|
// Validate the handle
|
||||||
if (Validate())
|
Validate();
|
||||||
|
// Return the requested information
|
||||||
return sqlite3_get_autocommit(m_Handle);
|
return sqlite3_get_autocommit(m_Handle);
|
||||||
// Request failed
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* --------------------------------------------------------------------------------------------
|
/* --------------------------------------------------------------------------------------------
|
||||||
@ -345,10 +343,9 @@ public:
|
|||||||
Int32 GetChanges() const
|
Int32 GetChanges() const
|
||||||
{
|
{
|
||||||
// Validate the handle
|
// Validate the handle
|
||||||
if (Validate())
|
Validate();
|
||||||
|
// Return the requested information
|
||||||
return sqlite3_changes(m_Handle);
|
return sqlite3_changes(m_Handle);
|
||||||
// Request failed
|
|
||||||
return -1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* --------------------------------------------------------------------------------------------
|
/* --------------------------------------------------------------------------------------------
|
||||||
@ -358,10 +355,9 @@ public:
|
|||||||
Int32 GetTotalChanges() const
|
Int32 GetTotalChanges() const
|
||||||
{
|
{
|
||||||
// Validate the handle
|
// Validate the handle
|
||||||
if (Validate())
|
Validate();
|
||||||
|
// Return the requested information
|
||||||
return sqlite3_total_changes(m_Handle);
|
return sqlite3_total_changes(m_Handle);
|
||||||
// Request failed
|
|
||||||
return -1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* --------------------------------------------------------------------------------------------
|
/* --------------------------------------------------------------------------------------------
|
||||||
@ -370,10 +366,9 @@ public:
|
|||||||
bool GetTracing() const
|
bool GetTracing() const
|
||||||
{
|
{
|
||||||
// Validate the handle
|
// Validate the handle
|
||||||
if (Validate())
|
Validate();
|
||||||
|
// Return the requested information
|
||||||
return m_Handle->mTrace;
|
return m_Handle->mTrace;
|
||||||
// Request failed
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* --------------------------------------------------------------------------------------------
|
/* --------------------------------------------------------------------------------------------
|
||||||
@ -381,8 +376,10 @@ public:
|
|||||||
*/
|
*/
|
||||||
void SetTracing(bool toggle)
|
void SetTracing(bool toggle)
|
||||||
{
|
{
|
||||||
// Validate the handle and check whether changes are necessary
|
// Validate the handle
|
||||||
if (!Validate() || m_Handle->mTrace == toggle)
|
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?
|
// Do we have to disable it?
|
||||||
else if (m_Handle->mTrace)
|
else if (m_Handle->mTrace)
|
||||||
@ -398,10 +395,9 @@ public:
|
|||||||
bool GetProfiling() const
|
bool GetProfiling() const
|
||||||
{
|
{
|
||||||
// Validate the handle
|
// Validate the handle
|
||||||
if (Validate())
|
Validate();
|
||||||
|
// Return the requested information
|
||||||
return m_Handle->mProfile;
|
return m_Handle->mProfile;
|
||||||
// Request failed
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* --------------------------------------------------------------------------------------------
|
/* --------------------------------------------------------------------------------------------
|
||||||
@ -409,8 +405,10 @@ public:
|
|||||||
*/
|
*/
|
||||||
void SetProfiling(bool toggle)
|
void SetProfiling(bool toggle)
|
||||||
{
|
{
|
||||||
// Validate the handle and check whether changes are necessary
|
// Validate the handle
|
||||||
if (!Validate() || m_Handle->mProfile == toggle)
|
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?
|
// Do we have to disable it?
|
||||||
else if (m_Handle->mProfile)
|
else if (m_Handle->mProfile)
|
||||||
@ -431,7 +429,8 @@ public:
|
|||||||
void InterruptOperation() const
|
void InterruptOperation() const
|
||||||
{
|
{
|
||||||
// Validate the handle
|
// Validate the handle
|
||||||
if (Validate())
|
Validate();
|
||||||
|
// Perform the requested action
|
||||||
sqlite3_interrupt(m_Handle);
|
sqlite3_interrupt(m_Handle);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -441,7 +440,8 @@ public:
|
|||||||
void ReleaseMemory() const
|
void ReleaseMemory() const
|
||||||
{
|
{
|
||||||
// Validate the handle
|
// Validate the handle
|
||||||
if (Validate())
|
Validate();
|
||||||
|
// Perform the requested action
|
||||||
sqlite3_db_release_memory(m_Handle);
|
sqlite3_db_release_memory(m_Handle);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -453,7 +453,7 @@ public:
|
|||||||
/* --------------------------------------------------------------------------------------------
|
/* --------------------------------------------------------------------------------------------
|
||||||
* Takes a snapshot of a database which is located in memory and saves it to a database file.
|
* Takes a snapshot of a database which is located in memory and saves it to a database file.
|
||||||
*/
|
*/
|
||||||
void CopyToDatabase(Connection & db);
|
void CopyToDatabase(const Connection & db);
|
||||||
|
|
||||||
/* --------------------------------------------------------------------------------------------
|
/* --------------------------------------------------------------------------------------------
|
||||||
* Returns internal runtime status information associated with the current database connection.
|
* Returns internal runtime status information associated with the current database connection.
|
||||||
@ -482,10 +482,9 @@ public:
|
|||||||
Uint32 QueueSize() const
|
Uint32 QueueSize() const
|
||||||
{
|
{
|
||||||
// Validate the handle
|
// Validate the handle
|
||||||
if (Validate())
|
Validate();
|
||||||
|
// Return the requested information
|
||||||
return (Uint32)m_Handle->mQueue.size();
|
return (Uint32)m_Handle->mQueue.size();
|
||||||
// Request failed
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* --------------------------------------------------------------------------------------------
|
/* --------------------------------------------------------------------------------------------
|
||||||
@ -494,7 +493,8 @@ public:
|
|||||||
void ClearQueue() const
|
void ClearQueue() const
|
||||||
{
|
{
|
||||||
// Validate the handle
|
// Validate the handle
|
||||||
if (Validate())
|
Validate();
|
||||||
|
// Return the requested information
|
||||||
m_Handle->mQueue.clear();
|
m_Handle->mQueue.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -504,7 +504,9 @@ public:
|
|||||||
void PopQueue() const
|
void PopQueue() const
|
||||||
{
|
{
|
||||||
// Validate the handle
|
// Validate the handle
|
||||||
if (Validate() && !m_Handle->mQueue.empty())
|
Validate();
|
||||||
|
// Perform the requested action
|
||||||
|
if (!m_Handle->mQueue.empty())
|
||||||
m_Handle->mQueue.pop_back();
|
m_Handle->mQueue.pop_back();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -514,10 +516,9 @@ public:
|
|||||||
Int32 Flush()
|
Int32 Flush()
|
||||||
{
|
{
|
||||||
// Validate the handle
|
// Validate the handle
|
||||||
if (Validate())
|
Validate();
|
||||||
|
// Return the requested information
|
||||||
return Flush(m_Handle->mQueue.size());
|
return Flush(m_Handle->mQueue.size());
|
||||||
// Request failed
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* --------------------------------------------------------------------------------------------
|
/* --------------------------------------------------------------------------------------------
|
||||||
@ -570,7 +571,7 @@ protected:
|
|||||||
/* --------------------------------------------------------------------------------------------
|
/* --------------------------------------------------------------------------------------------
|
||||||
* Takes and saves a snapshot of the memory database in a file.
|
* Takes and saves a snapshot of the memory database in a file.
|
||||||
*/
|
*/
|
||||||
void TakeSnapshot(ConnHnd & destination);
|
void TakeSnapshot(const ConnHnd & destination);
|
||||||
};
|
};
|
||||||
|
|
||||||
} // Namespace:: SqMod
|
} // Namespace:: SqMod
|
||||||
|
@ -325,6 +325,7 @@ void RegisterAPI(HSQUIRRELVM vm)
|
|||||||
.Func(_SC("Release"), &Column::Release)
|
.Func(_SC("Release"), &Column::Release)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
sqlns.Func(_SC("GetErrStr"), &GetErrStr);
|
||||||
sqlns.Func(_SC("SetSoftHeapLimit"), &SetSoftHeapLimit);
|
sqlns.Func(_SC("SetSoftHeapLimit"), &SetSoftHeapLimit);
|
||||||
sqlns.Func(_SC("ReleaseMemory"), &ReleaseMemory);
|
sqlns.Func(_SC("ReleaseMemory"), &ReleaseMemory);
|
||||||
sqlns.Func(_SC("MemoryUsage"), &GetMemoryUsage);
|
sqlns.Func(_SC("MemoryUsage"), &GetMemoryUsage);
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -27,17 +27,17 @@ protected:
|
|||||||
/* --------------------------------------------------------------------------------------------
|
/* --------------------------------------------------------------------------------------------
|
||||||
* Validate the statement reference and throw an error if invalid.
|
* Validate the statement reference and throw an error if invalid.
|
||||||
*/
|
*/
|
||||||
bool Validate() const;
|
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.
|
||||||
*/
|
*/
|
||||||
bool ValidateIndex(Int32 idx) const;
|
void ValidateIndex(Int32 idx) const;
|
||||||
|
|
||||||
/* --------------------------------------------------------------------------------------------
|
/* --------------------------------------------------------------------------------------------
|
||||||
* Validate the statement reference and row, and throw an error if they're invalid.
|
* Validate the statement reference and row, and throw an error if they're invalid.
|
||||||
*/
|
*/
|
||||||
bool RowAvailable() const;
|
void ValidateRow() const;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
@ -196,10 +196,9 @@ public:
|
|||||||
Int32 GetStatus() const
|
Int32 GetStatus() const
|
||||||
{
|
{
|
||||||
// Validate the handle
|
// Validate the handle
|
||||||
if (Validate())
|
Validate();
|
||||||
|
// Return the requested information
|
||||||
return m_Handle->mStatus;
|
return m_Handle->mStatus;
|
||||||
// Request failed
|
|
||||||
return -1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* --------------------------------------------------------------------------------------------
|
/* --------------------------------------------------------------------------------------------
|
||||||
@ -208,10 +207,9 @@ public:
|
|||||||
Int32 GetErrorCode() const
|
Int32 GetErrorCode() const
|
||||||
{
|
{
|
||||||
// Validate the handle
|
// Validate the handle
|
||||||
if (Validate())
|
Validate();
|
||||||
|
// Return the requested information
|
||||||
return m_Handle.ErrNo();
|
return m_Handle.ErrNo();
|
||||||
// Request failed
|
|
||||||
return -1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* --------------------------------------------------------------------------------------------
|
/* --------------------------------------------------------------------------------------------
|
||||||
@ -220,10 +218,9 @@ public:
|
|||||||
Int32 GetExtendedErrorCode() const
|
Int32 GetExtendedErrorCode() const
|
||||||
{
|
{
|
||||||
// Validate the handle
|
// Validate the handle
|
||||||
if (Validate())
|
Validate();
|
||||||
|
// Return the requested information
|
||||||
return m_Handle.ExErrNo();
|
return m_Handle.ExErrNo();
|
||||||
// Request failed
|
|
||||||
return -1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* --------------------------------------------------------------------------------------------
|
/* --------------------------------------------------------------------------------------------
|
||||||
@ -232,10 +229,9 @@ public:
|
|||||||
CSStr GetErrStr() const
|
CSStr GetErrStr() const
|
||||||
{
|
{
|
||||||
// Validate the handle
|
// Validate the handle
|
||||||
if (Validate())
|
Validate();
|
||||||
|
// Return the requested information
|
||||||
return m_Handle.ErrStr();
|
return m_Handle.ErrStr();
|
||||||
// Request failed
|
|
||||||
return _SC("");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* --------------------------------------------------------------------------------------------
|
/* --------------------------------------------------------------------------------------------
|
||||||
@ -244,10 +240,9 @@ public:
|
|||||||
CSStr GetErrMsg() const
|
CSStr GetErrMsg() const
|
||||||
{
|
{
|
||||||
// Validate the handle
|
// Validate the handle
|
||||||
if (Validate())
|
Validate();
|
||||||
|
// Return the requested information
|
||||||
return m_Handle.ErrMsg();
|
return m_Handle.ErrMsg();
|
||||||
// Request failed
|
|
||||||
return _SC("");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* --------------------------------------------------------------------------------------------
|
/* --------------------------------------------------------------------------------------------
|
||||||
@ -256,10 +251,9 @@ public:
|
|||||||
Int32 GetColumns() const
|
Int32 GetColumns() const
|
||||||
{
|
{
|
||||||
// Validate the handle
|
// Validate the handle
|
||||||
if (Validate())
|
Validate();
|
||||||
|
// Return the requested information
|
||||||
return m_Handle->mColumns;
|
return m_Handle->mColumns;
|
||||||
// Request failed
|
|
||||||
return -1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* --------------------------------------------------------------------------------------------
|
/* --------------------------------------------------------------------------------------------
|
||||||
@ -268,10 +262,9 @@ public:
|
|||||||
CSStr GetQuery() const
|
CSStr GetQuery() const
|
||||||
{
|
{
|
||||||
// Validate the handle
|
// Validate the handle
|
||||||
if (Validate())
|
Validate();
|
||||||
|
// Return the requested information
|
||||||
return m_Handle->mQuery.c_str();
|
return m_Handle->mQuery.c_str();
|
||||||
// Request failed
|
|
||||||
return _SC("");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* --------------------------------------------------------------------------------------------
|
/* --------------------------------------------------------------------------------------------
|
||||||
@ -280,10 +273,9 @@ public:
|
|||||||
bool GetGood() const
|
bool GetGood() const
|
||||||
{
|
{
|
||||||
// Validate the handle
|
// Validate the handle
|
||||||
if (Validate())
|
Validate();
|
||||||
|
// Return the requested information
|
||||||
return m_Handle->mGood;
|
return m_Handle->mGood;
|
||||||
// Request failed
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* --------------------------------------------------------------------------------------------
|
/* --------------------------------------------------------------------------------------------
|
||||||
@ -292,10 +284,9 @@ public:
|
|||||||
bool GetDone() const
|
bool GetDone() const
|
||||||
{
|
{
|
||||||
// Validate the handle
|
// Validate the handle
|
||||||
if (Validate())
|
Validate();
|
||||||
|
// Return the requested information
|
||||||
return m_Handle->mDone;
|
return m_Handle->mDone;
|
||||||
// Request failed
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* --------------------------------------------------------------------------------------------
|
/* --------------------------------------------------------------------------------------------
|
||||||
|
Loading…
x
Reference in New Issue
Block a user