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) + ")");
}
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);
}
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;
}
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) + ")";
}
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())));
}
Aggregations