diff --git a/common/src/main/java/dev/xhyrom/lighteco/common/config/storage/StorageConfig.java b/common/src/main/java/dev/xhyrom/lighteco/common/config/storage/StorageConfig.java index 5eb099f..12897ce 100644 --- a/common/src/main/java/dev/xhyrom/lighteco/common/config/storage/StorageConfig.java +++ b/common/src/main/java/dev/xhyrom/lighteco/common/config/storage/StorageConfig.java @@ -6,7 +6,7 @@ import eu.okaeri.configs.annotation.Comment; public class StorageConfig extends OkaeriConfig { @Comment("Storage provider.") - @Comment("Available providers: h2, sqlite, mysql, mariadb") + @Comment("Available providers: h2, sqlite, mysql, mariadb, postgresql") public StorageType provider = StorageType.H2; @Comment("Data storage settings.") @@ -14,5 +14,5 @@ public class StorageConfig extends OkaeriConfig { public StorageDataConfig data = new StorageDataConfig(); @Comment("Table prefix.") - public String tablePrefix = "lighteco_"; + public String tablePrefix = "lighteco"; } diff --git a/common/src/main/java/dev/xhyrom/lighteco/common/storage/StorageFactory.java b/common/src/main/java/dev/xhyrom/lighteco/common/storage/StorageFactory.java index d29726e..fce72c5 100644 --- a/common/src/main/java/dev/xhyrom/lighteco/common/storage/StorageFactory.java +++ b/common/src/main/java/dev/xhyrom/lighteco/common/storage/StorageFactory.java @@ -9,6 +9,7 @@ import dev.xhyrom.lighteco.common.storage.provider.sql.connection.file.H2Connect import dev.xhyrom.lighteco.common.storage.provider.sql.connection.file.SqliteConnectionFactory; import dev.xhyrom.lighteco.common.storage.provider.sql.connection.hikari.MariaDBConnectionFactory; import dev.xhyrom.lighteco.common.storage.provider.sql.connection.hikari.MySQLConnectionFactory; +import dev.xhyrom.lighteco.common.storage.provider.sql.connection.hikari.PostgreSQLConnectionFactory; import java.util.Set; @@ -51,6 +52,10 @@ public class StorageFactory { this.plugin, new MariaDBConnectionFactory(this.plugin.getConfig().storage.data) ); + case POSTGRESQL -> new SqlStorageProvider( + this.plugin, + new PostgreSQLConnectionFactory(this.plugin.getConfig().storage.data) + ); default -> throw new IllegalArgumentException("Unknown storage provider: " + type.name()); }; } diff --git a/common/src/main/java/dev/xhyrom/lighteco/common/storage/provider/sql/SqlStatements.java b/common/src/main/java/dev/xhyrom/lighteco/common/storage/provider/sql/SqlStatements.java index e475d1b..00ac722 100644 --- a/common/src/main/java/dev/xhyrom/lighteco/common/storage/provider/sql/SqlStatements.java +++ b/common/src/main/java/dev/xhyrom/lighteco/common/storage/provider/sql/SqlStatements.java @@ -6,27 +6,32 @@ public enum SqlStatements { SAVE_USER_LOCAL_CURRENCY( "INSERT INTO {prefix}_{context}_users (uuid, currency_identifier, balance) VALUES (?1, ?2, ?3) ON CONFLICT (uuid, currency_identifier) DO UPDATE SET balance=?3;", "INSERT INTO {prefix}_{context}_users (uuid, currency_identifier, balance) VALUES (?1, ?2, ?3) ON DUPLICATE KEY UPDATE balance=?3;", - "INSERT INTO {prefix}_{context}_users (uuid, currency_identifier, balance) VALUES (?, ?, ?) ON DUPLICATE KEY UPDATE balance=?;" + "INSERT INTO {prefix}_{context}_users (uuid, currency_identifier, balance) VALUES (?, ?, ?) ON DUPLICATE KEY UPDATE balance=?;", + "INSERT INTO {prefix}_{context}_users (uuid, currency_identifier, balance) VALUES (?, ?, ?) ON CONFLICT (uuid, currency_identifier) DO UPDATE SET balance=?;" ), SAVE_USER_GLOBAL_CURRENCY( "INSERT INTO {prefix}_users (uuid, currency_identifier, balance) VALUES (?1, ?2, ?3) ON CONFLICT (uuid, currency_identifier) DO UPDATE SET balance=?3;", "INSERT INTO {prefix}_users (uuid, currency_identifier, balance) VALUES (?1, ?2, ?3) ON DUPLICATE KEY UPDATE balance=?3;", - "INSERT INTO {prefix}_users (uuid, currency_identifier, balance) VALUES (?, ?, ?) ON DUPLICATE KEY UPDATE balance=?;" + "INSERT INTO {prefix}_users (uuid, currency_identifier, balance) VALUES (?, ?, ?) ON DUPLICATE KEY UPDATE balance=?;", + "INSERT INTO {prefix}_users (uuid, currency_identifier, balance) VALUES (?, ?, ?) ON CONFLICT (uuid, currency_identifier) DO UPDATE SET balance=?;" ), LOAD_WHOLE_USER( "SELECT currency_identifier, balance FROM ( SELECT currency_identifier, balance FROM '{prefix}_users' WHERE uuid = ?1 UNION ALL SELECT currency_identifier, balance FROM '{prefix}_{context}_users' WHERE uuid = ?1 ) AS combined_currencies;", "SELECT currency_identifier, balance FROM ( SELECT currency_identifier, balance FROM '{prefix}_users' WHERE uuid = ?1 UNION ALL SELECT currency_identifier, balance FROM '{prefix}_{context}_users' WHERE uuid = ?1 ) AS combined_currencies;", - "SELECT currency_identifier, balance FROM ( SELECT currency_identifier, balance FROM '{prefix}_users' WHERE uuid = ? UNION ALL SELECT currency_identifier, balance FROM '{prefix}_{context}_users' WHERE uuid = ? ) AS combined_currencies;" + "SELECT currency_identifier, balance FROM ( SELECT currency_identifier, balance FROM '{prefix}_users' WHERE uuid = ? UNION ALL SELECT currency_identifier, balance FROM '{prefix}_{context}_users' WHERE uuid = ? ) AS combined_currencies;", + null ); public final String sqlite; public final String mysql; public final String mariadb; + public final String postgresql; - SqlStatements(String sqlite, String mysql, String mariadb) { + SqlStatements(String sqlite, String mysql, String mariadb, String postgresql) { this.sqlite = sqlite; this.mysql = mysql; this.mariadb = mariadb; + this.postgresql = postgresql != null ? postgresql : mariadb; } public String get(StorageType implementationName) { @@ -40,8 +45,15 @@ public enum SqlStatements { case MARIADB -> { return this.mariadb; } + case POSTGRESQL -> { + return this.postgresql; + } } throw new IllegalArgumentException("Unknown implementation: " + implementationName); } + + public static boolean mustDuplicateParameters(StorageType implementationName) { + return implementationName == StorageType.MARIADB || implementationName == StorageType.POSTGRESQL; + } } diff --git a/common/src/main/java/dev/xhyrom/lighteco/common/storage/provider/sql/SqlStorageProvider.java b/common/src/main/java/dev/xhyrom/lighteco/common/storage/provider/sql/SqlStorageProvider.java index c30b0d3..2f59c45 100644 --- a/common/src/main/java/dev/xhyrom/lighteco/common/storage/provider/sql/SqlStorageProvider.java +++ b/common/src/main/java/dev/xhyrom/lighteco/common/storage/provider/sql/SqlStorageProvider.java @@ -83,7 +83,7 @@ public class SqlStorageProvider implements StorageProvider { try (Connection c = this.connectionFactory.getConnection()) { try (PreparedStatement ps = c.prepareStatement(this.statementProcessor.apply(LOAD_WHOLE_USER))) { ps.setString(1, uniqueIdString); - if (this.connectionFactory.getImplementationName() == StorageType.MARIADB) + if (SqlStatements.mustDuplicateParameters(this.connectionFactory.getImplementationName())) ps.setString(2, uniqueIdString); ResultSet rs = ps.executeQuery(); @@ -120,7 +120,7 @@ public class SqlStorageProvider implements StorageProvider { psGlobal.setString(1, uniqueIdString); psGlobal.setString(2, currency.getIdentifier()); psGlobal.setBigDecimal(3, balance); - if (this.connectionFactory.getImplementationName() == StorageType.MARIADB) + if (SqlStatements.mustDuplicateParameters(this.connectionFactory.getImplementationName())) psGlobal.setBigDecimal(4, balance); psGlobal.addBatch(); @@ -129,7 +129,7 @@ public class SqlStorageProvider implements StorageProvider { psLocal.setString(1, uniqueIdString); psLocal.setString(2, currency.getIdentifier()); psLocal.setBigDecimal(3, balance); - if (this.connectionFactory.getImplementationName() == StorageType.MARIADB) + if (SqlStatements.mustDuplicateParameters(this.connectionFactory.getImplementationName())) psLocal.setBigDecimal(4, balance); psLocal.addBatch(); diff --git a/common/src/main/java/dev/xhyrom/lighteco/common/storage/provider/sql/connection/hikari/PostgreSQLConnectionFactory.java b/common/src/main/java/dev/xhyrom/lighteco/common/storage/provider/sql/connection/hikari/PostgreSQLConnectionFactory.java new file mode 100644 index 0000000..4d344fb --- /dev/null +++ b/common/src/main/java/dev/xhyrom/lighteco/common/storage/provider/sql/connection/hikari/PostgreSQLConnectionFactory.java @@ -0,0 +1,47 @@ +package dev.xhyrom.lighteco.common.storage.provider.sql.connection.hikari; + +import dev.xhyrom.lighteco.common.config.storage.StorageDataConfig; +import dev.xhyrom.lighteco.common.storage.StorageType; + +import java.util.Map; +import java.util.function.Function; + +public class PostgreSQLConnectionFactory extends DriverBasedHikariConnectionFactory { + public PostgreSQLConnectionFactory(StorageDataConfig configuration) { + super(configuration); + } + + @Override + public StorageType getImplementationName() { + return StorageType.POSTGRESQL; + } + + @Override + protected String defaultPort() { + return "5432"; + } + + @Override + protected String driverClassName() { + return "org.postgresql.Driver"; + } + + @Override + protected String driverJdbcIdentifier() { + return "postgresql"; + } + + @Override + protected void overrideProperties(Map properties) { + super.overrideProperties(properties); + + // Doesn't work with PostgreSQL + properties.remove("useUnicode"); + properties.remove("characterEncoding"); + } + + @Override + public Function getStatementProcessor() { + return s -> s.replace("\'", "\""); + } +} diff --git a/common/src/main/resources/schema/postgresql.sql b/common/src/main/resources/schema/postgresql.sql new file mode 100644 index 0000000..1af0acf --- /dev/null +++ b/common/src/main/resources/schema/postgresql.sql @@ -0,0 +1,13 @@ +CREATE TABLE IF NOT EXISTS "{prefix}_users" ( + "uuid" VARCHAR(36) NOT NULL, + "currency_identifier" VARCHAR(255) NOT NULL, + "balance" DECIMAL(10, 2) NOT NULL, + PRIMARY KEY ("uuid", "currency_identifier") +); + +CREATE TABLE IF NOT EXISTS "{prefix}_{context}_users" ( + "uuid" VARCHAR(36) NOT NULL, + "currency_identifier" VARCHAR(255) NOT NULL, + "balance" DECIMAL(10, 2) NOT NULL, + PRIMARY KEY ("uuid", "currency_identifier") +); \ No newline at end of file