Search in sources :

Example 11 with Range

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

the class CassandraPartitionManager method getPartitions.

public CassandraPartitionResult getPartitions(ConnectorTableHandle tableHandle, TupleDomain<ColumnHandle> tupleDomain) {
    CassandraTableHandle cassandraTableHandle = (CassandraTableHandle) tableHandle;
    CassandraTable table = cassandraSession.getTable(cassandraTableHandle.getSchemaTableName());
    List<CassandraColumnHandle> partitionKeys = table.getPartitionKeyColumns();
    // fetch the partitions
    List<CassandraPartition> allPartitions = getCassandraPartitions(table, tupleDomain);
    log.debug("%s.%s #partitions: %d", cassandraTableHandle.getSchemaName(), cassandraTableHandle.getTableName(), allPartitions.size());
    // do a final pass to filter based on fields that could not be used to build the prefix
    List<CassandraPartition> partitions = allPartitions.stream().filter(partition -> tupleDomain.overlaps(partition.getTupleDomain())).collect(toList());
    // All partition key domains will be fully evaluated, so we don't need to include those
    TupleDomain<ColumnHandle> remainingTupleDomain = TupleDomain.none();
    if (!tupleDomain.isNone()) {
        if (partitions.size() == 1 && partitions.get(0).isUnpartitioned()) {
            remainingTupleDomain = tupleDomain;
        } else {
            @SuppressWarnings({ "rawtypes", "unchecked" }) List<ColumnHandle> partitionColumns = (List) partitionKeys;
            remainingTupleDomain = TupleDomain.withColumnDomains(Maps.filterKeys(tupleDomain.getDomains().get(), not(in(partitionColumns))));
        }
    }
    // push down indexed column fixed value predicates only for unpartitioned partition which uses token range query
    if ((partitions.size() == 1) && partitions.get(0).isUnpartitioned()) {
        Map<ColumnHandle, Domain> domains = tupleDomain.getDomains().get();
        List<ColumnHandle> indexedColumns = new ArrayList<>();
        // compose partitionId by using indexed column
        StringBuilder sb = new StringBuilder();
        for (Map.Entry<ColumnHandle, Domain> entry : domains.entrySet()) {
            CassandraColumnHandle column = (CassandraColumnHandle) entry.getKey();
            Domain domain = entry.getValue();
            if (column.isIndexed() && domain.isSingleValue()) {
                sb.append(CassandraCqlUtils.validColumnName(column.getName())).append(" = ").append(CassandraCqlUtils.cqlValue(toCQLCompatibleString(entry.getValue().getSingleValue()), column.getCassandraType()));
                indexedColumns.add(column);
                // Only one indexed column predicate can be pushed down.
                break;
            }
        }
        if (sb.length() > 0) {
            CassandraPartition partition = partitions.get(0);
            TupleDomain<ColumnHandle> filterIndexedColumn = TupleDomain.withColumnDomains(Maps.filterKeys(remainingTupleDomain.getDomains().get(), not(in(indexedColumns))));
            partitions = new ArrayList<>();
            partitions.add(new CassandraPartition(partition.getKey(), sb.toString(), filterIndexedColumn, true));
            return new CassandraPartitionResult(partitions, filterIndexedColumn);
        }
    }
    return new CassandraPartitionResult(partitions, remainingTupleDomain);
}
Also used : Logger(com.facebook.airlift.log.Logger) ImmutableSet(com.google.common.collect.ImmutableSet) Set(java.util.Set) CassandraCqlUtils.toCQLCompatibleString(com.facebook.presto.cassandra.util.CassandraCqlUtils.toCQLCompatibleString) ConnectorTableHandle(com.facebook.presto.spi.ConnectorTableHandle) Maps(com.google.common.collect.Maps) Domain(com.facebook.presto.common.predicate.Domain) TupleDomain(com.facebook.presto.common.predicate.TupleDomain) Sets(com.google.common.collect.Sets) Range(com.facebook.presto.common.predicate.Range) ArrayList(java.util.ArrayList) Inject(javax.inject.Inject) List(java.util.List) Predicates.in(com.google.common.base.Predicates.in) Collectors.toList(java.util.stream.Collectors.toList) ImmutableList(com.google.common.collect.ImmutableList) Predicates.not(com.google.common.base.Predicates.not) ColumnHandle(com.facebook.presto.spi.ColumnHandle) Map(java.util.Map) Objects.requireNonNull(java.util.Objects.requireNonNull) CassandraCqlUtils(com.facebook.presto.cassandra.util.CassandraCqlUtils) ColumnHandle(com.facebook.presto.spi.ColumnHandle) ArrayList(java.util.ArrayList) ArrayList(java.util.ArrayList) List(java.util.List) Collectors.toList(java.util.stream.Collectors.toList) ImmutableList(com.google.common.collect.ImmutableList) Domain(com.facebook.presto.common.predicate.Domain) TupleDomain(com.facebook.presto.common.predicate.TupleDomain) Map(java.util.Map)

Example 12 with Range

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

the class CassandraClusteringPredicatesExtractor method getClusteringKeysSet.

private static ClusteringPushDownResult getClusteringKeysSet(List<CassandraColumnHandle> clusteringColumns, TupleDomain<ColumnHandle> predicates, VersionNumber cassandraVersion) {
    ImmutableMap.Builder<ColumnHandle, Domain> domainsBuilder = ImmutableMap.builder();
    ImmutableList.Builder<String> clusteringColumnSql = ImmutableList.builder();
    int currentClusteringColumn = 0;
    for (CassandraColumnHandle columnHandle : clusteringColumns) {
        Domain domain = predicates.getDomains().get().get(columnHandle);
        if (domain == null) {
            break;
        }
        if (domain.isNullAllowed()) {
            break;
        }
        String predicateString = null;
        predicateString = domain.getValues().getValuesProcessor().transform(ranges -> {
            List<Object> singleValues = new ArrayList<>();
            List<String> rangeConjuncts = new ArrayList<>();
            String predicate = null;
            for (Range range : ranges.getOrderedRanges()) {
                if (range.isAll()) {
                    return null;
                }
                if (range.isSingleValue()) {
                    singleValues.add(CassandraCqlUtils.cqlValue(toCQLCompatibleString(range.getSingleValue()), columnHandle.getCassandraType()));
                } else {
                    if (!range.isLowUnbounded()) {
                        rangeConjuncts.add(format("%s %s %s", CassandraCqlUtils.validColumnName(columnHandle.getName()), range.isLowInclusive() ? ">=" : ">", CassandraCqlUtils.cqlValue(toCQLCompatibleString(range.getLowBoundedValue()), columnHandle.getCassandraType())));
                    }
                    if (!range.isHighUnbounded()) {
                        rangeConjuncts.add(format("%s %s %s", CassandraCqlUtils.validColumnName(columnHandle.getName()), range.isHighInclusive() ? "<=" : "<", CassandraCqlUtils.cqlValue(toCQLCompatibleString(range.getHighBoundedValue()), columnHandle.getCassandraType())));
                    }
                }
            }
            if (!singleValues.isEmpty() && !rangeConjuncts.isEmpty()) {
                return null;
            }
            if (!singleValues.isEmpty()) {
                if (singleValues.size() == 1) {
                    predicate = CassandraCqlUtils.validColumnName(columnHandle.getName()) + " = " + singleValues.get(0);
                } else {
                    predicate = CassandraCqlUtils.validColumnName(columnHandle.getName()) + " IN (" + Joiner.on(",").join(singleValues) + ")";
                }
            } else if (!rangeConjuncts.isEmpty()) {
                predicate = Joiner.on(" AND ").join(rangeConjuncts);
            }
            return predicate;
        }, discreteValues -> {
            if (discreteValues.isWhiteList()) {
                ImmutableList.Builder<Object> discreteValuesList = ImmutableList.builder();
                for (Object discreteValue : discreteValues.getValues()) {
                    discreteValuesList.add(CassandraCqlUtils.cqlValue(toCQLCompatibleString(discreteValue), columnHandle.getCassandraType()));
                }
                String predicate = CassandraCqlUtils.validColumnName(columnHandle.getName()) + " IN (" + Joiner.on(",").join(discreteValuesList.build()) + ")";
                return predicate;
            }
            return null;
        }, allOrNone -> null);
        if (predicateString == null) {
            break;
        }
        // IN restriction only on last clustering column for Cassandra version = 2.1
        if (predicateString.contains(" IN (") && cassandraVersion.compareTo(VersionNumber.parse("2.2.0")) < 0 && currentClusteringColumn != (clusteringColumns.size() - 1)) {
            break;
        }
        clusteringColumnSql.add(predicateString);
        domainsBuilder.put(columnHandle, domain);
        // Check for last clustering column should only be restricted by range condition
        if (predicateString.contains(">") || predicateString.contains("<")) {
            break;
        }
        currentClusteringColumn++;
    }
    List<String> clusteringColumnPredicates = clusteringColumnSql.build();
    return new ClusteringPushDownResult(domainsBuilder.build(), Joiner.on(" AND ").join(clusteringColumnPredicates));
}
Also used : ImmutableMap(com.google.common.collect.ImmutableMap) CassandraCqlUtils.toCQLCompatibleString(com.facebook.presto.cassandra.util.CassandraCqlUtils.toCQLCompatibleString) HashMap(java.util.HashMap) Domain(com.facebook.presto.common.predicate.Domain) TupleDomain(com.facebook.presto.common.predicate.TupleDomain) String.format(java.lang.String.format) Range(com.facebook.presto.common.predicate.Range) ArrayList(java.util.ArrayList) List(java.util.List) ImmutableList(com.google.common.collect.ImmutableList) ColumnHandle(com.facebook.presto.spi.ColumnHandle) Map(java.util.Map) Objects.requireNonNull(java.util.Objects.requireNonNull) CassandraCqlUtils(com.facebook.presto.cassandra.util.CassandraCqlUtils) VersionNumber(com.datastax.driver.core.VersionNumber) Joiner(com.google.common.base.Joiner) ColumnHandle(com.facebook.presto.spi.ColumnHandle) ImmutableList(com.google.common.collect.ImmutableList) CassandraCqlUtils.toCQLCompatibleString(com.facebook.presto.cassandra.util.CassandraCqlUtils.toCQLCompatibleString) Range(com.facebook.presto.common.predicate.Range) ImmutableMap(com.google.common.collect.ImmutableMap) ArrayList(java.util.ArrayList) List(java.util.List) ImmutableList(com.google.common.collect.ImmutableList) Domain(com.facebook.presto.common.predicate.Domain) TupleDomain(com.facebook.presto.common.predicate.TupleDomain)

Example 13 with Range

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

the class TupleDomainParquetPredicate method createDomain.

private static <T extends Comparable<T>> Domain createDomain(Type type, ColumnIndex columnIndex, boolean hasNullValue, List<T> mins, List<T> maxs) {
    if (mins.size() == 0 || maxs.size() == 0 || mins.size() != maxs.size()) {
        return Domain.create(ValueSet.all(type), hasNullValue);
    }
    int pageCount = columnIndex.getMinValues().size();
    List<Range> ranges = new ArrayList<>();
    for (int i = 0; i < pageCount; i++) {
        T min = mins.get(i);
        T max = maxs.get(i);
        if (min.compareTo(max) > 0) {
            return Domain.create(ValueSet.all(type), hasNullValue);
        }
        if (min instanceof Long) {
            if (isStatisticsOverflow(type, asLong(min), asLong(max))) {
                return Domain.create(ValueSet.all(type), hasNullValue);
            }
            ranges.add(Range.range(type, min, true, max, true));
        } else if (min instanceof Double) {
            if (((Double) min).isNaN() || ((Double) max).isNaN()) {
                return Domain.create(ValueSet.all(type), hasNullValue);
            }
            ranges.add(Range.range(type, min, true, max, true));
        } else if (min instanceof Slice) {
            ranges.add(Range.range(type, min, true, max, true));
        }
    }
    checkArgument(!ranges.isEmpty(), "cannot use empty ranges");
    return Domain.create(ValueSet.ofRanges(ranges), hasNullValue);
}
Also used : TINYINT(com.facebook.presto.common.type.TinyintType.TINYINT) BIGINT(com.facebook.presto.common.type.BigintType.BIGINT) FLOAT(org.apache.parquet.schema.PrimitiveType.PrimitiveTypeName.FLOAT) SMALLINT(com.facebook.presto.common.type.SmallintType.SMALLINT) Slice(io.airlift.slice.Slice) ArrayList(java.util.ArrayList) Range(com.facebook.presto.common.predicate.Range)

Example 14 with Range

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

the class TupleDomainParquetPredicate method getDomain.

/**
 * Get a domain for the ranges defined by each pair of elements from {@code minimums} and {@code maximums}.
 * Both arrays must have the same length.
 */
private static Domain getDomain(ColumnDescriptor column, Type type, List<Object> minimums, List<Object> maximums, boolean hasNullValue) {
    checkArgument(minimums.size() == maximums.size(), "Expected minimums and maximums to have the same size");
    List<Range> ranges = new ArrayList<>();
    if (type.equals(BOOLEAN)) {
        boolean hasTrueValues = minimums.stream().anyMatch(value -> (boolean) value) || maximums.stream().anyMatch(value -> (boolean) value);
        boolean hasFalseValues = minimums.stream().anyMatch(value -> !(boolean) value) || maximums.stream().anyMatch(value -> !(boolean) value);
        if (hasTrueValues && hasFalseValues) {
            return Domain.all(type);
        }
        if (hasTrueValues) {
            return Domain.create(ValueSet.of(type, true), hasNullValue);
        }
        if (hasFalseValues) {
            return Domain.create(ValueSet.of(type, false), hasNullValue);
        }
        // All nulls case is handled earlier
        throw new VerifyException("Impossible boolean statistics");
    }
    if ((type.equals(BIGINT) || type.equals(TINYINT) || type.equals(SMALLINT) || type.equals(INTEGER))) {
        for (int i = 0; i < minimums.size(); i++) {
            long min = asLong(minimums.get(i));
            long max = asLong(maximums.get(i));
            if (isStatisticsOverflow(type, min, max)) {
                return Domain.create(ValueSet.all(type), hasNullValue);
            }
            ranges.add(Range.range(type, min, true, max, true));
        }
        checkArgument(!ranges.isEmpty(), "cannot use empty ranges");
        return Domain.create(ValueSet.ofRanges(ranges), hasNullValue);
    }
    if (type.equals(REAL)) {
        for (int i = 0; i < minimums.size(); i++) {
            Float min = (Float) minimums.get(i);
            Float max = (Float) maximums.get(i);
            if (min.isNaN() || max.isNaN()) {
                return Domain.create(ValueSet.all(type), hasNullValue);
            }
            ranges.add(Range.range(type, (long) floatToRawIntBits(min), true, (long) floatToRawIntBits(max), true));
        }
        checkArgument(!ranges.isEmpty(), "cannot use empty ranges");
        return Domain.create(ValueSet.ofRanges(ranges), hasNullValue);
    }
    if (type.equals(DOUBLE)) {
        for (int i = 0; i < minimums.size(); i++) {
            Double min = (Double) minimums.get(i);
            Double max = (Double) maximums.get(i);
            if (min.isNaN() || max.isNaN()) {
                return Domain.create(ValueSet.all(type), hasNullValue);
            }
            ranges.add(Range.range(type, min, true, max, true));
        }
        checkArgument(!ranges.isEmpty(), "cannot use empty ranges");
        return Domain.create(ValueSet.ofRanges(ranges), hasNullValue);
    }
    if (isVarcharType(type)) {
        for (int i = 0; i < minimums.size(); i++) {
            Slice min = Slices.wrappedBuffer(((Binary) minimums.get(i)).toByteBuffer());
            Slice max = Slices.wrappedBuffer(((Binary) maximums.get(i)).toByteBuffer());
            ranges.add(Range.range(type, min, true, max, true));
        }
        checkArgument(!ranges.isEmpty(), "cannot use empty ranges");
        return Domain.create(ValueSet.ofRanges(ranges), hasNullValue);
    }
    if (type.equals(DATE)) {
        for (int i = 0; i < minimums.size(); i++) {
            long min = asLong(minimums.get(i));
            long max = asLong(maximums.get(i));
            if (isStatisticsOverflow(type, min, max)) {
                return Domain.create(ValueSet.all(type), hasNullValue);
            }
            ranges.add(Range.range(type, min, true, max, true));
        }
        checkArgument(!ranges.isEmpty(), "cannot use empty ranges");
        return Domain.create(ValueSet.ofRanges(ranges), hasNullValue);
    }
    return Domain.create(ValueSet.all(type), hasNullValue);
}
Also used : PrimitiveType(org.apache.parquet.schema.PrimitiveType) RichColumnDescriptor(com.facebook.presto.parquet.RichColumnDescriptor) PredicateUtils.isStatisticsOverflow(com.facebook.presto.parquet.predicate.PredicateUtils.isStatisticsOverflow) FilterPredicate(org.apache.parquet.filter2.predicate.FilterPredicate) ColumnIndex(org.apache.parquet.internal.column.columnindex.ColumnIndex) FilterApi(org.apache.parquet.filter2.predicate.FilterApi) ByteBuffer(java.nio.ByteBuffer) ParquetCorruptionException(com.facebook.presto.parquet.ParquetCorruptionException) Preconditions.checkArgument(com.google.common.base.Preconditions.checkArgument) Slices(io.airlift.slice.Slices) Map(java.util.Map) Varchars.isVarcharType(com.facebook.presto.common.type.Varchars.isVarcharType) UserDefinedPredicate(org.apache.parquet.filter2.predicate.UserDefinedPredicate) DOUBLE(com.facebook.presto.common.type.DoubleType.DOUBLE) BINARY(org.apache.parquet.schema.PrimitiveType.PrimitiveTypeName.BINARY) ColumnIndexStore(org.apache.parquet.internal.filter2.columnindex.ColumnIndexStore) String.format(java.lang.String.format) Range(com.facebook.presto.common.predicate.Range) Binary(org.apache.parquet.io.api.Binary) Serializable(java.io.Serializable) INT64(org.apache.parquet.schema.PrimitiveType.PrimitiveTypeName.INT64) List(java.util.List) LITTLE_ENDIAN(java.nio.ByteOrder.LITTLE_ENDIAN) ColumnDescriptor(org.apache.parquet.column.ColumnDescriptor) INTEGER(com.facebook.presto.common.type.IntegerType.INTEGER) Optional(java.util.Optional) DictionaryPage(com.facebook.presto.parquet.DictionaryPage) ColumnPath(org.apache.parquet.hadoop.metadata.ColumnPath) Slice(io.airlift.slice.Slice) TINYINT(com.facebook.presto.common.type.TinyintType.TINYINT) HashMap(java.util.HashMap) INT32(org.apache.parquet.schema.PrimitiveType.PrimitiveTypeName.INT32) Function(java.util.function.Function) DATE(com.facebook.presto.common.type.DateType.DATE) REAL(com.facebook.presto.common.type.RealType.REAL) ArrayList(java.util.ArrayList) Float.floatToRawIntBits(java.lang.Float.floatToRawIntBits) ImmutableList(com.google.common.collect.ImmutableList) Objects.requireNonNull(java.util.Objects.requireNonNull) ParquetDataSourceId(com.facebook.presto.parquet.ParquetDataSourceId) PrimitiveTypeName(org.apache.parquet.schema.PrimitiveType.PrimitiveTypeName) BOOLEAN(com.facebook.presto.common.type.BooleanType.BOOLEAN) Type(com.facebook.presto.common.type.Type) VerifyException(com.google.common.base.VerifyException) Statistics(org.apache.parquet.column.statistics.Statistics) BIGINT(com.facebook.presto.common.type.BigintType.BIGINT) Domain(com.facebook.presto.common.predicate.Domain) TupleDomain(com.facebook.presto.common.predicate.TupleDomain) Dictionary(com.facebook.presto.parquet.dictionary.Dictionary) FLOAT(org.apache.parquet.schema.PrimitiveType.PrimitiveTypeName.FLOAT) SMALLINT(com.facebook.presto.common.type.SmallintType.SMALLINT) VisibleForTesting(com.google.common.annotations.VisibleForTesting) ValueSet(com.facebook.presto.common.predicate.ValueSet) VerifyException(com.google.common.base.VerifyException) Slice(io.airlift.slice.Slice) ArrayList(java.util.ArrayList) Range(com.facebook.presto.common.predicate.Range)

Example 15 with Range

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

the class TestHiveSplitManager method testPartitionStatsBasedOptimizationForDouble.

@Test
public void testPartitionStatsBasedOptimizationForDouble() throws Exception {
    Type type = DOUBLE;
    Range partitionRange = range(type, 10.0, true, 20.0, true);
    HiveColumnHandle columnHandle = new HiveColumnHandle("t_double", HIVE_DOUBLE, type.getTypeSignature(), 0, REGULAR, Optional.empty(), Optional.empty());
    // Test no partition stats
    assertRedundantColumnDomains(partitionRange, PartitionStatistics.empty(), ImmutableList.of(ImmutableSet.of()), columnHandle);
    // Test partition left unchanged
    assertRedundantColumnDomains(partitionRange, createDoublePartitionStatistics(5.0, 25.0, columnHandle.getName()), ImmutableList.of(ImmutableSet.of()), columnHandle);
    // Test partition being pruned
    assertRedundantColumnDomains(partitionRange, createDoublePartitionStatistics(1.0, 3.0, columnHandle.getName()), ImmutableList.of(), columnHandle);
    // Test partition having subfield domain stripped
    assertRedundantColumnDomains(partitionRange, createDoublePartitionStatistics(13.0, 15.0, columnHandle.getName()), ImmutableList.of(ImmutableSet.of(columnHandle)), columnHandle);
}
Also used : VarcharType.createUnboundedVarcharType(com.facebook.presto.common.type.VarcharType.createUnboundedVarcharType) Type(com.facebook.presto.common.type.Type) Range(com.facebook.presto.common.predicate.Range) Test(org.testng.annotations.Test)

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