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 6a236ff51d6 Implementation of LowPass, HighPass, and XCorr Table 
Functions (#18539)
6a236ff51d6 is described below

commit 6a236ff51d6abd54aaf03fdc8f2b37179dfc5f3e
Author: CYB <[email protected]>
AuthorDate: Wed Sep 2 15:30:15 2026 +0800

    Implementation of LowPass, HighPass, and XCorr Table Functions (#18539)
---
 .../relational/it/db/it/IoTDBWindowTVFIT.java      | 273 ++++++++++++++++++
 .../relational/analyzer/StatementAnalyzer.java     |   3 +
 .../plan/relational/planner/RelationPlanner.java   |  15 +-
 .../apache/iotdb/commons/i18n/CommonMessages.java  | 255 ++++++++++++-----
 .../apache/iotdb/commons/i18n/CommonMessages.java  |   9 +-
 .../function/TableBuiltinTableFunction.java        |  14 +-
 .../tvf/FilterTransferTableFunction.java           | 315 +++++++++++++++++++++
 .../relational/tvf/HighPassTableFunction.java      |  81 ++++++
 .../relational/tvf/LowPassTableFunction.java       |  77 +++++
 .../builtin/relational/tvf/M4TableFunction.java    |  87 +-----
 .../udf/builtin/relational/tvf/WindowTVFUtils.java | 185 ++++++++++++
 .../builtin/relational/tvf/XCorrTableFunction.java | 249 ++++++++++++++++
 .../builtin/relational/tvf/fft/DoubleFFT_1D.java   |  34 ++-
 .../udf/builtin/relational/tvf/fft/FFT1DTest.java  |  39 +++
 14 files changed, 1476 insertions(+), 160 deletions(-)

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 3aa33889568..a225039b474 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
@@ -31,17 +31,23 @@ import org.junit.experimental.categories.Category;
 import org.junit.runner.RunWith;
 
 import java.sql.Connection;
+import java.sql.ResultSet;
+import java.sql.ResultSetMetaData;
+import java.sql.SQLException;
 import java.sql.Statement;
+import java.sql.Types;
 import java.util.Arrays;
 import java.util.List;
 
 import static org.apache.iotdb.db.it.utils.TestUtils.*;
+import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.fail;
 
 @RunWith(IoTDBTestRunner.class)
 @Category({TableLocalStandaloneIT.class, TableClusterIT.class})
 public class IoTDBWindowTVFIT {
   private static final String DATABASE_NAME = "test";
+  private static final double DELTA = 1e-9;
   private static final String[] sqls =
       new String[] {
         "CREATE DATABASE " + DATABASE_NAME,
@@ -1347,4 +1353,271 @@ public class IoTDBWindowTVFIT {
         "701: The type of the column [s1] is not as expected.",
         DATABASE_NAME);
   }
+
+  @Test
+  public void testLowPassWithOnePartition() {
+    String[] expectedHeader = new String[] {"stock_id", "time", 
"lowpass(price)", "lowpass(s1)"};
+    String[] retArray =
+        new String[] {
+          "AAPL,2021-01-01T09:05:00.000Z,101.66666666666667,101.0,",
+          "AAPL,2021-01-01T09:07:00.000Z,101.66666666666667,101.0,",
+          "AAPL,2021-01-01T09:09:00.000Z,101.66666666666667,101.0,",
+          "TESL,2021-01-01T09:06:00.000Z,199.0,212.0,",
+          "TESL,2021-01-01T09:07:00.000Z,199.0,212.0,",
+          "TESL,2021-01-01T09:15:00.000Z,199.0,212.0,"
+        };
+    tableResultSetEqualWithTolerance(
+        "SELECT * FROM LOWPASS(DATA => bid PARTITION BY stock_id ORDER BY 
time, "
+            + "TIMECOL => 'time', WPASS => 0.5) ORDER BY stock_id, time",
+        expectedHeader,
+        retArray,
+        DATABASE_NAME);
+  }
+
+  @Test
+  public void testLowPassWithNullValues() {
+    String[] expectedHeader = new String[] {"device_id", "time", 
"lowpass(s2)"};
+    String[] retArray =
+        new String[] {
+          "device_1,1970-01-01T00:00:00.001Z,23.5,",
+          "device_1,1970-01-01T00:00:00.003Z,null,",
+          "device_1,1970-01-01T00:00:00.006Z,null,",
+          "device_1,1970-01-01T00:00:00.009Z,null,",
+          "device_1,1970-01-01T00:00:00.020Z,23.5,"
+        };
+    tableResultSetEqualWithTolerance(
+        "SELECT * FROM LOWPASS(DATA => "
+            + "(SELECT time, device_id, s2 FROM table1 WHERE device_id = 
'device_1') "
+            + "PARTITION BY device_id ORDER BY time, TIMECOL => 'time', WPASS 
=> 0.5) "
+            + "ORDER BY time",
+        expectedHeader,
+        retArray,
+        DATABASE_NAME);
+  }
+
+  @Test
+  public void testLowPassWithMultiplePartitionColumns() {
+    String[] expectedHeader = new String[] {"factory_id", "device_id", "time", 
"lowpass(s1)"};
+    String[] retArray =
+        new String[] {
+          "F1,device_1,1970-01-01T00:00:00.001Z,10.0,",
+          "F1,device_1,1970-01-01T00:00:00.005Z,10.0,",
+          "F1,device_1,1970-01-01T00:00:00.009Z,10.0,",
+          "F1,device_2,1970-01-01T00:00:00.002Z,22.5,",
+          "F1,device_2,1970-01-01T00:00:00.011Z,22.5,",
+          "F2,device_1,1970-01-01T00:00:00.003Z,30.0,"
+        };
+    tableResultSetEqualWithTolerance(
+        "SELECT * FROM LOWPASS(DATA => table5 "
+            + "PARTITION BY (factory_id, device_id) ORDER BY time, "
+            + "TIMECOL => 'time', WPASS => 0.5) ORDER BY factory_id, 
device_id, time",
+        expectedHeader,
+        retArray,
+        DATABASE_NAME);
+  }
+
+  @Test
+  public void testLowPassRejectsUnsupportedCalculationColumnType() {
+    tableAssertTestFail(
+        "SELECT * FROM LOWPASS(DATA => (SELECT time, device_id, s3 FROM 
table1) "
+            + "PARTITION BY device_id ORDER BY time, TIMECOL => 'time', WPASS 
=> 0.5)",
+        "701: Only column with double, float, int32, int64 can be calculated 
by the function, s3 is the STRING.",
+        DATABASE_NAME);
+  }
+
+  @Test
+  public void testHighWithOnePartition() {
+    String[] expectedHeader = new String[] {"stock_id", "time", 
"highpass(price)", "highpass(s1)"};
+    String[] retArray =
+        new String[] {
+          "AAPL,2021-01-01T09:05:00.000Z,-1.6666666666666667,0.0,",
+          "AAPL,2021-01-01T09:07:00.000Z,1.3333333333333333,0.0,",
+          "AAPL,2021-01-01T09:09:00.000Z,0.3333333333333333,0.0,",
+          "TESL,2021-01-01T09:06:00.000Z,1.0,-110.0,",
+          "TESL,2021-01-01T09:07:00.000Z,3.0,-10.0,",
+          "TESL,2021-01-01T09:15:00.000Z,-4.0,120.0,"
+        };
+    tableResultSetEqualWithTolerance(
+        "SELECT * FROM HIGHPASS(DATA => bid PARTITION BY stock_id ORDER BY 
time, "
+            + "TIMECOL => 'time', WPASS => 0.5) ORDER BY stock_id, time",
+        expectedHeader,
+        retArray,
+        DATABASE_NAME);
+  }
+
+  @Test
+  public void testHighPassWithNullValues() {
+    String[] expectedHeader = new String[] {"device_id", "time", 
"highpass(s2)"};
+    String[] retArray =
+        new String[] {
+          "device_1,1970-01-01T00:00:00.001Z,-11.5,",
+          "device_1,1970-01-01T00:00:00.003Z,null,",
+          "device_1,1970-01-01T00:00:00.006Z,null,",
+          "device_1,1970-01-01T00:00:00.009Z,null,",
+          "device_1,1970-01-01T00:00:00.020Z,11.5,"
+        };
+    tableResultSetEqualWithTolerance(
+        "SELECT * FROM HIGHPASS(DATA => "
+            + "(SELECT time, device_id, s2 FROM table1 WHERE device_id = 
'device_1') "
+            + "PARTITION BY device_id ORDER BY time, TIMECOL => 'time', WPASS 
=> 0.5) "
+            + "ORDER BY time",
+        expectedHeader,
+        retArray,
+        DATABASE_NAME);
+  }
+
+  @Test
+  public void testHighPassWithMultiplePartitionColumns() {
+    String[] expectedHeader = new String[] {"factory_id", "device_id", "time", 
"highpass(s1)"};
+    String[] retArray =
+        new String[] {
+          "F1,device_1,1970-01-01T00:00:00.001Z,0.0,",
+          "F1,device_1,1970-01-01T00:00:00.005Z,5.0,",
+          "F1,device_1,1970-01-01T00:00:00.009Z,-5.0,",
+          "F1,device_2,1970-01-01T00:00:00.002Z,-2.5,",
+          "F1,device_2,1970-01-01T00:00:00.011Z,2.5,",
+          "F2,device_1,1970-01-01T00:00:00.003Z,0.0,"
+        };
+    tableResultSetEqualWithTolerance(
+        "SELECT * FROM HIGHPASS(DATA => table5 "
+            + "PARTITION BY (factory_id, device_id) ORDER BY time, "
+            + "TIMECOL => 'time', WPASS => 0.5) ORDER BY factory_id, 
device_id, time",
+        expectedHeader,
+        retArray,
+        DATABASE_NAME);
+  }
+
+  @Test
+  public void testHighPassRejectsUnsupportedCalculationColumnType() {
+    tableAssertTestFail(
+        "SELECT * FROM HIGHPASS(DATA => (SELECT time, device_id, s3 FROM 
table1) "
+            + "PARTITION BY device_id ORDER BY time, TIMECOL => 'time', WPASS 
=> 0.5)",
+        "701: Only column with double, float, int32, int64 can be calculated 
by the function, s3 is the STRING.",
+        DATABASE_NAME);
+  }
+
+  @Test
+  public void testXCorrP0() {
+    String[] expectedHeader = new String[] {"stock_id", "xcorr(price, s1)"};
+    String[] retArray =
+        new String[] {
+          "AAPL,10100.0,",
+          "AAPL,10251.5,",
+          "AAPL,10268.333333333334,",
+          "AAPL,10352.5,",
+          "AAPL,10302.0,",
+          "TESL,66400.0,",
+          "TESL,53732.0,",
+          "TESL,41981.333333333336,",
+          "TESL,29997.0,",
+          "TESL,19890.0,"
+        };
+    tableResultSetEqualTest(
+        "SELECT * FROM XCORR(DATA => bid PARTITION BY stock_id ORDER BY time, "
+            + "TIMECOL => 'time') ORDER BY stock_id",
+        expectedHeader,
+        retArray,
+        DATABASE_NAME);
+  }
+
+  @Test
+  public void testXCorrWithNullValues() {
+    String[] expectedHeader = new String[] {"device_id", "xcorr(s1, s2)"};
+    String[] retArray =
+        new String[] {
+          "device_1,525.0,",
+          "device_1,175.0,",
+          "device_1,1050.0,",
+          "device_1,350.0,",
+          "device_1,790.0,",
+          "device_1,60.0,",
+          "device_1,360.0,",
+          "device_1,120.0,",
+          "device_1,480.0,"
+        };
+    tableResultSetEqualTest(
+        "SELECT * FROM XCORR(DATA => "
+            + "(SELECT time, device_id, s1, s2 FROM table1 WHERE device_id = 
'device_1') "
+            + "PARTITION BY device_id ORDER BY time, TIMECOL => 'time')",
+        expectedHeader,
+        retArray,
+        DATABASE_NAME);
+  }
+
+  @Test
+  public void testXCorrWithMultiplePartitionColumns() {
+    String[] expectedHeader = new String[] {"factory_id", "device_id", 
"xcorr(s1, s2)"};
+    String[] retArray =
+        new String[] {
+          "F1,device_1,50.0,",
+          "F1,device_1,112.5,",
+          "F1,device_1,116.66666666666667,",
+          "F1,device_1,112.5,",
+          "F1,device_1,50.0,",
+          "F1,device_2,500.0,",
+          "F1,device_2,512.5,",
+          "F1,device_2,500.0,",
+          "F2,device_1,900.0,"
+        };
+    tableResultSetEqualTest(
+        "SELECT * FROM XCORR(DATA => "
+            + "(SELECT time, factory_id, device_id, s1, s1 AS s2 FROM table5) "
+            + "PARTITION BY (factory_id, device_id) ORDER BY time, TIMECOL => 
'time') "
+            + "ORDER BY factory_id, device_id",
+        expectedHeader,
+        retArray,
+        DATABASE_NAME);
+  }
+
+  @Test
+  public void testXCorrRejectsUnsupportedCalculationColumnType() {
+    tableAssertTestFail(
+        "SELECT * FROM XCORR(DATA => (SELECT time, device_id, s1, s3 FROM 
table1) "
+            + "PARTITION BY device_id ORDER BY time, TIMECOL => 'time')",
+        "701: Only column with double, float, int32, int64 can be calculated 
by the function, s3 is the STRING.",
+        DATABASE_NAME);
+  }
+
+  @Test
+  public void testXCorrRejectsUnexpectedCalculationColumnCount() {
+    tableAssertTestFail(
+        "SELECT * FROM XCORR(DATA => (select time, device_id, int_val, 
long_val, float_val from multi_type) PARTITION BY device_id ORDER BY time, 
TIMECOL => 'time')",
+        "701: XCorr requires exactly two calculation columns, but found 3.",
+        DATABASE_NAME);
+  }
+
+  private static void tableResultSetEqualWithTolerance(
+      String sql, String[] expectedHeader, String[] expectedRetArray, String 
database) {
+    try (Connection connection = EnvFactory.getEnv().getTableConnection();
+        Statement statement = connection.createStatement()) {
+      connection.setClientInfo("time_zone", "+00:00");
+      statement.execute("USE " + database);
+      try (ResultSet resultSet = statement.executeQuery(sql)) {
+        ResultSetMetaData metaData = resultSet.getMetaData();
+        assertEquals(expectedHeader.length, metaData.getColumnCount());
+        for (int i = 1; i <= metaData.getColumnCount(); i++) {
+          assertEquals(expectedHeader[i - 1], metaData.getColumnName(i));
+        }
+
+        int rowIndex = 0;
+        while (resultSet.next()) {
+          String[] expectedColumns = expectedRetArray[rowIndex].split(",", -1);
+          for (int i = 1; i <= expectedHeader.length; i++) {
+            String expected = expectedColumns[i - 1];
+            if (resultSet.getString(i) == null) {
+              assertEquals("null", expected);
+            } else if (metaData.getColumnType(i) == Types.DOUBLE) {
+              assertEquals(Double.parseDouble(expected), 
resultSet.getDouble(i), DELTA);
+            } else {
+              assertEquals(expected, resultSet.getString(i));
+            }
+          }
+          rowIndex++;
+        }
+        assertEquals(expectedRetArray.length, rowIndex);
+      }
+    } catch (SQLException e) {
+      fail(e.getMessage());
+    }
+  }
 }
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 9a54519953d..b5c394539f2 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
@@ -5923,6 +5923,9 @@ public class StatementAnalyzer {
 
     private boolean isPartitionColumnsProvidedByProperSchema(String 
functionName) {
       return 
TableBuiltinTableFunction.M4.getFunctionName().equalsIgnoreCase(functionName)
+          || 
TableBuiltinTableFunction.LOWPASS.getFunctionName().equalsIgnoreCase(functionName)
+          || 
TableBuiltinTableFunction.HIGHPASS.getFunctionName().equalsIgnoreCase(functionName)
+          || 
TableBuiltinTableFunction.XCORR.getFunctionName().equalsIgnoreCase(functionName)
           || 
TableBuiltinTableFunction.FFT.getFunctionName().equalsIgnoreCase(functionName);
     }
 
diff --git 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/planner/RelationPlanner.java
 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/planner/RelationPlanner.java
index 7fc367b3785..6f5f3c278ed 100644
--- 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/planner/RelationPlanner.java
+++ 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/planner/RelationPlanner.java
@@ -1572,12 +1572,7 @@ public class RelationPlanner implements 
AstVisitor<RelationPlan, Void> {
                 symbol ->
                     new TableFunctionNode.PassThroughColumn(symbol, 
partitionBy.contains(symbol)))
             .forEach(passThroughColumns::add);
-      } else if (!TableBuiltinTableFunction.M4
-              .getFunctionName()
-              .equalsIgnoreCase(functionAnalysis.getFunctionName())
-          && !TableBuiltinTableFunction.FFT
-              .getFunctionName()
-              .equalsIgnoreCase(functionAnalysis.getFunctionName())
+      } else if (needAddPartitionColumn(functionAnalysis.getFunctionName())
           && tableArgument.getPartitionBy().isPresent()) {
         tableArgument.getPartitionBy().get().stream()
             // the original symbols for partitioning columns, not coerced
@@ -1613,6 +1608,14 @@ public class RelationPlanner implements 
AstVisitor<RelationPlan, Void> {
     return new RelationPlan(root, analysis.getScope(node), 
outputSymbols.build(), outerContext);
   }
 
+  private boolean needAddPartitionColumn(String functionName) {
+    return 
!TableBuiltinTableFunction.M4.getFunctionName().equalsIgnoreCase(functionName)
+        && 
!TableBuiltinTableFunction.LOWPASS.getFunctionName().equalsIgnoreCase(functionName)
+        && 
!TableBuiltinTableFunction.HIGHPASS.getFunctionName().equalsIgnoreCase(functionName)
+        && 
!TableBuiltinTableFunction.XCORR.getFunctionName().equalsIgnoreCase(functionName)
+        && 
!TableBuiltinTableFunction.FFT.getFunctionName().equalsIgnoreCase(functionName);
+  }
+
   private RelationPlan planExternalTsFileScan(
       TableFunctionInvocation node, TableFunctionInvocationAnalysis 
functionAnalysis) {
     if (!(functionAnalysis.getTableFunctionHandle()
diff --git 
a/iotdb-core/node-commons/src/main/i18n/en/org/apache/iotdb/commons/i18n/CommonMessages.java
 
b/iotdb-core/node-commons/src/main/i18n/en/org/apache/iotdb/commons/i18n/CommonMessages.java
index 94194a086b4..40c75066d87 100644
--- 
a/iotdb-core/node-commons/src/main/i18n/en/org/apache/iotdb/commons/i18n/CommonMessages.java
+++ 
b/iotdb-core/node-commons/src/main/i18n/en/org/apache/iotdb/commons/i18n/CommonMessages.java
@@ -38,8 +38,7 @@ public final class CommonMessages {
   public static final String UNKNOWN_NODE_STATUS = "Unknown NodeStatus %s.";
 
   // --- consensus ---
-  public static final String UNRECOGNIZED_CONSENSUS_GROUP_ID =
-      "Unrecognized ConsensusGroupId: %s";
+  public static final String UNRECOGNIZED_CONSENSUS_GROUP_ID = "Unrecognized 
ConsensusGroupId: %s";
   public static final String IOTV2_BG_NOT_TERMINATED =
       "IoTV2 background service did not terminate within {}s";
   public static final String IOTV2_BG_STILL_RUNNING =
@@ -136,93 +135,197 @@ public final class CommonMessages {
   public static final String MAP_MUST_NOT_BE_NULL = "Map must not be null.";
   public static final String MAP_ENTRY_MUST_NOT_BE_NULL = "Map Entry must not 
be null.";
   public static final String ITERATOR_MUST_NOT_BE_NULL = "Iterator must not be 
null";
-  public static final String ITERATOR_REMOVE_ONLY_AFTER_NEXT = "Iterator 
remove() can only be called once after next()";
+  public static final String ITERATOR_REMOVE_ONLY_AFTER_NEXT =
+      "Iterator remove() can only be called once after next()";
   public static final String FAIL_TO_GET_DATA_TYPE_IN_ROW = "Fail to get data 
type in row ";
   // 
---------------------------------------------------------------------------
   // Additional auto-collected messages
   // 
---------------------------------------------------------------------------
-  public static final String 
LOG_STEP_METRICS_ARG_ARG_TOTAL_ARG_SUM_2FMS_AVG_ARG_87491AB0 = "step metrics 
[%d]-[%s] - Total: %d, SUM: %.2fms, AVG: %fms, Last%dAVG: %fms";
-  public static final String 
LOG_ERROR_OCCURRED_DURING_TRANSFERRING_FILE_ARG_BYTEBUFFER_CAUSE_ARG_FEDC38A3 = 
"Error occurred during transferring file{} to ByteBuffer, the cause is {}";
-  public static final String 
LOG_ERROR_OCCURRED_DURING_WRITING_BYTEBUFFER_ARG_CAUSE_ARG_F3AD2DA0 = "Error 
occurred during writing bytebuffer to {} , the cause is {}";
-  public static final String EXCEPTION_SIZE_FILE_EXCEED_ARG_BYTES_C60F1149 = 
"Size of file exceed %d bytes";
-  public static final String 
EXCEPTION_UNRECOGNIZED_TCONSENSUSGROUPTYPE_9204FF8E = "Unrecognized 
TConsensusGroupType: ";
+  public static final String 
LOG_STEP_METRICS_ARG_ARG_TOTAL_ARG_SUM_2FMS_AVG_ARG_87491AB0 =
+      "step metrics [%d]-[%s] - Total: %d, SUM: %.2fms, AVG: %fms, Last%dAVG: 
%fms";
+  public static final String
+      
LOG_ERROR_OCCURRED_DURING_TRANSFERRING_FILE_ARG_BYTEBUFFER_CAUSE_ARG_FEDC38A3 =
+          "Error occurred during transferring file{} to ByteBuffer, the cause 
is {}";
+  public static final String 
LOG_ERROR_OCCURRED_DURING_WRITING_BYTEBUFFER_ARG_CAUSE_ARG_F3AD2DA0 =
+      "Error occurred during writing bytebuffer to {} , the cause is {}";
+  public static final String EXCEPTION_SIZE_FILE_EXCEED_ARG_BYTES_C60F1149 =
+      "Size of file exceed %d bytes";
+  public static final String 
EXCEPTION_UNRECOGNIZED_TCONSENSUSGROUPTYPE_9204FF8E =
+      "Unrecognized TConsensusGroupType: ";
   public static final String EXCEPTION_ID_1F238F51 = " with id = ";
-  public static final String 
LOG_MEMORY_COST_RELEASED_LARGER_THAN_MEMORY_COST_MEMORY_BLOCK_ARG_00DD9DA9 = 
"The memory cost to be released is larger than the memory cost of memory block 
{}";
-  public static final String 
LOG_EXACTALLOCATEIFSUFFICIENT_FAILED_ALLOCATE_MEMORY_A47897D9 = 
"exactAllocateIfSufficient: failed to allocate memory, ";
-  public static final String 
LOG_TOTAL_MEMORY_SIZE_ARG_BYTES_USED_MEMORY_SIZE_ARG_BYTES_5FB5059F = "total 
memory size {} bytes, used memory size {} bytes, ";
-  public static final String 
LOG_REQUESTED_MEMORY_SIZE_ARG_BYTES_USED_THRESHOLD_ARG_D7061DEB = "requested 
memory size {} bytes, used threshold {}";
-  public static final String LOG_TRYALLOCATE_ALLOCATED_MEMORY_B3D564D9 = 
"tryAllocate: allocated memory, ";
-  public static final String 
LOG_ORIGINAL_REQUESTED_MEMORY_SIZE_ARG_BYTES_03D28A6B = "original requested 
memory size {} bytes, ";
-  public static final String 
LOG_ACTUAL_REQUESTED_MEMORY_SIZE_ARG_BYTES_62760058 = "actual requested memory 
size {} bytes";
-  public static final String LOG_TRYALLOCATE_FAILED_ALLOCATE_MEMORY_838FA6FB = 
"tryAllocate: failed to allocate memory, ";
-  public static final String LOG_REQUESTED_MEMORY_SIZE_ARG_BYTES_BF9CEF81 = 
"requested memory size {} bytes";
-  public static final String 
LOG_GETORREGISTERMEMORYBLOCK_FAILED_MEMORY_BLOCK_ARG_ALREADY_EXISTS_42CA8914 = 
"getOrRegisterMemoryBlock failed: memory block {} already exists, ";
-  public static final String LOG_IT_S_SIZE_ARG_REQUESTED_SIZE_ARG_AF8F04B2 = 
"it's size is {}, requested size is {}";
-  public static final String 
LOG_GETMEMORYMANAGER_MEMORY_MANAGER_ARG_ALREADY_EXISTS_IT_S_SIZE_ARG_0102560A = 
"getMemoryManager: memory manager {} already exists, it's size is {}, enabled 
is {}";
-  public static final String 
LOG_GETORCREATEMEMORYMANAGER_FAILED_TOTAL_MEMORY_SIZE_ARG_BYTES_LESS_THAN_ALLOCATED_3D110256
 =
-      "getOrCreateMemoryManager failed: total memory size {} bytes is less 
than allocated memory"
-      + " size {} bytes";
-  public static final String 
EXCEPTION_EXACTALLOCATE_FAILED_ALLOCATE_MEMORY_AFTER_ARG_RETRIES_957A647B = 
"exactAllocate: failed to allocate memory after %d retries, ";
-  public static final String 
EXCEPTION_TOTAL_MEMORY_SIZE_ARG_BYTES_USED_MEMORY_SIZE_ARG_BYTES_9FC9A9C6 = 
"total memory size %d bytes, used memory size %d bytes, ";
-  public static final String 
EXCEPTION_REQUESTED_MEMORY_SIZE_ARG_BYTES_E6340842 = "requested memory size %d 
bytes";
-  public static final String 
EXCEPTION_REGISTER_MEMORY_BLOCK_ARG_FAILED_SIZEINBYTES_SHOULD_NON_NEGATIVE_EC54AA75
 = "register memory block %s failed: sizeInBytes should be non-negative";
-  public static final String 
LOG_DELETE_SYSTEM_PROPERTIES_TMP_FILE_FAIL_YOU_MAY_MANUALLY_DELETE_F81C4A53 = 
"Delete system.properties tmp file fail, you may manually delete it: {}";
-  public static final String 
LOG_FAILED_DELETE_SYSTEM_PROPERTIES_FILE_YOU_SHOULD_MANUALLY_DELETE_THEM_77F91A98
 = "Failed to delete system.properties file, you should manually delete them: 
{}, {}";
-  public static final String 
EXCEPTION_LENGTH_PARAMETERS_SHOULD_EVENLY_DIVIDED_2_BUT_ACTUAL_LENGTH_E9A792D9 
= "Length of parameters should be evenly divided by 2, but the actual length is 
";
-  public static final String 
EXCEPTION_TMP_SYSTEM_PROPERTIES_FILE_MUST_EXIST_CALL_REPLACEFORMALFILE_FA63B976 
= "Tmp system properties file must exist when call replaceFormalFile";
-  public static final String 
LOG_UNRECOVERABLE_ERROR_OCCURS_CHANGE_SYSTEM_STATUS_READ_ONLY_BECAUSE_HANDLE_05C9AD1A
 =
-      "Unrecoverable error occurs! Change system status to read-only because 
handle_system_error is"
-      + " CHANGE_TO_READ_ONLY. Only query statements are permitted!";
-  public static final String 
LOG_UNRECOVERABLE_ERROR_OCCURS_SHUTDOWN_SYSTEM_DIRECTLY_BECAUSE_HANDLE_SYSTEM_ERROR_14FC06C9
 = "Unrecoverable error occurs! Shutdown system directly because 
handle_system_error is SHUTDOWN.";
-  public static final String 
EXCEPTION_TYPE_ARG_NOT_SUPPORTED_PIPE_RATE_AVERAGE_F74694AD = "The type %s is 
not supported in pipe rate average.";
+  public static final String
+      
LOG_MEMORY_COST_RELEASED_LARGER_THAN_MEMORY_COST_MEMORY_BLOCK_ARG_00DD9DA9 =
+          "The memory cost to be released is larger than the memory cost of 
memory block {}";
+  public static final String 
LOG_EXACTALLOCATEIFSUFFICIENT_FAILED_ALLOCATE_MEMORY_A47897D9 =
+      "exactAllocateIfSufficient: failed to allocate memory, ";
+  public static final String 
LOG_TOTAL_MEMORY_SIZE_ARG_BYTES_USED_MEMORY_SIZE_ARG_BYTES_5FB5059F =
+      "total memory size {} bytes, used memory size {} bytes, ";
+  public static final String 
LOG_REQUESTED_MEMORY_SIZE_ARG_BYTES_USED_THRESHOLD_ARG_D7061DEB =
+      "requested memory size {} bytes, used threshold {}";
+  public static final String LOG_TRYALLOCATE_ALLOCATED_MEMORY_B3D564D9 =
+      "tryAllocate: allocated memory, ";
+  public static final String 
LOG_ORIGINAL_REQUESTED_MEMORY_SIZE_ARG_BYTES_03D28A6B =
+      "original requested memory size {} bytes, ";
+  public static final String 
LOG_ACTUAL_REQUESTED_MEMORY_SIZE_ARG_BYTES_62760058 =
+      "actual requested memory size {} bytes";
+  public static final String LOG_TRYALLOCATE_FAILED_ALLOCATE_MEMORY_838FA6FB =
+      "tryAllocate: failed to allocate memory, ";
+  public static final String LOG_REQUESTED_MEMORY_SIZE_ARG_BYTES_BF9CEF81 =
+      "requested memory size {} bytes";
+  public static final String
+      
LOG_GETORREGISTERMEMORYBLOCK_FAILED_MEMORY_BLOCK_ARG_ALREADY_EXISTS_42CA8914 =
+          "getOrRegisterMemoryBlock failed: memory block {} already exists, ";
+  public static final String LOG_IT_S_SIZE_ARG_REQUESTED_SIZE_ARG_AF8F04B2 =
+      "it's size is {}, requested size is {}";
+  public static final String
+      
LOG_GETMEMORYMANAGER_MEMORY_MANAGER_ARG_ALREADY_EXISTS_IT_S_SIZE_ARG_0102560A =
+          "getMemoryManager: memory manager {} already exists, it's size is 
{}, enabled is {}";
+  public static final String
+      
LOG_GETORCREATEMEMORYMANAGER_FAILED_TOTAL_MEMORY_SIZE_ARG_BYTES_LESS_THAN_ALLOCATED_3D110256
 =
+          "getOrCreateMemoryManager failed: total memory size {} bytes is less 
than allocated memory"
+              + " size {} bytes";
+  public static final String
+      
EXCEPTION_EXACTALLOCATE_FAILED_ALLOCATE_MEMORY_AFTER_ARG_RETRIES_957A647B =
+          "exactAllocate: failed to allocate memory after %d retries, ";
+  public static final String
+      
EXCEPTION_TOTAL_MEMORY_SIZE_ARG_BYTES_USED_MEMORY_SIZE_ARG_BYTES_9FC9A9C6 =
+          "total memory size %d bytes, used memory size %d bytes, ";
+  public static final String 
EXCEPTION_REQUESTED_MEMORY_SIZE_ARG_BYTES_E6340842 =
+      "requested memory size %d bytes";
+  public static final String
+      
EXCEPTION_REGISTER_MEMORY_BLOCK_ARG_FAILED_SIZEINBYTES_SHOULD_NON_NEGATIVE_EC54AA75
 =
+          "register memory block %s failed: sizeInBytes should be 
non-negative";
+  public static final String
+      
LOG_DELETE_SYSTEM_PROPERTIES_TMP_FILE_FAIL_YOU_MAY_MANUALLY_DELETE_F81C4A53 =
+          "Delete system.properties tmp file fail, you may manually delete it: 
{}";
+  public static final String
+      
LOG_FAILED_DELETE_SYSTEM_PROPERTIES_FILE_YOU_SHOULD_MANUALLY_DELETE_THEM_77F91A98
 =
+          "Failed to delete system.properties file, you should manually delete 
them: {}, {}";
+  public static final String
+      
EXCEPTION_LENGTH_PARAMETERS_SHOULD_EVENLY_DIVIDED_2_BUT_ACTUAL_LENGTH_E9A792D9 =
+          "Length of parameters should be evenly divided by 2, but the actual 
length is ";
+  public static final String
+      
EXCEPTION_TMP_SYSTEM_PROPERTIES_FILE_MUST_EXIST_CALL_REPLACEFORMALFILE_FA63B976 
=
+          "Tmp system properties file must exist when call replaceFormalFile";
+  public static final String
+      
LOG_UNRECOVERABLE_ERROR_OCCURS_CHANGE_SYSTEM_STATUS_READ_ONLY_BECAUSE_HANDLE_05C9AD1A
 =
+          "Unrecoverable error occurs! Change system status to read-only 
because handle_system_error is"
+              + " CHANGE_TO_READ_ONLY. Only query statements are permitted!";
+  public static final String
+      
LOG_UNRECOVERABLE_ERROR_OCCURS_SHUTDOWN_SYSTEM_DIRECTLY_BECAUSE_HANDLE_SYSTEM_ERROR_14FC06C9
 =
+          "Unrecoverable error occurs! Shutdown system directly because 
handle_system_error is SHUTDOWN.";
+  public static final String 
EXCEPTION_TYPE_ARG_NOT_SUPPORTED_PIPE_RATE_AVERAGE_F74694AD =
+      "The type %s is not supported in pipe rate average.";
   public static final String EXCEPTION_UNKNOWN_UDFTYPE_9A8D1B23 = "Unknown 
UDFType:";
   public static final String EXCEPTION_8S_5F5F831F = "%8s";
-  public static final String EXCEPTION_CAN_NOT_RECOGNIZE_PIPETYPE_ARG_8850A249 
= "Can not recognize PipeType %s.";
-  public static final String 
EXCEPTION_TARGETREGIONLIST_EMPTY_DEVICE_ARG_TIMESLOT_ARG_E7E5818C = 
"targetRegionList is empty. device: %s, timeSlot: %s";
+  public static final String EXCEPTION_CAN_NOT_RECOGNIZE_PIPETYPE_ARG_8850A249 
=
+      "Can not recognize PipeType %s.";
+  public static final String 
EXCEPTION_TARGETREGIONLIST_EMPTY_DEVICE_ARG_TIMESLOT_ARG_E7E5818C =
+      "targetRegionList is empty. device: %s, timeSlot: %s";
   public static final String EXCEPTION_DATABASE_18F8303F = "Database ";
-  public static final String 
EXCEPTION_NOT_EXISTS_FAILED_CREATE_AUTOMATICALLY_BECAUSE_ENABLE_AUTO_CREATE_SCHEMA_80DE1A4B
 = " not exists and failed to create automatically because 
enable_auto_create_schema is FALSE.";
+  public static final String
+      
EXCEPTION_NOT_EXISTS_FAILED_CREATE_AUTOMATICALLY_BECAUSE_ENABLE_AUTO_CREATE_SCHEMA_80DE1A4B
 =
+          " not exists and failed to create automatically because 
enable_auto_create_schema is FALSE.";
   public static final String EXCEPTION_PATH_DOES_NOT_EXIST_737CB95D = "Path 
does not exist. ";
-  public static final String 
EXCEPTION_CAN_T_GET_NEXT_FOLDER_ARG_BECAUSE_THEY_ALL_FULL_A105BB2D = "Can't get 
next folder from [%s], because they are all full.";
-  public static final String 
EXCEPTION_PARAMETER_ARG_CAN_NOT_ARG_PLEASE_SET_ARG_BECAUSE_ARG_749738D1 = 
"Parameter %s can not be %s, please set to: %s. Because %s";
-  public static final String EXCEPTION_QUERY_EXECUTION_TIME_OUT_A5DC7BFB = 
"Query execution is time out";
-  public static final String EXCEPTION_OBJECT_FILE_ARG_DOES_NOT_EXIST_7EA8CB1C 
= "Object file %s does not exist";
-  public static final String EXCEPTION_ARG_NOT_LEGAL_PRIVILEGE_504838E8 = "%s 
is not a legal privilege";
+  public static final String 
EXCEPTION_CAN_T_GET_NEXT_FOLDER_ARG_BECAUSE_THEY_ALL_FULL_A105BB2D =
+      "Can't get next folder from [%s], because they are all full.";
+  public static final String
+      EXCEPTION_PARAMETER_ARG_CAN_NOT_ARG_PLEASE_SET_ARG_BECAUSE_ARG_749738D1 =
+          "Parameter %s can not be %s, please set to: %s. Because %s";
+  public static final String EXCEPTION_QUERY_EXECUTION_TIME_OUT_A5DC7BFB =
+      "Query execution is time out";
+  public static final String EXCEPTION_OBJECT_FILE_ARG_DOES_NOT_EXIST_7EA8CB1C 
=
+      "Object file %s does not exist";
+  public static final String EXCEPTION_ARG_NOT_LEGAL_PRIVILEGE_504838E8 =
+      "%s is not a legal privilege";
   public static final String EXCEPTION_SOME_PORTS_OCCUPIED_77ED044D = "Some 
ports are occupied";
   public static final String EXCEPTION_PORTS_ARG_OCCUPIED_B462E9DA = "Ports %s 
are occupied";
-  public static final String 
EXCEPTION_UNEXPECTED_ERROR_OCCURS_SERIALIZATION_A6B2E222 = "Unexpected error 
occurs in serialization";
-  public static final String 
EXCEPTION_COLUMN_ARG_TABLE_ARG_ARG_DOES_NOT_EXIST_D8145581 = "Column %s in 
table '%s.%s' does not exist.";
-  public static final String EXCEPTION_TABLE_ARG_ARG_DOES_NOT_EXIST_796E503B = 
"Table '%s.%s' does not exist.";
-  public static final String EXCEPTION_TABLE_ARG_ARG_ALREADY_EXISTS_D4BDF4B5 = 
"Table '%s.%s' already exists.";
-  public static final String 
EXCEPTION_COULDN_T_CONSTRUCTOR_SERIESPARTITIONEXECUTOR_CLASS_ARG_34FB9F45 = 
"Couldn't Constructor SeriesPartitionExecutor class: %s";
-  public static final String 
EXCEPTION_CANNOT_USE_SETVALUE_OBJECT_BEING_SET_ALREADY_MAP_676ED3BF = "Cannot 
use setValue() when the object being set is already in the map";
-  public static final String 
EXCEPTION_ITERATOR_GETKEY_CAN_ONLY_CALLED_AFTER_NEXT_BEFORE_REMOVE_009C456B = 
"Iterator getKey() can only be called after next() and before remove()";
-  public static final String 
EXCEPTION_ITERATOR_GETVALUE_CAN_ONLY_CALLED_AFTER_NEXT_BEFORE_REMOVE_927A88A2 = 
"Iterator getValue() can only be called after next() and before remove()";
-  public static final String 
EXCEPTION_ITERATOR_SETVALUE_CAN_ONLY_CALLED_AFTER_NEXT_BEFORE_REMOVE_51505AD1 = 
"Iterator setValue() can only be called after next() and before remove()";
-  public static final String 
LOG_FAILED_CLOSE_UDFCLASSLOADER_QUERYID_ARG_BECAUSE_ARG_8B1C3739 = "Failed to 
close UDFClassLoader (queryId: {}), because {}";
-  public static final String 
EXCEPTION_ATTRIBUTE_ARG_ARG_REQUIRED_BUT_WAS_NOT_PROVIDED_CD090883 = "attribute 
\"%s\"/\"%s\" is required but was not provided.";
-  public static final String 
EXCEPTION_USE_ATTRIBUTE_ARG_ARG_ONLY_ONE_AT_TIME_B431468C = "use attribute 
\"%s\" or \"%s\" only one at a time.";
-  public static final String 
EXCEPTION_ILLEGAL_OUTLIER_METHOD_OUTLIER_TYPE_SHOULD_AVG_STENDIS_COS_PRENEXTDIS_91D1C70A
 = "Illegal outlier method. Outlier type should be avg, stendis, cos or 
prenextdis.";
-  public static final String 
EXCEPTION_ILLEGAL_AGGREGATION_METHOD_AGGREGATION_TYPE_SHOULD_AVG_MIN_MAX_SUM_2D7BEC96
 = "Illegal aggregation method. Aggregation type should be avg, min, max, sum, 
extreme, variance.";
-  public static final String 
EXCEPTION_CUMULATIVE_TABLE_FUNCTION_REQUIRES_SIZE_MUST_INTEGRAL_MULTIPLE_STEP_D8A9DA94
 = "Cumulative table function requires size must be an integral multiple of 
step.";
-  public static final String 
EXCEPTION_COLUMN_TYPE_MUST_NUMERIC_IF_DELTA_NOT_0_F7864D4E = " The column type 
must be numeric if DELTA is not 0.";
-  public static final String 
EXCEPTION_TYPE_COLUMN_ARG_NOT_AS_EXPECTED_7A81636E = "The type of the column 
[%s] is not as expected.";
-  public static final String 
EXCEPTION_REQUIRED_COLUMN_ARG_NOT_FOUND_SOURCE_TABLE_ARGUMENT_993E1C08 = 
"Required column [%s] not found in the source table argument.";
-  public static final String 
EXCEPTION_UNSUPPORTED_PROGRESS_INDEX_TYPE_ARG_A84CDFF9 = "Unsupported progress 
index type %s.";
-  public static final String 
EXCEPTION_TIMEWINDOWSTATEPROGRESSINDEX_DOES_NOT_SUPPORT_TOPOLOGICAL_SORTING_897C8976
 = "TimeWindowStateProgressIndex does not support topological sorting";
-  public static final String 
EXCEPTION_INTENDED_READ_LENGTH_ARG_BUT_ARG_ACTUALLY_READ_DESERIALIZING_TIMEPROGRESSINDEX_63CD54E4
 =
-      "The intended read length is %s but %s is actually read when 
deserializing TimeProgressIndex,"
-      + " ProgressIndex: %s";
+  public static final String 
EXCEPTION_UNEXPECTED_ERROR_OCCURS_SERIALIZATION_A6B2E222 =
+      "Unexpected error occurs in serialization";
+  public static final String 
EXCEPTION_COLUMN_ARG_TABLE_ARG_ARG_DOES_NOT_EXIST_D8145581 =
+      "Column %s in table '%s.%s' does not exist.";
+  public static final String EXCEPTION_TABLE_ARG_ARG_DOES_NOT_EXIST_796E503B =
+      "Table '%s.%s' does not exist.";
+  public static final String EXCEPTION_TABLE_ARG_ARG_ALREADY_EXISTS_D4BDF4B5 =
+      "Table '%s.%s' already exists.";
+  public static final String
+      
EXCEPTION_COULDN_T_CONSTRUCTOR_SERIESPARTITIONEXECUTOR_CLASS_ARG_34FB9F45 =
+          "Couldn't Constructor SeriesPartitionExecutor class: %s";
+  public static final String 
EXCEPTION_CANNOT_USE_SETVALUE_OBJECT_BEING_SET_ALREADY_MAP_676ED3BF =
+      "Cannot use setValue() when the object being set is already in the map";
+  public static final String
+      
EXCEPTION_ITERATOR_GETKEY_CAN_ONLY_CALLED_AFTER_NEXT_BEFORE_REMOVE_009C456B =
+          "Iterator getKey() can only be called after next() and before 
remove()";
+  public static final String
+      
EXCEPTION_ITERATOR_GETVALUE_CAN_ONLY_CALLED_AFTER_NEXT_BEFORE_REMOVE_927A88A2 =
+          "Iterator getValue() can only be called after next() and before 
remove()";
+  public static final String
+      
EXCEPTION_ITERATOR_SETVALUE_CAN_ONLY_CALLED_AFTER_NEXT_BEFORE_REMOVE_51505AD1 =
+          "Iterator setValue() can only be called after next() and before 
remove()";
+  public static final String 
LOG_FAILED_CLOSE_UDFCLASSLOADER_QUERYID_ARG_BECAUSE_ARG_8B1C3739 =
+      "Failed to close UDFClassLoader (queryId: {}), because {}";
+  public static final String 
EXCEPTION_ATTRIBUTE_ARG_ARG_REQUIRED_BUT_WAS_NOT_PROVIDED_CD090883 =
+      "attribute \"%s\"/\"%s\" is required but was not provided.";
+  public static final String 
EXCEPTION_USE_ATTRIBUTE_ARG_ARG_ONLY_ONE_AT_TIME_B431468C =
+      "use attribute \"%s\" or \"%s\" only one at a time.";
+  public static final String
+      
EXCEPTION_ILLEGAL_OUTLIER_METHOD_OUTLIER_TYPE_SHOULD_AVG_STENDIS_COS_PRENEXTDIS_91D1C70A
 =
+          "Illegal outlier method. Outlier type should be avg, stendis, cos or 
prenextdis.";
+  public static final String
+      
EXCEPTION_ILLEGAL_AGGREGATION_METHOD_AGGREGATION_TYPE_SHOULD_AVG_MIN_MAX_SUM_2D7BEC96
 =
+          "Illegal aggregation method. Aggregation type should be avg, min, 
max, sum, extreme, variance.";
+  public static final String
+      
EXCEPTION_CUMULATIVE_TABLE_FUNCTION_REQUIRES_SIZE_MUST_INTEGRAL_MULTIPLE_STEP_D8A9DA94
 =
+          "Cumulative table function requires size must be an integral 
multiple of step.";
+  public static final String 
EXCEPTION_COLUMN_TYPE_MUST_NUMERIC_IF_DELTA_NOT_0_F7864D4E =
+      " The column type must be numeric if DELTA is not 0.";
+  public static final String 
EXCEPTION_TYPE_COLUMN_ARG_NOT_AS_EXPECTED_7A81636E =
+      "The type of the column [%s] is not as expected.";
+  public static final String
+      EXCEPTION_REQUIRED_COLUMN_ARG_NOT_FOUND_SOURCE_TABLE_ARGUMENT_993E1C08 =
+          "Required column [%s] not found in the source table argument.";
+  public static final String 
EXCEPTION_UNSUPPORTED_PROGRESS_INDEX_TYPE_ARG_A84CDFF9 =
+      "Unsupported progress index type %s.";
+  public static final String
+      
EXCEPTION_TIMEWINDOWSTATEPROGRESSINDEX_DOES_NOT_SUPPORT_TOPOLOGICAL_SORTING_897C8976
 =
+          "TimeWindowStateProgressIndex does not support topological sorting";
+  public static final String
+      
EXCEPTION_INTENDED_READ_LENGTH_ARG_BUT_ARG_ACTUALLY_READ_DESERIALIZING_TIMEPROGRESSINDEX_63CD54E4
 =
+          "The intended read length is %s but %s is actually read when 
deserializing TimeProgressIndex,"
+              + " ProgressIndex: %s";
   public static final String EXCEPTION_COLON_3A291246 = " : ";
-  public static final String EXCEPTION_DATAPARTITIONMAP_IS_NULL_B764418A = 
"dataPartitionMap is null";
+  public static final String EXCEPTION_DATAPARTITIONMAP_IS_NULL_B764418A =
+      "dataPartitionMap is null";
   public static final String EXCEPTION_ARG_634FCEDB = "%s";
-  public static final String 
EXCEPTION_TABLE_ARGUMENT_WITH_SET_SEMANTICS_REQUIRES_AN_ORDER_BY_CLAUSE_10C986D9
 = "Table argument with set semantics requires an ORDER BY clause.";
-  public static final String 
EXCEPTION_THE_TYPE_OF_THE_COLUMN_ARG_IS_NOT_COMPARABLE_E3098096 = "The type of 
the column [%s] is not comparable.";
-  public static final String 
EXCEPTION_NO_COMPARABLE_COLUMNS_FOUND_FOR_M4_CALCULATION_4E5A3092 = "No 
comparable columns found for M4 calculation.";
-  public static final String 
EXCEPTION_INVALID_SCALAR_ARGUMENT_SLIDE_SHOULD_BE_A_POSITIVE_VALUE_F019E091 = 
"Invalid scalar argument SLIDE, should be a positive value";
-  public static final String 
EXCEPTION_THE_ORDER_BY_CLAUSE_OF_THE_DATA_ARGUMENT_MUST_CONTAIN_EXACTLY_THE_TIME_COLUMN_SPECIFIED_BY_THE_TIMECOL_ARGUMENT_4375BAE9
 = "The ORDER BY clause of the DATA argument must contain exactly the time 
column specified by the TIMECOL argument.";
-  public static final String EXCEPTION_UNSUPPORTED_M4_VALUE_TYPE_AF0EF286 = 
"Unsupported M4 value type: ";
-  public static final String 
EXCEPTION_DISK_SPACE_WARNING_THRESHOLD_MUST_BE_IN_0_1_BUT_WAS_7B345766 = 
"disk_space_warning_threshold must be in [0, 1), but was ";
+  public static final String
+      
EXCEPTION_TABLE_ARGUMENT_WITH_SET_SEMANTICS_REQUIRES_AN_ORDER_BY_CLAUSE_10C986D9
 =
+          "Table argument with set semantics requires an ORDER BY clause.";
+  public static final String 
EXCEPTION_THE_TYPE_OF_THE_COLUMN_ARG_IS_NOT_COMPARABLE_E3098096 =
+      "The type of the column [%s] is not comparable.";
+  public static final String 
EXCEPTION_NO_COMPARABLE_COLUMNS_FOUND_FOR_M4_CALCULATION_4E5A3092 =
+      "No comparable columns found for M4 calculation.";
+  public static final String
+      
EXCEPTION_INVALID_SCALAR_ARGUMENT_SLIDE_SHOULD_BE_A_POSITIVE_VALUE_F019E091 =
+          "Invalid scalar argument SLIDE, should be a positive value";
+  public static final String
+      
EXCEPTION_THE_ORDER_BY_CLAUSE_OF_THE_DATA_ARGUMENT_MUST_CONTAIN_EXACTLY_THE_TIME_COLUMN_SPECIFIED_BY_THE_TIMECOL_ARGUMENT_4375BAE9
 =
+          "The ORDER BY clause of the DATA argument must contain exactly the 
time column specified by the TIMECOL argument.";
+  public static final String EXCEPTION_UNSUPPORTED_M4_VALUE_TYPE_AF0EF286 =
+      "Unsupported M4 value type: ";
+  public static final String
+      EXCEPTION_DISK_SPACE_WARNING_THRESHOLD_MUST_BE_IN_0_1_BUT_WAS_7B345766 =
+          "disk_space_warning_threshold must be in [0, 1), but was ";
+  public static final String EXCEPTION_FILTER_FUNCTION_WPASS_VALIDATION =
+      "the value of wpass should be in (0, 1)";
+  public static final String EXCEPTION_NO_CALCULATE_COLUMNS = "No columns 
could be calculated.";
+  public static final String EXCEPTION_NOT_ALLOWED_COLUMNS =
+      "Only column with double, float, int32, int64 can be calculated by the 
function, %s is the %s.";
   public static final String 
LOG_TRUSTED_CHANNEL_FUNCTION_FAILED_INITIATOR_ARG_TARGET_ARG_E4C28443 =
       "Trusted channel function failed: initiator=%s, target=%s";
-
+  public static final String 
EXCEPTION_FILTER_FUNCTION_ROW_INDEX_EXCEED_MAXIMUM =
+      "row index exceeds the maximum allowed number in one partition";
+  public static final String
+      
EXCEPTION_XCORR_REQUIRES_EXACTLY_TWO_CALCULATION_COLUMNS_BUT_FOUND_ARG_2FF8EB0C 
=
+          "XCorr requires exactly two calculation columns, but found %d.";
+  public static final String EXCEPTION_COLUMN_LACK_OF_NAME = "the column in 
table lack of the name";
 }
diff --git 
a/iotdb-core/node-commons/src/main/i18n/zh/org/apache/iotdb/commons/i18n/CommonMessages.java
 
b/iotdb-core/node-commons/src/main/i18n/zh/org/apache/iotdb/commons/i18n/CommonMessages.java
index 07d886a44f3..6cddaa0b1fc 100644
--- 
a/iotdb-core/node-commons/src/main/i18n/zh/org/apache/iotdb/commons/i18n/CommonMessages.java
+++ 
b/iotdb-core/node-commons/src/main/i18n/zh/org/apache/iotdb/commons/i18n/CommonMessages.java
@@ -217,5 +217,12 @@ public final class CommonMessages {
   public static final String 
EXCEPTION_DISK_SPACE_WARNING_THRESHOLD_MUST_BE_IN_0_1_BUT_WAS_7B345766 = 
"disk_space_warning_threshold 必须在 [0, 1) 范围内,但实际为 ";
   public static final String 
LOG_TRUSTED_CHANNEL_FUNCTION_FAILED_INITIATOR_ARG_TARGET_ARG_E4C28443 =
       "可信信道功能失效:发起者=%s,目标端=%s";
-
+  public static final String EXCEPTION_FILTER_FUNCTION_WPASS_VALIDATION = 
"wpass的取值范围应该位于(0, 1)";
+  public static final String EXCEPTION_NO_CALCULATE_COLUMNS = "没有找到可以计算的列.";
+  public static final String EXCEPTION_NOT_ALLOWED_COLUMNS = "只允许列类型为double, 
float, int32, int64参与函数计算, 当前列 %s 类型是 %s.";
+  public static final String 
EXCEPTION_FILTER_FUNCTION_ROW_INDEX_EXCEED_MAXIMUM = "分区行数超过了最大限制";
+  public static final String
+      
EXCEPTION_XCORR_REQUIRES_EXACTLY_TWO_CALCULATION_COLUMNS_BUT_FOUND_ARG_2FF8EB0C 
=
+          "XCorr 要求必须正好有两列计算列,但实际找到 %d 列。";
+  public static final String EXCEPTION_COLUMN_LACK_OF_NAME = "表参数中列缺少名字";
 }
diff --git 
a/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/queryengine/plan/relational/function/TableBuiltinTableFunction.java
 
b/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/queryengine/plan/relational/function/TableBuiltinTableFunction.java
index decaf8dc466..818747bb714 100644
--- 
a/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/queryengine/plan/relational/function/TableBuiltinTableFunction.java
+++ 
b/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/queryengine/plan/relational/function/TableBuiltinTableFunction.java
@@ -27,10 +27,13 @@ import 
org.apache.iotdb.commons.udf.builtin.relational.tvf.CapacityTableFunction
 import 
org.apache.iotdb.commons.udf.builtin.relational.tvf.CumulateTableFunction;
 import org.apache.iotdb.commons.udf.builtin.relational.tvf.FFTTableFunction;
 import org.apache.iotdb.commons.udf.builtin.relational.tvf.HOPTableFunction;
+import 
org.apache.iotdb.commons.udf.builtin.relational.tvf.HighPassTableFunction;
+import 
org.apache.iotdb.commons.udf.builtin.relational.tvf.LowPassTableFunction;
 import org.apache.iotdb.commons.udf.builtin.relational.tvf.M4TableFunction;
 import 
org.apache.iotdb.commons.udf.builtin.relational.tvf.SessionTableFunction;
 import org.apache.iotdb.commons.udf.builtin.relational.tvf.TumbleTableFunction;
 import 
org.apache.iotdb.commons.udf.builtin.relational.tvf.VariationTableFunction;
+import org.apache.iotdb.commons.udf.builtin.relational.tvf.XCorrTableFunction;
 import org.apache.iotdb.udf.api.relational.TableFunction;
 
 import java.util.Arrays;
@@ -49,7 +52,10 @@ public enum TableBuiltinTableFunction {
   FFT("fft"),
   FORECAST("forecast"),
   PATTERN_MATCH("pattern_match"),
-  CLASSIFY("classify");
+  CLASSIFY("classify"),
+  LOWPASS("lowpass"),
+  HIGHPASS("highpass"),
+  XCORR("xcorr");
 
   private final String functionName;
 
@@ -99,6 +105,12 @@ public enum TableBuiltinTableFunction {
         return new ForecastTableFunction();
       case "classify":
         return new ClassifyTableFunction();
+      case "lowpass":
+        return new LowPassTableFunction();
+      case "highpass":
+        return new HighPassTableFunction();
+      case "xcorr":
+        return new XCorrTableFunction();
       default:
         throw new UnsupportedOperationException(
             String.format(QueryMessages.UNSUPPORTED_TABLE_FUNCTION, 
functionName));
diff --git 
a/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/udf/builtin/relational/tvf/FilterTransferTableFunction.java
 
b/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/udf/builtin/relational/tvf/FilterTransferTableFunction.java
new file mode 100644
index 00000000000..0fe09c60cb7
--- /dev/null
+++ 
b/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/udf/builtin/relational/tvf/FilterTransferTableFunction.java
@@ -0,0 +1,315 @@
+/*
+ * 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.builtin.relational.tvf;
+
+import org.apache.iotdb.commons.exception.SemanticException;
+import org.apache.iotdb.commons.i18n.CommonMessages;
+import org.apache.iotdb.udf.api.exception.UDFException;
+import org.apache.iotdb.udf.api.relational.TableFunction;
+import org.apache.iotdb.udf.api.relational.access.Record;
+import org.apache.iotdb.udf.api.relational.table.MapTableFunctionHandle;
+import org.apache.iotdb.udf.api.relational.table.TableFunctionAnalysis;
+import org.apache.iotdb.udf.api.relational.table.TableFunctionHandle;
+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 org.apache.tsfile.block.column.ColumnBuilder;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.BitSet;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import static 
org.apache.iotdb.commons.i18n.CommonMessages.EXCEPTION_FILTER_FUNCTION_WPASS_VALIDATION;
+
+public abstract class FilterTransferTableFunction implements TableFunction {
+
+  public static final String DATA_PARAMETER_NAME = "DATA";
+  public static final String TIMECOL_PARAMETER_NAME = "TIMECOL";
+  public static final String WPASS = "WPASS";
+
+  protected static final String PARTITION_TYPES_PROPERTY = "PARTITION_TYPES";
+  protected static final String CALCULATION_COLUMN_COUNT_PROPERTY = 
"CALCULATION_COLUMN_COUNT";
+
+  @Override
+  public List<ParameterSpecification> getArgumentsSpecifications() {
+    return Arrays.asList(
+        
TableParameterSpecification.builder().name(DATA_PARAMETER_NAME).setSemantics().build(),
+        ScalarParameterSpecification.builder()
+            .name(TIMECOL_PARAMETER_NAME)
+            .type(Type.STRING)
+            .build(),
+        ScalarParameterSpecification.builder()
+            .name(WPASS)
+            .type(Type.DOUBLE)
+            .addChecker(
+                object -> {
+                  if (object instanceof Number) {
+                    double value = ((Number) object).doubleValue();
+                    if (value > 0 && value < 1) {
+                      return null;
+                    }
+                  }
+                  return EXCEPTION_FILTER_FUNCTION_WPASS_VALIDATION;
+                })
+            .build());
+  }
+
+  @Override
+  public TableFunctionAnalysis analyze(Map<String, Argument> arguments) throws 
UDFException {
+
+    // order by column must only be the time column
+    int timeColumnIndex =
+        WindowTVFUtils.checkOrderByColumn(arguments, DATA_PARAMETER_NAME, 
TIMECOL_PARAMETER_NAME);
+    TableArgument tableArgument = (TableArgument) 
arguments.get(DATA_PARAMETER_NAME);
+
+    List<Integer> partitionIndexes = 
WindowTVFUtils.getPartitionIndexes(tableArgument);
+    Set<Integer> excludedIndexes = new HashSet<>(partitionIndexes);
+    excludedIndexes.add(timeColumnIndex);
+
+    List<Type> partitionTypes = new ArrayList<>();
+    List<Integer> calculationIndexes = new ArrayList<>();
+    DescribedSchema.Builder schemaBuilder = new DescribedSchema.Builder();
+
+    // record the partition columns
+    for (int partitionIndex : partitionIndexes) {
+      Type type = tableArgument.getFieldTypes().get(partitionIndex);
+      partitionTypes.add(type);
+      
schemaBuilder.addField(tableArgument.getFieldNames().get(partitionIndex).get(), 
type);
+    }
+
+    // record the time column
+    schemaBuilder.addField(tableArgument.getFieldNames().get(timeColumnIndex), 
Type.TIMESTAMP);
+    // record the calculation columns, only double, float, int32, and int64 
are allowed
+    calculationIndexes.addAll(
+        WindowTVFUtils.getCalculationIndexes(
+            tableArgument,
+            excludedIndexes,
+            columnName -> 
schemaBuilder.addField(convertColumnName(columnName), Type.DOUBLE)));
+
+    if (calculationIndexes.isEmpty()) {
+      throw new 
SemanticException(CommonMessages.EXCEPTION_NO_CALCULATE_COLUMNS);
+    }
+
+    MapTableFunctionHandle.Builder handleBuilder =
+        new MapTableFunctionHandle.Builder()
+            .addProperty(PARTITION_TYPES_PROPERTY, 
WindowTVFUtils.joinTypes(partitionTypes))
+            .addProperty(CALCULATION_COLUMN_COUNT_PROPERTY, 
calculationIndexes.size())
+            .addProperty(WPASS, ((ScalarArgument) 
arguments.get(WPASS)).getValue());
+    List<Integer> requiredColumns = new ArrayList<>(partitionIndexes);
+    requiredColumns.add(timeColumnIndex);
+    requiredColumns.addAll(calculationIndexes);
+
+    return TableFunctionAnalysis.builder()
+        .properColumnSchema(schemaBuilder.build())
+        .requireRecordSnapshot(false)
+        .requiredColumns(DATA_PARAMETER_NAME, requiredColumns)
+        .handle(handleBuilder.build())
+        .build();
+  }
+
+  @Override
+  public TableFunctionHandle createTableFunctionHandle() {
+    return new MapTableFunctionHandle();
+  }
+
+  @Override
+  public abstract TableFunctionProcessorProvider getProcessorProvider(
+      TableFunctionHandle tableFunctionHandle);
+
+  protected abstract String convertColumnName(String columnName);
+
+  /**
+   * Processes one complete partition (which may contain multiple calculation 
columns).
+   *
+   * <p>FFT-based filters cannot operate on null values. We therefore collect 
only finite, non-null
+   * values for each calculation column and keep their original row positions. 
The compact sequence
+   * is passed to the filter, then the transformed values are expanded back to 
the partition's
+   * original row layout. Rows that had a null or non-finite input remain null 
in the output; they
+   * do not participate in the FFT calculation.
+   */
+  protected abstract static class FilterTransferDataProcessor
+      implements TableFunctionDataProcessor {
+
+    protected static final int INITIAL_CAPACITY = 512;
+    protected static final int MAX_COUNT_IN_ONE_PARTITION = 65536;
+
+    private final double wpass;
+    private int partitionRowCount;
+
+    private final int partitionColumnCount;
+    private final int timeColumnIndex;
+    private final int calculationColumnStartIndex;
+    private final Type[] partitionTypes;
+    private final Object[] partitionValues;
+
+    // CalculationColumnContainer collect the all value of a column in one 
partition
+    private long[] partitionTimestamps;
+    private final CalculationColumnContainer[] calculationColumnContainers;
+
+    protected FilterTransferDataProcessor(
+        double wpass, Type[] partitionTypes, int calculationColumnCount) {
+      this.wpass = wpass;
+      this.partitionColumnCount = partitionTypes.length;
+      this.timeColumnIndex = partitionColumnCount;
+      this.partitionRowCount = 0;
+      this.calculationColumnStartIndex = timeColumnIndex + 1;
+      this.partitionTypes = partitionTypes;
+      this.partitionValues = new Object[partitionTypes.length];
+      this.partitionTimestamps = new long[INITIAL_CAPACITY];
+      this.calculationColumnContainers = new 
CalculationColumnContainer[calculationColumnCount];
+      for (int i = 0; i < calculationColumnCount; i++) {
+        calculationColumnContainers[i] = new CalculationColumnContainer();
+      }
+    }
+
+    @Override
+    public void process(
+        Record input,
+        List<ColumnBuilder> properColumnBuilders,
+        ColumnBuilder passThroughIndexBuilder) {
+      if (partitionRowCount >= MAX_COUNT_IN_ONE_PARTITION) {
+        throw new SemanticException(
+            CommonMessages.EXCEPTION_FILTER_FUNCTION_ROW_INDEX_EXCEED_MAXIMUM);
+      }
+      if (partitionRowCount == 0) {
+        capturePartitionValues(input);
+      }
+      collectTimeColumnValue(input);
+      collectCalculationValues(input, partitionRowCount);
+      partitionRowCount++;
+    }
+
+    private void capturePartitionValues(Record input) {
+      for (int i = 0; i < partitionColumnCount; i++) {
+        partitionValues[i] =
+            input.isNull(i) ? null : WindowTVFUtils.readValue(input, i, 
partitionTypes[i]);
+      }
+    }
+
+    private void collectTimeColumnValue(Record input) {
+      if (partitionRowCount >= partitionTimestamps.length) {
+        int newCapacity = partitionTimestamps.length + 
(partitionTimestamps.length >> 2);
+        partitionTimestamps = Arrays.copyOf(partitionTimestamps, newCapacity);
+      }
+      partitionTimestamps[partitionRowCount] = input.getLong(timeColumnIndex);
+    }
+
+    private void collectCalculationValues(Record input, int partitionRowIndex) 
{
+      for (int i = 0; i < calculationColumnContainers.length; i++) {
+        // Missing and non-finite values are intentionally excluded from the 
compact FFT input.
+        if (!input.isNull(calculationColumnStartIndex + i)) {
+          double aDouble = input.getDouble(calculationColumnStartIndex + i);
+          if (Double.isFinite(aDouble)) {
+            calculationColumnContainers[i].add(partitionRowIndex, aDouble);
+          }
+          ;
+        }
+      }
+    }
+
+    @Override
+    public void finish(
+        List<ColumnBuilder> properColumnBuilders, ColumnBuilder 
passThroughIndexBuilder) {
+
+      // collect the partition columns
+      for (int columnIndex = 0; columnIndex < partitionColumnCount; 
columnIndex++) {
+        ColumnBuilder partitionColumnBuilder = 
properColumnBuilders.get(columnIndex);
+        Object partitionValue = partitionValues[columnIndex];
+        Type partitionType = partitionTypes[columnIndex];
+        for (int rowIndex = 0; rowIndex < partitionRowCount; rowIndex++) {
+          WindowTVFUtils.writeValue(partitionColumnBuilder, partitionValue, 
partitionType);
+        }
+      }
+
+      // collect the time column
+      ColumnBuilder timeColumnBuilder = 
properColumnBuilders.get(timeColumnIndex);
+      for (int rowIndex = 0; rowIndex < partitionRowCount; rowIndex++) {
+        timeColumnBuilder.writeLong(partitionTimestamps[rowIndex]);
+      }
+
+      // collect the calculation column
+      for (int i = 0; i < calculationColumnContainers.length; i++) {
+        transformSingleColumn(
+            calculationColumnContainers[i],
+            wpass,
+            properColumnBuilders.get(calculationColumnStartIndex + i));
+      }
+    }
+
+    private void transformSingleColumn(
+        CalculationColumnContainer columnContainer,
+        double wpass,
+        ColumnBuilder properColumnBuilder) {
+      int size = columnContainer.validValueCount;
+      if (size == 0) {
+        for (int rowIndex = 0; rowIndex < partitionRowCount; rowIndex++) {
+          properColumnBuilder.appendNull();
+        }
+        return;
+      }
+      double[] temp = filterTransform(columnContainer, size, wpass);
+      // Restore the transformed values to their original rows; excluded rows 
stay null.
+      int validValueIndex = 0;
+      for (int i = 0; i < partitionRowCount; i++) {
+        if (columnContainer.validRows.get(i)) {
+          properColumnBuilder.writeDouble(temp[2 * validValueIndex]);
+          validValueIndex++;
+        } else {
+          properColumnBuilder.appendNull();
+        }
+      }
+    }
+
+    protected abstract double[] filterTransform(
+        CalculationColumnContainer columnContainer, int size, double wpass);
+  }
+
+  protected static class CalculationColumnContainer {
+    protected double[] validValues = new 
double[FilterTransferDataProcessor.INITIAL_CAPACITY];
+    private int validValueCount = 0;
+    private final BitSet validRows = new BitSet();
+
+    public void add(int rowIndex, double value) {
+      ensureCapacity(validValueCount + 1);
+      validValues[validValueCount++] = value;
+      validRows.set(rowIndex);
+    }
+
+    private void ensureCapacity(int requiredCapacity) {
+      if (requiredCapacity <= validValues.length) {
+        return;
+      }
+      int newCapacity = validValues.length + (validValues.length >> 1);
+      validValues = Arrays.copyOf(validValues, newCapacity);
+    }
+  }
+}
diff --git 
a/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/udf/builtin/relational/tvf/HighPassTableFunction.java
 
b/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/udf/builtin/relational/tvf/HighPassTableFunction.java
new file mode 100644
index 00000000000..88fa37bee62
--- /dev/null
+++ 
b/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/udf/builtin/relational/tvf/HighPassTableFunction.java
@@ -0,0 +1,81 @@
+/*
+ * 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.builtin.relational.tvf;
+
+import org.apache.iotdb.commons.udf.builtin.relational.tvf.fft.DoubleFFT_1D;
+import org.apache.iotdb.udf.api.relational.table.MapTableFunctionHandle;
+import org.apache.iotdb.udf.api.relational.table.TableFunctionHandle;
+import 
org.apache.iotdb.udf.api.relational.table.TableFunctionProcessorProvider;
+import 
org.apache.iotdb.udf.api.relational.table.processor.TableFunctionDataProcessor;
+import org.apache.iotdb.udf.api.type.Type;
+
+public class HighPassTableFunction extends FilterTransferTableFunction {
+
+  @Override
+  public TableFunctionProcessorProvider getProcessorProvider(
+      TableFunctionHandle tableFunctionHandle) {
+    MapTableFunctionHandle handle = (MapTableFunctionHandle) 
tableFunctionHandle;
+    double wpass = (double) handle.getProperty(WPASS);
+    Type[] partitionTypes =
+        WindowTVFUtils.parseTypes((String) 
handle.getProperty(PARTITION_TYPES_PROPERTY));
+    int calculationColumnCount = (Integer) 
handle.getProperty(CALCULATION_COLUMN_COUNT_PROPERTY);
+
+    return new TableFunctionProcessorProvider() {
+      @Override
+      public TableFunctionDataProcessor getDataProcessor() {
+        return new HighPassDataProcessor(wpass, partitionTypes, 
calculationColumnCount);
+      }
+    };
+  }
+
+  @Override
+  protected String convertColumnName(String columnName) {
+    return String.format("highpass(%s)", columnName);
+  }
+
+  protected static class HighPassDataProcessor extends 
FilterTransferDataProcessor {
+
+    public HighPassDataProcessor(double wpass, Type[] partitionTypes, int 
calculationColumnCount) {
+      super(wpass, partitionTypes, calculationColumnCount);
+    }
+
+    @Override
+    protected double[] filterTransform(
+        CalculationColumnContainer columnContainer, int size, double wpass) {
+      DoubleFFT_1D fft = new DoubleFFT_1D(size);
+      double[] temp = new double[2 * size];
+      for (int i = 0; i < size; i++) {
+        temp[2 * i] = columnContainer.validValues[i];
+        temp[2 * i + 1] = 0;
+      }
+
+      fft.complexForward(temp);
+      int m = (int) Math.floor(wpass * size / 2);
+      for (int i = 0; i <= 2 * m + 1; i++) {
+        temp[i] = 0;
+      }
+      for (int i = 2 * (size - m); i < 2 * size; i++) {
+        temp[i] = 0;
+      }
+      fft.complexInverse(temp, true);
+      return temp;
+    }
+  }
+}
diff --git 
a/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/udf/builtin/relational/tvf/LowPassTableFunction.java
 
b/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/udf/builtin/relational/tvf/LowPassTableFunction.java
new file mode 100644
index 00000000000..b563af717a4
--- /dev/null
+++ 
b/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/udf/builtin/relational/tvf/LowPassTableFunction.java
@@ -0,0 +1,77 @@
+/*
+ * 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.builtin.relational.tvf;
+
+import org.apache.iotdb.commons.udf.builtin.relational.tvf.fft.DoubleFFT_1D;
+import org.apache.iotdb.udf.api.relational.table.MapTableFunctionHandle;
+import org.apache.iotdb.udf.api.relational.table.TableFunctionHandle;
+import 
org.apache.iotdb.udf.api.relational.table.TableFunctionProcessorProvider;
+import 
org.apache.iotdb.udf.api.relational.table.processor.TableFunctionDataProcessor;
+import org.apache.iotdb.udf.api.type.Type;
+
+public class LowPassTableFunction extends FilterTransferTableFunction {
+
+  @Override
+  public TableFunctionProcessorProvider getProcessorProvider(
+      TableFunctionHandle tableFunctionHandle) {
+    MapTableFunctionHandle handle = (MapTableFunctionHandle) 
tableFunctionHandle;
+    double wpass = (double) handle.getProperty(WPASS);
+    Type[] partitionTypes =
+        WindowTVFUtils.parseTypes((String) 
handle.getProperty(PARTITION_TYPES_PROPERTY));
+    int calculationColumnCount = (Integer) 
handle.getProperty(CALCULATION_COLUMN_COUNT_PROPERTY);
+
+    return new TableFunctionProcessorProvider() {
+      @Override
+      public TableFunctionDataProcessor getDataProcessor() {
+        return new LowPassDataProcessor(wpass, partitionTypes, 
calculationColumnCount);
+      }
+    };
+  }
+
+  @Override
+  protected String convertColumnName(String columnName) {
+    return String.format("lowpass(%s)", columnName);
+  }
+
+  protected static class LowPassDataProcessor extends 
FilterTransferDataProcessor {
+
+    public LowPassDataProcessor(double wpass, Type[] partitionTypes, int 
calculationColumnCount) {
+      super(wpass, partitionTypes, calculationColumnCount);
+    }
+
+    @Override
+    protected double[] filterTransform(
+        CalculationColumnContainer columnContainer, int size, double wpass) {
+      DoubleFFT_1D fft = new DoubleFFT_1D(size);
+      double[] temp = new double[2 * size];
+      for (int i = 0; i < size; i++) {
+        temp[2 * i] = columnContainer.validValues[i];
+        temp[2 * i + 1] = 0;
+      }
+      fft.complexForward(temp);
+      int m = (int) Math.ceil(wpass * size / 2);
+      for (int i = 2 * m; i <= 2 * (size - m) + 1; i++) {
+        temp[i] = 0;
+      }
+      fft.complexInverse(temp, true);
+      return temp;
+    }
+  }
+}
diff --git 
a/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/udf/builtin/relational/tvf/M4TableFunction.java
 
b/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/udf/builtin/relational/tvf/M4TableFunction.java
index 733696b6212..7b508fcb53d 100644
--- 
a/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/udf/builtin/relational/tvf/M4TableFunction.java
+++ 
b/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/udf/builtin/relational/tvf/M4TableFunction.java
@@ -53,7 +53,6 @@ import java.util.List;
 import java.util.Map;
 import java.util.Set;
 
-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 M4TableFunction implements TableFunction {
@@ -72,19 +71,6 @@ public class M4TableFunction implements TableFunction {
   private static final String PARTICIPANT_TYPES_PROPERTY = 
"__M4_PARTICIPANT_TYPES";
   private static final long UNSPECIFIED_SLIDE = Long.MIN_VALUE;
   private static final long INVALID_INDEX = -1;
-  private static final Set<Type> SUPPORTED_PARTITION_TYPES =
-      new HashSet<>(
-          Arrays.asList(
-              Type.BOOLEAN,
-              Type.INT32,
-              Type.INT64,
-              Type.FLOAT,
-              Type.DOUBLE,
-              Type.TEXT,
-              Type.TIMESTAMP,
-              Type.DATE,
-              Type.BLOB,
-              Type.STRING));
 
   @Override
   public List<ParameterSpecification> getArgumentsSpecifications() {
@@ -113,31 +99,20 @@ public class M4TableFunction implements TableFunction {
 
   @Override
   public TableFunctionAnalysis analyze(Map<String, Argument> arguments) throws 
UDFException {
-    TableArgument tableArgument = (TableArgument) 
arguments.get(DATA_PARAMETER_NAME);
-    if (tableArgument.getOrderBy().isEmpty()) {
-      throw new SemanticException(
-          CommonMessages
-              
.EXCEPTION_TABLE_ARGUMENT_WITH_SET_SEMANTICS_REQUIRES_AN_ORDER_BY_CLAUSE_10C986D9);
-    }
-
-    String timeColumn =
-        (String) ((ScalarArgument) 
arguments.get(TIMECOL_PARAMETER_NAME)).getValue();
     int timeColumnIndex =
-        findColumnIndex(tableArgument, timeColumn, 
Collections.singleton(Type.TIMESTAMP));
-    validateOrderBy(tableArgument, timeColumn);
-
-    List<Integer> partitionIndexes = getPartitionIndexes(tableArgument);
+        WindowTVFUtils.checkOrderByColumn(arguments, DATA_PARAMETER_NAME, 
TIMECOL_PARAMETER_NAME);
+    TableArgument tableArgument = (TableArgument) 
arguments.get(DATA_PARAMETER_NAME);
+    List<Integer> partitionIndexes = 
WindowTVFUtils.getPartitionIndexes(tableArgument);
     Set<Integer> excludedIndexes = new HashSet<>(partitionIndexes);
     excludedIndexes.add(timeColumnIndex);
 
-    boolean isTimeWindow =
-        arguments.containsKey(WINDOW_MODE_PARAMETER_NAME)
-            && (boolean) ((ScalarArgument) 
arguments.get(WINDOW_MODE_PARAMETER_NAME)).getValue();
-
     List<Integer> participantIndexes = new ArrayList<>();
     List<Type> partitionTypes = new ArrayList<>();
     List<Type> participantTypes = new ArrayList<>();
     DescribedSchema.Builder schemaBuilder = new DescribedSchema.Builder();
+    boolean isTimeWindow =
+        arguments.containsKey(WINDOW_MODE_PARAMETER_NAME)
+            && (boolean) ((ScalarArgument) 
arguments.get(WINDOW_MODE_PARAMETER_NAME)).getValue();
     if (isTimeWindow) {
       schemaBuilder
           .addField(OUTPUT_WINDOW_START_COLUMN, Type.TIMESTAMP)
@@ -189,8 +164,8 @@ public class M4TableFunction implements TableFunction {
             .addProperty(WINDOW_MODE_PARAMETER_NAME, isTimeWindow)
             .addProperty(SIZE_PARAMETER_NAME, size)
             .addProperty(SLIDE_PARAMETER_NAME, slide)
-            .addProperty(PARTITION_TYPES_PROPERTY, joinTypes(partitionTypes))
-            .addProperty(PARTICIPANT_TYPES_PROPERTY, 
joinTypes(participantTypes));
+            .addProperty(PARTITION_TYPES_PROPERTY, 
WindowTVFUtils.joinTypes(partitionTypes))
+            .addProperty(PARTICIPANT_TYPES_PROPERTY, 
WindowTVFUtils.joinTypes(participantTypes));
     if (isTimeWindow) {
       handleBuilder.addProperty(
           ORIGIN_PARAMETER_NAME,
@@ -224,8 +199,10 @@ public class M4TableFunction implements TableFunction {
     long size = (long) handle.getProperty(SIZE_PARAMETER_NAME);
     long slide = (long) handle.getProperty(SLIDE_PARAMETER_NAME);
     long origin = isTimeWindow ? (long) 
handle.getProperty(ORIGIN_PARAMETER_NAME) : 0L;
-    Type[] partitionTypes = parseTypes((String) 
handle.getProperty(PARTITION_TYPES_PROPERTY));
-    Type[] participantTypes = parseTypes((String) 
handle.getProperty(PARTICIPANT_TYPES_PROPERTY));
+    Type[] partitionTypes =
+        WindowTVFUtils.parseTypes((String) 
handle.getProperty(PARTITION_TYPES_PROPERTY));
+    Type[] participantTypes =
+        WindowTVFUtils.parseTypes((String) 
handle.getProperty(PARTICIPANT_TYPES_PROPERTY));
 
     return new TableFunctionProcessorProvider() {
       @Override
@@ -240,51 +217,11 @@ public class M4TableFunction implements TableFunction {
     };
   }
 
-  private static void validateOrderBy(TableArgument tableArgument, String 
timeColumn) {
-    if (tableArgument.getOrderBy().size() != 1
-        || !tableArgument.getOrderBy().get(0).equalsIgnoreCase(timeColumn)) {
-      throw new SemanticException(
-          CommonMessages
-              
.EXCEPTION_THE_ORDER_BY_CLAUSE_OF_THE_DATA_ARGUMENT_MUST_CONTAIN_EXACTLY_THE_TIME_COLUMN_SPECIFIED_BY_THE_TIMECOL_ARGUMENT_4375BAE9);
-    }
-  }
-
-  private static List<Integer> getPartitionIndexes(TableArgument 
tableArgument) {
-    List<Integer> indexes = new ArrayList<>();
-    for (String partitionColumn : tableArgument.getPartitionBy()) {
-      indexes.add(findColumnIndex(tableArgument, partitionColumn, 
SUPPORTED_PARTITION_TYPES));
-    }
-    return indexes;
-  }
-
   // BLOB can be used as a partition column because M4 only needs to 
read/write it there
   private static boolean isComparableType(Type type) {
     return type != Type.BLOB && type != Type.OBJECT;
   }
 
-  private static String joinTypes(List<Type> types) {
-    StringBuilder builder = new StringBuilder();
-    for (int i = 0; i < types.size(); i++) {
-      if (i > 0) {
-        builder.append(',');
-      }
-      builder.append(types.get(i).name());
-    }
-    return builder.toString();
-  }
-
-  private static Type[] parseTypes(String value) {
-    if (value.isEmpty()) {
-      return new Type[0];
-    }
-    String[] values = value.split(",");
-    Type[] types = new Type[values.length];
-    for (int i = 0; i < values.length; i++) {
-      types[i] = Type.valueOf(values[i]);
-    }
-    return types;
-  }
-
   private static M4Column[] createColumns(Type[] types, int firstInputIndex) {
     M4Column[] columns = new M4Column[types.length];
     for (int i = 0; i < types.length; i++) {
diff --git 
a/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/udf/builtin/relational/tvf/WindowTVFUtils.java
 
b/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/udf/builtin/relational/tvf/WindowTVFUtils.java
index 3271a30239a..36eae02cf64 100644
--- 
a/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/udf/builtin/relational/tvf/WindowTVFUtils.java
+++ 
b/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/udf/builtin/relational/tvf/WindowTVFUtils.java
@@ -19,17 +19,50 @@
 
 package org.apache.iotdb.commons.udf.builtin.relational.tvf;
 
+import org.apache.iotdb.commons.exception.SemanticException;
 import org.apache.iotdb.commons.i18n.CommonMessages;
 import org.apache.iotdb.udf.api.exception.UDFColumnNotFoundException;
 import org.apache.iotdb.udf.api.exception.UDFException;
 import org.apache.iotdb.udf.api.exception.UDFTypeMismatchException;
+import org.apache.iotdb.udf.api.relational.access.Record;
+import org.apache.iotdb.udf.api.relational.table.argument.Argument;
+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.type.Type;
 
+import org.apache.tsfile.block.column.ColumnBuilder;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
 import java.util.Optional;
 import java.util.Set;
+import java.util.function.Consumer;
+
+import static 
org.apache.iotdb.commons.i18n.CommonMessages.EXCEPTION_COLUMN_LACK_OF_NAME;
 
 public class WindowTVFUtils {
+
+  private static final Set<Type> ALLOWED_CALCULATION_TYPES =
+      Set.of(Type.DOUBLE, Type.FLOAT, Type.INT32, Type.INT64);
+
+  private static final Set<Type> SUPPORTED_PARTITION_TYPES =
+      new HashSet<>(
+          Arrays.asList(
+              Type.BOOLEAN,
+              Type.INT32,
+              Type.INT64,
+              Type.FLOAT,
+              Type.DOUBLE,
+              Type.TEXT,
+              Type.TIMESTAMP,
+              Type.DATE,
+              Type.BLOB,
+              Type.STRING));
+
   /**
    * Find the index of the column in the table argument.
    *
@@ -58,4 +91,156 @@ public class WindowTVFUtils {
             
CommonMessages.EXCEPTION_REQUIRED_COLUMN_ARG_NOT_FOUND_SOURCE_TABLE_ARGUMENT_993E1C08,
             expectedFieldName));
   }
+
+  public static void validateOrderBy(TableArgument tableArgument, String 
timeColumn) {
+    if (tableArgument.getOrderBy().size() != 1
+        || !tableArgument.getOrderBy().get(0).equalsIgnoreCase(timeColumn)) {
+      throw new SemanticException(
+          CommonMessages
+              
.EXCEPTION_THE_ORDER_BY_CLAUSE_OF_THE_DATA_ARGUMENT_MUST_CONTAIN_EXACTLY_THE_TIME_COLUMN_SPECIFIED_BY_THE_TIMECOL_ARGUMENT_4375BAE9);
+    }
+  }
+
+  public static List<Integer> getPartitionIndexes(TableArgument tableArgument) 
{
+    List<Integer> indexes = new ArrayList<>();
+    for (String partitionColumn : tableArgument.getPartitionBy()) {
+      indexes.add(findColumnIndex(tableArgument, partitionColumn, 
SUPPORTED_PARTITION_TYPES));
+    }
+    return indexes;
+  }
+
+  /**
+   * Collect calculation-column indexes after excluding partition and time 
columns.
+   *
+   * <p>If {@code calculationColumnConsumer} is provided, it is invoked with 
each calculation column
+   * name so the caller can append the corresponding result field to its 
output schema.
+   */
+  public static List<Integer> getCalculationIndexes(
+      TableArgument tableArgument,
+      Set<Integer> excludedIndexes,
+      Consumer<String> calculationColumnConsumer) {
+    List<Integer> calculationIndexes = new ArrayList<>();
+    for (int i = 0; i < tableArgument.getFieldTypes().size(); i++) {
+      if (excludedIndexes.contains(i)) {
+        continue;
+      }
+
+      Type type = tableArgument.getFieldTypes().get(i);
+      String columnName =
+          tableArgument
+              .getFieldNames()
+              .get(i)
+              .orElseThrow(() -> new 
SemanticException(EXCEPTION_COLUMN_LACK_OF_NAME));
+      if (!ALLOWED_CALCULATION_TYPES.contains(type)) {
+        throw new SemanticException(
+            String.format(CommonMessages.EXCEPTION_NOT_ALLOWED_COLUMNS, 
columnName, type));
+      }
+
+      calculationIndexes.add(i);
+      if (calculationColumnConsumer != null) {
+        calculationColumnConsumer.accept(columnName);
+      }
+    }
+    return calculationIndexes;
+  }
+
+  public static String joinTypes(List<Type> types) {
+    StringBuilder builder = new StringBuilder();
+    for (int i = 0; i < types.size(); i++) {
+      if (i > 0) {
+        builder.append(',');
+      }
+      builder.append(types.get(i).name());
+    }
+    return builder.toString();
+  }
+
+  /** check the order by column is the timeColumn */
+  public static int checkOrderByColumn(
+      Map<String, Argument> arguments, String dataParameterName, String 
timeParameterName) {
+    TableArgument tableArgument = (TableArgument) 
arguments.get(dataParameterName);
+    if (tableArgument.getOrderBy().isEmpty()) {
+      throw new SemanticException(
+          CommonMessages
+              
.EXCEPTION_TABLE_ARGUMENT_WITH_SET_SEMANTICS_REQUIRES_AN_ORDER_BY_CLAUSE_10C986D9);
+    }
+
+    String timeColumn = (String) ((ScalarArgument) 
arguments.get(timeParameterName)).getValue();
+    int timeColumnIndex =
+        findColumnIndex(tableArgument, timeColumn, 
Collections.singleton(Type.TIMESTAMP));
+    WindowTVFUtils.validateOrderBy(tableArgument, timeColumn);
+    return timeColumnIndex;
+  }
+
+  public static Type[] parseTypes(String value) {
+    if (value.isEmpty()) {
+      return new Type[0];
+    }
+    String[] values = value.split(",");
+    Type[] types = new Type[values.length];
+    for (int i = 0; i < values.length; i++) {
+      types[i] = Type.valueOf(values[i]);
+    }
+    return types;
+  }
+
+  public static Object readValue(Record input, int columnIndex, Type 
partitionType) {
+    switch (partitionType) {
+      case BOOLEAN:
+        return input.getBoolean(columnIndex);
+      case INT32:
+        return input.getInt(columnIndex);
+      case INT64:
+      case TIMESTAMP:
+        return input.getLong(columnIndex);
+      case FLOAT:
+        return input.getFloat(columnIndex);
+      case DOUBLE:
+        return input.getDouble(columnIndex);
+      case TEXT:
+      case STRING:
+      case BLOB:
+        return input.getBinary(columnIndex);
+      case DATE:
+        return input.getLocalDate(columnIndex);
+      default:
+        throw new IllegalArgumentException(String.valueOf(partitionType));
+    }
+  }
+
+  public static void writeValue(ColumnBuilder builder, Object value, Type 
type) {
+    if (value == null) {
+      builder.appendNull();
+      return;
+    }
+
+    switch (type) {
+      case BOOLEAN:
+        builder.writeBoolean((Boolean) value);
+        break;
+      case INT32:
+        builder.writeInt((Integer) value);
+        break;
+      case INT64:
+      case TIMESTAMP:
+        builder.writeLong((Long) value);
+        break;
+      case FLOAT:
+        builder.writeFloat((Float) value);
+        break;
+      case DOUBLE:
+        builder.writeDouble((Double) value);
+        break;
+      case TEXT:
+      case STRING:
+      case BLOB:
+        builder.writeBinary((org.apache.tsfile.utils.Binary) value);
+        break;
+      case DATE:
+        builder.writeObject(value);
+        break;
+      default:
+        throw new IllegalArgumentException(String.valueOf(type));
+    }
+  }
 }
diff --git 
a/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/udf/builtin/relational/tvf/XCorrTableFunction.java
 
b/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/udf/builtin/relational/tvf/XCorrTableFunction.java
new file mode 100644
index 00000000000..3f0ce745bae
--- /dev/null
+++ 
b/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/udf/builtin/relational/tvf/XCorrTableFunction.java
@@ -0,0 +1,249 @@
+/*
+ * 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.builtin.relational.tvf;
+
+import org.apache.iotdb.commons.exception.SemanticException;
+import org.apache.iotdb.commons.i18n.CommonMessages;
+import org.apache.iotdb.udf.api.exception.UDFException;
+import org.apache.iotdb.udf.api.relational.TableFunction;
+import org.apache.iotdb.udf.api.relational.access.Record;
+import org.apache.iotdb.udf.api.relational.table.MapTableFunctionHandle;
+import org.apache.iotdb.udf.api.relational.table.TableFunctionAnalysis;
+import org.apache.iotdb.udf.api.relational.table.TableFunctionHandle;
+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.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 org.apache.tsfile.block.column.ColumnBuilder;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+public class XCorrTableFunction implements TableFunction {
+
+  public static final String DATA_PARAMETER_NAME = "DATA";
+  public static final String TIMECOL_PARAMETER_NAME = "TIMECOL";
+  private static final String PARTITION_TYPES_PROPERTY = "PARTITION_TYPES";
+
+  @Override
+  public List<ParameterSpecification> getArgumentsSpecifications() {
+    return Arrays.asList(
+        
TableParameterSpecification.builder().name(DATA_PARAMETER_NAME).setSemantics().build(),
+        ScalarParameterSpecification.builder()
+            .name(TIMECOL_PARAMETER_NAME)
+            .type(Type.STRING)
+            .build());
+  }
+
+  @Override
+  public TableFunctionAnalysis analyze(Map<String, Argument> arguments) throws 
UDFException {
+    // order by column must only be the time column
+    int timeColumnIndex =
+        WindowTVFUtils.checkOrderByColumn(arguments, DATA_PARAMETER_NAME, 
TIMECOL_PARAMETER_NAME);
+    TableArgument tableArgument = (TableArgument) 
arguments.get(DATA_PARAMETER_NAME);
+
+    List<Integer> partitionIndexes = 
WindowTVFUtils.getPartitionIndexes(tableArgument);
+    Set<Integer> excludedIndexes = new HashSet<>(partitionIndexes);
+    excludedIndexes.add(timeColumnIndex);
+
+    List<Type> partitionTypes = new ArrayList<>();
+    DescribedSchema.Builder schemaBuilder = new DescribedSchema.Builder();
+
+    // record the partition columns
+    for (int partitionIndex : partitionIndexes) {
+      Type partitionType = tableArgument.getFieldTypes().get(partitionIndex);
+      partitionTypes.add(partitionType);
+      schemaBuilder.addField(
+          tableArgument.getFieldNames().get(partitionIndex).get(), 
partitionType);
+    }
+
+    List<Integer> calculationIndexes =
+        new ArrayList<>(WindowTVFUtils.getCalculationIndexes(tableArgument, 
excludedIndexes, null));
+
+    if (calculationIndexes.size() != 2) {
+      throw new SemanticException(
+          String.format(
+              CommonMessages
+                  
.EXCEPTION_XCORR_REQUIRES_EXACTLY_TWO_CALCULATION_COLUMNS_BUT_FOUND_ARG_2FF8EB0C,
+              calculationIndexes.size()));
+    }
+
+    // XCorr emits one correlation value per lag; the original time column is 
used for ordering
+    // only and is not part of the result schema.
+    String firstColumnName = 
tableArgument.getFieldNames().get(calculationIndexes.get(0)).get();
+    String secondColumnName = 
tableArgument.getFieldNames().get(calculationIndexes.get(1)).get();
+    schemaBuilder.addField(
+        String.format("xcorr(%s, %s)", firstColumnName, secondColumnName), 
Type.DOUBLE);
+
+    MapTableFunctionHandle handle =
+        new MapTableFunctionHandle.Builder()
+            .addProperty(PARTITION_TYPES_PROPERTY, 
WindowTVFUtils.joinTypes(partitionTypes))
+            .build();
+
+    List<Integer> requiredColumns = new ArrayList<>(partitionIndexes);
+    requiredColumns.add(timeColumnIndex);
+    requiredColumns.addAll(calculationIndexes);
+
+    return TableFunctionAnalysis.builder()
+        .properColumnSchema(schemaBuilder.build())
+        .requireRecordSnapshot(false)
+        .requiredColumns(DATA_PARAMETER_NAME, requiredColumns)
+        .handle(handle)
+        .build();
+  }
+
+  @Override
+  public TableFunctionHandle createTableFunctionHandle() {
+    return new MapTableFunctionHandle();
+  }
+
+  @Override
+  public TableFunctionProcessorProvider getProcessorProvider(
+      TableFunctionHandle tableFunctionHandle) {
+    MapTableFunctionHandle handle = (MapTableFunctionHandle) 
tableFunctionHandle;
+    Type[] partitionTypes =
+        WindowTVFUtils.parseTypes((String) 
handle.getProperty(PARTITION_TYPES_PROPERTY));
+
+    return new TableFunctionProcessorProvider() {
+      @Override
+      public TableFunctionDataProcessor getDataProcessor() {
+        return new XCorrDataProcessor(partitionTypes);
+      }
+    };
+  }
+
+  private static class XCorrDataProcessor implements 
TableFunctionDataProcessor {
+
+    private static final int INITIAL_CAPACITY = 512;
+    // Cross-correlation is O(n^2) in finish(); keep this far below the filter
+    // function's 65536 so a full partition stays within a few milliseconds.
+    private static final int MAX_COUNT_IN_ONE_PARTITION = 2048;
+
+    private final int partitionColumnCount;
+    private final Type[] partitionTypes;
+    private final Object[] partitionValues;
+
+    private double[] firstValues;
+    private double[] secondValues;
+    private int partitionRowCount;
+
+    private XCorrDataProcessor(Type[] partitionTypes) {
+      this.partitionTypes = partitionTypes;
+      this.partitionColumnCount = partitionTypes.length;
+      this.partitionValues = new Object[partitionColumnCount];
+      this.firstValues = new double[INITIAL_CAPACITY];
+      this.secondValues = new double[INITIAL_CAPACITY];
+      this.partitionRowCount = 0;
+    }
+
+    @Override
+    public void process(
+        Record input,
+        List<ColumnBuilder> properColumnBuilders,
+        ColumnBuilder passThroughIndexBuilder) {
+      if (partitionRowCount >= MAX_COUNT_IN_ONE_PARTITION) {
+        throw new SemanticException(
+            CommonMessages.EXCEPTION_FILTER_FUNCTION_ROW_INDEX_EXCEED_MAXIMUM);
+      }
+
+      if (partitionRowCount == 0) {
+        for (int i = 0; i < partitionColumnCount; i++) {
+          partitionValues[i] =
+              input.isNull(i) ? null : WindowTVFUtils.readValue(input, i, 
partitionTypes[i]);
+        }
+      }
+
+      ensureCapacity(partitionRowCount + 1);
+      int firstValueIndex = partitionColumnCount + 1;
+      int secondValueIndex = partitionColumnCount + 2;
+      // Keep the two series aligned. A null value is represented by NaN and 
skipped during a pair.
+      firstValues[partitionRowCount] = readFiniteValueOrNaN(input, 
firstValueIndex);
+      secondValues[partitionRowCount] = readFiniteValueOrNaN(input, 
secondValueIndex);
+      partitionRowCount++;
+    }
+
+    private static double readFiniteValueOrNaN(Record input, int columnIndex) {
+      if (input.isNull(columnIndex)) {
+        return Double.NaN;
+      }
+      double value = input.getDouble(columnIndex);
+      return Double.isFinite(value) ? value : Double.NaN;
+    }
+
+    @Override
+    public void finish(
+        List<ColumnBuilder> properColumnBuilders, ColumnBuilder 
passThroughIndexBuilder) {
+      if (partitionRowCount == 0) {
+        return;
+      }
+
+      ColumnBuilder correlationBuilder = 
properColumnBuilders.get(partitionColumnCount);
+      // Emit lags in the documented order: -(n - 1), ..., 0, ..., +(n - 1).
+      for (int lag = 1 - partitionRowCount; lag < partitionRowCount; lag++) {
+        int firstStart = Math.max(0, lag);
+        int secondStart = Math.max(0, -lag);
+        int overlapLength = partitionRowCount - Math.abs(lag);
+        double correlation = 0.0;
+        int validPairCount = 0;
+
+        for (int i = 0; i < overlapLength; i++) {
+          double firstValue = firstValues[firstStart + i];
+          double secondValue = secondValues[secondStart + i];
+          if (Double.isFinite(firstValue) && Double.isFinite(secondValue)) {
+            correlation += firstValue * secondValue;
+            validPairCount++;
+          }
+        }
+
+        for (int i = 0; i < partitionColumnCount; i++) {
+          WindowTVFUtils.writeValue(
+              properColumnBuilders.get(i), partitionValues[i], 
partitionTypes[i]);
+        }
+        if (validPairCount == 0) {
+          correlationBuilder.appendNull();
+        } else {
+          correlationBuilder.writeDouble(correlation / validPairCount);
+        }
+      }
+    }
+
+    private void ensureCapacity(int requiredCapacity) {
+      if (requiredCapacity <= firstValues.length) {
+        return;
+      }
+      int newCapacity = firstValues.length + (firstValues.length >> 1);
+      while (newCapacity < requiredCapacity) {
+        newCapacity += newCapacity >> 1;
+      }
+      firstValues = Arrays.copyOf(firstValues, newCapacity);
+      secondValues = Arrays.copyOf(secondValues, newCapacity);
+    }
+  }
+}
diff --git 
a/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/udf/builtin/relational/tvf/fft/DoubleFFT_1D.java
 
b/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/udf/builtin/relational/tvf/fft/DoubleFFT_1D.java
index e0d6b89f1ba..5c96f86e36d 100644
--- 
a/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/udf/builtin/relational/tvf/fft/DoubleFFT_1D.java
+++ 
b/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/udf/builtin/relational/tvf/fft/DoubleFFT_1D.java
@@ -21,7 +21,17 @@ package 
org.apache.iotdb.commons.udf.builtin.relational.tvf.fft;
 
 import org.apache.iotdb.commons.i18n.QueryMessages;
 
-/** Computes an in-place 1D forward DFT for interleaved complex double data. */
+/**
+ * Computes in-place 1D FFTs for interleaved complex double data.
+ *
+ * <p>This is an independent implementation and is not a bit-for-bit port of 
JTransforms 3.1. For
+ * the same input and frequency-domain operations, its results are 
mathematically equivalent to the
+ * original JTransforms-based implementation, but floating-point operation 
order may differ.
+ * Therefore, exact bitwise equality is not guaranteed. There is no universal 
absolute error bound
+ * independent of input magnitude and transform length; callers should compare 
results with a
+ * combined absolute/relative tolerance (1e-9 is a practical baseline for 
ordinary finite-valued
+ * LowPass inputs, not a correctness guarantee for every possible input).
+ */
 public final class DoubleFFT_1D {
 
   private final int length;
@@ -49,6 +59,28 @@ public final class DoubleFFT_1D {
     }
   }
 
+  public void complexInverse(double[] values, boolean scale) {
+    if (values.length < 2 * length) {
+      throw new IllegalArgumentException(
+          
QueryMessages.EXCEPTION_INPUT_ARRAY_LENGTH_MUST_BE_AT_LEAST_2_FFT_LENGTH_31DF6A25);
+    }
+
+    // IDFT(x) = conjugate(DFT(conjugate(x))).
+    for (int i = 1; i < 2 * length; i += 2) {
+      values[i] = -values[i];
+    }
+    complexForward(values);
+    for (int i = 1; i < 2 * length; i += 2) {
+      values[i] = -values[i];
+    }
+
+    if (scale) {
+      for (int i = 0; i < 2 * length; i++) {
+        values[i] /= length;
+      }
+    }
+  }
+
   private void bluesteinForward(double[] values) {
     int convolutionLength = nextPowerOfTwo(2 * length - 1);
     double[] a = new double[2 * convolutionLength];
diff --git 
a/iotdb-core/node-commons/src/test/java/org/apache/iotdb/commons/udf/builtin/relational/tvf/fft/FFT1DTest.java
 
b/iotdb-core/node-commons/src/test/java/org/apache/iotdb/commons/udf/builtin/relational/tvf/fft/FFT1DTest.java
index 86f9d6c11fa..feefefc4ce6 100644
--- 
a/iotdb-core/node-commons/src/test/java/org/apache/iotdb/commons/udf/builtin/relational/tvf/fft/FFT1DTest.java
+++ 
b/iotdb-core/node-commons/src/test/java/org/apache/iotdb/commons/udf/builtin/relational/tvf/fft/FFT1DTest.java
@@ -45,6 +45,45 @@ public class FFT1DTest {
     assertArrayEquals(expected, values, 1e-9);
   }
 
+  @Test
+  public void testDoubleComplexInversePowerOfTwoLength() {
+    double[] values = {1.0, 0.5, -2.0, 1.0, 0.0, -1.5, 3.0, 2.0};
+    double[] expected = values.clone();
+
+    DoubleFFT_1D fft = new DoubleFFT_1D(4);
+    fft.complexForward(values);
+    fft.complexInverse(values, true);
+
+    assertArrayEquals(expected, values, 1e-9);
+  }
+
+  @Test
+  public void testDoubleComplexInverseNonPowerOfTwoLength() {
+    double[] values = {1.0, 0.0, 2.0, -0.5, -1.0, 1.5, 0.0, 0.25, 3.0, -2.0};
+    double[] expected = values.clone();
+
+    DoubleFFT_1D fft = new DoubleFFT_1D(5);
+    fft.complexForward(values);
+    fft.complexInverse(values, true);
+
+    assertArrayEquals(expected, values, 1e-9);
+  }
+
+  @Test
+  public void testDoubleComplexInverseWithoutScaling() {
+    double[] values = {1.0, 0.5, -2.0, 1.0, 0.0, -1.5, 3.0, 2.0};
+    double[] expected = values.clone();
+    for (int i = 0; i < expected.length; i++) {
+      expected[i] *= 4;
+    }
+
+    DoubleFFT_1D fft = new DoubleFFT_1D(4);
+    fft.complexForward(values);
+    fft.complexInverse(values, false);
+
+    assertArrayEquals(expected, values, 1e-9);
+  }
+
   @Test
   public void testFloatComplexForwardPowerOfTwoLength() {
     float[] values = {1.0f, 0.5f, -2.0f, 1.0f, 0.0f, -1.5f, 3.0f, 2.0f};

Reply via email to