This is an automated email from the ASF dual-hosted git repository.

mihaibudiu 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 763726cfa9 [CALCITE-7695] COVAR and REGR aggregate results should be 
nullable if either argument is nullable
763726cfa9 is described below

commit 763726cfa9199a77a2d63be80c6ab725cef34621
Author: Mihai Budiu <[email protected]>
AuthorDate: Thu Aug 6 14:07:57 2026 -0700

    [CALCITE-7695] COVAR and REGR aggregate results should be nullable if 
either argument is nullable
    
    Signed-off-by: Mihai Budiu <[email protected]>
---
 .../org/apache/calcite/sql/type/ReturnTypes.java   |  8 ++++--
 .../org/apache/calcite/test/SqlOperatorTest.java   | 30 +++++++++++-----------
 2 files changed, 21 insertions(+), 17 deletions(-)

diff --git a/core/src/main/java/org/apache/calcite/sql/type/ReturnTypes.java 
b/core/src/main/java/org/apache/calcite/sql/type/ReturnTypes.java
index 5e5ab2207c..f64881cf43 100644
--- a/core/src/main/java/org/apache/calcite/sql/type/ReturnTypes.java
+++ b/core/src/main/java/org/apache/calcite/sql/type/ReturnTypes.java
@@ -1596,12 +1596,16 @@ private static RelDataType 
multivalentStringWithSepSumPrecision(
     final RelDataType relDataType =
         typeFactory.getTypeSystem().deriveCovarType(typeFactory,
             opBinding.getOperandType(0), opBinding.getOperandType(1));
+    // These functions ignore rows where either argument is NULL, so a
+    // non-empty group can still aggregate zero rows and return NULL;
+    // COVAR_SAMP also returns NULL for a group with a single row.
     if (opBinding.hasEmptyGroup() || opBinding.hasFilter()
+        || opBinding.getOperandType(0).isNullable()
+        || opBinding.getOperandType(1).isNullable()
         || opBinding.getOperator().kind == SqlKind.COVAR_SAMP) {
       return typeFactory.createTypeWithNullability(relDataType, true);
-    } else {
-      return relDataType;
     }
+    return relDataType;
   };
 
   public static final SqlReturnTypeInference PERCENTILE_DISC_CONT =
diff --git a/testkit/src/main/java/org/apache/calcite/test/SqlOperatorTest.java 
b/testkit/src/main/java/org/apache/calcite/test/SqlOperatorTest.java
index 7283e346e0..93b2f90aae 100644
--- a/testkit/src/main/java/org/apache/calcite/test/SqlOperatorTest.java
+++ b/testkit/src/main/java/org/apache/calcite/test/SqlOperatorTest.java
@@ -16169,11 +16169,13 @@ void testTimestampDiff(boolean coercionEnabled) {
     f.checkAggType("covar_pop(cast(null as integer), 2.5)", "DECIMAL(11, 1)");
     f.checkAggType("covar_pop(cast(null as integer), cast(null as double))",
         "DOUBLE");
-    if (!f.brokenTestsEnabled()) {
-      return;
-    }
-    // with zero values
-    f.checkAgg("covar_pop(x)", new String[]{}, isNullValue());
+    // [CALCITE-7695] COVAR and REGR aggregate results should be nullable if
+    // either argument is nullable
+    f.checkAggType("covar_pop(1.5, cast(null as double))", "DOUBLE");
+    // Nullable without GROUP BY even for non-nullable arguments, since the
+    // input may be empty
+    f.checkColumnType("select covar_pop(1.5, 2.5) from (values (1))",
+        "DECIMAL(2, 1)");
   }
 
   @Test void testCovarSampFunc() {
@@ -16216,11 +16218,9 @@ void testTimestampDiff(boolean coercionEnabled) {
         "INTEGER");
     f.checkAggType("regr_sxx(1.5, 2.5)", "DECIMAL(2, 1) NOT NULL");
     f.checkAggType("regr_sxx(1, cast(2 as double))", "DOUBLE NOT NULL");
-    if (!f.brokenTestsEnabled()) {
-      return;
-    }
-    // with zero values
-    f.checkAgg("regr_sxx(x)", new String[]{}, isNullValue());
+    f.checkAggType("regr_sxx(1.5, cast(null as double))", "DOUBLE");
+    f.checkColumnType("select regr_sxx(1.5, 2.5) from (values (1))",
+        "DECIMAL(2, 1)");
   }
 
   @Test void testRegrSyyFunc() {
@@ -16241,11 +16241,11 @@ void testTimestampDiff(boolean coercionEnabled) {
         "INTEGER");
     f.checkAggType("regr_syy(1.5, 2.5)", "DECIMAL(2, 1) NOT NULL");
     f.checkAggType("regr_syy(1, cast(2 as double))", "DOUBLE NOT NULL");
-    if (!f.brokenTestsEnabled()) {
-      return;
-    }
-    // with zero values
-    f.checkAgg("regr_syy(x)", new String[]{}, isNullValue());
+    // [CALCITE-7695] COVAR and REGR aggregate results should be nullable if
+    // either argument is nullable
+    f.checkAggType("regr_syy(1.5, cast(null as double))", "DOUBLE");
+    f.checkColumnType("select regr_syy(1.5, 2.5) from (values (1))",
+        "DECIMAL(2, 1)");
   }
 
   @Test void testStddevPopFunc() {

Reply via email to