diff --git a/dDatabase/GameDatabase/MySQL/MySQLDatabase.h b/dDatabase/GameDatabase/MySQL/MySQLDatabase.h index 5b26a075..b481877c 100644 --- a/dDatabase/GameDatabase/MySQL/MySQLDatabase.h +++ b/dDatabase/GameDatabase/MySQL/MySQLDatabase.h @@ -9,8 +9,8 @@ typedef std::unique_ptr& UniquePreppedStmtRef; typedef std::unique_ptr UniqueResultSet; -// Holds a PreparedStatement and its ResultSet together to ensure the statement -// outlives the result. +// This struct is used to keep the PreparedStatement alive alongside the ResultSet, since the ResultSet will be invalidated if the PreparedStatement is destroyed. +// Declaring the members in reverse order of usage to ensure the PreparedStatement is destroyed after the ResultSet. This is guaranteed by the C++ standard. struct PreparedStmtResultSet { std::unique_ptr m_stmt; std::unique_ptr m_resultSet; @@ -18,14 +18,6 @@ struct PreparedStmtResultSet { PreparedStmtResultSet(sql::PreparedStatement* stmt = nullptr, sql::ResultSet* resultSet = nullptr) : m_stmt(stmt), m_resultSet(resultSet) {} - PreparedStmtResultSet(PreparedStmtResultSet&&) = default; - PreparedStmtResultSet& operator=(PreparedStmtResultSet&&) = default; - - ~PreparedStmtResultSet() { - m_resultSet.reset(); - m_stmt.reset(); - } - sql::ResultSet* operator->() const { return m_resultSet.get(); } @@ -161,12 +153,12 @@ private: // The return type is a PreparedStmtResultSet which keeps the PreparedStatement alive alongside the ResultSet. template inline PreparedStmtResultSet ExecuteSelect(const std::string& query, Args&&... args) { - std::unique_ptr preppedStmt(CreatePreppedStmt(query)); - SetParams(preppedStmt, std::forward(args)...); - std::unique_ptr resultSet; - DLU_SQL_TRY_CATCH_RETHROW(resultSet.reset(preppedStmt->executeQuery())); - // Release ownership of the pointers to the PreparedStatement and ResultSet to the PreparedStmtResultSet struct, which will ensure they are properly cleaned up. - return PreparedStmtResultSet(preppedStmt.release(), resultSet.release()); + PreparedStmtResultSet toReturn; + toReturn.m_stmt.reset(CreatePreppedStmt(query)); + SetParams(toReturn.m_stmt, std::forward(args)...); + DLU_SQL_TRY_CATCH_RETHROW(toReturn.m_resultSet.reset(toReturn.m_stmt->executeQuery())); + // Return the PreparedStmtResultSet, which now owns both the PreparedStatement and ResultSet via unique_ptr and will ensure they are properly cleaned up. + return toReturn; } template