Skip to content

CQL Heuristics Calculator#1620

Open
gonzalotguerrero wants to merge 22 commits into
masterfrom
feature/cql-heuristics-calculator
Open

CQL Heuristics Calculator#1620
gonzalotguerrero wants to merge 22 commits into
masterfrom
feature/cql-heuristics-calculator

Conversation

@gonzalotguerrero

Copy link
Copy Markdown
Collaborator

Added CassandraHeuristicsCalculator/CassandraOperationEvaluator to compute a distance heuristic for CQL WHERE clauses

Distance calculation for each operator/data type follows the spec from this document


private final CassandraOperationEvaluator evaluator = new CassandraOperationEvaluator();

public double computeDistance(String cqlQuery, Iterable<Map<String, Object>> allRows) {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

add an abstraction for allRows.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

add Javadoc


private enum ComparisonType { EQUALS, GT, GTE, LT, LTE }

public Truthness evaluate(CqlQueryOperation op, Map<String, Object> row) {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add Javadoc for method


import static org.evomaster.client.java.controller.cassandra.CassandraHeuristicsCalculator.*;

public class CassandraOperationEvaluator {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add Javadoc for class

return any(op.getValue(), toElementList(rawCol));
}

private Truthness evaluateContainsKey(ContainsKeyOperation<?> op, Map<String, Object> row) {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

use abstraction for Row


public Truthness evaluate(CqlQueryOperation op, Map<String, Object> row) {
if (op instanceof AndOperation)
return evaluateAnd((AndOperation) op, row);

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

add {...} for each if. Avoid one if-liners.


private static String normalizeColumnName(String name) {
if (name == null) return null;
if (name.startsWith("\"") && name.endsWith("\"")) {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

replace " with constant value

return Collections.emptyList();
}

private static String normalizeColumnName(String name) {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

add Javadoc explaining what normalization means for a column name

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done!

this.nanos = nanos;
}

public static CqlDurationLiteral parse(String text) {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Move this code to a specific parser for this format.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done!

 - Small refactorings to follow dev guidelines
 - Refactor parsing of Duration literals and reorganise packages
 - Unify distance calculation for strings
 - Refactor operation evaluator
 - Add javadoc for calculator and CassandraRow abstraction
 - More refactorings in parser utils
 - Add missing docs in parser utils
return compareDuration(rowValue, literalValue, comparisonType);
}

SimpleLogger.uniqueWarn("CassandraHeuristicsCalculator: unsupported type "

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If the type is not unsupported it should throw an exception

}
}

private static Instant parseTimestampString(String rowValue) {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please improve the readability of this method. Consider adding different methods to try to parse different formats.

throw new IllegalArgumentException("Cannot parse timestamp string: " + rowValue);
}

private static boolean isCqlDuration(Object rowValue) {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am a bit skeptical of using reflection here to handle CqlDuration. What do you think of using java.time.temporal.TemporalAmount instead of CqlDuration ? Can we get rid of reflection ?

.equals("com.datastax.oss.driver.api.core.data.CqlDuration");
}

private static int getDurationMonths(Object durationRowValue) throws Exception {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

use java.time.temporal.TemporalAmount?

return (int) durationRowValue.getClass().getMethod("getMonths").invoke(durationRowValue);
}

private static int getDurationDays(Object durationRowValue) throws Exception {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

use java.time.temporal.TemporalAmount?

TruthnessUtils.getEqualityTruthness(nanos, literalDurationValue.nanos)
);
} catch (Exception e) {
return FALSE_TRUTHNESS;

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why a try-catch here? What are the expected exceptions at this point?

* {@code mo}, or {@code ms} consuming {@code m}.
*/
private static final Pattern TOKEN =
Pattern.compile("(\\d+)(mo|ms|µs|us|ns|y|d|h|m|s)", Pattern.CASE_INSENSITIVE);

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

replace mo, ms, us, µs, ns, y, d, h, m, s with corresponding constant values

private static CqlDurationLiteral parseIso(String isoDuration) {
// Split on T (or t) to separate date and time parts
String upper = isoDuration.toUpperCase();
int tIndex = upper.indexOf('T');

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

replace 'T' with constant value

long value = Long.parseLong(m.group(1));
String unit = m.group(2).toLowerCase();
switch (unit) {
case "y": months += (int)(value * 12); break;

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

replace these strings with constant values

* @return {@code true} if {@code cqlCommand} is a SELECT statement
*/
public static boolean isSelect(String cqlCommand) {
return cqlCommand.trim().toUpperCase().startsWith("SELECT");

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

replace "SELECT", "UPDATE", etc with constants

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants