Optimized MySQL manager and separated logging actions to its own class

This commit is contained in:
Anthony committed 2018-06-23 11:54:34 -04:00
1 parent f734df418a
commit 340376a52a
6 files changed
+121 -203

No files matched your search

@@ -11,6 +11,10 @@ import netneutrality.MusicBot;
import netneutrality.ThreadManager;
import org.reflections.Reflections;
/**
* When creating a controller, all database actions must be executed in another thread using an executor. One is provided in the {@link ThreadManager} class
* A simple thread can't be used in this case because unpredictable errors might happen and some actions might not be executed.
*/
public class DBController {
/**
@@ -30,13 +34,8 @@ public class DBController {
if (controllers.isEmpty())
init();
try {
if (database.isClosed()) {
if (database.isClosed())
database.reconnect();
}
} catch (SQLException e) {
e.printStackTrace();
}
if (controllers.containsKey(controller)) {
return controllers.get(controller);
@@ -46,15 +45,10 @@ public class DBController {
}
public static MysqlDatabase get() {
try {
if (database.isClosed()) {
MusicBot.LOGGER.info("Reconnecting to database..");
database.reconnect();
}
} catch (SQLException e) {
e.printStackTrace();
}
return database;
}
@@ -99,7 +93,7 @@ public class DBController {
if (!controllers.containsKey(c.getControllerName())) {
controllers.put(c.getControllerName(), c);
MusicBot.LOGGER.info("Loaded controller: " + c.getControllerName());
MusicBot.LOGGER.debug("Loaded controller: " + c.getControllerName());
}
} catch (NoSuchMethodException | InstantiationException | IllegalAccessException | IllegalArgumentException | InvocationTargetException | SecurityException e) {
@@ -14,13 +14,11 @@ import netneutrality.MusicBot;
import netneutrality.db.models.MRowModel;
import netneutrality.db.models.MTableModel;
import netneutrality.exceptions.UnimplementedParameterException;
import netneutrality.handler.LogHandler;
public class MysqlDatabase {
private Connection connection;
private PreparedStatement query = null;
private String prepareString;
private int nbRow;
private String dbName;
MysqlDatabase(String dbName) {
@@ -61,13 +59,9 @@ public class MysqlDatabase {
* @param sql The SQL query to execute
* @param params The parameters to include in the query
* @return an integer of how many row were affected
* @throws SQLException
*/
public int update(String sql, Object... params) throws SQLException {
prepareString = sql;
query = connection.prepareStatement(sql);
resolveParameters(query, params);
return query.executeUpdate();
public int update(String sql, Object... params) {
return executeUpdate(sql, params);
}
/**
@@ -77,13 +71,9 @@ public class MysqlDatabase {
* @param sql The SQL query to execute
* @param params The parameters to include in the query
* @return an integer of how many row were affected
* @throws SQLException
*/
public int insert(String sql, Object... params) throws SQLException {
prepareString = sql;
query = connection.prepareStatement(sql);
resolveParameters(query, params);
return query.executeUpdate();
public int insert(String sql, Object... params) {
return executeUpdate(sql, params);
}
/**
@@ -93,13 +83,21 @@ public class MysqlDatabase {
* @param sql The SQL query to execute
* @param params The parameters to include in the query
* @return an integer of how many row were affected
* @throws SQLException
*/
public int delete(String sql, Object... params) throws SQLException {
prepareString = sql;
query = connection.prepareStatement(sql);
public int delete(String sql, Object... params) {
return executeUpdate(sql, params);
}
private int executeUpdate(String sql, Object[] params) {
try {
PreparedStatement query = connection.prepareStatement(sql);
resolveParameters(query, params);
return query.executeUpdate();
} catch (SQLException e) {
e.printStackTrace();
}
return -1;
}
/**
@@ -108,12 +106,11 @@ public class MysqlDatabase {
*
* @param sql The SQL query to execute
* @param params The parameters to include in the query
* @return a ResultSet object, which can be converted to an array using {@link #convertToArray(ResultSet)}
* @throws SQLException
* @return a ResultSet object, which can be converted to an model using {@link MysqlDatabase#convertToTableModel(ResultSet)}
*/
public ResultSet prepareAndExecute(String sql, Object... params) {
try {
query = connection.prepareStatement(sql);
PreparedStatement query = connection.prepareStatement(sql);
resolveParameters(query, params);
return query.executeQuery();
} catch (SQLException e) {
@@ -123,8 +120,6 @@ public class MysqlDatabase {
return null;
}
//
/**
* Insert parameters (specified with a ?) in the SQL statement
* Taken from https://github.com/Kaaz/DiscordBot/blob/master/src/main/java/emily/db/MySQLAdapter.java#resolveParameters
@@ -186,7 +181,7 @@ public class MysqlDatabase {
connection = new MysqlConnector(dbName, "root", "localhost", "").connect().getConnection();
} catch (SQLException e) {
System.err.println("Error connecting to database. Shutting down..");
MusicBot.disconnect();
MusicBot.shutdown();
System.exit(0);
}
}
@@ -197,52 +192,12 @@ public class MysqlDatabase {
* @return the connection status
* @throws SQLException
*/
public boolean isClosed() throws SQLException {
return connection.isClosed();
}
/**
* Convert a ResultSet object into an array.
* <br>
* <br>The first row of the array is the names of the columns.
* <br>The other rows are their corresponding value
*
* @deprecated Use {@link #convertToTableModel(ResultSet)} instead
* @param rs The ResultSet returned by the SELECT query
* @return an array of Object with the table structure
* @throws SQLException
*/
public Object[][] convertToArray(ResultSet rs) throws SQLException {
nbRow = getNbRowFromTable(prepareString);
ResultSetMetaData metadata = rs.getMetaData();
Object array[][] = new Object[nbRow + 1][metadata.getColumnCount()];
for (int i = 1; i < metadata.getColumnCount() + 1; i++) {
array[0][i - 1] = metadata.getColumnName(i);
}
int pos = 1;
while (rs.next()) {
for (int i = 1; i < rs.getMetaData().getColumnCount() + 1; i++) {
array[pos][i - 1] = rs.getObject(i);
}
pos++;
}
public boolean isClosed() {
try {
if (array[1][0] == null) {
nbRow = 0;
return connection.isClosed();
} catch (SQLException e) {
return true;
}
} catch (ArrayIndexOutOfBoundsException ignored) {
}
rs.getStatement().close();
return array;
}
/**
@@ -273,34 +228,4 @@ public class MysqlDatabase {
return table;
}
/**
* Only usable when @link {@link #prepareAndExecute(String, Object...) prepareAndExecute()} is called
*
* @return the number of row
*/
public int getNbRow() {
return nbRow;
}
private static String findTable(String sql) {
int indexFrom = sql.indexOf("FROM") + 5;
int indexWhere = sql.indexOf("WHERE") - 1;
if (indexWhere < 0) {
return sql.substring(indexFrom, indexFrom + 4);
}
return sql.substring(indexFrom, indexWhere);
}
private static int getNbRowFromTable(String sql) throws SQLException {
ResultSet nbRowRs = DBController.get().query("SELECT COUNT(*) FROM " + findTable(sql));
if (nbRowRs.next())
return nbRowRs.getInt(1);
return 0;
}
}
@@ -28,73 +28,53 @@ public class DBBlacklist extends AbstractController {
}
public void add(MBlacklist obj) {
try {
if (!isAlreadyBlacklisted(obj.getWord(), obj.getServerId())) {
database.insert("INSERT INTO blacklist VALUES(?,?,?,?)", obj.getWord(), obj.getServerId(), obj.isEnabled(), obj.getCreatorId());
} else {
throw new RuntimeException("Word is already blacklisted");
}
} catch (SQLException e) {
e.printStackTrace();
}
}
public void delete(String word, String serverId) {
try {
if (isAlreadyBlacklisted(word, serverId)) {
database.delete("DELETE FROM blacklist WHERE word = ? AND serverId = ?", word, serverId);
} else {
throw new RuntimeException("Is not blacklisted");
}
} catch (SQLException e) {
e.printStackTrace();
}
}
public void enable(String word, String serverId) {
try {
if (isAlreadyBlacklisted(word, serverId)) {
database.update("UPDATE blacklist SET isEnabled = 1 WHERE word = ? AND serverId = ?", word, serverId);
} else {
throw new RuntimeException("Is not blacklisted");
}
} catch (SQLException e) {
e.printStackTrace();
}
}
public void disable(String word, String serverId) {
try {
if (isAlreadyBlacklisted(word, serverId)) {
database.update("UPDATE blacklist SET isEnabled = 0 WHERE word = ? AND serverId = ?", word, serverId);
} else {
throw new RuntimeException("Is not blacklisted");
}
} catch (SQLException e) {
e.printStackTrace();
}
}
public void getBlacklistForWord(String word, String serverId, Consumer<MBlacklist> success) {
ThreadManager.executor.submit(() -> {
MBlacklist blacklisted = null;
try {
if (isAlreadyBlacklisted(word, serverId)) {
ResultSet rs = database.prepareAndExecute("SELECT * FROM blacklist WHERE word = ? AND serverId = ?", word, serverId);
MTableModel table = database.convertToTableModel(rs);
if (table.getNbRows() != 0) {
if (table.getNbRows() > 0) {
blacklisted = new MBlacklist((String) table.getRow(0).get(0), (Boolean) table.getRow(0).get(2), (String) table.getRow(0).get(3),
(String) table.getRow(0).get(1));
}
} else {
throw new RuntimeException("Is not blacklisted");
}
} catch (SQLException e) {
e.printStackTrace();
}
success.accept(blacklisted);
@@ -126,9 +106,18 @@ public class DBBlacklist extends AbstractController {
}
public boolean isAlreadyBlacklisted(String word, String serverId) throws SQLException {
public boolean isAlreadyBlacklisted(String word, String serverId) {
ResultSet rs = database.prepareAndExecute("SELECT COUNT(*) FROM blacklist WHERE word = ? AND serverId = ?", word, serverId);
return !rs.next() || rs.getInt(1) != 0;
try {
if (rs.next()) {
return rs.getInt(1) != 0;
}
} catch (SQLException e) {
//TODO: error log
e.printStackTrace();
}
return false;
}
@Override
@@ -0,0 +1,67 @@
package netneutrality.db.controllers;
/*
* Copyright (c) anthorob
*
* https://xtremcommunity.com/
* https://discord.gg/CdFcyQ
*/
import net.dv8tion.jda.core.entities.TextChannel;
import netneutrality.MusicBot;
import netneutrality.ThreadManager;
import netneutrality.db.AbstractController;
import netneutrality.handler.LogHandler;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.function.Consumer;
public class DBLogging extends AbstractController {
public void getLoggingChannel(String serverId, Consumer<TextChannel> success) {
ThreadManager.executor.submit(() -> {
TextChannel txt = null;
ResultSet rs = database.prepareAndExecute("SELECT channelId FROM logging WHERE serverId = ?", serverId);
try {
if (rs.next()) {
txt = MusicBot.getJDA().getGuildById(serverId).getTextChannelById(rs.getString(1));
}
} catch (SQLException e) {
e.printStackTrace();
}
success.accept(txt);
});
}
public void setupLog(String serverId, String channelId) {
database.insert("INSERT INTO logging VALUES(?,?,?)", serverId, channelId, true);
}
public void toggleLog(String serverId, String channelId) {
database.update("UPDATE logging SET enabled = NOT enabled");
}
public boolean isLoggingEnabled(String serverId, String channelId) {
try {
ResultSet rs = database.prepareAndExecute("SELECT enabled FROM logging WHERE serverId = ? AND channelId = ?", serverId, channelId);
if (rs.next()) {
return rs.getBoolean(1);
}
} catch (SQLException e) {
e.printStackTrace();
}
return false;
}
@Override
public String getControllerName() {
return "logging";
}
}
@@ -9,8 +9,11 @@ import netneutrality.db.AbstractController;
import netneutrality.db.DBController;
import netneutrality.db.MysqlDatabase;
import netneutrality.db.models.MMessage;
import netneutrality.db.models.MTableModel;
import netneutrality.handler.LogHandler;
import javax.swing.table.TableModel;
public class DBMessage extends AbstractController {
public DBMessage() { }
@@ -27,11 +30,7 @@ public class DBMessage extends AbstractController {
public void log(String servername, String channelname, String username, String datesent, String messageId, String message) {
ThreadManager.executor.submit(() -> {
try {
database.insert("INSERT INTO log_message VALUES(?,?,?,?,?,?,?)", servername, channelname, username, datesent, messageId, message, null);
} catch (SQLException e) {
LogHandler.log(e);
}
});
}
@@ -39,46 +38,33 @@ public class DBMessage extends AbstractController {
public void logEdit(String messageId, String newMessage) {
ThreadManager.executor.submit(() -> {
try {
database.update("UPDATE log_message SET editedMessage = ? WHERE messageId = ?", newMessage, messageId);
} catch (SQLException e) {
LogHandler.log(e);
}
});
}
public MMessage getMessage(String messageId) {
try {
ResultSet rs = database.prepareAndExecute("SELECT * FROM log_message WHERE messageId = ?", messageId);
Object[][] array = database.convertToArray(rs);
if (database.getNbRow() != 0) {
return new MMessage(array[1][0], array[1][1], array[1][2], array[1][3], array[1][4], array[1][5]);
MTableModel table = MysqlDatabase.convertToTableModel(rs);
if (table.getNbRows() > 0) {
return new MMessage(table.getRowModel(0).getItem(0), table.getRowModel(0).getItem(1), table.getRowModel(0).getItem(2), table.getRowModel(0).getItem(3), table.getRowModel(0).getItem(4), table.getRowModel(0).getItem(5));
}
} catch (SQLException e) {
LogHandler.log(e);
}
return null;
}
public ArrayList<MMessage> getMessagesFromUser(String username, String serverName, int max) {
ArrayList<MMessage> messages = new ArrayList<>();
try {
ResultSet rs = database.prepareAndExecute("SELECT * FROM log_message WHERE userName = ? AND serverName = ? ORDER BY dateSent DESC", username, serverName);
Object[][] array = database.convertToArray(rs);
if (database.getNbRow() != 0) {
for (int row = 1; row <= max; row++) {
messages.add(new MMessage(array[row][0], array[row][1], array[row][2], array[row][3], array[row][4], array[row][5]));
ResultSet rs = database.prepareAndExecute("SELECT * FROM log_message WHERE userName = ? AND serverName = ? ORDER BY dateSent DESC LIMIT ?", username, serverName, max);
MTableModel table = MysqlDatabase.convertToTableModel(rs);
if (table.getNbRows() > 0) {
for (int row = 0; row < max; row++) {
messages.add(new MMessage(table.getRowModel(row).getItem(0), table.getRowModel(row).getItem(1), table.getRowModel(row).getItem(2), table.getRowModel(row).getItem(3), table.getRowModel(row).getItem(4), table.getRowModel(row).getItem(5)));
}
}
} catch (SQLException e) {
LogHandler.log(e);
}
return messages;
}
@@ -98,50 +84,7 @@ public class DBMessage extends AbstractController {
return "No message found";
}
public boolean setupLog(String serverId, String channelId) {
try {
int result = database.insert("INSERT INTO logging VALUES(?,?,?)", serverId, channelId, true);
if (result == 1) {
return true;
}
} catch (SQLException e) {
LogHandler.log(e);
}
return false;
}
public boolean toggleLog(String serverId, String channelId) {
try {
int result = database.update("UPDATE logging SET enabled = NOT enabled");
if (result == 1) {
return true;
}
} catch (SQLException e) {
LogHandler.log(e);
}
return false;
}
public boolean isLoggingEnabled(String serverId, String channelId) {
try {
ResultSet rs = database.prepareAndExecute("SELECT enabled FROM logging WHERE serverId = ? AND channelId = ?", serverId, channelId);
if (rs.next()) {
return rs.getBoolean(1);
}
} catch (SQLException e) {
e.printStackTrace();
}
return false;
}
@Override
public String getControllerName() {
@@ -21,7 +21,7 @@ public class DBSettings extends AbstractController {
MTableModel table = MysqlDatabase.convertToTableModel(rs);
if (table.getNbRows() == 1) {
value = table.getRow(0).get(0);
value = table.getRowModel(0).getItem(0);
}
success.accept(value);