blob: cd8f04229a55b0ef9b46e540aa73395698dfcb8e [file] [log] [blame]
/*
* Copyright 2009-2010 by The Regents of the University of California
* Licensed 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 from
*
* 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 edu.uci.ics.hyracks.algebricks.core.algebra.util;
import java.util.Collection;
import java.util.HashSet;
import java.util.Set;
import org.apache.commons.lang3.mutable.Mutable;
import edu.uci.ics.hyracks.algebricks.common.exceptions.AlgebricksException;
import edu.uci.ics.hyracks.algebricks.core.algebra.base.ILogicalExpression;
import edu.uci.ics.hyracks.algebricks.core.algebra.base.ILogicalOperator;
import edu.uci.ics.hyracks.algebricks.core.algebra.base.ILogicalPlan;
import edu.uci.ics.hyracks.algebricks.core.algebra.base.IOptimizationContext;
import edu.uci.ics.hyracks.algebricks.core.algebra.base.LogicalExpressionTag;
import edu.uci.ics.hyracks.algebricks.core.algebra.base.LogicalOperatorTag;
import edu.uci.ics.hyracks.algebricks.core.algebra.base.LogicalVariable;
import edu.uci.ics.hyracks.algebricks.core.algebra.expressions.AbstractFunctionCallExpression;
import edu.uci.ics.hyracks.algebricks.core.algebra.expressions.ConstantExpression;
import edu.uci.ics.hyracks.algebricks.core.algebra.functions.AlgebricksBuiltinFunctions;
import edu.uci.ics.hyracks.algebricks.core.algebra.operators.logical.AbstractLogicalOperator;
import edu.uci.ics.hyracks.algebricks.core.algebra.operators.logical.AbstractOperatorWithNestedPlans;
import edu.uci.ics.hyracks.algebricks.core.algebra.operators.logical.SelectOperator;
import edu.uci.ics.hyracks.algebricks.core.algebra.operators.logical.visitors.VariableUtilities;
public class OperatorPropertiesUtil {
public static <T> boolean disjoint(Collection<T> c1, Collection<T> c2) {
for (T m : c1) {
if (c2.contains(m)) {
return false;
}
}
return true;
}
// Obs: doesn't return expected result for op. with nested plans.
private static void getFreeVariablesInOp(ILogicalOperator op, Set<LogicalVariable> freeVars)
throws AlgebricksException {
VariableUtilities.getUsedVariables(op, freeVars);
HashSet<LogicalVariable> produced = new HashSet<LogicalVariable>();
VariableUtilities.getProducedVariables(op, produced);
for (LogicalVariable v : produced) {
freeVars.remove(v);
}
}
/**
* Adds the free variables of the plan rooted at that operator to the
* collection provided.
*
* @param op
* @param vars
* - The collection to which the free variables will be added.
*/
public static void getFreeVariablesInSelfOrDesc(AbstractLogicalOperator op, Set<LogicalVariable> freeVars)
throws AlgebricksException {
HashSet<LogicalVariable> produced = new HashSet<LogicalVariable>();
VariableUtilities.getProducedVariables(op, produced);
for (LogicalVariable v : produced) {
freeVars.remove(v);
}
HashSet<LogicalVariable> used = new HashSet<LogicalVariable>();
VariableUtilities.getUsedVariables(op, used);
for (LogicalVariable v : used) {
if (!freeVars.contains(v)) {
freeVars.add(v);
}
}
if (op.hasNestedPlans()) {
AbstractOperatorWithNestedPlans s = (AbstractOperatorWithNestedPlans) op;
for (ILogicalPlan p : s.getNestedPlans()) {
for (Mutable<ILogicalOperator> r : p.getRoots()) {
getFreeVariablesInSelfOrDesc((AbstractLogicalOperator) r.getValue(), freeVars);
}
}
s.getUsedVariablesExceptNestedPlans(freeVars);
HashSet<LogicalVariable> produced2 = new HashSet<LogicalVariable>();
s.getProducedVariablesExceptNestedPlans(produced2);
freeVars.removeAll(produced);
}
for (Mutable<ILogicalOperator> i : op.getInputs()) {
getFreeVariablesInSelfOrDesc((AbstractLogicalOperator) i.getValue(), freeVars);
}
}
public static void getFreeVariablesInSubplans(AbstractOperatorWithNestedPlans op, Set<LogicalVariable> freeVars)
throws AlgebricksException {
for (ILogicalPlan p : op.getNestedPlans()) {
for (Mutable<ILogicalOperator> r : p.getRoots()) {
getFreeVariablesInSelfOrDesc((AbstractLogicalOperator) r.getValue(), freeVars);
}
}
}
public static boolean hasFreeVariablesInSelfOrDesc(AbstractLogicalOperator op) throws AlgebricksException {
HashSet<LogicalVariable> free = new HashSet<LogicalVariable>();
getFreeVariablesInSelfOrDesc(op, free);
return !free.isEmpty();
}
public static boolean hasFreeVariables(ILogicalOperator op) throws AlgebricksException {
HashSet<LogicalVariable> free = new HashSet<LogicalVariable>();
getFreeVariablesInOp(op, free);
return !free.isEmpty();
}
public static void computeSchemaAndPropertiesRecIfNull(AbstractLogicalOperator op, IOptimizationContext context)
throws AlgebricksException {
if (op.getSchema() == null) {
for (Mutable<ILogicalOperator> i : op.getInputs()) {
computeSchemaAndPropertiesRecIfNull((AbstractLogicalOperator) i.getValue(), context);
}
if (op.hasNestedPlans()) {
AbstractOperatorWithNestedPlans a = (AbstractOperatorWithNestedPlans) op;
for (ILogicalPlan p : a.getNestedPlans()) {
for (Mutable<ILogicalOperator> r : p.getRoots()) {
computeSchemaAndPropertiesRecIfNull((AbstractLogicalOperator) r.getValue(), context);
}
}
}
op.recomputeSchema();
op.computeDeliveredPhysicalProperties(context);
}
}
public static void computeSchemaRecIfNull(AbstractLogicalOperator op) throws AlgebricksException {
if (op.getSchema() == null) {
for (Mutable<ILogicalOperator> i : op.getInputs()) {
computeSchemaRecIfNull((AbstractLogicalOperator) i.getValue());
}
if (op.hasNestedPlans()) {
AbstractOperatorWithNestedPlans a = (AbstractOperatorWithNestedPlans) op;
for (ILogicalPlan p : a.getNestedPlans()) {
for (Mutable<ILogicalOperator> r : p.getRoots()) {
computeSchemaRecIfNull((AbstractLogicalOperator) r.getValue());
}
}
}
op.recomputeSchema();
}
}
public static boolean isNullTest(AbstractLogicalOperator op) {
if (op.getOperatorTag() != LogicalOperatorTag.SELECT) {
return false;
}
AbstractLogicalOperator doubleUnder = (AbstractLogicalOperator) op.getInputs().get(0).getValue();
if (doubleUnder.getOperatorTag() != LogicalOperatorTag.NESTEDTUPLESOURCE) {
return false;
}
ILogicalExpression eu = ((SelectOperator) op).getCondition().getValue();
if (eu.getExpressionTag() != LogicalExpressionTag.FUNCTION_CALL) {
return false;
}
AbstractFunctionCallExpression f1 = (AbstractFunctionCallExpression) eu;
if (!f1.getFunctionIdentifier().equals(AlgebricksBuiltinFunctions.NOT)) {
return false;
}
ILogicalExpression a1 = f1.getArguments().get(0).getValue();
if (!a1.getExpressionTag().equals(LogicalExpressionTag.FUNCTION_CALL)) {
return false;
}
AbstractFunctionCallExpression f2 = (AbstractFunctionCallExpression) a1;
if (!f2.getFunctionIdentifier().equals(AlgebricksBuiltinFunctions.IS_NULL)) {
return false;
}
return true;
}
public static void typePlan(ILogicalPlan p, IOptimizationContext context) throws AlgebricksException {
for (Mutable<ILogicalOperator> r : p.getRoots()) {
typeOpRec(r, context);
}
}
public static void typeOpRec(Mutable<ILogicalOperator> r, IOptimizationContext context) throws AlgebricksException {
AbstractLogicalOperator op = (AbstractLogicalOperator) r.getValue();
for (Mutable<ILogicalOperator> i : op.getInputs()) {
typeOpRec(i, context);
}
if (op.hasNestedPlans()) {
for (ILogicalPlan p : ((AbstractOperatorWithNestedPlans) op).getNestedPlans()) {
typePlan(p, context);
}
}
context.computeAndSetTypeEnvironmentForOperator(op);
}
public static boolean isAlwaysTrueCond(ILogicalExpression cond) {
if (cond.getExpressionTag() == LogicalExpressionTag.CONSTANT) {
return ((ConstantExpression) cond).getValue().isTrue();
}
return false;
}
}