/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you 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 org.apache.drill.exec.planner.physical.visitor; import org.apache.drill.exec.planner.physical.ExchangePrel; import org.apache.drill.exec.planner.physical.JoinPrel; import org.apache.drill.exec.planner.physical.Prel; import org.apache.drill.exec.planner.physical.ProjectPrel; import org.apache.drill.exec.planner.physical.ScanPrel; import org.apache.drill.exec.planner.physical.ScreenPrel; import org.apache.drill.exec.planner.physical.WriterPrel; /** * Debug-time class that prints a PRel tree to the console for * inspection. Insert this into code during development to see * the state of the tree at various points of interest during * the planning process. * <p> * Use this by inserting lines into our prel transforms to see * what is happening. This is useful if you must understand the transforms, * or change them. For example: * <p> * In file: {@link DefaultSqlHandler#convertToPrel()}: * <pre><code> * PrelVisualizerVisitor.print("Before EER", phyRelNode); // Debug only * phyRelNode = ExcessiveExchangeIdentifier.removeExcessiveEchanges(phyRelNode, targetSliceSize); * PrelVisualizerVisitor.print("After EER", phyRelNode); // Debug only * <code></pre> */ public class PrelVisualizerVisitor implements PrelVisitor<Void, PrelVisualizerVisitor.VisualizationState, Exception> { public static class VisualizationState { public static String INDENT = " "; StringBuilder out = new StringBuilder(); int level; public void startNode(Prel prel) { indent(); out.append("{ "); out.append(prel.getClass().getSimpleName()); out.append("\n"); push(); } public void endNode() { pop(); indent(); out.append("}"); out.append("\n"); } private void indent() { for (int i = 0; i < level; i++) { out.append(INDENT); } } public void push() { level++; } public void pop() { level--; } public void endFields() { // TODO Auto-generated method stub } public void field(String label, boolean value) { field(label, Boolean.toString(value)); } private void field(String label, String value) { indent(); out.append(label) .append(" = ") .append(value) .append("\n"); } public void listField(String label, Object[] values) { if (values == null) { field(label, "null"); return; } StringBuilder buf = new StringBuilder(); buf.append("["); boolean first = true; for (Object obj : values) { if (! first) { buf.append(", "); } first = false; if (obj == null) { buf.append("null"); } else { buf.append(obj.toString()); } } buf.append("]"); field(label, buf.toString()); } @Override public String toString() { return out.toString(); } } public static void print(String label, Prel prel) { System.out.println(label); System.out.println(visualize(prel)); } public static String visualize(Prel prel) { try { VisualizationState state = new VisualizationState(); prel.accept(new PrelVisualizerVisitor(), state); return state.toString(); } catch (Exception e) { e.printStackTrace(); return "** ERROR **"; } } @Override public Void visitExchange(ExchangePrel prel, VisualizationState value) throws Exception { visitBasePrel(prel, value); endNode(prel, value); return null; } private void visitBasePrel(Prel prel, VisualizationState value) { value.startNode(prel); value.listField("encodings", prel.getSupportedEncodings()); value.field("needsReorder", prel.needsFinalColumnReordering()); } private void endNode(Prel prel, VisualizationState value) throws Exception { value.endFields(); visitChildren(prel, value); value.endNode(); } private void visitChildren(Prel prel, VisualizationState value) throws Exception { value.indent(); value.out.append("children = [\n"); value.push(); for (Prel child : prel) { child.accept(this, value); } value.pop(); value.indent(); value.out.append("]\n"); } @Override public Void visitScreen(ScreenPrel prel, VisualizationState value) throws Exception { visitBasePrel(prel, value); endNode(prel, value); return null; } @Override public Void visitWriter(WriterPrel prel, VisualizationState value) throws Exception { visitBasePrel(prel, value); endNode(prel, value); return null; } @Override public Void visitScan(ScanPrel prel, VisualizationState value) throws Exception { visitBasePrel(prel, value); endNode(prel, value); return null; } @Override public Void visitJoin(JoinPrel prel, VisualizationState value) throws Exception { visitBasePrel(prel, value); endNode(prel, value); return null; } @Override public Void visitProject(ProjectPrel prel, VisualizationState value) throws Exception { visitBasePrel(prel, value); endNode(prel, value); return null; } @Override public Void visitPrel(Prel prel, VisualizationState value) throws Exception { visitBasePrel(prel, value); endNode(prel, value); return null; } }