Skip to content

Commit

Permalink
Support explain verification
Browse files Browse the repository at this point in the history
Add a new functionality to the verifier to allow explain verification.

For each query pairs to be verified, explain both control and test, and
compare the query plans. Verification is marked as succeeded as long as
the test query can be explained.

Introduced a new field matchType in the output event, which can be used
to indicate whether there is plan difference.

For non-DML queries, we don't care much about plan difference and hence
the control query and plan comparison are skipped.
  • Loading branch information
caithagoras0 committed Sep 10, 2020
1 parent b388a1b commit 710f04e
Show file tree
Hide file tree
Showing 16 changed files with 616 additions and 92 deletions.
11 changes: 11 additions & 0 deletions presto-docs/src/main/sphinx/admin/verifier.rst
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,17 @@ automatically resolve certain mismatches.
* **Resolved Functions**: In the case of a results mismatch, if the query uses a function in a
specified list, the test case is marked as resolved.

Explain Mode
------------
In explain mode, Verifier checks whether source queries can be explained instead of whether
they produces the same results. Verification is marked as succeeded when both control query
and test query can be explained.

The field ``matchType`` in the output event can be used as an indicator whether there are
plan differences between the control run and the test run.

For non-DML queries, the control query and the plan comparison are skipped.

Extending Verifier
------------------

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ public class QueryInfo
private final List<String> setupQueries;
private final List<String> teardownQueries;
private final String checksumQuery;
private final String jsonPlan;

private final Double cpuTimeSecs;
private final Double wallTimeSecs;
Expand All @@ -52,25 +53,6 @@ public class QueryInfo

private final String extraStats;

public QueryInfo(
String catalog,
String schema,
String originalQuery)
{
this(
catalog,
schema,
originalQuery,
ImmutableList.of(),
ImmutableList.of(),
Optional.empty(),
Optional.empty(),
Optional.empty(),
Optional.empty(),
Optional.empty(),
Optional.empty());
}

public QueryInfo(
String catalog,
String schema,
Expand All @@ -82,6 +64,7 @@ public QueryInfo(
Optional<List<String>> setupQueries,
Optional<List<String>> teardownQueries,
Optional<String> checksumQuery,
Optional<String> jsonPlan,
Optional<QueryActionStats> queryActionStats)
{
Optional<QueryStats> stats = queryActionStats.flatMap(QueryActionStats::getQueryStats);
Expand All @@ -96,6 +79,7 @@ public QueryInfo(
this.setupQueries = setupQueries.orElse(null);
this.teardownQueries = teardownQueries.orElse(null);
this.checksumQuery = checksumQuery.orElse(null);
this.jsonPlan = jsonPlan.orElse(null);
this.cpuTimeSecs = stats.map(QueryStats::getCpuTimeMillis).map(QueryInfo::millisToSeconds).orElse(null);
this.wallTimeSecs = stats.map(QueryStats::getWallTimeMillis).map(QueryInfo::millisToSeconds).orElse(null);
this.peakTotalMemoryBytes = stats.map(QueryStats::getPeakTotalMemoryBytes).orElse(null);
Expand Down Expand Up @@ -174,6 +158,12 @@ public String getChecksumQuery()
return checksumQuery;
}

@EventField
public String getJsonPlan()
{
return jsonPlan;
}

@EventField
public Double getCpuTimeSecs()
{
Expand Down Expand Up @@ -203,4 +193,103 @@ public String getExtraStats()
{
return extraStats;
}

public static Builder builder(String catalog, String schema, String originalQuery)
{
return new Builder(catalog, schema, originalQuery);
}

public static class Builder
{
private final String catalog;
private final String schema;
private final String originalQuery;
private List<String> setupQueryIds = ImmutableList.of();
private List<String> teardownQueryIds = ImmutableList.of();
private Optional<String> checksumQueryId = Optional.empty();
private Optional<String> query = Optional.empty();
private Optional<List<String>> setupQueries = Optional.empty();
private Optional<List<String>> teardownQueries = Optional.empty();
private Optional<String> checksumQuery = Optional.empty();
private Optional<String> jsonPlan = Optional.empty();
private Optional<QueryActionStats> queryActionStats = Optional.empty();

private Builder(String catalog, String schema, String originalQuery)
{
this.catalog = requireNonNull(catalog, "catalog is null");
this.schema = requireNonNull(schema, "schema is null");
this.originalQuery = requireNonNull(originalQuery, "originalQuery is null");
}

public Builder setSetupQueryIds(List<String> setupQueryIds)
{
this.setupQueryIds = ImmutableList.copyOf(setupQueryIds);
return this;
}

public Builder setTeardownQueryIds(List<String> teardownQueryIds)
{
this.teardownQueryIds = ImmutableList.copyOf(teardownQueryIds);
return this;
}

public Builder setChecksumQueryId(Optional<String> checksumQueryId)
{
this.checksumQueryId = requireNonNull(checksumQueryId, "checksumQueryId is null");
return this;
}

public Builder setQuery(Optional<String> query)
{
this.query = requireNonNull(query, "query is null");
return this;
}

public Builder setSetupQueries(Optional<List<String>> setupQueries)
{
this.setupQueries = requireNonNull(setupQueries, "setupQueries is null");
return this;
}

public Builder setTeardownQueries(Optional<List<String>> teardownQueries)
{
this.teardownQueries = requireNonNull(teardownQueries, "teardownQueries is null");
return this;
}

public Builder setChecksumQuery(Optional<String> checksumQuery)
{
this.checksumQuery = requireNonNull(checksumQuery, "checksumQuery is null");
return this;
}

public Builder setJsonPlan(String jsonPlan)
{
this.jsonPlan = Optional.of(jsonPlan);
return this;
}

public Builder setQueryActionStats(Optional<QueryActionStats> queryActionStats)
{
this.queryActionStats = requireNonNull(queryActionStats, "queryActionStats is null");
return this;
}

public QueryInfo build()
{
return new QueryInfo(
catalog,
schema,
originalQuery,
setupQueryIds,
teardownQueryIds,
checksumQueryId,
query,
setupQueries,
teardownQueries,
checksumQuery,
jsonPlan,
queryActionStats);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ public enum EventStatus
private final String name;

private final String status;
private final String matchType;
private final String skippedReason;

private final String determinismAnalysis;
Expand All @@ -68,6 +69,7 @@ public VerifierQueryEvent(
String testId,
String name,
EventStatus status,
Optional<String> matchType,
Optional<SkippedReason> skippedReason,
Optional<DeterminismAnalysisDetails> determinismAnalysisDetails,
Optional<String> resolveMessage,
Expand All @@ -83,6 +85,7 @@ public VerifierQueryEvent(
this.testId = requireNonNull(testId, "testId is null");
this.name = requireNonNull(name, "name is null");
this.status = status.name();
this.matchType = matchType.orElse(null);
this.skippedReason = skippedReason.map(SkippedReason::name).orElse(null);
this.determinismAnalysis = determinismAnalysisDetails.map(DeterminismAnalysisDetails::getResult).orElse(null);
this.determinismAnalysisDetails = determinismAnalysisDetails.orElse(null);
Expand All @@ -108,19 +111,20 @@ public static VerifierQueryEvent skipped(
testId,
sourceQuery.getName(),
SKIPPED,
Optional.empty(),
Optional.of(skippedReason),
Optional.empty(),
Optional.empty(),
skipControl ?
Optional.empty() :
Optional.of(new QueryInfo(
Optional.of(QueryInfo.builder(
sourceQuery.getControlConfiguration().getCatalog(),
sourceQuery.getControlConfiguration().getSchema(),
sourceQuery.getQuery(CONTROL))),
new QueryInfo(
sourceQuery.getQuery(CONTROL)).build()),
QueryInfo.builder(
sourceQuery.getTestConfiguration().getCatalog(),
sourceQuery.getTestConfiguration().getSchema(),
sourceQuery.getQuery(TEST)),
sourceQuery.getQuery(TEST)).build(),
Optional.empty(),
Optional.empty(),
Optional.empty(),
Expand Down Expand Up @@ -152,6 +156,12 @@ public String getStatus()
return status;
}

@EventField
public String getMatchType()
{
return matchType;
}

@EventField
public String getSkippedReason()
{
Expand Down
Loading

0 comments on commit 710f04e

Please sign in to comment.