1
0
mirror of https://github.com/VCMP-SqMod/SqMod.git synced 2024-11-14 11:47:15 +01:00
SqMod/modules/sqlite/Handle/Statement.cpp
Sandu Liviu Catalin 4d77386b21 Update the SQLite module to work with the modified API.
Separate the SQLite handles into their own source files.
2016-06-03 21:31:00 +03:00

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