From 215b96ea4bea622d9abcb7bd6368cf5c2aa7628b Mon Sep 17 00:00:00 2001
From: aro <pantoine.rochas@gmail.com>
Date: Wed, 1 Feb 2023 18:16:53 +0100
Subject: [PATCH] fix(sql): correctly update database values

---
 .../nicko/storage/sql/SQLStorage.java         | 32 ++++++---
 .../nicko/test/storage/SQLStorageTest.java    | 69 +++++++++++++++----
 2 files changed, 81 insertions(+), 20 deletions(-)

diff --git a/core/src/main/java/net/artelnatif/nicko/storage/sql/SQLStorage.java b/core/src/main/java/net/artelnatif/nicko/storage/sql/SQLStorage.java
index 5cd36d0..a01797e 100644
--- a/core/src/main/java/net/artelnatif/nicko/storage/sql/SQLStorage.java
+++ b/core/src/main/java/net/artelnatif/nicko/storage/sql/SQLStorage.java
@@ -36,14 +36,8 @@ public class SQLStorage extends Storage {
         if (connection == null) return new ActionResult<>(I18NDict.Error.SQL_ERROR);
 
         try {
-            final String sql = "INSERT IGNORE INTO nicko.DATA (`uuid`, `name`, `skin`, `locale`, `bungeecord`) VALUES (?, ?, ?, ?, ?)";
-
-            final PreparedStatement statement = connection.prepareStatement(sql);
-            statement.setBinaryStream(1, uuidToBin(uuid));
-            statement.setString(2, profile.getName() == null ? null : profile.getName());
-            statement.setString(3, profile.getSkin() == null ? null : profile.getSkin());
-            statement.setString(4, profile.getLocale().getCode());
-            statement.setBoolean(5, profile.isBungeecordTransfer());
+            final PreparedStatement statement = isStored(uuid) ?
+                    getUpdateStatement(connection, uuid, profile) : getInsertStatement(connection, uuid, profile);
             statement.executeUpdate();
             return new ActionResult<>();
         } catch (SQLException e) {
@@ -102,6 +96,28 @@ public class SQLStorage extends Storage {
         }
     }
 
+    private PreparedStatement getInsertStatement(Connection connection, UUID uuid, NickoProfile profile) throws SQLException {
+        final String sql = "INSERT IGNORE INTO nicko.DATA (`uuid`, `name`, `skin`, `locale`, `bungeecord`) VALUES (?, ?, ?, ?, ?)";
+        final PreparedStatement statement = connection.prepareStatement(sql);
+        statement.setBinaryStream(1, uuidToBin(uuid));
+        statement.setString(2, profile.getName() == null ? null : profile.getName());
+        statement.setString(3, profile.getSkin() == null ? null : profile.getSkin());
+        statement.setString(4, profile.getLocale().getCode());
+        statement.setBoolean(5, profile.isBungeecordTransfer());
+        return statement;
+    }
+
+    private PreparedStatement getUpdateStatement(Connection connection, UUID uuid, NickoProfile profile) throws SQLException {
+        final String sql = "UPDATE nicko.DATA SET name = ?, skin = ?, locale = ?, bungeecord = ? WHERE uuid = ?";
+        final PreparedStatement statement = connection.prepareStatement(sql);
+        statement.setString(1, profile.getName() == null ? null : profile.getName());
+        statement.setString(2, profile.getSkin() == null ? null : profile.getSkin());
+        statement.setString(3, profile.getLocale().getCode());
+        statement.setBoolean(4, profile.isBungeecordTransfer());
+        statement.setBinaryStream(5, uuidToBin(uuid));
+        return statement;
+    }
+
     private ByteArrayInputStream uuidToBin(UUID uuid) {
         byte[] bytes = new byte[16];
         ByteBuffer.wrap(bytes)
diff --git a/core/src/test/java/net/artelnatif/nicko/test/storage/SQLStorageTest.java b/core/src/test/java/net/artelnatif/nicko/test/storage/SQLStorageTest.java
index 2d6d8ca..ed67f69 100644
--- a/core/src/test/java/net/artelnatif/nicko/test/storage/SQLStorageTest.java
+++ b/core/src/test/java/net/artelnatif/nicko/test/storage/SQLStorageTest.java
@@ -4,14 +4,15 @@ import be.seeseemelk.mockbukkit.MockBukkit;
 import be.seeseemelk.mockbukkit.ServerMock;
 import be.seeseemelk.mockbukkit.entity.PlayerMock;
 import net.artelnatif.nicko.bukkit.NickoBukkit;
+import net.artelnatif.nicko.bukkit.i18n.Locale;
 import net.artelnatif.nicko.config.Configuration;
 import net.artelnatif.nicko.disguise.ActionResult;
 import net.artelnatif.nicko.disguise.NickoProfile;
-import net.artelnatif.nicko.bukkit.i18n.Locale;
 import org.junit.jupiter.api.*;
 
 import java.util.Optional;
 
+@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
 public class SQLStorageTest {
     private static ServerMock server;
     private static NickoBukkit plugin;
@@ -34,33 +35,77 @@ public class SQLStorageTest {
 
     @Test
     @DisplayName("Create SQL Tables")
+    @Order(1)
     public void createSQLTables() {
         Assertions.assertFalse(plugin.getNicko().getDataStore().getStorage().isError());
     }
 
     @Test
     @DisplayName("Store Player Via SQL")
+    @Order(2)
     public void storePlayer() {
         final Optional<NickoProfile> optionalProfile = plugin.getNicko().getDataStore().getData(player.getUniqueId());
         Assertions.assertTrue(optionalProfile.isPresent());
-
-        final NickoProfile profile = optionalProfile.get();
-        profile.setName("Notch");
-        profile.setSkin("Notch");
-        profile.setLocale(Locale.ENGLISH);
-        profile.setBungeecordTransfer(true);
-        ActionResult<Void> result = plugin.getNicko().getDataStore().saveData(player);
-        Assertions.assertFalse(result.isError());
     }
 
     @Test
     @DisplayName("Retrieve Player Via SQL")
+    @Order(3)
     public void retrievePlayer() {
         final Optional<NickoProfile> storeAction = plugin.getNicko().getDataStore().getData(player.getUniqueId());
         Assertions.assertTrue(storeAction.isPresent());
-        final NickoProfile profile = storeAction.get();
-        Assertions.assertEquals("Notch", profile.getName());
-        Assertions.assertEquals(Locale.ENGLISH, profile.getLocale());
+    }
+
+    @Test
+    @DisplayName("Update Player Via SQL")
+    @Order(4)
+    public void updatePlayer() {
+        final Optional<NickoProfile> optionalProfile = plugin.getNicko().getDataStore().getData(player.getUniqueId());
+        Assertions.assertTrue(optionalProfile.isPresent());
+
+        final NickoProfile profile = optionalProfile.get();
+        Assertions.assertNull(profile.getName());
+        Assertions.assertNull(profile.getSkin());
+        Assertions.assertEquals(profile.getLocale(), Locale.ENGLISH);
+        Assertions.assertTrue(profile.isBungeecordTransfer());
+
+        profile.setName("Notch");
+        profile.setSkin("Notch");
+        profile.setLocale(Locale.FRENCH);
+        profile.setBungeecordTransfer(false);
+
+        final ActionResult<Void> result = plugin.getNicko().getDataStore().saveData(player);
+        Assertions.assertFalse(result.isError());
+
+        final Optional<NickoProfile> optionalUpdatedProfile = plugin.getNicko().getDataStore().getData(player.getUniqueId());
+        Assertions.assertTrue(optionalUpdatedProfile.isPresent());
+        final NickoProfile updatedProfile = optionalProfile.get();
+        Assertions.assertEquals(updatedProfile.getName(), "Notch");
+        Assertions.assertEquals(updatedProfile.getSkin(), "Notch");
+        Assertions.assertEquals(updatedProfile.getLocale(), Locale.FRENCH);
+        Assertions.assertFalse(updatedProfile.isBungeecordTransfer());
+    }
+
+    @Test
+    @DisplayName("Remove Player Disguise Via SQL")
+    @Order(5)
+    public void removePlayerDisguise() {
+        final Optional<NickoProfile> optionalProfile = plugin.getNicko().getDataStore().getData(player.getUniqueId());
+        Assertions.assertTrue(optionalProfile.isPresent());
+
+        final NickoProfile profile = optionalProfile.get();
+
+        profile.setName(null);
+        profile.setSkin(null);
+
+        final ActionResult<Void> result = plugin.getNicko().getDataStore().saveData(player);
+        Assertions.assertFalse(result.isError());
+
+        final Optional<NickoProfile> optionalUpdatedProfile = plugin.getNicko().getDataStore().getData(player.getUniqueId());
+        Assertions.assertTrue(optionalUpdatedProfile.isPresent());
+        final NickoProfile updatedProfile = optionalProfile.get();
+        Assertions.assertNull(updatedProfile.getName());
+        Assertions.assertNull(updatedProfile.getSkin());
     }
 
     @AfterAll