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