1
0
mirror of https://github.com/VCMP-SqMod/SqMod.git synced 2025-09-18 10:17:19 +02:00

Fixed excpetion throwing in SQLite document to that generated corrupted messages because snprintf was used instead of vsnprintf.

Revised most of the SQLite plugin and cleaned code.
This commit is contained in:
Sandu Liviu Catalin
2016-04-02 12:11:14 +03:00
parent b6466b9181
commit fab15840cb
9 changed files with 524 additions and 310 deletions

View File

@@ -17,14 +17,6 @@ SQInteger Connection::Typename(HSQUIRRELVM vm)
return 1;
}
// ------------------------------------------------------------------------------------------------
void Connection::Validate() const
{
// Is the handle valid?
if (!m_Handle)
STHROWF("Invalid SQLite connection reference");
}
// ------------------------------------------------------------------------------------------------
Connection::Connection()
: m_Handle()
@@ -37,7 +29,9 @@ Connection::Connection(CSStr name)
: m_Handle(name)
{
if (m_Handle.m_Hnd)
m_Handle->Create(name, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, NULL);
{
m_Handle->Create(name, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, nullptr);
}
}
// ------------------------------------------------------------------------------------------------
@@ -45,7 +39,9 @@ Connection::Connection(CSStr name, Int32 flags)
: m_Handle(name)
{
if (m_Handle.m_Hnd)
m_Handle->Create(name, flags, NULL);
{
m_Handle->Create(name, flags, nullptr);
}
}
// ------------------------------------------------------------------------------------------------
@@ -53,17 +49,21 @@ Connection::Connection(CSStr name, Int32 flags, CSStr vfs)
: m_Handle(name)
{
if (m_Handle.m_Hnd)
{
m_Handle->Create(name, flags, vfs);
}
}
// ------------------------------------------------------------------------------------------------
Int32 Connection::Exec(CSStr str)
{
// Validate the handle
Validate();
m_Handle.Validate();
// Attempt to execute the specified query
if ((m_Handle = sqlite3_exec(m_Handle, str, NULL, NULL, NULL)) != SQLITE_OK)
if ((m_Handle = sqlite3_exec(m_Handle, str, nullptr, nullptr, nullptr)) != SQLITE_OK)
{
STHROWF("Unable to execute query [%s]", m_Handle.ErrMsg());
}
// Return rows affected by this query
return sqlite3_changes(m_Handle);
}
@@ -72,7 +72,7 @@ Int32 Connection::Exec(CSStr str)
Object Connection::Query(CSStr str) const
{
// Validate the handle
Validate();
m_Handle.Validate();
// Return the requested information
return Object(new Statement(m_Handle, str));
}
@@ -81,10 +81,12 @@ Object Connection::Query(CSStr str) const
void Connection::Queue(CSStr str)
{
// Validate the handle
Validate();
m_Handle.Validate();
// Is there a query to commit?
if (IsQueryEmpty(str))
{
STHROWF("No query string to queue");
}
// Add the specified string to the queue
m_Handle->mQueue.push_back(str);
}
@@ -93,12 +95,14 @@ void Connection::Queue(CSStr str)
bool Connection::IsReadOnly() const
{
// Validate the handle
Validate();
m_Handle.Validate();
// Request the desired information
const int result = sqlite3_db_readonly(m_Handle, "main");
// Verify the result
if (result == -1)
{
STHROWF("'main' is not the name of a database on connection");
}
// Return the requested information
return (result != 1);
}
@@ -107,7 +111,7 @@ bool Connection::IsReadOnly() const
bool Connection::TableExists(CCStr name) const
{
// Validate the handle
Validate();
m_Handle.Validate();
// Prepare a statement to inspect the master table
Statement stmt(m_Handle, "SELECT count(*) FROM [sqlite_master] WHERE [type]='table' AND [name]=?");
// Could the statement be created?
@@ -117,7 +121,9 @@ bool Connection::TableExists(CCStr name) const
stmt.IndexBindS(1, name);
// Attempt to step the statement and obtain a value
if (stmt.Step())
{
return (sqlite3_column_int(stmt, 0) == 1);
}
}
// Assume it doesn't exist
return false;
@@ -127,7 +133,7 @@ bool Connection::TableExists(CCStr name) const
Object Connection::GetLastInsertRowID() const
{
// Validate the handle
Validate();
m_Handle.Validate();
// Obtain the initial stack size
const StackGuard sg(_SqVM);
// Push a long integer instance with the requested value on the stack
@@ -140,26 +146,32 @@ Object Connection::GetLastInsertRowID() const
void Connection::SetBusyTimeout(Int32 millis)
{
// Validate the handle
Validate();
m_Handle.Validate();
// Apply requested timeout
if ((m_Handle = sqlite3_busy_timeout(m_Handle, millis)) != SQLITE_OK)
{
STHROWF("Unable to set busy timeout [%s]", m_Handle.ErrMsg());
}
}
// ------------------------------------------------------------------------------------------------
Int32 Connection::GetInfo(Int32 operation, bool highwater, bool reset)
{
// Don't even bother to continue if there's no valid connection handle
Validate();
m_Handle.Validate();
// Where to retrieve the information
Int32 cur_value;
Int32 hiwtr_value;
// Attempt to retrieve the specified information
if ((m_Handle = sqlite3_db_status(m_Handle, operation, &cur_value, &hiwtr_value, reset)) != SQLITE_OK)
{
STHROWF("Unable to get runtime status information", m_Handle.ErrMsg());
}
// Return the high-water value if requested
else if (highwater)
{
return hiwtr_value;
}
// Return the requested information
return cur_value;
}
@@ -168,7 +180,7 @@ Int32 Connection::GetInfo(Int32 operation, bool highwater, bool reset)
void Connection::ReserveQueue(Uint32 num)
{
// Validate the handle
Validate();
m_Handle.Validate();
// Perform the requested operation
m_Handle->mQueue.reserve(m_Handle->mQueue.size() + num);
}
@@ -177,7 +189,7 @@ void Connection::ReserveQueue(Uint32 num)
Int32 Connection::Flush(Uint32 num)
{
// Validate the handle
Validate();
m_Handle.Validate();
// We need to supply a null callback
Object env;
Function func;
@@ -189,7 +201,7 @@ Int32 Connection::Flush(Uint32 num)
Int32 Connection::Flush(Uint32 num, Object & env, Function & func)
{
// Validate the handle
Validate();
m_Handle.Validate();
// Attempt to flush the requested amount of queries
return m_Handle->Flush(num, env, func);
}
@@ -232,56 +244,21 @@ SQInteger Connection::ExecF(HSQUIRRELVM vm)
return sq_throwerror(vm, "Invalid SQLite connection instance");
}
// Do we have a valid connection identifier?
else if (!conn->m_Handle)
else if (!(conn->m_Handle))
{
return sq_throwerror(vm, "Invalid SQLite connection reference");
}
// Do we have enough values to call the format function?
else if (top > 2)
// Attempt to retrieve the value from the stack as a string
StackStrF val(vm, 2);
// Have we failed to retrieve the string?
if (SQ_FAILED(val.mRes))
{
SStr sql = NULL;
SQInteger len = 0;
// Attempt to generate the specified string format
SQRESULT ret = sqstd_format(vm, 2, &len, &sql);
// Did the format failed?
if (SQ_FAILED(ret))
{
return ret; // Propagate the exception
}
// Attempt to execute the specified query
else if ((conn->m_Handle = sqlite3_exec(conn->m_Handle, sql, NULL, NULL, NULL)) != SQLITE_OK)
{
// Generate the query message first
String msg("Unable to execute query ");
// (we can't use FmtStr here because Squirrel doesn't make a copy of the message)
msg.push_back('[');
msg.append(conn->m_Handle.ErrMsg());
msg.push_back(']');
// Now throw the message
return sq_throwerror(vm, msg.c_str());
}
return val.mRes; // Propagate the error!
}
else
// Attempt to execute the specified query
else if ((conn->m_Handle = sqlite3_exec(conn->m_Handle, val.mPtr, nullptr, nullptr, nullptr)) != SQLITE_OK)
{
// Attempt to retrieve the value from the stack as a string
Var< CSStr > sql(vm, 2);
// See if the obtained value is a valid query string
if (!sql.value)
{
return sq_throwerror(vm, "Unable to retrieve the query");
}
// Attempt to execute the specified query
else if ((conn->m_Handle = sqlite3_exec(conn->m_Handle, sql.value, NULL, NULL, NULL)) != SQLITE_OK)
{
// Generate the query message first
String msg("Unable to execute query ");
// (we can't use FmtStr here because Squirrel doesn't make a copy of the message)
msg.push_back('[');
msg.append(conn->m_Handle.ErrMsg());
msg.push_back(']');
// Now throw the message
return sq_throwerror(vm, msg.c_str());
}
return sq_throwerror(vm, FmtStr("Unable to execute query [%s]", conn->m_Handle.ErrMsg()));
}
// Push the number of changes onto the stack
sq_pushinteger(vm, sqlite3_changes(conn->m_Handle));
@@ -316,37 +293,19 @@ SQInteger Connection::QueueF(HSQUIRRELVM vm)
return sq_throwerror(vm, "Invalid SQLite connection instance");
}
// Do we have a valid connection identifier?
else if (!conn->m_Handle)
else if (!(conn->m_Handle))
{
return sq_throwerror(vm, "Invalid SQLite connection reference");
}
// Do we have enough values to call the format function?
else if (top > 2)
// Attempt to retrieve the value from the stack as a string
StackStrF val(vm, 2);
// Have we failed to retrieve the string?
if (SQ_FAILED(val.mRes))
{
SStr sql = NULL;
SQInteger len = 0;
// Attempt to generate the specified string format
SQRESULT ret = sqstd_format(vm, 2, &len, &sql);
// Did the format failed?
if (SQ_FAILED(ret))
{
return ret; // Propagate the exception
}
// Attempt to queue the specified query
conn->m_Handle->mQueue.emplace_back(sql);
}
else
{
// Attempt to retrieve the value from the stack as a string
Var< CSStr > sql(vm, 2);
// See if the obtained value is a valid query string
if (!sql.value)
{
return sq_throwerror(vm, "Unable to retrieve the query");
}
// Attempt to queue the specified query
conn->m_Handle->mQueue.emplace_back(sql.value);
return val.mRes; // Propagate the error!
}
// Attempt to queue the specified query
conn->m_Handle->mQueue.emplace_back(val.mPtr);
// This function does not return a value
return 0;
}
@@ -378,50 +337,25 @@ SQInteger Connection::QueryF(HSQUIRRELVM vm)
return sq_throwerror(vm, "Invalid SQLite connection instance");
}
// Do we have a valid connection identifier?
else if (!conn->m_Handle)
else if (!(conn->m_Handle))
{
return sq_throwerror(vm, "Invalid SQLite connection reference");
}
// Do we have enough values to call the format function?
else if (top > 2)
// Attempt to retrieve the value from the stack as a string
StackStrF val(vm, 2);
// Have we failed to retrieve the string?
if (SQ_FAILED(val.mRes))
{
SStr sql = NULL;
SQInteger len = 0;
// Attempt to generate the specified string format
SQRESULT ret = sqstd_format(vm, 2, &len, &sql);
// Did the format failed?
if (SQ_FAILED(ret))
{
return ret; // Propagate the exception
}
// Attempt to create a statement with the specified query
try
{
ClassType< Statement >::PushInstance(vm, new Statement(conn->m_Handle, sql));
}
catch (const Sqrat::Exception & e)
{
return sq_throwerror(vm, e.Message().c_str());
}
return val.mRes; // Propagate the error!
}
else
// Attempt to create a statement with the specified query
try
{
// Attempt to retrieve the value from the stack as a string
Var< CSStr > sql(vm, 2);
// See if the obtained value is a valid query string
if (!sql.value)
{
return sq_throwerror(vm, "Unable to retrieve the query");
}
// Attempt to create a statement with the specified query
try
{
ClassType< Statement >::PushInstance(vm, new Statement(conn->m_Handle, sql.value));
}
catch (const Sqrat::Exception & e)
{
return sq_throwerror(vm, e.Message().c_str());
}
ClassType< Statement >::PushInstance(vm, new Statement(conn->m_Handle, val.mPtr));
}
catch (const Sqrat::Exception & e)
{
return sq_throwerror(vm, e.Message().c_str());
}
// This function returned a value
return 1;