[ASTERIXDB-3094][COMP] Add cost and cardinality to explain

Backport changes:
- Compensate for lack of add'l operator stats change in this branch

Change-Id: I7b4a6c78dca3326f070e1dda888d774dc6100c0b
Reviewed-on: https://asterix-gerrit.ics.uci.edu/c/asterixdb/+/17301
Integration-Tests: Jenkins <jenkins@fulliautomatix.ics.uci.edu>
Tested-by: Jenkins <jenkins@fulliautomatix.ics.uci.edu>
Reviewed-by: Ali Alsuliman <ali.al.solaiman@gmail.com>
Reviewed-on: https://asterix-gerrit.ics.uci.edu/c/asterixdb/+/17341
Reviewed-by: Michael Blow <mblow@apache.org>
Tested-by: Michael Blow <mblow@apache.org>
diff --git a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/cbo/EnumerateJoinsRule.java b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/cbo/EnumerateJoinsRule.java
index dc722e1..20b4d82 100644
--- a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/cbo/EnumerateJoinsRule.java
+++ b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/cbo/EnumerateJoinsRule.java
@@ -513,7 +513,7 @@
             throws AlgebricksException {
         if (LOGGER.isTraceEnabled()) {
             pp.reset();
-            pp.printOperator(op, true);
+            pp.printOperator(op, true, false);
             LOGGER.trace("---------------------------- {}\n{}\n----------------------------", text, pp);
         }
     }
diff --git a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/cbo/EstimatedCostComputationVisitor.java b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/cbo/EstimatedCostComputationVisitor.java
index 9b9fd28..f9f34bf 100644
--- a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/cbo/EstimatedCostComputationVisitor.java
+++ b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/cbo/EstimatedCostComputationVisitor.java
@@ -86,7 +86,7 @@
     public Pair<Double, Double> visitEmptyTupleSourceOperator(EmptyTupleSourceOperator op, Double arg)
             throws AlgebricksException {
         // Empty tuple source operator sends an empty tuple to downstream operators.
-        return new Pair<>(1.0, 1.0);
+        return new Pair<>(0.0, 0.0);
     }
 
     @Override
@@ -220,7 +220,7 @@
     @Override
     public Pair<Double, Double> visitDataScanOperator(DataSourceScanOperator op, Double arg)
             throws AlgebricksException {
-        Pair<Double, Double> cardCost = new Pair<>(1.0, 1.0);
+        Pair<Double, Double> cardCost = new Pair<>(0.0, 0.0);
 
         for (Map.Entry<String, Object> anno : op.getAnnotations().entrySet()) {
             if (anno.getValue() != null && anno.getKey().equals(OperatorAnnotations.OP_INPUT_CARDINALITY)) {
@@ -250,7 +250,7 @@
             op.getAnnotations().put(OperatorAnnotations.OP_COST_LOCAL, exchCost);
             op.getAnnotations().put(OperatorAnnotations.OP_COST_TOTAL, exchCost + cardCost.getSecond());
         } else {
-            op.getAnnotations().put(OperatorAnnotations.OP_COST_LOCAL, cardCost.getSecond());
+            op.getAnnotations().put(OperatorAnnotations.OP_COST_LOCAL, 0.0);
             op.getAnnotations().put(OperatorAnnotations.OP_COST_TOTAL, cardCost.getSecond());
         }
         op.getAnnotations().put(OperatorAnnotations.OP_OUTPUT_CARDINALITY, cardCost.getFirst());
@@ -305,12 +305,12 @@
     private static Pair<Double, Double> annotate(EstimatedCostComputationVisitor visitor, ILogicalOperator op,
             Double arg) throws AlgebricksException {
         if (op.getInputs().isEmpty()) {
-            return new Pair<>(1.0, 1.0);
+            return new Pair<>(0.0, 0.0);
         }
         Pair<Double, Double> cardCost = op.getInputs().get(0).getValue().accept(visitor, arg);
         op.getAnnotations().put(OperatorAnnotations.OP_OUTPUT_CARDINALITY, cardCost.getFirst());
         op.getAnnotations().put(OperatorAnnotations.OP_COST_TOTAL, cardCost.getSecond());
-        op.getAnnotations().put(OperatorAnnotations.OP_COST_LOCAL, cardCost.getSecond());
+        op.getAnnotations().put(OperatorAnnotations.OP_COST_LOCAL, 0.0);
         return cardCost;
     }
 
@@ -322,9 +322,9 @@
         return operator.getInputs().get(0).getValue().accept(this, arg);
     }
 
-    // Visits an inner join operator, particularly, deals with the case the join is a cartesian product.
+    // Visits an inner join operator.
     private Pair<Double, Double> visitInnerJoin(InnerJoinOperator joinOperator, Double arg) throws AlgebricksException {
-        Pair<Double, Double> cardCost = new Pair<>(1.0, 1.0);
+        Pair<Double, Double> cardCost = new Pair<>(0.0, 0.0);
 
         ILogicalOperator left = joinOperator.getInputs().get(0).getValue();
         ILogicalOperator right = joinOperator.getInputs().get(1).getValue();
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 fcac5b4..3409621 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
@@ -217,7 +217,7 @@
 
         if ((isQuery || isLoad) && !conf.is(SessionConfig.FORMAT_ONLY_PHYSICAL_OPS)
                 && conf.is(SessionConfig.OOB_LOGICAL_PLAN)) {
-            generateLogicalPlan(plan, output.config().getPlanFormat());
+            generateLogicalPlan(plan, output.config().getPlanFormat(), isExplainOnly);
         }
         ICcApplicationContext ccAppContext = metadataProvider.getApplicationContext();
         CompilerProperties compilerProperties = ccAppContext.getCompilerProperties();
@@ -277,7 +277,7 @@
                     output.out().write(buf.toString());
                 } else {
                     if (isQuery || isLoad) {
-                        generateOptimizedLogicalPlan(plan, output.config().getPlanFormat());
+                        generateOptimizedLogicalPlan(plan, output.config().getPlanFormat(), isExplainOnly);
                     }
                 }
             }
@@ -311,6 +311,9 @@
         }
 
         if (!conf.isGenerateJobSpec()) {
+            if (isQuery || isLoad) {
+                generateOptimizedLogicalPlan(plan, output.config().getPlanFormat(), isExplainOnly);
+            }
             return null;
         }
 
@@ -331,6 +334,21 @@
                 spec.setRequiredClusterCapacity(jobRequiredCapacity);
             }
         }
+
+        if (conf.is(SessionConfig.OOB_OPTIMIZED_LOGICAL_PLAN) || isExplainOnly) {
+            if (isQuery || isLoad) {
+                generateOptimizedLogicalPlan(plan, output.config().getPlanFormat(), isExplainOnly);
+            }
+        }
+
+        if (isExplainOnly) {
+            printPlanAsResult(metadataProvider, output, printer, printSignature);
+            if (!conf.is(SessionConfig.OOB_OPTIMIZED_LOGICAL_PLAN)) {
+                executionPlans.setOptimizedLogicalPlan(null);
+            }
+            return null;
+        }
+
         if (isQuery && conf.is(SessionConfig.OOB_HYRACKS_JOB)) {
             generateJob(spec);
         }
@@ -516,13 +534,16 @@
         }
     }
 
-    private void generateLogicalPlan(ILogicalPlan plan, SessionConfig.PlanFormat format) throws AlgebricksException {
-        executionPlans.setLogicalPlan(getPrettyPrintVisitor(format).printPlan(plan).toString());
+    private void generateLogicalPlan(ILogicalPlan plan, SessionConfig.PlanFormat format,
+            boolean printOptimizerEstimates) throws AlgebricksException {
+        executionPlans
+                .setLogicalPlan(getPrettyPrintVisitor(format).printPlan(plan, printOptimizerEstimates).toString());
     }
 
-    private void generateOptimizedLogicalPlan(ILogicalPlan plan, SessionConfig.PlanFormat format)
-            throws AlgebricksException {
-        executionPlans.setOptimizedLogicalPlan(getPrettyPrintVisitor(format).printPlan(plan).toString());
+    private void generateOptimizedLogicalPlan(ILogicalPlan plan, SessionConfig.PlanFormat format,
+            boolean printOptimizerEstimates) throws AlgebricksException {
+        executionPlans.setOptimizedLogicalPlan(
+                getPrettyPrintVisitor(format).printPlan(plan, printOptimizerEstimates).toString());
     }
 
     private void generateJob(JobSpecification spec) {
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/api/compileonly/compileonly.2.regexjson b/asterixdb/asterix-app/src/test/resources/runtimets/results/api/compileonly/compileonly.2.regexjson
index 40a764c..9856681 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/results/api/compileonly/compileonly.2.regexjson
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/api/compileonly/compileonly.2.regexjson
@@ -4,6 +4,7 @@
 	  "expressions":"R{.*}",
 	  "operatorId":"R{.*}",
 	  "execution-mode":"R{.*}",
+	  "optimizer-estimates":{"cardinality":0.0,"op-cost":0.0,"total-cost":0.0},
 	  "inputs":"R{.*}"
   }
 }
\ No newline at end of file
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 b5b01a0..1bf2579 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
@@ -53,7 +53,7 @@
     }
 
     public static String prettyPrintPlan(ILogicalPlan plan) throws AlgebricksException {
-        return PlanPrettyPrinter.createStringPlanPrettyPrinter().printPlan(plan).toString();
+        return PlanPrettyPrinter.createStringPlanPrettyPrinter().printPlan(plan, true).toString();
     }
 
     @Override
diff --git a/hyracks-fullstack/algebricks/algebricks-core/src/main/java/org/apache/hyracks/algebricks/core/algebra/plan/PlanStabilityVerifier.java b/hyracks-fullstack/algebricks/algebricks-core/src/main/java/org/apache/hyracks/algebricks/core/algebra/plan/PlanStabilityVerifier.java
index 65aa64a..d6ffe9e 100644
--- a/hyracks-fullstack/algebricks/algebricks-core/src/main/java/org/apache/hyracks/algebricks/core/algebra/plan/PlanStabilityVerifier.java
+++ b/hyracks-fullstack/algebricks/algebricks-core/src/main/java/org/apache/hyracks/algebricks/core/algebra/plan/PlanStabilityVerifier.java
@@ -263,7 +263,7 @@
 
     static String printOperator(ILogicalOperator op, IPlanPrettyPrinter printer) {
         try {
-            return printer.reset().printOperator((AbstractLogicalOperator) op, false).toString();
+            return printer.reset().printOperator((AbstractLogicalOperator) op, false, false).toString();
         } catch (AlgebricksException e) {
             // shouldn't happen
             return op.toString();
diff --git a/hyracks-fullstack/algebricks/algebricks-core/src/main/java/org/apache/hyracks/algebricks/core/algebra/prettyprint/IPlanPrettyPrinter.java b/hyracks-fullstack/algebricks/algebricks-core/src/main/java/org/apache/hyracks/algebricks/core/algebra/prettyprint/IPlanPrettyPrinter.java
index faf4976..66d48d3 100644
--- a/hyracks-fullstack/algebricks/algebricks-core/src/main/java/org/apache/hyracks/algebricks/core/algebra/prettyprint/IPlanPrettyPrinter.java
+++ b/hyracks-fullstack/algebricks/algebricks-core/src/main/java/org/apache/hyracks/algebricks/core/algebra/prettyprint/IPlanPrettyPrinter.java
@@ -30,17 +30,18 @@
 
     /** Prints the plan rooted at the operator argument. */
     default IPlanPrettyPrinter printOperator(AbstractLogicalOperator operator) throws AlgebricksException {
-        return printOperator(operator, true);
+        return printOperator(operator, true, false);
     }
 
     /** Prints given operator and optionally it's inputs */
-    IPlanPrettyPrinter printOperator(AbstractLogicalOperator operator, boolean printInputs) throws AlgebricksException;
+    IPlanPrettyPrinter printOperator(AbstractLogicalOperator operator, boolean printInputs,
+            boolean printOptimizerEstimates) throws AlgebricksException;
 
     /** Prints given expression */
     IPlanPrettyPrinter printExpression(ILogicalExpression expression) throws AlgebricksException;
 
     /** Prints the whole logical plan. */
-    IPlanPrettyPrinter printPlan(ILogicalPlan plan) throws AlgebricksException;
+    IPlanPrettyPrinter printPlan(ILogicalPlan plan, boolean printOptimizerEstimates) throws AlgebricksException;
 
     /** Resets the state of the pretty printer. */
     IPlanPrettyPrinter reset() throws AlgebricksException;
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 64abaee..710e6e0 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
@@ -90,14 +90,15 @@
     }
 
     @Override
-    public final IPlanPrettyPrinter printPlan(ILogicalPlan plan) throws AlgebricksException {
+    public final IPlanPrettyPrinter printPlan(ILogicalPlan plan, boolean printOptimizerEstimates)
+            throws AlgebricksException {
         printPlanImpl(plan, 0);
         return this;
     }
 
     @Override
-    public final IPlanPrettyPrinter printOperator(AbstractLogicalOperator op, boolean printInputs)
-            throws AlgebricksException {
+    public final IPlanPrettyPrinter printOperator(AbstractLogicalOperator op, boolean printInputs,
+            boolean printOptimizerEstimates) throws AlgebricksException {
         printOperatorImpl(op, 0, printInputs);
         return this;
     }
diff --git a/hyracks-fullstack/algebricks/algebricks-core/src/main/java/org/apache/hyracks/algebricks/core/algebra/prettyprint/LogicalOperatorPrettyPrintVisitorJson.java b/hyracks-fullstack/algebricks/algebricks-core/src/main/java/org/apache/hyracks/algebricks/core/algebra/prettyprint/LogicalOperatorPrettyPrintVisitorJson.java
index cf96c83..b1cdeb1 100644
--- a/hyracks-fullstack/algebricks/algebricks-core/src/main/java/org/apache/hyracks/algebricks/core/algebra/prettyprint/LogicalOperatorPrettyPrintVisitorJson.java
+++ b/hyracks-fullstack/algebricks/algebricks-core/src/main/java/org/apache/hyracks/algebricks/core/algebra/prettyprint/LogicalOperatorPrettyPrintVisitorJson.java
@@ -157,28 +157,30 @@
     }
 
     @Override
-    public final IPlanPrettyPrinter printPlan(ILogicalPlan plan) throws AlgebricksException {
-        printPlanImpl(plan);
+    public final IPlanPrettyPrinter printPlan(ILogicalPlan plan, boolean printOptimizerEstimates)
+            throws AlgebricksException {
+        printPlanImpl(plan, printOptimizerEstimates);
         flushContentToWriter();
         return this;
     }
 
     @Override
-    public final IPlanPrettyPrinter printOperator(AbstractLogicalOperator op, boolean printInputs)
-            throws AlgebricksException {
-        printOperatorImpl(op, printInputs);
+
+    public final IPlanPrettyPrinter printOperator(AbstractLogicalOperator op, boolean printInputs,
+            boolean printOptimizerEstimates) throws AlgebricksException {
+        printOperatorImpl(op, printInputs, printOptimizerEstimates);
         flushContentToWriter();
         return this;
     }
 
-    private void printPlanImpl(ILogicalPlan plan) throws AlgebricksException {
+    private void printPlanImpl(ILogicalPlan plan, boolean printOptimizerEstimates) throws AlgebricksException {
         try {
             boolean writeArrayOfRoots = plan.getRoots().size() > 1;
             if (writeArrayOfRoots) {
                 jsonGenerator.writeStartArray();
             }
             for (Mutable<ILogicalOperator> root : plan.getRoots()) {
-                printOperatorImpl((AbstractLogicalOperator) root.getValue(), true);
+                printOperatorImpl((AbstractLogicalOperator) root.getValue(), true, printOptimizerEstimates);
             }
             if (writeArrayOfRoots) {
                 jsonGenerator.writeEndArray();
@@ -188,8 +190,11 @@
         }
     }
 
-    private void printOperatorImpl(AbstractLogicalOperator op, boolean printInputs) throws AlgebricksException {
+    private void printOperatorImpl(AbstractLogicalOperator op, boolean printInputs, boolean printOptimizerEstimates)
+            throws AlgebricksException {
         try {
+            boolean nestPlanInPlanField = nestPlanInPlanField(op, printOptimizerEstimates);
+
             jsonGenerator.writeStartObject();
             op.accept(this, null);
             jsonGenerator.writeStringField("operatorId", idCounter.printOperatorId(op));
@@ -199,24 +204,71 @@
             }
             jsonGenerator.writeStringField("execution-mode", op.getExecutionMode().toString());
 
+            generateCardCostFields(op);
+
+            if (printInputs && !op.getInputs().isEmpty()) {
+                jsonGenerator.writeArrayFieldStart("inputs");
+                for (Mutable<ILogicalOperator> k : op.getInputs()) {
+                    printOperatorImpl((AbstractLogicalOperator) k.getValue(), printInputs, printOptimizerEstimates);
+                }
+                jsonGenerator.writeEndArray();
+            }
+            jsonGenerator.writeEndObject();
+            if (nestPlanInPlanField) {
+                jsonGenerator.writeEndObject();
+            }
+        } catch (IOException e) {
+            throw AlgebricksException.create(ErrorCode.ERROR_PRINTING_PLAN, e, String.valueOf(e));
+        }
+    }
+
+    private boolean nestPlanInPlanField(AbstractLogicalOperator op, boolean printOptimizerEstimates)
+            throws IOException {
+        if (op.getOperatorTag() == LogicalOperatorTag.DISTRIBUTE_RESULT && printOptimizerEstimates) {
+            double cardinality = 0.0;
+            double cost = 0.0;
+            for (Map.Entry<String, Object> anno : op.getAnnotations().entrySet()) {
+                if (anno.getValue() != null && anno.getKey().equals(OperatorAnnotations.OP_OUTPUT_CARDINALITY)) {
+                    cardinality = (double) anno.getValue();
+                } else if (anno.getValue() != null && anno.getKey().equals(OperatorAnnotations.OP_COST_TOTAL)) {
+                    cost = (double) anno.getValue();
+                }
+            }
+
+            jsonGenerator.writeStartObject();
+            jsonGenerator.writeNumberField("cardinality", cardinality);
+            jsonGenerator.writeNumberField("cost", cost);
+            jsonGenerator.writeFieldName("plan");
+            return true;
+        }
+        return false;
+    }
+
+    private void generateCardCostFields(AbstractLogicalOperator op) throws AlgebricksException {
+        try {
+            double opCard = 0.0;
+            double opCostLocal = 0.0;
+            double opCostTotal = 0.0;
+
             for (Map.Entry<String, Object> anno : op.getAnnotations().entrySet()) {
                 Object annotationVal = anno.getValue();
                 if (annotationVal != null) {
                     String annotation = anno.getKey();
                     switch (annotation) {
                         case OperatorAnnotations.OP_COST_LOCAL:
+                            opCostLocal = (double) annotationVal;
+                            break;
                         case OperatorAnnotations.OP_COST_TOTAL:
-                            jsonGenerator.writeStringField(annotation.toLowerCase().replace('_', '-'),
-                                    annotationVal.toString());
+                            opCostTotal = (double) annotationVal;
                             break;
                         case OperatorAnnotations.OP_INPUT_CARDINALITY:
                             if (op.getOperatorTag() == LogicalOperatorTag.DATASOURCESCAN) {
-                                jsonGenerator.writeStringField(OP_CARDINALITY, annotationVal.toString());
+                                opCard = (double) annotationVal;
                             }
                             break;
                         case OperatorAnnotations.OP_OUTPUT_CARDINALITY:
                             if (op.getOperatorTag() != LogicalOperatorTag.DATASOURCESCAN) {
-                                jsonGenerator.writeStringField(OP_CARDINALITY, annotationVal.toString());
+                                opCard = (double) annotationVal;
                             }
                             break;
                         default:
@@ -224,14 +276,12 @@
                     }
                 }
             }
-
-            if (printInputs && !op.getInputs().isEmpty()) {
-                jsonGenerator.writeArrayFieldStart("inputs");
-                for (Mutable<ILogicalOperator> k : op.getInputs()) {
-                    printOperatorImpl((AbstractLogicalOperator) k.getValue(), printInputs);
-                }
-                jsonGenerator.writeEndArray();
-            }
+            jsonGenerator.writeObjectFieldStart("optimizer-estimates");
+            jsonGenerator.writeNumberField(OP_CARDINALITY, opCard);
+            jsonGenerator.writeNumberField(OperatorAnnotations.OP_COST_LOCAL.toLowerCase().replace('_', '-'),
+                    opCostLocal);
+            jsonGenerator.writeNumberField(OperatorAnnotations.OP_COST_TOTAL.toLowerCase().replace('_', '-'),
+                    opCostTotal);
             jsonGenerator.writeEndObject();
         } catch (IOException e) {
             throw AlgebricksException.create(ErrorCode.ERROR_PRINTING_PLAN, e, String.valueOf(e));
@@ -796,7 +846,7 @@
             jsonGenerator.writeArrayFieldStart("subplan");
             List<ILogicalPlan> nestedPlans = op.getNestedPlans();
             for (int i = 0, size = nestedPlans.size(); i < size; i++) {
-                printPlanImpl(nestedPlans.get(i));
+                printPlanImpl(nestedPlans.get(i), false);
             }
             jsonGenerator.writeEndArray();
             idCounter.previousPrefix();
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 a717295..676b9c7 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
@@ -69,7 +69,7 @@
 
     private void logPlanAt(String name, Level lvl) throws AlgebricksException {
         if (AlgebricksConfig.ALGEBRICKS_LOGGER.isEnabled(lvl)) {
-            String planStr = context.getPrettyPrinter().reset().printPlan(plan).toString();
+            String planStr = context.getPrettyPrinter().reset().printPlan(plan, true).toString();
             AlgebricksConfig.ALGEBRICKS_LOGGER.log(lvl, name + ":\n" + LogRedactionUtil.userData(planStr));
         }
     }
diff --git a/hyracks-fullstack/algebricks/algebricks-core/src/test/java/org/apache/hyracks/algebricks/core/algebra/plan/PlanVerifierTestBase.java b/hyracks-fullstack/algebricks/algebricks-core/src/test/java/org/apache/hyracks/algebricks/core/algebra/plan/PlanVerifierTestBase.java
index 65d6460..2f7bc9b 100644
--- a/hyracks-fullstack/algebricks/algebricks-core/src/test/java/org/apache/hyracks/algebricks/core/algebra/plan/PlanVerifierTestBase.java
+++ b/hyracks-fullstack/algebricks/algebricks-core/src/test/java/org/apache/hyracks/algebricks/core/algebra/plan/PlanVerifierTestBase.java
@@ -71,7 +71,7 @@
 
     String printOp(ILogicalOperator op) {
         try {
-            return planPrinter.reset().printOperator((AbstractLogicalOperator) op, false).toString();
+            return planPrinter.reset().printOperator((AbstractLogicalOperator) op, false, false).toString();
         } catch (AlgebricksException e) {
             throw new RuntimeException(e);
         }