Use prepared sql statements
This commit is contained in:
parent
68125c7c92
commit
728d65f220
1 changed files with 174 additions and 105 deletions
|
@ -186,7 +186,6 @@ public class DatabaseController {
|
||||||
dropTables(() -> initTables(callback, errorCallback), errorCallback);
|
dropTables(() -> initTables(callback, errorCallback), errorCallback);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Fetches the list of users for which we already have a chat history
|
* Fetches the list of users for which we already have a chat history
|
||||||
*
|
*
|
||||||
|
@ -232,82 +231,6 @@ public class DatabaseController {
|
||||||
executor.start();
|
executor.start();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Adds a message to the database for this user.
|
|
||||||
* If the user does not exist, we create it.
|
|
||||||
*
|
|
||||||
* @param message The message to add to the database
|
|
||||||
* @param callback Function called when the request is done
|
|
||||||
* @param errorCallback The function to call on error
|
|
||||||
*/
|
|
||||||
public void addMessage(Message message, @Nullable DatabaseController.UpdateCallback callback, ErrorCallback errorCallback) {
|
|
||||||
// Insert the correspondent if not already in the database
|
|
||||||
Log.v(getClass().getSimpleName(), "Inserting correspondent into db... ");
|
|
||||||
addUser(message.getCorrespondent(), () -> {
|
|
||||||
// Handle messages containing a file
|
|
||||||
String filePath = "NULL";
|
|
||||||
if (message instanceof FileMessage) {
|
|
||||||
filePath = "'" + ((FileMessage) message).getPath() + "'";
|
|
||||||
}
|
|
||||||
|
|
||||||
String recipientId = message.getRecipient().id;
|
|
||||||
String senderId = message.getSender().id;
|
|
||||||
|
|
||||||
// Insert the new message
|
|
||||||
@Language("SQL") String sql = "INSERT INTO message " +
|
|
||||||
"(timestamp, sender, recipient, text, file_path) " +
|
|
||||||
"VALUES (" +
|
|
||||||
message.getDate().getTime() + ", " +
|
|
||||||
"'" + senderId + "', " +
|
|
||||||
"'" + recipientId + "', " +
|
|
||||||
"'" + message.getText() + "', " +
|
|
||||||
filePath +
|
|
||||||
")";
|
|
||||||
Log.v(getClass().getSimpleName(), "Inserting message into db... ");
|
|
||||||
UpdateExecutor executor = new UpdateExecutor(sql, callback, errorCallback);
|
|
||||||
executor.start();
|
|
||||||
|
|
||||||
}, errorCallback);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Inserts the given user if not existing
|
|
||||||
*
|
|
||||||
* @param user The user information to store
|
|
||||||
* @param callback The function to call on success
|
|
||||||
* @param errorCallback The function to call on error
|
|
||||||
*/
|
|
||||||
public void addUser(UserInformation user, @Nullable DatabaseController.UpdateCallback callback, ErrorCallback errorCallback) {
|
|
||||||
@Language("SQL") String sql;
|
|
||||||
if (user.getUsername() != null) {
|
|
||||||
sql = "INSERT OR IGNORE INTO user (id, username) " +
|
|
||||||
"VALUES ('" + user.id + "', '" + user.getUsername() + "')";
|
|
||||||
} else {
|
|
||||||
sql = "INSERT OR IGNORE INTO user (id) " +
|
|
||||||
"VALUES ('" + user.id + "')";
|
|
||||||
}
|
|
||||||
|
|
||||||
Log.v(getClass().getSimpleName(), "Adding user to db: " + user.id + " / " + user.getUsername());
|
|
||||||
UpdateExecutor executor = new UpdateExecutor(sql, callback, errorCallback);
|
|
||||||
executor.start();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void addCurrentUser(UserInformation user, @Nullable DatabaseController.UpdateCallback callback, ErrorCallback errorCallback) {
|
|
||||||
@Language("SQL") String sql;
|
|
||||||
if (user.getUsername() != null) {
|
|
||||||
sql = "INSERT OR IGNORE INTO current_user (id, username) " +
|
|
||||||
"VALUES ('" + user.id + "', '" + user.getUsername() + "')";
|
|
||||||
} else {
|
|
||||||
sql = "INSERT OR IGNORE INTO current_user (id) " +
|
|
||||||
"VALUES ('" + user.id + "')";
|
|
||||||
}
|
|
||||||
|
|
||||||
Log.v(getClass().getSimpleName(), "Adding current_user to db: " + user.id + " / " + user.getUsername());
|
|
||||||
UpdateExecutor executor = new UpdateExecutor(sql, callback, errorCallback);
|
|
||||||
executor.start();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the chat history for a given time frame
|
* Gets the chat history for a given time frame
|
||||||
*
|
*
|
||||||
|
@ -319,20 +242,14 @@ public class DatabaseController {
|
||||||
* @param errorCallback The function to call on error
|
* @param errorCallback The function to call on error
|
||||||
*/
|
*/
|
||||||
public void getChatHistory(UserInformation user1, UserInformation user2, Date from, Date to, HistoryCallback callback, ErrorCallback errorCallback) {
|
public void getChatHistory(UserInformation user1, UserInformation user2, Date from, Date to, HistoryCallback callback, ErrorCallback errorCallback) {
|
||||||
// TODO update to search in current_user table as well
|
|
||||||
@Language("SQL") String sql =
|
@Language("SQL") String sql =
|
||||||
"SELECT timestamp," +
|
"SELECT timestamp, sender, recipient, text, file_path " +
|
||||||
" sender," +
|
"FROM message WHERE (sender = ? OR recipient = ?)" +
|
||||||
" recipient," +
|
" AND timestamp > ? AND timestamp < ? " +
|
||||||
" text," +
|
|
||||||
" file_path " +
|
|
||||||
"FROM message WHERE (sender = '" + user1.id + "'" +
|
|
||||||
" OR recipient = '" + user1.id + "')" +
|
|
||||||
" AND timestamp > " + from.getTime() + " AND timestamp < " + to.getTime() + " " +
|
|
||||||
"ORDER BY timestamp";
|
"ORDER BY timestamp";
|
||||||
|
|
||||||
Log.v(getClass().getSimpleName(), "Fetching chat history from db... ");
|
Log.v(getClass().getSimpleName(), "Fetching chat history from db... ");
|
||||||
QueryExecutor executor = new QueryExecutor(sql, res -> {
|
executeGetChatHistory(user1, from, to, sql, res -> {
|
||||||
ArrayList<Message> chatHistory = new ArrayList<>();
|
ArrayList<Message> chatHistory = new ArrayList<>();
|
||||||
while (res.next()) {
|
while (res.next()) {
|
||||||
Date date = new Date(res.getTimestamp("timestamp").getTime());
|
Date date = new Date(res.getTimestamp("timestamp").getTime());
|
||||||
|
@ -365,20 +282,141 @@ public class DatabaseController {
|
||||||
Log.v(getClass().getSimpleName(), chatHistory.size() + " messages fetched");
|
Log.v(getClass().getSimpleName(), chatHistory.size() + " messages fetched");
|
||||||
callback.onHistoryFetched(chatHistory);
|
callback.onHistoryFetched(chatHistory);
|
||||||
}, errorCallback);
|
}, errorCallback);
|
||||||
|
}
|
||||||
|
|
||||||
executor.start();
|
private void executeGetChatHistory(UserInformation user, Date from, Date to, @Language("SQL") String sql, QueryCallback callback, ErrorCallback errorCallback) {
|
||||||
|
try {
|
||||||
|
PreparedStatement preparedStatement = connection.prepareStatement(sql);
|
||||||
|
preparedStatement.setString(1, user.id);
|
||||||
|
preparedStatement.setString(2, user.id);
|
||||||
|
preparedStatement.setLong(3, from.getTime());
|
||||||
|
preparedStatement.setLong(4, to.getTime());
|
||||||
|
QueryExecutor executor = new QueryExecutor(
|
||||||
|
preparedStatement,
|
||||||
|
callback,
|
||||||
|
errorCallback);
|
||||||
|
executor.start();
|
||||||
|
} catch (SQLException e) {
|
||||||
|
Log.e(this.getClass().getSimpleName(), "Could not prepare statement: ", e);
|
||||||
|
errorCallback.onError(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds a message to the database for this user.
|
||||||
|
* If the user does not exist, we create it.
|
||||||
|
*
|
||||||
|
* @param message The message to add to the database
|
||||||
|
* @param callback Function called when the request is done
|
||||||
|
* @param errorCallback The function to call on error
|
||||||
|
*/
|
||||||
|
public void addMessage(Message message, @Nullable DatabaseController.UpdateCallback callback, ErrorCallback errorCallback) {
|
||||||
|
// Insert the correspondent if not already in the database
|
||||||
|
Log.v(getClass().getSimpleName(), "Inserting correspondent into db... ");
|
||||||
|
addUser(message.getCorrespondent(), () -> {
|
||||||
|
// Handle messages containing a file
|
||||||
|
String filePath = null;
|
||||||
|
if (message instanceof FileMessage) {
|
||||||
|
filePath = "'" + ((FileMessage) message).getPath() + "'";
|
||||||
|
}
|
||||||
|
@Language("SQL") String sql = "INSERT INTO message " +
|
||||||
|
"(timestamp, sender, recipient, text, file_path) VALUES (?, ?, ?, ?, ?)";
|
||||||
|
Log.v(getClass().getSimpleName(), "Inserting message into db... ");
|
||||||
|
executeAddMessage(message, filePath, sql, callback, errorCallback);
|
||||||
|
}, errorCallback);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void executeAddMessage(Message message, String filePath, @Language("SQL") String sql, @Nullable UpdateCallback callback, ErrorCallback errorCallback) {
|
||||||
|
try {
|
||||||
|
PreparedStatement preparedStatement = connection.prepareStatement(sql);
|
||||||
|
preparedStatement.setLong(1, message.getDate().getTime());
|
||||||
|
preparedStatement.setString(2, message.getSender().id);
|
||||||
|
preparedStatement.setString(3, message.getRecipient().id);
|
||||||
|
preparedStatement.setString(4, message.getText());
|
||||||
|
preparedStatement.setString(5, filePath);
|
||||||
|
UpdateExecutor executor = new UpdateExecutor(
|
||||||
|
preparedStatement,
|
||||||
|
callback,
|
||||||
|
errorCallback);
|
||||||
|
executor.start();
|
||||||
|
} catch (SQLException e) {
|
||||||
|
Log.e(this.getClass().getSimpleName(), "Could not prepare statement: ", e);
|
||||||
|
errorCallback.onError(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Inserts the given user if not existing
|
||||||
|
*
|
||||||
|
* @param user The user information to store
|
||||||
|
* @param callback The function to call on success
|
||||||
|
* @param errorCallback The function to call on error
|
||||||
|
*/
|
||||||
|
public void addUser(UserInformation user, @Nullable DatabaseController.UpdateCallback callback, ErrorCallback errorCallback) {
|
||||||
|
@Language("SQL") String sql;
|
||||||
|
if (user.getUsername() != null) {
|
||||||
|
sql = "INSERT OR IGNORE INTO user (id, username) VALUES (?, ?)";
|
||||||
|
} else {
|
||||||
|
sql = "INSERT OR IGNORE INTO user (id) VALUES (?)";
|
||||||
|
}
|
||||||
|
Log.v(getClass().getSimpleName(), "Adding user to db: " + user.id + " / " + user.getUsername());
|
||||||
|
executeAddUser(user, sql, callback, errorCallback);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addCurrentUser(UserInformation user, @Nullable DatabaseController.UpdateCallback callback, ErrorCallback errorCallback) {
|
||||||
|
@Language("SQL") String sql;
|
||||||
|
if (user.getUsername() != null) {
|
||||||
|
sql = "INSERT OR IGNORE INTO current_user (id, username) VALUES (?, ?)";
|
||||||
|
} else {
|
||||||
|
sql = "INSERT OR IGNORE INTO current_user (id) VALUES (?)";
|
||||||
|
}
|
||||||
|
Log.v(getClass().getSimpleName(), "Adding current_user to db: " + user.id + " / " + user.getUsername());
|
||||||
|
executeAddUser(user, sql, callback, errorCallback);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void executeAddUser(UserInformation user, @Language("SQL") String sql, @Nullable UpdateCallback callback, ErrorCallback errorCallback) {
|
||||||
|
try {
|
||||||
|
PreparedStatement preparedStatement = connection.prepareStatement(sql);
|
||||||
|
preparedStatement.setString(1, user.id);
|
||||||
|
if (user.getUsername() != null) {
|
||||||
|
preparedStatement.setString(2, user.getUsername());
|
||||||
|
}
|
||||||
|
UpdateExecutor executor = new UpdateExecutor(
|
||||||
|
preparedStatement,
|
||||||
|
callback,
|
||||||
|
errorCallback);
|
||||||
|
executor.start();
|
||||||
|
} catch (SQLException e) {
|
||||||
|
Log.e(this.getClass().getSimpleName(), "Could not prepare statement: ", e);
|
||||||
|
errorCallback.onError(e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void updateUsername(UserInformation user, @Nullable DatabaseController.UpdateCallback callback, ErrorCallback errorCallback) {
|
public void updateUsername(UserInformation user, @Nullable DatabaseController.UpdateCallback callback, ErrorCallback errorCallback) {
|
||||||
@Language("SQL") String sql = "UPDATE user SET username = '" + user.getUsername() + "' where id = '" + user.id + "'";
|
@Language("SQL") String sql = "UPDATE user SET username = ? where id = ?";
|
||||||
UpdateExecutor executor = new UpdateExecutor(sql, callback, errorCallback);
|
executeUsernameUpdate(user, sql, callback, errorCallback);
|
||||||
executor.start();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void updateCurrentUsername(UserInformation user, @Nullable DatabaseController.UpdateCallback callback, ErrorCallback errorCallback) {
|
public void updateCurrentUsername(UserInformation user, @Nullable DatabaseController.UpdateCallback callback, ErrorCallback errorCallback) {
|
||||||
@Language("SQL") String sql = "UPDATE current_user SET username = '" + user.getUsername() + "' where id = '" + user.id + "'";
|
@Language("SQL") String sql = "UPDATE current_user SET username = ? where id = ?";
|
||||||
UpdateExecutor executor = new UpdateExecutor(sql, callback, errorCallback);
|
executeUsernameUpdate(user, sql, callback, errorCallback);
|
||||||
executor.start();
|
}
|
||||||
|
|
||||||
|
private void executeUsernameUpdate(UserInformation user, @Language("SQL") String sql, @Nullable UpdateCallback callback, ErrorCallback errorCallback) {
|
||||||
|
try {
|
||||||
|
PreparedStatement preparedStatement = connection.prepareStatement(sql);
|
||||||
|
preparedStatement.setString(1, user.getUsername());
|
||||||
|
preparedStatement.setString(2, user.id);
|
||||||
|
UpdateExecutor executor = new UpdateExecutor(
|
||||||
|
preparedStatement,
|
||||||
|
callback,
|
||||||
|
errorCallback);
|
||||||
|
executor.start();
|
||||||
|
} catch (SQLException e) {
|
||||||
|
Log.e(this.getClass().getSimpleName(), "Could not prepare statement: ", e);
|
||||||
|
errorCallback.onError(e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public interface UsersCallback {
|
public interface UsersCallback {
|
||||||
|
@ -389,11 +427,6 @@ public class DatabaseController {
|
||||||
void onFetched(UserInformation user);
|
void onFetched(UserInformation user);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public interface UsernameCallback {
|
|
||||||
void onUsernameFetched(String username);
|
|
||||||
}
|
|
||||||
|
|
||||||
public interface HistoryCallback {
|
public interface HistoryCallback {
|
||||||
void onHistoryFetched(ArrayList<Message> history);
|
void onHistoryFetched(ArrayList<Message> history);
|
||||||
}
|
}
|
||||||
|
@ -408,6 +441,7 @@ public class DatabaseController {
|
||||||
|
|
||||||
private class UpdateExecutor extends Thread {
|
private class UpdateExecutor extends Thread {
|
||||||
private final String sqlQuery;
|
private final String sqlQuery;
|
||||||
|
private final PreparedStatement preparedStatement;
|
||||||
private final UpdateCallback callback;
|
private final UpdateCallback callback;
|
||||||
private final ErrorCallback errorCallback;
|
private final ErrorCallback errorCallback;
|
||||||
|
|
||||||
|
@ -419,18 +453,33 @@ public class DatabaseController {
|
||||||
* @param errorCallback The function to call on error
|
* @param errorCallback The function to call on error
|
||||||
*/
|
*/
|
||||||
public UpdateExecutor(@Language("SQL") String sqlQuery, @Nullable DatabaseController.UpdateCallback callback, ErrorCallback errorCallback) {
|
public UpdateExecutor(@Language("SQL") String sqlQuery, @Nullable DatabaseController.UpdateCallback callback, ErrorCallback errorCallback) {
|
||||||
|
this.preparedStatement = null;
|
||||||
this.sqlQuery = sqlQuery;
|
this.sqlQuery = sqlQuery;
|
||||||
this.callback = callback;
|
this.callback = callback;
|
||||||
this.errorCallback = errorCallback;
|
this.errorCallback = errorCallback;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public UpdateExecutor(PreparedStatement preparedStatement, @Nullable DatabaseController.UpdateCallback callback, ErrorCallback errorCallback) {
|
||||||
|
this.preparedStatement = preparedStatement;
|
||||||
|
this.sqlQuery = null;
|
||||||
|
this.callback = callback;
|
||||||
|
this.errorCallback = errorCallback;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
try {
|
try {
|
||||||
Statement statement = connection.createStatement();
|
int rowsModified;
|
||||||
final int rowsModified = statement.executeUpdate(sqlQuery);
|
if (preparedStatement == null) {
|
||||||
|
Statement statement = connection.createStatement();
|
||||||
|
rowsModified = statement.executeUpdate(sqlQuery);
|
||||||
|
statement.close();
|
||||||
|
} else {
|
||||||
|
rowsModified = preparedStatement.executeUpdate();
|
||||||
|
preparedStatement.close();
|
||||||
|
}
|
||||||
Log.v(getClass().getSimpleName(), rowsModified + " rows modified");
|
Log.v(getClass().getSimpleName(), rowsModified + " rows modified");
|
||||||
statement.close();
|
|
||||||
if (callback != null) {
|
if (callback != null) {
|
||||||
callback.onUpdateExecuted();
|
callback.onUpdateExecuted();
|
||||||
}
|
}
|
||||||
|
@ -443,6 +492,7 @@ public class DatabaseController {
|
||||||
|
|
||||||
private class QueryExecutor extends Thread {
|
private class QueryExecutor extends Thread {
|
||||||
private final String sqlQuery;
|
private final String sqlQuery;
|
||||||
|
private final PreparedStatement preparedStatement;
|
||||||
private final QueryCallback callback;
|
private final QueryCallback callback;
|
||||||
private final ErrorCallback errorCallback;
|
private final ErrorCallback errorCallback;
|
||||||
|
|
||||||
|
@ -454,21 +504,40 @@ public class DatabaseController {
|
||||||
* @param errorCallback The function to call on error
|
* @param errorCallback The function to call on error
|
||||||
*/
|
*/
|
||||||
public QueryExecutor(@Language("SQL") String sqlQuery, @Nullable QueryCallback callback, ErrorCallback errorCallback) {
|
public QueryExecutor(@Language("SQL") String sqlQuery, @Nullable QueryCallback callback, ErrorCallback errorCallback) {
|
||||||
|
this.preparedStatement = null;
|
||||||
this.sqlQuery = sqlQuery;
|
this.sqlQuery = sqlQuery;
|
||||||
this.callback = callback;
|
this.callback = callback;
|
||||||
this.errorCallback = errorCallback;
|
this.errorCallback = errorCallback;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public QueryExecutor(PreparedStatement preparedStatement, @Nullable QueryCallback callback, ErrorCallback errorCallback) {
|
||||||
|
this.preparedStatement = preparedStatement;
|
||||||
|
this.sqlQuery = null;
|
||||||
|
this.callback = callback;
|
||||||
|
this.errorCallback = errorCallback;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
try {
|
try {
|
||||||
Statement statement = connection.createStatement();
|
Statement statement = null;
|
||||||
final ResultSet resultSet = statement.executeQuery(sqlQuery);
|
final ResultSet resultSet;
|
||||||
|
if (preparedStatement == null) {
|
||||||
|
statement = connection.createStatement();
|
||||||
|
resultSet = statement.executeQuery(sqlQuery);
|
||||||
|
} else {
|
||||||
|
resultSet = preparedStatement.executeQuery();
|
||||||
|
}
|
||||||
if (callback != null) {
|
if (callback != null) {
|
||||||
callback.onQueryExecuted(resultSet);
|
callback.onQueryExecuted(resultSet);
|
||||||
}
|
}
|
||||||
resultSet.close();
|
resultSet.close();
|
||||||
statement.close();
|
if (statement != null) {
|
||||||
|
statement.close();
|
||||||
|
}
|
||||||
|
if (preparedStatement != null) {
|
||||||
|
preparedStatement.close();
|
||||||
|
}
|
||||||
} catch (SQLException e) {
|
} catch (SQLException e) {
|
||||||
Log.e(this.getClass().getSimpleName(), "Error executing update: ", e);
|
Log.e(this.getClass().getSimpleName(), "Error executing update: ", e);
|
||||||
errorCallback.onError(e);
|
errorCallback.onError(e);
|
||||||
|
|
Loading…
Reference in a new issue