Search in sources :

Example 21 with Range

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

the class GlueExpressionUtil method buildGlueExpressionForSingleDomain.

/**
 * Converts domain to a valid glue expression per
 * https://docs.aws.amazon.com/glue/latest/dg/aws-glue-api-catalog-partitions.html#aws-glue-api-catalog-partitions-GetPartitions
 *
 * @return optional glue-compatible expression. if empty, either tye type of the {@link Domain} cannot be converted to a string, or the filter is {@link Domain#all}
 */
@VisibleForTesting
static Optional<String> buildGlueExpressionForSingleDomain(String columnName, Domain domain, boolean assumeCanonicalPartitionKeys) {
    ValueSet valueSet = domain.getValues();
    if (domain.isAll() || !canConvertSqlTypeToStringForGlue(domain.getType(), assumeCanonicalPartitionKeys)) {
        // if the type can't be converted or Domain.all()
        return Optional.empty();
    }
    if (domain.getValues().isAll()) {
        return Optional.of(format("(%s <> '%s')", columnName, NULL_STRING));
    }
    // null must be allowed for this case since callers must filter Domain.none() out
    if (domain.getValues().isNone()) {
        return Optional.of(format("(%s = '%s')", columnName, NULL_STRING));
    }
    List<String> disjuncts = new ArrayList<>();
    List<String> singleValues = new ArrayList<>();
    for (Range range : valueSet.getRanges().getOrderedRanges()) {
        // Already checked
        checkState(!range.isAll());
        if (range.isSingleValue()) {
            singleValues.add(valueToString(range.getType(), range.getSingleValue()));
        } else {
            List<String> rangeConjuncts = new ArrayList<>();
            if (!range.isLowUnbounded()) {
                rangeConjuncts.add(format("%s %s %s", columnName, range.isLowInclusive() ? ">=" : ">", valueToString(range.getType(), range.getLowBoundedValue())));
            }
            if (!range.isHighUnbounded()) {
                rangeConjuncts.add(format("%s %s %s", columnName, range.isHighInclusive() ? "<=" : "<", valueToString(range.getType(), range.getHighBoundedValue())));
            }
            // If rangeConjuncts is null, then the range was ALL, which should already have been checked for by callers
            checkState(!rangeConjuncts.isEmpty());
            disjuncts.add("(" + CONJUNCT_JOINER.join(rangeConjuncts) + ")");
        }
    }
    if (singleValues.size() == 1) {
        String equalsTest = format("(%s = %s)", columnName, getOnlyElement(singleValues));
        disjuncts.add(equalsTest);
    } else if (singleValues.size() > 1) {
        String values = Joiner.on(", ").join(singleValues);
        String inClause = format("(%s in (%s))", columnName, values);
        disjuncts.add(inClause);
    }
    return Optional.of("(" + DISJUNCT_JOINER.join(disjuncts) + ")");
}
Also used : ArrayList(java.util.ArrayList) Range(io.trino.spi.predicate.Range) ValueSet(io.trino.spi.predicate.ValueSet) VisibleForTesting(com.google.common.annotations.VisibleForTesting)

Example 22 with Range

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

the class IcebergSplitSource method domainForStatistics.

private static Domain domainForStatistics(io.trino.spi.type.Type type, @Nullable Object lowerBound, @Nullable Object upperBound, boolean mayContainNulls) {
    Type icebergType = toIcebergType(type);
    if (lowerBound == null && upperBound == null) {
        return Domain.create(ValueSet.all(type), mayContainNulls);
    }
    Range statisticsRange;
    if (lowerBound != null && upperBound != null) {
        statisticsRange = Range.range(type, convertIcebergValueToTrino(icebergType, lowerBound), true, convertIcebergValueToTrino(icebergType, upperBound), true);
    } else if (upperBound != null) {
        statisticsRange = Range.lessThanOrEqual(type, convertIcebergValueToTrino(icebergType, upperBound));
    } else {
        statisticsRange = Range.greaterThanOrEqual(type, convertIcebergValueToTrino(icebergType, lowerBound));
    }
    return Domain.create(ValueSet.ofRanges(statisticsRange), mayContainNulls);
}
Also used : TypeConverter.toIcebergType(io.trino.plugin.iceberg.TypeConverter.toIcebergType) Type(org.apache.iceberg.types.Type) Range(io.trino.spi.predicate.Range)

Example 23 with Range

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

the class DomainTranslator method extractDisjuncts.

private List<Expression> extractDisjuncts(Session session, 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 types including NaN, it is incorrect to introduce range "all" while processing a set of ranges,
        even if the component ranges cover the entire value set.
        This is because partial ranges don't include NaN, while range "all" does.
        Example: ranges (unbounded , 1.0) and (1.0, unbounded) should not be coalesced to (unbounded, unbounded) with excluded point 1.0.
        That result would be further translated to expression "xxx <> 1.0", which is satisfied by NaN.
        To avoid error, in such case the ranges are not optimised.
         */
    if (type instanceof RealType || type instanceof DoubleType) {
        boolean originalRangeIsAll = orderedRanges.stream().anyMatch(Range::isAll);
        boolean coalescedRangeIsAll = originalUnionSingleValues.stream().anyMatch(Range::isAll);
        if (!originalRangeIsAll && coalescedRangeIsAll) {
            for (Range range : orderedRanges) {
                disjuncts.add(processRange(session, type, range, reference));
            }
            return disjuncts;
        }
    }
    for (Range range : originalUnionSingleValues) {
        if (range.isSingleValue()) {
            singleValues.add(literalEncoder.toExpression(session, 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(session, singleValueExclusions.next().getSingleValue(), type));
        }
        if (!singleValuesInRange.isEmpty()) {
            disjuncts.add(combineRangeWithExcludedPoints(session, type, reference, range, singleValuesInRange));
            continue;
        }
        disjuncts.add(processRange(session, 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 : ArrayList(java.util.ArrayList) InListExpression(io.trino.sql.tree.InListExpression) Range(io.trino.spi.predicate.Range) InPredicate(io.trino.sql.tree.InPredicate) RealType(io.trino.spi.type.RealType) ComparisonExpression(io.trino.sql.tree.ComparisonExpression) SortedRangeSet(io.trino.spi.predicate.SortedRangeSet) ComparisonExpression(io.trino.sql.tree.ComparisonExpression) Expression(io.trino.sql.tree.Expression) InListExpression(io.trino.sql.tree.InListExpression) NotExpression(io.trino.sql.tree.NotExpression) LogicalExpression(io.trino.sql.tree.LogicalExpression) DoubleType(io.trino.spi.type.DoubleType)

Example 24 with Range

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

the class PinotQueryBuilder method toPredicate.

private static String toPredicate(String columnName, Domain domain) {
    List<String> disjuncts = new ArrayList<>();
    List<Object> singleValues = new ArrayList<>();
    for (Range range : domain.getValues().getRanges().getOrderedRanges()) {
        // Already checked
        checkState(!range.isAll());
        if (range.isSingleValue()) {
            singleValues.add(convertValue(range.getType(), range.getSingleValue()));
        } else {
            List<String> rangeConjuncts = new ArrayList<>();
            if (!range.isLowUnbounded()) {
                rangeConjuncts.add(toConjunct(columnName, range.isLowInclusive() ? ">=" : ">", convertValue(range.getType(), range.getLowBoundedValue())));
            }
            if (!range.isHighUnbounded()) {
                rangeConjuncts.add(toConjunct(columnName, range.isHighInclusive() ? "<=" : "<", convertValue(range.getType(), range.getHighBoundedValue())));
            }
            // If rangeConjuncts is null, then the range was ALL, which is not supported in pql
            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(toConjunct(columnName, "=", getOnlyElement(singleValues)));
    } else if (singleValues.size() > 1) {
        disjuncts.add(inClauseValues(columnName, singleValues));
    }
    return "(" + Joiner.on(" OR ").join(disjuncts) + ")";
}
Also used : ArrayList(java.util.ArrayList) Range(io.trino.spi.predicate.Range)

Example 25 with Range

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

the class MongoSession method buildPredicate.

private static Optional<Document> buildPredicate(MongoColumnHandle column, Domain domain) {
    String name = column.getName();
    Type type = column.getType();
    if (domain.getValues().isNone() && domain.isNullAllowed()) {
        return Optional.of(documentOf(name, isNullPredicate()));
    }
    if (domain.getValues().isAll() && !domain.isNullAllowed()) {
        return Optional.of(documentOf(name, isNotNullPredicate()));
    }
    List<Object> singleValues = new ArrayList<>();
    List<Document> disjuncts = new ArrayList<>();
    for (Range range : domain.getValues().getRanges().getOrderedRanges()) {
        if (range.isSingleValue()) {
            Optional<Object> translated = translateValue(range.getSingleValue(), type);
            if (translated.isEmpty()) {
                return Optional.empty();
            }
            singleValues.add(translated.get());
        } else {
            Document rangeConjuncts = new Document();
            if (!range.isLowUnbounded()) {
                Optional<Object> translated = translateValue(range.getLowBoundedValue(), type);
                if (translated.isEmpty()) {
                    return Optional.empty();
                }
                rangeConjuncts.put(range.isLowInclusive() ? GTE_OP : GT_OP, translated.get());
            }
            if (!range.isHighUnbounded()) {
                Optional<Object> translated = translateValue(range.getHighBoundedValue(), type);
                if (translated.isEmpty()) {
                    return Optional.empty();
                }
                rangeConjuncts.put(range.isHighInclusive() ? LTE_OP : LT_OP, translated.get());
            }
            // If rangeConjuncts is null, then the range was ALL, which should already have been checked for
            verify(!rangeConjuncts.isEmpty());
            disjuncts.add(rangeConjuncts);
        }
    }
    // Add back all of the possible single values either as an equality or an IN predicate
    if (singleValues.size() == 1) {
        disjuncts.add(documentOf(EQ_OP, singleValues.get(0)));
    } else if (singleValues.size() > 1) {
        disjuncts.add(documentOf(IN_OP, singleValues));
    }
    if (domain.isNullAllowed()) {
        disjuncts.add(isNullPredicate());
    }
    return Optional.of(orPredicate(disjuncts.stream().map(disjunct -> new Document(name, disjunct)).collect(toImmutableList())));
}
Also used : Document(org.bson.Document) Arrays(java.util.Arrays) NamedTypeSignature(io.trino.spi.type.NamedTypeSignature) Date(java.util.Date) MongoDatabase(com.mongodb.client.MongoDatabase) SchemaNotFoundException(io.trino.spi.connector.SchemaNotFoundException) Preconditions.checkArgument(com.google.common.base.Preconditions.checkArgument) EvictableCacheBuilder(io.trino.collect.cache.EvictableCacheBuilder) TableNotFoundException(io.trino.spi.connector.TableNotFoundException) Map(java.util.Map) ENGLISH(java.util.Locale.ENGLISH) SMALLINT(io.trino.spi.type.SmallintType.SMALLINT) Collectors.toSet(java.util.stream.Collectors.toSet) TypeSignature(io.trino.spi.type.TypeSignature) ImmutableSet(com.google.common.collect.ImmutableSet) ImmutableMap(com.google.common.collect.ImmutableMap) Range(io.trino.spi.predicate.Range) Domain(io.trino.spi.predicate.Domain) ImmutableList.toImmutableList(com.google.common.collect.ImmutableList.toImmutableList) Set(java.util.Set) TrinoException(io.trino.spi.TrinoException) Collectors(java.util.stream.Collectors) SchemaTableName(io.trino.spi.connector.SchemaTableName) String.format(java.lang.String.format) Preconditions.checkState(com.google.common.base.Preconditions.checkState) List(java.util.List) BIGINT(io.trino.spi.type.BigintType.BIGINT) FindIterable(com.mongodb.client.FindIterable) OBJECT_ID(io.trino.plugin.mongodb.ObjectIdType.OBJECT_ID) Optional(java.util.Optional) HostAddress(io.trino.spi.HostAddress) TypeSignatureParameter(io.trino.spi.type.TypeSignatureParameter) IntStream(java.util.stream.IntStream) MongoClient(com.mongodb.client.MongoClient) MongoCollection(com.mongodb.client.MongoCollection) Slice(io.airlift.slice.Slice) Logger(io.airlift.log.Logger) ColumnMetadata(io.trino.spi.connector.ColumnMetadata) TIMESTAMP_MILLIS(io.trino.spi.type.TimestampType.TIMESTAMP_MILLIS) Type(io.trino.spi.type.Type) BOOLEAN(io.trino.spi.type.BooleanType.BOOLEAN) VarcharType.createUnboundedVarcharType(io.trino.spi.type.VarcharType.createUnboundedVarcharType) Shorts(com.google.common.primitives.Shorts) MINUTES(java.util.concurrent.TimeUnit.MINUTES) ArrayList(java.util.ArrayList) HashSet(java.util.HashSet) VarcharType(io.trino.spi.type.VarcharType) VARCHAR(io.trino.spi.type.VarcharType.VARCHAR) ImmutableList(com.google.common.collect.ImmutableList) MongoCursor(com.mongodb.client.MongoCursor) Verify.verify(com.google.common.base.Verify.verify) UncheckedExecutionException(com.google.common.util.concurrent.UncheckedExecutionException) Objects.requireNonNull(java.util.Objects.requireNonNull) ColumnHandle(io.trino.spi.connector.ColumnHandle) RowFieldName(io.trino.spi.type.RowFieldName) HostAddress.fromParts(io.trino.spi.HostAddress.fromParts) VARBINARY(io.trino.spi.type.VarbinaryType.VARBINARY) Math.toIntExact(java.lang.Math.toIntExact) Binary(org.bson.types.Binary) IntegerType(io.trino.spi.type.IntegerType) SignedBytes(com.google.common.primitives.SignedBytes) StandardTypes(io.trino.spi.type.StandardTypes) IndexOptions(com.mongodb.client.model.IndexOptions) TupleDomain(io.trino.spi.predicate.TupleDomain) Throwables.throwIfInstanceOf(com.google.common.base.Throwables.throwIfInstanceOf) Primitives(com.google.common.primitives.Primitives) ExecutionException(java.util.concurrent.ExecutionException) DOUBLE(io.trino.spi.type.DoubleType.DOUBLE) Collectors.toList(java.util.stream.Collectors.toList) DBRef(com.mongodb.DBRef) DeleteResult(com.mongodb.client.result.DeleteResult) ObjectId(org.bson.types.ObjectId) VisibleForTesting(com.google.common.annotations.VisibleForTesting) TINYINT(io.trino.spi.type.TinyintType.TINYINT) Cache(com.google.common.cache.Cache) TypeManager(io.trino.spi.type.TypeManager) Type(io.trino.spi.type.Type) VarcharType.createUnboundedVarcharType(io.trino.spi.type.VarcharType.createUnboundedVarcharType) VarcharType(io.trino.spi.type.VarcharType) IntegerType(io.trino.spi.type.IntegerType) ArrayList(java.util.ArrayList) Document(org.bson.Document) Range(io.trino.spi.predicate.Range)

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