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

Reject invalid usages of window frames in optimize()

上级 0ef8cba8
...@@ -2555,7 +2555,7 @@ ROWS|RANGE|GROUP ...@@ -2555,7 +2555,7 @@ ROWS|RANGE|GROUP
[EXCLUDE {CURRENT ROW|GROUP|TIES|NO OTHERS}] [EXCLUDE {CURRENT ROW|GROUP|TIES|NO OTHERS}]
"," ","
A window frame clause. A window frame clause.
Is currently supported only in aggregates and FIRST_VALUE(), LAST_VALUE(), and NTH_VALUE() window functions. May be specified only for aggregates and FIRST_VALUE(), LAST_VALUE(), and NTH_VALUE() window functions.
"," ","
RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW EXCLUDE GROUP RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW EXCLUDE GROUP
" "
......
...@@ -3049,7 +3049,7 @@ public class Parser { ...@@ -3049,7 +3049,7 @@ public class Parser {
} }
Window over = null; Window over = null;
if (readIf("OVER")) { if (readIf("OVER")) {
over = readWindowSpecification(aggregate); over = readWindowSpecification();
aggregate.setOverCondition(over); aggregate.setOverCondition(over);
currentSelect.setWindowQuery(); currentSelect.setWindowQuery();
} else if (!isAggregate) { } else if (!isAggregate) {
...@@ -3059,7 +3059,7 @@ public class Parser { ...@@ -3059,7 +3059,7 @@ public class Parser {
} }
} }
private Window readWindowSpecification(AbstractAggregate aggregate) { private Window readWindowSpecification() {
read(OPEN_PAREN); read(OPEN_PAREN);
ArrayList<Expression> partitionBy = null; ArrayList<Expression> partitionBy = null;
if (readIf("PARTITION")) { if (readIf("PARTITION")) {
...@@ -3075,21 +3075,7 @@ public class Parser { ...@@ -3075,21 +3075,7 @@ public class Parser {
read("BY"); read("BY");
orderBy = parseSimpleOrderList(); orderBy = parseSimpleOrderList();
} }
WindowFrame frame; WindowFrame frame = readWindowFrame();
if (aggregate instanceof WindowFunction) {
WindowFunction w = (WindowFunction) aggregate;
switch (w.getFunctionType()) {
case FIRST_VALUE:
case LAST_VALUE:
case NTH_VALUE:
frame = readWindowFrame();
break;
default:
frame = null;
}
} else {
frame = readWindowFrame();
}
read(CLOSE_PAREN); read(CLOSE_PAREN);
return new Window(partitionBy, orderBy, frame); return new Window(partitionBy, orderBy, frame);
} }
......
...@@ -177,7 +177,7 @@ public final class Window { ...@@ -177,7 +177,7 @@ public final class Window {
* @see Expression#getSQL() * @see Expression#getSQL()
*/ */
public String getSQL() { public String getSQL() {
if (partitionBy == null && orderBy == null) { if (partitionBy == null && orderBy == null && frame == null) {
return "OVER ()"; return "OVER ()";
} }
StringBuilder builder = new StringBuilder().append("OVER ("); StringBuilder builder = new StringBuilder().append("OVER (");
...@@ -192,7 +192,10 @@ public final class Window { ...@@ -192,7 +192,10 @@ public final class Window {
} }
appendOrderBy(builder, orderBy); appendOrderBy(builder, orderBy);
if (frame != null && !frame.isDefault()) { if (frame != null && !frame.isDefault()) {
builder.append(' ').append(frame.getSQL()); if (builder.charAt(builder.length() - 1) != '(') {
builder.append(' ');
}
builder.append(frame.getSQL());
} }
return builder.append(')').toString(); return builder.append(')').toString();
} }
......
...@@ -400,6 +400,17 @@ public class WindowFunction extends AbstractAggregate { ...@@ -400,6 +400,17 @@ public class WindowFunction extends AbstractAggregate {
@Override @Override
public Expression optimize(Session session) { public Expression optimize(Session session) {
if (over.getWindowFrame() != null) {
switch (type) {
case FIRST_VALUE:
case LAST_VALUE:
case NTH_VALUE:
break;
default:
String sql = getSQL();
throw DbException.getSyntaxError(sql, sql.length() - 1);
}
}
super.optimize(session); super.optimize(session);
if (args != null) { if (args != null) {
for (int i = 0; i < args.length; i++) { for (int i = 0; i < args.length; i++) {
......
...@@ -129,5 +129,11 @@ SELECT LEAD(VALUE, -1) OVER (ORDER BY ID) FROM TEST; ...@@ -129,5 +129,11 @@ SELECT LEAD(VALUE, -1) OVER (ORDER BY ID) FROM TEST;
SELECT LAG(VALUE, -1) OVER (ORDER BY ID) FROM TEST; SELECT LAG(VALUE, -1) OVER (ORDER BY ID) FROM TEST;
> exception INVALID_VALUE_2 > exception INVALID_VALUE_2
SELECT LEAD(VALUE) OVER (ORDER BY ID RANGE CURRENT ROW) FROM TEST;
> exception SYNTAX_ERROR_1
SELECT LAG(VALUE) OVER (ORDER BY ID RANGE CURRENT ROW) FROM TEST;
> exception SYNTAX_ERROR_1
DROP TABLE TEST; DROP TABLE TEST;
> ok > ok
...@@ -113,3 +113,5 @@ SELECT NTILE(X) OVER (ORDER BY X) FROM (SELECT * FROM SYSTEM_RANGE(1, 6)); ...@@ -113,3 +113,5 @@ SELECT NTILE(X) OVER (ORDER BY X) FROM (SELECT * FROM SYSTEM_RANGE(1, 6));
> 6 > 6
> rows (ordered): 6 > rows (ordered): 6
SELECT NTILE(X) OVER (ORDER BY X RANGE CURRENT ROW) FROM (SELECT * FROM SYSTEM_RANGE(1, 1));
> exception SYNTAX_ERROR_1
...@@ -100,6 +100,21 @@ SELECT ...@@ -100,6 +100,21 @@ SELECT
> 4 1 1 0.0 1.0 > 4 1 1 0.0 1.0
> rows: 4 > rows: 4
SELECT ROW_NUMBER() OVER (ORDER BY ID RANGE CURRENT ROW) FROM TEST;
> exception SYNTAX_ERROR_1
SELECT RANK() OVER (ORDER BY ID RANGE CURRENT ROW) FROM TEST;
> exception SYNTAX_ERROR_1
SELECT DENSE_RANK() OVER (ORDER BY ID RANGE CURRENT ROW) FROM TEST;
> exception SYNTAX_ERROR_1
SELECT PERCENT_RANK() OVER (ORDER BY ID RANGE CURRENT ROW) FROM TEST;
> exception SYNTAX_ERROR_1
SELECT CUME_DIST() OVER (ORDER BY ID RANGE CURRENT ROW) FROM TEST;
> exception SYNTAX_ERROR_1
DROP TABLE TEST; DROP TABLE TEST;
> ok > ok
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论