use of com.facebook.presto.verifier.event.DeterminismAnalysisDetails in project presto by prestodb.
the class DeterminismAnalyzer method analyze.
private DeterminismAnalysis analyze(QueryObjectBundle control, ChecksumResult controlChecksum, DeterminismAnalysisDetails.Builder determinismAnalysisDetails) {
// Handle mutable catalogs
if (isNonDeterministicCatalogReferenced(control.getQuery())) {
return NON_DETERMINISTIC_CATALOG;
}
// Handle limit query
LimitQueryDeterminismAnalysis limitQueryAnalysis = new LimitQueryDeterminismAnalyzer(prestoAction, handleLimitQuery, control.getQuery(), controlChecksum.getRowCount(), determinismAnalysisDetails).analyze();
switch(limitQueryAnalysis) {
case NOT_RUN:
case FAILED_QUERY_FAILURE:
case DETERMINISTIC:
// try the next analysis
break;
case NON_DETERMINISTIC:
return NON_DETERMINISTIC_LIMIT_CLAUSE;
case FAILED_DATA_CHANGED:
return ANALYSIS_FAILED_DATA_CHANGED;
default:
throw new IllegalArgumentException(format("Invalid limitQueryAnalysis: %s", limitQueryAnalysis));
}
// Rerun control query multiple times
List<Column> columns = getColumns(prestoAction, typeManager, control.getObjectName());
Map<QueryBundle, DeterminismAnalysisRun.Builder> queryRuns = new HashMap<>();
try {
for (int i = 0; i < maxAnalysisRuns; i++) {
QueryObjectBundle queryBundle = queryRewriter.rewriteQuery(sourceQuery.getQuery(CONTROL), CONTROL);
DeterminismAnalysisRun.Builder run = determinismAnalysisDetails.addRun().setTableName(queryBundle.getObjectName().toString());
queryRuns.put(queryBundle, run);
// Rerun setup and main query
queryBundle.getSetupQueries().forEach(query -> runAndConsume(() -> prestoAction.execute(query, DETERMINISM_ANALYSIS_SETUP), stats -> stats.getQueryStats().map(QueryStats::getQueryId).ifPresent(run::addSetupQueryId)));
runAndConsume(() -> prestoAction.execute(queryBundle.getQuery(), DETERMINISM_ANALYSIS_MAIN), stats -> stats.getQueryStats().map(QueryStats::getQueryId).ifPresent(run::setQueryId));
// Run checksum query
Query checksumQuery = checksumValidator.generateChecksumQuery(queryBundle.getObjectName(), columns);
ChecksumResult testChecksum = getOnlyElement(callAndConsume(() -> prestoAction.execute(checksumQuery, DETERMINISM_ANALYSIS_CHECKSUM, ChecksumResult::fromResultSet), stats -> stats.getQueryStats().map(QueryStats::getQueryId).ifPresent(run::setChecksumQueryId)).getResults());
DeterminismAnalysis analysis = matchResultToDeterminism(match(checksumValidator, columns, columns, controlChecksum, testChecksum));
if (analysis != DETERMINISTIC) {
return analysis;
}
}
return DETERMINISTIC;
} catch (QueryException qe) {
return ANALYSIS_FAILED_QUERY_FAILURE;
} finally {
if (runTeardown) {
queryRuns.forEach((queryBundle, run) -> teardownSafely(prestoAction, Optional.of(queryBundle), queryStats -> queryStats.getQueryStats().map(QueryStats::getQueryId).ifPresent(run::addTeardownQueryId)));
}
}
}
use of com.facebook.presto.verifier.event.DeterminismAnalysisDetails in project presto by prestodb.
the class AbstractVerification method run.
@Override
public VerificationResult run() {
Optional<B> control = Optional.empty();
Optional<B> test = Optional.empty();
Optional<QueryResult<V>> controlQueryResult = Optional.empty();
Optional<QueryResult<V>> testQueryResult = Optional.empty();
QueryContext controlQueryContext = new QueryContext();
QueryContext testQueryContext = new QueryContext();
ChecksumQueryContext controlChecksumQueryContext = new ChecksumQueryContext();
ChecksumQueryContext testChecksumQueryContext = new ChecksumQueryContext();
Optional<R> matchResult = Optional.empty();
Optional<DeterminismAnalysisDetails> determinismAnalysisDetails = Optional.empty();
Optional<PartialVerificationResult> partialResult = Optional.empty();
Optional<Throwable> throwable = Optional.empty();
try {
// Rewrite queries
if (!skipControl) {
control = Optional.of(getQueryRewrite(CONTROL));
}
test = Optional.of(getQueryRewrite(TEST));
// Run control queries
if (!skipControl) {
QueryBundle controlQueryBundle = control.get();
QueryAction controlSetupAction = setupOnMainClusters ? queryActions.getControlAction() : queryActions.getHelperAction();
controlQueryBundle.getSetupQueries().forEach(query -> runAndConsume(() -> controlSetupAction.execute(query, CONTROL_SETUP), controlQueryContext::addSetupQuery, controlQueryContext::setException));
controlQueryResult = runMainQuery(controlQueryBundle.getQuery(), CONTROL, controlQueryContext);
controlQueryContext.setState(QueryState.SUCCEEDED);
} else {
controlQueryContext.setState(NOT_RUN);
}
// Run test queries
QueryBundle testQueryBundle = test.get();
QueryAction testSetupAction = setupOnMainClusters ? queryActions.getTestAction() : queryActions.getHelperAction();
testQueryBundle.getSetupQueries().forEach(query -> runAndConsume(() -> testSetupAction.execute(query, TEST_SETUP), testQueryContext::addSetupQuery, testQueryContext::setException));
testQueryResult = runMainQuery(testQueryBundle.getQuery(), TEST, testQueryContext);
testQueryContext.setState(QueryState.SUCCEEDED);
// Verify results
if (!skipControl && !skipChecksum) {
matchResult = Optional.of(verify(control.get(), test.get(), controlQueryResult, testQueryResult, controlChecksumQueryContext, testChecksumQueryContext));
// Determinism analysis
if (matchResult.get().isMismatchPossiblyCausedByNonDeterminism()) {
determinismAnalysisDetails = Optional.of(analyzeDeterminism(control.get(), matchResult.get()));
}
}
partialResult = Optional.of(concludeVerificationPartial(control, test, controlQueryContext, testQueryContext, matchResult, determinismAnalysisDetails, Optional.empty()));
} catch (Throwable t) {
if (exceptionClassifier.shouldResubmit(t) && verificationContext.getResubmissionCount() < verificationResubmissionLimit) {
return new VerificationResult(this, true, Optional.empty());
}
throwable = Optional.of(t);
partialResult = Optional.of(concludeVerificationPartial(control, test, controlQueryContext, testQueryContext, matchResult, determinismAnalysisDetails, Optional.of(t)));
} finally {
if (!smartTeardown || testQueryContext.getState() != QueryState.SUCCEEDED || (partialResult.isPresent() && partialResult.get().getStatus().equals(SUCCEEDED))) {
QueryAction controlTeardownAction = teardownOnMainClusters ? queryActions.getControlAction() : queryActions.getHelperAction();
QueryAction testTeardownAction = teardownOnMainClusters ? queryActions.getTestAction() : queryActions.getHelperAction();
teardownSafely(controlTeardownAction, control, controlQueryContext::addTeardownQuery);
teardownSafely(testTeardownAction, test, testQueryContext::addTeardownQuery);
}
}
return concludeVerification(partialResult.get(), control, test, controlQueryResult, testQueryResult, controlQueryContext, testQueryContext, matchResult, controlChecksumQueryContext, testChecksumQueryContext, determinismAnalysisDetails, throwable);
}
use of com.facebook.presto.verifier.event.DeterminismAnalysisDetails in project presto by prestodb.
the class LimitQueryDeterminismAnalyzer method analyzeLimitNoOrderBy.
private LimitQueryDeterminismAnalysis analyzeLimitNoOrderBy(Query newLimitQuery, long limit) {
Query rowCountQuery = simpleQuery(new Select(false, ImmutableList.of(new SingleColumn(new FunctionCall(QualifiedName.of("count"), ImmutableList.of(new LongLiteral("1")))))), new TableSubquery(newLimitQuery));
QueryResult<Long> result = callAndConsume(() -> prestoAction.execute(rowCountQuery, DETERMINISM_ANALYSIS_MAIN, resultSet -> Optional.of(resultSet.getLong(1))), stats -> stats.getQueryStats().map(QueryStats::getQueryId).ifPresent(determinismAnalysisDetails::setLimitQueryAnalysisQueryId));
long rowCountHigherLimit = getOnlyElement(result.getResults());
if (rowCountHigherLimit == rowCount) {
return DETERMINISTIC;
}
if (rowCountHigherLimit > rowCount) {
return NON_DETERMINISTIC;
}
return FAILED_DATA_CHANGED;
}
use of com.facebook.presto.verifier.event.DeterminismAnalysisDetails in project presto by prestodb.
the class TestLimitQueryDeterminismAnalyzer method assertAnalysis.
private static void assertAnalysis(PrestoAction prestoAction, String query, long controlRowCount, LimitQueryDeterminismAnalysis expectedAnalysis, boolean queryRan) {
DeterminismAnalysisDetails.Builder determinismAnalysisDetailsBuilder = DeterminismAnalysisDetails.builder();
LimitQueryDeterminismAnalysis analysis = new LimitQueryDeterminismAnalyzer(prestoAction, true, sqlParser.createStatement(query, PARSING_OPTIONS), controlRowCount, determinismAnalysisDetailsBuilder).analyze();
DeterminismAnalysisDetails determinismAnalysisDetails = determinismAnalysisDetailsBuilder.build(NON_DETERMINISTIC_LIMIT_CLAUSE);
assertEquals(analysis, expectedAnalysis);
assertEquals(determinismAnalysisDetails.getLimitQueryAnalysisQueryId() != null, queryRan);
}
use of com.facebook.presto.verifier.event.DeterminismAnalysisDetails in project presto by prestodb.
the class AbstractVerification method concludeVerification.
private VerificationResult concludeVerification(PartialVerificationResult partialResult, Optional<B> control, Optional<B> test, Optional<QueryResult<V>> controlQueryResult, Optional<QueryResult<V>> testQueryResult, QueryContext controlQueryContext, QueryContext testQueryContext, Optional<R> matchResult, ChecksumQueryContext controlChecksumQueryContext, ChecksumQueryContext testChecksumQueryContext, Optional<DeterminismAnalysisDetails> determinismAnalysisDetails, Optional<Throwable> throwable) {
Optional<String> errorCode = Optional.empty();
Optional<String> errorMessage = Optional.empty();
if (partialResult.getStatus() != SUCCEEDED) {
errorCode = Optional.ofNullable(throwable.map(t -> t instanceof QueryException ? ((QueryException) t).getErrorCodeName() : INTERNAL_ERROR).orElse(matchResult.map(MatchResult::getMatchTypeName).orElse(null)));
errorMessage = Optional.of(constructErrorMessage(throwable, matchResult, controlQueryContext.getState(), testQueryContext.getState()));
}
VerifierQueryEvent event = new VerifierQueryEvent(sourceQuery.getSuite(), testId, sourceQuery.getName(), partialResult.getStatus(), matchResult.map(MatchResult::getMatchTypeName), partialResult.getSkippedReason(), determinismAnalysisDetails, partialResult.getResolveMessage(), skipControl ? Optional.empty() : Optional.of(buildQueryInfo(sourceQuery.getControlConfiguration(), sourceQuery.getQuery(CONTROL), controlChecksumQueryContext, control, controlQueryContext, controlQueryResult)), buildQueryInfo(sourceQuery.getTestConfiguration(), sourceQuery.getQuery(TEST), testChecksumQueryContext, test, testQueryContext, testQueryResult), errorCode, errorMessage, throwable.filter(QueryException.class::isInstance).map(QueryException.class::cast).map(QueryException::toQueryFailure), verificationContext.getQueryFailures(), verificationContext.getResubmissionCount());
return new VerificationResult(this, false, Optional.of(event));
}
Aggregations