Removed logic for equality of query actions for now.
This commit is contained in:
parent
d6e84f47e7
commit
305ea4211c
|
@ -1,5 +1,6 @@
|
|||
package nl.andrewlalis;
|
||||
|
||||
import nl.andrewlalis.log.ExecutionAction;
|
||||
import nl.andrewlalis.log.ExecutionLog;
|
||||
import nl.andrewlalis.log.QueryAction;
|
||||
import nl.andrewlalis.log.UpdateAction;
|
||||
|
@ -8,6 +9,8 @@ import java.sql.*;
|
|||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import static nl.andrewlalis.Window.*;
|
||||
|
||||
public class DatabaseHelper {
|
||||
|
||||
private String host;
|
||||
|
@ -16,24 +19,60 @@ public class DatabaseHelper {
|
|||
private String password;
|
||||
private Window window;
|
||||
|
||||
private ExecutionLog executionLog;
|
||||
|
||||
public DatabaseHelper(String host, int port, String user, String password, Window window) {
|
||||
this.host = host;
|
||||
this.port = port;
|
||||
this.user = user;
|
||||
this.password = password;
|
||||
this.window = window;
|
||||
}
|
||||
|
||||
this.executionLog = new ExecutionLog();
|
||||
public void executeSQLComparison(String initializationSQL, String templateSQL, String testingSQL) {
|
||||
// Run the database code in a separate thread to update the UI quickly.
|
||||
Thread t = new Thread(() -> {
|
||||
// Setup both databases.
|
||||
this.window.appendOutput("Dropping old databases and re-creating them...");
|
||||
this.window.indentOutput();
|
||||
String dropDatabases = "DROP DATABASE " + DB_TEMPLATE + "; " +
|
||||
"DROP DATABASE " + DB_TESTING + ";";
|
||||
String createDatabases = "CREATE DATABASE " + DB_TEMPLATE + "; " +
|
||||
"CREATE DATABASE " + DB_TESTING + ";";
|
||||
this.executeQueries("", dropDatabases);
|
||||
this.executeQueries("", createDatabases);
|
||||
this.window.unindentOutput();
|
||||
|
||||
// Run initialization script on each database.
|
||||
this.window.appendOutput("Running initialization SQL on databases...");
|
||||
this.window.indentOutput();
|
||||
this.executeQueries(DB_TEMPLATE, initializationSQL);
|
||||
this.executeQueries(DB_TESTING, initializationSQL);
|
||||
this.window.unindentOutput();
|
||||
|
||||
// TESTING SQL HERE
|
||||
|
||||
// Template-specific output.
|
||||
this.window.setOutputChannel(OUTPUT_TEMPLATE);
|
||||
ExecutionLog templateLog = this.executeQueries(DB_TEMPLATE, templateSQL);
|
||||
|
||||
// Testing-specific output.
|
||||
this.window.setOutputChannel(OUTPUT_TESTING);
|
||||
ExecutionLog testingLog = this.executeQueries(DB_TESTING, testingSQL);
|
||||
|
||||
// Output results.
|
||||
this.window.setOutputChannel(OUTPUT_GENERAL);
|
||||
this.window.appendOutput("Execution test result: " + templateLog.equals(testingLog));
|
||||
});
|
||||
t.start();
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes possibly many queries which are contained in one string.
|
||||
* @param database The database name to connect to, or an empty string to connect to the user's database.
|
||||
* @param queriesString The string of queries.
|
||||
* @return The execution log from this series of queries.
|
||||
*/
|
||||
public void executeQueries(String database, String queriesString) {
|
||||
public ExecutionLog executeQueries(String database, String queriesString) {
|
||||
ExecutionLog executionLog = new ExecutionLog();
|
||||
String url = String.format(
|
||||
"jdbc:postgresql://%s:%4d/%s?user=%s&password=%s",
|
||||
host,
|
||||
|
@ -54,7 +93,7 @@ public class DatabaseHelper {
|
|||
|
||||
for (String query : queries) {
|
||||
try {
|
||||
executeQuery(query, st);
|
||||
executionLog.recordAction(executeQuery(query, st));
|
||||
} catch (SQLException e) {
|
||||
window.appendOutput("Exception while executing statement: " + e.getMessage());
|
||||
}
|
||||
|
@ -67,27 +106,30 @@ public class DatabaseHelper {
|
|||
window.appendOutput("Unexpected SQL Exception occurred. URL:\n" + url + "\n\tException: " + e.getMessage() + "\n\tSQL State: " + e.getSQLState());
|
||||
window.setOutputChannel(previousChannel);
|
||||
}
|
||||
|
||||
return executionLog;
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes a single query and outputs the results.
|
||||
* @param query The query to execute. Must be only one query in the string.
|
||||
* @param statement The statement used to execute the query.
|
||||
* @return The execution action which was done by executing this query.
|
||||
*/
|
||||
private void executeQuery(String query, Statement statement) throws SQLException {
|
||||
private ExecutionAction executeQuery(String query, Statement statement) throws SQLException {
|
||||
if (isSQLStatementQuery(query)) {
|
||||
// A result set is expected.
|
||||
window.appendOutput("Executing query:\n" + query);
|
||||
|
||||
QueryAction action = new QueryAction(statement.executeQuery(query));
|
||||
window.appendOutput(action.toString());
|
||||
this.executionLog.recordAction(action);
|
||||
return action;
|
||||
} else {
|
||||
// A result set is not expected.
|
||||
window.appendOutput("Executing update:\n" + query);
|
||||
UpdateAction action = new UpdateAction(statement.executeUpdate(query), query);
|
||||
window.appendOutput(action.toString());
|
||||
this.executionLog.recordAction(action);
|
||||
return action;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package nl.andrewlalis;
|
||||
|
||||
import javax.swing.*;
|
||||
import javax.xml.crypto.Data;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
|
||||
|
@ -69,37 +70,8 @@ public class Window extends JFrame {
|
|||
String password = this.passwordTextField.getText();
|
||||
String initialization = this.initializationTextArea.getText();
|
||||
|
||||
// Run the database code in a separate thread to update the UI quickly.
|
||||
Thread t = new Thread(() -> {
|
||||
DatabaseHelper dbHelper = new DatabaseHelper(host, port, user, password, this);
|
||||
|
||||
// Setup both databases.
|
||||
this.appendOutput("Dropping old databases and re-creating them...");
|
||||
this.indentOutput();
|
||||
String dropDatabases = "DROP DATABASE " + DB_TEMPLATE + "; " +
|
||||
"DROP DATABASE " + DB_TESTING + ";";
|
||||
String createDatabases = "CREATE DATABASE " + DB_TEMPLATE + "; " +
|
||||
"CREATE DATABASE " + DB_TESTING + ";";
|
||||
dbHelper.executeQueries("", dropDatabases);
|
||||
dbHelper.executeQueries("", createDatabases);
|
||||
this.unindentOutput();
|
||||
|
||||
// Run initialization script on each database.
|
||||
this.appendOutput("Running initialization SQL on databases...");
|
||||
this.indentOutput();
|
||||
dbHelper.executeQueries(DB_TEMPLATE, initialization);
|
||||
dbHelper.executeQueries(DB_TESTING, initialization);
|
||||
this.unindentOutput();
|
||||
|
||||
// Template-specific output.
|
||||
this.setOutputChannel(OUTPUT_TEMPLATE);
|
||||
dbHelper.executeQueries(DB_TEMPLATE, this.templateTextArea.getText());
|
||||
|
||||
// Testing-specific output.
|
||||
this.setOutputChannel(OUTPUT_TESTING);
|
||||
dbHelper.executeQueries(DB_TESTING, this.testingTextArea.getText());
|
||||
});
|
||||
t.start();
|
||||
DatabaseHelper helper = new DatabaseHelper(host, port, user, password, this);
|
||||
helper.executeSQLComparison(initialization, this.templateTextArea.getText(), this.testingTextArea.getText());
|
||||
}
|
||||
|
||||
int getOutputChannel() {
|
||||
|
|
|
@ -31,15 +31,17 @@ public class ExecutionLog {
|
|||
ExecutionLog otherLog = (ExecutionLog) other;
|
||||
|
||||
if (otherLog.getActions().size() != this.getActions().size()) {
|
||||
System.out.println("Size difference in logs.");
|
||||
return false;
|
||||
}
|
||||
|
||||
List<ExecutionAction> otherLogActions = otherLog.getActions();
|
||||
|
||||
for (int i = 0; i < this.getActions().size(); i++) {
|
||||
if (!this.getActions().get(i).equals(otherLogActions.get(i))) {
|
||||
return false;
|
||||
}
|
||||
ExecutionAction myAction = this.getActions().get(i);
|
||||
ExecutionAction theirAction = otherLogActions.get(i);
|
||||
System.out.println("My action: " + myAction + "\nTheir action: " + theirAction);
|
||||
System.out.println("\tEqual? " + myAction.equals(theirAction));
|
||||
}
|
||||
|
||||
return true;
|
||||
|
|
|
@ -3,97 +3,58 @@ package nl.andrewlalis.log;
|
|||
import java.sql.ResultSet;
|
||||
import java.sql.ResultSetMetaData;
|
||||
import java.sql.SQLException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* An action in which a query result set is returned.
|
||||
* An action in which a query result set is returned. Note that SCROLL_INSENSITIVE statements must be used, otherwise
|
||||
* an SQL exception will be thrown at each attempt to go through the result set.
|
||||
*/
|
||||
public class QueryAction extends ExecutionAction {
|
||||
|
||||
private String[] columns;
|
||||
private String[][] values;
|
||||
private ResultSet resultSet;
|
||||
|
||||
public QueryAction(ResultSet resultSet) throws SQLException {
|
||||
// Read the columns into this object's memory.
|
||||
ResultSetMetaData metaData = resultSet.getMetaData();
|
||||
this.columns = new String[metaData.getColumnCount()];
|
||||
for (int i = 0; i < metaData.getColumnCount(); i++) {
|
||||
columns[i] = metaData.getColumnName(i + 1);
|
||||
}
|
||||
|
||||
resultSet.absolute(1);// Ensure that this result set cursor is at the beginning.
|
||||
|
||||
// Read the rows into this object's memory.
|
||||
List<String[]> rows = new ArrayList<>();
|
||||
while (resultSet.next()) {
|
||||
String[] row = new String[columns.length];
|
||||
for (int i = 0; i < columns.length; i++) {
|
||||
row[i] = resultSet.getString(i + 1);
|
||||
}
|
||||
rows.add(row);
|
||||
}
|
||||
this.values = new String[rows.size()][];
|
||||
rows.toArray(this.values);
|
||||
}
|
||||
|
||||
public String[] getColumns() {
|
||||
return this.columns;
|
||||
}
|
||||
|
||||
public String[][] getValues() {
|
||||
return this.values;
|
||||
public QueryAction(ResultSet resultSet) {
|
||||
this.resultSet = resultSet;
|
||||
}
|
||||
|
||||
/**
|
||||
* The algorithm to determine if two query sets are equivalent is as follows:
|
||||
* If all of the values of one column contain all of the values of another column, then these two columns must
|
||||
* almost certainly represent the same value, even if in the wrong order.
|
||||
* @param other The other object to check equality with.
|
||||
* @return True if the two query sets are equivalent, or false otherwise.
|
||||
*/
|
||||
@Override
|
||||
public boolean equals(Object other) {
|
||||
if (!(other instanceof QueryAction)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
QueryAction action = (QueryAction) other;
|
||||
|
||||
if (action.getColumns().length != this.columns.length || action.getValues().length != this.values.length) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (int i = 0; i < this.values.length; i++) {
|
||||
Map<String, String> thisColumnValues = new HashMap<>();
|
||||
Map<String, String> otherColumnValues = new HashMap<>();
|
||||
for (int k = 0; k < this.values[i].length; k++) {
|
||||
thisColumnValues.put(this.columns[k], this.values[i][k]);
|
||||
otherColumnValues.put(action.getColumns()[k], action.getValues()[i][k]);
|
||||
}
|
||||
for (String column : this.columns) {
|
||||
if (thisColumnValues.get(column).equals(otherColumnValues.get(column))) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
QueryAction otherAction = (QueryAction) other;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
// First build a list of columns.
|
||||
try {
|
||||
this.resultSet.absolute(1);
|
||||
ResultSetMetaData metaData = this.resultSet.getMetaData();
|
||||
int columnCount = metaData.getColumnCount();
|
||||
|
||||
StringBuilder sb = new StringBuilder("Query Result:\n\tColumns: (");
|
||||
for (int i = 0; i < this.columns.length; i++) {
|
||||
sb.append(this.columns[i]);
|
||||
if (i < this.columns.length - 1) {
|
||||
for (int i = 0; i < columnCount; i++) {
|
||||
sb.append(metaData.getColumnName(i + 1));
|
||||
if (i < columnCount - 1) {
|
||||
sb.append(", ");
|
||||
}
|
||||
}
|
||||
sb.append(")\n\tValues:\n");
|
||||
|
||||
// Then build a list of the rows.
|
||||
for (int i = 0; i < this.values.length; i++) {
|
||||
while (this.resultSet.next()) {
|
||||
sb.append("\t(");
|
||||
for (int k = 0; k < this.values[i].length; k++) {
|
||||
sb.append(this.values[i][k]);
|
||||
if (k < this.values[i].length - 1) {
|
||||
for (int i = 0; i < columnCount; i++) {
|
||||
sb.append(this.resultSet.getString(i + 1));
|
||||
if (i < columnCount - 1) {
|
||||
sb.append(", ");
|
||||
}
|
||||
}
|
||||
|
@ -101,6 +62,11 @@ public class QueryAction extends ExecutionAction {
|
|||
}
|
||||
|
||||
return sb.toString();
|
||||
|
||||
} catch (SQLException e) {
|
||||
e.printStackTrace();
|
||||
return "SQLException; Please use a SCROLL_INSENSITIVE statement when executing the query.";
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue