use of org.apache.hyracks.algebricks.core.algebra.operators.logical.OrderOperator in project asterixdb by apache.
the class EnforceOrderByAfterSubplan method rewritePost.
@Override
public boolean rewritePost(Mutable<ILogicalOperator> opRef, IOptimizationContext context) throws AlgebricksException {
AbstractLogicalOperator op1 = (AbstractLogicalOperator) opRef.getValue();
if (context.checkIfInDontApplySet(this, op1)) {
return false;
}
List<Mutable<ILogicalOperator>> inputs = op1.getInputs();
context.addToDontApplySet(this, op1);
if (op1.getOperatorTag() == LogicalOperatorTag.ORDER || inputs == null) {
/**
* does not apply if
* 1. there is yet-another order operator on-top-of the subplan, because the downstream order operator's ordering will be broken anyway
* 2. the input operator(s) is null
*/
return false;
}
boolean changed = false;
for (int i = 0; i < inputs.size(); i++) {
Mutable<ILogicalOperator> inputOpRef = inputs.get(i);
AbstractLogicalOperator op = (AbstractLogicalOperator) inputOpRef.getValue();
context.addToDontApplySet(this, op);
if (op.getOperatorTag() != LogicalOperatorTag.SUBPLAN) {
continue;
}
/**
* check the order operators whose ordering is not broken before the subplan operator, and then
* duplicate them on-top-of the subplan operator
*/
boolean foundTarget = true;
boolean orderSensitive = false;
Mutable<ILogicalOperator> childRef = op.getInputs().get(0);
AbstractLogicalOperator child = (AbstractLogicalOperator) childRef.getValue();
while (child.getOperatorTag() != LogicalOperatorTag.ORDER) {
context.addToDontApplySet(this, child);
if (orderBreakingOps.contains(child.getOperatorTag())) {
foundTarget = false;
break;
}
if (child.getOperatorTag() == LogicalOperatorTag.GROUP) {
foundTarget = false;
break;
}
if (orderSensitiveOps.contains(child.getOperatorTag())) {
orderSensitive = true;
}
List<Mutable<ILogicalOperator>> childInputs = child.getInputs();
if (childInputs == null || childInputs.size() > 2 || childInputs.size() < 1) {
foundTarget = false;
break;
} else {
childRef = childInputs.get(0);
child = (AbstractLogicalOperator) childRef.getValue();
}
}
/** the target order-by operator has not been found. */
if (!foundTarget) {
return false;
}
/** copy the original order-by operator and insert on-top-of the subplan operator */
context.addToDontApplySet(this, child);
OrderOperator sourceOrderOp = (OrderOperator) child;
for (Pair<IOrder, Mutable<ILogicalExpression>> expr : sourceOrderOp.getOrderExpressions()) {
if (!expr.second.getValue().isFunctional()) {
return false;
}
}
List<Pair<IOrder, Mutable<ILogicalExpression>>> orderExprs = deepCopyOrderAndExpression(sourceOrderOp.getOrderExpressions());
OrderOperator newOrderOp = new OrderOperator(orderExprs);
context.addToDontApplySet(this, newOrderOp);
inputs.set(i, new MutableObject<ILogicalOperator>(newOrderOp));
newOrderOp.getInputs().add(inputOpRef);
context.computeAndSetTypeEnvironmentForOperator(newOrderOp);
if (!orderSensitive) {
/** remove the original order-by */
childRef.setValue(sourceOrderOp.getInputs().get(0).getValue());
}
changed = true;
}
return changed;
}
use of org.apache.hyracks.algebricks.core.algebra.operators.logical.OrderOperator in project asterixdb by apache.
the class PushLimitIntoOrderByRule method pushLimitIntoOrder.
/**
* Generate new ORDER operator that uses TopKSort module and replaces the old ORDER operator.
*/
private boolean pushLimitIntoOrder(Mutable<ILogicalOperator> opRef, Mutable<ILogicalOperator> opRef2, IOptimizationContext context) throws AlgebricksException {
PhysicalOptimizationConfig physicalOptimizationConfig = context.getPhysicalOptimizationConfig();
LimitOperator limitOp = (LimitOperator) opRef.getValue();
OrderOperator orderOp = (OrderOperator) opRef2.getValue();
long topK = -1;
// We don't push-down LIMIT into in-memory sort.
if (orderOp.getPhysicalOperator().getOperatorTag() != PhysicalOperatorTag.STABLE_SORT) {
return false;
}
// Get the LIMIT constant
if (limitOp.getMaxObjects().getValue().getExpressionTag() == LogicalExpressionTag.CONSTANT) {
// Currently, we support LIMIT with a constant value.
topK = AccessMethodUtils.getInt64Constant(limitOp.getMaxObjects());
// since the original external sort's performance might be better.
if (topK > Integer.MAX_VALUE) {
return false;
}
if (topK < 0) {
topK = 0;
}
} else {
return false;
}
// Final topK will be applied through LIMIT.
if (limitOp.getOffset().getValue() != null) {
if (limitOp.getOffset().getValue().getExpressionTag() == LogicalExpressionTag.CONSTANT) {
long offset = AccessMethodUtils.getInt64Constant(limitOp.getOffset());
if (offset < 0) {
offset = 0;
}
// Check the overflow case.
if (offset >= Integer.MAX_VALUE - topK) {
return false;
}
topK += offset;
} else {
return false;
}
}
// Create the new ORDER operator, set the topK value, and replace the current one.
OrderOperator newOrderOp = new OrderOperator(orderOp.getOrderExpressions(), (int) topK);
newOrderOp.setPhysicalOperator(new StableSortPOperator(physicalOptimizationConfig.getMaxFramesExternalSort(), newOrderOp.getTopK()));
newOrderOp.getInputs().addAll(orderOp.getInputs());
newOrderOp.setExecutionMode(orderOp.getExecutionMode());
newOrderOp.recomputeSchema();
newOrderOp.computeDeliveredPhysicalProperties(context);
opRef2.setValue(newOrderOp);
context.computeAndSetTypeEnvironmentForOperator(newOrderOp);
context.addToDontApplySet(this, limitOp);
return true;
}
use of org.apache.hyracks.algebricks.core.algebra.operators.logical.OrderOperator in project asterixdb by apache.
the class LogicalOperatorDeepCopyWithNewVariablesVisitor method visitOrderOperator.
@Override
public ILogicalOperator visitOrderOperator(OrderOperator op, ILogicalOperator arg) throws AlgebricksException {
OrderOperator opCopy = new OrderOperator(deepCopyOrderExpressionReferencePairList(op.getOrderExpressions()));
deepCopyInputsAnnotationsAndExecutionMode(op, arg, opCopy);
return opCopy;
}
use of org.apache.hyracks.algebricks.core.algebra.operators.logical.OrderOperator in project asterixdb by apache.
the class InlineAllNtsInSubplanVisitor method wrapLimitInGroupBy.
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().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(BuiltinFunctions.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);
}
use of org.apache.hyracks.algebricks.core.algebra.operators.logical.OrderOperator in project asterixdb by apache.
the class InlineLeftNtsInSubplanJoinFlatteningVisitor method visitOrderOperator.
@Override
public ILogicalOperator visitOrderOperator(OrderOperator op, Void arg) throws AlgebricksException {
boolean underJoin = hasJoinAncestor;
visitSingleInputOperator(op);
if (!rewritten || !underJoin) {
return op;
}
// Adjust the ordering if its input operator pipeline has been rewritten.
List<Pair<IOrder, Mutable<ILogicalExpression>>> orderExprList = new ArrayList<>();
// Adds keyVars to the prefix of sorting columns.
for (LogicalVariable liveVar : liveVarsFromSubplanInput) {
orderExprList.add(new Pair<IOrder, Mutable<ILogicalExpression>>(OrderOperator.ASC_ORDER, new MutableObject<ILogicalExpression>(new VariableReferenceExpression(liveVar))));
}
orderExprList.addAll(op.getOrderExpressions());
// Creates an order operator with the new expression list.
OrderOperator orderOp = new OrderOperator(orderExprList);
orderOp.getInputs().addAll(op.getInputs());
context.computeAndSetTypeEnvironmentForOperator(orderOp);
return orderOp;
}
Aggregations