From f3c8778ad261fb1059995eb981c621a2b4680eea Mon Sep 17 00:00:00 2001 From: ceze88 Date: Wed, 2 Aug 2023 17:20:52 +0200 Subject: [PATCH] Updates to new database system --- .../com/craftaro/epicanchors/api/Anchor.java | 3 +- .../com/craftaro/epicanchors/AnchorImpl.java | 38 +++ .../epicanchors/AnchorManagerImpl.java | 44 ++- .../com/craftaro/epicanchors/EpicAnchors.java | 19 +- .../epicanchors/files/DataManager.java | 306 ++++-------------- .../files/migration/AnchorMigration.java | 21 +- .../files/migration/_1_InitialMigration.java | 8 +- .../epicanchors/listener/AnchorListener.java | 2 +- .../epicanchors/utils/DataHelper.java | 101 ++++++ 9 files changed, 253 insertions(+), 289 deletions(-) create mode 100644 EpicAnchors-Plugin/src/main/java/com/craftaro/epicanchors/utils/DataHelper.java diff --git a/EpicAnchors-API/src/main/java/com/craftaro/epicanchors/api/Anchor.java b/EpicAnchors-API/src/main/java/com/craftaro/epicanchors/api/Anchor.java index e7345c0..e61633c 100644 --- a/EpicAnchors-API/src/main/java/com/craftaro/epicanchors/api/Anchor.java +++ b/EpicAnchors-API/src/main/java/com/craftaro/epicanchors/api/Anchor.java @@ -1,5 +1,6 @@ package com.craftaro.epicanchors.api; +import com.craftaro.core.database.Data; import org.bukkit.Chunk; import org.bukkit.Location; import org.bukkit.World; @@ -7,7 +8,7 @@ import org.jetbrains.annotations.NotNull; import java.util.UUID; -public interface Anchor { +public interface Anchor extends Data { int getDbId(); UUID getOwner(); diff --git a/EpicAnchors-Plugin/src/main/java/com/craftaro/epicanchors/AnchorImpl.java b/EpicAnchors-Plugin/src/main/java/com/craftaro/epicanchors/AnchorImpl.java index c63feef..9a0e521 100644 --- a/EpicAnchors-Plugin/src/main/java/com/craftaro/epicanchors/AnchorImpl.java +++ b/EpicAnchors-Plugin/src/main/java/com/craftaro/epicanchors/AnchorImpl.java @@ -1,5 +1,7 @@ package com.craftaro.epicanchors; +import com.craftaro.core.database.Data; +import com.craftaro.core.database.SerializedLocation; import com.craftaro.epicanchors.api.Anchor; import com.craftaro.epicanchors.utils.WorldUtils; import org.bukkit.Bukkit; @@ -10,6 +12,8 @@ import org.bukkit.plugin.Plugin; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import java.util.LinkedHashMap; +import java.util.Map; import java.util.Objects; import java.util.UUID; @@ -21,6 +25,15 @@ public class AnchorImpl implements Anchor { private final Location location; private int ticksLeft; + /** + * Default constructor for deserialization. + */ + public AnchorImpl() { + dbId = 0; + owner = null; + location = null; + } + public AnchorImpl(int dbId, @Nullable UUID owner, @NotNull Location location, int ticksLeft) { if (dbId <= 0) throw new IllegalArgumentException("Invalid value for dbId"); if (ticksLeft <= 0 && ticksLeft != -1) throw new IllegalArgumentException("Invalid value for ticksLeft"); @@ -137,4 +150,29 @@ public class AnchorImpl implements Anchor { public boolean isInfinite() { return this.ticksLeft == -1; } + + @Override + public Map serialize() { + Map map = new LinkedHashMap<>(); + map.put("id", dbId); + map.putAll(SerializedLocation.of(location)); + map.put("ticks_left", ticksLeft); + map.put("owner", owner == null ? null : owner.toString()); + return map; + } + + @Override + public Data deserialize(Map map) { + return new AnchorImpl( + (int) map.get("id"), + map.get("owner") == null ? null : UUID.fromString((String) map.get("owner")), + SerializedLocation.of(map), + (int) map.get("ticks_left") + ); + } + + @Override + public String getTableName() { + return "anchors"; + } } diff --git a/EpicAnchors-Plugin/src/main/java/com/craftaro/epicanchors/AnchorManagerImpl.java b/EpicAnchors-Plugin/src/main/java/com/craftaro/epicanchors/AnchorManagerImpl.java index 7c19a56..3e22153 100644 --- a/EpicAnchors-Plugin/src/main/java/com/craftaro/epicanchors/AnchorManagerImpl.java +++ b/EpicAnchors-Plugin/src/main/java/com/craftaro/epicanchors/AnchorManagerImpl.java @@ -3,6 +3,8 @@ package com.craftaro.epicanchors; import com.craftaro.core.SongodaPlugin; import com.craftaro.core.compatibility.CompatibleMaterial; import com.craftaro.core.compatibility.CompatibleParticleHandler; +import com.craftaro.core.database.Data; +import com.craftaro.core.database.DataManager; import com.craftaro.core.hooks.HologramManager; import com.craftaro.core.third_party.com.cryptomorin.xseries.XMaterial; import com.craftaro.core.third_party.com.cryptomorin.xseries.XSound; @@ -12,9 +14,9 @@ import com.craftaro.core.utils.TimeUtils; import com.craftaro.epicanchors.api.Anchor; import com.craftaro.epicanchors.api.AnchorAccessCheck; import com.craftaro.epicanchors.api.AnchorManager; -import com.craftaro.epicanchors.files.DataManager; import com.craftaro.epicanchors.files.Settings; import com.craftaro.epicanchors.utils.Callback; +import com.craftaro.epicanchors.utils.DataHelper; import com.craftaro.epicanchors.utils.UpdateCallback; import com.craftaro.epicanchors.utils.Utils; import org.bukkit.Bukkit; @@ -31,6 +33,7 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.util.ArrayList; +import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; @@ -62,7 +65,8 @@ public class AnchorManagerImpl implements AnchorManager { protected void saveAll() { for (Set anchorSet : this.anchors.values()) { - this.dataManager.updateAnchors(anchorSet, null); + Collection asData = new ArrayList<>(anchorSet.size()); + this.dataManager.saveBatch(asData); } } @@ -83,7 +87,7 @@ public class AnchorManagerImpl implements AnchorManager { long start = System.nanoTime(); - this.dataManager.getAnchors(world, (ex, result) -> { + DataHelper.getAnchors(world, (ex, result) -> { if (ex == null) { this.anchors.computeIfAbsent(world, key -> new HashSet<>()); @@ -114,8 +118,10 @@ public class AnchorManagerImpl implements AnchorManager { protected void deInitAnchors(@NotNull World world) { Set tmpAnchors = this.anchors.remove(world); + if (tmpAnchors != null) { - this.dataManager.updateAnchors(tmpAnchors, null); + Collection asData = new ArrayList<>(tmpAnchors.size()); + this.dataManager.saveBatch(asData); for (Anchor anchor : tmpAnchors) { ((AnchorImpl) anchor).deInit(this.plugin); @@ -229,27 +235,19 @@ public class AnchorManagerImpl implements AnchorManager { throw new IllegalStateException(ERR_WORLD_NOT_READY); } - this.dataManager.insertAnchorAsync(loc, Objects.requireNonNull(owner), ticks, (ex, anchor) -> { - if (ex != null) { - if (callback != null) { - callback.accept(ex, null); - } else { - Utils.logException(this.plugin, ex, "SQLite"); - } - } else { - Bukkit.getScheduler().runTask(this.plugin, () -> { - Block block = loc.getBlock(); - block.setType(Settings.MATERIAL.getMaterial().parseMaterial()); + Anchor anchor = new AnchorImpl(dataManager.getNextId("anchors"), owner, loc, ticks); + this.dataManager.save(anchor); + Bukkit.getScheduler().runTask(this.plugin, () -> { //TODO: Do we need to run this sync, or we are already on the main thread? + Block block = loc.getBlock(); + block.setType(Settings.MATERIAL.getMaterial().parseMaterial()); - this.anchors.computeIfAbsent(anchor.getWorld(), key -> new HashSet<>()) - .add(anchor); + this.anchors.computeIfAbsent(anchor.getWorld(), key -> new HashSet<>()) + .add(anchor); - updateHologram(anchor); + updateHologram(anchor); - if (callback != null) { - callback.accept(null, anchor); - } - }); + if (callback != null) { + callback.accept(null, anchor); } }); } @@ -292,7 +290,7 @@ public class AnchorManagerImpl implements AnchorManager { anchor.getLocation().add(.5, .5, .5), 100, .5, .5, .5); ((AnchorImpl) anchor).deInit(this.plugin); - this.dataManager.deleteAnchorAsync(anchor); + this.dataManager.delete(anchor); } /* Anchor access */ diff --git a/EpicAnchors-Plugin/src/main/java/com/craftaro/epicanchors/EpicAnchors.java b/EpicAnchors-Plugin/src/main/java/com/craftaro/epicanchors/EpicAnchors.java index 154089e..265cf5c 100644 --- a/EpicAnchors-Plugin/src/main/java/com/craftaro/epicanchors/EpicAnchors.java +++ b/EpicAnchors-Plugin/src/main/java/com/craftaro/epicanchors/EpicAnchors.java @@ -30,6 +30,7 @@ import org.bukkit.Bukkit; import org.bukkit.World; import org.bukkit.plugin.PluginManager; +import java.util.Arrays; import java.util.Collections; import java.util.List; import java.util.logging.Level; @@ -38,8 +39,6 @@ public final class EpicAnchors extends SongodaPlugin { private GuiManager guiManager; private AnchorManagerImpl anchorManager; - private DataManager dataManager; - @Override public void onPluginLoad() { } @@ -49,13 +48,15 @@ public final class EpicAnchors extends SongodaPlugin { SongodaCore.registerPlugin(this, 31, XMaterial.END_PORTAL_FRAME); // Initialize database - this.getLogger().info("Initializing SQLite..."); - DatabaseConnector dbCon = new SQLiteConnector(this); - this.dataManager = new DataManager(dbCon, this); - AnchorMigration anchorMigration = new AnchorMigration(dbCon, this.dataManager, new _1_InitialMigration()); - anchorMigration.runMigrations(); +// this.getLogger().info("Initializing SQLite..."); +// DatabaseConnector dbCon = new SQLiteConnector(this); +// this.dataManager = new DataManager(dbCon, this); +// AnchorMigration anchorMigration = new AnchorMigration(dbCon, this.dataManager, new _1_InitialMigration()); +// anchorMigration.runMigrations(); +// anchorMigration.migrateLegacyData(this); + + initDatabase(Arrays.asList(new _1_InitialMigration(), new AnchorMigration())); - anchorMigration.migrateLegacyData(this); this.anchorManager = new AnchorManagerImpl(this, this.dataManager); EpicAnchorsApi.initApi(this.anchorManager); @@ -100,7 +101,7 @@ public final class EpicAnchors extends SongodaPlugin { if (this.dataManager != null) { this.anchorManager.deInitAll(); - this.dataManager.close(); + this.dataManager.shutdown(); } // Remove all holograms diff --git a/EpicAnchors-Plugin/src/main/java/com/craftaro/epicanchors/files/DataManager.java b/EpicAnchors-Plugin/src/main/java/com/craftaro/epicanchors/files/DataManager.java index 1daf7c0..8e196e3 100644 --- a/EpicAnchors-Plugin/src/main/java/com/craftaro/epicanchors/files/DataManager.java +++ b/EpicAnchors-Plugin/src/main/java/com/craftaro/epicanchors/files/DataManager.java @@ -1,6 +1,5 @@ package com.craftaro.epicanchors.files; -import com.craftaro.core.database.DataManagerAbstract; import com.craftaro.core.database.DatabaseConnector; import com.craftaro.epicanchors.AnchorImpl; import com.craftaro.epicanchors.api.Anchor; @@ -28,248 +27,71 @@ import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit; -public class DataManager extends DataManagerAbstract { - private final ExecutorService thread = Executors.newSingleThreadExecutor(); +public class DataManager { - private final String anchorTable; - public DataManager(DatabaseConnector databaseConnector, Plugin plugin) { - super(databaseConnector, plugin); - this.anchorTable = getTableName(super.getTablePrefix(), "anchors"); - } - - public void close() { - if (!this.thread.isShutdown()) { - this.thread.shutdown(); - - try { - if (!this.thread.awaitTermination(60, TimeUnit.SECONDS)) { - // Try stopping the thread forcefully (there is basically no hope left for the data) - this.thread.shutdownNow(); - } - } catch (InterruptedException ex) { - Utils.logException(super.plugin, ex); - } - - this.databaseConnector.closeConnection(); - } - } - - public void exists(@NotNull String worldName, int x, int y, int z, @NotNull Callback callback) { - this.databaseConnector.connect((con) -> { - try (PreparedStatement ps = con.prepareStatement("SELECT id FROM " + this.anchorTable + - " WHERE world_name =? AND x =? AND y =? AND z=?;")) { - ps.setString(1, worldName); - ps.setInt(2, x); - ps.setInt(3, y); - ps.setInt(4, z); - - ResultSet rs = ps.executeQuery(); - - callback.accept(null, rs.next()); - } catch (Exception ex) { - resolveCallback(callback, ex); - } - }); - } - - public void getAnchors(@Nullable World world, @NotNull Callback> callback) { - List result = new ArrayList<>(); - - this.databaseConnector.connect((con) -> { - try (PreparedStatement ps = con.prepareStatement("SELECT * FROM " + this.anchorTable + - (world != null ? " WHERE world_name =?" : "") + ";")) { - if (world != null) { - ps.setString(1, world.getName()); - } - - ResultSet rs = ps.executeQuery(); - - while (rs.next()) { - result.add(extractAnchor(rs)); - } - - callback.accept(null, result); - } catch (Exception ex) { - resolveCallback(callback, ex); - } - }); - } - - public void insertAnchorAsync(Location loc, UUID owner, int ticks, Callback callback) { - this.thread.execute(() -> insertAnchor(loc, owner, ticks, callback)); - } - - public void insertAnchor(Location loc, UUID owner, int ticks, Callback callback) { - this.databaseConnector.connect((con) -> { - try (PreparedStatement ps = con.prepareStatement("INSERT INTO " + this.anchorTable + - "(owner, world_name,x,y,z, ticks_left) VALUES (?,?,?,?,?, ?);");// Future SQLite version might support 'RETURNING *' - PreparedStatement psFetch = con.prepareStatement("SELECT * FROM " + this.anchorTable + - " WHERE world_name =? AND x =? AND y =? AND z=?;")) { - ps.setString(1, owner != null ? owner.toString() : null); - - ps.setString(2, Objects.requireNonNull(loc.getWorld()).getName()); - psFetch.setString(1, Objects.requireNonNull(loc.getWorld()).getName()); - - ps.setInt(3, loc.getBlockX()); - psFetch.setInt(2, loc.getBlockX()); - - ps.setInt(4, loc.getBlockY()); - psFetch.setInt(3, loc.getBlockY()); - - ps.setInt(5, loc.getBlockZ()); - psFetch.setInt(4, loc.getBlockZ()); - - ps.setInt(6, ticks); - - ps.executeUpdate(); - - if (callback != null) { - ResultSet rs = psFetch.executeQuery(); - rs.next(); - - callback.accept(null, extractAnchor(rs)); - } - } catch (Exception ex) { - resolveCallback(callback, ex); - } - }); - } - - public void migrateAnchor(List anchorEntries, UpdateCallback callback) { - this.databaseConnector.connect((con) -> { - con.setAutoCommit(false); - - SQLException err = null; - - try (PreparedStatement ps = con.prepareStatement("INSERT INTO " + this.anchorTable + - "(world_name,x,y,z, ticks_left) VALUES (?,?,?,?, ?);")) { - for (AnchorMigration.LegacyAnchorEntry entry : anchorEntries) { - ps.setString(1, entry.worldName); - ps.setInt(2, entry.x); - ps.setInt(3, entry.y); - ps.setInt(4, entry.z); - - ps.setInt(5, entry.ticksLeft); - - ps.addBatch(); - } - - int[] batchRes = ps.executeBatch(); - - for (int i : batchRes) { - if (i < 0 && i != Statement.SUCCESS_NO_INFO) { - throw new AssertionError("Batch-INSERT failed for at least one statement with code " + i); - } - } - } catch (SQLException ex) { - err = ex; - } - - if (err == null) { - con.commit(); - - resolveUpdateCallback(callback, null); - } else { - con.rollback(); - - resolveUpdateCallback(callback, err); - } - - con.setAutoCommit(true); - }); - } - - public void updateAnchors(Collection anchors, UpdateCallback callback) { - this.databaseConnector.connect((con) -> { - con.setAutoCommit(false); - - SQLException err = null; - - for (Anchor anchor : anchors) { - try (PreparedStatement ps = con.prepareStatement("UPDATE " + this.anchorTable + - " SET ticks_left =? WHERE id =?;")) { - ps.setInt(1, anchor.getTicksLeft()); - ps.setInt(2, anchor.getDbId()); - - ps.executeUpdate(); - } catch (SQLException ex) { - err = ex; - break; - } - } - - if (err == null) { - con.commit(); - - resolveUpdateCallback(callback, null); - } else { - con.rollback(); - - resolveUpdateCallback(callback, err); - } - - con.setAutoCommit(true); - }); - } - - public void deleteAnchorAsync(Anchor anchor) { - deleteAnchorAsync(anchor, null); - } - - public void deleteAnchorAsync(Anchor anchor, UpdateCallback callback) { - this.thread.execute(() -> - this.databaseConnector.connect((con) -> { - try (PreparedStatement ps = con.prepareStatement("DELETE FROM " + this.anchorTable + - " WHERE id =?;")) { - ps.setInt(1, anchor.getDbId()); - - ps.executeUpdate(); - - resolveUpdateCallback(callback, null); - } catch (Exception ex) { - resolveUpdateCallback(callback, ex); - } - }) - ); - } - - public static String getTableName(String prefix, String name) { - String result = prefix + name; - - if (!result.matches("[a-z0-9_]+")) { - throw new IllegalStateException("The generated table name '" + result + "' contains invalid characters"); - } - - return result; - } - - private Anchor extractAnchor(ResultSet rs) throws SQLException { - String ownerStr = rs.getString("owner"); - - return new AnchorImpl(rs.getInt("id"), - ownerStr != null ? UUID.fromString(ownerStr) : null, - new Location(Bukkit.getWorld(rs.getString("world_name")), - rs.getInt("x"), - rs.getInt("y"), - rs.getInt("z")), - rs.getInt("ticks_left")); - } - - private void resolveUpdateCallback(@Nullable UpdateCallback callback, @Nullable Exception ex) { - if (callback != null) { - callback.accept(ex); - } else if (ex != null) { - Utils.logException(this.plugin, ex, "SQLite"); - } - } - - private void resolveCallback(@Nullable Callback callback, @NotNull Exception ex) { - if (callback != null) { - callback.accept(ex, null); - } else { - Utils.logException(this.plugin, ex, "SQLite"); - } - } +// public void updateAnchors(Collection anchors, UpdateCallback callback) { +// this.databaseConnector.connect((con) -> { +// con.setAutoCommit(false); +// +// SQLException err = null; +// +// for (Anchor anchor : anchors) { +// try (PreparedStatement ps = con.prepareStatement("UPDATE " + this.anchorTable + +// " SET ticks_left =? WHERE id =?;")) { +// ps.setInt(1, anchor.getTicksLeft()); +// ps.setInt(2, anchor.getDbId()); +// +// ps.executeUpdate(); +// } catch (SQLException ex) { +// err = ex; +// break; +// } +// } +// +// if (err == null) { +// con.commit(); +// +// resolveUpdateCallback(callback, null); +// } else { +// con.rollback(); +// +// resolveUpdateCallback(callback, err); +// } +// +// con.setAutoCommit(true); +// }); +// } +// +// public void deleteAnchorAsync(Anchor anchor) { +// deleteAnchorAsync(anchor, null); +// } +// +// public void deleteAnchorAsync(Anchor anchor, UpdateCallback callback) { +// this.thread.execute(() -> +// this.databaseConnector.connect((con) -> { +// try (PreparedStatement ps = con.prepareStatement("DELETE FROM " + this.anchorTable + +// " WHERE id =?;")) { +// ps.setInt(1, anchor.getDbId()); +// +// ps.executeUpdate(); +// +// resolveUpdateCallback(callback, null); +// } catch (Exception ex) { +// resolveUpdateCallback(callback, ex); +// } +// }) +// ); +// } +// +// public static String getTableName(String prefix, String name) { +// String result = prefix + name; +// +// if (!result.matches("[a-z0-9_]+")) { +// throw new IllegalStateException("The generated table name '" + result + "' contains invalid characters"); +// } +// +// return result; +// } } diff --git a/EpicAnchors-Plugin/src/main/java/com/craftaro/epicanchors/files/migration/AnchorMigration.java b/EpicAnchors-Plugin/src/main/java/com/craftaro/epicanchors/files/migration/AnchorMigration.java index ed9483a..2de69ca 100644 --- a/EpicAnchors-Plugin/src/main/java/com/craftaro/epicanchors/files/migration/AnchorMigration.java +++ b/EpicAnchors-Plugin/src/main/java/com/craftaro/epicanchors/files/migration/AnchorMigration.java @@ -3,31 +3,32 @@ package com.craftaro.epicanchors.files.migration; import com.craftaro.core.configuration.Config; import com.craftaro.core.configuration.ConfigSection; import com.craftaro.core.database.DataMigration; -import com.craftaro.core.database.DataMigrationManager; import com.craftaro.core.database.DatabaseConnector; +import com.craftaro.epicanchors.EpicAnchors; import com.craftaro.epicanchors.files.DataManager; +import com.craftaro.epicanchors.utils.DataHelper; import com.craftaro.epicanchors.utils.ThreadSync; import org.bukkit.Location; import org.bukkit.plugin.Plugin; import java.io.IOException; import java.nio.file.Files; +import java.sql.Connection; import java.util.ArrayList; import java.util.List; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicBoolean; import java.util.logging.Level; -public class AnchorMigration extends DataMigrationManager { - private final DataManager dataManager; +public class AnchorMigration extends DataMigration { - public AnchorMigration(DatabaseConnector databaseConnector, DataManager dataManager, DataMigration... migrations) { - super(databaseConnector, dataManager, migrations); - - this.dataManager = dataManager; + public AnchorMigration() { + super(2); } - public void migrateLegacyData(Plugin plugin) { + @Override + public void migrate(DatabaseConnector databaseConnector, String tablePrefix) { + Plugin plugin = EpicAnchors.getPlugin(EpicAnchors.class); long start = System.nanoTime(); AtomicBoolean abortMigration = new AtomicBoolean(false); @@ -67,7 +68,7 @@ public class AnchorMigration extends DataMigrationManager { int z = Location.locToBlock(Double.parseDouble(locArgs[3])); int finalTicksLeft = ticksLeft; - this.dataManager.exists(worldName, x, y, z, (ex, anchorExists) -> { + DataHelper.exists(worldName, x, y, z, (ex, anchorExists) -> { if (ex == null) { if (anchorExists) { cfgSection.set(locationStr, null); @@ -94,7 +95,7 @@ public class AnchorMigration extends DataMigrationManager { if (!abortMigration.get()) { int finalMigratedAnchors = migratedAnchors; - this.dataManager.migrateAnchor(anchorQueue, ex -> { + DataHelper.migrateAnchor(anchorQueue, ex -> { long end = System.nanoTime(); if (ex == null) { diff --git a/EpicAnchors-Plugin/src/main/java/com/craftaro/epicanchors/files/migration/_1_InitialMigration.java b/EpicAnchors-Plugin/src/main/java/com/craftaro/epicanchors/files/migration/_1_InitialMigration.java index ac135f1..67ba8d0 100644 --- a/EpicAnchors-Plugin/src/main/java/com/craftaro/epicanchors/files/migration/_1_InitialMigration.java +++ b/EpicAnchors-Plugin/src/main/java/com/craftaro/epicanchors/files/migration/_1_InitialMigration.java @@ -1,6 +1,8 @@ package com.craftaro.epicanchors.files.migration; import com.craftaro.core.database.DataMigration; +import com.craftaro.core.database.DatabaseConnector; +import com.craftaro.epicanchors.EpicAnchors; import com.craftaro.epicanchors.files.DataManager; import java.sql.Connection; @@ -13,9 +15,9 @@ public class _1_InitialMigration extends DataMigration { } @Override - public void migrate(Connection connection, String tablePrefix) throws SQLException { - try (Statement statement = connection.createStatement()) { - statement.execute("CREATE TABLE " + DataManager.getTableName(tablePrefix, "anchors") + "(" + + public void migrate(DatabaseConnector databaseConnector, String tablePrefix) throws SQLException { + try (Statement statement = databaseConnector.getConnection().createStatement()) { + statement.execute("CREATE TABLE " + EpicAnchors.getPlugin(EpicAnchors.class).getDataManager().getTablePrefix() + "anchors (" + "id INTEGER NOT NULL," + "world_name TEXT NOT NULL," + "x INTEGER NOT NULL," + diff --git a/EpicAnchors-Plugin/src/main/java/com/craftaro/epicanchors/listener/AnchorListener.java b/EpicAnchors-Plugin/src/main/java/com/craftaro/epicanchors/listener/AnchorListener.java index 58a2ce6..0c47201 100644 --- a/EpicAnchors-Plugin/src/main/java/com/craftaro/epicanchors/listener/AnchorListener.java +++ b/EpicAnchors-Plugin/src/main/java/com/craftaro/epicanchors/listener/AnchorListener.java @@ -49,7 +49,7 @@ public class AnchorListener implements Listener { this.plugin.getAnchorManager().createAnchor(e.getBlock().getLocation(), e.getPlayer().getUniqueId(), ticksLeft, (ex, result) -> { if (ex != null) { - Utils.logException(this.plugin, ex, "SQLite"); + Utils.logException(this.plugin, ex, "SQL"); e.getPlayer().sendMessage("Error creating anchor!"); // TODO Bukkit.getScheduler().runTask(this.plugin, () -> { diff --git a/EpicAnchors-Plugin/src/main/java/com/craftaro/epicanchors/utils/DataHelper.java b/EpicAnchors-Plugin/src/main/java/com/craftaro/epicanchors/utils/DataHelper.java new file mode 100644 index 0000000..d95eb5b --- /dev/null +++ b/EpicAnchors-Plugin/src/main/java/com/craftaro/epicanchors/utils/DataHelper.java @@ -0,0 +1,101 @@ +package com.craftaro.epicanchors.utils; + +import com.craftaro.core.database.Data; +import com.craftaro.core.database.DataManager; +import com.craftaro.core.third_party.org.jooq.Queries; +import com.craftaro.core.third_party.org.jooq.Query; +import com.craftaro.core.third_party.org.jooq.Record1; +import com.craftaro.core.third_party.org.jooq.Result; +import com.craftaro.core.third_party.org.jooq.impl.DSL; +import com.craftaro.epicanchors.AnchorImpl; +import com.craftaro.epicanchors.EpicAnchors; +import com.craftaro.epicanchors.api.Anchor; +import com.craftaro.epicanchors.files.migration.AnchorMigration; +import org.bukkit.World; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.List; + +public class DataHelper { + + public static void exists(@NotNull String worldName, int x, int y, int z, @NotNull Callback callback) { + DataManager dataManager = EpicAnchors.getPlugin(EpicAnchors.class).getDataManager(); + + dataManager.getDatabaseConnector().connectDSL(dslContext -> { + try { + @NotNull Result> result = dslContext.select(DSL.field("id")).from(DSL.table(dataManager.getTablePrefix() + "anchors")) + .where(DSL.field("world_name").eq(worldName)) + .and(DSL.field("x").eq(x)) + .and(DSL.field("y").eq(y)) + .and(DSL.field("z").eq(z)).fetch(); + + callback.accept(null, result.size() > 0); + } catch (Exception ex) { + resolveCallback(callback, ex); + } + }); + } + + public static void getAnchors(@Nullable World world, @NotNull Callback> callback) { + try { + callback.accept(null, EpicAnchors.getPlugin(EpicAnchors.class).getDataManager().loadBatch(AnchorImpl.class, "anchors")); + } catch (Exception ex) { + resolveCallback(callback, ex); + } + } + + private static void resolveUpdateCallback(@Nullable UpdateCallback callback, @Nullable Exception ex) { + if (callback != null) { + callback.accept(ex); + } else if (ex != null) { + Utils.logException(EpicAnchors.getPlugin(EpicAnchors.class), ex, "SQL"); + } + } + + private static void resolveCallback(@Nullable Callback callback, @NotNull Exception ex) { + if (callback != null) { + callback.accept(ex, null); + } else { + Utils.logException(EpicAnchors.getPlugin(EpicAnchors.class), ex, "SQL"); + } + } + + + public static void migrateAnchor(List anchorQueue, UpdateCallback callback) { + DataManager dataManager = EpicAnchors.getPlugin(EpicAnchors.class).getDataManager(); + + //recreate it with Jooq + dataManager.getDatabaseConnector().connectDSL(dslContext -> { + Connection connection = dslContext.configuration().connectionProvider().acquire(); + connection.setAutoCommit(false); + try { + List queries = new ArrayList<>(); + for (AnchorMigration.LegacyAnchorEntry entry : anchorQueue) { + queries.add(dslContext.insertInto(DSL.table(dataManager.getTablePrefix() + "anchors")) + .columns( + DSL.field("world_name"), + DSL.field("x"), + DSL.field("y"), + DSL.field("z"), + DSL.field("ticks_left")) + .values(entry.worldName, entry.x, entry.y, entry.z, entry.ticksLeft)); + } + dslContext.batch(queries).execute(); + connection.commit(); + } catch (Exception ex) { + connection.rollback(); + resolveUpdateCallback(callback, ex); + } finally { + connection.setAutoCommit(true); + dslContext.configuration().connectionProvider().release(connection); + } + }); + } +}