mirror of
https://github.com/VCMP-SqMod/SqMod.git
synced 2024-11-14 11:47:15 +01:00
4d77386b21
Separate the SQLite handles into their own source files.
117 lines
3.7 KiB
C++
117 lines
3.7 KiB
C++
// ------------------------------------------------------------------------------------------------
|
|
#include "Handle/Statement.hpp"
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
namespace SqMod {
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
void StmtHnd::Validate() const
|
|
{
|
|
// Is the handle valid?
|
|
if ((m_Hnd == nullptr) || (m_Hnd->mPtr == nullptr))
|
|
{
|
|
STHROWF("Invalid SQLite statement reference");
|
|
}
|
|
}
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
StmtHnd::Handle::~Handle()
|
|
{
|
|
// Is there anything to finalize?
|
|
if (!mPtr)
|
|
{
|
|
return; // Nothing to finalize
|
|
}
|
|
// Are we dealing with a memory leak? Technically shouldn't reach this situation!
|
|
else if (mRef != 0)
|
|
{
|
|
// Should we deal with undefined behavior instead? How bad is one statement left alive?
|
|
_SqMod->LogErr("SQLite statement is still referenced (%s)", mQuery.c_str());
|
|
}
|
|
else
|
|
{
|
|
// Attempt to finalize the statement
|
|
if ((sqlite3_finalize(mPtr)) != SQLITE_OK)
|
|
{
|
|
_SqMod->LogErr("Unable to finalize SQLite statement [%s]", mConn.ErrMsg());
|
|
}
|
|
}
|
|
}
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
void StmtHnd::Handle::Create(CSStr query)
|
|
{
|
|
// Make sure a previous statement doesn't exist
|
|
if (mPtr)
|
|
{
|
|
STHROWF("Unable to prepare statement. Statement already prepared");
|
|
}
|
|
// Is the specified database connection is valid?
|
|
else if (!mConn)
|
|
{
|
|
STHROWF("Unable to prepare statement. Invalid connection handle");
|
|
}
|
|
// Save the query string and therefore multiple strlen(...) calls
|
|
mQuery.assign(query ? query : _SC(""));
|
|
// Is the specified query string we just saved, valid?
|
|
if (mQuery.empty())
|
|
{
|
|
STHROWF("Unable to prepare statement. Invalid query string");
|
|
}
|
|
// Attempt to prepare a statement with the specified query string
|
|
else if ((mStatus = sqlite3_prepare_v2(mConn, mQuery.c_str(), (Int32)mQuery.size(),
|
|
&mPtr, nullptr)) != SQLITE_OK)
|
|
{
|
|
// Clear the query string since it failed
|
|
mQuery.clear();
|
|
// Explicitly make sure the handle is null
|
|
mPtr = nullptr;
|
|
// Now it's safe to throw the error
|
|
STHROWF("Unable to prepare statement [%s]", mConn.ErrMsg());
|
|
}
|
|
else
|
|
{
|
|
// Obtain the number of available columns
|
|
mColumns = sqlite3_column_count(mPtr);
|
|
}
|
|
}
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
Int32 StmtHnd::Handle::GetColumnIndex(CSStr name)
|
|
{
|
|
// Validate the handle
|
|
if (!mPtr)
|
|
{
|
|
STHROWF("Invalid SQLite statement");
|
|
}
|
|
// Are the names cached?
|
|
else if (mIndexes.empty())
|
|
{
|
|
for (Int32 i = 0; i < mColumns; ++i)
|
|
{
|
|
// Get the column name at the current index
|
|
CSStr name = (CSStr)sqlite3_column_name(mPtr, i);
|
|
// Validate the name
|
|
if (!name)
|
|
{
|
|
STHROWF("Unable to retrieve column name for index (%d)", i);
|
|
}
|
|
// Save it to guarantee the same lifetime as this instance
|
|
else
|
|
{
|
|
mIndexes[name] = i;
|
|
}
|
|
}
|
|
}
|
|
// Attempt to find the specified column
|
|
const Indexes::iterator itr = mIndexes.find(name);
|
|
// Was there a column with the specified name?
|
|
if (itr != mIndexes.end())
|
|
{
|
|
return itr->second;
|
|
}
|
|
// No such column exists (expecting the invoker to validate the result)
|
|
return -1;
|
|
}
|
|
|
|
} // Namespace:: SqMod
|