diff --git a/Plan/src/main/java/com/djrapitops/plan/system/database/databases/sql/SQLDB.java b/Plan/src/main/java/com/djrapitops/plan/system/database/databases/sql/SQLDB.java index 4ded946b4..9935158f9 100644 --- a/Plan/src/main/java/com/djrapitops/plan/system/database/databases/sql/SQLDB.java +++ b/Plan/src/main/java/com/djrapitops/plan/system/database/databases/sql/SQLDB.java @@ -133,7 +133,7 @@ public abstract class SQLDB extends Database { if (newDatabase) { Log.info("New Database created."); - versionTable.setVersion(15); + versionTable.setVersion(16); } int version = versionTable.getVersion(); @@ -172,6 +172,11 @@ public abstract class SQLDB extends Database { sessionsTable.alterTableV15(); versionTable.setVersion(15); } + if (version < 16) { + killsTable.alterTableV16(); + worldTimesTable.alterTableV16(); + versionTable.setVersion(16); + } } catch (SQLException e) { throw new DBInitException("Failed to set-up Database", e); } diff --git a/Plan/src/main/java/com/djrapitops/plan/system/database/databases/sql/tables/KillsTable.java b/Plan/src/main/java/com/djrapitops/plan/system/database/databases/sql/tables/KillsTable.java index 72d34a41f..ca4ae6d98 100644 --- a/Plan/src/main/java/com/djrapitops/plan/system/database/databases/sql/tables/KillsTable.java +++ b/Plan/src/main/java/com/djrapitops/plan/system/database/databases/sql/tables/KillsTable.java @@ -10,6 +10,7 @@ import com.djrapitops.plan.system.database.databases.sql.processing.QueryStateme import com.djrapitops.plan.system.database.databases.sql.statements.Column; import com.djrapitops.plan.system.database.databases.sql.statements.Sql; import com.djrapitops.plan.system.database.databases.sql.statements.TableSqlParser; +import com.djrapitops.plan.system.info.server.ServerInfo; import com.djrapitops.plugin.utilities.Verify; import java.sql.PreparedStatement; @@ -28,18 +29,23 @@ import java.util.*; */ public class KillsTable extends UserIDTable { + private final ServerTable serverTable; + public KillsTable(SQLDB db) { super("plan_kills", db); sessionsTable = db.getSessionsTable(); + serverTable = db.getServerTable(); insertStatement = "INSERT INTO " + tableName + " (" + Col.KILLER_ID + ", " + Col.VICTIM_ID + ", " + + Col.SERVER_ID + ", " + Col.SESSION_ID + ", " + Col.DATE + ", " + Col.WEAPON + ") VALUES (" + usersTable.statementSelectID + ", " + usersTable.statementSelectID + ", " + + serverTable.statementSelectServerID + ", " + "?, ?, ?)"; } @@ -51,12 +57,14 @@ public class KillsTable extends UserIDTable { createTable(TableSqlParser.createTable(tableName) .column(Col.KILLER_ID, Sql.INT).notNull() .column(Col.VICTIM_ID, Sql.INT).notNull() + .column(Col.SERVER_ID, Sql.INT).notNull() .column(Col.WEAPON, Sql.varchar(30)).notNull() .column(Col.DATE, Sql.LONG).notNull() .column(Col.SESSION_ID, Sql.INT).notNull() .foreignKey(Col.KILLER_ID, usersTable.getTableName(), UsersTable.Col.ID) .foreignKey(Col.VICTIM_ID, usersTable.getTableName(), UsersTable.Col.ID) .foreignKey(Col.SESSION_ID, sessionsTable.getTableName(), SessionsTable.Col.ID) + .foreignKey(Col.SERVER_ID, serverTable.getTableName(), ServerTable.Col.SERVER_ID) .toString() ); } @@ -131,9 +139,10 @@ public class KillsTable extends UserIDTable { statement.setString(1, uuid.toString()); statement.setString(2, victim.toString()); - statement.setInt(3, sessionID); - statement.setLong(4, date); - statement.setString(5, weapon); + statement.setString(3, ServerInfo.getServerUUID().toString()); + statement.setInt(4, sessionID); + statement.setLong(5, date); + statement.setString(6, weapon); statement.addBatch(); } } @@ -243,9 +252,10 @@ public class KillsTable extends UserIDTable { String weapon = kill.getWeapon(); statement.setString(1, killer.toString()); statement.setString(2, victim.toString()); - statement.setInt(3, sessionID); - statement.setLong(4, date); - statement.setString(5, weapon); + statement.setString(3, serverUUID.toString()); + statement.setInt(4, sessionID); + statement.setLong(5, date); + statement.setString(6, weapon); statement.addBatch(); } } @@ -255,9 +265,33 @@ public class KillsTable extends UserIDTable { }); } + public void alterTableV16() throws SQLException { + addColumns(Col.SERVER_ID + " integer NOT NULL DEFAULT 0"); + + Map sessionIDServerIDRelation = sessionsTable.getIDServerIDRelation(); + + String sql = "UPDATE " + tableName + " SET " + + Col.SERVER_ID + "=?" + + " WHERE " + Col.SESSION_ID + "=?"; + + executeBatch(new ExecStatement(sql) { + @Override + public void prepare(PreparedStatement statement) throws SQLException { + for (Map.Entry entry : sessionIDServerIDRelation.entrySet()) { + Integer sessionID = entry.getKey(); + Integer serverID = entry.getValue(); + statement.setInt(1, serverID); + statement.setInt(2, sessionID); + statement.addBatch(); + } + } + }); + } + public enum Col implements Column { KILLER_ID("killer_id"), VICTIM_ID("victim_id"), + SERVER_ID("server_id"), SESSION_ID("session_id"), WEAPON("weapon"), DATE("date"); diff --git a/Plan/src/main/java/com/djrapitops/plan/system/database/databases/sql/tables/ServerTable.java b/Plan/src/main/java/com/djrapitops/plan/system/database/databases/sql/tables/ServerTable.java index f0bb04d92..9346f5117 100644 --- a/Plan/src/main/java/com/djrapitops/plan/system/database/databases/sql/tables/ServerTable.java +++ b/Plan/src/main/java/com/djrapitops/plan/system/database/databases/sql/tables/ServerTable.java @@ -30,8 +30,10 @@ import java.util.*; */ public class ServerTable extends Table { + public static final String TABLE_NAME = "plan_servers"; + public ServerTable(SQLDB db) { - super("plan_servers", db); + super(TABLE_NAME, db); statementSelectServerID = "(" + Select.from(tableName, tableName + "." + Col.SERVER_ID).where(tableName + "." + Col.SERVER_UUID + "=?").toString() + " LIMIT 1)"; statementSelectServerNameID = "(" + Select.from(tableName, tableName + "." + Col.NAME).where(tableName + "." + Col.SERVER_ID + "=?").toString() + " LIMIT 1)"; insertStatement = Insert.values(tableName, diff --git a/Plan/src/main/java/com/djrapitops/plan/system/database/databases/sql/tables/SessionsTable.java b/Plan/src/main/java/com/djrapitops/plan/system/database/databases/sql/tables/SessionsTable.java index eb254064d..c5dad7565 100644 --- a/Plan/src/main/java/com/djrapitops/plan/system/database/databases/sql/tables/SessionsTable.java +++ b/Plan/src/main/java/com/djrapitops/plan/system/database/databases/sql/tables/SessionsTable.java @@ -737,6 +737,24 @@ public class SessionsTable extends UserIDTable { addColumns(Col.AFK_TIME + " bigint NOT NULL DEFAULT 0"); } + public Map getIDServerIDRelation() throws SQLException { + String sql = "SELECT " + + Col.ID + ", " + + Col.SERVER_ID + + " FROM " + tableName; + + return query(new QueryAllStatement>(sql, 10000) { + @Override + public Map processResults(ResultSet set) throws SQLException { + HashMap idServerIdMap = new HashMap<>(); + while (set.next()) { + idServerIdMap.put(set.getInt(Col.ID.get()), set.getInt(Col.SERVER_ID.get())); + } + return idServerIdMap; + } + }); + } + public enum Col implements Column { USER_ID(UserIDTable.Col.USER_ID.get()), ID("id"), diff --git a/Plan/src/main/java/com/djrapitops/plan/system/database/databases/sql/tables/Table.java b/Plan/src/main/java/com/djrapitops/plan/system/database/databases/sql/tables/Table.java index c9b96cc16..73eb1d9f0 100644 --- a/Plan/src/main/java/com/djrapitops/plan/system/database/databases/sql/tables/Table.java +++ b/Plan/src/main/java/com/djrapitops/plan/system/database/databases/sql/tables/Table.java @@ -43,6 +43,13 @@ public abstract class Table { } } + protected void renameTable(String to) throws SQLException { + String sql = usingMySQL ? + "RENAME TABLE " + tableName + " TO " + to : + "ALTER TABLE " + tableName + " RENAME TO " + to; + execute(sql); + } + /** * Used to get a new Connection to the Database. * diff --git a/Plan/src/main/java/com/djrapitops/plan/system/database/databases/sql/tables/WorldTable.java b/Plan/src/main/java/com/djrapitops/plan/system/database/databases/sql/tables/WorldTable.java index feb37de00..742876af0 100644 --- a/Plan/src/main/java/com/djrapitops/plan/system/database/databases/sql/tables/WorldTable.java +++ b/Plan/src/main/java/com/djrapitops/plan/system/database/databases/sql/tables/WorldTable.java @@ -10,11 +10,14 @@ import com.djrapitops.plan.system.database.databases.sql.statements.Sql; import com.djrapitops.plan.system.database.databases.sql.statements.TableSqlParser; import com.djrapitops.plan.system.info.server.ServerInfo; import com.djrapitops.plugin.utilities.Verify; +import com.google.common.base.Objects; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.util.*; +import java.util.function.Function; +import java.util.stream.Collectors; /** * Table class representing database table plan_worlds. @@ -26,19 +29,26 @@ import java.util.*; */ public class WorldTable extends Table { + public final String statementSelectID; + private final ServerTable serverTable; + public WorldTable(SQLDB db) { super("plan_worlds", db); - statementSelectID = "(SELECT " + Col.ID + " FROM " + tableName + " WHERE (" + Col.NAME + "=?) LIMIT 1)"; + serverTable = db.getServerTable(); + statementSelectID = "(SELECT " + Col.ID + " FROM " + tableName + + " WHERE (" + Col.NAME + "=?)" + + " AND (" + Col.SERVER_ID + "=" + serverTable.statementSelectServerID + ")" + + " LIMIT 1)"; } - public final String statementSelectID; - @Override public void createTable() throws DBInitException { createTable(TableSqlParser.createTable(tableName) .primaryKeyIDColumn(usingMySQL, Col.ID) .column(Col.NAME, Sql.varchar(100)).notNull() + .column(Col.SERVER_ID, Sql.INT).notNull() .primaryKey(usingMySQL, Col.ID) + .foreignKey(Col.SERVER_ID, ServerTable.TABLE_NAME, ServerTable.Col.SERVER_ID) .toString() ); } @@ -49,7 +59,7 @@ public class WorldTable extends Table { * @return List of all world names in the database. * @throws SQLException Database error occurs. */ - public List getWorlds() throws SQLException { + public List getAllWorlds() throws SQLException { String sql = "SELECT * FROM " + tableName; return query(new QueryAllStatement>(sql) { @@ -65,6 +75,78 @@ public class WorldTable extends Table { }); } + public Map> getWorldsPerServer() throws SQLException { + Map serverUUIDsByID = serverTable.getServerUUIDsByID(); + String sql = "SELECT * FROM " + tableName; + + return query(new QueryAllStatement>>(sql, 1000) { + @Override + public Map> processResults(ResultSet set) throws SQLException { + Map> worldsPerServer = new HashMap<>(); + while (set.next()) { + UUID serverUUID = serverUUIDsByID.get(set.getInt(Col.SERVER_ID.get())); + String worldName = set.getString(Col.NAME.get()); + List worlds = worldsPerServer.getOrDefault(serverUUID, new ArrayList<>()); + worlds.add(worldName); + worldsPerServer.put(serverUUID, worlds); + } + return worldsPerServer; + } + }); + } + + public Map getServerUUIDByWorldID() throws SQLException { + Map serverUUIDsByID = serverTable.getServerUUIDsByID(); + String sql = "SELECT DISTINCT " + + Col.ID + ", " + + Col.SERVER_ID + + " FROM " + tableName; + return query(new QueryAllStatement>(sql, 100) { + @Override + public Map processResults(ResultSet set) throws SQLException { + Map idMap = new HashMap<>(); + while (set.next()) { + int worldId = set.getInt(Col.ID.get()); + int serverId = set.getInt(Col.SERVER_ID.get()); + UUID serverUUID = serverUUIDsByID.getOrDefault(serverId, ServerInfo.getServerUUID()); + idMap.put(worldId, serverUUID); + } + return idMap; + } + }); + } + + public List getWorlds() throws SQLException { + return getWorlds(ServerInfo.getServerUUID()); + } + + public List getWorlds(UUID serverUUID) throws SQLException { + String sql = "SELECT * FROM " + tableName + + " WHERE " + Col.SERVER_ID + "=" + serverTable.statementSelectServerID; + + return query(new QueryStatement>(sql) { + + @Override + public void prepare(PreparedStatement statement) throws SQLException { + statement.setString(1, serverUUID.toString()); + } + + @Override + public List processResults(ResultSet set) throws SQLException { + List worldNames = new ArrayList<>(); + while (set.next()) { + String worldName = set.getString(Col.NAME.get()); + worldNames.add(worldName); + } + return worldNames; + } + }); + } + + public void saveWorlds(Collection worlds) throws SQLException { + saveWorlds(worlds, ServerInfo.getServerUUID()); + } + /** * Used to save a list of world names. *

@@ -73,25 +155,27 @@ public class WorldTable extends Table { * @param worlds List of world names. * @throws SQLException Database error occurs. */ - public void saveWorlds(Collection worlds) throws SQLException { + public void saveWorlds(Collection worlds, UUID serverUUID) throws SQLException { Verify.nullCheck(worlds); Set worldsToSave = new HashSet<>(worlds); - List saved = getWorlds(); + List saved = getWorlds(serverUUID); worldsToSave.removeAll(saved); if (Verify.isEmpty(worlds)) { return; } String sql = "INSERT INTO " + tableName + " (" - + Col.NAME - + ") VALUES (?)"; + + Col.NAME + ", " + + Col.SERVER_ID + + ") VALUES (?, " + serverTable.statementSelectServerID + ")"; executeBatch(new ExecStatement(sql) { @Override public void prepare(PreparedStatement statement) throws SQLException { for (String world : worldsToSave) { statement.setString(1, world); + statement.setString(2, ServerInfo.getServerUUID().toString()); statement.addBatch(); } } @@ -99,9 +183,37 @@ public class WorldTable extends Table { } public Set getWorldNames(UUID serverUUID) throws SQLException { + String sql = "SELECT DISTINCT " + Col.NAME + " FROM " + tableName + + " WHERE " + Col.SERVER_ID + "=" + serverTable.statementSelectServerID; + return query(new QueryStatement>(sql, 100) { + @Override + public void prepare(PreparedStatement statement) throws SQLException { + statement.setString(1, serverUUID.toString()); + } + + @Override + public Set processResults(ResultSet set) throws SQLException { + Set worldNames = new HashSet<>(); + while (set.next()) { + worldNames.add(set.getString(Col.NAME.get())); + } + return worldNames; + } + }); + } + + /** + * Used to get world names for this server. + * + * @param serverUUID UUID of the Server + * @return World names known for that server + * @throws SQLException If DB Error occurs + * @deprecated Use getWorldNames instead, this method is slower. + */ + @Deprecated + public Set getWorldNamesOld(UUID serverUUID) throws SQLException { WorldTimesTable worldTimesTable = db.getWorldTimesTable(); SessionsTable sessionsTable = db.getSessionsTable(); - ServerTable serverTable = db.getServerTable(); String statementSelectServerID = serverTable.statementSelectServerID; @@ -134,32 +246,120 @@ public class WorldTable extends Table { }); } - public Set getWorldNames() throws SQLException { - return getWorldNames(ServerInfo.getServerUUID()); + private Map getWorldIDServerIDRelation() throws SQLException { + String sql = "SELECT " + + Col.ID + ", " + + Col.SERVER_ID + + " FROM " + tableName; + return query(new QueryAllStatement>(sql, 100) { + @Override + public Map processResults(ResultSet set) throws SQLException { + HashMap idServerIdMap = new HashMap<>(); + while (set.next()) { + idServerIdMap.put(set.getInt(Col.ID.get()), set.getInt(Col.SERVER_ID.get())); + } + return idServerIdMap; + } + }); } - public Map getWorldIds() throws SQLException { - String sql = "SELECT DISTINCT " + - Col.NAME + ", " + - Col.ID + " FROM " + - tableName; + public void alterTableV16() throws SQLException { + addColumns(Col.SERVER_ID + " integer NOT NULL DEFAULT 0"); - return query(new QueryAllStatement>(sql, 200) { + List serverUUIDs = serverTable.getServerUUIDs(); + + Map> worldsPerServer = new HashMap<>(); + for (UUID serverUUID : serverUUIDs) { + worldsPerServer.put(serverUUID, getWorldNamesOld(serverUUID)); + } + + for (Map.Entry> entry : worldsPerServer.entrySet()) { + UUID serverUUID = entry.getKey(); + Set worlds = entry.getValue(); + + saveWorlds(worlds, serverUUID); + } + + updateWorldTimesTableWorldIDs(); + execute("DELETE FROM " + tableName + " WHERE " + Col.SERVER_ID + "=0"); + } + + private void updateWorldTimesTableWorldIDs() throws SQLException { + List worldObjects = getWorldObjects(); + Map> oldToNewMap = + worldObjects.stream() + .filter(worldObj -> worldObj.serverId == 0) + .collect(Collectors.toMap( + Function.identity(), + oldWorld -> worldObjects.stream() + .filter(worldObj -> worldObj.equals(oldWorld)) + .collect(Collectors.toList() + ))); + + WorldTimesTable worldTimesTable = db.getWorldTimesTable(); + String sql = "UPDATE " + worldTimesTable + " SET " + + WorldTimesTable.Col.WORLD_ID + "=?" + + " WHERE " + WorldTimesTable.Col.WORLD_ID + "=?" + + " AND " + WorldTimesTable.Col.SERVER_ID + "=?"; + executeBatch(new ExecStatement(sql) { @Override - public Map processResults(ResultSet set) throws SQLException { - Map worldIds = new HashMap<>(); - while (set.next()) { - String worldName = set.getString(Col.NAME.get()); - int worldId = set.getInt(Col.ID.get()); - worldIds.put(worldName, worldId); + public void prepare(PreparedStatement statement) throws SQLException { + for (Map.Entry> entry : oldToNewMap.entrySet()) { + WorldObj old = entry.getKey(); + for (WorldObj newWorld : entry.getValue()) { + statement.setInt(1, newWorld.id); + statement.setInt(2, old.id); + statement.setInt(3, newWorld.serverId); + statement.addBatch(); + } } - return worldIds; + } + }); + } + + public Map> getWorldIDsByServerIDs() throws SQLException { + String sql = "SELECT " + + Col.ID + ", " + + Col.SERVER_ID + + " FROM " + tableName; + return query(new QueryAllStatement>>(sql, 100) { + @Override + public Map> processResults(ResultSet set) throws SQLException { + HashMap> map = new HashMap<>(); + while (set.next()) { + + int serverID = set.getInt(Col.SERVER_ID.get()); + int worldID = set.getInt(Col.ID.get()); + List worldIDs = map.getOrDefault(serverID, new ArrayList<>()); + worldIDs.add(worldID); + map.put(serverID, worldIDs); + } + return map; + } + }); + } + + public List getWorldObjects() throws SQLException { + String sql = "SELECT * FROM " + tableName; + return query(new QueryAllStatement>(sql, 100) { + @Override + public List processResults(ResultSet set) throws SQLException { + List objects = new ArrayList<>(); + while (set.next()) { + + int worldID = set.getInt(Col.ID.get()); + int serverID = set.getInt(Col.SERVER_ID.get()); + String worldName = set.getString(Col.NAME.get()); + objects.add(new WorldObj(worldID, serverID, worldName)); + } + return objects; } }); } public enum Col implements Column { ID("id"), + SERVER_ID("server_id"), NAME("world_name"); private final String column; @@ -179,3 +379,28 @@ public class WorldTable extends Table { } } } + +class WorldObj { + final int id; + final int serverId; + final String name; + + public WorldObj(int id, int serverId, String name) { + this.id = id; + this.serverId = serverId; + this.name = name; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + WorldObj worldObj = (WorldObj) o; + return Objects.equal(name, worldObj.name); + } + + @Override + public int hashCode() { + return Objects.hashCode(name); + } +} diff --git a/Plan/src/main/java/com/djrapitops/plan/system/database/databases/sql/tables/WorldTimesTable.java b/Plan/src/main/java/com/djrapitops/plan/system/database/databases/sql/tables/WorldTimesTable.java index 6c9b6897d..ed0aca9ea 100644 --- a/Plan/src/main/java/com/djrapitops/plan/system/database/databases/sql/tables/WorldTimesTable.java +++ b/Plan/src/main/java/com/djrapitops/plan/system/database/databases/sql/tables/WorldTimesTable.java @@ -12,6 +12,10 @@ import com.djrapitops.plan.system.database.databases.sql.statements.Column; import com.djrapitops.plan.system.database.databases.sql.statements.Sql; import com.djrapitops.plan.system.database.databases.sql.statements.TableSqlParser; import com.djrapitops.plan.system.info.server.ServerInfo; +import com.djrapitops.plugin.api.TimeAmount; +import com.djrapitops.plugin.api.utility.log.Log; +import com.djrapitops.plugin.task.AbsRunnable; +import com.djrapitops.plugin.task.RunnableFactory; import com.djrapitops.plugin.utilities.Verify; import java.sql.PreparedStatement; @@ -31,13 +35,20 @@ import java.util.stream.Collectors; */ public class WorldTimesTable extends UserIDTable { + private final ServerTable serverTable; + private final WorldTable worldTable; + private final SessionsTable sessionsTable; + private String insertStatement; + public WorldTimesTable(SQLDB db) { super("plan_world_times", db); worldTable = db.getWorldTable(); sessionsTable = db.getSessionsTable(); + serverTable = db.getServerTable(); insertStatement = "INSERT INTO " + tableName + " (" + Col.USER_ID + ", " + Col.WORLD_ID + ", " + + Col.SERVER_ID + ", " + Col.SESSION_ID + ", " + Col.SURVIVAL + ", " + Col.CREATIVE + ", " + @@ -46,18 +57,16 @@ public class WorldTimesTable extends UserIDTable { ") VALUES (" + usersTable.statementSelectID + ", " + worldTable.statementSelectID + ", " + + serverTable.statementSelectServerID + ", " + "?, ?, ?, ?, ?)"; } - private final WorldTable worldTable; - private final SessionsTable sessionsTable; - private String insertStatement; - @Override public void createTable() throws DBInitException { createTable(TableSqlParser.createTable(tableName) .column(Col.USER_ID, Sql.INT).notNull() .column(Col.WORLD_ID, Sql.INT).notNull() + .column(Col.SERVER_ID, Sql.INT).notNull() .column(Col.SESSION_ID, Sql.INT).notNull() .column(Col.SURVIVAL, Sql.LONG).notNull().defaultValue("0") .column(Col.CREATIVE, Sql.LONG).notNull().defaultValue("0") @@ -65,6 +74,7 @@ public class WorldTimesTable extends UserIDTable { .column(Col.SPECTATOR, Sql.LONG).notNull().defaultValue("0") .foreignKey(Col.USER_ID, usersTable.getTableName(), UsersTable.Col.ID) .foreignKey(Col.WORLD_ID, worldTable.getTableName(), WorldTable.Col.ID) + .foreignKey(Col.SERVER_ID, serverTable.getTableName(), ServerTable.Col.SERVER_ID) .foreignKey(Col.SESSION_ID, sessionsTable.getTableName(), SessionsTable.Col.ID) .toString() ); @@ -135,13 +145,16 @@ public class WorldTimesTable extends UserIDTable { GMTimes gmTimes = entry.getValue(); statement.setString(1, uuid.toString()); statement.setString(2, worldName); - statement.setInt(3, sessionID); + String serverUUID = ServerInfo.getServerUUID().toString(); + statement.setString(3, serverUUID); + statement.setString(4, serverUUID); + statement.setInt(5, sessionID); String[] gms = GMTimes.getGMKeyArray(); - statement.setLong(4, gmTimes.getTime(gms[0])); - statement.setLong(5, gmTimes.getTime(gms[1])); - statement.setLong(6, gmTimes.getTime(gms[2])); - statement.setLong(7, gmTimes.getTime(gms[3])); + statement.setLong(6, gmTimes.getTime(gms[0])); + statement.setLong(7, gmTimes.getTime(gms[1])); + statement.setLong(8, gmTimes.getTime(gms[2])); + statement.setLong(9, gmTimes.getTime(gms[3])); statement.addBatch(); } } @@ -151,8 +164,6 @@ public class WorldTimesTable extends UserIDTable { public WorldTimes getWorldTimesOfServer(UUID serverUUID) throws SQLException { String worldIDColumn = worldTable + "." + WorldTable.Col.ID; String worldNameColumn = worldTable + "." + WorldTable.Col.NAME + " as world_name"; - String sessionIDColumn = sessionsTable + "." + SessionsTable.Col.ID; - String sessionServerIDColumn = sessionsTable + ".server_id"; String sql = "SELECT " + "SUM(" + Col.SURVIVAL + ") as survival, " + "SUM(" + Col.CREATIVE + ") as creative, " + @@ -161,8 +172,7 @@ public class WorldTimesTable extends UserIDTable { worldNameColumn + " FROM " + tableName + " INNER JOIN " + worldTable + " on " + worldIDColumn + "=" + Col.WORLD_ID + - " INNER JOIN " + sessionsTable + " on " + sessionIDColumn + "=" + Col.SESSION_ID + - " WHERE " + sessionServerIDColumn + "=" + db.getServerTable().statementSelectServerID + + " WHERE " + tableName + "." + Col.SERVER_ID + "=" + db.getServerTable().statementSelectServerID + " GROUP BY " + Col.WORLD_ID; return query(new QueryStatement(sql, 1000) { @@ -315,9 +325,10 @@ public class WorldTimesTable extends UserIDTable { public void prepare(PreparedStatement statement) throws SQLException { String[] gms = GMTimes.getGMKeyArray(); // Every Server - for (Map> serverSessions : allSessions.values()) { + for (Map.Entry>> serverSessions : allSessions.entrySet()) { + UUID serverUUID = serverSessions.getKey(); // Every User - for (Map.Entry> entry : serverSessions.entrySet()) { + for (Map.Entry> entry : serverSessions.getValue().entrySet()) { UUID uuid = entry.getKey(); List sessions = entry.getValue(); // Every Session @@ -329,11 +340,13 @@ public class WorldTimesTable extends UserIDTable { GMTimes gmTimes = worldTimesEntry.getValue(); statement.setString(1, uuid.toString()); statement.setString(2, worldName); - statement.setInt(3, sessionID); - statement.setLong(4, gmTimes.getTime(gms[0])); - statement.setLong(5, gmTimes.getTime(gms[1])); - statement.setLong(6, gmTimes.getTime(gms[2])); - statement.setLong(7, gmTimes.getTime(gms[3])); + statement.setString(3, serverUUID.toString()); + statement.setString(4, serverUUID.toString()); + statement.setInt(5, sessionID); + statement.setLong(6, gmTimes.getTime(gms[0])); + statement.setLong(7, gmTimes.getTime(gms[1])); + statement.setLong(8, gmTimes.getTime(gms[2])); + statement.setLong(9, gmTimes.getTime(gms[3])); statement.addBatch(); } } @@ -343,8 +356,45 @@ public class WorldTimesTable extends UserIDTable { }); } + public void alterTableV16() { + addColumns(Col.SERVER_ID + " integer NOT NULL DEFAULT 0"); + + RunnableFactory.createNew("DB version -> 16", new AbsRunnable() { + @Override + public void run() { + try { + Map sessionIDServerIDRelation = sessionsTable.getIDServerIDRelation(); + + String sql = "UPDATE " + tableName + " SET " + + Col.SERVER_ID + "=?" + + " WHERE " + Col.SESSION_ID + "=?"; + + executeBatch(new ExecStatement(sql) { + @Override + public void prepare(PreparedStatement statement) throws SQLException { + for (Map.Entry entry : sessionIDServerIDRelation.entrySet()) { + Integer sessionID = entry.getKey(); + Integer serverID = entry.getValue(); + statement.setInt(1, serverID); + statement.setInt(2, sessionID); + statement.addBatch(); + } + } + }); + + worldTable.alterTableV16(); + } catch (SQLException e) { + Log.toLog(this.getClass().getName(), e); + } finally { + cancel(); + } + } + }).runTaskLaterAsynchronously(TimeAmount.SECOND.ticks() * 2); + } + public enum Col implements Column { USER_ID(UserIDTable.Col.USER_ID.get()), + SERVER_ID("server_id"), SESSION_ID("session_id"), WORLD_ID("world_id"), SURVIVAL("survival_time"), diff --git a/Plan/src/main/java/com/djrapitops/plan/system/database/databases/sql/tables/move/BatchOperationTable.java b/Plan/src/main/java/com/djrapitops/plan/system/database/databases/sql/tables/move/BatchOperationTable.java index 0e8ded0cd..9250679b7 100644 --- a/Plan/src/main/java/com/djrapitops/plan/system/database/databases/sql/tables/move/BatchOperationTable.java +++ b/Plan/src/main/java/com/djrapitops/plan/system/database/databases/sql/tables/move/BatchOperationTable.java @@ -169,7 +169,7 @@ public class BatchOperationTable extends Table { return; } Log.debug("Batch Copy Worlds"); - toDB.getDb().getWorldTable().saveWorlds(db.getWorldTable().getWorlds()); + toDB.getDb().getWorldTable().saveWorlds(db.getWorldTable().getAllWorlds()); } public void copyUsers(BatchOperationTable toDB) throws SQLException { diff --git a/Plan/src/main/java/com/djrapitops/plan/system/database/databases/sql/tables/move/Version8TransferTable.java b/Plan/src/main/java/com/djrapitops/plan/system/database/databases/sql/tables/move/Version8TransferTable.java index fd74bbcb6..e3f3fc0bf 100644 --- a/Plan/src/main/java/com/djrapitops/plan/system/database/databases/sql/tables/move/Version8TransferTable.java +++ b/Plan/src/main/java/com/djrapitops/plan/system/database/databases/sql/tables/move/Version8TransferTable.java @@ -38,14 +38,16 @@ public class Version8TransferTable extends Table { throw new IllegalStateException("Method not supposed to be used on this table."); } - private String tableRenameSql(String from, String to) { - return usingMySQL ? + private void renameTable(String from, String to) throws SQLException { + String sql = usingMySQL ? "RENAME TABLE " + from + " TO " + to : "ALTER TABLE " + from + " RENAME TO " + to; + execute(sql); } - private String dropTableSql(String name) { - return "DROP TABLE " + name; + private void dropTable(String name) throws SQLException { + String sql = "DROP TABLE " + name; + execute(sql); } public void alterTablesToV10() throws SQLException, DBInitException { @@ -54,23 +56,23 @@ public class Version8TransferTable extends Table { copyTPS(); - execute(dropTableSql("plan_user_info")); + dropTable("plan_user_info"); copyUsers(); - execute(dropTableSql("plan_ips")); + dropTable("plan_ips"); db.getGeoInfoTable().createTable(); - execute(dropTableSql("plan_world_times")); - execute(dropTableSql("plan_worlds")); + dropTable("plan_world_times"); + dropTable("plan_worlds"); db.getWorldTable().createTable(); db.getWorldTimesTable().createTable(); - execute(dropTableSql("plan_actions")); + dropTable("plan_actions"); db.getActionsTable().createTable(); - execute(dropTableSql("plan_gamemodetimes")); - execute(dropTableSql("temp_nicks")); - execute(dropTableSql("temp_kills")); - execute(dropTableSql("temp_users")); + dropTable("plan_gamemodetimes"); + dropTable("temp_nicks"); + dropTable("temp_kills"); + dropTable("temp_users"); db.setVersion(10); Benchmark.stop("Schema copy from 8 to 10"); @@ -79,19 +81,19 @@ public class Version8TransferTable extends Table { private void copyUsers() throws SQLException, DBInitException { String tempTableName = "temp_users"; UsersTable usersTable = db.getUsersTable(); - execute(tableRenameSql("plan_users", tempTableName)); + renameTable("plan_users", tempTableName); String tempNickTableName = "temp_nicks"; NicknamesTable nicknamesTable = db.getNicknamesTable(); - execute(tableRenameSql(nicknamesTable.toString(), tempNickTableName)); + renameTable(nicknamesTable.toString(), tempNickTableName); String tempKillsTableName = "temp_kills"; KillsTable killsTable = db.getKillsTable(); - execute(tableRenameSql(killsTable.toString(), tempKillsTableName)); + renameTable(killsTable.toString(), tempKillsTableName); usersTable.createTable(); nicknamesTable.createTable(); - execute(dropTableSql("plan_sessions")); + dropTable("plan_sessions"); db.getSessionsTable().createTable(); killsTable.createTable(); @@ -141,7 +143,7 @@ public class Version8TransferTable extends Table { String tempTableName = "temp_cmdusg"; CommandUseTable commandUseTable = db.getCommandUseTable(); - execute(tableRenameSql("plan_commandusages", tempTableName)); + renameTable("plan_commandusages", tempTableName); commandUseTable.createTable(); @@ -153,14 +155,14 @@ public class Version8TransferTable extends Table { " FROM " + tempTableName; execute(statement); - execute(dropTableSql(tempTableName)); + dropTable(tempTableName); } private void copyTPS() throws SQLException, DBInitException { String tempTableName = "temp_tps"; TPSTable tpsTable = db.getTpsTable(); - execute(tableRenameSql(tpsTable.toString(), tempTableName)); + renameTable(tpsTable.toString(), tempTableName); tpsTable.createTable(); @@ -172,6 +174,6 @@ public class Version8TransferTable extends Table { " FROM " + tempTableName; execute(statement); - execute(dropTableSql(tempTableName)); + dropTable(tempTableName); } } \ No newline at end of file diff --git a/Plan/src/main/java/com/djrapitops/plan/system/info/request/GenerateAnalysisPageRequest.java b/Plan/src/main/java/com/djrapitops/plan/system/info/request/GenerateAnalysisPageRequest.java index a39122b83..37cf23ca0 100644 --- a/Plan/src/main/java/com/djrapitops/plan/system/info/request/GenerateAnalysisPageRequest.java +++ b/Plan/src/main/java/com/djrapitops/plan/system/info/request/GenerateAnalysisPageRequest.java @@ -16,6 +16,7 @@ import com.djrapitops.plan.system.info.server.ServerInfo; import com.djrapitops.plan.system.webserver.pages.parsing.AnalysisPage; import com.djrapitops.plan.system.webserver.response.DefaultResponses; import com.djrapitops.plan.system.webserver.response.Response; +import com.djrapitops.plan.system.webserver.response.errors.InternalErrorResponse; import com.djrapitops.plan.utilities.analysis.Analysis; import com.djrapitops.plugin.api.utility.log.Log; import com.djrapitops.plugin.utilities.Verify; @@ -93,7 +94,7 @@ public class GenerateAnalysisPageRequest extends InfoRequestWithVariables implem throw new InternalErrorException("Analysis failed due to exception", e); } catch (InterruptedException | ExecutionException e) { /* Plugin is shutting down, exceptions ignored */ - return "

Plugin is shutting down..

"; + return new InternalErrorResponse("Plugin may be shutting down", e).getContent(); } catch (Exception e) { Log.toLog(this.getClass(), e); throw new InternalErrorException("Analysis failed due to exception", e); diff --git a/Plan/src/test/java/com/djrapitops/plan/system/database/databases/SQLiteTest.java b/Plan/src/test/java/com/djrapitops/plan/system/database/databases/SQLiteTest.java index f5e0b8903..fb70fc211 100644 --- a/Plan/src/test/java/com/djrapitops/plan/system/database/databases/SQLiteTest.java +++ b/Plan/src/test/java/com/djrapitops/plan/system/database/databases/SQLiteTest.java @@ -323,7 +323,7 @@ public class SQLiteTest { commitTest(); - List saved = worldTable.getWorlds(); + List saved = worldTable.getAllWorlds(); assertEquals(new HashSet<>(worlds), new HashSet<>(saved)); } @@ -602,7 +602,7 @@ public class SQLiteTest { assertTrue(sessionsTable.getSessions(playerUUID).isEmpty()); assertTrue(actionsTable.getActions(playerUUID).isEmpty()); assertTrue(db.getCommandUseTable().getCommandUse().isEmpty()); - assertTrue(db.getWorldTable().getWorlds().isEmpty()); + assertTrue(db.getWorldTable().getAllWorlds().isEmpty()); assertTrue(tpsTable.getTPSData().isEmpty()); assertTrue(db.getServerTable().getBukkitServers().isEmpty()); assertTrue(securityTable.getUsers().isEmpty()); @@ -784,7 +784,7 @@ public class SQLiteTest { assertFalse(sessionsTable.getSessions(playerUUID).isEmpty()); assertFalse(actionsTable.getActions(playerUUID).isEmpty()); assertFalse(backup.getCommandUseTable().getCommandUse().isEmpty()); - assertFalse(backup.getWorldTable().getWorlds().isEmpty()); + assertFalse(backup.getWorldTable().getAllWorlds().isEmpty()); assertFalse(tpsTable.getTPSData().isEmpty()); assertFalse(backup.getServerTable().getBukkitServers().isEmpty()); assertFalse(securityTable.getUsers().isEmpty()); @@ -852,6 +852,20 @@ public class SQLiteTest { assertEquals(worldTimes, allSessions.get(serverUUID).get(playerUUID).get(0).getWorldTimes()); } + @Test + public void testGetUserWorldTimes() throws SQLException { + testSaveSessionsWorldTimes(); + WorldTimes worldTimesOfUser = db.getWorldTimesTable().getWorldTimesOfUser(playerUUID); + assertEquals(createWorldTimes(), worldTimesOfUser); + } + + @Test + public void testGetServerWorldTimes() throws SQLException { + testSaveSessionsWorldTimes(); + WorldTimes worldTimesOfServer = db.getWorldTimesTable().getWorldTimesOfServer(TestConstants.SERVER_UUID); + assertEquals(createWorldTimes(), worldTimesOfServer); + } + @Test public void testRegisterProcessorRegisterException() throws SQLException { assertFalse(db.getUsersTable().isRegistered(playerUUID)); @@ -881,7 +895,7 @@ public class SQLiteTest { @Test public void testWorldTableGetWorldNamesNoException() throws SQLException { - Set worldNames = db.getWorldTable().getWorldNames(); + Set worldNames = db.getWorldTable().getWorldNames(TestConstants.SERVER_UUID); } @Test