diff --git a/src/game/game.cpp b/src/game/game.cpp index a0256f37fdb..5ce501c8288 100644 --- a/src/game/game.cpp +++ b/src/game/game.cpp @@ -8533,58 +8533,64 @@ void Game::playerCyclopediaCharacterInfo(const std::shared_ptr &player, } } -std::string Game::generateHighscoreQueryForEntries(const std::string &categoryName, uint32_t page, uint8_t entriesPerPage, uint32_t vocation) { +std::string Game::generateHighscoreQuery( + const std::string &categoryName, + uint32_t page, + uint8_t entriesPerPage, + uint32_t vocation, + uint32_t playerGUID /*= 0*/ +) { uint32_t startPage = (page - 1) * static_cast(entriesPerPage); uint32_t endPage = startPage + static_cast(entriesPerPage); + std::string entriesStr = std::to_string(entriesPerPage); - std::string escapedCategoryName = g_database().escapeString(categoryName); + if (categoryName.empty()) { + g_logger().error("Category name cannot be empty."); + return ""; + } std::string query = fmt::format( - "SELECT `id`, `name`, `level`, `vocation`, `points`, `rank`, `entries`, {} AS `page` FROM (" - "SELECT `id`, `name`, `level`, `vocation`, `points`, `rank`, (@row := @row + 1) AS `entries` FROM (" - "SELECT `id`, `name`, `level`, `vocation`, {} AS `points`, " - "@curRank := IF(@prevRank = {}, @curRank, IF(@prevRank := {}, @curRank + 1, @curRank + 1)) AS `rank` " - "FROM `players` p, (SELECT @curRank := 0, @prevRank := NULL, @row := 0) r " - "WHERE `group_id` < {} ORDER BY {} DESC" - ") t", - page, categoryName, escapedCategoryName, escapedCategoryName, static_cast(GROUP_TYPE_GAMEMASTER), escapedCategoryName + "SELECT `id`, `name`, `level`, `vocation`, `points`, `rank`, `rn` AS `entries`, " ); - if (vocation != 0xFFFFFFFF) { - query += generateVocationConditionHighscore(vocation); + if (playerGUID != 0) { + query += fmt::format("(@ourRow DIV {0}) + 1 AS `page` FROM (", entriesStr); + } else { + query += fmt::format("{} AS `page` FROM (", page); } - query += fmt::format(") T WHERE `entries` > {} AND `entries` <= {}", startPage, endPage); - - return query; -} + query += fmt::format( + "SELECT `id`, `name`, `level`, `vocation`, `{}` AS `points`, " + "@curRank := IF(@prevRank = `{}`, @curRank, IF(@prevRank := `{}`, @curRank + 1, @curRank + 1)) AS `rank`, " + "(@row := @row + 1) AS `rn`", + categoryName, categoryName, categoryName + ); -std::string Game::generateHighscoreQueryForOurRank(const std::string &categoryName, uint8_t entriesPerPage, uint32_t playerGUID, uint32_t vocation) { - Database &db = Database::getInstance(); - std::string escapedCategoryName = db.escapeString(categoryName); - std::string entriesStr = std::to_string(entriesPerPage); + if (playerGUID != 0) { + query += fmt::format(", @ourRow := IF(`id` = {}, @row - 1, @ourRow) AS `rw`", playerGUID); + } - std::string query = fmt::format( - "SELECT `id`, `name`, `level`, `vocation`, `points`, `rank`, @row AS `entries`, " - "(@ourRow DIV {0}) + 1 AS `page` FROM (" - "SELECT `id`, `name`, `level`, `vocation`, `{1}` AS `points`, " - "@curRank := IF(@prevRank = `{1}`, @curRank, IF(@prevRank := `{1}`, @curRank + 1, @curRank + 1)) AS `rank`, " - "(@row := @row + 1) AS `rn`, @ourRow := IF(`id` = {2}, @row - 1, @ourRow) AS `rw` FROM (" - "SELECT `id`, `name`, `level`, `vocation`, `{1}` FROM `players` `p`, " + query += fmt::format( + " FROM (SELECT `id`, `name`, `level`, `vocation`, `{}` FROM `players` `p`, " "(SELECT @curRank := 0, @prevRank := NULL, @row := 0, @ourRow := 0) `r` " - "WHERE `group_id` < {3} ORDER BY `{1}` DESC" - ") `t`", - entriesStr, escapedCategoryName, playerGUID, static_cast(GROUP_TYPE_GAMEMASTER) + "WHERE `group_id` < {} ORDER BY `{}` DESC) `t`", + categoryName, static_cast(GROUP_TYPE_GAMEMASTER), categoryName ); if (vocation != 0xFFFFFFFF) { query += generateVocationConditionHighscore(vocation); } - query += fmt::format( - ") `T` WHERE `rn` > ((@ourRow DIV {0}) * {0}) AND `rn` <= (((@ourRow DIV {0}) * {0}) + {0})", - entriesStr - ); + query += ") `T` WHERE "; + + if (playerGUID != 0) { + query += fmt::format( + "`rn` > ((@ourRow DIV {0}) * {0}) AND `rn` <= (((@ourRow DIV {0}) * {0}) + {0})", + entriesStr + ); + } else { + query += fmt::format("`rn` > {} AND `rn` <= {}", startPage, endPage); + } return query; } @@ -8674,7 +8680,7 @@ std::string Game::generateHighscoreOrGetCachedQueryForEntries(const std::string } } - std::string newQuery = generateHighscoreQueryForEntries(categoryName, page, entriesPerPage, vocation); + std::string newQuery = generateHighscoreQuery(categoryName, page, entriesPerPage, vocation); cacheQueryHighscore(cacheKey, newQuery, page, entriesPerPage); return newQuery; @@ -8692,7 +8698,7 @@ std::string Game::generateHighscoreOrGetCachedQueryForOurRank(const std::string } } - std::string newQuery = generateHighscoreQueryForOurRank(categoryName, entriesPerPage, playerGUID, vocation); + std::string newQuery = generateHighscoreQuery(categoryName, 0, entriesPerPage, vocation, playerGUID); cacheQueryHighscore(cacheKey, newQuery, entriesPerPage, entriesPerPage); return newQuery; diff --git a/src/game/game.hpp b/src/game/game.hpp index a59c7d13a70..9a4b59f8a55 100644 --- a/src/game/game.hpp +++ b/src/game/game.hpp @@ -957,8 +957,13 @@ class Game { void processHighscoreResults(const DBResult_ptr &result, uint32_t playerID, uint8_t category, uint32_t vocation, uint8_t entriesPerPage); std::string generateVocationConditionHighscore(uint32_t vocation); - std::string generateHighscoreQueryForEntries(const std::string &categoryName, uint32_t page, uint8_t entriesPerPage, uint32_t vocation); - std::string generateHighscoreQueryForOurRank(const std::string &categoryName, uint8_t entriesPerPage, uint32_t playerGUID, uint32_t vocation); + std::string generateHighscoreQuery( + const std::string &categoryName, + uint32_t page, + uint8_t entriesPerPage, + uint32_t vocation, + uint32_t playerGUID = 0 + ); std::string generateHighscoreOrGetCachedQueryForEntries(const std::string &categoryName, uint32_t page, uint8_t entriesPerPage, uint32_t vocation); std::string generateHighscoreOrGetCachedQueryForOurRank(const std::string &categoryName, uint8_t entriesPerPage, uint32_t playerGUID, uint32_t vocation);