提交 3e61ab53 authored 作者: Evgenij Ryazanov's avatar Evgenij Ryazanov

Fix RANGE BETWEEN with same direction

上级 fca685a7
......@@ -182,20 +182,16 @@ public final class WindowFrame {
return value;
}
private static Value plus(Session session, ArrayList<Value[]> orderedRows, int currentRow, WindowFrameBound bound,
int index) {
return new BinaryOperation(OpType.PLUS, //
ValueExpression.get(orderedRows.get(currentRow)[index]),
ValueExpression.get(getValueOffset(bound, session))) //
.optimize(session).getValue(session);
}
private static Value minus(Session session, ArrayList<Value[]> orderedRows, int currentRow, WindowFrameBound bound,
int index) {
return new BinaryOperation(OpType.MINUS, //
ValueExpression.get(orderedRows.get(currentRow)[index]),
ValueExpression.get(getValueOffset(bound, session))) //
private static Value[] getCompareRow(Session session, ArrayList<Value[]> orderedRows, SortOrder sortOrder,
int currentRow, WindowFrameBound bound, boolean add) {
int sortIndex = sortOrder.getQueryColumnIndexes()[0];
OpType opType = add ^ (sortOrder.getSortTypes()[0] & SortOrder.DESCENDING) != 0 ? OpType.PLUS : OpType.MINUS;
Value[] row = orderedRows.get(currentRow);
Value[] newRow = row.clone();
newRow[sortIndex] = new BinaryOperation(opType, //
ValueExpression.get(row[sortIndex]), ValueExpression.get(getValueOffset(bound, session))) //
.optimize(session).getValue(session);
return newRow;
}
private static Value getValueOffset(WindowFrameBound bound, Session session) {
......@@ -273,6 +269,9 @@ public final class WindowFrame {
int endIndex = following != null ? getIndex(session, orderedRows, sortOrder, currentRow, following, true)
: currentRow;
if (endIndex < startIndex) {
startIndex = getIndex(session, orderedRows, sortOrder, currentRow, starting, false);
endIndex = following != null ? getIndex(session, orderedRows, sortOrder, currentRow, following, true)
: currentRow;
throw DbException.get(ErrorCode.SYNTAX_ERROR_1, getSQL());
}
int size = orderedRows.size();
......@@ -334,15 +333,25 @@ public final class WindowFrame {
}
case RANGE: {
index = currentRow;
int sortIndex = sortOrder.getQueryColumnIndexes()[0];
if ((sortOrder.getSortTypes()[0] & SortOrder.DESCENDING) != 0) {
Value c = plus(session, orderedRows, currentRow, bound, sortIndex);
while (index > 0 && session.getDatabase().compare(c, orderedRows.get(index - 1)[sortIndex]) >= 0) {
index--;
Value[] row = getCompareRow(session, orderedRows, sortOrder, index, bound, false);
index = Collections.binarySearch(orderedRows, row, sortOrder);
if (index >= 0) {
if (!forFollowing) {
while (index > 0 && sortOrder.compare(row, orderedRows.get(index - 1)) == 0) {
index--;
}
} else {
while (index < last && sortOrder.compare(row, orderedRows.get(index + 1)) == 0) {
index++;
}
}
} else {
Value c = minus(session, orderedRows, currentRow, bound, sortIndex);
while (index > 0 && session.getDatabase().compare(c, orderedRows.get(index - 1)[sortIndex]) <= 0) {
index = ~index;
if (!forFollowing) {
if (index == 0) {
index = -1;
}
} else {
index--;
}
}
......@@ -389,18 +398,24 @@ public final class WindowFrame {
}
case RANGE: {
index = currentRow;
int sortIndex = sortOrder.getQueryColumnIndexes()[0];
if ((sortOrder.getSortTypes()[0] & SortOrder.DESCENDING) != 0) {
Value c = minus(session, orderedRows, currentRow, bound, sortIndex);
while (index < last
&& session.getDatabase().compare(c, orderedRows.get(index + 1)[sortIndex]) <= 0) {
index++;
Value[] row = getCompareRow(session, orderedRows, sortOrder, index, bound, true);
index = Collections.binarySearch(orderedRows, row, sortOrder);
if (index >= 0) {
if (forFollowing) {
while (index < last && sortOrder.compare(row, orderedRows.get(index + 1)) == 0) {
index++;
}
} else {
while (index > 0 && sortOrder.compare(row, orderedRows.get(index - 1)) == 0) {
index--;
}
}
} else {
Value c = plus(session, orderedRows, currentRow, bound, sortIndex);
while (index < last
&& session.getDatabase().compare(c, orderedRows.get(index + 1)[sortIndex]) >= 0) {
index++;
index = ~index;
if (forFollowing) {
if (index != size) {
index--;
}
}
}
break;
......
......@@ -332,6 +332,24 @@ SELECT *, ARRAY_AGG(ID) OVER (ORDER BY ID ROWS BETWEEN 1 FOLLOWING AND 2 FOLLOWI
> 8 9 null
> rows (ordered): 4
SELECT *, ARRAY_AGG(ID) OVER (ORDER BY ID RANGE BETWEEN 2 PRECEDING AND 1 PRECEDING) FROM TEST FETCH FIRST 4 ROWS ONLY;
> ID VALUE ARRAY_AGG(ID) OVER (ORDER BY ID RANGE BETWEEN 2 PRECEDING AND 1 PRECEDING)
> -- ----- --------------------------------------------------------------------------
> 1 1 null
> 2 1 (1)
> 3 5 (1, 2)
> 4 8 (2, 3)
> rows (ordered): 4
SELECT *, ARRAY_AGG(ID) OVER (ORDER BY ID RANGE BETWEEN 1 FOLLOWING AND 2 FOLLOWING) FROM TEST OFFSET 4 ROWS;
> ID VALUE ARRAY_AGG(ID) OVER (ORDER BY ID RANGE BETWEEN 1 FOLLOWING AND 2 FOLLOWING)
> -- ----- --------------------------------------------------------------------------
> 5 8 (6, 7)
> 6 8 (7, 8)
> 7 9 (8)
> 8 9 null
> rows (ordered): 4
SELECT *,
ARRAY_AGG(ID) OVER (ORDER BY VALUE GROUPS BETWEEN UNBOUNDED PRECEDING AND 1 PRECEDING) U_P,
ARRAY_AGG(ID) OVER (ORDER BY VALUE GROUPS BETWEEN 2 PRECEDING AND 1 PRECEDING) P,
......@@ -371,3 +389,46 @@ SELECT *, ARRAY_AGG(ID) OVER (ORDER BY ID RANGE BETWEEN CURRENT ROW AND 1 PRECED
DROP TABLE TEST;
> ok
CREATE TABLE TEST (ID INT, VALUE INT);
> ok
INSERT INTO TEST VALUES
(1, 1),
(2, 1),
(3, 2),
(4, 2),
(5, 3),
(6, 3),
(7, 4),
(8, 4);
> update count: 8
SELECT *, ARRAY_AGG(ID) OVER (ORDER BY VALUE RANGE BETWEEN 2 PRECEDING AND 1 PRECEDING) FROM TEST;
> ID VALUE ARRAY_AGG(ID) OVER (ORDER BY VALUE RANGE BETWEEN 2 PRECEDING AND 1 PRECEDING)
> -- ----- -----------------------------------------------------------------------------
> 1 1 null
> 2 1 null
> 3 2 (1, 2)
> 4 2 (1, 2)
> 5 3 (1, 2, 3, 4)
> 6 3 (1, 2, 3, 4)
> 7 4 (3, 4, 5, 6)
> 8 4 (3, 4, 5, 6)
> rows (ordered): 8
SELECT *, ARRAY_AGG(ID) OVER (ORDER BY VALUE RANGE BETWEEN 1 FOLLOWING AND 2 FOLLOWING) FROM TEST;
> ID VALUE ARRAY_AGG(ID) OVER (ORDER BY VALUE RANGE BETWEEN 1 FOLLOWING AND 2 FOLLOWING)
> -- ----- -----------------------------------------------------------------------------
> 1 1 (3, 4, 5, 6)
> 2 1 (3, 4, 5, 6)
> 3 2 (5, 6, 7, 8)
> 4 2 (5, 6, 7, 8)
> 5 3 (7, 8)
> 6 3 (7, 8)
> 7 4 null
> 8 4 null
> rows (ordered): 8
DROP TABLE TEST;
> ok
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论