Example usage for org.apache.commons.lang3.mutable Mutable getValue

List of usage examples for org.apache.commons.lang3.mutable Mutable getValue

Introduction

In this page you can find the example usage for org.apache.commons.lang3.mutable Mutable getValue.

Prototype

T getValue();

Source Link

Document

Gets the value of this mutable.

Usage

From source file:edu.uci.ics.asterix.optimizer.rules.PushProperJoinThroughProduct.java

@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;
    }//from   w  ww.  ja  va2  s  .  c o m
    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;
}

From source file:edu.uci.ics.hyracks.algebricks.rewriter.rules.CopyLimitDownRule.java

@Override
public boolean rewritePre(Mutable<ILogicalOperator> opRef, IOptimizationContext context)
        throws AlgebricksException {
    AbstractLogicalOperator op = (AbstractLogicalOperator) opRef.getValue();
    if (op.getOperatorTag() != LogicalOperatorTag.LIMIT) {
        return false;
    }/*from w ww.  ja v a  2 s.  com*/
    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
                || !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 {
            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());
        limitCloneOp.recomputeSchema();
        unsafeOpRef.setValue(limitCloneOp);
        context.computeAndSetTypeEnvironmentForOperator(limitCloneOp);
        context.addToDontApplySet(this, limitOp);
    }

    return safeOpRef != null;
}

From source file:edu.uci.ics.asterix.optimizer.rules.RemoveUnusedOneToOneEquiJoinRule.java

private boolean isEquiJoin(Mutable<ILogicalExpression> conditionExpr) {
    AbstractLogicalExpression expr = (AbstractLogicalExpression) conditionExpr.getValue();
    if (expr.getExpressionTag() == LogicalExpressionTag.FUNCTION_CALL) {
        AbstractFunctionCallExpression funcExpr = (AbstractFunctionCallExpression) expr;
        FunctionIdentifier funcIdent = funcExpr.getFunctionIdentifier();
        if (funcIdent != AlgebricksBuiltinFunctions.AND && funcIdent != AlgebricksBuiltinFunctions.EQ) {
            return false;
        }//from  w w w .j  a v  a 2s.  c  o  m
    }
    return true;
}

From source file:edu.uci.ics.hyracks.algebricks.rewriter.rules.ConsolidateSelectsRule.java

@Override
public boolean rewritePre(Mutable<ILogicalOperator> opRef, IOptimizationContext context)
        throws AlgebricksException {
    AbstractLogicalOperator op = (AbstractLogicalOperator) opRef.getValue();
    if (op.getOperatorTag() != LogicalOperatorTag.SELECT) {
        return false;
    }/*www .j a va  2s.  co  m*/
    SelectOperator firstSelect = (SelectOperator) op;

    IFunctionInfo andFn = context.getMetadataProvider().lookupFunction(AlgebricksBuiltinFunctions.AND);
    // New conjuncts for consolidated select.
    AbstractFunctionCallExpression conj = null;
    AbstractLogicalOperator topMostOp = null;
    AbstractLogicalOperator selectParent = null;
    AbstractLogicalOperator nextSelect = firstSelect;
    do {
        // Skip through assigns.
        do {
            selectParent = nextSelect;
            nextSelect = (AbstractLogicalOperator) selectParent.getInputs().get(0).getValue();
        } while (nextSelect.getOperatorTag() == LogicalOperatorTag.ASSIGN);
        // Stop if the child op is not a select.
        if (nextSelect.getOperatorTag() != LogicalOperatorTag.SELECT) {
            break;
        }
        // Remember the top-most op that we are not removing.
        topMostOp = selectParent;

        // Initialize the new conjuncts, if necessary.
        if (conj == null) {
            conj = new ScalarFunctionCallExpression(andFn);
            // Add the first select's condition.
            conj.getArguments()
                    .add(new MutableObject<ILogicalExpression>(firstSelect.getCondition().getValue()));
        }

        // Consolidate all following selects.
        do {
            // Add the condition nextSelect to the new list of conjuncts.
            conj.getArguments().add(((SelectOperator) nextSelect).getCondition());
            selectParent = nextSelect;
            nextSelect = (AbstractLogicalOperator) nextSelect.getInputs().get(0).getValue();
        } while (nextSelect.getOperatorTag() == LogicalOperatorTag.SELECT);

        // Hook up the input of the top-most remaining op if necessary.
        if (topMostOp.getOperatorTag() == LogicalOperatorTag.ASSIGN || topMostOp == firstSelect) {
            topMostOp.getInputs().set(0, selectParent.getInputs().get(0));
        }

        // Prepare for next iteration.
        nextSelect = selectParent;
    } while (true);

    // Did we consolidate any selects?
    if (conj == null) {
        return false;
    }

    // Set the new conjuncts.
    firstSelect.getCondition().setValue(conj);
    context.computeAndSetTypeEnvironmentForOperator(firstSelect);
    return true;
}

From source file:edu.uci.ics.hyracks.algebricks.rewriter.rules.PushFunctionsBelowJoin.java

private boolean pushDownFunctions(AbstractBinaryJoinOperator joinOp, int inputIndex,
        List<Mutable<ILogicalExpression>> funcExprs, IOptimizationContext context) throws AlgebricksException {
    ILogicalOperator joinInputOp = joinOp.getInputs().get(inputIndex).getValue();
    liveVars.clear();/*from  ww w .  j  av a2 s .  c  o m*/
    VariableUtilities.getLiveVariables(joinInputOp, liveVars);
    Iterator<Mutable<ILogicalExpression>> funcIter = funcExprs.iterator();
    List<LogicalVariable> assignVars = null;
    List<Mutable<ILogicalExpression>> assignExprs = null;
    while (funcIter.hasNext()) {
        Mutable<ILogicalExpression> funcExprRef = funcIter.next();
        ILogicalExpression funcExpr = funcExprRef.getValue();
        usedVars.clear();
        funcExpr.getUsedVariables(usedVars);
        // Check if we can push the function down this branch.
        if (liveVars.containsAll(usedVars)) {
            if (assignVars == null) {
                assignVars = new ArrayList<LogicalVariable>();
                assignExprs = new ArrayList<Mutable<ILogicalExpression>>();
            }
            // Replace the original expression with a variable reference expression.
            LogicalVariable replacementVar = context.newVar();
            assignVars.add(replacementVar);
            assignExprs.add(new MutableObject<ILogicalExpression>(funcExpr));
            funcExprRef.setValue(new VariableReferenceExpression(replacementVar));
            funcIter.remove();
        }
    }
    // Create new assign operator below the join if any functions can be pushed.
    if (assignVars != null) {
        AssignOperator newAssign = new AssignOperator(assignVars, assignExprs);
        newAssign.getInputs().add(new MutableObject<ILogicalOperator>(joinInputOp));
        newAssign.setExecutionMode(joinOp.getExecutionMode());
        joinOp.getInputs().get(inputIndex).setValue(newAssign);
        context.computeAndSetTypeEnvironmentForOperator(newAssign);
        return true;
    }
    return false;
}

From source file:edu.uci.ics.hyracks.algebricks.rewriter.rules.PushNestedOrderByUnderPreSortedGroupByRule.java

@Override
public boolean rewritePost(Mutable<ILogicalOperator> opRef, IOptimizationContext context)
        throws AlgebricksException {
    AbstractLogicalOperator op = (AbstractLogicalOperator) opRef.getValue();
    if (op.getOperatorTag() != LogicalOperatorTag.GROUP) {
        return false;
    }/*from   ww w  . ja  v a  2s. c o m*/
    if (op.getPhysicalOperator() == null) {
        return false;
    }
    AbstractPhysicalOperator pOp = (AbstractPhysicalOperator) op.getPhysicalOperator();
    if (pOp.getOperatorTag() != PhysicalOperatorTag.PRE_CLUSTERED_GROUP_BY) {
        return false;
    }
    GroupByOperator gby = (GroupByOperator) op;
    ILogicalPlan plan = gby.getNestedPlans().get(0);
    AbstractLogicalOperator op1 = (AbstractLogicalOperator) plan.getRoots().get(0).getValue();
    if (op1.getOperatorTag() != LogicalOperatorTag.AGGREGATE) {
        return false;
    }
    Mutable<ILogicalOperator> opRef2 = op1.getInputs().get(0);
    AbstractLogicalOperator op2 = (AbstractLogicalOperator) opRef2.getValue();
    if (op2.getOperatorTag() != LogicalOperatorTag.ORDER) {
        return false;
    }
    OrderOperator order1 = (OrderOperator) op2;
    if (!isIndependentFromChildren(order1)) {
        return false;
    }
    AbstractPhysicalOperator pOrder1 = (AbstractPhysicalOperator) op2.getPhysicalOperator();
    if (pOrder1.getOperatorTag() != PhysicalOperatorTag.STABLE_SORT
            && pOrder1.getOperatorTag() != PhysicalOperatorTag.IN_MEMORY_STABLE_SORT) {
        return false;
    }
    // StableSortPOperator sort1 = (StableSortPOperator) pOrder1;
    AbstractLogicalOperator op3 = (AbstractLogicalOperator) op.getInputs().get(0).getValue();
    if (op3.getOperatorTag() != LogicalOperatorTag.ORDER) {
        return false;
    }
    AbstractPhysicalOperator pOp3 = (AbstractPhysicalOperator) op3.getPhysicalOperator();
    if (pOp3.getOperatorTag() != PhysicalOperatorTag.STABLE_SORT) {
        return false;
    }
    OrderOperator order2 = (OrderOperator) op3;
    StableSortPOperator sort2 = (StableSortPOperator) pOp3;
    // int n1 = sort1.getSortColumns().length;
    // int n2 = sort2.getSortColumns().length;
    // OrderColumn[] sortColumns = new OrderColumn[n2 + n1];
    // System.arraycopy(sort2.getSortColumns(), 0, sortColumns, 0, n2);
    // int k = 0;
    for (Pair<IOrder, Mutable<ILogicalExpression>> oe : order1.getOrderExpressions()) {
        order2.getOrderExpressions().add(oe);
        // sortColumns[n2 + k] = sort1.getSortColumns()[k];
        // ++k;
    }
    // sort2.setSortColumns(sortColumns);
    sort2.computeDeliveredProperties(order2, null);
    // remove order1
    ILogicalOperator underOrder1 = order1.getInputs().get(0).getValue();
    opRef2.setValue(underOrder1);
    return true;
}

From source file:edu.uci.ics.hyracks.algebricks.core.jobgen.impl.PlanCompiler.java

private void compileOpRef(Mutable<ILogicalOperator> opRef, IOperatorDescriptorRegistry spec,
        IHyracksJobBuilder builder, IOperatorSchema outerPlanSchema) throws AlgebricksException {
    ILogicalOperator op = opRef.getValue();
    int n = op.getInputs().size();
    IOperatorSchema[] schemas = new IOperatorSchema[n];
    int i = 0;/*from   w ww .  j av a  2  s .c o m*/
    for (Mutable<ILogicalOperator> opRef2 : op.getInputs()) {
        List<Mutable<ILogicalOperator>> parents = operatorVisitedToParents.get(opRef2);
        if (parents == null) {
            parents = new ArrayList<Mutable<ILogicalOperator>>();
            operatorVisitedToParents.put(opRef2, parents);
            parents.add(opRef);
            compileOpRef(opRef2, spec, builder, outerPlanSchema);
            schemas[i++] = context.getSchema(opRef2.getValue());
        } else {
            if (!parents.contains(opRef))
                parents.add(opRef);
            schemas[i++] = context.getSchema(opRef2.getValue());
            continue;
        }
    }

    IOperatorSchema opSchema = new OperatorSchemaImpl();
    context.putSchema(op, opSchema);
    op.getVariablePropagationPolicy().propagateVariables(opSchema, schemas);
    op.contributeRuntimeOperator(builder, context, opSchema, schemas, outerPlanSchema);
}

From source file:edu.uci.ics.asterix.optimizer.rules.ReplaceSinkOpWithCommitOpRule.java

@Override
public boolean rewritePost(Mutable<ILogicalOperator> opRef, IOptimizationContext context)
        throws AlgebricksException {

    AbstractLogicalOperator op = (AbstractLogicalOperator) opRef.getValue();
    if (op.getOperatorTag() != LogicalOperatorTag.SINK) {
        return false;
    }/*from w w w.j av  a2s .  co m*/
    SinkOperator sinkOperator = (SinkOperator) op;

    List<Mutable<ILogicalExpression>> primaryKeyExprs = null;
    int datasetId = 0;
    AbstractLogicalOperator descendantOp = (AbstractLogicalOperator) sinkOperator.getInputs().get(0).getValue();
    while (descendantOp != null) {
        if (descendantOp.getOperatorTag() == LogicalOperatorTag.INDEX_INSERT_DELETE) {
            IndexInsertDeleteOperator indexInsertDeleteOperator = (IndexInsertDeleteOperator) descendantOp;
            if (!indexInsertDeleteOperator.isBulkload()) {
                primaryKeyExprs = indexInsertDeleteOperator.getPrimaryKeyExpressions();
                datasetId = ((DatasetDataSource) indexInsertDeleteOperator.getDataSourceIndex().getDataSource())
                        .getDataset().getDatasetId();
                break;
            }
        } else if (descendantOp.getOperatorTag() == LogicalOperatorTag.INSERT_DELETE) {
            InsertDeleteOperator insertDeleteOperator = (InsertDeleteOperator) descendantOp;
            if (!insertDeleteOperator.isBulkload()) {
                primaryKeyExprs = insertDeleteOperator.getPrimaryKeyExpressions();
                datasetId = ((DatasetDataSource) insertDeleteOperator.getDataSource()).getDataset()
                        .getDatasetId();
                break;
            }
        }
        if (descendantOp.getInputs().size() < 1) {
            break;
        }
        descendantOp = (AbstractLogicalOperator) descendantOp.getInputs().get(0).getValue();
    }

    if (primaryKeyExprs == null) {
        return false;
    }

    //copy primaryKeyExprs
    List<LogicalVariable> primaryKeyLogicalVars = new ArrayList<LogicalVariable>();
    for (Mutable<ILogicalExpression> expr : primaryKeyExprs) {
        VariableReferenceExpression varRefExpr = (VariableReferenceExpression) expr.getValue();
        primaryKeyLogicalVars.add(new LogicalVariable(varRefExpr.getVariableReference().getId()));
    }

    //get JobId(TransactorId)
    AqlMetadataProvider mp = (AqlMetadataProvider) context.getMetadataProvider();
    JobId jobId = mp.getJobId();

    //create the logical and physical operator
    CommitOperator commitOperator = new CommitOperator(primaryKeyLogicalVars);
    CommitPOperator commitPOperator = new CommitPOperator(jobId, datasetId, primaryKeyLogicalVars);
    commitOperator.setPhysicalOperator(commitPOperator);

    //create ExtensionOperator and put the commitOperator in it.
    ExtensionOperator extensionOperator = new ExtensionOperator(commitOperator);
    extensionOperator.setPhysicalOperator(commitPOperator);

    //update plan link
    extensionOperator.getInputs().add(sinkOperator.getInputs().get(0));
    context.computeAndSetTypeEnvironmentForOperator(extensionOperator);
    opRef.setValue(extensionOperator);
    return true;
}

From source file:edu.uci.ics.asterix.optimizer.rules.IntroduceInstantLockSearchCallbackRule.java

@Override
public boolean rewritePost(Mutable<ILogicalOperator> opRef, IOptimizationContext context)
        throws AlgebricksException {

    AbstractLogicalOperator op = (AbstractLogicalOperator) opRef.getValue();

    if (!checkIfRuleIsApplicable(op)) {
        return false;
    }//from  ww  w. ja  v  a 2  s .  c  o  m
    Map<String, Triple<Integer, LogicalOperatorTag, IPhysicalOperator>> dataSourcesMap = new HashMap<String, Triple<Integer, LogicalOperatorTag, IPhysicalOperator>>();
    extractDataSourcesInfo(op, dataSourcesMap);

    boolean introducedInstantLock = false;

    Iterator<Map.Entry<String, Triple<Integer, LogicalOperatorTag, IPhysicalOperator>>> it = dataSourcesMap
            .entrySet().iterator();
    while (it.hasNext()) {
        Entry<String, Triple<Integer, LogicalOperatorTag, IPhysicalOperator>> entry = it.next();
        Triple<Integer, LogicalOperatorTag, IPhysicalOperator> triple = entry.getValue();
        if (triple.first == 1) {
            AqlMetadataImplConfig aqlMetadataImplConfig = new AqlMetadataImplConfig(true);
            if (triple.second == LogicalOperatorTag.UNNEST_MAP) {
                BTreeSearchPOperator pOperator = (BTreeSearchPOperator) triple.third;
                pOperator.setImplConfig(aqlMetadataImplConfig);
                introducedInstantLock = true;
            } else {
                DataSourceScanPOperator pOperator = (DataSourceScanPOperator) triple.third;
                pOperator.setImplConfig(aqlMetadataImplConfig);
                introducedInstantLock = true;
            }
        }

    }
    return introducedInstantLock;
}

From source file:edu.uci.ics.hyracks.algebricks.rewriter.rules.PushGroupByIntoSortRule.java

@Override
public boolean rewritePost(Mutable<ILogicalOperator> opRef, IOptimizationContext context)
        throws AlgebricksException {
    ILogicalOperator op1 = opRef.getValue();
    if (op1 == null) {
        return false;
    }//www.  j a  v a 2  s  .c o m
    boolean changed = false;
    for (Mutable<ILogicalOperator> childRef : op1.getInputs()) {
        AbstractLogicalOperator op = (AbstractLogicalOperator) childRef.getValue();
        if (op.getOperatorTag() == LogicalOperatorTag.GROUP) {
            PhysicalOperatorTag opTag = op.getPhysicalOperator().getOperatorTag();
            GroupByOperator groupByOperator = (GroupByOperator) op;
            if (opTag == PhysicalOperatorTag.PRE_CLUSTERED_GROUP_BY) {
                Mutable<ILogicalOperator> op2Ref = op.getInputs().get(0).getValue().getInputs().get(0);
                AbstractLogicalOperator op2 = (AbstractLogicalOperator) op2Ref.getValue();
                if (op2.getPhysicalOperator().getOperatorTag() == PhysicalOperatorTag.STABLE_SORT) {
                    AbstractStableSortPOperator sortPhysicalOperator = (AbstractStableSortPOperator) op2
                            .getPhysicalOperator();
                    if (groupByOperator.getNestedPlans().size() != 1) {
                        //Sort group-by currently works only for one nested plan with one root containing
                        //an aggregate and a nested-tuple-source.
                        continue;
                    }
                    ILogicalPlan p0 = groupByOperator.getNestedPlans().get(0);
                    if (p0.getRoots().size() != 1) {
                        //Sort group-by currently works only for one nested plan with one root containing
                        //an aggregate and a nested-tuple-source.
                        continue;
                    }

                    Mutable<ILogicalOperator> r0 = p0.getRoots().get(0);
                    AbstractLogicalOperator r0Logical = (AbstractLogicalOperator) r0.getValue();
                    if (r0Logical.getOperatorTag() != LogicalOperatorTag.AGGREGATE) {
                        //we only rewrite aggregation function; do nothing for running aggregates
                        continue;
                    }
                    AggregateOperator aggOp = (AggregateOperator) r0.getValue();
                    AbstractLogicalOperator aggInputOp = (AbstractLogicalOperator) aggOp.getInputs().get(0)
                            .getValue();
                    if (aggInputOp.getOperatorTag() != LogicalOperatorTag.NESTEDTUPLESOURCE) {
                        continue;
                    }

                    boolean hasIntermediateAggregate = generateMergeAggregationExpressions(groupByOperator,
                            context);
                    if (!hasIntermediateAggregate) {
                        continue;
                    }

                    //replace preclustered gby with sort gby
                    op.setPhysicalOperator(new SortGroupByPOperator(groupByOperator.getGroupByList(),
                            context.getPhysicalOptimizationConfig().getMaxFramesExternalGroupBy(),
                            sortPhysicalOperator.getSortColumns()));

                    // remove the stable sort operator
                    op.getInputs().clear();
                    op.getInputs().addAll(op2.getInputs());
                    changed = true;
                }
            }
            continue;
        } else {
            continue;
        }
    }
    return changed;
}