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

Add support for both preceding or both following bounds

上级 2170322c
......@@ -2551,7 +2551,7 @@ They also may require a lot of memory for large queries.
"Other Grammar","Window frame","
ROWS|RANGE|GROUP
{windowFramePreceding|BETWEEN windowFramePreceding AND windowFrameFollowing}
{windowFramePreceding|BETWEEN windowFrameBound AND windowFrameBound}
[EXCLUDE {CURRENT ROW|GROUP|TIES|NO OTHERS}]
","
A window frame clause.
......@@ -2571,12 +2571,14 @@ UNBOUNDED PRECEDING
CURRENT ROW
"
"Other Grammar","Window frame following","
UNBOUNDED FOLLOWING|value FOLLOWING|CURRENT ROW
"Other Grammar","Window frame bound","
UNBOUNDED PRECEDING|value PRECEDING|CURRENT ROW
|value FOLLOWING|UNBOUNDED FOLLOWING
","
A window frame following clause.
A window frame bound clause.
If value is specified it should be non-negative value or parameter.
","
UNBOUNDED PRECEDING
UNBOUNDED FOLLOWING
1 FOLLOWING
CURRENT ROW
......
......@@ -177,7 +177,7 @@ import org.h2.expression.aggregate.JavaAggregate;
import org.h2.expression.aggregate.Window;
import org.h2.expression.aggregate.WindowFrame;
import org.h2.expression.aggregate.WindowFrameBound;
import org.h2.expression.aggregate.WindowFrameBound.WindowFrameBoundType;
import org.h2.expression.aggregate.WindowFrameBoundType;
import org.h2.expression.aggregate.WindowFrameExclusion;
import org.h2.expression.aggregate.WindowFrameUnits;
import org.h2.expression.aggregate.WindowFunction;
......@@ -3105,9 +3105,9 @@ public class Parser {
}
WindowFrameBound starting, following;
if (readIf("BETWEEN")) {
starting = readWindowFrameStarting();
starting = readWindowFrameRange();
read("AND");
following = readWindowFrameFollowing();
following = readWindowFrameRange();
} else {
starting = readWindowFrameStarting();
following = null;
......@@ -3132,7 +3132,7 @@ public class Parser {
private WindowFrameBound readWindowFrameStarting() {
if (readIf("UNBOUNDED")) {
read("PRECEDING");
return new WindowFrameBound(WindowFrameBoundType.UNBOUNDED, null);
return new WindowFrameBound(WindowFrameBoundType.UNBOUNDED_PRECEDING, null);
}
if (readIf("CURRENT")) {
read("ROW");
......@@ -3140,21 +3140,27 @@ public class Parser {
}
Expression value = readValueOrParameter();
read("PRECEDING");
return new WindowFrameBound(WindowFrameBoundType.VALUE, value);
return new WindowFrameBound(WindowFrameBoundType.PRECEDING, value);
}
private WindowFrameBound readWindowFrameFollowing() {
private WindowFrameBound readWindowFrameRange() {
if (readIf("UNBOUNDED")) {
if (readIf("PRECEDING")) {
return new WindowFrameBound(WindowFrameBoundType.UNBOUNDED_PRECEDING, null);
}
read("FOLLOWING");
return new WindowFrameBound(WindowFrameBoundType.UNBOUNDED, null);
return new WindowFrameBound(WindowFrameBoundType.UNBOUNDED_FOLLOWING, null);
}
if (readIf("CURRENT")) {
read("ROW");
return new WindowFrameBound(WindowFrameBoundType.CURRENT_ROW, null);
}
Expression value = readValueOrParameter();
if (readIf("PRECEDING")) {
return new WindowFrameBound(WindowFrameBoundType.PRECEDING, value);
}
read("FOLLOWING");
return new WindowFrameBound(WindowFrameBoundType.VALUE, value);
return new WindowFrameBound(WindowFrameBoundType.FOLLOWING, value);
}
private Expression readValueOrParameter() {
......
......@@ -10,7 +10,6 @@ import java.util.ArrayList;
import org.h2.command.dml.SelectOrderBy;
import org.h2.engine.Session;
import org.h2.expression.Expression;
import org.h2.expression.aggregate.WindowFrameBound.WindowFrameBoundType;
import org.h2.result.SortOrder;
import org.h2.table.ColumnResolver;
import org.h2.table.TableFilter;
......@@ -66,8 +65,9 @@ public final class Window {
this.partitionBy = partitionBy;
this.orderBy = orderBy;
if (frame == null) {
frame = new WindowFrame(WindowFrameUnits.RANGE, new WindowFrameBound(WindowFrameBoundType.UNBOUNDED, null),
null, WindowFrameExclusion.EXCLUDE_NO_OTHERS);
frame = new WindowFrame(WindowFrameUnits.RANGE,
new WindowFrameBound(WindowFrameBoundType.UNBOUNDED_PRECEDING, null), null,
WindowFrameExclusion.EXCLUDE_NO_OTHERS);
}
this.frame = frame;
}
......
......@@ -6,35 +6,12 @@
package org.h2.expression.aggregate;
import org.h2.expression.Expression;
import org.h2.message.DbException;
/**
* Window frame bound.
*/
public class WindowFrameBound {
/**
* Window frame bound type.
*/
public enum WindowFrameBoundType {
/**
* UNBOUNDED PRECEDING or UNBOUNDED FOLLOWING clause.
*/
UNBOUNDED,
/**
* CURRENT_ROW clause.
*/
CURRENT_ROW,
/**
* PRECEDING or FOLLOWING clause.
*/
VALUE;
}
private final WindowFrameBoundType type;
private final Expression value;
......@@ -49,7 +26,7 @@ public class WindowFrameBound {
*/
public WindowFrameBound(WindowFrameBoundType type, Expression value) {
this.type = type;
if (type == WindowFrameBoundType.VALUE) {
if (type == WindowFrameBoundType.PRECEDING || type == WindowFrameBoundType.FOLLOWING) {
this.value = value;
} else {
this.value = null;
......@@ -84,16 +61,10 @@ public class WindowFrameBound {
* @see Expression#getSQL()
*/
public String getSQL(boolean following) {
switch (type) {
case UNBOUNDED:
return following ? "UNBOUNDED FOLLOWING" : "UNBOUNDED PRECEDING";
case CURRENT_ROW:
return "CURRENT ROW";
case VALUE:
return value.getSQL() + (following ? " FOLLOWING" : " PRECEDING");
default:
throw DbException.throwInternalError("type=" + type);
if (type == WindowFrameBoundType.PRECEDING || type == WindowFrameBoundType.FOLLOWING) {
return value.getSQL() + ' ' + type.getSQL();
}
return type.getSQL();
}
}
/*
* Copyright 2004-2018 H2 Group. Multiple-Licensed under the MPL 2.0,
* and the EPL 1.0 (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package org.h2.expression.aggregate;
/**
* Window frame bound type.
*/
public enum WindowFrameBoundType {
/**
* UNBOUNDED PRECEDING clause.
*/
UNBOUNDED_PRECEDING("UNBOUNDED PRECEDING"),
/**
* PRECEDING clause.
*/
PRECEDING("PRECEDING"),
/**
* CURRENT_ROW clause.
*/
CURRENT_ROW("CURRENT_ROW"),
/**
* FOLLOWING clause.
*/
FOLLOWING("FOLLOWING"),
/**
* UNBOUNDED FOLLOWING clause.
*/
UNBOUNDED_FOLLOWING("UNBOUNDED FOLLOWING");
private final String sql;
private WindowFrameBoundType(String sql) {
this.sql = sql;
}
/**
* Returns SQL representation.
*
* @return SQL representation.
* @see org.h2.expression.Expression#getSQL()
*/
public String getSQL() {
return sql;
}
}
......@@ -314,5 +314,17 @@ SELECT *,
SELECT *, ARRAY_AGG(ID) OVER (ORDER BY VALUE ROWS -1 PRECEDING) FROM TEST;
> exception INVALID_VALUE_2
SELECT *, ARRAY_AGG(ID) OVER (ORDER BY ID ROWS BETWEEN 2 PRECEDING AND 1 PRECEDING) FROM TEST FETCH FIRST 4 ROWS ONLY;
> ID VALUE ARRAY_AGG(ID) OVER (ORDER BY ID ROWS 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 CURRENT ROW AND 1 PRECEDING) FROM TEST;
> exception SYNTAX_ERROR_1
DROP TABLE TEST;
> ok
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论