Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

handling of join queries without WHERE/ON clauses #1145

Merged
merged 10 commits into from
Dec 23, 2024
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package org.evomaster.client.java.distance.heuristics;

import java.util.Arrays;

public class TruthnessUtils {

/**
Expand All @@ -13,7 +15,7 @@ public static double normalizeValue(double v) {
throw new IllegalArgumentException("Negative value: " + v);
}

if(Double.isInfinite(v) || v == Double.MAX_VALUE){
if (Double.isInfinite(v) || v == Double.MAX_VALUE) {
return 1d;
}

Expand All @@ -26,7 +28,6 @@ public static double normalizeValue(double v) {
}



public static Truthness getEqualityTruthness(int a, int b) {
double distance = DistanceHelper.getDistanceToEquality(a, b);
double normalizedDistance = normalizeValue(distance);
Expand All @@ -45,6 +46,15 @@ public static Truthness getEqualityTruthness(long a, long b) {
);
}


public static Truthness getLessThanTruthness(double a, double b) {
double distance = DistanceHelper.getDistanceToEquality(a, b);
return new Truthness(
a < b ? 1d : 1d / (1.1d + distance),
a >= b ? 1d : 1d / (1.1d + distance)
);
}

public static Truthness getLessThanTruthness(long a, long b) {
double distance = DistanceHelper.getDistanceToEquality(a, b);
return new Truthness(
Expand Down Expand Up @@ -79,4 +89,58 @@ public static Truthness getTruthnessToEmpty(int len) {
}
return t;
}

public static Truthness buildAndAggregationTruthness(Truthness... truthnesses) {
double averageOfTrue = averageOfTrue(truthnesses);
double falseOrAverageFalse = falseOrAverageFalse(truthnesses);
return new Truthness(averageOfTrue, falseOrAverageFalse);
}

private static double averageOfTrue(Truthness... truthnesses) {
checkValidTruthnesses(truthnesses);
double[] getOfTrueValues = Arrays.stream(truthnesses).mapToDouble(Truthness::getOfTrue)
.toArray();
return average(getOfTrueValues);
}

private static void checkValidTruthnesses(Truthness[] truthnesses) {
if (truthnesses == null || truthnesses.length == 0 || Arrays.stream(truthnesses).anyMatch(e -> e == null)) {
throw new IllegalArgumentException("null or empty Truthness instance");
}
}

private static double average(double... values) {
if (values == null || values.length == 0) {
throw new IllegalArgumentException("null or empty values");
}
double total = 0.0;
for (double v : values) {
total += v;
}
return total / values.length;
}

private static double averageOfFalse(Truthness... truthnesses) {
checkValidTruthnesses(truthnesses);
double[] getOfFalseValues = Arrays.stream(truthnesses).mapToDouble(Truthness::getOfFalse)
.toArray();
return average(getOfFalseValues);
}

private static double falseOrAverageFalse(Truthness... truthnesses) {
checkValidTruthnesses(truthnesses);
if (Arrays.stream(truthnesses).anyMatch(t -> t.isFalse())) {
return 1.0d;
} else {
return averageOfFalse(truthnesses);
}
}

public static Truthness buildScaledTruthness(double base, double ofTrueToScale) {
final double scaledOfTrue = DistanceHelper.scaleHeuristicWithBase(ofTrueToScale, base);
final double ofFalse = 1.0d;
return new Truthness(scaledOfTrue, ofFalse);
}


}
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ public QueryResult(List<VariableDescriptor> variableDescriptorList) {
variableDescriptors.addAll(variableDescriptorList);
}



/**
* WARNING: Constructor only needed for testing
*
Expand Down Expand Up @@ -173,4 +175,17 @@ public QueryResultDto toDto(){

return dto;
}

/**
* Retrieves the table name of this queryResult.
*
* @return the table name of the first {@code VariableDescriptor} in the {@code variableDescriptors} list.
* @throws IllegalStateException if the {@code variableDescriptors} list is empty.
*/
public String getTableName() {
if (variableDescriptors.isEmpty()) {
throw new IllegalStateException("No variable descriptors found");
}
return variableDescriptors.get(0).getTableName();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
package org.evomaster.client.java.sql;

import java.util.Map;
import java.util.TreeMap;

/**
* Represents a collection of query results mapped to table names,
* with support for both named and virtual tables.
*
* This class allows case-sensitive or case-insensitive handling of table names
* and provides mechanisms to add, retrieve, and manage query results.
*
*/
public class QueryResultSet {
jgaleotti marked this conversation as resolved.
Show resolved Hide resolved

/**
* A map storing query results associated with table names.
* The keys are table names, and the values are {@link QueryResult} objects.
*/
private final Map<String, QueryResult> queryResults;

/**
* Indicates whether table name comparisons are case-sensitive.
*/
private final boolean isCaseSensitive;

/**
* Stores the query result for a virtual table, if any.
*/
private QueryResult queryResultForVirtualTable;

public QueryResultSet() {
this(true);
}

/**
* Creates a new {@code QueryResultSet}.
*
* @param isCaseSensitive whether table name comparisons should be case-sensitive
*/
public QueryResultSet(boolean isCaseSensitive) {
queryResults = new TreeMap<>(isCaseSensitive ? null : String.CASE_INSENSITIVE_ORDER);
this.isCaseSensitive = isCaseSensitive;
}

/**
* Returns whether table name comparisons are case-sensitive.
*
* @return {@code true} if comparisons are case-sensitive, {@code false} otherwise
*/
public boolean isCaseSensitive() {
return isCaseSensitive;
}

/**
* Adds a query result to the result set.
* <p>
* If the query result corresponds to a named table, it is stored in the map.
* If it corresponds to a virtual table, it is stored separately.
* Throws an exception if a duplicate table (named or virtual) is added.
* </p>
*
* @param queryResult the query result to add
* @throws IllegalArgumentException if the table name already exists in the set
*/
public void addQueryResult(QueryResult queryResult) {
String tableName = queryResult.seeVariableDescriptors()
.stream()
.findFirst()
.map(VariableDescriptor::getTableName)
.orElse(null);

if (tableName == null) {
handleVirtualTable(queryResult);
} else {
handleNamedTable(tableName, queryResult);
}
}

private void handleNamedTable(String tableName, QueryResult queryResult) {
if (queryResults.containsKey(tableName)) {
throw new IllegalArgumentException("Duplicate table in QueryResultSet: " + tableName);
}
queryResults.put(tableName, queryResult);
}

private void handleVirtualTable(QueryResult queryResult) {
if (queryResultForVirtualTable != null) {
throw new IllegalArgumentException("Duplicate values for virtual table");
}
queryResultForVirtualTable = queryResult;
}

/**
* Retrieves the query result associated with a named table.
*
* @param tableName the name of the table
* @return the query result for the table, or {@code null} if no result exists
*/
public QueryResult getQueryResultForNamedTable(String tableName) {
return queryResults.get(tableName);
}

/**
* Retrieves the query result for a virtual table.
*
* @return the query result for the virtual table, or {@code null} if none exists
*/
public QueryResult getQueryResultForVirtualTable() {
return queryResultForVirtualTable;
}

}
Loading
Loading