diff --git a/src/engine/server/databases/connection.h b/src/engine/server/databases/connection.h index 0fb16366e..6ed6ce63e 100644 --- a/src/engine/server/databases/connection.h +++ b/src/engine/server/databases/connection.h @@ -26,6 +26,8 @@ public: // explicitly convert before inserting timestamps, NOTE: CURRENT_TIMESTAMP in SQLite is UTC by // default and doesn't have to be converted virtual const char *InsertTimestampAsUtc() const = 0; + // can be used in the context of `LIKE Map`, adds `? COLLATE` + virtual const char *CollateNocase() const = 0; enum Status { diff --git a/src/engine/server/databases/mysql.h b/src/engine/server/databases/mysql.h index f99cc816b..4c1e6e4b9 100644 --- a/src/engine/server/databases/mysql.h +++ b/src/engine/server/databases/mysql.h @@ -31,6 +31,7 @@ public: virtual const char *BinaryCollate() const { return "utf8mb4_bin"; } virtual void ToUnixTimestamp(const char *pTimestamp, char *aBuf, unsigned int BufferSize); virtual const char *InsertTimestampAsUtc() const { return "?"; } + virtual const char *CollateNocase() const { return "CONVERT(? USING utf8mb4) COLLATE utf8mb4_general_ci"; } virtual Status Connect(); virtual void Disconnect(); diff --git a/src/engine/server/databases/sqlite.h b/src/engine/server/databases/sqlite.h index 186c9fdbe..fda14f2fb 100644 --- a/src/engine/server/databases/sqlite.h +++ b/src/engine/server/databases/sqlite.h @@ -18,6 +18,7 @@ public: virtual const char *BinaryCollate() const { return "BINARY"; } virtual void ToUnixTimestamp(const char *pTimestamp, char *aBuf, unsigned int BufferSize); virtual const char *InsertTimestampAsUtc() const { return "DATETIME(?, 'utc')"; } + virtual const char *CollateNocase() const { return "? COLLATE NOCASE"; } virtual Status Connect(); virtual void Disconnect(); diff --git a/src/game/server/score.cpp b/src/game/server/score.cpp index 0e5264fa8..d88529df5 100644 --- a/src/game/server/score.cpp +++ b/src/game/server/score.cpp @@ -291,13 +291,13 @@ bool CScore::MapVoteThread(IDbConnection *pSqlServer, const ISqlData *pGameData) str_format(aBuf, sizeof(aBuf), "SELECT Map, Server " "FROM %s_maps " - "WHERE Map LIKE convert(? using utf8mb4) COLLATE utf8mb4_general_ci " + "WHERE Map LIKE %s " "ORDER BY " "CASE WHEN Map = ? THEN 0 ELSE 1 END, " "CASE WHEN Map LIKE ? THEN 0 ELSE 1 END, " "LENGTH(Map), Map " "LIMIT 1;", - pSqlServer->GetPrefix()); + pSqlServer->GetPrefix(), pSqlServer->CollateNocase()); pSqlServer->PrepareStatement(aBuf); pSqlServer->BindString(1, aFuzzyMap); pSqlServer->BindString(2, pData->m_Name); @@ -362,7 +362,7 @@ bool CScore::MapInfoThread(IDbConnection *pSqlServer, const ISqlData *pGameData) "(SELECT MIN(Time) FROM %s_race WHERE Map = l.Map AND Name = ?) AS OwnTime " "FROM (" "SELECT * FROM %s_maps " - "WHERE Map LIKE convert(? using utf8mb4) COLLATE utf8mb4_general_ci " + "WHERE Map LIKE %s " "ORDER BY " "CASE WHEN Map = ? THEN 0 ELSE 1 END, " "CASE WHEN Map LIKE ? THEN 0 ELSE 1 END, " @@ -372,7 +372,8 @@ bool CScore::MapInfoThread(IDbConnection *pSqlServer, const ISqlData *pGameData) ") as l;", pSqlServer->GetPrefix(), pSqlServer->GetPrefix(), pSqlServer->GetPrefix(), aTimestamp, aCurrentTimestamp, aTimestamp, - pSqlServer->GetPrefix(), pSqlServer->GetPrefix() + pSqlServer->GetPrefix(), pSqlServer->GetPrefix(), + pSqlServer->CollateNocase() ); pSqlServer->PrepareStatement(aBuf); pSqlServer->BindString(1, pData->m_RequestingPlayer);