This is an automated email from the ASF dual-hosted git repository.
xiedeyantu pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/calcite.git
The following commit(s) were added to refs/heads/main by this push:
new 1cf47f86a9 [CALCITE-7590] Improve error message for window functions
missing OVER clause to include function name
1cf47f86a9 is described below
commit 1cf47f86a9d798dd66a8425f529ed97c06820da9
Author: Zhen Chen <[email protected]>
AuthorDate: Sat Jun 6 22:32:15 2026 +0800
[CALCITE-7590] Improve error message for window functions missing OVER
clause to include function name
---
.../org/apache/calcite/runtime/CalciteResource.java | 4 ++--
.../java/org/apache/calcite/sql/SqlAggFunction.java | 2 +-
.../calcite/sql/validate/SqlValidatorImpl.java | 2 +-
.../calcite/runtime/CalciteResource.properties | 2 +-
.../org/apache/calcite/test/SqlValidatorTest.java | 20 ++++++++++----------
5 files changed, 15 insertions(+), 15 deletions(-)
diff --git a/core/src/main/java/org/apache/calcite/runtime/CalciteResource.java
b/core/src/main/java/org/apache/calcite/runtime/CalciteResource.java
index 40c680e2ee..a9cb02d065 100644
--- a/core/src/main/java/org/apache/calcite/runtime/CalciteResource.java
+++ b/core/src/main/java/org/apache/calcite/runtime/CalciteResource.java
@@ -341,8 +341,8 @@ ExInst<CalciteException> invalidCompare(String a0, String
a1, String a2,
ExInst<SqlValidatorException> naturalOrUsingColumnNotCompatible(String a0,
String a1, String a2);
- @BaseMessage("OVER clause is necessary for window functions")
- ExInst<SqlValidatorException> absentOverClause();
+ @BaseMessage("window function {0} requires an OVER clause")
+ ExInst<SqlValidatorException> absentOverClause(String a0);
@BaseMessage("MEASURE not valid in aggregate or DISTINCT query")
ExInst<SqlValidatorException> measureInAggregateQuery();
diff --git a/core/src/main/java/org/apache/calcite/sql/SqlAggFunction.java
b/core/src/main/java/org/apache/calcite/sql/SqlAggFunction.java
index 7ba19c48de..609bfee6d5 100644
--- a/core/src/main/java/org/apache/calcite/sql/SqlAggFunction.java
+++ b/core/src/main/java/org/apache/calcite/sql/SqlAggFunction.java
@@ -138,7 +138,7 @@ protected SqlAggFunction(
SqlValidatorScope operandScope) {
if (requiresOver() && !validator.isInWindow()) {
throw validator.newValidationError(call,
- Static.RESOURCE.absentOverClause());
+ Static.RESOURCE.absentOverClause(getName()));
}
super.validateCall(call, validator, scope, operandScope);
validator.validateAggregateParams(call, null, null, null, scope);
diff --git
a/core/src/main/java/org/apache/calcite/sql/validate/SqlValidatorImpl.java
b/core/src/main/java/org/apache/calcite/sql/validate/SqlValidatorImpl.java
index ae179400b0..370ef5ecc3 100644
--- a/core/src/main/java/org/apache/calcite/sql/validate/SqlValidatorImpl.java
+++ b/core/src/main/java/org/apache/calcite/sql/validate/SqlValidatorImpl.java
@@ -5528,7 +5528,7 @@ private void validateExpr(SqlNode expr, SqlValidatorScope
scope) {
final SqlOperator op = ((SqlCall) expr).getOperator();
if (op.isAggregator() && op.requiresOver()) {
throw newValidationError(expr,
- RESOURCE.absentOverClause());
+ RESOURCE.absentOverClause(op.getName()));
}
if (op instanceof SqlTableFunction) {
throw RESOURCE.cannotCallTableFunctionHere(op.getName()).ex();
diff --git
a/core/src/main/resources/org/apache/calcite/runtime/CalciteResource.properties
b/core/src/main/resources/org/apache/calcite/runtime/CalciteResource.properties
index ae64b08bdd..056aeb7b07 100644
---
a/core/src/main/resources/org/apache/calcite/runtime/CalciteResource.properties
+++
b/core/src/main/resources/org/apache/calcite/runtime/CalciteResource.properties
@@ -161,7 +161,7 @@ RowMustBeNonNegativeIntegral=ROWS value must be a
non-negative integral constant
OverMissingOrderBy=Window specification must contain an ORDER BY clause
PartitionbyShouldNotContainOver=PARTITION BY expression should not contain
OVER clause
OrderbyShouldNotContainOver=ORDER BY expression should not contain OVER clause
-AbsentOverClause=OVER clause is necessary for window functions
+AbsentOverClause=window function {0} requires an OVER clause
BadLowerBoundary=UNBOUNDED FOLLOWING cannot be specified for the lower frame
boundary
BadUpperBoundary=UNBOUNDED PRECEDING cannot be specified for the upper frame
boundary
CurrentRowPrecedingError=Upper frame boundary cannot be PRECEDING when lower
boundary is CURRENT ROW
diff --git a/core/src/test/java/org/apache/calcite/test/SqlValidatorTest.java
b/core/src/test/java/org/apache/calcite/test/SqlValidatorTest.java
index 1cba948097..5cd74f62f2 100644
--- a/core/src/test/java/org/apache/calcite/test/SqlValidatorTest.java
+++ b/core/src/test/java/org/apache/calcite/test/SqlValidatorTest.java
@@ -3448,11 +3448,11 @@ void testWinPartClause() {
+ "from emp\n"
+ "group by deptno\n"
+ "order by ^row_number()^")
- .fails("OVER clause is necessary for window functions");
+ .fails("window function ROW_NUMBER requires an OVER clause");
winSql("select ^rank()^\n"
+ "from emp")
- .fails("OVER clause is necessary for window functions");
+ .fails("window function RANK requires an OVER clause");
// With [CALCITE-1340], the validator would see RANK without OVER,
// mistakenly think this is an aggregate query, and wrongly complain
@@ -3460,33 +3460,33 @@ void testWinPartClause() {
winSql("select cume_dist() over w , ^rank()^\n"
+ "from emp\n"
+ "window w as (partition by deptno order by deptno)")
- .fails("OVER clause is necessary for window functions");
+ .fails("window function RANK requires an OVER clause");
winSql("select ^nth_value(sal, 2)^\n"
+ "from emp")
- .fails("OVER clause is necessary for window functions");
+ .fails("window function NTH_VALUE requires an OVER clause");
winSql("select ^first_value(sal)^\n"
+ "from emp")
- .fails("OVER clause is necessary for window functions");
+ .fails("window function FIRST_VALUE requires an OVER clause");
winSql("select ^last_value(sal)^\n"
+ "from emp")
- .fails("OVER clause is necessary for window functions");
+ .fails("window function LAST_VALUE requires an OVER clause");
// With alias, first_value and last_value without OVER should also fail
winSql("select ^first_value(sal)^ as sal_first\n"
+ "from emp")
- .fails("OVER clause is necessary for window functions");
+ .fails("window function FIRST_VALUE requires an OVER clause");
winSql("select ^last_value(sal)^ as sal_last\n"
+ "from emp")
- .fails("OVER clause is necessary for window functions");
+ .fails("window function LAST_VALUE requires an OVER clause");
// In GROUP BY context, first_value and last_value without OVER should fail
winSql("select sal, ^first_value(sal)^ as sal_first\n"
+ "from emp group by sal, deptno")
- .fails("OVER clause is necessary for window functions");
+ .fails("window function FIRST_VALUE requires an OVER clause");
// first_value and last_value with OVER clause should succeed
winSql("select first_value(sal) over (order by empno)\n"
@@ -3632,7 +3632,7 @@ void testWinPartClause() {
// rank function type
if (defined.contains("DENSE_RANK")) {
winExp("^dense_rank()^")
- .fails("OVER clause is necessary for window functions");
+ .fails("window function DENSE_RANK requires an OVER clause");
} else {
checkWinFuncExpWithWinClause("^dense_rank()^",
"Function 'DENSE_RANK\\(\\)' is not defined");