| /* |
| * 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.List; |
| |
| 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.LogicalVariable; |
| import org.apache.hyracks.algebricks.core.algebra.expressions.AbstractLogicalExpression; |
| 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.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.ExtensionOperator; |
| 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.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.OrderOperator.IOrder; |
| 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.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.util.OperatorManipulationUtil; |
| import org.apache.hyracks.algebricks.core.algebra.visitors.ILogicalOperatorVisitor; |
| |
| public class OperatorDeepCopyVisitor implements ILogicalOperatorVisitor<ILogicalOperator, Void> { |
| |
| @Override |
| public ILogicalOperator visitAggregateOperator(AggregateOperator op, Void arg) throws AlgebricksException { |
| ArrayList<LogicalVariable> newList = new ArrayList<>(); |
| ArrayList<Mutable<ILogicalExpression>> newExpressions = new ArrayList<>(); |
| newList.addAll(op.getVariables()); |
| deepCopyExpressionRefs(newExpressions, op.getExpressions()); |
| return new AggregateOperator(newList, newExpressions); |
| } |
| |
| @Override |
| public ILogicalOperator visitRunningAggregateOperator(RunningAggregateOperator op, Void arg) |
| throws AlgebricksException { |
| ArrayList<LogicalVariable> newList = new ArrayList<>(); |
| ArrayList<Mutable<ILogicalExpression>> newExpressions = new ArrayList<>(); |
| newList.addAll(op.getVariables()); |
| deepCopyExpressionRefs(newExpressions, op.getExpressions()); |
| return new RunningAggregateOperator(newList, newExpressions); |
| } |
| |
| @Override |
| public ILogicalOperator visitEmptyTupleSourceOperator(EmptyTupleSourceOperator op, Void arg) |
| throws AlgebricksException { |
| return new EmptyTupleSourceOperator(); |
| } |
| |
| @Override |
| public ILogicalOperator visitGroupByOperator(GroupByOperator op, Void arg) throws AlgebricksException { |
| List<Pair<LogicalVariable, Mutable<ILogicalExpression>>> groupByList = new ArrayList<>(); |
| List<Pair<LogicalVariable, Mutable<ILogicalExpression>>> decoList = new ArrayList<>(); |
| ArrayList<ILogicalPlan> newSubplans = new ArrayList<>(); |
| for (Pair<LogicalVariable, Mutable<ILogicalExpression>> pair : op.getGroupByList()) { |
| groupByList.add(new Pair<>(pair.first, deepCopyExpressionRef(pair.second))); |
| } |
| for (Pair<LogicalVariable, Mutable<ILogicalExpression>> pair : op.getDecorList()) { |
| decoList.add(new Pair<>(pair.first, deepCopyExpressionRef(pair.second))); |
| } |
| GroupByOperator gbyOp = new GroupByOperator(groupByList, decoList, newSubplans, op.isGroupAll()); |
| for (ILogicalPlan plan : op.getNestedPlans()) { |
| newSubplans.add(OperatorManipulationUtil.deepCopy(plan, gbyOp)); |
| } |
| return gbyOp; |
| } |
| |
| @Override |
| public ILogicalOperator visitLimitOperator(LimitOperator op, Void arg) throws AlgebricksException { |
| return new LimitOperator(deepCopyExpressionRef(op.getMaxObjects()).getValue(), |
| deepCopyExpressionRef(op.getOffset()).getValue(), op.isTopmostLimitOp()); |
| } |
| |
| @Override |
| public ILogicalOperator visitInnerJoinOperator(InnerJoinOperator op, Void arg) throws AlgebricksException { |
| return new InnerJoinOperator(deepCopyExpressionRef(op.getCondition()), op.getInputs().get(0), |
| op.getInputs().get(1)); |
| } |
| |
| @Override |
| public ILogicalOperator visitLeftOuterJoinOperator(LeftOuterJoinOperator op, Void arg) throws AlgebricksException { |
| return new LeftOuterJoinOperator(deepCopyExpressionRef(op.getCondition()), op.getInputs().get(0), |
| op.getInputs().get(1)); |
| } |
| |
| @Override |
| public ILogicalOperator visitNestedTupleSourceOperator(NestedTupleSourceOperator op, Void arg) |
| throws AlgebricksException { |
| return new NestedTupleSourceOperator(op.getDataSourceReference()); |
| } |
| |
| @Override |
| public ILogicalOperator visitOrderOperator(OrderOperator op, Void arg) throws AlgebricksException { |
| return new OrderOperator(this.deepCopyOrderAndExpression(op.getOrderExpressions())); |
| } |
| |
| @Override |
| public ILogicalOperator visitAssignOperator(AssignOperator op, Void arg) throws AlgebricksException { |
| ArrayList<LogicalVariable> newList = new ArrayList<>(); |
| ArrayList<Mutable<ILogicalExpression>> newExpressions = new ArrayList<>(); |
| newList.addAll(op.getVariables()); |
| deepCopyExpressionRefs(newExpressions, op.getExpressions()); |
| return new AssignOperator(newList, newExpressions); |
| } |
| |
| @Override |
| public ILogicalOperator visitSelectOperator(SelectOperator op, Void arg) throws AlgebricksException { |
| return new SelectOperator(deepCopyExpressionRef(op.getCondition()), op.getRetainMissing(), |
| op.getMissingPlaceholderVariable()); |
| } |
| |
| @Override |
| public ILogicalOperator visitProjectOperator(ProjectOperator op, Void arg) throws AlgebricksException { |
| ArrayList<LogicalVariable> newList = new ArrayList<>(); |
| newList.addAll(op.getVariables()); |
| return new ProjectOperator(newList); |
| } |
| |
| @Override |
| public ILogicalOperator visitReplicateOperator(ReplicateOperator op, Void arg) throws AlgebricksException { |
| return new ReplicateOperator(op.getOutputArity()); |
| } |
| |
| @Override |
| public ILogicalOperator visitSplitOperator(SplitOperator op, Void arg) throws AlgebricksException { |
| return new SplitOperator(op.getOutputArity(), op.getBranchingExpression()); |
| } |
| |
| @Override |
| public ILogicalOperator visitScriptOperator(ScriptOperator op, Void arg) throws AlgebricksException { |
| ArrayList<LogicalVariable> newInputList = new ArrayList<>(); |
| ArrayList<LogicalVariable> newOutputList = new ArrayList<>(); |
| newInputList.addAll(op.getInputVariables()); |
| newOutputList.addAll(op.getOutputVariables()); |
| return new ScriptOperator(op.getScriptDescription(), newInputList, newOutputList); |
| } |
| |
| @Override |
| public ILogicalOperator visitSubplanOperator(SubplanOperator op, Void arg) throws AlgebricksException { |
| ArrayList<ILogicalPlan> newSubplans = new ArrayList<>(); |
| SubplanOperator subplanOp = new SubplanOperator(newSubplans); |
| for (ILogicalPlan plan : op.getNestedPlans()) { |
| newSubplans.add(OperatorManipulationUtil.deepCopy(plan, subplanOp)); |
| } |
| return subplanOp; |
| } |
| |
| @Override |
| public ILogicalOperator visitUnionOperator(UnionAllOperator op, Void arg) throws AlgebricksException { |
| List<Triple<LogicalVariable, LogicalVariable, LogicalVariable>> newVarMap = new ArrayList<>(); |
| List<Triple<LogicalVariable, LogicalVariable, LogicalVariable>> varMap = op.getVariableMappings(); |
| for (Triple<LogicalVariable, LogicalVariable, LogicalVariable> triple : varMap) { |
| newVarMap.add(new Triple<>(triple.first, triple.second, triple.third)); |
| } |
| return new UnionAllOperator(newVarMap); |
| } |
| |
| @Override |
| public ILogicalOperator visitIntersectOperator(IntersectOperator op, Void arg) throws AlgebricksException { |
| List<LogicalVariable> outputVar = new ArrayList<>(op.getOutputVars()); |
| List<List<LogicalVariable>> inputVars = new ArrayList<>(op.getNumInput()); |
| for (int i = 0; i < op.getNumInput(); i++) { |
| inputVars.add(new ArrayList<>(op.getInputVariables(i))); |
| } |
| return new IntersectOperator(outputVar, inputVars); |
| } |
| |
| @Override |
| public ILogicalOperator visitUnnestOperator(UnnestOperator op, Void arg) throws AlgebricksException { |
| return new UnnestOperator(op.getVariable(), deepCopyExpressionRef(op.getExpressionRef()), |
| op.getPositionalVariable(), op.getPositionalVariableType(), op.getPositionWriter()); |
| } |
| |
| @Override |
| public ILogicalOperator visitUnnestMapOperator(UnnestMapOperator op, Void arg) throws AlgebricksException { |
| ArrayList<LogicalVariable> newInputList = new ArrayList<>(); |
| newInputList.addAll(op.getVariables()); |
| return new UnnestMapOperator(newInputList, deepCopyExpressionRef(op.getExpressionRef()), |
| new ArrayList<>(op.getVariableTypes()), op.propagatesInput()); |
| } |
| |
| @Override |
| public ILogicalOperator visitLeftOuterUnnestMapOperator(LeftOuterUnnestMapOperator op, Void arg) |
| throws AlgebricksException { |
| ArrayList<LogicalVariable> newInputList = new ArrayList<>(); |
| newInputList.addAll(op.getVariables()); |
| return new LeftOuterUnnestMapOperator(newInputList, deepCopyExpressionRef(op.getExpressionRef()), |
| new ArrayList<>(op.getVariableTypes()), op.propagatesInput()); |
| } |
| |
| @Override |
| public ILogicalOperator visitDataScanOperator(DataSourceScanOperator op, Void arg) throws AlgebricksException { |
| ArrayList<LogicalVariable> newInputList = new ArrayList<>(); |
| newInputList.addAll(op.getVariables()); |
| return new DataSourceScanOperator(newInputList, op.getDataSource()); |
| } |
| |
| @Override |
| public ILogicalOperator visitDistinctOperator(DistinctOperator op, Void arg) throws AlgebricksException { |
| ArrayList<Mutable<ILogicalExpression>> newExpressions = new ArrayList<>(); |
| deepCopyExpressionRefs(newExpressions, op.getExpressions()); |
| return new DistinctOperator(newExpressions); |
| } |
| |
| @Override |
| public ILogicalOperator visitExchangeOperator(ExchangeOperator op, Void arg) throws AlgebricksException { |
| return new ExchangeOperator(); |
| } |
| |
| @Override |
| public ILogicalOperator visitWriteOperator(WriteOperator op, Void arg) throws AlgebricksException { |
| ArrayList<Mutable<ILogicalExpression>> newExpressions = new ArrayList<>(); |
| deepCopyExpressionRefs(newExpressions, op.getExpressions()); |
| return new WriteOperator(newExpressions, op.getDataSink()); |
| } |
| |
| @Override |
| public ILogicalOperator visitDistributeResultOperator(DistributeResultOperator op, Void arg) |
| throws AlgebricksException { |
| ArrayList<Mutable<ILogicalExpression>> newExpressions = new ArrayList<>(); |
| deepCopyExpressionRefs(newExpressions, op.getExpressions()); |
| return new DistributeResultOperator(newExpressions, op.getDataSink()); |
| } |
| |
| @Override |
| public ILogicalOperator visitWriteResultOperator(WriteResultOperator op, Void arg) throws AlgebricksException { |
| ArrayList<Mutable<ILogicalExpression>> newKeyExpressions = new ArrayList<>(); |
| deepCopyExpressionRefs(newKeyExpressions, op.getKeyExpressions()); |
| List<Mutable<ILogicalExpression>> newLSMComponentFilterExpressions = new ArrayList<>(); |
| deepCopyExpressionRefs(newKeyExpressions, op.getAdditionalFilteringExpressions()); |
| WriteResultOperator writeResultOp = new WriteResultOperator(op.getDataSource(), |
| deepCopyExpressionRef(op.getPayloadExpression()), newKeyExpressions); |
| writeResultOp.setAdditionalFilteringExpressions(newLSMComponentFilterExpressions); |
| return writeResultOp; |
| } |
| |
| @Override |
| public ILogicalOperator visitInsertDeleteUpsertOperator(InsertDeleteUpsertOperator op, Void arg) |
| throws AlgebricksException { |
| List<Mutable<ILogicalExpression>> newKeyExpressions = new ArrayList<>(); |
| deepCopyExpressionRefs(newKeyExpressions, op.getPrimaryKeyExpressions()); |
| List<Mutable<ILogicalExpression>> newLSMComponentFilterExpressions = new ArrayList<>(); |
| deepCopyExpressionRefs(newKeyExpressions, op.getAdditionalFilteringExpressions()); |
| InsertDeleteUpsertOperator insertDeleteOp = new InsertDeleteUpsertOperator(op.getDataSource(), |
| deepCopyExpressionRef(op.getPayloadExpression()), newKeyExpressions, op.getOperation(), |
| op.isBulkload()); |
| insertDeleteOp.setAdditionalFilteringExpressions(newLSMComponentFilterExpressions); |
| return insertDeleteOp; |
| } |
| |
| @Override |
| public ILogicalOperator visitIndexInsertDeleteUpsertOperator(IndexInsertDeleteUpsertOperator op, Void arg) |
| throws AlgebricksException { |
| List<Mutable<ILogicalExpression>> newPrimaryKeyExpressions = new ArrayList<>(); |
| deepCopyExpressionRefs(newPrimaryKeyExpressions, op.getPrimaryKeyExpressions()); |
| List<Mutable<ILogicalExpression>> newSecondaryKeyExpressions = new ArrayList<>(); |
| deepCopyExpressionRefs(newSecondaryKeyExpressions, op.getSecondaryKeyExpressions()); |
| Mutable<ILogicalExpression> newFilterExpression = new MutableObject<>( |
| ((AbstractLogicalExpression) op.getFilterExpression()).cloneExpression()); |
| List<Mutable<ILogicalExpression>> newLSMComponentFilterExpressions = new ArrayList<>(); |
| deepCopyExpressionRefs(newLSMComponentFilterExpressions, op.getAdditionalFilteringExpressions()); |
| IndexInsertDeleteUpsertOperator indexInsertDeleteOp = new IndexInsertDeleteUpsertOperator( |
| op.getDataSourceIndex(), newPrimaryKeyExpressions, newSecondaryKeyExpressions, newFilterExpression, |
| op.getOperation(), op.isBulkload(), op.getNumberOfAdditionalNonFilteringFields()); |
| indexInsertDeleteOp.setAdditionalFilteringExpressions(newLSMComponentFilterExpressions); |
| return indexInsertDeleteOp; |
| } |
| |
| @Override |
| public ILogicalOperator visitTokenizeOperator(TokenizeOperator op, Void arg) throws AlgebricksException { |
| List<Mutable<ILogicalExpression>> newPrimaryKeyExpressions = new ArrayList<>(); |
| deepCopyExpressionRefs(newPrimaryKeyExpressions, op.getPrimaryKeyExpressions()); |
| List<Mutable<ILogicalExpression>> newSecondaryKeyExpressions = new ArrayList<>(); |
| deepCopyExpressionRefs(newSecondaryKeyExpressions, op.getSecondaryKeyExpressions()); |
| List<LogicalVariable> newTokenizeVars = new ArrayList<>(); |
| deepCopyVars(newTokenizeVars, op.getTokenizeVars()); |
| Mutable<ILogicalExpression> newFilterExpression = new MutableObject<>( |
| ((AbstractLogicalExpression) op.getFilterExpression()).cloneExpression()); |
| List<Object> newTokenizeVarTypes = new ArrayList<>(); |
| deepCopyObjects(newTokenizeVarTypes, op.getTokenizeVarTypes()); |
| |
| TokenizeOperator tokenizeOp = new TokenizeOperator(op.getDataSourceIndex(), newPrimaryKeyExpressions, |
| newSecondaryKeyExpressions, newTokenizeVars, newFilterExpression, op.getOperation(), op.isBulkload(), |
| op.isPartitioned(), newTokenizeVarTypes); |
| return tokenizeOp; |
| } |
| |
| @Override |
| public ILogicalOperator visitSinkOperator(SinkOperator op, Void arg) throws AlgebricksException { |
| return new SinkOperator(); |
| } |
| |
| private void deepCopyExpressionRefs(List<Mutable<ILogicalExpression>> newExprs, |
| List<Mutable<ILogicalExpression>> oldExprs) { |
| for (Mutable<ILogicalExpression> oldExpr : oldExprs) { |
| newExprs.add(new MutableObject<>(((AbstractLogicalExpression) oldExpr.getValue()).cloneExpression())); |
| } |
| } |
| |
| private Mutable<ILogicalExpression> deepCopyExpressionRef(Mutable<ILogicalExpression> oldExprRef) { |
| ILogicalExpression oldExpr = oldExprRef.getValue(); |
| if (oldExpr == null) { |
| return new MutableObject<>(null); |
| } |
| return new MutableObject<>(oldExpr.cloneExpression()); |
| } |
| |
| private List<LogicalVariable> deepCopyVars(List<LogicalVariable> newVars, List<LogicalVariable> oldVars) { |
| for (LogicalVariable oldVar : oldVars) { |
| newVars.add(oldVar); |
| } |
| return newVars; |
| } |
| |
| private List<Object> deepCopyObjects(List<Object> newObjs, List<Object> oldObjs) { |
| for (Object oldObj : oldObjs) { |
| newObjs.add(oldObj); |
| } |
| return newObjs; |
| } |
| |
| private List<Pair<IOrder, Mutable<ILogicalExpression>>> deepCopyOrderAndExpression( |
| List<Pair<IOrder, Mutable<ILogicalExpression>>> ordersAndExprs) { |
| List<Pair<IOrder, Mutable<ILogicalExpression>>> newOrdersAndExprs = new ArrayList<>(); |
| for (Pair<IOrder, Mutable<ILogicalExpression>> pair : ordersAndExprs) { |
| newOrdersAndExprs.add(new Pair<>(pair.first, deepCopyExpressionRef(pair.second))); |
| } |
| return newOrdersAndExprs; |
| } |
| |
| @Override |
| public ILogicalOperator visitExtensionOperator(ExtensionOperator op, Void arg) throws AlgebricksException { |
| return new ExtensionOperator(op.getNewInstanceOfDelegateOperator()); |
| } |
| |
| @Override |
| public ILogicalOperator visitRangeForwardOperator(RangeForwardOperator op, Void arg) throws AlgebricksException { |
| return new RangeForwardOperator(op.getRangeId(), op.getRangeMap()); |
| } |
| |
| @Override |
| public ILogicalOperator visitMaterializeOperator(MaterializeOperator op, Void arg) throws AlgebricksException { |
| return new MaterializeOperator(); |
| } |
| |
| @Override |
| public ILogicalOperator visitLeftOuterUnnestOperator(LeftOuterUnnestOperator op, Void arg) |
| throws AlgebricksException { |
| return new LeftOuterUnnestOperator(op.getVariable(), deepCopyExpressionRef(op.getExpressionRef()), |
| op.getPositionalVariable(), op.getPositionalVariableType(), op.getPositionWriter()); |
| } |
| } |