提交 b3f9834d authored 作者: Evgenij Ryazanov's avatar Evgenij Ryazanov

Remember expression index in window frame bound

上级 05ea7099
......@@ -95,13 +95,12 @@ public abstract class AbstractAggregate extends DataAnalysisOperation {
boolean grouped = frame == null
|| frame.getUnits() != WindowFrameUnits.ROWS && frame.getExclusion().isGroupOrNoOthers();
if (frame == null) {
aggregateFastPartition(session, result, ordered, -1, rowIdColumn, grouped);
aggregateFastPartition(session, result, ordered, rowIdColumn, grouped);
return;
}
int frameParametersOffset = getWindowFrameParametersOffset();
boolean variableBounds = frame.isVariableBounds();
if (variableBounds) {
variableBounds = checkVariableBounds(frame, ordered, frameParametersOffset);
variableBounds = checkVariableBounds(frame, ordered);
}
if (variableBounds) {
grouped = false;
......@@ -113,12 +112,12 @@ public abstract class AbstractAggregate extends DataAnalysisOperation {
if (unboundedFollowing) {
aggregateWholePartition(session, result, ordered, rowIdColumn);
} else {
aggregateFastPartition(session, result, ordered, frameParametersOffset, rowIdColumn, grouped);
aggregateFastPartition(session, result, ordered, rowIdColumn, grouped);
}
return;
}
if (unboundedFollowing) {
aggregateFastPartitionInReverse(session, result, ordered, frameParametersOffset, rowIdColumn, grouped);
aggregateFastPartitionInReverse(session, result, ordered, rowIdColumn, grouped);
return;
}
}
......@@ -126,8 +125,8 @@ public abstract class AbstractAggregate extends DataAnalysisOperation {
int size = ordered.size();
for (int i = 0; i < size;) {
Object aggregateData = createAggregateData();
for (Iterator<Value[]> iter = WindowFrame.iterator(over, session, ordered, getOverOrderBySort(),
frameParametersOffset, i, false); iter.hasNext();) {
for (Iterator<Value[]> iter = WindowFrame.iterator(over, session, ordered, getOverOrderBySort(), i,
false); iter.hasNext();) {
updateFromExpressions(session, aggregateData, iter.next());
}
Value r = getAggregatedValue(session, aggregateData);
......@@ -135,20 +134,21 @@ public abstract class AbstractAggregate extends DataAnalysisOperation {
}
}
private static boolean checkVariableBounds(WindowFrame frame, ArrayList<Value[]> ordered,
int frameParametersOffset) {
private static boolean checkVariableBounds(WindowFrame frame, ArrayList<Value[]> ordered) {
int size = ordered.size();
int offset = frameParametersOffset;
if (frame.getStarting().isVariable()) {
WindowFrameBound bound = frame.getStarting();
if (bound.isVariable()) {
int offset = bound.getExpressionIndex();
Value v = ordered.get(0)[offset];
for (int i = 1; i < size; i++) {
if (!v.equals(ordered.get(i)[offset])) {
return true;
}
}
offset++;
}
if (frame.getFollowing() != null && frame.getFollowing().isVariable()) {
bound = frame.getFollowing();
if (bound != null && bound.isVariable()) {
int offset = bound.getExpressionIndex();
Value v = ordered.get(0)[offset];
for (int i = 1; i < size; i++) {
if (!v.equals(ordered.get(i)[offset])) {
......@@ -160,14 +160,13 @@ public abstract class AbstractAggregate extends DataAnalysisOperation {
}
private void aggregateFastPartition(Session session, HashMap<Integer, Value> result, ArrayList<Value[]> ordered,
int frameParametersOffset, int rowIdColumn, boolean grouped) {
int rowIdColumn, boolean grouped) {
Object aggregateData = createAggregateData();
int size = ordered.size();
int lastIncludedRow = -1;
Value r = null;
for (int i = 0; i < size;) {
int newLast = WindowFrame.getEndIndex(over, session, ordered, frameParametersOffset, getOverOrderBySort(),
i);
int newLast = WindowFrame.getEndIndex(over, session, ordered, getOverOrderBySort(), i);
assert newLast >= lastIncludedRow;
if (newLast > lastIncludedRow) {
for (int j = lastIncludedRow + 1; j <= newLast; j++) {
......@@ -183,13 +182,12 @@ public abstract class AbstractAggregate extends DataAnalysisOperation {
}
private void aggregateFastPartitionInReverse(Session session, HashMap<Integer, Value> result,
ArrayList<Value[]> ordered, int frameParametersOffset, int rowIdColumn, boolean grouped) {
ArrayList<Value[]> ordered, int rowIdColumn, boolean grouped) {
Object aggregateData = createAggregateData();
int firstIncludedRow = ordered.size();
Value r = null;
for (int i = firstIncludedRow - 1; i >= 0;) {
int newLast = over.getWindowFrame().getStartIndex(session, ordered, frameParametersOffset,
getOverOrderBySort(), i);
int newLast = over.getWindowFrame().getStartIndex(session, ordered, getOverOrderBySort(), i);
assert newLast <= firstIncludedRow;
if (newLast < firstIncludedRow) {
for (int j = firstIncludedRow - 1; j >= newLast; j--) {
......
......@@ -161,12 +161,19 @@ public abstract class DataAnalysisOperation extends Expression {
}
WindowFrame frame = over.getWindowFrame();
if (frame != null) {
int index = getNumExpressions();
if (orderBy != null) {
index += orderBy.size();
}
int n = 0;
if (frame.getStarting().isVariable()) {
WindowFrameBound bound = frame.getStarting();
if (bound.isVariable()) {
bound.setExpressionIndex(index);
n++;
}
WindowFrameBound following = frame.getFollowing();
if (following != null && following.isVariable()) {
bound = frame.getFollowing();
if (bound != null && bound.isVariable()) {
bound.setExpressionIndex(index + n);
n++;
}
numFrameExpressions = n;
......@@ -358,20 +365,6 @@ public abstract class DataAnalysisOperation extends Expression {
: getWindowResult(session, groupData);
}
/**
* Returns offset of window frame parameters.
*
* @return offset of window frame parameters
*/
protected final int getWindowFrameParametersOffset() {
int frameParametersOffset = getNumExpressions();
ArrayList<SelectOrderBy> orderBy = over.getOrderBy();
if (orderBy != null) {
frameParametersOffset += orderBy.size();
}
return frameParametersOffset;
}
/**
* Returns result of this window function or window aggregate. This method
* is not used for plain aggregates.
......
......@@ -202,8 +202,6 @@ public final class WindowFrame {
* ordered rows
* @param sortOrder
* sort order
* @param frameParametersOffset
* offset of window frame parameters
* @param currentRow
* index of the current row
* @param reverse
......@@ -211,10 +209,10 @@ public final class WindowFrame {
* @return iterator
*/
public static Iterator<Value[]> iterator(Window over, Session session, ArrayList<Value[]> orderedRows,
SortOrder sortOrder, int frameParametersOffset, int currentRow, boolean reverse) {
SortOrder sortOrder, int currentRow, boolean reverse) {
WindowFrame frame = over.getWindowFrame();
if (frame != null) {
return frame.iterator(session, orderedRows, sortOrder, frameParametersOffset, currentRow, reverse);
return frame.iterator(session, orderedRows, sortOrder, currentRow, reverse);
}
int endIndex = orderedRows.size() - 1;
return plainIterator(orderedRows, 0,
......@@ -232,8 +230,6 @@ public final class WindowFrame {
* the session
* @param orderedRows
* ordered rows
* @param frameParametersOffset
* offset of window frame parameters
* @param sortOrder
* sort order
* @param currentRow
......@@ -243,11 +239,11 @@ public final class WindowFrame {
* if over is not null and its exclusion clause is not EXCLUDE
* NO OTHERS
*/
public static int getEndIndex(Window over, Session session, ArrayList<Value[]> orderedRows,
int frameParametersOffset, SortOrder sortOrder, int currentRow) {
public static int getEndIndex(Window over, Session session, ArrayList<Value[]> orderedRows, SortOrder sortOrder,
int currentRow) {
WindowFrame frame = over.getWindowFrame();
if (frame != null) {
return frame.getEndIndex(session, orderedRows, frameParametersOffset, sortOrder, currentRow);
return frame.getEndIndex(session, orderedRows, sortOrder, currentRow);
}
int endIndex = orderedRows.size() - 1;
return over.getOrderBy() == null ? endIndex : toGroupEnd(orderedRows, sortOrder, currentRow, endIndex);
......@@ -291,8 +287,8 @@ public final class WindowFrame {
return offset;
}
private static int getIntOffset(WindowFrameBound bound, Value[] values, int parameterOffset, Session session) {
Value v = bound.isVariable() ? values[parameterOffset] : bound.getValue().getValue(session);
private static int getIntOffset(WindowFrameBound bound, Value[] values, Session session) {
Value v = bound.isVariable() ? values[bound.getExpressionIndex()] : bound.getValue().getValue(session);
int value = v.getInt();
if (value < 0) {
throw DbException.getInvalidValueException("unsigned", value);
......@@ -301,20 +297,20 @@ public final class WindowFrame {
}
private static Value[] getCompareRow(Session session, ArrayList<Value[]> orderedRows, SortOrder sortOrder,
int currentRow, WindowFrameBound bound, int parameterOffset, boolean add) {
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, orderedRows.get(currentRow), parameterOffset, session)))
ValueExpression.get(getValueOffset(bound, orderedRows.get(currentRow), session))) //
.optimize(session).getValue(session);
return newRow;
}
private static Value getValueOffset(WindowFrameBound bound, Value[] values, int parameterOffset, Session session) {
Value value = bound.isVariable() ? values[parameterOffset] : bound.getValue().getValue(session);
private static Value getValueOffset(WindowFrameBound bound, Value[] values, Session session) {
Value value = bound.isVariable() ? values[bound.getExpressionIndex()] : bound.getValue().getValue(session);
if (value.getSignum() < 0) {
throw DbException.getInvalidValueException("unsigned", value.getTraceSQL());
}
......@@ -463,8 +459,6 @@ public final class WindowFrame {
* ordered rows
* @param sortOrder
* sort order
* @param frameParametersOffset
* offset of window frame parameters
* @param currentRow
* index of the current row
* @param reverse
......@@ -472,14 +466,9 @@ public final class WindowFrame {
* @return iterator
*/
public Iterator<Value[]> iterator(Session session, ArrayList<Value[]> orderedRows, SortOrder sortOrder,
int frameParametersOffset, int currentRow, boolean reverse) {
int followingOffset = frameParametersOffset;
if (starting.isVariable()) {
followingOffset++;
}
int startIndex = getIndex(session, orderedRows, sortOrder, currentRow, starting, frameParametersOffset, false);
int endIndex = following != null
? getIndex(session, orderedRows, sortOrder, currentRow, following, followingOffset, true)
int currentRow, boolean reverse) {
int startIndex = getIndex(session, orderedRows, sortOrder, currentRow, starting, false);
int endIndex = following != null ? getIndex(session, orderedRows, sortOrder, currentRow, following, true)
: units == WindowFrameUnits.ROWS ? currentRow
: toGroupEnd(orderedRows, sortOrder, currentRow, orderedRows.size() - 1);
if (endIndex < startIndex) {
......@@ -507,8 +496,6 @@ public final class WindowFrame {
* the session
* @param orderedRows
* ordered rows
* @param frameParametersOffset
* offset of window frame parameters
* @param sortOrder
* sort order
* @param currentRow
......@@ -517,12 +504,11 @@ public final class WindowFrame {
* @throws UnsupportedOperationException
* if exclusion clause is not EXCLUDE NO OTHERS
*/
public int getStartIndex(Session session, ArrayList<Value[]> orderedRows, int frameParametersOffset,
SortOrder sortOrder, int currentRow) {
public int getStartIndex(Session session, ArrayList<Value[]> orderedRows, SortOrder sortOrder, int currentRow) {
if (exclusion != WindowFrameExclusion.EXCLUDE_NO_OTHERS) {
throw new UnsupportedOperationException();
}
int startIndex = getIndex(session, orderedRows, sortOrder, currentRow, starting, frameParametersOffset, false);
int startIndex = getIndex(session, orderedRows, sortOrder, currentRow, starting, false);
if (startIndex < 0) {
startIndex = 0;
}
......@@ -536,8 +522,6 @@ public final class WindowFrame {
* the session
* @param orderedRows
* ordered rows
* @param frameParametersOffset
* offset of window frame parameters
* @param sortOrder
* sort order
* @param currentRow
......@@ -546,17 +530,11 @@ public final class WindowFrame {
* @throws UnsupportedOperationException
* if exclusion clause is not EXCLUDE NO OTHERS
*/
private int getEndIndex(Session session, ArrayList<Value[]> orderedRows, int frameParametersOffset,
SortOrder sortOrder, int currentRow) {
private int getEndIndex(Session session, ArrayList<Value[]> orderedRows, SortOrder sortOrder, int currentRow) {
if (exclusion != WindowFrameExclusion.EXCLUDE_NO_OTHERS) {
throw new UnsupportedOperationException();
}
int followingOffset = frameParametersOffset;
if (starting.isVariable()) {
followingOffset++;
}
int endIndex = following != null
? getIndex(session, orderedRows, sortOrder, currentRow, following, followingOffset, true)
int endIndex = following != null ? getIndex(session, orderedRows, sortOrder, currentRow, following, true)
: units == WindowFrameUnits.ROWS ? currentRow
: toGroupEnd(orderedRows, sortOrder, currentRow, orderedRows.size() - 1);
int size = orderedRows.size();
......@@ -567,7 +545,7 @@ public final class WindowFrame {
}
private int getIndex(Session session, ArrayList<Value[]> orderedRows, SortOrder sortOrder, int currentRow,
WindowFrameBound bound, int parameterOffset, boolean forFollowing) {
WindowFrameBound bound, boolean forFollowing) {
int size = orderedRows.size();
int last = size - 1;
int index;
......@@ -578,12 +556,12 @@ public final class WindowFrame {
case PRECEDING:
switch (units) {
case ROWS: {
int value = getIntOffset(bound, orderedRows.get(currentRow), parameterOffset, session);
int value = getIntOffset(bound, orderedRows.get(currentRow), session);
index = value > currentRow ? -1 : currentRow - value;
break;
}
case GROUPS: {
int value = getIntOffset(bound, orderedRows.get(currentRow), parameterOffset, session);
int value = getIntOffset(bound, orderedRows.get(currentRow), session);
if (!forFollowing) {
index = toGroupStart(orderedRows, sortOrder, currentRow, 0);
while (value > 0 && index > 0) {
......@@ -608,7 +586,7 @@ public final class WindowFrame {
}
case RANGE: {
index = currentRow;
Value[] row = getCompareRow(session, orderedRows, sortOrder, index, bound, parameterOffset, false);
Value[] row = getCompareRow(session, orderedRows, sortOrder, index, bound, false);
index = Collections.binarySearch(orderedRows, row, sortOrder);
if (index >= 0) {
if (!forFollowing) {
......@@ -653,13 +631,13 @@ public final class WindowFrame {
case FOLLOWING:
switch (units) {
case ROWS: {
int value = getIntOffset(bound, orderedRows.get(currentRow), parameterOffset, session);
int value = getIntOffset(bound, orderedRows.get(currentRow), session);
int rem = last - currentRow;
index = value > rem ? size : currentRow + value;
break;
}
case GROUPS: {
int value = getIntOffset(bound, orderedRows.get(currentRow), parameterOffset, session);
int value = getIntOffset(bound, orderedRows.get(currentRow), session);
if (forFollowing) {
index = toGroupEnd(orderedRows, sortOrder, currentRow, last);
while (value > 0 && index < last) {
......@@ -684,7 +662,7 @@ public final class WindowFrame {
}
case RANGE: {
index = currentRow;
Value[] row = getCompareRow(session, orderedRows, sortOrder, index, bound, parameterOffset, true);
Value[] row = getCompareRow(session, orderedRows, sortOrder, index, bound, true);
index = Collections.binarySearch(orderedRows, row, sortOrder);
if (index >= 0) {
if (forFollowing) {
......
......@@ -20,6 +20,8 @@ public class WindowFrameBound {
private boolean isVariable;
private int expressionIndex = -1;
/**
* Creates new instance of window frame bound.
*
......@@ -65,6 +67,25 @@ public class WindowFrameBound {
return isVariable;
}
/**
* Returns the index of preserved expression.
*
* @return the index of preserved expression, or -1
*/
public int getExpressionIndex() {
return expressionIndex;
}
/**
* Sets the index of preserved expression.
*
* @param expressionIndex
* the index to set
*/
void setExpressionIndex(int expressionIndex) {
this.expressionIndex = expressionIndex;
}
/**
* Map the columns of the resolver to expression columns.
*
......
......@@ -349,19 +349,18 @@ public class WindowFunction extends DataAnalysisOperation {
private void getNth(Session session, HashMap<Integer, Value> result, ArrayList<Value[]> ordered, int rowIdColumn) {
int size = ordered.size();
int frameParametersOffset = getWindowFrameParametersOffset();
for (int i = 0; i < size; i++) {
Value[] row = ordered.get(i);
int rowId = row[rowIdColumn].getInt();
Value v;
switch (type) {
case FIRST_VALUE:
v = getNthValue(WindowFrame.iterator(over, session, ordered, getOverOrderBySort(),
frameParametersOffset, i, false), 0, ignoreNulls);
v = getNthValue(WindowFrame.iterator(over, session, ordered, getOverOrderBySort(), i, false), 0,
ignoreNulls);
break;
case LAST_VALUE:
v = getNthValue(WindowFrame.iterator(over, session, ordered, getOverOrderBySort(),
frameParametersOffset, i, true), 0, ignoreNulls);
v = getNthValue(WindowFrame.iterator(over, session, ordered, getOverOrderBySort(), i, true), 0,
ignoreNulls);
break;
case NTH_VALUE: {
int n = row[1].getInt();
......@@ -369,8 +368,8 @@ public class WindowFunction extends DataAnalysisOperation {
throw DbException.getInvalidValueException("nth row", n);
}
n--;
Iterator<Value[]> iter = WindowFrame.iterator(over, session, ordered, getOverOrderBySort(),
frameParametersOffset, i, fromLast);
Iterator<Value[]> iter = WindowFrame.iterator(over, session, ordered, getOverOrderBySort(), i,
fromLast);
v = getNthValue(iter, n, ignoreNulls);
break;
}
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论