From 8d6e730bee4fc46f32dc69cda89b83a20ade9def Mon Sep 17 00:00:00 2001 From: rtldg <55846624+rtldg@users.noreply.github.com> Date: Wed, 10 Mar 2021 06:01:40 +0000 Subject: [PATCH] make my wrrank/wrcount queries work with mysql 5.6/5.7 also my DeleteWR() query that used variables to be fancy is unneeded and just breaks sqlite compatibility have you noticed that i've been winging it with all the sql stuff? --- addons/sourcemod/scripting/shavit-chat.sp | 69 ++++-- addons/sourcemod/scripting/shavit-stats.sp | 251 +++++++++++---------- addons/sourcemod/scripting/shavit-wr.sp | 81 +++---- 3 files changed, 221 insertions(+), 180 deletions(-) diff --git a/addons/sourcemod/scripting/shavit-chat.sp b/addons/sourcemod/scripting/shavit-chat.sp index f51c0f5f..609df24c 100644 --- a/addons/sourcemod/scripting/shavit-chat.sp +++ b/addons/sourcemod/scripting/shavit-chat.sp @@ -105,6 +105,7 @@ char gS_MySQLPrefix[32]; // modules bool gB_Rankings = false; +bool gB_Stats = false; bool gB_RTLer = false; // cvars @@ -599,6 +600,11 @@ public void OnLibraryAdded(const char[] name) { gB_Rankings = true; } + + else if(StrEqual(name, "shavit-stats")) + { + gB_Stats = true; + } } public void OnLibraryRemoved(const char[] name) @@ -612,6 +618,11 @@ public void OnLibraryRemoved(const char[] name) { gB_Rankings = false; } + + else if(StrEqual(name, "shavit-stats")) + { + gB_Stats = false; + } } public void OnClientCookiesCached(int client) @@ -1108,7 +1119,13 @@ bool HasRankAccess(int client, int rank) return true; } - if(!gB_Rankings || !gCV_RankingsIntegration.BoolValue) + if(/*!gB_Rankings ||*/ !gCV_RankingsIntegration.BoolValue) + { + return false; + } + + if ((!gB_Rankings && (cache.iRequire == Require_Rank || cache.iRequire == Require_Points)) + || (!gB_Stats && (cache.iRequire == Require_WR_Count || cache.iRequire == Require_WR_Rank))) { return false; } @@ -1151,6 +1168,11 @@ bool HasRankAccess(int client, int rank) fTotal = 1.0; } + if(fVal == 1.0 && (fTotal == 1.0 || cache.fFrom == cache.fTo)) + { + return true; + } + float fPercentile = (fVal / fTotal) * 100.0; if(cache.fFrom <= fPercentile <= cache.fTo) @@ -1281,19 +1303,19 @@ void FormatChat(int client, char[] buffer, int size) FormatColors(buffer, size, true, true); FormatRandom(buffer, size); + char temp[32]; + if(gEV_Type != Engine_TF2) { - char sTag[32]; - CS_GetClientClanTag(client, sTag, 32); - ReplaceString(buffer, size, "{clan}", sTag); + CS_GetClientClanTag(client, temp, 32); + ReplaceString(buffer, size, "{clan}", temp); } if(gB_Rankings) { int iRank = Shavit_GetRank(client); - char sRank[16]; - IntToString(iRank, sRank, 16); - ReplaceString(buffer, size, "{rank}", sRank); + IntToString(iRank, temp, 32); + ReplaceString(buffer, size, "{rank}", temp); int iRanked = Shavit_GetRankedPlayers(); @@ -1303,28 +1325,27 @@ void FormatChat(int client, char[] buffer, int size) } float fPercentile = (float(iRank) / iRanked) * 100.0; - FormatEx(sRank, 16, "%.01f", fPercentile); - ReplaceString(buffer, size, "{rank1}", sRank); + FormatEx(temp, 32, "%.01f", fPercentile); + ReplaceString(buffer, size, "{rank1}", temp); - FormatEx(sRank, 16, "%.02f", fPercentile); - ReplaceString(buffer, size, "{rank2}", sRank); + FormatEx(temp, 32, "%.02f", fPercentile); + ReplaceString(buffer, size, "{rank2}", temp); - FormatEx(sRank, 16, "%.03f", fPercentile); - ReplaceString(buffer, size, "{rank3}", sRank); + FormatEx(temp, 32, "%.03f", fPercentile); + ReplaceString(buffer, size, "{rank3}", temp); - FormatEx(sRank, 16, "%d", Shavit_GetWRCount(client)); - ReplaceString(buffer, size, "{wrs}", sRank); - - FormatEx(sRank, 16, "%0.f", Shavit_GetPoints(client)); - ReplaceString(buffer, size, "{pts}", sRank); - - FormatEx(sRank, 16, "%d", Shavit_GetWRHolderRank(client)); - ReplaceString(buffer, size, "{wrrank}", sRank); + FormatEx(temp, 32, "%0.f", Shavit_GetPoints(client)); + ReplaceString(buffer, size, "{pts}", temp); } - char sName[MAX_NAME_LENGTH]; - GetClientName(client, sName, MAX_NAME_LENGTH); - ReplaceString(buffer, size, "{name}", sName); + FormatEx(temp, 32, "%d", Shavit_GetWRHolderRank(client)); + ReplaceString(buffer, size, "{wrrank}", temp); + + FormatEx(temp, 32, "%d", Shavit_GetWRCount(client)); + ReplaceString(buffer, size, "{wrs}", temp); + + GetClientName(client, temp, 32); + ReplaceString(buffer, size, "{name}", temp); } void SQL_DBConnect() diff --git a/addons/sourcemod/scripting/shavit-stats.sp b/addons/sourcemod/scripting/shavit-stats.sp index 09aa50f2..cdf46b1a 100644 --- a/addons/sourcemod/scripting/shavit-stats.sp +++ b/addons/sourcemod/scripting/shavit-stats.sp @@ -87,6 +87,8 @@ public APLRes AskPluginLoad2(Handle myself, bool late, char[] error, int err_max { // natives CreateNative("Shavit_OpenStatsMenu", Native_OpenStatsMenu); + // TODO: Move to shavit-rankings in 3.0 + // These are only here because of the cvars but it should really be in rankings... CreateNative("Shavit_GetWRCount", Native_GetWRCount); CreateNative("Shavit_GetWRHolders", Native_GetWRHolders); CreateNative("Shavit_GetWRHolderRank", Native_GetWRHolderRank); @@ -126,6 +128,7 @@ public void OnPluginStart() HookEvent("player_team", Player_Event); // cvars + // TODO: Move to shavit-rankings in 3.0 gCV_MVPRankOnes = new Convar("shavit_stats_mvprankones", "2", "Set the players' amount of MVPs to the amount of #1 times they have.\n0 - Disabled\n1 - Enabled, for all styles.\n2 - Enabled, for default style only.\n(CS:S/CS:GO only)", 0, true, 0.0, true, 2.0); gCV_MVPRankOnes_Main = new Convar("shavit_stats_mvprankones_maintrack", "1", "If set to 0, all tracks will be counted for the MVP stars.\nOtherwise, only the main track will be checked.\n\nRequires \"shavit_stats_mvprankones\" set to 1 or above.\n(CS:S/CS:GO only)", 0, true, 0.0, true, 1.0); @@ -256,90 +259,22 @@ void UpdateWRs(int client) return; } - char sQuery[1666]; + char sQuery[512]; - // TODO: Replace with big sexy query that'll calc the stuff sql-side like below FormatEx(sQuery, sizeof(sQuery), - "SELECT a.track, a.style FROM %splayertimes a JOIN (SELECT MIN(time) time, map, track, style FROM %splayertimes GROUP BY map, track, style) b ON a.time = b.time AND a.map = b.map AND a.track = b.track AND a.style = b.style WHERE auth = %d;", - gS_MySQLPrefix, gS_MySQLPrefix, iSteamID); - + " SELECT *, 0 as track, 0 as type FROM wrhrankmain WHERE auth = %d \ + UNION SELECT *, 1 as track, 0 as type FROM wrhrankbonus WHERE auth = %d \ + UNION SELECT *, -1, 1 as type FROM wrhrankall WHERE auth = %d \ + UNION SELECT *, -1, 2 as type FROM wrhrankcvar WHERE auth = %d;", + iSteamID, iSteamID, iSteamID, iSteamID); gH_SQL.Query(SQL_GetWRs_Callback, sQuery, GetClientSerial(client)); - - FormatEx(sQuery, sizeof(sQuery), - "WITH wrs AS ( \ - SELECT a.track, a.style, a.auth FROM %splayertimes a \ - JOIN (SELECT MIN(time) time, map, track, style FROM %splayertimes GROUP BY map, track, style) b \ - ON a.time = b.time AND a.map = b.map AND a.track = b.track AND a.style = b.style \ - ), hrankall AS ( \ - SELECT -1 as style, auth, c, RANK() OVER(ORDER BY c DESC, auth ASC) as wrrank FROM (SELECT COUNT(*) as c, auth FROM wrs GROUP BY auth) z \ - ), hrankcvar AS ( \ - SELECT -1 as style, auth, c, RANK() OVER(ORDER BY c DESC, auth ASC) as wrrank FROM (SELECT COUNT(*) as c, auth FROM wrs %s %s %s %s GROUP BY auth) z \ - ) \ - SELECT *, 0 as track, 0 as type FROM (SELECT style, auth, c, RANK() OVER(PARTITION BY style ORDER BY c DESC, auth ASC) as wrrank FROM (SELECT sum(c) as c, auth, style FROM (SELECT style, auth, COUNT(auth) as c FROM wrs WHERE track = 0 GROUP BY style, auth) a GROUP BY style, auth) z) a WHERE auth = %d \ - UNION SELECT *, 1 as track, 0 as type FROM (SELECT style, auth, c, RANK() OVER(PARTITION BY style ORDER BY c DESC, auth ASC) as wrrank FROM (SELECT sum(c) as c, auth, style FROM (SELECT style, auth, COUNT(auth) as c FROM wrs WHERE track > 0 GROUP BY style, auth) a GROUP BY style, auth) z) a WHERE auth = %d \ - UNION SELECT *, -1 as track, 1 as type FROM hrankall WHERE auth = %d \ - UNION SELECT *, -1 as track, 2 as type FROM %s WHERE auth = %d;", - gS_MySQLPrefix, gS_MySQLPrefix, - (gCV_MVPRankOnes.IntValue == 2 || gCV_MVPRankOnes_Main.BoolValue) ? "WHERE" : "", - (gCV_MVPRankOnes.IntValue == 2) ? "style = 0" : "", - (gCV_MVPRankOnes.IntValue == 2 && gCV_MVPRankOnes_Main.BoolValue) ? "AND" : "", - (gCV_MVPRankOnes_Main.BoolValue) ? "track = 0" : "", - iSteamID, - iSteamID, - iSteamID, - (gCV_MVPRankOnes.IntValue == 2 || gCV_MVPRankOnes_Main.BoolValue) ? "hrankcvar" : "hrankall", - iSteamID - ); - - gH_SQL.Query(SQL_GetWRHolderRank_Callback, sQuery, GetClientSerial(client)); -} - -public void SQL_GetWRHolderRank_Callback(Database db, DBResultSet results, const char[] error, any data) -{ - if(results == null) - { - LogError("Timer (get WR Holder Rank) SQL query failed. Reason: %s", error); - - return; - } - - int client = GetClientFromSerial(data); - - if(client == 0) - { - return; - } - - while (results.FetchRow()) - { - int style = results.FetchInt(0); - results.FetchInt(1); // auth - int total = results.FetchInt(2); - int wrrank = results.FetchInt(3); - int track = results.FetchInt(4); - int type = results.FetchInt(5); - - if (type == 0) - { - gI_WRHolderRank[client][track][style] = total; - } - else if (type == 1) - { - gI_WRHolderRankAll[client] = wrrank; - } - else if (type == 2) - { - gI_WRHolderRankCvar[client] = wrrank; - } - } } public void SQL_GetWRs_Callback(Database db, DBResultSet results, const char[] error, any data) { if(results == null) { - LogError("Timer (get WR amount) SQL query failed. Reason: %s", error); - + LogError("SQL_GetWRs_Callback failed. Reason: %s", error); return; } @@ -350,22 +285,29 @@ public void SQL_GetWRs_Callback(Database db, DBResultSet results, const char[] e return; } - bool defaultStyleOnly = gCV_MVPRankOnes.IntValue == 2; - bool mainOnly = gCV_MVPRankOnes_Main.BoolValue; - while (results.FetchRow()) { - int track = results.FetchInt(0); - int style = results.FetchInt(1); - ++gI_WRAmount[client][track > Track_Main][style]; - ++gI_WRAmountAll[client]; + int wrrank = results.FetchInt(0); + int style = results.FetchInt(1); + //int auth = results.FetchInt(2); + int wrcount = results.FetchInt(3); + int track = results.FetchInt(4); + int type = results.FetchInt(5); - if (!defaultStyleOnly || style == 0) + if (type == 0) { - if (!mainOnly || track == Track_Main) - { - ++gI_WRAmountCvar[client]; - } + gI_WRAmount[client][track][style] = wrcount; + gI_WRHolderRank[client][track][style] = wrrank; + } + else if (type == 1) + { + gI_WRAmountAll[client] = wrcount; + gI_WRHolderRankAll[client] = wrrank; + } + else if (type == 2) + { + gI_WRAmountCvar[client] = wrcount; + gI_WRHolderRankCvar[client] = wrrank; } } @@ -1036,36 +978,111 @@ public int Native_OpenStatsMenu(Handle handler, int numParams) void UpdateWRHolders() { - char sQuery[1111]; - FormatEx(sQuery, sizeof(sQuery), - "WITH x AS ("... - " SELECT a.track, a.style, a.auth FROM %splayertimes a"... - " JOIN (SELECT MIN(time) time, map, track, style FROM %splayertimes GROUP BY map, track, style) b"... - " ON a.time = b.time AND a.map = b.map AND a.track = b.track AND a.style = b.style"... - "), main AS ("... - " SELECT 0 as track, style, COUNT(DISTINCT auth) FROM x WHERE track = 0 GROUP BY style"... - "), bonus AS ("... - " SELECT 1 as track, style, COUNT(DISTINCT auth) FROM x WHERE track > 0 GROUP BY style"... - "), myall AS ("... - " SELECT -1 as track, -1 as style, COUNT(DISTINCT auth) FROM x"... - "), mycvar AS ("... - " SELECT -1 as track, -1 as style, COUNT(DISTINCT auth) FROM x %s %s %s %s"... - ")"... - " SELECT *, 0 as type FROM main"... - " UNION SELECT *, 0 as type FROM bonus"... - " UNION SELECT *, 1 as type FROM myall"... - " UNION SELECT *, 2 as type FROM %s;", - gS_MySQLPrefix, gS_MySQLPrefix, - (gCV_MVPRankOnes.IntValue == 2 || gCV_MVPRankOnes_Main.BoolValue) ? "WHERE" : "", - (gCV_MVPRankOnes.IntValue == 2) ? "style = 0" : "", - (gCV_MVPRankOnes.IntValue == 2 && gCV_MVPRankOnes_Main.BoolValue) ? "AND" : "", - (gCV_MVPRankOnes_Main.BoolValue) ? "track = 0" : "", - (gCV_MVPRankOnes.IntValue == 2 || gCV_MVPRankOnes_Main.BoolValue) ? "mycvar" : "myall" - ); + // Compatible with MySQL 5.6, 5.7, 8.0 + char sWRHolderRankTrackQueryYuck[] = + "CREATE TEMPORARY TABLE %s AS \ + SELECT ( \ + CASE style \ + WHEN @curGroup \ + THEN @curRow := @curRow + 1 \ + ELSE @curRow := 1 AND @curGroup := style END \ + ) as wrrank, \ + style, auth, wrcount \ + FROM ( \ + SELECT style, auth, SUM(c) as wrcount FROM ( \ + SELECT style, auth, COUNT(auth) as c FROM %swrs WHERE track %c 0 GROUP BY style, auth \ + ) a GROUP BY style, auth ORDER BY style ASC, wrcount DESC, auth ASC \ + ) x, \ + (SELECT @curRow := 0, @curGroup := 0) r \ + ORDER BY style ASC, wrrank ASC, auth ASC;"; + + // Compatible with MySQL 8.0 and SQLite // TODO: SELECT VERSION() and check... + char sWRHolderRankTrackQueryRANK[] = + "CREATE TEMPORARY TABLE %s AS \ + SELECT \ + RANK() OVER(PARTITION BY style ORDER BY wrcount DESC, auth ASC) \ + as wrrank, \ + style, auth, wrcount \ + FROM ( \ + SELECT style, auth, SUM(c) as wrcount FROM ( \ + SELECT style, auth, COUNT(auth) as c FROM %swrs WHERE track %c 0 GROUP BY style, auth \ + ) a GROUP BY style, auth \ + ) x;"; + // Compatible with MySQL 5.6, 5.7, 8.0 + char sWRHolderRankOtherQueryYuck[] = + "CREATE TEMPORARY TABLE %s AS \ + SELECT ( \ + @curRow := @curRow + 1 \ + ) as wrrank, \ + -1 as style, auth, wrcount \ + FROM ( \ + SELECT COUNT(*) as wrcount, auth FROM %swrs %s %s %s %s GROUP BY auth ORDER BY wrcount DESC, auth ASC \ + ) x, \ + (SELECT @curRow := 0) r \ + ORDER BY style ASC, wrrank ASC, auth ASC;"; + + // Compatible with MySQL 8.0 and SQLite // TODO: SELECT VERSION() and check... + char sWRHolderRankOtherQueryRANK[] = + "CREATE TEMPORARY TABLE %s AS \ + SELECT \ + RANK() OVER(ORDER BY wrcount DESC, auth ASC) \ + as wrrank, \ + -1 as style, auth, wrcount \ + FROM ( \ + SELECT COUNT(*) as wrcount, auth FROM %swrs %s %s %s %s GROUP BY auth \ + ) x;"; + + char sQuery[800]; + Transaction hTransaction = new Transaction(); + + hTransaction.AddQuery("DROP TABLE IF EXISTS wrhrankmain;"); + FormatEx(sQuery, sizeof(sQuery), + IsMySQLDatabase(gH_SQL) ? sWRHolderRankTrackQueryYuck : sWRHolderRankTrackQueryRANK, + "wrhrankmain", gS_MySQLPrefix, '='); + hTransaction.AddQuery(sQuery); + + hTransaction.AddQuery("DROP TABLE IF EXISTS wrhrankbonus;"); + FormatEx(sQuery, sizeof(sQuery), + IsMySQLDatabase(gH_SQL) ? sWRHolderRankTrackQueryYuck : sWRHolderRankTrackQueryRANK, + "wrhrankbonus", gS_MySQLPrefix, '>'); + hTransaction.AddQuery(sQuery); + + hTransaction.AddQuery("DROP TABLE IF EXISTS wrhrankall;"); + FormatEx(sQuery, sizeof(sQuery), + IsMySQLDatabase(gH_SQL) ? sWRHolderRankOtherQueryYuck : sWRHolderRankOtherQueryRANK, + "wrhrankall", gS_MySQLPrefix, "", "", "", ""); + hTransaction.AddQuery(sQuery); + + hTransaction.AddQuery("DROP TABLE IF EXISTS wrhrankcvar;"); + FormatEx(sQuery, sizeof(sQuery), + IsMySQLDatabase(gH_SQL) ? sWRHolderRankOtherQueryYuck : sWRHolderRankOtherQueryRANK, + "wrhrankcvar", gS_MySQLPrefix, + (gCV_MVPRankOnes.IntValue == 2 || gCV_MVPRankOnes_Main.BoolValue) ? "WHERE" : "", + (gCV_MVPRankOnes.IntValue == 2) ? "style = 0" : "", + (gCV_MVPRankOnes.IntValue == 2 && gCV_MVPRankOnes_Main.BoolValue) ? "AND" : "", + (gCV_MVPRankOnes_Main.BoolValue) ? "track = 0" : ""); + hTransaction.AddQuery(sQuery); + + gH_SQL.Execute(hTransaction, Trans_WRHolderRankTablesSuccess, Trans_WRHolderRankTablesError, 0, DBPrio_High); +} + +public void Trans_WRHolderRankTablesSuccess(Database db, any data, int numQueries, DBResultSet[] results, any[] queryData) +{ + char sQuery[1024]; + FormatEx(sQuery, sizeof(sQuery), + " SELECT 0 as type, 0 as track, style, COUNT(DISTINCT auth) FROM wrhrankmain GROUP BY STYLE \ + UNION SELECT 0 as type, 1 as track, style, COUNT(DISTINCT auth) FROM wrhrankbonus GROUP BY STYLE \ + UNION SELECT 1 as type, -1 as track, -1 as style, COUNT(DISTINCT auth) FROM wrhrankall \ + UNION SELECT 2 as type, -1 as track, -1 as style, COUNT(DISTINCT auth) FROM wrhrankcvar;"); gH_SQL.Query(SQL_GetWRHolders_Callback, sQuery); } +public void Trans_WRHolderRankTablesError(Database db, any data, int numQueries, const char[] error, int failIndex, any[] queryData) +{ + LogError("Timer (WR Holder Rank table creation %d/%d) SQL query failed. Reason: %s", failIndex, numQueries, error); +} + public void SQL_GetWRHolders_Callback(Database db, DBResultSet results, const char[] error, any data) { if(results == null) @@ -1077,10 +1094,10 @@ public void SQL_GetWRHolders_Callback(Database db, DBResultSet results, const ch while (results.FetchRow()) { - int track = results.FetchInt(0); - int style = results.FetchInt(1); - int total = results.FetchInt(2); - int type = results.FetchInt(3); + int type = results.FetchInt(0); + int track = results.FetchInt(1); + int style = results.FetchInt(2); + int total = results.FetchInt(3); if (type == 0) { diff --git a/addons/sourcemod/scripting/shavit-wr.sp b/addons/sourcemod/scripting/shavit-wr.sp index 4f162591..49b882d2 100644 --- a/addons/sourcemod/scripting/shavit-wr.sp +++ b/addons/sourcemod/scripting/shavit-wr.sp @@ -679,34 +679,42 @@ public void DeleteWR_Callback(Database db, DBResultSet results, const char[] err int track = hPack.ReadCell(); char map[PLATFORM_MAX_PATH]; hPack.ReadString(map, sizeof(map)); + bool update_cache = view_as(hPack.ReadCell()); int steamid = hPack.ReadCell(); int recordid = hPack.ReadCell(); - bool update_cache = view_as(hPack.ReadCell()); delete hPack; if(results == null) { LogError("Timer (WR DeleteWR) SQL query failed. Reason: %s", error); - return; } - if (recordid == -1) + DeleteWRFinal(style, track, map, steamid, recordid, update_cache); +} + +void DeleteWRInner(int recordid, int steamid, DataPack hPack) +{ + hPack.WriteCell(steamid); + hPack.WriteCell(recordid); + + char sQuery[169]; + FormatEx(sQuery, sizeof(sQuery), + "DELETE FROM %splayertimes WHERE id = %d;", + gS_MySQLPrefix, recordid); + gH_SQL.Query(DeleteWR_Callback, sQuery, hPack, DBPrio_High); +} + +public void DeleteWRGetID_Callback(Database db, DBResultSet results, const char[] error, DataPack hPack) +{ + if(results == null || !results.FetchRow()) { - results.FetchRow(); - - if (results.IsFieldNull(0) || results.IsFieldNull(1)) - { - LogError("Timer (WR DeleteWR) SQL query failed. Reason: @deletewrid or @deletewrauth is NULL"); - return; - } - - recordid = results.FetchInt(0); - steamid = results.FetchInt(1); + LogError("Timer (WR DeleteWRGetID) SQL query failed. Reason: %s", error); + return; } - DeleteWRFinal(style, track, map, steamid, recordid, update_cache); + DeleteWRInner(results.FetchInt(0), results.FetchInt(1), hPack); } void DeleteWR(int style, int track, const char[] map, int steamid, int recordid, bool delete_sql, bool update_cache) @@ -717,32 +725,21 @@ void DeleteWR(int style, int track, const char[] map, int steamid, int recordid, hPack.WriteCell(style); hPack.WriteCell(track); hPack.WriteString(map); - hPack.WriteCell(steamid); - hPack.WriteCell(recordid); hPack.WriteCell(update_cache); char sQuery[512]; if (recordid == -1) // missing WR recordid thing... { - // TODO: probably doesn't work well with sqlite... FormatEx(sQuery, sizeof(sQuery), - "SELECT p1.id, p1.auth INTO @deletewrid, @deletewrauth FROM %splayertimes p1 " ... - "JOIN (SELECT style, track, MIN(time) time FROM %splayertimes WHERE " ... - "map = '%s' AND style = %d AND track = %d) p2 " ... - "ON p1.style = p2.style AND p1.track = p2.track AND p1.time = p2.time; " ... - "DELETE FROM %splayertimes WHERE id = @deletewrid; " ... - "SELECT @deletewrid, @deletewrauth;", - gS_MySQLPrefix, gS_MySQLPrefix, map, style, track, gS_MySQLPrefix); + "SELECT id, auth FROM %swrs WHERE map = '%s' AND style = %d AND track = %d;", + gS_MySQLPrefix, map, style, track, gS_MySQLPrefix, map, style, track); + gH_SQL.Query(DeleteWRGetID_Callback, sQuery, hPack, DBPrio_High); } else { - FormatEx(sQuery, sizeof(sQuery), - "DELETE FROM %splayertimes WHERE id = %d;", - gS_MySQLPrefix, recordid); + DeleteWRInner(recordid, steamid, hPack); } - - gH_SQL.Query(DeleteWR_Callback, sQuery, hPack, DBPrio_High); } else { @@ -1280,7 +1277,6 @@ public void GetRecordDetails_Callback(Database db, DBResultSet results, const ch return; } - // TODO: work DeleteWR() into here... if(results.FetchRow()) { int iSteamID = results.FetchInt(0); @@ -2040,6 +2036,7 @@ void SQL_DBConnect() gB_MySQL = IsMySQLDatabase(gH_SQL); char sQuery[1024]; + Transaction hTransaction = new Transaction(); if(gB_MySQL) { @@ -2055,23 +2052,29 @@ void SQL_DBConnect() gS_MySQLPrefix, gS_MySQLPrefix, gS_MySQLPrefix); } - gH_SQL.Query(SQL_CreateTable_Callback, sQuery); + hTransaction.AddQuery(sQuery); + + FormatEx(sQuery, sizeof(sQuery), + "%s %swrs AS SELECT a.* FROM %splayertimes a JOIN (SELECT MIN(time) time, map, track, style FROM %splayertimes GROUP BY map, track, style) b ON a.time = b.time AND a.map = b.map AND a.track = b.track AND a.style = b.style;", + gB_MySQL ? "CREATE OR REPLACE VIEW" : "CREATE VIEW IF NOT EXISTS", + gS_MySQLPrefix, gS_MySQLPrefix, gS_MySQLPrefix); + hTransaction.AddQuery(sQuery); + + gH_SQL.Execute(hTransaction, Trans_CreateTable_Success, Trans_CreateTable_Error, 0, DBPrio_High); } -public void SQL_CreateTable_Callback(Database db, DBResultSet results, const char[] error, any data) +public void Trans_CreateTable_Success(Database db, any data, int numQueries, DBResultSet[] results, any[] queryData) { - if(results == null) - { - LogError("Timer (WR module) error! Users' times table creation failed. Reason: %s", error); - - return; - } - gB_Connected = true; OnMapStart(); } +public void Trans_CreateTable_Error(Database db, any data, int numQueries, const char[] error, int failIndex, any[] queryData) +{ + LogError("Timer (WR module) SQL query %d/%d failed. Reason: %s", failIndex, numQueries, error); +} + public void Shavit_OnFinish(int client, int style, float time, int jumps, int strafes, float sync, int track, float oldtime, float perfs, float avgvel, float maxvel, int timestamp) { // do not risk overwriting the player's data if their PB isn't loaded to cache yet