提交 122fa953 authored 作者: Evgenij Ryazanov's avatar Evgenij Ryazanov

Throw exception on NULL ranges or unsupported data types in window frames

上级 af273ca0
...@@ -19,6 +19,7 @@ import org.h2.message.DbException; ...@@ -19,6 +19,7 @@ import org.h2.message.DbException;
import org.h2.result.SortOrder; import org.h2.result.SortOrder;
import org.h2.table.ColumnResolver; import org.h2.table.ColumnResolver;
import org.h2.value.Value; import org.h2.value.Value;
import org.h2.value.ValueNull;
/** /**
* Window frame clause. * Window frame clause.
...@@ -290,8 +291,8 @@ public final class WindowFrame { ...@@ -290,8 +291,8 @@ public final class WindowFrame {
private static int getIntOffset(WindowFrameBound bound, Value[] values, Session session) { private static int getIntOffset(WindowFrameBound bound, Value[] values, Session session) {
Value v = bound.isVariable() ? values[bound.getExpressionIndex()] : bound.getValue().getValue(session); Value v = bound.isVariable() ? values[bound.getExpressionIndex()] : bound.getValue().getValue(session);
int value = v.getInt(); int value = v.getInt();
if (value < 0) { if (v == ValueNull.INSTANCE || value < 0) {
throw DbException.getInvalidValueException("unsigned", value); throw DbException.getInvalidValueException("unsigned range", v.getTraceSQL());
} }
return value; return value;
} }
...@@ -302,17 +303,47 @@ public final class WindowFrame { ...@@ -302,17 +303,47 @@ public final class WindowFrame {
OpType opType = add ^ (sortOrder.getSortTypes()[0] & SortOrder.DESCENDING) != 0 ? OpType.PLUS : OpType.MINUS; OpType opType = add ^ (sortOrder.getSortTypes()[0] & SortOrder.DESCENDING) != 0 ? OpType.PLUS : OpType.MINUS;
Value[] row = orderedRows.get(currentRow); Value[] row = orderedRows.get(currentRow);
Value[] newRow = row.clone(); Value[] newRow = row.clone();
newRow[sortIndex] = new BinaryOperation(opType, // Value currentValue = row[sortIndex];
ValueExpression.get(row[sortIndex]), switch (currentValue.getType()) {
ValueExpression.get(getValueOffset(bound, orderedRows.get(currentRow), session))) // case Value.BYTE:
.optimize(session).getValue(session); case Value.SHORT:
case Value.INT:
case Value.LONG:
case Value.DECIMAL:
case Value.DOUBLE:
case Value.FLOAT:
case Value.TIME:
case Value.DATE:
case Value.TIMESTAMP:
case Value.TIMESTAMP_TZ:
case Value.INTERVAL_YEAR:
case Value.INTERVAL_MONTH:
case Value.INTERVAL_DAY:
case Value.INTERVAL_HOUR:
case Value.INTERVAL_MINUTE:
case Value.INTERVAL_SECOND:
case Value.INTERVAL_YEAR_TO_MONTH:
case Value.INTERVAL_DAY_TO_HOUR:
case Value.INTERVAL_DAY_TO_MINUTE:
case Value.INTERVAL_DAY_TO_SECOND:
case Value.INTERVAL_HOUR_TO_MINUTE:
case Value.INTERVAL_HOUR_TO_SECOND:
case Value.INTERVAL_MINUTE_TO_SECOND:
break;
default:
throw DbException.getInvalidValueException("ORDER BY value for RANGE frame", currentValue.getTraceSQL());
}
Value range = getValueOffset(bound, orderedRows.get(currentRow), session);
Value newValue = new BinaryOperation(opType, ValueExpression.get(currentValue), ValueExpression.get(range))
.optimize(session).getValue(session);
newRow[sortIndex] = newValue;
return newRow; return newRow;
} }
private static Value getValueOffset(WindowFrameBound bound, Value[] values, Session session) { private static Value getValueOffset(WindowFrameBound bound, Value[] values, Session session) {
Value value = bound.isVariable() ? values[bound.getExpressionIndex()] : bound.getValue().getValue(session); Value value = bound.isVariable() ? values[bound.getExpressionIndex()] : bound.getValue().getValue(session);
if (value.getSignum() < 0) { if (value == ValueNull.INSTANCE || value.getSignum() < 0) {
throw DbException.getInvalidValueException("unsigned", value.getTraceSQL()); throw DbException.getInvalidValueException("unsigned range", value.getTraceSQL());
} }
return value; return value;
} }
......
...@@ -109,5 +109,17 @@ SELECT ROW_NUMBER() OVER (ORDER BY CATEGORY), SUM(ID) FROM TEST GROUP BY CATEGOR ...@@ -109,5 +109,17 @@ SELECT ROW_NUMBER() OVER (ORDER BY CATEGORY), SUM(ID) FROM TEST GROUP BY CATEGOR
> 1 12 > 1 12
> rows: 1 > rows: 1
SELECT SUM(ID) OVER (ORDER BY ID ROWS NULL PRECEDING) P FROM TEST;
> exception INVALID_VALUE_2
SELECT SUM(ID) OVER (ORDER BY ID RANGE NULL PRECEDING) P FROM TEST;
> exception INVALID_VALUE_2
SELECT SUM(V) OVER (ORDER BY V RANGE BETWEEN 1 PRECEDING AND 1 FOLLOWING) FROM VALUES (1), (NULL), (2) T(V);
> exception INVALID_VALUE_2
SELECT SUM(V) OVER (ORDER BY V RANGE BETWEEN 1 PRECEDING AND 1 FOLLOWING) FROM VALUES (TRUE) T(V);
> exception INVALID_VALUE_2
DROP TABLE TEST; DROP TABLE TEST;
> ok > ok
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论