use of io.trino.sql.planner.plan.PlanNode in project trino by trinodb.
the class DecorrelateLeftUnnestWithGlobalAggregation method isSupportedUnnest.
/**
* This rule supports decorrelation of UnnestNode meeting certain conditions:
* - the UnnestNode should be based on correlation symbols, that is: either unnest correlation symbols directly,
* or unnest symbols produced by a projection that uses only correlation symbols.
* - the UnnestNode should not have any replicate symbols,
* - the UnnestNode should be of type LEFT,
* - the UnnestNode should not have a filter.
*/
private static boolean isSupportedUnnest(PlanNode node, List<Symbol> correlation, Lookup lookup) {
if (!(node instanceof UnnestNode)) {
return false;
}
UnnestNode unnestNode = (UnnestNode) node;
List<Symbol> unnestSymbols = unnestNode.getMappings().stream().map(UnnestNode.Mapping::getInput).collect(toImmutableList());
PlanNode unnestSource = lookup.resolve(unnestNode.getSource());
boolean basedOnCorrelation = ImmutableSet.copyOf(correlation).containsAll(unnestSymbols) || unnestSource instanceof ProjectNode && ImmutableSet.copyOf(correlation).containsAll(SymbolsExtractor.extractUnique(((ProjectNode) unnestSource).getAssignments().getExpressions()));
return isScalar(unnestNode.getSource(), lookup) && unnestNode.getReplicateSymbols().isEmpty() && basedOnCorrelation && unnestNode.getJoinType() == LEFT && (unnestNode.getFilter().isEmpty() || unnestNode.getFilter().get().equals(TRUE_LITERAL));
}
use of io.trino.sql.planner.plan.PlanNode in project trino by trinodb.
the class DecorrelateUnnest method isSupportedUnnest.
/**
* This rule supports decorrelation of UnnestNode meeting certain conditions:
* - the UnnestNode should be based on correlation symbols, that is: either unnest correlation symbols directly,
* or unnest symbols produced by a projection that uses only correlation symbols.
* - the UnnestNode should not have any replicate symbols,
* - the UnnestNode should be of type INNER or LEFT,
* - the UnnestNode should not have a filter.
*/
private static boolean isSupportedUnnest(PlanNode node, List<Symbol> correlation, Lookup lookup) {
if (!(node instanceof UnnestNode)) {
return false;
}
UnnestNode unnestNode = (UnnestNode) node;
List<Symbol> unnestSymbols = unnestNode.getMappings().stream().map(UnnestNode.Mapping::getInput).collect(toImmutableList());
PlanNode unnestSource = lookup.resolve(unnestNode.getSource());
boolean basedOnCorrelation = ImmutableSet.copyOf(correlation).containsAll(unnestSymbols) || unnestSource instanceof ProjectNode && ImmutableSet.copyOf(correlation).containsAll(SymbolsExtractor.extractUnique(((ProjectNode) unnestSource).getAssignments().getExpressions()));
return isScalar(unnestNode.getSource(), lookup) && unnestNode.getReplicateSymbols().isEmpty() && basedOnCorrelation && (unnestNode.getJoinType() == INNER || unnestNode.getJoinType() == LEFT) && (unnestNode.getFilter().isEmpty() || unnestNode.getFilter().get().equals(TRUE_LITERAL));
}
use of io.trino.sql.planner.plan.PlanNode in project trino by trinodb.
the class AddIntermediateAggregations method apply.
@Override
public Result apply(AggregationNode aggregation, Captures captures, Context context) {
Lookup lookup = context.getLookup();
PlanNodeIdAllocator idAllocator = context.getIdAllocator();
Session session = context.getSession();
Optional<PlanNode> rewrittenSource = recurseToPartial(lookup.resolve(aggregation.getSource()), lookup, idAllocator);
if (rewrittenSource.isEmpty()) {
return Result.empty();
}
PlanNode source = rewrittenSource.get();
if (getTaskConcurrency(session) > 1) {
source = ExchangeNode.partitionedExchange(idAllocator.getNextId(), ExchangeNode.Scope.LOCAL, source, new PartitioningScheme(Partitioning.create(FIXED_ARBITRARY_DISTRIBUTION, ImmutableList.of()), source.getOutputSymbols()));
source = new AggregationNode(idAllocator.getNextId(), source, inputsAsOutputs(aggregation.getAggregations()), aggregation.getGroupingSets(), aggregation.getPreGroupedSymbols(), AggregationNode.Step.INTERMEDIATE, aggregation.getHashSymbol(), aggregation.getGroupIdSymbol());
source = ExchangeNode.gatheringExchange(idAllocator.getNextId(), ExchangeNode.Scope.LOCAL, source);
}
return Result.ofPlanNode(aggregation.replaceChildren(ImmutableList.of(source)));
}
use of io.trino.sql.planner.plan.PlanNode in project trino by trinodb.
the class MultipleDistinctAggregationToMarkDistinct method apply.
@Override
public Result apply(AggregationNode parent, Captures captures, Context context) {
if (!SystemSessionProperties.useMarkDistinct(context.getSession())) {
return Result.empty();
}
// the distinct marker for the given set of input columns
Map<Set<Symbol>, Symbol> markers = new HashMap<>();
Map<Symbol, Aggregation> newAggregations = new HashMap<>();
PlanNode subPlan = parent.getSource();
for (Map.Entry<Symbol, Aggregation> entry : parent.getAggregations().entrySet()) {
Aggregation aggregation = entry.getValue();
if (aggregation.isDistinct() && aggregation.getFilter().isEmpty() && aggregation.getMask().isEmpty()) {
Set<Symbol> inputs = aggregation.getArguments().stream().map(Symbol::from).collect(toSet());
Symbol marker = markers.get(inputs);
if (marker == null) {
marker = context.getSymbolAllocator().newSymbol(Iterables.getLast(inputs).getName(), BOOLEAN, "distinct");
markers.put(inputs, marker);
ImmutableSet.Builder<Symbol> distinctSymbols = ImmutableSet.<Symbol>builder().addAll(parent.getGroupingKeys()).addAll(inputs);
parent.getGroupIdSymbol().ifPresent(distinctSymbols::add);
subPlan = new MarkDistinctNode(context.getIdAllocator().getNextId(), subPlan, marker, ImmutableList.copyOf(distinctSymbols.build()), Optional.empty());
}
// remove the distinct flag and set the distinct marker
newAggregations.put(entry.getKey(), new Aggregation(aggregation.getResolvedFunction(), aggregation.getArguments(), false, aggregation.getFilter(), aggregation.getOrderingScheme(), Optional.of(marker)));
} else {
newAggregations.put(entry.getKey(), aggregation);
}
}
return Result.ofPlanNode(new AggregationNode(parent.getId(), subPlan, newAggregations, parent.getGroupingSets(), ImmutableList.of(), parent.getStep(), parent.getHashSymbol(), parent.getGroupIdSymbol()));
}
use of io.trino.sql.planner.plan.PlanNode in project trino by trinodb.
the class PruneApplyColumns method pushDownProjectOff.
@Override
protected Optional<PlanNode> pushDownProjectOff(Context context, ApplyNode applyNode, Set<Symbol> referencedOutputs) {
// remove unused apply node
if (intersection(applyNode.getSubqueryAssignments().getSymbols(), referencedOutputs).isEmpty()) {
return Optional.of(applyNode.getInput());
}
// extract referenced assignments
ImmutableSet.Builder<Symbol> requiredAssignmentsSymbols = ImmutableSet.builder();
Assignments.Builder newSubqueryAssignments = Assignments.builder();
for (Map.Entry<Symbol, Expression> entry : applyNode.getSubqueryAssignments().entrySet()) {
if (referencedOutputs.contains(entry.getKey())) {
requiredAssignmentsSymbols.addAll(extractUnique(entry.getValue()));
newSubqueryAssignments.put(entry);
}
}
// prune subquery symbols
Optional<PlanNode> newSubquery = restrictOutputs(context.getIdAllocator(), applyNode.getSubquery(), requiredAssignmentsSymbols.build());
// prune input symbols
Set<Symbol> requiredInputSymbols = ImmutableSet.<Symbol>builder().addAll(referencedOutputs).addAll(applyNode.getCorrelation()).addAll(requiredAssignmentsSymbols.build()).build();
Optional<PlanNode> newInput = restrictOutputs(context.getIdAllocator(), applyNode.getInput(), requiredInputSymbols);
boolean pruned = newSubquery.isPresent() || newInput.isPresent() || newSubqueryAssignments.build().size() < applyNode.getSubqueryAssignments().size();
if (pruned) {
return Optional.of(new ApplyNode(applyNode.getId(), newInput.orElse(applyNode.getInput()), newSubquery.orElse(applyNode.getSubquery()), newSubqueryAssignments.build(), applyNode.getCorrelation(), applyNode.getOriginSubquery()));
}
return Optional.empty();
}
Aggregations