Flipped a < to minimize register dates

An issue in register date minimization was reported,
which was caused by a flipped < in
PlayerServerRegisterTransaction - Maximizing the
register date instead.

< was flipped and a Patch was written to fix the
incorrect data.
This commit is contained in:
Rsl1122 2019-11-30 10:47:52 +02:00
parent c553a2c606
commit d2a616cee5
6 changed files with 112 additions and 4 deletions

View File

@ -168,7 +168,8 @@ public abstract class SQLDB extends AbstractDatabase {
new DeleteIPsPatch(),
new ExtensionShowInPlayersTablePatch(),
new ExtensionTableRowValueLengthPatch(),
new CommandUsageTableRemovalPatch()
new CommandUsageTableRemovalPatch(),
new RegisterDateMinimizationPatch()
};
}

View File

@ -28,6 +28,7 @@ import com.djrapitops.plan.storage.database.transactions.patches.Version10Patch;
* Patches related to this table:
* {@link Version10Patch}
* {@link UserInfoOptimizationPatch}
* {@link com.djrapitops.plan.storage.database.transactions.patches.RegisterDateMinimizationPatch}
*
* @author Rsl1122
*/

View File

@ -23,11 +23,12 @@ import com.djrapitops.plan.storage.database.sql.parsing.Sql;
/**
* Table information about 'plan_users'.
*
* <p>
* This table is used to store Player information that applies to all servers.
*
* <p>
* Patches that apply to this table:
* {@link com.djrapitops.plan.storage.database.transactions.patches.Version10Patch}
* {@link com.djrapitops.plan.storage.database.transactions.patches.RegisterDateMinimizationPatch}
*
* @author Rsl1122
*/

View File

@ -47,7 +47,7 @@ public class PlayerServerRegisterTransaction extends PlayerRegisterTransaction {
// Updates register date to smallest possible value.
Optional<Long> foundRegisterDate = query(PlayerFetchQueries.fetchRegisterDate(playerUUID));
if (foundRegisterDate.isPresent() && foundRegisterDate.get() < registerDate) {
if (foundRegisterDate.isPresent() && foundRegisterDate.get() > registerDate) {
execute(DataStoreQueries.updateMainRegisterDate(playerUUID, registerDate));
}
}

View File

@ -0,0 +1,75 @@
package com.djrapitops.plan.storage.database.transactions.patches;
import com.djrapitops.plan.storage.database.queries.Query;
import com.djrapitops.plan.storage.database.queries.QueryAllStatement;
import com.djrapitops.plan.storage.database.sql.tables.UserInfoTable;
import com.djrapitops.plan.storage.database.sql.tables.UsersTable;
import com.djrapitops.plan.storage.database.transactions.ExecBatchStatement;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import static com.djrapitops.plan.storage.database.sql.parsing.Sql.*;
public class RegisterDateMinimizationPatch extends Patch {
private Map<UUID, Long> registerDates;
@Override
public boolean hasBeenApplied() {
registerDates = query(fetchSmallestServerRegisterDates());
return registerDates.isEmpty();
}
private Query<Map<UUID, Long>> fetchSmallestServerRegisterDates() {
String sql = SELECT + "u1.uuid,u1." + UsersTable.REGISTERED + ",min_registered" + FROM + '(' +
SELECT + UserInfoTable.USER_UUID + ',' +
"MIN(" + UserInfoTable.REGISTERED + ") as min_registered" +
FROM + UserInfoTable.TABLE_NAME +
GROUP_BY + UserInfoTable.USER_UUID + ") u2" +
INNER_JOIN + UsersTable.TABLE_NAME + " u1 on u1.uuid=u2.uuid" +
WHERE + "u1." + UsersTable.REGISTERED + ">min_registered";
return new QueryAllStatement<Map<UUID, Long>>(sql, 500) {
@Override
public Map<UUID, Long> processResults(ResultSet set) throws SQLException {
Map<UUID, Long> registerDates = new HashMap<>();
while (set.next()) {
UUID playerUUID = UUID.fromString(set.getString(1));
long newRegisterDate = set.getLong("min_registered");
registerDates.put(playerUUID, newRegisterDate);
}
return registerDates;
}
};
}
@Override
protected void applyPatch() {
if (registerDates.isEmpty()) return;
String sql = "UPDATE " + UsersTable.TABLE_NAME + " SET " + UsersTable.REGISTERED + "=?" +
WHERE + UsersTable.USER_UUID + "=?" +
AND + UsersTable.REGISTERED + ">?";
execute(new ExecBatchStatement(sql) {
@Override
public void prepare(PreparedStatement statement) throws SQLException {
for (Map.Entry<UUID, Long> entry : registerDates.entrySet()) {
UUID playerUUID = entry.getKey();
Long registerDate = entry.getValue();
statement.setLong(1, registerDate);
statement.setString(2, playerUUID.toString());
statement.setLong(3, registerDate);
statement.addBatch();
}
}
});
}
}

View File

@ -56,6 +56,7 @@ import com.djrapitops.plan.storage.database.queries.containers.ContainerFetchQue
import com.djrapitops.plan.storage.database.queries.containers.ServerPlayerContainersQuery;
import com.djrapitops.plan.storage.database.queries.objects.*;
import com.djrapitops.plan.storage.database.sql.parsing.Sql;
import com.djrapitops.plan.storage.database.sql.tables.UserInfoTable;
import com.djrapitops.plan.storage.database.transactions.*;
import com.djrapitops.plan.storage.database.transactions.commands.*;
import com.djrapitops.plan.storage.database.transactions.events.*;
@ -63,6 +64,7 @@ import com.djrapitops.plan.storage.database.transactions.init.CreateIndexTransac
import com.djrapitops.plan.storage.database.transactions.init.CreateTablesTransaction;
import com.djrapitops.plan.storage.database.transactions.init.RemoveDuplicateUserInfoTransaction;
import com.djrapitops.plan.storage.database.transactions.patches.Patch;
import com.djrapitops.plan.storage.database.transactions.patches.RegisterDateMinimizationPatch;
import com.djrapitops.plan.storage.upkeep.DBCleanTask;
import com.djrapitops.plan.utilities.comparators.DateHolderRecentComparator;
import com.djrapitops.plugin.logging.console.TestPluginLogger;
@ -84,6 +86,7 @@ import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
import static com.djrapitops.plan.storage.database.sql.parsing.Sql.SELECT;
import static com.djrapitops.plan.storage.database.sql.parsing.Sql.WHERE;
import static org.junit.jupiter.api.Assertions.*;
/**
@ -1193,6 +1196,33 @@ public interface DatabaseTest {
assertEquals(javaCalculation.getValue(), currentActivityIndex.get().getValue(), 0.001);
}
@Test
default void registerDateIsMinimized() {
executeTransactions(
new PlayerServerRegisterTransaction(playerUUID, () -> 1000, TestConstants.PLAYER_ONE_NAME, serverUUID())
, new Transaction() {
@Override
protected void performOperations() {
execute("UPDATE " + UserInfoTable.TABLE_NAME + " SET " + UserInfoTable.REGISTERED + "=0" + WHERE + UserInfoTable.USER_UUID + "='" + playerUUID + "'");
}
}
);
// Check test assumptions
Map<UUID, Long> registerDates = db().query(UserInfoQueries.fetchRegisterDates(0L, System.currentTimeMillis(), serverUUID()));
assertEquals(0L, registerDates.get(playerUUID));
Optional<BaseUser> baseUser = db().query(BaseUserQueries.fetchBaseUserOfPlayer(playerUUID));
assertEquals(1000L, baseUser.isPresent() ? baseUser.get().getRegistered() : null);
RegisterDateMinimizationPatch testedPatch = new RegisterDateMinimizationPatch();
executeTransactions(testedPatch);
// Test expected result
Optional<BaseUser> updatedBaseUser = db().query(BaseUserQueries.fetchBaseUserOfPlayer(playerUUID));
assertEquals(0L, updatedBaseUser.isPresent() ? updatedBaseUser.get().getRegistered() : null);
assertTrue(testedPatch.hasBeenApplied());
}
@Test
default void extensionPlayerValuesAreStored() {
ExtensionServiceImplementation extensionService = (ExtensionServiceImplementation) system().getExtensionService();