mirror of
https://github.com/plan-player-analytics/Plan.git
synced 2025-01-30 16:19:56 +08:00
Add /plan db migrate_to_online_uuids command
This commit is contained in:
parent
2f6718a78f
commit
7b41165af5
@ -58,6 +58,7 @@ dependencies {
|
||||
shadow "org.eclipse.jetty:jetty-server:$jettyVersion"
|
||||
shadow "org.eclipse.jetty:jetty-alpn-java-server:$jettyVersion"
|
||||
shadow "org.eclipse.jetty.http2:http2-server:$jettyVersion"
|
||||
shadow 'com.googlecode.json-simple:json-simple:1.1.1' // json simple used by UUIDFetcher
|
||||
|
||||
// Swagger annotations
|
||||
implementation "jakarta.ws.rs:jakarta.ws.rs-api:3.1.0"
|
||||
|
@ -333,15 +333,27 @@ public class PlanCommand {
|
||||
.subcommand(removeCommand())
|
||||
.subcommand(uninstalledCommand())
|
||||
.subcommand(removeJoinAddressesCommand())
|
||||
.subcommand(onlineUuidMigration())
|
||||
.requirePermission(Permissions.DATA_BASE)
|
||||
.description(locale.getString(HelpLang.DB))
|
||||
.inDepthDescription(locale.getString(DeepHelpLang.DB))
|
||||
.build();
|
||||
}
|
||||
|
||||
private Subcommand onlineUuidMigration() {
|
||||
return Subcommand.builder()
|
||||
.aliases("migrate_to_online_uuids", "migratetoonlineuuids")
|
||||
.requirePermission(Permissions.DATA_CLEAR)
|
||||
.optionalArgument("--remove_offline", "Remove offline players if given")
|
||||
.description(locale.getString(HelpLang.ONLINE_UUID_MIGRATION))
|
||||
.inDepthDescription("Moves and combines offline uuid data to online uuids where possible. Leaves offline-only players to database.")
|
||||
.onCommand((sender, arguments) -> databaseCommands.onOnlineConversion(commandName, sender, arguments))
|
||||
.build();
|
||||
}
|
||||
|
||||
private Subcommand removeJoinAddressesCommand() {
|
||||
return Subcommand.builder()
|
||||
.aliases("removejoinaddresses")
|
||||
.aliases("remove_join_addresses", "removejoinaddresses")
|
||||
.requirePermission(Permissions.DATA_CLEAR)
|
||||
.requiredArgument(locale.getString(HelpLang.ARG_SERVER), locale.getString(HelpLang.DESC_ARG_SERVER_IDENTIFIER))
|
||||
.description(locale.getString(HelpLang.JOIN_ADDRESS_REMOVAL))
|
||||
|
@ -39,7 +39,7 @@ public class Confirmation {
|
||||
) {
|
||||
this.locale = locale;
|
||||
awaiting = Caffeine.newBuilder()
|
||||
.expireAfterWrite(90, TimeUnit.SECONDS)
|
||||
.expireAfterWrite(5, TimeUnit.MINUTES)
|
||||
.build();
|
||||
}
|
||||
|
||||
|
@ -19,13 +19,16 @@ package com.djrapitops.plan.commands.subcommands;
|
||||
import com.djrapitops.plan.commands.use.Arguments;
|
||||
import com.djrapitops.plan.commands.use.CMDSender;
|
||||
import com.djrapitops.plan.commands.use.ColorScheme;
|
||||
import com.djrapitops.plan.commands.use.MessageBuilder;
|
||||
import com.djrapitops.plan.delivery.formatting.Formatter;
|
||||
import com.djrapitops.plan.delivery.formatting.Formatters;
|
||||
import com.djrapitops.plan.exceptions.database.DBOpException;
|
||||
import com.djrapitops.plan.gathering.domain.BaseUser;
|
||||
import com.djrapitops.plan.identification.Identifiers;
|
||||
import com.djrapitops.plan.identification.Server;
|
||||
import com.djrapitops.plan.identification.ServerInfo;
|
||||
import com.djrapitops.plan.identification.ServerUUID;
|
||||
import com.djrapitops.plan.processing.Processing;
|
||||
import com.djrapitops.plan.query.QuerySvc;
|
||||
import com.djrapitops.plan.settings.config.PlanConfig;
|
||||
import com.djrapitops.plan.settings.config.paths.DatabaseSettings;
|
||||
@ -36,23 +39,24 @@ import com.djrapitops.plan.storage.database.DBSystem;
|
||||
import com.djrapitops.plan.storage.database.DBType;
|
||||
import com.djrapitops.plan.storage.database.Database;
|
||||
import com.djrapitops.plan.storage.database.SQLiteDB;
|
||||
import com.djrapitops.plan.storage.database.queries.objects.BaseUserQueries;
|
||||
import com.djrapitops.plan.storage.database.queries.objects.ServerQueries;
|
||||
import com.djrapitops.plan.storage.database.transactions.BackupCopyTransaction;
|
||||
import com.djrapitops.plan.storage.database.transactions.commands.RemoveEverythingTransaction;
|
||||
import com.djrapitops.plan.storage.database.transactions.commands.RemovePlayerTransaction;
|
||||
import com.djrapitops.plan.storage.database.transactions.commands.SetServerAsUninstalledTransaction;
|
||||
import com.djrapitops.plan.storage.database.transactions.Transaction;
|
||||
import com.djrapitops.plan.storage.database.transactions.commands.*;
|
||||
import com.djrapitops.plan.storage.database.transactions.patches.BadFabricJoinAddressValuePatch;
|
||||
import com.djrapitops.plan.storage.file.PlanFiles;
|
||||
import com.djrapitops.plan.utilities.logging.ErrorContext;
|
||||
import com.djrapitops.plan.utilities.logging.ErrorLogger;
|
||||
import net.playeranalytics.plugin.player.UUIDFetcher;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Singleton;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Singleton
|
||||
public class DatabaseCommands {
|
||||
@ -69,8 +73,10 @@ public class DatabaseCommands {
|
||||
private final Identifiers identifiers;
|
||||
private final PluginStatusCommands statusCommands;
|
||||
private final ErrorLogger errorLogger;
|
||||
private final Processing processing;
|
||||
|
||||
private final Formatter<Long> timestamp;
|
||||
private final Formatter<Long> clock;
|
||||
|
||||
@Inject
|
||||
public DatabaseCommands(
|
||||
@ -86,7 +92,8 @@ public class DatabaseCommands {
|
||||
Formatters formatters,
|
||||
Identifiers identifiers,
|
||||
PluginStatusCommands statusCommands,
|
||||
ErrorLogger errorLogger
|
||||
ErrorLogger errorLogger,
|
||||
Processing processing
|
||||
) {
|
||||
this.locale = locale;
|
||||
this.confirmation = confirmation;
|
||||
@ -102,6 +109,8 @@ public class DatabaseCommands {
|
||||
this.errorLogger = errorLogger;
|
||||
|
||||
this.timestamp = formatters.iso8601NoClockLong();
|
||||
clock = formatters.clockLong();
|
||||
this.processing = processing;
|
||||
}
|
||||
|
||||
public void onBackup(CMDSender sender, Arguments arguments) {
|
||||
@ -472,4 +481,102 @@ public class DatabaseCommands {
|
||||
}
|
||||
statusCommands.onReload(sender);
|
||||
}
|
||||
|
||||
public void onOnlineConversion(String mainCommand, CMDSender sender, Arguments arguments) {
|
||||
boolean removeOfflinePlayers = arguments.get(0)
|
||||
.map("--remove_offline"::equals)
|
||||
.orElse(false);
|
||||
sender.send(locale.getString(CommandLang.PROGRESS_PREPARING));
|
||||
processing.submitNonCritical(() -> {
|
||||
Map<UUID, BaseUser> baseUsersByUUID = dbSystem.getDatabase().query(BaseUserQueries.fetchAllBaseUsersByUUID());
|
||||
List<String> playerNames = baseUsersByUUID.values().stream().map(BaseUser::getName).collect(Collectors.toList());
|
||||
sender.send("Performing lookup for " + playerNames.size() + " uuids from Mojang..");
|
||||
sender.send("Preparation estimated complete at: " + clock.apply(System.currentTimeMillis() + playerNames.size() * 100) + " (due to request rate limiting)");
|
||||
Map<String, UUID> onlineUUIDsOfPlayers = getUUIDViaUUIDFetcher(playerNames);
|
||||
|
||||
if (onlineUUIDsOfPlayers.isEmpty()) {
|
||||
sender.send(locale.getString(CommandLang.PROGRESS_FAIL, "Did not get any UUIDs from Mojang."));
|
||||
return;
|
||||
}
|
||||
|
||||
int totalProfiles = baseUsersByUUID.size();
|
||||
int offlineOnlyUsers = 0;
|
||||
int combine = 0;
|
||||
int move = 0;
|
||||
|
||||
List<Transaction> transactions = new ArrayList<>();
|
||||
|
||||
for (BaseUser user : baseUsersByUUID.values()) {
|
||||
String playerName = user.getName();
|
||||
UUID recordedUUID = user.getUuid();
|
||||
UUID actualUUID = onlineUUIDsOfPlayers.get(playerName);
|
||||
|
||||
if (actualUUID == null) {
|
||||
offlineOnlyUsers++;
|
||||
if (removeOfflinePlayers) transactions.add(new RemovePlayerTransaction(recordedUUID));
|
||||
continue;
|
||||
}
|
||||
if (recordedUUID == actualUUID) {
|
||||
continue;
|
||||
}
|
||||
BaseUser alreadyExistingProfile = baseUsersByUUID.get(actualUUID);
|
||||
if (alreadyExistingProfile == null) {
|
||||
move++;
|
||||
transactions.add(new ChangeUserUUIDTransaction(recordedUUID, actualUUID));
|
||||
} else {
|
||||
combine++;
|
||||
transactions.add(new CombineUserTransaction(recordedUUID, actualUUID));
|
||||
}
|
||||
}
|
||||
|
||||
MessageBuilder messageBuilder = sender.buildMessage()
|
||||
.addPart(colors.getMainColor() + "Moving to online-only UUIDs (irreversible):").newLine()
|
||||
.addPart(colors.getSecondaryColor() + " Total players in database: " + totalProfiles).newLine()
|
||||
.addPart(colors.getSecondaryColor() + (removeOfflinePlayers ? "Removing (no online UUID): " : " Offline only (no online UUID): ") + offlineOnlyUsers).newLine()
|
||||
.addPart(colors.getSecondaryColor() + " Moving to new UUID: " + move).newLine()
|
||||
.addPart(colors.getSecondaryColor() + " Combining offline and online profiles: " + combine).newLine()
|
||||
.newLine()
|
||||
.addPart(colors.getSecondaryColor() + " Estimated online UUID players in database after: " + (totalProfiles - combine - offlineOnlyUsers) + (removeOfflinePlayers ? "" : " (+" + offlineOnlyUsers + " offline)")).newLine()
|
||||
.addPart(colors.getTertiaryColor() + locale.getString(CommandLang.CONFIRM));
|
||||
if (sender.supportsChatEvents()) {
|
||||
messageBuilder
|
||||
.addPart("§2§l[\u2714]").command("/" + mainCommand + " accept").hover(locale.getString(CommandLang.CONFIRM_ACCEPT))
|
||||
.addPart(" ")
|
||||
.addPart("§4§l[\u2718]").command("/" + mainCommand + " cancel").hover(locale.getString(CommandLang.CONFIRM_DENY))
|
||||
.send();
|
||||
} else {
|
||||
messageBuilder
|
||||
.addPart(colors.getTertiaryColor() + locale.getString(CommandLang.CONFIRM)).addPart("§a/" + mainCommand + " accept")
|
||||
.addPart(" ")
|
||||
.addPart("§c/" + mainCommand + " cancel")
|
||||
.send();
|
||||
}
|
||||
|
||||
confirmation.confirm(sender, choice -> {
|
||||
if (Boolean.TRUE.equals(choice)) {
|
||||
transactions.forEach(dbSystem.getDatabase()::executeTransaction);
|
||||
dbSystem.getDatabase().executeTransaction(new Transaction() {
|
||||
@Override
|
||||
protected void performOperations() {
|
||||
sender.send(locale.getString(CommandLang.PROGRESS_SUCCESS));
|
||||
}
|
||||
});
|
||||
} else {
|
||||
sender.send(colors.getMainColor() + locale.getString(CommandLang.CONFIRM_CANCELLED_DATA));
|
||||
}
|
||||
});
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
private Map<String, UUID> getUUIDViaUUIDFetcher(List<String> playerNames) {
|
||||
try {
|
||||
return new UUIDFetcher(playerNames).call();
|
||||
} catch (Exception | NoClassDefFoundError failure) {
|
||||
errorLogger.error(failure, ErrorContext.builder()
|
||||
.related("Migrating offline uuids to online uuids")
|
||||
.build());
|
||||
return new HashMap<>();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -118,6 +118,7 @@ public enum CommandLang implements Lang {
|
||||
HOTSWAP_REMINDER("command.database.manage.hotswap", "Manage - Remind HotSwap", "§eRemember to swap to the new database (/plan db hotswap ${0}) & reload the plugin."),
|
||||
PROGRESS_START("command.database.manage.start", "Manage - Start", "> §2Processing data.."),
|
||||
PROGRESS("command.database.manage.progress", "Manage - Progress", "${0} / ${1} processed.."),
|
||||
PROGRESS_PREPARING("command.database.manage.preparing", "Manage - preparing", "Preparing.."),
|
||||
PROGRESS_SUCCESS("command.database.manage.success", "Manage - Success", "> §aSuccess!"),
|
||||
PROGRESS_FAIL("command.database.manage.fail", "Manage - Fail", "> §cSomething went wrong: ${0}"),
|
||||
CONFIRMATION("command.database.manage.confirm", "Manage - Fail, Confirmation", "> §cAdd '-a' argument to confirm execution: ${0}"),
|
||||
@ -131,7 +132,8 @@ public enum CommandLang implements Lang {
|
||||
FAIL_IMPORTER_NOT_FOUND("command.general.failNoImporter", "Manage - Fail No Importer", "§eImporter '${0}' doesn't exist"),
|
||||
FAIL_EXPORTER_NOT_FOUND("command.general.failNoExporter", "Manage - Fail No Exporter", "§eExporter '${0}' doesn't exist"),
|
||||
NO_SERVER("command.database.manage.failNoServer", "Manage - Fail No Server", "No server found with given parameters."),
|
||||
UNINSTALLING_SAME_SERVER("command.database.manage.failSameServer", "Manage - Fail Same server", "Can not mark this server as uninstalled (You are on it)");
|
||||
UNINSTALLING_SAME_SERVER("command.database.manage.failSameServer", "Manage - Fail Same server", "Can not mark this server as uninstalled (You are on it)"),
|
||||
;
|
||||
|
||||
private final String key;
|
||||
private final String identifier;
|
||||
@ -149,7 +151,7 @@ public enum CommandLang implements Lang {
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getKey() { return key; }
|
||||
public String getKey() {return key;}
|
||||
|
||||
@Override
|
||||
public String getDefault() {
|
||||
|
@ -71,7 +71,8 @@ public enum HelpLang implements Lang {
|
||||
IMPORT("command.help.import.description", "Command Help - /plan import", "Import data"),
|
||||
JSON("command.help.json.description", "Command Help - /plan json", "View json of Player's raw data."),
|
||||
LOGOUT("command.help.logout.description", "Command Help - /plan logout", "Log out other users from the panel."),
|
||||
JOIN_ADDRESS_REMOVAL("command.help.removejoinaddresses.description", "Command Help - /plan db removejoinaddresses", "Remove join addresses of a specified server");
|
||||
JOIN_ADDRESS_REMOVAL("command.help.removejoinaddresses.description", "Command Help - /plan db removejoinaddresses", "Remove join addresses of a specified server"),
|
||||
ONLINE_UUID_MIGRATION("command.help.migrateToOnlineUuids.description", "Command Help - /plan db migratetoonlineuuids", "Migrate offline uuid data to online uuids");
|
||||
|
||||
private final String identifier;
|
||||
private final String key;
|
||||
|
@ -26,10 +26,7 @@ import org.apache.commons.text.TextStringBuilder;
|
||||
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.util.Collection;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import java.util.*;
|
||||
|
||||
import static com.djrapitops.plan.storage.database.sql.building.Sql.*;
|
||||
|
||||
@ -57,6 +54,15 @@ public class BaseUserQueries {
|
||||
return db -> db.queryList(sql, BaseUserQueries::extractBaseUser);
|
||||
}
|
||||
|
||||
public static Query<Map<UUID, BaseUser>> fetchAllBaseUsersByUUID() {
|
||||
String sql = Select.all(UsersTable.TABLE_NAME).toString();
|
||||
|
||||
return db -> db.queryMap(sql, (results, map) -> {
|
||||
BaseUser baseUser = extractBaseUser(results);
|
||||
map.put(baseUser.getUuid(), baseUser);
|
||||
}, HashMap::new);
|
||||
}
|
||||
|
||||
private static BaseUser extractBaseUser(ResultSet set) throws SQLException {
|
||||
UUID playerUUID = UUID.fromString(set.getString(UsersTable.USER_UUID));
|
||||
String name = set.getString(UsersTable.USER_NAME);
|
||||
|
@ -25,6 +25,8 @@ import com.djrapitops.plan.storage.database.SQLDB;
|
||||
import com.djrapitops.plan.storage.database.queries.Query;
|
||||
import com.djrapitops.plan.storage.database.queries.QueryAPIQuery;
|
||||
import com.djrapitops.plan.storage.database.queries.QueryStatement;
|
||||
import com.djrapitops.plan.storage.database.queries.schema.MySQLSchemaQueries;
|
||||
import com.djrapitops.plan.storage.database.queries.schema.SQLiteSchemaQueries;
|
||||
import com.djrapitops.plan.storage.database.transactions.patches.Patch;
|
||||
import com.djrapitops.plan.utilities.logging.ErrorContext;
|
||||
import net.playeranalytics.plugin.scheduling.TimeAmount;
|
||||
@ -274,4 +276,15 @@ public abstract class Transaction {
|
||||
String simpleName = getClass().getSimpleName();
|
||||
return simpleName.isEmpty() ? getClass().getName() : simpleName;
|
||||
}
|
||||
|
||||
protected boolean hasTable(String tableName) {
|
||||
switch (dbType) {
|
||||
case SQLITE:
|
||||
return query(SQLiteSchemaQueries.doesTableExist(tableName));
|
||||
case MYSQL:
|
||||
return query(MySQLSchemaQueries.doesTableExist(tableName));
|
||||
default:
|
||||
throw new IllegalStateException("Unsupported Database Type: " + dbType.getName());
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,68 @@
|
||||
/*
|
||||
* This file is part of Player Analytics (Plan).
|
||||
*
|
||||
* Plan is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License v3 as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Plan is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Plan. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package com.djrapitops.plan.storage.database.transactions.commands;
|
||||
|
||||
import com.djrapitops.plan.storage.database.sql.tables.*;
|
||||
import com.djrapitops.plan.storage.database.transactions.ExecStatement;
|
||||
import com.djrapitops.plan.storage.database.transactions.Executable;
|
||||
import com.djrapitops.plan.storage.database.transactions.Transaction;
|
||||
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.SQLException;
|
||||
import java.util.UUID;
|
||||
|
||||
import static com.djrapitops.plan.storage.database.sql.building.Sql.WHERE;
|
||||
|
||||
/**
|
||||
* Intends to correct UUID of a user.
|
||||
*
|
||||
* @author AuroraLS3
|
||||
*/
|
||||
public class ChangeUserUUIDTransaction extends Transaction {
|
||||
|
||||
protected final UUID oldUUID;
|
||||
protected final UUID newUUID;
|
||||
|
||||
public ChangeUserUUIDTransaction(UUID oldUUID, UUID newUUID) {
|
||||
this.oldUUID = oldUUID;
|
||||
this.newUUID = newUUID;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void performOperations() {
|
||||
execute(updateUUID(ExtensionGroupsTable.TABLE_NAME, ExtensionGroupsTable.USER_UUID));
|
||||
execute(updateUUID(ExtensionPlayerTableValueTable.TABLE_NAME, ExtensionPlayerTableValueTable.USER_UUID));
|
||||
execute(updateUUID(NicknamesTable.TABLE_NAME, NicknamesTable.USER_UUID));
|
||||
execute(updateUUID(UsersTable.TABLE_NAME, UsersTable.USER_UUID));
|
||||
execute(updateUUID(KillsTable.TABLE_NAME, KillsTable.VICTIM_UUID));
|
||||
execute(updateUUID(KillsTable.TABLE_NAME, KillsTable.KILLER_UUID));
|
||||
|
||||
if (hasTable("plan_platforms")) execute(updateUUID("plan_platforms", "uuid"));
|
||||
if (hasTable("plan_tebex_payments")) execute(updateUUID("plan_tebex_payments", "uuid"));
|
||||
if (hasTable("plan_version_protocol")) execute(updateUUID("plan_version_protocol", "uuid"));
|
||||
}
|
||||
|
||||
private Executable updateUUID(String tableName, String columnName) {
|
||||
return new ExecStatement("UPDATE " + tableName + " SET " + columnName + "=?" + WHERE + columnName + "=?") {
|
||||
@Override
|
||||
public void prepare(PreparedStatement statement) throws SQLException {
|
||||
statement.setString(1, newUUID.toString());
|
||||
statement.setString(2, oldUUID.toString());
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
@ -0,0 +1,87 @@
|
||||
/*
|
||||
* This file is part of Player Analytics (Plan).
|
||||
*
|
||||
* Plan is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License v3 as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Plan is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Plan. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package com.djrapitops.plan.storage.database.transactions.commands;
|
||||
|
||||
import com.djrapitops.plan.storage.database.queries.objects.BaseUserQueries;
|
||||
import com.djrapitops.plan.storage.database.sql.tables.*;
|
||||
import com.djrapitops.plan.storage.database.transactions.ExecStatement;
|
||||
import com.djrapitops.plan.storage.database.transactions.Executable;
|
||||
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.SQLException;
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
|
||||
import static com.djrapitops.plan.storage.database.sql.building.Sql.*;
|
||||
|
||||
/**
|
||||
* Intends to correct UUID of a user.
|
||||
*
|
||||
* @author AuroraLS3
|
||||
*/
|
||||
public class CombineUserTransaction extends ChangeUserUUIDTransaction {
|
||||
|
||||
public CombineUserTransaction(UUID oldUUID, UUID newUUID) {
|
||||
super(oldUUID, newUUID);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void performOperations() {
|
||||
Optional<Integer> foundOldId = query(BaseUserQueries.fetchUserId(oldUUID));
|
||||
Optional<Integer> foundNewId = query(BaseUserQueries.fetchUserId(newUUID));
|
||||
if (foundOldId.isEmpty() || foundNewId.isEmpty()) return;
|
||||
|
||||
Integer oldId = foundOldId.get();
|
||||
Integer newId = foundNewId.get();
|
||||
|
||||
execute(updateUserId(GeoInfoTable.TABLE_NAME, GeoInfoTable.USER_ID, oldId, newId));
|
||||
execute(updateUserId(PingTable.TABLE_NAME, PingTable.USER_ID, oldId, newId));
|
||||
execute(updateUserId(SessionsTable.TABLE_NAME, SessionsTable.USER_ID, oldId, newId));
|
||||
execute(updateUserId(WorldTimesTable.TABLE_NAME, WorldTimesTable.USER_ID, oldId, newId));
|
||||
|
||||
execute(updateUserInfo(newId, oldId));
|
||||
execute(DELETE_FROM + UserInfoTable.TABLE_NAME + WHERE + UserInfoTable.USER_ID + "=" + oldId);
|
||||
|
||||
super.performOperations(); // Change UUID fields to match where user_id is not used
|
||||
}
|
||||
|
||||
private Executable updateUserInfo(Integer newId, Integer oldId) {
|
||||
String sql = "UPDATE " + UserInfoTable.TABLE_NAME +
|
||||
" SET " + UserInfoTable.USER_ID + "=?" +
|
||||
WHERE + UserInfoTable.USER_ID + "=?" +
|
||||
AND + UserInfoTable.SERVER_ID + " NOT IN (" +
|
||||
SELECT + UserInfoTable.SERVER_ID + FROM + UserInfoTable.TABLE_NAME + WHERE + UserInfoTable.USER_ID + "=?)";
|
||||
return new ExecStatement(sql) {
|
||||
@Override
|
||||
public void prepare(PreparedStatement statement) throws SQLException {
|
||||
statement.setInt(1, newId);
|
||||
statement.setInt(2, oldId);
|
||||
statement.setInt(3, newId);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private Executable updateUserId(String tableName, String columnName, Integer oldId, Integer newId) {
|
||||
return new ExecStatement("UPDATE " + tableName + " SET " + columnName + "=?" + WHERE + columnName + "=?") {
|
||||
@Override
|
||||
public void prepare(PreparedStatement statement) throws SQLException {
|
||||
statement.setInt(1, newId);
|
||||
statement.setInt(2, oldId);
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
@ -72,17 +72,6 @@ public abstract class Patch extends OperationCriticalTransaction {
|
||||
execute("SET FOREIGN_KEY_CHECKS=0");
|
||||
}
|
||||
|
||||
protected boolean hasTable(String tableName) {
|
||||
switch (dbType) {
|
||||
case SQLITE:
|
||||
return query(SQLiteSchemaQueries.doesTableExist(tableName));
|
||||
case MYSQL:
|
||||
return query(MySQLSchemaQueries.doesTableExist(tableName));
|
||||
default:
|
||||
throw new IllegalStateException("Unsupported Database Type: " + dbType.getName());
|
||||
}
|
||||
}
|
||||
|
||||
protected boolean hasColumn(String tableName, String columnName) {
|
||||
switch (dbType) {
|
||||
case MYSQL:
|
||||
|
@ -103,6 +103,8 @@ shadowJar {
|
||||
|
||||
relocate 'org.slf4j', 'plan.org.slf4j'
|
||||
|
||||
relocate 'org.json.simple', 'plan.org.json.simple'
|
||||
|
||||
mergeServiceFiles()
|
||||
}
|
||||
|
||||
|
@ -88,6 +88,8 @@ shadowJar {
|
||||
relocate 'jakarta.servlet', 'plan.jakarta.servlet'
|
||||
relocate 'javax.servlet', 'plan.javax.servlet'
|
||||
|
||||
relocate 'org.json.simple', 'plan.org.json.simple'
|
||||
|
||||
destinationDirectory.set(file("$rootDir/builds/"))
|
||||
archiveBaseName.set('Plan')
|
||||
archiveClassifier.set('')
|
||||
|
Loading…
Reference in New Issue
Block a user