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");

Reply via email to