diff --git a/common/src/main/java/me/lucko/luckperms/common/managers/impl/GenericUserManager.java b/common/src/main/java/me/lucko/luckperms/common/managers/impl/GenericUserManager.java index fc8b70e5..a0666b7e 100644 --- a/common/src/main/java/me/lucko/luckperms/common/managers/impl/GenericUserManager.java +++ b/common/src/main/java/me/lucko/luckperms/common/managers/impl/GenericUserManager.java @@ -56,8 +56,7 @@ public class GenericUserManager extends AbstractManager im user.setPrimaryGroup("default"); try { user.setPermission("group.default", true); - } catch (ObjectAlreadyHasException ignored) { - } + } catch (ObjectAlreadyHasException ignored) {} if (save) { plugin.getStorage().saveUser(user); diff --git a/common/src/main/java/me/lucko/luckperms/common/storage/backing/SQLBacking.java b/common/src/main/java/me/lucko/luckperms/common/storage/backing/SQLBacking.java index 3cf99126..7194341b 100644 --- a/common/src/main/java/me/lucko/luckperms/common/storage/backing/SQLBacking.java +++ b/common/src/main/java/me/lucko/luckperms/common/storage/backing/SQLBacking.java @@ -33,6 +33,7 @@ import me.lucko.luckperms.common.core.model.Group; import me.lucko.luckperms.common.core.model.Track; import me.lucko.luckperms.common.core.model.User; import me.lucko.luckperms.common.data.Log; +import me.lucko.luckperms.common.managers.GroupManager; import me.lucko.luckperms.common.managers.TrackManager; import me.lucko.luckperms.common.managers.impl.GenericUserManager; import me.lucko.luckperms.common.storage.backing.sqlprovider.SQLProvider; @@ -58,7 +59,7 @@ import java.util.function.Function; import java.util.stream.Collectors; public class SQLBacking extends AbstractBacking { - private static final Type LIST_STRING_TYPE = new TypeToken>() {}.getType(); + private static final Type LIST_STRING_TYPE = new TypeToken>(){}.getType(); private static final String USER_PERMISSIONS_SELECT = "SELECT permission, value, server, world, expiry, contexts FROM {prefix}user_permissions WHERE uuid=?"; private static final String USER_PERMISSIONS_DELETE = "DELETE FROM {prefix}user_permissions WHERE uuid=?"; @@ -66,6 +67,19 @@ public class SQLBacking extends AbstractBacking { private static final String USER_PERMISSIONS_SELECT_DISTINCT = "SELECT DISTINCT uuid FROM {prefix}user_permissions"; private static final String PLAYER_SELECT = "SELECT username, primary_group FROM {prefix}players WHERE uuid=?"; + private static final String PLAYER_SELECT_UUID = "SELECT uuid FROM {prefix}players WHERE username=? LIMIT 1"; + private static final String PLAYER_SELECT_USERNAME = "SELECT username FROM {prefix}players WHERE uuid=? LIMIT 1"; + private static final String PLAYER_INSERT = "INSERT INTO {prefix}players VALUES(?, ?, ?)"; + private static final String PLAYER_UPDATE = "UPDATE {prefix}players SET username=? WHERE uuid=?"; + private static final String PLAYER_UPDATE_FULL = "UPDATE {prefix}players SET username=?, primary_group=? WHERE uuid=?"; + + private static final String GROUP_PERMISSIONS_SELECT = "SELECT permission, value, server, world, expiry, contexts FROM {prefix}group_permissions WHERE name=?"; + private static final String GROUP_PERMISSIONS_DELETE = "DELETE FROM {prefix}group_permissions WHERE name=?"; + private static final String GROUP_PERMISSIONS_INSERT = "INSERT INTO {prefix}group_permissions VALUES(?, ?, ?, ?, ?, ?, ?)"; + + private static final String GROUP_SELECT = "SELECT name FROM {prefix}groups"; + private static final String GROUP_INSERT = "INSERT INTO {prefix}groups VALUES(?)"; + private static final String GROUP_DELETE = "DELETE FROM {prefix}groups WHERE name=?"; private static final String TRACK_INSERT = "INSERT INTO {prefix}tracks VALUES(?, ?)"; private static final String TRACK_SELECT = "SELECT groups FROM {prefix}tracks WHERE name=?"; @@ -105,7 +119,9 @@ public class SQLBacking extends AbstractBacking { } private boolean tableExists(String table) throws SQLException { - return provider.getConnection().getMetaData().getTables(null, null, table.toUpperCase(), null).next(); + try (Connection connection = provider.getConnection()) { + return connection.getMetaData().getTables(null, null, table.toUpperCase(), null).next(); + } } @Override @@ -122,26 +138,28 @@ public class SQLBacking extends AbstractBacking { } try (BufferedReader reader = new BufferedReader(new InputStreamReader(is, StandardCharsets.UTF_8))) { - try (Statement s = provider.getConnection().createStatement()) { - StringBuilder sb = new StringBuilder(); - String line; - while ((line = reader.readLine()) != null) { - if (line.startsWith("--") || line.startsWith("#")) continue; + try (Connection connection = provider.getConnection()) { + try (Statement s = connection.createStatement()) { + StringBuilder sb = new StringBuilder(); + String line; + while ((line = reader.readLine()) != null) { + if (line.startsWith("--") || line.startsWith("#")) continue; - sb.append(line); + sb.append(line); - // check for end of declaration - if (line.endsWith(";")) { - sb.deleteCharAt(sb.length() - 1); + // check for end of declaration + if (line.endsWith(";")) { + sb.deleteCharAt(sb.length() - 1); - String result = prefix.apply(sb.toString().trim()); - if (!result.isEmpty()) s.addBatch(result); + String result = prefix.apply(sb.toString().trim()); + if (!result.isEmpty()) s.addBatch(result); - // reset - sb = new StringBuilder(); + // reset + sb = new StringBuilder(); + } } + s.executeBatch(); } - s.executeBatch(); } } } @@ -166,31 +184,31 @@ public class SQLBacking extends AbstractBacking { @Override public boolean logAction(LogEntry entry) { - return runQuery(prefix.apply(ACTION_INSERT), preparedStatement -> { - preparedStatement.setLong(1, entry.getTimestamp()); - preparedStatement.setString(2, entry.getActor().toString()); - preparedStatement.setString(3, entry.getActorName()); - preparedStatement.setString(4, Character.toString(entry.getType())); - preparedStatement.setString(5, entry.getActed() == null ? "null" : entry.getActed().toString()); - preparedStatement.setString(6, entry.getActedName()); - preparedStatement.setString(7, entry.getAction()); + return runQuery(prefix.apply(ACTION_INSERT), ps -> { + ps.setLong(1, entry.getTimestamp()); + ps.setString(2, entry.getActor().toString()); + ps.setString(3, entry.getActorName()); + ps.setString(4, Character.toString(entry.getType())); + ps.setString(5, entry.getActed() == null ? "null" : entry.getActed().toString()); + ps.setString(6, entry.getActedName()); + ps.setString(7, entry.getAction()); }); } @Override public Log getLog() { final Log.Builder log = Log.builder(); - boolean success = runQuery(prefix.apply(ACTION_SELECT_ALL), resultSet -> { - while (resultSet.next()) { - final String actedUuid = resultSet.getString("acted_uuid"); + boolean success = runQuery(prefix.apply(ACTION_SELECT_ALL), rs -> { + while (rs.next()) { + final String actedUuid = rs.getString("acted_uuid"); LogEntry e = new LogEntry( - resultSet.getLong("time"), - UUID.fromString(resultSet.getString("actor_uuid")), - resultSet.getString("actor_name"), - resultSet.getString("type").toCharArray()[0], + rs.getLong("time"), + UUID.fromString(rs.getString("actor_uuid")), + rs.getString("actor_name"), + rs.getString("type").toCharArray()[0], actedUuid.equals("null") ? null : UUID.fromString(actedUuid), - resultSet.getString("acted_name"), - resultSet.getString("action") + rs.getString("acted_name"), + rs.getString("action") ); log.add(e); } @@ -248,17 +266,81 @@ public class SQLBacking extends AbstractBacking { if (pg == null) { pg = "default"; } + user.setPrimaryGroup(pg); String name = userName.get(); if (name == null) { name = "null"; } + boolean save = plugin.getUserManager().giveDefaultIfNeeded(user, false); + if (user.getName() == null || user.getName().equalsIgnoreCase("null")) { user.setName(name); + } else { + if (!name.equals(user.getName())) { + save = true; + } } - user.setPrimaryGroup(pg); + // Save back to the store if there was a username change + if (save) { + boolean s3 = runQuery(prefix.apply(USER_PERMISSIONS_DELETE), ps -> { + ps.setString(1, user.getUuid().toString()); + }); + + if (!s3) return false; + + List newData = user.getNodes().stream().map(NodeDataHolder::fromNode).collect(Collectors.toList()); + if (newData.isEmpty()) return true; + + try (Connection connection = provider.getConnection()) { + try (PreparedStatement ps = connection.prepareStatement(prefix.apply(USER_PERMISSIONS_INSERT))) { + for (NodeDataHolder nd : newData) { + ps.setString(1, user.getUuid().toString()); + ps.setString(2, nd.getPermission()); + ps.setBoolean(3, nd.isValue()); + ps.setString(4, nd.getServer()); + ps.setString(5, nd.getWorld()); + ps.setLong(6, nd.getExpiry()); + ps.setString(7, nd.getContexts()); + ps.addBatch(); + } + ps.executeBatch(); + } + } catch (SQLException e) { + e.printStackTrace(); + } + + AtomicBoolean exists = new AtomicBoolean(false); + boolean success = runQuery( + prefix.apply(PLAYER_SELECT_USERNAME), + ps -> ps.setString(1, uuid.toString()), + rs -> { + if (rs.next()) { + exists.set(true); + } + return true; + } + ); + if (!success) { + return false; + } + + if (exists.get()) { + return runQuery(prefix.apply(PLAYER_UPDATE_FULL), ps -> { + ps.setString(1, user.getName().toLowerCase()); + ps.setString(2, user.getPrimaryGroup() == null ? "default" : user.getPrimaryGroup()); + ps.setString(3, uuid.toString()); + }); + } else { + return runQuery(prefix.apply(PLAYER_INSERT), ps -> { + ps.setString(1, uuid.toString()); + ps.setString(2, user.getName().toLowerCase()); + ps.setString(3, user.getPrimaryGroup() == null ? "default" : user.getPrimaryGroup()); + }); + } + } } else { if (GenericUserManager.shouldSave(user)) { @@ -281,18 +363,16 @@ public class SQLBacking extends AbstractBacking { user.getIoLock().lock(); try { - boolean s = runQuery(prefix.apply(USER_PERMISSIONS_DELETE), preparedStatement -> { - preparedStatement.setString(1, user.getUuid().toString()); + boolean s = runQuery(prefix.apply(USER_PERMISSIONS_DELETE), ps -> { + ps.setString(1, user.getUuid().toString()); }); - if (!s) { - return false; - } - if (!shouldSave) { - return true; - } + if (!s) return false; + if (!shouldSave) return true; List data = user.getNodes().stream().map(NodeDataHolder::fromNode).collect(Collectors.toList()); + if (data.isEmpty()) return true; + try (Connection connection = provider.getConnection()) { try (PreparedStatement ps = connection.prepareStatement(prefix.apply(USER_PERMISSIONS_INSERT))) { for (NodeDataHolder nd : data) { @@ -311,7 +391,34 @@ public class SQLBacking extends AbstractBacking { e.printStackTrace(); } - return true; + AtomicBoolean exists = new AtomicBoolean(false); + boolean success = runQuery( + prefix.apply(PLAYER_SELECT_USERNAME), + ps -> ps.setString(1, user.getUuid().toString()), + rs -> { + if (rs.next()) { + exists.set(true); + } + return true; + } + ); + if (!success) { + return false; + } + + if (exists.get()) { + return runQuery(prefix.apply(PLAYER_UPDATE_FULL), ps -> { + ps.setString(1, user.getName().toLowerCase()); + ps.setString(2, user.getPrimaryGroup() == null ? "default" : user.getPrimaryGroup()); + ps.setString(3, user.getUuid().toString()); + }); + } else { + return runQuery(prefix.apply(PLAYER_INSERT), ps -> { + ps.setString(1, user.getUuid().toString()); + ps.setString(2, user.getName().toLowerCase()); + ps.setString(3, user.getPrimaryGroup() == null ? "default" : user.getPrimaryGroup()); + }); + } } finally { user.getIoLock().unlock(); } @@ -339,27 +446,175 @@ public class SQLBacking extends AbstractBacking { @Override public boolean createAndLoadGroup(String name) { - return false; + List groups = new ArrayList<>(); + runQuery( + prefix.apply(GROUP_SELECT), + rs -> { + while (rs.next()) { + groups.add(rs.getString("name").toLowerCase()); + } + return true; + } + ); + + if (!groups.contains(name)) { + runQuery( + prefix.apply(GROUP_INSERT), + ps -> { + ps.setString(1, name); + } + ); + } + + return loadGroup(name); } @Override public boolean loadGroup(String name) { - return false; + List groups = new ArrayList<>(); + runQuery( + prefix.apply(GROUP_SELECT), + rs -> { + while (rs.next()) { + groups.add(rs.getString("name").toLowerCase()); + } + return true; + } + ); + + if (!groups.contains(name)) { + return false; + } + + Group group = plugin.getGroupManager().getOrMake(name); + group.getIoLock().lock(); + try { + List data = new ArrayList<>(); + boolean s = runQuery( + prefix.apply(GROUP_PERMISSIONS_SELECT), + ps -> ps.setString(1, group.getName()), + rs -> { + while (rs.next()) { + String permission = rs.getString("permission"); + boolean value = rs.getBoolean("value"); + String server = rs.getString("server"); + String world = rs.getString("world"); + long expiry = rs.getLong("expiry"); + String contexts = rs.getString("contexts"); + data.add(NodeDataHolder.of(permission, value, server, world, expiry, contexts)); + } + return true; + } + ); + + if (!s) { + return false; + } + + if (!data.isEmpty()) { + Set nodes = data.stream().map(NodeDataHolder::toNode).collect(Collectors.toSet()); + group.setNodes(nodes); + } else { + group.clearNodes(); + } + + return true; + } finally { + group.getIoLock().unlock(); + } } @Override public boolean loadAllGroups() { - return false; + List groups = new ArrayList<>(); + boolean b = runQuery( + prefix.apply(GROUP_SELECT), + rs -> { + while (rs.next()) { + groups.add(rs.getString("name").toLowerCase()); + } + return true; + } + ); + + if (!b) { + return false; + } + + for (String g : groups) { + if (!loadGroup(g)) { + b = false; + } + } + + if (b) { + GroupManager gm = plugin.getGroupManager(); + gm.getAll().values().stream() + .filter(g -> !groups.contains(g.getName())) + .forEach(gm::unload); + } + return b; } @Override public boolean saveGroup(Group group) { - return false; + group.getIoLock().lock(); + try { + boolean s = runQuery(prefix.apply(GROUP_PERMISSIONS_DELETE), ps -> { + ps.setString(1, group.getName()); + }); + if (!s) { + return false; + } + + List data = group.getNodes().stream().map(NodeDataHolder::fromNode).collect(Collectors.toList()); + + if (data.isEmpty()) { + return true; + } + + try (Connection connection = provider.getConnection()) { + try (PreparedStatement ps = connection.prepareStatement(prefix.apply(GROUP_PERMISSIONS_INSERT))) { + for (NodeDataHolder nd : data) { + ps.setString(1, group.getName()); + ps.setString(2, nd.getPermission()); + ps.setBoolean(3, nd.isValue()); + ps.setString(4, nd.getServer()); + ps.setString(5, nd.getWorld()); + ps.setLong(6, nd.getExpiry()); + ps.setString(7, nd.getContexts()); + ps.addBatch(); + } + ps.executeBatch(); + } + } catch (SQLException e) { + e.printStackTrace(); + } + + return true; + } finally { + group.getIoLock().unlock(); + } } @Override public boolean deleteGroup(Group group) { - return false; + group.getIoLock().lock(); + try { + + boolean s = runQuery( + prefix.apply(GROUP_PERMISSIONS_DELETE), + ps -> { + ps.setString(1, group.getName()); + } + ); + return s && runQuery(prefix.apply(GROUP_DELETE), ps -> { + ps.setString(1, group.getName()); + }); + + } finally { + group.getIoLock().unlock(); + } } @Override @@ -392,9 +647,9 @@ public class SQLBacking extends AbstractBacking { return true; } else { String json = gson.toJson(track.getGroups()); - return runQuery(TRACK_INSERT, preparedStatement -> { - preparedStatement.setString(1, track.getName()); - preparedStatement.setString(2, json); + return runQuery(prefix.apply(TRACK_INSERT), ps -> { + ps.setString(1, track.getName()); + ps.setString(2, json); }); } @@ -410,7 +665,7 @@ public class SQLBacking extends AbstractBacking { try { AtomicReference groups = new AtomicReference<>(null); boolean s = runQuery( - TRACK_SELECT, + prefix.apply(TRACK_SELECT), ps -> ps.setString(1, name), rs -> { if (rs.next()) { @@ -504,16 +759,74 @@ public class SQLBacking extends AbstractBacking { @Override public boolean saveUUIDData(String username, UUID uuid) { - return false; + final String u = username.toLowerCase(); + AtomicBoolean exists = new AtomicBoolean(false); + + boolean success = runQuery( + prefix.apply(PLAYER_SELECT_USERNAME), + ps -> ps.setString(1, uuid.toString()), + rs -> { + if (rs.next()) { + exists.set(true); + } + return true; + } + ); + + if (!success) { + return false; + } + + if (exists.get()) { + return runQuery(prefix.apply(PLAYER_UPDATE), ps -> { + ps.setString(1, u); + ps.setString(2, uuid.toString()); + }); + } else { + return runQuery(prefix.apply(PLAYER_INSERT), ps -> { + ps.setString(1, uuid.toString()); + ps.setString(2, u); + ps.setString(3, "default"); + }); + } } @Override public UUID getUUID(String username) { - return null; + final String u = username.toLowerCase(); + final AtomicReference uuid = new AtomicReference<>(null); + + boolean success = runQuery( + prefix.apply(PLAYER_SELECT_UUID), + ps -> ps.setString(1, u), + rs -> { + if (rs.next()) { + uuid.set(UUID.fromString(rs.getString("uuid"))); + return true; + } + return false; + } + ); + + return success ? uuid.get() : null; } @Override public String getName(UUID uuid) { - return null; + final AtomicReference name = new AtomicReference<>(null); + + boolean success = runQuery( + prefix.apply(PLAYER_SELECT_USERNAME), + ps -> ps.setString(1, uuid.toString()), + rs -> { + if (rs.next()) { + name.set(rs.getString("username")); + return true; + } + return false; + } + ); + + return success ? name.get() : null; } } diff --git a/common/src/main/java/me/lucko/luckperms/common/storage/backing/sqlprovider/FlatfileProvider.java b/common/src/main/java/me/lucko/luckperms/common/storage/backing/sqlprovider/FlatfileProvider.java index 2b446c0d..b0c60f0a 100644 --- a/common/src/main/java/me/lucko/luckperms/common/storage/backing/sqlprovider/FlatfileProvider.java +++ b/common/src/main/java/me/lucko/luckperms/common/storage/backing/sqlprovider/FlatfileProvider.java @@ -23,10 +23,7 @@ package me.lucko.luckperms.common.storage.backing.sqlprovider; import java.io.File; -import java.sql.Connection; import java.sql.DriverManager; -import java.sql.PreparedStatement; -import java.sql.ResultSet; import java.sql.SQLException; import java.util.concurrent.locks.ReentrantLock; @@ -34,7 +31,7 @@ abstract class FlatfileProvider extends SQLProvider { private final File file; private final ReentrantLock lock = new ReentrantLock(); - private Connection connection; + private WrappedConnection connection; FlatfileProvider(String name, File file) { super(name); @@ -57,7 +54,7 @@ abstract class FlatfileProvider extends SQLProvider { } @Override - public Connection getConnection() throws SQLException { + public WrappedConnection getConnection() throws SQLException { lock.lock(); try { if (connection == null || connection.isClosed()) { @@ -65,7 +62,7 @@ abstract class FlatfileProvider extends SQLProvider { Class.forName(getDriverClass()); } catch (ClassNotFoundException ignored) {} - connection = DriverManager.getConnection(getDriverId() + ":" + file.getAbsolutePath()); + connection = new WrappedConnection(DriverManager.getConnection(getDriverId() + ":" + file.getAbsolutePath()), false); } } finally { @@ -74,45 +71,4 @@ abstract class FlatfileProvider extends SQLProvider { return connection; } - - @Override - public boolean runQuery(String query, QueryPS queryPS) { - try { - Connection connection = getConnection(); - if (connection == null || connection.isClosed()) { - throw new IllegalStateException("SQL connection is null"); - } - - try (PreparedStatement preparedStatement = connection.prepareStatement(query)) { - queryPS.onRun(preparedStatement); - - preparedStatement.execute(); - return true; - } - } catch (SQLException e) { - e.printStackTrace(); - } - return false; - } - - @Override - public boolean runQuery(String query, QueryPS queryPS, QueryRS queryRS) { - try { - Connection connection = getConnection(); - if (connection == null || connection.isClosed()) { - throw new IllegalStateException("SQL connection is null"); - } - - try (PreparedStatement preparedStatement = connection.prepareStatement(query)) { - queryPS.onRun(preparedStatement); - - try (ResultSet resultSet = preparedStatement.executeQuery()) { - return queryRS.onResult(resultSet); - } - } - } catch (SQLException e) { - e.printStackTrace(); - } - return false; - } } diff --git a/common/src/main/java/me/lucko/luckperms/common/storage/backing/sqlprovider/MySQLProvider.java b/common/src/main/java/me/lucko/luckperms/common/storage/backing/sqlprovider/MySQLProvider.java index 279d089c..74805fdd 100644 --- a/common/src/main/java/me/lucko/luckperms/common/storage/backing/sqlprovider/MySQLProvider.java +++ b/common/src/main/java/me/lucko/luckperms/common/storage/backing/sqlprovider/MySQLProvider.java @@ -27,9 +27,6 @@ import com.zaxxer.hikari.HikariDataSource; import me.lucko.luckperms.common.storage.DatastoreConfiguration; -import java.sql.Connection; -import java.sql.PreparedStatement; -import java.sql.ResultSet; import java.sql.SQLException; import java.util.concurrent.TimeUnit; @@ -91,50 +88,7 @@ public class MySQLProvider extends SQLProvider { } @Override - public Connection getConnection() throws SQLException { - return hikari.getConnection(); - } - - @Override - public boolean runQuery(String query, QueryPS queryPS) { - try { - try (Connection connection = getConnection()) { - if (connection == null || connection.isClosed()) { - throw new IllegalStateException("SQL connection is null"); - } - - try (PreparedStatement preparedStatement = connection.prepareStatement(query)) { - queryPS.onRun(preparedStatement); - - preparedStatement.execute(); - return true; - } - } - } catch (SQLException e) { - e.printStackTrace(); - } - return false; - } - - @Override - public boolean runQuery(String query, QueryPS queryPS, QueryRS queryRS) { - try { - try (Connection connection = getConnection()) { - if (connection == null || connection.isClosed()) { - throw new IllegalStateException("SQL connection is null"); - } - - try (PreparedStatement preparedStatement = connection.prepareStatement(query)) { - queryPS.onRun(preparedStatement); - - try (ResultSet resultSet = preparedStatement.executeQuery()) { - return queryRS.onResult(resultSet); - } - } - } - } catch (SQLException e) { - e.printStackTrace(); - } - return false; + public WrappedConnection getConnection() throws SQLException { + return new WrappedConnection(hikari.getConnection(), true); } } diff --git a/common/src/main/java/me/lucko/luckperms/common/storage/backing/sqlprovider/SQLProvider.java b/common/src/main/java/me/lucko/luckperms/common/storage/backing/sqlprovider/SQLProvider.java index b5a85dc2..7cece9ac 100644 --- a/common/src/main/java/me/lucko/luckperms/common/storage/backing/sqlprovider/SQLProvider.java +++ b/common/src/main/java/me/lucko/luckperms/common/storage/backing/sqlprovider/SQLProvider.java @@ -41,11 +41,48 @@ public abstract class SQLProvider { public abstract void shutdown() throws Exception; - public abstract Connection getConnection() throws SQLException; + public abstract WrappedConnection getConnection() throws SQLException; - public abstract boolean runQuery(String query, QueryPS queryPS); + public boolean runQuery(String query, QueryPS queryPS) { + try { + try (Connection connection = getConnection()) { + if (connection == null || connection.isClosed()) { + throw new IllegalStateException("SQL connection is null"); + } - public abstract boolean runQuery(String query, QueryPS queryPS, QueryRS queryRS); + try (PreparedStatement preparedStatement = connection.prepareStatement(query)) { + queryPS.onRun(preparedStatement); + + preparedStatement.execute(); + return true; + } + } + } catch (SQLException e) { + e.printStackTrace(); + } + return false; + } + + public boolean runQuery(String query, QueryPS queryPS, QueryRS queryRS) { + try { + try (Connection connection = getConnection()) { + if (connection == null || connection.isClosed()) { + throw new IllegalStateException("SQL connection is null"); + } + + try (PreparedStatement preparedStatement = connection.prepareStatement(query)) { + queryPS.onRun(preparedStatement); + + try (ResultSet resultSet = preparedStatement.executeQuery()) { + return queryRS.onResult(resultSet); + } + } + } + } catch (SQLException e) { + e.printStackTrace(); + } + return false; + } public boolean runQuery(String query) { return runQuery(query, EMPTY_PS); diff --git a/common/src/main/java/me/lucko/luckperms/common/storage/backing/sqlprovider/WrappedConnection.java b/common/src/main/java/me/lucko/luckperms/common/storage/backing/sqlprovider/WrappedConnection.java new file mode 100644 index 00000000..c313a80d --- /dev/null +++ b/common/src/main/java/me/lucko/luckperms/common/storage/backing/sqlprovider/WrappedConnection.java @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2016 Lucko (Luck) + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package me.lucko.luckperms.common.storage.backing.sqlprovider; + +import lombok.AllArgsConstructor; +import lombok.experimental.Delegate; + +import java.sql.Connection; +import java.sql.SQLException; + +@AllArgsConstructor +public class WrappedConnection implements Connection { + + @Delegate(excludes = Exclude.class) + private Connection delegate; + + private final boolean shouldClose; + + @Override + public void close() throws SQLException { + if (shouldClose) { + delegate.close(); + } + } + + private interface Exclude { + void close(); + } +} diff --git a/common/src/main/resources/sql/lp-schema-h2.sql b/common/src/main/resources/sql/lp-schema-h2.sql index a37c0495..beef6994 100644 --- a/common/src/main/resources/sql/lp-schema-h2.sql +++ b/common/src/main/resources/sql/lp-schema-h2.sql @@ -1,32 +1,32 @@ -- LuckPerms H2 Schema. -CREATE TABLE '{prefix}user_permissions' ( - 'id' INT AUTO_INCREMENT NOT NULL, - 'uuid' VARCHAR(36) NOT NULL, - 'permission' VARCHAR(200) NOT NULL, - 'value' BOOL NOT NULL, - 'server' VARCHAR(36) NULL, - 'world' VARCHAR(36) NULL, - 'expiry' INT(11) NOT NULL, - 'contexts' VARCHAR(200) NULL, - PRIMARY KEY ('id') +CREATE TABLE `{prefix}user_permissions` ( + `id` INT AUTO_INCREMENT NOT NULL, + `uuid` VARCHAR(36) NOT NULL, + `permission` VARCHAR(200) NOT NULL, + `value` BOOL NOT NULL, + `server` VARCHAR(36) NOT NULL, + `world` VARCHAR(36) NOT NULL, + `expiry` INT(11) NOT NULL, + `contexts` VARCHAR(200) NOT NULL, + PRIMARY KEY (`id`) ); -CREATE INDEX ON '{prefix}user_permissions' ('uuid'); -CREATE INDEX ON '{prefix}user_permissions' ('permission'); +CREATE INDEX ON `{prefix}user_permissions` (`uuid`); +CREATE INDEX ON `{prefix}user_permissions` (`permission`); -CREATE TABLE '{prefix}group_permissions' ( - 'id' INT AUTO_INCREMENT NOT NULL, - 'name' VARCHAR(36) NOT NULL, - 'permission' VARCHAR(200) NOT NULL, - 'value' BOOL NOT NULL, - 'server' VARCHAR(36) NOT NULL, - 'world' VARCHAR(36) NOT NULL, - 'expiry' INT(11) NOT NULL, - 'contexts' VARCHAR(200) NOT NULL, - PRIMARY KEY ('id') +CREATE TABLE `{prefix}group_permissions` ( + `id` INT AUTO_INCREMENT NOT NULL, + `name` VARCHAR(36) NOT NULL, + `permission` VARCHAR(200) NOT NULL, + `value` BOOL NOT NULL, + `server` VARCHAR(36) NOT NULL, + `world` VARCHAR(36) NOT NULL, + `expiry` INT(11) NOT NULL, + `contexts` VARCHAR(200) NOT NULL, + PRIMARY KEY (`id`) ); -CREATE INDEX ON '{prefix}group_permissions' ('name'); -CREATE INDEX ON '{prefix}group_permissions' ('permission'); +CREATE INDEX ON `{prefix}group_permissions` (`name`); +CREATE INDEX ON `{prefix}group_permissions` (`permission`); CREATE TABLE `{prefix}players` ( `uuid` VARCHAR(36) NOT NULL, @@ -34,7 +34,12 @@ CREATE TABLE `{prefix}players` ( `primary_group` VARCHAR(36) NOT NULL, PRIMARY KEY (`uuid`) ); -CREATE INDEX ON '{prefix}players' ('username'); +CREATE INDEX ON `{prefix}players` (`username`); + +CREATE TABLE `{prefix}groups` ( + `name` VARCHAR(36) NOT NULL, + PRIMARY KEY (`name`) +); CREATE TABLE `{prefix}actions` ( `id` INT AUTO_INCREMENT NOT NULL, diff --git a/common/src/main/resources/sql/lp-schema-mysql.sql b/common/src/main/resources/sql/lp-schema-mysql.sql index a8c3d8ee..5d49d841 100644 --- a/common/src/main/resources/sql/lp-schema-mysql.sql +++ b/common/src/main/resources/sql/lp-schema-mysql.sql @@ -1,32 +1,32 @@ -- LuckPerms MySQL Schema -CREATE TABLE '{prefix}user_permissions' ( - 'id' INT AUTO_INCREMENT NOT NULL, - 'uuid' VARCHAR(36) NOT NULL, - 'permission' VARCHAR(200) NOT NULL, - 'value' BOOL NOT NULL, - 'server' VARCHAR(36) NOT NULL, - 'world' VARCHAR(36) NOT NULL, - 'expiry' INT(11) NOT NULL, - 'contexts' VARCHAR(200) NOT NULL, - PRIMARY KEY ('id') +CREATE TABLE `{prefix}user_permissions` ( + `id` INT AUTO_INCREMENT NOT NULL, + `uuid` VARCHAR(36) NOT NULL, + `permission` VARCHAR(200) NOT NULL, + `value` BOOL NOT NULL, + `server` VARCHAR(36) NOT NULL, + `world` VARCHAR(36) NOT NULL, + `expiry` INT(11) NOT NULL, + `contexts` VARCHAR(200) NOT NULL, + PRIMARY KEY (`id`) ) DEFAULT CHARSET = utf8; -CREATE INDEX '{prefix}user_permissions_uuid' ON '{prefix}user_permissions' ('uuid'); -CREATE INDEX '{prefix}user_permissions_permission' ON '{prefix}user_permissions' ('permission'); +CREATE INDEX `{prefix}user_permissions_uuid` ON `{prefix}user_permissions` (`uuid`); +CREATE INDEX `{prefix}user_permissions_permission` ON `{prefix}user_permissions` (`permission`); -CREATE TABLE '{prefix}group_permissions' ( - 'id' INT AUTO_INCREMENT NOT NULL, - 'name' VARCHAR(36) NOT NULL, - 'permission' VARCHAR(200) NOT NULL, - 'value' BOOL NOT NULL, - 'server' VARCHAR(36) NULL, - 'world' VARCHAR(36) NULL, - 'expiry' INT(11) NOT NULL, - 'contexts' VARCHAR(200) NULL, - PRIMARY KEY ('id') +CREATE TABLE `{prefix}group_permissions` ( + `id` INT AUTO_INCREMENT NOT NULL, + `name` VARCHAR(36) NOT NULL, + `permission` VARCHAR(200) NOT NULL, + `value` BOOL NOT NULL, + `server` VARCHAR(36) NOT NULL, + `world` VARCHAR(36) NOT NULL, + `expiry` INT(11) NOT NULL, + `contexts` VARCHAR(200) NOT NULL, + PRIMARY KEY (`id`) ) DEFAULT CHARSET = utf8; -CREATE INDEX '{prefix}group_permissions_name' ON '{prefix}group_permissions' ('name'); -CREATE INDEX '{prefix}group_permissions_permission' ON '{prefix}group_permissions' ('permission'); +CREATE INDEX `{prefix}group_permissions_name` ON `{prefix}group_permissions` (`name`); +CREATE INDEX `{prefix}group_permissions_permission` ON `{prefix}group_permissions` (`permission`); CREATE TABLE `{prefix}players` ( `uuid` VARCHAR(36) NOT NULL, @@ -34,12 +34,11 @@ CREATE TABLE `{prefix}players` ( `primary_group` VARCHAR(36) NOT NULL, PRIMARY KEY (`uuid`) ) DEFAULT CHARSET = utf8; -CREATE INDEX '{prefix}players_username' ON '{prefix}players' ('username'); +CREATE INDEX `{prefix}players_username` ON `{prefix}players` (`username`); CREATE TABLE `{prefix}groups` ( - `id` INT AUTO_INCREMENT NOT NULL, `name` VARCHAR(36) NOT NULL, - PRIMARY KEY (`id`) + PRIMARY KEY (`name`) ); CREATE TABLE `{prefix}actions` ( diff --git a/common/src/main/resources/sql/lp-schema-postgresql.sql b/common/src/main/resources/sql/lp-schema-postgresql.sql index 51ad3c00..c11bf569 100644 --- a/common/src/main/resources/sql/lp-schema-postgresql.sql +++ b/common/src/main/resources/sql/lp-schema-postgresql.sql @@ -18,10 +18,10 @@ CREATE TABLE "{prefix}group_permissions" ( "name" VARCHAR(36) NOT NULL, "permission" VARCHAR(200) NOT NULL, "value" BOOL NOT NULL, - "server" VARCHAR(36) NULL, - "world" VARCHAR(36) NULL, + "server" VARCHAR(36) NOT NULL, + "world" VARCHAR(36) NOT NULL, "expiry" INT NOT NULL, - "contexts" VARCHAR(200) NULL + "contexts" VARCHAR(200) NOT NULL ); CREATE INDEX "{prefix}group_permissions_name" ON "{prefix}group_permissions" ("name"); CREATE INDEX "{prefix}group_permissions_permission" ON "{prefix}group_permissions" ("permission"); @@ -33,6 +33,10 @@ CREATE TABLE "{prefix}players" ( ); CREATE INDEX "{prefix}players_username" ON "{prefix}players" ("username"); +CREATE TABLE "{prefix}groups" ( + "name" VARCHAR(36) PRIMARY KEY NOT NULL +); + CREATE TABLE "{prefix}actions" ( "id" SERIAL PRIMARY KEY NOT NULL, "time" BIGINT NOT NULL, diff --git a/common/src/main/resources/sql/lp-schema-sqlite.sql b/common/src/main/resources/sql/lp-schema-sqlite.sql index 2255230b..dec6bbc9 100644 --- a/common/src/main/resources/sql/lp-schema-sqlite.sql +++ b/common/src/main/resources/sql/lp-schema-sqlite.sql @@ -1,32 +1,30 @@ -- LuckPerms SQLite Schema -CREATE TABLE '{prefix}user_permissions' ( - 'id' INTEGER PRIMARY KEY NOT NULL, - 'uuid' VARCHAR(36) NOT NULL, - 'permission' VARCHAR(200) NOT NULL, - 'value' BOOL NOT NULL, - 'server' VARCHAR(36) NOT NULL, - 'world' VARCHAR(36) NOT NULL, - 'expiry' INT(11) NOT NULL, - 'contexts' VARCHAR(200) NOT NULL, - PRIMARY KEY ('id') +CREATE TABLE `{prefix}user_permissions` ( + `id` INTEGER PRIMARY KEY NOT NULL, + `uuid` VARCHAR(36) NOT NULL, + `permission` VARCHAR(200) NOT NULL, + `value` BOOL NOT NULL, + `server` VARCHAR(36) NOT NULL, + `world` VARCHAR(36) NOT NULL, + `expiry` INT(11) NOT NULL, + `contexts` VARCHAR(200) NOT NULL ); -CREATE INDEX '{prefix}user_permissions_uuid' ON '{prefix}user_permissions' ('uuid'); -CREATE INDEX '{prefix}user_permissions_permission' ON '{prefix}user_permissions' ('permission'); +CREATE INDEX `{prefix}user_permissions_uuid` ON `{prefix}user_permissions` (`uuid`); +CREATE INDEX `{prefix}user_permissions_permission` ON `{prefix}user_permissions` (`permission`); -CREATE TABLE '{prefix}group_permissions' ( - 'id' INTEGER PRIMARY KEY NOT NULL, - 'name' VARCHAR(36) NOT NULL, - 'permission' VARCHAR(200) NOT NULL, - 'value' BOOL NOT NULL, - 'server' VARCHAR(36) NULL, - 'world' VARCHAR(36) NULL, - 'expiry' INT(11) NOT NULL, - 'contexts' VARCHAR(200) NULL, - PRIMARY KEY ('id') +CREATE TABLE `{prefix}group_permissions` ( + `id` INTEGER PRIMARY KEY NOT NULL, + `name` VARCHAR(36) NOT NULL, + `permission` VARCHAR(200) NOT NULL, + `value` BOOL NOT NULL, + `server` VARCHAR(36) NOT NULL, + `world` VARCHAR(36) NOT NULL, + `expiry` INT(11) NOT NULL, + `contexts` VARCHAR(200) NOT NULL ); -CREATE INDEX '{prefix}group_permissions_name' ON '{prefix}group_permissions' ('name'); -CREATE INDEX '{prefix}group_permissions_permission' ON '{prefix}group_permissions' ('permission'); +CREATE INDEX `{prefix}group_permissions_name` ON `{prefix}group_permissions` (`name`); +CREATE INDEX `{prefix}group_permissions_permission` ON `{prefix}group_permissions` (`permission`); CREATE TABLE `{prefix}players` ( `uuid` VARCHAR(36) NOT NULL, @@ -34,7 +32,12 @@ CREATE TABLE `{prefix}players` ( `primary_group` VARCHAR(36) NOT NULL, PRIMARY KEY (`uuid`) ); -CREATE INDEX '{prefix}players_username' ON '{prefix}players' ('username'); +CREATE INDEX `{prefix}players_username` ON `{prefix}players` (`username`); + +CREATE TABLE `{prefix}groups` ( + `name` VARCHAR(36) NOT NULL, + PRIMARY KEY (`name`) +); CREATE TABLE `{prefix}actions` ( `id` INTEGER PRIMARY KEY NOT NULL,