-
Notifications
You must be signed in to change notification settings - Fork 14
Fix SQLite schema bootstrap and legacy database detection #21
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: develop
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,77 @@ | ||
| package fr.maxlego08.zauctionhouse.storage; | ||
|
|
||
| import fr.maxlego08.sarah.database.Schema; | ||
| import fr.maxlego08.zauctionhouse.api.item.StorageType; | ||
| import fr.maxlego08.zauctionhouse.api.storage.Tables; | ||
|
|
||
| import java.util.LinkedHashMap; | ||
| import java.util.Map; | ||
| import java.util.function.Consumer; | ||
|
|
||
| public final class StorageSchemaDefinitions { | ||
|
|
||
| private StorageSchemaDefinitions() { | ||
| } | ||
|
|
||
| public static Map<String, Consumer<Schema>> requiredTables() { | ||
| Map<String, Consumer<Schema>> tables = new LinkedHashMap<>(); | ||
| tables.put(Tables.PLAYERS, StorageSchemaDefinitions::players); | ||
| tables.put(Tables.ITEMS, StorageSchemaDefinitions::items); | ||
| tables.put(Tables.AUCTION_ITEMS, StorageSchemaDefinitions::auctionItems); | ||
| tables.put(Tables.TRANSACTIONS, StorageSchemaDefinitions::transactions); | ||
| tables.put(Tables.LOGS, StorageSchemaDefinitions::logs); | ||
| return tables; | ||
| } | ||
|
|
||
| public static void players(Schema table) { | ||
| table.uuid("unique_id").primary().unique(); | ||
| table.string("name", 16); | ||
| table.timestamps(); | ||
| } | ||
|
|
||
| public static void items(Schema table) { | ||
| table.autoIncrement("id"); | ||
| table.string("item_type", 255); | ||
| table.string("seller_unique_id", 36).foreignKey(Tables.PLAYERS, "unique_id", true); | ||
| table.string("buyer_unique_id", 36).nullable().foreignKey(Tables.PLAYERS, "unique_id", true); | ||
| table.decimal("price", 65, 2); | ||
| table.string("economy_name", 255); | ||
| table.enumType("storage_type", StorageType.class); | ||
| table.string("server_name", 255); | ||
| table.timestamp("expired_at"); | ||
| table.timestamps(); | ||
| } | ||
|
|
||
| public static void auctionItems(Schema table) { | ||
| table.autoIncrement("id"); | ||
| table.integer("item_id").foreignKey(Tables.ITEMS, "id", true); | ||
| table.longText("itemstack"); | ||
| table.timestamps(); | ||
| } | ||
|
|
||
| public static void transactions(Schema table) { | ||
| table.autoIncrement("id"); | ||
| table.integer("item_id").foreignKey(Tables.ITEMS, "id", true); | ||
| table.string("player_unique_id", 36).foreignKey(Tables.PLAYERS, "unique_id", true); | ||
| table.string("economy_name", 255); | ||
| table.decimal("before", 65, 2); | ||
| table.decimal("after", 65, 2); | ||
| table.decimal("value", 65, 2); | ||
| table.string("status", 32); | ||
| table.timestamps(); | ||
| } | ||
|
|
||
| public static void logs(Schema table) { | ||
| table.autoIncrement("id"); | ||
| table.integer("item_id").foreignKey(Tables.ITEMS, "id", true); | ||
| table.string("log_type", 255); | ||
| table.string("player_unique_id", 36).foreignKey(Tables.PLAYERS, "unique_id", true); | ||
| table.string("target_unique_id", 36).nullable().foreignKey(Tables.PLAYERS, "unique_id", true); | ||
| table.longText("itemstack").nullable(); | ||
| table.decimal("price", 65, 2).defaultValue(0); | ||
| table.string("economy_name", 255).nullable(); | ||
| table.longText("additional_data").nullable(); | ||
| table.timestamp("readed_at").nullable(); | ||
| table.timestamps(); | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -25,13 +25,21 @@ | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import org.bukkit.inventory.ItemStack; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import org.jetbrains.annotations.NotNull; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import java.io.File; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import java.sql.Connection; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import java.sql.DatabaseMetaData; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import java.sql.ResultSet; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import java.sql.SQLException; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import java.math.BigDecimal; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import java.util.*; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import java.util.concurrent.CompletableFuture; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import java.util.stream.Collectors; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| public class ZStorageManager extends ItemLoaderUtils implements StorageManager { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| private static final String SQLITE_DATABASE_FILE = "database.db"; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| private static final String SQLITE_LEGACY_DATABASE_FILE = "storage.db"; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| private final AuctionPlugin plugin; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| private AuctionLoader auctionLoader; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| private Repositories repositories; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -48,6 +56,9 @@ public boolean onEnable() { | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| var databaseConfiguration = this.getDatabaseConfiguration(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| var isSqlite = databaseConfiguration.getDatabaseType() == DatabaseType.SQLITE; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| this.databaseConnection = isSqlite ? new SqliteConnection(databaseConfiguration, this.plugin.getDataFolder(), sarahLogger) : new HikariDatabaseConnection(databaseConfiguration, sarahLogger); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (isSqlite && this.databaseConnection instanceof SqliteConnection sqliteConnection) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| configureSqliteFile(sqliteConnection); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (!databaseConnection.isValid()) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -58,7 +69,7 @@ public boolean onEnable() { | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| this.plugin.getLogger().info("The database connection is valid !"); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| MigrationManager.setMigrationTableName("zauctionhousev4_migrations"); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| MigrationManager.setMigrationTableName(resolveMigrationTableName(databaseConfiguration.getTablePrefix())); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| MigrationManager.setDatabaseConfiguration(databaseConfiguration); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| MigrationManager.registerMigration(new CreatePlayerMigration()); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -77,6 +88,7 @@ public boolean onEnable() { | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| this.repositories.register(TransactionRepository.class); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| MigrationManager.execute(this.databaseConnection, sarahLogger); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ensureRequiredTablesExist(sarahLogger); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return true; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -239,4 +251,63 @@ public List<Item> selectItems(List<Integer> integers) { | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| public Map<UUID, String> selectPlayers(List<String> uuids) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return with(PlayerRepository.class).select(uuids).stream().collect(Collectors.toMap(PlayerDTO::unique_id, PlayerDTO::name)); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| private void configureSqliteFile(SqliteConnection sqliteConnection) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| File dataFolder = this.plugin.getDataFolder(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| File currentFile = new File(dataFolder, SQLITE_DATABASE_FILE); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| File legacyFile = new File(dataFolder, SQLITE_LEGACY_DATABASE_FILE); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (legacyFile.exists() && !currentFile.exists()) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| sqliteConnection.setFileName(SQLITE_LEGACY_DATABASE_FILE); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| this.plugin.getLogger().info("Using legacy SQLite database file: " + SQLITE_LEGACY_DATABASE_FILE); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| sqliteConnection.setFileName(SQLITE_DATABASE_FILE); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| private String resolveMigrationTableName(String tablePrefix) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return (tablePrefix == null ? "" : tablePrefix) + "migrations"; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| private void ensureRequiredTablesExist(fr.maxlego08.sarah.logger.Logger logger) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| StorageSchemaDefinitions.requiredTables().forEach((tableName, definition) -> { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (tableExists(tableName)) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| String resolvedTableName = this.databaseConnection.getDatabaseConfiguration().replacePrefix(tableName); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| this.plugin.getLogger().warning("Missing required table '" + resolvedTableName + "'. Recreating it now."); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| try { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| SchemaBuilder.create(null, tableName, definition).execute(this.databaseConnection, logger); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } catch (SQLException exception) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| throw new IllegalStateException("Failed to recreate missing table '" + resolvedTableName + "'", exception); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| private boolean tableExists(String tableName) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| String resolvedTableName = this.databaseConnection.getDatabaseConfiguration().replacePrefix(tableName); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| try (Connection connection = this.databaseConnection.getConnection()) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| DatabaseMetaData metaData = connection.getMetaData(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+274
to
+292
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| StorageSchemaDefinitions.requiredTables().forEach((tableName, definition) -> { | |
| if (tableExists(tableName)) { | |
| return; | |
| } | |
| String resolvedTableName = this.databaseConnection.getDatabaseConfiguration().replacePrefix(tableName); | |
| this.plugin.getLogger().warning("Missing required table '" + resolvedTableName + "'. Recreating it now."); | |
| try { | |
| SchemaBuilder.create(null, tableName, definition).execute(this.databaseConnection, logger); | |
| } catch (SQLException exception) { | |
| throw new IllegalStateException("Failed to recreate missing table '" + resolvedTableName + "'", exception); | |
| } | |
| }); | |
| } | |
| private boolean tableExists(String tableName) { | |
| String resolvedTableName = this.databaseConnection.getDatabaseConfiguration().replacePrefix(tableName); | |
| try (Connection connection = this.databaseConnection.getConnection()) { | |
| DatabaseMetaData metaData = connection.getMetaData(); | |
| try (Connection connection = this.databaseConnection.getConnection()) { | |
| DatabaseMetaData metaData = connection.getMetaData(); | |
| if (metaData == null) { | |
| this.plugin.getLogger().warning("Failed to inspect required tables: database metadata is unavailable."); | |
| return; | |
| } | |
| StorageSchemaDefinitions.requiredTables().forEach((tableName, definition) -> { | |
| if (tableExists(connection, metaData, tableName)) { | |
| return; | |
| } | |
| String resolvedTableName = this.databaseConnection.getDatabaseConfiguration().replacePrefix(tableName); | |
| this.plugin.getLogger().warning("Missing required table '" + resolvedTableName + "'. Recreating it now."); | |
| try { | |
| SchemaBuilder.create(null, tableName, definition).execute(this.databaseConnection, logger); | |
| } catch (SQLException exception) { | |
| throw new IllegalStateException("Failed to recreate missing table '" + resolvedTableName + "'", exception); | |
| } | |
| }); | |
| } catch (SQLException exception) { | |
| throw new IllegalStateException("Failed to inspect required tables", exception); | |
| } | |
| } | |
| private boolean tableExists(String tableName) { | |
| try (Connection connection = this.databaseConnection.getConnection()) { | |
| DatabaseMetaData metaData = connection.getMetaData(); | |
| return tableExists(connection, metaData, tableName); | |
| } catch (SQLException exception) { | |
| String resolvedTableName = this.databaseConnection.getDatabaseConfiguration().replacePrefix(tableName); | |
| this.plugin.getLogger().warning("Failed to inspect table '" + resolvedTableName + "': " + exception.getMessage()); | |
| return false; | |
| } | |
| } | |
| private boolean tableExists(Connection connection, DatabaseMetaData metaData, String tableName) { | |
| String resolvedTableName = this.databaseConnection.getDatabaseConfiguration().replacePrefix(tableName); | |
| try { |
Copilot
AI
Apr 6, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
tableExists() returns false on any SQLException while inspecting metadata, which makes ensureRequiredTablesExist() assume the table is missing and attempt a CREATE TABLE. If metadata inspection fails for driver/permission reasons, this can incorrectly try to recreate existing tables (and potentially fail startup). Consider treating inspection failure as a hard error (disable plugin) or skipping self-heal when table existence can't be determined reliably.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,24 +1,13 @@ | ||
| package fr.maxlego08.zauctionhouse.storage.migrations; | ||
|
|
||
| import fr.maxlego08.sarah.database.Migration; | ||
| import fr.maxlego08.zauctionhouse.api.item.StorageType; | ||
| import fr.maxlego08.zauctionhouse.api.storage.Tables; | ||
| import fr.maxlego08.zauctionhouse.storage.StorageSchemaDefinitions; | ||
|
|
||
| public class CreateItemMigration extends Migration { | ||
|
|
||
| @Override | ||
| public void up() { | ||
| create(Tables.ITEMS, table -> { | ||
| table.autoIncrement("id"); | ||
| table.string("item_type", 255); | ||
| table.string("seller_unique_id", 36).foreignKey(Tables.PLAYERS, "unique_id", true); | ||
| table.string("buyer_unique_id", 36).nullable().foreignKey(Tables.PLAYERS, "unique_id", true); | ||
| table.decimal("price", 65, 2); | ||
| table.string("economy_name", 255); | ||
| table.enumType("storage_type", StorageType.class); | ||
| table.string("server_name", 255); | ||
| table.timestamp("expired_at"); | ||
| table.timestamps(); | ||
| }); | ||
| create(Tables.ITEMS, StorageSchemaDefinitions::items); | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,16 +1,13 @@ | ||
| package fr.maxlego08.zauctionhouse.storage.migrations; | ||
|
|
||
| import fr.maxlego08.sarah.database.Migration; | ||
| import fr.maxlego08.zauctionhouse.storage.StorageSchemaDefinitions; | ||
| import fr.maxlego08.zauctionhouse.api.storage.Tables; | ||
|
|
||
| public class CreatePlayerMigration extends Migration { | ||
|
|
||
| @Override | ||
| public void up() { | ||
| create(Tables.PLAYERS, table -> { | ||
| table.uuid("unique_id").primary().unique(); | ||
| table.string("name", 16); | ||
| table.timestamps(); | ||
| }); | ||
| create(Tables.PLAYERS, StorageSchemaDefinitions::players); | ||
| } | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Switching the migration tracking table name from the previously hard-coded value to a prefix-derived value can orphan existing installs' migration history (e.g., upgrades that already have the old migrations table). Consider adding a compatibility fallback (detect old table name and reuse/rename/copy it) or at least log clearly that migrations will be re-evaluated under a new tracking table to avoid unexpected behavior on upgrade.