use of com.facebook.presto.spi.plan.ProjectNode in project presto by prestodb.
the class ImplementOffset method apply.
@Override
public Result apply(OffsetNode parent, Captures captures, Context context) {
VariableReferenceExpression rowNumberSymbol = context.getVariableAllocator().newVariable("row_number", BIGINT);
RowNumberNode rowNumberNode = new RowNumberNode(parent.getSourceLocation(), context.getIdAllocator().getNextId(), parent.getSource(), ImmutableList.of(), rowNumberSymbol, Optional.empty(), Optional.empty());
FilterNode filterNode = new FilterNode(parent.getSourceLocation(), context.getIdAllocator().getNextId(), rowNumberNode, castToRowExpression(new ComparisonExpression(ComparisonExpression.Operator.GREATER_THAN, createSymbolReference(rowNumberSymbol), new GenericLiteral("BIGINT", Long.toString(parent.getCount())))));
ProjectNode projectNode = new ProjectNode(context.getIdAllocator().getNextId(), filterNode, identityAssignmentsAsSymbolReferences(parent.getOutputVariables()));
return Result.ofPlanNode(projectNode);
}
use of com.facebook.presto.spi.plan.ProjectNode in project presto by prestodb.
the class PlanRemotePojections method apply.
@Override
public Result apply(ProjectNode node, Captures captures, Rule.Context context) {
if (!node.getLocality().equals(UNKNOWN)) {
// Already planned
return Result.empty();
}
// Fast check for remote functions
if (node.getAssignments().getExpressions().stream().noneMatch(expression -> expression.accept(new ExternalCallExpressionChecker(functionAndTypeManager), null))) {
// No remote function
return Result.ofPlanNode(new ProjectNode(node.getSourceLocation(), node.getId(), node.getSource(), node.getAssignments(), LOCAL));
}
if (!isRemoteFunctionsEnabled(context.getSession())) {
throw new PrestoException(GENERIC_USER_ERROR, "Remote functions are not enabled");
}
List<ProjectionContext> projectionContexts = planRemoteAssignments(node.getAssignments(), context.getVariableAllocator());
checkState(!projectionContexts.isEmpty(), "Expect non-empty projectionContexts");
PlanNode rewritten = node.getSource();
for (ProjectionContext projectionContext : projectionContexts) {
rewritten = new ProjectNode(node.getSourceLocation(), context.getIdAllocator().getNextId(), rewritten, Assignments.builder().putAll(projectionContext.getProjections()).build(), projectionContext.remote ? REMOTE : LOCAL);
}
return Result.ofPlanNode(rewritten);
}
use of com.facebook.presto.spi.plan.ProjectNode in project presto by prestodb.
the class PushAggregationThroughOuterJoin method coalesceWithNullAggregation.
// When the aggregation is done after the join, there will be a null value that gets aggregated over
// where rows did not exist in the inner table. For some aggregate functions, such as count, the result
// of an aggregation over a single null row is one or zero rather than null. In order to ensure correct results,
// we add a coalesce function with the output of the new outer join and the agggregation performed over a single
// null row.
private Optional<PlanNode> coalesceWithNullAggregation(AggregationNode aggregationNode, PlanNode outerJoin, PlanVariableAllocator variableAllocator, PlanNodeIdAllocator idAllocator, Lookup lookup) {
// Create an aggregation node over a row of nulls.
Optional<MappedAggregationInfo> aggregationOverNullInfoResultNode = createAggregationOverNull(aggregationNode, variableAllocator, idAllocator, lookup);
if (!aggregationOverNullInfoResultNode.isPresent()) {
return Optional.empty();
}
MappedAggregationInfo aggregationOverNullInfo = aggregationOverNullInfoResultNode.get();
AggregationNode aggregationOverNull = aggregationOverNullInfo.getAggregation();
Map<VariableReferenceExpression, VariableReferenceExpression> sourceAggregationToOverNullMapping = aggregationOverNullInfo.getVariableMapping();
// Do a cross join with the aggregation over null
JoinNode crossJoin = new JoinNode(outerJoin.getSourceLocation(), idAllocator.getNextId(), JoinNode.Type.INNER, outerJoin, aggregationOverNull, ImmutableList.of(), ImmutableList.<VariableReferenceExpression>builder().addAll(outerJoin.getOutputVariables()).addAll(aggregationOverNull.getOutputVariables()).build(), Optional.empty(), Optional.empty(), Optional.empty(), Optional.empty(), ImmutableMap.of());
// Add coalesce expressions for all aggregation functions
Assignments.Builder assignmentsBuilder = Assignments.builder();
for (VariableReferenceExpression variable : outerJoin.getOutputVariables()) {
if (aggregationNode.getAggregations().keySet().contains(variable)) {
assignmentsBuilder.put(variable, coalesce(ImmutableList.of(variable, sourceAggregationToOverNullMapping.get(variable))));
} else {
assignmentsBuilder.put(variable, variable);
}
}
return Optional.of(new ProjectNode(idAllocator.getNextId(), crossJoin, assignmentsBuilder.build()));
}
use of com.facebook.presto.spi.plan.ProjectNode in project presto by prestodb.
the class PruneRedundantProjectionAssignments method apply.
@Override
public Result apply(ProjectNode node, Captures captures, Context context) {
Map<Boolean, List<Map.Entry<VariableReferenceExpression, RowExpression>>> projections = node.getAssignments().entrySet().stream().collect(Collectors.partitioningBy(entry -> entry.getValue() instanceof VariableReferenceExpression || entry.getValue() instanceof ConstantExpression));
Map<RowExpression, ImmutableMap<VariableReferenceExpression, RowExpression>> uniqueProjections = projections.get(false).stream().collect(Collectors.groupingBy(Map.Entry::getValue, toImmutableMap(Map.Entry::getKey, Map.Entry::getValue)));
if (uniqueProjections.size() == projections.get(false).size()) {
return Result.empty();
}
Assignments.Builder childAssignments = Assignments.builder();
Assignments.Builder parentAssignments = Assignments.builder();
projections.get(true).forEach(entry -> childAssignments.put(entry.getKey(), entry.getValue()));
projections.get(true).forEach(entry -> parentAssignments.put(entry.getKey(), entry.getKey()));
for (Map.Entry<RowExpression, ImmutableMap<VariableReferenceExpression, RowExpression>> entry : uniqueProjections.entrySet()) {
VariableReferenceExpression variable = getFirst(entry.getValue().keySet(), null);
checkState(variable != null, "variable should not be null");
childAssignments.put(variable, entry.getKey());
entry.getValue().keySet().forEach(v -> parentAssignments.put(v, variable));
}
return Result.ofPlanNode(new ProjectNode(node.getSourceLocation(), context.getIdAllocator().getNextId(), new ProjectNode(node.getSourceLocation(), node.getId(), node.getSource(), childAssignments.build(), node.getLocality()), parentAssignments.build(), LOCAL));
}
use of com.facebook.presto.spi.plan.ProjectNode in project presto by prestodb.
the class RewriteSpatialPartitioningAggregation method apply.
@Override
public Result apply(AggregationNode node, Captures captures, Context context) {
ImmutableMap.Builder<VariableReferenceExpression, Aggregation> aggregations = ImmutableMap.builder();
VariableReferenceExpression partitionCountVariable = context.getVariableAllocator().newVariable("partition_count", INTEGER);
ImmutableMap.Builder<VariableReferenceExpression, RowExpression> envelopeAssignments = ImmutableMap.builder();
for (Map.Entry<VariableReferenceExpression, Aggregation> entry : node.getAggregations().entrySet()) {
Aggregation aggregation = entry.getValue();
QualifiedObjectName name = metadata.getFunctionAndTypeManager().getFunctionMetadata(aggregation.getFunctionHandle()).getName();
Type geometryType = metadata.getType(GEOMETRY_TYPE_SIGNATURE);
if (name.equals(NAME) && aggregation.getArguments().size() == 1) {
RowExpression geometry = getOnlyElement(aggregation.getArguments());
VariableReferenceExpression envelopeVariable = context.getVariableAllocator().newVariable(aggregation.getCall().getSourceLocation(), "envelope", geometryType);
if (isFunctionNameMatch(geometry, "ST_Envelope")) {
envelopeAssignments.put(envelopeVariable, geometry);
} else {
envelopeAssignments.put(envelopeVariable, castToRowExpression(new FunctionCall(QualifiedName.of("ST_Envelope"), ImmutableList.of(castToExpression(geometry)))));
}
aggregations.put(entry.getKey(), new Aggregation(new CallExpression(envelopeVariable.getSourceLocation(), name.getObjectName(), metadata.getFunctionAndTypeManager().lookupFunction(NAME.getObjectName(), fromTypes(geometryType, INTEGER)), entry.getKey().getType(), ImmutableList.of(castToRowExpression(asSymbolReference(envelopeVariable)), castToRowExpression(asSymbolReference(partitionCountVariable)))), Optional.empty(), Optional.empty(), false, aggregation.getMask()));
} else {
aggregations.put(entry);
}
}
return Result.ofPlanNode(new AggregationNode(node.getSourceLocation(), node.getId(), new ProjectNode(context.getIdAllocator().getNextId(), node.getSource(), Assignments.builder().putAll(identitiesAsSymbolReferences(node.getSource().getOutputVariables())).put(partitionCountVariable, castToRowExpression(new LongLiteral(Integer.toString(getHashPartitionCount(context.getSession()))))).putAll(envelopeAssignments.build()).build()), aggregations.build(), node.getGroupingSets(), node.getPreGroupedVariables(), node.getStep(), node.getHashVariable(), node.getGroupIdVariable()));
}
Aggregations