use of com.facebook.presto.common.predicate.Range in project presto by prestodb.
the class TestPrometheusSplit method testPredicatePushDownLowerBoundDirect.
@Test
public void testPredicatePushDownLowerBoundDirect() {
Range lowRange = Range.greaterThanOrEqual(TIMESTAMP_WITH_TIME_ZONE, packDateTimeWithZone(1570460709643L, UTC_KEY));
ValueSet valueSet = ValueSet.ofRanges(lowRange);
Domain testDomain = Domain.create(valueSet, false);
TupleDomain<ColumnHandle> testTupleDomain = TupleDomain.withColumnDomains(ImmutableMap.of(new PrometheusColumnHandle("timestamp", TIMESTAMP_WITH_TIME_ZONE, 2), testDomain));
PrometheusPredicateTimeInfo predicateTimes = PrometheusSplitManager.determinePredicateTimes(testTupleDomain).orElseThrow(() -> new AssertionError("predicate pushdown error on Prometheus Column"));
Instant expected = ofEpochMilli(1570460709643L);
assertEquals(predicateTimes.getPredicateLowerTimeBound().orElseThrow(() -> new AssertionError("predicate pushdown error on Prometheus Column")), expected);
}
use of com.facebook.presto.common.predicate.Range in project presto by prestodb.
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.isWhiteList() ? "" : " 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");
});
}
use of com.facebook.presto.common.predicate.Range in project presto by prestodb.
the class ShardPredicate method createShardPredicate.
private static String createShardPredicate(ImmutableList.Builder<JDBCType> types, ImmutableList.Builder<Object> values, Domain domain, JDBCType jdbcType) {
List<Range> ranges = domain.getValues().getRanges().getOrderedRanges();
// only apply predicates if all ranges are single values
if (ranges.isEmpty() || !ranges.stream().allMatch(Range::isSingleValue)) {
return "true";
}
ImmutableList.Builder<Object> valuesBuilder = ImmutableList.builder();
ImmutableList.Builder<JDBCType> typesBuilder = ImmutableList.builder();
StringJoiner rangePredicate = new StringJoiner(" OR ");
for (Range range : ranges) {
Slice uuidText = (Slice) range.getSingleValue();
try {
Slice uuidBytes = uuidStringToBytes(uuidText);
typesBuilder.add(jdbcType);
valuesBuilder.add(uuidBytes);
} catch (IllegalArgumentException e) {
return "true";
}
rangePredicate.add("shard_uuid = ?");
}
types.addAll(typesBuilder.build());
values.addAll(valuesBuilder.build());
return rangePredicate.toString();
}
use of com.facebook.presto.common.predicate.Range in project presto by prestodb.
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: Evaluate Apache Iceberg's support for predicate on structural types
if (type instanceof ArrayType || type instanceof MapType || type instanceof RowType) {
return alwaysTrue();
}
ValueSet domainValues = domain.getValues();
Expression expression = null;
if (domain.isNullAllowed()) {
expression = isNull(columnName);
}
if (domainValues instanceof SortedRangeSet) {
List<Range> orderedRanges = ((SortedRangeSet) domainValues).getOrderedRanges();
expression = firstNonNull(expression, alwaysFalse());
for (Range range : orderedRanges) {
Marker low = range.getLow();
Marker high = range.getHigh();
Marker.Bound lowBound = low.getBound();
Marker.Bound highBound = high.getBound();
// case col <> 'val' is represented as (col < 'val' or col > 'val')
if (lowBound == EXACTLY && highBound == EXACTLY) {
// case ==
if (getIcebergLiteralValue(type, low).equals(getIcebergLiteralValue(type, high))) {
expression = or(expression, equal(columnName, getIcebergLiteralValue(type, low)));
} else {
// case between
Expression between = and(greaterThanOrEqual(columnName, getIcebergLiteralValue(type, low)), lessThanOrEqual(columnName, getIcebergLiteralValue(type, high)));
expression = or(expression, between);
}
} else {
if (lowBound == EXACTLY && low.getValueBlock().isPresent()) {
// case >=
expression = or(expression, greaterThanOrEqual(columnName, getIcebergLiteralValue(type, low)));
} else if (lowBound == ABOVE && low.getValueBlock().isPresent()) {
// case >
expression = or(expression, greaterThan(columnName, getIcebergLiteralValue(type, low)));
}
if (highBound == EXACTLY && high.getValueBlock().isPresent()) {
// case <=
if (low.getValueBlock().isPresent()) {
expression = and(expression, lessThanOrEqual(columnName, getIcebergLiteralValue(type, high)));
} else {
expression = or(expression, lessThanOrEqual(columnName, getIcebergLiteralValue(type, high)));
}
} else if (highBound == BELOW && high.getValueBlock().isPresent()) {
// case <
if (low.getValueBlock().isPresent()) {
expression = and(expression, lessThan(columnName, getIcebergLiteralValue(type, high)));
} else {
expression = or(expression, lessThan(columnName, getIcebergLiteralValue(type, high)));
}
}
}
}
return expression;
}
throw new VerifyException("Did not expect a domain value set other than SortedRangeSet but got " + domainValues.getClass().getSimpleName());
}
use of com.facebook.presto.common.predicate.Range in project presto by prestodb.
the class CassandraPartitionManager method getPartitionKeysList.
private static List<Set<Object>> getPartitionKeysList(CassandraTable table, TupleDomain<ColumnHandle> tupleDomain) {
ImmutableList.Builder<Set<Object>> partitionColumnValues = ImmutableList.builder();
for (CassandraColumnHandle columnHandle : table.getPartitionKeyColumns()) {
Domain domain = tupleDomain.getDomains().get().get(columnHandle);
// if there is no constraint on a partition key, return an empty set
if (domain == null) {
return ImmutableList.of();
}
// todo does cassandra allow null partition keys?
if (domain.isNullAllowed()) {
return ImmutableList.of();
}
Set<Object> values = domain.getValues().getValuesProcessor().transform(ranges -> {
ImmutableSet.Builder<Object> columnValues = ImmutableSet.builder();
for (Range range : ranges.getOrderedRanges()) {
// if the range is not a single value, we can not perform partition pruning
if (!range.isSingleValue()) {
return ImmutableSet.of();
}
Object value = range.getSingleValue();
CassandraType valueType = columnHandle.getCassandraType();
if (valueType.isSupportedPartitionKey()) {
columnValues.add(value);
}
}
return columnValues.build();
}, discreteValues -> {
if (discreteValues.isWhiteList()) {
return ImmutableSet.copyOf(discreteValues.getValues());
}
return ImmutableSet.of();
}, allOrNone -> ImmutableSet.of());
partitionColumnValues.add(values);
}
return partitionColumnValues.build();
}
Aggregations