use of org.apache.commons.lang3.mutable.Mutable in project asterixdb by apache.
the class InvertedIndexAccessMethod method createPrimaryKeysEqJoinCondition.
private Mutable<ILogicalExpression> createPrimaryKeysEqJoinCondition(List<LogicalVariable> originalSubTreePKs, List<LogicalVariable> surrogateSubTreePKs) {
List<Mutable<ILogicalExpression>> eqExprs = new ArrayList<Mutable<ILogicalExpression>>();
int numPKVars = originalSubTreePKs.size();
for (int i = 0; i < numPKVars; i++) {
List<Mutable<ILogicalExpression>> args = new ArrayList<Mutable<ILogicalExpression>>();
args.add(new MutableObject<ILogicalExpression>(new VariableReferenceExpression(surrogateSubTreePKs.get(i))));
args.add(new MutableObject<ILogicalExpression>(new VariableReferenceExpression(originalSubTreePKs.get(i))));
ILogicalExpression eqFunc = new ScalarFunctionCallExpression(FunctionUtil.getFunctionInfo(AlgebricksBuiltinFunctions.EQ), args);
eqExprs.add(new MutableObject<ILogicalExpression>(eqFunc));
}
if (eqExprs.size() == 1) {
return eqExprs.get(0);
} else {
ILogicalExpression andFunc = new ScalarFunctionCallExpression(FunctionUtil.getFunctionInfo(AlgebricksBuiltinFunctions.AND), eqExprs);
return new MutableObject<ILogicalExpression>(andFunc);
}
}
use of org.apache.commons.lang3.mutable.Mutable in project asterixdb by apache.
the class IntroduceSelectAccessMethodRule method intersectAllSecondaryIndexes.
/**
* Construct all applicable secondary index-based access paths in the given selection plan and
* intersect them using INTERSECT operator to guide to the common primary index search.
* In case where the applicable index is one, we only construct one path.
*/
private boolean intersectAllSecondaryIndexes(List<Pair<IAccessMethod, Index>> chosenIndexes, Map<IAccessMethod, AccessMethodAnalysisContext> analyzedAMs, IOptimizationContext context) throws AlgebricksException {
Pair<IAccessMethod, Index> chosenIndex = null;
Optional<Pair<IAccessMethod, Index>> primaryIndex = chosenIndexes.stream().filter(pair -> pair.second.isPrimaryIndex()).findFirst();
if (chosenIndexes.size() == 1) {
chosenIndex = chosenIndexes.get(0);
} else if (primaryIndex.isPresent()) {
// one primary + secondary indexes, choose the primary index directly.
chosenIndex = primaryIndex.get();
}
if (chosenIndex != null) {
AccessMethodAnalysisContext analysisCtx = analyzedAMs.get(chosenIndex.first);
return chosenIndex.first.applySelectPlanTransformation(afterSelectRefs, selectRef, subTree, chosenIndex.second, analysisCtx, context);
}
// Intersect all secondary indexes, and postpone the primary index search.
Mutable<ILogicalExpression> conditionRef = selectOp.getCondition();
List<ILogicalOperator> subRoots = new ArrayList<>();
for (Pair<IAccessMethod, Index> pair : chosenIndexes) {
AccessMethodAnalysisContext analysisCtx = analyzedAMs.get(pair.first);
subRoots.add(pair.first.createSecondaryToPrimaryPlan(conditionRef, subTree, null, pair.second, analysisCtx, AccessMethodUtils.retainInputs(subTree.getDataSourceVariables(), subTree.getDataSourceRef().getValue(), afterSelectRefs), false, subTree.getDataSourceRef().getValue().getInputs().get(0).getValue().getExecutionMode() == ExecutionMode.UNPARTITIONED, context));
}
// Connect each secondary index utilization plan to a common intersect operator.
ILogicalOperator primaryUnnestOp = connectAll2ndarySearchPlanWithIntersect(subRoots, context);
subTree.getDataSourceRef().setValue(primaryUnnestOp);
return primaryUnnestOp != null;
}
use of org.apache.commons.lang3.mutable.Mutable in project asterixdb by apache.
the class AbstractFunctionCallExpression method cloneArguments.
protected List<Mutable<ILogicalExpression>> cloneArguments() {
List<Mutable<ILogicalExpression>> clonedArgs = new ArrayList<Mutable<ILogicalExpression>>(arguments.size());
for (Mutable<ILogicalExpression> e : arguments) {
ILogicalExpression e2 = e.getValue().cloneExpression();
clonedArgs.add(new MutableObject<ILogicalExpression>(e2));
}
return clonedArgs;
}
use of org.apache.commons.lang3.mutable.Mutable in project asterixdb by apache.
the class PushSelectDownRule method propagateSelectionRec.
private static boolean propagateSelectionRec(Mutable<ILogicalOperator> sigmaRef, Mutable<ILogicalOperator> opRef2) throws AlgebricksException {
AbstractLogicalOperator op2 = (AbstractLogicalOperator) opRef2.getValue();
if (op2.getInputs().size() != 1 || op2.getOperatorTag() == LogicalOperatorTag.DATASOURCESCAN || !OperatorPropertiesUtil.isMovable(op2)) {
return false;
}
SelectOperator sigma = (SelectOperator) sigmaRef.getValue();
LinkedList<LogicalVariable> usedInSigma = new LinkedList<LogicalVariable>();
sigma.getCondition().getValue().getUsedVariables(usedInSigma);
LinkedList<LogicalVariable> produced2 = new LinkedList<LogicalVariable>();
VariableUtilities.getProducedVariables(op2, produced2);
if (OperatorPropertiesUtil.disjoint(produced2, usedInSigma)) {
// just swap
opRef2.setValue(sigma);
sigmaRef.setValue(op2);
List<Mutable<ILogicalOperator>> sigmaInpList = sigma.getInputs();
sigmaInpList.clear();
sigmaInpList.addAll(op2.getInputs());
List<Mutable<ILogicalOperator>> op2InpList = op2.getInputs();
op2InpList.clear();
op2InpList.add(opRef2);
propagateSelectionRec(opRef2, sigma.getInputs().get(0));
return true;
}
return false;
}
use of org.apache.commons.lang3.mutable.Mutable 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;
}
Aggregations