diff options
author | ariel- <ariel-@users.noreply.github.com> | 2017-03-01 22:20:53 -0300 |
---|---|---|
committer | Shauren <shauren.trinity@gmail.com> | 2019-08-17 20:04:14 +0200 |
commit | d131bd1da0bf1b835ef912713dd7444361aa0089 (patch) | |
tree | eaf996d245eb0d7b1ad525841050a1fb4336dbb9 /src/server/database/Database/MySQLConnection.cpp | |
parent | 60663d1374beef3103f4787152654034fa4a8897 (diff) |
Core/Database: Prepared statement parameter preallocation (#18999)
- Pass prepared statement size to the helper class to prevent runtime resizing.
- Rename CheckValidIndex -> AssertValidIndex
- Cached prepared size on the worker pool as it's shared among all connections
- Cached query data only for each connection, done lookup in map instead of possibly creating a new element
- Kill the prepared statement map, and store raw sql string on the MySQLPreparedStatement class
(This info is only used for logging, and there is no need of keeping a second container just for it)
(cherrypicked from affee140c6a8e1e9358be2aa0d0088ede218acaa)
Diffstat (limited to 'src/server/database/Database/MySQLConnection.cpp')
-rw-r--r-- | src/server/database/Database/MySQLConnection.cpp | 141 |
1 files changed, 66 insertions, 75 deletions
diff --git a/src/server/database/Database/MySQLConnection.cpp b/src/server/database/Database/MySQLConnection.cpp index 229081a3ce0..cf953015d19 100644 --- a/src/server/database/Database/MySQLConnection.cpp +++ b/src/server/database/Database/MySQLConnection.cpp @@ -199,105 +199,100 @@ bool MySQLConnection::Execute(PreparedStatementBase* stmt) return false; uint32 index = stmt->m_index; - { - MySQLPreparedStatement* m_mStmt = GetPreparedStatement(index); - ASSERT(m_mStmt); // Can only be null if preparation failed, server side error or bad query - m_mStmt->m_stmt = stmt; // Cross reference them for debug output - stmt->m_stmt = m_mStmt; /// @todo Cleaner way - - stmt->BindParameters(); - MYSQL_STMT* msql_STMT = m_mStmt->GetSTMT(); - MYSQL_BIND* msql_BIND = m_mStmt->GetBind(); + MySQLPreparedStatement* m_mStmt = GetPreparedStatement(index); + ASSERT(m_mStmt); // Can only be null if preparation failed, server side error or bad query + m_mStmt->m_stmt = stmt; // Cross reference them for debug output - uint32 _s = getMSTime(); + stmt->BindParameters(m_mStmt); - if (mysql_stmt_bind_param(msql_STMT, msql_BIND)) - { - uint32 lErrno = mysql_errno(m_Mysql); - TC_LOG_ERROR("sql.sql", "SQL(p): %s\n [ERROR]: [%u] %s", m_mStmt->getQueryString(m_queries[index].first).c_str(), lErrno, mysql_stmt_error(msql_STMT)); + MYSQL_STMT* msql_STMT = m_mStmt->GetSTMT(); + MYSQL_BIND* msql_BIND = m_mStmt->GetBind(); - if (_HandleMySQLErrno(lErrno)) // If it returns true, an error was handled successfully (i.e. reconnection) - return Execute(stmt); // Try again + uint32 _s = getMSTime(); - m_mStmt->ClearParameters(); - return false; - } + if (mysql_stmt_bind_param(msql_STMT, msql_BIND)) + { + uint32 lErrno = mysql_errno(m_Mysql); + TC_LOG_ERROR("sql.sql", "SQL(p): %s\n [ERROR]: [%u] %s", m_mStmt->getQueryString().c_str(), lErrno, mysql_stmt_error(msql_STMT)); - if (mysql_stmt_execute(msql_STMT)) - { - uint32 lErrno = mysql_errno(m_Mysql); - TC_LOG_ERROR("sql.sql", "SQL(p): %s\n [ERROR]: [%u] %s", m_mStmt->getQueryString(m_queries[index].first).c_str(), lErrno, mysql_stmt_error(msql_STMT)); + if (_HandleMySQLErrno(lErrno)) // If it returns true, an error was handled successfully (i.e. reconnection) + return Execute(stmt); // Try again - if (_HandleMySQLErrno(lErrno)) // If it returns true, an error was handled successfully (i.e. reconnection) - return Execute(stmt); // Try again + m_mStmt->ClearParameters(); + return false; + } - m_mStmt->ClearParameters(); - return false; - } + if (mysql_stmt_execute(msql_STMT)) + { + uint32 lErrno = mysql_errno(m_Mysql); + TC_LOG_ERROR("sql.sql", "SQL(p): %s\n [ERROR]: [%u] %s", m_mStmt->getQueryString().c_str(), lErrno, mysql_stmt_error(msql_STMT)); - TC_LOG_DEBUG("sql.sql", "[%u ms] SQL(p): %s", getMSTimeDiff(_s, getMSTime()), m_mStmt->getQueryString(m_queries[index].first).c_str()); + if (_HandleMySQLErrno(lErrno)) // If it returns true, an error was handled successfully (i.e. reconnection) + return Execute(stmt); // Try again m_mStmt->ClearParameters(); - return true; + return false; } + + TC_LOG_DEBUG("sql.sql", "[%u ms] SQL(p): %s", getMSTimeDiff(_s, getMSTime()), m_mStmt->getQueryString().c_str()); + + m_mStmt->ClearParameters(); + return true; } -bool MySQLConnection::_Query(PreparedStatementBase* stmt, MYSQL_RES **pResult, uint64* pRowCount, uint32* pFieldCount) +bool MySQLConnection::_Query(PreparedStatementBase* stmt, MYSQL_RES** pResult, uint64* pRowCount, uint32* pFieldCount) { if (!m_Mysql) return false; uint32 index = stmt->m_index; - { - MySQLPreparedStatement* m_mStmt = GetPreparedStatement(index); - ASSERT(m_mStmt); // Can only be null if preparation failed, server side error or bad query - m_mStmt->m_stmt = stmt; // Cross reference them for debug output - stmt->m_stmt = m_mStmt; /// @todo Cleaner way - - stmt->BindParameters(); - MYSQL_STMT* msql_STMT = m_mStmt->GetSTMT(); - MYSQL_BIND* msql_BIND = m_mStmt->GetBind(); + MySQLPreparedStatement* m_mStmt = GetPreparedStatement(index); + ASSERT(m_mStmt); // Can only be null if preparation failed, server side error or bad query + m_mStmt->m_stmt = stmt; // Cross reference them for debug output - uint32 _s = getMSTime(); + stmt->BindParameters(m_mStmt); - if (mysql_stmt_bind_param(msql_STMT, msql_BIND)) - { - uint32 lErrno = mysql_errno(m_Mysql); - TC_LOG_ERROR("sql.sql", "SQL(p): %s\n [ERROR]: [%u] %s", m_mStmt->getQueryString(m_queries[index].first).c_str(), lErrno, mysql_stmt_error(msql_STMT)); + MYSQL_STMT* msql_STMT = m_mStmt->GetSTMT(); + MYSQL_BIND* msql_BIND = m_mStmt->GetBind(); - if (_HandleMySQLErrno(lErrno)) // If it returns true, an error was handled successfully (i.e. reconnection) - return _Query(stmt, pResult, pRowCount, pFieldCount); // Try again + uint32 _s = getMSTime(); - m_mStmt->ClearParameters(); - return false; - } + if (mysql_stmt_bind_param(msql_STMT, msql_BIND)) + { + uint32 lErrno = mysql_errno(m_Mysql); + TC_LOG_ERROR("sql.sql", "SQL(p): %s\n [ERROR]: [%u] %s", m_mStmt->getQueryString().c_str(), lErrno, mysql_stmt_error(msql_STMT)); - if (mysql_stmt_execute(msql_STMT)) - { - uint32 lErrno = mysql_errno(m_Mysql); - TC_LOG_ERROR("sql.sql", "SQL(p): %s\n [ERROR]: [%u] %s", - m_mStmt->getQueryString(m_queries[index].first).c_str(), lErrno, mysql_stmt_error(msql_STMT)); + if (_HandleMySQLErrno(lErrno)) // If it returns true, an error was handled successfully (i.e. reconnection) + return _Query(stmt, pResult, pRowCount, pFieldCount); // Try again - if (_HandleMySQLErrno(lErrno)) // If it returns true, an error was handled successfully (i.e. reconnection) - return _Query(stmt, pResult, pRowCount, pFieldCount); // Try again + m_mStmt->ClearParameters(); + return false; + } - m_mStmt->ClearParameters(); - return false; - } + if (mysql_stmt_execute(msql_STMT)) + { + uint32 lErrno = mysql_errno(m_Mysql); + TC_LOG_ERROR("sql.sql", "SQL(p): %s\n [ERROR]: [%u] %s", + m_mStmt->getQueryString().c_str(), lErrno, mysql_stmt_error(msql_STMT)); - TC_LOG_DEBUG("sql.sql", "[%u ms] SQL(p): %s", getMSTimeDiff(_s, getMSTime()), m_mStmt->getQueryString(m_queries[index].first).c_str()); + if (_HandleMySQLErrno(lErrno)) // If it returns true, an error was handled successfully (i.e. reconnection) + return _Query(stmt, pResult, pRowCount, pFieldCount); // Try again m_mStmt->ClearParameters(); + return false; + } - *pResult = mysql_stmt_result_metadata(msql_STMT); - *pRowCount = mysql_stmt_num_rows(msql_STMT); - *pFieldCount = mysql_stmt_field_count(msql_STMT); + TC_LOG_DEBUG("sql.sql", "[%u ms] SQL(p): %s", getMSTimeDiff(_s, getMSTime()), m_mStmt->getQueryString().c_str()); - return true; + m_mStmt->ClearParameters(); - } + *pResult = mysql_stmt_result_metadata(msql_STMT); + *pRowCount = mysql_stmt_num_rows(msql_STMT); + *pFieldCount = mysql_stmt_field_count(msql_STMT); + + return true; } ResultSet* MySQLConnection::Query(const char* sql) @@ -454,10 +449,8 @@ MySQLPreparedStatement* MySQLConnection::GetPreparedStatement(uint32 index) return ret; } -void MySQLConnection::PrepareStatement(uint32 index, const char* sql, ConnectionFlags flags) +void MySQLConnection::PrepareStatement(uint32 index, std::string const& sql, ConnectionFlags flags) { - m_queries.insert(PreparedStatementMap::value_type(index, std::make_pair(sql, flags))); - // Check if specified query should be prepared on this connection // i.e. don't prepare async statements on synchronous connections // to save memory that will not be used. @@ -470,23 +463,21 @@ void MySQLConnection::PrepareStatement(uint32 index, const char* sql, Connection MYSQL_STMT* stmt = mysql_stmt_init(m_Mysql); if (!stmt) { - TC_LOG_ERROR("sql.sql", "In mysql_stmt_init() id: %u, sql: \"%s\"", index, sql); + TC_LOG_ERROR("sql.sql", "In mysql_stmt_init() id: %u, sql: \"%s\"", index, sql.c_str()); TC_LOG_ERROR("sql.sql", "%s", mysql_error(m_Mysql)); m_prepareError = true; } else { - if (mysql_stmt_prepare(stmt, sql, static_cast<unsigned long>(strlen(sql)))) + if (mysql_stmt_prepare(stmt, sql.c_str(), static_cast<unsigned long>(sql.size()))) { - TC_LOG_ERROR("sql.sql", "In mysql_stmt_prepare() id: %u, sql: \"%s\"", index, sql); + TC_LOG_ERROR("sql.sql", "In mysql_stmt_prepare() id: %u, sql: \"%s\"", index, sql.c_str()); TC_LOG_ERROR("sql.sql", "%s", mysql_stmt_error(stmt)); mysql_stmt_close(stmt); m_prepareError = true; } else - { - m_stmts[index] = Trinity::make_unique<MySQLPreparedStatement>(stmt); - } + m_stmts[index] = Trinity::make_unique<MySQLPreparedStatement>(stmt, sql); } } |