use of com.facebook.presto.spi.relation.DomainTranslator.ExtractionResult in project presto by prestodb.
the class TestRowExpressionDomainTranslator method assertPredicateTranslates.
private void assertPredicateTranslates(RowExpression expression, TupleDomain<VariableReferenceExpression> tupleDomain) {
ExtractionResult result = fromPredicate(expression);
assertEquals(result.getRemainingExpression(), TRUE_CONSTANT);
assertEquals(result.getTupleDomain(), tupleDomain);
}
use of com.facebook.presto.spi.relation.DomainTranslator.ExtractionResult in project presto by prestodb.
the class TestRowExpressionDomainTranslator method testFromOrPredicate.
@Test
public void testFromOrPredicate() {
RowExpression originalPredicate = or(and(greaterThan(C_BIGINT, bigintLiteral(1L)), unprocessableExpression1(C_BIGINT)), and(lessThan(C_BIGINT, bigintLiteral(5L)), unprocessableExpression2(C_BIGINT)));
ExtractionResult result = fromPredicate(originalPredicate);
assertEquals(result.getRemainingExpression(), originalPredicate);
assertEquals(result.getTupleDomain(), withColumnDomains(ImmutableMap.of(C_BIGINT, Domain.notNull(BIGINT))));
originalPredicate = or(and(equal(C_BIGINT, bigintLiteral(1L)), unprocessableExpression1(C_BIGINT)), and(equal(C_BIGINT, bigintLiteral(2L)), unprocessableExpression2(C_BIGINT)));
result = fromPredicate(originalPredicate);
assertEquals(result.getRemainingExpression(), originalPredicate);
assertEquals(result.getTupleDomain(), withColumnDomains(ImmutableMap.of(C_BIGINT, Domain.create(ValueSet.ofRanges(Range.equal(BIGINT, 1L), Range.equal(BIGINT, 2L)), false))));
// Same unprocessableExpression means that we can do more extraction
// If both sides are operating on the same single symbol
originalPredicate = or(and(equal(C_BIGINT, bigintLiteral(1L)), unprocessableExpression1(C_BIGINT)), and(equal(C_BIGINT, bigintLiteral(2L)), unprocessableExpression1(C_BIGINT)));
result = fromPredicate(originalPredicate);
assertEquals(result.getRemainingExpression(), unprocessableExpression1(C_BIGINT));
assertEquals(result.getTupleDomain(), withColumnDomains(ImmutableMap.of(C_BIGINT, Domain.create(ValueSet.ofRanges(Range.equal(BIGINT, 1L), Range.equal(BIGINT, 2L)), false))));
// And not if they have different symbols
assertUnsupportedPredicate(or(and(equal(C_BIGINT, bigintLiteral(1L)), unprocessableExpression1(C_BIGINT)), and(equal(C_DOUBLE, doubleLiteral(2.0)), unprocessableExpression1(C_BIGINT))));
// We can make another optimization if one side is the super set of the other side
originalPredicate = or(and(greaterThan(C_BIGINT, bigintLiteral(1L)), greaterThan(C_DOUBLE, doubleLiteral(1.0)), unprocessableExpression1(C_BIGINT)), and(greaterThan(C_BIGINT, bigintLiteral(2L)), greaterThan(C_DOUBLE, doubleLiteral(2.0)), unprocessableExpression1(C_BIGINT)));
result = fromPredicate(originalPredicate);
assertEquals(result.getRemainingExpression(), unprocessableExpression1(C_BIGINT));
assertEquals(result.getTupleDomain(), withColumnDomains(ImmutableMap.of(C_BIGINT, Domain.create(ValueSet.ofRanges(Range.greaterThan(BIGINT, 1L)), false), C_DOUBLE, Domain.create(ValueSet.ofRanges(Range.greaterThan(DOUBLE, 1.0)), false))));
// We can't make those inferences if the unprocessableExpressions are non-deterministic
originalPredicate = or(and(equal(C_BIGINT, bigintLiteral(1L)), randPredicate(C_BIGINT)), and(equal(C_BIGINT, bigintLiteral(2L)), randPredicate(C_BIGINT)));
result = fromPredicate(originalPredicate);
assertEquals(result.getRemainingExpression(), originalPredicate);
assertEquals(result.getTupleDomain(), withColumnDomains(ImmutableMap.of(C_BIGINT, Domain.create(ValueSet.ofRanges(Range.equal(BIGINT, 1L), Range.equal(BIGINT, 2L)), false))));
// Test complements
originalPredicate = not(or(and(greaterThan(C_BIGINT, bigintLiteral(1L)), unprocessableExpression1(C_BIGINT)), and(lessThan(C_BIGINT, bigintLiteral(5L)), unprocessableExpression2(C_BIGINT))));
result = fromPredicate(originalPredicate);
assertEquals(result.getRemainingExpression(), and(not(and(greaterThan(C_BIGINT, bigintLiteral(1L)), unprocessableExpression1(C_BIGINT))), not(and(lessThan(C_BIGINT, bigintLiteral(5L)), unprocessableExpression2(C_BIGINT)))));
assertTrue(result.getTupleDomain().isAll());
originalPredicate = not(or(not(and(greaterThan(C_BIGINT, bigintLiteral(1L)), unprocessableExpression1(C_BIGINT))), not(and(lessThan(C_BIGINT, bigintLiteral(5L)), unprocessableExpression2(C_BIGINT)))));
result = fromPredicate(originalPredicate);
assertEquals(result.getRemainingExpression(), and(unprocessableExpression1(C_BIGINT), unprocessableExpression2(C_BIGINT)));
assertEquals(result.getTupleDomain(), withColumnDomains(ImmutableMap.of(C_BIGINT, Domain.create(ValueSet.ofRanges(Range.range(BIGINT, 1L, false, 5L, false)), false))));
}
use of com.facebook.presto.spi.relation.DomainTranslator.ExtractionResult in project presto by prestodb.
the class TestRowExpressionDomainTranslator method testSimpleComparison.
private void testSimpleComparison(RowExpression expression, VariableReferenceExpression input, Domain domain) {
ExtractionResult result = fromPredicate(expression);
assertEquals(result.getRemainingExpression(), TRUE_CONSTANT);
TupleDomain<VariableReferenceExpression> actual = result.getTupleDomain();
TupleDomain<VariableReferenceExpression> expected = withColumnDomains(ImmutableMap.of(input, domain));
if (!actual.equals(expected)) {
fail(format("for comparison [%s] expected %s but found %s", expression.toString(), expected.toString(SESSION.getSqlFunctionProperties()), actual.toString(SESSION.getSqlFunctionProperties())));
}
}
use of com.facebook.presto.spi.relation.DomainTranslator.ExtractionResult in project presto by prestodb.
the class TestRowExpressionDomainTranslator method testNoneRoundTrip.
@Test
public void testNoneRoundTrip() {
TupleDomain<VariableReferenceExpression> tupleDomain = TupleDomain.none();
ExtractionResult result = fromPredicate(toPredicate(tupleDomain));
assertEquals(result.getRemainingExpression(), TRUE_CONSTANT);
assertEquals(result.getTupleDomain(), tupleDomain);
}
use of com.facebook.presto.spi.relation.DomainTranslator.ExtractionResult in project presto by prestodb.
the class MaterializedViewQueryOptimizer method visitQuerySpecification.
@Override
protected Node visitQuerySpecification(QuerySpecification node, Void context) {
if (!node.getFrom().isPresent()) {
throw new IllegalStateException("Query with no From clause is not rewritable by materialized view");
}
Relation relation = node.getFrom().get();
if (relation instanceof AliasedRelation) {
removablePrefix = Optional.of(((AliasedRelation) relation).getAlias());
relation = ((AliasedRelation) relation).getRelation();
}
if (!(relation instanceof Table)) {
throw new SemanticException(NOT_SUPPORTED, node, "Relation other than Table is not supported in query optimizer");
}
Table baseTable = (Table) relation;
if (!removablePrefix.isPresent()) {
removablePrefix = Optional.of(new Identifier(baseTable.getName().toString()));
}
if (node.getGroupBy().isPresent()) {
ImmutableSet.Builder<Expression> expressionsInGroupByBuilder = ImmutableSet.builder();
for (GroupingElement element : node.getGroupBy().get().getGroupingElements()) {
element = removeGroupingElementPrefix(element, removablePrefix);
Optional<Set<Expression>> groupByOfMaterializedView = materializedViewInfo.getGroupBy();
if (groupByOfMaterializedView.isPresent()) {
for (Expression expression : element.getExpressions()) {
if (!groupByOfMaterializedView.get().contains(expression) || !materializedViewInfo.getBaseToViewColumnMap().containsKey(expression)) {
throw new IllegalStateException(format("Grouping element %s is not present in materialized view groupBy field", element));
}
}
}
expressionsInGroupByBuilder.addAll(element.getExpressions());
}
expressionsInGroupBy = Optional.of(expressionsInGroupByBuilder.build());
}
// TODO: Add HAVING validation to the validator https://github.com/prestodb/presto/issues/16406
if (node.getHaving().isPresent()) {
throw new SemanticException(NOT_SUPPORTED, node, "Having clause is not supported in query optimizer");
}
if (materializedViewInfo.getWhereClause().isPresent()) {
if (!node.getWhere().isPresent()) {
throw new IllegalStateException("Query with no where clause is not rewritable by materialized view with where clause");
}
QualifiedObjectName baseTableName = createQualifiedObjectName(session, baseTable, baseTable.getName());
Optional<TableHandle> tableHandle = metadata.getTableHandle(session, baseTableName);
if (!tableHandle.isPresent()) {
throw new SemanticException(MISSING_TABLE, node, "Table does not exist");
}
ImmutableList.Builder<Field> fields = ImmutableList.builder();
for (ColumnHandle columnHandle : metadata.getColumnHandles(session, tableHandle.get()).values()) {
ColumnMetadata columnMetadata = metadata.getColumnMetadata(session, tableHandle.get(), columnHandle);
fields.add(Field.newUnqualified(materializedViewInfo.getWhereClause().get().getLocation(), columnMetadata.getName(), columnMetadata.getType()));
}
Scope scope = Scope.builder().withRelationType(RelationId.anonymous(), new RelationType(fields.build())).build();
// Given base query's filter condition and materialized view's filter condition, the goal is to check if MV's filters contain Base's filters (Base implies MV).
// Let base query's filter condition be A, and MV's filter condition be B.
// One way to evaluate A implies B is to evaluate logical expression A^~B and check if the output domain is none.
// If the resulting domain is none, then A^~B is false. Thus A implies B.
// For more information and examples: https://fb.quip.com/WwmxA40jLMxR
// TODO: Implement method that utilizes external SAT solver libraries. https://github.com/prestodb/presto/issues/16536
RowExpression materializedViewWhereCondition = convertToRowExpression(materializedViewInfo.getWhereClause().get(), scope);
RowExpression baseQueryWhereCondition = convertToRowExpression(node.getWhere().get(), scope);
RowExpression rewriteLogicExpression = and(baseQueryWhereCondition, call(baseQueryWhereCondition.getSourceLocation(), "not", new FunctionResolution(metadata.getFunctionAndTypeManager()).notFunction(), materializedViewWhereCondition.getType(), materializedViewWhereCondition));
RowExpression disjunctiveNormalForm = logicalRowExpressions.convertToDisjunctiveNormalForm(rewriteLogicExpression);
ExtractionResult<VariableReferenceExpression> result = domainTranslator.fromPredicate(session.toConnectorSession(), disjunctiveNormalForm, BASIC_COLUMN_EXTRACTOR);
if (!result.getTupleDomain().equals(TupleDomain.none())) {
throw new IllegalStateException("View filter condition does not contain base query's filter condition");
}
}
return new QuerySpecification((Select) process(node.getSelect(), context), node.getFrom().map(from -> (Relation) process(from, context)), node.getWhere().map(where -> (Expression) process(where, context)), node.getGroupBy().map(groupBy -> (GroupBy) process(groupBy, context)), node.getHaving().map(having -> (Expression) process(having, context)), node.getOrderBy().map(orderBy -> (OrderBy) process(orderBy, context)), node.getOffset(), node.getLimit());
}
Aggregations