blob: 1cea0a951873446b05602aae4e1c4d02624b294e [file] [log] [blame]
/*
* 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.utils;
import static org.apache.hyracks.algebricks.core.algebra.properties.ILocalStructuralProperty.PropertyType.LOCAL_GROUPING_PROPERTY;
import static org.apache.hyracks.algebricks.core.algebra.properties.ILocalStructuralProperty.PropertyType.LOCAL_ORDER_PROPERTY;
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.exceptions.NotImplementedException;
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.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.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.ForwardOperator;
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.SwitchOperator;
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.WindowOperator;
import org.apache.hyracks.algebricks.core.algebra.operators.logical.WriteOperator;
import org.apache.hyracks.algebricks.core.algebra.properties.DefaultNodeGroupDomain;
import org.apache.hyracks.algebricks.core.algebra.properties.ILocalStructuralProperty;
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.IPhysicalPropertiesVector;
import org.apache.hyracks.algebricks.core.algebra.visitors.ILogicalOperatorVisitor;
public class LogicalOperatorDotVisitor implements ILogicalOperatorVisitor<String, Boolean> {
private final StringBuilder stringBuilder;
public LogicalOperatorDotVisitor() {
stringBuilder = new StringBuilder();
}
@Override
public String toString() {
return "";
}
private CharSequence str(Object o) {
return String.valueOf(o);
}
@Override
public String visitAggregateOperator(AggregateOperator op, Boolean showDetails) throws AlgebricksException {
stringBuilder.setLength(0);
stringBuilder.append("aggregate ").append(str(op.getVariables())).append(" <- ");
printExprList(op.getExpressions());
appendSchema(op, showDetails);
appendAnnotations(op, showDetails);
appendPhysicalOperatorInfo(op, showDetails);
return stringBuilder.toString();
}
@Override
public String visitRunningAggregateOperator(RunningAggregateOperator op, Boolean showDetails)
throws AlgebricksException {
stringBuilder.setLength(0);
stringBuilder.append("running-aggregate ").append(str(op.getVariables())).append(" <- ");
printExprList(op.getExpressions());
appendSchema(op, showDetails);
appendAnnotations(op, showDetails);
appendPhysicalOperatorInfo(op, showDetails);
return stringBuilder.toString();
}
@Override
public String visitEmptyTupleSourceOperator(EmptyTupleSourceOperator op, Boolean showDetails) {
stringBuilder.setLength(0);
stringBuilder.append("empty-tuple-source");
appendSchema(op, showDetails);
appendAnnotations(op, showDetails);
appendPhysicalOperatorInfo(op, showDetails);
return stringBuilder.toString();
}
@Override
public String visitGroupByOperator(GroupByOperator op, Boolean showDetails) throws AlgebricksException {
stringBuilder.setLength(0);
stringBuilder.append("group by").append(op.isGroupAll() ? " (all)" : "").append(" (");
printVariableAndExprList(op.getGroupByList());
stringBuilder.append(") decor (");
printVariableAndExprList(op.getDecorList());
stringBuilder.append(")");
appendSchema(op, showDetails);
appendAnnotations(op, showDetails);
appendPhysicalOperatorInfo(op, showDetails);
return stringBuilder.toString();
}
@Override
public String visitDistinctOperator(DistinctOperator op, Boolean showDetails) {
stringBuilder.setLength(0);
stringBuilder.append("distinct (");
printExprList(op.getExpressions());
stringBuilder.append(")");
appendSchema(op, showDetails);
appendAnnotations(op, showDetails);
appendPhysicalOperatorInfo(op, showDetails);
return stringBuilder.toString();
}
@Override
public String visitInnerJoinOperator(InnerJoinOperator op, Boolean showDetails) throws AlgebricksException {
stringBuilder.setLength(0);
stringBuilder.append("join (").append(op.getCondition().getValue().toString()).append(")");
appendSchema(op, showDetails);
appendAnnotations(op, showDetails);
appendPhysicalOperatorInfo(op, showDetails);
return stringBuilder.toString();
}
@Override
public String visitLeftOuterJoinOperator(LeftOuterJoinOperator op, Boolean showDetails) throws AlgebricksException {
stringBuilder.setLength(0);
stringBuilder.append("left outer join ").append("(").append(op.getCondition().getValue().toString())
.append(")");
stringBuilder.append(op.getMissingValue().isNull() ? " (or null) " : "");
appendSchema(op, showDetails);
appendAnnotations(op, showDetails);
appendPhysicalOperatorInfo(op, showDetails);
return stringBuilder.toString();
}
@Override
public String visitNestedTupleSourceOperator(NestedTupleSourceOperator op, Boolean showDetails)
throws AlgebricksException {
stringBuilder.setLength(0);
stringBuilder.append("nested tuple source");
appendSchema(op, showDetails);
appendAnnotations(op, showDetails);
appendPhysicalOperatorInfo(op, showDetails);
return stringBuilder.toString();
}
@Override
public String visitOrderOperator(OrderOperator op, Boolean showDetails) throws AlgebricksException {
stringBuilder.setLength(0);
stringBuilder.append("order ");
int topK = op.getTopK();
if (topK != -1) {
stringBuilder.append("(topK: ").append(topK).append(") ");
}
printOrderExprList(op.getOrderExpressions());
appendSchema(op, showDetails);
appendAnnotations(op, showDetails);
appendPhysicalOperatorInfo(op, showDetails);
return stringBuilder.toString();
}
private void appendOrder(OrderOperator.IOrder order) {
switch (order.getKind()) {
case ASC:
stringBuilder.append("ASC");
break;
case DESC:
stringBuilder.append("DESC");
break;
default:
final Mutable<ILogicalExpression> expressionRef = order.getExpressionRef();
stringBuilder.append(expressionRef == null ? "null" : expressionRef.toString());
}
}
@Override
public String visitAssignOperator(AssignOperator op, Boolean showDetails) throws AlgebricksException {
stringBuilder.setLength(0);
stringBuilder.append("assign ").append(str(op.getVariables())).append(" <- ");
printExprList(op.getExpressions());
appendSchema(op, showDetails);
appendAnnotations(op, showDetails);
appendPhysicalOperatorInfo(op, showDetails);
return stringBuilder.toString();
}
@Override
public String visitWriteOperator(WriteOperator op, Boolean showDetails) {
stringBuilder.setLength(0);
stringBuilder.append("write ");
printExprList(op.getExpressions());
appendSchema(op, showDetails);
appendAnnotations(op, showDetails);
appendPhysicalOperatorInfo(op, showDetails);
return stringBuilder.toString();
}
@Override
public String visitDistributeResultOperator(DistributeResultOperator op, Boolean showDetails) {
stringBuilder.setLength(0);
stringBuilder.append("distribute result ");
printExprList(op.getExpressions());
appendSchema(op, showDetails);
appendAnnotations(op, showDetails);
appendPhysicalOperatorInfo(op, showDetails);
return stringBuilder.toString();
}
@Override
public String visitSelectOperator(SelectOperator op, Boolean showDetails) {
stringBuilder.setLength(0);
stringBuilder.append("select (").append(op.getCondition().getValue().toString()).append(")");
appendSchema(op, showDetails);
appendAnnotations(op, showDetails);
appendPhysicalOperatorInfo(op, showDetails);
return stringBuilder.toString();
}
@Override
public String visitProjectOperator(ProjectOperator op, Boolean showDetails) throws AlgebricksException {
stringBuilder.setLength(0);
stringBuilder.append("project ").append("(").append(op.getVariables()).append(")");
appendSchema(op, showDetails);
appendAnnotations(op, showDetails);
appendPhysicalOperatorInfo(op, showDetails);
return stringBuilder.toString();
}
@Override
public String visitSubplanOperator(SubplanOperator op, Boolean showDetails) throws AlgebricksException {
stringBuilder.setLength(0);
stringBuilder.append("subplan {}");
appendSchema(op, showDetails);
appendAnnotations(op, showDetails);
appendPhysicalOperatorInfo(op, showDetails);
return stringBuilder.toString();
}
@Override
public String visitUnionOperator(UnionAllOperator op, Boolean showDetails) throws AlgebricksException {
stringBuilder.setLength(0);
stringBuilder.append("union");
for (Triple<LogicalVariable, LogicalVariable, LogicalVariable> v : op.getVariableMappings()) {
stringBuilder.append(" (").append(v.first).append(", ").append(v.second).append(", ").append(v.third)
.append(")");
}
appendSchema(op, showDetails);
appendAnnotations(op, showDetails);
appendPhysicalOperatorInfo(op, showDetails);
return stringBuilder.toString();
}
@Override
public String visitIntersectOperator(IntersectOperator op, Boolean showDetails) throws AlgebricksException {
stringBuilder.setLength(0);
stringBuilder.append("intersect (");
pprintVarList(op.getOutputCompareVariables());
if (op.hasExtraVariables()) {
stringBuilder.append(" extra ");
pprintVarList(op.getOutputExtraVariables());
}
stringBuilder.append(" <- [");
for (int i = 0, n = op.getNumInput(); i < n; i++) {
if (i > 0) {
stringBuilder.append(", ");
}
pprintVarList(op.getInputCompareVariables(i));
if (op.hasExtraVariables()) {
stringBuilder.append(" extra ");
pprintVarList(op.getInputExtraVariables(i));
}
}
stringBuilder.append("])");
appendSchema(op, showDetails);
appendAnnotations(op, showDetails);
appendPhysicalOperatorInfo(op, showDetails);
return stringBuilder.toString();
}
@Override
public String visitUnnestOperator(UnnestOperator op, Boolean showDetails) throws AlgebricksException {
stringBuilder.setLength(0);
stringBuilder.append("unnest ").append(op.getVariable());
if (op.getPositionalVariable() != null) {
stringBuilder.append(" at ").append(op.getPositionalVariable());
}
stringBuilder.append(" <- ").append(op.getExpressionRef().getValue().toString());
appendSchema(op, showDetails);
appendAnnotations(op, showDetails);
appendPhysicalOperatorInfo(op, showDetails);
return stringBuilder.toString();
}
@Override
public String visitLeftOuterUnnestOperator(LeftOuterUnnestOperator op, Boolean showDetails)
throws AlgebricksException {
stringBuilder.setLength(0);
stringBuilder.append("outer-unnest ").append(op.getVariable());
if (op.getPositionalVariable() != null) {
stringBuilder.append(" at ").append(op.getPositionalVariable());
}
stringBuilder.append(op.getMissingValue().isNull() ? " (or null) " : "");
stringBuilder.append(" <- ").append(op.getExpressionRef().getValue().toString());
appendSchema(op, showDetails);
appendAnnotations(op, showDetails);
appendPhysicalOperatorInfo(op, showDetails);
return stringBuilder.toString();
}
@Override
public String visitUnnestMapOperator(UnnestMapOperator op, Boolean showDetails) throws AlgebricksException {
stringBuilder.setLength(0);
printAbstractUnnestMapOperator(op, "unnest-map", showDetails);
appendSelectConditionInformation(op.getSelectCondition());
appendLimitInformation(op.getOutputLimit());
return stringBuilder.toString();
}
@Override
public String visitLeftOuterUnnestMapOperator(LeftOuterUnnestMapOperator op, Boolean showDetails)
throws AlgebricksException {
stringBuilder.setLength(0);
printAbstractUnnestMapOperator(op, "left-outer-unnest-map", showDetails);
return stringBuilder.toString();
}
private void printAbstractUnnestMapOperator(AbstractUnnestMapOperator op, String opSignature, boolean show) {
stringBuilder.append(opSignature).append(" ").append(op.getVariables()).append(" <- ")
.append(op.getExpressionRef().getValue().toString());
appendFilterInformation(op.getMinFilterVars(), op.getMaxFilterVars());
appendSchema(op, show);
appendAnnotations(op, show);
appendPhysicalOperatorInfo(op, show);
}
@Override
public String visitDataScanOperator(DataSourceScanOperator op, Boolean showDetails) throws AlgebricksException {
stringBuilder.setLength(0);
stringBuilder.append("data-scan ").append(op.getProjectVariables()).append("<-").append(op.getVariables())
.append(" <- ").append(op.getDataSource());
appendFilterInformation(op.getMinFilterVars(), op.getMaxFilterVars());
appendSelectConditionInformation(op.getSelectCondition());
appendLimitInformation(op.getOutputLimit());
appendSchema(op, showDetails);
appendAnnotations(op, showDetails);
appendPhysicalOperatorInfo(op, showDetails);
return stringBuilder.toString();
}
private void appendFilterInformation(List<LogicalVariable> minFilterVars, List<LogicalVariable> maxFilterVars) {
if (minFilterVars != null || maxFilterVars != null) {
stringBuilder.append(" with filter on");
}
if (minFilterVars != null) {
stringBuilder.append(" min:").append(minFilterVars);
}
if (maxFilterVars != null) {
stringBuilder.append(" max:").append(maxFilterVars);
}
}
private void appendSelectConditionInformation(Mutable<ILogicalExpression> condition) throws AlgebricksException {
if (condition != null) {
stringBuilder.append(" condition:").append(condition.getValue().toString());
}
}
private void appendLimitInformation(long outputLimit) throws AlgebricksException {
if (outputLimit >= 0) {
stringBuilder.append(" limit:").append(String.valueOf(outputLimit));
}
}
@Override
public String visitLimitOperator(LimitOperator op, Boolean showDetails) throws AlgebricksException {
stringBuilder.setLength(0);
stringBuilder.append("limit");
if (op.hasMaxObjects()) {
stringBuilder.append(' ').append(op.getMaxObjects().getValue());
}
if (op.hasOffset()) {
stringBuilder.append(" offset ").append(op.getOffset().getValue());
}
appendSchema(op, showDetails);
appendAnnotations(op, showDetails);
appendPhysicalOperatorInfo(op, showDetails);
return stringBuilder.toString();
}
@Override
public String visitExchangeOperator(ExchangeOperator op, Boolean showDetails) throws AlgebricksException {
stringBuilder.setLength(0);
stringBuilder.append("exchange");
appendSchema(op, showDetails);
appendAnnotations(op, showDetails);
appendPhysicalOperatorInfo(op, showDetails);
return stringBuilder.toString();
}
@Override
public String visitScriptOperator(ScriptOperator op, Boolean showDetails) throws AlgebricksException {
stringBuilder.setLength(0);
stringBuilder.append("script (in: ").append(op.getInputVariables()).append(") (out: ")
.append(op.getOutputVariables()).append(")");
appendSchema(op, showDetails);
appendAnnotations(op, showDetails);
appendPhysicalOperatorInfo(op, showDetails);
return stringBuilder.toString();
}
@Override
public String visitReplicateOperator(ReplicateOperator op, Boolean showDetails) throws AlgebricksException {
stringBuilder.setLength(0);
stringBuilder.append("replicate");
appendSchema(op, showDetails);
appendAnnotations(op, showDetails);
appendPhysicalOperatorInfo(op, showDetails);
return stringBuilder.toString();
}
@Override
public String visitSplitOperator(SplitOperator op, Boolean showDetails) throws AlgebricksException {
stringBuilder.setLength(0);
Mutable<ILogicalExpression> branchingExpression = op.getBranchingExpression();
stringBuilder.append("split ").append(branchingExpression.getValue().toString());
appendSchema(op, showDetails);
appendAnnotations(op, showDetails);
appendPhysicalOperatorInfo(op, showDetails);
return stringBuilder.toString();
}
@Override
public String visitSwitchOperator(SwitchOperator op, Boolean showDetails) throws AlgebricksException {
// TODO (GLENN): Implement this logic
throw new NotImplementedException();
}
@Override
public String visitMaterializeOperator(MaterializeOperator op, Boolean showDetails) throws AlgebricksException {
stringBuilder.setLength(0);
stringBuilder.append("materialize");
appendSchema(op, showDetails);
appendAnnotations(op, showDetails);
appendPhysicalOperatorInfo(op, showDetails);
return stringBuilder.toString();
}
@Override
public String visitInsertDeleteUpsertOperator(InsertDeleteUpsertOperator op, Boolean showDetails) {
stringBuilder.setLength(0);
String header = getIndexOpString(op.getOperation());
stringBuilder.append(header).append(str(op.getDataSource())).append(" from record: ")
.append(op.getPayloadExpression().getValue().toString());
if (op.getAdditionalNonFilteringExpressions() != null) {
stringBuilder.append(", meta: ");
printExprList(op.getAdditionalNonFilteringExpressions());
}
stringBuilder.append(" partitioned by ");
printExprList(op.getPrimaryKeyExpressions());
if (op.getOperation() == Kind.UPSERT) {
stringBuilder.append(" out: ([record-before-upsert:").append(op.getBeforeOpRecordVar());
if (op.getBeforeOpAdditionalNonFilteringVars() != null) {
stringBuilder.append(", additional-before-upsert: ").append(op.getBeforeOpAdditionalNonFilteringVars());
}
stringBuilder.append("]) ");
}
if (op.isBulkload()) {
stringBuilder.append(" [bulkload]");
}
appendSchema(op, showDetails);
appendAnnotations(op, showDetails);
appendPhysicalOperatorInfo(op, showDetails);
return stringBuilder.toString();
}
@Override
public String visitIndexInsertDeleteUpsertOperator(IndexInsertDeleteUpsertOperator op, Boolean showDetails) {
stringBuilder.setLength(0);
String header = getIndexOpString(op.getOperation());
stringBuilder.append(header).append(op.getIndexName()).append(" on ")
.append(str(op.getDataSourceIndex().getDataSource())).append(" from ");
if (op.getOperation() == Kind.UPSERT) {
stringBuilder.append(" replace:");
printExprList(op.getPrevSecondaryKeyExprs());
stringBuilder.append(" with:");
printExprList(op.getSecondaryKeyExpressions());
}
if (!op.getNestedPlans().isEmpty()) {
// TODO: Finish this for nested plans.
stringBuilder.append("{ a nested plan }");
} else {
printExprList(op.getSecondaryKeyExpressions());
}
if (op.isBulkload()) {
stringBuilder.append(" [bulkload]");
}
appendSchema(op, showDetails);
appendAnnotations(op, showDetails);
appendPhysicalOperatorInfo(op, showDetails);
return stringBuilder.toString();
}
private String getIndexOpString(Kind opKind) {
switch (opKind) {
case DELETE:
return "delete from ";
case INSERT:
return "insert into ";
case UPSERT:
return "upsert into ";
}
return "";
}
@Override
public String visitTokenizeOperator(TokenizeOperator op, Boolean showDetails) throws AlgebricksException {
stringBuilder.setLength(0);
stringBuilder.append("tokenize ").append(str(op.getTokenizeVars())).append(" <- ");
printExprList(op.getSecondaryKeyExpressions());
appendSchema(op, showDetails);
appendAnnotations(op, showDetails);
appendPhysicalOperatorInfo(op, showDetails);
return stringBuilder.toString();
}
@Override
public String visitSinkOperator(SinkOperator op, Boolean showDetails) {
stringBuilder.setLength(0);
stringBuilder.append("sink");
appendSchema(op, showDetails);
appendAnnotations(op, showDetails);
appendPhysicalOperatorInfo(op, showDetails);
return stringBuilder.toString();
}
@Override
public String visitDelegateOperator(DelegateOperator op, Boolean showDetails) throws AlgebricksException {
stringBuilder.setLength(0);
stringBuilder.append(op.toString());
appendSchema(op, showDetails);
appendAnnotations(op, showDetails);
appendPhysicalOperatorInfo(op, showDetails);
return stringBuilder.toString();
}
@Override
public String visitForwardOperator(ForwardOperator op, Boolean showDetails) throws AlgebricksException {
stringBuilder.setLength(0);
stringBuilder.append("forward(").append(op.getSideDataExpression().getValue().toString()).append(")");
appendSchema(op, showDetails);
appendAnnotations(op, showDetails);
appendPhysicalOperatorInfo(op, showDetails);
return stringBuilder.toString();
}
@Override
public String visitWindowOperator(WindowOperator op, Boolean showDetails) throws AlgebricksException {
stringBuilder.setLength(0);
stringBuilder.append("window (").append(str(op.getVariables())).append(" <- ");
printExprList(op.getExpressions());
stringBuilder.append(") partition by (");
printExprList(op.getPartitionExpressions());
stringBuilder.append(") order by (");
printOrderExprList(op.getOrderExpressions());
if (op.hasNestedPlans()) {
stringBuilder.append(") frame on (");
printOrderExprList(op.getFrameValueExpressions());
List<Mutable<ILogicalExpression>> frameStartExpressions = op.getFrameStartExpressions();
if (!frameStartExpressions.isEmpty()) {
stringBuilder.append(") frame start (");
printExprList(frameStartExpressions);
}
List<Mutable<ILogicalExpression>> frameStartValidationExpressions = op.getFrameStartValidationExpressions();
if (!frameStartValidationExpressions.isEmpty()) {
stringBuilder.append(") if (");
printExprList(frameStartValidationExpressions);
}
List<Mutable<ILogicalExpression>> frameEndExpressions = op.getFrameEndExpressions();
if (!frameEndExpressions.isEmpty()) {
stringBuilder.append(") frame end (");
printExprList(frameEndExpressions);
}
List<Mutable<ILogicalExpression>> frameEndValidationExpressions = op.getFrameEndValidationExpressions();
if (!frameEndValidationExpressions.isEmpty()) {
stringBuilder.append(") if (");
printExprList(frameEndValidationExpressions);
}
List<Mutable<ILogicalExpression>> frameExcludeExpressions = op.getFrameExcludeExpressions();
if (!frameExcludeExpressions.isEmpty()) {
stringBuilder.append(") frame exclude (");
stringBuilder.append(" (negation start: ").append(op.getFrameExcludeNegationStartIdx()).append(") ");
printExprList(frameExcludeExpressions);
}
Mutable<ILogicalExpression> frameExcludeUnaryExpression = op.getFrameExcludeUnaryExpression();
if (frameExcludeUnaryExpression.getValue() != null) {
stringBuilder.append(") frame exclude unary (");
stringBuilder.append(frameExcludeUnaryExpression.getValue());
stringBuilder.append(") ");
}
Mutable<ILogicalExpression> frameOffsetExpression = op.getFrameOffsetExpression();
if (frameOffsetExpression.getValue() != null) {
stringBuilder.append(") frame offset (");
stringBuilder.append(frameOffsetExpression.getValue());
stringBuilder.append(") ");
}
int frameMaxObjects = op.getFrameMaxObjects();
if (frameMaxObjects != -1) {
stringBuilder.append("(frame maxObjects: ").append(frameMaxObjects).append(") ");
}
}
stringBuilder.append(")");
appendSchema(op, showDetails);
appendAnnotations(op, showDetails);
appendPhysicalOperatorInfo(op, showDetails);
return stringBuilder.toString();
}
protected void pprintVarList(List<LogicalVariable> variables) {
stringBuilder.append("[");
variables.forEach(var -> stringBuilder.append(str(var)).append(", "));
stringBuilder.append("]");
}
private void printExprList(List<Mutable<ILogicalExpression>> expressions) {
stringBuilder.append("[");
expressions.forEach(exprRef -> stringBuilder.append(exprRef.getValue().toString()).append(", "));
stringBuilder.append("]");
}
private void printVariableAndExprList(List<Pair<LogicalVariable, Mutable<ILogicalExpression>>> variableExprList) {
stringBuilder.append("[");
boolean first = true;
for (Pair<LogicalVariable, Mutable<ILogicalExpression>> variableExpressionPair : variableExprList) {
if (first) {
first = false;
} else {
stringBuilder.append("; ");
}
if (variableExpressionPair.first != null) {
stringBuilder.append(variableExpressionPair.first).append(" := ").append(variableExpressionPair.second);
} else {
stringBuilder.append(variableExpressionPair.second.getValue().toString());
}
}
stringBuilder.append("]");
}
private void printOrderExprList(List<Pair<OrderOperator.IOrder, Mutable<ILogicalExpression>>> orderExprList) {
for (Pair<OrderOperator.IOrder, Mutable<ILogicalExpression>> p : orderExprList) {
stringBuilder.append("(");
appendOrder(p.first);
stringBuilder.append(", ").append(p.second.getValue().toString()).append(") ");
}
}
private void appendSchema(AbstractLogicalOperator op, boolean show) {
if (show) {
stringBuilder.append("\\nSchema: ");
final List<LogicalVariable> schema = op.getSchema();
stringBuilder.append(schema == null ? "null" : schema);
}
}
private void appendAnnotations(AbstractLogicalOperator op, boolean show) {
if (show) {
final Map<String, Object> annotations = op.getAnnotations();
if (!annotations.isEmpty()) {
stringBuilder.append("\\nAnnotations: ").append(annotations);
}
}
}
private void appendPhysicalOperatorInfo(AbstractLogicalOperator op, boolean show) {
IPhysicalOperator physicalOp = op.getPhysicalOperator();
stringBuilder.append("\\n").append(physicalOp == null ? "null" : physicalOp.toString().trim());
stringBuilder.append(", Exec: ").append(op.getExecutionMode());
if (show) {
IPhysicalPropertiesVector properties = physicalOp == null ? null : physicalOp.getDeliveredProperties();
List<ILocalStructuralProperty> localProp = properties == null ? null : properties.getLocalProperties();
IPartitioningProperty partitioningProp = properties == null ? null : properties.getPartitioningProperty();
if (localProp != null) {
stringBuilder.append("\\nProperties in each partition: [");
for (ILocalStructuralProperty property : localProp) {
if (property == null) {
stringBuilder.append("null, ");
} else if (property.getPropertyType() == LOCAL_ORDER_PROPERTY) {
stringBuilder.append("ordered by ");
} else if (property.getPropertyType() == LOCAL_GROUPING_PROPERTY) {
stringBuilder.append("group by ");
}
stringBuilder.append(property).append(", ");
}
stringBuilder.append("]");
}
if (partitioningProp != null) {
stringBuilder.append("\\n").append(partitioningProp.getPartitioningType()).append(":");
INodeDomain nodeDomain = partitioningProp.getNodeDomain();
stringBuilder.append("\\n ");
if (nodeDomain != null && nodeDomain.cardinality() != null) {
stringBuilder.append(nodeDomain.cardinality()).append(" partitions. ");
}
switch (partitioningProp.getPartitioningType()) {
case BROADCAST:
stringBuilder.append("Data is broadcast to partitions.");
break;
case RANDOM:
stringBuilder.append("Data is randomly partitioned.");
break;
case ORDERED_PARTITIONED:
stringBuilder.append("Data is orderly partitioned via a range.");
break;
case UNORDERED_PARTITIONED:
stringBuilder.append("Data is hash partitioned.");
break;
case UNPARTITIONED:
stringBuilder.append("Data is in one place.");
case PARTIAL_BROADCAST_ORDERED_FOLLOWING:
stringBuilder.append("Data is partially broadcasted to partitions.");
break;
case PARTIAL_BROADCAST_ORDERED_INTERSECT:
stringBuilder.append("Data is partially broadcasted to partitions.");
break;
}
if (nodeDomain instanceof DefaultNodeGroupDomain) {
DefaultNodeGroupDomain nd = (DefaultNodeGroupDomain) nodeDomain;
stringBuilder.append("\\n").append(nd);
}
}
}
}
}