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

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


The following commit(s) were added to refs/heads/object_type by this push:
     new c93161e555e add read_object scalar function
c93161e555e is described below

commit c93161e555ef64a4cf533550e9a9fa53d5183d01
Author: shuwenwei <[email protected]>
AuthorDate: Thu Jul 3 17:13:59 2025 +0800

    add read_object scalar function
---
 .../relational/ColumnTransformerBuilder.java       |  21 ++++
 .../builtin/helper/ReadObjectFunctionHelper.java   |  80 +++++++++++++++
 .../relational/metadata/TableMetadataImpl.java     |  24 ++++-
 .../unary/scalar/ReadObjectColumnTransformer.java  | 114 +++++++++++++++++++++
 .../relational/TableBuiltinScalarFunction.java     |   1 +
 5 files changed, 238 insertions(+), 2 deletions(-)

diff --git 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/execution/relational/ColumnTransformerBuilder.java
 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/execution/relational/ColumnTransformerBuilder.java
index d0b7e35e94c..48586f6a34c 100644
--- 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/execution/relational/ColumnTransformerBuilder.java
+++ 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/execution/relational/ColumnTransformerBuilder.java
@@ -133,6 +133,7 @@ import 
org.apache.iotdb.db.queryengine.transformation.dag.column.unary.scalar.Lo
 import 
org.apache.iotdb.db.queryengine.transformation.dag.column.unary.scalar.RTrim2ColumnTransformer;
 import 
org.apache.iotdb.db.queryengine.transformation.dag.column.unary.scalar.RTrimColumnTransformer;
 import 
org.apache.iotdb.db.queryengine.transformation.dag.column.unary.scalar.RadiansColumnTransformer;
+import 
org.apache.iotdb.db.queryengine.transformation.dag.column.unary.scalar.ReadObjectColumnTransformer;
 import 
org.apache.iotdb.db.queryengine.transformation.dag.column.unary.scalar.RegexpLike2ColumnTransformer;
 import 
org.apache.iotdb.db.queryengine.transformation.dag.column.unary.scalar.RegexpLikeColumnTransformer;
 import 
org.apache.iotdb.db.queryengine.transformation.dag.column.unary.scalar.Replace2ColumnTransformer;
@@ -199,6 +200,7 @@ import static 
org.apache.tsfile.read.common.type.BooleanType.BOOLEAN;
 import static org.apache.tsfile.read.common.type.DoubleType.DOUBLE;
 import static org.apache.tsfile.read.common.type.IntType.INT32;
 import static org.apache.tsfile.read.common.type.LongType.INT64;
+import static org.apache.tsfile.read.common.type.ObjectType.OBJECT;
 import static org.apache.tsfile.read.common.type.StringType.STRING;
 
 public class ColumnTransformerBuilder
@@ -999,6 +1001,25 @@ public class ColumnTransformerBuilder
       Type returnType = columnTransformers.get(0).getType();
       return AbstractGreatestLeastColumnTransformer.getLeastColumnTransformer(
           returnType, columnTransformers);
+    } else if (TableBuiltinScalarFunction.READ_OBJECT
+        .getFunctionName()
+        .equalsIgnoreCase(functionName)) {
+      ColumnTransformer first = this.process(children.get(0), context);
+      if (children.size() == 1) {
+        return new ReadObjectColumnTransformer(OBJECT, first);
+      } else if (children.size() == 2) {
+        return new ReadObjectColumnTransformer(
+            OBJECT, ((LongLiteral) children.get(1)).getParsedValue(), first);
+      } else {
+        long offset = ((LongLiteral) children.get(1)).getParsedValue();
+        long length = ((LongLiteral) children.get(2)).getParsedValue();
+        checkArgument(offset >= 0 && length >= 0);
+        return new ReadObjectColumnTransformer(
+            OBJECT,
+            ((LongLiteral) children.get(1)).getParsedValue(),
+            ((LongLiteral) children.get(2)).getParsedValue(),
+            first);
+      }
     } else {
       // user defined function
       if (TableUDFUtils.isScalarFunction(functionName)) {
diff --git 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/expression/multi/builtin/helper/ReadObjectFunctionHelper.java
 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/expression/multi/builtin/helper/ReadObjectFunctionHelper.java
new file mode 100644
index 00000000000..c1a11d948d7
--- /dev/null
+++ 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/expression/multi/builtin/helper/ReadObjectFunctionHelper.java
@@ -0,0 +1,80 @@
+/*
+ * 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.plan.expression.multi.builtin.helper;
+
+import org.apache.iotdb.db.exception.sql.SemanticException;
+import 
org.apache.iotdb.db.queryengine.plan.expression.multi.FunctionExpression;
+import 
org.apache.iotdb.db.queryengine.plan.expression.multi.builtin.BuiltInScalarFunctionHelper;
+import org.apache.iotdb.db.queryengine.transformation.api.LayerReader;
+import 
org.apache.iotdb.db.queryengine.transformation.dag.column.ColumnTransformer;
+import 
org.apache.iotdb.db.queryengine.transformation.dag.transformer.Transformer;
+
+import org.apache.tsfile.enums.TSDataType;
+
+import java.util.Map;
+
+import static 
org.apache.iotdb.db.queryengine.plan.parser.ASTVisitor.checkFunctionExpressionInputSize;
+
+public class ReadObjectFunctionHelper implements BuiltInScalarFunctionHelper {
+  @Override
+  public void checkBuiltInScalarFunctionInputSize(FunctionExpression 
functionExpression)
+      throws SemanticException {
+    checkFunctionExpressionInputSize(
+        functionExpression.getExpressionString(),
+        functionExpression.getExpressions().size(),
+        1,
+        2,
+        3);
+  }
+
+  @Override
+  public void checkBuiltInScalarFunctionInputDataType(TSDataType tsDataType)
+      throws SemanticException {
+    if (tsDataType == TSDataType.OBJECT) {
+      return;
+    }
+    throw new SemanticException(
+        "Input series of Scalar function [READ_OBJECT] only supports data type 
[OBJECT]");
+  }
+
+  @Override
+  public TSDataType getBuiltInScalarFunctionReturnType(FunctionExpression 
functionExpression) {
+    return TSDataType.BLOB;
+  }
+
+  @Override
+  public ColumnTransformer getBuiltInScalarFunctionColumnTransformer(
+      FunctionExpression expression, ColumnTransformer columnTransformer) {
+    return null;
+  }
+
+  @Override
+  public Transformer getBuiltInScalarFunctionTransformer(
+      FunctionExpression expression, LayerReader layerReader) {
+    return null;
+  }
+
+  @Override
+  public void appendFunctionAttributes(
+      boolean hasExpression, StringBuilder builder, Map<String, String> 
functionAttributes) {
+    BuiltInScalarFunctionHelper.super.appendFunctionAttributes(
+        hasExpression, builder, functionAttributes);
+  }
+}
diff --git 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/metadata/TableMetadataImpl.java
 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/metadata/TableMetadataImpl.java
index 8934de172e9..b9e167d1b43 100644
--- 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/metadata/TableMetadataImpl.java
+++ 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/metadata/TableMetadataImpl.java
@@ -65,7 +65,7 @@ import org.apache.iotdb.udf.api.relational.ScalarFunction;
 import org.apache.iotdb.udf.api.relational.TableFunction;
 
 import org.apache.tsfile.file.metadata.IDeviceID;
-import org.apache.tsfile.read.common.type.BlobType;
+import org.apache.tsfile.read.common.type.ObjectType;
 import org.apache.tsfile.read.common.type.StringType;
 import org.apache.tsfile.read.common.type.Type;
 import org.apache.tsfile.read.common.type.TypeFactory;
@@ -79,6 +79,7 @@ import java.util.stream.Collectors;
 
 import static 
org.apache.iotdb.db.queryengine.transformation.dag.column.FailFunctionColumnTransformer.FAIL_FUNCTION_NAME;
 import static org.apache.tsfile.read.common.type.BinaryType.TEXT;
+import static org.apache.tsfile.read.common.type.BlobType.BLOB;
 import static org.apache.tsfile.read.common.type.BooleanType.BOOLEAN;
 import static org.apache.tsfile.read.common.type.DateType.DATE;
 import static org.apache.tsfile.read.common.type.DoubleType.DOUBLE;
@@ -570,6 +571,21 @@ public class TableMetadataImpl implements Metadata {
                 + " must have at least two arguments, and all type must be the 
same.");
       }
       return argumentTypes.get(0);
+    } else if (TableBuiltinScalarFunction.READ_OBJECT
+        .getFunctionName()
+        .equalsIgnoreCase(functionName)) {
+      if (argumentTypes.isEmpty()
+          || argumentTypes.size() > 3
+          || !isIntegerNumber(argumentTypes.get(0))
+          //          || !isObjectType(argumentTypes.get(0))
+          || (argumentTypes.size() >= 2 && 
!isIntegerNumber(argumentTypes.get(1)))
+          || (argumentTypes.size() >= 3 && 
!isIntegerNumber(argumentTypes.get(2)))) {
+        throw new SemanticException(
+            "Scalar function "
+                + functionName.toLowerCase(Locale.ENGLISH)
+                + " must have at 1~3 arguments, and first argument must be 
OBJECT type, other arguments must be int32 or int64 type");
+      }
+      return BLOB;
     }
 
     // builtin aggregation function
@@ -962,8 +978,12 @@ public class TableMetadataImpl implements Metadata {
     return TEXT.equals(type) || StringType.STRING.equals(type);
   }
 
+  public static boolean isObjectType(Type type) {
+    return ObjectType.OBJECT.equals(type);
+  }
+
   public static boolean isBlobType(Type type) {
-    return BlobType.BLOB.equals(type);
+    return BLOB.equals(type);
   }
 
   public static boolean isBool(Type type) {
diff --git 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/transformation/dag/column/unary/scalar/ReadObjectColumnTransformer.java
 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/transformation/dag/column/unary/scalar/ReadObjectColumnTransformer.java
new file mode 100644
index 00000000000..15e82be9d8b
--- /dev/null
+++ 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/transformation/dag/column/unary/scalar/ReadObjectColumnTransformer.java
@@ -0,0 +1,114 @@
+/*
+ * 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.column.unary.scalar;
+
+import org.apache.iotdb.commons.exception.IoTDBRuntimeException;
+import 
org.apache.iotdb.db.queryengine.transformation.dag.column.ColumnTransformer;
+import 
org.apache.iotdb.db.queryengine.transformation.dag.column.unary.UnaryColumnTransformer;
+import org.apache.iotdb.rpc.TSStatusCode;
+
+import org.apache.tsfile.block.column.Column;
+import org.apache.tsfile.block.column.ColumnBuilder;
+import org.apache.tsfile.read.common.type.Type;
+import org.apache.tsfile.utils.Binary;
+
+import java.io.File;
+import java.io.IOException;
+import java.nio.ByteBuffer;
+import java.nio.channels.FileChannel;
+import java.nio.file.StandardOpenOption;
+
+public class ReadObjectColumnTransformer extends UnaryColumnTransformer {
+
+  private long offset = -1;
+  private long length = -1;
+
+  public ReadObjectColumnTransformer(Type type, ColumnTransformer 
childColumnTransformer) {
+    super(type, childColumnTransformer);
+  }
+
+  public ReadObjectColumnTransformer(
+      Type type, long offset, ColumnTransformer childColumnTransformer) {
+    super(type, childColumnTransformer);
+    this.offset = offset;
+  }
+
+  public ReadObjectColumnTransformer(
+      Type type, long offset, long length, ColumnTransformer 
childColumnTransformer) {
+    super(type, childColumnTransformer);
+    this.offset = offset;
+    this.length = length;
+  }
+
+  @Override
+  protected void doTransform(Column column, ColumnBuilder columnBuilder) {
+    for (int i = 0, n = column.getPositionCount(); i < n; i++) {
+      if (!column.isNull(i)) {
+        transform(column, columnBuilder, i);
+      } else {
+        columnBuilder.appendNull();
+      }
+    }
+  }
+
+  @Override
+  protected void doTransform(Column column, ColumnBuilder columnBuilder, 
boolean[] selection) {
+    for (int i = 0, n = column.getPositionCount(); i < n; i++) {
+      if (selection[i] && !column.isNull(i)) {
+        transform(column, columnBuilder, i);
+      } else {
+        columnBuilder.appendNull();
+      }
+    }
+  }
+
+  private void transform(Column column, ColumnBuilder columnBuilder, int i) {
+    //    if (TSDataType.OBJECT.equals(column.getDataType())) {
+    //      Binary binary = column.getBinary(i);
+    //      columnBuilder.writeBinary(readObject(binary));
+    //    }
+    columnBuilder.writeBinary(readObject(new Binary(new byte[0])));
+  }
+
+  private Binary readObject(Binary binary) {
+    File file = new File(getObjectPathFromBinary(binary));
+    // TODO: allocate memory
+    long fileSize = file.length();
+    if (offset >= fileSize) {
+      throw new UnsupportedOperationException("offset is greater than object 
size");
+    }
+    long actualReadSize = Math.min(length, fileSize - offset);
+    if (actualReadSize > Integer.MAX_VALUE) {
+      throw new UnsupportedOperationException("Read object size is too large 
(size > 2G)");
+    }
+    byte[] bytes = new byte[(int) actualReadSize];
+    ByteBuffer buffer = ByteBuffer.wrap(bytes);
+    try (FileChannel fileChannel = FileChannel.open(file.toPath(), 
StandardOpenOption.READ)) {
+      fileChannel.read(buffer);
+    } catch (IOException e) {
+      throw new IoTDBRuntimeException(e, 
TSStatusCode.INTERNAL_SERVER_ERROR.getStatusCode());
+    }
+    return new Binary(bytes);
+  }
+
+  private String getObjectPathFromBinary(Binary binary) {
+    return "/Users/shuww/Downloads/test_0703/aaa";
+  }
+}
diff --git 
a/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/udf/builtin/relational/TableBuiltinScalarFunction.java
 
b/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/udf/builtin/relational/TableBuiltinScalarFunction.java
index 6d5b1ef4721..ced804e681c 100644
--- 
a/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/udf/builtin/relational/TableBuiltinScalarFunction.java
+++ 
b/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/udf/builtin/relational/TableBuiltinScalarFunction.java
@@ -67,6 +67,7 @@ public enum TableBuiltinScalarFunction {
   FORMAT("format"),
   GREATEST("greatest"),
   LEAST("least"),
+  READ_OBJECT("read_object"),
   ;
 
   private final String functionName;

Reply via email to