use of org.apache.commons.lang3.mutable.MutableObject in project asterixdb by apache.
the class ExtractFunctionsFromJoinConditionRule method assignFunctionExpressions.
private boolean assignFunctionExpressions(AbstractLogicalOperator joinOp, ILogicalExpression expr, IOptimizationContext context) throws AlgebricksException {
if (expr.getExpressionTag() != LogicalExpressionTag.FUNCTION_CALL) {
return false;
}
AbstractFunctionCallExpression fexp = (AbstractFunctionCallExpression) expr;
FunctionIdentifier fi = fexp.getFunctionIdentifier();
boolean modified = false;
if (fi.equals(AlgebricksBuiltinFunctions.AND) || fi.equals(AlgebricksBuiltinFunctions.OR) || processArgumentsToFunction(fi)) {
for (Mutable<ILogicalExpression> a : fexp.getArguments()) {
if (assignFunctionExpressions(joinOp, a.getValue(), context)) {
modified = true;
}
}
return modified;
} else if (AlgebricksBuiltinFunctions.isComparisonFunction(fi) || isComparisonFunction(fi)) {
for (Mutable<ILogicalExpression> exprRef : fexp.getArguments()) {
if (exprRef.getValue().getExpressionTag() == LogicalExpressionTag.FUNCTION_CALL) {
LogicalVariable newVar = context.newVar();
AssignOperator newAssign = new AssignOperator(newVar, new MutableObject<ILogicalExpression>(exprRef.getValue().cloneExpression()));
newAssign.setExecutionMode(joinOp.getExecutionMode());
// Place assign below joinOp.
List<LogicalVariable> used = new ArrayList<LogicalVariable>();
VariableUtilities.getUsedVariables(newAssign, used);
Mutable<ILogicalOperator> leftBranchRef = joinOp.getInputs().get(0);
ILogicalOperator leftBranch = leftBranchRef.getValue();
List<LogicalVariable> leftBranchVariables = new ArrayList<LogicalVariable>();
VariableUtilities.getLiveVariables(leftBranch, leftBranchVariables);
if (leftBranchVariables.containsAll(used)) {
// place assign on left branch
newAssign.getInputs().add(new MutableObject<ILogicalOperator>(leftBranch));
leftBranchRef.setValue(newAssign);
modified = true;
} else {
Mutable<ILogicalOperator> rightBranchRef = joinOp.getInputs().get(1);
ILogicalOperator rightBranch = rightBranchRef.getValue();
List<LogicalVariable> rightBranchVariables = new ArrayList<LogicalVariable>();
VariableUtilities.getLiveVariables(rightBranch, rightBranchVariables);
if (rightBranchVariables.containsAll(used)) {
// place assign on right branch
newAssign.getInputs().add(new MutableObject<ILogicalOperator>(rightBranch));
rightBranchRef.setValue(newAssign);
modified = true;
}
}
if (modified) {
// Replace original expr with variable reference.
exprRef.setValue(new VariableReferenceExpression(newVar));
context.computeAndSetTypeEnvironmentForOperator(newAssign);
context.computeAndSetTypeEnvironmentForOperator(joinOp);
}
}
}
return modified;
} else {
return false;
}
}
use of org.apache.commons.lang3.mutable.MutableObject in project asterixdb by apache.
the class ExtractGroupByDecorVariablesRule method rewritePost.
@Override
public boolean rewritePost(Mutable<ILogicalOperator> opRef, IOptimizationContext context) throws AlgebricksException {
ILogicalOperator op = opRef.getValue();
if (op.getOperatorTag() != LogicalOperatorTag.GROUP) {
return false;
}
GroupByOperator groupByOperator = (GroupByOperator) op;
List<Pair<LogicalVariable, Mutable<ILogicalExpression>>> decorList = groupByOperator.getDecorList();
// Returns immediately if there is no decoration entry.
if (groupByOperator.getDecorList() == null || groupByOperator.getDecorList().isEmpty()) {
return false;
}
// Goes over the decoration list and performs the rewrite.
boolean changed = false;
List<LogicalVariable> vars = new ArrayList<>();
List<Mutable<ILogicalExpression>> exprs = new ArrayList<>();
for (Pair<LogicalVariable, Mutable<ILogicalExpression>> decorVarExpr : decorList) {
Mutable<ILogicalExpression> exprRef = decorVarExpr.second;
ILogicalExpression expr = exprRef.getValue();
if (expr == null || expr.getExpressionTag() == LogicalExpressionTag.VARIABLE) {
continue;
}
// Rewrites the decoration entry if the decoration expression is not a variable reference expression.
changed = true;
LogicalVariable newVar = context.newVar();
vars.add(newVar);
exprs.add(exprRef);
// Normalizes the decor entry -- expression be a variable reference
decorVarExpr.second = new MutableObject<>(new VariableReferenceExpression(newVar));
}
if (!changed) {
return false;
}
// Injects an assign operator to evaluate the decoration expression.
AssignOperator assignOperator = new AssignOperator(vars, exprs);
assignOperator.getInputs().addAll(op.getInputs());
op.getInputs().set(0, new MutableObject<>(assignOperator));
return changed;
}
use of org.apache.commons.lang3.mutable.MutableObject in project asterixdb by apache.
the class AbstractIntroduceGroupByCombinerRule method tryToPushRoot.
private boolean tryToPushRoot(Mutable<ILogicalOperator> root, GroupByOperator oldGbyOp, GroupByOperator newGbyOp, BookkeepingInfo bi, List<LogicalVariable> gbyVars, IOptimizationContext context, List<Mutable<ILogicalOperator>> toPushAccumulate, Set<SimilarAggregatesInfo> toReplaceSet) throws AlgebricksException {
AbstractLogicalOperator op1 = (AbstractLogicalOperator) root.getValue();
if (op1.getOperatorTag() != LogicalOperatorTag.AGGREGATE) {
return false;
}
AbstractLogicalOperator op2 = (AbstractLogicalOperator) op1.getInputs().get(0).getValue();
// Finds nested group-by if any.
AbstractLogicalOperator op3 = op2;
while (op3.getOperatorTag() != LogicalOperatorTag.GROUP && op3.getInputs().size() == 1) {
op3 = (AbstractLogicalOperator) op3.getInputs().get(0).getValue();
}
if (op3.getOperatorTag() != LogicalOperatorTag.GROUP) {
AggregateOperator initAgg = (AggregateOperator) op1;
Pair<Boolean, Mutable<ILogicalOperator>> pOpRef = tryToPushAgg(initAgg, newGbyOp, toReplaceSet, context);
if (!pOpRef.first) {
return false;
}
Mutable<ILogicalOperator> opRef = pOpRef.second;
if (opRef != null) {
toPushAccumulate.add(opRef);
}
bi.modifyGbyMap.put(oldGbyOp, gbyVars);
return true;
} else {
GroupByOperator nestedGby = (GroupByOperator) op3;
List<LogicalVariable> gbyVars2 = nestedGby.getGbyVarList();
Set<LogicalVariable> freeVars = new HashSet<>();
// Removes non-free variables defined in the nested plan.
OperatorPropertiesUtil.getFreeVariablesInSelfOrDesc(nestedGby, freeVars);
gbyVars2.retainAll(freeVars);
List<LogicalVariable> concatGbyVars = new ArrayList<LogicalVariable>(gbyVars);
concatGbyVars.addAll(gbyVars2);
for (ILogicalPlan p : nestedGby.getNestedPlans()) {
for (Mutable<ILogicalOperator> r2 : p.getRoots()) {
if (!tryToPushRoot(r2, nestedGby, newGbyOp, bi, concatGbyVars, context, toPushAccumulate, toReplaceSet)) {
return false;
}
}
}
/***
* Push the nested pipeline which provides the input to the nested group operator into newGbyOp (the combined gby op).
* The change is to fix asterixdb issue 782.
*/
// Finds the reference of the bottom-most operator in the pipeline that
// should not be pushed to the combiner group-by.
Mutable<ILogicalOperator> currentOpRef = new MutableObject<ILogicalOperator>(nestedGby);
Mutable<ILogicalOperator> bottomOpRef = findBottomOpRefStayInOldGby(currentOpRef);
// Adds the used variables in the pipeline from <code>currentOpRef</code> to <code>bottomOpRef</code>
// into the group-by keys for the introduced combiner group-by operator.
Set<LogicalVariable> usedVars = collectUsedFreeVariables(currentOpRef, bottomOpRef);
for (LogicalVariable usedVar : usedVars) {
if (!concatGbyVars.contains(usedVar)) {
concatGbyVars.add(usedVar);
}
}
// Retains the nested pipeline above the identified operator in the old group-by operator.
// Pushes the nested pipeline under the select operator into the new group-by operator.
Mutable<ILogicalOperator> oldNtsRef = findNtsRef(currentOpRef);
ILogicalOperator opToCombiner = bottomOpRef.getValue().getInputs().get(0).getValue();
if (opToCombiner.getOperatorTag() == LogicalOperatorTag.NESTEDTUPLESOURCE) {
// No pipeline other than the aggregate operator needs to push to combiner.
return true;
}
bottomOpRef.getValue().getInputs().set(0, new MutableObject<ILogicalOperator>(oldNtsRef.getValue()));
Mutable<ILogicalOperator> newGbyNestedOpRef = findNtsRef(toPushAccumulate.get(0));
NestedTupleSourceOperator newNts = (NestedTupleSourceOperator) newGbyNestedOpRef.getValue();
newGbyNestedOpRef.setValue(opToCombiner);
oldNtsRef.setValue(newNts);
return true;
}
}
use of org.apache.commons.lang3.mutable.MutableObject in project asterixdb by apache.
the class ExtractCommonOperatorsRule method rewritePre.
@Override
public boolean rewritePre(Mutable<ILogicalOperator> opRef, IOptimizationContext context) throws AlgebricksException {
AbstractLogicalOperator op = (AbstractLogicalOperator) opRef.getValue();
if (op.getOperatorTag() != LogicalOperatorTag.WRITE && op.getOperatorTag() != LogicalOperatorTag.WRITE_RESULT && op.getOperatorTag() != LogicalOperatorTag.DISTRIBUTE_RESULT) {
return false;
}
MutableObject<ILogicalOperator> mutableOp = new MutableObject<>(op);
if (!roots.contains(mutableOp)) {
roots.add(mutableOp);
}
return false;
}
use of org.apache.commons.lang3.mutable.MutableObject in project asterixdb by apache.
the class RTreeAccessMethod method createSecondaryToPrimaryPlan.
private ILogicalOperator createSecondaryToPrimaryPlan(OptimizableOperatorSubTree indexSubTree, OptimizableOperatorSubTree probeSubTree, Index chosenIndex, AccessMethodAnalysisContext analysisCtx, boolean retainInput, boolean retainNull, boolean requiresBroadcast, IOptimizationContext context) throws AlgebricksException {
IOptimizableFuncExpr optFuncExpr = AccessMethodUtils.chooseFirstOptFuncExpr(chosenIndex, analysisCtx);
Dataset dataset = indexSubTree.getDataset();
ARecordType recordType = indexSubTree.getRecordType();
ARecordType metaRecordType = indexSubTree.getMetaRecordType();
int optFieldIdx = AccessMethodUtils.chooseFirstOptFuncVar(chosenIndex, analysisCtx);
Pair<IAType, Boolean> keyPairType = Index.getNonNullableOpenFieldType(optFuncExpr.getFieldType(optFieldIdx), optFuncExpr.getFieldName(optFieldIdx), recordType);
if (keyPairType == null) {
return null;
}
// Get the number of dimensions corresponding to the field indexed by chosenIndex.
IAType spatialType = keyPairType.first;
int numDimensions = NonTaggedFormatUtil.getNumDimensions(spatialType.getTypeTag());
int numSecondaryKeys = numDimensions * 2;
// we made sure indexSubTree has datasource scan
AbstractDataSourceOperator dataSourceOp = (AbstractDataSourceOperator) indexSubTree.getDataSourceRef().getValue();
RTreeJobGenParams jobGenParams = new RTreeJobGenParams(chosenIndex.getIndexName(), IndexType.RTREE, dataset.getDataverseName(), dataset.getDatasetName(), retainInput, requiresBroadcast);
// A spatial object is serialized in the constant of the func expr we are optimizing.
// The R-Tree expects as input an MBR represented with 1 field per dimension.
// Here we generate vars and funcs for extracting MBR fields from the constant into fields of a tuple (as the
// R-Tree expects them).
// List of variables for the assign.
ArrayList<LogicalVariable> keyVarList = new ArrayList<>();
// List of expressions for the assign.
ArrayList<Mutable<ILogicalExpression>> keyExprList = new ArrayList<>();
Pair<ILogicalExpression, Boolean> returnedSearchKeyExpr = AccessMethodUtils.createSearchKeyExpr(optFuncExpr, indexSubTree, probeSubTree);
ILogicalExpression searchKeyExpr = returnedSearchKeyExpr.first;
for (int i = 0; i < numSecondaryKeys; i++) {
// The create MBR function "extracts" one field of an MBR around the given spatial object.
AbstractFunctionCallExpression createMBR = new ScalarFunctionCallExpression(FunctionUtil.getFunctionInfo(BuiltinFunctions.CREATE_MBR));
// Spatial object is the constant from the func expr we are optimizing.
createMBR.getArguments().add(new MutableObject<>(searchKeyExpr));
// The number of dimensions.
createMBR.getArguments().add(new MutableObject<ILogicalExpression>(new ConstantExpression(new AsterixConstantValue(new AInt32(numDimensions)))));
// Which part of the MBR to extract.
createMBR.getArguments().add(new MutableObject<ILogicalExpression>(new ConstantExpression(new AsterixConstantValue(new AInt32(i)))));
// Add a variable and its expr to the lists which will be passed into an assign op.
LogicalVariable keyVar = context.newVar();
keyVarList.add(keyVar);
keyExprList.add(new MutableObject<ILogicalExpression>(createMBR));
}
jobGenParams.setKeyVarList(keyVarList);
// Assign operator that "extracts" the MBR fields from the func-expr constant into a tuple.
AssignOperator assignSearchKeys = new AssignOperator(keyVarList, keyExprList);
if (probeSubTree == null) {
// We are optimizing a selection query.
// Input to this assign is the EmptyTupleSource (which the dataSourceScan also must have had as input).
assignSearchKeys.getInputs().add(new MutableObject<>(OperatorManipulationUtil.deepCopy(dataSourceOp.getInputs().get(0).getValue())));
assignSearchKeys.setExecutionMode(dataSourceOp.getExecutionMode());
} else {
// We are optimizing a join, place the assign op top of the probe subtree.
assignSearchKeys.getInputs().add(probeSubTree.getRootRef());
}
ILogicalOperator secondaryIndexUnnestOp = AccessMethodUtils.createSecondaryIndexUnnestMap(dataset, recordType, metaRecordType, chosenIndex, assignSearchKeys, jobGenParams, context, false, retainInput, retainNull);
// Generate the rest of the upstream plan which feeds the search results into the primary index.
return dataset.getDatasetType() == DatasetType.EXTERNAL ? AccessMethodUtils.createExternalDataLookupUnnestMap(dataSourceOp, dataset, recordType, secondaryIndexUnnestOp, context, retainInput, retainNull) : AccessMethodUtils.createPrimaryIndexUnnestMap(dataSourceOp, dataset, recordType, metaRecordType, secondaryIndexUnnestOp, context, true, retainInput, false, false);
}
Aggregations