use of org.apache.hyracks.algebricks.core.algebra.base.ILogicalExpression in project asterixdb by apache.
the class ComplexUnnestToProductRule method rewritePost.
@Override
public boolean rewritePost(Mutable<ILogicalOperator> opRef, IOptimizationContext context) throws AlgebricksException {
AbstractLogicalOperator op = (AbstractLogicalOperator) opRef.getValue();
if (op.getOperatorTag() != LogicalOperatorTag.DATASOURCESCAN && op.getOperatorTag() != LogicalOperatorTag.UNNEST) {
return false;
}
//stop rewriting if the operators originates from a nested tuple source
if (insideSubplan(opRef)) {
return false;
}
// We may pull selects above the join we create in order to eliminate possible dependencies between
// the outer and inner input plans of the join.
List<ILogicalOperator> topSelects = new ArrayList<ILogicalOperator>();
// Keep track of the operators and used variables participating in the inner input plan.
HashSet<LogicalVariable> innerUsedVars = new HashSet<LogicalVariable>();
List<ILogicalOperator> innerOps = new ArrayList<ILogicalOperator>();
HashSet<LogicalVariable> outerUsedVars = new HashSet<LogicalVariable>();
List<ILogicalOperator> outerOps = new ArrayList<ILogicalOperator>();
innerOps.add(op);
VariableUtilities.getUsedVariables(op, innerUsedVars);
Mutable<ILogicalOperator> opRef2 = op.getInputs().get(0);
AbstractLogicalOperator op2 = (AbstractLogicalOperator) opRef2.getValue();
// Find an unnest or join and partition the plan between the first unnest and that operator into independent parts.
if (!findPlanPartition(op2, innerUsedVars, outerUsedVars, innerOps, outerOps, topSelects, false)) {
// We could not find an unnest or join.
return false;
}
// The last operator must be an unnest or join.
AbstractLogicalOperator unnestOrJoin = (AbstractLogicalOperator) outerOps.get(outerOps.size() - 1);
ILogicalOperator outerRoot = null;
ILogicalOperator innerRoot = null;
EmptyTupleSourceOperator ets = new EmptyTupleSourceOperator();
// If we found a join, simply use it as the outer root.
if (unnestOrJoin.getOperatorTag() != LogicalOperatorTag.INNERJOIN && unnestOrJoin.getOperatorTag() != LogicalOperatorTag.LEFTOUTERJOIN) {
// We've found a second unnest. First, sanity check that the unnest does not output any live variables
// that are used by the plan above (until the first unnest).
List<LogicalVariable> liveVars = new ArrayList<>();
VariableUtilities.getLiveVariables(unnestOrJoin, liveVars);
for (LogicalVariable liveVar : liveVars) {
if (innerUsedVars.contains(liveVar)) {
return false;
}
}
// Continue finding a partitioning of the plan such that the inner and outer partitions are independent, in order to feed a join.
// Now, we look below the second unnest or join.
VariableUtilities.getUsedVariables(unnestOrJoin, outerUsedVars);
AbstractLogicalOperator unnestChild = (AbstractLogicalOperator) unnestOrJoin.getInputs().get(0).getValue();
if (!findPlanPartition(unnestChild, innerUsedVars, outerUsedVars, innerOps, outerOps, topSelects, true)) {
// We could not find a suitable partitioning.
return false;
}
}
innerRoot = buildOperatorChain(innerOps, ets, context);
context.computeAndSetTypeEnvironmentForOperator(innerRoot);
outerRoot = buildOperatorChain(outerOps, null, context);
context.computeAndSetTypeEnvironmentForOperator(outerRoot);
InnerJoinOperator product = new InnerJoinOperator(new MutableObject<ILogicalExpression>(ConstantExpression.TRUE));
// Outer branch.
product.getInputs().add(new MutableObject<ILogicalOperator>(outerRoot));
// Inner branch.
product.getInputs().add(new MutableObject<ILogicalOperator>(innerRoot));
context.computeAndSetTypeEnvironmentForOperator(product);
// Put the selects on top of the join.
ILogicalOperator topOp = product;
if (!topSelects.isEmpty()) {
topOp = buildOperatorChain(topSelects, product, context);
}
// Plug the selects + product in the plan.
opRef.setValue(topOp);
context.computeAndSetTypeEnvironmentForOperator(topOp);
return true;
}
use of org.apache.hyracks.algebricks.core.algebra.base.ILogicalExpression in project asterixdb by apache.
the class ConsolidateSelectsRule method rewritePre.
@Override
public boolean rewritePre(Mutable<ILogicalOperator> opRef, IOptimizationContext context) throws AlgebricksException {
AbstractLogicalOperator op = (AbstractLogicalOperator) opRef.getValue();
if (op.getOperatorTag() != LogicalOperatorTag.SELECT) {
return false;
}
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 && OperatorPropertiesUtil.isMovable(nextSelect));
// 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;
}
use of org.apache.hyracks.algebricks.core.algebra.base.ILogicalExpression 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.hyracks.algebricks.core.algebra.base.ILogicalExpression 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.hyracks.algebricks.core.algebra.base.ILogicalExpression in project asterixdb by apache.
the class AbstractExtractExprRule method extractExprIntoAssignOpRef.
protected LogicalVariable extractExprIntoAssignOpRef(ILogicalExpression gExpr, Mutable<ILogicalOperator> opRef2, IOptimizationContext context) throws AlgebricksException {
LogicalVariable v = context.newVar();
AssignOperator a = new AssignOperator(v, new MutableObject<ILogicalExpression>(gExpr));
a.getInputs().add(new MutableObject<ILogicalOperator>(opRef2.getValue()));
opRef2.setValue(a);
if (gExpr.getExpressionTag() == LogicalExpressionTag.CONSTANT) {
context.addNotToBeInlinedVar(v);
}
context.computeAndSetTypeEnvironmentForOperator(a);
return v;
}
Aggregations