Added query result equality algorithm.
This commit is contained in:
parent
305ea4211c
commit
9efc91f82f
|
@ -121,7 +121,7 @@ public class DatabaseHelper {
|
||||||
// A result set is expected.
|
// A result set is expected.
|
||||||
window.appendOutput("Executing query:\n" + query);
|
window.appendOutput("Executing query:\n" + query);
|
||||||
|
|
||||||
QueryAction action = new QueryAction(statement.executeQuery(query));
|
QueryAction action = new QueryAction(statement.executeQuery(query), isQueryOrdered(query));
|
||||||
window.appendOutput(action.toString());
|
window.appendOutput(action.toString());
|
||||||
return action;
|
return action;
|
||||||
} else {
|
} else {
|
||||||
|
@ -162,4 +162,13 @@ public class DatabaseHelper {
|
||||||
return upper.startsWith("SELECT");
|
return upper.startsWith("SELECT");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determines if a query is ordered by something.
|
||||||
|
* @param query The query to check.
|
||||||
|
* @return True if the query makes use of the 'ORDER BY' clause.
|
||||||
|
*/
|
||||||
|
private static boolean isQueryOrdered(String query) {
|
||||||
|
return query.toUpperCase().contains("ORDER BY");
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -44,7 +44,7 @@
|
||||||
<component id="c2e9b" class="javax.swing.JTextArea" binding="templateTextArea">
|
<component id="c2e9b" class="javax.swing.JTextArea" binding="templateTextArea">
|
||||||
<constraints/>
|
<constraints/>
|
||||||
<properties>
|
<properties>
|
||||||
<text value="select * from primes;"/>
|
<text value="select id, value, other_value from primes;"/>
|
||||||
</properties>
|
</properties>
|
||||||
</component>
|
</component>
|
||||||
</children>
|
</children>
|
||||||
|
@ -89,7 +89,7 @@
|
||||||
<component id="17867" class="javax.swing.JTextArea" binding="testingTextArea">
|
<component id="17867" class="javax.swing.JTextArea" binding="testingTextArea">
|
||||||
<constraints/>
|
<constraints/>
|
||||||
<properties>
|
<properties>
|
||||||
<text value="select * from primes;"/>
|
<text value="select value, other_value, id from primes;"/>
|
||||||
</properties>
|
</properties>
|
||||||
</component>
|
</component>
|
||||||
</children>
|
</children>
|
||||||
|
@ -356,7 +356,7 @@
|
||||||
<component id="cc50b" class="javax.swing.JTextArea" binding="initializationTextArea">
|
<component id="cc50b" class="javax.swing.JTextArea" binding="initializationTextArea">
|
||||||
<constraints/>
|
<constraints/>
|
||||||
<properties>
|
<properties>
|
||||||
<text value="CREATE TABLE primes ( 	id SERIAL NOT NULL, 	value INT NOT NULL ); INSERT INTO primes(value) VALUES (2), (3), (5), (7), (11);" noi18n="true"/>
|
<text value="CREATE TABLE primes ( 	id SERIAL NOT NULL, 	value INT NOT NULL, 	other_value TEXT NOT NULL DEFAULT 'fuck' ); INSERT INTO primes(value, other_value) VALUES (2, 'nigger'), (3, 'cunt'), (5, 'piss'), (7, 'shit'), (11, 'spic');" noi18n="true"/>
|
||||||
</properties>
|
</properties>
|
||||||
</component>
|
</component>
|
||||||
</children>
|
</children>
|
||||||
|
|
|
@ -42,6 +42,9 @@ public class ExecutionLog {
|
||||||
ExecutionAction theirAction = otherLogActions.get(i);
|
ExecutionAction theirAction = otherLogActions.get(i);
|
||||||
System.out.println("My action: " + myAction + "\nTheir action: " + theirAction);
|
System.out.println("My action: " + myAction + "\nTheir action: " + theirAction);
|
||||||
System.out.println("\tEqual? " + myAction.equals(theirAction));
|
System.out.println("\tEqual? " + myAction.equals(theirAction));
|
||||||
|
if (!myAction.equals(theirAction)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -3,6 +3,8 @@ package nl.andrewlalis.log;
|
||||||
import java.sql.ResultSet;
|
import java.sql.ResultSet;
|
||||||
import java.sql.ResultSetMetaData;
|
import java.sql.ResultSetMetaData;
|
||||||
import java.sql.SQLException;
|
import java.sql.SQLException;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An action in which a query result set is returned. Note that SCROLL_INSENSITIVE statements must be used, otherwise
|
* An action in which a query result set is returned. Note that SCROLL_INSENSITIVE statements must be used, otherwise
|
||||||
|
@ -11,9 +13,11 @@ import java.sql.SQLException;
|
||||||
public class QueryAction extends ExecutionAction {
|
public class QueryAction extends ExecutionAction {
|
||||||
|
|
||||||
private ResultSet resultSet;
|
private ResultSet resultSet;
|
||||||
|
private boolean isOrdered;
|
||||||
|
|
||||||
public QueryAction(ResultSet resultSet) {
|
public QueryAction(ResultSet resultSet, boolean isOrdered) {
|
||||||
this.resultSet = resultSet;
|
this.resultSet = resultSet;
|
||||||
|
this.isOrdered = isOrdered;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -31,9 +35,124 @@ public class QueryAction extends ExecutionAction {
|
||||||
|
|
||||||
QueryAction otherAction = (QueryAction) other;
|
QueryAction otherAction = (QueryAction) other;
|
||||||
|
|
||||||
return true;
|
try {
|
||||||
|
ResultSetMetaData myMetaData = this.resultSet.getMetaData();
|
||||||
|
ResultSetMetaData theirMetaData = otherAction.resultSet.getMetaData();
|
||||||
|
|
||||||
|
if (myMetaData.getColumnCount() != theirMetaData.getColumnCount()) {
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int columnCount = myMetaData.getColumnCount();
|
||||||
|
|
||||||
|
List<Integer> myColumnsQueue = new ArrayList<>(columnCount);
|
||||||
|
List<Integer> theirColumnsQueue = new ArrayList<>(columnCount);
|
||||||
|
for (int i = 1; i <= columnCount; i++) {
|
||||||
|
myColumnsQueue.add(i);
|
||||||
|
theirColumnsQueue.add(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
while (!myColumnsQueue.isEmpty()) {
|
||||||
|
|
||||||
|
System.out.println(myColumnsQueue);
|
||||||
|
System.out.println(theirColumnsQueue);
|
||||||
|
|
||||||
|
// Pop the first column value.
|
||||||
|
int myColumn = myColumnsQueue.remove(0);
|
||||||
|
System.out.println("Testing my column " + myColumn);
|
||||||
|
|
||||||
|
// Find a column in their columns which has the same type as this one.
|
||||||
|
boolean columnMatchFound = false;
|
||||||
|
int failedAttempts = 0;
|
||||||
|
while (!theirColumnsQueue.isEmpty() && failedAttempts < myColumnsQueue.size() + 1) {
|
||||||
|
int theirColumn = theirColumnsQueue.remove(0);
|
||||||
|
System.out.println("\tWith their column " + theirColumn);
|
||||||
|
// Check if this column is of a compatible type.
|
||||||
|
if (myMetaData.getColumnType(myColumn) == theirMetaData.getColumnType(theirColumn)) {
|
||||||
|
System.out.println("\t\t+ Column type matches.");
|
||||||
|
// Now check if the data inside is a match.
|
||||||
|
List<String> myValues = new ArrayList<>();
|
||||||
|
List<String> theirValues = new ArrayList<>();
|
||||||
|
this.resultSet.beforeFirst();
|
||||||
|
otherAction.resultSet.beforeFirst();
|
||||||
|
|
||||||
|
// Iterate until one of the result sets goes past the last row.
|
||||||
|
while (true) {
|
||||||
|
this.resultSet.next();
|
||||||
|
otherAction.resultSet.next();
|
||||||
|
if (this.resultSet.isAfterLast() || otherAction.resultSet.isAfterLast()) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
// Collect this row's values for both my column and their column.
|
||||||
|
myValues.add(this.resultSet.getString(myColumn));
|
||||||
|
theirValues.add(otherAction.resultSet.getString(theirColumn));
|
||||||
|
}
|
||||||
|
// Check if both row counts are the same; i.e. both reach the end at the same time.
|
||||||
|
if (this.resultSet.isAfterLast() != otherAction.resultSet.isAfterLast()) {
|
||||||
|
System.out.println("\t\t- Result sets have differing row counts!");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Compare the values until an error.
|
||||||
|
boolean isMatch = true;
|
||||||
|
int index = 0;
|
||||||
|
for (String value : myValues) {
|
||||||
|
// If either query action is ordered, then require this.
|
||||||
|
if (this.isOrdered || otherAction.isOrdered) {
|
||||||
|
if (!(myValues.get(index).equals(theirValues.get(index)))) {
|
||||||
|
System.out.println("\t\t- Their column (" + theirColumn + ") does not contain my column's (" + myColumn + ") value of " + value);
|
||||||
|
isMatch = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (!theirValues.contains(value)) {
|
||||||
|
System.out.println("\t\t- Their column (" + theirColumn + ") does not contain my column's (" + myColumn + ") value of " + value);
|
||||||
|
isMatch = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
index++;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the column data matches.
|
||||||
|
if (isMatch) {
|
||||||
|
System.out.println("\t\t+ Columns Match! Ensuring my column " + myColumn +" and their column " + theirColumn + " are not added back to the queues.");
|
||||||
|
// Leave the loop knowing we found a column, without adding it back.
|
||||||
|
columnMatchFound = true;
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
System.out.println("\t\t- Columns do not match.");
|
||||||
|
// No column was found to match, so add it back to their queue.
|
||||||
|
theirColumnsQueue.add(theirColumn);
|
||||||
|
failedAttempts++;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
System.out.println("\t\t- Column types do not match.");
|
||||||
|
theirColumnsQueue.add(theirColumn);
|
||||||
|
failedAttempts++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// columnMatchFound == true when a column match has been found somewhere in other result set.
|
||||||
|
if (!columnMatchFound) {
|
||||||
|
System.out.println("\t\t- Could not find a matching column for my column " + myColumn);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we manage to get to the end without failing, return true.
|
||||||
|
return true;
|
||||||
|
|
||||||
|
} catch (SQLException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Translates the result set into a listing of column names and queries.
|
||||||
|
* @return The string representation of this QueryAction.
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
try {
|
try {
|
||||||
|
|
Loading…
Reference in New Issue