diff --git a/.gitignore b/.gitignore index d037336..a4bcb99 100644 --- a/.gitignore +++ b/.gitignore @@ -4,8 +4,9 @@ build/ !**/src/main/**/build/ !**/src/test/**/build/ -*/run -*/logs +run/* +**/run +**/logs ### IntelliJ IDEA ### .idea diff --git a/Database/build.gradle b/Database/build.gradle index 9aa1fc3..52c3f78 100644 --- a/Database/build.gradle +++ b/Database/build.gradle @@ -1,9 +1,9 @@ dependencies { - implementation 'org.postgresql:postgresql:42.5.0' + implementation 'org.postgresql:postgresql:42.6.0' testImplementation 'com.google.code.gson:gson:2.10' implementation project(':Core') } test { - exclude 'fr/altarik/toolbox/database/**' + exclude 'fr/altarik/toolbox/database/**' // exclude for runner } \ No newline at end of file diff --git a/Database/src/main/java/fr/altarik/toolbox/database/Connections.java b/Database/src/main/java/fr/altarik/toolbox/database/Connections.java index 7d8f5a7..4f30e9b 100644 --- a/Database/src/main/java/fr/altarik/toolbox/database/Connections.java +++ b/Database/src/main/java/fr/altarik/toolbox/database/Connections.java @@ -1,14 +1,28 @@ package fr.altarik.toolbox.database; +import fr.altarik.toolbox.database.keyValue.KeyValueBuilder; +import fr.altarik.toolbox.database.keyValue.KeyValueTable; + import java.sql.SQLException; public class Connections { /** * Create a new Connection object for a postgresql database server - * @return + * @return postgresql connection */ public static SqlConnection newPostgresConnection(ConnectionConfig config) throws SQLException { return new PostgresConnection(config); } + + /** + * Create a new (key, value) table if not exist and use it through {@link KeyValueTable} interface + * @param connection Postgresql connection + * @param tableName name of the table to use + * @return interface to control the table + * @throws SQLException if connection is lost + */ + public static KeyValueTable newKeyValueTable(SqlConnection connection, String tableName) throws SQLException { + return KeyValueBuilder.builder().setConnection(connection).setTableName(tableName).build(); + } } diff --git a/Database/src/main/java/fr/altarik/toolbox/database/keyValue/KeyValueBuilder.java b/Database/src/main/java/fr/altarik/toolbox/database/keyValue/KeyValueBuilder.java index d086a91..b393cbb 100644 --- a/Database/src/main/java/fr/altarik/toolbox/database/keyValue/KeyValueBuilder.java +++ b/Database/src/main/java/fr/altarik/toolbox/database/keyValue/KeyValueBuilder.java @@ -8,7 +8,7 @@ import org.jetbrains.annotations.NotNull; import java.sql.SQLException; -public class KeyValueBuilder implements IBuilder { +public class KeyValueBuilder implements IBuilder { private final RequiredParamBuilder tableName; private final RequiredParamBuilder connection; @@ -32,8 +32,8 @@ public class KeyValueBuilder implements IBuilder { return this; } - public KeyValueConnection build() throws SQLException { - return new KeyValueConnection(connection.get(), tableName.get()); + public KeyValuePostgresql build() throws SQLException { + return new KeyValuePostgresql(connection.get(), tableName.get()); } } diff --git a/Database/src/main/java/fr/altarik/toolbox/database/keyValue/KeyValueConnection.java b/Database/src/main/java/fr/altarik/toolbox/database/keyValue/KeyValuePostgresql.java similarity index 71% rename from Database/src/main/java/fr/altarik/toolbox/database/keyValue/KeyValueConnection.java rename to Database/src/main/java/fr/altarik/toolbox/database/keyValue/KeyValuePostgresql.java index 85b1994..28a55bf 100644 --- a/Database/src/main/java/fr/altarik/toolbox/database/keyValue/KeyValueConnection.java +++ b/Database/src/main/java/fr/altarik/toolbox/database/keyValue/KeyValuePostgresql.java @@ -9,16 +9,19 @@ import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; -public class KeyValueConnection implements KeyValueTable { +public class KeyValuePostgresql implements KeyValueTable { private final SqlConnection connection; private final String tableName; - public KeyValueConnection(@NotNull SqlConnection connection, @NotNull String tableName) throws SQLException { + public KeyValuePostgresql(@NotNull SqlConnection connection, @NotNull String tableName) throws SQLException { this.connection = connection; this.tableName = tableName; connection.checkConnection(); + createTable(tableName); + } + private void createTable(String tableName) throws SQLException { try(Statement statement = connection.getConnection().createStatement()) { statement.executeUpdate("CREATE TABLE IF NOT EXISTS " + tableName + "(key VARCHAR(50) NOT NULL, value TEXT NOT NULL, PRIMARY KEY(key));"); } @@ -55,4 +58,21 @@ public class KeyValueConnection implements KeyValueTable { preparedStatement.executeUpdate(); } } + + @Override + public void deleteRow(String key) throws SQLException { + connection.checkConnection(); + try(PreparedStatement preparedStatement = connection.getConnection().prepareStatement("DELETE FROM " + tableName + " WHERE key=?")) { + preparedStatement.setString(1, key); + preparedStatement.executeUpdate(); + } + } + + @Override + public void truncateTable() throws SQLException { + connection.checkConnection(); + try(PreparedStatement preparedStatement = connection.getConnection().prepareStatement("TRUNCATE TABLE " + tableName)) { + preparedStatement.executeUpdate(); + } + } } diff --git a/Database/src/main/java/fr/altarik/toolbox/database/keyValue/KeyValueTable.java b/Database/src/main/java/fr/altarik/toolbox/database/keyValue/KeyValueTable.java index 71054ee..567c4be 100644 --- a/Database/src/main/java/fr/altarik/toolbox/database/keyValue/KeyValueTable.java +++ b/Database/src/main/java/fr/altarik/toolbox/database/keyValue/KeyValueTable.java @@ -4,6 +4,10 @@ import org.jetbrains.annotations.Nullable; import java.sql.SQLException; +/** + *

Implement of a key value table, abstract the actual representation of the table and its manipulation between this interface

+ * @see KeyValuePostgresql + */ public interface KeyValueTable { /** @@ -33,4 +37,18 @@ public interface KeyValueTable { */ void updateValue(String key, String value) throws SQLException; + /** + *

Delete row with having {@code key} as unique key

+ *

If key doesn't exist in database, will delete no row without warning

+ * @param key the key of the row to delete + * @throws SQLException if connection is lost + */ + void deleteRow(String key) throws SQLException; + + /** + * Will delete every data inside the table + * @throws SQLException if connection is lost + */ + void truncateTable() throws SQLException; + } diff --git a/Database/src/test/java/fr/altarik/toolbox/database/keyValue/KeyValueTest.java b/Database/src/test/java/fr/altarik/toolbox/database/keyValue/KeyValueTest.java new file mode 100644 index 0000000..78990a6 --- /dev/null +++ b/Database/src/test/java/fr/altarik/toolbox/database/keyValue/KeyValueTest.java @@ -0,0 +1,68 @@ +package fr.altarik.toolbox.database.keyValue; + +import com.google.gson.Gson; +import fr.altarik.toolbox.database.ConnectionConfig; +import fr.altarik.toolbox.database.Connections; +import fr.altarik.toolbox.database.SqlConnection; +import org.junit.jupiter.api.Test; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.net.URL; +import java.net.URLConnection; +import java.util.Objects; +import java.util.stream.Collectors; + +import static org.junit.jupiter.api.Assertions.*; + +public class KeyValueTest { + + @Test + void tableTest() { + System.out.println("Hello"); + assertDoesNotThrow(() -> {InputStream configInput = getResource("config.yml"); + String configStr = new BufferedReader(new InputStreamReader(Objects.requireNonNull(configInput))) + .lines().collect(Collectors.joining("\n")); + Gson gson = new Gson(); + ConnectionConfig config = gson.fromJson(configStr, ConnectionConfig.class); + try(SqlConnection connection = Connections.newPostgresConnection(config)) { + KeyValueTable keyValueTable = Connections.newKeyValueTable(connection, "toolbox_keyvalue"); + keyValueTable.truncateTable(); + keyValueTable.insertValue("location", "here"); + keyValueTable.insertValue("experience", "5"); + assertEquals("here", keyValueTable.getValue("location")); + assertEquals("5", keyValueTable.getValue("experience")); + keyValueTable.updateValue("location", "Elsewhere"); + assertEquals("Elsewhere", keyValueTable.getValue("location")); + assertEquals("5", keyValueTable.getValue("experience")); + keyValueTable.updateValue("experience", "10"); + assertEquals("Elsewhere", keyValueTable.getValue("location")); + assertEquals("10", keyValueTable.getValue("experience")); + keyValueTable.deleteRow("experience"); + assertEquals("Elsewhere", keyValueTable.getValue("location")); + assertNull(keyValueTable.getValue("experience")); + keyValueTable.truncateTable(); + assertNull(keyValueTable.getValue("location")); + assertNull(keyValueTable.getValue("experience")); + } + }); + } + + // TODO: 08/06/2023 Move to Core module in a toolkit class + private InputStream getResource(String resourcePath) { + try { + URL url = this.getClass().getClassLoader().getResource(resourcePath); + if(url == null) + return null; + + URLConnection connection = url.openConnection(); + connection.setUseCaches(false); + return connection.getInputStream(); + } catch (IOException e){ + return null; + } + } + +} diff --git a/Database/src/test/resources/config.yml b/Database/src/test/resources/config.yml index 9e2feb9..4f42d65 100644 --- a/Database/src/test/resources/config.yml +++ b/Database/src/test/resources/config.yml @@ -3,5 +3,5 @@ "port": 5432, "database": "postgres", "username": "postgres", - "password": "root" + "password": "Vaubadon1" } \ No newline at end of file