1
0
mirror of https://github.com/VCMP-SqMod/SqMod.git synced 2024-11-08 08:47:17 +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:
Sandu Liviu Catalin 2016-02-27 17:53:12 +02:00
parent 8340a5dbc4
commit 331b03028c
10 changed files with 582 additions and 832 deletions

View File

@ -363,6 +363,7 @@
<Add option="-Wextra" />
<Add option="-Wall" />
<Add option="-DSQMOD_PLUGIN_API" />
<Add option="-DSCRAT_USE_EXCEPTIONS" />
<Add directory="../modules/sqlite" />
<Add directory="../shared" />
<Add directory="../include" />

View File

@ -19,107 +19,91 @@ SQInteger Column::Typename(HSQUIRRELVM vm)
}
// ------------------------------------------------------------------------------------------------
bool Column::Validate() const
void Column::Validate() const
{
// Are we pointing to a valid index?
if (m_Index < 0)
_SqMod->SqThrow("Invalid column index");
SqThrowF("Invalid column index");
// Do we belong to a valid statement?
else if (!m_Stmt)
_SqMod->SqThrow("Invalid SQLite statement reference");
// Requirements satisfied
else
return true;
// Validation failed
return false;
SqThrowF("Invalid SQLite statement reference");
}
// ------------------------------------------------------------------------------------------------
bool Column::RowAvailable() const
void Column::ValidateRow() const
{
// Are we pointing to a valid index?
if (m_Index < 0)
_SqMod->SqThrow("Invalid column index");
SqThrowF("Invalid column index");
// Do we belong to a valid statement?
else if (!m_Stmt)
_SqMod->SqThrow("Invalid SQLite statement reference");
SqThrowF("Invalid SQLite statement reference");
// Do we have any rows available?
else if (!m_Stmt->mGood)
_SqMod->SqThrow("No row available");
// Requirements satisfied
else
return true;
// Validation failed
return false;
SqThrowF("No row available");
}
// ------------------------------------------------------------------------------------------------
Object Column::GetStatement() const
{
// Validate the handle
if (Validate())
return Object(new Statement(m_Stmt));
// Request failed
return Object(new Statement());
// Validate the column
Validate();
// Return the requested information
return Object(new Statement(m_Stmt));
}
// ------------------------------------------------------------------------------------------------
Object Column::GetConnection() const
{
// Validate the handle
if (Validate())
return Object(new Connection(m_Stmt->mConn));
// Request failed
return Object(new Connection());
// Validate the column
Validate();
// Return the requested information
return Object(new Connection(m_Stmt->mConn));
}
// ------------------------------------------------------------------------------------------------
Int32 Column::GetNumber() const
{
// Validate the handle and index
if (RowAvailable())
return sqlite3_column_int(m_Stmt, m_Index);
// Request failed
return 0;
// Validate the column and statement row
ValidateRow();
// Return the requested information
return sqlite3_column_int(m_Stmt, m_Index);
}
// ------------------------------------------------------------------------------------------------
SQInteger Column::GetInteger() const
{
// Validate the handle and index
if (RowAvailable())
// Validate the column and statement row
ValidateRow();
// Return the requested information
#ifdef _SQ64
return sqlite3_column_int64(m_Stmt, m_Index);
return sqlite3_column_int64(m_Stmt, m_Index);
#else
return sqlite3_column_int(m_Stmt, m_Index);
return sqlite3_column_int(m_Stmt, m_Index);
#endif
// Request failed
return 0;
}
// ------------------------------------------------------------------------------------------------
SQFloat Column::GetFloat() const
{
// Validate the handle and index
if (RowAvailable())
return (SQFloat)sqlite3_column_double(m_Stmt, m_Index);
// Request failed
return SQFloat(0.0);
// Validate the column and statement row
ValidateRow();
// Return the requested information
return (SQFloat)sqlite3_column_double(m_Stmt, m_Index);
}
// ------------------------------------------------------------------------------------------------
Object Column::GetLong() const
{
// Validate the handle and index
if (!RowAvailable())
return Object(); // Request failed
// Validate the column and statement row
ValidateRow();
// Obtain the initial stack size
const Int32 top = sq_gettop(_SqVM);
// Push a long integer instance with the requested value on the stack
_SqMod->PushSLongObject(_SqVM, sqlite3_column_int64(m_Stmt, m_Index));
// Obtain the object from the stack
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);
// Return the long integer instance
return inst.value;
@ -128,9 +112,8 @@ Object Column::GetLong() const
// ------------------------------------------------------------------------------------------------
Object Column::GetString() const
{
// Validate the handle and index
if (!RowAvailable())
return Object(); // Request failed
// Validate the column and statement row
ValidateRow();
// Obtain the initial stack size
const Int32 top = sq_gettop(_SqVM);
// Push the column text on the stack
@ -138,7 +121,7 @@ Object Column::GetString() const
sqlite3_column_bytes(m_Stmt, m_Index));
// Obtain the object from the stack
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);
// Return the long integer instance
return inst.value;
@ -147,19 +130,17 @@ Object Column::GetString() const
// ------------------------------------------------------------------------------------------------
bool Column::GetBoolean() const
{
// Validate the handle and index
if (RowAvailable())
return sqlite3_column_int(m_Stmt, m_Index) > 0;
// Request failed
return false;
// Validate the column and statement row
ValidateRow();
// Return the requested information
return sqlite3_column_int(m_Stmt, m_Index) > 0;
}
// ------------------------------------------------------------------------------------------------
Object Column::GetBlob() const
{
// Validate the handle and index
if (RowAvailable())
return Object(); // Request failed
// Validate the column and statement row
ValidateRow();
// Obtain the initial stack size
const Int32 top = sq_gettop(_SqVM);
// Obtain the size of the data
@ -170,71 +151,63 @@ Object Column::GetBlob() const
const void * b = sqlite3_column_blob(m_Stmt, m_Index);
// Could the memory blob be allocated?
if (!p)
{
_SqMod->SqThrow("Unable to allocate space for column blob value");
// Request failed
return Object();
}
SqThrowF("Unable to allocate space for column blob value");
// Is there any data to read?
else if (!b)
{
// Pop the memory blob from the stack
sq_pop(_SqVM, sq_gettop(_SqVM) - top);
// Now throw the error
_SqMod->SqThrow("Unable to read data from column blob value");
// Request failed
return Object();
// Push a null value instead
sq_pushnull(_SqVM);
}
// Copy the data into the memory blob
else
memcpy(p, b, sz);
// Obtain the object from the stack
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);
// Return the long integer instance
// Return the blob instance
return inst.value;
}
// ------------------------------------------------------------------------------------------------
SQChar Column::GetChar() const
{
// Validate the handle and index
if (RowAvailable())
return (SQChar)sqlite3_column_int(m_Stmt, m_Index);
// Request failed
return 0;
// Validate the column and statement row
ValidateRow();
// Return the requested information
return (SQChar)sqlite3_column_int(m_Stmt, m_Index);
}
// ------------------------------------------------------------------------------------------------
bool Column::IsNull() const
{
// Can we make the request?
if (Validate())
return (sqlite3_column_type(m_Stmt, m_Index) == SQLITE_NULL);
// Request failed
return true;
// Validate the column
Validate();
// Return the requested information
return (sqlite3_column_type(m_Stmt, m_Index) == SQLITE_NULL);
}
// ------------------------------------------------------------------------------------------------
CSStr Column::GetName() const
{
// Can we make the request?
if (Validate())
return sqlite3_column_name(m_Stmt, m_Index);
// Request failed
return _SC("");
// Validate the column
Validate();
// Return the requested information
return sqlite3_column_name(m_Stmt, m_Index);
}
// ------------------------------------------------------------------------------------------------
CSStr Column::GetOriginName() const
{
#ifdef SQLITE_ENABLE_COLUMN_METADATA
// Can we make the request?
if (Validate())
return sqlite3_column_origin_name(m_Stmt, m_Index);
// Validate the column
Validate();
// Return the requested information
return sqlite3_column_origin_name(m_Stmt, m_Index);
#else
_SqMod->SqThrow("The module was compiled without this feature");
SqThrowF("The module was compiled without this feature");
#endif
// Request failed
return _SC("");
@ -243,22 +216,19 @@ CSStr Column::GetOriginName() const
// ------------------------------------------------------------------------------------------------
Int32 Column::GetType() const
{
// Can we make the request?
if (Validate())
return sqlite3_column_type(m_Stmt, m_Index);
// Request failed
return -1;
// Validate the column
Validate();
// Return the requested information
return sqlite3_column_type(m_Stmt, m_Index);
}
// ------------------------------------------------------------------------------------------------
Int32 Column::GetBytes() const
{
// Can we make the request?
if (Validate())
return sqlite3_column_bytes(m_Stmt, m_Index);
// Request failed
return -1;
// Validate the column
Validate();
// Return the requested information
return sqlite3_column_bytes(m_Stmt, m_Index);
}
} // Namespace:: SqMod

View File

@ -27,12 +27,12 @@ private:
/* --------------------------------------------------------------------------------------------
* 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.
*/
bool RowAvailable() const;
void ValidateRow() const;
/* --------------------------------------------------------------------------------------------
* Base constructor.

View File

@ -15,6 +15,27 @@ static SQChar g_Buffer[4096]; // Common buffer to reduce memory allocations.
// ------------------------------------------------------------------------------------------------
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, ...)
{
@ -72,7 +93,7 @@ ConnHnd::Handle::~Handle()
// 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.");
_SqMod->LogErr("SQLite connection is still referenced (%s)", mName.c_str());
else
{
// 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
if (mPtr)
{
_SqMod->SqThrow("Unable to connect to database. Database already connected");
// Unable to proceed
return;
}
SqThrowF("Unable to connect to database. Database already connected");
// Make sure the name is valid
else if (!name || strlen(name) <= 0)
{
_SqMod->SqThrow("Unable to connect to database. The name is invalid");
// Unable to proceed
return;
}
SqThrowF("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)
{
@ -111,9 +124,7 @@ void ConnHnd::Handle::Create(CSStr name, Int32 flags, CSStr vfs)
// Explicitly make sure it's null
mPtr = NULL;
// Now its safe to throw the error
_SqMod->SqThrow("Unable to connect to database [%s]", sqlite3_errstr(mStatus));
// Unable to proceed
return;
SqThrowF("Unable to connect to database [%s]", sqlite3_errstr(mStatus));
}
// Let's save the specified information
mName.assign(name);
@ -142,11 +153,7 @@ Int32 ConnHnd::Handle::Flush(Uint32 num, Object & env, Function & func)
QueryList::iterator end = mQueue.begin() + num;
// Attempt to begin the flush transaction
if ((mStatus = sqlite3_exec(mPtr, "BEGIN", NULL, NULL, NULL)) != SQLITE_OK)
{
_SqMod->SqThrow("Unable to begin transaction [%s]", sqlite3_errmsg(mPtr));
// Unable to proceed
return -1;
}
SqThrowF("Unable to begin transaction [%s]", sqlite3_errmsg(mPtr));
// Process all queries within range of selection
for (; itr != end; ++itr)
{
@ -175,10 +182,10 @@ Int32 ConnHnd::Handle::Flush(Uint32 num, Object & env, Function & func)
return sqlite3_changes(mPtr);
// Attempt to roll back erroneous changes
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
else
_SqMod->SqThrow("Unable to commit transaction because [%s]", sqlite3_errmsg(mPtr));
SqThrowF("Unable to commit transaction because [%s]", sqlite3_errmsg(mPtr));
// Operation failed
return -1;
}
@ -192,7 +199,7 @@ StmtHnd::Handle::~Handle()
// 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.");
_SqMod->LogErr("SQLite statement is still referenced (%s)", mQuery.c_str());
else
{
// Attempt to finalize the statement
@ -206,33 +213,25 @@ void StmtHnd::Handle::Create(CSStr query)
{
// Make sure a previous statement doesn't exist
if (mPtr)
{
_SqMod->SqThrow("Unable to prepare statement. Statement already prepared");
// Unable to proceed
return;
}
SqThrowF("Unable to prepare statement. Statement already prepared");
// Is the specified database connection is valid?
else if (!mConn)
{
_SqMod->SqThrow("Unable to prepare statement. Invalid connection handle");
// Unable to proceed
return;
}
SqThrowF("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())
_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
else if ((mStatus = sqlite3_prepare_v2(mConn, mQuery.c_str(), (Int32)mQuery.size(),
&mPtr, NULL)) != SQLITE_OK)
{
// Clear the query string since it failed
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
mPtr = NULL;
// Now it's safe to throw the error
SqThrowF("Unable to prepare statement [%s]", mConn.ErrMsg());
}
else
// Obtain the number of available columns
@ -244,7 +243,7 @@ Int32 StmtHnd::Handle::GetColumnIndex(CSStr name)
{
// Validate the handle
if (!mPtr)
_SqMod->SqThrow("Invalid SQLite statement");
SqThrowF("Invalid SQLite statement");
// Are the names cached?
else if (mIndexes.empty())
{
@ -254,7 +253,7 @@ Int32 StmtHnd::Handle::GetColumnIndex(CSStr name)
CSStr name = (CSStr)sqlite3_column_name(mPtr, i);
// Validate the 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
else
mIndexes[name] = i;
@ -269,6 +268,12 @@ Int32 StmtHnd::Handle::GetColumnIndex(CSStr name)
return -1;
}
// ------------------------------------------------------------------------------------------------
CSStr GetErrStr(Int32 status)
{
return sqlite3_errstr(status);
}
// ------------------------------------------------------------------------------------------------
void SetSoftHeapLimit(Int32 limit)
{
@ -290,7 +295,7 @@ Object GetMemoryUsage()
_SqMod->PushSLongObject(_SqVM, sqlite3_memory_used());
// Obtain the object from the stack
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);
// Return the long integer instance
return inst.value;
@ -305,7 +310,7 @@ Object GetMemoryHighwaterMark(bool reset)
_SqMod->PushSLongObject(_SqVM, sqlite3_memory_highwater(reset));
// Obtain the object from the stack
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);
// Return the long integer instance
return inst.value;
@ -331,7 +336,7 @@ CCStr EscapeStringEx(SQChar spec, CCStr str)
// Validate the specified format specifier
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
return _SC("");
}
@ -367,11 +372,7 @@ CCStr ArrayToQueryColumns(Array & arr)
{
// Is the name valid?
if (itr->empty())
{
_SqMod->SqThrow("Invalid column name");
// Default to empty string
return _SC("");
}
SqThrowF("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
@ -403,11 +404,7 @@ CCStr TableToQueryColumns(Table & tbl)
name.assign(itr.getName());
// Is the name valid?
if (name.empty())
{
_SqMod->SqThrow("Invalid column name");
// Default to empty string
return _SC("");
}
SqThrowF("Invalid 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

View File

@ -38,6 +38,16 @@ class Transaction;
#define SQSQLITE_VERSION_MINOR 0
#define SQSQLITE_VERSION_PATCH 1
/* ------------------------------------------------------------------------------------------------
* Retrieve the temporary buffer.
*/
SStr GetTempBuff();
/* ------------------------------------------------------------------------------------------------
* Throw a formatted exception.
*/
void SqThrowF(CSStr str, ...);
/* ------------------------------------------------------------------------------------------------
* 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);
/* ------------------------------------------------------------------------------------------------
*
* Release the specified amount of memory.
*/
Int32 ReleaseMemory(Int32 bytes);
/* ------------------------------------------------------------------------------------------------
*
* Retrieve the current memory usage.
*/
Object GetMemoryUsage();
/* ------------------------------------------------------------------------------------------------
*
* Retrieve the memory high watermark.
*/
Object GetMemoryHighwaterMark(bool reset);
/* ------------------------------------------------------------------------------------------------
*
* Retrieve the escaped version of the specified string.
*/
CSStr EscapeString(CSStr str);
/* ------------------------------------------------------------------------------------------------
*
* Retrieve the escaped version of the specified string using the supplied format specifier.
*/
CCStr EscapeStringEx(SQChar spec, CCStr str);
/* ------------------------------------------------------------------------------------------------
*
* Convert the values from the specified array to a list of column names string.
*/
CCStr ArrayToQueryColumns(Array & arr);
/* ------------------------------------------------------------------------------------------------
*
* Convert the keys from the specified array to a list of column names string.
*/
CCStr TableToQueryColumns(Table & tbl);

View File

@ -18,13 +18,11 @@ SQInteger Connection::Typename(HSQUIRRELVM vm)
}
// ------------------------------------------------------------------------------------------------
bool Connection::Validate() const
void Connection::Validate() const
{
if (m_Handle)
return true;
// Invalid connection reference
_SqMod->SqThrow("Invalid SQLite connection reference");
return false;
// Is the handle valid?
if (!m_Handle)
SqThrowF("Invalid SQLite connection reference");
}
// ------------------------------------------------------------------------------------------------
@ -40,12 +38,6 @@ Connection::Connection(CSStr name)
{
if (m_Handle.m_Hnd)
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)
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,75 +54,60 @@ Connection::Connection(CSStr name, Int32 flags, CSStr vfs)
{
if (m_Handle.m_Hnd)
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)
{
// Validate the handle
if (Validate() && (m_Handle = sqlite3_exec(m_Handle, str, NULL, NULL, NULL)) != SQLITE_OK)
_SqMod->SqThrow("Unable to execute query [%s]", m_Handle.ErrMsg());
Validate();
// 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
else
return sqlite3_changes(m_Handle);
// Operation failed
return -1;
return sqlite3_changes(m_Handle);
}
// ------------------------------------------------------------------------------------------------
Object Connection::Query(CSStr str) const
{
// Validate the handle
if (Validate())
return Object(new Statement(m_Handle, str));
// Request failed
return Object(new Statement());
Validate();
// Return the requested information
return Object(new Statement(m_Handle, str));
}
// ------------------------------------------------------------------------------------------------
void Connection::Queue(CSStr str)
{
// Validate the handle
if (!Validate())
return; // Nothing to commit
Validate();
// Is there a query to commit?
else if (IsQueryEmpty(str))
_SqMod->SqThrow("No query to queue");
if (IsQueryEmpty(str))
SqThrowF("No query string to queue");
// Add the specified string to the queue
else
m_Handle->mQueue.push_back(str);
m_Handle->mQueue.push_back(str);
}
// ------------------------------------------------------------------------------------------------
bool Connection::IsReadOnly() const
{
// Validate the handle
if (!Validate())
return false;
Validate();
// Request the desired information
const int result = sqlite3_db_readonly(m_Handle, "main");
// Verify the result
if (result == -1)
_SqMod->SqThrow("'main' is not the name of a database on connection");
// Return the result
else
return (result != 1);
// Inexistent is same as read-only
return true;
SqThrowF("'main' is not the name of a database on connection");
// Return the requested information
return (result != 1);
}
// ------------------------------------------------------------------------------------------------
bool Connection::TableExists(CCStr name) const
{
// Validate the handle
if (!Validate())
return false;
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?
@ -156,8 +127,7 @@ bool Connection::TableExists(CCStr name) const
Object Connection::GetLastInsertRowID() const
{
// Validate the handle
if (!Validate())
return Object();
Validate();
// Obtain the initial stack size
const Int32 top = sq_gettop(_SqVM);
// Push a long integer instance with the requested value on the stack
@ -173,155 +143,130 @@ Object Connection::GetLastInsertRowID() const
// ------------------------------------------------------------------------------------------------
void Connection::SetBusyTimeout(Int32 millis)
{
// Validate the handle and apply requested timeout
if (Validate() && ((m_Handle = sqlite3_busy_timeout(m_Handle, millis)) != SQLITE_OK))
_SqMod->SqThrow("Unable to set busy timeout [%s]", m_Handle.ErrMsg());
// Validate the handle
Validate();
// 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)
{
// Don't even bother to continue if there's no valid connection handle
if (!Validate())
return -1;
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)
_SqMod->SqThrow("Unable to get runtime status information", m_Handle.ErrMsg());
// Return what was requested
if ((m_Handle = sqlite3_db_status(m_Handle, operation, &cur_value, &hiwtr_value, reset)) != SQLITE_OK)
SqThrowF("Unable to get runtime status information", m_Handle.ErrMsg());
// Return the high-water value if requested
else if (highwater)
return hiwtr_value;
else
return cur_value;
// Request failed
return -1;
// Return the requested information
return cur_value;
}
// ------------------------------------------------------------------------------------------------
Connection Connection::CopyToMemory()
{
// Validate the handle
if (!Validate())
return Connection();
Validate();
// Is the database already in memory?
else if (m_Handle->mMemory)
{
_SqMod->SqThrow("The database is already in memory");
// No reason to move it again
return Connection();
}
if (m_Handle->mMemory)
SqThrowF("The database is already in memory");
// Destination database
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);
// See if the database could be opened
if (!db)
// 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);
// Clear the temporary buffer
GetTempBuff()[0] = 0;
// Begin a transaction to replicate the schema of origin database
if ((m_Handle = sqlite3_exec(m_Handle, "BEGIN", NULL, NULL, NULL)) != SQLITE_OK)
_SqMod->SqThrow("Unable to begin schema replication [%s]", m_Handle.ErrMsg());
// Attempt to replicate the schema of origin database to the in-memory one
SqThrowF("Unable to begin schema replication [%s]", m_Handle.ErrMsg());
// Attempt to replicate the schema of origin database to the in-memory one
else if ((m_Handle = sqlite3_exec(m_Handle,
"SELECT [sql] FROM [sqlite_master] WHERE [sql] NOT NULL AND [tbl_name] != 'sqlite_sequence'",
&Connection::ProcessDDLRow, db->mPtr, NULL)) != SQLITE_OK)
{
// Did the error occurred from the DDL process function?
if (Sqrat::Error::Occurred(_SqVM))
{
// Obtain the occurred message
String msg(Sqrat::Error::Message(_SqVM));
if (GetTempBuff()[0] != 0)
// 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
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
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
else if ((db = sqlite3_exec(db, QFmtStr("ATTACH DATABASE '%q' as origin", m_Handle->mName.c_str()),
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
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
else if ((db = sqlite3_exec(db, "SELECT [name] FROM [origin.sqlite_master] WHERE [type]='table'",
&Connection::ProcessDMLRow, db->mPtr, NULL)) != SQLITE_OK)
{
// 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
_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
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
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
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
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
else
return Connection(db);
// Failed to replicate the database
return Connection();
return Connection(db);
}
// ------------------------------------------------------------------------------------------------
void Connection::CopyToDatabase(Connection & db)
void Connection::CopyToDatabase(const Connection & db)
{
// Make sure that we have two valid database handles
if (Validate() && db.Validate())
_SqMod->SqThrow("Invalid database connections");
Validate();
db.Validate();
// Attempt to take the snapshot and return the result
else
TakeSnapshot(db.m_Handle);
TakeSnapshot(db.m_Handle);
}
// ------------------------------------------------------------------------------------------------
Int32 Connection::Flush(Uint32 num)
{
// Validate the handle
if (Validate())
{
// We need to supply a null callback
Object env;
Function func;
// Attempt to flush the requested amount of queries
return m_Handle->Flush(num, env, func);
}
// Request failed
return -1;
Validate();
// We need to supply a null callback
Object env;
Function func;
// Attempt to flush the requested amount of queries
return m_Handle->Flush(num, env, func);
}
// ------------------------------------------------------------------------------------------------
Int32 Connection::Flush(Uint32 num, Object & env, Function & func)
{
// Validate the handle
if (Validate())
// Attempt to flush the requested amount of queries
return m_Handle->Flush(num, env, func);
// Request failed
return -1;
Validate();
// Attempt to flush the requested amount of queries
return m_Handle->Flush(num, env, func);
}
// ------------------------------------------------------------------------------------------------
@ -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
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
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
// Continue processing
return 0;
@ -354,9 +299,9 @@ int Connection::ProcessDDLRow(void * db, int columns_count, char ** values, char
int Connection::ProcessDMLRow(void * db, int columns_count, char ** values, char ** /*columns*/)
{
// 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
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]);
// Attempt to execute the generated query string on the received database connection
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
{
// 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
sqlite3_backup * backup = sqlite3_backup_init(destination, "main", m_Handle, "main");
// See if the backup structure could be created
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
else if ((m_Handle = sqlite3_backup_step(backup, -1)) != SQLITE_DONE)
_SqMod->SqThrow("Unable to copy source [%s]", m_Handle.ErrStr());
if ((m_Handle = sqlite3_backup_step(backup, -1)) != SQLITE_DONE)
{
// 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()
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
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
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
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
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
sq_pop(vm, sq_gettop(vm) - top);
// Now we can throw the error message
return sq_throwerror(vm,"No query to queue");
}
// Attempt to queue the specified query
@ -549,17 +500,18 @@ SQInteger Connection::QueryF(HSQUIRRELVM vm)
// Now we can throw the error message
return sq_throwerror(vm, "Unable to retrieve the query");
}
// Attempt to create a statement with the specified query
ClassType< Statement >::PushInstance(vm, new Statement(inst.value->m_Handle, sql));
// 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);
// See if any errors occured
if (Sqrat::Error::Occurred(vm))
// Attempt to create a statement with the specified query
try
{
// Obtain the error message from sqrat
String msg = Sqrat::Error::Message(vm);
// Throw the error message further down the line
return sq_throwerror(vm, msg.c_str());
ClassType< Statement >::PushInstance(vm, new Statement(inst.value->m_Handle, sql));
}
catch (const Sqrat::Exception & e)
{
return sq_throwerror(vm, e.Message().c_str());
}
}
// Do we have enough values to call the format function?
@ -573,14 +525,13 @@ SQInteger Connection::QueryF(HSQUIRRELVM vm)
if (SQ_FAILED(ret))
return ret;
// Attempt to create a statement with the specified query
ClassType< Statement >::PushInstance(vm, new Statement(inst.value->m_Handle, sql));
// See if any errors occured
if (Sqrat::Error::Occurred(vm))
try
{
// Obtain the error message from sqrat
String msg = Sqrat::Error::Message(vm);
// Throw the error message further down the line
return sq_throwerror(vm, msg.c_str());
ClassType< Statement >::PushInstance(vm, new Statement(inst.value->m_Handle, sql));
}
catch (const Sqrat::Exception & e)
{
return sq_throwerror(vm, e.Message().c_str());
}
}
// All methods of retrieving the message value failed

View File

@ -23,7 +23,7 @@ protected:
/* --------------------------------------------------------------------------------------------
* Validate the document reference and throw an error if invalid.
*/
bool Validate() const;
void Validate() const;
private:
@ -138,10 +138,9 @@ public:
CSStr ToString() const
{
// Validate the handle
if (Validate())
return m_Handle->mName.c_str();
// Request failed
return _SC("");
Validate();
// Return the requested information
return m_Handle->mName.c_str();
}
/* --------------------------------------------------------------------------------------------
@ -187,10 +186,9 @@ public:
Int32 GetStatus() const
{
// Validate the handle
if (Validate())
return m_Handle->mStatus;
// Request failed
return -1;
Validate();
// Return the requested information
return m_Handle->mStatus;
}
/* --------------------------------------------------------------------------------------------
@ -199,10 +197,9 @@ public:
Int32 GetFlags() const
{
// Validate the handle
if (Validate())
return m_Handle->mFlags;
// Request failed
return 0;
Validate();
// Return the requested information
return m_Handle->mFlags;
}
/* --------------------------------------------------------------------------------------------
@ -211,10 +208,9 @@ public:
CSStr GetName() const
{
// Validate the handle
if (Validate())
return m_Handle->mName.c_str();
// Request failed
return _SC("");
Validate();
// Return the requested information
return m_Handle->mName.c_str();
}
/* --------------------------------------------------------------------------------------------
@ -223,10 +219,9 @@ public:
CSStr GetVFS() const
{
// Validate the handle
if (Validate())
return m_Handle->mVFS.c_str();
// Request failed
return _SC("");
Validate();
// Return the requested information
return m_Handle->mVFS.c_str();
}
/* --------------------------------------------------------------------------------------------
@ -234,9 +229,10 @@ public:
*/
Int32 GetErrorCode() const
{
if (Validate())
return m_Handle.ErrNo();
return -1;
// Validate the handle
Validate();
// Return the requested information
return m_Handle.ErrNo();
}
/* --------------------------------------------------------------------------------------------
@ -244,9 +240,10 @@ public:
*/
Int32 GetExtendedErrorCode() const
{
if (Validate())
return m_Handle.ExErrNo();
return -1;
// Validate the handle
Validate();
// Return the requested information
return m_Handle.ExErrNo();
}
/* --------------------------------------------------------------------------------------------
@ -254,9 +251,10 @@ public:
*/
CSStr GetErrStr() const
{
if (Validate())
return m_Handle.ErrStr();
return _SC("");
// Validate the handle
Validate();
// Return the requested information
return m_Handle.ErrStr();
}
/* --------------------------------------------------------------------------------------------
@ -264,9 +262,10 @@ public:
*/
CSStr GetErrMsg() const
{
if (Validate())
return m_Handle.ErrMsg();
return _SC("");
// Validate the handle
Validate();
// Return the requested information
return m_Handle.ErrMsg();
}
/* --------------------------------------------------------------------------------------------
@ -326,11 +325,10 @@ public:
*/
bool GetAutoCommit() const
{
// Request failed
if (Validate())
return sqlite3_get_autocommit(m_Handle);
// Request failed
return false;
// Validate the handle
Validate();
// Return the requested information
return sqlite3_get_autocommit(m_Handle);
}
/* --------------------------------------------------------------------------------------------
@ -345,10 +343,9 @@ public:
Int32 GetChanges() const
{
// Validate the handle
if (Validate())
return sqlite3_changes(m_Handle);
// Request failed
return -1;
Validate();
// Return the requested information
return sqlite3_changes(m_Handle);
}
/* --------------------------------------------------------------------------------------------
@ -358,10 +355,9 @@ public:
Int32 GetTotalChanges() const
{
// Validate the handle
if (Validate())
return sqlite3_total_changes(m_Handle);
// Request failed
return -1;
Validate();
// Return the requested information
return sqlite3_total_changes(m_Handle);
}
/* --------------------------------------------------------------------------------------------
@ -370,10 +366,9 @@ public:
bool GetTracing() const
{
// Validate the handle
if (Validate())
return m_Handle->mTrace;
// Request failed
return false;
Validate();
// Return the requested information
return m_Handle->mTrace;
}
/* --------------------------------------------------------------------------------------------
@ -381,8 +376,10 @@ public:
*/
void SetTracing(bool toggle)
{
// Validate the handle and check whether changes are necessary
if (!Validate() || m_Handle->mTrace == toggle)
// Validate the handle
Validate();
// Check whether changes are necessary
if (m_Handle->mTrace == toggle)
return; /* No point in proceeding */
// Do we have to disable it?
else if (m_Handle->mTrace)
@ -398,10 +395,9 @@ public:
bool GetProfiling() const
{
// Validate the handle
if (Validate())
return m_Handle->mProfile;
// Request failed
return false;
Validate();
// Return the requested information
return m_Handle->mProfile;
}
/* --------------------------------------------------------------------------------------------
@ -409,8 +405,10 @@ public:
*/
void SetProfiling(bool toggle)
{
// Validate the handle and check whether changes are necessary
if (!Validate() || m_Handle->mProfile == toggle)
// Validate the handle
Validate();
// Check whether changes are necessary
if (m_Handle->mProfile == toggle)
return; /* No point in proceeding */
// Do we have to disable it?
else if (m_Handle->mProfile)
@ -431,8 +429,9 @@ public:
void InterruptOperation() const
{
// Validate the handle
if (Validate())
sqlite3_interrupt(m_Handle);
Validate();
// Perform the requested action
sqlite3_interrupt(m_Handle);
}
/* --------------------------------------------------------------------------------------------
@ -441,8 +440,9 @@ public:
void ReleaseMemory() const
{
// Validate the handle
if (Validate())
sqlite3_db_release_memory(m_Handle);
Validate();
// Perform the requested action
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.
*/
void CopyToDatabase(Connection & db);
void CopyToDatabase(const Connection & db);
/* --------------------------------------------------------------------------------------------
* Returns internal runtime status information associated with the current database connection.
@ -482,10 +482,9 @@ public:
Uint32 QueueSize() const
{
// Validate the handle
if (Validate())
return (Uint32)m_Handle->mQueue.size();
// Request failed
return 0;
Validate();
// Return the requested information
return (Uint32)m_Handle->mQueue.size();
}
/* --------------------------------------------------------------------------------------------
@ -494,8 +493,9 @@ public:
void ClearQueue() const
{
// Validate the handle
if (Validate())
m_Handle->mQueue.clear();
Validate();
// Return the requested information
m_Handle->mQueue.clear();
}
/* --------------------------------------------------------------------------------------------
@ -504,7 +504,9 @@ public:
void PopQueue() const
{
// Validate the handle
if (Validate() && !m_Handle->mQueue.empty())
Validate();
// Perform the requested action
if (!m_Handle->mQueue.empty())
m_Handle->mQueue.pop_back();
}
@ -514,10 +516,9 @@ public:
Int32 Flush()
{
// Validate the handle
if (Validate())
return Flush(m_Handle->mQueue.size());
// Request failed
return 0;
Validate();
// Return the requested information
return Flush(m_Handle->mQueue.size());
}
/* --------------------------------------------------------------------------------------------
@ -570,7 +571,7 @@ protected:
/* --------------------------------------------------------------------------------------------
* Takes and saves a snapshot of the memory database in a file.
*/
void TakeSnapshot(ConnHnd & destination);
void TakeSnapshot(const ConnHnd & destination);
};
} // Namespace:: SqMod

View File

@ -325,6 +325,7 @@ void RegisterAPI(HSQUIRRELVM vm)
.Func(_SC("Release"), &Column::Release)
);
sqlns.Func(_SC("GetErrStr"), &GetErrStr);
sqlns.Func(_SC("SetSoftHeapLimit"), &SetSoftHeapLimit);
sqlns.Func(_SC("ReleaseMemory"), &ReleaseMemory);
sqlns.Func(_SC("MemoryUsage"), &GetMemoryUsage);

File diff suppressed because it is too large Load Diff

View File

@ -27,17 +27,17 @@ protected:
/* --------------------------------------------------------------------------------------------
* 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.
*/
bool ValidateIndex(Int32 idx) const;
void ValidateIndex(Int32 idx) const;
/* --------------------------------------------------------------------------------------------
* Validate the statement reference and row, and throw an error if they're invalid.
*/
bool RowAvailable() const;
void ValidateRow() const;
public:
@ -196,10 +196,9 @@ public:
Int32 GetStatus() const
{
// Validate the handle
if (Validate())
return m_Handle->mStatus;
// Request failed
return -1;
Validate();
// Return the requested information
return m_Handle->mStatus;
}
/* --------------------------------------------------------------------------------------------
@ -208,10 +207,9 @@ public:
Int32 GetErrorCode() const
{
// Validate the handle
if (Validate())
return m_Handle.ErrNo();
// Request failed
return -1;
Validate();
// Return the requested information
return m_Handle.ErrNo();
}
/* --------------------------------------------------------------------------------------------
@ -220,10 +218,9 @@ public:
Int32 GetExtendedErrorCode() const
{
// Validate the handle
if (Validate())
return m_Handle.ExErrNo();
// Request failed
return -1;
Validate();
// Return the requested information
return m_Handle.ExErrNo();
}
/* --------------------------------------------------------------------------------------------
@ -232,10 +229,9 @@ public:
CSStr GetErrStr() const
{
// Validate the handle
if (Validate())
return m_Handle.ErrStr();
// Request failed
return _SC("");
Validate();
// Return the requested information
return m_Handle.ErrStr();
}
/* --------------------------------------------------------------------------------------------
@ -244,10 +240,9 @@ public:
CSStr GetErrMsg() const
{
// Validate the handle
if (Validate())
return m_Handle.ErrMsg();
// Request failed
return _SC("");
Validate();
// Return the requested information
return m_Handle.ErrMsg();
}
/* --------------------------------------------------------------------------------------------
@ -256,10 +251,9 @@ public:
Int32 GetColumns() const
{
// Validate the handle
if (Validate())
return m_Handle->mColumns;
// Request failed
return -1;
Validate();
// Return the requested information
return m_Handle->mColumns;
}
/* --------------------------------------------------------------------------------------------
@ -268,10 +262,9 @@ public:
CSStr GetQuery() const
{
// Validate the handle
if (Validate())
return m_Handle->mQuery.c_str();
// Request failed
return _SC("");
Validate();
// Return the requested information
return m_Handle->mQuery.c_str();
}
/* --------------------------------------------------------------------------------------------
@ -280,10 +273,9 @@ public:
bool GetGood() const
{
// Validate the handle
if (Validate())
return m_Handle->mGood;
// Request failed
return false;
Validate();
// Return the requested information
return m_Handle->mGood;
}
/* --------------------------------------------------------------------------------------------
@ -292,10 +284,9 @@ public:
bool GetDone() const
{
// Validate the handle
if (Validate())
return m_Handle->mDone;
// Request failed
return false;
Validate();
// Return the requested information
return m_Handle->mDone;
}
/* --------------------------------------------------------------------------------------------