use of org.apache.calcite.rel.logical.LogicalWindow in project calcite by apache.
the class ProjectWindowTransposeRule method onMatch.
@Override
public void onMatch(RelOptRuleCall call) {
final LogicalProject project = call.rel(0);
final LogicalWindow window = call.rel(1);
final RelOptCluster cluster = window.getCluster();
final List<RelDataTypeField> rowTypeWindowInput = window.getInput().getRowType().getFieldList();
final int windowInputColumn = rowTypeWindowInput.size();
// Record the window input columns which are actually referred
// either in the LogicalProject above LogicalWindow or LogicalWindow itself
// (Note that the constants used in LogicalWindow are not considered here)
final ImmutableBitSet beReferred = findReference(project, window);
// it is impossible to trim anyone of them out
if (beReferred.cardinality() == windowInputColumn) {
return;
}
// Put a DrillProjectRel below LogicalWindow
final List<RexNode> exps = new ArrayList<>();
final RelDataTypeFactory.Builder builder = cluster.getTypeFactory().builder();
// Keep only the fields which are referred
for (int index : BitSets.toIter(beReferred)) {
final RelDataTypeField relDataTypeField = rowTypeWindowInput.get(index);
exps.add(new RexInputRef(index, relDataTypeField.getType()));
builder.add(relDataTypeField);
}
final LogicalProject projectBelowWindow = new LogicalProject(cluster, window.getTraitSet(), window.getInput(), exps, builder.build());
// Create a new LogicalWindow with necessary inputs only
final List<Window.Group> groups = new ArrayList<>();
// As the un-referred columns are trimmed by the LogicalProject,
// the indices specified in LogicalWindow would need to be adjusted
final RexShuttle indexAdjustment = new RexShuttle() {
@Override
public RexNode visitInputRef(RexInputRef inputRef) {
final int newIndex = getAdjustedIndex(inputRef.getIndex(), beReferred, windowInputColumn);
return new RexInputRef(newIndex, inputRef.getType());
}
@Override
public RexNode visitCall(final RexCall call) {
if (call instanceof Window.RexWinAggCall) {
boolean[] update = { false };
final List<RexNode> clonedOperands = visitList(call.operands, update);
if (update[0]) {
return new Window.RexWinAggCall((SqlAggFunction) call.getOperator(), call.getType(), clonedOperands, ((Window.RexWinAggCall) call).ordinal, ((Window.RexWinAggCall) call).distinct);
} else {
return call;
}
} else {
return super.visitCall(call);
}
}
};
int aggCallIndex = windowInputColumn;
final RelDataTypeFactory.Builder outputBuilder = cluster.getTypeFactory().builder();
outputBuilder.addAll(projectBelowWindow.getRowType().getFieldList());
for (Window.Group group : window.groups) {
final ImmutableBitSet.Builder keys = ImmutableBitSet.builder();
final List<RelFieldCollation> orderKeys = new ArrayList<>();
final List<Window.RexWinAggCall> aggCalls = new ArrayList<>();
// Adjust keys
for (int index : group.keys) {
keys.set(getAdjustedIndex(index, beReferred, windowInputColumn));
}
// Adjust orderKeys
for (RelFieldCollation relFieldCollation : group.orderKeys.getFieldCollations()) {
final int index = relFieldCollation.getFieldIndex();
orderKeys.add(relFieldCollation.copy(getAdjustedIndex(index, beReferred, windowInputColumn)));
}
// Adjust Window Functions
for (Window.RexWinAggCall rexWinAggCall : group.aggCalls) {
aggCalls.add((Window.RexWinAggCall) rexWinAggCall.accept(indexAdjustment));
final RelDataTypeField relDataTypeField = window.getRowType().getFieldList().get(aggCallIndex);
outputBuilder.add(relDataTypeField);
++aggCallIndex;
}
groups.add(new Window.Group(keys.build(), group.isRows, group.lowerBound, group.upperBound, RelCollations.of(orderKeys), aggCalls));
}
final LogicalWindow newLogicalWindow = LogicalWindow.create(window.getTraitSet(), projectBelowWindow, window.constants, outputBuilder.build(), groups);
// Modify the top LogicalProject
final List<RexNode> topProjExps = new ArrayList<>();
for (RexNode rexNode : project.getChildExps()) {
topProjExps.add(rexNode.accept(indexAdjustment));
}
final LogicalProject newTopProj = project.copy(newLogicalWindow.getTraitSet(), newLogicalWindow, topProjExps, project.getRowType());
if (ProjectRemoveRule.isTrivial(newTopProj)) {
call.transformTo(newLogicalWindow);
} else {
call.transformTo(newTopProj);
}
}
use of org.apache.calcite.rel.logical.LogicalWindow in project calcite by apache.
the class EnumerableWindowRule method convert.
public RelNode convert(RelNode rel) {
final LogicalWindow winAgg = (LogicalWindow) rel;
final RelTraitSet traitSet = winAgg.getTraitSet().replace(EnumerableConvention.INSTANCE);
final RelNode child = winAgg.getInput();
final RelNode convertedChild = convert(child, child.getTraitSet().replace(EnumerableConvention.INSTANCE));
return new EnumerableWindow(rel.getCluster(), traitSet, convertedChild, winAgg.getConstants(), winAgg.getRowType(), winAgg.groups);
}
use of org.apache.calcite.rel.logical.LogicalWindow in project calcite by apache.
the class ProjectWindowTransposeRule method findReference.
private ImmutableBitSet findReference(final LogicalProject project, final LogicalWindow window) {
final int windowInputColumn = window.getInput().getRowType().getFieldCount();
final ImmutableBitSet.Builder beReferred = ImmutableBitSet.builder();
final RexShuttle referenceFinder = new RexShuttle() {
@Override
public RexNode visitInputRef(RexInputRef inputRef) {
final int index = inputRef.getIndex();
if (index < windowInputColumn) {
beReferred.set(index);
}
return inputRef;
}
};
// Reference in LogicalProject
for (RexNode rexNode : project.getChildExps()) {
rexNode.accept(referenceFinder);
}
// Reference in LogicalWindow
for (Window.Group group : window.groups) {
// Reference in Partition-By
for (int index : group.keys) {
if (index < windowInputColumn) {
beReferred.set(index);
}
}
// Reference in Order-By
for (RelFieldCollation relFieldCollation : group.orderKeys.getFieldCollations()) {
if (relFieldCollation.getFieldIndex() < windowInputColumn) {
beReferred.set(relFieldCollation.getFieldIndex());
}
}
// Reference in Window Functions
for (Window.RexWinAggCall rexWinAggCall : group.aggCalls) {
rexWinAggCall.accept(referenceFinder);
}
}
return beReferred.build();
}
Aggregations