List of usage examples for org.apache.commons.lang3.mutable MutableObject MutableObject
public MutableObject(final T value)
From source file:org.apache.asterix.optimizer.rules.ResolveVariableRule.java
private boolean resolveInternal(Mutable<ILogicalExpression> funcRef, boolean hasMatchedDataset, Collection<Pair<ILogicalExpression, List<String>>> varAccessCandidates, String unresolvedVarName, Triple<Boolean, String, String> fullyQualifiedDatasetPathCandidateFromParent, Mutable<ILogicalExpression> parentFuncRef, IOptimizationContext context) throws AlgebricksException { AbstractFunctionCallExpression func = (AbstractFunctionCallExpression) funcRef.getValue(); int numVarCandidates = varAccessCandidates.size(); boolean hasAmbiguity = hasAmbiguity(hasMatchedDataset, fullyQualifiedDatasetPathCandidateFromParent, numVarCandidates);/*from w w w . ja v a2s . co m*/ if (hasAmbiguity) { // More than one possibilities. throw new AlgebricksException( "Cannot resolve ambiguous alias reference for undefined identifier " + unresolvedVarName); } else if (hasMatchedDataset) { // Rewrites the "resolve" function to a "dataset" function and only keep the dataset name argument. func.setFunctionInfo(FunctionUtil.getFunctionInfo(AsterixBuiltinFunctions.DATASET)); Mutable<ILogicalExpression> datasetNameExpression = func.getArguments().get(0); func.getArguments().clear(); func.getArguments().add(datasetNameExpression); } else if (fullyQualifiedDatasetPathCandidateFromParent.first) { // Rewrites the parent "field-access" function to a "dataset" function. AbstractFunctionCallExpression parentFunc = (AbstractFunctionCallExpression) parentFuncRef.getValue(); parentFunc.setFunctionInfo(FunctionUtil.getFunctionInfo(AsterixBuiltinFunctions.DATASET)); parentFunc.getArguments().clear(); parentFunc.getArguments() .add(new MutableObject<>(new ConstantExpression( new AsterixConstantValue(new AString(fullyQualifiedDatasetPathCandidateFromParent.second + "." + fullyQualifiedDatasetPathCandidateFromParent.third))))); } else if (numVarCandidates == 1) { resolveAsFieldAccess(funcRef, varAccessCandidates.iterator().next()); } else { AqlMetadataProvider metadataProvider = (AqlMetadataProvider) context.getMetadataProvider(); // Cannot find any resolution. throw new AlgebricksException("Cannot find dataset " + unresolvedVarName + " in dataverse " + metadataProvider.getDefaultDataverseName() + " nor an alias with name " + unresolvedVarName); } return true; }
From source file:org.apache.asterix.optimizer.rules.ResolveVariableRule.java
private void resolveAsFieldAccess(Mutable<ILogicalExpression> funcRef, Pair<ILogicalExpression, List<String>> varAndPath) { // Rewrites to field-access-by-names. ILogicalExpression expr = varAndPath.first; List<String> path = varAndPath.second; Mutable<ILogicalExpression> firstArgRef = new MutableObject<>(expr); ILogicalExpression newFunc = null;// ww w . j av a 2s .co m for (String fieldName : path) { List<Mutable<ILogicalExpression>> args = new ArrayList<>(); args.add(firstArgRef); args.add(new MutableObject<>(new ConstantExpression(new AsterixConstantValue(new AString(fieldName))))); newFunc = new ScalarFunctionCallExpression( FunctionUtil.getFunctionInfo(AsterixBuiltinFunctions.FIELD_ACCESS_BY_NAME), args); firstArgRef = new MutableObject<>(newFunc); } funcRef.setValue(newFunc); }
From source file:org.apache.asterix.optimizer.rules.SetupCommitExtensionOpRule.java
@Override public boolean rewritePost(Mutable<ILogicalOperator> opRef, IOptimizationContext context) throws AlgebricksException { AbstractLogicalOperator op = (AbstractLogicalOperator) opRef.getValue(); if (op.getOperatorTag() != LogicalOperatorTag.DELEGATE_OPERATOR) { return false; }/*from w w w .jav a 2s . c om*/ DelegateOperator eOp = (DelegateOperator) op; if (!(eOp.getDelegate() instanceof CommitOperator)) { return false; } boolean isSink = ((CommitOperator) eOp.getDelegate()).isSink(); List<Mutable<ILogicalExpression>> primaryKeyExprs = null; int datasetId = 0; String dataverse = null; String datasetName = null; AbstractLogicalOperator descendantOp = (AbstractLogicalOperator) eOp.getInputs().get(0).getValue(); LogicalVariable upsertVar = null; while (descendantOp != null) { if (descendantOp.getOperatorTag() == LogicalOperatorTag.INDEX_INSERT_DELETE_UPSERT) { IndexInsertDeleteUpsertOperator operator = (IndexInsertDeleteUpsertOperator) descendantOp; if (!operator.isBulkload() && operator.getPrevSecondaryKeyExprs() == null) { primaryKeyExprs = operator.getPrimaryKeyExpressions(); datasetId = ((DatasetDataSource) operator.getDataSourceIndex().getDataSource()).getDataset() .getDatasetId(); dataverse = ((DatasetDataSource) operator.getDataSourceIndex().getDataSource()).getDataset() .getDataverseName(); datasetName = ((DatasetDataSource) operator.getDataSourceIndex().getDataSource()).getDataset() .getDatasetName(); break; } } else if (descendantOp.getOperatorTag() == LogicalOperatorTag.INSERT_DELETE_UPSERT) { InsertDeleteUpsertOperator insertDeleteUpsertOperator = (InsertDeleteUpsertOperator) descendantOp; if (!insertDeleteUpsertOperator.isBulkload()) { primaryKeyExprs = insertDeleteUpsertOperator.getPrimaryKeyExpressions(); datasetId = ((DatasetDataSource) insertDeleteUpsertOperator.getDataSource()).getDataset() .getDatasetId(); dataverse = ((DatasetDataSource) insertDeleteUpsertOperator.getDataSource()).getDataset() .getDataverseName(); datasetName = ((DatasetDataSource) insertDeleteUpsertOperator.getDataSource()).getDataset() .getDatasetName(); if (insertDeleteUpsertOperator.getOperation() == Kind.UPSERT) { //we need to add a function that checks if previous record was found upsertVar = context.newVar(); AbstractFunctionCallExpression orFunc = new ScalarFunctionCallExpression( FunctionUtil.getFunctionInfo(AsterixBuiltinFunctions.OR)); // is new value missing? -> this means that the expected operation is delete AbstractFunctionCallExpression isNewMissingFunc = new ScalarFunctionCallExpression( FunctionUtil.getFunctionInfo(AsterixBuiltinFunctions.IS_MISSING)); isNewMissingFunc.getArguments().add(insertDeleteUpsertOperator.getPayloadExpression()); AbstractFunctionCallExpression isPrevMissingFunc = new ScalarFunctionCallExpression( FunctionUtil.getFunctionInfo(AsterixBuiltinFunctions.IS_MISSING)); // argument is the previous record isPrevMissingFunc.getArguments() .add(new MutableObject<ILogicalExpression>(new VariableReferenceExpression( insertDeleteUpsertOperator.getBeforeOpRecordVar()))); orFunc.getArguments().add(new MutableObject<ILogicalExpression>(isPrevMissingFunc)); orFunc.getArguments().add(new MutableObject<ILogicalExpression>(isNewMissingFunc)); // AssignOperator puts in the cast var the casted record AssignOperator upsertFlagAssign = new AssignOperator(upsertVar, new MutableObject<ILogicalExpression>(orFunc)); // Connect the current top of the plan to the cast operator upsertFlagAssign.getInputs() .add(new MutableObject<ILogicalOperator>(eOp.getInputs().get(0).getValue())); eOp.getInputs().clear(); eOp.getInputs().add(new MutableObject<ILogicalOperator>(upsertFlagAssign)); context.computeAndSetTypeEnvironmentForOperator(upsertFlagAssign); } break; } } if (descendantOp.getInputs().isEmpty()) { break; } descendantOp = (AbstractLogicalOperator) descendantOp.getInputs().get(0).getValue(); } if (primaryKeyExprs == null) { return false; } //copy primaryKeyExprs List<LogicalVariable> primaryKeyLogicalVars = new ArrayList<>(); 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, upsertVar, isSink); CommitPOperator commitPOperator = new CommitPOperator(jobId, dataverse, datasetName, datasetId, primaryKeyLogicalVars, upsertVar, isSink); commitOperator.setPhysicalOperator(commitPOperator); //create ExtensionOperator and put the commitOperator in it. DelegateOperator extensionOperator = new DelegateOperator(commitOperator); extensionOperator.setPhysicalOperator(commitPOperator); //update plan link extensionOperator.getInputs().add(eOp.getInputs().get(0)); context.computeAndSetTypeEnvironmentForOperator(extensionOperator); opRef.setValue(extensionOperator); return true; }
From source file:org.apache.asterix.optimizer.rules.SimilarityCheckRule.java
private boolean replaceWithVariableArg(Mutable<ILogicalExpression> expRef, FunctionIdentifier normFuncIdent, AsterixConstantValue constVal, VariableReferenceExpression varRefExpr, List<AssignOperator> assigns, IOptimizationContext context) throws AlgebricksException { // Find variable in assigns to determine its originating function. LogicalVariable var = varRefExpr.getVariableReference(); Mutable<ILogicalExpression> simFuncExprRef = null; ScalarFunctionCallExpression simCheckFuncExpr = null; AssignOperator matchingAssign = null; for (int i = 0; i < assigns.size(); i++) { AssignOperator assign = assigns.get(i); for (int j = 0; j < assign.getVariables().size(); j++) { // Check if variables match. if (var != assign.getVariables().get(j)) { continue; }//from w w w .j av a2 s . c om // Check if corresponding expr is a function call. if (assign.getExpressions().get(j).getValue() .getExpressionTag() != LogicalExpressionTag.FUNCTION_CALL) { continue; } simFuncExprRef = assign.getExpressions().get(j); // Analyze function expression and get equivalent similarity check function. simCheckFuncExpr = getSimilarityCheckExpr(normFuncIdent, constVal, (AbstractFunctionCallExpression) simFuncExprRef.getValue()); matchingAssign = assign; break; } if (simCheckFuncExpr != null) { break; } } // Only non-null if we found that varRefExpr refers to an optimizable similarity function call. if (simCheckFuncExpr != null) { // Create a new assign under matchingAssign which assigns the result of our similarity-check function to a variable. LogicalVariable newVar = context.newVar(); AssignOperator newAssign = new AssignOperator(newVar, new MutableObject<ILogicalExpression>(simCheckFuncExpr)); // Hook up inputs. newAssign.getInputs() .add(new MutableObject<ILogicalOperator>(matchingAssign.getInputs().get(0).getValue())); matchingAssign.getInputs().get(0).setValue(newAssign); // Replace select condition with a get-item on newVar. List<Mutable<ILogicalExpression>> selectGetItemArgs = new ArrayList<Mutable<ILogicalExpression>>(); // First arg is a variable reference expr on newVar. selectGetItemArgs.add(new MutableObject<ILogicalExpression>(new VariableReferenceExpression(newVar))); // Second arg is the item index to be accessed, here 0. selectGetItemArgs.add(new MutableObject<ILogicalExpression>( new ConstantExpression(new AsterixConstantValue(new AInt32(0))))); ILogicalExpression selectGetItemExpr = new ScalarFunctionCallExpression( FunctionUtil.getFunctionInfo(AsterixBuiltinFunctions.GET_ITEM), selectGetItemArgs); // Replace the old similarity function call with the new getItemExpr. expRef.setValue(selectGetItemExpr); // Replace expr corresponding to original variable in the original assign with a get-item on newVar. List<Mutable<ILogicalExpression>> assignGetItemArgs = new ArrayList<Mutable<ILogicalExpression>>(); // First arg is a variable reference expr on newVar. assignGetItemArgs.add(new MutableObject<ILogicalExpression>(new VariableReferenceExpression(newVar))); // Second arg is the item index to be accessed, here 1. assignGetItemArgs.add(new MutableObject<ILogicalExpression>( new ConstantExpression(new AsterixConstantValue(new AInt32(1))))); ILogicalExpression assignGetItemExpr = new ScalarFunctionCallExpression( FunctionUtil.getFunctionInfo(AsterixBuiltinFunctions.GET_ITEM), assignGetItemArgs); // Replace the original assign expr with the get-item expr. simFuncExprRef.setValue(assignGetItemExpr); context.computeAndSetTypeEnvironmentForOperator(newAssign); context.computeAndSetTypeEnvironmentForOperator(matchingAssign); return true; } return false; }
From source file:org.apache.asterix.optimizer.rules.SimilarityCheckRule.java
private boolean replaceWithFunctionCallArg(Mutable<ILogicalExpression> expRef, FunctionIdentifier normFuncIdent, AsterixConstantValue constVal, AbstractFunctionCallExpression funcExpr) throws AlgebricksException { // Analyze func expr to see if it is an optimizable similarity function. ScalarFunctionCallExpression simCheckFuncExpr = getSimilarityCheckExpr(normFuncIdent, constVal, funcExpr); // Replace the expr in the select condition. if (simCheckFuncExpr != null) { // Get item 0 from var. List<Mutable<ILogicalExpression>> getItemArgs = new ArrayList<Mutable<ILogicalExpression>>(); // First arg is the similarity-check function call. getItemArgs.add(new MutableObject<ILogicalExpression>(simCheckFuncExpr)); // Second arg is the item index to be accessed. getItemArgs.add(new MutableObject<ILogicalExpression>( new ConstantExpression(new AsterixConstantValue(new AInt32(0))))); ILogicalExpression getItemExpr = new ScalarFunctionCallExpression( FunctionUtil.getFunctionInfo(AsterixBuiltinFunctions.GET_ITEM), getItemArgs); // Replace the old similarity function call with the new getItemExpr. expRef.setValue(getItemExpr);/*from www. j av a 2 s . com*/ return true; } return false; }
From source file:org.apache.asterix.optimizer.rules.SimilarityCheckRule.java
private ScalarFunctionCallExpression getSimilarityCheckExpr(FunctionIdentifier normFuncIdent, AsterixConstantValue constVal, AbstractFunctionCallExpression funcExpr) throws AlgebricksException { // Remember args from original similarity function to add them to the similarity-check function later. ArrayList<Mutable<ILogicalExpression>> similarityArgs = null; ScalarFunctionCallExpression simCheckFuncExpr = null; // Look for jaccard function call, and GE or GT. if (funcExpr.getFunctionIdentifier() == AsterixBuiltinFunctions.SIMILARITY_JACCARD) { IAObject jaccThresh;/* ww w. j av a2 s . c o m*/ if (normFuncIdent == AlgebricksBuiltinFunctions.GE) { if (constVal.getObject() instanceof AFloat) { jaccThresh = constVal.getObject(); } else { jaccThresh = new AFloat((float) ((ADouble) constVal.getObject()).getDoubleValue()); } } else if (normFuncIdent == AlgebricksBuiltinFunctions.GT) { float threshVal = 0.0f; if (constVal.getObject() instanceof AFloat) { threshVal = ((AFloat) constVal.getObject()).getFloatValue(); } else { threshVal = (float) ((ADouble) constVal.getObject()).getDoubleValue(); } float f = threshVal + Float.MIN_VALUE; if (f > 1.0f) f = 1.0f; jaccThresh = new AFloat(f); } else { return null; } similarityArgs = new ArrayList<Mutable<ILogicalExpression>>(); similarityArgs.addAll(funcExpr.getArguments()); similarityArgs.add(new MutableObject<ILogicalExpression>( new ConstantExpression(new AsterixConstantValue(jaccThresh)))); simCheckFuncExpr = new ScalarFunctionCallExpression( FunctionUtil.getFunctionInfo(AsterixBuiltinFunctions.SIMILARITY_JACCARD_CHECK), similarityArgs); } // Look for edit-distance function call, and LE or LT. if (funcExpr.getFunctionIdentifier() == AsterixBuiltinFunctions.EDIT_DISTANCE) { AInt32 aInt = new AInt32(0); try { aInt = (AInt32) ATypeHierarchy.convertNumericTypeObject(constVal.getObject(), ATypeTag.INT32); } catch (AsterixException e) { throw new AlgebricksException(e); } AInt32 edThresh; if (normFuncIdent == AlgebricksBuiltinFunctions.LE) { edThresh = aInt; } else if (normFuncIdent == AlgebricksBuiltinFunctions.LT) { int ed = aInt.getIntegerValue() - 1; if (ed < 0) ed = 0; edThresh = new AInt32(ed); } else { return null; } similarityArgs = new ArrayList<Mutable<ILogicalExpression>>(); similarityArgs.addAll(funcExpr.getArguments()); similarityArgs.add(new MutableObject<ILogicalExpression>( new ConstantExpression(new AsterixConstantValue(edThresh)))); simCheckFuncExpr = new ScalarFunctionCallExpression( FunctionUtil.getFunctionInfo(AsterixBuiltinFunctions.EDIT_DISTANCE_CHECK), similarityArgs); } // Preserve all annotations. if (simCheckFuncExpr != null) { simCheckFuncExpr.getAnnotations().putAll(funcExpr.getAnnotations()); } return simCheckFuncExpr; }
From source file:org.apache.asterix.optimizer.rules.subplan.InlineAllNtsInSubplanVisitor.java
@Override public ILogicalOperator visitGroupByOperator(GroupByOperator op, Void arg) throws AlgebricksException { visitSingleInputOperator(op);//from w w w .j a v a 2s. c om Set<LogicalVariable> groupKeyVars = new HashSet<>(); // Maps group by key variables if the corresponding expressions are // VariableReferenceExpressions. for (Pair<LogicalVariable, Mutable<ILogicalExpression>> keyVarExprRef : op.getGroupByList()) { ILogicalExpression expr = keyVarExprRef.second.getValue(); if (expr.getExpressionTag() == LogicalExpressionTag.VARIABLE) { VariableReferenceExpression varExpr = (VariableReferenceExpression) expr; LogicalVariable sourceVar = varExpr.getVariableReference(); updateInputToOutputVarMapping(sourceVar, keyVarExprRef.first, false); groupKeyVars.add(keyVarExprRef.first); } } // Add correlated key variables into group-by keys. Map<LogicalVariable, LogicalVariable> addedGroupKeyMapping = new HashMap<>(); for (LogicalVariable keyVar : correlatedKeyVars) { if (!groupKeyVars.contains(keyVar)) { LogicalVariable newVar = context.newVar(); op.getGroupByList().add(new Pair<LogicalVariable, Mutable<ILogicalExpression>>(newVar, new MutableObject<ILogicalExpression>(new VariableReferenceExpression(keyVar)))); addedGroupKeyMapping.put(keyVar, newVar); } } // Updates decor list. Iterator<Pair<LogicalVariable, Mutable<ILogicalExpression>>> decorExprIter = op.getDecorList().iterator(); while (decorExprIter.hasNext()) { ILogicalExpression expr = decorExprIter.next().second.getValue(); if (expr.getExpressionTag() == LogicalExpressionTag.VARIABLE) { VariableReferenceExpression varExpr = (VariableReferenceExpression) expr; if (correlatedKeyVars.contains(varExpr.getVariableReference())) { decorExprIter.remove(); } } } // Updates the var mapping for added group-by keys. for (Map.Entry<LogicalVariable, LogicalVariable> entry : addedGroupKeyMapping.entrySet()) { updateInputToOutputVarMapping(entry.getKey(), entry.getValue(), false); } return op; }
From source file:org.apache.asterix.optimizer.rules.subplan.InlineAllNtsInSubplanVisitor.java
@Override public ILogicalOperator visitLimitOperator(LimitOperator op, Void arg) throws AlgebricksException { // Processes its input operator. visitSingleInputOperator(op);/*from w ww . j a v a 2 s. c o m*/ if (correlatedKeyVars.isEmpty()) { return op; } // Get live variables before limit. Set<LogicalVariable> inputLiveVars = new HashSet<LogicalVariable>(); VariableUtilities.getSubplanLocalLiveVariables(op.getInputs().get(0).getValue(), inputLiveVars); // Creates a record construction assign operator. Pair<ILogicalOperator, LogicalVariable> assignOpAndRecordVar = createRecordConstructorAssignOp( inputLiveVars); ILogicalOperator assignOp = assignOpAndRecordVar.first; LogicalVariable recordVar = assignOpAndRecordVar.second; ILogicalOperator inputOp = op.getInputs().get(0).getValue(); assignOp.getInputs().add(new MutableObject<ILogicalOperator>(inputOp)); // Rewrites limit to a group-by with limit as its nested operator. Pair<ILogicalOperator, LogicalVariable> gbyOpAndAggVar = wrapLimitInGroupBy(op, recordVar, inputLiveVars); ILogicalOperator gbyOp = gbyOpAndAggVar.first; LogicalVariable aggVar = gbyOpAndAggVar.second; gbyOp.getInputs().add(new MutableObject<ILogicalOperator>(assignOp)); // Adds an unnest operators on top of the group-by operator. Pair<ILogicalOperator, LogicalVariable> unnestOpAndUnnestVar = createUnnestForAggregatedList(aggVar); ILogicalOperator unnestOp = unnestOpAndUnnestVar.first; LogicalVariable unnestVar = unnestOpAndUnnestVar.second; unnestOp.getInputs().add(new MutableObject<ILogicalOperator>(gbyOp)); // Adds field accesses to recover input live variables. ILogicalOperator fieldAccessAssignOp = createFieldAccessAssignOperator(unnestVar, inputLiveVars); fieldAccessAssignOp.getInputs().add(new MutableObject<ILogicalOperator>(unnestOp)); OperatorManipulationUtil.computeTypeEnvironmentBottomUp(fieldAccessAssignOp, context); return fieldAccessAssignOp; }
From source file:org.apache.asterix.optimizer.rules.subplan.InlineAllNtsInSubplanVisitor.java
private Pair<ILogicalOperator, LogicalVariable> createRecordConstructorAssignOp( Set<LogicalVariable> inputLiveVars) { // Creates a nested record. List<Mutable<ILogicalExpression>> recordConstructorArgs = new ArrayList<>(); for (LogicalVariable inputLiveVar : inputLiveVars) { if (!correlatedKeyVars.contains(inputLiveVar)) { recordConstructorArgs.add(new MutableObject<ILogicalExpression>(new ConstantExpression( new AsterixConstantValue(new AString(Integer.toString(inputLiveVar.getId())))))); recordConstructorArgs//from w ww. j a v a 2 s . com .add(new MutableObject<ILogicalExpression>(new VariableReferenceExpression(inputLiveVar))); } } LogicalVariable recordVar = context.newVar(); Mutable<ILogicalExpression> recordExprRef = new MutableObject<ILogicalExpression>( new ScalarFunctionCallExpression( FunctionUtil.getFunctionInfo(AsterixBuiltinFunctions.OPEN_RECORD_CONSTRUCTOR), recordConstructorArgs)); AssignOperator assignOp = new AssignOperator(recordVar, recordExprRef); return new Pair<ILogicalOperator, LogicalVariable>(assignOp, recordVar); }
From source file:org.apache.asterix.optimizer.rules.subplan.InlineAllNtsInSubplanVisitor.java
private Pair<ILogicalOperator, LogicalVariable> wrapLimitInGroupBy(ILogicalOperator op, LogicalVariable recordVar, Set<LogicalVariable> inputLiveVars) throws AlgebricksException { GroupByOperator gbyOp = new GroupByOperator(); List<Pair<LogicalVariable, LogicalVariable>> keyVarNewVarPairs = new ArrayList<>(); for (LogicalVariable keyVar : correlatedKeyVars) { // This limits the visitor can only be applied to a nested logical // plan inside a Subplan operator, // where the keyVarsToEnforce forms a candidate key which can // uniquely identify a tuple out of the nested-tuple-source. LogicalVariable newVar = context.newVar(); gbyOp.getGroupByList()//from w ww. j av a2 s . co m .add(new Pair<>(newVar, new MutableObject<>(new VariableReferenceExpression(keyVar)))); keyVarNewVarPairs.add(new Pair<>(keyVar, newVar)); } // Creates an aggregate operator doing LISTIFY, as the root of the // nested plan of the added group-by operator. List<LogicalVariable> aggVarList = new ArrayList<LogicalVariable>(); List<Mutable<ILogicalExpression>> aggExprList = new ArrayList<Mutable<ILogicalExpression>>(); LogicalVariable aggVar = context.newVar(); List<Mutable<ILogicalExpression>> aggArgList = new ArrayList<>(); aggVarList.add(aggVar); // Creates an aggregation function expression. aggArgList.add(new MutableObject<>(new VariableReferenceExpression(recordVar))); ILogicalExpression aggExpr = new AggregateFunctionCallExpression( FunctionUtil.getFunctionInfo(AsterixBuiltinFunctions.LISTIFY), false, aggArgList); aggExprList.add(new MutableObject<>(aggExpr)); AggregateOperator aggOp = new AggregateOperator(aggVarList, aggExprList); // Adds the original limit operator as the input operator to the added // aggregate operator. aggOp.getInputs().add(new MutableObject<>(op)); op.getInputs().clear(); ILogicalOperator currentOp = op; if (!orderingExprs.isEmpty()) { OrderOperator orderOp = new OrderOperator(cloneOrderingExpression(orderingExprs)); op.getInputs().add(new MutableObject<>(orderOp)); currentOp = orderOp; } // Adds a nested tuple source operator as the input operator to the // limit operator. NestedTupleSourceOperator nts = new NestedTupleSourceOperator(new MutableObject<ILogicalOperator>(gbyOp)); currentOp.getInputs().add(new MutableObject<>(nts)); // Sets the root of the added nested plan to the aggregate operator. ILogicalPlan nestedPlan = new ALogicalPlanImpl(); nestedPlan.getRoots().add(new MutableObject<>(aggOp)); // Sets the nested plan for the added group-by operator. gbyOp.getNestedPlans().add(nestedPlan); // Updates variable mapping for ancestor operators. for (Pair<LogicalVariable, LogicalVariable> keyVarNewVar : keyVarNewVarPairs) { updateInputToOutputVarMapping(keyVarNewVar.first, keyVarNewVar.second, false); } return new Pair<>(gbyOp, aggVar); }