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

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


The following commit(s) were added to refs/heads/remove_swtich_type by this 
push:
     new a6aacb1e643 multiple refactors
a6aacb1e643 is described below

commit a6aacb1e643c7ade28ac62784dd388d8cd3d2b92
Author: Tian Jiang <[email protected]>
AuthorDate: Tue Sep 8 11:22:28 2026 +0800

    multiple refactors
---
 .../java/org/apache/iotdb/udf/api/access/Row.java  |  7 +-
 .../org/apache/iotdb/udf/api/utils/RowImpl.java    |  2 +-
 ...ializableRowRecordListBackedMultiColumnRow.java |  2 +-
 .../dag/adapter/RowGetDoubleTest.java              | 98 ++++++++++++++++++++++
 .../iotdb/commons/udf/utils/MasterRepairUtil.java  | 32 ++-----
 .../commons/udf/utils/MasterRepairUtilTest.java    | 94 +++++++++++++++++++++
 6 files changed, 207 insertions(+), 28 deletions(-)

diff --git 
a/iotdb-api/udf-api/src/main/java/org/apache/iotdb/udf/api/access/Row.java 
b/iotdb-api/udf-api/src/main/java/org/apache/iotdb/udf/api/access/Row.java
index e2dc13a39ab..c1b466786cd 100644
--- a/iotdb-api/udf-api/src/main/java/org/apache/iotdb/udf/api/access/Row.java
+++ b/iotdb-api/udf-api/src/main/java/org/apache/iotdb/udf/api/access/Row.java
@@ -68,10 +68,11 @@ public interface Row {
   float getFloat(int columnIndex) throws IOException;
 
   /**
-   * Returns the double value at the specified column in this row.
+   * Returns the numeric value at the specified column in this row as a double.
    *
-   * <p>Users need to ensure that the data type of the specified column is 
{@code
-   * TSDataType.DOUBLE}.
+   * <p>Users need to ensure that the data type of the specified column is 
{@code TSDataType.INT32},
+   * {@code TSDataType.INT64}, {@code TSDataType.FLOAT}, or {@code 
TSDataType.DOUBLE}, and that the
+   * value is not null. INT64 values may lose precision when converted to 
double.
    *
    * @param columnIndex index of the specified column
    * @return the double value at the specified column in this row
diff --git 
a/iotdb-api/udf-api/src/main/java/org/apache/iotdb/udf/api/utils/RowImpl.java 
b/iotdb-api/udf-api/src/main/java/org/apache/iotdb/udf/api/utils/RowImpl.java
index 10b7dc7417d..4033ff9ac76 100644
--- 
a/iotdb-api/udf-api/src/main/java/org/apache/iotdb/udf/api/utils/RowImpl.java
+++ 
b/iotdb-api/udf-api/src/main/java/org/apache/iotdb/udf/api/utils/RowImpl.java
@@ -73,7 +73,7 @@ public class RowImpl implements Row {
     if (columnIndex >= size()) {
       throw new IndexOutOfBoundsException(UdfApiMessages.INDEX_OUT_OF_BOUND);
     }
-    return (double) rowRecord[columnIndex];
+    return ((Number) rowRecord[columnIndex]).doubleValue();
   }
 
   @Override
diff --git 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/transformation/dag/adapter/ElasticSerializableRowRecordListBackedMultiColumnRow.java
 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/transformation/dag/adapter/ElasticSerializableRowRecordListBackedMultiColumnRow.java
index 6f42b95a6ac..e2f16d6f748 100644
--- 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/transformation/dag/adapter/ElasticSerializableRowRecordListBackedMultiColumnRow.java
+++ 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/transformation/dag/adapter/ElasticSerializableRowRecordListBackedMultiColumnRow.java
@@ -62,7 +62,7 @@ public class 
ElasticSerializableRowRecordListBackedMultiColumnRow implements Row
 
   @Override
   public double getDouble(int columnIndex) {
-    return (double) rowRecord[columnIndex];
+    return ((Number) rowRecord[columnIndex]).doubleValue();
   }
 
   @Override
diff --git 
a/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/queryengine/transformation/dag/adapter/RowGetDoubleTest.java
 
b/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/queryengine/transformation/dag/adapter/RowGetDoubleTest.java
new file mode 100644
index 00000000000..26d88281257
--- /dev/null
+++ 
b/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/queryengine/transformation/dag/adapter/RowGetDoubleTest.java
@@ -0,0 +1,98 @@
+/*
+ * 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.db.queryengine.transformation.dag.adapter;
+
+import org.apache.iotdb.udf.api.access.Row;
+import org.apache.iotdb.udf.api.utils.RowImpl;
+
+import org.apache.tsfile.enums.TSDataType;
+import org.junit.Test;
+
+import java.io.IOException;
+import java.util.Arrays;
+import java.util.List;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertThrows;
+import static org.junit.Assert.assertTrue;
+
+public class RowGetDoubleTest {
+
+  @Test
+  public void testNumericConversion() throws IOException {
+    // Both Object[] implementations must widen all four numeric types, 
including large longs.
+    for (Row row :
+        createRows(
+            new TSDataType[] {
+              TSDataType.INT32, TSDataType.INT64, TSDataType.FLOAT, 
TSDataType.DOUBLE
+            },
+            new Object[] {Integer.MIN_VALUE, Long.MAX_VALUE, 0.1f, -1.25d, 
123L})) {
+      assertEquals((double) Integer.MIN_VALUE, row.getDouble(0), 0d);
+      assertEquals((double) Long.MAX_VALUE, row.getDouble(1), 0d);
+      assertEquals((double) 0.1f, row.getDouble(2), 0d);
+      assertEquals(-1.25d, row.getDouble(3), 0d);
+      assertEquals(123L, row.getTime());
+      assertEquals(4, row.size());
+    }
+  }
+
+  @Test
+  public void testSpecialFloatingPointValues() throws IOException {
+    // Widening must preserve NaN, infinities, and the sign of zero.
+    for (Row row :
+        createRows(
+            new TSDataType[] {
+              TSDataType.FLOAT, TSDataType.FLOAT, TSDataType.DOUBLE, 
TSDataType.DOUBLE
+            },
+            new Object[] {
+              Float.NaN, Float.POSITIVE_INFINITY, Double.NEGATIVE_INFINITY, 
-0.0d, 123L
+            })) {
+      assertTrue(Double.isNaN(row.getDouble(0)));
+      assertEquals(Double.POSITIVE_INFINITY, row.getDouble(1), 0d);
+      assertEquals(Double.NEGATIVE_INFINITY, row.getDouble(2), 0d);
+      assertEquals(Double.doubleToLongBits(-0.0d), 
Double.doubleToLongBits(row.getDouble(3)));
+    }
+  }
+
+  @Test
+  public void testInvalidReads() throws IOException {
+    // Null, nonnumeric values, and invalid array indices retain their failure 
behavior.
+    for (Row row :
+        createRows(
+            new TSDataType[] {TSDataType.DOUBLE, TSDataType.BOOLEAN},
+            new Object[] {null, true, 123L})) {
+      assertTrue(row.isNull(0));
+      assertThrows(NullPointerException.class, () -> row.getDouble(0));
+      assertThrows(ClassCastException.class, () -> row.getDouble(1));
+      assertThrows(IndexOutOfBoundsException.class, () -> row.getDouble(-1));
+      assertThrows(IndexOutOfBoundsException.class, () -> row.getDouble(3));
+    }
+  }
+
+  private List<Row> createRows(TSDataType[] types, Object[] values) {
+    // RowImpl includes the trailing timestamp in its schema; the adapter does 
not.
+    TSDataType[] typesWithTime = Arrays.copyOf(types, types.length + 1);
+    typesWithTime[types.length] = TSDataType.TIMESTAMP;
+    RowImpl row = new RowImpl(typesWithTime);
+    row.setRowRecord(values);
+    return Arrays.asList(
+        row, new 
ElasticSerializableRowRecordListBackedMultiColumnRow(types).setRowRecord(values));
+  }
+}
diff --git 
a/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/udf/utils/MasterRepairUtil.java
 
b/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/udf/utils/MasterRepairUtil.java
index 79d5381f45d..5a9fe141fe1 100644
--- 
a/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/udf/utils/MasterRepairUtil.java
+++ 
b/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/udf/utils/MasterRepairUtil.java
@@ -20,13 +20,18 @@ package org.apache.iotdb.commons.udf.utils;
 
 import org.apache.iotdb.commons.i18n.CommonMessages;
 import org.apache.iotdb.udf.api.access.Row;
+import org.apache.iotdb.udf.api.type.Type;
 
 import java.io.IOException;
 import java.math.BigDecimal;
 import java.util.ArrayList;
 import java.util.Collections;
+import java.util.EnumSet;
+import java.util.Set;
 
 public class MasterRepairUtil {
+  private static final Set<Type> NUMERIC_TYPES =
+      EnumSet.of(Type.INT32, Type.INT64, Type.FLOAT, Type.DOUBLE);
   private final ArrayList<ArrayList<Double>> td = new ArrayList<>();
   private final ArrayList<ArrayList<Double>> tdCleaned = new ArrayList<>();
   private final ArrayList<ArrayList<Double>> md = new ArrayList<>();
@@ -90,34 +95,15 @@ public class MasterRepairUtil {
   }
 
   public static double getValueAsDouble(Row row, int index) throws Exception {
-    double ans;
     try {
-      switch (row.getDataType(index)) {
-        case INT32:
-          ans = row.getInt(index);
-          break;
-        case INT64:
-          ans = row.getLong(index);
-          break;
-        case FLOAT:
-          ans = row.getFloat(index);
-          break;
-        case DOUBLE:
-          ans = row.getDouble(index);
-          break;
-        case DATE:
-        case BLOB:
-        case STRING:
-        case TIMESTAMP:
-        case BOOLEAN:
-        case TEXT:
-        default:
-          throw new Exception(CommonMessages.VALUE_NOT_NUMERIC);
+      // DATE and TIMESTAMP have numeric storage but are not repairable 
numeric measurements.
+      if (!NUMERIC_TYPES.contains(row.getDataType(index))) {
+        throw new Exception(CommonMessages.VALUE_NOT_NUMERIC);
       }
+      return row.getDouble(index);
     } catch (IOException e) {
       throw new Exception(CommonMessages.FAIL_TO_GET_DATA_TYPE_IN_ROW + 
row.getTime(), e);
     }
-    return ans;
   }
 
   public void buildKDTree() {
diff --git 
a/iotdb-core/node-commons/src/test/java/org/apache/iotdb/commons/udf/utils/MasterRepairUtilTest.java
 
b/iotdb-core/node-commons/src/test/java/org/apache/iotdb/commons/udf/utils/MasterRepairUtilTest.java
new file mode 100644
index 00000000000..45e8eeefe48
--- /dev/null
+++ 
b/iotdb-core/node-commons/src/test/java/org/apache/iotdb/commons/udf/utils/MasterRepairUtilTest.java
@@ -0,0 +1,94 @@
+/*
+ * 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.commons.udf.utils;
+
+import org.apache.iotdb.commons.i18n.CommonMessages;
+import org.apache.iotdb.udf.api.access.Row;
+import org.apache.iotdb.udf.api.type.Type;
+import org.apache.iotdb.udf.api.utils.RowImpl;
+
+import org.apache.tsfile.enums.TSDataType;
+import org.junit.Test;
+
+import java.io.IOException;
+import java.util.EnumSet;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertSame;
+import static org.junit.Assert.assertThrows;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+public class MasterRepairUtilTest {
+
+  @Test
+  public void testNumericValues() throws Exception {
+    // Use real boxed values to catch casts to Double and exercise nonzero 
column indices.
+    RowImpl row =
+        new RowImpl(
+            new TSDataType[] {
+              TSDataType.INT32,
+              TSDataType.INT64,
+              TSDataType.FLOAT,
+              TSDataType.DOUBLE,
+              TSDataType.TIMESTAMP
+            });
+    row.setRowRecord(new Object[] {-42, Long.MAX_VALUE, 0.1f, -1.25d, 123L});
+
+    assertEquals(-42d, MasterRepairUtil.getValueAsDouble(row, 0), 0d);
+    assertEquals((double) Long.MAX_VALUE, 
MasterRepairUtil.getValueAsDouble(row, 1), 0d);
+    assertEquals((double) 0.1f, MasterRepairUtil.getValueAsDouble(row, 2), 0d);
+    assertEquals(-1.25d, MasterRepairUtil.getValueAsDouble(row, 3), 0d);
+  }
+
+  @Test
+  public void testRejectNonNumericTypes() throws Exception {
+    // In particular, DATE and TIMESTAMP must not become valid repair 
measurements.
+    for (Type type :
+        EnumSet.complementOf(EnumSet.of(Type.INT32, Type.INT64, Type.FLOAT, 
Type.DOUBLE))) {
+      Row row = mock(Row.class);
+      when(row.getDataType(1)).thenReturn(type);
+
+      Exception exception =
+          assertThrows(Exception.class, () -> 
MasterRepairUtil.getValueAsDouble(row, 1));
+
+      assertEquals(CommonMessages.VALUE_NOT_NUMERIC, exception.getMessage());
+      verify(row, never()).getDouble(1);
+    }
+  }
+
+  @Test
+  public void testWrapIOException() throws Exception {
+    // A failed value read must retain the original cause and row timestamp in 
the message.
+    Row row = mock(Row.class);
+    IOException cause = new IOException("test read failure");
+    when(row.getDataType(1)).thenReturn(Type.INT32);
+    when(row.getDouble(1)).thenThrow(cause);
+    when(row.getTime()).thenReturn(123L);
+
+    Exception exception =
+        assertThrows(Exception.class, () -> 
MasterRepairUtil.getValueAsDouble(row, 1));
+
+    assertSame(cause, exception.getCause());
+    assertEquals(CommonMessages.FAIL_TO_GET_DATA_TYPE_IN_ROW + 123L, 
exception.getMessage());
+  }
+}

Reply via email to