Search in sources :

Example 1 with LogicalOperatorTag

use of org.apache.hyracks.algebricks.core.algebra.base.LogicalOperatorTag in project asterixdb by apache.

the class CopyLimitDownRule method rewritePre.

@Override
public boolean rewritePre(Mutable<ILogicalOperator> opRef, IOptimizationContext context) throws AlgebricksException {
    AbstractLogicalOperator op = (AbstractLogicalOperator) opRef.getValue();
    if (op.getOperatorTag() != LogicalOperatorTag.LIMIT) {
        return false;
    }
    LimitOperator limitOp = (LimitOperator) op;
    if (!limitOp.isTopmostLimitOp()) {
        return false;
    }
    List<LogicalVariable> limitUsedVars = new ArrayList<>();
    VariableUtilities.getUsedVariables(limitOp, limitUsedVars);
    Mutable<ILogicalOperator> safeOpRef = null;
    Mutable<ILogicalOperator> candidateOpRef = limitOp.getInputs().get(0);
    List<LogicalVariable> candidateProducedVars = new ArrayList<>();
    while (true) {
        candidateProducedVars.clear();
        ILogicalOperator candidateOp = candidateOpRef.getValue();
        LogicalOperatorTag candidateOpTag = candidateOp.getOperatorTag();
        if (candidateOp.getInputs().size() > 1 || !candidateOp.isMap() || candidateOpTag == LogicalOperatorTag.SELECT || candidateOpTag == LogicalOperatorTag.LIMIT || candidateOpTag == LogicalOperatorTag.UNNEST_MAP || !OperatorPropertiesUtil.disjoint(limitUsedVars, candidateProducedVars)) {
            break;
        }
        safeOpRef = candidateOpRef;
        candidateOpRef = safeOpRef.getValue().getInputs().get(0);
    }
    if (safeOpRef != null) {
        ILogicalOperator safeOp = safeOpRef.getValue();
        Mutable<ILogicalOperator> unsafeOpRef = safeOp.getInputs().get(0);
        ILogicalOperator unsafeOp = unsafeOpRef.getValue();
        LimitOperator limitCloneOp = null;
        if (limitOp.getOffset().getValue() == null) {
            limitCloneOp = new LimitOperator(limitOp.getMaxObjects().getValue(), false);
        } else {
            // Need to add an offset to the given limit value
            // since the original topmost limit will use the offset value.
            // We can't apply the offset multiple times.
            IFunctionInfo finfoAdd = context.getMetadataProvider().lookupFunction(AlgebricksBuiltinFunctions.NUMERIC_ADD);
            List<Mutable<ILogicalExpression>> addArgs = new ArrayList<>();
            addArgs.add(new MutableObject<ILogicalExpression>(limitOp.getMaxObjects().getValue().cloneExpression()));
            addArgs.add(new MutableObject<ILogicalExpression>(limitOp.getOffset().getValue().cloneExpression()));
            ScalarFunctionCallExpression maxPlusOffset = new ScalarFunctionCallExpression(finfoAdd, addArgs);
            limitCloneOp = new LimitOperator(maxPlusOffset, false);
        }
        limitCloneOp.setPhysicalOperator(new StreamLimitPOperator());
        limitCloneOp.getInputs().add(new MutableObject<ILogicalOperator>(unsafeOp));
        limitCloneOp.setExecutionMode(unsafeOp.getExecutionMode());
        OperatorPropertiesUtil.computeSchemaRecIfNull((AbstractLogicalOperator) unsafeOp);
        limitCloneOp.recomputeSchema();
        unsafeOpRef.setValue(limitCloneOp);
        context.computeAndSetTypeEnvironmentForOperator(limitCloneOp);
        context.addToDontApplySet(this, limitOp);
    }
    return safeOpRef != null;
}
Also used : LogicalVariable(org.apache.hyracks.algebricks.core.algebra.base.LogicalVariable) IFunctionInfo(org.apache.hyracks.algebricks.core.algebra.functions.IFunctionInfo) AbstractLogicalOperator(org.apache.hyracks.algebricks.core.algebra.operators.logical.AbstractLogicalOperator) ILogicalOperator(org.apache.hyracks.algebricks.core.algebra.base.ILogicalOperator) ArrayList(java.util.ArrayList) Mutable(org.apache.commons.lang3.mutable.Mutable) ILogicalExpression(org.apache.hyracks.algebricks.core.algebra.base.ILogicalExpression) LimitOperator(org.apache.hyracks.algebricks.core.algebra.operators.logical.LimitOperator) LogicalOperatorTag(org.apache.hyracks.algebricks.core.algebra.base.LogicalOperatorTag) StreamLimitPOperator(org.apache.hyracks.algebricks.core.algebra.operators.physical.StreamLimitPOperator) ScalarFunctionCallExpression(org.apache.hyracks.algebricks.core.algebra.expressions.ScalarFunctionCallExpression)

Example 2 with LogicalOperatorTag

use of org.apache.hyracks.algebricks.core.algebra.base.LogicalOperatorTag in project asterixdb by apache.

the class InlineLeftNtsInSubplanJoinFlatteningVisitor method visitSingleInputOperator.

private ILogicalOperator visitSingleInputOperator(ILogicalOperator op) throws AlgebricksException {
    if (op.getInputs().size() == 1) {
        // Deals with single input operators.
        Mutable<ILogicalOperator> childRef = op.getInputs().get(0);
        ILogicalOperator newChild = childRef.getValue().accept(this, null);
        LogicalOperatorTag childOpTag = newChild.getOperatorTag();
        if (childOpTag == LogicalOperatorTag.INNERJOIN || childOpTag == LogicalOperatorTag.LEFTOUTERJOIN) {
            topJoinRef = childRef;
        }
        op.getInputs().get(0).setValue(newChild);
    }
    return op;
}
Also used : LogicalOperatorTag(org.apache.hyracks.algebricks.core.algebra.base.LogicalOperatorTag) ILogicalOperator(org.apache.hyracks.algebricks.core.algebra.base.ILogicalOperator)

Example 3 with LogicalOperatorTag

use of org.apache.hyracks.algebricks.core.algebra.base.LogicalOperatorTag in project asterixdb by apache.

the class PushSelectIntoJoinRule method rewritePost.

@Override
public boolean rewritePost(Mutable<ILogicalOperator> opRef, IOptimizationContext context) throws AlgebricksException {
    Collection<LogicalVariable> joinLiveVarsLeft = new HashSet<LogicalVariable>();
    Collection<LogicalVariable> joinLiveVarsRight = new HashSet<LogicalVariable>();
    Collection<LogicalVariable> liveInOpsToPushLeft = new HashSet<LogicalVariable>();
    Collection<LogicalVariable> liveInOpsToPushRight = new HashSet<LogicalVariable>();
    List<ILogicalOperator> pushedOnLeft = new ArrayList<ILogicalOperator>();
    List<ILogicalOperator> pushedOnRight = new ArrayList<ILogicalOperator>();
    List<ILogicalOperator> pushedOnEither = new ArrayList<ILogicalOperator>();
    LinkedList<ILogicalOperator> notPushedStack = new LinkedList<ILogicalOperator>();
    Collection<LogicalVariable> usedVars = new HashSet<LogicalVariable>();
    Collection<LogicalVariable> producedVars = new HashSet<LogicalVariable>();
    AbstractLogicalOperator op = (AbstractLogicalOperator) opRef.getValue();
    if (op.getOperatorTag() != LogicalOperatorTag.SELECT) {
        return false;
    }
    SelectOperator select = (SelectOperator) op;
    Mutable<ILogicalOperator> opRef2 = op.getInputs().get(0);
    AbstractLogicalOperator son = (AbstractLogicalOperator) opRef2.getValue();
    AbstractLogicalOperator op2 = son;
    boolean needToPushOps = false;
    while (son.isMap()) {
        needToPushOps = true;
        Mutable<ILogicalOperator> opRefLink = son.getInputs().get(0);
        son = (AbstractLogicalOperator) opRefLink.getValue();
    }
    if (son.getOperatorTag() != LogicalOperatorTag.INNERJOIN && son.getOperatorTag() != LogicalOperatorTag.LEFTOUTERJOIN) {
        return false;
    }
    boolean isLoj = son.getOperatorTag() == LogicalOperatorTag.LEFTOUTERJOIN;
    AbstractBinaryJoinOperator join = (AbstractBinaryJoinOperator) son;
    Mutable<ILogicalOperator> joinBranchLeftRef = join.getInputs().get(0);
    Mutable<ILogicalOperator> joinBranchRightRef = join.getInputs().get(1);
    if (needToPushOps) {
        ILogicalOperator joinBranchLeft = joinBranchLeftRef.getValue();
        ILogicalOperator joinBranchRight = joinBranchRightRef.getValue();
        VariableUtilities.getLiveVariables(joinBranchLeft, joinLiveVarsLeft);
        VariableUtilities.getLiveVariables(joinBranchRight, joinLiveVarsRight);
        Mutable<ILogicalOperator> opIterRef = opRef2;
        ILogicalOperator opIter = op2;
        while (opIter != join) {
            LogicalOperatorTag tag = ((AbstractLogicalOperator) opIter).getOperatorTag();
            if (tag == LogicalOperatorTag.PROJECT) {
                notPushedStack.addFirst(opIter);
            } else {
                VariableUtilities.getUsedVariables(opIter, usedVars);
                VariableUtilities.getProducedVariables(opIter, producedVars);
                if (usedVars.size() == 0) {
                    pushedOnEither.add(opIter);
                } else if (joinLiveVarsLeft.containsAll(usedVars)) {
                    pushedOnLeft.add(opIter);
                    liveInOpsToPushLeft.addAll(producedVars);
                } else if (joinLiveVarsRight.containsAll(usedVars)) {
                    pushedOnRight.add(opIter);
                    liveInOpsToPushRight.addAll(producedVars);
                } else {
                    return false;
                }
            }
            opIterRef = opIter.getInputs().get(0);
            opIter = opIterRef.getValue();
        }
        if (isLoj && pushedOnLeft.isEmpty()) {
            return false;
        }
    }
    boolean intersectsAllBranches = true;
    boolean[] intersectsBranch = new boolean[join.getInputs().size()];
    LinkedList<LogicalVariable> selectVars = new LinkedList<LogicalVariable>();
    select.getCondition().getValue().getUsedVariables(selectVars);
    int i = 0;
    for (Mutable<ILogicalOperator> branch : join.getInputs()) {
        LinkedList<LogicalVariable> branchVars = new LinkedList<LogicalVariable>();
        VariableUtilities.getLiveVariables(branch.getValue(), branchVars);
        if (i == 0) {
            branchVars.addAll(liveInOpsToPushLeft);
        } else {
            branchVars.addAll(liveInOpsToPushRight);
        }
        if (OperatorPropertiesUtil.disjoint(selectVars, branchVars)) {
            intersectsAllBranches = false;
        } else {
            intersectsBranch[i] = true;
        }
        i++;
    }
    if (!intersectsBranch[0] && !intersectsBranch[1]) {
        return false;
    }
    if (needToPushOps) {
        //We should push independent ops into the first branch that the selection depends on
        if (intersectsBranch[0]) {
            pushOps(pushedOnEither, joinBranchLeftRef, context);
        } else {
            pushOps(pushedOnEither, joinBranchRightRef, context);
        }
        pushOps(pushedOnLeft, joinBranchLeftRef, context);
        pushOps(pushedOnRight, joinBranchRightRef, context);
    }
    if (intersectsAllBranches) {
        addCondToJoin(select, join, context);
    } else {
        // push down
        Iterator<Mutable<ILogicalOperator>> branchIter = join.getInputs().iterator();
        ILogicalExpression selectCondition = select.getCondition().getValue();
        boolean lojToInner = false;
        for (int j = 0; j < intersectsBranch.length; j++) {
            Mutable<ILogicalOperator> branch = branchIter.next();
            boolean inter = intersectsBranch[j];
            if (!inter) {
                continue;
            }
            // to inner join for this case.
            if (j > 0 && isLoj && containsNotMissingFiltering(selectCondition)) {
                lojToInner = true;
            }
            if ((j > 0 && isLoj) && containsMissingFiltering(selectCondition)) {
                // Select "is-not-missing($$var)" cannot be pushed in the right branch of a LOJ;
                notPushedStack.addFirst(select);
            } else {
                // Conditions for the left branch can always be pushed.
                // Other conditions can be pushed to the right branch of a LOJ.
                copySelectToBranch(select, branch, context);
            }
        }
        if (lojToInner) {
            // Rewrites left outer join  to inner join.
            InnerJoinOperator innerJoin = new InnerJoinOperator(join.getCondition());
            innerJoin.getInputs().addAll(join.getInputs());
            join = innerJoin;
            context.computeAndSetTypeEnvironmentForOperator(join);
        }
    }
    ILogicalOperator top = join;
    for (ILogicalOperator npOp : notPushedStack) {
        List<Mutable<ILogicalOperator>> npInpList = npOp.getInputs();
        npInpList.clear();
        npInpList.add(new MutableObject<ILogicalOperator>(top));
        context.computeAndSetTypeEnvironmentForOperator(npOp);
        top = npOp;
    }
    opRef.setValue(top);
    return true;
}
Also used : LogicalVariable(org.apache.hyracks.algebricks.core.algebra.base.LogicalVariable) AbstractLogicalOperator(org.apache.hyracks.algebricks.core.algebra.operators.logical.AbstractLogicalOperator) ILogicalOperator(org.apache.hyracks.algebricks.core.algebra.base.ILogicalOperator) ArrayList(java.util.ArrayList) InnerJoinOperator(org.apache.hyracks.algebricks.core.algebra.operators.logical.InnerJoinOperator) LinkedList(java.util.LinkedList) AbstractBinaryJoinOperator(org.apache.hyracks.algebricks.core.algebra.operators.logical.AbstractBinaryJoinOperator) Mutable(org.apache.commons.lang3.mutable.Mutable) ILogicalExpression(org.apache.hyracks.algebricks.core.algebra.base.ILogicalExpression) SelectOperator(org.apache.hyracks.algebricks.core.algebra.operators.logical.SelectOperator) LogicalOperatorTag(org.apache.hyracks.algebricks.core.algebra.base.LogicalOperatorTag) HashSet(java.util.HashSet)

Example 4 with LogicalOperatorTag

use of org.apache.hyracks.algebricks.core.algebra.base.LogicalOperatorTag in project asterixdb by apache.

the class RemoveUnusedOneToOneEquiJoinRule method isSelectionAboveDataScan.

private boolean isSelectionAboveDataScan(Mutable<ILogicalOperator> opRef) {
    boolean hasSelection = false;
    AbstractLogicalOperator op = (AbstractLogicalOperator) opRef.getValue();
    LogicalOperatorTag tag = op.getOperatorTag();
    switch(tag) {
        case DATASOURCESCAN:
            return false;
        case UNNEST_MAP:
        case LEFT_OUTER_UNNEST_MAP:
        case LIMIT:
        case SELECT:
            return true;
        default:
            for (Mutable<ILogicalOperator> inputOp : op.getInputs()) {
                hasSelection |= isSelectionAboveDataScan(inputOp);
            }
    }
    return hasSelection;
}
Also used : AbstractLogicalOperator(org.apache.hyracks.algebricks.core.algebra.operators.logical.AbstractLogicalOperator) LogicalOperatorTag(org.apache.hyracks.algebricks.core.algebra.base.LogicalOperatorTag) ILogicalOperator(org.apache.hyracks.algebricks.core.algebra.base.ILogicalOperator)

Example 5 with LogicalOperatorTag

use of org.apache.hyracks.algebricks.core.algebra.base.LogicalOperatorTag in project asterixdb by apache.

the class PushProperJoinThroughProduct method rewritePost.

@Override
public boolean rewritePost(Mutable<ILogicalOperator> opRef, IOptimizationContext context) throws AlgebricksException {
    AbstractLogicalOperator op = (AbstractLogicalOperator) opRef.getValue();
    LogicalOperatorTag tag1 = op.getOperatorTag();
    if (tag1 != LogicalOperatorTag.INNERJOIN && tag1 != LogicalOperatorTag.LEFTOUTERJOIN) {
        return false;
    }
    AbstractBinaryJoinOperator join1 = (AbstractBinaryJoinOperator) op;
    ILogicalExpression cond1 = join1.getCondition().getValue();
    // don't try to push a product down
    if (OperatorPropertiesUtil.isAlwaysTrueCond(cond1)) {
        return false;
    }
    Mutable<ILogicalOperator> opRef2 = op.getInputs().get(0);
    AbstractLogicalOperator op2 = (AbstractLogicalOperator) opRef2.getValue();
    while (op2.isMap()) {
        opRef2 = op2.getInputs().get(0);
        op2 = (AbstractLogicalOperator) opRef2.getValue();
    }
    if (op2.getOperatorTag() != LogicalOperatorTag.INNERJOIN) {
        return false;
    }
    InnerJoinOperator product = (InnerJoinOperator) op2;
    if (!OperatorPropertiesUtil.isAlwaysTrueCond(product.getCondition().getValue())) {
        return false;
    }
    usedInCond1AndMaps.clear();
    cond1.getUsedVariables(usedInCond1AndMaps);
    Mutable<ILogicalOperator> opIterRef = op.getInputs().get(0);
    ILogicalOperator opIter = opIterRef.getValue();
    do {
        VariableUtilities.getUsedVariables(opIter, usedInCond1AndMaps);
        opIterRef = opIter.getInputs().get(0);
        opIter = opIterRef.getValue();
    } while (opIter.isMap());
    productLeftBranchVars.clear();
    ILogicalOperator opLeft = op2.getInputs().get(0).getValue();
    VariableUtilities.getLiveVariables(opLeft, productLeftBranchVars);
    if (!OperatorPropertiesUtil.disjoint(usedInCond1AndMaps, productLeftBranchVars)) {
        return false;
    }
    // now push the operators from in between joins, too
    opIterRef = op.getInputs().get(0);
    opIter = opIterRef.getValue();
    Mutable<ILogicalOperator> op3Ref = product.getInputs().get(1);
    ILogicalOperator op3 = op3Ref.getValue();
    opRef2.setValue(op3);
    op3Ref.setValue(join1);
    opRef.setValue(product);
    return true;
}
Also used : ILogicalExpression(org.apache.hyracks.algebricks.core.algebra.base.ILogicalExpression) AbstractLogicalOperator(org.apache.hyracks.algebricks.core.algebra.operators.logical.AbstractLogicalOperator) LogicalOperatorTag(org.apache.hyracks.algebricks.core.algebra.base.LogicalOperatorTag) ILogicalOperator(org.apache.hyracks.algebricks.core.algebra.base.ILogicalOperator) InnerJoinOperator(org.apache.hyracks.algebricks.core.algebra.operators.logical.InnerJoinOperator) AbstractBinaryJoinOperator(org.apache.hyracks.algebricks.core.algebra.operators.logical.AbstractBinaryJoinOperator)

Aggregations

ILogicalOperator (org.apache.hyracks.algebricks.core.algebra.base.ILogicalOperator)9 LogicalOperatorTag (org.apache.hyracks.algebricks.core.algebra.base.LogicalOperatorTag)9 AbstractLogicalOperator (org.apache.hyracks.algebricks.core.algebra.operators.logical.AbstractLogicalOperator)6 ILogicalExpression (org.apache.hyracks.algebricks.core.algebra.base.ILogicalExpression)4 LogicalVariable (org.apache.hyracks.algebricks.core.algebra.base.LogicalVariable)4 ArrayList (java.util.ArrayList)2 HashSet (java.util.HashSet)2 Mutable (org.apache.commons.lang3.mutable.Mutable)2 AbstractBinaryJoinOperator (org.apache.hyracks.algebricks.core.algebra.operators.logical.AbstractBinaryJoinOperator)2 InnerJoinOperator (org.apache.hyracks.algebricks.core.algebra.operators.logical.InnerJoinOperator)2 LinkedList (java.util.LinkedList)1 ILogicalPlan (org.apache.hyracks.algebricks.core.algebra.base.ILogicalPlan)1 ScalarFunctionCallExpression (org.apache.hyracks.algebricks.core.algebra.expressions.ScalarFunctionCallExpression)1 VariableReferenceExpression (org.apache.hyracks.algebricks.core.algebra.expressions.VariableReferenceExpression)1 IFunctionInfo (org.apache.hyracks.algebricks.core.algebra.functions.IFunctionInfo)1 AbstractOperatorWithNestedPlans (org.apache.hyracks.algebricks.core.algebra.operators.logical.AbstractOperatorWithNestedPlans)1 AssignOperator (org.apache.hyracks.algebricks.core.algebra.operators.logical.AssignOperator)1 LimitOperator (org.apache.hyracks.algebricks.core.algebra.operators.logical.LimitOperator)1 ProjectOperator (org.apache.hyracks.algebricks.core.algebra.operators.logical.ProjectOperator)1 SelectOperator (org.apache.hyracks.algebricks.core.algebra.operators.logical.SelectOperator)1