http://git-wip-us.apache.org/repos/asf/asterixdb/blob/f2c18aa9/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/translator/SqlppExpressionToPlanTranslator.java
----------------------------------------------------------------------
diff --git
a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/translator/SqlppExpressionToPlanTranslator.java
b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/translator/SqlppExpressionToPlanTranslator.java
index dfe0208..a99f9d4 100644
---
a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/translator/SqlppExpressionToPlanTranslator.java
+++
b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/translator/SqlppExpressionToPlanTranslator.java
@@ -48,6 +48,7 @@ import org.apache.asterix.lang.common.expression.OperatorExpr;
import org.apache.asterix.lang.common.expression.QuantifiedExpression;
import org.apache.asterix.lang.common.expression.RecordConstructor;
import org.apache.asterix.lang.common.expression.VariableExpr;
+import org.apache.asterix.lang.common.literal.IntegerLiteral;
import org.apache.asterix.lang.common.literal.StringLiteral;
import org.apache.asterix.lang.common.statement.Query;
import org.apache.asterix.lang.common.struct.OperatorType;
@@ -74,6 +75,7 @@ import org.apache.asterix.lang.sqlpp.optype.JoinType;
import org.apache.asterix.lang.sqlpp.optype.SetOpType;
import org.apache.asterix.lang.sqlpp.struct.SetOperationInput;
import org.apache.asterix.lang.sqlpp.struct.SetOperationRight;
+import org.apache.asterix.lang.sqlpp.util.SqlppRewriteUtil;
import org.apache.asterix.lang.sqlpp.util.SqlppVariableUtil;
import org.apache.asterix.lang.sqlpp.visitor.base.ISqlppVisitor;
import org.apache.asterix.metadata.declared.MetadataProvider;
@@ -91,6 +93,7 @@ import org.apache.asterix.om.types.IAType;
import org.apache.commons.lang3.mutable.Mutable;
import org.apache.commons.lang3.mutable.MutableObject;
import org.apache.hyracks.algebricks.common.exceptions.AlgebricksException;
+import org.apache.hyracks.algebricks.common.utils.ListSet;
import org.apache.hyracks.algebricks.common.utils.Pair;
import org.apache.hyracks.algebricks.core.algebra.base.ILogicalExpression;
import org.apache.hyracks.algebricks.core.algebra.base.ILogicalOperator;
@@ -99,11 +102,13 @@ import
org.apache.hyracks.algebricks.core.algebra.base.LogicalExpressionTag;
import org.apache.hyracks.algebricks.core.algebra.base.LogicalOperatorTag;
import org.apache.hyracks.algebricks.core.algebra.base.LogicalVariable;
import
org.apache.hyracks.algebricks.core.algebra.expressions.AbstractFunctionCallExpression;
+import
org.apache.hyracks.algebricks.core.algebra.expressions.AbstractLogicalExpression;
import
org.apache.hyracks.algebricks.core.algebra.expressions.AggregateFunctionCallExpression;
import
org.apache.hyracks.algebricks.core.algebra.expressions.ConstantExpression;
import
org.apache.hyracks.algebricks.core.algebra.expressions.ScalarFunctionCallExpression;
import
org.apache.hyracks.algebricks.core.algebra.expressions.UnnestingFunctionCallExpression;
import
org.apache.hyracks.algebricks.core.algebra.expressions.VariableReferenceExpression;
+import org.apache.hyracks.algebricks.core.algebra.functions.FunctionIdentifier;
import
org.apache.hyracks.algebricks.core.algebra.operators.logical.AbstractBinaryJoinOperator;
import
org.apache.hyracks.algebricks.core.algebra.operators.logical.AbstractUnnestNonMapOperator;
import
org.apache.hyracks.algebricks.core.algebra.operators.logical.AbstractUnnestOperator;
@@ -120,6 +125,7 @@ import
org.apache.hyracks.algebricks.core.algebra.operators.logical.SubplanOpera
import
org.apache.hyracks.algebricks.core.algebra.operators.logical.UnnestOperator;
import
org.apache.hyracks.algebricks.core.algebra.operators.logical.WindowOperator;
import org.apache.hyracks.algebricks.core.algebra.plan.ALogicalPlanImpl;
+import
org.apache.hyracks.algebricks.core.algebra.util.OperatorManipulationUtil;
import org.apache.hyracks.api.exceptions.SourceLocation;
/**
@@ -1027,9 +1033,17 @@ public class SqlppExpressionToPlanTranslator extends
LangExpressionToPlanTransla
public Pair<ILogicalOperator, LogicalVariable> visit(WindowExpression
winExpr, Mutable<ILogicalOperator> tupSource)
throws CompilationException {
SourceLocation sourceLoc = winExpr.getSourceLocation();
+ List<Expression> fargs = winExpr.getExprList();
+
+ FunctionSignature fs = winExpr.getFunctionSignature();
+ FunctionIdentifier fi = getBuiltinFunctionIdentifier(fs.getName(),
fs.getArity());
+ boolean isWin = BuiltinFunctions.isWindowFunction(fi);
+ boolean isWinAgg = isWin &&
BuiltinFunctions.windowFunctionWithListArg(fi);
+ boolean supportsFrameClause = isWin &&
BuiltinFunctions.windowFunctionSupportsFrameClause(fi);
+
Mutable<ILogicalOperator> currentOpRef = tupSource;
- List<Mutable<ILogicalExpression>> partExprListOut = null;
+ List<Mutable<ILogicalExpression>> partExprListOut =
Collections.emptyList();
if (winExpr.hasPartitionList()) {
List<Expression> partExprList = winExpr.getPartitionList();
partExprListOut = new ArrayList<>(partExprList.size());
@@ -1042,57 +1056,489 @@ public class SqlppExpressionToPlanTranslator extends
LangExpressionToPlanTransla
}
}
- List<Expression> orderExprList = winExpr.getOrderbyList();
- List<OrderbyClause.OrderModifier> orderModifierList =
winExpr.getOrderbyModifierList();
- List<Pair<OrderOperator.IOrder, Mutable<ILogicalExpression>>>
orderExprListOut =
- new ArrayList<>(orderExprList.size());
- for (int i = 0, ln = orderExprList.size(); i < ln; i++) {
- Expression orderExpr = orderExprList.get(i);
- OrderbyClause.OrderModifier orderModifier =
orderModifierList.get(i);
- Pair<ILogicalOperator, LogicalVariable> orderExprResult =
orderExpr.accept(this, currentOpRef);
- VariableReferenceExpression orderExprOut = new
VariableReferenceExpression(orderExprResult.second);
- orderExprOut.setSourceLocation(orderExpr.getSourceLocation());
- OrderOperator.IOrder orderModifierOut =
translateOrderModifier(orderModifier);
- orderExprListOut.add(new Pair<>(orderModifierOut, new
MutableObject<>(orderExprOut)));
- currentOpRef = new MutableObject<>(orderExprResult.first);
+ int orderExprCount = 0;
+ List<Pair<OrderOperator.IOrder, Mutable<ILogicalExpression>>>
orderExprListOut = Collections.emptyList();
+ List<Pair<OrderOperator.IOrder, Mutable<ILogicalExpression>>>
frameValueExprRefs = null;
+ List<Mutable<ILogicalExpression>> frameStartExprRefs = null;
+ List<Mutable<ILogicalExpression>> frameEndExprRefs = null;
+ List<Mutable<ILogicalExpression>> frameExcludeExprRefs = null;
+ int frameExcludeNotStartIdx = -1;
+
+ if (winExpr.hasOrderByList()) {
+ List<Expression> orderExprList = winExpr.getOrderbyList();
+ List<OrderbyClause.OrderModifier> orderModifierList =
winExpr.getOrderbyModifierList();
+ orderExprCount = orderExprList.size();
+ orderExprListOut = new ArrayList<>(orderExprCount);
+ for (int i = 0; i < orderExprCount; i++) {
+ Expression orderExpr = orderExprList.get(i);
+ OrderbyClause.OrderModifier orderModifier =
orderModifierList.get(i);
+ Pair<ILogicalOperator, LogicalVariable> orderExprResult =
orderExpr.accept(this, currentOpRef);
+ VariableReferenceExpression orderExprOut = new
VariableReferenceExpression(orderExprResult.second);
+ orderExprOut.setSourceLocation(orderExpr.getSourceLocation());
+ OrderOperator.IOrder orderModifierOut =
translateOrderModifier(orderModifier);
+ orderExprListOut.add(new Pair<>(orderModifierOut, new
MutableObject<>(orderExprOut)));
+ currentOpRef = new MutableObject<>(orderExprResult.first);
+ }
+ } else if (winExpr.hasFrameDefinition()) {
+ // frame definition without ORDER BY is not allowed by the grammar
+ throw new
CompilationException(ErrorCode.COMPILATION_UNEXPECTED_WINDOW_FRAME, sourceLoc);
}
- Expression expr = winExpr.getExpr();
- Pair<ILogicalOperator, LogicalVariable> exprResult = expr.accept(this,
currentOpRef);
- ILogicalOperator exprOp = exprResult.first;
- if (exprOp.getOperatorTag() != LogicalOperatorTag.ASSIGN) {
- throw new CompilationException(ErrorCode.COMPILATION_ERROR,
sourceLoc);
- }
- AssignOperator exprAssignOp = (AssignOperator) exprOp;
- currentOpRef = exprAssignOp.getInputs().get(0);
- List<LogicalVariable> exprAssignVars = exprAssignOp.getVariables();
- if (exprAssignVars.size() != 1) {
- throw new CompilationException(ErrorCode.COMPILATION_ERROR,
sourceLoc);
+ WindowExpression.FrameMode winFrameMode = null;
+ WindowExpression.FrameExclusionKind winFrameExclusionKind = null;
+ WindowExpression.FrameBoundaryKind winFrameStartKind = null,
winFrameEndKind = null;
+ Expression winFrameStartExpr = null, winFrameEndExpr = null;
+ Expression winFrameOffsetExpr = null;
+ int winFrameMaxOjbects = -1;
+
+ if (winExpr.hasFrameDefinition()) {
+ if (isWin && !supportsFrameClause) {
+ throw new
CompilationException(ErrorCode.COMPILATION_UNEXPECTED_WINDOW_FRAME, sourceLoc);
+ }
+ winFrameMode = winExpr.getFrameMode();
+ winFrameStartKind = winExpr.getFrameStartKind();
+ winFrameStartExpr = winExpr.getFrameStartExpr();
+ winFrameEndKind = winExpr.getFrameEndKind();
+ winFrameEndExpr = winExpr.getFrameEndExpr();
+ winFrameExclusionKind = winExpr.getFrameExclusionKind();
+ if (!isValidWindowFrameDefinition(winFrameMode, winFrameStartKind,
winFrameEndKind, orderExprCount)) {
+ throw new
CompilationException(ErrorCode.COMPILATION_INVALID_WINDOW_FRAME, sourceLoc);
+ }
+ } else if (!isWin || supportsFrameClause) {
+ winFrameMode = WindowExpression.FrameMode.RANGE;
+ winFrameStartKind =
WindowExpression.FrameBoundaryKind.UNBOUNDED_PRECEDING;
+ winFrameEndKind = WindowExpression.FrameBoundaryKind.CURRENT_ROW;
+ winFrameExclusionKind =
WindowExpression.FrameExclusionKind.NO_OTHERS;
}
- LogicalVariable exprAssignVar = exprAssignVars.get(0);
- List<Mutable<ILogicalExpression>> exprAssignExprs =
exprAssignOp.getExpressions();
- ILogicalExpression exprAssignExpr = exprAssignExprs.get(0).getValue();
- if (exprAssignExpr.getExpressionTag() !=
LogicalExpressionTag.FUNCTION_CALL) {
- throw new
CompilationException(ErrorCode.COMPILATION_EXPECTED_FUNCTION_CALL, sourceLoc);
+
+ FunctionIdentifier winAggFunc = null;
+ FunctionIdentifier winAggDefaultIfNullFunc = null;
+ Expression winAggDefaultExpr = null;
+ if (isWinAgg) {
+ if (BuiltinFunctions.LEAD_IMPL.equals(fi) ||
BuiltinFunctions.LAG_IMPL.equals(fi)) {
+ int argCount = fargs.size();
+ if (argCount < 1 || argCount > 3) {
+ throw new
CompilationException(ErrorCode.COMPILATION_INVALID_NUM_OF_ARGS, sourceLoc,
fi.getName());
+ }
+ winFrameMode = WindowExpression.FrameMode.ROWS;
+ winFrameExclusionKind =
WindowExpression.FrameExclusionKind.NO_OTHERS;
+ winFrameStartKind = winFrameEndKind =
+ BuiltinFunctions.LEAD_IMPL.equals(fi) ?
WindowExpression.FrameBoundaryKind.BOUNDED_FOLLOWING
+ :
WindowExpression.FrameBoundaryKind.BOUNDED_PRECEDING;
+ winFrameStartExpr = argCount > 1 ? fargs.get(1) : new
LiteralExpr(new IntegerLiteral(1));
+ winFrameEndExpr = (Expression)
SqlppRewriteUtil.deepCopy(winFrameStartExpr);
+ // if lead/lag default expression is specified
+ // then use local-first-element() because it returns
SYSTEM_NULL if the list is empty,
+ // otherwise (no default expression) use first-element() which
returns NULL if the list is empty
+ if (argCount > 2) {
+ winAggFunc = BuiltinFunctions.LOCAL_FIRST_ELEMENT;
+ winAggDefaultIfNullFunc = BuiltinFunctions.IF_SYSTEM_NULL;
+ winAggDefaultExpr = fargs.get(2);
+ } else {
+ winAggFunc = BuiltinFunctions.FIRST_ELEMENT;
+ }
+ winFrameMaxOjbects = 1;
+ } else if (BuiltinFunctions.FIRST_VALUE_IMPL.equals(fi)) {
+ winAggFunc = BuiltinFunctions.FIRST_ELEMENT;
+ winFrameMaxOjbects = 1;
+ } else if (BuiltinFunctions.LAST_VALUE_IMPL.equals(fi)) {
+ winAggFunc = BuiltinFunctions.LAST_ELEMENT;
+ } else if (BuiltinFunctions.NTH_VALUE_IMPL.equals(fi)) {
+ winAggFunc = BuiltinFunctions.FIRST_ELEMENT;
+ winFrameMaxOjbects = 1;
+ OperatorExpr opExpr = new OperatorExpr();
+ opExpr.addOperand(fargs.get(1));
+ opExpr.addOperator(OperatorType.MINUS);
+ opExpr.addOperand(new LiteralExpr(new IntegerLiteral(1)));
+ opExpr.setSourceLocation(sourceLoc);
+ winFrameOffsetExpr = opExpr;
+ } else {
+ throw new
CompilationException(ErrorCode.COMPILATION_ILLEGAL_STATE, sourceLoc,
fi.getName());
+ }
}
- AbstractFunctionCallExpression callExpr =
(AbstractFunctionCallExpression) exprAssignExpr;
- if
(BuiltinFunctions.windowFunctionRequiresOrderArgs(callExpr.getFunctionIdentifier()))
{
- List<Mutable<ILogicalExpression>> callArgs =
callExpr.getArguments();
- for (Pair<OrderOperator.IOrder, Mutable<ILogicalExpression>> p :
orderExprListOut) {
- callArgs.add(new
MutableObject<>(p.second.getValue().cloneExpression()));
+
+ if (winFrameMode != null) {
+ LogicalVariable rowNumVar = context.newVar();
+ LogicalVariable denseRankVar = context.newVar();
+ ListSet<LogicalVariable> usedVars = new ListSet<>();
+
+ frameValueExprRefs = translateWindowFrameMode(winFrameMode,
orderExprListOut, rowNumVar, denseRankVar,
+ usedVars, sourceLoc);
+
+ Pair<List<Mutable<ILogicalExpression>>, Integer>
frameExclusionResult =
+ translateWindowExclusion(winFrameExclusionKind, rowNumVar,
denseRankVar, usedVars, sourceLoc);
+ if (frameExclusionResult != null) {
+ frameExcludeExprRefs = frameExclusionResult.first;
+ frameExcludeNotStartIdx = frameExclusionResult.second;
+ }
+
+ if (!usedVars.isEmpty()) {
+ List<Mutable<ILogicalExpression>> partExprListClone =
+
OperatorManipulationUtil.cloneExpressions(partExprListOut);
+ List<Pair<OrderOperator.IOrder, Mutable<ILogicalExpression>>>
orderExprListClone =
+
OperatorManipulationUtil.cloneOrderExpressions(orderExprListOut);
+ WindowOperator helperWinOp =
createHelperWindowOperator(partExprListClone, orderExprListClone,
+ rowNumVar, denseRankVar, usedVars, sourceLoc);
+ helperWinOp.getInputs().add(currentOpRef);
+ currentOpRef = new MutableObject<>(helperWinOp);
+ }
+
+ Pair<List<Mutable<ILogicalExpression>>, ILogicalOperator>
frameStartResult =
+ translateWindowBoundary(winFrameStartKind,
winFrameStartExpr, frameValueExprRefs, currentOpRef);
+ if (frameStartResult != null) {
+ frameStartExprRefs = frameStartResult.first;
+ if (frameStartResult.second != null) {
+ currentOpRef = new
MutableObject<>(frameStartResult.second);
+ }
+ }
+ Pair<List<Mutable<ILogicalExpression>>, ILogicalOperator>
frameEndResult =
+ translateWindowBoundary(winFrameEndKind, winFrameEndExpr,
frameValueExprRefs, currentOpRef);
+ if (frameEndResult != null) {
+ frameEndExprRefs = frameEndResult.first;
+ if (frameEndResult.second != null) {
+ currentOpRef = new MutableObject<>(frameEndResult.second);
+ }
}
}
- WindowOperator winOp = new WindowOperator(partExprListOut,
orderExprListOut, exprAssignVars, exprAssignExprs);
+ AbstractLogicalExpression frameOffsetExpr = null;
+ if (winFrameOffsetExpr != null) {
+ Pair<ILogicalOperator, LogicalVariable> frameOffsetResult =
winFrameOffsetExpr.accept(this, currentOpRef);
+ frameOffsetExpr = new
VariableReferenceExpression(frameOffsetResult.second);
+ frameOffsetExpr.setSourceLocation(sourceLoc);
+ currentOpRef = new MutableObject<>(frameOffsetResult.first);
+ }
+
+ WindowOperator winOp = new WindowOperator(partExprListOut,
orderExprListOut, frameValueExprRefs,
+ frameStartExprRefs, frameEndExprRefs, frameExcludeExprRefs,
frameExcludeNotStartIdx, frameOffsetExpr,
+ winFrameMaxOjbects);
winOp.setSourceLocation(sourceLoc);
- winOp.getInputs().add(currentOpRef);
+ AbstractLogicalExpression resultExpr;
+
+ if (isWin && !isWinAgg) {
+ CallExpr callExpr = new CallExpr(new FunctionSignature(fi), fargs);
+ Pair<ILogicalOperator, LogicalVariable> callExprResult =
callExpr.accept(this, currentOpRef);
+ ILogicalOperator op = callExprResult.first;
+ if (op.getOperatorTag() != LogicalOperatorTag.ASSIGN) {
+ throw new
CompilationException(ErrorCode.COMPILATION_ILLEGAL_STATE, sourceLoc, "");
+ }
+ AssignOperator assignOp = (AssignOperator) op;
+ List<LogicalVariable> assignVars = assignOp.getVariables();
+ if (assignVars.size() != 1) {
+ throw new
CompilationException(ErrorCode.COMPILATION_ILLEGAL_STATE, sourceLoc, "");
+ }
+ List<Mutable<ILogicalExpression>> assignExprs =
assignOp.getExpressions();
+ if (assignExprs.size() != 1) {
+ throw new
CompilationException(ErrorCode.COMPILATION_ILLEGAL_STATE, sourceLoc, "");
+ }
+ ILogicalExpression assignExpr = assignExprs.get(0).getValue();
+ if (assignExpr.getExpressionTag() !=
LogicalExpressionTag.FUNCTION_CALL) {
+ throw new
CompilationException(ErrorCode.COMPILATION_ILLEGAL_STATE, sourceLoc);
+ }
+ AbstractFunctionCallExpression fcallExpr =
(AbstractFunctionCallExpression) assignExpr;
+ if (fcallExpr.getKind() !=
AbstractFunctionCallExpression.FunctionKind.STATEFUL) {
+ throw new
CompilationException(ErrorCode.COMPILATION_ILLEGAL_STATE, sourceLoc);
+ }
+ if (BuiltinFunctions.windowFunctionRequiresOrderArgs(fi)) {
+ for (Pair<OrderOperator.IOrder, Mutable<ILogicalExpression>> p
: orderExprListOut) {
+ fcallExpr.getArguments().add(new
MutableObject<>(p.second.getValue().cloneExpression()));
+ }
+ }
+
+ winOp.getInputs().add(assignOp.getInputs().get(0));
+ winOp.getVariables().addAll(assignVars);
+ winOp.getExpressions().addAll(assignExprs);
+
+ resultExpr = new VariableReferenceExpression(assignVars.get(0));
+ resultExpr.setSourceLocation(sourceLoc);
+ currentOpRef = new MutableObject<>(winOp);
+ } else {
+ LogicalVariable windowRecordVar = context.newVar();
+ ILogicalExpression windowRecordConstr =
+ createRecordConstructor(winExpr.getWindowFieldList(),
currentOpRef, sourceLoc);
+ AssignOperator assignOp = new AssignOperator(windowRecordVar, new
MutableObject<>(windowRecordConstr));
+ assignOp.getInputs().add(currentOpRef);
+ assignOp.setSourceLocation(sourceLoc);
+
+ winOp.getInputs().add(new MutableObject<>(assignOp));
+
+ NestedTupleSourceOperator ntsOp = new
NestedTupleSourceOperator(new MutableObject<>(winOp));
+ ntsOp.setSourceLocation(sourceLoc);
+
+ VariableReferenceExpression frameRecordVarRef = new
VariableReferenceExpression(windowRecordVar);
+ frameRecordVarRef.setSourceLocation(sourceLoc);
+
+ AggregateFunctionCallExpression listifyCall =
BuiltinFunctions.makeAggregateFunctionExpression(
+ BuiltinFunctions.LISTIFY, mkSingletonArrayList(new
MutableObject<>(frameRecordVarRef)));
+ listifyCall.setSourceLocation(sourceLoc);
+ LogicalVariable windowVar = context.newVar();
+ AggregateOperator aggOp = new
AggregateOperator(mkSingletonArrayList(windowVar),
+ mkSingletonArrayList(new MutableObject<>(listifyCall)));
+ aggOp.getInputs().add(new MutableObject<>(ntsOp));
+ aggOp.setSourceLocation(sourceLoc);
+
+ context.setVar(winExpr.getWindowVar(), windowVar);
+
+ if (isWinAgg) {
+ Expression listArgExpr = fargs.get(0);
+ Pair<ILogicalOperator, LogicalVariable> listArgExprResult =
+ listArgExpr.accept(this, new MutableObject<>(aggOp));
+ VariableReferenceExpression listArgVarRef = new
VariableReferenceExpression(listArgExprResult.second);
+ listArgVarRef.setSourceLocation(sourceLoc);
+
+ LogicalVariable unnestVar = context.newVar();
+ UnnestingFunctionCallExpression unnestExpr = new
UnnestingFunctionCallExpression(
+
FunctionUtil.getFunctionInfo(BuiltinFunctions.SCAN_COLLECTION),
+ mkSingletonArrayList(new
MutableObject<>(listArgVarRef)));
+ unnestExpr.setSourceLocation(sourceLoc);
+ UnnestOperator unnestOp = new UnnestOperator(unnestVar, new
MutableObject<>(unnestExpr));
+ unnestOp.setSourceLocation(sourceLoc);
+ unnestOp.getInputs().add(new
MutableObject<>(listArgExprResult.first));
+
+ VariableReferenceExpression unnestVarRef = new
VariableReferenceExpression(unnestVar);
+ unnestVarRef.setSourceLocation(sourceLoc);
+
+ AggregateFunctionCallExpression winAggCall =
BuiltinFunctions.makeAggregateFunctionExpression(
+ winAggFunc, mkSingletonArrayList(new
MutableObject<>(unnestVarRef)));
+ winAggCall.setSourceLocation(sourceLoc);
+ LogicalVariable winAggVar = context.newVar();
+ AggregateOperator winAggOp = new
AggregateOperator(mkSingletonArrayList(winAggVar),
+ mkSingletonArrayList(new MutableObject<>(winAggCall)));
+ winAggOp.getInputs().add(new MutableObject<>(unnestOp));
+ winAggOp.setSourceLocation(sourceLoc);
+
+ winOp.getNestedPlans().add(new ALogicalPlanImpl(new
MutableObject<>(winAggOp)));
+ currentOpRef = new MutableObject<>(winOp);
+
+ resultExpr = new VariableReferenceExpression(winAggVar);
+ resultExpr.setSourceLocation(sourceLoc);
+
+ if (winAggDefaultExpr != null) {
+ Pair<ILogicalOperator, LogicalVariable>
winAggDefaultExprResult =
+ winAggDefaultExpr.accept(this, currentOpRef);
+ VariableReferenceExpression winAggDefaultVarRef =
+ new
VariableReferenceExpression(winAggDefaultExprResult.second);
+ winAggDefaultVarRef.setSourceLocation(sourceLoc);
+ AbstractFunctionCallExpression ifNullExpr =
+
createFunctionCallExpression(winAggDefaultIfNullFunc, sourceLoc);
+ ifNullExpr.getArguments().add(new
MutableObject<>(resultExpr));
+ ifNullExpr.getArguments().add(new
MutableObject<>(winAggDefaultVarRef));
+ resultExpr = ifNullExpr;
+ currentOpRef = new
MutableObject<>(winAggDefaultExprResult.first);
+ }
+ } else {
+ CallExpr callExpr = new CallExpr(new FunctionSignature(fi),
fargs);
+ Pair<ILogicalOperator, LogicalVariable> exprResult =
callExpr.accept(this, new MutableObject<>(aggOp));
+ winOp.getNestedPlans().add(new ALogicalPlanImpl(new
MutableObject<>(exprResult.first)));
+ resultExpr = new
VariableReferenceExpression(exprResult.second);
+ resultExpr.setSourceLocation(sourceLoc);
+ currentOpRef = new MutableObject<>(winOp);
+ }
+ }
// must return ASSIGN
- LogicalVariable assignVar = context.newVar();
- AssignOperator assignOp =
- new AssignOperator(assignVar, new MutableObject<>(new
VariableReferenceExpression(exprAssignVar)));
+ LogicalVariable resultVar = context.newVar();
+ AssignOperator resultOp = new AssignOperator(resultVar, new
MutableObject<>(resultExpr));
+ resultOp.setSourceLocation(sourceLoc);
+ resultOp.getInputs().add(currentOpRef);
+ return new Pair<>(resultOp, resultVar);
+ }
+
+ private List<Pair<OrderOperator.IOrder, Mutable<ILogicalExpression>>>
translateWindowFrameMode(
+ WindowExpression.FrameMode frameMode,
+ List<Pair<OrderOperator.IOrder, Mutable<ILogicalExpression>>>
orderExprList, LogicalVariable rowNumVar,
+ LogicalVariable denseRankVar, Set<LogicalVariable> outUsedVars,
SourceLocation sourceLoc)
+ throws CompilationException {
+ switch (frameMode) {
+ case RANGE:
+ List<Pair<OrderOperator.IOrder, Mutable<ILogicalExpression>>>
result =
+ new ArrayList<>(orderExprList.size());
+ for (Pair<OrderOperator.IOrder, Mutable<ILogicalExpression>> p
: orderExprList) {
+ result.add(new Pair<>(p.first, new
MutableObject<>(p.second.getValue().cloneExpression())));
+ }
+ return result;
+ case ROWS:
+ outUsedVars.add(rowNumVar);
+ VariableReferenceExpression rowNumRefExpr = new
VariableReferenceExpression(rowNumVar);
+ rowNumRefExpr.setSourceLocation(sourceLoc);
+ return mkSingletonArrayList(new
Pair<>(OrderOperator.ASC_ORDER, new MutableObject<>(rowNumRefExpr)));
+ case GROUPS:
+ outUsedVars.add(denseRankVar);
+ VariableReferenceExpression denseRankRefExpr = new
VariableReferenceExpression(denseRankVar);
+ denseRankRefExpr.setSourceLocation(sourceLoc);
+ return mkSingletonArrayList(new
Pair<>(OrderOperator.ASC_ORDER, new MutableObject<>(denseRankRefExpr)));
+ default:
+ throw new
CompilationException(ErrorCode.COMPILATION_ILLEGAL_STATE, sourceLoc,
frameMode.toString());
+ }
+ }
+
+ private boolean isValidWindowFrameDefinition(WindowExpression.FrameMode
frameMode,
+ WindowExpression.FrameBoundaryKind startKind,
WindowExpression.FrameBoundaryKind endKind,
+ int orderExprCount) {
+ switch (startKind) {
+ case UNBOUNDED_FOLLOWING:
+ return false;
+ case BOUNDED_FOLLOWING:
+ switch (endKind) {
+ case BOUNDED_FOLLOWING:
+ case UNBOUNDED_FOLLOWING:
+ break;
+ default:
+ return false;
+ }
+ break;
+ }
+ switch (endKind) {
+ case UNBOUNDED_PRECEDING:
+ return false;
+ case BOUNDED_PRECEDING:
+ switch (startKind) {
+ case BOUNDED_PRECEDING:
+ case UNBOUNDED_PRECEDING:
+ break;
+ default:
+ return false;
+ }
+ }
+ if (frameMode == WindowExpression.FrameMode.RANGE && orderExprCount !=
1) {
+ switch (startKind) {
+ case CURRENT_ROW:
+ case UNBOUNDED_PRECEDING:
+ switch (endKind) {
+ case CURRENT_ROW:
+ case UNBOUNDED_FOLLOWING:
+ break;
+ default:
+ return false;
+ }
+ break;
+ default:
+ return false;
+ }
+ }
+ return true;
+ }
+
+ private Pair<List<Mutable<ILogicalExpression>>, ILogicalOperator>
translateWindowBoundary(
+ WindowExpression.FrameBoundaryKind boundaryKind, Expression
boundaryExpr,
+ List<Pair<OrderOperator.IOrder, Mutable<ILogicalExpression>>>
valueExprs,
+ Mutable<ILogicalOperator> tupSource) throws CompilationException {
+ switch (boundaryKind) {
+ case CURRENT_ROW:
+ List<Mutable<ILogicalExpression>> resultExprs = new
ArrayList<>(valueExprs.size());
+ for (Pair<OrderOperator.IOrder, Mutable<ILogicalExpression>> p
: valueExprs) {
+ resultExprs.add(new
MutableObject<>(p.second.getValue().cloneExpression()));
+ }
+ return new Pair<>(resultExprs, null);
+ case BOUNDED_PRECEDING:
+ OperatorType opTypePreceding =
valueExprs.get(0).first.getKind() == OrderOperator.IOrder.OrderKind.ASC
+ ? OperatorType.MINUS : OperatorType.PLUS;
+ return translateWindowBoundaryExpr(boundaryExpr, valueExprs,
tupSource, opTypePreceding);
+ case BOUNDED_FOLLOWING:
+ OperatorType opTypeFollowing =
valueExprs.get(0).first.getKind() == OrderOperator.IOrder.OrderKind.ASC
+ ? OperatorType.PLUS : OperatorType.MINUS;
+ return translateWindowBoundaryExpr(boundaryExpr, valueExprs,
tupSource, opTypeFollowing);
+ case UNBOUNDED_PRECEDING:
+ case UNBOUNDED_FOLLOWING:
+ return null;
+ default:
+ throw new
CompilationException(ErrorCode.COMPILATION_ILLEGAL_STATE,
boundaryExpr.getSourceLocation(),
+ boundaryKind.toString());
+ }
+ }
+
+ private Pair<List<Mutable<ILogicalExpression>>, ILogicalOperator>
translateWindowBoundaryExpr(
+ Expression boundaryExpr, List<Pair<OrderOperator.IOrder,
Mutable<ILogicalExpression>>> valueExprs,
+ Mutable<ILogicalOperator> tupSource, OperatorType
boundaryOperator) throws CompilationException {
+ SourceLocation sourceLoc = boundaryExpr.getSourceLocation();
+ if (valueExprs.size() != 1) {
+ throw new
CompilationException(ErrorCode.COMPILATION_ILLEGAL_STATE, sourceLoc,
valueExprs.size());
+ }
+ ILogicalExpression valueExpr = valueExprs.get(0).second.getValue();
+
+ AbstractFunctionCallExpression resultExpr =
+
createFunctionCallExpressionForBuiltinOperator(boundaryOperator, sourceLoc);
+ resultExpr.getArguments().add(new
MutableObject<>(valueExpr.cloneExpression()));
+ Pair<ILogicalExpression, Mutable<ILogicalOperator>> eo =
langExprToAlgExpression(boundaryExpr, tupSource);
+ resultExpr.getArguments().add(new MutableObject<>(eo.first));
+
+ LogicalVariable resultVar = context.newVar();
+ AssignOperator assignOp = new AssignOperator(resultVar, new
MutableObject<>(resultExpr));
assignOp.setSourceLocation(sourceLoc);
- assignOp.getInputs().add(new MutableObject<>(winOp));
- return new Pair<>(assignOp, assignVar);
+ assignOp.getInputs().add(eo.second);
+
+ VariableReferenceExpression resultVarRefExpr = new
VariableReferenceExpression(resultVar);
+ resultVarRefExpr.setSourceLocation(sourceLoc);
+
+ return new Pair<>(mkSingletonArrayList(new
MutableObject<>(resultVarRefExpr)), assignOp);
+ }
+
+ private Pair<List<Mutable<ILogicalExpression>>, Integer>
translateWindowExclusion(
+ WindowExpression.FrameExclusionKind frameExclusionKind,
LogicalVariable rowNumVar,
+ LogicalVariable denseRankVar, Set<LogicalVariable> outUsedVars,
SourceLocation sourceLoc)
+ throws CompilationException {
+ VariableReferenceExpression rowNumVarRefExpr, denseRankVarRefExpr;
+ List<Mutable<ILogicalExpression>> resultExprs;
+ switch (frameExclusionKind) {
+ case CURRENT_ROW:
+ rowNumVarRefExpr = new VariableReferenceExpression(rowNumVar);
+ rowNumVarRefExpr.setSourceLocation(sourceLoc);
+ resultExprs = new ArrayList<>(1);
+ resultExprs.add(new MutableObject<>(rowNumVarRefExpr));
+ outUsedVars.add(rowNumVar);
+ return new Pair<>(resultExprs, 1);
+ case GROUP:
+ denseRankVarRefExpr = new
VariableReferenceExpression(denseRankVar);
+ denseRankVarRefExpr.setSourceLocation(sourceLoc);
+ resultExprs = new ArrayList<>(1);
+ resultExprs.add(new MutableObject<>(denseRankVarRefExpr));
+ outUsedVars.add(denseRankVar);
+ return new Pair<>(resultExprs, 1);
+ case TIES:
+ denseRankVarRefExpr = new
VariableReferenceExpression(denseRankVar);
+ denseRankVarRefExpr.setSourceLocation(sourceLoc);
+ rowNumVarRefExpr = new VariableReferenceExpression(rowNumVar);
+ rowNumVarRefExpr.setSourceLocation(sourceLoc);
+ resultExprs = new ArrayList<>(2);
+ resultExprs.add(new MutableObject<>(denseRankVarRefExpr));
+ outUsedVars.add(denseRankVar);
+ resultExprs.add(new MutableObject<>(rowNumVarRefExpr));
+ outUsedVars.add(rowNumVar);
+ return new Pair<>(resultExprs, 1); // exclude if same
denseRank but different rowNumber
+ case NO_OTHERS:
+ return null;
+ default:
+ throw new
CompilationException(ErrorCode.COMPILATION_ILLEGAL_STATE, sourceLoc,
+ frameExclusionKind.toString());
+ }
+ }
+
+ private WindowOperator
createHelperWindowOperator(List<Mutable<ILogicalExpression>> partExprList,
+ List<Pair<OrderOperator.IOrder, Mutable<ILogicalExpression>>>
orderExprList, LogicalVariable rowNumVar,
+ LogicalVariable denseRankVar, ListSet<LogicalVariable> usedVars,
SourceLocation sourceLoc)
+ throws CompilationException {
+ WindowOperator winOp = new WindowOperator(partExprList, orderExprList);
+ winOp.setSourceLocation(sourceLoc);
+ for (LogicalVariable usedVar : usedVars) {
+ FunctionIdentifier fid;
+ if (usedVar.equals(rowNumVar)) {
+ fid = BuiltinFunctions.ROW_NUMBER_IMPL;
+ } else if (usedVar.equals(denseRankVar)) {
+ fid = BuiltinFunctions.DENSE_RANK_IMPL;
+ } else {
+ throw new
CompilationException(ErrorCode.COMPILATION_ILLEGAL_STATE, sourceLoc,
usedVar.toString());
+ }
+ AbstractFunctionCallExpression valueExpr =
+ BuiltinFunctions.makeWindowFunctionExpression(fid, new
ArrayList<>());
+ if
(BuiltinFunctions.windowFunctionRequiresOrderArgs(valueExpr.getFunctionIdentifier()))
{
+ for (Pair<OrderOperator.IOrder, Mutable<ILogicalExpression>> p
: orderExprList) {
+ valueExpr.getArguments().add(new
MutableObject<>(p.second.getValue().cloneExpression()));
+ }
+ }
+ valueExpr.setSourceLocation(winOp.getSourceLocation());
+ winOp.getVariables().add(usedVar);
+ winOp.getExpressions().add(new MutableObject<>(valueExpr));
+ }
+ return winOp;
}
}