-
Notifications
You must be signed in to change notification settings - Fork 1.5k
[multistage] Initial (phase 1) Query runtime for window functions - empty OVER() and OVER(PARTITION BY) #10286
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
93ab5ca
0f80c6a
a1695e2
9134cd7
489ccca
4e27f47
ffec253
2a37006
ab4ab8f
7b6df18
6c2cd27
9eeb102
826f874
1c6af7d
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -20,36 +20,46 @@ | |
|
|
||
| import com.clearspring.analytics.util.Preconditions; | ||
| import java.util.ArrayList; | ||
| import java.util.Collections; | ||
somandal marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| import java.util.List; | ||
| import java.util.stream.Collectors; | ||
| import org.apache.calcite.rel.RelFieldCollation; | ||
| import org.apache.calcite.rel.core.Window; | ||
| import org.apache.calcite.rex.RexLiteral; | ||
| import org.apache.calcite.rex.RexWindowBound; | ||
| import org.apache.pinot.common.utils.DataSchema; | ||
| import org.apache.pinot.query.planner.logical.RexExpression; | ||
| import org.apache.pinot.query.planner.serde.ProtoProperties; | ||
|
|
||
|
|
||
| public class WindowNode extends AbstractStageNode { | ||
| @ProtoProperties | ||
| public List<RexExpression> _groupSet; | ||
| private List<RexExpression> _groupSet; | ||
| @ProtoProperties | ||
| public List<RexExpression> _orderSet; | ||
| private List<RexExpression> _orderSet; | ||
| @ProtoProperties | ||
| public List<RelFieldCollation.Direction> _orderSetDirection; | ||
| private List<RelFieldCollation.Direction> _orderSetDirection; | ||
| @ProtoProperties | ||
| public List<RelFieldCollation.NullDirection> _orderSetNullDirection; | ||
| private List<RelFieldCollation.NullDirection> _orderSetNullDirection; | ||
| @ProtoProperties | ||
| public List<RexExpression> _aggCalls; | ||
| private List<RexExpression> _aggCalls; | ||
| @ProtoProperties | ||
| public int _lowerBound; | ||
| private int _lowerBound; | ||
| @ProtoProperties | ||
| public int _upperBound; | ||
| @ProtoProperties | ||
| public boolean _isRows; | ||
| private int _upperBound; | ||
| @ProtoProperties | ||
| private List<RexExpression> _constants; | ||
| @ProtoProperties | ||
| private WindowFrameType _windowFrameType; | ||
|
|
||
| /** | ||
| * Enum to denote the type of window frame | ||
| * ROW - ROW type window frame | ||
| * RANGE - RANGE type window frame | ||
| */ | ||
| public enum WindowFrameType { | ||
| ROW, | ||
| RANGE | ||
| } | ||
|
|
||
| public WindowNode(int stageId) { | ||
| super(stageId); | ||
|
|
@@ -62,7 +72,7 @@ public WindowNode(int stageId, List<Window.Group> windowGroups, List<RexLiteral> | |
| String.format("Only a single window group is allowed! Number of window groups: %d", windowGroups.size())); | ||
| Window.Group windowGroup = windowGroups.get(0); | ||
|
|
||
| _groupSet = windowGroup.keys == null ? new ArrayList<>() : RexExpression.toRexInputRefs(windowGroup.keys); | ||
| _groupSet = windowGroup.keys == null ? Collections.emptyList() : RexExpression.toRexInputRefs(windowGroup.keys); | ||
| List<RelFieldCollation> relFieldCollations = windowGroup.orderKeys == null ? new ArrayList<>() | ||
| : windowGroup.orderKeys.getFieldCollations(); | ||
| _orderSet = new ArrayList<>(relFieldCollations.size()); | ||
|
|
@@ -79,12 +89,12 @@ public WindowNode(int stageId, List<Window.Group> windowGroups, List<RexLiteral> | |
| // Frame literals come in the constants from the LogicalWindow and the bound.getOffset() stores the | ||
| // InputRef to the constants array offset by the input array length. These need to be extracted here and | ||
| // set to the bounds. | ||
| validateFrameBounds(windowGroup.lowerBound, windowGroup.upperBound, windowGroup.isRows); | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. commented previously not sure isRows is a clear enough flag. let's name it
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. done - I renamed it here, and store it as an enum in
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. never mind, updated this to add the enum directly into |
||
|
|
||
| // Lower bound can only be unbounded preceding for now, set to Integer.MIN_VALUE | ||
| _lowerBound = Integer.MIN_VALUE; | ||
| // Upper bound can only be unbounded following or current row for now | ||
| _upperBound = windowGroup.upperBound.isUnbounded() ? Integer.MAX_VALUE : 0; | ||
| _isRows = windowGroup.isRows; | ||
| _windowFrameType = windowGroup.isRows ? WindowFrameType.ROW : WindowFrameType.RANGE; | ||
|
|
||
| // TODO: Constants are used to store constants needed such as the frame literals. For now just save this, need to | ||
| // extract the constant values into bounds as a part of frame support. | ||
|
|
@@ -132,26 +142,11 @@ public int getUpperBound() { | |
| return _upperBound; | ||
| } | ||
|
|
||
| public boolean isRows() { | ||
| return _isRows; | ||
| public WindowFrameType getWindowFrameType() { | ||
| return _windowFrameType; | ||
| } | ||
|
|
||
| public List<RexExpression> getConstants() { | ||
| return _constants; | ||
| } | ||
|
|
||
| private void validateFrameBounds(RexWindowBound lowerBound, RexWindowBound upperBound, boolean isRows) { | ||
| Preconditions.checkState(!isRows, "Only default frame is supported which must be RANGE and not ROWS"); | ||
| Preconditions.checkState(lowerBound.isPreceding() && lowerBound.isUnbounded() | ||
| && lowerBound.getOffset() == null, | ||
| String.format("Only default frame is supported, actual lower bound frame provided: %s", lowerBound)); | ||
| if (_orderSet.isEmpty()) { | ||
| Preconditions.checkState(upperBound.isFollowing() && upperBound.isUnbounded() | ||
| && upperBound.getOffset() == null, | ||
| String.format("Only default frame is supported, actual upper bound frame provided: %s", upperBound)); | ||
| } else { | ||
| Preconditions.checkState(upperBound.isCurrentRow() && upperBound.getOffset() == null, | ||
| String.format("Only default frame is supported, actual upper bound frame provided: %s", upperBound)); | ||
| } | ||
| } | ||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
what is the other function we've supported? can we add a comment for this? (i think it is BOOL_AND and BOOL_OR)
but IMO, BOOL_AND and BOOL_OR are just MIN(booleanCol) and MAX(booleanCol) :-P i didn't understand why we needed that in the first place lol
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah good point, I think we just saw that PostgreSQL has support for all aggregation functions and thought why not add what we have (at least the basic ones). Hope it's alright to leave this here. I've updated to add a comment here.