Till Westmann has submitted this change and it was merged.

Change subject: some pretty printing refactoring/cleanup
......................................................................


some pretty printing refactoring/cleanup

- introduce AlgebricksAppendable
- use AlgebricksAppendable instead of PrintWriter and StringBuilder for plan
  printing
- avoid creation of intermediate strings for each Operator
- only log plans in the optimizer if the log-level requires it
- change param to indent output JSON from INDENT to PRETTY

Change-Id: Ied0203adc51e9710690ace74fe1e152eb7a716e8
Reviewed-on: https://asterix-gerrit.ics.uci.edu/1004
Tested-by: Jenkins <jenk...@fulliautomatix.ics.uci.edu>
Integration-Tests: Jenkins <jenk...@fulliautomatix.ics.uci.edu>
Reviewed-by: Yingyi Bu <buyin...@gmail.com>
---
M 
asterixdb/asterix-app/src/main/java/org/apache/asterix/api/common/APIFramework.java
M 
asterixdb/asterix-app/src/main/java/org/apache/asterix/api/common/SessionConfig.java
M 
asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/servlet/QueryServiceServlet.java
M asterixdb/asterix-app/src/main/java/org/apache/asterix/result/ResultUtils.java
M 
hyracks-fullstack/algebricks/algebricks-core/src/main/java/org/apache/hyracks/algebricks/core/algebra/plan/ALogicalPlanImpl.java
A 
hyracks-fullstack/algebricks/algebricks-core/src/main/java/org/apache/hyracks/algebricks/core/algebra/prettyprint/AlgebricksAppendable.java
M 
hyracks-fullstack/algebricks/algebricks-core/src/main/java/org/apache/hyracks/algebricks/core/algebra/prettyprint/LogicalOperatorPrettyPrintVisitor.java
M 
hyracks-fullstack/algebricks/algebricks-core/src/main/java/org/apache/hyracks/algebricks/core/algebra/prettyprint/PlanPrettyPrinter.java
M 
hyracks-fullstack/algebricks/algebricks-core/src/main/java/org/apache/hyracks/algebricks/core/rewriter/base/AbstractRuleController.java
M 
hyracks-fullstack/algebricks/algebricks-core/src/main/java/org/apache/hyracks/algebricks/core/rewriter/base/HeuristicOptimizer.java
M 
hyracks-fullstack/algebricks/algebricks-examples/piglet-example/src/main/java/org/apache/hyracks/algebricks/examples/piglet/compiler/PigletCompiler.java
M 
hyracks-fullstack/algebricks/algebricks-rewriter/src/main/java/org/apache/hyracks/algebricks/rewriter/rules/EnforceStructuralPropertiesRule.java
12 files changed, 350 insertions(+), 276 deletions(-)

Approvals:
  Yingyi Bu: Looks good to me, approved
  Jenkins: Verified; Verified

Objections:
  Jenkins: Violations found



diff --git 
a/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/common/APIFramework.java
 
b/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/common/APIFramework.java
index 68fbba4..6fb82ef 100644
--- 
a/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/common/APIFramework.java
+++ 
b/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/common/APIFramework.java
@@ -66,6 +66,7 @@
 import 
org.apache.hyracks.algebricks.core.algebra.expressions.IMergeAggregationExpressionFactory;
 import 
org.apache.hyracks.algebricks.core.algebra.expressions.IMissableTypeComputer;
 import 
org.apache.hyracks.algebricks.core.algebra.expressions.LogicalExpressionJobGenToExpressionRuntimeProviderAdapter;
+import 
org.apache.hyracks.algebricks.core.algebra.prettyprint.AlgebricksAppendable;
 import 
org.apache.hyracks.algebricks.core.algebra.prettyprint.LogicalOperatorPrettyPrintVisitor;
 import org.apache.hyracks.algebricks.core.algebra.prettyprint.PlanPlotter;
 import 
org.apache.hyracks.algebricks.core.algebra.prettyprint.PlanPrettyPrinter;
@@ -214,15 +215,13 @@
             plan = t.translateLoad(statement);
         }
 
-        LogicalOperatorPrettyPrintVisitor pvisitor = new 
LogicalOperatorPrettyPrintVisitor();
         if (!conf.is(SessionConfig.FORMAT_ONLY_PHYSICAL_OPS) && 
conf.is(SessionConfig.OOB_LOGICAL_PLAN)) {
             conf.out().println();
 
             printPlanPrefix(conf, "Logical plan");
             if (rwQ != null || (statement != null && statement.getKind() == 
Kind.LOAD)) {
-                StringBuilder buffer = new StringBuilder();
-                PlanPrettyPrinter.printPlan(plan, buffer, pvisitor, 0);
-                conf.out().print(buffer);
+                LogicalOperatorPrettyPrintVisitor pvisitor = new 
LogicalOperatorPrettyPrintVisitor(conf.out());
+                PlanPrettyPrinter.printPlan(plan, pvisitor, 0);
             }
             printPlanPostfix(conf);
         }
@@ -268,15 +267,13 @@
             if (conf.is(SessionConfig.OOB_OPTIMIZED_LOGICAL_PLAN)) {
                 if (conf.is(SessionConfig.FORMAT_ONLY_PHYSICAL_OPS)) {
                     // For Optimizer tests.
-                    StringBuilder buffer = new StringBuilder();
+                    AlgebricksAppendable buffer = new 
AlgebricksAppendable(conf.out());
                     PlanPrettyPrinter.printPhysicalOps(plan, buffer, 0);
-                    conf.out().print(buffer);
                 } else {
                     printPlanPrefix(conf, "Optimized logical plan");
                     if (rwQ != null || (statement != null && 
statement.getKind() == Kind.LOAD)) {
-                        StringBuilder buffer = new StringBuilder();
-                        PlanPrettyPrinter.printPlan(plan, buffer, pvisitor, 0);
-                        conf.out().print(buffer);
+                        LogicalOperatorPrettyPrintVisitor pvisitor = new 
LogicalOperatorPrettyPrintVisitor(conf.out());
+                        PlanPrettyPrinter.printPlan(plan, pvisitor, 0);
                     }
                     printPlanPostfix(conf);
                 }
diff --git 
a/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/common/SessionConfig.java
 
b/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/common/SessionConfig.java
index c09b424..ba205d1 100644
--- 
a/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/common/SessionConfig.java
+++ 
b/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/common/SessionConfig.java
@@ -22,6 +22,9 @@
 import java.util.HashMap;
 import java.util.Map;
 
+import org.apache.hyracks.algebricks.common.exceptions.AlgebricksException;
+import 
org.apache.hyracks.algebricks.core.algebra.prettyprint.AlgebricksAppendable;
+
 /**
  * SessionConfig captures several different parameters for controlling
  * the execution of an APIFramework call.
@@ -103,7 +106,7 @@
     public static final String FORMAT_QUOTE_RECORD = "quote-record";
 
     public interface ResultDecorator {
-        PrintWriter print(PrintWriter pw);
+        AlgebricksAppendable append(AlgebricksAppendable app) throws 
AlgebricksException;
     }
 
     // Standard execution flags.
@@ -193,12 +196,12 @@
         return this.fmt;
     }
 
-    public PrintWriter resultPrefix(PrintWriter pw) {
-        return this.preResultDecorator != null ? 
this.preResultDecorator.print(pw) : pw;
+    public AlgebricksAppendable resultPrefix(AlgebricksAppendable app) throws 
AlgebricksException {
+        return this.preResultDecorator != null ? 
this.preResultDecorator.append(app) : app;
     };
 
-    public PrintWriter resultPostfix(PrintWriter pw) {
-        return this.postResultDecorator != null ? 
this.postResultDecorator.print(pw) : pw;
+    public AlgebricksAppendable resultPostfix(AlgebricksAppendable app) throws 
AlgebricksException {
+        return this.postResultDecorator != null ? 
this.postResultDecorator.append(app) : app;
     };
 
     /**
diff --git 
a/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/servlet/QueryServiceServlet.java
 
b/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/servlet/QueryServiceServlet.java
index 8fa09a4..ed23195 100644
--- 
a/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/servlet/QueryServiceServlet.java
+++ 
b/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/servlet/QueryServiceServlet.java
@@ -47,6 +47,7 @@
 import org.apache.asterix.result.ResultReader;
 import org.apache.asterix.result.ResultUtils;
 import org.apache.commons.io.IOUtils;
+import 
org.apache.hyracks.algebricks.core.algebra.prettyprint.AlgebricksAppendable;
 import org.apache.hyracks.api.client.IHyracksClientConnection;
 import org.apache.hyracks.api.dataset.IHyracksDataset;
 import org.apache.hyracks.client.dataset.HyracksDataset;
@@ -66,7 +67,7 @@
         STATEMENT("statement"),
         FORMAT("format"),
         // Asterix
-        INDENT("indent");
+        PRETTY("pretty");
 
         private final String str;
 
@@ -244,23 +245,23 @@
      * output-format based on the Accept: header and other servlet parameters.
      */
     private static SessionConfig createSessionConfig(HttpServletRequest 
request, PrintWriter resultWriter) {
-        SessionConfig.ResultDecorator resultPrefix = (PrintWriter pw) -> {
-            pw.print("\t\"");
-            pw.print(ResultFields.RESULTS.str());
-            pw.print("\": ");
-            return pw;
+        SessionConfig.ResultDecorator resultPrefix = (AlgebricksAppendable 
app) -> {
+            app.append("\t\"");
+            app.append(ResultFields.RESULTS.str());
+            app.append("\": ");
+            return app;
         };
 
-        SessionConfig.ResultDecorator resultPostfix = (PrintWriter pw) -> {
-            pw.print("\t,\n");
-            return pw;
+        SessionConfig.ResultDecorator resultPostfix = (AlgebricksAppendable 
app) -> {
+            app.append("\t,\n");
+            return app;
         };
 
         String formatstr = 
request.getParameter(Parameter.FORMAT.str()).toLowerCase();
         SessionConfig.OutputFormat format = getFormat(formatstr);
         SessionConfig sessionConfig = new SessionConfig(resultWriter, format, 
resultPrefix, resultPostfix);
         sessionConfig.set(SessionConfig.FORMAT_WRAPPER_ARRAY, true);
-        boolean indentJson = 
Boolean.parseBoolean(request.getParameter(Parameter.INDENT.str()));
+        boolean indentJson = 
Boolean.parseBoolean(request.getParameter(Parameter.PRETTY.str()));
         sessionConfig.set(SessionConfig.FORMAT_INDENT_JSON, indentJson);
         sessionConfig.set(SessionConfig.FORMAT_QUOTE_RECORD,
                 format != SessionConfig.OutputFormat.CLEAN_JSON && format != 
SessionConfig.OutputFormat.LOSSLESS_JSON);
diff --git 
a/asterixdb/asterix-app/src/main/java/org/apache/asterix/result/ResultUtils.java
 
b/asterixdb/asterix-app/src/main/java/org/apache/asterix/result/ResultUtils.java
index 73dd706..8c3ccfc 100644
--- 
a/asterixdb/asterix-app/src/main/java/org/apache/asterix/result/ResultUtils.java
+++ 
b/asterixdb/asterix-app/src/main/java/org/apache/asterix/result/ResultUtils.java
@@ -38,6 +38,7 @@
 import org.apache.asterix.om.types.ARecordType;
 import org.apache.http.ParseException;
 import org.apache.hyracks.algebricks.common.exceptions.AlgebricksException;
+import 
org.apache.hyracks.algebricks.core.algebra.prettyprint.AlgebricksAppendable;
 import org.apache.hyracks.api.comm.IFrame;
 import org.apache.hyracks.api.comm.IFrameTupleAccessor;
 import org.apache.hyracks.api.comm.VSizeFrame;
@@ -104,7 +105,11 @@
             conf.out().println("<pre>");
         }
 
-        conf.resultPrefix(conf.out());
+        try {
+            conf.resultPrefix(new AlgebricksAppendable(conf.out()));
+        } catch (AlgebricksException e) {
+            throw new HyracksDataException(e);
+        }
 
         if (conf.is(SessionConfig.FORMAT_WRAPPER_ARRAY)) {
             conf.out().print("[ ");
@@ -178,7 +183,11 @@
             conf.out().println(" ]");
         }
 
-        conf.resultPostfix(conf.out());
+        try {
+            conf.resultPostfix(new AlgebricksAppendable(conf.out()));
+        } catch (AlgebricksException e) {
+            throw new HyracksDataException(e);
+        }
 
         if (conf.is(SessionConfig.FORMAT_HTML)) {
             conf.out().println("</pre>");
diff --git 
a/hyracks-fullstack/algebricks/algebricks-core/src/main/java/org/apache/hyracks/algebricks/core/algebra/plan/ALogicalPlanImpl.java
 
b/hyracks-fullstack/algebricks/algebricks-core/src/main/java/org/apache/hyracks/algebricks/core/algebra/plan/ALogicalPlanImpl.java
index 082c2ce..f8d0a50 100644
--- 
a/hyracks-fullstack/algebricks/algebricks-core/src/main/java/org/apache/hyracks/algebricks/core/algebra/plan/ALogicalPlanImpl.java
+++ 
b/hyracks-fullstack/algebricks/algebricks-core/src/main/java/org/apache/hyracks/algebricks/core/algebra/plan/ALogicalPlanImpl.java
@@ -55,9 +55,8 @@
 
     public static String prettyPrintPlan(ILogicalPlan plan) throws 
AlgebricksException {
         LogicalOperatorPrettyPrintVisitor pvisitor = new 
LogicalOperatorPrettyPrintVisitor();
-        StringBuilder buffer = new StringBuilder();
-        PlanPrettyPrinter.printPlan(plan, buffer, pvisitor, 0);
-        return buffer.toString();
+        PlanPrettyPrinter.printPlan(plan, pvisitor, 0);
+        return pvisitor.get().toString();
     }
 
     @Override
diff --git 
a/hyracks-fullstack/algebricks/algebricks-core/src/main/java/org/apache/hyracks/algebricks/core/algebra/prettyprint/AlgebricksAppendable.java
 
b/hyracks-fullstack/algebricks/algebricks-core/src/main/java/org/apache/hyracks/algebricks/core/algebra/prettyprint/AlgebricksAppendable.java
new file mode 100644
index 0000000..7002493
--- /dev/null
+++ 
b/hyracks-fullstack/algebricks/algebricks-core/src/main/java/org/apache/hyracks/algebricks/core/algebra/prettyprint/AlgebricksAppendable.java
@@ -0,0 +1,70 @@
+/*
+ * 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.hyracks.algebricks.core.algebra.prettyprint;
+
+import java.io.IOException;
+
+import org.apache.hyracks.algebricks.common.exceptions.AlgebricksException;
+
+public class AlgebricksAppendable {
+    final Appendable app;
+
+    public AlgebricksAppendable() {
+        this.app = new StringBuilder();
+    }
+
+    public AlgebricksAppendable(Appendable app) {
+        this.app = app;
+    }
+
+    public Appendable getAppendable() {
+        return app;
+    }
+
+    @Override public String toString() {
+        return app.toString();
+    }
+
+    public AlgebricksAppendable append(CharSequence csq) throws 
AlgebricksException {
+        try {
+            app.append(csq);
+            return this;
+        } catch (IOException e) {
+            throw new AlgebricksException(e);
+        }
+    }
+
+    public AlgebricksAppendable append(CharSequence csq, int start, int end) 
throws AlgebricksException {
+        try {
+            app.append(csq, start, end);
+            return this;
+        } catch (IOException e) {
+            throw new AlgebricksException(e);
+        }
+    }
+
+    public AlgebricksAppendable append(char c) throws AlgebricksException {
+        try {
+            app.append(c);
+            return this;
+        } catch (IOException e) {
+            throw new AlgebricksException(e);
+        }
+    }
+}
diff --git 
a/hyracks-fullstack/algebricks/algebricks-core/src/main/java/org/apache/hyracks/algebricks/core/algebra/prettyprint/LogicalOperatorPrettyPrintVisitor.java
 
b/hyracks-fullstack/algebricks/algebricks-core/src/main/java/org/apache/hyracks/algebricks/core/algebra/prettyprint/LogicalOperatorPrettyPrintVisitor.java
index f961bd9..7c749ed 100644
--- 
a/hyracks-fullstack/algebricks/algebricks-core/src/main/java/org/apache/hyracks/algebricks/core/algebra/prettyprint/LogicalOperatorPrettyPrintVisitor.java
+++ 
b/hyracks-fullstack/algebricks/algebricks-core/src/main/java/org/apache/hyracks/algebricks/core/algebra/prettyprint/LogicalOperatorPrettyPrintVisitor.java
@@ -41,7 +41,6 @@
 import 
org.apache.hyracks.algebricks.core.algebra.operators.logical.IndexInsertDeleteUpsertOperator;
 import 
org.apache.hyracks.algebricks.core.algebra.operators.logical.InnerJoinOperator;
 import 
org.apache.hyracks.algebricks.core.algebra.operators.logical.InsertDeleteUpsertOperator;
-import 
org.apache.hyracks.algebricks.core.algebra.operators.logical.InsertDeleteUpsertOperator.Kind;
 import 
org.apache.hyracks.algebricks.core.algebra.operators.logical.IntersectOperator;
 import 
org.apache.hyracks.algebricks.core.algebra.operators.logical.LeftOuterJoinOperator;
 import 
org.apache.hyracks.algebricks.core.algebra.operators.logical.LeftOuterUnnestMapOperator;
@@ -64,328 +63,323 @@
 import 
org.apache.hyracks.algebricks.core.algebra.operators.logical.UnnestOperator;
 import 
org.apache.hyracks.algebricks.core.algebra.operators.logical.WriteOperator;
 import 
org.apache.hyracks.algebricks.core.algebra.operators.logical.WriteResultOperator;
+import 
org.apache.hyracks.algebricks.core.algebra.operators.logical.InsertDeleteUpsertOperator.Kind;
 import 
org.apache.hyracks.algebricks.core.algebra.visitors.ILogicalExpressionVisitor;
 import 
org.apache.hyracks.algebricks.core.algebra.visitors.ILogicalOperatorVisitor;
 
-public class LogicalOperatorPrettyPrintVisitor implements 
ILogicalOperatorVisitor<String, Integer> {
+public class LogicalOperatorPrettyPrintVisitor implements 
ILogicalOperatorVisitor<Void, Integer> {
 
     ILogicalExpressionVisitor<String, Integer> exprVisitor;
+    AlgebricksAppendable buffer;
 
     public LogicalOperatorPrettyPrintVisitor() {
-        exprVisitor = new LogicalExpressionPrettyPrintVisitor();
+        this(new AlgebricksAppendable());
     }
 
-    public LogicalOperatorPrettyPrintVisitor(ILogicalExpressionVisitor<String, 
Integer> exprVisitor) {
+    public LogicalOperatorPrettyPrintVisitor(Appendable app) {
+        this(new AlgebricksAppendable(app), new 
LogicalExpressionPrettyPrintVisitor());
+    }
+
+    public LogicalOperatorPrettyPrintVisitor(AlgebricksAppendable buffer) {
+        this(buffer, new LogicalExpressionPrettyPrintVisitor());
+    }
+
+    public LogicalOperatorPrettyPrintVisitor(AlgebricksAppendable buffer,
+            ILogicalExpressionVisitor<String, Integer> exprVisitor) {
+        reset(buffer);
         this.exprVisitor = exprVisitor;
     }
 
-    @Override
-    public String visitAggregateOperator(AggregateOperator op, Integer indent) 
throws AlgebricksException {
-        StringBuilder buffer = new StringBuilder();
-        addIndent(buffer, indent).append("aggregate 
").append(op.getVariables()).append(" <- ");
-        pprintExprList(op.getExpressions(), buffer, indent);
-        return buffer.toString();
+    public AlgebricksAppendable reset(AlgebricksAppendable buffer) {
+        AlgebricksAppendable old = this.buffer;
+        this.buffer = buffer;
+        return old;
+    }
+
+    public AlgebricksAppendable get() {
+        return buffer;
     }
 
     @Override
-    public String visitRunningAggregateOperator(RunningAggregateOperator op, 
Integer indent)
-            throws AlgebricksException {
-        StringBuilder buffer = new StringBuilder();
-        addIndent(buffer, indent).append("running-aggregate 
").append(op.getVariables()).append(" <- ");
-        pprintExprList(op.getExpressions(), buffer, indent);
+    public String toString() {
         return buffer.toString();
     }
 
-    @Override
-    public String visitEmptyTupleSourceOperator(EmptyTupleSourceOperator op, 
Integer indent) {
-        StringBuilder buffer = new StringBuilder();
-        addIndent(buffer, indent).append("empty-tuple-source");
-        return buffer.toString();
+    CharSequence str(Object o) {
+        return String.valueOf(o);
     }
 
     @Override
-    public String visitGroupByOperator(GroupByOperator op, Integer indent) 
throws AlgebricksException {
-        StringBuilder buffer = new StringBuilder();
-        addIndent(buffer, indent).append("group by (");
-        pprintVeList(buffer, op.getGroupByList(), indent);
+    public Void visitAggregateOperator(AggregateOperator op, Integer indent) 
throws AlgebricksException {
+        addIndent(indent).append("aggregate 
").append(str(op.getVariables())).append(" <- ");
+        pprintExprList(op.getExpressions(), indent);
+        return null;
+    }
+
+    @Override
+    public Void visitRunningAggregateOperator(RunningAggregateOperator op, 
Integer indent) throws AlgebricksException {
+        addIndent(indent).append("running-aggregate 
").append(str(op.getVariables())).append(" <- ");
+        pprintExprList(op.getExpressions(), indent);
+        return null;
+    }
+
+    @Override
+    public Void visitEmptyTupleSourceOperator(EmptyTupleSourceOperator op, 
Integer indent) throws AlgebricksException {
+        addIndent(indent).append("empty-tuple-source");
+        return null;
+    }
+
+    @Override
+    public Void visitGroupByOperator(GroupByOperator op, Integer indent) 
throws AlgebricksException {
+        addIndent(indent).append("group by (");
+        pprintVeList(op.getGroupByList(), indent);
         buffer.append(") decor (");
-        pprintVeList(buffer, op.getDecorList(), indent);
+        pprintVeList(op.getDecorList(), indent);
         buffer.append(") {");
-        printNestedPlans(op, indent, buffer);
-        return buffer.toString();
+        printNestedPlans(op, indent);
+        return null;
     }
 
     @Override
-    public String visitDistinctOperator(DistinctOperator op, Integer indent) 
throws AlgebricksException {
-        StringBuilder buffer = new StringBuilder();
-        addIndent(buffer, indent).append("distinct " + "(");
-        pprintExprList(op.getExpressions(), buffer, indent);
+    public Void visitDistinctOperator(DistinctOperator op, Integer indent) 
throws AlgebricksException {
+        addIndent(indent).append("distinct " + "(");
+        pprintExprList(op.getExpressions(), indent);
         buffer.append(")");
-        return buffer.toString();
+        return null;
     }
 
     @Override
-    public String visitInnerJoinOperator(InnerJoinOperator op, Integer indent) 
throws AlgebricksException {
-        StringBuilder buffer = new StringBuilder();
-        addIndent(buffer, indent).append("join 
(").append(op.getCondition().getValue().accept(exprVisitor, indent))
+    public Void visitInnerJoinOperator(InnerJoinOperator op, Integer indent) 
throws AlgebricksException {
+        addIndent(indent).append("join 
(").append(op.getCondition().getValue().accept(exprVisitor, 
indent)).append(")");
+        return null;
+    }
+
+    @Override
+    public Void visitLeftOuterJoinOperator(LeftOuterJoinOperator op, Integer 
indent) throws AlgebricksException {
+        addIndent(indent).append("left outer join 
(").append(op.getCondition().getValue().accept(exprVisitor, indent))
                 .append(")");
-        return buffer.toString();
+        return null;
     }
 
     @Override
-    public String visitLeftOuterJoinOperator(LeftOuterJoinOperator op, Integer 
indent) throws AlgebricksException {
-        StringBuilder buffer = new StringBuilder();
-        addIndent(buffer, indent).append("left outer join (")
-                .append(op.getCondition().getValue().accept(exprVisitor, 
indent)).append(")");
-        return buffer.toString();
+    public Void visitNestedTupleSourceOperator(NestedTupleSourceOperator op, 
Integer indent)
+            throws AlgebricksException {
+        addIndent(indent).append("nested tuple source");
+        return null;
     }
 
     @Override
-    public String visitNestedTupleSourceOperator(NestedTupleSourceOperator op, 
Integer indent) {
-        StringBuilder buffer = new StringBuilder();
-        addIndent(buffer, indent).append("nested tuple source");
-        return buffer.toString();
-    }
-
-    @Override
-    public String visitOrderOperator(OrderOperator op, Integer indent) throws 
AlgebricksException {
-        StringBuilder buffer = new StringBuilder();
-        addIndent(buffer, indent).append("order ");
+    public Void visitOrderOperator(OrderOperator op, Integer indent) throws 
AlgebricksException {
+        addIndent(indent).append("order ");
         for (Pair<OrderOperator.IOrder, Mutable<ILogicalExpression>> p : 
op.getOrderExpressions()) {
-            String fst;
-
             if (op.getTopK() != -1) {
                 buffer.append("(topK: " + op.getTopK() + ") ");
             }
-
-            switch (p.first.getKind()) {
-                case ASC: {
-                    fst = "ASC";
-                    break;
-                }
-                case DESC: {
-                    fst = "DESC";
-                    break;
-                }
-                default: {
-                    fst = p.first.getExpressionRef().toString();
-                }
-            }
+            String fst = getOrderString(p.first);
             buffer.append("(" + fst + ", " + 
p.second.getValue().accept(exprVisitor, indent) + ") ");
 
         }
-        return buffer.toString();
+        return null;
+    }
+
+    private String getOrderString(OrderOperator.IOrder first) {
+        switch (first.getKind()) {
+            case ASC:
+                return "ASC";
+            case DESC:
+                return "DESC";
+            default:
+                return first.getExpressionRef().toString();
+        }
     }
 
     @Override
-    public String visitAssignOperator(AssignOperator op, Integer indent) 
throws AlgebricksException {
-        StringBuilder buffer = new StringBuilder();
-        addIndent(buffer, indent).append("assign 
").append(op.getVariables()).append(" <- ");
-        pprintExprList(op.getExpressions(), buffer, indent);
-        return buffer.toString();
+    public Void visitAssignOperator(AssignOperator op, Integer indent) throws 
AlgebricksException {
+        addIndent(indent).append("assign 
").append(str(op.getVariables())).append(" <- ");
+        pprintExprList(op.getExpressions(), indent);
+        return null;
     }
 
     @Override
-    public String visitWriteOperator(WriteOperator op, Integer indent) throws 
AlgebricksException {
-        StringBuilder buffer = new StringBuilder();
-        addIndent(buffer, indent).append("write ");
-        pprintExprList(op.getExpressions(), buffer, indent);
-        return buffer.toString();
+    public Void visitWriteOperator(WriteOperator op, Integer indent) throws 
AlgebricksException {
+        addIndent(indent).append("write ");
+        pprintExprList(op.getExpressions(), indent);
+        return null;
     }
 
     @Override
-    public String visitDistributeResultOperator(DistributeResultOperator op, 
Integer indent)
-            throws AlgebricksException {
-        StringBuilder buffer = new StringBuilder();
-        addIndent(buffer, indent).append("distribute result ");
-        pprintExprList(op.getExpressions(), buffer, indent);
-        return buffer.toString();
+    public Void visitDistributeResultOperator(DistributeResultOperator op, 
Integer indent) throws AlgebricksException {
+        addIndent(indent).append("distribute result ");
+        pprintExprList(op.getExpressions(), indent);
+        return null;
     }
 
     @Override
-    public String visitWriteResultOperator(WriteResultOperator op, Integer 
indent) throws AlgebricksException {
-        StringBuilder buffer = new StringBuilder();
-        addIndent(buffer, indent).append("load 
").append(op.getDataSource()).append(" from ")
+    public Void visitWriteResultOperator(WriteResultOperator op, Integer 
indent) throws AlgebricksException {
+        addIndent(indent).append("load 
").append(str(op.getDataSource())).append(" from ")
                 
.append(op.getPayloadExpression().getValue().accept(exprVisitor, 
indent)).append(" partitioned by ");
-        pprintExprList(op.getKeyExpressions(), buffer, indent);
-        return buffer.toString();
+        pprintExprList(op.getKeyExpressions(), indent);
+        return null;
     }
 
     @Override
-    public String visitSelectOperator(SelectOperator op, Integer indent) 
throws AlgebricksException {
-        StringBuilder buffer = new StringBuilder();
-        addIndent(buffer, indent).append("select 
(").append(op.getCondition().getValue().accept(exprVisitor, indent))
+    public Void visitSelectOperator(SelectOperator op, Integer indent) throws 
AlgebricksException {
+        addIndent(indent).append("select 
(").append(op.getCondition().getValue().accept(exprVisitor, indent))
                 .append(")");
-        return buffer.toString();
+        return null;
     }
 
     @Override
-    public String visitProjectOperator(ProjectOperator op, Integer indent) {
-        StringBuilder buffer = new StringBuilder();
-        addIndent(buffer, indent).append("project " + "(" + op.getVariables() 
+ ")");
-        return buffer.toString();
+    public Void visitProjectOperator(ProjectOperator op, Integer indent) 
throws AlgebricksException {
+        addIndent(indent).append("project " + "(" + op.getVariables() + ")");
+        return null;
     }
 
     @Override
-    public String visitPartitioningSplitOperator(PartitioningSplitOperator op, 
Integer indent)
+    public Void visitPartitioningSplitOperator(PartitioningSplitOperator op, 
Integer indent)
             throws AlgebricksException {
-        StringBuilder buffer = new StringBuilder();
-        addIndent(buffer, indent).append("partitioning-split (");
-        pprintExprList(op.getExpressions(), buffer, indent);
+        addIndent(indent).append("partitioning-split (");
+        pprintExprList(op.getExpressions(), indent);
         buffer.append(")");
-        return buffer.toString();
+        return null;
     }
 
     @Override
-    public String visitSubplanOperator(SubplanOperator op, Integer indent) 
throws AlgebricksException {
-        StringBuilder buffer = new StringBuilder();
-        addIndent(buffer, indent).append("subplan {");
-        printNestedPlans(op, indent, buffer);
-        return buffer.toString();
+    public Void visitSubplanOperator(SubplanOperator op, Integer indent) 
throws AlgebricksException {
+        addIndent(indent).append("subplan {");
+        printNestedPlans(op, indent);
+        return null;
     }
 
     @Override
-    public String visitUnionOperator(UnionAllOperator op, Integer indent) {
-        StringBuilder buffer = new StringBuilder();
-        addIndent(buffer, indent).append("union");
+    public Void visitUnionOperator(UnionAllOperator op, Integer indent) throws 
AlgebricksException {
+        addIndent(indent).append("union");
         for (Triple<LogicalVariable, LogicalVariable, LogicalVariable> v : 
op.getVariableMappings()) {
             buffer.append(" (" + v.first + ", " + v.second + ", " + v.third + 
")");
         }
-        return buffer.toString();
+        return null;
     }
 
     @Override
-    public String visitIntersectOperator(IntersectOperator op, Integer indent) 
throws AlgebricksException {
-        StringBuilder builder = new StringBuilder();
-        addIndent(builder, indent).append("intersect (");
+    public Void visitIntersectOperator(IntersectOperator op, Integer indent) 
throws AlgebricksException {
+        addIndent(indent).append("intersect (");
 
-        builder.append('[');
+        buffer.append('[');
         for (int i = 0; i < op.getOutputVars().size(); i++) {
             if (i > 0) {
-                builder.append(", ");
+                buffer.append(", ");
             }
-            builder.append(op.getOutputVars().get(i));
+            buffer.append(str(op.getOutputVars().get(i)));
         }
-        builder.append("] <- [");
+        buffer.append("] <- [");
         for (int i = 0; i < op.getNumInput(); i++) {
             if (i > 0) {
-                builder.append(", ");
+                buffer.append(", ");
             }
-            builder.append('[');
+            buffer.append('[');
             for (int j = 0; j < op.getInputVariables(i).size(); j++) {
                 if (j > 0) {
-                    builder.append(", ");
+                    buffer.append(", ");
                 }
-                builder.append(op.getInputVariables(i).get(j));
+                buffer.append(str(op.getInputVariables(i).get(j)));
             }
-            builder.append(']');
+            buffer.append(']');
         }
-        builder.append("])");
-        return builder.toString();
+        buffer.append("])");
+        return null;
     }
 
     @Override
-    public String visitUnnestOperator(UnnestOperator op, Integer indent) 
throws AlgebricksException {
-        StringBuilder buffer = new StringBuilder();
-        addIndent(buffer, indent).append("unnest " + op.getVariable());
+    public Void visitUnnestOperator(UnnestOperator op, Integer indent) throws 
AlgebricksException {
+        addIndent(indent).append("unnest " + op.getVariable());
         if (op.getPositionalVariable() != null) {
             buffer.append(" at " + op.getPositionalVariable());
         }
         buffer.append(" <- " + 
op.getExpressionRef().getValue().accept(exprVisitor, indent));
-        return buffer.toString();
+        return null;
     }
 
     @Override
-    public String visitLeftOuterUnnestOperator(LeftOuterUnnestOperator op, 
Integer indent) throws AlgebricksException {
-        StringBuilder buffer = new StringBuilder();
-        addIndent(buffer, indent).append("outer-unnest " + op.getVariable());
+    public Void visitLeftOuterUnnestOperator(LeftOuterUnnestOperator op, 
Integer indent) throws AlgebricksException {
+        addIndent(indent).append("outer-unnest " + op.getVariable());
         if (op.getPositionalVariable() != null) {
             buffer.append(" at " + op.getPositionalVariable());
         }
         buffer.append(" <- " + 
op.getExpressionRef().getValue().accept(exprVisitor, indent));
-        return buffer.toString();
+        return null;
     }
 
     @Override
-    public String visitUnnestMapOperator(UnnestMapOperator op, Integer indent) 
throws AlgebricksException {
+    public Void visitUnnestMapOperator(UnnestMapOperator op, Integer indent) 
throws AlgebricksException {
         return printAbstractUnnestMapOperator(op, indent, "unnest-map");
     }
 
     @Override
-    public String visitLeftOuterUnnestMapOperator(LeftOuterUnnestMapOperator 
op, Integer indent)
+    public Void visitLeftOuterUnnestMapOperator(LeftOuterUnnestMapOperator op, 
Integer indent)
             throws AlgebricksException {
         return printAbstractUnnestMapOperator(op, indent, 
"left-outer-unnest-map");
     }
 
-    private String printAbstractUnnestMapOperator(AbstractUnnestMapOperator 
op, Integer indent, String opSignature)
+    private Void printAbstractUnnestMapOperator(AbstractUnnestMapOperator op, 
Integer indent, String opSignature)
             throws AlgebricksException {
-        StringBuilder buffer = new StringBuilder();
-        addIndent(buffer, indent).append(opSignature + " " + op.getVariables() 
+ " <- "
+        addIndent(indent).append(opSignature + " " + op.getVariables() + " <- "
                 + op.getExpressionRef().getValue().accept(exprVisitor, 
indent));
-        return buffer.toString();
+        return null;
     }
 
     @Override
-    public String visitDataScanOperator(DataSourceScanOperator op, Integer 
indent) {
-        StringBuilder buffer = new StringBuilder();
-        addIndent(buffer, indent).append(
+    public Void visitDataScanOperator(DataSourceScanOperator op, Integer 
indent) throws AlgebricksException {
+        addIndent(indent).append(
                 "data-scan " + op.getProjectVariables() + "<-" + 
op.getVariables() + " <- " + op.getDataSource());
-        return buffer.toString();
+        return null;
     }
 
     @Override
-    public String visitLimitOperator(LimitOperator op, Integer indent) throws 
AlgebricksException {
-        StringBuilder buffer = new StringBuilder();
-        addIndent(buffer, indent).append("limit " + 
op.getMaxObjects().getValue().accept(exprVisitor, indent));
+    public Void visitLimitOperator(LimitOperator op, Integer indent) throws 
AlgebricksException {
+        addIndent(indent).append("limit " + 
op.getMaxObjects().getValue().accept(exprVisitor, indent));
         ILogicalExpression offset = op.getOffset().getValue();
         if (offset != null) {
             buffer.append(", " + offset.accept(exprVisitor, indent));
         }
-        return buffer.toString();
+        return null;
     }
 
     @Override
-    public String visitExchangeOperator(ExchangeOperator op, Integer indent) {
-        StringBuilder buffer = new StringBuilder();
-        addIndent(buffer, indent).append("exchange ");
-        return buffer.toString();
+    public Void visitExchangeOperator(ExchangeOperator op, Integer indent) 
throws AlgebricksException {
+        addIndent(indent).append("exchange ");
+        return null;
     }
 
     @Override
-    public String visitScriptOperator(ScriptOperator op, Integer indent) {
-        StringBuilder buffer = new StringBuilder();
-        addIndent(buffer, indent)
-                .append("script (in: " + op.getInputVariables() + ") (out: " + 
op.getOutputVariables() + ")");
-        return buffer.toString();
+    public Void visitScriptOperator(ScriptOperator op, Integer indent) throws 
AlgebricksException {
+        addIndent(indent).append("script (in: " + op.getInputVariables() + ") 
(out: " + op.getOutputVariables() + ")");
+        return null;
     }
 
     @Override
-    public String visitReplicateOperator(ReplicateOperator op, Integer indent) 
throws AlgebricksException {
-        StringBuilder buffer = new StringBuilder();
-        addIndent(buffer, indent).append("replicate ");
-        return buffer.toString();
+    public Void visitReplicateOperator(ReplicateOperator op, Integer indent) 
throws AlgebricksException {
+        addIndent(indent).append("replicate ");
+        return null;
     }
 
     @Override
-    public String visitMaterializeOperator(MaterializeOperator op, Integer 
indent) throws AlgebricksException {
-        StringBuilder buffer = new StringBuilder();
-        addIndent(buffer, indent).append("materialize ");
-        return buffer.toString();
+    public Void visitMaterializeOperator(MaterializeOperator op, Integer 
indent) throws AlgebricksException {
+        addIndent(indent).append("materialize ");
+        return null;
     }
 
     @Override
-    public String visitInsertDeleteUpsertOperator(InsertDeleteUpsertOperator 
op, Integer indent)
+    public Void visitInsertDeleteUpsertOperator(InsertDeleteUpsertOperator op, 
Integer indent)
             throws AlgebricksException {
-        StringBuilder buffer = new StringBuilder();
         String header = getIndexOpString(op.getOperation());
-        addIndent(buffer, 
indent).append(header).append(op.getDataSource()).append(" from record: ")
+        
addIndent(indent).append(header).append(str(op.getDataSource())).append(" from 
record: ")
                 
.append(op.getPayloadExpression().getValue().accept(exprVisitor, indent));
         if (op.getAdditionalNonFilteringExpressions() != null) {
             buffer.append(", meta: ");
-            pprintExprList(op.getAdditionalNonFilteringExpressions(), buffer, 
indent);
+            pprintExprList(op.getAdditionalNonFilteringExpressions(), indent);
         }
         buffer.append(" partitioned by ");
-        pprintExprList(op.getPrimaryKeyExpressions(), buffer, indent);
+        pprintExprList(op.getPrimaryKeyExpressions(), indent);
         if (op.getOperation() == Kind.UPSERT) {
             buffer.append(
                     " out: ([record-before-upsert:" + op.getPrevRecordVar()
@@ -396,28 +390,27 @@
         if (op.isBulkload()) {
             buffer.append(" [bulkload]");
         }
-        return buffer.toString();
+        return null;
     }
 
     @Override
-    public String 
visitIndexInsertDeleteUpsertOperator(IndexInsertDeleteUpsertOperator op, 
Integer indent)
+    public Void 
visitIndexInsertDeleteUpsertOperator(IndexInsertDeleteUpsertOperator op, 
Integer indent)
             throws AlgebricksException {
-        StringBuilder buffer = new StringBuilder();
         String header = getIndexOpString(op.getOperation());
-        addIndent(buffer, 
indent).append(header).append(op.getIndexName()).append(" on ")
-                .append(op.getDataSourceIndex().getDataSource()).append(" from 
");
+        addIndent(indent).append(header).append(op.getIndexName()).append(" on 
")
+                .append(str(op.getDataSourceIndex().getDataSource())).append(" 
from ");
         if (op.getOperation() == Kind.UPSERT) {
             buffer.append(" replace:");
-            pprintExprList(op.getPrevSecondaryKeyExprs(), buffer, indent);
+            pprintExprList(op.getPrevSecondaryKeyExprs(), indent);
             buffer.append(" with:");
-            pprintExprList(op.getSecondaryKeyExpressions(), buffer, indent);
+            pprintExprList(op.getSecondaryKeyExpressions(), indent);
         } else {
-            pprintExprList(op.getSecondaryKeyExpressions(), buffer, indent);
+            pprintExprList(op.getSecondaryKeyExpressions(), indent);
         }
         if (op.isBulkload()) {
             buffer.append(" [bulkload]");
         }
-        return buffer.toString();
+        return null;
     }
 
     public String getIndexOpString(Kind opKind) {
@@ -433,36 +426,32 @@
     }
 
     @Override
-    public String visitTokenizeOperator(TokenizeOperator op, Integer indent) 
throws AlgebricksException {
-        StringBuilder buffer = new StringBuilder();
-        addIndent(buffer, indent).append("tokenize 
").append(op.getTokenizeVars()).append(" <- ");
-        pprintExprList(op.getSecondaryKeyExpressions(), buffer, indent);
-        return buffer.toString();
+    public Void visitTokenizeOperator(TokenizeOperator op, Integer indent) 
throws AlgebricksException {
+        addIndent(indent).append("tokenize 
").append(str(op.getTokenizeVars())).append(" <- ");
+        pprintExprList(op.getSecondaryKeyExpressions(), indent);
+        return null;
     }
 
     @Override
-    public String visitSinkOperator(SinkOperator op, Integer indent) throws 
AlgebricksException {
-        StringBuilder buffer = new StringBuilder();
-        addIndent(buffer, indent).append("sink");
-        return buffer.toString();
+    public Void visitSinkOperator(SinkOperator op, Integer indent) throws 
AlgebricksException {
+        addIndent(indent).append("sink");
+        return null;
     }
 
     @Override
-    public String visitExtensionOperator(ExtensionOperator op, Integer indent) 
throws AlgebricksException {
-        StringBuilder buffer = new StringBuilder();
-        addIndent(buffer, indent).append(op.toString());
-        return buffer.toString();
+    public Void visitExtensionOperator(ExtensionOperator op, Integer indent) 
throws AlgebricksException {
+        addIndent(indent).append(op.toString());
+        return null;
     }
 
-    protected static StringBuilder addIndent(StringBuilder buffer, int level) {
+    protected AlgebricksAppendable addIndent(int level) throws 
AlgebricksException {
         for (int i = 0; i < level; ++i) {
             buffer.append(' ');
         }
         return buffer;
     }
 
-    protected void printNestedPlans(AbstractOperatorWithNestedPlans op, 
Integer indent, StringBuilder buffer)
-            throws AlgebricksException {
+    protected void printNestedPlans(AbstractOperatorWithNestedPlans op, 
Integer indent) throws AlgebricksException {
         boolean first = true;
         if (op.getNestedPlans().isEmpty()) {
             buffer.append("}");
@@ -474,15 +463,15 @@
                 if (first) {
                     first = false;
                 } else {
-                    addIndent(buffer, indent).append("       {\n");
+                    addIndent(indent).append("       {\n");
                 }
-                PlanPrettyPrinter.printPlan(p, buffer, this, indent + 10);
-                addIndent(buffer, indent).append("       }");
+                PlanPrettyPrinter.printPlan(p, this, indent + 10);
+                addIndent(indent).append("       }");
             }
         }
     }
 
-    protected void pprintExprList(List<Mutable<ILogicalExpression>> 
expressions, StringBuilder buffer, Integer indent)
+    protected void pprintExprList(List<Mutable<ILogicalExpression>> 
expressions, Integer indent)
             throws AlgebricksException {
         buffer.append("[");
         boolean first = true;
@@ -497,22 +486,22 @@
         buffer.append("]");
     }
 
-    protected void pprintVeList(StringBuilder sb, List<Pair<LogicalVariable, 
Mutable<ILogicalExpression>>> vePairList,
-            Integer indent) throws AlgebricksException {
-        sb.append("[");
+    protected void pprintVeList(List<Pair<LogicalVariable, 
Mutable<ILogicalExpression>>> vePairList, Integer indent)
+            throws AlgebricksException {
+        buffer.append("[");
         boolean fst = true;
         for (Pair<LogicalVariable, Mutable<ILogicalExpression>> ve : 
vePairList) {
             if (fst) {
                 fst = false;
             } else {
-                sb.append("; ");
+                buffer.append("; ");
             }
             if (ve.first != null) {
-                sb.append(ve.first + " := " + ve.second);
+                buffer.append(ve.first + " := " + ve.second);
             } else {
-                sb.append(ve.second.getValue().accept(exprVisitor, indent));
+                buffer.append(ve.second.getValue().accept(exprVisitor, 
indent));
             }
         }
-        sb.append("]");
+        buffer.append("]");
     }
 }
diff --git 
a/hyracks-fullstack/algebricks/algebricks-core/src/main/java/org/apache/hyracks/algebricks/core/algebra/prettyprint/PlanPrettyPrinter.java
 
b/hyracks-fullstack/algebricks/algebricks-core/src/main/java/org/apache/hyracks/algebricks/core/algebra/prettyprint/PlanPrettyPrinter.java
index fcf53ec..9a55f11 100644
--- 
a/hyracks-fullstack/algebricks/algebricks-core/src/main/java/org/apache/hyracks/algebricks/core/algebra/prettyprint/PlanPrettyPrinter.java
+++ 
b/hyracks-fullstack/algebricks/algebricks-core/src/main/java/org/apache/hyracks/algebricks/core/algebra/prettyprint/PlanPrettyPrinter.java
@@ -19,7 +19,6 @@
 package org.apache.hyracks.algebricks.core.algebra.prettyprint;
 
 import org.apache.commons.lang3.mutable.Mutable;
-
 import org.apache.hyracks.algebricks.common.exceptions.AlgebricksException;
 import org.apache.hyracks.algebricks.core.algebra.base.ILogicalOperator;
 import org.apache.hyracks.algebricks.core.algebra.base.ILogicalPlan;
@@ -28,22 +27,24 @@
 import 
org.apache.hyracks.algebricks.core.algebra.operators.logical.AbstractOperatorWithNestedPlans;
 
 public class PlanPrettyPrinter {
-    public static void printPlan(ILogicalPlan plan, StringBuilder out, 
LogicalOperatorPrettyPrintVisitor pvisitor,
-            int indent) throws AlgebricksException {
+    public static void printPlan(ILogicalPlan plan, 
LogicalOperatorPrettyPrintVisitor pvisitor, int indent)
+            throws AlgebricksException {
         for (Mutable<ILogicalOperator> root : plan.getRoots()) {
-            printOperator((AbstractLogicalOperator) root.getValue(), out, 
pvisitor, indent);
+            printOperator((AbstractLogicalOperator) root.getValue(), pvisitor, 
indent);
         }
     }
 
-    public static void printPhysicalOps(ILogicalPlan plan, StringBuilder out, 
int indent) {
+    public static void printPhysicalOps(ILogicalPlan plan, 
AlgebricksAppendable out, int indent)
+            throws AlgebricksException {
         for (Mutable<ILogicalOperator> root : plan.getRoots()) {
             printPhysicalOperator((AbstractLogicalOperator) root.getValue(), 
indent, out);
         }
     }
 
-    public static void printOperator(AbstractLogicalOperator op, StringBuilder 
out,
-            LogicalOperatorPrettyPrintVisitor pvisitor, int indent) throws 
AlgebricksException {
-        out.append(op.accept(pvisitor, indent));
+    public static void printOperator(AbstractLogicalOperator op, 
LogicalOperatorPrettyPrintVisitor pvisitor, int indent)
+            throws AlgebricksException {
+        final AlgebricksAppendable out = pvisitor.get();
+        op.accept(pvisitor, indent);
         IPhysicalOperator pOp = op.getPhysicalOperator();
 
         if (pOp != null) {
@@ -55,12 +56,12 @@
         }
 
         for (Mutable<ILogicalOperator> i : op.getInputs()) {
-            printOperator((AbstractLogicalOperator) i.getValue(), out, 
pvisitor, indent + 2);
+            printOperator((AbstractLogicalOperator) i.getValue(), pvisitor, 
indent + 2);
         }
-
     }
 
-    public static void printPhysicalOperator(AbstractLogicalOperator op, int 
indent, StringBuilder out) {
+    private static void printPhysicalOperator(AbstractLogicalOperator op, int 
indent, AlgebricksAppendable out)
+            throws AlgebricksException {
         IPhysicalOperator pOp = op.getPhysicalOperator();
         pad(out, indent);
         appendln(out, "-- " + pOp.toString() + "  |" + op.getExecutionMode() + 
"|");
@@ -74,19 +75,17 @@
                 appendln(out, "}");
             }
         }
-
         for (Mutable<ILogicalOperator> i : op.getInputs()) {
             printPhysicalOperator((AbstractLogicalOperator) i.getValue(), 
indent + 2, out);
         }
-
     }
 
-    private static void appendln(StringBuilder buf, String s) {
+    private static void appendln(AlgebricksAppendable buf, String s) throws 
AlgebricksException {
         buf.append(s);
         buf.append("\n");
     }
 
-    private static void pad(StringBuilder buf, int indent) {
+    private static void pad(AlgebricksAppendable buf, int indent) throws 
AlgebricksException {
         for (int i = 0; i < indent; ++i) {
             buf.append(' ');
         }
diff --git 
a/hyracks-fullstack/algebricks/algebricks-core/src/main/java/org/apache/hyracks/algebricks/core/rewriter/base/AbstractRuleController.java
 
b/hyracks-fullstack/algebricks/algebricks-core/src/main/java/org/apache/hyracks/algebricks/core/rewriter/base/AbstractRuleController.java
index 5adb566..98fe7b0 100644
--- 
a/hyracks-fullstack/algebricks/algebricks-core/src/main/java/org/apache/hyracks/algebricks/core/rewriter/base/AbstractRuleController.java
+++ 
b/hyracks-fullstack/algebricks/algebricks-core/src/main/java/org/apache/hyracks/algebricks/core/rewriter/base/AbstractRuleController.java
@@ -28,6 +28,7 @@
 import org.apache.hyracks.algebricks.core.algebra.base.IOptimizationContext;
 import 
org.apache.hyracks.algebricks.core.algebra.operators.logical.AbstractLogicalOperator;
 import 
org.apache.hyracks.algebricks.core.algebra.operators.logical.AbstractOperatorWithNestedPlans;
+import 
org.apache.hyracks.algebricks.core.algebra.prettyprint.AlgebricksAppendable;
 import 
org.apache.hyracks.algebricks.core.algebra.prettyprint.LogicalOperatorPrettyPrintVisitor;
 import 
org.apache.hyracks.algebricks.core.algebra.prettyprint.PlanPrettyPrinter;
 import org.apache.hyracks.algebricks.core.config.AlgebricksConfig;
@@ -66,10 +67,10 @@
 
     private String getPlanString(Mutable<ILogicalOperator> opRef) throws 
AlgebricksException {
         if (AlgebricksConfig.ALGEBRICKS_LOGGER.isLoggable(Level.FINE)) {
-            StringBuilder sb = new StringBuilder();
             LogicalOperatorPrettyPrintVisitor pvisitor = 
context.getPrettyPrintVisitor();
-            PlanPrettyPrinter.printOperator((AbstractLogicalOperator) 
opRef.getValue(), sb, pvisitor, 0);
-            return sb.toString();
+            pvisitor.reset(new AlgebricksAppendable());
+            PlanPrettyPrinter.printOperator((AbstractLogicalOperator) 
opRef.getValue(), pvisitor, 0);
+            return pvisitor.get().toString();
         }
         return null;
     }
diff --git 
a/hyracks-fullstack/algebricks/algebricks-core/src/main/java/org/apache/hyracks/algebricks/core/rewriter/base/HeuristicOptimizer.java
 
b/hyracks-fullstack/algebricks/algebricks-core/src/main/java/org/apache/hyracks/algebricks/core/rewriter/base/HeuristicOptimizer.java
index 2a28d2e..4d72576 100644
--- 
a/hyracks-fullstack/algebricks/algebricks-core/src/main/java/org/apache/hyracks/algebricks/core/rewriter/base/HeuristicOptimizer.java
+++ 
b/hyracks-fullstack/algebricks/algebricks-core/src/main/java/org/apache/hyracks/algebricks/core/rewriter/base/HeuristicOptimizer.java
@@ -19,9 +19,9 @@
 package org.apache.hyracks.algebricks.core.rewriter.base;
 
 import java.util.List;
+import java.util.logging.Level;
 
 import org.apache.commons.lang3.mutable.Mutable;
-
 import org.apache.hyracks.algebricks.common.exceptions.AlgebricksException;
 import org.apache.hyracks.algebricks.common.utils.Pair;
 import org.apache.hyracks.algebricks.core.algebra.base.ILogicalOperator;
@@ -30,6 +30,8 @@
 import org.apache.hyracks.algebricks.core.algebra.base.PhysicalOperatorTag;
 import 
org.apache.hyracks.algebricks.core.algebra.operators.logical.AbstractLogicalOperator;
 import 
org.apache.hyracks.algebricks.core.algebra.operators.logical.AbstractOperatorWithNestedPlans;
+import 
org.apache.hyracks.algebricks.core.algebra.prettyprint.AlgebricksAppendable;
+import 
org.apache.hyracks.algebricks.core.algebra.prettyprint.LogicalOperatorPrettyPrintVisitor;
 import 
org.apache.hyracks.algebricks.core.algebra.prettyprint.PlanPrettyPrinter;
 import org.apache.hyracks.algebricks.core.config.AlgebricksConfig;
 
@@ -53,10 +55,10 @@
         return false;
     }
 
-    private IOptimizationContext context;
-    private List<Pair<AbstractRuleController, List<IAlgebraicRewriteRule>>> 
logicalRewrites;
-    private List<Pair<AbstractRuleController, List<IAlgebraicRewriteRule>>> 
physicalRewrites;
-    private ILogicalPlan plan;
+    private final IOptimizationContext context;
+    private final List<Pair<AbstractRuleController, 
List<IAlgebraicRewriteRule>>> logicalRewrites;
+    private final List<Pair<AbstractRuleController, 
List<IAlgebraicRewriteRule>>> physicalRewrites;
+    private final ILogicalPlan plan;
 
     public HeuristicOptimizer(ILogicalPlan plan,
             List<Pair<AbstractRuleController, List<IAlgebraicRewriteRule>>> 
logicalRewrites,
@@ -76,15 +78,20 @@
             AlgebricksConfig.ALGEBRICKS_LOGGER.fine("Starting logical 
optimizations.\n");
         }
 
-        StringBuilder sb = new StringBuilder();
-        PlanPrettyPrinter.printPlan(plan, sb, context.getPrettyPrintVisitor(), 
0);
-        AlgebricksConfig.ALGEBRICKS_LOGGER.fine("Logical Plan:\n" + 
sb.toString());
+        logPlanAt("Logical Plan", Level.FINE);
         runOptimizationSets(plan, logicalRewrites);
         computeSchemaBottomUpForPlan(plan);
         runPhysicalOptimizations(plan, physicalRewrites);
-        StringBuilder sb2 = new StringBuilder();
-        PlanPrettyPrinter.printPlan(plan, sb2, 
context.getPrettyPrintVisitor(), 0);
-        AlgebricksConfig.ALGEBRICKS_LOGGER.info("Optimized Plan:\n" + 
sb2.toString());
+        logPlanAt("Optimized Plan", Level.INFO);
+    }
+
+    private void logPlanAt(String name, Level lvl) throws AlgebricksException {
+        if (AlgebricksConfig.ALGEBRICKS_LOGGER.isLoggable(lvl)) {
+            final LogicalOperatorPrettyPrintVisitor pvisitor = 
context.getPrettyPrintVisitor();
+            pvisitor.reset(new AlgebricksAppendable());
+            PlanPrettyPrinter.printPlan(plan, pvisitor, 0);
+            AlgebricksConfig.ALGEBRICKS_LOGGER.info(name + ":\n" + 
pvisitor.get().toString());
+        }
     }
 
     private void runOptimizationSets(ILogicalPlan plan,
diff --git 
a/hyracks-fullstack/algebricks/algebricks-examples/piglet-example/src/main/java/org/apache/hyracks/algebricks/examples/piglet/compiler/PigletCompiler.java
 
b/hyracks-fullstack/algebricks/algebricks-examples/piglet-example/src/main/java/org/apache/hyracks/algebricks/examples/piglet/compiler/PigletCompiler.java
index b5751fa..0ac08c3 100644
--- 
a/hyracks-fullstack/algebricks/algebricks-examples/piglet-example/src/main/java/org/apache/hyracks/algebricks/examples/piglet/compiler/PigletCompiler.java
+++ 
b/hyracks-fullstack/algebricks/algebricks-examples/piglet-example/src/main/java/org/apache/hyracks/algebricks/examples/piglet/compiler/PigletCompiler.java
@@ -56,6 +56,7 @@
 import 
org.apache.hyracks.algebricks.core.algebra.operators.logical.SelectOperator;
 import 
org.apache.hyracks.algebricks.core.algebra.operators.logical.WriteOperator;
 import org.apache.hyracks.algebricks.core.algebra.plan.ALogicalPlanImpl;
+import 
org.apache.hyracks.algebricks.core.algebra.prettyprint.AlgebricksAppendable;
 import 
org.apache.hyracks.algebricks.core.algebra.prettyprint.LogicalOperatorPrettyPrintVisitor;
 import 
org.apache.hyracks.algebricks.core.algebra.prettyprint.PlanPrettyPrinter;
 import org.apache.hyracks.algebricks.core.rewriter.base.AbstractRuleController;
@@ -376,8 +377,7 @@
 
     private String getPrettyPrintedPlan(ILogicalPlan plan) throws 
AlgebricksException {
         LogicalOperatorPrettyPrintVisitor v = new 
LogicalOperatorPrettyPrintVisitor();
-        StringBuilder buffer = new StringBuilder();
-        PlanPrettyPrinter.printPlan(plan, buffer, v, 0);
-        return buffer.toString();
+        PlanPrettyPrinter.printPlan(plan, v, 0);
+        return v.get().toString();
     }
 }
diff --git 
a/hyracks-fullstack/algebricks/algebricks-rewriter/src/main/java/org/apache/hyracks/algebricks/rewriter/rules/EnforceStructuralPropertiesRule.java
 
b/hyracks-fullstack/algebricks/algebricks-rewriter/src/main/java/org/apache/hyracks/algebricks/rewriter/rules/EnforceStructuralPropertiesRule.java
index 8edf0ba..35d16a9 100644
--- 
a/hyracks-fullstack/algebricks/algebricks-rewriter/src/main/java/org/apache/hyracks/algebricks/rewriter/rules/EnforceStructuralPropertiesRule.java
+++ 
b/hyracks-fullstack/algebricks/algebricks-rewriter/src/main/java/org/apache/hyracks/algebricks/rewriter/rules/EnforceStructuralPropertiesRule.java
@@ -60,18 +60,16 @@
 import 
org.apache.hyracks.algebricks.core.algebra.operators.physical.PreclusteredGroupByPOperator;
 import 
org.apache.hyracks.algebricks.core.algebra.operators.physical.RandomMergeExchangePOperator;
 import 
org.apache.hyracks.algebricks.core.algebra.operators.physical.RandomPartitionExchangePOperator;
-import 
org.apache.hyracks.algebricks.core.algebra.operators.physical.RangePartitionMergeExchangePOperator;
 import 
org.apache.hyracks.algebricks.core.algebra.operators.physical.RangePartitionExchangePOperator;
+import 
org.apache.hyracks.algebricks.core.algebra.operators.physical.RangePartitionMergeExchangePOperator;
 import 
org.apache.hyracks.algebricks.core.algebra.operators.physical.SortMergeExchangePOperator;
 import 
org.apache.hyracks.algebricks.core.algebra.operators.physical.StableSortPOperator;
 import 
org.apache.hyracks.algebricks.core.algebra.prettyprint.LogicalOperatorPrettyPrintVisitor;
 import 
org.apache.hyracks.algebricks.core.algebra.prettyprint.PlanPrettyPrinter;
 import 
org.apache.hyracks.algebricks.core.algebra.properties.FunctionalDependency;
 import 
org.apache.hyracks.algebricks.core.algebra.properties.ILocalStructuralProperty;
-import 
org.apache.hyracks.algebricks.core.algebra.properties.ILocalStructuralProperty.PropertyType;
 import org.apache.hyracks.algebricks.core.algebra.properties.INodeDomain;
 import 
org.apache.hyracks.algebricks.core.algebra.properties.IPartitioningProperty;
-import 
org.apache.hyracks.algebricks.core.algebra.properties.IPartitioningProperty.PartitioningType;
 import 
org.apache.hyracks.algebricks.core.algebra.properties.IPartitioningRequirementsCoordinator;
 import 
org.apache.hyracks.algebricks.core.algebra.properties.IPhysicalPropertiesVector;
 import 
org.apache.hyracks.algebricks.core.algebra.properties.LocalGroupingProperty;
@@ -83,6 +81,8 @@
 import 
org.apache.hyracks.algebricks.core.algebra.properties.RandomPartitioningProperty;
 import 
org.apache.hyracks.algebricks.core.algebra.properties.StructuralPropertiesVector;
 import 
org.apache.hyracks.algebricks.core.algebra.properties.UnorderedPartitionedProperty;
+import 
org.apache.hyracks.algebricks.core.algebra.properties.ILocalStructuralProperty.PropertyType;
+import 
org.apache.hyracks.algebricks.core.algebra.properties.IPartitioningProperty.PartitioningType;
 import org.apache.hyracks.algebricks.core.algebra.util.OperatorPropertiesUtil;
 import org.apache.hyracks.algebricks.core.config.AlgebricksConfig;
 import org.apache.hyracks.algebricks.core.rewriter.base.IAlgebraicRewriteRule;
@@ -331,7 +331,7 @@
 
     private IPhysicalPropertiesVector 
newPropertiesDiff(AbstractLogicalOperator newChild,
             IPhysicalPropertiesVector required, boolean 
mayExpandPartitioningProperties, IOptimizationContext context)
-                    throws AlgebricksException {
+            throws AlgebricksException {
         IPhysicalPropertiesVector newDelivered = 
newChild.getDeliveredPhysicalProperties();
 
         Map<LogicalVariable, EquivalenceClass> newChildEqClasses = 
context.getEquivalenceClassMap(newChild);
@@ -501,7 +501,7 @@
 
     private Mutable<ILogicalOperator> 
enforceOrderProperties(List<LocalOrderProperty> oList,
             Mutable<ILogicalOperator> topOp, boolean isMicroOp, 
IOptimizationContext context)
-                    throws AlgebricksException {
+            throws AlgebricksException {
         List<Pair<IOrder, Mutable<ILogicalExpression>>> oe = new 
LinkedList<Pair<IOrder, Mutable<ILogicalExpression>>>();
         for (LocalOrderProperty orderProperty : oList) {
             for (OrderColumn oc : orderProperty.getOrderColumns()) {
@@ -573,8 +573,8 @@
                     break;
                 }
                 case ORDERED_PARTITIONED: {
-                    pop = new 
RangePartitionExchangePOperator(((OrderedPartitionedProperty) 
pp).getOrderColumns(), domain,
-                            null);
+                    pop = new 
RangePartitionExchangePOperator(((OrderedPartitionedProperty) 
pp).getOrderColumns(),
+                            domain, null);
                     break;
                 }
                 case BROADCAST: {
@@ -617,10 +617,9 @@
     }
 
     private void printOp(AbstractLogicalOperator op) throws 
AlgebricksException {
-        StringBuilder sb = new StringBuilder();
         LogicalOperatorPrettyPrintVisitor pvisitor = new 
LogicalOperatorPrettyPrintVisitor();
-        PlanPrettyPrinter.printOperator(op, sb, pvisitor, 0);
-        AlgebricksConfig.ALGEBRICKS_LOGGER.fine(sb.toString());
+        PlanPrettyPrinter.printOperator(op, pvisitor, 0);
+        AlgebricksConfig.ALGEBRICKS_LOGGER.fine(pvisitor.get().toString());
     }
 
     private List<OrderColumn> computeOrderColumns(IPhysicalPropertiesVector 
pv) {

-- 
To view, visit https://asterix-gerrit.ics.uci.edu/1004
To unsubscribe, visit https://asterix-gerrit.ics.uci.edu/settings

Gerrit-MessageType: merged
Gerrit-Change-Id: Ied0203adc51e9710690ace74fe1e152eb7a716e8
Gerrit-PatchSet: 7
Gerrit-Project: asterixdb
Gerrit-Branch: master
Gerrit-Owner: Till Westmann <ti...@apache.org>
Gerrit-Reviewer: Jenkins <jenk...@fulliautomatix.ics.uci.edu>
Gerrit-Reviewer: Till Westmann <ti...@apache.org>
Gerrit-Reviewer: Yingyi Bu <buyin...@gmail.com>

Reply via email to