提交 5ea4c890 authored 作者: Evgenij Ryazanov's avatar Evgenij Ryazanov

Fix window functions with order but without frame

上级 04415644
......@@ -75,37 +75,39 @@ public abstract class AbstractAggregate extends DataAnalysisOperation {
protected void getOrderedResultLoop(Session session, HashMap<Integer, Value> result, ArrayList<Value[]> ordered,
int rowIdColumn) {
WindowFrame frame = over.getWindowFrame();
if (frame == null || frame.isDefault()) {
// Aggregate all values before the current row (including)
Object aggregateData = createAggregateData();
for (Value[] row : ordered) {
// Collect values one by one
updateFromExpressions(session, aggregateData, row);
result.put(row[rowIdColumn].getInt(), getAggregatedValue(session, aggregateData));
if (frame == null) {
if (over.getOrderBy() == null) {
aggregateWholePartition(session, result, ordered, rowIdColumn);
return;
}
} else if (frame.isFullPartition()) {
// Aggregate values from the whole partition
Object aggregateData = createAggregateData();
for (Value[] row : ordered) {
updateFromExpressions(session, aggregateData, row);
aggregateWholePartition(session, result, ordered, rowIdColumn);
return;
}
// All rows have the same value
Value value = getAggregatedValue(session, aggregateData);
for (Value[] row : ordered) {
result.put(row[rowIdColumn].getInt(), value);
}
} else {
// All other types of frames (slow)
int size = ordered.size();
for (int i = 0; i < size; i++) {
Object aggregateData = createAggregateData();
for (Iterator<Value[]> iter = frame.iterator(session, ordered, getOverOrderBySort(), i, false); iter
.hasNext();) {
for (Iterator<Value[]> iter = WindowFrame.iterator(over, session, ordered, getOverOrderBySort(), i,
false); iter.hasNext();) {
updateFromExpressions(session, aggregateData, iter.next());
}
result.put(ordered.get(i)[rowIdColumn].getInt(), getAggregatedValue(session, aggregateData));
}
}
private void aggregateWholePartition(Session session, HashMap<Integer, Value> result, ArrayList<Value[]> ordered,
int rowIdColumn) {
// Aggregate values from the whole partition
Object aggregateData = createAggregateData();
for (Value[] row : ordered) {
updateFromExpressions(session, aggregateData, row);
}
// All rows have the same value
Value value = getAggregatedValue(session, aggregateData);
for (Value[] row : ordered) {
result.put(row[rowIdColumn].getInt(), value);
}
}
/**
......
......@@ -224,7 +224,7 @@ public final class Window {
}
}
appendOrderBy(builder, orderBy);
if (frame != null && !frame.isDefault()) {
if (frame != null) {
if (builder.charAt(builder.length() - 1) != '(') {
builder.append(' ');
}
......
......@@ -192,8 +192,8 @@ public final class WindowFrame {
* Returns iterator for the specified frame, or default iterator if frame is
* null.
*
* @param frame
* window frame, or null
* @param over
* window
* @param session
* the session
* @param orderedRows
......@@ -207,10 +207,16 @@ public final class WindowFrame {
*
* @return iterator
*/
public static Iterator<Value[]> iterator(WindowFrame frame, Session session, ArrayList<Value[]> orderedRows,
public static Iterator<Value[]> iterator(Window over, Session session, ArrayList<Value[]> orderedRows,
SortOrder sortOrder, int currentRow, boolean reverse) {
return frame != null ? frame.iterator(session, orderedRows, sortOrder, currentRow, reverse)
: plainIterator(orderedRows, 0, currentRow, reverse);
WindowFrame frame = over.getWindowFrame();
if (frame != null) {
return frame.iterator(session, orderedRows, sortOrder, currentRow, reverse);
}
int endIndex = orderedRows.size() - 1;
return plainIterator(orderedRows, 0,
over.getOrderBy() == null ? endIndex : toGroupEnd(orderedRows, sortOrder, currentRow, endIndex),
reverse);
}
private static Iterator<Value[]> plainIterator(ArrayList<Value[]> orderedRows, int startIndex, int endIndex,
......@@ -314,16 +320,6 @@ public final class WindowFrame {
&& s.compareTo(f) <= 0;
}
/**
* Returns whether window frame specification can be omitted.
*
* @return whether window frame specification can be omitted
*/
public boolean isDefault() {
return starting.getType() == WindowFrameBoundType.UNBOUNDED_PRECEDING && following == null
&& exclusion == WindowFrameExclusion.EXCLUDE_NO_OTHERS;
}
/**
* Returns whether window frame specification contains all rows in
* partition.
......
......@@ -345,17 +345,16 @@ public class WindowFunction extends DataAnalysisOperation {
private void getNth(Session session, HashMap<Integer, Value> result, ArrayList<Value[]> ordered, int rowIdColumn) {
int size = ordered.size();
for (int i = 0; i < size; i++) {
WindowFrame frame = over.getWindowFrame();
Value[] row = ordered.get(i);
int rowId = row[rowIdColumn].getInt();
Value v;
switch (type) {
case FIRST_VALUE:
v = getNthValue(WindowFrame.iterator(frame, session, ordered, getOverOrderBySort(), i, false), 0,
v = getNthValue(WindowFrame.iterator(over, session, ordered, getOverOrderBySort(), i, false), 0,
ignoreNulls);
break;
case LAST_VALUE:
v = getNthValue(WindowFrame.iterator(frame, session, ordered, getOverOrderBySort(), i, true), 0,
v = getNthValue(WindowFrame.iterator(over, session, ordered, getOverOrderBySort(), i, true), 0,
ignoreNulls);
break;
case NTH_VALUE: {
......@@ -364,7 +363,7 @@ public class WindowFunction extends DataAnalysisOperation {
throw DbException.getInvalidValueException("nth row", n);
}
n--;
Iterator<Value[]> iter = WindowFrame.iterator(frame, session, ordered, getOverOrderBySort(), i,
Iterator<Value[]> iter = WindowFrame.iterator(over, session, ordered, getOverOrderBySort(), i,
fromLast);
v = getNthValue(iter, n, ignoreNulls);
break;
......
......@@ -94,3 +94,13 @@ SELECT I, C, COUNT(I) OVER (PARTITION BY C) CNT FROM
> 4 2 3
> 5 2 3
> rows: 5
SELECT X, COUNT(*) OVER (ORDER BY X) C FROM VALUES (1), (1), (2), (2), (3) V(X);
> X C
> - -
> 1 2
> 1 2
> 2 4
> 2 4
> 3 5
> rows: 5
......@@ -219,3 +219,13 @@ SELECT ID, CATEGORY,
DROP TABLE TEST;
> ok
SELECT I, X, LAST_VALUE(I) OVER (ORDER BY X) L FROM VALUES (1, 1), (2, 1), (3, 2), (4, 2), (5, 3) V(I, X);
> I X L
> - - -
> 1 1 2
> 2 1 2
> 3 2 4
> 4 2 4
> 5 3 5
> rows: 5
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论