public boolean rewritePre(Mutable<ILogicalOperator> opRef, IOptimizationContext context) throws AlgebricksException {
AbstractLogicalOperator op = (AbstractLogicalOperator) opRef.getValue();
if (op.getOperatorTag() != LogicalOperatorTag.UNNEST) {
return false;
}
UnnestOperator unnest = (UnnestOperator) op;
// Check to see if the expression is the iterate operator.
ILogicalExpression logicalExpression = (ILogicalExpression) unnest.getExpressionRef().getValue();
if (logicalExpression.getExpressionTag() != LogicalExpressionTag.FUNCTION_CALL) {
return false;
}
AbstractFunctionCallExpression functionCall = (AbstractFunctionCallExpression) logicalExpression;
if (!functionCall.getFunctionIdentifier().equals(BuiltinOperators.ITERATE.getFunctionIdentifier())) {
return false;
}
AbstractLogicalOperator op2 = (AbstractLogicalOperator) unnest.getInputs().get(0).getValue();
if (op2.getOperatorTag() != LogicalOperatorTag.SUBPLAN) {
return false;
}
SubplanOperator subplan = (SubplanOperator) op2;
AbstractLogicalOperator subplanOp = (AbstractLogicalOperator) subplan.getNestedPlans().get(0).getRoots().get(0)
.getValue();
if (subplanOp.getOperatorTag() != LogicalOperatorTag.AGGREGATE) {
return false;
}
AggregateOperator aggregate = (AggregateOperator) subplanOp;
// Check to see if the expression is a function and op:sequence.
ILogicalExpression logicalExpression2 = (ILogicalExpression) aggregate.getExpressions().get(0).getValue();
if (logicalExpression2.getExpressionTag() != LogicalExpressionTag.FUNCTION_CALL) {
return false;
}
AbstractFunctionCallExpression functionCall2 = (AbstractFunctionCallExpression) logicalExpression2;
if (!functionCall2.getFunctionIdentifier().equals(BuiltinOperators.SEQUENCE.getFunctionIdentifier())) {
return false;
}
// Make inline the arguments for the subplan.
AbstractLogicalOperator subplanEnd = OperatorToolbox.findLastSubplanOperator(subplanOp);
int count = 0;
for (Mutable<ILogicalOperator> input : subplan.getInputs()) {
subplanEnd.getInputs().get(count++).setValue(input.getValue());
}
// Replace search string with assign.
Mutable<ILogicalExpression> assignExpression = functionCall2.getArguments().get(0);
LogicalVariable assignVariable = context.newVar();
AssignOperator aOp = new AssignOperator(assignVariable, assignExpression);
for (Mutable<ILogicalOperator> input : aggregate.getInputs()) {
aOp.getInputs().add(input);
}
functionCall.getArguments().get(0).setValue(new VariableReferenceExpression(assignVariable));
unnest.getInputs().get(0).setValue(aOp);
return true;
}