blob: 71fde6110ce1d0d7faf70274df52a86501056843 [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.rewriter.rules;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
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.IOptimizationContext;
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.visitors.VariableUtilities;
/**
* Inlines variables that are referenced exactly once.
*
* Preconditions/Assumptions:
* Assumes no projects are in the plan.
*
* Example assuming variable $$3 is referenced exactly once.
*
* Before plan:
* select (funcA($$3))
* ...
* assign [$$3] <- [field-access($$0, 1)]
*
* After plan:
* select (funcA(field-access($$0, 1))
* ...
* assign [] <- []
*/
public class InlineSingleReferenceVariablesRule extends InlineVariablesRule {
// Maps from variable to a list of operators using that variable.
protected Map<LogicalVariable, List<ILogicalOperator>> usedVarsMap = new HashMap<LogicalVariable, List<ILogicalOperator>>();
protected List<LogicalVariable> usedVars = new ArrayList<LogicalVariable>();
@Override
protected void prepare(IOptimizationContext context) {
super.prepare(context);
usedVarsMap.clear();
usedVars.clear();
}
@Override
protected boolean performFinalAction() throws AlgebricksException {
boolean modified = false;
for (Map.Entry<LogicalVariable, List<ILogicalOperator>> entry : usedVarsMap.entrySet()) {
// Perform replacement only if variable is referenced a single time.
if (entry.getValue().size() == 1) {
ILogicalOperator op = entry.getValue().get(0);
if (!op.requiresVariableReferenceExpressions()) {
inlineVisitor.setOperator(op);
inlineVisitor.setTargetVariable(entry.getKey());
if (op.acceptExpressionTransform(inlineVisitor)) {
modified = true;
}
inlineVisitor.setTargetVariable(null);
}
}
}
return modified;
}
@Override
protected boolean performBottomUpAction(AbstractLogicalOperator op) throws AlgebricksException {
usedVars.clear();
VariableUtilities.getUsedVariables(op, usedVars);
for (LogicalVariable var : usedVars) {
List<ILogicalOperator> opsUsingVar = usedVarsMap.get(var);
if (opsUsingVar == null) {
opsUsingVar = new ArrayList<ILogicalOperator>();
usedVarsMap.put(var, opsUsingVar);
}
opsUsingVar.add(op);
}
return false;
}
}