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

Fix window functions with order but without frame

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