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() {