use of io.trino.sql.planner.plan.FilterNode in project trino by trinodb.
the class TransformFilteringSemiJoinToInnerJoin method apply.
@Override
public Result apply(FilterNode filterNode, Captures captures, Context context) {
SemiJoinNode semiJoin = captures.get(SEMI_JOIN);
// Do not transform semi-join in context of DELETE
if (PlanNodeSearcher.searchFrom(semiJoin.getSource(), context.getLookup()).where(node -> node instanceof TableScanNode && ((TableScanNode) node).isUpdateTarget()).matches()) {
return Result.empty();
}
Symbol semiJoinSymbol = semiJoin.getSemiJoinOutput();
Predicate<Expression> isSemiJoinSymbol = expression -> expression.equals(semiJoinSymbol.toSymbolReference());
List<Expression> conjuncts = extractConjuncts(filterNode.getPredicate());
if (conjuncts.stream().noneMatch(isSemiJoinSymbol)) {
return Result.empty();
}
Expression filteredPredicate = and(conjuncts.stream().filter(not(isSemiJoinSymbol)).collect(toImmutableList()));
Expression simplifiedPredicate = inlineSymbols(symbol -> {
if (symbol.equals(semiJoinSymbol)) {
return TRUE_LITERAL;
}
return symbol.toSymbolReference();
}, filteredPredicate);
Optional<Expression> joinFilter = simplifiedPredicate.equals(TRUE_LITERAL) ? Optional.empty() : Optional.of(simplifiedPredicate);
PlanNode filteringSourceDistinct = new AggregationNode(context.getIdAllocator().getNextId(), semiJoin.getFilteringSource(), ImmutableMap.of(), singleGroupingSet(ImmutableList.of(semiJoin.getFilteringSourceJoinSymbol())), ImmutableList.of(), SINGLE, Optional.empty(), Optional.empty());
JoinNode innerJoin = new JoinNode(semiJoin.getId(), INNER, semiJoin.getSource(), filteringSourceDistinct, ImmutableList.of(new EquiJoinClause(semiJoin.getSourceJoinSymbol(), semiJoin.getFilteringSourceJoinSymbol())), semiJoin.getSource().getOutputSymbols(), ImmutableList.of(), false, joinFilter, Optional.empty(), Optional.empty(), Optional.empty(), Optional.empty(), semiJoin.getDynamicFilterId().map(id -> ImmutableMap.of(id, semiJoin.getFilteringSourceJoinSymbol())).orElse(ImmutableMap.of()), Optional.empty());
ProjectNode project = new ProjectNode(context.getIdAllocator().getNextId(), innerJoin, Assignments.builder().putIdentities(innerJoin.getOutputSymbols()).put(semiJoinSymbol, TRUE_LITERAL).build());
return Result.ofPlanNode(project);
}
use of io.trino.sql.planner.plan.FilterNode in project trino by trinodb.
the class PushdownFilterIntoWindow method apply.
@Override
public Result apply(FilterNode node, Captures captures, Context context) {
Session session = context.getSession();
TypeProvider types = context.getSymbolAllocator().getTypes();
WindowNode windowNode = captures.get(childCapture);
DomainTranslator.ExtractionResult extractionResult = DomainTranslator.getExtractionResult(plannerContext, session, node.getPredicate(), types);
TupleDomain<Symbol> tupleDomain = extractionResult.getTupleDomain();
Optional<RankingType> rankingType = toTopNRankingType(windowNode);
Symbol rankingSymbol = getOnlyElement(windowNode.getWindowFunctions().keySet());
OptionalInt upperBound = extractUpperBound(tupleDomain, rankingSymbol);
if (upperBound.isEmpty()) {
return Result.empty();
}
if (upperBound.getAsInt() <= 0) {
return Result.ofPlanNode(new ValuesNode(node.getId(), node.getOutputSymbols(), ImmutableList.of()));
}
TopNRankingNode newSource = new TopNRankingNode(windowNode.getId(), windowNode.getSource(), windowNode.getSpecification(), rankingType.get(), rankingSymbol, upperBound.getAsInt(), false, Optional.empty());
if (!allRowNumberValuesInDomain(tupleDomain, rankingSymbol, upperBound.getAsInt())) {
return Result.ofPlanNode(new FilterNode(node.getId(), newSource, node.getPredicate()));
}
// Remove the row number domain because it is absorbed into the node
TupleDomain<Symbol> newTupleDomain = tupleDomain.filter((symbol, domain) -> !symbol.equals(rankingSymbol));
Expression newPredicate = ExpressionUtils.combineConjuncts(plannerContext.getMetadata(), extractionResult.getRemainingExpression(), new DomainTranslator(plannerContext).toPredicate(session, newTupleDomain));
if (newPredicate.equals(BooleanLiteral.TRUE_LITERAL)) {
return Result.ofPlanNode(newSource);
}
return Result.ofPlanNode(new FilterNode(node.getId(), newSource, newPredicate));
}
use of io.trino.sql.planner.plan.FilterNode in project trino by trinodb.
the class TestEffectivePredicateExtractor method testInnerJoin.
@Test
public void testInnerJoin() {
ImmutableList.Builder<JoinNode.EquiJoinClause> criteriaBuilder = ImmutableList.builder();
criteriaBuilder.add(new JoinNode.EquiJoinClause(A, D));
criteriaBuilder.add(new JoinNode.EquiJoinClause(B, E));
List<JoinNode.EquiJoinClause> criteria = criteriaBuilder.build();
Map<Symbol, ColumnHandle> leftAssignments = Maps.filterKeys(scanAssignments, Predicates.in(ImmutableList.of(A, B, C)));
TableScanNode leftScan = tableScanNode(leftAssignments);
Map<Symbol, ColumnHandle> rightAssignments = Maps.filterKeys(scanAssignments, Predicates.in(ImmutableList.of(D, E, F)));
TableScanNode rightScan = tableScanNode(rightAssignments);
FilterNode left = filter(leftScan, and(lessThan(BE, AE), lessThan(CE, bigintLiteral(10)), equals(GE, bigintLiteral(10))));
FilterNode right = filter(rightScan, and(equals(DE, EE), lessThan(FE, bigintLiteral(100))));
PlanNode node = new JoinNode(newId(), JoinNode.Type.INNER, left, right, criteria, left.getOutputSymbols(), right.getOutputSymbols(), false, Optional.of(lessThanOrEqual(BE, EE)), Optional.empty(), Optional.empty(), Optional.empty(), Optional.empty(), ImmutableMap.of(), Optional.empty());
Expression effectivePredicate = effectivePredicateExtractor.extract(SESSION, node, TypeProvider.empty(), typeAnalyzer);
// All predicates having output symbol should be carried through
assertEquals(normalizeConjuncts(effectivePredicate), normalizeConjuncts(lessThan(BE, AE), lessThan(CE, bigintLiteral(10)), equals(DE, EE), lessThan(FE, bigintLiteral(100)), equals(AE, DE), equals(BE, EE), lessThanOrEqual(BE, EE)));
}
use of io.trino.sql.planner.plan.FilterNode in project trino by trinodb.
the class TestEffectivePredicateExtractor method testRightJoin.
@Test
public void testRightJoin() {
ImmutableList.Builder<JoinNode.EquiJoinClause> criteriaBuilder = ImmutableList.builder();
criteriaBuilder.add(new JoinNode.EquiJoinClause(A, D));
criteriaBuilder.add(new JoinNode.EquiJoinClause(B, E));
List<JoinNode.EquiJoinClause> criteria = criteriaBuilder.build();
Map<Symbol, ColumnHandle> leftAssignments = Maps.filterKeys(scanAssignments, Predicates.in(ImmutableList.of(A, B, C)));
TableScanNode leftScan = tableScanNode(leftAssignments);
Map<Symbol, ColumnHandle> rightAssignments = Maps.filterKeys(scanAssignments, Predicates.in(ImmutableList.of(D, E, F)));
TableScanNode rightScan = tableScanNode(rightAssignments);
FilterNode left = filter(leftScan, and(lessThan(BE, AE), lessThan(CE, bigintLiteral(10)), equals(GE, bigintLiteral(10))));
FilterNode right = filter(rightScan, and(equals(DE, EE), lessThan(FE, bigintLiteral(100))));
PlanNode node = new JoinNode(newId(), JoinNode.Type.RIGHT, left, right, criteria, left.getOutputSymbols(), right.getOutputSymbols(), false, Optional.empty(), Optional.empty(), Optional.empty(), Optional.empty(), Optional.empty(), ImmutableMap.of(), Optional.empty());
Expression effectivePredicate = effectivePredicateExtractor.extract(SESSION, node, TypeProvider.empty(), typeAnalyzer);
// All left side symbols should be checked against NULL
assertEquals(normalizeConjuncts(effectivePredicate), normalizeConjuncts(or(lessThan(BE, AE), and(isNull(BE), isNull(AE))), or(lessThan(CE, bigintLiteral(10)), isNull(CE)), equals(DE, EE), lessThan(FE, bigintLiteral(100)), or(equals(AE, DE), isNull(AE)), or(equals(BE, EE), isNull(BE))));
}
use of io.trino.sql.planner.plan.FilterNode in project trino by trinodb.
the class TestEffectivePredicateExtractor method testLeftJoin.
@Test
public void testLeftJoin() {
ImmutableList.Builder<JoinNode.EquiJoinClause> criteriaBuilder = ImmutableList.builder();
criteriaBuilder.add(new JoinNode.EquiJoinClause(A, D));
criteriaBuilder.add(new JoinNode.EquiJoinClause(B, E));
List<JoinNode.EquiJoinClause> criteria = criteriaBuilder.build();
Map<Symbol, ColumnHandle> leftAssignments = Maps.filterKeys(scanAssignments, Predicates.in(ImmutableList.of(A, B, C)));
TableScanNode leftScan = tableScanNode(leftAssignments);
Map<Symbol, ColumnHandle> rightAssignments = Maps.filterKeys(scanAssignments, Predicates.in(ImmutableList.of(D, E, F)));
TableScanNode rightScan = tableScanNode(rightAssignments);
FilterNode left = filter(leftScan, and(lessThan(BE, AE), lessThan(CE, bigintLiteral(10)), equals(GE, bigintLiteral(10))));
FilterNode right = filter(rightScan, and(equals(DE, EE), lessThan(FE, bigintLiteral(100))));
PlanNode node = new JoinNode(newId(), JoinNode.Type.LEFT, left, right, criteria, left.getOutputSymbols(), right.getOutputSymbols(), false, Optional.empty(), Optional.empty(), Optional.empty(), Optional.empty(), Optional.empty(), ImmutableMap.of(), Optional.empty());
Expression effectivePredicate = effectivePredicateExtractor.extract(SESSION, node, TypeProvider.empty(), typeAnalyzer);
// All right side symbols having output symbols should be checked against NULL
assertEquals(normalizeConjuncts(effectivePredicate), normalizeConjuncts(lessThan(BE, AE), lessThan(CE, bigintLiteral(10)), or(equals(DE, EE), and(isNull(DE), isNull(EE))), or(lessThan(FE, bigintLiteral(100)), isNull(FE)), or(equals(AE, DE), isNull(DE)), or(equals(BE, EE), isNull(EE))));
}
Aggregations