Added builder, DataTracker and KeyValue #16
@ -25,16 +25,18 @@ public abstract class AbstractSqlConnection implements SqlConnection {
|
|||||||
return connection;
|
return connection;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public void closeConnection() {
|
public void closeConnection() {
|
||||||
try {
|
try {
|
||||||
|
close();
|
||||||
|
} catch (Exception ignored) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void close() throws Exception {
|
||||||
if(!connection.isClosed()) {
|
if(!connection.isClosed()) {
|
||||||
connection.close();
|
connection.close();
|
||||||
connection = null;
|
connection = null;
|
||||||
}
|
}
|
||||||
} catch(SQLException ignored) {
|
|
||||||
// no op
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
@ -5,7 +5,7 @@ import java.sql.SQLException;
|
|||||||
|
|
||||||
public class PostgresConnection extends AbstractSqlConnection {
|
public class PostgresConnection extends AbstractSqlConnection {
|
||||||
|
|
||||||
PostgresConnection(ConnectionConfig config) throws SQLException {
|
public PostgresConnection(ConnectionConfig config) throws SQLException {
|
||||||
super(config);
|
super(config);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3,14 +3,30 @@ package fr.altarik.toolbox.database;
|
|||||||
import java.sql.Connection;
|
import java.sql.Connection;
|
||||||
import java.sql.SQLException;
|
import java.sql.SQLException;
|
||||||
|
|
||||||
public interface SqlConnection {
|
public interface SqlConnection extends AutoCloseable {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Start the connection to sql database
|
||||||
|
* @throws SQLException if unable to connect to database
|
||||||
|
*/
|
||||||
void connect() throws SQLException;
|
void connect() throws SQLException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the sql connection
|
||||||
|
* @return the connection session
|
||||||
|
*/
|
||||||
Connection getConnection();
|
Connection getConnection();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reconnect you to database if it has closed or lost.
|
||||||
|
* @throws SQLException if unable to reconnect you
|
||||||
|
*/
|
||||||
void checkConnection() throws SQLException;
|
void checkConnection() throws SQLException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @deprecated replaced with {@link AutoCloseable#close()}
|
||||||
|
*/
|
||||||
|
@Deprecated(forRemoval = true)
|
||||||
void closeConnection();
|
void closeConnection();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,59 @@
|
|||||||
|
package fr.altarik.toolbox.database.keyvalue;
|
||||||
|
|
||||||
|
import fr.altarik.toolbox.database.SqlConnection;
|
||||||
|
import net.minecraft.util.Pair;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
import java.sql.JDBCType;
|
||||||
|
import java.sql.SQLException;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
|
public class KeyValueBuilder {
|
||||||
|
|
||||||
|
private final String tableName;
|
||||||
|
private final List<AdditionalColumn> additionalColumns;
|
||||||
|
private final SqlConnection connection;
|
||||||
|
|
||||||
|
private KeyValueBuilder(SqlConnection connection, String tableName) {
|
||||||
|
this.connection = connection;
|
||||||
|
this.tableName = tableName;
|
||||||
|
this.additionalColumns = new ArrayList<>();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static KeyValueBuilder builder(@NotNull SqlConnection connection, @NotNull String tableName) {
|
||||||
|
return new KeyValueBuilder(connection, tableName);
|
||||||
|
}
|
||||||
|
|
||||||
|
public KeyValueBuilder addColumn(AdditionalColumn additionalColumn) {
|
||||||
|
this.additionalColumns.add(additionalColumn);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public KeyValueConnection build() throws SQLException {
|
||||||
|
return new KeyValueConnection(connection, tableName, additionalColumns);
|
||||||
|
}
|
||||||
|
|
||||||
|
public record AdditionalColumn(@NotNull String columnName, @NotNull JDBCType type, boolean notNull, @Nullable AdditionalColumnReference reference) {
|
||||||
|
public AdditionalColumn {
|
||||||
|
Objects.requireNonNull(columnName);
|
||||||
|
Objects.requireNonNull(type);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Pair<AdditionalColumn, Object> toPair(Object value) {
|
||||||
|
return new Pair<>(this, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public record AdditionalColumnReference(@NotNull String referenceTable, @NotNull String... referenceColumns) {
|
||||||
|
public AdditionalColumnReference {
|
||||||
|
Objects.requireNonNull(referenceTable);
|
||||||
|
if(Objects.requireNonNull(referenceColumns).length == 0)
|
||||||
|
throw new IllegalArgumentException("Reference Columns should not be empty");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,146 @@
|
|||||||
|
package fr.altarik.toolbox.database.keyvalue;
|
||||||
|
|
||||||
|
import fr.altarik.toolbox.database.SqlConnection;
|
||||||
|
import net.minecraft.util.Pair;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
import java.sql.PreparedStatement;
|
||||||
|
import java.sql.ResultSet;
|
||||||
|
import java.sql.SQLException;
|
||||||
|
import java.sql.Statement;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class KeyValueConnection {
|
||||||
|
|
||||||
|
private final SqlConnection connection;
|
||||||
|
private final String tableName;
|
||||||
|
private final List<KeyValueBuilder.AdditionalColumn> additionColumns;
|
||||||
|
|
||||||
|
public KeyValueConnection(SqlConnection connection, String tableName, List<KeyValueBuilder.AdditionalColumn> additionalColumns) throws SQLException {
|
||||||
|
this.connection = connection;
|
||||||
|
this.tableName = tableName;
|
||||||
|
this.additionColumns = additionalColumns;
|
||||||
|
|
||||||
|
try(Statement statement = connection.getConnection().createStatement()) {
|
||||||
|
StringBuilder sql = new StringBuilder("CREATE TABLE IF NOT EXISTS ").append(tableName).append("(id SERIAL,");
|
||||||
|
for(KeyValueBuilder.AdditionalColumn additionalColumn : additionalColumns) {
|
||||||
|
sql.append(additionalColumn.columnName()).append(" ").append(additionalColumn.type().getName());
|
||||||
|
if(additionalColumn.notNull()) {
|
||||||
|
sql.append(" NOT NULL ");
|
||||||
|
}
|
||||||
|
if(additionalColumn.reference() != null) {
|
||||||
|
sql.append("REFERENCES ").append(additionalColumn.reference().referenceTable()).append("(");
|
||||||
|
for(int i = 0; i < additionalColumn.reference().referenceColumns().length; ++i) {
|
||||||
|
sql.append(additionalColumn.reference().referenceColumns()[i]);
|
||||||
|
if(i != additionalColumn.reference().referenceColumns().length - 1) {
|
||||||
|
sql.append(", ");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
sql.append(")");
|
||||||
|
}
|
||||||
|
sql.append(",");
|
||||||
|
sql.append("key VARCHAR(50) NOT NULL,").append("value TEXT NOT NULL,").append("PRIMARY KEY(id)");
|
||||||
|
}
|
||||||
|
statement.executeUpdate(sql.toString());
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public @Nullable String getValueById(int id) throws SQLException {
|
||||||
|
try(PreparedStatement preparedStatement = connection.getConnection().prepareStatement("SELECT value FROM " + tableName + " WHERE id=?")) {
|
||||||
|
preparedStatement.setInt(1, id);
|
||||||
|
ResultSet resultSet = preparedStatement.executeQuery();
|
||||||
|
if(resultSet.next()) {
|
||||||
|
return resultSet.getString(1);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public @Nullable String getValueByAdditionalColumnAndKey(String key, List<Pair<KeyValueBuilder.AdditionalColumn, Object>> additionalColumns) throws SQLException {
|
||||||
|
StringBuilder sql = new StringBuilder("SELECT value FROM ").append(tableName).append(" WHERE key=? AND ");
|
||||||
|
for(int i = 0; i < additionalColumns.size(); ++i) {
|
||||||
|
sql.append(additionalColumns.get(i).getLeft().columnName()).append("=?");
|
||||||
|
if(i != additionalColumns.size() - 1) {
|
||||||
|
sql.append(" AND ");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
sql.append(";");
|
||||||
|
try(PreparedStatement preparedStatement = connection.getConnection().prepareStatement(sql.toString())) {
|
||||||
|
preparedStatement.setString(1, key);
|
||||||
|
for(int i = 0; i < additionalColumns.size(); ++i) {
|
||||||
|
preparedStatement.setObject(i + 1, additionalColumns.get(i).getRight());
|
||||||
|
}
|
||||||
|
ResultSet resultSet = preparedStatement.executeQuery();
|
||||||
|
if(resultSet.next())
|
||||||
|
return resultSet.getString(1);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public long insertValue(String key, String value, List<Pair<KeyValueBuilder.AdditionalColumn, Object>> additionalColumns) throws SQLException {
|
||||||
|
StringBuilder sql = new StringBuilder("INSERT INTO " + tableName + "(key, value");
|
||||||
|
for(int i = 0; i < additionalColumns.size(); ++i) {
|
||||||
|
if(i != additionalColumns.size() - 1) {
|
||||||
|
sql.append(", ");
|
||||||
|
}
|
||||||
|
sql.append(additionalColumns.get(i).getLeft().columnName());
|
||||||
|
|
||||||
|
}
|
||||||
|
sql.append(") VALUES (?, ?");
|
||||||
|
for(int i = 0; i < additionalColumns.size(); ++i) {
|
||||||
|
if(i != additionalColumns.size() - 1) {
|
||||||
|
sql.append(", ");
|
||||||
|
}
|
||||||
|
sql.append("?");
|
||||||
|
}
|
||||||
|
sql.append(");");
|
||||||
|
try(PreparedStatement preparedStatement = connection.getConnection().prepareStatement(sql.toString(), Statement.RETURN_GENERATED_KEYS)){
|
||||||
|
preparedStatement.setString(1, key);
|
||||||
|
preparedStatement.setString(2, value);
|
||||||
|
for(int i = 0; i < additionalColumns.size(); ++i) {
|
||||||
|
preparedStatement.setObject(i + 3, additionalColumns.get(i).getRight());
|
||||||
|
}
|
||||||
|
preparedStatement.executeUpdate();
|
||||||
|
try(ResultSet resultSet = preparedStatement.getGeneratedKeys()) {
|
||||||
|
if(resultSet.next()) {
|
||||||
|
return resultSet.getLong(1);
|
||||||
|
}
|
||||||
|
return -1L;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void updateValueById(String key, String value) throws SQLException {
|
||||||
|
try(PreparedStatement preparedStatement = connection.getConnection().prepareStatement("UPDATE " + tableName + " SET value=? WHERE key=?")) {
|
||||||
|
preparedStatement.setString(1, value);
|
||||||
|
preparedStatement.setString(2, key);
|
||||||
|
preparedStatement.executeUpdate();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public void updateValue(String key, String value, List<Pair<KeyValueBuilder.AdditionalColumn, Object>> additionalColumns) throws SQLException {
|
||||||
|
StringBuilder sql = new StringBuilder("UPDATE " + tableName + " SET value=? WHERE key=?");
|
||||||
|
for(int i = 0; i < additionalColumns.size(); ++i) {
|
||||||
|
if(i != additionalColumns.size() - 1) {
|
||||||
|
sql.append(" AND ");
|
||||||
|
}
|
||||||
|
sql.append(additionalColumns.get(i).getLeft().columnName()).append("=?");
|
||||||
|
}
|
||||||
|
sql.append(";");
|
||||||
|
try(PreparedStatement preparedStatement = connection.getConnection().prepareStatement(sql.toString())) {
|
||||||
|
preparedStatement.setString(1, value);
|
||||||
|
preparedStatement.setString(2, key);
|
||||||
|
for(int i = 0; i < additionalColumns.size(); ++i) {
|
||||||
|
preparedStatement.setObject(3 + i, additionalColumns.get(i).getRight());
|
||||||
|
}
|
||||||
|
preparedStatement.executeUpdate();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<KeyValueBuilder.AdditionalColumn> getAdditionColumns() {
|
||||||
|
return additionColumns;
|
||||||
|
}
|
||||||
|
}
|
@ -1,5 +1,5 @@
|
|||||||
plugins {
|
plugins {
|
||||||
id 'fabric-loom' version '1.1-SNAPSHOT' apply false
|
id 'fabric-loom' version '1.2-SNAPSHOT' apply false
|
||||||
}
|
}
|
||||||
|
|
||||||
allprojects {
|
allprojects {
|
||||||
|
2
gradle/wrapper/gradle-wrapper.properties
vendored
2
gradle/wrapper/gradle-wrapper.properties
vendored
@ -1,5 +1,5 @@
|
|||||||
distributionBase=GRADLE_USER_HOME
|
distributionBase=GRADLE_USER_HOME
|
||||||
distributionPath=wrapper/dists
|
distributionPath=wrapper/dists
|
||||||
distributionUrl=https\://services.gradle.org/distributions/gradle-7.6-bin.zip
|
distributionUrl=https\://services.gradle.org/distributions/gradle-8.1-bin.zip
|
||||||
zipStoreBase=GRADLE_USER_HOME
|
zipStoreBase=GRADLE_USER_HOME
|
||||||
zipStorePath=wrapper/dists
|
zipStorePath=wrapper/dists
|
||||||
|
Loading…
Reference in New Issue
Block a user