Search in sources :

Example 1 with SortedRangeSet

use of com.facebook.presto.common.predicate.SortedRangeSet in project presto by prestodb.

the class ExpressionConverter method toIcebergExpression.

private static Expression toIcebergExpression(String columnName, Type type, Domain domain) {
    if (domain.isAll()) {
        return alwaysTrue();
    }
    if (domain.getValues().isNone()) {
        return domain.isNullAllowed() ? isNull(columnName) : alwaysFalse();
    }
    if (domain.getValues().isAll()) {
        return domain.isNullAllowed() ? alwaysTrue() : not(isNull(columnName));
    }
    // Skip structural types. TODO: Evaluate Apache Iceberg's support for predicate on structural types
    if (type instanceof ArrayType || type instanceof MapType || type instanceof RowType) {
        return alwaysTrue();
    }
    ValueSet domainValues = domain.getValues();
    Expression expression = null;
    if (domain.isNullAllowed()) {
        expression = isNull(columnName);
    }
    if (domainValues instanceof SortedRangeSet) {
        List<Range> orderedRanges = ((SortedRangeSet) domainValues).getOrderedRanges();
        expression = firstNonNull(expression, alwaysFalse());
        for (Range range : orderedRanges) {
            Marker low = range.getLow();
            Marker high = range.getHigh();
            Marker.Bound lowBound = low.getBound();
            Marker.Bound highBound = high.getBound();
            // case col <> 'val' is represented as (col < 'val' or col > 'val')
            if (lowBound == EXACTLY && highBound == EXACTLY) {
                // case ==
                if (getIcebergLiteralValue(type, low).equals(getIcebergLiteralValue(type, high))) {
                    expression = or(expression, equal(columnName, getIcebergLiteralValue(type, low)));
                } else {
                    // case between
                    Expression between = and(greaterThanOrEqual(columnName, getIcebergLiteralValue(type, low)), lessThanOrEqual(columnName, getIcebergLiteralValue(type, high)));
                    expression = or(expression, between);
                }
            } else {
                if (lowBound == EXACTLY && low.getValueBlock().isPresent()) {
                    // case >=
                    expression = or(expression, greaterThanOrEqual(columnName, getIcebergLiteralValue(type, low)));
                } else if (lowBound == ABOVE && low.getValueBlock().isPresent()) {
                    // case >
                    expression = or(expression, greaterThan(columnName, getIcebergLiteralValue(type, low)));
                }
                if (highBound == EXACTLY && high.getValueBlock().isPresent()) {
                    // case <=
                    if (low.getValueBlock().isPresent()) {
                        expression = and(expression, lessThanOrEqual(columnName, getIcebergLiteralValue(type, high)));
                    } else {
                        expression = or(expression, lessThanOrEqual(columnName, getIcebergLiteralValue(type, high)));
                    }
                } else if (highBound == BELOW && high.getValueBlock().isPresent()) {
                    // case <
                    if (low.getValueBlock().isPresent()) {
                        expression = and(expression, lessThan(columnName, getIcebergLiteralValue(type, high)));
                    } else {
                        expression = or(expression, lessThan(columnName, getIcebergLiteralValue(type, high)));
                    }
                }
            }
        }
        return expression;
    }
    throw new VerifyException("Did not expect a domain value set other than SortedRangeSet but got " + domainValues.getClass().getSimpleName());
}
Also used : ArrayType(com.facebook.presto.common.type.ArrayType) SortedRangeSet(com.facebook.presto.common.predicate.SortedRangeSet) Expression(org.apache.iceberg.expressions.Expression) VerifyException(com.google.common.base.VerifyException) RowType(com.facebook.presto.common.type.RowType) Marker(com.facebook.presto.common.predicate.Marker) Range(com.facebook.presto.common.predicate.Range) ValueSet(com.facebook.presto.common.predicate.ValueSet) MapType(com.facebook.presto.common.type.MapType)

Example 2 with SortedRangeSet

use of com.facebook.presto.common.predicate.SortedRangeSet in project presto by prestodb.

the class RowExpressionDomainTranslator method extractDisjuncts.

private List<RowExpression> extractDisjuncts(Type type, Ranges ranges, RowExpression reference) {
    List<RowExpression> disjuncts = new ArrayList<>();
    List<RowExpression> singleValues = new ArrayList<>();
    List<Range> orderedRanges = ranges.getOrderedRanges();
    SortedRangeSet sortedRangeSet = SortedRangeSet.copyOf(type, orderedRanges);
    SortedRangeSet complement = sortedRangeSet.complement();
    List<Range> singleValueExclusionsList = complement.getOrderedRanges().stream().filter(Range::isSingleValue).collect(toList());
    List<Range> originalUnionSingleValues = SortedRangeSet.copyOf(type, singleValueExclusionsList).union(sortedRangeSet).getOrderedRanges();
    PeekingIterator<Range> singleValueExclusions = peekingIterator(singleValueExclusionsList.iterator());
    for (Range range : originalUnionSingleValues) {
        if (range.isSingleValue()) {
            singleValues.add(toRowExpression(reference.getSourceLocation(), range.getSingleValue(), type));
            continue;
        }
        // attempt to optimize ranges that can be coalesced as long as single value points are excluded
        List<RowExpression> singleValuesInRange = new ArrayList<>();
        while (singleValueExclusions.hasNext() && range.contains(singleValueExclusions.peek())) {
            singleValuesInRange.add(toRowExpression(reference.getSourceLocation(), singleValueExclusions.next().getSingleValue(), type));
        }
        if (!singleValuesInRange.isEmpty()) {
            disjuncts.add(combineRangeWithExcludedPoints(type, reference, range, singleValuesInRange));
            continue;
        }
        disjuncts.add(processRange(type, range, reference));
    }
    // Add back all of the possible single values either as an equality or an IN predicate
    if (singleValues.size() == 1) {
        disjuncts.add(equal(reference, getOnlyElement(singleValues)));
    } else if (singleValues.size() > 1) {
        disjuncts.add(in(reference, singleValues));
    }
    return disjuncts;
}
Also used : SortedRangeSet(com.facebook.presto.common.predicate.SortedRangeSet) ArrayList(java.util.ArrayList) LiteralEncoder.toRowExpression(com.facebook.presto.sql.planner.LiteralEncoder.toRowExpression) RowExpression(com.facebook.presto.spi.relation.RowExpression) Range(com.facebook.presto.common.predicate.Range)

Example 3 with SortedRangeSet

use of com.facebook.presto.common.predicate.SortedRangeSet in project presto by prestodb.

the class KuduClientSession method addConstraintPredicates.

/**
 * translates TupleDomain to KuduPredicates.
 *
 * @return false if TupleDomain or one of its domains is none
 */
private boolean addConstraintPredicates(KuduTable table, KuduScanToken.KuduScanTokenBuilder builder, TupleDomain<ColumnHandle> constraintSummary) {
    if (constraintSummary.isNone()) {
        return false;
    } else if (!constraintSummary.isAll()) {
        Schema schema = table.getSchema();
        for (TupleDomain.ColumnDomain<ColumnHandle> columnDomain : constraintSummary.getColumnDomains().get()) {
            int position = ((KuduColumnHandle) columnDomain.getColumn()).getOrdinalPosition();
            ColumnSchema columnSchema = schema.getColumnByIndex(position);
            Domain domain = columnDomain.getDomain();
            if (domain.isNone()) {
                return false;
            } else if (domain.isAll()) {
            // no restriction
            } else if (domain.isOnlyNull()) {
                builder.addPredicate(KuduPredicate.newIsNullPredicate(columnSchema));
            } else if (domain.getValues().isAll() && domain.isNullAllowed()) {
                builder.addPredicate(KuduPredicate.newIsNotNullPredicate(columnSchema));
            } else if (domain.isSingleValue()) {
                KuduPredicate predicate = createEqualsPredicate(columnSchema, domain.getSingleValue());
                builder.addPredicate(predicate);
            } else {
                ValueSet valueSet = domain.getValues();
                if (valueSet instanceof EquatableValueSet) {
                    DiscreteValues discreteValues = valueSet.getDiscreteValues();
                    KuduPredicate predicate = createInListPredicate(columnSchema, discreteValues);
                    builder.addPredicate(predicate);
                } else if (valueSet instanceof SortedRangeSet) {
                    Ranges ranges = ((SortedRangeSet) valueSet).getRanges();
                    Range span = ranges.getSpan();
                    Marker low = span.getLow();
                    if (!low.isLowerUnbounded()) {
                        KuduPredicate.ComparisonOp op = (low.getBound() == Marker.Bound.ABOVE) ? KuduPredicate.ComparisonOp.GREATER : KuduPredicate.ComparisonOp.GREATER_EQUAL;
                        KuduPredicate predicate = createComparisonPredicate(columnSchema, op, low.getValue());
                        builder.addPredicate(predicate);
                    }
                    Marker high = span.getHigh();
                    if (!high.isUpperUnbounded()) {
                        KuduPredicate.ComparisonOp op = (low.getBound() == Marker.Bound.BELOW) ? KuduPredicate.ComparisonOp.LESS : KuduPredicate.ComparisonOp.LESS_EQUAL;
                        KuduPredicate predicate = createComparisonPredicate(columnSchema, op, high.getValue());
                        builder.addPredicate(predicate);
                    }
                } else {
                    throw new IllegalStateException("Unexpected domain: " + domain);
                }
            }
        }
    }
    return true;
}
Also used : Ranges(com.facebook.presto.common.predicate.Ranges) Schema(org.apache.kudu.Schema) ColumnSchema(org.apache.kudu.ColumnSchema) EquatableValueSet(com.facebook.presto.common.predicate.EquatableValueSet) ColumnSchema(org.apache.kudu.ColumnSchema) Marker(com.facebook.presto.common.predicate.Marker) Range(com.facebook.presto.common.predicate.Range) KuduPredicate(org.apache.kudu.client.KuduPredicate) SortedRangeSet(com.facebook.presto.common.predicate.SortedRangeSet) DiscreteValues(com.facebook.presto.common.predicate.DiscreteValues) Domain(com.facebook.presto.common.predicate.Domain) TupleDomain(com.facebook.presto.common.predicate.TupleDomain) EquatableValueSet(com.facebook.presto.common.predicate.EquatableValueSet) ValueSet(com.facebook.presto.common.predicate.ValueSet)

Example 4 with SortedRangeSet

use of com.facebook.presto.common.predicate.SortedRangeSet in project presto by prestodb.

the class ExpressionDomainTranslator method extractDisjuncts.

private List<Expression> extractDisjuncts(Type type, Ranges ranges, SymbolReference reference) {
    List<Expression> disjuncts = new ArrayList<>();
    List<Expression> singleValues = new ArrayList<>();
    List<Range> orderedRanges = ranges.getOrderedRanges();
    SortedRangeSet sortedRangeSet = SortedRangeSet.copyOf(type, orderedRanges);
    SortedRangeSet complement = sortedRangeSet.complement();
    List<Range> singleValueExclusionsList = complement.getOrderedRanges().stream().filter(Range::isSingleValue).collect(toList());
    List<Range> originalUnionSingleValues = SortedRangeSet.copyOf(type, singleValueExclusionsList).union(sortedRangeSet).getOrderedRanges();
    PeekingIterator<Range> singleValueExclusions = peekingIterator(singleValueExclusionsList.iterator());
    for (Range range : originalUnionSingleValues) {
        if (range.isSingleValue()) {
            singleValues.add(literalEncoder.toExpression(range.getSingleValue(), type));
            continue;
        }
        // attempt to optimize ranges that can be coalesced as long as single value points are excluded
        List<Expression> singleValuesInRange = new ArrayList<>();
        while (singleValueExclusions.hasNext() && range.contains(singleValueExclusions.peek())) {
            singleValuesInRange.add(literalEncoder.toExpression(singleValueExclusions.next().getSingleValue(), type));
        }
        if (!singleValuesInRange.isEmpty()) {
            disjuncts.add(combineRangeWithExcludedPoints(type, reference, range, singleValuesInRange));
            continue;
        }
        disjuncts.add(processRange(type, range, reference));
    }
    // Add back all of the possible single values either as an equality or an IN predicate
    if (singleValues.size() == 1) {
        disjuncts.add(new ComparisonExpression(EQUAL, reference, getOnlyElement(singleValues)));
    } else if (singleValues.size() > 1) {
        disjuncts.add(new InPredicate(reference, new InListExpression(singleValues)));
    }
    return disjuncts;
}
Also used : ComparisonExpression(com.facebook.presto.sql.tree.ComparisonExpression) SortedRangeSet(com.facebook.presto.common.predicate.SortedRangeSet) NotExpression(com.facebook.presto.sql.tree.NotExpression) LogicalBinaryExpression(com.facebook.presto.sql.tree.LogicalBinaryExpression) InListExpression(com.facebook.presto.sql.tree.InListExpression) ComparisonExpression(com.facebook.presto.sql.tree.ComparisonExpression) Expression(com.facebook.presto.sql.tree.Expression) ArrayList(java.util.ArrayList) InListExpression(com.facebook.presto.sql.tree.InListExpression) Range(com.facebook.presto.common.predicate.Range) InPredicate(com.facebook.presto.sql.tree.InPredicate)

Aggregations

Range (com.facebook.presto.common.predicate.Range)4 SortedRangeSet (com.facebook.presto.common.predicate.SortedRangeSet)4 Marker (com.facebook.presto.common.predicate.Marker)2 ValueSet (com.facebook.presto.common.predicate.ValueSet)2 ArrayList (java.util.ArrayList)2 DiscreteValues (com.facebook.presto.common.predicate.DiscreteValues)1 Domain (com.facebook.presto.common.predicate.Domain)1 EquatableValueSet (com.facebook.presto.common.predicate.EquatableValueSet)1 Ranges (com.facebook.presto.common.predicate.Ranges)1 TupleDomain (com.facebook.presto.common.predicate.TupleDomain)1 ArrayType (com.facebook.presto.common.type.ArrayType)1 MapType (com.facebook.presto.common.type.MapType)1 RowType (com.facebook.presto.common.type.RowType)1 RowExpression (com.facebook.presto.spi.relation.RowExpression)1 LiteralEncoder.toRowExpression (com.facebook.presto.sql.planner.LiteralEncoder.toRowExpression)1 ComparisonExpression (com.facebook.presto.sql.tree.ComparisonExpression)1 Expression (com.facebook.presto.sql.tree.Expression)1 InListExpression (com.facebook.presto.sql.tree.InListExpression)1 InPredicate (com.facebook.presto.sql.tree.InPredicate)1 LogicalBinaryExpression (com.facebook.presto.sql.tree.LogicalBinaryExpression)1