Search in sources :

Example 1 with Range

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

the class TestPrometheusSplit method testPredicatePushDownLowerBoundDirect.

@Test
public void testPredicatePushDownLowerBoundDirect() {
    Range lowRange = Range.greaterThanOrEqual(TIMESTAMP_WITH_TIME_ZONE, packDateTimeWithZone(1570460709643L, UTC_KEY));
    ValueSet valueSet = ValueSet.ofRanges(lowRange);
    Domain testDomain = Domain.create(valueSet, false);
    TupleDomain<ColumnHandle> testTupleDomain = TupleDomain.withColumnDomains(ImmutableMap.of(new PrometheusColumnHandle("timestamp", TIMESTAMP_WITH_TIME_ZONE, 2), testDomain));
    PrometheusPredicateTimeInfo predicateTimes = PrometheusSplitManager.determinePredicateTimes(testTupleDomain).orElseThrow(() -> new AssertionError("predicate pushdown error on Prometheus Column"));
    Instant expected = ofEpochMilli(1570460709643L);
    assertEquals(predicateTimes.getPredicateLowerTimeBound().orElseThrow(() -> new AssertionError("predicate pushdown error on Prometheus Column")), expected);
}
Also used : ColumnHandle(com.facebook.presto.spi.ColumnHandle) Instant(java.time.Instant) Range(com.facebook.presto.common.predicate.Range) Domain(com.facebook.presto.common.predicate.Domain) TupleDomain(com.facebook.presto.common.predicate.TupleDomain) ValueSet(com.facebook.presto.common.predicate.ValueSet) Test(org.testng.annotations.Test)

Example 2 with Range

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

the class PreparedStatementBuilder method toPredicate.

private static String toPredicate(int columnIndex, String columnName, Type type, Domain domain, Set<Integer> uuidColumnIndexes, List<ValueBuffer> bindValues) {
    if (domain.getValues().isAll()) {
        return domain.isNullAllowed() ? "TRUE" : columnName + " IS NOT NULL";
    }
    if (domain.getValues().isNone()) {
        return domain.isNullAllowed() ? columnName + " IS NULL" : "FALSE";
    }
    return domain.getValues().getValuesProcessor().transform(ranges -> {
        // Add disjuncts for ranges
        List<String> disjuncts = new ArrayList<>();
        List<Object> singleValues = new ArrayList<>();
        // Add disjuncts for ranges
        for (Range range : ranges.getOrderedRanges()) {
            // Already checked
            checkState(!range.isAll());
            if (range.isSingleValue()) {
                singleValues.add(range.getSingleValue());
            } else {
                List<String> rangeConjuncts = new ArrayList<>();
                if (!range.isLowUnbounded()) {
                    Object bindValue = getBindValue(columnIndex, uuidColumnIndexes, range.getLowBoundedValue());
                    rangeConjuncts.add(toBindPredicate(columnName, range.isLowInclusive() ? ">=" : ">"));
                    bindValues.add(ValueBuffer.create(columnIndex, type, bindValue));
                }
                if (!range.isHighUnbounded()) {
                    Object bindValue = getBindValue(columnIndex, uuidColumnIndexes, range.getHighBoundedValue());
                    rangeConjuncts.add(toBindPredicate(columnName, range.isHighInclusive() ? "<=" : "<"));
                    bindValues.add(ValueBuffer.create(columnIndex, type, bindValue));
                }
                // If rangeConjuncts is null, then the range was ALL, which should already have been checked for
                checkState(!rangeConjuncts.isEmpty());
                disjuncts.add("(" + Joiner.on(" AND ").join(rangeConjuncts) + ")");
            }
        }
        // Add back all of the possible single values either as an equality or an IN predicate
        if (singleValues.size() == 1) {
            disjuncts.add(toBindPredicate(columnName, "="));
            bindValues.add(ValueBuffer.create(columnIndex, type, getBindValue(columnIndex, uuidColumnIndexes, getOnlyElement(singleValues))));
        } else if (singleValues.size() > 1) {
            disjuncts.add(columnName + " IN (" + Joiner.on(",").join(nCopies(singleValues.size(), "?")) + ")");
            for (Object singleValue : singleValues) {
                bindValues.add(ValueBuffer.create(columnIndex, type, getBindValue(columnIndex, uuidColumnIndexes, singleValue)));
            }
        }
        // Add nullability disjuncts
        checkState(!disjuncts.isEmpty());
        if (domain.isNullAllowed()) {
            disjuncts.add(columnName + " IS NULL");
        }
        return "(" + Joiner.on(" OR ").join(disjuncts) + ")";
    }, discreteValues -> {
        String values = Joiner.on(",").join(nCopies(discreteValues.getValues().size(), "?"));
        String predicate = columnName + (discreteValues.isWhiteList() ? "" : " NOT") + " IN (" + values + ")";
        for (Object value : discreteValues.getValues()) {
            bindValues.add(ValueBuffer.create(columnIndex, type, getBindValue(columnIndex, uuidColumnIndexes, value)));
        }
        if (domain.isNullAllowed()) {
            predicate = "(" + predicate + " OR " + columnName + " IS NULL)";
        }
        return predicate;
    }, allOrNone -> {
        throw new IllegalStateException("Case should not be reachable");
    });
}
Also used : ArrayList(java.util.ArrayList) UUID.fromString(java.util.UUID.fromString) Range(com.facebook.presto.common.predicate.Range)

Example 3 with Range

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

the class ShardPredicate method createShardPredicate.

private static String createShardPredicate(ImmutableList.Builder<JDBCType> types, ImmutableList.Builder<Object> values, Domain domain, JDBCType jdbcType) {
    List<Range> ranges = domain.getValues().getRanges().getOrderedRanges();
    // only apply predicates if all ranges are single values
    if (ranges.isEmpty() || !ranges.stream().allMatch(Range::isSingleValue)) {
        return "true";
    }
    ImmutableList.Builder<Object> valuesBuilder = ImmutableList.builder();
    ImmutableList.Builder<JDBCType> typesBuilder = ImmutableList.builder();
    StringJoiner rangePredicate = new StringJoiner(" OR ");
    for (Range range : ranges) {
        Slice uuidText = (Slice) range.getSingleValue();
        try {
            Slice uuidBytes = uuidStringToBytes(uuidText);
            typesBuilder.add(jdbcType);
            valuesBuilder.add(uuidBytes);
        } catch (IllegalArgumentException e) {
            return "true";
        }
        rangePredicate.add("shard_uuid = ?");
    }
    types.addAll(typesBuilder.build());
    values.addAll(valuesBuilder.build());
    return rangePredicate.toString();
}
Also used : JDBCType(java.sql.JDBCType) ImmutableList(com.google.common.collect.ImmutableList) Slice(io.airlift.slice.Slice) Range(com.facebook.presto.common.predicate.Range) StringJoiner(java.util.StringJoiner)

Example 4 with Range

use of com.facebook.presto.common.predicate.Range 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 5 with Range

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

the class CassandraPartitionManager method getPartitionKeysList.

private static List<Set<Object>> getPartitionKeysList(CassandraTable table, TupleDomain<ColumnHandle> tupleDomain) {
    ImmutableList.Builder<Set<Object>> partitionColumnValues = ImmutableList.builder();
    for (CassandraColumnHandle columnHandle : table.getPartitionKeyColumns()) {
        Domain domain = tupleDomain.getDomains().get().get(columnHandle);
        // if there is no constraint on a partition key, return an empty set
        if (domain == null) {
            return ImmutableList.of();
        }
        // todo does cassandra allow null partition keys?
        if (domain.isNullAllowed()) {
            return ImmutableList.of();
        }
        Set<Object> values = domain.getValues().getValuesProcessor().transform(ranges -> {
            ImmutableSet.Builder<Object> columnValues = ImmutableSet.builder();
            for (Range range : ranges.getOrderedRanges()) {
                // if the range is not a single value, we can not perform partition pruning
                if (!range.isSingleValue()) {
                    return ImmutableSet.of();
                }
                Object value = range.getSingleValue();
                CassandraType valueType = columnHandle.getCassandraType();
                if (valueType.isSupportedPartitionKey()) {
                    columnValues.add(value);
                }
            }
            return columnValues.build();
        }, discreteValues -> {
            if (discreteValues.isWhiteList()) {
                return ImmutableSet.copyOf(discreteValues.getValues());
            }
            return ImmutableSet.of();
        }, allOrNone -> ImmutableSet.of());
        partitionColumnValues.add(values);
    }
    return partitionColumnValues.build();
}
Also used : ImmutableSet(com.google.common.collect.ImmutableSet) Set(java.util.Set) ImmutableSet(com.google.common.collect.ImmutableSet) ImmutableList(com.google.common.collect.ImmutableList) Domain(com.facebook.presto.common.predicate.Domain) TupleDomain(com.facebook.presto.common.predicate.TupleDomain) Range(com.facebook.presto.common.predicate.Range)

Aggregations

Range (com.facebook.presto.common.predicate.Range)25 Domain (com.facebook.presto.common.predicate.Domain)11 TupleDomain (com.facebook.presto.common.predicate.TupleDomain)10 ArrayList (java.util.ArrayList)10 ValueSet (com.facebook.presto.common.predicate.ValueSet)7 ColumnHandle (com.facebook.presto.spi.ColumnHandle)7 Test (org.testng.annotations.Test)7 Type (com.facebook.presto.common.type.Type)6 ImmutableList (com.google.common.collect.ImmutableList)6 SortedRangeSet (com.facebook.presto.common.predicate.SortedRangeSet)4 VarcharType.createUnboundedVarcharType (com.facebook.presto.common.type.VarcharType.createUnboundedVarcharType)4 Instant (java.time.Instant)4 List (java.util.List)4 Map (java.util.Map)4 Marker (com.facebook.presto.common.predicate.Marker)3 PrometheusSplitManager.decimalSecondString (com.facebook.presto.plugin.prometheus.PrometheusSplitManager.decimalSecondString)3 Slice (io.airlift.slice.Slice)3 Duration (java.time.Duration)3 TemporalAmount (java.time.temporal.TemporalAmount)3 Objects.requireNonNull (java.util.Objects.requireNonNull)3