You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@calcite.apache.org by jh...@apache.org on 2014/06/28 00:27:54 UTC
[7/7] git commit: [OPTIQ-310] Implement LEAD,
LAG and NTILE windowed aggregates.
[OPTIQ-310] Implement LEAD, LAG and NTILE windowed aggregates.
Refactor aggregate implementation to interfaces.
Add rowInFrame, and rowInPartition, and needCacheWhenFrameIntact APIs for
windowed aggregates.
Project: http://git-wip-us.apache.org/repos/asf/incubator-optiq/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-optiq/commit/99f39682
Tree: http://git-wip-us.apache.org/repos/asf/incubator-optiq/tree/99f39682
Diff: http://git-wip-us.apache.org/repos/asf/incubator-optiq/diff/99f39682
Branch: refs/heads/master
Commit: 99f3968285d5e7c7c50d6d1fc01e3f3aa5486e62
Parents: e34e6e1
Author: Vladimir Sitnikov <si...@gmail.com>
Authored: Tue Jun 24 11:07:29 2014 +0400
Committer: Julian Hyde <ju...@gmail.com>
Committed: Tue Jun 24 20:17:26 2014 -0600
----------------------------------------------------------------------
REFERENCE.md | 4 +
.../optiq/rules/java/AggAddContext.java | 30 +-
.../optiq/rules/java/AggResetContext.java | 22 +-
.../optiq/rules/java/AggResultContext.java | 18 +-
.../hydromatic/optiq/rules/java/JavaRules.java | 266 +++++++--------
.../optiq/rules/java/NestedBlockBuilder.java | 57 +---
.../rules/java/NestedBlockBuilderImpl.java | 117 +++++++
.../optiq/rules/java/RexImpTable.java | 144 +++++++-
.../optiq/rules/java/RexToLixTranslator.java | 10 +-
.../optiq/rules/java/StrictAggImplementor.java | 4 +-
.../rules/java/StrictWinAggImplementor.java | 4 +
.../optiq/rules/java/WinAggAddContext.java | 38 +--
.../optiq/rules/java/WinAggContext.java | 27 ++
.../optiq/rules/java/WinAggFrameContext.java | 73 +++++
.../rules/java/WinAggFrameResultContext.java | 69 ++++
.../optiq/rules/java/WinAggImplementor.java | 106 +-----
.../optiq/rules/java/WinAggResetContext.java | 60 +---
.../optiq/rules/java/WinAggResultContext.java | 41 ++-
.../rules/java/impl/AggAddContextImpl.java | 39 +++
.../rules/java/impl/AggResetContextImpl.java | 51 +++
.../rules/java/impl/AggResultContextImpl.java | 44 +++
.../rules/java/impl/WinAggAddContextImpl.java | 53 +++
.../rules/java/impl/WinAggResetContextImpl.java | 89 +++++
.../java/impl/WinAggResultContextImpl.java | 108 ++++++
.../optiq/rules/java/impl/package-info.java | 24 ++
.../sql/fun/SqlLeadLagAggFunction.java | 94 ++++++
.../eigenbase/sql/fun/SqlNtileAggFunction.java | 58 ++++
.../eigenbase/sql/fun/SqlStdOperatorTable.java | 18 +
.../sql/type/CompositeOperandTypeChecker.java | 6 +
.../sql/type/SqlSingleOperandTypeChecker.java | 2 +-
.../net/hydromatic/optiq/test/JdbcTest.java | 328 ++++++++++++++-----
31 files changed, 1438 insertions(+), 566 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-optiq/blob/99f39682/REFERENCE.md
----------------------------------------------------------------------
diff --git a/REFERENCE.md b/REFERENCE.md
index 5fe4fdb..92f54eb 100644
--- a/REFERENCE.md
+++ b/REFERENCE.md
@@ -434,8 +434,12 @@ Not implemented:
| ROW_NUMBER() OVER window
| FIRST_VALUE(value) OVER window
| LAST_VALUE(value) OVER window
+| LEAD(value, offset, default) OVER window
+| LAG(value, offset, default) OVER window
+| NTILE(value) OVER window
Not implemented:
+* COUNT(DISTINCT value) OVER window
* FIRST_VALUE(value) IGNORE NULLS OVER window
* LAST_VALUE(value) IGNORE NULLS OVER window
* PERCENT_RANK(value) OVER window
http://git-wip-us.apache.org/repos/asf/incubator-optiq/blob/99f39682/core/src/main/java/net/hydromatic/optiq/rules/java/AggAddContext.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/net/hydromatic/optiq/rules/java/AggAddContext.java b/core/src/main/java/net/hydromatic/optiq/rules/java/AggAddContext.java
index 88a88c3..cd1aca3 100644
--- a/core/src/main/java/net/hydromatic/optiq/rules/java/AggAddContext.java
+++ b/core/src/main/java/net/hydromatic/optiq/rules/java/AggAddContext.java
@@ -17,7 +17,6 @@
*/
package net.hydromatic.optiq.rules.java;
-import net.hydromatic.linq4j.expressions.BlockBuilder;
import net.hydromatic.linq4j.expressions.Expression;
import org.eigenbase.rex.RexNode;
@@ -25,22 +24,18 @@ import org.eigenbase.rex.RexNode;
import java.util.List;
/**
- * Information for a call to {@link AggImplementor#implementAdd(AggContext, AggAddContext)}.
+ * Information for a call to {@link net.hydromatic.optiq.rules.java.AggImplementor#implementAdd(AggContext, AggAddContext)}.
* Typically, the aggregation implementation will use {@link #arguments()}
* or {@link #rexArguments()} to update aggregate value.
*/
-public abstract class AggAddContext extends AggResultContext {
- public AggAddContext(BlockBuilder block, List<Expression> accumulator) {
- super(block, accumulator);
- }
-
+public interface AggAddContext extends AggResultContext {
/**
- * Returns {@link RexNode} representation of arguments.
+ * Returns {@link org.eigenbase.rex.RexNode} representation of arguments.
* This can be useful for manual translation of required arguments with
- * different {@link net.hydromatic.optiq.rules.java.NullPolicy}.
- * @return {@link RexNode} representation of arguments
+ * different {@link NullPolicy}.
+ * @return {@link org.eigenbase.rex.RexNode} representation of arguments
*/
- public abstract List<RexNode> rexArguments();
+ List<RexNode> rexArguments();
/**
* Returns Linq4j form of arguments.
@@ -49,14 +44,13 @@ public abstract class AggAddContext extends AggResultContext {
* This is handy if you need just operate on argument.
* @return Linq4j form of arguments.
*/
- public final List<Expression> arguments() {
- return rowTranslator().translateList(rexArguments());
- }
+ List<Expression> arguments();
/**
- * Returns {@link RexToLixTranslator} suitable to transform the arguments.
- * @return {@link RexToLixTranslator} suitable to transform the arguments.
+ * Returns {@link net.hydromatic.optiq.rules.java.RexToLixTranslator} suitable to transform the arguments.
+ * @return {@link net.hydromatic.optiq.rules.java.RexToLixTranslator} suitable to transform the arguments.
*/
- public abstract RexToLixTranslator rowTranslator();
-
+ RexToLixTranslator rowTranslator();
}
+
+// End AggAddContext.java
http://git-wip-us.apache.org/repos/asf/incubator-optiq/blob/99f39682/core/src/main/java/net/hydromatic/optiq/rules/java/AggResetContext.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/net/hydromatic/optiq/rules/java/AggResetContext.java b/core/src/main/java/net/hydromatic/optiq/rules/java/AggResetContext.java
index 22276a1..b6faada 100644
--- a/core/src/main/java/net/hydromatic/optiq/rules/java/AggResetContext.java
+++ b/core/src/main/java/net/hydromatic/optiq/rules/java/AggResetContext.java
@@ -17,7 +17,6 @@
*/
package net.hydromatic.optiq.rules.java;
-import net.hydromatic.linq4j.expressions.BlockBuilder;
import net.hydromatic.linq4j.expressions.Expression;
import java.util.List;
@@ -27,30 +26,15 @@ import java.util.List;
* {@link AggResetContext} provides access to the accumulator variables
* that should be reset.
*/
-public class AggResetContext extends NestedBlockBuilder {
- private final List<Expression> accumulator;
-
- /**
- * Creates aggregate reset context
- * @param block code block that will contain the added initialization
- * @param accumulator accumulator variables that store the intermediate
- * aggregate state
- */
- public AggResetContext(BlockBuilder block, List<Expression> accumulator) {
- super(block);
- this.accumulator = accumulator;
- }
-
+public interface AggResetContext extends NestedBlockBuilder {
/**
* Returns accumulator variables that should be reset.
* There MUST be an assignment even if you just assign the default value.
* @return accumulator variables that should be reset or empty list when no
* accumulator variables are used by the aggregate implementation.
- * @see net.hydromatic.optiq.rules.java.AggImplementor#getStateType(AggContext)
+ * @see AggImplementor#getStateType(net.hydromatic.optiq.rules.java.AggContext)
*/
- public List<Expression> accumulator() {
- return accumulator;
- }
+ List<Expression> accumulator();
}
// End AggResetContext.java
http://git-wip-us.apache.org/repos/asf/incubator-optiq/blob/99f39682/core/src/main/java/net/hydromatic/optiq/rules/java/AggResultContext.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/net/hydromatic/optiq/rules/java/AggResultContext.java b/core/src/main/java/net/hydromatic/optiq/rules/java/AggResultContext.java
index 3c096df..71ab4af 100644
--- a/core/src/main/java/net/hydromatic/optiq/rules/java/AggResultContext.java
+++ b/core/src/main/java/net/hydromatic/optiq/rules/java/AggResultContext.java
@@ -17,27 +17,13 @@
*/
package net.hydromatic.optiq.rules.java;
-import net.hydromatic.linq4j.expressions.BlockBuilder;
-import net.hydromatic.linq4j.expressions.Expression;
-
-import java.util.List;
-
/**
* Information for a call to {@link AggImplementor#implementResult(AggContext, AggResultContext)}
* Typically, the aggregation implementation will convert {@link #accumulator()}
* to the resulting value of the aggregation.
- * The implementation MUST NOT destroy the cotents of {@link #accumulator()}.
+ * The implementation MUST NOT destroy the contents of {@link #accumulator()}.
*/
-public class AggResultContext extends AggResetContext {
- /**
- * Creates aggregate result context
- * @param block code block that will contain the result calculation statements
- * @param accumulator accumulator variables that store the intermediate
- * aggregate state
- */
- public AggResultContext(BlockBuilder block, List<Expression> accumulator) {
- super(block, accumulator);
- }
+public interface AggResultContext extends NestedBlockBuilder, AggResetContext {
}
// End AggResultContext.java
http://git-wip-us.apache.org/repos/asf/incubator-optiq/blob/99f39682/core/src/main/java/net/hydromatic/optiq/rules/java/JavaRules.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/net/hydromatic/optiq/rules/java/JavaRules.java b/core/src/main/java/net/hydromatic/optiq/rules/java/JavaRules.java
index cf8ce44..266a7b4 100644
--- a/core/src/main/java/net/hydromatic/optiq/rules/java/JavaRules.java
+++ b/core/src/main/java/net/hydromatic/optiq/rules/java/JavaRules.java
@@ -26,6 +26,7 @@ import net.hydromatic.optiq.*;
import net.hydromatic.optiq.impl.java.JavaTypeFactory;
import net.hydromatic.optiq.prepare.OptiqPrepareImpl;
import net.hydromatic.optiq.prepare.Prepare;
+import net.hydromatic.optiq.rules.java.impl.*;
import net.hydromatic.optiq.runtime.SortedMultiMap;
import net.hydromatic.optiq.util.BitSets;
@@ -1049,7 +1050,7 @@ public class JavaRules {
agg.state = decls;
initExpressions.addAll(decls);
agg.implementor.implementReset(agg.context,
- new AggResultContext(initBlock, decls));
+ new AggResultContextImpl(initBlock, decls));
}
final PhysType accPhysType =
@@ -1094,7 +1095,7 @@ public class JavaRules {
stateOffset += stateSize;
AggAddContext addContext =
- new AggAddContext(builder2, accumulator) {
+ new AggAddContextImpl(builder2, accumulator) {
public List<RexNode> rexArguments() {
List<RelDataTypeField> inputTypes =
inputPhysType.getRowType().getFieldList();
@@ -1149,7 +1150,7 @@ public class JavaRules {
for (final AggImpState agg : aggs) {
results.add(agg.implementor.implementResult(
agg.context,
- new AggResultContext(resultBlock, agg.state)));
+ new AggResultContextImpl(resultBlock, agg.state)));
}
resultBlock.add(physType.record(results));
if (keyArity == 0) {
@@ -2256,10 +2257,14 @@ public class JavaRules {
declareAndResetState(typeFactory, builder, result, windowIdx, aggs,
outputPhysType, outputRow);
+ // There are assumptions that minX==0. If ever change this, look for
+ // frameRowCount, bounds checking, etc
final Expression minX = Expressions.constant(0);
+ final Expression partitionRowCount =
+ builder3.append("partRows", Expressions.field(rows_, "length"));
final Expression maxX = builder3.append("maxX",
Expressions.subtract(
- Expressions.field(rows_, "length"), Expressions.constant(1)));
+ partitionRowCount, Expressions.constant(1)));
final Expression startUnchecked = builder4.append("start",
translateBound(translator, i_, row_, minX, maxX, rows_,
@@ -2323,14 +2328,14 @@ public class JavaRules {
startX == minX ? endX : Expressions.subtract(endX, startX),
Expressions.constant(1));
- final Expression partitionRowCount;
+ final Expression frameRowCount;
if (hasRows.equals(Expressions.constant(true))) {
- partitionRowCount =
- builder3.append("totalRows", rowCountWhenNonEmpty);
+ frameRowCount =
+ builder4.append("totalRows", rowCountWhenNonEmpty);
} else {
- partitionRowCount =
- builder5.append("totalRows", Expressions.condition(hasRows,
+ frameRowCount =
+ builder4.append("totalRows", Expressions.condition(hasRows,
rowCountWhenNonEmpty, Expressions.constant(0)));
}
@@ -2343,8 +2348,8 @@ public class JavaRules {
for (final AggImpState agg : aggs) {
agg.implementor.implementReset(agg.context,
- new WinAggResetContext(builder6, agg.state, i_, startX, endX,
- hasRows, partitionRowCount));
+ new WinAggResetContextImpl(builder6, agg.state, i_, startX, endX,
+ hasRows, partitionRowCount, frameRowCount));
}
Expression lowerBoundCanChange =
@@ -2381,10 +2386,12 @@ public class JavaRules {
Expressions.declare(0, "j", actualStart);
final PhysType inputPhysTypeFinal = inputPhysType;
- final Function<BlockBuilder, WinAggImplementor.WinAggFrameResultContext>
+ final Function<BlockBuilder, WinAggFrameResultContext>
resultContextBuilder =
getBlockBuilderWinAggFrameResultContextFunction(typeFactory, result,
translatedConstants, comparator_, rows_, i_, startX, endX,
+ minX, maxX,
+ hasRows, frameRowCount, partitionRowCount,
jDecl, inputPhysTypeFinal);
final Function<AggImpState, List<RexNode>> rexArguments =
@@ -2406,8 +2413,7 @@ public class JavaRules {
}
};
- implementAdd(aggs, i_, startX, endX, hasRows, partitionRowCount,
- builder7, jDecl, resultContextBuilder, rexArguments);
+ implementAdd(aggs, builder7, resultContextBuilder, rexArguments, jDecl);
BlockStatement forBlock = builder7.toBlock();
if (!forBlock.statements.isEmpty()) {
@@ -2423,13 +2429,15 @@ public class JavaRules {
builder5.add(forAggLoop);
}
- implementResult(aggs, i_, startX, endX, hasRows, builder5,
- partitionRowCount,
- resultContextBuilder, rexArguments);
+ if (implementResult(aggs, builder5, resultContextBuilder, rexArguments,
+ true)) {
+ builder4.add(Expressions.ifThen(Expressions.orElse(
+ lowerBoundCanChange,
+ Expressions.notEqual(endX, prevEnd)), builder5.toBlock()));
+ }
- builder4.add(Expressions.ifThen(Expressions.orElse(
- lowerBoundCanChange,
- Expressions.notEqual(endX, prevEnd)), builder5.toBlock()));
+ implementResult(aggs, builder4, resultContextBuilder, rexArguments,
+ false);
builder4.add(
Expressions.statement(
@@ -2476,25 +2484,28 @@ public class JavaRules {
return implementor.result(inputPhysType, builder.toBlock());
}
- private Function<BlockBuilder, WinAggImplementor.WinAggFrameResultContext>
+ private Function<BlockBuilder, WinAggFrameResultContext>
getBlockBuilderWinAggFrameResultContextFunction(
final JavaTypeFactory typeFactory, final Result result,
final List<Expression> translatedConstants,
final Expression comparator_,
final Expression rows_, final ParameterExpression i_,
- final Expression startX,
- final Expression endX, final DeclarationStatement jDecl,
- final PhysType inputPhysTypeFinal) {
+ final Expression startX, final Expression endX,
+ final Expression minX, final Expression maxX,
+ final Expression hasRows, final Expression frameRowCount,
+ final Expression partitionRowCount,
+ final DeclarationStatement jDecl,
+ final PhysType inputPhysType) {
return new Function<BlockBuilder,
- WinAggImplementor.WinAggFrameResultContext>() {
- public WinAggImplementor.WinAggFrameResultContext apply(
+ WinAggFrameResultContext>() {
+ public WinAggFrameResultContext apply(
final BlockBuilder block) {
- return new WinAggImplementor.WinAggFrameResultContext() {
+ return new WinAggFrameResultContext() {
public RexToLixTranslator rowTranslator(Expression rowIndex) {
Expression row =
getRow(rowIndex);
final RexToLixTranslator.InputGetter inputGetter =
- new WindowRelInputGetter(row, inputPhysTypeFinal,
+ new WindowRelInputGetter(row, inputPhysType,
result.physType.getRowType().getFieldCount(),
translatedConstants);
@@ -2502,16 +2513,6 @@ public class JavaRules {
block, inputGetter);
}
- public List<RexNode> rexArguments() {
- throw new UnsupportedOperationException(
- "Should not be used");
- }
-
- public List<Expression> arguments(Expression rowIndex) {
- throw new UnsupportedOperationException(
- "Should not be used");
- }
-
public Expression computeIndex(Expression offset,
WinAggImplementor.SeekType seekType) {
Expression index;
@@ -2528,15 +2529,35 @@ public class JavaRules {
+ " is not supported");
}
if (!Expressions.constant(0).equals(offset)) {
- index = Expressions.add(index, offset);
- index = Expressions.call(
- BuiltinMethod.MATH_MIN.method, index, endX);
- index = Expressions.call(
- BuiltinMethod.MATH_MAX.method, index, startX);
+ index = block.append("idx", Expressions.add(index, offset));
}
return index;
}
+ private Expression checkBounds(Expression rowIndex,
+ Expression minIndex, Expression maxIndex) {
+ if (rowIndex == i_ || rowIndex == startX || rowIndex == endX) {
+ // No additional bounds check required
+ return hasRows;
+ }
+
+ //noinspection UnnecessaryLocalVariable
+ Expression res = block.append("rowInFrame", Expressions.foldAnd(
+ ImmutableList.of(hasRows,
+ Expressions.greaterThanOrEqual(rowIndex, minIndex),
+ Expressions.lessThanOrEqual(rowIndex, maxIndex))));
+
+ return res;
+ }
+
+ public Expression rowInFrame(Expression rowIndex) {
+ return checkBounds(rowIndex, startX, endX);
+ }
+
+ public Expression rowInPartition(Expression rowIndex) {
+ return checkBounds(rowIndex, minX, maxX);
+ }
+
public Expression compareRows(Expression a, Expression b) {
return Expressions.call(comparator_,
BuiltinMethod.COMPARATOR_COMPARE.method,
@@ -2548,7 +2569,31 @@ public class JavaRules {
"jRow",
RexToLixTranslator.convert(
Expressions.arrayIndex(rows_, rowIndex),
- inputPhysTypeFinal.getJavaRowType()));
+ inputPhysType.getJavaRowType()));
+ }
+
+ public Expression index() {
+ return i_;
+ }
+
+ public Expression startIndex() {
+ return startX;
+ }
+
+ public Expression endIndex() {
+ return endX;
+ }
+
+ public Expression hasRows() {
+ return hasRows;
+ }
+
+ public Expression getFrameRowCount() {
+ return frameRowCount;
+ }
+
+ public Expression getPartitionRowCount() {
+ return partitionRowCount;
}
};
}
@@ -2668,7 +2713,7 @@ public class JavaRules {
List<Expression> outputRow) {
for (final AggImpState agg: aggs) {
agg.context =
- new WinAggImplementor.WinAggContext() {
+ new WinAggContext() {
public Aggregation aggregation() {
return agg.call.getAggregation();
}
@@ -2727,68 +2772,23 @@ public class JavaRules {
agg.result = aggRes;
outputRow.add(aggRes);
agg.implementor.implementReset(agg.context,
- new WinAggResetContext(builder, agg.state,
- null, null, null, null, null));
+ new WinAggResetContextImpl(builder, agg.state,
+ null, null, null, null, null, null));
}
}
private void implementAdd(List<AggImpState> aggs,
- final ParameterExpression i_,
- final Expression startX, final Expression endX,
- final Expression hasRows,
- final Expression partitionRowCount, final BlockBuilder builder7,
- final DeclarationStatement jDecl,
- final Function<BlockBuilder, WinAggImplementor
- .WinAggFrameResultContext> resultContextBuilder,
- final Function<AggImpState, List<RexNode>> rexArguments) {
+ final BlockBuilder builder7,
+ final Function<BlockBuilder, WinAggFrameResultContext> frame,
+ final Function<AggImpState, List<RexNode>> rexArguments,
+ final DeclarationStatement jDecl) {
for (final AggImpState agg : aggs) {
final WinAggAddContext addContext =
- new WinAggAddContext(builder7, agg.state) {
- public Expression computeIndex(Expression offset,
- WinAggImplementor.SeekType seekType) {
- WinAggImplementor.WinAggFrameResultContext context =
- resultContextBuilder.apply(currentBlock());
- return context.computeIndex(offset, seekType);
- }
-
- public RexToLixTranslator rowTranslator(Expression rowIndex) {
- WinAggImplementor.WinAggFrameResultContext context =
- resultContextBuilder.apply(currentBlock());
- return context.rowTranslator(rowIndex)
- .setNullable(currentNullables());
- }
-
- public Expression compareRows(Expression a, Expression b) {
- WinAggImplementor.WinAggFrameResultContext context =
- resultContextBuilder.apply(currentBlock());
- return context.compareRows(a, b);
- }
-
+ new WinAggAddContextImpl(builder7, agg.state, frame) {
public Expression currentPosition() {
return jDecl.parameter;
}
- public Expression index() {
- return i_;
- }
-
- public Expression startIndex() {
- return startX;
- }
-
- public Expression endIndex() {
- return endX;
- }
-
- public Expression hasRows() {
- return hasRows;
- }
-
- public Expression getPartitionRowCount() {
- return partitionRowCount;
- }
-
- @Override
public List<RexNode> rexArguments() {
return rexArguments.apply(agg);
}
@@ -2797,67 +2797,37 @@ public class JavaRules {
}
}
- private void implementResult(List<AggImpState> aggs,
- final ParameterExpression i_,
- final Expression startX, final Expression endX,
- final Expression hasRows,
- final BlockBuilder builder5, final Expression partitionRowCount,
- final Function<BlockBuilder, WinAggImplementor
- .WinAggFrameResultContext> resultContextBuilder,
- final Function<AggImpState, List<RexNode>> rexArguments) {
+ private boolean implementResult(List<AggImpState> aggs,
+ final BlockBuilder builder,
+ final Function<BlockBuilder, WinAggFrameResultContext> frame,
+ final Function<AggImpState, List<RexNode>> rexArguments,
+ boolean cachedBlock) {
+ boolean nonEmpty = false;
for (final AggImpState agg : aggs) {
+ boolean needCache = true;
+ if (agg.implementor instanceof WinAggImplementor) {
+ WinAggImplementor imp = (WinAggImplementor) agg.implementor;
+ needCache = imp.needCacheWhenFrameIntact();
+ }
+ if (needCache ^ cachedBlock) {
+ // Regular aggregates do not change when the windowing frame keeps
+ // the same. Ths
+ continue;
+ }
+ nonEmpty = true;
Expression res = agg.implementor.implementResult(agg.context,
- new WinAggResultContext(builder5, agg.state) {
+ new WinAggResultContextImpl(builder, agg.state, frame) {
public List<RexNode> rexArguments() {
return rexArguments.apply(agg);
}
-
- public Expression computeIndex(Expression offset,
- WinAggImplementor.SeekType seekType) {
- WinAggImplementor.WinAggFrameResultContext context =
- resultContextBuilder.apply(currentBlock());
- return context.computeIndex(offset, seekType);
- }
-
- public RexToLixTranslator rowTranslator(Expression rowIndex) {
- WinAggImplementor.WinAggFrameResultContext context =
- resultContextBuilder.apply(currentBlock());
- return context.rowTranslator(rowIndex)
- .setNullable(currentNullables());
- }
-
- public Expression compareRows(Expression a, Expression b) {
- WinAggImplementor.WinAggFrameResultContext context =
- resultContextBuilder.apply(currentBlock());
- return context.compareRows(a, b);
- }
-
- public Expression index() {
- return i_;
- }
-
- public Expression startIndex() {
- return startX;
- }
-
- public Expression endIndex() {
- return endX;
- }
-
- public Expression hasRows() {
- return hasRows;
- }
-
- public Expression getPartitionRowCount() {
- return partitionRowCount;
- }
});
// Several count(a) and count(b) might share the result
- Expression aggRes = builder5.append("a" + agg.aggIdx + "res",
+ Expression aggRes = builder.append("a" + agg.aggIdx + "res",
RexToLixTranslator.convert(res, agg.result.getType()));
- builder5.add(Expressions.statement(
+ builder.add(Expressions.statement(
Expressions.assign(agg.result, aggRes)));
}
+ return nonEmpty;
}
private Expression translateBound(RexToLixTranslator translator,
http://git-wip-us.apache.org/repos/asf/incubator-optiq/blob/99f39682/core/src/main/java/net/hydromatic/optiq/rules/java/NestedBlockBuilder.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/net/hydromatic/optiq/rules/java/NestedBlockBuilder.java b/core/src/main/java/net/hydromatic/optiq/rules/java/NestedBlockBuilder.java
index dac5f59..7371e93 100644
--- a/core/src/main/java/net/hydromatic/optiq/rules/java/NestedBlockBuilder.java
+++ b/core/src/main/java/net/hydromatic/optiq/rules/java/NestedBlockBuilder.java
@@ -21,37 +21,21 @@ import net.hydromatic.linq4j.expressions.BlockBuilder;
import org.eigenbase.rex.RexNode;
-import java.util.*;
+import java.util.Map;
/**
* Allows to build nested code blocks with tracking of current context and
* the nullability of particular {@link org.eigenbase.rex.RexNode} expressions.
* @see net.hydromatic.optiq.rules.java.StrictAggImplementor#implementAdd(AggContext, AggAddContext)
*/
-public class NestedBlockBuilder {
- private final List<BlockBuilder> blocks = new ArrayList<BlockBuilder>();
- private final List<Map<RexNode, Boolean>> nullables =
- new ArrayList<Map<RexNode, Boolean>>();
-
- /**
- * Constructs nested block builders starting of a given code block.
- * @param block root code block
- */
- public NestedBlockBuilder(BlockBuilder block) {
- nestBlock(block);
- }
-
+public interface NestedBlockBuilder {
/**
* Starts nested code block. The resulting block can optimize expressions
* and reuse already calculated values from the parent blocks.
* @return new code block that can optimize expressions and reuse already
* calculated values from the parent blocks.
*/
- public final BlockBuilder nestBlock() {
- BlockBuilder block = new BlockBuilder(true, currentBlock());
- nestBlock(block, Collections.<RexNode, Boolean>emptyMap());
- return block;
- }
+ BlockBuilder nestBlock();
/**
* Uses given block as the new code context.
@@ -59,9 +43,7 @@ public class NestedBlockBuilder {
* @param block new code block
* @see #exitBlock()
*/
- public final void nestBlock(BlockBuilder block) {
- nestBlock(block, Collections.<RexNode, Boolean>emptyMap());
- }
+ void nestBlock(BlockBuilder block);
/**
* Uses given block as the new code context and the map of nullability.
@@ -70,48 +52,27 @@ public class NestedBlockBuilder {
* @param nullables map of expression to its nullability state
* @see #exitBlock()
*/
- public final void nestBlock(BlockBuilder block,
- Map<RexNode, Boolean> nullables) {
- blocks.add(block);
- Map<RexNode, Boolean> prev = this.nullables.isEmpty()
- ? Collections.<RexNode, Boolean>emptyMap()
- : this.nullables.get(this.nullables.size() - 1);
- Map<RexNode, Boolean> next;
- if (nullables == null || nullables.isEmpty()) {
- next = prev;
- } else {
- next = new HashMap<RexNode, Boolean>(nullables);
- next.putAll(prev);
- next = Collections.unmodifiableMap(next);
- }
- this.nullables.add(next);
- }
+ void nestBlock(BlockBuilder block,
+ Map<RexNode, Boolean> nullables);
/**
* Returns the current code block
* @return current code block
*/
- public final BlockBuilder currentBlock() {
- return blocks.get(blocks.size() - 1);
- }
+ BlockBuilder currentBlock();
/**
* Returns the current nullability state of rex nodes.
* The resulting value is the summary of all the maps in the block hierarchy.
* @return current nullability state of rex nodes
*/
- public final Map<RexNode, Boolean> currentNullables() {
- return nullables.get(nullables.size() - 1);
- }
+ Map<RexNode, Boolean> currentNullables();
/**
* Leaves the current code block.
* @see #nestBlock()
*/
- public final void exitBlock() {
- blocks.remove(blocks.size() - 1);
- nullables.remove(nullables.size() - 1);
- }
+ void exitBlock();
}
// End NestedBlockBuilder.java
http://git-wip-us.apache.org/repos/asf/incubator-optiq/blob/99f39682/core/src/main/java/net/hydromatic/optiq/rules/java/NestedBlockBuilderImpl.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/net/hydromatic/optiq/rules/java/NestedBlockBuilderImpl.java b/core/src/main/java/net/hydromatic/optiq/rules/java/NestedBlockBuilderImpl.java
new file mode 100644
index 0000000..0fee5ed
--- /dev/null
+++ b/core/src/main/java/net/hydromatic/optiq/rules/java/NestedBlockBuilderImpl.java
@@ -0,0 +1,117 @@
+/*
+// Licensed to Julian Hyde under one or more contributor license
+// agreements. See the NOTICE file distributed with this work for
+// additional information regarding copyright ownership.
+//
+// Julian Hyde licenses this file to you under the Apache License,
+// Version 2.0 (the "License"); you may not use this file except in
+// compliance with the License. You may obtain a copy of the License at:
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+*/
+package net.hydromatic.optiq.rules.java;
+
+import net.hydromatic.linq4j.expressions.BlockBuilder;
+
+import org.eigenbase.rex.RexNode;
+
+import java.util.*;
+
+/**
+ * Allows to build nested code blocks with tracking of current context and
+ * the nullability of particular {@link org.eigenbase.rex.RexNode} expressions.
+ * @see net.hydromatic.optiq.rules.java.StrictAggImplementor#implementAdd(AggContext, AggAddContext)
+ */
+public class NestedBlockBuilderImpl implements NestedBlockBuilder {
+ private final List<BlockBuilder> blocks = new ArrayList<BlockBuilder>();
+ private final List<Map<RexNode, Boolean>> nullables =
+ new ArrayList<Map<RexNode, Boolean>>();
+
+ /**
+ * Constructs nested block builders starting of a given code block.
+ * @param block root code block
+ */
+ public NestedBlockBuilderImpl(BlockBuilder block) {
+ nestBlock(block);
+ }
+
+ /**
+ * Starts nested code block. The resulting block can optimize expressions
+ * and reuse already calculated values from the parent blocks.
+ * @return new code block that can optimize expressions and reuse already
+ * calculated values from the parent blocks.
+ */
+ public final BlockBuilder nestBlock() {
+ BlockBuilder block = new BlockBuilder(true, currentBlock());
+ nestBlock(block, Collections.<RexNode, Boolean>emptyMap());
+ return block;
+ }
+
+ /**
+ * Uses given block as the new code context.
+ * The current block will be restored after {@link #exitBlock()} call.
+ * @param block new code block
+ * @see #exitBlock()
+ */
+ public final void nestBlock(BlockBuilder block) {
+ nestBlock(block, Collections.<RexNode, Boolean>emptyMap());
+ }
+
+ /**
+ * Uses given block as the new code context and the map of nullability.
+ * The current block will be restored after {@link #exitBlock()} call.
+ * @param block new code block
+ * @param nullables map of expression to its nullability state
+ * @see #exitBlock()
+ */
+ public final void nestBlock(BlockBuilder block,
+ Map<RexNode, Boolean> nullables) {
+ blocks.add(block);
+ Map<RexNode, Boolean> prev = this.nullables.isEmpty()
+ ? Collections.<RexNode, Boolean>emptyMap()
+ : this.nullables.get(this.nullables.size() - 1);
+ Map<RexNode, Boolean> next;
+ if (nullables == null || nullables.isEmpty()) {
+ next = prev;
+ } else {
+ next = new HashMap<RexNode, Boolean>(nullables);
+ next.putAll(prev);
+ next = Collections.unmodifiableMap(next);
+ }
+ this.nullables.add(next);
+ }
+
+ /**
+ * Returns the current code block
+ * @return current code block
+ */
+ public final BlockBuilder currentBlock() {
+ return blocks.get(blocks.size() - 1);
+ }
+
+ /**
+ * Returns the current nullability state of rex nodes.
+ * The resulting value is the summary of all the maps in the block hierarchy.
+ * @return current nullability state of rex nodes
+ */
+ public final Map<RexNode, Boolean> currentNullables() {
+ return nullables.get(nullables.size() - 1);
+ }
+
+ /**
+ * Leaves the current code block.
+ * @see #nestBlock()
+ */
+ public final void exitBlock() {
+ blocks.remove(blocks.size() - 1);
+ nullables.remove(nullables.size() - 1);
+ }
+}
+
+// End NestedBlockBuilder.java
http://git-wip-us.apache.org/repos/asf/incubator-optiq/blob/99f39682/core/src/main/java/net/hydromatic/optiq/rules/java/RexImpTable.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/net/hydromatic/optiq/rules/java/RexImpTable.java b/core/src/main/java/net/hydromatic/optiq/rules/java/RexImpTable.java
index e80eeb0..45fc0a0 100644
--- a/core/src/main/java/net/hydromatic/optiq/rules/java/RexImpTable.java
+++ b/core/src/main/java/net/hydromatic/optiq/rules/java/RexImpTable.java
@@ -194,6 +194,9 @@ public class RexImpTable {
winAggMap.put(FIRST_VALUE,
constructorSupplier(FirstValueImplementor.class));
winAggMap.put(LAST_VALUE, constructorSupplier(LastValueImplementor.class));
+ winAggMap.put(LEAD, constructorSupplier(LeadImplementor.class));
+ winAggMap.put(LAG, constructorSupplier(LagImplementor.class));
+ winAggMap.put(NTILE, constructorSupplier(NtileImplementor.class));
winAggMap.put(COUNT, constructorSupplier(CountWinImplementor.class));
}
@@ -774,7 +777,7 @@ public class RexImpTable {
}
static class CountWinImplementor extends StrictWinAggImplementor {
- boolean justPartitionRowCount;
+ boolean justFrameRowCount;
@Override
public List<Type> getNotNullState(WinAggContext info) {
@@ -786,7 +789,7 @@ public class RexImpTable {
}
}
if (!hasNullable) {
- justPartitionRowCount = true;
+ justFrameRowCount = true;
return Collections.emptyList();
}
return super.getNotNullState(info);
@@ -794,7 +797,7 @@ public class RexImpTable {
@Override
public void implementNotNullAdd(WinAggContext info, WinAggAddContext add) {
- if (justPartitionRowCount) {
+ if (justFrameRowCount) {
return;
}
add.currentBlock().add(Expressions.statement(
@@ -804,8 +807,8 @@ public class RexImpTable {
@Override
protected Expression implementNotNullResult(WinAggContext info,
WinAggResultContext result) {
- if (justPartitionRowCount) {
- return result.getPartitionRowCount();
+ if (justFrameRowCount) {
+ return result.getFrameRowCount();
}
return super.implementNotNullResult(info, result);
}
@@ -1034,13 +1037,18 @@ public class RexImpTable {
// no op
}
+ public boolean needCacheWhenFrameIntact() {
+ return true;
+ }
+
public Expression implementResult(AggContext info,
AggResultContext result) {
WinAggResultContext winResult = (WinAggResultContext) result;
+
return Expressions.condition(winResult.hasRows(),
- RexToLixTranslator.convert(
- winResult.arguments(winResult.computeIndex(
- Expressions.constant(0), seekType)).get(0), info.returnType()),
+ winResult.rowTranslator(winResult.computeIndex(
+ Expressions.constant(0), seekType)).translate(
+ winResult.rexArguments().get(0), info.returnType()),
getDefaultValue(info.returnType()));
}
}
@@ -1057,6 +1065,126 @@ public class RexImpTable {
}
}
+ static class LeadLagImplementor implements WinAggImplementor {
+ private final boolean isLead;
+
+ protected LeadLagImplementor(boolean isLead) {
+ this.isLead = isLead;
+ }
+
+ public List<Type> getStateType(AggContext info) {
+ return Collections.emptyList();
+ }
+
+ public void implementReset(AggContext info, AggResetContext reset) {
+ // no op
+ }
+
+ public void implementAdd(AggContext info, AggAddContext add) {
+ // no op
+ }
+
+ public boolean needCacheWhenFrameIntact() {
+ return false;
+ }
+
+ public Expression implementResult(AggContext info,
+ AggResultContext result) {
+ WinAggResultContext winResult = (WinAggResultContext) result;
+
+ List<RexNode> rexArgs = winResult.rexArguments();
+
+ ParameterExpression res = Expressions.parameter(0, info.returnType(),
+ result.currentBlock().newName(isLead ? "lead" : "lag"));
+
+ Expression offset;
+ RexToLixTranslator currentRowTranslator =
+ winResult.rowTranslator(winResult.computeIndex(
+ Expressions.constant(0), SeekType.SET));
+ if (rexArgs.size() >= 2) {
+ // lead(x, offset) or lead(x, offset, default)
+ offset = currentRowTranslator.translate(
+ rexArgs.get(1), int.class);
+ } else {
+ offset = Expressions.constant(1);
+ }
+ if (!isLead) {
+ offset = Expressions.negate(offset);
+ }
+ Expression dstIndex = winResult.computeIndex(offset, SeekType.SET);
+
+ Expression rowInRange = winResult.rowInPartition(dstIndex);
+
+ BlockBuilder thenBlock = result.nestBlock();
+ Expression lagResult = winResult.rowTranslator(dstIndex).translate(
+ rexArgs.get(0), res.type);
+ thenBlock.add(Expressions.statement(Expressions.assign(res, lagResult)));
+ result.exitBlock();
+ BlockStatement thenBranch = thenBlock.toBlock();
+
+ Expression defaultValue = rexArgs.size() == 3
+ ? currentRowTranslator.translate(rexArgs.get(2), res.type)
+ : getDefaultValue(res.type);
+
+ result.currentBlock().add(Expressions.declare(0, res, null));
+ result.currentBlock().add(Expressions.ifThenElse(rowInRange, thenBranch,
+ Expressions.statement(Expressions.assign(res, defaultValue))));
+ return res;
+ }
+ }
+
+ public static class LeadImplementor extends LeadLagImplementor {
+ protected LeadImplementor() {
+ super(true);
+ }
+ }
+
+ public static class LagImplementor extends LeadLagImplementor {
+ protected LagImplementor() {
+ super(false);
+ }
+ }
+
+ static class NtileImplementor implements WinAggImplementor {
+ public List<Type> getStateType(AggContext info) {
+ return Collections.emptyList();
+ }
+
+ public void implementReset(AggContext info, AggResetContext reset) {
+ // no op
+ }
+
+ public void implementAdd(AggContext info, AggAddContext add) {
+ // no op
+ }
+
+ public boolean needCacheWhenFrameIntact() {
+ return false;
+ }
+
+ public Expression implementResult(AggContext info,
+ AggResultContext result) {
+ WinAggResultContext winResult = (WinAggResultContext) result;
+
+ List<RexNode> rexArgs = winResult.rexArguments();
+
+ Expression tiles =
+ winResult.rowTranslator(winResult.index()).translate(
+ rexArgs.get(0), int.class);
+
+ Expression ntile =
+ Expressions.add(Expressions.constant(1),
+ Expressions.divide(
+ Expressions.multiply(
+ tiles,
+ Expressions.subtract(
+ winResult.index(), winResult.startIndex())),
+ winResult.getPartitionRowCount()));
+
+ return ntile;
+ }
+ }
+
static class RowNumberImplementor extends StrictWinAggImplementor {
@Override
public List<Type> getNotNullState(WinAggContext info) {
http://git-wip-us.apache.org/repos/asf/incubator-optiq/blob/99f39682/core/src/main/java/net/hydromatic/optiq/rules/java/RexToLixTranslator.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/net/hydromatic/optiq/rules/java/RexToLixTranslator.java b/core/src/main/java/net/hydromatic/optiq/rules/java/RexToLixTranslator.java
index d15e140..34cf83e 100644
--- a/core/src/main/java/net/hydromatic/optiq/rules/java/RexToLixTranslator.java
+++ b/core/src/main/java/net/hydromatic/optiq/rules/java/RexToLixTranslator.java
@@ -328,6 +328,12 @@ public class RexToLixTranslator {
Expression x = inputGetter.field(list, index, storageType);
Expression input = list.append("inp" + index + "_", x); // safe to share
+ if (nullAs == RexImpTable.NullAs.NOT_POSSIBLE
+ && input.type.equals(storageType)) {
+ // When we asked for not null input that would be stored as box, avoid
+ // unboxing via nullAs.handle below.
+ return input;
+ }
Expression nullHandled = nullAs.handle(input);
// If we get ConstantExpression, just return it (i.e. primitive false)
@@ -525,7 +531,7 @@ public class RexToLixTranslator {
*
* @return translated expressions
*/
- List<Expression> translateList(List<? extends RexNode> operandList) {
+ public List<Expression> translateList(List<? extends RexNode> operandList) {
return translateList(operandList, null);
}
@@ -543,7 +549,7 @@ public class RexToLixTranslator {
*
* @return translated expressions
*/
- List<Expression> translateList(List<? extends RexNode> operandList,
+ public List<Expression> translateList(List<? extends RexNode> operandList,
List<? extends Type> storageTypes) {
final List<Expression> list = new ArrayList<Expression>(operandList.size());
http://git-wip-us.apache.org/repos/asf/incubator-optiq/blob/99f39682/core/src/main/java/net/hydromatic/optiq/rules/java/StrictAggImplementor.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/net/hydromatic/optiq/rules/java/StrictAggImplementor.java b/core/src/main/java/net/hydromatic/optiq/rules/java/StrictAggImplementor.java
index c973e56..d1e96ae 100644
--- a/core/src/main/java/net/hydromatic/optiq/rules/java/StrictAggImplementor.java
+++ b/core/src/main/java/net/hydromatic/optiq/rules/java/StrictAggImplementor.java
@@ -64,9 +64,7 @@ public abstract class StrictAggImplementor implements AggImplementor {
break;
}
}
- trackNullsPerRow =
- !(info instanceof WinAggImplementor.WinAggContext)
- || hasNullableArgs;
+ trackNullsPerRow = !(info instanceof WinAggContext) || hasNullableArgs;
List<Type> res = new ArrayList<Type>(subState.size() + 1);
res.addAll(subState);
http://git-wip-us.apache.org/repos/asf/incubator-optiq/blob/99f39682/core/src/main/java/net/hydromatic/optiq/rules/java/StrictWinAggImplementor.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/net/hydromatic/optiq/rules/java/StrictWinAggImplementor.java b/core/src/main/java/net/hydromatic/optiq/rules/java/StrictWinAggImplementor.java
index 805b557..56257c6 100644
--- a/core/src/main/java/net/hydromatic/optiq/rules/java/StrictWinAggImplementor.java
+++ b/core/src/main/java/net/hydromatic/optiq/rules/java/StrictWinAggImplementor.java
@@ -78,4 +78,8 @@ public abstract class StrictWinAggImplementor extends StrictAggImplementor
return implementNotNullResult((WinAggContext) info,
(WinAggResultContext) result);
}
+
+ public boolean needCacheWhenFrameIntact() {
+ return true;
+ }
}
http://git-wip-us.apache.org/repos/asf/incubator-optiq/blob/99f39682/core/src/main/java/net/hydromatic/optiq/rules/java/WinAggAddContext.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/net/hydromatic/optiq/rules/java/WinAggAddContext.java b/core/src/main/java/net/hydromatic/optiq/rules/java/WinAggAddContext.java
index 41cf6c6..e00587f 100644
--- a/core/src/main/java/net/hydromatic/optiq/rules/java/WinAggAddContext.java
+++ b/core/src/main/java/net/hydromatic/optiq/rules/java/WinAggAddContext.java
@@ -17,51 +17,27 @@
*/
package net.hydromatic.optiq.rules.java;
-import net.hydromatic.linq4j.expressions.BlockBuilder;
import net.hydromatic.linq4j.expressions.Expression;
-import net.hydromatic.linq4j.expressions.Expressions;
-
-import java.util.List;
/**
* Information for a call to {@link AggImplementor#implementAdd(AggContext, AggAddContext)}.
* {@link WinAggAddContext} is used when implementing windowed aggregate.
- * Note: logically, {@link WinAggAddContext} should extend {@link WinAggResultContext},
- * however this would prohibit usage of the same {@link AggImplementor} for both
- * regular aggregate and window aggregate.
* Typically, the aggregation implementation will use {@link #arguments()}
* or {@link #rexArguments()} to update aggregate value.
- * @see net.hydromatic.optiq.rules.java.AggAddContext
+ * @see AggAddContext
*/
-public abstract class WinAggAddContext
- extends AggAddContext
- implements WinAggImplementor.WinAggFrameContext,
- WinAggImplementor.WinAggFrameResultContext {
- public WinAggAddContext(BlockBuilder block, List<Expression> accumulator) {
- super(block, accumulator);
- }
-
+public interface WinAggAddContext extends AggAddContext, WinAggResultContext {
/**
* Returns current position inside for-loop of window aggregate.
- * Note, the position is relative to {@link WinAggImplementor.WinAggFrameContext#startIndex()}.
+ * Note, the position is relative to {@link WinAggFrameContext#startIndex()}.
* This is NOT current row as in "rows between current row".
* If you need to know the relative index of the current row in the partition,
- * use {@link WinAggImplementor.WinAggFrameContext#index()}.
+ * use {@link WinAggFrameContext#index()}.
* @return current position inside for-loop of window aggregate.
- * @see WinAggImplementor.WinAggFrameContext#index()
- * @see WinAggImplementor.WinAggFrameContext#startIndex()
+ * @see WinAggFrameContext#index()
+ * @see WinAggFrameContext#startIndex()
*/
- public abstract Expression currentPosition();
-
- public List<Expression> arguments(Expression rowIndex) {
- return rowTranslator(rowIndex).translateList(rexArguments());
- }
-
- @Override
- public final RexToLixTranslator rowTranslator() {
- return rowTranslator(computeIndex(Expressions.constant(0),
- WinAggImplementor.SeekType.AGG_INDEX));
- }
+ Expression currentPosition();
}
// End WinAggAddContext.java
http://git-wip-us.apache.org/repos/asf/incubator-optiq/blob/99f39682/core/src/main/java/net/hydromatic/optiq/rules/java/WinAggContext.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/net/hydromatic/optiq/rules/java/WinAggContext.java b/core/src/main/java/net/hydromatic/optiq/rules/java/WinAggContext.java
new file mode 100644
index 0000000..281aade
--- /dev/null
+++ b/core/src/main/java/net/hydromatic/optiq/rules/java/WinAggContext.java
@@ -0,0 +1,27 @@
+/*
+// Licensed to Julian Hyde under one or more contributor license
+// agreements. See the NOTICE file distributed with this work for
+// additional information regarding copyright ownership.
+//
+// Julian Hyde licenses this file to you under the Apache License,
+// Version 2.0 (the "License"); you may not use this file except in
+// compliance with the License. You may obtain a copy of the License at:
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+*/
+package net.hydromatic.optiq.rules.java;
+
+/**
+ * Marker interface to allow {@link net.hydromatic.optiq.rules.java.AggImplementor} to tell if it is used in
+ * regular or windowed context.
+ */
+public interface WinAggContext extends AggContext {
+}
+
+// End WinAggContext.java
http://git-wip-us.apache.org/repos/asf/incubator-optiq/blob/99f39682/core/src/main/java/net/hydromatic/optiq/rules/java/WinAggFrameContext.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/net/hydromatic/optiq/rules/java/WinAggFrameContext.java b/core/src/main/java/net/hydromatic/optiq/rules/java/WinAggFrameContext.java
new file mode 100644
index 0000000..c5db249
--- /dev/null
+++ b/core/src/main/java/net/hydromatic/optiq/rules/java/WinAggFrameContext.java
@@ -0,0 +1,73 @@
+/*
+// Licensed to Julian Hyde under one or more contributor license
+// agreements. See the NOTICE file distributed with this work for
+// additional information regarding copyright ownership.
+//
+// Julian Hyde licenses this file to you under the Apache License,
+// Version 2.0 (the "License"); you may not use this file except in
+// compliance with the License. You may obtain a copy of the License at:
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+*/
+package net.hydromatic.optiq.rules.java;
+
+import net.hydromatic.linq4j.expressions.Expression;
+
+/**
+ * Provides information on the current window.
+ * All the indexes are ready to be used in {@link WinAggFrameResultContext#arguments(net.hydromatic.linq4j.expressions.Expression)},
+ * {@link WinAggFrameResultContext#rowTranslator(net.hydromatic.linq4j.expressions.Expression)} and similar methods.
+ */
+public interface WinAggFrameContext {
+ /**
+ * Returns the index of the current row in the partition.
+ * In other words, it is close to ~ROWS BETWEEN CURRENT ROW.
+ * Note to use {@link #startIndex()} when you need zero-based row position.
+ * @return the index of the very first row in partition
+ */
+ Expression index();
+
+ /**
+ * Returns the index of the very first row in partition.
+ * @return index of the very first row in partition
+ */
+ Expression startIndex();
+
+ /**
+ * Returns the index of the very last row in partition.
+ * @return index of the very last row in partition
+ */
+ Expression endIndex();
+
+ /**
+ * Returns the boolean expression that tells if the partition has rows.
+ * The partition might lack rows in cases like ROWS BETWEEN 1000 PRECEDING
+ * AND 900 PRECEDING.
+ * @return boolean expression that tells if the partition has rows
+ */
+ Expression hasRows();
+
+ /**
+ * Returns the number of rows in the current frame (subject to framing
+ * clause).
+ * @return number of rows in the current partition or 0 if the partition
+ * is empty
+ */
+ Expression getFrameRowCount();
+
+ /**
+ * Returns the number of rows in the current partition (as determined by
+ * PARTITION BY clause).
+ * @return number of rows in the current partition or 0 if the partition
+ * is empty
+ */
+ Expression getPartitionRowCount();
+}
+
+// End WinAggFrameContext.java
http://git-wip-us.apache.org/repos/asf/incubator-optiq/blob/99f39682/core/src/main/java/net/hydromatic/optiq/rules/java/WinAggFrameResultContext.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/net/hydromatic/optiq/rules/java/WinAggFrameResultContext.java b/core/src/main/java/net/hydromatic/optiq/rules/java/WinAggFrameResultContext.java
new file mode 100644
index 0000000..d648fb4
--- /dev/null
+++ b/core/src/main/java/net/hydromatic/optiq/rules/java/WinAggFrameResultContext.java
@@ -0,0 +1,69 @@
+/*
+// Licensed to Julian Hyde under one or more contributor license
+// agreements. See the NOTICE file distributed with this work for
+// additional information regarding copyright ownership.
+//
+// Julian Hyde licenses this file to you under the Apache License,
+// Version 2.0 (the "License"); you may not use this file except in
+// compliance with the License. You may obtain a copy of the License at:
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+*/
+package net.hydromatic.optiq.rules.java;
+
+import net.hydromatic.linq4j.expressions.Expression;
+
+/**
+ * Provides information on the current window when computing the result of
+ * the aggregation.
+ */
+public interface WinAggFrameResultContext extends WinAggFrameContext {
+ /**
+ * Converts absolute index position of the given relative position.
+ * @param offset offset of the requested row
+ * @param seekType the type of offset (start of window, end of window, etc)
+ * @return absolute position of the requested row
+ */
+ Expression computeIndex(Expression offset,
+ WinAggImplementor.SeekType seekType);
+
+ /**
+ * Returns boolean the expression that checks if the given index is in
+ * the frame bounds.
+ * @param rowIndex index if the row to check
+ * @return expression that validates frame bounds for the given index
+ */
+ Expression rowInFrame(Expression rowIndex);
+
+ /**
+ * Returns boolean the expression that checks if the given index is in
+ * the partition bounds.
+ * @param rowIndex index if the row to check
+ * @return expression that validates partition bounds for the given index
+ */
+ Expression rowInPartition(Expression rowIndex);
+
+ /**
+ * Returns row translator for given absolute row position.
+ * @param rowIndex absolute index of the row.
+ * @return translator for the requested row
+ */
+ RexToLixTranslator rowTranslator(Expression rowIndex);
+
+ /**
+ * Compares two rows given by absolute positions according to the order
+ * collation of the current window.
+ * @param a absolute index of the first row
+ * @param b absolute index of the second row
+ * @return result of comparison as as in {@link Comparable#compareTo}
+ */
+ Expression compareRows(Expression a, Expression b);
+}
+
+// End WinAggFrameResultContext.java
http://git-wip-us.apache.org/repos/asf/incubator-optiq/blob/99f39682/core/src/main/java/net/hydromatic/optiq/rules/java/WinAggImplementor.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/net/hydromatic/optiq/rules/java/WinAggImplementor.java b/core/src/main/java/net/hydromatic/optiq/rules/java/WinAggImplementor.java
index 5190a30..34f8389 100644
--- a/core/src/main/java/net/hydromatic/optiq/rules/java/WinAggImplementor.java
+++ b/core/src/main/java/net/hydromatic/optiq/rules/java/WinAggImplementor.java
@@ -17,18 +17,14 @@
*/
package net.hydromatic.optiq.rules.java;
-import net.hydromatic.linq4j.expressions.Expression;
-
-import org.eigenbase.rex.RexNode;
-
-import java.util.List;
-
/**
* Implements a windowed aggregate function by generating expressions to
* initialize, add to, and get a result from, an accumulator.
* Windowed aggregate is more powerful than regular aggregate since it can
* access rows in the current partition by row indices.
* Regular aggregate can be used to implement windowed aggregate.
+ * <p>This interface does not define new methods: window-specific
+ * sub-interfaces are passed when implementing window aggregate.
*
* @see net.hydromatic.optiq.rules.java.StrictWinAggImplementor
* @see net.hydromatic.optiq.rules.java.RexImpTable.FirstLastValueImplementor
@@ -64,103 +60,7 @@ public interface WinAggImplementor extends AggImplementor {
END
}
- /**
- * Marker interface to allow {@link AggImplementor} to tell if it is used in
- * regular or windowed context.
- */
- public interface WinAggContext extends AggContext {
- }
-
- /**
- * Provides information on the current window.
- * All the indexes are ready to be used in {@link WinAggFrameResultContext#arguments(Expression)},
- * {@link WinAggFrameResultContext#rowTranslator(Expression)} and similar methods.
- */
- public interface WinAggFrameContext {
- /**
- * Returns the index of the current row in the partition.
- * In other words, it is close to ~ROWS BETWEEN CURRENT ROW.
- * Note to use {@link #startIndex()} when you need zero-based row position.
- * @return the index of the very first row in partition
- */
- Expression index();
-
- /**
- * Returns the index of the very first row in partition.
- * @return index of the very first row in partition
- */
- Expression startIndex();
-
- /**
- * Returns the index of the very last row in partition.
- * @return index of the very last row in partition
- */
- Expression endIndex();
-
- /**
- * Returns the boolean expression that tells if the partition has rows.
- * The partition might lack rows in cases like ROWS BETWEEN 1000 PRECEDING
- * AND 900 PRECEDING.
- * @return boolean expression that tells if the partition has rows
- */
- Expression hasRows();
-
- /**
- * Returns the number of rows in the current partition.
- * @return number of rows in the current partition or 0 if the partition
- * is empty
- */
- Expression getPartitionRowCount();
- }
-
- /**
- * Provides information on the current window when computing the result of
- * the aggregation.
- */
- public interface WinAggFrameResultContext {
- /**
- * Returns {@link RexNode} representation of arguments.
- * This can be useful for manual translation of required arguments with
- * different {@link net.hydromatic.optiq.rules.java.NullPolicy}.
- * @return {@link RexNode} representation of arguments
- */
- List<RexNode> rexArguments();
-
- /**
- * Returns Linq4j form of arguments.
- * The resulting value is equivalent to
- * {@code rowTranslator().translateList(rexArguments())}.
- * This is handy if you need just operate on argument.
- * @param rowIndex index of the requested row. The index must be in range
- * of partition's startIndex and endIndex.
- * @return Linq4j form of arguments of the particular row
- */
- List<Expression> arguments(Expression rowIndex);
-
- /**
- * Converts absolute index position of the given relative position.
- * @param offset offset of the requested row
- * @param seekType the type of offset (start of window, end of window, etc)
- * @return absolute position of the requested row
- */
- Expression computeIndex(Expression offset, SeekType seekType);
-
- /**
- * Returns row translator for given absolute row position.
- * @param rowIndex absolute index of the row.
- * @return translator for the requested row
- */
- RexToLixTranslator rowTranslator(Expression rowIndex);
-
- /**
- * Compares two rows given by absolute positions according to the order
- * collation of the current window.
- * @param a absolute index of the first row
- * @param b absolute index of the second row
- * @return result of comparison as as in {@link Comparable#compareTo}
- */
- Expression compareRows(Expression a, Expression b);
- }
+ boolean needCacheWhenFrameIntact();
}
// End WinAggImplementor.java
http://git-wip-us.apache.org/repos/asf/incubator-optiq/blob/99f39682/core/src/main/java/net/hydromatic/optiq/rules/java/WinAggResetContext.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/net/hydromatic/optiq/rules/java/WinAggResetContext.java b/core/src/main/java/net/hydromatic/optiq/rules/java/WinAggResetContext.java
index bfbe5ab..0baff8b 100644
--- a/core/src/main/java/net/hydromatic/optiq/rules/java/WinAggResetContext.java
+++ b/core/src/main/java/net/hydromatic/optiq/rules/java/WinAggResetContext.java
@@ -17,11 +17,6 @@
*/
package net.hydromatic.optiq.rules.java;
-import net.hydromatic.linq4j.expressions.BlockBuilder;
-import net.hydromatic.linq4j.expressions.Expression;
-
-import java.util.List;
-
/**
* Information for a call to {@link AggImplementor#implementReset(AggContext, AggResetContext)}.
* {@link AggResetContext} provides access to the accumulator variables
@@ -31,57 +26,8 @@ import java.util.List;
* In other words, the implementation should treat indices and partition row
* count as a hint to pre-size the collections.
*/
-public class WinAggResetContext extends AggResetContext
- implements WinAggImplementor.WinAggFrameContext {
- private final Expression index;
- private final Expression startIndex;
- private final Expression endIndex;
- private final Expression partitionRowCount;
- private final Expression hasRows;
-
- /**
- * Creates window aggregate reset context.
- * @param block code block that will contain the added initialization
- * @param accumulator accumulator variables that store the intermediate
- * aggregate state
- * @param index index of the current row in the partition
- * @param startIndex index of the very first row in partition
- * @param endIndex index of the very last row in partition
- * @param hasRows boolean expression that tells if the partition has rows
- * @param partitionRowCount number of rows in the current partition or
- * 0 if the partition is empty
- *
- */
- public WinAggResetContext(BlockBuilder block,
- List<Expression> accumulator, Expression index,
- Expression startIndex, Expression endIndex,
- Expression hasRows, Expression partitionRowCount) {
- super(block, accumulator);
- this.index = index;
- this.startIndex = startIndex;
- this.endIndex = endIndex;
- this.partitionRowCount = partitionRowCount;
- this.hasRows = hasRows;
- }
-
- public Expression index() {
- return index;
- }
-
- public Expression startIndex() {
- return startIndex;
- }
-
- public Expression endIndex() {
- return endIndex;
- }
-
- public Expression hasRows() {
- return hasRows;
- }
-
- public Expression getPartitionRowCount() {
- return partitionRowCount;
- }
+public interface WinAggResetContext
+ extends AggResetContext, WinAggFrameContext {
}
+// End WinAggResetContext.java
http://git-wip-us.apache.org/repos/asf/incubator-optiq/blob/99f39682/core/src/main/java/net/hydromatic/optiq/rules/java/WinAggResultContext.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/net/hydromatic/optiq/rules/java/WinAggResultContext.java b/core/src/main/java/net/hydromatic/optiq/rules/java/WinAggResultContext.java
index 9aa5a68..7d4131f 100644
--- a/core/src/main/java/net/hydromatic/optiq/rules/java/WinAggResultContext.java
+++ b/core/src/main/java/net/hydromatic/optiq/rules/java/WinAggResultContext.java
@@ -17,39 +17,38 @@
*/
package net.hydromatic.optiq.rules.java;
-import net.hydromatic.linq4j.expressions.BlockBuilder;
import net.hydromatic.linq4j.expressions.Expression;
+import org.eigenbase.rex.RexNode;
+
import java.util.List;
/**
* Information for a call to {@link AggImplementor#implementResult(AggContext, AggResultContext)}
* Typically, the aggregation implementation will convert {@link #accumulator()}
* to the resulting value of the aggregation.
- * The implementation MUST NOT destroy the cotents of {@link #accumulator()}.
- * Note: logically, {@link WinAggResultContext} should extend {@link WinAggResetContext},
- * however this would prohibit usage of the same {@link AggImplementor} for both
- * regular aggregate and window aggregate.
+ * The implementation MUST NOT destroy the contents of {@link #accumulator()}.
*/
-public abstract class WinAggResultContext
- extends AggResultContext
- implements WinAggImplementor.WinAggFrameContext,
- WinAggImplementor.WinAggFrameResultContext {
-
+public interface WinAggResultContext extends AggResultContext,
+ WinAggFrameResultContext {
/**
- * Creates window aggregate result context.
- * @param block code block that will contain the added initialization
- * @param accumulator accumulator variables that store the intermediate
- * aggregate state
+ * Returns {@link org.eigenbase.rex.RexNode} representation of arguments.
+ * This can be useful for manual translation of required arguments with
+ * different {@link NullPolicy}.
+ * @return {@link org.eigenbase.rex.RexNode} representation of arguments
*/
- public WinAggResultContext(BlockBuilder block,
- List<Expression> accumulator) {
- super(block, accumulator);
- }
+ List<RexNode> rexArguments();
- public final List<Expression> arguments(Expression rowIndex) {
- return rowTranslator(rowIndex).translateList(rexArguments());
- }
+ /**
+ * Returns Linq4j form of arguments.
+ * The resulting value is equivalent to
+ * {@code rowTranslator().translateList(rexArguments())}.
+ * This is handy if you need just operate on argument.
+ * @param rowIndex index of the requested row. The index must be in range
+ * of partition's startIndex and endIndex.
+ * @return Linq4j form of arguments of the particular row
+ */
+ List<Expression> arguments(Expression rowIndex);
}
// End WinAggResultContext.java
http://git-wip-us.apache.org/repos/asf/incubator-optiq/blob/99f39682/core/src/main/java/net/hydromatic/optiq/rules/java/impl/AggAddContextImpl.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/net/hydromatic/optiq/rules/java/impl/AggAddContextImpl.java b/core/src/main/java/net/hydromatic/optiq/rules/java/impl/AggAddContextImpl.java
new file mode 100644
index 0000000..a88ce18
--- /dev/null
+++ b/core/src/main/java/net/hydromatic/optiq/rules/java/impl/AggAddContextImpl.java
@@ -0,0 +1,39 @@
+/*
+// Licensed to Julian Hyde under one or more contributor license
+// agreements. See the NOTICE file distributed with this work for
+// additional information regarding copyright ownership.
+//
+// Julian Hyde licenses this file to you under the Apache License,
+// Version 2.0 (the "License"); you may not use this file except in
+// compliance with the License. You may obtain a copy of the License at:
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+*/
+package net.hydromatic.optiq.rules.java.impl;
+
+import net.hydromatic.linq4j.expressions.BlockBuilder;
+import net.hydromatic.linq4j.expressions.Expression;
+
+import net.hydromatic.optiq.rules.java.AggAddContext;
+
+import java.util.List;
+
+/**
+ * Implementation of {@link net.hydromatic.optiq.rules.java.AggAddContext}.
+ */
+public abstract class AggAddContextImpl extends AggResultContextImpl
+ implements AggAddContext {
+ public AggAddContextImpl(BlockBuilder block, List<Expression> accumulator) {
+ super(block, accumulator);
+ }
+
+ public final List<Expression> arguments() {
+ return rowTranslator().translateList(rexArguments());
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-optiq/blob/99f39682/core/src/main/java/net/hydromatic/optiq/rules/java/impl/AggResetContextImpl.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/net/hydromatic/optiq/rules/java/impl/AggResetContextImpl.java b/core/src/main/java/net/hydromatic/optiq/rules/java/impl/AggResetContextImpl.java
new file mode 100644
index 0000000..93d518f
--- /dev/null
+++ b/core/src/main/java/net/hydromatic/optiq/rules/java/impl/AggResetContextImpl.java
@@ -0,0 +1,51 @@
+/*
+// Licensed to Julian Hyde under one or more contributor license
+// agreements. See the NOTICE file distributed with this work for
+// additional information regarding copyright ownership.
+//
+// Julian Hyde licenses this file to you under the Apache License,
+// Version 2.0 (the "License"); you may not use this file except in
+// compliance with the License. You may obtain a copy of the License at:
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+*/
+package net.hydromatic.optiq.rules.java.impl;
+
+import net.hydromatic.linq4j.expressions.BlockBuilder;
+import net.hydromatic.linq4j.expressions.Expression;
+
+import net.hydromatic.optiq.rules.java.AggResetContext;
+import net.hydromatic.optiq.rules.java.NestedBlockBuilderImpl;
+
+import java.util.List;
+
+/**
+ * Implementation of {@link net.hydromatic.optiq.rules.java.AggResetContext}
+ */
+public class AggResetContextImpl extends NestedBlockBuilderImpl
+ implements AggResetContext {
+ private final List<Expression> accumulator;
+
+ /**
+ * Creates aggregate reset context
+ * @param block code block that will contain the added initialization
+ * @param accumulator accumulator variables that store the intermediate
+ * aggregate state
+ */
+ public AggResetContextImpl(BlockBuilder block, List<Expression> accumulator) {
+ super(block);
+ this.accumulator = accumulator;
+ }
+
+ public List<Expression> accumulator() {
+ return accumulator;
+ }
+}
+
+// End AggResetContext.java
http://git-wip-us.apache.org/repos/asf/incubator-optiq/blob/99f39682/core/src/main/java/net/hydromatic/optiq/rules/java/impl/AggResultContextImpl.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/net/hydromatic/optiq/rules/java/impl/AggResultContextImpl.java b/core/src/main/java/net/hydromatic/optiq/rules/java/impl/AggResultContextImpl.java
new file mode 100644
index 0000000..43d9190
--- /dev/null
+++ b/core/src/main/java/net/hydromatic/optiq/rules/java/impl/AggResultContextImpl.java
@@ -0,0 +1,44 @@
+/*
+// Licensed to Julian Hyde under one or more contributor license
+// agreements. See the NOTICE file distributed with this work for
+// additional information regarding copyright ownership.
+//
+// Julian Hyde licenses this file to you under the Apache License,
+// Version 2.0 (the "License"); you may not use this file except in
+// compliance with the License. You may obtain a copy of the License at:
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+*/
+package net.hydromatic.optiq.rules.java.impl;
+
+import net.hydromatic.linq4j.expressions.BlockBuilder;
+import net.hydromatic.linq4j.expressions.Expression;
+
+import net.hydromatic.optiq.rules.java.AggResultContext;
+
+import java.util.List;
+
+/**
+ * Implementation of {@link net.hydromatic.optiq.rules.java.AggResultContext}
+ */
+public class AggResultContextImpl extends AggResetContextImpl
+ implements AggResultContext {
+ /**
+ * Creates aggregate result context
+ * @param block code block that will contain the result calculation statements
+ * @param accumulator accumulator variables that store the intermediate
+ * aggregate state
+ */
+ public AggResultContextImpl(BlockBuilder block,
+ List<Expression> accumulator) {
+ super(block, accumulator);
+ }
+}
+
+// End AggResultContext.java
http://git-wip-us.apache.org/repos/asf/incubator-optiq/blob/99f39682/core/src/main/java/net/hydromatic/optiq/rules/java/impl/WinAggAddContextImpl.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/net/hydromatic/optiq/rules/java/impl/WinAggAddContextImpl.java b/core/src/main/java/net/hydromatic/optiq/rules/java/impl/WinAggAddContextImpl.java
new file mode 100644
index 0000000..1533415
--- /dev/null
+++ b/core/src/main/java/net/hydromatic/optiq/rules/java/impl/WinAggAddContextImpl.java
@@ -0,0 +1,53 @@
+/*
+// Licensed to Julian Hyde under one or more contributor license
+// agreements. See the NOTICE file distributed with this work for
+// additional information regarding copyright ownership.
+//
+// Julian Hyde licenses this file to you under the Apache License,
+// Version 2.0 (the "License"); you may not use this file except in
+// compliance with the License. You may obtain a copy of the License at:
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+*/
+package net.hydromatic.optiq.rules.java.impl;
+
+import net.hydromatic.linq4j.expressions.BlockBuilder;
+import net.hydromatic.linq4j.expressions.Expression;
+import net.hydromatic.linq4j.expressions.Expressions;
+
+import net.hydromatic.optiq.rules.java.RexToLixTranslator;
+import net.hydromatic.optiq.rules.java.WinAggAddContext;
+import net.hydromatic.optiq.rules.java.WinAggFrameResultContext;
+import net.hydromatic.optiq.rules.java.WinAggImplementor;
+
+import com.google.common.base.Function;
+
+import java.util.List;
+
+/**
+ * Implementation of {@link net.hydromatic.optiq.rules.java.WinAggAddContext}.
+ */
+public abstract class WinAggAddContextImpl extends WinAggResultContextImpl
+ implements WinAggAddContext {
+ public WinAggAddContextImpl(BlockBuilder block, List<Expression> accumulator,
+ Function<BlockBuilder, WinAggFrameResultContext> frame) {
+ super(block, accumulator, frame);
+ }
+
+ public final RexToLixTranslator rowTranslator() {
+ return rowTranslator(computeIndex(Expressions.constant(0),
+ WinAggImplementor.SeekType.AGG_INDEX));
+ }
+
+ public final List<Expression> arguments() {
+ return rowTranslator().translateList(rexArguments());
+ }
+}
+
+// End WinAggAddContext.java
http://git-wip-us.apache.org/repos/asf/incubator-optiq/blob/99f39682/core/src/main/java/net/hydromatic/optiq/rules/java/impl/WinAggResetContextImpl.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/net/hydromatic/optiq/rules/java/impl/WinAggResetContextImpl.java b/core/src/main/java/net/hydromatic/optiq/rules/java/impl/WinAggResetContextImpl.java
new file mode 100644
index 0000000..15ed040
--- /dev/null
+++ b/core/src/main/java/net/hydromatic/optiq/rules/java/impl/WinAggResetContextImpl.java
@@ -0,0 +1,89 @@
+/*
+// Licensed to Julian Hyde under one or more contributor license
+// agreements. See the NOTICE file distributed with this work for
+// additional information regarding copyright ownership.
+//
+// Julian Hyde licenses this file to you under the Apache License,
+// Version 2.0 (the "License"); you may not use this file except in
+// compliance with the License. You may obtain a copy of the License at:
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+*/
+package net.hydromatic.optiq.rules.java.impl;
+
+import net.hydromatic.linq4j.expressions.BlockBuilder;
+import net.hydromatic.linq4j.expressions.Expression;
+
+import net.hydromatic.optiq.rules.java.WinAggResetContext;
+
+import java.util.List;
+
+/**
+ * Implementation of {@link net.hydromatic.optiq.rules.java.WinAggResetContext}.
+ */
+public class WinAggResetContextImpl extends AggResetContextImpl
+ implements WinAggResetContext {
+ private final Expression index;
+ private final Expression startIndex;
+ private final Expression endIndex;
+ private final Expression frameRowCount;
+ private final Expression partitionRowCount;
+ private final Expression hasRows;
+
+ /**
+ * Creates window aggregate reset context.
+ * @param block code block that will contain the added initialization
+ * @param accumulator accumulator variables that store the intermediate
+ * aggregate state
+ * @param index index of the current row in the partition
+ * @param startIndex index of the very first row in partition
+ * @param endIndex index of the very last row in partition
+ * @param hasRows boolean expression that tells if the partition has rows
+ * @param frameRowCount number of rows in the current frame
+ * @param partitionRowCount number of rows in the current partition
+ */
+ public WinAggResetContextImpl(BlockBuilder block,
+ List<Expression> accumulator, Expression index,
+ Expression startIndex, Expression endIndex,
+ Expression hasRows,
+ Expression frameRowCount, Expression partitionRowCount) {
+ super(block, accumulator);
+ this.index = index;
+ this.startIndex = startIndex;
+ this.endIndex = endIndex;
+ this.frameRowCount = frameRowCount;
+ this.partitionRowCount = partitionRowCount;
+ this.hasRows = hasRows;
+ }
+
+ public Expression index() {
+ return index;
+ }
+
+ public Expression startIndex() {
+ return startIndex;
+ }
+
+ public Expression endIndex() {
+ return endIndex;
+ }
+
+ public Expression hasRows() {
+ return hasRows;
+ }
+
+ public Expression getFrameRowCount() {
+ return frameRowCount;
+ }
+
+ public Expression getPartitionRowCount() {
+ return partitionRowCount;
+ }
+}
+
http://git-wip-us.apache.org/repos/asf/incubator-optiq/blob/99f39682/core/src/main/java/net/hydromatic/optiq/rules/java/impl/WinAggResultContextImpl.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/net/hydromatic/optiq/rules/java/impl/WinAggResultContextImpl.java b/core/src/main/java/net/hydromatic/optiq/rules/java/impl/WinAggResultContextImpl.java
new file mode 100644
index 0000000..f29cbd4
--- /dev/null
+++ b/core/src/main/java/net/hydromatic/optiq/rules/java/impl/WinAggResultContextImpl.java
@@ -0,0 +1,108 @@
+/*
+// Licensed to Julian Hyde under one or more contributor license
+// agreements. See the NOTICE file distributed with this work for
+// additional information regarding copyright ownership.
+//
+// Julian Hyde licenses this file to you under the Apache License,
+// Version 2.0 (the "License"); you may not use this file except in
+// compliance with the License. You may obtain a copy of the License at:
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+*/
+package net.hydromatic.optiq.rules.java.impl;
+
+import net.hydromatic.linq4j.expressions.BlockBuilder;
+import net.hydromatic.linq4j.expressions.Expression;
+
+import net.hydromatic.optiq.rules.java.RexToLixTranslator;
+import net.hydromatic.optiq.rules.java.WinAggFrameResultContext;
+import net.hydromatic.optiq.rules.java.WinAggImplementor;
+import net.hydromatic.optiq.rules.java.WinAggResultContext;
+
+import com.google.common.base.Function;
+
+import java.util.List;
+
+/**
+ * Implementation of {@link net.hydromatic.optiq.rules.java.WinAggResultContext}.
+ */
+public abstract class WinAggResultContextImpl extends AggResultContextImpl
+ implements WinAggResultContext {
+
+ private final Function<BlockBuilder, WinAggFrameResultContext> frame;
+
+ /**
+ * Creates window aggregate result context.
+ * @param block code block that will contain the added initialization
+ * @param accumulator accumulator variables that store the intermediate
+ * aggregate state
+ */
+ public WinAggResultContextImpl(BlockBuilder block,
+ List<Expression> accumulator,
+ Function<BlockBuilder, WinAggFrameResultContext> frameContextBuilder) {
+ super(block, accumulator);
+ this.frame = frameContextBuilder;
+ }
+
+ private WinAggFrameResultContext getFrame() {
+ return frame.apply(currentBlock());
+ }
+
+ public final List<Expression> arguments(Expression rowIndex) {
+ return rowTranslator(rowIndex).translateList(rexArguments());
+ }
+
+ public Expression computeIndex(Expression offset,
+ WinAggImplementor.SeekType seekType) {
+ return getFrame().computeIndex(offset, seekType);
+ }
+
+ public Expression rowInFrame(Expression rowIndex) {
+ return getFrame().rowInFrame(rowIndex);
+ }
+
+ public Expression rowInPartition(Expression rowIndex) {
+ return getFrame().rowInPartition(rowIndex);
+ }
+
+ public RexToLixTranslator rowTranslator(Expression rowIndex) {
+ return getFrame().rowTranslator(rowIndex)
+ .setNullable(currentNullables());
+ }
+
+ public Expression compareRows(Expression a, Expression b) {
+ return getFrame().compareRows(a, b);
+ }
+
+ public Expression index() {
+ return getFrame().index();
+ }
+
+ public Expression startIndex() {
+ return getFrame().startIndex();
+ }
+
+ public Expression endIndex() {
+ return getFrame().endIndex();
+ }
+
+ public Expression hasRows() {
+ return getFrame().hasRows();
+ }
+
+ public Expression getFrameRowCount() {
+ return getFrame().getFrameRowCount();
+ }
+
+ public Expression getPartitionRowCount() {
+ return getFrame().getPartitionRowCount();
+ }
+}
+
+// End WinAggResultContext.java
http://git-wip-us.apache.org/repos/asf/incubator-optiq/blob/99f39682/core/src/main/java/net/hydromatic/optiq/rules/java/impl/package-info.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/net/hydromatic/optiq/rules/java/impl/package-info.java b/core/src/main/java/net/hydromatic/optiq/rules/java/impl/package-info.java
new file mode 100644
index 0000000..1c019c8
--- /dev/null
+++ b/core/src/main/java/net/hydromatic/optiq/rules/java/impl/package-info.java
@@ -0,0 +1,24 @@
+/*
+// Licensed to Julian Hyde under one or more contributor license
+// agreements. See the NOTICE file distributed with this work for
+// additional information regarding copyright ownership.
+//
+// Julian Hyde licenses this file to you under the Apache License,
+// Version 2.0 (the "License"); you may not use this file except in
+// compliance with the License. You may obtain a copy of the License at:
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+*/
+
+/**
+ * Optiq-specific classes for implementation of regular and window aggregates.
+ */
+package net.hydromatic.optiq.rules.java.impl;
+
+// End package-info.java