Search in sources :

Example 1 with Range

use of io.trino.spi.predicate.Range in project trino by trinodb.

the class PushPredicateThroughProjectIntoWindow method extractUpperBound.

private static OptionalInt extractUpperBound(TupleDomain<Symbol> tupleDomain, Symbol symbol) {
    if (tupleDomain.isNone()) {
        return OptionalInt.empty();
    }
    Domain rankingDomain = tupleDomain.getDomains().get().get(symbol);
    if (rankingDomain == null) {
        return OptionalInt.empty();
    }
    ValueSet values = rankingDomain.getValues();
    if (values.isAll() || values.isNone() || values.getRanges().getRangeCount() <= 0) {
        return OptionalInt.empty();
    }
    Range span = values.getRanges().getSpan();
    if (span.isHighUnbounded()) {
        return OptionalInt.empty();
    }
    long upperBound = (Long) span.getHighBoundedValue();
    if (!span.isHighInclusive()) {
        upperBound--;
    }
    if (upperBound >= Integer.MIN_VALUE && upperBound <= Integer.MAX_VALUE) {
        return OptionalInt.of(toIntExact(upperBound));
    }
    return OptionalInt.empty();
}
Also used : Domain(io.trino.spi.predicate.Domain) TupleDomain(io.trino.spi.predicate.TupleDomain) Range(io.trino.spi.predicate.Range) ValueSet(io.trino.spi.predicate.ValueSet)

Example 2 with Range

use of io.trino.spi.predicate.Range in project trino by trinodb.

the class IonSqlQueryBuilder method toPredicate.

private String toPredicate(Domain domain, Type type, int position) {
    checkArgument(domain.getType().isOrderable(), "Domain type must be orderable");
    if (domain.getValues().isNone()) {
        if (domain.isNullAllowed()) {
            return format("s._%d", position + 1) + " = '' ";
        }
        return "FALSE";
    }
    if (domain.getValues().isAll()) {
        if (domain.isNullAllowed()) {
            return "TRUE";
        }
        return format("s._%d", position + 1) + " <> '' ";
    }
    List<String> disjuncts = new ArrayList<>();
    List<Object> singleValues = new ArrayList<>();
    for (Range range : domain.getValues().getRanges().getOrderedRanges()) {
        checkState(!range.isAll());
        if (range.isSingleValue()) {
            singleValues.add(range.getSingleValue());
            continue;
        }
        List<String> rangeConjuncts = new ArrayList<>();
        if (!range.isLowUnbounded()) {
            rangeConjuncts.add(toPredicate(range.isLowInclusive() ? ">=" : ">", range.getLowBoundedValue(), type, position));
        }
        if (!range.isHighUnbounded()) {
            rangeConjuncts.add(toPredicate(range.isHighInclusive() ? "<=" : "<", range.getHighBoundedValue(), type, position));
        }
        // 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(toPredicate("=", getOnlyElement(singleValues), type, position));
    } else if (singleValues.size() > 1) {
        List<String> values = new ArrayList<>();
        for (Object value : singleValues) {
            checkType(type);
            values.add(valueToQuery(type, value));
        }
        disjuncts.add(createColumn(type, position) + " IN (" + Joiner.on(",").join(values) + ")");
    }
    // Add nullability disjuncts
    checkState(!disjuncts.isEmpty());
    if (domain.isNullAllowed()) {
        disjuncts.add(format("s._%d", position + 1) + " = '' ");
    }
    return "(" + Joiner.on(" OR ").join(disjuncts) + ")";
}
Also used : ArrayList(java.util.ArrayList) ArrayList(java.util.ArrayList) ImmutableList(com.google.common.collect.ImmutableList) List(java.util.List) Range(io.trino.spi.predicate.Range)

Example 3 with Range

use of io.trino.spi.predicate.Range in project trino by trinodb.

the class CassandraClusteringPredicatesExtractor method getClusteringKeysSet.

private static ClusteringPushDownResult getClusteringKeysSet(List<CassandraColumnHandle> clusteringColumns, TupleDomain<ColumnHandle> predicates, VersionNumber cassandraVersion) {
    ImmutableSet.Builder<ColumnHandle> fullyPushedColumnPredicates = ImmutableSet.builder();
    ImmutableList.Builder<String> clusteringColumnSql = ImmutableList.builder();
    int allProcessedClusteringColumns = 0;
    for (CassandraColumnHandle columnHandle : clusteringColumns) {
        Domain domain = predicates.getDomains().get().get(columnHandle);
        if (domain == null) {
            break;
        }
        if (domain.isNullAllowed()) {
            break;
        }
        int currentlyProcessedClusteringColumn = allProcessedClusteringColumns;
        String predicateString = domain.getValues().getValuesProcessor().transform(ranges -> {
            if (ranges.getRangeCount() == 1) {
                fullyPushedColumnPredicates.add(columnHandle);
                return translateRangeIntoCql(columnHandle, getOnlyElement(ranges.getOrderedRanges()));
            }
            if (ranges.getOrderedRanges().stream().allMatch(Range::isSingleValue)) {
                if (isInExpressionNotAllowed(clusteringColumns, cassandraVersion, currentlyProcessedClusteringColumn)) {
                    return translateRangeIntoCql(columnHandle, ranges.getSpan());
                }
                String inValues = ranges.getOrderedRanges().stream().map(range -> toCqlLiteral(columnHandle, range.getSingleValue())).collect(joining(","));
                fullyPushedColumnPredicates.add(columnHandle);
                return CassandraCqlUtils.validColumnName(columnHandle.getName()) + " IN (" + inValues + ")";
            }
            return translateRangeIntoCql(columnHandle, ranges.getSpan());
        }, discreteValues -> {
            if (discreteValues.isInclusive()) {
                if (discreteValues.getValuesCount() == 0) {
                    return null;
                }
                if (discreteValues.getValuesCount() == 1) {
                    fullyPushedColumnPredicates.add(columnHandle);
                    return format("%s = %s", CassandraCqlUtils.validColumnName(columnHandle.getName()), toCqlLiteral(columnHandle, getOnlyElement(discreteValues.getValues())));
                }
                if (isInExpressionNotAllowed(clusteringColumns, cassandraVersion, currentlyProcessedClusteringColumn)) {
                    return null;
                }
                String inValues = discreteValues.getValues().stream().map(columnHandle.getCassandraType()::toCqlLiteral).collect(joining(","));
                fullyPushedColumnPredicates.add(columnHandle);
                return CassandraCqlUtils.validColumnName(columnHandle.getName()) + " IN (" + inValues + " )";
            }
            return null;
        }, allOrNone -> null);
        if (predicateString == null) {
            break;
        }
        clusteringColumnSql.add(predicateString);
        // Check for last clustering column should only be restricted by range condition
        if (predicateString.contains(">") || predicateString.contains("<")) {
            break;
        }
        allProcessedClusteringColumns++;
    }
    List<String> clusteringColumnPredicates = clusteringColumnSql.build();
    return new ClusteringPushDownResult(fullyPushedColumnPredicates.build(), Joiner.on(" AND ").join(clusteringColumnPredicates));
}
Also used : ImmutableSet(com.google.common.collect.ImmutableSet) Range(io.trino.spi.predicate.Range) Domain(io.trino.spi.predicate.Domain) Set(java.util.Set) Iterables.getOnlyElement(com.google.common.collect.Iterables.getOnlyElement) TupleDomain(io.trino.spi.predicate.TupleDomain) String.format(java.lang.String.format) Collectors.joining(java.util.stream.Collectors.joining) CassandraCqlUtils(io.trino.plugin.cassandra.util.CassandraCqlUtils) List(java.util.List) ImmutableList(com.google.common.collect.ImmutableList) Objects.requireNonNull(java.util.Objects.requireNonNull) ColumnHandle(io.trino.spi.connector.ColumnHandle) VersionNumber(com.datastax.driver.core.VersionNumber) Joiner(com.google.common.base.Joiner) ColumnHandle(io.trino.spi.connector.ColumnHandle) ImmutableList(com.google.common.collect.ImmutableList) Range(io.trino.spi.predicate.Range) ImmutableSet(com.google.common.collect.ImmutableSet) Domain(io.trino.spi.predicate.Domain) TupleDomain(io.trino.spi.predicate.TupleDomain)

Example 4 with Range

use of io.trino.spi.predicate.Range in project trino by trinodb.

the class CassandraPartitionManager method getPartitions.

public CassandraPartitionResult getPartitions(CassandraTableHandle cassandraTableHandle, TupleDomain<ColumnHandle> tupleDomain) {
    // TODO support repeated applyFilter
    checkArgument(cassandraTableHandle.getPartitions().isEmpty(), "getPartitions() currently does not take into account table handle's partitions");
    CassandraTable table = cassandraSession.getTable(cassandraTableHandle.getSchemaTableName());
    // 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 {
            Set<ColumnHandle> usedPartitionColumns = partitions.stream().flatMap(partition -> Optional.ofNullable(partition.getTupleDomain()).flatMap(partitionTupleDomain -> partitionTupleDomain.getDomains().map(Map::keySet).map(Set::stream)).orElse(Stream.empty())).collect(toImmutableSet());
            remainingTupleDomain = tupleDomain.filter((column, domain) -> !usedPartitionColumns.contains(column));
        }
    }
    // 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(column.getCassandraType().toCqlLiteral(entry.getValue().getSingleValue()));
                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 : ImmutableSet(com.google.common.collect.ImmutableSet) Logger(io.airlift.log.Logger) Range(io.trino.spi.predicate.Range) Domain(io.trino.spi.predicate.Domain) Set(java.util.Set) TupleDomain(io.trino.spi.predicate.TupleDomain) Maps(com.google.common.collect.Maps) Sets(com.google.common.collect.Sets) ArrayList(java.util.ArrayList) Inject(javax.inject.Inject) CassandraCqlUtils(io.trino.plugin.cassandra.util.CassandraCqlUtils) List(java.util.List) Preconditions.checkArgument(com.google.common.base.Preconditions.checkArgument) Predicates.in(com.google.common.base.Predicates.in) Collectors.toList(java.util.stream.Collectors.toList) Stream(java.util.stream.Stream) ImmutableList(com.google.common.collect.ImmutableList) Predicates.not(com.google.common.base.Predicates.not) Map(java.util.Map) Objects.requireNonNull(java.util.Objects.requireNonNull) ColumnHandle(io.trino.spi.connector.ColumnHandle) Optional(java.util.Optional) ImmutableSet.toImmutableSet(com.google.common.collect.ImmutableSet.toImmutableSet) ColumnHandle(io.trino.spi.connector.ColumnHandle) ImmutableSet(com.google.common.collect.ImmutableSet) Set(java.util.Set) ImmutableSet.toImmutableSet(com.google.common.collect.ImmutableSet.toImmutableSet) ArrayList(java.util.ArrayList) Domain(io.trino.spi.predicate.Domain) TupleDomain(io.trino.spi.predicate.TupleDomain) Map(java.util.Map)

Example 5 with Range

use of io.trino.spi.predicate.Range in project trino by trinodb.

the class TestOrcBloomFilters method testMatchesExpandedRange.

@Test
public void testMatchesExpandedRange() {
    Range range = Range.range(BIGINT, 1233L, true, 1235L, true);
    TupleDomainOrcPredicate predicate = TupleDomainOrcPredicate.builder().setBloomFiltersEnabled(true).addColumn(ROOT_COLUMN, Domain.create(ValueSet.ofRanges(range), false)).setDomainCompactionThreshold(100).build();
    ColumnMetadata<ColumnStatistics> matchingStatisticsByColumnIndex = new ColumnMetadata<>(ImmutableList.of(new ColumnStatistics(null, 0, null, new IntegerStatistics(10L, 2000L, null), null, null, null, null, null, null, new Utf8BloomFilterBuilder(1000, 0.01).addLong(1234L).buildBloomFilter())));
    ColumnMetadata<ColumnStatistics> nonMatchingStatisticsByColumnIndex = new ColumnMetadata<>(ImmutableList.of(new ColumnStatistics(null, 0, null, new IntegerStatistics(10L, 2000L, null), null, null, null, null, null, null, new Utf8BloomFilterBuilder(1000, 0.01).addLong(9876L).buildBloomFilter())));
    assertTrue(predicate.matches(1L, matchingStatisticsByColumnIndex));
    assertFalse(predicate.matches(1L, nonMatchingStatisticsByColumnIndex));
}
Also used : ColumnStatistics(io.trino.orc.metadata.statistics.ColumnStatistics) ColumnMetadata(io.trino.orc.metadata.ColumnMetadata) Utf8BloomFilterBuilder(io.trino.orc.metadata.statistics.Utf8BloomFilterBuilder) Range(io.trino.spi.predicate.Range) IntegerStatistics(io.trino.orc.metadata.statistics.IntegerStatistics) Test(org.testng.annotations.Test)

Aggregations

Range (io.trino.spi.predicate.Range)30 TupleDomain (io.trino.spi.predicate.TupleDomain)16 Domain (io.trino.spi.predicate.Domain)15 ValueSet (io.trino.spi.predicate.ValueSet)12 ArrayList (java.util.ArrayList)12 ImmutableList (com.google.common.collect.ImmutableList)10 ColumnHandle (io.trino.spi.connector.ColumnHandle)9 List (java.util.List)7 Test (org.testng.annotations.Test)7 ImmutableSet (com.google.common.collect.ImmutableSet)4 Instant (java.time.Instant)4 Objects.requireNonNull (java.util.Objects.requireNonNull)4 Set (java.util.Set)4 VisibleForTesting (com.google.common.annotations.VisibleForTesting)3 Preconditions.checkArgument (com.google.common.base.Preconditions.checkArgument)3 ImmutableList.toImmutableList (com.google.common.collect.ImmutableList.toImmutableList)3 Slice (io.airlift.slice.Slice)3 PrometheusSplitManager.decimalSecondString (io.trino.plugin.prometheus.PrometheusSplitManager.decimalSecondString)3 Type (io.trino.spi.type.Type)3 String.format (java.lang.String.format)3