Add mariadb support

This commit is contained in:
NotAlexNoyle committed 2026-06-18 14:48:28 -04:00
1 parent b7ffb5d4e7
commit bd111ac271
8 files changed
+80 -26

No files matched your search

+1
View File
@@ -36,6 +36,7 @@ dependencies {
implementation(libs.bstats.bukkit)
implementation(libs.commons.dbcp)
implementation(libs.commons.pool)
implementation(libs.mysql.connector)
compileOnlyApi(libs.purpur.api)
compileOnlyApi(libs.battlearena)
+2
View File
@@ -4,6 +4,7 @@ purpur-api = "1.19.4-R0.1-SNAPSHOT"
commons = "2.12.0"
battlearena = "4.0.0-SNAPSHOT"
placeholderapi = "2.11.6"
mysql-connector = "9.6.0"
[libraries]
battlearena = { group = "org.battleplugins", name = "arena", version.ref = "battlearena" }
@@ -11,4 +12,5 @@ bstats-bukkit = { group = "org.bstats", name = "bstats-bukkit", version.ref = "b
purpur-api = { group = "org.purpurmc.purpur", name = "purpur-api", version.ref = "purpur-api" }
commons-dbcp = { group = "org.apache.commons", name = "commons-dbcp2", version.ref = "commons" }
commons-pool = { group = "org.apache.commons", name = "commons-pool2", version.ref = "commons" }
mysql-connector = { group = "com.mysql", name = "mysql-connector-j", version.ref = "mysql-connector" }
placeholderapi = { group = "me.clip", name = "placeholderapi", version.ref = "placeholderapi" }
@@ -59,7 +59,14 @@ public class BattleTrackerConfig {
) {
public static DatabaseOptions load(ConfigurationSection section) {
SqlSerializer.SqlType type = SqlSerializer.SqlType.valueOf(section.getString("type").toUpperCase(Locale.ROOT));
String typeName = section.getString("type", "sqlite").trim().toUpperCase(Locale.ROOT);
SqlSerializer.SqlType type;
try {
type = SqlSerializer.SqlType.valueOf(typeName);
} catch (IllegalArgumentException e) {
throw new IllegalArgumentException("Unknown database type '" + section.getString("type") + "'. Supported types: sqlite, mysql, mariadb.", e);
}
String prefix = section.getString("prefix");
String db = section.getString("db");
String url = section.getString("url");
@@ -2,10 +2,12 @@ package org.battleplugins.tracker.feature.placeholderapi;
import me.clip.placeholderapi.expansion.PlaceholderExpansion;
import org.battleplugins.tracker.BattleTracker;
import org.battleplugins.tracker.SqlTracker;
import org.battleplugins.tracker.Tracker;
import org.battleplugins.tracker.stat.Record;
import org.battleplugins.tracker.stat.StatType;
import org.battleplugins.tracker.util.Util;
import org.bukkit.OfflinePlayer;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -37,6 +39,10 @@ class BattleTrackerExpansion extends PlaceholderExpansion {
@Override
public @Nullable String onPlaceholderRequest(Player player, @NotNull String params) {
String[] split = params.split("_");
if (split.length < 2) {
return null;
}
String trackerName = split[0];
// The tracker is not tracked or does not exist
@@ -94,11 +100,30 @@ class BattleTrackerExpansion extends PlaceholderExpansion {
type = StatType.get(split[1] + "_" + split[2]);
}
Record record = tracker.getRecord(player);
Record record = this.getRecord(tracker, player);
if (record == null) {
return "";
}
if (type != null) {
return Util.STAT_FORMAT.format(record.getStat(type));
}
return null;
}
private Record getRecord(Tracker tracker, Player player) {
if (tracker instanceof SqlTracker sqlTracker) {
Record record = sqlTracker.getRecords().getCached(player.getUniqueId());
if (record != null) {
return record;
}
// PlaceholderAPI resolves synchronously, but SQL records load asynchronously on join.
tracker.getRecord((OfflinePlayer) player);
return null;
}
return tracker.getRecord(player);
}
}
@@ -93,11 +93,17 @@ public final class SqlInstance {
private void initDataSource() {
Connection connection = null;
// See if the driver exists
try {
Class.forName(this.type.getDriver());
} catch (ClassNotFoundException e) {
throw new IllegalStateException("Could not find SQL driver " + this.type.getDriver());
boolean driverLoaded = false;
for (String driver : this.type.getDrivers()) {
try {
Class.forName(driver);
driverLoaded = true;
break;
} catch (ClassNotFoundException ignored) {
}
}
if (!driverLoaded) {
throw new IllegalStateException("Could not find SQL driver for " + this.type.getName() + ": " + this.type.getDrivers());
}
String connectionString;
@@ -110,12 +116,12 @@ public final class SqlInstance {
maxActive = 2;
minIdle = 1;
break;
case MYSQL:
case MYSQL, MARIADB:
default:
minIdle = 10;
maxActive = 20;
datasourceString = "jdbc:mysql://" + this.url + ":" + this.port + "/" + this.db + "?autoReconnect=true";
connectionString = "jdbc:mysql://" + this.url + ":" + this.port + "?autoReconnect=true";
datasourceString = this.type.getJdbcProtocol() + "://" + this.url + ":" + this.port + "/" + this.db + "?autoReconnect=true";
connectionString = this.type.getJdbcProtocol() + "://" + this.url + ":" + this.port + "?autoReconnect=true";
break;
}
@@ -126,7 +132,7 @@ public final class SqlInstance {
throw new IllegalStateException("Could not create data source for SQL connection", e);
}
if (this.type == SqlSerializer.SqlType.MYSQL) {
if (this.type.isMysqlLike()) {
String statement = String.format(CREATE_DATABASE, this.db);
try {
connection = DriverManager.getConnection(connectionString, this.username, this.password);
@@ -20,23 +20,36 @@ public abstract class SqlSerializer {
protected static final int TIMEOUT = 5;
public enum SqlType {
MYSQL("MySQL", "com.mysql.jdbc.Driver"),
SQLITE("SQLite", "org.sqlite.JDBC");
MYSQL("MySQL", "jdbc:mysql", true, "com.mysql.cj.jdbc.Driver", "com.mysql.jdbc.Driver"),
MARIADB("MariaDB", "jdbc:mysql", true, "com.mysql.cj.jdbc.Driver", "com.mysql.jdbc.Driver"),
SQLITE("SQLite", "jdbc:sqlite", false, "org.sqlite.JDBC");
private final String name;
private final String driver;
private final String jdbcProtocol;
private final boolean mysqlLike;
private final List<String> drivers;
SqlType(String name, String driver) {
SqlType(String name, String jdbcProtocol, boolean mysqlLike, String... drivers) {
this.name = name;
this.driver = driver;
this.jdbcProtocol = jdbcProtocol;
this.mysqlLike = mysqlLike;
this.drivers = List.of(drivers);
}
public String getName() {
return this.name;
}
public String getDriver() {
return this.driver;
public String getJdbcProtocol() {
return this.jdbcProtocol;
}
public boolean isMysqlLike() {
return this.mysqlLike;
}
public List<String> getDrivers() {
return this.drivers;
}
}
@@ -159,7 +172,7 @@ public abstract class SqlSerializer {
Boolean columnExists;
SqlType type = SqlInstance.getInstance().getType();
switch (type) {
case MYSQL:
case MYSQL, MARIADB:
statement = "SELECT COUNT(*) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = ? " +
"AND TABLE_NAME = ? AND COLUMN_NAME = ?";
columnExists = this.getBoolean(true, 2, statement, SqlInstance.getInstance().getDatabase(), table, column);
@@ -330,7 +330,7 @@ public class TrackerSqlSerializer extends SqlSerializer {
private String constructInsertOverallStatement() {
StringBuilder builder = new StringBuilder();
switch (this.getType()) {
case MYSQL:
case MYSQL, MARIADB:
String insertOverall = "INSERT INTO " + this.overallTable + " VALUES (?, ?, ";
builder.append(insertOverall);
for (int i = 0; i < this.overallColumns.size(); i++) {
@@ -374,7 +374,7 @@ public class TrackerSqlSerializer extends SqlSerializer {
private String constructInsertVersusStatement() {
StringBuilder builder = new StringBuilder();
switch (this.getType()) {
case MYSQL:
case MYSQL, MARIADB:
String insertOverall = "INSERT INTO " + this.versusTable + " VALUES (?, ?, ";
builder.append(insertOverall);
for (int i = 0; i < this.versusColumns.size(); i++) {
@@ -416,7 +416,7 @@ public class TrackerSqlSerializer extends SqlSerializer {
private String constructInsertTallyStatement() {
return switch (this.getType()) {
case MYSQL -> "INSERT IGNORE INTO " + this.tallyTable + " VALUES (?, ?, ?, ?)";
case MYSQL, MARIADB -> "INSERT IGNORE INTO " + this.tallyTable + " VALUES (?, ?, ?, ?)";
case SQLITE -> "INSERT OR REPLACE INTO " + this.tallyTable + " VALUES (?, ?, ?, ?)";
};
}
@@ -472,7 +472,7 @@ public class TrackerSqlSerializer extends SqlSerializer {
"timestamp TIMESTAMP NOT NULL, " +
"PRIMARY KEY (id1, id2, timestamp)";
if (this.getType() == SqlType.MYSQL) {
if (this.getType().isMysqlLike()) {
createTally += ", INDEX (id1), INDEX (id2))";
} else {
createTally += ")";
+3 -3
View File
@@ -16,11 +16,11 @@ rating:
# Database options
database:
type: sqlite # sqlite or mysql
type: sqlite # sqlite, mysql, or mariadb
prefix: bt_
db: battletracker # Database name
url : localhost # Ignored if not mysql
port : "3306" # Ignored if not mysql
url : localhost # Ignored if sqlite
port : "3306" # Ignored if sqlite
username: "^{MARIADB_USER}"
password: "^{MARIADB_PASSWORD}"