Core/DBLayer:

- Allow transactions to contain both raw ad-hoc queries and prepared statement elements
* When coding on high level code, just make sure you use the right argument type for Transaction::Append and the proper execution will be done automagically

--HG--
branch : trunk
This commit is contained in:
Machiavelli
2010-09-04 16:49:23 +02:00
parent fd1c6c5440
commit 27c00a8cbb
2 changed files with 79 additions and 17 deletions

View File

@@ -19,9 +19,13 @@
#include "DatabaseEnv.h"
#include "Transaction.h"
//- Append a raw ad-hoc query to the transaction
void Transaction::Append(const char* sql)
{
m_queries.push(strdup(sql));
TransactionElementData data;
data.type = TRANSACTION_ELEMENT_RAW;
data.element.query = strdup(sql);
m_queries.push(data);
}
void Transaction::PAppend(const char* sql, ...)
@@ -35,41 +39,74 @@ void Transaction::PAppend(const char* sql, ...)
Append(szQuery);
}
//- Append a prepared statement to the transaction
void Transaction::Append(PreparedStatement* stmt)
{
TransactionElementData data;
data.type = TRANSACTION_ELEMENT_PREPARED;
data.element.stmt = stmt;
m_queries.push(data);
}
void Transaction::Cleanup()
{
while (!m_queries.empty())
{
free((void*)const_cast<char*>(m_queries.front()));
TransactionElementData data = m_queries.front();
switch (data.type)
{
case TRANSACTION_ELEMENT_PREPARED:
delete data.element.stmt;
break;
case TRANSACTION_ELEMENT_RAW:
free((void*)(data.element.query));
break;
}
m_queries.pop();
}
}
bool TransactionTask::Execute()
{
std::queue<char*>& queries = m_trans->m_queries;
std::queue<TransactionElementData> &queries = m_trans->m_queries;
if (queries.empty())
return false;
const char* sql;
m_conn->BeginTransaction();
while (!queries.empty())
{
sql = queries.front();
ASSERT(sql);
if (!m_conn->Execute(sql))
TransactionElementData data = queries.front();
switch (data.type)
{
sLog.outSQLDriver("[Warning] Transaction aborted. %u queries not executed.", (uint32)queries.size());
free((void*)const_cast<char*>(sql));
queries.pop();
m_conn->RollbackTransaction();
return false;
case TRANSACTION_ELEMENT_PREPARED:
{
PreparedStatement* stmt = data.element.stmt;
ASSERT(stmt);
if (!m_conn->Execute(stmt))
{
sLog.outSQLDriver("[Warning] Transaction aborted. %u queries not executed.", (uint32)queries.size());
m_conn->RollbackTransaction();
return false;
}
delete data.element.stmt;
}
break;
case TRANSACTION_ELEMENT_RAW:
{
const char* sql = data.element.query;
ASSERT(sql)
if (!m_conn->Execute(sql))
{
sLog.outSQLDriver("[Warning] Transaction aborted. %u queries not executed.", (uint32)queries.size());
m_conn->RollbackTransaction();
return false;
}
free((void*)const_cast<char*>(sql));
}
break;
}
free((void*)const_cast<char*>(sql));
queries.pop();
}
m_conn->CommitTransaction();
return true;
}

View File

@@ -21,6 +21,30 @@
#include "SQLOperation.h"
//- Forward declare (don't include header to prevent circular includes)
class PreparedStatement;
//- Union that holds element data
union TransactionElementUnion
{
PreparedStatement* stmt;
const char* query;
};
//- Type specifier of our element data
enum TransactionElementDataType
{
TRANSACTION_ELEMENT_RAW,
TRANSACTION_ELEMENT_PREPARED,
};
//- The transaction element
struct TransactionElementData
{
TransactionElementUnion element;
TransactionElementDataType type;
};
/*! Transactions, high level class. */
class Transaction
{
@@ -28,6 +52,7 @@ class Transaction
public:
~Transaction() { Cleanup(); }
void Append(PreparedStatement* statement);
void Append(const char* sql);
void PAppend(const char* sql, ...);
@@ -35,7 +60,7 @@ class Transaction
protected:
void Cleanup();
std::queue<char*> m_queries;
std::queue<TransactionElementData> m_queries;
private:
bool m_actioned;