Search in sources :

Example 6 with Range

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

the class TestOrcBloomFilters method testMatchesNonExpandedRange.

@Test
public void testMatchesNonExpandedRange() {
    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(1500L).buildBloomFilter())));
    Range range = Range.range(BIGINT, 1233L, true, 1235L, true);
    TupleDomainOrcPredicate.TupleDomainOrcPredicateBuilder builder = TupleDomainOrcPredicate.builder().setBloomFiltersEnabled(true).addColumn(ROOT_COLUMN, Domain.create(ValueSet.ofRanges(range), false));
    // Domain expansion doesn't take place -> no bloom filtering -> ranges overlap
    assertTrue(builder.setDomainCompactionThreshold(1).build().matches(1L, matchingStatisticsByColumnIndex));
    assertFalse(builder.setDomainCompactionThreshold(100).build().matches(1L, matchingStatisticsByColumnIndex));
}
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)

Example 7 with Range

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

the class ElasticsearchQueryBuilder method buildTermQuery.

private static QueryBuilder buildTermQuery(BoolQueryBuilder queryBuilder, String columnName, Domain domain, Type type) {
    for (Range range : domain.getValues().getRanges().getOrderedRanges()) {
        BoolQueryBuilder rangeQueryBuilder = new BoolQueryBuilder();
        Set<Object> valuesToInclude = new HashSet<>();
        checkState(!range.isAll(), "Invalid range for column: %s", columnName);
        if (range.isSingleValue()) {
            valuesToInclude.add(range.getSingleValue());
        } else {
            if (!range.isLowUnbounded()) {
                Object lowBound = getValue(type, range.getLowBoundedValue());
                if (range.isLowInclusive()) {
                    rangeQueryBuilder.filter(new RangeQueryBuilder(columnName).gte(lowBound));
                } else {
                    rangeQueryBuilder.filter(new RangeQueryBuilder(columnName).gt(lowBound));
                }
            }
            if (!range.isHighUnbounded()) {
                Object highBound = getValue(type, range.getHighBoundedValue());
                if (range.isHighInclusive()) {
                    rangeQueryBuilder.filter(new RangeQueryBuilder(columnName).lte(highBound));
                } else {
                    rangeQueryBuilder.filter(new RangeQueryBuilder(columnName).lt(highBound));
                }
            }
        }
        if (valuesToInclude.size() == 1) {
            rangeQueryBuilder.filter(new TermQueryBuilder(columnName, getValue(type, getOnlyElement(valuesToInclude))));
        }
        queryBuilder.should(rangeQueryBuilder);
    }
    if (domain.isNullAllowed()) {
        queryBuilder.should(new BoolQueryBuilder().mustNot(new ExistsQueryBuilder(columnName)));
    }
    return queryBuilder;
}
Also used : BoolQueryBuilder(org.elasticsearch.index.query.BoolQueryBuilder) ExistsQueryBuilder(org.elasticsearch.index.query.ExistsQueryBuilder) TermQueryBuilder(org.elasticsearch.index.query.TermQueryBuilder) Range(io.trino.spi.predicate.Range) RangeQueryBuilder(org.elasticsearch.index.query.RangeQueryBuilder) HashSet(java.util.HashSet)

Example 8 with Range

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

the class TestPrometheusSplit method testPredicatePushDownSetsUpperBoundOnly.

@Test
public void testPredicatePushDownSetsUpperBoundOnly() {
    long predicateHighValue = 1568638171999L;
    Range highRange = Range.lessThanOrEqual(TIMESTAMP_COLUMN_TYPE, packDateTimeWithZone(predicateHighValue, UTC_KEY));
    ValueSet valueSet = ValueSet.ofRanges(highRange);
    Domain testDomain = Domain.create(valueSet, false);
    TupleDomain<ColumnHandle> testTupleDomain = TupleDomain.withColumnDomains(ImmutableMap.of(new PrometheusColumnHandle("timestamp", TIMESTAMP_COLUMN_TYPE, 2), testDomain));
    PrometheusTableHandle prometheusTableHandle = new PrometheusTableHandle("schemaName", "tableName").withPredicate(testTupleDomain);
    io.airlift.units.Duration maxQueryRangeDuration = new io.airlift.units.Duration(120, TimeUnit.SECONDS);
    io.airlift.units.Duration queryChunkSizeDuration = new io.airlift.units.Duration(30, TimeUnit.SECONDS);
    Instant now = ofEpochMilli(1568638171999L + 600000L);
    List<String> splitTimes = PrometheusSplitManager.generateTimesForSplits(now, maxQueryRangeDuration, queryChunkSizeDuration, prometheusTableHandle);
    TemporalAmount expectedMaxQueryAsTime = java.time.Duration.ofMillis(maxQueryRangeDuration.toMillis() + ((splitTimes.size() - 1) * OFFSET_MILLIS));
    String lastSplit = splitTimes.get(splitTimes.size() - 1);
    Instant lastSplitAsTime = ofEpochMilli(longFromDecimalSecondString(lastSplit));
    String earliestSplit = splitTimes.get(0);
    Instant earliestSplitAsTime = ofEpochMilli(longFromDecimalSecondString(earliestSplit));
    TemporalAmount queryChunkAsTime = java.time.Duration.ofMillis(queryChunkSizeDuration.toMillis());
    java.time.Duration actualMaxDuration = Duration.between(earliestSplitAsTime.minus(queryChunkAsTime), lastSplitAsTime);
    assertEquals(lastSplitAsTime.toEpochMilli(), 1568638171999L);
    assertEquals(actualMaxDuration, expectedMaxQueryAsTime);
}
Also used : ColumnHandle(io.trino.spi.connector.ColumnHandle) Instant(java.time.Instant) Duration(java.time.Duration) PrometheusSplitManager.decimalSecondString(io.trino.plugin.prometheus.PrometheusSplitManager.decimalSecondString) Range(io.trino.spi.predicate.Range) TemporalAmount(java.time.temporal.TemporalAmount) Duration(java.time.Duration) Domain(io.trino.spi.predicate.Domain) TupleDomain(io.trino.spi.predicate.TupleDomain) ValueSet(io.trino.spi.predicate.ValueSet) Test(org.testng.annotations.Test)

Example 9 with Range

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

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.isInclusive() ? "" : " 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(io.trino.spi.predicate.Range)

Example 10 with Range

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

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 (https://github.com/trinodb/trino/issues/8759) Evaluate Apache Iceberg's support for predicate on structural types
    if (type instanceof ArrayType || type instanceof MapType || type instanceof RowType) {
        // Fail fast. Ignoring expression could lead to data loss in case of deletions.
        throw new UnsupportedOperationException("Unsupported type for expression: " + type);
    }
    if (type.isOrderable()) {
        List<Range> orderedRanges = domain.getValues().getRanges().getOrderedRanges();
        List<Object> icebergValues = new ArrayList<>();
        List<Expression> rangeExpressions = new ArrayList<>();
        for (Range range : orderedRanges) {
            if (range.isSingleValue()) {
                icebergValues.add(getIcebergLiteralValue(type, range.getLowBoundedValue()));
            } else {
                rangeExpressions.add(toIcebergExpression(columnName, range));
            }
        }
        Expression ranges = or(rangeExpressions);
        Expression values = icebergValues.isEmpty() ? alwaysFalse() : in(columnName, icebergValues);
        Expression nullExpression = domain.isNullAllowed() ? isNull(columnName) : alwaysFalse();
        return or(nullExpression, or(values, ranges));
    }
    throw new VerifyException(format("Unsupported type %s with domain values %s", type, domain));
}
Also used : ArrayType(io.trino.spi.type.ArrayType) Expression(org.apache.iceberg.expressions.Expression) VerifyException(com.google.common.base.VerifyException) ArrayList(java.util.ArrayList) RowType(io.trino.spi.type.RowType) Range(io.trino.spi.predicate.Range) MapType(io.trino.spi.type.MapType)

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