@Override protected Void visitPlan(PlanNode node, Void context) { for (PlanNode child : node.getSources()) { child.accept(this, context); } return null; }
private static void findSources(PlanNode node, Set<PlanNodeId> nodeIds, ImmutableSet.Builder<PlanNode> nodes) { if (nodeIds.contains(node.getId())) { nodes.add(node); } for (PlanNode source : node.getSources()) { nodes.addAll(findSources(source, nodeIds)); } }
@Override public Void visitDistinctLimit(DistinctLimitNode node, Set<Symbol> boundSymbols) { PlanNode source = node.getSource(); source.accept(this, boundSymbols); // visit child checkDependencies(source.getOutputSymbols(), node.getOutputSymbols(), "Invalid node. Output column dependencies (%s) not in source plan output (%s)", node.getOutputSymbols(), source.getOutputSymbols()); return null; }
/** * Transforms a plan like P->C->X to C->P->X */ public static PlanNode transpose(PlanNode parent, PlanNode child) { return child.replaceChildren(ImmutableList.of( parent.replaceChildren( child.getSources()))); }
@Override protected PlanNode visitPlan(PlanNode node, Void context) { List<PlanNode> children = node.getSources().stream() .map(child -> child.accept(this, context)) .collect(Collectors.toList()); return node.replaceChildren(children); }
private Map<PlanNodeId, SplitSource> processSources(List<PlanNode> sources, Void context) { ImmutableMap.Builder<PlanNodeId, SplitSource> result = ImmutableMap.builder(); for (PlanNode child : sources) { result.putAll(child.accept(this, context)); } return result.build(); }
@Override public List<Symbol> getOutputSymbols() { return source.getOutputSymbols(); }
private PlanNode reportDuplicateId(PlanNode first, PlanNode second) { requireNonNull(first, "first is null"); requireNonNull(second, "second is null"); checkArgument(first.getId().equals(second.getId())); throw new IllegalStateException(format( "Generated plan contains nodes with duplicated id %s: %s and %s", first.getId(), first, second)); } }
private PlanNode insertChildrenAndRewrite(PlanNode node) { return node.replaceChildren( node.getSources().stream() .map(child -> new GroupReference( idAllocator.getNextId(), insertRecursive(child), child.getOutputSymbols())) .collect(Collectors.toList())); }
private String formatPlanNodeStatsAndCost(PlanNode node) { PlanNodeStatsEstimate stats = estimatedStatsAndCosts.getStats().getOrDefault(node.getId(), PlanNodeStatsEstimate.unknown()); PlanNodeCostEstimate cost = estimatedStatsAndCosts.getCosts().getOrDefault(node.getId(), PlanNodeCostEstimate.unknown()); return format("{rows: %s (%s), cpu: %s, memory: %s, network: %s}", formatAsLong(stats.getOutputRowCount()), formatEstimateAsDataSize(stats.getOutputSizeInBytes(node.getOutputSymbols(), types)), formatDouble(cost.getCpuCost()), formatDouble(cost.getMemoryCost()), formatDouble(cost.getNetworkCost())); } }
private Set<Integer> getAllReferences(PlanNode node) { return node.getSources().stream() .map(GroupReference.class::cast) .map(GroupReference::getGroupId) .collect(Collectors.toSet()); }
private PlanWithProperties planAndEnforceChildren(PlanNode node, StreamPreferredProperties requiredProperties, StreamPreferredProperties preferredProperties) { // plan and enforce each child, but strip any requirement not in terms of symbols produced from the child // Note: this assumes the child uses the same symbols as the parent List<PlanWithProperties> children = node.getSources().stream() .map(source -> planAndEnforce( source, requiredProperties.constrainTo(source.getOutputSymbols()), preferredProperties.constrainTo(source.getOutputSymbols()))) .collect(toImmutableList()); return rebaseAndDeriveProperties(node, children); }
@Override public PlanNodeCostEstimate calculateCost(PlanNode node, StatsProvider stats, Session session, TypeProvider types) { CostEstimator costEstimator = new CostEstimator(stats, types, taskCountEstimator); return node.accept(costEstimator, null); }
private static ImmutableSet<Symbol> createInputs(PlanNode source, Set<Symbol> boundSymbols) { return ImmutableSet.<Symbol>builder() .addAll(source.getOutputSymbols()) .addAll(boundSymbols) .build(); } }
@Override public void validate(PlanNode planNode, Session session, Metadata metadata, SqlParser sqlParser, TypeProvider types, WarningCollector warningCollector) { Map<PlanNodeId, PlanNode> planNodeIds = new HashMap<>(); searchFrom(planNode) .findAll() .forEach(node -> planNodeIds.merge(node.getId(), node, this::reportDuplicateId)); }
private PlanNode insertChildrenAndRewrite(PlanNode node) { return node.replaceChildren( node.getSources().stream() .map(child -> new GroupReference( idAllocator.getNextId(), insertRecursive(child), child.getOutputSymbols())) .collect(Collectors.toList())); }
private String formatPlanNodeStatsAndCost(PlanNode node) { PlanNodeStatsEstimate stats = estimatedStatsAndCosts.getStats().getOrDefault(node.getId(), PlanNodeStatsEstimate.unknown()); PlanNodeCostEstimate cost = estimatedStatsAndCosts.getCosts().getOrDefault(node.getId(), PlanNodeCostEstimate.unknown()); return format("{rows: %s (%s), cpu: %s, memory: %s, network: %s}", formatAsLong(stats.getOutputRowCount()), formatEstimateAsDataSize(stats.getOutputSizeInBytes(node.getOutputSymbols(), types)), formatDouble(cost.getCpuCost()), formatDouble(cost.getMemoryCost()), formatDouble(cost.getNetworkCost())); } }
public static Property<PlanNode, Lookup, PlanNode> source() { return optionalProperty( "source", (node, lookup) -> { if (node.getSources().size() == 1) { PlanNode source = getOnlyElement(node.getSources()); return Optional.of(lookup.resolve(source)); } return Optional.empty(); }); }
@Override public Result apply(PlanNode node, Captures captures, Context context) { return Result.ofPlanNode(node.replaceChildren(node.getSources())); } }
@Override protected Void visitPlan(PlanNode node, C context) { for (PlanNode source : node.getSources()) { source.accept(this, context); } return null; } }