use of io.trino.sql.planner.plan.ProjectNode in project trino by trinodb.
the class PushProjectionThroughJoin method inlineProjections.
private static PlanNode inlineProjections(PlannerContext plannerContext, ProjectNode parentProjection, Lookup lookup, Session session, TypeAnalyzer typeAnalyzer, TypeProvider types) {
PlanNode child = lookup.resolve(parentProjection.getSource());
if (!(child instanceof ProjectNode)) {
return parentProjection;
}
ProjectNode childProjection = (ProjectNode) child;
return InlineProjections.inlineProjections(plannerContext, parentProjection, childProjection, session, typeAnalyzer, types).map(node -> inlineProjections(plannerContext, node, lookup, session, typeAnalyzer, types)).orElse(parentProjection);
}
use of io.trino.sql.planner.plan.ProjectNode in project trino by trinodb.
the class PushProjectionThroughJoin method pushProjectionThroughJoin.
public static Optional<PlanNode> pushProjectionThroughJoin(PlannerContext plannerContext, ProjectNode projectNode, Lookup lookup, PlanNodeIdAllocator planNodeIdAllocator, Session session, TypeAnalyzer typeAnalyzer, TypeProvider types) {
if (!projectNode.getAssignments().getExpressions().stream().allMatch(expression -> isDeterministic(expression, plannerContext.getMetadata()))) {
return Optional.empty();
}
PlanNode child = lookup.resolve(projectNode.getSource());
if (!(child instanceof JoinNode)) {
return Optional.empty();
}
JoinNode joinNode = (JoinNode) child;
PlanNode leftChild = joinNode.getLeft();
PlanNode rightChild = joinNode.getRight();
if (joinNode.getType() != INNER) {
return Optional.empty();
}
Assignments.Builder leftAssignmentsBuilder = Assignments.builder();
Assignments.Builder rightAssignmentsBuilder = Assignments.builder();
for (Map.Entry<Symbol, Expression> assignment : projectNode.getAssignments().entrySet()) {
Expression expression = assignment.getValue();
Set<Symbol> symbols = extractUnique(expression);
if (leftChild.getOutputSymbols().containsAll(symbols)) {
// expression is satisfied with left child symbols
leftAssignmentsBuilder.put(assignment.getKey(), expression);
} else if (rightChild.getOutputSymbols().containsAll(symbols)) {
// expression is satisfied with right child symbols
rightAssignmentsBuilder.put(assignment.getKey(), expression);
} else {
// expression is using symbols from both join sides
return Optional.empty();
}
}
// add projections for symbols required by the join itself
Set<Symbol> joinRequiredSymbols = getJoinRequiredSymbols(joinNode);
for (Symbol requiredSymbol : joinRequiredSymbols) {
if (leftChild.getOutputSymbols().contains(requiredSymbol)) {
leftAssignmentsBuilder.putIdentity(requiredSymbol);
} else {
checkState(rightChild.getOutputSymbols().contains(requiredSymbol));
rightAssignmentsBuilder.putIdentity(requiredSymbol);
}
}
Assignments leftAssignments = leftAssignmentsBuilder.build();
Assignments rightAssignments = rightAssignmentsBuilder.build();
List<Symbol> leftOutputSymbols = leftAssignments.getOutputs().stream().filter(ImmutableSet.copyOf(projectNode.getOutputSymbols())::contains).collect(toImmutableList());
List<Symbol> rightOutputSymbols = rightAssignments.getOutputs().stream().filter(ImmutableSet.copyOf(projectNode.getOutputSymbols())::contains).collect(toImmutableList());
return Optional.of(new JoinNode(joinNode.getId(), joinNode.getType(), inlineProjections(plannerContext, new ProjectNode(planNodeIdAllocator.getNextId(), leftChild, leftAssignments), lookup, session, typeAnalyzer, types), inlineProjections(plannerContext, new ProjectNode(planNodeIdAllocator.getNextId(), rightChild, rightAssignments), lookup, session, typeAnalyzer, types), joinNode.getCriteria(), leftOutputSymbols, rightOutputSymbols, joinNode.isMaySkipOutputDuplicates(), joinNode.getFilter(), joinNode.getLeftHashSymbol(), joinNode.getRightHashSymbol(), joinNode.getDistributionType(), joinNode.isSpillable(), joinNode.getDynamicFilters(), joinNode.getReorderJoinStatsAndCost()));
}
use of io.trino.sql.planner.plan.ProjectNode in project trino by trinodb.
the class PushProjectionThroughUnion method apply.
@Override
public Result apply(ProjectNode parent, Captures captures, Context context) {
UnionNode source = captures.get(CHILD);
// OutputLayout of the resultant Union, will be same as the layout of the Project
List<Symbol> outputLayout = parent.getOutputSymbols();
// Mapping from the output symbol to ordered list of symbols from each of the sources
ImmutableListMultimap.Builder<Symbol, Symbol> mappings = ImmutableListMultimap.builder();
// sources for the resultant UnionNode
ImmutableList.Builder<PlanNode> outputSources = ImmutableList.builder();
for (int i = 0; i < source.getSources().size(); i++) {
// Map: output of union -> input of this source to the union
Map<Symbol, SymbolReference> outputToInput = source.sourceSymbolMap(i);
// assignments for the new ProjectNode
Assignments.Builder assignments = Assignments.builder();
// mapping from current ProjectNode to new ProjectNode, used to identify the output layout
Map<Symbol, Symbol> projectSymbolMapping = new HashMap<>();
// Translate the assignments in the ProjectNode using symbols of the source of the UnionNode
for (Map.Entry<Symbol, Expression> entry : parent.getAssignments().entrySet()) {
Expression translatedExpression = inlineSymbols(outputToInput, entry.getValue());
Type type = context.getSymbolAllocator().getTypes().get(entry.getKey());
Symbol symbol = context.getSymbolAllocator().newSymbol(translatedExpression, type);
assignments.put(symbol, translatedExpression);
projectSymbolMapping.put(entry.getKey(), symbol);
}
outputSources.add(new ProjectNode(context.getIdAllocator().getNextId(), source.getSources().get(i), assignments.build()));
outputLayout.forEach(symbol -> mappings.put(symbol, projectSymbolMapping.get(symbol)));
}
return Result.ofPlanNode(new UnionNode(parent.getId(), outputSources.build(), mappings.build(), ImmutableList.copyOf(mappings.build().keySet())));
}
use of io.trino.sql.planner.plan.ProjectNode in project trino by trinodb.
the class RewriteSpatialPartitioningAggregation method apply.
@Override
public Result apply(AggregationNode node, Captures captures, Context context) {
ResolvedFunction spatialPartitioningFunction = plannerContext.getMetadata().resolveFunction(context.getSession(), QualifiedName.of(NAME), fromTypeSignatures(GEOMETRY_TYPE_SIGNATURE, INTEGER.getTypeSignature()));
ResolvedFunction stEnvelopeFunction = plannerContext.getMetadata().resolveFunction(context.getSession(), QualifiedName.of("ST_Envelope"), fromTypeSignatures(GEOMETRY_TYPE_SIGNATURE));
ImmutableMap.Builder<Symbol, Aggregation> aggregations = ImmutableMap.builder();
Symbol partitionCountSymbol = context.getSymbolAllocator().newSymbol("partition_count", INTEGER);
ImmutableMap.Builder<Symbol, Expression> envelopeAssignments = ImmutableMap.builder();
for (Map.Entry<Symbol, Aggregation> entry : node.getAggregations().entrySet()) {
Aggregation aggregation = entry.getValue();
String name = aggregation.getResolvedFunction().getSignature().getName();
if (name.equals(NAME) && aggregation.getArguments().size() == 1) {
Expression geometry = getOnlyElement(aggregation.getArguments());
Symbol envelopeSymbol = context.getSymbolAllocator().newSymbol("envelope", plannerContext.getTypeManager().getType(GEOMETRY_TYPE_SIGNATURE));
if (isStEnvelopeFunctionCall(geometry, stEnvelopeFunction)) {
envelopeAssignments.put(envelopeSymbol, geometry);
} else {
envelopeAssignments.put(envelopeSymbol, FunctionCallBuilder.resolve(context.getSession(), plannerContext.getMetadata()).setName(QualifiedName.of("ST_Envelope")).addArgument(GEOMETRY_TYPE_SIGNATURE, geometry).build());
}
aggregations.put(entry.getKey(), new Aggregation(spatialPartitioningFunction, ImmutableList.of(envelopeSymbol.toSymbolReference(), partitionCountSymbol.toSymbolReference()), false, Optional.empty(), Optional.empty(), aggregation.getMask()));
} else {
aggregations.put(entry);
}
}
return Result.ofPlanNode(new AggregationNode(node.getId(), new ProjectNode(context.getIdAllocator().getNextId(), node.getSource(), Assignments.builder().putIdentities(node.getSource().getOutputSymbols()).put(partitionCountSymbol, new LongLiteral(Integer.toString(getHashPartitionCount(context.getSession())))).putAll(envelopeAssignments.buildOrThrow()).build()), aggregations.buildOrThrow(), node.getGroupingSets(), node.getPreGroupedSymbols(), node.getStep(), node.getHashSymbol(), node.getGroupIdSymbol()));
}
use of io.trino.sql.planner.plan.ProjectNode in project trino by trinodb.
the class SetOperationNodeTranslator method appendMarkers.
private static PlanNode appendMarkers(PlanNodeIdAllocator idAllocator, SymbolAllocator symbolAllocator, PlanNode source, int markerIndex, List<Symbol> markers, Map<Symbol, SymbolReference> projections) {
Assignments.Builder assignments = Assignments.builder();
// add existing intersect symbols to projection
for (Map.Entry<Symbol, SymbolReference> entry : projections.entrySet()) {
Symbol symbol = symbolAllocator.newSymbol(entry.getKey().getName(), symbolAllocator.getTypes().get(entry.getKey()));
assignments.put(symbol, entry.getValue());
}
// add extra marker fields to the projection
for (int i = 0; i < markers.size(); ++i) {
Expression expression = (i == markerIndex) ? TRUE_LITERAL : new Cast(new NullLiteral(), toSqlType(BOOLEAN));
assignments.put(symbolAllocator.newSymbol(markers.get(i).getName(), BOOLEAN), expression);
}
return new ProjectNode(idAllocator.getNextId(), source, assignments.build());
}
Aggregations