use of io.trino.sql.planner.plan.FilterNode in project trino by trinodb.
the class SimpleFilterProjectSemiJoinStatsRule method calculate.
private Optional<PlanNodeStatsEstimate> calculate(FilterNode filterNode, SemiJoinNode semiJoinNode, StatsProvider statsProvider, Session session, TypeProvider types) {
PlanNodeStatsEstimate sourceStats = statsProvider.getStats(semiJoinNode.getSource());
PlanNodeStatsEstimate filteringSourceStats = statsProvider.getStats(semiJoinNode.getFilteringSource());
Symbol filteringSourceJoinSymbol = semiJoinNode.getFilteringSourceJoinSymbol();
Symbol sourceJoinSymbol = semiJoinNode.getSourceJoinSymbol();
Optional<SemiJoinOutputFilter> semiJoinOutputFilter = extractSemiJoinOutputFilter(filterNode.getPredicate(), semiJoinNode.getSemiJoinOutput());
if (semiJoinOutputFilter.isEmpty()) {
return Optional.empty();
}
PlanNodeStatsEstimate semiJoinStats;
if (semiJoinOutputFilter.get().isNegated()) {
semiJoinStats = computeAntiJoin(sourceStats, filteringSourceStats, sourceJoinSymbol, filteringSourceJoinSymbol);
} else {
semiJoinStats = computeSemiJoin(sourceStats, filteringSourceStats, sourceJoinSymbol, filteringSourceJoinSymbol);
}
if (semiJoinStats.isOutputRowCountUnknown()) {
return Optional.of(PlanNodeStatsEstimate.unknown());
}
// apply remaining predicate
PlanNodeStatsEstimate filteredStats = filterStatsCalculator.filterStats(semiJoinStats, semiJoinOutputFilter.get().getRemainingPredicate(), session, types);
if (filteredStats.isOutputRowCountUnknown()) {
return Optional.of(semiJoinStats.mapOutputRowCount(rowCount -> rowCount * UNKNOWN_FILTER_COEFFICIENT));
}
return Optional.of(filteredStats);
}
use of io.trino.sql.planner.plan.FilterNode in project trino by trinodb.
the class RelationPlanner method addRowFilters.
public RelationPlan addRowFilters(Table node, RelationPlan plan, Function<Expression, Expression> predicateTransformation, Function<Table, Scope> accessControlScope) {
List<Expression> filters = analysis.getRowFilters(node);
if (filters.isEmpty()) {
return plan;
}
PlanBuilder planBuilder = newPlanBuilder(plan, analysis, lambdaDeclarationToSymbolMap).withScope(accessControlScope.apply(node), // The fields in the access control scope has the same layout as those for the table scope
plan.getFieldMappings());
for (Expression filter : filters) {
planBuilder = subqueryPlanner.handleSubqueries(planBuilder, filter, analysis.getSubqueries(filter));
Expression predicate = planBuilder.rewrite(filter);
predicate = predicateTransformation.apply(predicate);
planBuilder = planBuilder.withNewRoot(new FilterNode(idAllocator.getNextId(), planBuilder.getRoot(), predicate));
}
return new RelationPlan(planBuilder.getRoot(), plan.getScope(), plan.getFieldMappings(), outerContext);
}
use of io.trino.sql.planner.plan.FilterNode in project trino by trinodb.
the class FilterMatcher method detailMatches.
@Override
public MatchResult detailMatches(PlanNode node, StatsProvider stats, Session session, Metadata metadata, SymbolAliases symbolAliases) {
checkState(shapeMatches(node), "Plan testing framework error: shapeMatches returned false in detailMatches in %s", this.getClass().getName());
FilterNode filterNode = (FilterNode) node;
Expression filterPredicate = filterNode.getPredicate();
ExpressionVerifier verifier = new ExpressionVerifier(symbolAliases);
if (dynamicFilter.isPresent()) {
return new MatchResult(verifier.process(filterPredicate, combineConjuncts(metadata, predicate, dynamicFilter.get())));
}
DynamicFilters.ExtractResult extractResult = extractDynamicFilters(filterPredicate);
return new MatchResult(verifier.process(combineConjuncts(metadata, extractResult.getStaticConjuncts()), predicate));
}
use of io.trino.sql.planner.plan.FilterNode in project trino by trinodb.
the class TestRuleIndex method testWithPlanNodeHierarchy.
@Test
public void testWithPlanNodeHierarchy() {
Rule<?> projectRule1 = new NoOpRule<>(Pattern.typeOf(ProjectNode.class));
Rule<?> projectRule2 = new NoOpRule<>(Pattern.typeOf(ProjectNode.class));
Rule<?> filterRule = new NoOpRule<>(Pattern.typeOf(FilterNode.class));
Rule<?> anyRule = new NoOpRule<>(Pattern.any());
RuleIndex ruleIndex = RuleIndex.builder().register(projectRule1).register(projectRule2).register(filterRule).register(anyRule).build();
ProjectNode projectNode = planBuilder.project(Assignments.of(), planBuilder.values());
FilterNode filterNode = planBuilder.filter(BooleanLiteral.TRUE_LITERAL, planBuilder.values());
ValuesNode valuesNode = planBuilder.values();
assertEquals(ruleIndex.getCandidates(projectNode).collect(toSet()), ImmutableSet.of(projectRule1, projectRule2, anyRule));
assertEquals(ruleIndex.getCandidates(filterNode).collect(toSet()), ImmutableSet.of(filterRule, anyRule));
assertEquals(ruleIndex.getCandidates(valuesNode).collect(toSet()), ImmutableSet.of(anyRule));
}
use of io.trino.sql.planner.plan.FilterNode in project trino by trinodb.
the class SemiJoinMatcher method detailMatches.
@Override
public MatchResult detailMatches(PlanNode node, StatsProvider stats, Session session, Metadata metadata, SymbolAliases symbolAliases) {
checkState(shapeMatches(node), "Plan testing framework error: shapeMatches returned false in detailMatches in %s", this.getClass().getName());
SemiJoinNode semiJoinNode = (SemiJoinNode) node;
if (!(symbolAliases.get(sourceSymbolAlias).equals(semiJoinNode.getSourceJoinSymbol().toSymbolReference()) && symbolAliases.get(filteringSymbolAlias).equals(semiJoinNode.getFilteringSourceJoinSymbol().toSymbolReference()))) {
return NO_MATCH;
}
if (distributionType.isPresent() && !distributionType.equals(semiJoinNode.getDistributionType())) {
return NO_MATCH;
}
if (hasDynamicFilter.isPresent()) {
if (hasDynamicFilter.get()) {
if (semiJoinNode.getDynamicFilterId().isEmpty()) {
return NO_MATCH;
}
DynamicFilterId dynamicFilterId = semiJoinNode.getDynamicFilterId().get();
List<DynamicFilters.Descriptor> matchingDescriptors = searchFrom(semiJoinNode.getSource()).where(FilterNode.class::isInstance).findAll().stream().flatMap(filterNode -> extractExpressions(filterNode).stream()).flatMap(expression -> extractDynamicFilters(expression).getDynamicConjuncts().stream()).filter(descriptor -> descriptor.getId().equals(dynamicFilterId)).collect(toImmutableList());
boolean sourceSymbolsMatch = matchingDescriptors.stream().map(descriptor -> Symbol.from(descriptor.getInput())).allMatch(sourceSymbol -> symbolAliases.get(sourceSymbolAlias).equals(sourceSymbol.toSymbolReference()));
if (!matchingDescriptors.isEmpty() && sourceSymbolsMatch) {
return match(outputAlias, semiJoinNode.getSemiJoinOutput().toSymbolReference());
}
return NO_MATCH;
}
if (semiJoinNode.getDynamicFilterId().isPresent()) {
return NO_MATCH;
}
}
return match(outputAlias, semiJoinNode.getSemiJoinOutput().toSymbolReference());
}
Aggregations