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

JackieTien97 pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/iotdb.git


The following commit(s) were added to refs/heads/master by this push:
     new 939500d0990 Fix grouped max for non-positive floating-point values 
(#18300)
939500d0990 is described below

commit 939500d09903baa3b0a9454b53ff499b938e2e94
Author: Jackie Tien <[email protected]>
AuthorDate: Fri Jul 24 17:05:08 2026 +0800

    Fix grouped max for non-positive floating-point values (#18300)
---
 .../it/query/recent/IoTDBTableAggregationIT.java   |  15 +++
 .../aggregation/grouped/GroupedMaxAccumulator.java |   4 +-
 .../aggregation/GroupedMaxAccumulatorTest.java     | 124 +++++++++++++++++++++
 3 files changed, 141 insertions(+), 2 deletions(-)

diff --git 
a/integration-test/src/test/java/org/apache/iotdb/relational/it/query/recent/IoTDBTableAggregationIT.java
 
b/integration-test/src/test/java/org/apache/iotdb/relational/it/query/recent/IoTDBTableAggregationIT.java
index aa635d8288d..9d4dcb78240 100644
--- 
a/integration-test/src/test/java/org/apache/iotdb/relational/it/query/recent/IoTDBTableAggregationIT.java
+++ 
b/integration-test/src/test/java/org/apache/iotdb/relational/it/query/recent/IoTDBTableAggregationIT.java
@@ -1927,6 +1927,21 @@ public class IoTDBTableAggregationIT {
         "select max(time),max(s3) from table1", expectedHeader, retArray, 
DATABASE_NAME);
   }
 
+  @Test
+  public void maxNonPositiveFloatingPointTest() {
+    String[] expectedHeader = new String[] {"region", "_col1", "_col2"};
+    String[] retArray =
+        new String[] {
+          "huangpu,0.0,-35.0,", "pudong,0.0,-36.0,",
+        };
+
+    tableResultSetEqualTest(
+        "select region,max(s4 * 0.0),max(0.0 - s4) from table1 where device_id 
in ('d01','d07') group by region order by region",
+        expectedHeader,
+        retArray,
+        DATABASE_NAME);
+  }
+
   @Test
   public void maxByTest() {
     String[] expectedHeader = new String[] {"device_id", "color", "type", 
"_col3", "_col4"};
diff --git 
a/iotdb-core/calc-commons/src/main/java/org/apache/iotdb/calc/execution/operator/source/relational/aggregation/grouped/GroupedMaxAccumulator.java
 
b/iotdb-core/calc-commons/src/main/java/org/apache/iotdb/calc/execution/operator/source/relational/aggregation/grouped/GroupedMaxAccumulator.java
index c4da41c8acb..bbdb71c2810 100644
--- 
a/iotdb-core/calc-commons/src/main/java/org/apache/iotdb/calc/execution/operator/source/relational/aggregation/grouped/GroupedMaxAccumulator.java
+++ 
b/iotdb-core/calc-commons/src/main/java/org/apache/iotdb/calc/execution/operator/source/relational/aggregation/grouped/GroupedMaxAccumulator.java
@@ -62,10 +62,10 @@ public class GroupedMaxAccumulator implements 
GroupedAccumulator {
         longValues = new LongBigArray(Long.MIN_VALUE);
         return;
       case FLOAT:
-        floatValues = new FloatBigArray(Float.MIN_VALUE);
+        floatValues = new FloatBigArray(Float.NEGATIVE_INFINITY);
         return;
       case DOUBLE:
-        doubleValues = new DoubleBigArray(Double.MIN_VALUE);
+        doubleValues = new DoubleBigArray(Double.NEGATIVE_INFINITY);
         return;
       case TEXT:
       case STRING:
diff --git 
a/iotdb-core/calc-commons/src/test/java/org/apache/iotdb/calc/execution/operator/source/relational/aggregation/GroupedMaxAccumulatorTest.java
 
b/iotdb-core/calc-commons/src/test/java/org/apache/iotdb/calc/execution/operator/source/relational/aggregation/GroupedMaxAccumulatorTest.java
new file mode 100644
index 00000000000..cadc5591f7d
--- /dev/null
+++ 
b/iotdb-core/calc-commons/src/test/java/org/apache/iotdb/calc/execution/operator/source/relational/aggregation/GroupedMaxAccumulatorTest.java
@@ -0,0 +1,124 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.iotdb.calc.execution.operator.source.relational.aggregation;
+
+import 
org.apache.iotdb.calc.execution.operator.source.relational.aggregation.grouped.GroupedMaxAccumulator;
+
+import org.apache.tsfile.block.column.Column;
+import org.apache.tsfile.block.column.ColumnBuilder;
+import org.apache.tsfile.enums.TSDataType;
+import org.apache.tsfile.read.common.block.TsBlock;
+import org.apache.tsfile.read.common.block.TsBlockBuilder;
+import org.apache.tsfile.read.common.block.column.DoubleColumnBuilder;
+import org.apache.tsfile.read.common.block.column.FloatColumnBuilder;
+import org.junit.Assert;
+import org.junit.Test;
+
+import java.util.Collections;
+
+public class GroupedMaxAccumulatorTest {
+
+  @Test
+  public void testFloatMaxWithNonPositiveInput() {
+    GroupedMaxAccumulator accumulator = new 
GroupedMaxAccumulator(TSDataType.FLOAT);
+    accumulator.setGroupCount(4);
+    TsBlock input = buildFloatBlock(0.0F, 0.0F, -3.5F, -1.25F, 
Float.NEGATIVE_INFINITY);
+
+    accumulator.addInput(
+        new int[] {0, 0, 1, 1, 2},
+        new Column[] {input.getColumn(0)},
+        AggregationMask.createSelectAll(input.getPositionCount()));
+
+    ColumnBuilder resultBuilder = new FloatColumnBuilder(null, 4);
+    accumulator.evaluateFinal(0, resultBuilder);
+    accumulator.evaluateFinal(1, resultBuilder);
+    accumulator.evaluateFinal(2, resultBuilder);
+    accumulator.evaluateFinal(3, resultBuilder);
+    Column result = resultBuilder.build();
+
+    Assert.assertFalse(result.isNull(0));
+    Assert.assertEquals(0.0F, result.getFloat(0), 0.0F);
+    Assert.assertEquals(-1.25F, result.getFloat(1), 0.0F);
+    Assert.assertEquals(Float.NEGATIVE_INFINITY, result.getFloat(2), 0.0F);
+    Assert.assertTrue(result.isNull(3));
+  }
+
+  @Test
+  public void testDoubleMaxWithNonPositiveInput() {
+    GroupedMaxAccumulator accumulator = new 
GroupedMaxAccumulator(TSDataType.DOUBLE);
+    accumulator.setGroupCount(4);
+    TsBlock input = buildDoubleBlock(0.0, 0.0, -8.5, -2.75, 
Double.NEGATIVE_INFINITY);
+
+    accumulator.addInput(
+        new int[] {0, 0, 1, 1, 2},
+        new Column[] {input.getColumn(0)},
+        AggregationMask.createSelectAll(input.getPositionCount()));
+
+    assertDoubleResults(accumulator);
+  }
+
+  @Test
+  public void testDoubleMaxWithNonPositiveIntermediateInput() {
+    GroupedMaxAccumulator accumulator = new 
GroupedMaxAccumulator(TSDataType.DOUBLE);
+    accumulator.setGroupCount(4);
+    TsBlock input = buildDoubleBlock(0.0, 0.0, -8.5, -2.75, 
Double.NEGATIVE_INFINITY);
+
+    accumulator.addIntermediate(new int[] {0, 0, 1, 1, 2}, input.getColumn(0));
+
+    assertDoubleResults(accumulator);
+  }
+
+  private void assertDoubleResults(GroupedMaxAccumulator accumulator) {
+    ColumnBuilder resultBuilder = new DoubleColumnBuilder(null, 4);
+    accumulator.evaluateFinal(0, resultBuilder);
+    accumulator.evaluateFinal(1, resultBuilder);
+    accumulator.evaluateFinal(2, resultBuilder);
+    accumulator.evaluateFinal(3, resultBuilder);
+    Column result = resultBuilder.build();
+
+    Assert.assertFalse(result.isNull(0));
+    Assert.assertEquals(0.0, result.getDouble(0), 0.0);
+    Assert.assertEquals(-2.75, result.getDouble(1), 0.0);
+    Assert.assertEquals(Double.NEGATIVE_INFINITY, result.getDouble(2), 0.0);
+    Assert.assertTrue(result.isNull(3));
+  }
+
+  private TsBlock buildFloatBlock(float... values) {
+    TsBlockBuilder builder = new 
TsBlockBuilder(Collections.singletonList(TSDataType.FLOAT));
+    ColumnBuilder valueBuilder = builder.getValueColumnBuilders()[0];
+    for (int i = 0; i < values.length; i++) {
+      builder.getTimeColumnBuilder().writeLong(i);
+      valueBuilder.writeFloat(values[i]);
+      builder.declarePosition();
+    }
+    return builder.build();
+  }
+
+  private TsBlock buildDoubleBlock(double... values) {
+    TsBlockBuilder builder = new 
TsBlockBuilder(Collections.singletonList(TSDataType.DOUBLE));
+    ColumnBuilder valueBuilder = builder.getValueColumnBuilders()[0];
+    for (int i = 0; i < values.length; i++) {
+      builder.getTimeColumnBuilder().writeLong(i);
+      valueBuilder.writeDouble(values[i]);
+      builder.declarePosition();
+    }
+    return builder.build();
+  }
+}

Reply via email to