diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/server/shared/Database/Transaction.cpp | 69 | ||||
-rw-r--r-- | src/server/shared/Database/Transaction.h | 27 |
2 files changed, 79 insertions, 17 deletions
diff --git a/src/server/shared/Database/Transaction.cpp b/src/server/shared/Database/Transaction.cpp index 93dc8fdc195..e45717864cf 100644 --- a/src/server/shared/Database/Transaction.cpp +++ b/src/server/shared/Database/Transaction.cpp @@ -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; } diff --git a/src/server/shared/Database/Transaction.h b/src/server/shared/Database/Transaction.h index 58c87b61270..cd749b0c2d7 100644 --- a/src/server/shared/Database/Transaction.h +++ b/src/server/shared/Database/Transaction.h @@ -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; |