private PlanNode rewriteFilterSource(FilterNode filterNode, PlanNode source, Symbol rowNumberSymbol, int upperBound) { ExtractionResult extractionResult = fromPredicate(metadata, session, filterNode.getPredicate(), types); TupleDomain<Symbol> tupleDomain = extractionResult.getTupleDomain(); if (!isEqualRange(tupleDomain, rowNumberSymbol, upperBound)) { return new FilterNode(filterNode.getId(), source, filterNode.getPredicate()); } // Remove the row number domain because it is absorbed into the node Map<Symbol, Domain> newDomains = tupleDomain.getDomains().get().entrySet().stream() .filter(entry -> !entry.getKey().equals(rowNumberSymbol)) .collect(toMap(Map.Entry::getKey, Map.Entry::getValue)); // Construct a new predicate TupleDomain<Symbol> newTupleDomain = TupleDomain.withColumnDomains(newDomains); Expression newPredicate = ExpressionUtils.combineConjuncts( extractionResult.getRemainingExpression(), domainTranslator.toPredicate(newTupleDomain)); if (newPredicate.equals(BooleanLiteral.TRUE_LITERAL)) { return source; } return new FilterNode(filterNode.getId(), source, newPredicate); }
public PredicatePushDown(Metadata metadata, SqlParser sqlParser) { this.metadata = requireNonNull(metadata, "metadata is null"); this.literalEncoder = new LiteralEncoder(metadata.getBlockEncodingSerde()); this.effectivePredicateExtractor = new EffectivePredicateExtractor(new DomainTranslator(literalEncoder)); this.sqlParser = requireNonNull(sqlParser, "sqlParser is null"); }
disjuncts.add(combineRangeWithExcludedPoints(type, reference, range, singleValuesInRange)); continue; disjuncts.add(processRange(type, range, reference));
private Expression toPredicate(TupleDomain<Symbol> tupleDomain) { return domainTranslator.toPredicate(tupleDomain); }
private ExtractionResult fromPredicate(Expression originalPredicate) { return DomainTranslator.fromPredicate(metadata, TEST_SESSION, originalPredicate, TYPES); }
private Expression combineRangeWithExcludedPoints(Type type, SymbolReference reference, Range range, List<Expression> excludedPoints) { if (excludedPoints.isEmpty()) { return processRange(type, range, reference); } Expression excludedPointsExpression = new NotExpression(new InPredicate(reference, new InListExpression(excludedPoints))); if (excludedPoints.size() == 1) { excludedPointsExpression = new ComparisonExpression(NOT_EQUAL, reference, getOnlyElement(excludedPoints)); } return combineConjuncts(processRange(type, range, reference), excludedPointsExpression); }
private Expression toPredicate(Domain domain, SymbolReference reference) { if (domain.getValues().isNone()) { return domain.isNullAllowed() ? new IsNullPredicate(reference) : FALSE_LITERAL; } if (domain.getValues().isAll()) { return domain.isNullAllowed() ? TRUE_LITERAL : new NotExpression(new IsNullPredicate(reference)); } List<Expression> disjuncts = new ArrayList<>(); disjuncts.addAll(domain.getValues().getValuesProcessor().transform( ranges -> extractDisjuncts(domain.getType(), ranges, reference), discreteValues -> extractDisjuncts(domain.getType(), discreteValues, reference), allOrNone -> { throw new IllegalStateException("Case should not be reachable"); })); // Add nullability disjuncts if (domain.isNullAllowed()) { disjuncts.add(new IsNullPredicate(reference)); } return combineDisjunctsWithDefault(disjuncts, TRUE_LITERAL); }
if (isBetween(range)) {
public Expression toPredicate(TupleDomain<Symbol> tupleDomain) { if (tupleDomain.isNone()) { return FALSE_LITERAL; } Map<Symbol, Domain> domains = tupleDomain.getDomains().get(); return domains.entrySet().stream() .sorted(comparing(entry -> entry.getKey().getName())) .map(entry -> toPredicate(entry.getValue(), entry.getKey().toSymbolReference())) .collect(collectingAndThen(toImmutableList(), ExpressionUtils::combineConjuncts)); }
@Override public ActualProperties visitFilter(FilterNode node, List<ActualProperties> inputProperties) { ActualProperties properties = Iterables.getOnlyElement(inputProperties); DomainTranslator.ExtractionResult decomposedPredicate = DomainTranslator.fromPredicate( metadata, session, node.getPredicate(), types); Map<Symbol, NullableValue> constants = new HashMap<>(properties.getConstants()); constants.putAll(extractFixedValues(decomposedPredicate.getTupleDomain()).orElse(ImmutableMap.of())); return ActualProperties.builderFrom(properties) .constants(constants) .build(); }
private static Expression combineRangeWithExcludedPoints(Type type, QualifiedNameReference reference, Range range, List<Expression> excludedPoints) { if (excludedPoints.isEmpty()) { return processRange(type, range, reference); } Expression excludedPointsExpression = new NotExpression(new InPredicate(reference, new InListExpression(excludedPoints))); if (excludedPoints.size() == 1) { excludedPointsExpression = new ComparisonExpression(NOT_EQUAL, reference, getOnlyElement(excludedPoints)); } return combineConjuncts(processRange(type, range, reference), excludedPointsExpression); }
private static Expression toPredicate(Domain domain, QualifiedNameReference reference) { if (domain.getValues().isNone()) { return domain.isNullAllowed() ? new IsNullPredicate(reference) : FALSE_LITERAL; } if (domain.getValues().isAll()) { return domain.isNullAllowed() ? TRUE_LITERAL : new NotExpression(new IsNullPredicate(reference)); } List<Expression> disjuncts = new ArrayList<>(); disjuncts.addAll(domain.getValues().getValuesProcessor().transform( ranges -> extractDisjuncts(domain.getType(), ranges, reference), discreteValues -> extractDisjuncts(domain.getType(), discreteValues, reference), allOrNone -> { throw new IllegalStateException("Case should not be reachable"); })); // Add nullability disjuncts if (domain.isNullAllowed()) { disjuncts.add(new IsNullPredicate(reference)); } return combineDisjunctsWithDefault(disjuncts, TRUE_LITERAL); }
if (isBetween(range)) {
private PlanNode planTableScan(TableScanNode node, Expression predicate, Context context) DomainTranslator.ExtractionResult decomposedPredicate = DomainTranslator.fromPredicate( metadata, session, domainTranslator.toPredicate(resolvedIndex.getUnresolvedTupleDomain().transform(inverseAssignments::get)), decomposedPredicate.getRemainingExpression());
@Override public Expression visitTableScan(TableScanNode node, Void context) { Map<ColumnHandle, Symbol> assignments = ImmutableBiMap.copyOf(node.getAssignments()).inverse(); return domainTranslator.toPredicate(node.getCurrentConstraint().simplify().transform(assignments::get)); }
@Override public PlanNode visitFilter(FilterNode node, RewriteContext<Void> context) { PlanNode source = context.rewrite(node.getSource()); TupleDomain<Symbol> tupleDomain = fromPredicate(metadata, session, node.getPredicate(), types).getTupleDomain(); if (source instanceof RowNumberNode) { Symbol rowNumberSymbol = ((RowNumberNode) source).getRowNumberSymbol(); OptionalInt upperBound = extractUpperBound(tupleDomain, rowNumberSymbol); if (upperBound.isPresent()) { source = mergeLimit(((RowNumberNode) source), upperBound.getAsInt()); return rewriteFilterSource(node, source, rowNumberSymbol, upperBound.getAsInt()); } } else if (source instanceof WindowNode && canOptimizeWindowFunction((WindowNode) source) && isOptimizeTopNRowNumber(session)) { WindowNode windowNode = (WindowNode) source; Symbol rowNumberSymbol = getOnlyElement(windowNode.getWindowFunctions().entrySet()).getKey(); OptionalInt upperBound = extractUpperBound(tupleDomain, rowNumberSymbol); if (upperBound.isPresent()) { source = convertToTopNRowNumber(windowNode, upperBound.getAsInt()); return rewriteFilterSource(node, source, rowNumberSymbol, upperBound.getAsInt()); } } return replaceChildren(node, ImmutableList.of(source)); }
disjuncts.add(combineRangeWithExcludedPoints(type, reference, range, singleValuesInRange)); continue; disjuncts.add(processRange(type, range, reference));
private IndexSourceRewriter(SymbolAllocator symbolAllocator, PlanNodeIdAllocator idAllocator, Metadata metadata, Session session) { this.metadata = requireNonNull(metadata, "metadata is null"); this.domainTranslator = new DomainTranslator(new LiteralEncoder(metadata.getBlockEncodingSerde())); this.symbolAllocator = requireNonNull(symbolAllocator, "symbolAllocator is null"); this.idAllocator = requireNonNull(idAllocator, "idAllocator is null"); this.session = requireNonNull(session, "session is null"); }
DomainTranslator.ExtractionResult decomposedPredicate = DomainTranslator.fromPredicate( metadata, session, domainTranslator.toPredicate(newDomain.simplify().transform(assignments::get)))); constraint = new Constraint<>(newDomain, evaluator::isCandidate); domainTranslator.toPredicate(layout.getUnenforcedConstraint().transform(assignments::get)), filterNonDeterministicConjuncts(predicate), decomposedPredicate.getRemainingExpression());
private static Expression toPredicate(TupleDomain<Symbol> tupleDomain) { return DomainTranslator.toPredicate(tupleDomain); }