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 netneutrality.ThreadManager;
import org.reflections.Reflections; 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 { public class DBController {
/** /**
@@ -30,13 +34,8 @@ public class DBController {
if (controllers.isEmpty()) if (controllers.isEmpty())
init(); init();
try { if (database.isClosed())
if (database.isClosed()) {
database.reconnect(); database.reconnect();
}
} catch (SQLException e) {
e.printStackTrace();
}
if (controllers.containsKey(controller)) { if (controllers.containsKey(controller)) {
return controllers.get(controller); return controllers.get(controller);
@@ -46,15 +45,10 @@ public class DBController {
} }
public static MysqlDatabase get() { public static MysqlDatabase get() {
try {
if (database.isClosed()) { if (database.isClosed()) {
MusicBot.LOGGER.info("Reconnecting to database.."); MusicBot.LOGGER.info("Reconnecting to database..");
database.reconnect(); database.reconnect();
} }
} catch (SQLException e) {
e.printStackTrace();
}
return database; return database;
} }
@@ -99,7 +93,7 @@ public class DBController {
if (!controllers.containsKey(c.getControllerName())) { if (!controllers.containsKey(c.getControllerName())) {
controllers.put(c.getControllerName(), c); 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) { } catch (NoSuchMethodException | InstantiationException | IllegalAccessException | IllegalArgumentException | InvocationTargetException | SecurityException e) {
@@ -14,13 +14,11 @@ import netneutrality.MusicBot;
import netneutrality.db.models.MRowModel; import netneutrality.db.models.MRowModel;
import netneutrality.db.models.MTableModel; import netneutrality.db.models.MTableModel;
import netneutrality.exceptions.UnimplementedParameterException; import netneutrality.exceptions.UnimplementedParameterException;
import netneutrality.handler.LogHandler;
public class MysqlDatabase { public class MysqlDatabase {
private Connection connection; private Connection connection;
private PreparedStatement query = null;
private String prepareString;
private int nbRow;
private String dbName; private String dbName;
MysqlDatabase(String dbName) { MysqlDatabase(String dbName) {
@@ -61,13 +59,9 @@ public class MysqlDatabase {
* @param sql The SQL query to execute * @param sql The SQL query to execute
* @param params The parameters to include in the query * @param params The parameters to include in the query
* @return an integer of how many row were affected * @return an integer of how many row were affected
* @throws SQLException
*/ */
public int update(String sql, Object... params) throws SQLException { public int update(String sql, Object... params) {
prepareString = sql; return executeUpdate(sql, params);
query = connection.prepareStatement(sql);
resolveParameters(query, params);
return query.executeUpdate();
} }
/** /**
@@ -77,13 +71,9 @@ public class MysqlDatabase {
* @param sql The SQL query to execute * @param sql The SQL query to execute
* @param params The parameters to include in the query * @param params The parameters to include in the query
* @return an integer of how many row were affected * @return an integer of how many row were affected
* @throws SQLException
*/ */
public int insert(String sql, Object... params) throws SQLException { public int insert(String sql, Object... params) {
prepareString = sql; return executeUpdate(sql, params);
query = connection.prepareStatement(sql);
resolveParameters(query, params);
return query.executeUpdate();
} }
/** /**
@@ -93,13 +83,21 @@ public class MysqlDatabase {
* @param sql The SQL query to execute * @param sql The SQL query to execute
* @param params The parameters to include in the query * @param params The parameters to include in the query
* @return an integer of how many row were affected * @return an integer of how many row were affected
* @throws SQLException
*/ */
public int delete(String sql, Object... params) throws SQLException { public int delete(String sql, Object... params) {
prepareString = sql; return executeUpdate(sql, params);
query = connection.prepareStatement(sql); }
private int executeUpdate(String sql, Object[] params) {
try {
PreparedStatement query = connection.prepareStatement(sql);
resolveParameters(query, params); resolveParameters(query, params);
return query.executeUpdate(); 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 sql The SQL query to execute
* @param params The parameters to include in the query * @param params The parameters to include in the query
* @return a ResultSet object, which can be converted to an array using {@link #convertToArray(ResultSet)} * @return a ResultSet object, which can be converted to an model using {@link MysqlDatabase#convertToTableModel(ResultSet)}
* @throws SQLException
*/ */
public ResultSet prepareAndExecute(String sql, Object... params) { public ResultSet prepareAndExecute(String sql, Object... params) {
try { try {
query = connection.prepareStatement(sql); PreparedStatement query = connection.prepareStatement(sql);
resolveParameters(query, params); resolveParameters(query, params);
return query.executeQuery(); return query.executeQuery();
} catch (SQLException e) { } catch (SQLException e) {
@@ -123,8 +120,6 @@ public class MysqlDatabase {
return null; return null;
} }
//
/** /**
* Insert parameters (specified with a ?) in the SQL statement * 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 * 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(); connection = new MysqlConnector(dbName, "root", "localhost", "").connect().getConnection();
} catch (SQLException e) { } catch (SQLException e) {
System.err.println("Error connecting to database. Shutting down.."); System.err.println("Error connecting to database. Shutting down..");
MusicBot.disconnect(); MusicBot.shutdown();
System.exit(0); System.exit(0);
} }
} }
@@ -197,52 +192,12 @@ public class MysqlDatabase {
* @return the connection status * @return the connection status
* @throws SQLException * @throws SQLException
*/ */
public boolean isClosed() throws SQLException { public boolean isClosed() {
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++;
}
try { try {
if (array[1][0] == null) { return connection.isClosed();
nbRow = 0; } catch (SQLException e) {
return true;
} }
} catch (ArrayIndexOutOfBoundsException ignored) {
}
rs.getStatement().close();
return array;
} }
/** /**
@@ -273,34 +228,4 @@ public class MysqlDatabase {
return table; 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) { public void add(MBlacklist obj) {
try {
if (!isAlreadyBlacklisted(obj.getWord(), obj.getServerId())) { if (!isAlreadyBlacklisted(obj.getWord(), obj.getServerId())) {
database.insert("INSERT INTO blacklist VALUES(?,?,?,?)", obj.getWord(), obj.getServerId(), obj.isEnabled(), obj.getCreatorId()); database.insert("INSERT INTO blacklist VALUES(?,?,?,?)", obj.getWord(), obj.getServerId(), obj.isEnabled(), obj.getCreatorId());
} else { } else {
throw new RuntimeException("Word is already blacklisted"); throw new RuntimeException("Word is already blacklisted");
} }
} catch (SQLException e) {
e.printStackTrace();
}
} }
public void delete(String word, String serverId) { public void delete(String word, String serverId) {
try {
if (isAlreadyBlacklisted(word, serverId)) { if (isAlreadyBlacklisted(word, serverId)) {
database.delete("DELETE FROM blacklist WHERE word = ? AND serverId = ?", word, serverId); database.delete("DELETE FROM blacklist WHERE word = ? AND serverId = ?", word, serverId);
} else { } else {
throw new RuntimeException("Is not blacklisted"); throw new RuntimeException("Is not blacklisted");
} }
} catch (SQLException e) {
e.printStackTrace();
}
} }
public void enable(String word, String serverId) { public void enable(String word, String serverId) {
try {
if (isAlreadyBlacklisted(word, serverId)) { if (isAlreadyBlacklisted(word, serverId)) {
database.update("UPDATE blacklist SET isEnabled = 1 WHERE word = ? AND serverId = ?", word, serverId); database.update("UPDATE blacklist SET isEnabled = 1 WHERE word = ? AND serverId = ?", word, serverId);
} else { } else {
throw new RuntimeException("Is not blacklisted"); throw new RuntimeException("Is not blacklisted");
} }
} catch (SQLException e) {
e.printStackTrace();
}
} }
public void disable(String word, String serverId) { public void disable(String word, String serverId) {
try {
if (isAlreadyBlacklisted(word, serverId)) { if (isAlreadyBlacklisted(word, serverId)) {
database.update("UPDATE blacklist SET isEnabled = 0 WHERE word = ? AND serverId = ?", word, serverId); database.update("UPDATE blacklist SET isEnabled = 0 WHERE word = ? AND serverId = ?", word, serverId);
} else { } else {
throw new RuntimeException("Is not blacklisted"); throw new RuntimeException("Is not blacklisted");
} }
} catch (SQLException e) {
e.printStackTrace();
}
} }
public void getBlacklistForWord(String word, String serverId, Consumer<MBlacklist> success) { public void getBlacklistForWord(String word, String serverId, Consumer<MBlacklist> success) {
ThreadManager.executor.submit(() -> { ThreadManager.executor.submit(() -> {
MBlacklist blacklisted = null; MBlacklist blacklisted = null;
try {
if (isAlreadyBlacklisted(word, serverId)) { if (isAlreadyBlacklisted(word, serverId)) {
ResultSet rs = database.prepareAndExecute("SELECT * FROM blacklist WHERE word = ? AND serverId = ?", word, serverId); ResultSet rs = database.prepareAndExecute("SELECT * FROM blacklist WHERE word = ? AND serverId = ?", word, serverId);
MTableModel table = database.convertToTableModel(rs); 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), 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)); (String) table.getRow(0).get(1));
} }
} else { } else {
throw new RuntimeException("Is not blacklisted"); throw new RuntimeException("Is not blacklisted");
}
} catch (SQLException e) {
e.printStackTrace();
} }
success.accept(blacklisted); 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); 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 @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.DBController;
import netneutrality.db.MysqlDatabase; import netneutrality.db.MysqlDatabase;
import netneutrality.db.models.MMessage; import netneutrality.db.models.MMessage;
import netneutrality.db.models.MTableModel;
import netneutrality.handler.LogHandler; import netneutrality.handler.LogHandler;
import javax.swing.table.TableModel;
public class DBMessage extends AbstractController { public class DBMessage extends AbstractController {
public DBMessage() { } 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) { public void log(String servername, String channelname, String username, String datesent, String messageId, String message) {
ThreadManager.executor.submit(() -> { ThreadManager.executor.submit(() -> {
try {
database.insert("INSERT INTO log_message VALUES(?,?,?,?,?,?,?)", servername, channelname, username, datesent, messageId, message, null); 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) { public void logEdit(String messageId, String newMessage) {
ThreadManager.executor.submit(() -> { ThreadManager.executor.submit(() -> {
try {
database.update("UPDATE log_message SET editedMessage = ? WHERE messageId = ?", newMessage, messageId); database.update("UPDATE log_message SET editedMessage = ? WHERE messageId = ?", newMessage, messageId);
} catch (SQLException e) {
LogHandler.log(e);
}
}); });
} }
public MMessage getMessage(String messageId) { public MMessage getMessage(String messageId) {
try {
ResultSet rs = database.prepareAndExecute("SELECT * FROM log_message WHERE messageId = ?", messageId); ResultSet rs = database.prepareAndExecute("SELECT * FROM log_message WHERE messageId = ?", messageId);
Object[][] array = database.convertToArray(rs); MTableModel table = MysqlDatabase.convertToTableModel(rs);
if (database.getNbRow() != 0) { if (table.getNbRows() > 0) {
return new MMessage(array[1][0], array[1][1], array[1][2], array[1][3], array[1][4], array[1][5]); 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; return null;
} }
public ArrayList<MMessage> getMessagesFromUser(String username, String serverName, int max) { public ArrayList<MMessage> getMessagesFromUser(String username, String serverName, int max) {
ArrayList<MMessage> messages = new ArrayList<>(); ArrayList<MMessage> messages = new ArrayList<>();
try { ResultSet rs = database.prepareAndExecute("SELECT * FROM log_message WHERE userName = ? AND serverName = ? ORDER BY dateSent DESC LIMIT ?", username, serverName, max);
ResultSet rs = database.prepareAndExecute("SELECT * FROM log_message WHERE userName = ? AND serverName = ? ORDER BY dateSent DESC", username, serverName); MTableModel table = MysqlDatabase.convertToTableModel(rs);
Object[][] array = database.convertToArray(rs); if (table.getNbRows() > 0) {
if (database.getNbRow() != 0) { for (int row = 0; row < max; row++) {
for (int row = 1; 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)));
messages.add(new MMessage(array[row][0], array[row][1], array[row][2], array[row][3], array[row][4], array[row][5]));
} }
} }
} catch (SQLException e) {
LogHandler.log(e);
}
return messages; return messages;
} }
@@ -98,50 +84,7 @@ public class DBMessage extends AbstractController {
return "No message found"; 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 @Override
public String getControllerName() { public String getControllerName() {
@@ -21,7 +21,7 @@ public class DBSettings extends AbstractController {
MTableModel table = MysqlDatabase.convertToTableModel(rs); MTableModel table = MysqlDatabase.convertToTableModel(rs);
if (table.getNbRows() == 1) { if (table.getNbRows() == 1) {
value = table.getRow(0).get(0); value = table.getRowModel(0).getItem(0);
} }
success.accept(value); success.accept(value);