Earlier I claimed (correctly) that installing the holder mod on a Bukkit-
family server doesn't override the bundled driver under default semantics,
because plugin classloaders delegate parent-first. That's true for
Class.forName / DriverManager paths. What I missed: the holder mods now
ship a small public API (MinecraftSqliteJdbc / MinecraftMysqlJdbc) that
wraps a child-first URLClassLoader pointing at the holder's own jar,
giving consumers a way to access the holder's driver while leaving the
bundled-driver default in place. Tested on paper-1.12.2 — same JVM, same
boot, baseline DriverManager returns engine 3.21.0, holder API returns
engine 3.53.0.
Grim's SqliteBackend has been updated to probe for this API at init and
route through the holder when it's strictly newer than the bundled
engine. So a Paper 1.8 / 1.12 server (bundled SQLite 3.7.2 / 3.21.0,
both pre-3.24, both legacy-dialect-only) plus the holder mod gets the
modern UPSERT path automatically.
The IMPORTANT callout is rewritten to distinguish the two paths:
- Default path uses bundled — works everywhere, recommended
- Workaround path uses the holder API — for newer engine features
Adds a new "Using a newer SQLite engine on a Bukkit-family server"
subsection with the actual log line operators see when the upgrade
kicks in, plus a pointer at the consumer-side API for plugin authors
who want to use the same pattern from their own code.
Database wiki: empirical fix — holder is inert when bundled exists
I claimed the holder mod could 'rescue' an old bundled SQLite engine on
Bukkit 1.8-1.12. Tested it on the live harness (paper-1.12.2 with engine
3.21.0 bundled, paper-1.21.11 with engine 3.49.1.0 in libraries/) with a
probe plugin that logs the resolved org.sqlite.JDBC class jar URL plus
sqlite_version() round-trip. Both servers, with the holder installed and
without: bundled wins every time. Plugin classloaders delegate parent-
first, the parent classloader (or Paper's library URLClassLoader) already
holds org.sqlite.JDBC, the holder's PluginClassLoader is never consulted,
and DriverManager only ever has the bundled driver registered.
Two fixes:
1. Drop the false 'On 1.8–1.12, install holder' guidance. Grim's storage
layer ALREADY supports legacy SQLite engines via the dialect probe
(cff31ed sqlite: legacy-dialect upserters + sqlite_version probe at
init). Modern engines get the ON CONFLICT path, pre-3.24 engines get
the INSERT OR IGNORE + UPDATE path; both write byte-identical rows.
Bundled engine is sufficient on every Bukkit-family MC version, no
holder needed for Grim.
2. Add an IMPORTANT callout documenting the parent-first classloader
rule: holder mod cannot override a bundled driver on Bukkit/Spigot/
Paper. Holder is only useful on Fabric/NeoForge (no bundled driver)
or Bukkit forks that strip the bundled driver.
Engine-version table updated: 'Works with Grim's schema?' becomes
'Grim's SQLite backend' showing dialect picked per engine. Schema-
portability cross-link added pointing at the History page.
The TIP block at the top of the page was claiming you need the holder
on 'older Bukkit'; corrected to just Fabric/NeoForge.
Database wiki: point sqlite link at the maintained Modrinth project
The slug 'sqlite-jdbc' is the dormant kosma-era project. The maintained
fork is at 'minecraft-sqlite-jdbc' (matching this project's GitHub repo
name and the four sibling holder mods). All three SQLite link references
on the page now resolve to the actively-maintained project, which auto-
bumps on Xerial releases via GitHub Actions and tracks the latest engine
version (currently 3.53.0.0).
Replaces the bolded '(coming soon)' placeholders with real Modrinth links.
The four Axionize-published holders are submitted for moderator approval —
links go live once approved (typically a few hours for library mods).
Slugs:
- minecraft-postgresql-jdbc
- minecraft-mysql-jdbc
- minecraft-mongodb-driver
- minecraft-jedis
The two -jdbc slugs are prefixed with 'minecraft-' because the bare
'postgresql-jdbc' and 'mysql-jdbc' Modrinth slugs are squatted by
unrelated third-party projects.
- Database page: split the 'Planned' section into two distinct items —
boot-time backend chains (operator-configurable ordered fallback list
per category) and per-category isolation (separate chains per category).
Adds a NOTE callout that both are boot-time-resolution only; mid-session
hot-failover is explicitly out of scope because of the divergence
problem on primary recovery.
- History page: adds a 'SQLite file portability across server versions'
subsection explaining that the schema is identical regardless of MC
version. Modern (≥3.24, ON CONFLICT) and legacy (<3.24, INSERT OR
IGNORE + UPDATE) writer dialects produce byte-equivalent rows, and a
data.db file from a 1.8 server can be moved to a 1.21+ server (or vice
versa) with no migration step. The dialect picks itself at init from
sqlite_version().
Database wiki section: overview + History subsystem
Adds two operator-facing pages plus sidebar entries:
- Database.md: backend matrix (SQLite/MySQL/Postgres/Mongo/Redis), which
drivers ship bundled with which server flavour vs need a holder mod,
per-platform install instructions, the SQLite engine version floor
(3.24.0, met by CraftBukkit 1.13+), backend-by-backend database.yml
config snippets, JDBC-URL gotchas (useSSL, allowPublicKeyRetrieval,
reWriteBatchedInserts), startup verification, and a roadmap note on
per-category failure isolation.
- Database-History.md: the /grim history command tree (list, page,
session detail with --detailed/--verbose flags, latest alias),
what's stored per session/violation, retention windows, performance
notes per backend, customisation via messages.yml grim-history-* keys.
The Database entry sits between Configuration and Discord-webhooks in
the sidebar, with History indented as a subpage. Settings is reserved
as a future sibling once that subsystem ships.