Class AbstractSqlStorage

java.lang.Object
com.enhancedechest.storage.sql.AbstractSqlStorage
All Implemented Interfaces:
StorageBackend
Direct Known Subclasses:
MysqlStorage, PostgresStorage, SqliteStorage

public abstract class AbstractSqlStorage extends Object implements StorageBackend
JDBC-backed StorageBackend shared by all three dialects.

Since the in-memory CachedStorage became the authoritative store, this class holds no per-row write DML: its job is schema creation/migration, per-player reads on a cache miss, the batched flush of dirty rows (autosave/quit/shutdown), the handful of whole-database read questions the cache cannot answer alone (expiry candidates, chest count, name resolution), and the verbatim /ee import copy. All SQL below is standard and valid for SQLite, MySQL/MariaDB and PostgreSQL except the flush upserts, whose conflict clause is dialect-specific and selected by the AbstractSqlStorage.UpsertSyntax the subclass passes in (a native upsert is one B-tree mutation per row and one batch execution, versus two of each for the portable delete-then-insert it replaced — the flush runs under the cache's flush lock, so this directly gates quit write-back latency).

  • Field Details

    • dataSource

      protected final com.zaxxer.hikari.HikariDataSource dataSource
    • tablePrefix

      protected final String tablePrefix
      Prepended to every table name (see PluginConfig.getTablePrefix()).
  • Constructor Details

  • Method Details

    • init

      public void init()
      Description copied from interface: StorageBackend
      Creates schema, runs schema migrations, and prepares connections. Called once before anything else.
      Specified by:
      init in interface StorageBackend
    • close

      public void close()
      Description copied from interface: StorageBackend
      Closes all connections. Safe to call even if init() was not completed.
      Specified by:
      close in interface StorageBackend
    • loadAllPlayers

      public List<EnderChestStorage.RawPlayerRow> loadAllPlayers()
      Description copied from interface: StorageBackend
      Reads every players row verbatim. Used once at startup to build the in-memory PlayerNameIndex (uuid → username is tiny even for huge rosters); chest data is never bulk-loaded.
      Specified by:
      loadAllPlayers in interface StorageBackend
    • loadOwner

      public StorageBackend.OwnerRows loadOwner(String playerUuid)
      Description copied from interface: StorageBackend
      Reads one player's enderchests rows and players row verbatim in a single connection acquisition (lazy cache load on first touch — the hottest backend read, so it must not pay for two pool round-trips).
      Specified by:
      loadOwner in interface StorageBackend
    • findExpired

      public List<StorageBackend.ExpiredKey> findExpired(long now)
      Description copied from interface: StorageBackend
      Keys of every row whose expires_at is set and at or before now. Candidates only: the caller re-verifies each hit against the authoritative in-memory row (which may be newer than what was last flushed here).
      Specified by:
      findExpired in interface StorageBackend
    • countChests

      public long countChests()
      Description copied from interface: StorageBackend
      Total number of enderchests rows. The caller flushes first so pending changes count.
      Specified by:
      countChests in interface StorageBackend
    • findUuidByName

      public String findUuidByName(String name)
      Description copied from interface: StorageBackend
      Resolves a stored username to its UUID string, case-insensitively, or null when unknown. The caller checks resident (possibly renamed-but-unflushed) owners first.
      Specified by:
      findUuidByName in interface StorageBackend
    • flushDirty

      public void flushDirty(List<EnderChestStorage.RawChestRow> chestUpserts, List<StorageBackend.ChestKey> chestDeletes, List<EnderChestStorage.RawPlayerRow> playerRows)
      Description copied from interface: StorageBackend
      Writes every dirty row back in one transaction: each chestUpserts / playerRows row replaces whatever the table holds for its key (native dialect upsert), and every chestDeletes key is removed. A single transaction and a single connection acquisition — the flush runs under the cache's flush lock, so its duration directly gates quit write-back latency. A failure rolls the whole flush back and throws, so the caller can re-mark the rows dirty and retry on the next autosave.
      Specified by:
      flushDirty in interface StorageBackend
    • importRows

      public int[] importRows(List<EnderChestStorage.RawPlayerRow> players, List<EnderChestStorage.RawChestRow> chests)
      Description copied from interface: StorageBackend
      Bulk-inserts raw players and enderchests rows verbatim into this (fresh) backend, in a single transaction — the DB→DB conversion primitive behind /ee import. A duplicate primary key (or any other failure) rolls the whole transaction back and throws.
      Specified by:
      importRows in interface StorageBackend
      Returns:
      [playersInserted, chestsInserted]