Repository: asterixdb Updated Branches: refs/heads/master 7ea84894b -> a22ca7bf8
http://git-wip-us.apache.org/repos/asf/asterixdb/blob/a22ca7bf/hyracks-fullstack/algebricks/algebricks-core/src/main/java/org/apache/hyracks/algebricks/core/algebra/prettyprint/LogicalOperatorPrettyPrintVisitorJson.java ---------------------------------------------------------------------- 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 new file mode 100644 index 0000000..fefb1e9 --- /dev/null +++ b/hyracks-fullstack/algebricks/algebricks-core/src/main/java/org/apache/hyracks/algebricks/core/algebra/prettyprint/LogicalOperatorPrettyPrintVisitorJson.java @@ -0,0 +1,748 @@ +/* + * 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.util.Deque; +import java.util.HashMap; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; + +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.common.utils.Triple; +import org.apache.hyracks.algebricks.core.algebra.base.ILogicalExpression; +import org.apache.hyracks.algebricks.core.algebra.base.ILogicalOperator; +import org.apache.hyracks.algebricks.core.algebra.base.ILogicalPlan; +import org.apache.hyracks.algebricks.core.algebra.base.IPhysicalOperator; +import org.apache.hyracks.algebricks.core.algebra.base.LogicalVariable; +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.operators.logical.AbstractUnnestMapOperator; +import org.apache.hyracks.algebricks.core.algebra.operators.logical.AggregateOperator; +import org.apache.hyracks.algebricks.core.algebra.operators.logical.AssignOperator; +import org.apache.hyracks.algebricks.core.algebra.operators.logical.DataSourceScanOperator; +import org.apache.hyracks.algebricks.core.algebra.operators.logical.DelegateOperator; +import org.apache.hyracks.algebricks.core.algebra.operators.logical.DistinctOperator; +import org.apache.hyracks.algebricks.core.algebra.operators.logical.DistributeResultOperator; +import org.apache.hyracks.algebricks.core.algebra.operators.logical.EmptyTupleSourceOperator; +import org.apache.hyracks.algebricks.core.algebra.operators.logical.ExchangeOperator; +import org.apache.hyracks.algebricks.core.algebra.operators.logical.GroupByOperator; +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; +import org.apache.hyracks.algebricks.core.algebra.operators.logical.LeftOuterUnnestOperator; +import org.apache.hyracks.algebricks.core.algebra.operators.logical.LimitOperator; +import org.apache.hyracks.algebricks.core.algebra.operators.logical.MaterializeOperator; +import org.apache.hyracks.algebricks.core.algebra.operators.logical.NestedTupleSourceOperator; +import org.apache.hyracks.algebricks.core.algebra.operators.logical.OrderOperator; +import org.apache.hyracks.algebricks.core.algebra.operators.logical.ProjectOperator; +import org.apache.hyracks.algebricks.core.algebra.operators.logical.ReplicateOperator; +import org.apache.hyracks.algebricks.core.algebra.operators.logical.RunningAggregateOperator; +import org.apache.hyracks.algebricks.core.algebra.operators.logical.ScriptOperator; +import org.apache.hyracks.algebricks.core.algebra.operators.logical.SelectOperator; +import org.apache.hyracks.algebricks.core.algebra.operators.logical.SinkOperator; +import org.apache.hyracks.algebricks.core.algebra.operators.logical.SplitOperator; +import org.apache.hyracks.algebricks.core.algebra.operators.logical.SubplanOperator; +import org.apache.hyracks.algebricks.core.algebra.operators.logical.TokenizeOperator; +import org.apache.hyracks.algebricks.core.algebra.operators.logical.UnionAllOperator; +import org.apache.hyracks.algebricks.core.algebra.operators.logical.UnnestMapOperator; +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.visitors.ILogicalExpressionVisitor; + +public class LogicalOperatorPrettyPrintVisitorJson extends AbstractLogicalOperatorPrettyPrintVisitor { + Map<AbstractLogicalOperator, String> operatorIdentity = new HashMap<>(); + + public LogicalOperatorPrettyPrintVisitorJson(Appendable app) { + super(app); + } + + IdCounter idCounter = new IdCounter(); + + public class IdCounter { + private int id; + private Deque<Integer> prefix; + + public IdCounter() { + prefix = new LinkedList<Integer>(); + prefix.add(1); + this.id = 0; + } + + public void previousPrefix() { + this.id = prefix.removeLast(); + } + + public void nextPrefix() { + prefix.add(this.id); + this.id = 0; + } + + public String printOperatorId(AbstractLogicalOperator op) { + String stringPrefix = ""; + Object[] values = this.prefix.toArray(); + for (Object val : values) { + stringPrefix = stringPrefix.isEmpty() ? val.toString() : stringPrefix + "." + val.toString(); + } + if (!operatorIdentity.containsKey(op)) { + String opId = stringPrefix.isEmpty() ? "" + Integer.toString(++id) + : stringPrefix + "." + Integer.toString(++id); + operatorIdentity.put(op, opId); + } + return operatorIdentity.get(op); + } + } + + public static void printPlanJson(ILogicalPlan plan, LogicalOperatorPrettyPrintVisitorJson pvisitor, int indent) + throws AlgebricksException { + for (Mutable<ILogicalOperator> root : plan.getRoots()) { + printOperatorJson((AbstractLogicalOperator) root.getValue(), pvisitor, indent); + } + } + + public static void printOperatorJson(AbstractLogicalOperator op, LogicalOperatorPrettyPrintVisitorJson pvisitor, + int indent) throws AlgebricksException { + int currentIndent = indent; + final AlgebricksAppendable out = pvisitor.get(); + pad(out, currentIndent); + appendln(out, "{"); + currentIndent++; + op.accept(pvisitor, currentIndent); + appendln(out, ","); + pad(out, currentIndent); + append(out, "\"operatorId\" : \"" + pvisitor.idCounter.printOperatorId(op) + "\""); + IPhysicalOperator pOp = op.getPhysicalOperator(); + if (pOp != null) { + appendln(out, ","); + pad(out, currentIndent); + String pOperator = "\"physical-operator\":\"" + pOp.toString() + "\""; + append(out, pOperator); + } + appendln(out, ","); + pad(out, currentIndent); + append(out, "\"execution-mode\":\"" + op.getExecutionMode() + '"'); + if (!op.getInputs().isEmpty()) { + appendln(out, ","); + pad(out, currentIndent); + appendln(out, "\"inputs\":["); + boolean moreInputes = false; + for (Mutable<ILogicalOperator> k : op.getInputs()) { + if (moreInputes) { + append(out, ","); + } + printOperatorJson((AbstractLogicalOperator) k.getValue(), pvisitor, currentIndent + 4); + moreInputes = true; + } + pad(out, currentIndent + 2); + appendln(out, "]"); + } + out.append("\n"); + pad(out, currentIndent - 1); + appendln(out, "}"); + } + + public void variablePrintHelper(List<LogicalVariable> variables, Integer indent) throws AlgebricksException { + if (!variables.isEmpty()) { + addIndent(0).append(",\n"); + addIndent(indent).append("\"variables\" :["); + boolean first = true; + for (LogicalVariable v : variables) { + if (!first) { + buffer.append(","); + } + buffer.append("\"" + str(v) + "\""); + first = false; + } + buffer.append("]"); + } + } + + @Override + public Void visitAggregateOperator(AggregateOperator op, Integer indent) throws AlgebricksException { + addIndent(indent).append("\"operator\":\"aggregate\""); + variablePrintHelper(op.getVariables(), indent); + + return null; + } + + @Override + public Void visitRunningAggregateOperator(RunningAggregateOperator op, Integer indent) throws AlgebricksException { + addIndent(indent).append("\"operator\":\"running-aggregate\""); + variablePrintHelper(op.getVariables(), indent); + if (!op.getExpressions().isEmpty()) { + addIndent(0).append(",\n"); + pprintExprList(op.getExpressions(), indent); + } + return null; + } + + @Override + public Void visitEmptyTupleSourceOperator(EmptyTupleSourceOperator op, Integer indent) throws AlgebricksException { + addIndent(indent).append("\"operator\":\"empty-tuple-source\""); + return null; + } + + @Override + public Void visitGroupByOperator(GroupByOperator op, Integer indent) throws AlgebricksException { + addIndent(indent).append("\"operator\":\"group-by\""); + + if (op.isGroupAll()) { + buffer.append(",\n"); + addIndent(indent).append("\"option\":\"all\""); + } + if (!op.getGroupByList().isEmpty()) { + buffer.append(",\n"); + addIndent(indent).append("\"group-by-list\":"); + pprintVeList(op.getGroupByList(), indent); + } + if (!op.getDecorList().isEmpty()) { + buffer.append(",\n"); + addIndent(indent).append("\"decor-list\":"); + pprintVeList(op.getDecorList(), indent); + } + if (!op.getNestedPlans().isEmpty()) { + buffer.append(",\n"); + addIndent(indent).append("\"subplan\":"); + printNestedPlans(op, indent); + } + return null; + } + + @Override + public Void visitDistinctOperator(DistinctOperator op, Integer indent) throws AlgebricksException { + addIndent(indent).append("\"operator\":\"distinct\""); + if (!op.getExpressions().isEmpty()) { + addIndent(0).append(",\n"); + pprintExprList(op.getExpressions(), indent); + } + return null; + } + + @Override + public Void visitInnerJoinOperator(InnerJoinOperator op, Integer indent) throws AlgebricksException { + addIndent(indent).append("\"operator\":\"join\",\n"); + addIndent(indent) + .append("\"condition\":" + "\"" + op.getCondition().getValue().accept(exprVisitor, indent) + "\""); + return null; + } + + @Override + public Void visitLeftOuterJoinOperator(LeftOuterJoinOperator op, Integer indent) throws AlgebricksException { + addIndent(indent).append("\"operator\":\"left-outer-join\",\n"); + addIndent(indent) + .append("\"condition\":" + "\"" + op.getCondition().getValue().accept(exprVisitor, indent) + "\""); + return null; + } + + @Override + public Void visitNestedTupleSourceOperator(NestedTupleSourceOperator op, Integer indent) + throws AlgebricksException { + addIndent(indent).append("\"operator\":\"nested-tuple-source\""); + return null; + } + + @Override + public Void visitOrderOperator(OrderOperator op, Integer indent) throws AlgebricksException { + addIndent(indent).append("\"operator\":\"order\""); + for (Pair<OrderOperator.IOrder, Mutable<ILogicalExpression>> p : op.getOrderExpressions()) { + buffer.append(",\n"); + if (op.getTopK() != -1) { + addIndent(indent).append("\"topK\":\"" + op.getTopK() + "\",\n"); + } + String fst = getOrderString(p.first); + addIndent(indent).append("\"first\":" + fst + ",\n"); + addIndent(indent) + .append("\"second\":\"" + p.second.getValue().accept(exprVisitor, indent).replace('"', ' ') + "\""); + } + 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 Void visitAssignOperator(AssignOperator op, Integer indent) throws AlgebricksException { + addIndent(indent).append("\"operator\":\"assign\""); + variablePrintHelper(op.getVariables(), indent); + if (!op.getExpressions().isEmpty()) { + addIndent(0).append(",\n"); + pprintExprList(op.getExpressions(), indent); + } + return null; + } + + @Override + public Void visitWriteOperator(WriteOperator op, Integer indent) throws AlgebricksException { + addIndent(indent).append("\"operator\":\"write\""); + if (!op.getExpressions().isEmpty()) { + addIndent(0).append(",\n"); + pprintExprList(op.getExpressions(), indent); + } + return null; + } + + @Override + public Void visitDistributeResultOperator(DistributeResultOperator op, Integer indent) throws AlgebricksException { + addIndent(indent).append("\"operator\":\"distribute-result\""); + if (!op.getExpressions().isEmpty()) { + addIndent(0).append(",\n"); + pprintExprList(op.getExpressions(), indent); + } + return null; + } + + @Override + public Void visitWriteResultOperator(WriteResultOperator op, Integer indent) throws AlgebricksException { + addIndent(indent).append("\"operator\":\"load\",\n"); + addIndent(indent).append(str(op.getDataSource())).append("\"from\":") + .append(op.getPayloadExpression().getValue().accept(exprVisitor, indent) + ",\n"); + addIndent(indent).append("\"partitioned-by\":{"); + pprintExprList(op.getKeyExpressions(), indent); + addIndent(indent).append("}"); + return null; + } + + @Override + public Void visitSelectOperator(SelectOperator op, Integer indent) throws AlgebricksException { + addIndent(indent).append("\"operator\":\"select\",\n"); + addIndent(indent).append("\"expressions\":\"" + + op.getCondition().getValue().accept(exprVisitor, indent).replace('"', ' ') + "\""); + return null; + } + + @Override + public Void visitProjectOperator(ProjectOperator op, Integer indent) throws AlgebricksException { + addIndent(indent).append("\"operator\":\"project\""); + variablePrintHelper(op.getVariables(), indent); + return null; + } + + @Override + public Void visitSubplanOperator(SubplanOperator op, Integer indent) throws AlgebricksException { + if (!op.getNestedPlans().isEmpty()) { + addIndent(indent).append("\"subplan\":"); + printNestedPlans(op, indent); + } + return null; + } + + @Override + public Void visitUnionOperator(UnionAllOperator op, Integer indent) throws AlgebricksException { + addIndent(indent).append("\"operator\":\"union\""); + for (Triple<LogicalVariable, LogicalVariable, LogicalVariable> v : op.getVariableMappings()) { + buffer.append(",\n"); + addIndent(indent) + .append("\"values\":[" + "\"" + v.first + "\"," + "\"" + v.second + "\"," + "\"" + v.third + "\"]"); + } + return null; + } + + @Override + public Void visitIntersectOperator(IntersectOperator op, Integer indent) throws AlgebricksException { + addIndent(indent).append("\"operator\":\"intersect\",\n"); + + addIndent(indent).append("\"output-variables\":["); + for (int i = 0; i < op.getOutputVars().size(); i++) { + if (i > 0) { + buffer.append(", "); + } + buffer.append("\"" + str(op.getOutputVars().get(i)) + "\""); + } + buffer.append("],"); + addIndent(indent).append("\"input_variables\":["); + for (int i = 0; i < op.getNumInput(); i++) { + if (i > 0) { + buffer.append(",\n"); + } + buffer.append("["); + for (int j = 0; j < op.getInputVariables(i).size(); j++) { + if (j > 0) { + buffer.append(", "); + } + buffer.append("\"" + str(op.getInputVariables(i).get(j)) + "\""); + } + buffer.append(']'); + } + buffer.append("]"); + return null; + } + + @Override + public Void visitUnnestOperator(UnnestOperator op, Integer indent) throws AlgebricksException { + addIndent(indent).append("\"operator\":\"unnest\""); + variablePrintHelper(op.getVariables(), indent); + if (op.getPositionalVariable() != null) { + buffer.append(",\n"); + addIndent(indent).append("\"position\":\"" + op.getPositionalVariable() + "\""); + } + buffer.append(",\n"); + addIndent(indent).append("\"expressions\":\"" + + op.getExpressionRef().getValue().accept(exprVisitor, indent).replace('"', ' ') + "\""); + return null; + } + + @Override + public Void visitLeftOuterUnnestOperator(LeftOuterUnnestOperator op, Integer indent) throws AlgebricksException { + addIndent(indent).append("\"operator\":\"outer-unnest\",\n"); + addIndent(indent).append("\"variables\":[\"" + op.getVariable() + "\"]"); + if (op.getPositionalVariable() != null) { + buffer.append(",\n"); + addIndent(indent).append("\"position\":" + op.getPositionalVariable()); + } + buffer.append(",\n"); + addIndent(indent).append("\"expressions\":\"" + + op.getExpressionRef().getValue().accept(exprVisitor, indent).replace('"', ' ') + "\""); + return null; + } + + @Override + public Void visitUnnestMapOperator(UnnestMapOperator op, Integer indent) throws AlgebricksException { + return printAbstractUnnestMapOperator(op, indent, "unnest-map"); + } + + @Override + public Void visitLeftOuterUnnestMapOperator(LeftOuterUnnestMapOperator op, Integer indent) + throws AlgebricksException { + return printAbstractUnnestMapOperator(op, indent, "left-outer-unnest-map"); + } + + private Void printAbstractUnnestMapOperator(AbstractUnnestMapOperator op, Integer indent, String opSignature) + throws AlgebricksException { + AlgebricksAppendable plan = addIndent(indent).append("\"operator\":\"" + opSignature + "\""); + variablePrintHelper(op.getVariables(), indent); + buffer.append(",\n"); + addIndent(indent).append("\"expressions\":\"" + + op.getExpressionRef().getValue().accept(exprVisitor, indent).replace('"', ' ') + "\""); + appendFilterInformation(plan, op.getMinFilterVars(), op.getMaxFilterVars(), indent); + return null; + } + + @Override + public Void visitDataScanOperator(DataSourceScanOperator op, Integer indent) throws AlgebricksException { + AlgebricksAppendable plan = addIndent(indent).append("\"operator\":\"data-scan\""); + if (!op.getProjectVariables().isEmpty()) { + addIndent(0).append(",\n"); + addIndent(indent).append("\"project-variables\":["); + boolean first = true; + for (LogicalVariable v : op.getProjectVariables()) { + if (!first) { + buffer.append(","); + } + buffer.append("\"" + str(v) + "\""); + first = false; + } + buffer.append("]"); + } + variablePrintHelper(op.getVariables(), indent); + if (op.getDataSource() != null) { + addIndent(0).append(",\n"); + addIndent(indent).append("\"data-source\":\"" + op.getDataSource() + "\""); + } + appendFilterInformation(plan, op.getMinFilterVars(), op.getMaxFilterVars(), indent); + return null; + } + + private Void appendFilterInformation(AlgebricksAppendable plan, List<LogicalVariable> minFilterVars, + List<LogicalVariable> maxFilterVars, Integer indent) throws AlgebricksException { + if (minFilterVars != null || maxFilterVars != null) { + plan.append(",\n"); + addIndent(indent); + plan.append("\"with-filter-on\":{"); + } + if (minFilterVars != null) { + buffer.append("\n"); + addIndent(indent).append("\"min\":["); + boolean first = true; + for (LogicalVariable v : minFilterVars) { + if (!first) { + buffer.append(","); + } + buffer.append("\"" + str(v) + "\""); + first = false; + } + buffer.append("]"); + } + if (minFilterVars != null && maxFilterVars != null) { + buffer.append(","); + } + if (maxFilterVars != null) { + buffer.append("\n"); + addIndent(indent).append("\"max\":["); + boolean first = true; + for (LogicalVariable v : maxFilterVars) { + if (!first) { + buffer.append(","); + } + buffer.append("\"" + str(v) + "\""); + first = false; + } + buffer.append("]"); + } + if (minFilterVars != null || maxFilterVars != null) { + plan.append("\n"); + addIndent(indent).append("}"); + } + return null; + } + + @Override + public Void visitLimitOperator(LimitOperator op, Integer indent) throws AlgebricksException { + addIndent(indent).append("\"operator\":\"limit\",\n"); + addIndent(indent).append("\"value\":\"" + op.getMaxObjects().getValue().accept(exprVisitor, indent) + "\""); + ILogicalExpression offset = op.getOffset().getValue(); + if (offset != null) { + buffer.append(",\n"); + addIndent(indent).append("\"offset\":\"" + offset.accept(exprVisitor, indent) + "\""); + } + return null; + } + + @Override + public Void visitExchangeOperator(ExchangeOperator op, Integer indent) throws AlgebricksException { + addIndent(indent).append("\"operator\":\"exchange\""); + return null; + } + + @Override + public Void visitScriptOperator(ScriptOperator op, Integer indent) throws AlgebricksException { + addIndent(indent).append("\"operator\":\"script\""); + if (!op.getInputVariables().isEmpty()) { + addIndent(0).append(",\n"); + addIndent(indent).append("\"in\":["); + boolean first = true; + for (LogicalVariable v : op.getInputVariables()) { + if (!first) { + buffer.append(","); + } + buffer.append("\"" + str(v) + "\""); + first = false; + } + buffer.append("]"); + } + if (!op.getOutputVariables().isEmpty()) { + addIndent(0).append(",\n"); + addIndent(indent).append("\"out\":["); + boolean first = true; + for (LogicalVariable v : op.getOutputVariables()) { + if (!first) { + buffer.append(","); + } + buffer.append("\"" + str(v) + "\""); + first = false; + } + buffer.append("]"); + } + return null; + } + + @Override + public Void visitReplicateOperator(ReplicateOperator op, Integer indent) throws AlgebricksException { + addIndent(indent).append("\"operator\":\"replicate\""); + return null; + } + + @Override + public Void visitSplitOperator(SplitOperator op, Integer indent) throws AlgebricksException { + Mutable<ILogicalExpression> branchingExpression = op.getBranchingExpression(); + addIndent(indent).append("\"operator\":\"split\",\n"); + addIndent(indent).append("\"" + branchingExpression.getValue().accept(exprVisitor, indent) + "\""); + return null; + } + + @Override + public Void visitMaterializeOperator(MaterializeOperator op, Integer indent) throws AlgebricksException { + addIndent(indent).append("\"operator\":\"materialize\""); + return null; + } + + @Override + public Void visitInsertDeleteUpsertOperator(InsertDeleteUpsertOperator op, Integer indent) + throws AlgebricksException { + String header = "\"operator\":\"" + getIndexOpString(op.getOperation()) + "\",\n"; + addIndent(indent).append(header); + addIndent(indent).append(str("\"data-source\":\"" + op.getDataSource() + "\",\n")); + addIndent(indent).append("\"from-record\":\"") + .append(op.getPayloadExpression().getValue().accept(exprVisitor, indent) + "\""); + if (op.getAdditionalNonFilteringExpressions() != null) { + buffer.append(",\n\"meta\":\""); + pprintExprList(op.getAdditionalNonFilteringExpressions(), 0); + buffer.append("\""); + } + buffer.append(",\n"); + addIndent(indent).append("\"partitioned-by\":{"); + pprintExprList(op.getPrimaryKeyExpressions(), 0); + buffer.append("}"); + if (op.getOperation() == Kind.UPSERT) { + addIndent(indent).append(",\n\"out\":{\n"); + addIndent(indent).append("\"record-before-upsert\":\"" + op.getBeforeOpRecordVar() + "\""); + if (op.getBeforeOpAdditionalNonFilteringVars() != null) { + buffer.append(",\n"); + addIndent(indent) + .append("\"additional-before-upsert\":\"" + op.getBeforeOpAdditionalNonFilteringVars() + "\""); + } + addIndent(indent).append("}"); + } + if (op.isBulkload()) { + buffer.append(",\n"); + addIndent(indent).append("\"bulkload\":\"true\""); + } + return null; + } + + @Override + public Void visitIndexInsertDeleteUpsertOperator(IndexInsertDeleteUpsertOperator op, Integer indent) + throws AlgebricksException { + String header = getIndexOpString(op.getOperation()); + addIndent(indent).append("\"operator\":\"" + header + "\",\n"); + addIndent(indent).append("\"index\":\"" + op.getIndexName() + "\",\n"); + addIndent(indent).append("\"on\":\"").append(str(op.getDataSourceIndex().getDataSource()) + "\",\n"); + addIndent(indent).append("\"from\":{"); + + if (op.getOperation() == Kind.UPSERT) { + + addIndent(indent).append("[\"replace\":\""); + pprintExprList(op.getPrevSecondaryKeyExprs(), 0); + buffer.append("\",\n"); + addIndent(indent).append("\"with\":\""); + pprintExprList(op.getSecondaryKeyExpressions(), 0); + buffer.append("\"}"); + } else { + pprintExprList(op.getSecondaryKeyExpressions(), 0); + } + buffer.append("\n"); + addIndent(indent).append("}"); + if (op.isBulkload()) { + buffer.append(",\n"); + buffer.append("\"bulkload\":\"true\""); + } + return null; + } + + public String getIndexOpString(Kind opKind) { + switch (opKind) { + case DELETE: + return "delete-from"; + case INSERT: + return "insert-into"; + case UPSERT: + return "upsert-into"; + } + return null; + } + + @Override + public Void visitTokenizeOperator(TokenizeOperator op, Integer indent) throws AlgebricksException { + addIndent(indent).append("\"operator\":\"tokenize\""); + variablePrintHelper(op.getTokenizeVars(), indent); + if (!op.getSecondaryKeyExpressions().isEmpty()) { + addIndent(0).append(",\n"); + pprintExprList(op.getSecondaryKeyExpressions(), indent); + } + return null; + } + + @Override + public Void visitSinkOperator(SinkOperator op, Integer indent) throws AlgebricksException { + addIndent(indent).append("\"operator\":\"sink\""); + return null; + } + + @Override + public Void visitDelegateOperator(DelegateOperator op, Integer indent) throws AlgebricksException { + addIndent(indent).append("\"operator\":\"" + op.toString() + "\""); + return null; + } + + 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) throws AlgebricksException { + idCounter.nextPrefix(); + buffer.append("[\n"); + boolean first = true; + for (ILogicalPlan p : op.getNestedPlans()) { + if (!first) { + buffer.append(","); + } + printPlanJson(p, this, indent + 4); + first = false; + + } + addIndent(indent).append("]"); + idCounter.previousPrefix(); + } + + //Done--Look for exprRef + protected void pprintExprList(List<Mutable<ILogicalExpression>> expressions, Integer indent) + throws AlgebricksException { + addIndent(indent); + buffer.append("\"expressions\":\""); + boolean first = true; + for (Mutable<ILogicalExpression> exprRef : expressions) { + if (first) { + first = false; + } else { + buffer.append(", "); + } + buffer.append(exprRef.getValue().accept(exprVisitor, indent).replace('"', ' ')); + } + buffer.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 { + buffer.append(","); + } + if (ve.first != null) { + buffer.append("{\"variable\":\"" + ve.first.toString().replace('"', ' ') + "\"," + "\"expression\":\"" + + ve.second.toString().replace('"', ' ') + "\"}"); + } else { + buffer.append("{\"expression\":\"" + ve.second.getValue().accept(exprVisitor, indent).replace('"', ' ') + + "\"}"); + } + } + buffer.append("]"); + } + +} http://git-wip-us.apache.org/repos/asf/asterixdb/blob/a22ca7bf/hyracks-fullstack/algebricks/algebricks-core/src/main/java/org/apache/hyracks/algebricks/core/algebra/prettyprint/PlanPrettyPrinter.java ---------------------------------------------------------------------- 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 9a55f11..cf99d3b 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 @@ -18,76 +18,42 @@ */ 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; -import org.apache.hyracks.algebricks.core.algebra.base.IPhysicalOperator; import org.apache.hyracks.algebricks.core.algebra.operators.logical.AbstractLogicalOperator; -import org.apache.hyracks.algebricks.core.algebra.operators.logical.AbstractOperatorWithNestedPlans; public class PlanPrettyPrinter { - public static void printPlan(ILogicalPlan plan, LogicalOperatorPrettyPrintVisitor pvisitor, int indent) - throws AlgebricksException { - for (Mutable<ILogicalOperator> root : plan.getRoots()) { - printOperator((AbstractLogicalOperator) root.getValue(), pvisitor, indent); - } + @FunctionalInterface + public interface print<T1, T2, T3> { + void apply(T1 arg1, T2 arg2, T3 arg3) throws AlgebricksException; } - 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, LogicalOperatorPrettyPrintVisitor pvisitor, + int indent) throws AlgebricksException { + print<AbstractLogicalOperator, LogicalOperatorPrettyPrintVisitor, Integer> printOperator = + LogicalOperatorPrettyPrintVisitor::printOperator; + printOperator.apply(op, 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) { - out.append("\n"); - pad(out, indent); - appendln(out, "-- " + pOp.toString() + " |" + op.getExecutionMode() + "|"); - } else { - appendln(out, " -- |" + op.getExecutionMode() + "|"); + public static <T extends AbstractLogicalOperatorPrettyPrintVisitor> void printPlan(ILogicalPlan plan, + T pvisitor, int indent) throws AlgebricksException { + if (pvisitor.getClass().equals(LogicalOperatorPrettyPrintVisitor.class)) { + print<ILogicalPlan, LogicalOperatorPrettyPrintVisitor, Integer> printPlan = + LogicalOperatorPrettyPrintVisitor::printPlan; + printPlan.apply(plan,(LogicalOperatorPrettyPrintVisitor) pvisitor, indent); } - - for (Mutable<ILogicalOperator> i : op.getInputs()) { - printOperator((AbstractLogicalOperator) i.getValue(), pvisitor, indent + 2); + else if (pvisitor.getClass().equals(LogicalOperatorPrettyPrintVisitorJson.class)) { + print<ILogicalPlan, LogicalOperatorPrettyPrintVisitorJson, Integer> printPlan = + LogicalOperatorPrettyPrintVisitorJson::printPlanJson; + printPlan.apply(plan, (LogicalOperatorPrettyPrintVisitorJson)pvisitor, indent); } - } - 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() + "|"); - if (op.hasNestedPlans()) { - AbstractOperatorWithNestedPlans opNest = (AbstractOperatorWithNestedPlans) op; - for (ILogicalPlan p : opNest.getNestedPlans()) { - pad(out, indent + 8); - appendln(out, "{"); - printPhysicalOps(p, out, indent + 10); - pad(out, indent + 8); - appendln(out, "}"); - } - } - for (Mutable<ILogicalOperator> i : op.getInputs()) { - printPhysicalOperator((AbstractLogicalOperator) i.getValue(), indent + 2, out); - } - } - - private static void appendln(AlgebricksAppendable buf, String s) throws AlgebricksException { - buf.append(s); - buf.append("\n"); } - private static void pad(AlgebricksAppendable buf, int indent) throws AlgebricksException { - for (int i = 0; i < indent; ++i) { - buf.append(' '); - } + public static void printPhysicalOps(ILogicalPlan plan, AlgebricksAppendable out, int indent) + throws AlgebricksException { + print<ILogicalPlan, AlgebricksAppendable, Integer> printOperator = + AbstractLogicalOperatorPrettyPrintVisitor::printPhysicalOps; + printOperator.apply(plan, out, indent); } } http://git-wip-us.apache.org/repos/asf/asterixdb/blob/a22ca7bf/hyracks-fullstack/algebricks/algebricks-core/src/main/java/org/apache/hyracks/algebricks/core/algebra/visitors/ILogicalOperatorVisitor.java ---------------------------------------------------------------------- diff --git a/hyracks-fullstack/algebricks/algebricks-core/src/main/java/org/apache/hyracks/algebricks/core/algebra/visitors/ILogicalOperatorVisitor.java b/hyracks-fullstack/algebricks/algebricks-core/src/main/java/org/apache/hyracks/algebricks/core/algebra/visitors/ILogicalOperatorVisitor.java index 8da41e2..deb98b0 100644 --- a/hyracks-fullstack/algebricks/algebricks-core/src/main/java/org/apache/hyracks/algebricks/core/algebra/visitors/ILogicalOperatorVisitor.java +++ b/hyracks-fullstack/algebricks/algebricks-core/src/main/java/org/apache/hyracks/algebricks/core/algebra/visitors/ILogicalOperatorVisitor.java @@ -22,11 +22,11 @@ import org.apache.hyracks.algebricks.common.exceptions.AlgebricksException; import org.apache.hyracks.algebricks.core.algebra.operators.logical.AggregateOperator; import org.apache.hyracks.algebricks.core.algebra.operators.logical.AssignOperator; import org.apache.hyracks.algebricks.core.algebra.operators.logical.DataSourceScanOperator; +import org.apache.hyracks.algebricks.core.algebra.operators.logical.DelegateOperator; import org.apache.hyracks.algebricks.core.algebra.operators.logical.DistinctOperator; import org.apache.hyracks.algebricks.core.algebra.operators.logical.DistributeResultOperator; import org.apache.hyracks.algebricks.core.algebra.operators.logical.EmptyTupleSourceOperator; import org.apache.hyracks.algebricks.core.algebra.operators.logical.ExchangeOperator; -import org.apache.hyracks.algebricks.core.algebra.operators.logical.DelegateOperator; import org.apache.hyracks.algebricks.core.algebra.operators.logical.GroupByOperator; import org.apache.hyracks.algebricks.core.algebra.operators.logical.IndexInsertDeleteUpsertOperator; import org.apache.hyracks.algebricks.core.algebra.operators.logical.InnerJoinOperator;
