use of io.trino.sql.planner.plan.PlanNode in project trino by trinodb.
the class PruneWindowColumns method pushDownProjectOff.
@Override
protected Optional<PlanNode> pushDownProjectOff(Context context, WindowNode windowNode, Set<Symbol> referencedOutputs) {
Map<Symbol, WindowNode.Function> referencedFunctions = Maps.filterKeys(windowNode.getWindowFunctions(), referencedOutputs::contains);
if (referencedFunctions.isEmpty()) {
return Optional.of(windowNode.getSource());
}
ImmutableSet.Builder<Symbol> referencedInputs = ImmutableSet.<Symbol>builder().addAll(windowNode.getSource().getOutputSymbols().stream().filter(referencedOutputs::contains).iterator()).addAll(windowNode.getPartitionBy());
windowNode.getOrderingScheme().ifPresent(orderingScheme -> orderingScheme.getOrderBy().forEach(referencedInputs::add));
windowNode.getHashSymbol().ifPresent(referencedInputs::add);
for (WindowNode.Function windowFunction : referencedFunctions.values()) {
referencedInputs.addAll(SymbolsExtractor.extractUnique(windowFunction));
}
PlanNode prunedWindowNode = new WindowNode(windowNode.getId(), restrictOutputs(context.getIdAllocator(), windowNode.getSource(), referencedInputs.build()).orElse(windowNode.getSource()), windowNode.getSpecification(), referencedFunctions, windowNode.getHashSymbol(), windowNode.getPrePartitionedInputs(), windowNode.getPreSortedOrderPrefix());
if (prunedWindowNode.getOutputSymbols().size() == windowNode.getOutputSymbols().size()) {
// Neither function pruning nor input pruning was successful.
return Optional.empty();
}
return Optional.of(prunedWindowNode);
}
use of io.trino.sql.planner.plan.PlanNode in project trino by trinodb.
the class PushAggregationThroughOuterJoin method getInnerTable.
private static PlanNode getInnerTable(JoinNode join) {
checkState(join.getType() == JoinNode.Type.LEFT || join.getType() == JoinNode.Type.RIGHT, "expected LEFT or RIGHT JOIN");
PlanNode innerNode;
if (join.getType() == JoinNode.Type.LEFT) {
innerNode = join.getRight();
} else {
innerNode = join.getLeft();
}
return innerNode;
}
use of io.trino.sql.planner.plan.PlanNode in project trino by trinodb.
the class PushDownDereferenceThroughFilter method apply.
@Override
public Result apply(ProjectNode node, Captures captures, Rule.Context context) {
FilterNode filterNode = captures.get(CHILD);
// Pushdown superset of dereference expressions from projections and filtering predicate
List<Expression> expressions = ImmutableList.<Expression>builder().addAll(node.getAssignments().getExpressions()).add(filterNode.getPredicate()).build();
// Extract dereferences from project node assignments for pushdown
Set<SubscriptExpression> dereferences = extractRowSubscripts(expressions, false, context.getSession(), typeAnalyzer, context.getSymbolAllocator().getTypes());
if (dereferences.isEmpty()) {
return Result.empty();
}
// Create new symbols for dereference expressions
Assignments dereferenceAssignments = Assignments.of(dereferences, context.getSession(), context.getSymbolAllocator(), typeAnalyzer);
// Rewrite project node assignments using new symbols for dereference expressions
Map<Expression, SymbolReference> mappings = HashBiMap.create(dereferenceAssignments.getMap()).inverse().entrySet().stream().collect(toImmutableMap(Map.Entry::getKey, entry -> entry.getValue().toSymbolReference()));
Assignments assignments = node.getAssignments().rewrite(expression -> replaceExpression(expression, mappings));
PlanNode source = filterNode.getSource();
return Result.ofPlanNode(new ProjectNode(context.getIdAllocator().getNextId(), new FilterNode(context.getIdAllocator().getNextId(), new ProjectNode(context.getIdAllocator().getNextId(), source, Assignments.builder().putIdentities(source.getOutputSymbols()).putAll(dereferenceAssignments).build()), replaceExpression(filterNode.getPredicate(), mappings)), assignments));
}
use of io.trino.sql.planner.plan.PlanNode in project trino by trinodb.
the class TransformCorrelatedDistinctAggregationWithProjection method apply.
@Override
public Result apply(CorrelatedJoinNode correlatedJoinNode, Captures captures, Context context) {
// decorrelate nested plan
PlanNodeDecorrelator decorrelator = new PlanNodeDecorrelator(plannerContext, context.getSymbolAllocator(), context.getLookup());
Optional<PlanNodeDecorrelator.DecorrelatedNode> decorrelatedSource = decorrelator.decorrelateFilters(captures.get(AGGREGATION).getSource(), correlatedJoinNode.getCorrelation());
if (decorrelatedSource.isEmpty()) {
return Result.empty();
}
PlanNode source = decorrelatedSource.get().getNode();
// assign unique id on correlated join's input. It will be used to distinguish between original input rows after join
PlanNode inputWithUniqueId = new AssignUniqueId(context.getIdAllocator().getNextId(), correlatedJoinNode.getInput(), context.getSymbolAllocator().newSymbol("unique", BIGINT));
JoinNode join = new JoinNode(context.getIdAllocator().getNextId(), JoinNode.Type.LEFT, inputWithUniqueId, source, ImmutableList.of(), inputWithUniqueId.getOutputSymbols(), source.getOutputSymbols(), false, decorrelatedSource.get().getCorrelatedPredicates(), Optional.empty(), Optional.empty(), Optional.empty(), Optional.empty(), ImmutableMap.of(), Optional.empty());
// restore aggregation
AggregationNode aggregation = captures.get(AGGREGATION);
aggregation = new AggregationNode(aggregation.getId(), join, aggregation.getAggregations(), singleGroupingSet(ImmutableList.<Symbol>builder().addAll(join.getLeftOutputSymbols()).addAll(aggregation.getGroupingKeys()).build()), ImmutableList.of(), aggregation.getStep(), Optional.empty(), Optional.empty());
// restrict outputs and apply projection
Set<Symbol> outputSymbols = new HashSet<>(correlatedJoinNode.getOutputSymbols());
List<Symbol> expectedAggregationOutputs = aggregation.getOutputSymbols().stream().filter(outputSymbols::contains).collect(toImmutableList());
Assignments assignments = Assignments.builder().putIdentities(expectedAggregationOutputs).putAll(captures.get(PROJECTION).getAssignments()).build();
return Result.ofPlanNode(new ProjectNode(context.getIdAllocator().getNextId(), aggregation, assignments));
}
use of io.trino.sql.planner.plan.PlanNode in project trino by trinodb.
the class TransformCorrelatedDistinctAggregationWithoutProjection method apply.
@Override
public Result apply(CorrelatedJoinNode correlatedJoinNode, Captures captures, Context context) {
// decorrelate nested plan
PlanNodeDecorrelator decorrelator = new PlanNodeDecorrelator(plannerContext, context.getSymbolAllocator(), context.getLookup());
Optional<PlanNodeDecorrelator.DecorrelatedNode> decorrelatedSource = decorrelator.decorrelateFilters(captures.get(AGGREGATION).getSource(), correlatedJoinNode.getCorrelation());
if (decorrelatedSource.isEmpty()) {
return Result.empty();
}
PlanNode source = decorrelatedSource.get().getNode();
// assign unique id on correlated join's input. It will be used to distinguish between original input rows after join
PlanNode inputWithUniqueId = new AssignUniqueId(context.getIdAllocator().getNextId(), correlatedJoinNode.getInput(), context.getSymbolAllocator().newSymbol("unique", BIGINT));
JoinNode join = new JoinNode(context.getIdAllocator().getNextId(), JoinNode.Type.LEFT, inputWithUniqueId, source, ImmutableList.of(), inputWithUniqueId.getOutputSymbols(), source.getOutputSymbols(), false, decorrelatedSource.get().getCorrelatedPredicates(), Optional.empty(), Optional.empty(), Optional.empty(), Optional.empty(), ImmutableMap.of(), Optional.empty());
// restore aggregation
AggregationNode aggregation = captures.get(AGGREGATION);
aggregation = new AggregationNode(aggregation.getId(), join, aggregation.getAggregations(), singleGroupingSet(ImmutableList.<Symbol>builder().addAll(join.getLeftOutputSymbols()).addAll(aggregation.getGroupingKeys()).build()), ImmutableList.of(), aggregation.getStep(), Optional.empty(), Optional.empty());
// restrict outputs
Optional<PlanNode> project = restrictOutputs(context.getIdAllocator(), aggregation, ImmutableSet.copyOf(correlatedJoinNode.getOutputSymbols()));
return Result.ofPlanNode(project.orElse(aggregation));
}
Aggregations