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

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

commit 3ed7261fa1bdf9fda56cf2cdc694ba37f97352dd
Author: Chen YZ <[email protected]>
AuthorDate: Mon Apr 21 23:55:24 2025 +0800

    done
---
 .../udf/example/relational/MySelectColumn.java     | 89 ++++++++++++++++++++++
 .../relational/it/db/it/IoTDBWindowTVFIT.java      | 23 +++++-
 .../db/it/udf/IoTDBUserDefinedTableFunctionIT.java | 16 ++++
 .../table/argument/ScalarArgumentChecker.java      | 32 ++++++++
 .../processor/TableFunctionDataProcessor.java      |  6 +-
 .../ScalarParameterSpecification.java              | 23 +++++-
 .../process/function/TableFunctionOperator.java    | 18 ++++-
 .../plan/planner/TableOperatorGenerator.java       |  3 +
 .../relational/analyzer/StatementAnalyzer.java     |  8 ++
 .../relational/tvf/CumulateTableFunction.java      | 13 +++-
 .../builtin/relational/tvf/HOPTableFunction.java   | 13 +++-
 .../relational/tvf/TumbleTableFunction.java        |  7 +-
 12 files changed, 237 insertions(+), 14 deletions(-)

diff --git 
a/integration-test/src/main/java/org/apache/iotdb/db/query/udf/example/relational/MySelectColumn.java
 
b/integration-test/src/main/java/org/apache/iotdb/db/query/udf/example/relational/MySelectColumn.java
new file mode 100644
index 00000000000..27409032702
--- /dev/null
+++ 
b/integration-test/src/main/java/org/apache/iotdb/db/query/udf/example/relational/MySelectColumn.java
@@ -0,0 +1,89 @@
+/*
+ * 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.query.udf.example.relational;
+
+import org.apache.iotdb.udf.api.exception.UDFException;
+import org.apache.iotdb.udf.api.relational.TableFunction;
+import org.apache.iotdb.udf.api.relational.table.TableFunctionAnalysis;
+import 
org.apache.iotdb.udf.api.relational.table.TableFunctionProcessorProvider;
+import org.apache.iotdb.udf.api.relational.table.argument.Argument;
+import org.apache.iotdb.udf.api.relational.table.argument.DescribedSchema;
+import org.apache.iotdb.udf.api.relational.table.argument.ScalarArgument;
+import org.apache.iotdb.udf.api.relational.table.argument.TableArgument;
+import 
org.apache.iotdb.udf.api.relational.table.processor.TableFunctionDataProcessor;
+import 
org.apache.iotdb.udf.api.relational.table.specification.ParameterSpecification;
+import 
org.apache.iotdb.udf.api.relational.table.specification.ScalarParameterSpecification;
+import 
org.apache.iotdb.udf.api.relational.table.specification.TableParameterSpecification;
+import org.apache.iotdb.udf.api.type.Type;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+
+public class MySelectColumn implements TableFunction {
+  private final String TBL_PARAM = "DATA";
+  private final String COL_PARAM = "SELECT";
+
+  @Override
+  public List<ParameterSpecification> getArgumentsSpecifications() {
+    return Arrays.asList(
+        TableParameterSpecification.builder().name(TBL_PARAM).build(),
+        
ScalarParameterSpecification.builder().name(COL_PARAM).type(Type.STRING).build());
+  }
+
+  @Override
+  public TableFunctionAnalysis analyze(Map<String, Argument> arguments) throws 
UDFException {
+    TableArgument tableArgument = (TableArgument) arguments.get(TBL_PARAM);
+    String selectColumn = (String) ((ScalarArgument) 
arguments.get(COL_PARAM)).getValue();
+    List<Integer> requiredColumns = new ArrayList<>();
+    DescribedSchema.Builder schemaBuilder = DescribedSchema.builder();
+    for (int i = 0; i < tableArgument.getFieldNames().size(); i++) {
+      Optional<String> fieldName = tableArgument.getFieldNames().get(i);
+      if (fieldName.isPresent() && 
fieldName.get().equalsIgnoreCase(selectColumn)) {
+        requiredColumns.add(i);
+        schemaBuilder.addField(fieldName, 
tableArgument.getFieldTypes().get(i));
+      }
+    }
+    return TableFunctionAnalysis.builder()
+        .properColumnSchema(schemaBuilder.build())
+        .requiredColumns(TBL_PARAM, requiredColumns)
+        .build();
+  }
+
+  @Override
+  public TableFunctionProcessorProvider getProcessorProvider(Map<String, 
Argument> arguments) {
+    return new TableFunctionProcessorProvider() {
+      @Override
+      public TableFunctionDataProcessor getDataProcessor() {
+        return (input, properColumnBuilders, passThroughIndexBuilder) -> {
+          for (int i = 0; i < input.size(); i++) {
+            if (input.isNull(i)) {
+              properColumnBuilders.get(i).appendNull();
+            } else {
+              properColumnBuilders.get(i).writeObject(input.getObject(i));
+            }
+          }
+        };
+      }
+    };
+  }
+}
diff --git 
a/integration-test/src/test/java/org/apache/iotdb/relational/it/db/it/IoTDBWindowTVFIT.java
 
b/integration-test/src/test/java/org/apache/iotdb/relational/it/db/it/IoTDBWindowTVFIT.java
index 68cd390f094..c947722f26d 100644
--- 
a/integration-test/src/test/java/org/apache/iotdb/relational/it/db/it/IoTDBWindowTVFIT.java
+++ 
b/integration-test/src/test/java/org/apache/iotdb/relational/it/db/it/IoTDBWindowTVFIT.java
@@ -130,6 +130,14 @@ public class IoTDBWindowTVFIT {
         expectedHeader,
         retArray,
         DATABASE_NAME);
+    tableAssertTestFail(
+        "SELECT * FROM HOP(DATA => bid, TIMECOL => 'time', SLIDE => -300000, 
SIZE => 600000) ORDER BY stock_id, time",
+        "Invalid scalar argument SLIDE, should be a positive value",
+        DATABASE_NAME);
+    tableAssertTestFail(
+        "SELECT * FROM HOP(DATA => bid, TIMECOL => 'time', SLIDE => 300000, 
SIZE => -600000) ORDER BY stock_id, time",
+        "Invalid scalar argument SIZE, should be a positive value",
+        DATABASE_NAME);
   }
 
   @Test
@@ -274,6 +282,10 @@ public class IoTDBWindowTVFIT {
         expectedHeader,
         retArray,
         DATABASE_NAME);
+    tableAssertTestFail(
+        "SELECT * FROM TUMBLE(DATA => bid, TIMECOL => 'time', SIZE => 0m) 
ORDER BY stock_id, time",
+        "Invalid scalar argument SIZE, should be a positive value",
+        DATABASE_NAME);
   }
 
   @Test
@@ -325,10 +337,17 @@ public class IoTDBWindowTVFIT {
         DATABASE_NAME);
 
     // test UDFException
-    String errMsg = "Cumulative table function requires size must be an 
integral multiple of step.";
     tableAssertTestFail(
         "SELECT window_start, window_end, stock_id, sum(price) as sum FROM 
CUMULATE(DATA => bid, TIMECOL => 'time', STEP => 4m, SIZE => 10m) GROUP BY 
window_start, window_end, stock_id ORDER BY stock_id, window_start",
-        errMsg,
+        "Cumulative table function requires size must be an integral multiple 
of step.",
+        DATABASE_NAME);
+    tableAssertTestFail(
+        "SELECT * FROM CUMULATE(DATA => bid, TIMECOL => 'time', STEP => 0m, 
SIZE => 5m) ORDER BY stock_id, time",
+        "Invalid scalar argument STEP, should be a positive value",
+        DATABASE_NAME);
+    tableAssertTestFail(
+        "SELECT * FROM CUMULATE(DATA => bid, TIMECOL => 'time', STEP => 1m, 
SIZE => 0m) ORDER BY stock_id, time",
+        "Invalid scalar argument SIZE, should be a positive value",
         DATABASE_NAME);
   }
 }
diff --git 
a/integration-test/src/test/java/org/apache/iotdb/relational/it/db/it/udf/IoTDBUserDefinedTableFunctionIT.java
 
b/integration-test/src/test/java/org/apache/iotdb/relational/it/db/it/udf/IoTDBUserDefinedTableFunctionIT.java
index 26f229c082f..7fe6648fe70 100644
--- 
a/integration-test/src/test/java/org/apache/iotdb/relational/it/db/it/udf/IoTDBUserDefinedTableFunctionIT.java
+++ 
b/integration-test/src/test/java/org/apache/iotdb/relational/it/db/it/udf/IoTDBUserDefinedTableFunctionIT.java
@@ -242,6 +242,22 @@ public class IoTDBUserDefinedTableFunctionIT {
         DATABASE_NAME);
   }
 
+  @Test
+  public void testPassThroughPartitionColumn() {
+    SQLFunctionUtils.createUDF(
+        "MY_SELECT", 
"org.apache.iotdb.db.query.udf.example.relational.MySelectColumn");
+    String[] expectedHeader = new String[] {"s1", "device_id"};
+    String[] retArray =
+        new String[] {
+          "1,d0,", "null,d0,", "3,d0,", "4,d1,",
+        };
+    tableResultSetEqualTest(
+        "select * from MY_SELECT(vehicle PARTITION BY device_id, 's1') ORDER 
BY device_id",
+        expectedHeader,
+        retArray,
+        DATABASE_NAME);
+  }
+
   @Test
   public void testIllegalInput() {
     SQLFunctionUtils.createUDF(
diff --git 
a/iotdb-api/udf-api/src/main/java/org/apache/iotdb/udf/api/relational/table/argument/ScalarArgumentChecker.java
 
b/iotdb-api/udf-api/src/main/java/org/apache/iotdb/udf/api/relational/table/argument/ScalarArgumentChecker.java
new file mode 100644
index 00000000000..241ce5939bc
--- /dev/null
+++ 
b/iotdb-api/udf-api/src/main/java/org/apache/iotdb/udf/api/relational/table/argument/ScalarArgumentChecker.java
@@ -0,0 +1,32 @@
+/*
+ * 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.udf.api.relational.table.argument;
+
+import java.util.function.Function;
+
+public class ScalarArgumentChecker {
+  public static Function<Object, String> POSITIVE_LONG_CHECKER =
+      (value) -> {
+        if (value instanceof Long && (Long) value > 0) {
+          return null;
+        }
+        return "should be a positive value";
+      };
+}
diff --git 
a/iotdb-api/udf-api/src/main/java/org/apache/iotdb/udf/api/relational/table/processor/TableFunctionDataProcessor.java
 
b/iotdb-api/udf-api/src/main/java/org/apache/iotdb/udf/api/relational/table/processor/TableFunctionDataProcessor.java
index c3cd5483b64..d96cc4a98c4 100644
--- 
a/iotdb-api/udf-api/src/main/java/org/apache/iotdb/udf/api/relational/table/processor/TableFunctionDataProcessor.java
+++ 
b/iotdb-api/udf-api/src/main/java/org/apache/iotdb/udf/api/relational/table/processor/TableFunctionDataProcessor.java
@@ -43,7 +43,8 @@ public interface TableFunctionDataProcessor {
    * @param properColumnBuilders A list of {@link ColumnBuilder} for each 
column in the output
    *     table.
    * @param passThroughIndexBuilder A {@link ColumnBuilder} for pass through 
columns. Index is
-   *     started from 0 of the whole partition.
+   *     started from 0 of the whole partition. It will be null if table 
argument is not declared
+   *     with PASS_THROUGH_COLUMNS.
    */
   void process(
       Record input,
@@ -56,7 +57,8 @@ public interface TableFunctionDataProcessor {
    *
    * @param columnBuilders A list of {@link ColumnBuilder} for each column in 
the output table.
    * @param passThroughIndexBuilder A {@link ColumnBuilder} for pass through 
columns. Index is
-   *     started from 0 of the whole partition.
+   *     started from 0 of the whole partition. It will be null if table 
argument is not declared
+   *     with PASS_THROUGH_COLUMNS.
    */
   default void finish(List<ColumnBuilder> columnBuilders, ColumnBuilder 
passThroughIndexBuilder) {
     // do nothing
diff --git 
a/iotdb-api/udf-api/src/main/java/org/apache/iotdb/udf/api/relational/table/specification/ScalarParameterSpecification.java
 
b/iotdb-api/udf-api/src/main/java/org/apache/iotdb/udf/api/relational/table/specification/ScalarParameterSpecification.java
index 496d923b079..7333bd32601 100644
--- 
a/iotdb-api/udf-api/src/main/java/org/apache/iotdb/udf/api/relational/table/specification/ScalarParameterSpecification.java
+++ 
b/iotdb-api/udf-api/src/main/java/org/apache/iotdb/udf/api/relational/table/specification/ScalarParameterSpecification.java
@@ -21,13 +21,21 @@ package 
org.apache.iotdb.udf.api.relational.table.specification;
 
 import org.apache.iotdb.udf.api.type.Type;
 
+import java.util.ArrayList;
+import java.util.List;
 import java.util.Optional;
+import java.util.function.Function;
 
 public class ScalarParameterSpecification extends ParameterSpecification {
   private final Type type;
+  private final List<Function<Object, String>> checkers;
 
   private ScalarParameterSpecification(
-      String name, Type type, boolean required, Object defaultValue) {
+      String name,
+      Type type,
+      boolean required,
+      Object defaultValue,
+      List<Function<Object, String>> checkers) {
     super(name, required, Optional.ofNullable(defaultValue));
     this.type = type;
     if (defaultValue != null && !type.checkObjectType(defaultValue)) {
@@ -35,12 +43,17 @@ public class ScalarParameterSpecification extends 
ParameterSpecification {
           String.format(
               "default value %s does not match the declared type: %s", 
defaultValue, type));
     }
+    this.checkers = checkers;
   }
 
   public Type getType() {
     return type;
   }
 
+  public List<Function<Object, String>> getCheckers() {
+    return checkers;
+  }
+
   public static Builder builder() {
     return new Builder();
   }
@@ -50,6 +63,7 @@ public class ScalarParameterSpecification extends 
ParameterSpecification {
     private Type type;
     private boolean required = true;
     private Object defaultValue;
+    private List<Function<Object, String>> checkers = new ArrayList<>();
 
     private Builder() {}
 
@@ -63,6 +77,11 @@ public class ScalarParameterSpecification extends 
ParameterSpecification {
       return this;
     }
 
+    public Builder addChecker(Function<Object, String> checker) {
+      this.checkers.add(checker);
+      return this;
+    }
+
     public Builder defaultValue(Object defaultValue) {
       this.required = false;
       this.defaultValue = defaultValue;
@@ -70,7 +89,7 @@ public class ScalarParameterSpecification extends 
ParameterSpecification {
     }
 
     public ScalarParameterSpecification build() {
-      return new ScalarParameterSpecification(name, type, required, 
defaultValue);
+      return new ScalarParameterSpecification(name, type, required, 
defaultValue, checkers);
     }
   }
 }
diff --git 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/execution/operator/process/function/TableFunctionOperator.java
 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/execution/operator/process/function/TableFunctionOperator.java
index a0a2073f7cf..4e9f7e436a5 100644
--- 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/execution/operator/process/function/TableFunctionOperator.java
+++ 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/execution/operator/process/function/TableFunctionOperator.java
@@ -38,6 +38,7 @@ import org.apache.tsfile.common.conf.TSFileDescriptor;
 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.LongColumn;
 import org.apache.tsfile.read.common.block.column.LongColumnBuilder;
 import org.apache.tsfile.read.common.block.column.RunLengthEncodedColumn;
 import org.apache.tsfile.utils.RamUsageEstimator;
@@ -48,6 +49,7 @@ import java.util.Collections;
 import java.util.Iterator;
 import java.util.LinkedList;
 import java.util.List;
+import java.util.Optional;
 import java.util.Queue;
 
 import static 
org.apache.iotdb.db.queryengine.execution.operator.source.relational.TableScanOperator.TIME_COLUMN_TEMPLATE;
@@ -70,6 +72,7 @@ public class TableFunctionOperator implements ProcessOperator 
{
   private final boolean needPassThrough;
   private final PartitionCache partitionCache;
   private final boolean requireRecordSnapshot;
+  private final boolean isDeclaredAsPassThrough;
 
   private TableFunctionDataProcessor processor;
   private PartitionState partitionState;
@@ -87,6 +90,7 @@ public class TableFunctionOperator implements ProcessOperator 
{
       int properChannelCount,
       List<Integer> requiredChannels,
       List<Integer> passThroughChannels,
+      boolean isDeclaredAsPassThrough,
       List<Integer> partitionChannels,
       boolean requireRecordSnapshot) {
     this.operatorContext = operatorContext;
@@ -96,6 +100,7 @@ public class TableFunctionOperator implements 
ProcessOperator {
     this.partitionRecognizer =
         new PartitionRecognizer(
             partitionChannels, requiredChannels, passThroughChannels, 
inputDataTypes);
+    this.isDeclaredAsPassThrough = isDeclaredAsPassThrough;
     this.needPassThrough = properChannelCount != outputDataTypes.size();
     this.partitionState = null;
     this.properBlockBuilder = new TsBlockBuilder(outputDataTypes.subList(0, 
properChannelCount));
@@ -192,7 +197,7 @@ public class TableFunctionOperator implements 
ProcessOperator {
   }
 
   private ColumnBuilder getPassThroughIndexBuilder() {
-    return new LongColumnBuilder(null, 1);
+    return isDeclaredAsPassThrough ? new LongColumnBuilder(null, 1) : null;
   }
 
   private List<TsBlock> buildTsBlock(
@@ -201,7 +206,7 @@ public class TableFunctionOperator implements 
ProcessOperator {
     if (properChannelCount > 0) {
       // if there is proper column, use its position count
       positionCount = properColumnBuilders.get(0).getPositionCount();
-    } else if (needPassThrough) {
+    } else if (isDeclaredAsPassThrough) {
       // if there is no proper column, use pass through column's position count
       positionCount = passThroughIndexBuilder.getPositionCount();
     }
@@ -215,7 +220,14 @@ public class TableFunctionOperator implements 
ProcessOperator {
     if (needPassThrough) {
       // handle pass through column only if needed
       int builtCount = 0;
-      Column passThroughIndex = passThroughIndexBuilder.build();
+      Column passThroughIndex;
+      if (isDeclaredAsPassThrough) {
+        passThroughIndex = passThroughIndexBuilder.build();
+      } else {
+        passThroughIndex =
+            new RunLengthEncodedColumn(
+                new LongColumn(1, Optional.empty(), new long[] {0}), 
positionCount);
+      }
       for (Column[] passThroughColumns : 
partitionCache.getPassThroughResult(passThroughIndex)) {
         int subBlockPositionCount = passThroughColumns[0].getPositionCount();
         TsBlock subProperBlock = properBlock.getRegion(builtCount, 
subBlockPositionCount);
diff --git 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/planner/TableOperatorGenerator.java
 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/planner/TableOperatorGenerator.java
index ee6a13a006c..e98259a353a 100644
--- 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/planner/TableOperatorGenerator.java
+++ 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/planner/TableOperatorGenerator.java
@@ -2934,6 +2934,9 @@ public class TableOperatorGenerator extends 
PlanVisitor<Operator, LocalExecution
           properChannelCount,
           requiredChannels,
           passThroughChannels,
+          passThroughSpecification
+              
.map(TableFunctionNode.PassThroughSpecification::isDeclaredAsPassThrough)
+              .orElse(false),
           partitionChannels,
           node.isRequireRecordSnapshot());
     }
diff --git 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/analyzer/StatementAnalyzer.java
 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/analyzer/StatementAnalyzer.java
index ec8279853bd..8c945bd72ab 100644
--- 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/analyzer/StatementAnalyzer.java
+++ 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/analyzer/StatementAnalyzer.java
@@ -4417,6 +4417,14 @@ public class StatementAnalyzer {
                   argumentSpecification.getType(), 
constantValue.getClass().getSimpleName()));
         }
       }
+      for (Function<Object, String> checker : 
argumentSpecification.getCheckers()) {
+        String errMsg = checker.apply(constantValue);
+        if (errMsg != null) {
+          throw new SemanticException(
+              String.format(
+                  "Invalid scalar argument %s, %s", 
argumentSpecification.getName(), errMsg));
+        }
+      }
       return new ArgumentAnalysis(
           new ScalarArgument(argumentSpecification.getType(), constantValue), 
Optional.empty());
     }
diff --git 
a/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/udf/builtin/relational/tvf/CumulateTableFunction.java
 
b/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/udf/builtin/relational/tvf/CumulateTableFunction.java
index acb3e588f05..aee0481cd24 100644
--- 
a/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/udf/builtin/relational/tvf/CumulateTableFunction.java
+++ 
b/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/udf/builtin/relational/tvf/CumulateTableFunction.java
@@ -42,6 +42,7 @@ import java.util.List;
 import java.util.Map;
 
 import static 
org.apache.iotdb.commons.udf.builtin.relational.tvf.WindowTVFUtils.findColumnIndex;
+import static 
org.apache.iotdb.udf.api.relational.table.argument.ScalarArgumentChecker.POSITIVE_LONG_CHECKER;
 
 public class CumulateTableFunction implements TableFunction {
 
@@ -64,8 +65,16 @@ public class CumulateTableFunction implements TableFunction {
             .type(Type.STRING)
             .defaultValue("time")
             .build(),
-        
ScalarParameterSpecification.builder().name(SIZE_PARAMETER_NAME).type(Type.INT64).build(),
-        
ScalarParameterSpecification.builder().name(STEP_PARAMETER_NAME).type(Type.INT64).build(),
+        ScalarParameterSpecification.builder()
+            .name(SIZE_PARAMETER_NAME)
+            .type(Type.INT64)
+            .addChecker(POSITIVE_LONG_CHECKER)
+            .build(),
+        ScalarParameterSpecification.builder()
+            .name(STEP_PARAMETER_NAME)
+            .type(Type.INT64)
+            .addChecker(POSITIVE_LONG_CHECKER)
+            .build(),
         ScalarParameterSpecification.builder()
             .name(ORIGIN_PARAMETER_NAME)
             .type(Type.TIMESTAMP)
diff --git 
a/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/udf/builtin/relational/tvf/HOPTableFunction.java
 
b/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/udf/builtin/relational/tvf/HOPTableFunction.java
index b2178c5805a..f621d24e80b 100644
--- 
a/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/udf/builtin/relational/tvf/HOPTableFunction.java
+++ 
b/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/udf/builtin/relational/tvf/HOPTableFunction.java
@@ -41,6 +41,7 @@ import java.util.List;
 import java.util.Map;
 
 import static 
org.apache.iotdb.commons.udf.builtin.relational.tvf.WindowTVFUtils.findColumnIndex;
+import static 
org.apache.iotdb.udf.api.relational.table.argument.ScalarArgumentChecker.POSITIVE_LONG_CHECKER;
 
 public class HOPTableFunction implements TableFunction {
 
@@ -63,8 +64,16 @@ public class HOPTableFunction implements TableFunction {
             .type(Type.STRING)
             .defaultValue("time")
             .build(),
-        
ScalarParameterSpecification.builder().name(SIZE_PARAMETER_NAME).type(Type.INT64).build(),
-        
ScalarParameterSpecification.builder().name(SLIDE_PARAMETER_NAME).type(Type.INT64).build(),
+        ScalarParameterSpecification.builder()
+            .name(SIZE_PARAMETER_NAME)
+            .addChecker(POSITIVE_LONG_CHECKER)
+            .type(Type.INT64)
+            .build(),
+        ScalarParameterSpecification.builder()
+            .name(SLIDE_PARAMETER_NAME)
+            .addChecker(POSITIVE_LONG_CHECKER)
+            .type(Type.INT64)
+            .build(),
         ScalarParameterSpecification.builder()
             .name(ORIGIN_PARAMETER_NAME)
             .type(Type.TIMESTAMP)
diff --git 
a/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/udf/builtin/relational/tvf/TumbleTableFunction.java
 
b/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/udf/builtin/relational/tvf/TumbleTableFunction.java
index a239c694129..3c7ec080cef 100644
--- 
a/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/udf/builtin/relational/tvf/TumbleTableFunction.java
+++ 
b/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/udf/builtin/relational/tvf/TumbleTableFunction.java
@@ -42,6 +42,7 @@ import java.util.List;
 import java.util.Map;
 
 import static 
org.apache.iotdb.commons.udf.builtin.relational.tvf.WindowTVFUtils.findColumnIndex;
+import static 
org.apache.iotdb.udf.api.relational.table.argument.ScalarArgumentChecker.POSITIVE_LONG_CHECKER;
 
 public class TumbleTableFunction implements TableFunction {
   private static final String DATA_PARAMETER_NAME = "DATA";
@@ -62,7 +63,11 @@ public class TumbleTableFunction implements TableFunction {
             .type(Type.STRING)
             .defaultValue("time")
             .build(),
-        
ScalarParameterSpecification.builder().name(SIZE_PARAMETER_NAME).type(Type.INT64).build(),
+        ScalarParameterSpecification.builder()
+            .name(SIZE_PARAMETER_NAME)
+            .addChecker(POSITIVE_LONG_CHECKER)
+            .type(Type.INT64)
+            .build(),
         ScalarParameterSpecification.builder()
             .name(ORIGIN_PARAMETER_NAME)
             .type(Type.TIMESTAMP)

Reply via email to