mirror of
https://github.com/LuckPerms/LuckPerms.git
synced 2024-11-18 16:45:36 +01:00
Upgrade h2 database engine to v2 (#3458)
This commit is contained in:
parent
495d951556
commit
e35f46798b
@ -160,7 +160,7 @@ public enum Dependency {
|
|||||||
"IydH+gkk2Iom36QrgSi2+hFAgC2AQSWJFZboyl8pEyI=",
|
"IydH+gkk2Iom36QrgSi2+hFAgC2AQSWJFZboyl8pEyI=",
|
||||||
Relocation.of("postgresql", "org{}postgresql")
|
Relocation.of("postgresql", "org{}postgresql")
|
||||||
),
|
),
|
||||||
H2_DRIVER(
|
H2_DRIVER_LEGACY(
|
||||||
"com.h2database",
|
"com.h2database",
|
||||||
"h2",
|
"h2",
|
||||||
// seems to be a compat bug in 1.4.200 with older dbs
|
// seems to be a compat bug in 1.4.200 with older dbs
|
||||||
@ -170,6 +170,14 @@ public enum Dependency {
|
|||||||
// we don't apply relocations to h2 - it gets loaded via
|
// we don't apply relocations to h2 - it gets loaded via
|
||||||
// an isolated classloader
|
// an isolated classloader
|
||||||
),
|
),
|
||||||
|
H2_DRIVER(
|
||||||
|
"com.h2database",
|
||||||
|
"h2",
|
||||||
|
"2.1.214",
|
||||||
|
"1iPNwPYdIYz1SajQnxw5H/kQlhFrIuJHVHX85PvnK9A="
|
||||||
|
// we don't apply relocations to h2 - it gets loaded via
|
||||||
|
// an isolated classloader
|
||||||
|
),
|
||||||
SQLITE_DRIVER(
|
SQLITE_DRIVER(
|
||||||
"org.xerial",
|
"org.xerial",
|
||||||
"sqlite-jdbc",
|
"sqlite-jdbc",
|
||||||
|
@ -128,6 +128,7 @@ public class DependencyRegistry {
|
|||||||
case ASM_COMMONS:
|
case ASM_COMMONS:
|
||||||
case JAR_RELOCATOR:
|
case JAR_RELOCATOR:
|
||||||
case H2_DRIVER:
|
case H2_DRIVER:
|
||||||
|
case H2_DRIVER_LEGACY:
|
||||||
case SQLITE_DRIVER:
|
case SQLITE_DRIVER:
|
||||||
return false;
|
return false;
|
||||||
default:
|
default:
|
||||||
|
@ -114,7 +114,7 @@ public class StorageFactory {
|
|||||||
case H2:
|
case H2:
|
||||||
return new SqlStorage(
|
return new SqlStorage(
|
||||||
this.plugin,
|
this.plugin,
|
||||||
new H2ConnectionFactory(this.plugin.getBootstrap().getDataDirectory().resolve("luckperms-h2")),
|
new H2ConnectionFactory(this.plugin.getBootstrap().getDataDirectory().resolve("luckperms-h2-v2")),
|
||||||
this.plugin.getConfiguration().get(ConfigKeys.SQL_TABLE_PREFIX)
|
this.plugin.getConfiguration().get(ConfigKeys.SQL_TABLE_PREFIX)
|
||||||
);
|
);
|
||||||
case POSTGRESQL:
|
case POSTGRESQL:
|
||||||
|
@ -30,9 +30,12 @@ import me.lucko.luckperms.common.dependencies.classloader.IsolatedClassLoader;
|
|||||||
import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
|
import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
|
||||||
|
|
||||||
import java.lang.reflect.Constructor;
|
import java.lang.reflect.Constructor;
|
||||||
|
import java.nio.file.Files;
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
import java.sql.Connection;
|
import java.sql.Connection;
|
||||||
import java.sql.SQLException;
|
import java.sql.SQLException;
|
||||||
|
import java.sql.Statement;
|
||||||
|
import java.util.Collections;
|
||||||
import java.util.EnumSet;
|
import java.util.EnumSet;
|
||||||
import java.util.Properties;
|
import java.util.Properties;
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
@ -56,16 +59,22 @@ public class H2ConnectionFactory extends FlatfileConnectionFactory {
|
|||||||
IsolatedClassLoader classLoader = plugin.getDependencyManager().obtainClassLoaderWith(EnumSet.of(Dependency.H2_DRIVER));
|
IsolatedClassLoader classLoader = plugin.getDependencyManager().obtainClassLoaderWith(EnumSet.of(Dependency.H2_DRIVER));
|
||||||
try {
|
try {
|
||||||
Class<?> connectionClass = classLoader.loadClass("org.h2.jdbc.JdbcConnection");
|
Class<?> connectionClass = classLoader.loadClass("org.h2.jdbc.JdbcConnection");
|
||||||
this.connectionConstructor = connectionClass.getConstructor(String.class, Properties.class);
|
this.connectionConstructor = connectionClass.getConstructor(String.class, Properties.class, String.class, Object.class, boolean.class);
|
||||||
} catch (ReflectiveOperationException e) {
|
} catch (ReflectiveOperationException e) {
|
||||||
throw new RuntimeException(e);
|
throw new RuntimeException(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
new MigrateH2ToVersion2(plugin, super.getWriteFile().getParent()).run(this);
|
||||||
|
} catch (Exception e) {
|
||||||
|
plugin.getLogger().warn("Something went wrong whilst upgrading the LuckPerms database. Please report this on GitHub.", e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Connection createConnection(Path file) throws SQLException {
|
protected Connection createConnection(Path file) throws SQLException {
|
||||||
try {
|
try {
|
||||||
return (Connection) this.connectionConstructor.newInstance("jdbc:h2:" + file.toString(), new Properties());
|
return (Connection) this.connectionConstructor.newInstance("jdbc:h2:" + file.toString(), new Properties(), null, null, false);
|
||||||
} catch (ReflectiveOperationException e) {
|
} catch (ReflectiveOperationException e) {
|
||||||
if (e.getCause() instanceof SQLException) {
|
if (e.getCause() instanceof SQLException) {
|
||||||
throw (SQLException) e.getCause();
|
throw (SQLException) e.getCause();
|
||||||
@ -83,6 +92,79 @@ public class H2ConnectionFactory extends FlatfileConnectionFactory {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Function<String, String> getStatementProcessor() {
|
public Function<String, String> getStatementProcessor() {
|
||||||
return s -> s.replace('\'', '`').replace("LIKE", "ILIKE");
|
return s -> s.replace('\'', '`')
|
||||||
|
.replace("LIKE", "ILIKE")
|
||||||
|
.replace("value", "`value`")
|
||||||
|
.replace("``value``", "`value`");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Migrates the old (version 1) H2 database to version 2.
|
||||||
|
*
|
||||||
|
* See <a href="http://www.h2database.com/html/migration-to-v2.html">here</a> for more info.
|
||||||
|
*/
|
||||||
|
private static final class MigrateH2ToVersion2 {
|
||||||
|
private final LuckPermsPlugin plugin;
|
||||||
|
private final Path directory;
|
||||||
|
|
||||||
|
MigrateH2ToVersion2(LuckPermsPlugin plugin, Path directory) {
|
||||||
|
this.plugin = plugin;
|
||||||
|
this.directory = directory;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void run(H2ConnectionFactory newFactory) throws Exception {
|
||||||
|
Path oldDatabase = this.directory.resolve("luckperms-h2");
|
||||||
|
Path oldDatabaseWriteFile = this.directory.resolve("luckperms-h2.mv.db");
|
||||||
|
|
||||||
|
if (!Files.exists(oldDatabaseWriteFile)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Path tempMigrationFile = this.directory.resolve("luckperms-h2-migration.sql");
|
||||||
|
|
||||||
|
this.plugin.getLogger().warn("[DB Upgrade] Found an old (v1) H2 database file. LuckPerms will now attempt to upgrade it to v2 (this is a one time operation).");
|
||||||
|
|
||||||
|
this.plugin.getLogger().info("[DB Upgrade] Stage 1: Exporting the old database to an intermediary file...");
|
||||||
|
Constructor<?> constructor = getConnectionConstructor();
|
||||||
|
try (Connection c = getConnection(constructor, oldDatabase)) {
|
||||||
|
try (Statement stmt = c.createStatement()) {
|
||||||
|
stmt.execute(String.format("SCRIPT TO '%s'", tempMigrationFile));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.plugin.getLogger().info("[DB Upgrade] Stage 2: Importing the intermediary file into the new database...");
|
||||||
|
try (Connection c = newFactory.getConnection()) {
|
||||||
|
try (Statement stmt = c.createStatement()) {
|
||||||
|
stmt.execute(String.format("RUNSCRIPT FROM '%s'", tempMigrationFile));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this.plugin.getLogger().info("[DB Upgrade] Stage 3: Tidying up...");
|
||||||
|
Files.deleteIfExists(tempMigrationFile);
|
||||||
|
Files.move(oldDatabaseWriteFile, this.directory.resolve("luckperms-h2-v1-backup.mv.db"));
|
||||||
|
|
||||||
|
this.plugin.getLogger().info("[DB Upgrade] All done!");
|
||||||
|
}
|
||||||
|
|
||||||
|
private Constructor<?> getConnectionConstructor() {
|
||||||
|
this.plugin.getDependencyManager().loadDependencies(Collections.singleton(Dependency.H2_DRIVER_LEGACY));
|
||||||
|
IsolatedClassLoader classLoader = this.plugin.getDependencyManager().obtainClassLoaderWith(EnumSet.of(Dependency.H2_DRIVER_LEGACY));
|
||||||
|
try {
|
||||||
|
Class<?> connectionClass = classLoader.loadClass("org.h2.jdbc.JdbcConnection");
|
||||||
|
return connectionClass.getConstructor(String.class, Properties.class);
|
||||||
|
} catch (ReflectiveOperationException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private Connection getConnection(Constructor<?> constructor, Path file) {
|
||||||
|
try {
|
||||||
|
return (Connection) constructor.newInstance("jdbc:h2:" + file.toString(), new Properties());
|
||||||
|
} catch (ReflectiveOperationException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user