| /* |
| * 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.operators.logical.visitors; |
| |
| import java.util.ArrayList; |
| import java.util.LinkedHashMap; |
| import java.util.List; |
| import java.util.Map; |
| |
| import org.apache.commons.lang3.mutable.Mutable; |
| import org.apache.commons.lang3.mutable.MutableObject; |
| 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.IOptimizationContext; |
| import org.apache.hyracks.algebricks.core.algebra.base.IVariableContext; |
| 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.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.DistinctOperator; |
| 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.ExtensionOperator; |
| import org.apache.hyracks.algebricks.core.algebra.operators.logical.GroupByOperator; |
| import org.apache.hyracks.algebricks.core.algebra.operators.logical.InnerJoinOperator; |
| 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.PartitioningSplitOperator; |
| import org.apache.hyracks.algebricks.core.algebra.operators.logical.ProjectOperator; |
| import org.apache.hyracks.algebricks.core.algebra.operators.logical.RangeForwardOperator; |
| 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.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.OrderOperator.IOrder; |
| import org.apache.hyracks.algebricks.core.algebra.plan.ALogicalPlanImpl; |
| import org.apache.hyracks.algebricks.core.algebra.properties.FunctionalDependency; |
| import org.apache.hyracks.algebricks.core.algebra.typing.ITypingContext; |
| import org.apache.hyracks.algebricks.core.algebra.util.OperatorManipulationUtil; |
| import org.apache.hyracks.algebricks.core.algebra.visitors.IQueryOperatorVisitor; |
| |
| /** |
| * This visitor deep-copies a query plan but uses a new set of variables. Method |
| * getInputToOutputVariableMapping() will return a map that maps input variables |
| * to their corresponding output variables. |
| */ |
| public class LogicalOperatorDeepCopyWithNewVariablesVisitor |
| implements IQueryOperatorVisitor<ILogicalOperator, ILogicalOperator> { |
| private final ITypingContext typeContext; |
| private final IVariableContext varContext; |
| private final LogicalExpressionDeepCopyWithNewVariablesVisitor exprDeepCopyVisitor; |
| |
| // Key: Variable in the original plan. Value: New variable replacing the |
| // original one in the copied plan. |
| private final LinkedHashMap<LogicalVariable, LogicalVariable> inputVarToOutputVarMapping; |
| |
| // Key: New variable in the new plan. Value: The old variable in the |
| // original plan. |
| private final LinkedHashMap<LogicalVariable, LogicalVariable> outputVarToInputVarMapping; |
| |
| /** |
| * @param varContext |
| * , the variable context. |
| * @param typeContext |
| * the type context. |
| */ |
| public LogicalOperatorDeepCopyWithNewVariablesVisitor(IVariableContext varContext, ITypingContext typeContext) { |
| this.varContext = varContext; |
| this.typeContext = typeContext; |
| this.inputVarToOutputVarMapping = new LinkedHashMap<>(); |
| this.outputVarToInputVarMapping = new LinkedHashMap<>(); |
| this.exprDeepCopyVisitor = new LogicalExpressionDeepCopyWithNewVariablesVisitor(varContext, |
| outputVarToInputVarMapping, inputVarToOutputVarMapping); |
| } |
| |
| /** |
| * @param varContext |
| * , the variable context. |
| * @param typeContext |
| * the type context. |
| * @param inVarMapping |
| * Variable mapping keyed by variables in the original plan. |
| * Those variables are replaced by their corresponding value in |
| * the map in the copied plan. |
| */ |
| public LogicalOperatorDeepCopyWithNewVariablesVisitor(IVariableContext varContext, ITypingContext typeContext, |
| LinkedHashMap<LogicalVariable, LogicalVariable> inVarMapping) { |
| this.varContext = varContext; |
| this.typeContext = typeContext; |
| this.inputVarToOutputVarMapping = inVarMapping; |
| this.outputVarToInputVarMapping = new LinkedHashMap<>(); |
| exprDeepCopyVisitor = new LogicalExpressionDeepCopyWithNewVariablesVisitor(varContext, inVarMapping, |
| inputVarToOutputVarMapping); |
| } |
| |
| private void copyAnnotations(ILogicalOperator src, ILogicalOperator dest) { |
| dest.getAnnotations().putAll(src.getAnnotations()); |
| } |
| |
| public ILogicalOperator deepCopy(ILogicalOperator op) throws AlgebricksException { |
| // The deep copy call outside this visitor always has a null argument. |
| return deepCopy(op, null); |
| } |
| |
| private ILogicalOperator deepCopy(ILogicalOperator op, ILogicalOperator arg) throws AlgebricksException { |
| if (op == null) { |
| return null; |
| } |
| ILogicalOperator opCopy = op.accept(this, arg); |
| if (typeContext != null) { |
| OperatorManipulationUtil.computeTypeEnvironmentBottomUp(opCopy, typeContext); |
| } |
| return opCopy; |
| } |
| |
| private void deepCopyInputs(ILogicalOperator src, ILogicalOperator dest, ILogicalOperator arg) |
| throws AlgebricksException { |
| List<Mutable<ILogicalOperator>> inputs = src.getInputs(); |
| List<Mutable<ILogicalOperator>> inputsCopy = dest.getInputs(); |
| for (Mutable<ILogicalOperator> input : inputs) { |
| inputsCopy.add(deepCopyOperatorReference(input, arg)); |
| } |
| } |
| |
| private Mutable<ILogicalOperator> deepCopyOperatorReference(Mutable<ILogicalOperator> opRef, ILogicalOperator arg) |
| throws AlgebricksException { |
| return new MutableObject<ILogicalOperator>(deepCopy(opRef.getValue(), arg)); |
| } |
| |
| private List<Mutable<ILogicalOperator>> deepCopyOperatorReferenceList(List<Mutable<ILogicalOperator>> list, |
| ILogicalOperator arg) throws AlgebricksException { |
| List<Mutable<ILogicalOperator>> listCopy = new ArrayList<Mutable<ILogicalOperator>>(list.size()); |
| for (Mutable<ILogicalOperator> opRef : list) { |
| listCopy.add(deepCopyOperatorReference(opRef, arg)); |
| } |
| return listCopy; |
| } |
| |
| private IOrder deepCopyOrder(IOrder order) { |
| switch (order.getKind()) { |
| case ASC: |
| case DESC: |
| return order; |
| case FUNCTIONCALL: |
| default: |
| throw new UnsupportedOperationException(); |
| } |
| } |
| |
| private List<Pair<IOrder, Mutable<ILogicalExpression>>> deepCopyOrderExpressionReferencePairList( |
| List<Pair<IOrder, Mutable<ILogicalExpression>>> list) throws AlgebricksException { |
| ArrayList<Pair<IOrder, Mutable<ILogicalExpression>>> listCopy = new ArrayList<Pair<IOrder, Mutable<ILogicalExpression>>>( |
| list.size()); |
| for (Pair<IOrder, Mutable<ILogicalExpression>> pair : list) { |
| listCopy.add(new Pair<OrderOperator.IOrder, Mutable<ILogicalExpression>>(deepCopyOrder(pair.first), |
| exprDeepCopyVisitor.deepCopyExpressionReference(pair.second))); |
| } |
| return listCopy; |
| } |
| |
| private ILogicalPlan deepCopyPlan(ILogicalPlan plan, ILogicalOperator arg) throws AlgebricksException { |
| List<Mutable<ILogicalOperator>> rootsCopy = deepCopyOperatorReferenceList(plan.getRoots(), arg); |
| ILogicalPlan planCopy = new ALogicalPlanImpl(rootsCopy); |
| return planCopy; |
| } |
| |
| private List<ILogicalPlan> deepCopyPlanList(List<ILogicalPlan> list, List<ILogicalPlan> listCopy, |
| ILogicalOperator arg) throws AlgebricksException { |
| for (ILogicalPlan plan : list) { |
| listCopy.add(deepCopyPlan(plan, arg)); |
| } |
| return listCopy; |
| } |
| |
| private LogicalVariable deepCopyVariable(LogicalVariable var) { |
| if (var == null) { |
| return null; |
| } |
| LogicalVariable givenVarReplacement = outputVarToInputVarMapping.get(var); |
| if (givenVarReplacement != null) { |
| inputVarToOutputVarMapping.put(var, givenVarReplacement); |
| return givenVarReplacement; |
| } |
| LogicalVariable varCopy = inputVarToOutputVarMapping.get(var); |
| if (varCopy == null) { |
| varCopy = varContext.newVar(); |
| inputVarToOutputVarMapping.put(var, varCopy); |
| } |
| return varCopy; |
| } |
| |
| private List<Pair<LogicalVariable, Mutable<ILogicalExpression>>> deepCopyVariableExpressionReferencePairList( |
| List<Pair<LogicalVariable, Mutable<ILogicalExpression>>> list) throws AlgebricksException { |
| List<Pair<LogicalVariable, Mutable<ILogicalExpression>>> listCopy = new ArrayList<Pair<LogicalVariable, Mutable<ILogicalExpression>>>( |
| list.size()); |
| for (Pair<LogicalVariable, Mutable<ILogicalExpression>> pair : list) { |
| listCopy.add(new Pair<LogicalVariable, Mutable<ILogicalExpression>>(deepCopyVariable(pair.first), |
| exprDeepCopyVisitor.deepCopyExpressionReference(pair.second))); |
| } |
| return listCopy; |
| } |
| |
| private List<LogicalVariable> deepCopyVariableList(List<LogicalVariable> list) { |
| ArrayList<LogicalVariable> listCopy = new ArrayList<LogicalVariable>(list.size()); |
| for (LogicalVariable var : list) { |
| listCopy.add(deepCopyVariable(var)); |
| } |
| return listCopy; |
| } |
| |
| private void deepCopyInputsAnnotationsAndExecutionMode(ILogicalOperator op, ILogicalOperator arg, |
| AbstractLogicalOperator opCopy) throws AlgebricksException { |
| deepCopyInputs(op, opCopy, arg); |
| copyAnnotations(op, opCopy); |
| opCopy.setExecutionMode(op.getExecutionMode()); |
| } |
| |
| public void reset() { |
| inputVarToOutputVarMapping.clear(); |
| outputVarToInputVarMapping.clear(); |
| } |
| |
| public void updatePrimaryKeys(IOptimizationContext context) { |
| for (Map.Entry<LogicalVariable, LogicalVariable> entry : inputVarToOutputVarMapping.entrySet()) { |
| List<LogicalVariable> primaryKey = context.findPrimaryKey(entry.getKey()); |
| if (primaryKey != null) { |
| List<LogicalVariable> head = new ArrayList<LogicalVariable>(); |
| for (LogicalVariable variable : primaryKey) { |
| head.add(inputVarToOutputVarMapping.get(variable)); |
| } |
| List<LogicalVariable> tail = new ArrayList<LogicalVariable>(1); |
| tail.add(entry.getValue()); |
| context.addPrimaryKey(new FunctionalDependency(head, tail)); |
| } |
| } |
| } |
| |
| public LogicalVariable varCopy(LogicalVariable var) throws AlgebricksException { |
| return inputVarToOutputVarMapping.get(var); |
| } |
| |
| @Override |
| public ILogicalOperator visitAggregateOperator(AggregateOperator op, ILogicalOperator arg) |
| throws AlgebricksException { |
| AggregateOperator opCopy = new AggregateOperator(deepCopyVariableList(op.getVariables()), |
| exprDeepCopyVisitor.deepCopyExpressionReferenceList(op.getExpressions())); |
| deepCopyInputsAnnotationsAndExecutionMode(op, arg, opCopy); |
| return opCopy; |
| } |
| |
| @Override |
| public ILogicalOperator visitAssignOperator(AssignOperator op, ILogicalOperator arg) throws AlgebricksException { |
| AssignOperator opCopy = new AssignOperator(deepCopyVariableList(op.getVariables()), |
| exprDeepCopyVisitor.deepCopyExpressionReferenceList(op.getExpressions())); |
| deepCopyInputsAnnotationsAndExecutionMode(op, arg, opCopy); |
| return opCopy; |
| } |
| |
| @Override |
| public ILogicalOperator visitDataScanOperator(DataSourceScanOperator op, ILogicalOperator arg) |
| throws AlgebricksException { |
| DataSourceScanOperator opCopy = new DataSourceScanOperator(deepCopyVariableList(op.getVariables()), |
| op.getDataSource()); |
| deepCopyInputsAnnotationsAndExecutionMode(op, arg, opCopy); |
| return opCopy; |
| } |
| |
| @Override |
| public ILogicalOperator visitDistinctOperator(DistinctOperator op, ILogicalOperator arg) |
| throws AlgebricksException { |
| DistinctOperator opCopy = new DistinctOperator( |
| exprDeepCopyVisitor.deepCopyExpressionReferenceList(op.getExpressions())); |
| deepCopyInputsAnnotationsAndExecutionMode(op, arg, opCopy); |
| return opCopy; |
| } |
| |
| @Override |
| public ILogicalOperator visitEmptyTupleSourceOperator(EmptyTupleSourceOperator op, ILogicalOperator arg) { |
| EmptyTupleSourceOperator opCopy = new EmptyTupleSourceOperator(); |
| opCopy.setExecutionMode(op.getExecutionMode()); |
| return opCopy; |
| } |
| |
| @Override |
| public ILogicalOperator visitExchangeOperator(ExchangeOperator op, ILogicalOperator arg) |
| throws AlgebricksException { |
| ExchangeOperator opCopy = new ExchangeOperator(); |
| deepCopyInputsAnnotationsAndExecutionMode(op, arg, opCopy); |
| return opCopy; |
| } |
| |
| @Override |
| public ILogicalOperator visitGroupByOperator(GroupByOperator op, ILogicalOperator arg) throws AlgebricksException { |
| List<Pair<LogicalVariable, Mutable<ILogicalExpression>>> groupByListCopy = deepCopyVariableExpressionReferencePairList( |
| op.getGroupByList()); |
| List<Pair<LogicalVariable, Mutable<ILogicalExpression>>> decorListCopy = deepCopyVariableExpressionReferencePairList( |
| op.getDecorList()); |
| List<ILogicalPlan> nestedPlansCopy = new ArrayList<ILogicalPlan>(); |
| |
| GroupByOperator opCopy = new GroupByOperator(groupByListCopy, decorListCopy, nestedPlansCopy, op.isGroupAll()); |
| deepCopyInputsAnnotationsAndExecutionMode(op, arg, opCopy); |
| deepCopyPlanList(op.getNestedPlans(), nestedPlansCopy, opCopy); |
| return opCopy; |
| } |
| |
| @Override |
| public ILogicalOperator visitInnerJoinOperator(InnerJoinOperator op, ILogicalOperator arg) |
| throws AlgebricksException { |
| InnerJoinOperator opCopy = new InnerJoinOperator( |
| exprDeepCopyVisitor.deepCopyExpressionReference(op.getCondition()), |
| deepCopyOperatorReference(op.getInputs().get(0), arg), |
| deepCopyOperatorReference(op.getInputs().get(1), arg)); |
| copyAnnotations(op, opCopy); |
| opCopy.setExecutionMode(op.getExecutionMode()); |
| return opCopy; |
| } |
| |
| @Override |
| public ILogicalOperator visitLeftOuterJoinOperator(LeftOuterJoinOperator op, ILogicalOperator arg) |
| throws AlgebricksException { |
| LeftOuterJoinOperator opCopy = new LeftOuterJoinOperator( |
| exprDeepCopyVisitor.deepCopyExpressionReference(op.getCondition()), |
| deepCopyOperatorReference(op.getInputs().get(0), arg), |
| deepCopyOperatorReference(op.getInputs().get(1), arg)); |
| copyAnnotations(op, opCopy); |
| opCopy.setExecutionMode(op.getExecutionMode()); |
| return opCopy; |
| } |
| |
| @Override |
| public ILogicalOperator visitLimitOperator(LimitOperator op, ILogicalOperator arg) throws AlgebricksException { |
| LimitOperator opCopy = new LimitOperator(exprDeepCopyVisitor.deepCopy(op.getMaxObjects().getValue()), |
| exprDeepCopyVisitor.deepCopy(op.getOffset().getValue()), op.isTopmostLimitOp()); |
| deepCopyInputsAnnotationsAndExecutionMode(op, arg, opCopy); |
| return opCopy; |
| } |
| |
| @Override |
| public ILogicalOperator visitNestedTupleSourceOperator(NestedTupleSourceOperator op, ILogicalOperator arg) |
| throws AlgebricksException { |
| Mutable<ILogicalOperator> dataSourceReference = arg == null ? op.getDataSourceReference() |
| : new MutableObject<ILogicalOperator>(arg); |
| NestedTupleSourceOperator opCopy = new NestedTupleSourceOperator(dataSourceReference); |
| deepCopyInputsAnnotationsAndExecutionMode(op, arg, opCopy); |
| return opCopy; |
| } |
| |
| @Override |
| public ILogicalOperator visitOrderOperator(OrderOperator op, ILogicalOperator arg) throws AlgebricksException { |
| OrderOperator opCopy = new OrderOperator(deepCopyOrderExpressionReferencePairList(op.getOrderExpressions())); |
| deepCopyInputsAnnotationsAndExecutionMode(op, arg, opCopy); |
| return opCopy; |
| } |
| |
| @Override |
| public ILogicalOperator visitPartitioningSplitOperator(PartitioningSplitOperator op, ILogicalOperator arg) |
| throws AlgebricksException { |
| PartitioningSplitOperator opCopy = new PartitioningSplitOperator( |
| exprDeepCopyVisitor.deepCopyExpressionReferenceList(op.getExpressions()), op.getDefaultBranchIndex()); |
| return opCopy; |
| } |
| |
| @Override |
| public ILogicalOperator visitProjectOperator(ProjectOperator op, ILogicalOperator arg) throws AlgebricksException { |
| ProjectOperator opCopy = new ProjectOperator(deepCopyVariableList(op.getVariables())); |
| deepCopyInputsAnnotationsAndExecutionMode(op, arg, opCopy); |
| return opCopy; |
| } |
| |
| @Override |
| public ILogicalOperator visitReplicateOperator(ReplicateOperator op, ILogicalOperator arg) |
| throws AlgebricksException { |
| boolean[] outputMatFlags = op.getOutputMaterializationFlags(); |
| boolean[] copiedOutputMatFlags = new boolean[outputMatFlags.length]; |
| System.arraycopy(outputMatFlags, 0, copiedOutputMatFlags, 0, outputMatFlags.length); |
| ReplicateOperator opCopy = new ReplicateOperator(op.getOutputArity(), copiedOutputMatFlags); |
| deepCopyInputsAnnotationsAndExecutionMode(op, arg, opCopy); |
| return opCopy; |
| } |
| |
| @Override |
| public ILogicalOperator visitRangeForwardOperator(RangeForwardOperator op, ILogicalOperator arg) |
| throws AlgebricksException { |
| // TODO fix deep copy of range map |
| RangeForwardOperator opCopy = new RangeForwardOperator(op.getRangeId(), op.getRangeMap()); |
| deepCopyInputsAnnotationsAndExecutionMode(op, arg, opCopy); |
| return opCopy; |
| } |
| |
| @Override |
| public ILogicalOperator visitMaterializeOperator(MaterializeOperator op, ILogicalOperator arg) |
| throws AlgebricksException { |
| MaterializeOperator opCopy = new MaterializeOperator(); |
| deepCopyInputsAnnotationsAndExecutionMode(op, arg, opCopy); |
| return opCopy; |
| } |
| |
| @Override |
| public ILogicalOperator visitRunningAggregateOperator(RunningAggregateOperator op, ILogicalOperator arg) |
| throws AlgebricksException { |
| RunningAggregateOperator opCopy = new RunningAggregateOperator(deepCopyVariableList(op.getVariables()), |
| exprDeepCopyVisitor.deepCopyExpressionReferenceList(op.getExpressions())); |
| deepCopyInputsAnnotationsAndExecutionMode(op, arg, opCopy); |
| return opCopy; |
| } |
| |
| @Override |
| public ILogicalOperator visitScriptOperator(ScriptOperator op, ILogicalOperator arg) throws AlgebricksException { |
| ScriptOperator opCopy = new ScriptOperator(op.getScriptDescription(), |
| deepCopyVariableList(op.getInputVariables()), deepCopyVariableList(op.getOutputVariables())); |
| deepCopyInputsAnnotationsAndExecutionMode(op, arg, opCopy); |
| return opCopy; |
| } |
| |
| @Override |
| public ILogicalOperator visitSelectOperator(SelectOperator op, ILogicalOperator arg) throws AlgebricksException { |
| SelectOperator opCopy = new SelectOperator(exprDeepCopyVisitor.deepCopyExpressionReference(op.getCondition()), |
| op.getRetainMissing(), deepCopyVariable(op.getMissingPlaceholderVariable())); |
| deepCopyInputsAnnotationsAndExecutionMode(op, arg, opCopy); |
| return opCopy; |
| } |
| |
| @Override |
| public ILogicalOperator visitSubplanOperator(SubplanOperator op, ILogicalOperator arg) throws AlgebricksException { |
| List<ILogicalPlan> nestedPlansCopy = new ArrayList<ILogicalPlan>(); |
| SubplanOperator opCopy = new SubplanOperator(nestedPlansCopy); |
| deepCopyInputsAnnotationsAndExecutionMode(op, arg, opCopy); |
| deepCopyPlanList(op.getNestedPlans(), nestedPlansCopy, opCopy); |
| return opCopy; |
| } |
| |
| @Override |
| public ILogicalOperator visitUnionOperator(UnionAllOperator op, ILogicalOperator arg) throws AlgebricksException { |
| List<Mutable<ILogicalOperator>> copiedInputs = new ArrayList<>(); |
| for (Mutable<ILogicalOperator> childRef : op.getInputs()) { |
| copiedInputs.add(deepCopyOperatorReference(childRef, null)); |
| } |
| List<List<LogicalVariable>> liveVarsInInputs = new ArrayList<>(); |
| for (Mutable<ILogicalOperator> inputOpRef : copiedInputs) { |
| List<LogicalVariable> liveVars = new ArrayList<>(); |
| VariableUtilities.getLiveVariables(inputOpRef.getValue(), liveVars); |
| liveVarsInInputs.add(liveVars); |
| } |
| List<LogicalVariable> liveVarsInLeftInput = liveVarsInInputs.get(0); |
| List<LogicalVariable> liveVarsInRightInput = liveVarsInInputs.get(1); |
| List<Triple<LogicalVariable, LogicalVariable, LogicalVariable>> copiedTriples = new ArrayList<>(); |
| int index = 0; |
| for (Triple<LogicalVariable, LogicalVariable, LogicalVariable> triple : op.getVariableMappings()) { |
| LogicalVariable producedVar = deepCopyVariable(triple.third); |
| Triple<LogicalVariable, LogicalVariable, LogicalVariable> copiedTriple = new Triple<>( |
| liveVarsInLeftInput.get(index), liveVarsInRightInput.get(index), producedVar); |
| copiedTriples.add(copiedTriple); |
| ++index; |
| } |
| UnionAllOperator opCopy = new UnionAllOperator(copiedTriples); |
| deepCopyInputsAnnotationsAndExecutionMode(op, arg, opCopy); |
| return opCopy; |
| } |
| |
| @Override |
| public ILogicalOperator visitIntersectOperator(IntersectOperator op, ILogicalOperator arg) |
| throws AlgebricksException { |
| List<List<LogicalVariable>> liveVarsInInputs = getLiveVarsInInputs(op); |
| List<LogicalVariable> outputCopy = new ArrayList<>(); |
| for (LogicalVariable var : op.getOutputVars()) { |
| outputCopy.add(deepCopyVariable(var)); |
| } |
| IntersectOperator opCopy = new IntersectOperator(outputCopy, liveVarsInInputs); |
| deepCopyInputsAnnotationsAndExecutionMode(op, arg, opCopy); |
| return opCopy; |
| } |
| |
| private List<List<LogicalVariable>> getLiveVarsInInputs(AbstractLogicalOperator op) throws AlgebricksException { |
| List<Mutable<ILogicalOperator>> copiedInputs = new ArrayList<>(); |
| for (Mutable<ILogicalOperator> childRef : op.getInputs()) { |
| copiedInputs.add(deepCopyOperatorReference(childRef, null)); |
| } |
| List<List<LogicalVariable>> liveVarsInInputs = new ArrayList<>(); |
| for (Mutable<ILogicalOperator> inputOpRef : copiedInputs) { |
| List<LogicalVariable> liveVars = new ArrayList<>(); |
| VariableUtilities.getLiveVariables(inputOpRef.getValue(), liveVars); |
| liveVarsInInputs.add(liveVars); |
| } |
| return liveVarsInInputs; |
| } |
| |
| @Override |
| public ILogicalOperator visitUnnestMapOperator(UnnestMapOperator op, ILogicalOperator arg) |
| throws AlgebricksException { |
| UnnestMapOperator opCopy = new UnnestMapOperator(deepCopyVariableList(op.getVariables()), |
| exprDeepCopyVisitor.deepCopyExpressionReference(op.getExpressionRef()), op.getVariableTypes(), |
| op.propagatesInput()); |
| deepCopyInputsAnnotationsAndExecutionMode(op, arg, opCopy); |
| return opCopy; |
| } |
| |
| @Override |
| public ILogicalOperator visitLeftOuterUnnestMapOperator(LeftOuterUnnestMapOperator op, ILogicalOperator arg) |
| throws AlgebricksException { |
| LeftOuterUnnestMapOperator opCopy = new LeftOuterUnnestMapOperator(deepCopyVariableList(op.getVariables()), |
| exprDeepCopyVisitor.deepCopyExpressionReference(op.getExpressionRef()), op.getVariableTypes(), |
| op.propagatesInput()); |
| deepCopyInputsAnnotationsAndExecutionMode(op, arg, opCopy); |
| return opCopy; |
| } |
| |
| @Override |
| public ILogicalOperator visitUnnestOperator(UnnestOperator op, ILogicalOperator arg) throws AlgebricksException { |
| UnnestOperator opCopy = new UnnestOperator(deepCopyVariable(op.getVariable()), |
| exprDeepCopyVisitor.deepCopyExpressionReference(op.getExpressionRef()), |
| deepCopyVariable(op.getPositionalVariable()), op.getPositionalVariableType(), op.getPositionWriter()); |
| deepCopyInputsAnnotationsAndExecutionMode(op, arg, opCopy); |
| return opCopy; |
| } |
| |
| @Override |
| public ILogicalOperator visitTokenizeOperator(TokenizeOperator op, ILogicalOperator arg) |
| throws AlgebricksException { |
| TokenizeOperator opCopy = new TokenizeOperator(op.getDataSourceIndex(), |
| exprDeepCopyVisitor.deepCopyExpressionReferenceList(op.getPrimaryKeyExpressions()), |
| exprDeepCopyVisitor.deepCopyExpressionReferenceList(op.getSecondaryKeyExpressions()), |
| this.deepCopyVariableList(op.getTokenizeVars()), |
| exprDeepCopyVisitor.deepCopyExpressionReference(op.getFilterExpression()), op.getOperation(), |
| op.isBulkload(), op.isPartitioned(), op.getTokenizeVarTypes()); |
| deepCopyInputsAnnotationsAndExecutionMode(op, arg, opCopy); |
| return opCopy; |
| } |
| |
| @Override |
| public ILogicalOperator visitExtensionOperator(ExtensionOperator op, ILogicalOperator arg) |
| throws AlgebricksException { |
| throw new UnsupportedOperationException(); |
| } |
| |
| @Override |
| public ILogicalOperator visitLeftOuterUnnestOperator(LeftOuterUnnestOperator op, ILogicalOperator arg) |
| throws AlgebricksException { |
| LeftOuterUnnestOperator opCopy = new LeftOuterUnnestOperator(deepCopyVariable(op.getVariable()), |
| exprDeepCopyVisitor.deepCopyExpressionReference(op.getExpressionRef()), |
| deepCopyVariable(op.getPositionalVariable()), op.getPositionalVariableType(), op.getPositionWriter()); |
| deepCopyInputsAnnotationsAndExecutionMode(op, arg, opCopy); |
| return opCopy; |
| } |
| |
| public LinkedHashMap<LogicalVariable, LogicalVariable> getOutputToInputVariableMapping() { |
| return outputVarToInputVarMapping; |
| } |
| |
| public LinkedHashMap<LogicalVariable, LogicalVariable> getInputToOutputVariableMapping() { |
| return inputVarToOutputVarMapping; |
| } |
| |
| } |