use of org.apache.commons.lang3.mutable.Mutable in project asterixdb by apache.
the class EnforceStructuralPropertiesRule method physOptimizeOp.
private boolean physOptimizeOp(Mutable<ILogicalOperator> opRef, IPhysicalPropertiesVector required, boolean nestedPlan, IOptimizationContext context) throws AlgebricksException {
boolean changed = false;
AbstractLogicalOperator op = (AbstractLogicalOperator) opRef.getValue();
optimizeUsingConstraintsAndEquivClasses(op);
PhysicalRequirements pr = op.getRequiredPhysicalPropertiesForChildren(required, context);
IPhysicalPropertiesVector[] reqdProperties = null;
if (pr != null) {
reqdProperties = pr.getRequiredProperties();
}
boolean opIsRedundantSort = false;
// compute properties and figure out the domain
INodeDomain childrenDomain = null;
{
int j = 0;
for (Mutable<ILogicalOperator> childRef : op.getInputs()) {
AbstractLogicalOperator child = (AbstractLogicalOperator) childRef.getValue();
// recursive call
if (physOptimizeOp(childRef, reqdProperties[j], nestedPlan, context)) {
changed = true;
}
child.computeDeliveredPhysicalProperties(context);
IPhysicalPropertiesVector delivered = child.getDeliveredPhysicalProperties();
if (childrenDomain == null) {
childrenDomain = delivered.getPartitioningProperty().getNodeDomain();
} else {
INodeDomain dom2 = delivered.getPartitioningProperty().getNodeDomain();
if (!childrenDomain.sameAs(dom2)) {
childrenDomain = context.getComputationNodeDomain();
}
}
j++;
}
}
if (reqdProperties != null) {
for (int k = 0; k < reqdProperties.length; k++) {
IPhysicalPropertiesVector pv = reqdProperties[k];
IPartitioningProperty pp = pv.getPartitioningProperty();
if (pp != null && pp.getNodeDomain() == null) {
pp.setNodeDomain(childrenDomain);
}
}
}
// The child index of the child operator to optimize first.
int startChildIndex = getStartChildIndex(op, pr, nestedPlan, context);
IPartitioningProperty firstDeliveredPartitioning = null;
// Enforce data properties in a top-down manner.
for (int j = 0; j < op.getInputs().size(); j++) {
// Starts from a partitioning-compatible child if any to loop over all children.
int childIndex = (j + startChildIndex) % op.getInputs().size();
IPhysicalPropertiesVector requiredProperty = reqdProperties[childIndex];
AbstractLogicalOperator child = (AbstractLogicalOperator) op.getInputs().get(childIndex).getValue();
IPhysicalPropertiesVector delivered = child.getDeliveredPhysicalProperties();
AlgebricksConfig.ALGEBRICKS_LOGGER.finest(">>>> Properties delivered by " + child.getPhysicalOperator() + ": " + delivered + "\n");
IPartitioningRequirementsCoordinator prc = pr.getPartitioningCoordinator();
// Coordinates requirements by looking at the firstDeliveredPartitioning.
Pair<Boolean, IPartitioningProperty> pbpp = prc.coordinateRequirements(requiredProperty.getPartitioningProperty(), firstDeliveredPartitioning, op, context);
boolean mayExpandPartitioningProperties = pbpp.first;
IPhysicalPropertiesVector rqd = new StructuralPropertiesVector(pbpp.second, requiredProperty.getLocalProperties());
AlgebricksConfig.ALGEBRICKS_LOGGER.finest(">>>> Required properties for " + child.getPhysicalOperator() + ": " + rqd + "\n");
// The partitioning property of reqdProperties[childIndex] could be updated here because
// rqd.getPartitioningProperty() is the same object instance as requiredProperty.getPartitioningProperty().
IPhysicalPropertiesVector diff = delivered.getUnsatisfiedPropertiesFrom(rqd, mayExpandPartitioningProperties, context.getEquivalenceClassMap(child), context.getFDList(child));
if (isRedundantSort(opRef, delivered, diff, context)) {
opIsRedundantSort = true;
}
if (diff != null) {
changed = true;
addEnforcers(op, childIndex, diff, rqd, delivered, childrenDomain, nestedPlan, context);
AbstractLogicalOperator newChild = (AbstractLogicalOperator) op.getInputs().get(childIndex).getValue();
if (newChild != child) {
delivered = newChild.getDeliveredPhysicalProperties();
IPhysicalPropertiesVector newDiff = newPropertiesDiff(newChild, rqd, mayExpandPartitioningProperties, context);
AlgebricksConfig.ALGEBRICKS_LOGGER.finest(">>>> New properties diff: " + newDiff + "\n");
if (isRedundantSort(opRef, delivered, newDiff, context)) {
opIsRedundantSort = true;
break;
}
}
}
if (firstDeliveredPartitioning == null) {
firstDeliveredPartitioning = delivered.getPartitioningProperty();
}
}
if (op.hasNestedPlans()) {
AbstractOperatorWithNestedPlans nested = (AbstractOperatorWithNestedPlans) op;
for (ILogicalPlan p : nested.getNestedPlans()) {
if (physOptimizePlan(p, required, true, context)) {
changed = true;
}
}
}
if (opIsRedundantSort) {
if (AlgebricksConfig.DEBUG) {
AlgebricksConfig.ALGEBRICKS_LOGGER.fine(">>>> Removing redundant SORT operator " + op.getPhysicalOperator() + "\n");
printOp(op);
}
changed = true;
AbstractLogicalOperator nextOp = (AbstractLogicalOperator) op.getInputs().get(0).getValue();
if (nextOp.getOperatorTag() == LogicalOperatorTag.PROJECT) {
nextOp = (AbstractLogicalOperator) nextOp.getInputs().get(0).getValue();
}
opRef.setValue(nextOp);
// Now, transfer annotations from the original sort op. to this one.
AbstractLogicalOperator transferTo = nextOp;
if (transferTo.getOperatorTag() == LogicalOperatorTag.EXCHANGE) {
// remove duplicate exchange operator
transferTo = (AbstractLogicalOperator) transferTo.getInputs().get(0).getValue();
}
transferTo.getAnnotations().putAll(op.getAnnotations());
physOptimizeOp(opRef, required, nestedPlan, context);
}
return changed;
}
use of org.apache.commons.lang3.mutable.Mutable in project asterixdb by apache.
the class ComplexUnnestToProductRule method insideSubplan.
/**
* check whether the operator is inside a sub-plan
*
* @param nestedRootRef
* @return true-if it is; false otherwise.
*/
private boolean insideSubplan(Mutable<ILogicalOperator> nestedRootRef) {
AbstractLogicalOperator nestedRoot = (AbstractLogicalOperator) nestedRootRef.getValue();
if (nestedRoot.getOperatorTag() == LogicalOperatorTag.NESTEDTUPLESOURCE) {
return true;
}
List<Mutable<ILogicalOperator>> inputs = nestedRoot.getInputs();
for (Mutable<ILogicalOperator> input : inputs) {
if (insideSubplan(input)) {
return true;
}
}
return false;
}
use of org.apache.commons.lang3.mutable.Mutable 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;
}
use of org.apache.commons.lang3.mutable.Mutable in project asterixdb by apache.
the class AbstractDecorrelationRule method buildVarExprList.
protected void buildVarExprList(Collection<LogicalVariable> vars, IOptimizationContext context, GroupByOperator g, List<Pair<LogicalVariable, Mutable<ILogicalExpression>>> outVeList) throws AlgebricksException {
for (LogicalVariable ov : vars) {
LogicalVariable newVar = context.newVar();
ILogicalExpression varExpr = new VariableReferenceExpression(newVar);
outVeList.add(new Pair<LogicalVariable, Mutable<ILogicalExpression>>(ov, new MutableObject<ILogicalExpression>(varExpr)));
for (ILogicalPlan p : g.getNestedPlans()) {
for (Mutable<ILogicalOperator> r : p.getRoots()) {
OperatorManipulationUtil.substituteVarRec((AbstractLogicalOperator) r.getValue(), ov, newVar, true, context);
}
}
}
}
use of org.apache.commons.lang3.mutable.Mutable in project asterixdb by apache.
the class AbstractIntroduceCombinerRule method tryToPushAgg.
protected Pair<Boolean, Mutable<ILogicalOperator>> tryToPushAgg(AggregateOperator initAgg, GroupByOperator newGbyOp, Set<SimilarAggregatesInfo> toReplaceSet, IOptimizationContext context) throws AlgebricksException {
ArrayList<LogicalVariable> pushedVars = new ArrayList<LogicalVariable>();
ArrayList<Mutable<ILogicalExpression>> pushedExprs = new ArrayList<Mutable<ILogicalExpression>>();
List<LogicalVariable> initVars = initAgg.getVariables();
List<Mutable<ILogicalExpression>> initExprs = initAgg.getExpressions();
int numExprs = initVars.size();
// First make sure that all agg funcs are two step, otherwise we cannot use local aggs.
for (int i = 0; i < numExprs; i++) {
AggregateFunctionCallExpression aggFun = (AggregateFunctionCallExpression) initExprs.get(i).getValue();
if (!aggFun.isTwoStep()) {
return new Pair<Boolean, Mutable<ILogicalOperator>>(false, null);
}
}
boolean haveAggToReplace = false;
for (int i = 0; i < numExprs; i++) {
Mutable<ILogicalExpression> expRef = initExprs.get(i);
AggregateFunctionCallExpression aggFun = (AggregateFunctionCallExpression) expRef.getValue();
IFunctionInfo fi1 = aggFun.getStepOneAggregate();
// Clone the aggregate's args.
List<Mutable<ILogicalExpression>> newArgs = new ArrayList<Mutable<ILogicalExpression>>(aggFun.getArguments().size());
for (Mutable<ILogicalExpression> er : aggFun.getArguments()) {
newArgs.add(new MutableObject<ILogicalExpression>(er.getValue().cloneExpression()));
}
IFunctionInfo fi2 = aggFun.getStepTwoAggregate();
SimilarAggregatesInfo inf = new SimilarAggregatesInfo();
LogicalVariable newAggVar = context.newVar();
pushedVars.add(newAggVar);
inf.stepOneResult = new VariableReferenceExpression(newAggVar);
inf.simAggs = new ArrayList<AggregateExprInfo>();
toReplaceSet.add(inf);
AggregateFunctionCallExpression aggLocal = new AggregateFunctionCallExpression(fi1, false, newArgs);
pushedExprs.add(new MutableObject<ILogicalExpression>(aggLocal));
AggregateExprInfo aei = new AggregateExprInfo();
aei.aggExprRef = expRef;
aei.newFunInfo = fi2;
inf.simAggs.add(aei);
haveAggToReplace = true;
}
if (!pushedVars.isEmpty()) {
AggregateOperator pushedAgg = new AggregateOperator(pushedVars, pushedExprs);
pushedAgg.setExecutionMode(ExecutionMode.LOCAL);
// If newGbyOp is null, then we optimizing an aggregate without group by.
if (newGbyOp != null) {
// Cut and paste nested input pipelines of initAgg to pushedAgg's input
Mutable<ILogicalOperator> inputRef = initAgg.getInputs().get(0);
Mutable<ILogicalOperator> bottomRef = inputRef;
while (bottomRef.getValue().getInputs().size() > 0) {
bottomRef = bottomRef.getValue().getInputs().get(0);
}
ILogicalOperator oldNts = bottomRef.getValue();
initAgg.getInputs().clear();
initAgg.getInputs().add(new MutableObject<ILogicalOperator>(oldNts));
// Hook up the nested aggregate op with the outer group by.
NestedTupleSourceOperator nts = new NestedTupleSourceOperator(new MutableObject<ILogicalOperator>(newGbyOp));
nts.setExecutionMode(ExecutionMode.LOCAL);
bottomRef.setValue(nts);
pushedAgg.getInputs().add(inputRef);
} else {
// The local aggregate operator is fed by the input of the original aggregate operator.
pushedAgg.getInputs().add(new MutableObject<ILogicalOperator>(initAgg.getInputs().get(0).getValue()));
// Reintroduce assign op for the global agg partitioning var.
initAgg.getInputs().get(0).setValue(pushedAgg);
pushedAgg.setGlobal(false);
context.computeAndSetTypeEnvironmentForOperator(pushedAgg);
}
return new Pair<Boolean, Mutable<ILogicalOperator>>(true, new MutableObject<ILogicalOperator>(pushedAgg));
} else {
return new Pair<Boolean, Mutable<ILogicalOperator>>(haveAggToReplace, null);
}
}
Aggregations