Start line:  
End line:  

Snippet Preview

Snippet HTML Code

Stack Overflow Questions
  /*
   * Licensed under the Apache License, Version 2.0 (the "License");
   * you may not use this file except in compliance with the License.
   * You may obtain a copy of the License at
   *
   *     http://www.apache.org/licenses/LICENSE-2.0
   *
   * Unless required by applicable law or agreed to in writing, software
   * distributed under the License is distributed on an "AS IS" BASIS,
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
 package com.facebook.presto.sql.planner;
 
 
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
 
 import static com.facebook.presto.spi.type.VarcharType.VARCHAR;
 import static com.facebook.presto.sql.planner.DomainUtils.simplifyDomain;
 import static com.google.common.base.Preconditions.checkNotNull;
 import static java.lang.String.format;
 
 public class PlanPrinter
 {
     private final StringBuilder output = new StringBuilder();
     private final Metadata metadata;
 
     private PlanPrinter(PlanNode planMap<SymbolTypetypesMetadata metadata)
     {
         this(plantypesmetadata, 0);
     }
 
     private PlanPrinter(PlanNode planMap<SymbolTypetypesMetadata metadataint indent)
     {
         checkNotNull(plan"plan is null");
         checkNotNull(types"types is null");
         checkNotNull(metadata"metadata is null");
 
        this. = metadata;
        Visitor visitor = new Visitor(types);
        plan.accept(visitorindent);
    }
    @Override
    public String toString()
    {
        return .toString();
    }
    public static String textLogicalPlan(PlanNode planMap<SymbolTypetypesMetadata metadata)
    {
        return new PlanPrinter(plantypesmetadata).toString();
    }
    public static String textLogicalPlan(PlanNode planMap<SymbolTypetypesMetadata metadataint indent)
    {
        return new PlanPrinter(plantypesmetadataindent).toString();
    }
    public static String getJsonPlanSource(PlanNode planMetadata metadata)
    {
        return JsonPlanPrinter.getPlan(planmetadata);
    }
    public static String textDistributedPlan(SubPlan planMetadata metadata)
    {
        StringBuilder builder = new StringBuilder();
        for (PlanFragment fragment : plan.getAllFragments()) {
            builder.append(String.format("Fragment %s [%s]\n",
                    fragment.getId(),
                    fragment.getDistribution()));
            builder.append(indentString(1))
                    .append(String.format("Output layout: [%s]\n",
                            Joiner.on(", ").join(fragment.getOutputLayout())));
            if (fragment.getOutputPartitioning() == .) {
                builder.append(indentString(1))
                        .append(String.format("Output partitioning: [%s]\n",
                                Joiner.on(", ").join(fragment.getPartitionBy())));
            }
            builder.append(textLogicalPlan(fragment.getRoot(), fragment.getSymbols(), metadata, 1))
                    .append("\n");
        }
        return builder.toString();
    }
    public static String graphvizLogicalPlan(PlanNode planMap<SymbolTypetypes)
    {
        PlanFragment fragment = new PlanFragment(new PlanFragmentId("graphviz_plan"), plantypesplan.getOutputSymbols(), .plan.getId(), ., ImmutableList.<Symbol>of(), Optional.empty());
        return GraphvizPrinter.printLogical(ImmutableList.of(fragment));
    }
    public static String graphvizDistributedPlan(SubPlan plan)
    {
        return GraphvizPrinter.printDistributed(plan);
    }
    private void print(int indentString formatObject... args)
    {
        String value;
        if (args.length == 0) {
            value = format;
        }
        else {
            value = format(formatargs);
        }
        .append(indentString(indent)).append(value).append('\n');
    }
    private static String indentString(int indent)
    {
        return Strings.repeat("    "indent);
    }
    private class Visitor
            extends PlanVisitor<IntegerVoid>
    {
        private final Map<SymbolTypetypes;
        public Visitor(Map<SymbolTypetypes)
        {
            this. = types;
        }
        @Override
        public Void visitJoin(JoinNode nodeInteger indent)
        {
            List<ExpressionjoinExpressions = new ArrayList<>();
            for (JoinNode.EquiJoinClause clause : node.getCriteria()) {
                joinExpressions.add(new ComparisonExpression(..,
                        new QualifiedNameReference(clause.getLeft().toQualifiedName()),
                        new QualifiedNameReference(clause.getRight().toQualifiedName())));
            }
            print(indent"- %s[%s] => [%s]"node.getType().getJoinLabel(), Joiner.on(" AND ").join(joinExpressions), formatOutputs(node.getOutputSymbols()));
            node.getLeft().accept(thisindent + 1);
            node.getRight().accept(thisindent + 1);
            return null;
        }
        @Override
        public Void visitSemiJoin(SemiJoinNode nodeInteger indent)
        {
            print(indent"- SemiJoin[%s = %s] => [%s]"node.getSourceJoinSymbol(), node.getFilteringSourceJoinSymbol(), formatOutputs(node.getOutputSymbols()));
            node.getSource().accept(thisindent + 1);
            node.getFilteringSource().accept(thisindent + 1);
            return null;
        }
        @Override
        public Void visitIndexSource(IndexSourceNode nodeInteger indent)
        {
            print(indent"- IndexSource[%s, lookup = %s] => [%s]"node.getIndexHandle(), node.getLookupSymbols(), formatOutputs(node.getOutputSymbols()));
            for (Map.Entry<SymbolColumnHandleentry : node.getAssignments().entrySet()) {
                if (node.getOutputSymbols().contains(entry.getKey())) {
                    print(indent + 2, "%s := %s"entry.getKey(), entry.getValue());
                }
            }
            return null;
        }
        @Override
        public Void visitIndexJoin(IndexJoinNode nodeInteger indent)
        {
            List<ExpressionjoinExpressions = new ArrayList<>();
            for (IndexJoinNode.EquiJoinClause clause : node.getCriteria()) {
                joinExpressions.add(new ComparisonExpression(..,
                        new QualifiedNameReference(clause.getProbe().toQualifiedName()),
                        new QualifiedNameReference(clause.getIndex().toQualifiedName())));
            }
            print(indent"- %sIndexJoin[%s] => [%s]"node.getType().getJoinLabel(), Joiner.on(" AND ").join(joinExpressions), formatOutputs(node.getOutputSymbols()));
            node.getProbeSource().accept(thisindent + 1);
            node.getIndexSource().accept(thisindent + 1);
            return null;
        }
        @Override
        public Void visitLimit(LimitNode nodeInteger indent)
        {
            print(indent"- Limit[%s] => [%s]"node.getCount(), formatOutputs(node.getOutputSymbols()));
            return processChildren(nodeindent + 1);
        }
        @Override
        public Void visitDistinctLimit(DistinctLimitNode nodeInteger indent)
        {
            print(indent"- DistinctLimit[%s] => [%s]"node.getLimit(), formatOutputs(node.getOutputSymbols()));
            return processChildren(nodeindent + 1);
        }
        @Override
        public Void visitAggregation(AggregationNode nodeInteger indent)
        {
            String type = "";
            if (node.getStep() != ..) {
                type = format("(%s)"node.getStep().toString());
            }
            String key = "";
            if (!node.getGroupBy().isEmpty()) {
                key = node.getGroupBy().toString();
            }
            String sampleWeight = "";
            if (node.getSampleWeight().isPresent()) {
                sampleWeight = format("[sampleWeight = %s]"node.getSampleWeight().get());
            }
            print(indent"- Aggregate%s%s%s => [%s]"typekeysampleWeightformatOutputs(node.getOutputSymbols()));
            for (Map.Entry<SymbolFunctionCallentry : node.getAggregations().entrySet()) {
                if (node.getMasks().containsKey(entry.getKey())) {
                    print(indent + 2, "%s := %s (mask = %s)"entry.getKey(), entry.getValue(), node.getMasks().get(entry.getKey()));
                }
                else {
                    print(indent + 2, "%s := %s"entry.getKey(), entry.getValue());
                }
            }
            return processChildren(nodeindent + 1);
        }
        @Override
        public Void visitMarkDistinct(MarkDistinctNode nodeInteger indent)
        {
            print(indent"- MarkDistinct[distinct=%s marker=%s] => [%s]"formatOutputs(node.getDistinctSymbols()), node.getMarkerSymbol(), formatOutputs(node.getOutputSymbols()));
            return processChildren(nodeindent + 1);
        }
        @Override
        public Void visitWindow(final WindowNode nodeInteger indent)
        {
            List<StringpartitionBy = Lists.transform(node.getPartitionBy(), Functions.toStringFunction());
            List<StringorderBy = Lists.transform(node.getOrderBy(), input -> input + " " + node.getOrderings().get(input));
            List<Stringargs = new ArrayList<>();
            if (!partitionBy.isEmpty()) {
                args.add(format("partition by (%s)", Joiner.on(", ").join(partitionBy)));
            }
            if (!orderBy.isEmpty()) {
                args.add(format("order by (%s)", Joiner.on(", ").join(orderBy)));
            }
            print(indent"- Window[%s] => [%s]", Joiner.on(", ").join(args), formatOutputs(node.getOutputSymbols()));
            for (Map.Entry<SymbolFunctionCallentry : node.getWindowFunctions().entrySet()) {
                print(indent + 2, "%s := %s(%s)"entry.getKey(), entry.getValue().getName(), Joiner.on(", ").join(entry.getValue().getArguments()));
            }
            return processChildren(nodeindent + 1);
        }
        @Override
        public Void visitTopNRowNumber(final TopNRowNumberNode nodeInteger indent)
        {
            List<StringpartitionBy = Lists.transform(node.getPartitionBy(), Functions.toStringFunction());
            List<StringorderBy = Lists.transform(node.getOrderBy(), input -> input + " " + node.getOrderings().get(input));
            List<Stringargs = new ArrayList<>();
            args.add(format("partition by (%s)", Joiner.on(", ").join(partitionBy)));
            args.add(format("order by (%s)", Joiner.on(", ").join(orderBy)));
            print(indent"- TopNRowNumber[%s limit %s] => [%s]", Joiner.on(", ").join(args), node.getMaxRowCountPerPartition(), formatOutputs(node.getOutputSymbols()));
            print(indent + 2, "%s := %s"node.getRowNumberSymbol(), "row_number()");
            return processChildren(nodeindent + 1);
        }
        @Override
        public Void visitRowNumber(final RowNumberNode nodeInteger indent)
        {
            List<StringpartitionBy = Lists.transform(node.getPartitionBy(), Functions.toStringFunction());
            List<Stringargs = new ArrayList<>();
            if (!partitionBy.isEmpty()) {
                args.add(format("partition by (%s) ", Joiner.on(", ").join(partitionBy)));
            }
            if (node.getMaxRowCountPerPartition().isPresent()) {
                args.add(format("limit (%s) "node.getMaxRowCountPerPartition().get()));
            }
            print(indent"- RowNumber[%s] => [%s]", Joiner.on(", ").join(args), formatOutputs(node.getOutputSymbols()));
            print(indent + 2, "%s := %s"node.getRowNumberSymbol(), "row_number()");
            return processChildren(nodeindent + 1);
        }
        @Override
        public Void visitTableScan(TableScanNode nodeInteger indent)
        {
            TupleDomain<ColumnHandlepartitionsDomainSummary = node.getPartitionsDomainSummary();
            print(indent"- TableScan[%s, original constraint=%s] => [%s]"node.getTable(), node.getOriginalConstraint(), formatOutputs(node.getOutputSymbols()));
            Set<Symboloutputs = ImmutableSet.copyOf(node.getOutputSymbols());
            for (Map.Entry<SymbolColumnHandleentry : node.getAssignments().entrySet()) {
                boolean isOutputSymbol = outputs.contains(entry.getKey());
                boolean isInOriginalConstraint = node.getOriginalConstraint() == null ? false : DependencyExtractor.extractUnique(node.getOriginalConstraint()).contains(entry.getKey());
                boolean isInDomainSummary = !partitionsDomainSummary.isNone() && partitionsDomainSummary.getDomains().keySet().contains(entry.getValue());
                if (isOutputSymbol || isInOriginalConstraint || isInDomainSummary) {
                    print(indent + 2, "%s := %s"entry.getKey(), entry.getValue());
                    if (isInDomainSummary) {
                        print(indent + 3, ":: %s"formatDomain(node.getTable(), entry.getValue(), simplifyDomain(partitionsDomainSummary.getDomains().get(entry.getValue()))));
                    }
                    else if (partitionsDomainSummary.isNone()) {
                        print(indent + 3, ":: NONE");
                    }
                }
            }
            return null;
        }
        @Override
        public Void visitValues(ValuesNode nodeInteger indent)
        {
            print(indent"- Values => [%s]"formatOutputs(node.getOutputSymbols()));
            for (List<Expressionrow : node.getRows()) {
                print(indent + 2, "(" + Joiner.on(", ").join(row) + ")");
            }
            return null;
        }
        @Override
        public Void visitFilter(FilterNode nodeInteger indent)
        {
            print(indent"- Filter[%s] => [%s]"node.getPredicate(), formatOutputs(node.getOutputSymbols()));
            return processChildren(nodeindent + 1);
        }
        @Override
        public Void visitProject(ProjectNode nodeInteger indent)
        {
            print(indent"- Project => [%s]"formatOutputs(node.getOutputSymbols()));
            for (Map.Entry<SymbolExpressionentry : node.getAssignments().entrySet()) {
                if (entry.getValue() instanceof QualifiedNameReference && ((QualifiedNameReferenceentry.getValue()).getName().equals(entry.getKey().toQualifiedName())) {
                    // skip identity assignments
                    continue;
                }
                print(indent + 2, "%s := %s"entry.getKey(), entry.getValue());
            }
            return processChildren(nodeindent + 1);
        }
        @Override
        public Void visitUnnest(UnnestNode nodeInteger indent)
        {
            print(indent"- Unnest [replicate=%s, unnest=%s] => [%s]"formatOutputs(node.getReplicateSymbols()), formatOutputs(node.getUnnestSymbols().keySet()), formatOutputs(node.getOutputSymbols()));
            return processChildren(nodeindent + 1);
        }
        @Override
        public Void visitOutput(OutputNode nodeInteger indent)
        {
            print(indent"- Output[%s] => [%s]", Joiner.on(", ").join(node.getColumnNames()), formatOutputs(node.getOutputSymbols()));
            for (int i = 0; i < node.getColumnNames().size(); i++) {
                String name = node.getColumnNames().get(i);
                Symbol symbol = node.getOutputSymbols().get(i);
                if (!name.equals(symbol.toString())) {
                    print(indent + 2, "%s := %s"namesymbol);
                }
            }
            return processChildren(nodeindent + 1);
        }
        @Override
        public Void visitTopN(final TopNNode nodeInteger indent)
        {
            Iterable<Stringkeys = Iterables.transform(node.getOrderBy(), input -> input + " " + node.getOrderings().get(input));
            print(indent"- TopN[%s by (%s)] => [%s]"node.getCount(), Joiner.on(", ").join(keys), formatOutputs(node.getOutputSymbols()));
            return processChildren(nodeindent + 1);
        }
        @Override
        public Void visitSort(final SortNode nodeInteger indent)
        {
            Iterable<Stringkeys = Iterables.transform(node.getOrderBy(), input -> input + " " + node.getOrderings().get(input));
            print(indent"- Sort[%s] => [%s]", Joiner.on(", ").join(keys), formatOutputs(node.getOutputSymbols()));
            return processChildren(nodeindent + 1);
        }
        @Override
        public Void visitRemoteSource(RemoteSourceNode nodeInteger indent)
        {
            print(indent"- RemoteSource[%s] => [%s]", Joiner.on(',').join(node.getSourceFragmentIds()), formatOutputs(node.getOutputSymbols()));
            return null;
        }
        @Override
        public Void visitUnion(UnionNode nodeInteger indent)
        {
            print(indent"- Union => [%s]"formatOutputs(node.getOutputSymbols()));
            return processChildren(nodeindent + 1);
        }
        @Override
        public Void visitTableWriter(TableWriterNode nodeInteger indent)
        {
            print(indent"- TableWriter => [%s]"formatOutputs(node.getOutputSymbols()));
            for (int i = 0; i < node.getColumnNames().size(); i++) {
                String name = node.getColumnNames().get(i);
                Symbol symbol = node.getColumns().get(i);
                print(indent + 2, "%s := %s"namesymbol);
            }
            return processChildren(nodeindent + 1);
        }
        @Override
        public Void visitTableCommit(TableCommitNode nodeInteger indent)
        {
            print(indent"- TableCommit[%s] => [%s]"node.getTarget(), formatOutputs(node.getOutputSymbols()));
            return processChildren(nodeindent + 1);
        }
        @Override
        public Void visitSample(SampleNode nodeInteger indent)
        {
            print(indent"- Sample[%s: %s] => [%s]"node.getSampleType(), node.getSampleRatio(), formatOutputs(node.getOutputSymbols()));
            return processChildren(nodeindent + 1);
        }
        @Override
        public Void visitExchange(ExchangeNode nodeInteger indent)
        {
            print(indent"- Exchange[%s] => %s"node.getType(), formatOutputs(node.getOutputSymbols()));
            return processChildren(nodeindent + 1);
        }
        @Override
        protected Void visitPlan(PlanNode nodeInteger context)
        {
            throw new UnsupportedOperationException("not yet implemented: " + node.getClass().getName());
        }
        private Void processChildren(PlanNode nodeint indent)
        {
            for (PlanNode child : node.getSources()) {
                child.accept(thisindent);
            }
            return null;
        }
        private String formatOutputs(Iterable<Symbolsymbols)
        {
            return Joiner.on(", ").join(Iterables.transform(symbolsinput -> input + ":" + .get(input)));
        }
    }
    private String formatDomain(TableHandle tableColumnHandle columnDomain domain)
    {
        ImmutableList.Builder<Stringparts = ImmutableList.builder();
        if (domain.isNullAllowed()) {
            parts.add("NULL");
        }
        try {
            ColumnMetadata columnMetadata = .getColumnMetadata(tablecolumn);
            MethodHandle method = .getFunctionRegistry().getCoercion(columnMetadata.getType(), )
                    .getMethodHandle();
            for (Range range : domain.getRanges()) {
                StringBuilder builder = new StringBuilder();
                if (range.isSingleValue()) {
                    String value = ((Slicemethod.invokeWithArguments(range.getSingleValue())).toStringUtf8();
                    builder.append('[').append(value).append(']');
                }
                else {
                    builder.append((range.getLow().getBound() == ..) ? '[' : '(');
                    if (range.getLow().isLowerUnbounded()) {
                        builder.append("<min>");
                    }
                    else {
                        builder.append(((Slicemethod.invokeWithArguments(range.getLow().getValue())).toStringUtf8());
                    }
                    builder.append(", ");
                    if (range.getHigh().isUpperUnbounded()) {
                        builder.append("<max>");
                    }
                    else {
                        builder.append(((Slicemethod.invokeWithArguments(range.getHigh().getValue())).toStringUtf8());
                    }
                    builder.append((range.getHigh().getBound() == ..) ? ']' : ')');
                }
                parts.add(builder.toString());
            }
        }
        catch (OperatorNotFoundException e) {
            parts.add("<UNREPRESENTABLE VALUE>");
        }
        catch (Throwable e) {
            throw Throwables.propagate(e);
        }
        return "[" + Joiner.on(", ").join(parts.build()) + "]";
    }
New to GrepCode? Check out our FAQ X